Sync third-party and MCP marketplace plugins

Constraint: Public skills are published only by explicit administrator action unless they are tracked third-party market sources.
Confidence: high
Scope-risk: narrow
Directive: Keep private/internal skills out of the public marketplace and preserve normal incremental market Git history.
Tested: Marketplace validation passed.
This commit is contained in:
KeyInfo Bot
2026-09-02 18:39:16 +08:00
parent 6f0a36b303
commit ddff47784c
105 changed files with 4135 additions and 695 deletions
@@ -268,6 +268,18 @@
},
"category": "Developer Tools"
},
{
"name": "updating-gitea-repositories",
"source": {
"source": "local",
"path": "./plugins/updating-gitea-repositories"
},
"policy": {
"installation": "AVAILABLE",
"authentication": "ON_INSTALL"
},
"category": "Developer Tools"
},
{
"name": "design-md",
"source": {
@@ -375,6 +387,18 @@
"authentication": "ON_INSTALL"
},
"category": "Education & Research"
},
{
"name": "etunel-role-collaboration",
"source": {
"source": "local",
"path": "./plugins/etunel-role-collaboration"
},
"policy": {
"installation": "AVAILABLE",
"authentication": "ON_INSTALL"
},
"category": "Business & Operations"
}
]
}
@@ -2,8 +2,8 @@
"sourceId": "caveman",
"repo": "https://github.com/JuliusBrussee/caveman.git",
"ref": "main",
"commit": "df2ccd85c94ec3c8289cb62ac020d241ccfb0c60",
"commit": "b4de606fb871b0d9d454495f3d636b744d560875",
"adapter": "codex-plugin",
"sourcePath": "plugins/caveman",
"syncedAt": "2026-08-30T16:00:00Z"
"syncedAt": "2026-09-02T10:37:18Z"
}
@@ -0,0 +1,41 @@
{
"name": "etunel-role-collaboration",
"version": "0.1.0",
"description": "Etunel 多 Agent 项目的角色识别、Hub 中介、依赖任务波次、成果交接和消息流程协作规范。",
"author": {
"name": "chenmingxuan",
"url": "https://git.playones.com/chenmingxuan"
},
"homepage": "https://git.playones.com/chenmingxuan/EP-Hub-Skill",
"repository": "https://git.playones.com/chenmingxuan/EP-Hub-Skill.git",
"license": "UNKNOWN",
"keywords": [
"etunel",
"multi-agent",
"role-collaboration",
"project-hub",
"workflow"
],
"skills": "./skills/",
"interface": {
"displayName": "Etunel 多角色协作",
"shortDescription": "约束 Hub 中介、成员状态、依赖任务波次、正式成果与消息流程。",
"longDescription": "用于 Etunel 多 Agent 项目中的角色和成员识别、Hub 唯一跨角色中介、依赖就绪任务波次、正式成果交接、异常协调及消息流程。该 skill 依赖 Etunel 运行时提供的 Hook、角色契约和任务上下文。",
"developerName": "chenmingxuan",
"category": "Business & Operations",
"capabilities": [
"Interactive",
"Read",
"Write"
],
"defaultPrompt": [
"使用 Etunel 多角色协作识别当前角色并推进项目任务。",
"使用 Etunel 多角色协作检查任务依赖、成果和交接状态。"
],
"websiteURL": "https://git.playones.com/chenmingxuan/EP-Hub-Skill",
"privacyPolicyURL": "https://git.playones.com/chenmingxuan/EP-Hub-Skill",
"termsOfServiceURL": "https://git.playones.com/chenmingxuan/EP-Hub-Skill",
"brandColor": "#0F766E",
"screenshots": []
}
}
@@ -0,0 +1,9 @@
{
"sourceId": "etunel-role-collaboration",
"repo": "https://git.playones.com/chenmingxuan/EP-Hub-Skill.git",
"ref": "main",
"commit": "127bcc4ad3b6eb6efc8e0221258959e7ae85acb1",
"adapter": "claude-skill",
"sourcePath": "etunel-role-collaboration",
"syncedAt": "2026-09-02T10:37:18Z"
}
@@ -0,0 +1,76 @@
---
name: etunel-role-collaboration
description: "用于 Etunel 多 Agent 项目的角色识别、Hub 中介、依赖任务波次、正式成果、人类负责人确认、阶段交接和消息流程协作。"
---
# Etunel 多角色项目协作
一个 WORK_ID 使用一个持续的项目Hub会话贯穿生命周期。默认角色为项目Hub、业务、产品、技术负责人、嵌入式应用层、嵌入式底层、硬件和测试;已完成契约并由 Hub 真人负责人在 Etunel 中手动添加的自定义角色也可参与。
## 先确认身份与任务
从当前 Hook、Etunel 角色契约和入站任务确认:
- semantic role、实际 role ID、role member ID、session ID 和 human owner
- WORK_ID、SUBTASK_ID、项目模式、流程基线、阶段、任务波次和本任务范围;
- 唯一主责角色与主责成员、协作角色、上游依赖和要求完成时间;
- 要求产出的文件或连贯成果包、最低内容、证据、完成条件和下游用途。
不要根据文件夹名、历史消息或记忆猜身份。成员、会话、职责或任务归属不清时,先报告边界问题,不自行换角色。
## 共享硬约束
1. 项目Hub是成员 Agent 之间唯一的跨角色中介。现阶段 Etunel 不支持成员间直接通信;成员只交 Hub,Hub 再定向路由,且不替角色改写或作出专业结论。
2. 正常阶段顺序为:业务需求、产品定义、方案设计、项目规划、软硬件实现、测试验证、业务验收、发布结项。阶段按有效流程基线和依赖推进。
3. 同一阶段中,依赖已满足的任务可组成任务波次;一个工具调用只有一个接收方,同一角色的多项工作可以内聚成任务包或连续派发多个 SUBTASK_ID。
4. 每个 SUBTASK_ID 只有一个主责角色、一个主责成员和一个可独立判定的结果。协作角色不等于共同主责。
5. Hub 给足当前任务需要的已登记信息,但不默认广播完整计划、全部资料或私有对话。缺口应聚合后经 Hub 定向补齐。
6. 正式执行任务必须要求具体产出文件或连贯成果包,且派发要求与预期产出一致。纯信息查询、确认或决定请求不虚构文件。
7. 角色 AI 收到任务后先与本角色 human owner 对齐,形成成果后完成专业自审并取得负责人确认,才可正式返回。
8. Hub 只校验身份、结构、版本、证据、确认状态、跨角色冲突、依赖和门禁,不替专业角色判断内容是否充分。
9. 项目模式、任务结果、成果生命周期、成果适用性、阶段门禁、测试结论、业务验收和消息通知是不同状态层;不适用项统一只写 NA,也不混用状态。
10. 正式项目只在已有成果覆盖且取得必要确认时受控跳转。明确的流程模拟可记录 BYPASSED_WITH_RISK 和 SIMULATION_ONLY,并只能以 SIMULATION_COMPLETED 结束。
11. Etunel 运行时负责队列、投递、重试、去重、会话授权和文件传输;本 Skill 不另造这些软件机制。
12. 当前 Hook、工具 schema、项目角色契约、成员登记和已确认流程基线高于本 Skill 的通用说明;不存在的工具、角色或参数不得伪造。
## 渐进式路由
只读取当前工作需要的引用:
- Hub:先读 [Hub 工作流](references/hub-workflow.md)。
- 创建项目、选择成员、配置自定义角色、成员交接、维护状态或发送状态快照:读 [成员与项目状态](references/project-status-and-membership.md)。
- 选择阶段、正式成果、任务波次或交接:读 [项目生命周期](references/project-lifecycle.md)。
- 成员:先读 [成员通用工作流](references/member-workflow.md),再只读当前角色文件:
- [业务](references/roles/business.md)
- [产品](references/roles/product.md)
- [技术负责人](references/roles/technical-lead.md)
- [嵌入式应用层](references/roles/embedded-application.md)
- [嵌入式底层](references/roles/embedded-lowlevel.md)
- [硬件](references/roles/hardware.md)
- [测试](references/roles/testing.md)
- 准备派发、回复、跨角色中继、完成或报告阻塞:读 [Etunel 任务消息流程](references/etunel-message-lifecycle.md)。
- 定义或校验成果、状态、版本、证据、额外产出或豁免:读 [成果与完成判定](references/artifacts-and-evidence.md)。
- 缺信息、错投、阻塞、会议决定、返工、变更、流程跳转或模拟:读 [异常与协调](references/exceptions-and-coordination.md)。
- 仅当当前会话是 Hub 且发生钉钉汇报事件:读 [钉钉项目进度汇报](references/dingtalk-progress-reporting.md)。
- 测试角色仅在任务类型匹配时,按 [测试职责](references/roles/testing.md) 中的二级链接读取更深细则。
不要为“全面了解”一次加载全部引用或全部角色文件。Etunel Hook 源文件独立配置,不属于本 Skill 的渐进式发现树。
## 每项任务的控制循环
1. 确认身份、成员映射、有效流程与成果基线、任务目标、主责边界和 human owner。
2. 向负责人复述任务;一次核对输入、输出、证据、版本、期限、完成条件和下游用途。
3. 信息足够后执行本角色工作;缺少跨角色输入时,先走负责人路径,再向 Hub 提交聚合请求。
4. 形成产出文件或成果包,完成专业自审并取得负责人确认。
5. 通过当前 Hook 和 Etunel schema 对应的工具返回结果、补充请求或正式阻塞。
6. Hub 校验并登记;合格则更新成果、状态、依赖和下一波次,不合格则精确补齐或按异常流程路由。
## 提交前检查
- 身份、成员、会话、WORK_ID、SUBTASK_ID 和流程基线是否来自运行时?
- 是否只有一个主责角色和主责成员,且未越过其他角色专业或批准边界?
- 输入是否足够,输出文件、证据、期限和完成条件是否与任务要求一致?
- 自审、版本、负责人确认、开放项和风险是否明确?
- 状态层是否正确,NA、DEFERRED、WAIVED 和模拟状态是否被混用?
- 是否把并行任务波次误当成无依赖广播,或把消息排队、通知接受误当成业务完成?
- 是否只使用当前 schema 中与本次意图匹配的 Etunel 工具?
@@ -0,0 +1,4 @@
interface:
display_name: "Etunel 多角色协作"
short_description: "约束 Hub 中介、成员状态、依赖任务波次、正式成果与消息流程"
default_prompt: "Use $etunel-role-collaboration to identify my Etunel role and member mapping, load only the relevant workflow and role rules, and complete the current project task through the Hub-mediated Etunel process."
@@ -0,0 +1,118 @@
# 成果与完成判定
Hub 定义任务产出、成员提交结果、判断状态或校验门禁时读取。具体职责和上下游见 [项目生命周期](project-lifecycle.md) 与当前角色契约。
## 正式成果集合
正式门禁成果只使用以下名称:
| 阶段 | 正式成果 |
|---|---|
| 1 业务需求 | Project Background BriefProject Milestone Plan |
| 2 产品定义 | Project Initiation PackageTest & Acceptance CriteriaMilestone Requirements |
| 3 方案设计 | Solution ArchitectureSoftware/Hardware Interface ContractHardware Design PackageArchitecture Decision RecordTest Plan |
| 4 项目规划 | Project PlanRisk RegisterRole AssignmentProduct Documentation PackageProject Status Record |
| 5 软硬件实现 | Hardware Implementation PackageLow-Level Implementation PackageApplication Firmware Package |
| 6 测试验证 | Functional Test ReportReliability Test ReportSpecialized Test ReportTest Evidence PackageDefect Analysis Report |
| 7 业务验收 | Platform Test Approval ReportCustomer Acceptance Approval ReportConditional Acceptance Items |
| 8 发布结项 | Closure Documentation ArchiveChange LogClosure ReportProcess Closure Summary |
角色自定义文件可作为 supporting、internal 或 ADDITIONAL 材料,但不能替代适用正式成果。阶段 6 的质量结论和通用证据必须归入对应测试报告、Test Evidence Package 或 Defect Analysis Report,不另立正式成果类别。
## 先定义产出契约
正式执行任务派发时明确:
1. 正式成果或内聚成果包名称及主责角色、主责成员;
2. 每项最低内容、适用子项和协作边界;
3. 输入基线、版本、supersedes 和可追踪引用;
4. 所需证据及未执行验证的表达方式;
5. 下游用途、期限和可检查完成条件;
6. 本角色必须给出的专业结论;
7. 专业自审和 human owner 确认要求。
任务要求和实际产出应一一对应。纯信息、澄清和批准决定不为形式创建空文件,但答复仍需可追踪、经有权角色确认且结论明确。
## 任务结果最低结构
不强制统一复杂 JSON,但正式结果必须让 Hub 找到:
- WORK_ID、SUBTASK_ID、模式、流程基线、阶段、波次;
- semantic role、实际 role ID、主责成员、session、human owner 和输入基线;
- 实际完成内容和要求完成时间状态;
- 成果名称、位置或传输引用、版本及 supersedes
- 每项完成条件对应的证据;
- NA、未执行项、开放问题、依赖和剩余风险;
- 本角色明确结论:满足、部分满足或无法满足;
- self_check_result
- internal_approved,以及确认人、时间、范围和条件。
一句“已完成”“没问题”或“测试通过”不能关闭任务。
## 状态分层
以下层级彼此独立:
1. 项目运行模式;
2. 任务执行结果;
3. 成果生命周期;
4. 成果适用性;
5. 阶段与门禁;
6. 测试结论;
7. 业务验收结论;
8. Etunel 消息或钉钉通知状态。
按当前运行时或角色规则记录状态属于哪一层。任务成功不等于成果已基线;成果存在不等于门禁满足;测试 PASS 不等于业务验收;消息 Consumed 或通知 ACCEPTED 不等于项目完成。
internal_approved=true 是本次消息/提交的人工确认字段;INTERNALLY_APPROVED 是成果生命周期语义。前者不能自动替代后者,成果状态仍需按其版本、证据和流程明确更新。
## 内聚任务包与多任务
- 同一角色、同一基线、紧密相关且共同交付的成果可组成一个任务包;全部必需产出满足才成功。
- 能独立验收、失败或服务不同依赖的工作使用独立 SUBTASK_ID,即使同批发送。
- 包内有效成果保留,未完成部分可拆为关联新任务;一个子项失败不能被其他成功掩盖。
## 专业自审和人类确认
self_check_result 说明角色如何按任务契约检查产出,可为 PASS、PARTIAL 或 FAIL,并列出依据与例外。
internal_approved 表示本角色 human owner 实际查看本次结果并确认可作为角色正式提交。至少记录确认人、时间、文件/版本/范围和附带条件。AI 不得自行设为 true;模拟项目只确认模拟使用和流程推进,不证明模拟值真实。
## 适用性、NA 与豁免
- 适用内容必须形成;不适用统一标记 NA,并说明条件和依据。
- NA 只表示不适用,不能表示时间不足、环境缺失、尚未执行、失败或阻塞。
- DEFERRED 是延后;WAIVED 是完成正式豁免;二者都不等于 NA。
- 适用内容缺失不能用 NA 掩盖;固定成果不能靠空文件或虚假 PASS 通过。
Artifact Waiver 由成果主责角色提出,提供成果标识、阶段、NA 原因、替代证据、下游影响、风险和内部确认。Hub 识别受影响角色与门禁:
1. 受影响角色负责人确认不会产生需求、接口、实现、测试、发布或审计缺口;
2. 低影响、无专业争议时,Hub AI 可完成形式审查、批准和登记;
3. 涉及范围、质量、安全、合规、客户承诺、重大风险、不可逆影响或存在争议时,升级业务和相关专业角色,必要时由 Hub 负责人介入;
4. 只有状态为 WAIVED、批准记录完整才满足对应门禁;
5. 条件变化使成果重新适用时撤销豁免并恢复 REQUIRED。
## 额外产出
角色可提交职责内有价值的额外文件,标记 ADDITIONAL 并说明与原任务的关系、对完成结论的影响、下游用途以及新增依赖、风险和维护责任。
Hub 可将其纳入成果索引。若改变范围、接口、成员责任、基线、排期、正式成果或验收,先走 Change Request,不静默生效。
## 事实、判断和证据
结果应区分:已确认事实、原始证据、本角色专业判断、未验证假设、已批准决定、开放问题、外部依赖、剩余风险、客户期望、内部目标、正式承诺、REAL 与 SIMULATED 数据。
研发自测不能替代测试独立结论;测试不能替代产品或业务验收。无法执行的检查说明原因、影响和恢复条件。
## 版本与可追踪性
代码、固件、硬件、配置、设计、计划或报告给出足以唯一识别对象的版本/引用,并说明上游输入、产生或验证版本、被替代旧版本、与接口/板卡/BOM/ECO/构建/环境的匹配关系和下游约束。
新结果不能静默覆盖旧基线。正式变更保留旧版本、新版本、生效范围和 supersedes 关系。
## Hub 校验边界
Hub 检查文件存在、最低结构、身份、版本、证据引用、自审、负责人确认、冲突、依赖、状态层和门禁;不替专业角色判断内容是否充分。专业冲突定向交拥有决定权的角色。
向下游只传递任务需要的已登记成果、版本、约束、风险和证据引用,不复制完整聊天或全部资料。
@@ -0,0 +1,78 @@
# Hub 钉钉项目进度汇报
仅当当前会话是 Hub 且发生本文件定义的汇报事件时读取。钉钉是面向项目群组的单向辅助可见性与异常提醒,不是任务派发、跨角色沟通、审批、门禁、人类确认或项目记录的事实源。
## 权限与唯一入口
- 只有 Hub/主 Agent 可以发送;成员 Agent 只把成果、状态或阻塞交给 Hub。
- 项目配置为启用时视为持续发送授权,不需每条消息再次询问。
- 只能调用项目封装入口:
`./scripts/dingtalk-progress <start|milestone|blocked|complete|failed> "<简短、人类可读的摘要和下一步>"`
- Agent 不得直接调用底层 OpenAPI、`dws api` 或其他消息入口绕过封装脚本。
- Agent 不读取、修改、输出或请求 Client Secret、DING_SEC、App Token、Client ID、robotCode、openConversationId 等凭据和内部标识。
- Skill 与消息正文不得硬编码项目 Client ID、robotCode、openConversationId、Client Secret 或群名;项目差异只由 `.dingtalk/config.env` 和封装脚本处理。
## 汇报单位
汇报以整个 WORK_ID 生命周期为单位。Hub 聚合阶段、任务波次和 SUBTASK_ID 的结果,不为每条队列消息、普通回复、单个小步骤或短小只读问答发送通知。
## 事件判定
### start
每个 WORK_ID 最多一次。在第一个真实可执行任务或任务波次已经通过 Etunel 实际派发后发送。仅建立计划、等待输入或讨论想法时不发送。
### milestone
在可验证、会改变下一步的实质进展发生时发送,例如:
- 关键基线/成果包经校验成为有效版本;
- 一个有意义的任务波次完成并触发角色或阶段交接;
- 门禁、受控跳转、回退或豁免完成真实记录和必要确认;
- 正式阻塞解除,项目恢复到明确下一动作;
- 统一固件、版本矩阵、测试结论、验收或发布组合形成。
同一处理轮或同一波次的相关结果合并成一条,不逐个 SUBTASK_ID 刷屏。没有固定时间间隔;依靠事件语义和去重控制频率。
### blocked
出现下列实际阻塞时立即发送:
- 角色已完成负责人询问和必要线下协调,仍需用户、Hub 负责人或外部条件才能继续;
- 关键路径等待有权决定;
- Etunel 的任务投递、成员返回、会话或消息链路实际中断。
普通排队、正常等待、角色仍可自行推进或尚未完成产出不算 blocked。阻塞解除后用 milestone 汇报恢复,不修改历史消息。
### complete
整个 WORK_ID 或用户明确指定的整体目标最终完成时发送一次。模拟项目必须写 `SIMULATION_COMPLETED`,不得表达真实发布、客户验收或生产就绪。
### failed
整个 WORK_ID/整体目标已最终终止、无法恢复或明确失败时发送。可返工的测试 FAIL、单个 SUBTASK_ID 失败或临时脚本异常不使用 failed。
## 消息写法
写成一段短摘要,或 2–4 条简洁要点,像项目负责人向团队说明进展,不像日志转储。优先包含:
- 可公开的项目名或 WORK_ID、正式/模拟模式;
- 当前阶段或任务波次;
- 已验证进展、关键成果或版本;
- 下一步和主责角色;
- blocked 时补充原因、影响和需要谁采取什么动作。
只写已验证结论。不得包含密钥、Token、个人数据、客户敏感信息、大段日志、完整内部对话或未经验证的根因推断。
## 调用与结果
1. Hub 判断事件并合并摘要。
2. 调用封装脚本一次;脚本自行处理配置检查、发送和有限重试。
3. 只有真实发送响应含非空 `processQueryKey`,才记为 `ACCEPTED`,含义仅是钉钉服务端接受,不证明群成员已读。
4. 缺少或未启用配置记为 `SKIPPED`dry-run 记为 `DRY_RUN`;没有有效 key 或最终发送错误记为 `FAILED_OR_UNKNOWN`
5. `SKIPPED``DRY_RUN` 和发送前配置/依赖校验错误不重试。真实发送失败或响应无有效 key 时,由脚本最多总计尝试 3 次,尝试间隔 10 秒;首次成功立即停止。未知响应重试可能造成极少量重复通知,按当前项目策略接受。
6. 三次仍失败只终止本次钉钉发送,Etunel 主任务继续。Hub 在本地最终结果中向负责人说明一次,不再递归发送 blocked/failed,不自动补发历史事件。
脚本输出和退出码用于判断通知调用,不得把钉钉结果升级成项目门禁。Agent 不自行在脚本外追加重试循环。
@@ -0,0 +1,115 @@
# Etunel 任务消息流程
准备派发、补充、跨角色中继、返回、完成、阻塞或结算 Hub 入站消息时读取。当前 Hook 和 MCP schema 是工具名、参数与授权的最终依据;本文只约束职责和消息意图。
## 标识与身份
| 标识 | 含义 |
|---|---|
| WORK_ID | 贯穿项目生命周期的工作容器 |
| 流程基线/阶段 | 当前 WORK_ID 已登记的流程版本与位置 |
| 任务波次 | 同一有效基线下依赖已满足、可连续派发的一组任务 |
| SUBTASK_ID | 一个主责角色和主责成员可独立判定的一项任务 |
| role/member/session | 语义角色、实际角色实例、主责成员和绑定会话 |
| message_id | 一条 Etunel 消息的单跳关联或结算标识 |
正文已有有效标识时复用。已终态 SUBTASK_ID 不重新作为活动任务;运行时字段命名不同则按实际 schema 映射。
## 工具职责
| 意图 | 调用者 | Etunel 工具 |
|---|---|---|
| 向一个角色派发一条任务消息 | Hub | etunel_send_to_rolekind=task |
| 向同一来源角色返回信息或终态状态 | Hub | etunel_send_to_rolekind=reply 或 kind=status,并按 schema 关联来源 message_id |
| Hub 已处理入站且无需回复 | Hub | etunel_complete_coordination |
| 成员向 Hub 补充、聚合询问或报告非终态状态 | 成员 | etunel_send_to_hub |
| 成员成功结束自己的任务 | 主责成员 | etunel_complete_task |
| 成员以具体阻塞结束自己的任务 | 主责成员 | etunel_report_blocked |
| 读取当前消息列出的必要附件 | 当前绑定会话 | etunel_receive_message |
工具未暴露、名称或参数不同,以当前 Hook 和 schema 为准并报告能力缺口;不得猜参数或请求内部授权字段。
## 任务波次如何发送
etunel_send_to_role 一次调用只发送一个接收角色和一条消息:
- 同一角色多个独立 SUBTASK_ID 可连续发送,由 Etunel 队列处理;
- 同一角色紧密相关且共同交付的内容可合并为内聚任务包;
- 不同角色的依赖就绪任务分别发送、独立返回;
- 排队不代表角色业务并行完成,也不代表下游依赖已经满足。
Hub 不实现队列、ACK、锁、重试、去重或文件传输;这些由 Etunel 软件承担。
## Hub 发送任务
每条正式任务消息应包含:
- WORK_ID、SUBTASK_ID、模式、流程基线、阶段和波次;
- semantic role、实际 role ID、主责成员、session、human owner 和协作角色;
- 目标、背景、上游成果、输入版本和成果引用;
- IN_SCOPE、OUT_OF_SCOPE、依赖、接口、限制和风险;
- 指定成果及最低内容、证据、版本、下游用途;
- 要求完成时间、完成条件和职责内结论;
- 专业自审和 human owner 确认要求;
- 信息不足、额外产出和阻塞的处理边界。
纯信息、澄清或授权消息写清问题、已确认事实、影响、选项和所需答复,不要求空文件。不要转发无关聊天、全量计划或无法消化的资料堆。
## 成员请求补充
成员先询问自己的负责人并完成必要线下沟通。仍需 Hub 时,用一条 etunel_send_to_hub 写清:
- SUBTASK_ID、已完成工作和现有成果;
- 聚合后的缺失信息/决定及用途;
- 已向负责人询问和线下协调的结果;
- 对结论、范围、期限、风险和下游的影响;
- 建议的信息所有者角色;
- 当前仍可继续的范围与希望 Hub 返回的具体内容。
Hub 已有登记答案时一次补足;没有时才产生必要的跨角色查询或任务。
## 经 Hub 的跨角色中继
当前 Etunel 没有成员间直连工具。跨角色交流必须是:来源成员 → Hub → 目标成员 → Hub → 来源成员。
- Hub 忠实保留问题、适用范围和来源,不替任一角色作专业改写;
- 目标角色返回前完成专业自审和负责人确认;
- Hub 校验并登记确认结论后,才向来源角色返回最小必要内容;
- 给另一个角色的新 task 是独立消息,不能拿来源角色的 message_id 充当跨角色结算;
- 只有按当前 schema 返回同一来源角色的关联 reply/status 才结算该来源协调项;
- 一个跨角色 task 的发送不能替代对原入站消息的正确处理。
默认一次聚合请求和一次答复;复杂异常使用 Meeting Decision Record,不把多轮聊天当成项目事实。
## Project Status Snapshot
状态快照只由 Hub 向受影响角色发送,是裁剪后的状态同步,不是新专业任务、成果或门禁。写明变化、有效版本、对接收方影响、下一步、责任方和期限;同一处理轮聚合一次。若需要角色执行动作,应另有明确 task 或按当前 schema 明确消息意图。
## 成员完成或阻塞
调用 etunel_complete_task 前,确认指定成果、证据、版本、期限状态、专业自审、负责人确认和明确结论均已包含。
调用 etunel_report_blocked 时至少说明:
- 阻塞条件;
- 已完成成果和已尝试排查/负责人/线下协调;
- 缺失输入或决定及建议责任人;
- 对本任务和下游的影响;
- 恢复条件和建议下一步。
成员只能结束自己的任务。Hub 不能代成员完成或阻塞;成员不能结算 Hub 的协调消息。
## Hub 处理成员入站
Hub 对每条入站消息选择:
- 需要向同一来源角色回复:按 schema 发送关联 reply/status
- 无需回复且已处理:调用 etunel_complete_coordination
- 需要其他角色:正确处理来源协调项,并按依赖创建一个或多个必要任务;
- 同一轮到达多个相关结果:先更新成果、状态和依赖,再统一选择下一波次。
消息结算、排队和送达不代表 SUBTASK_ID、成果、阶段或 WORK_ID 完成。
## 附件
直接使用当前消息正文和内嵌内容。仅当消息明确列出附件且为当前任务必要输入时,调用 etunel_receive_message 获取所需附件。不要为探测队列或重复确认而读取。
@@ -0,0 +1,124 @@
# 异常与协调
出现缺失信息、错投、职责冲突、阻塞、复杂线下会议、缺陷、返工、变更、流程跳转、成果豁免或模拟流程时读取。所有成员 Agent 跨角色通信都经 Hub;现阶段没有成员直连。
## 缺失信息
成员按以下顺序处理:
1. 检查任务和本会话已有的已确认资料;
2. 一次向本角色负责人列清缺什么、用途、影响和建议来源;
3. 负责人能回答时记录来源、时间、范围和条件后继续;
4. 负责人不能回答时,提醒其线下寻找能解决问题的人;
5. 线下结果回到本角色会话,经本角色负责人确认;
6. 仍无法解决,或必须取得另一角色正式成果时,向 Hub 发送一组聚合问题或正式阻塞。
Hub 有登记答案时直接补足;没有时只向实际信息所有者角色创建必要查询或任务。取得确认结果后返回原任务,不广播无关角色。
## 结果不完整
- 原任务目标不变;Hub 只列缺失成果、字段、证据、版本、自审或确认。
- 已终态任务使用关联的新 SUBTASK_ID 补齐;有效部分保留,不要求无关重做。
- 补齐后按原契约重新校验。
- Hub 不用推测补专业结论,也不为一个格式字段增加虚假评审层。
## 错投与职责冲突
成员保留本角色已完成部分,向 Hub 说明错误身份/成员、越界内容、影响和建议责任方。Hub 按决定权路由:
- 目标、业务范围、优先级、资源、组织授权和最终业务风险接受:业务;
- 产品行为、需求含义、用例与验收标准:产品;
- 总体架构、跨层接口、技术取舍、依赖与集成:技术负责人;
- 应用逻辑、状态机、应用协议和应用服务:嵌入式应用层;
- BSP、Bootloader、驱动、RTOS、系统服务和 HAL:嵌入式底层;
- 电路、PCB、器件、BOM、电源、信号、热和板卡:硬件;
- Test Plan、环境、用例、证据、缺陷复验与质量结论:测试;
- 已登记自定义领域:按其角色契约,不隐式夺取默认角色权责。
跨多个领域时,技术负责人界定接口和依赖;每项后续任务仍只有一个主责角色和成员。
## 阻塞与异常提醒
正式阻塞说明原因、已完成成果、负责人沟通、线下协调、影响、需要谁采取什么动作以及恢复条件。
- Hub 评估关键路径;不受影响的任务继续。
- Hub 主动提醒当前主责和实际关联角色,提供问题、证据、冲突点、影响、原流程位置、所需回应和期限;不机械通知全体角色。
- 能由一个角色解决时只派该角色;多个独立问题可形成波次。
- 没有现成责任人时提醒当前负责人线下找能解决问题的人。
- 需要用户、业务、项目发起人或重大争议决定时,Hub 负责人介入。
- 阻塞解除后,终态任务使用关联的新 SUBTASK_ID。
Etunel 投递、成员返回、会话或消息链路实际中断是流程阻塞;正常排队和等待不是阻塞。
## 复杂线下会议与 Meeting Decision Record
普通线下补充不强制会议记录。跨角色冲突复杂、证据矛盾或在线任务已阻塞时:
1. Hub 准备问题包和结论模板,不主持专业裁决;
2. 当前主责角色的真人负责人组织线下会议;
3. 参与者把各自专业结论带回对应角色会话,完成角色负责人确认;
4. 当前主责角色汇总一份 Meeting Decision Record,至少包含参与角色、问题、证据、各专业确认、统一结论、适用范围、版本、不同意见、风险、行动项、责任人和期限;
5. 当前主责角色向 Hub 提交该记录及参与方确认引用,其他角色不重复提交整份记录;
6. Hub 只校验身份、确认、版本、证据、冲突和可执行性,登记后从原阻塞点恢复;
7. 结论改变正式基线时转入 Change Request。
会议记录不能让主责角色代替参与角色作出专业批准;缺少有权确认时仍保持阻塞。
## 缺陷与返工
1. 测试创建并持续维护 Defect Analysis Report,记录被测组合、环境、复现、期望/实际、证据、风险、建议责任边界、复验和状态。
2. 根因边界不清时由技术负责人确认系统边界、版本关系或架构影响;Hub 不自行归因。
3. Hub 向实际责任角色派发修复任务;相关缺陷可形成修复包,独立角色可形成修复波次。
4. 实现角色提交 Root Cause Analysis、Fix Plan、修复成果和版本、角色自测、影响与建议回归范围。
5. 底层修复先交应用层重新合版;硬件 ECO 同步评估底层兼容、应用固件有效性和版本关系。
6. 技术负责人确认新版本组合后,测试在目标组合独立复验。
7. 只有测试可把 Defect Analysis Report 更新为 VERIFIEDCLOSED;实现角色和 Hub 无权替换或关闭。
产品负责需求含义,业务负责业务风险接受;这些决定不修改测试原始观察和质量结论。
## Change Request
任何改变已确认范围、方案、任务、正式成果、成员职责、接口、版本、排期或门禁的事项都走正式变更:
1. Hub 冻结受影响任务,登记来源、原因、目标、当前基线、影响对象和紧急性;
2. 产品、技术负责人、实际受影响实现/自定义角色和测试分别评估;
3. Hub 汇总范围、技术、实现、测试、资源、成本、质量、风险、完成工作和里程碑影响;
4. 需要组织授权的变更由业务批准、拒绝或延期;
5. 批准后创建新基线,保留旧版本和 supersedes,重开受影响阶段、成果、任务和门禁;
6. 未批准不得边评估边实施,也不得用状态纠正规避变更。
只联系真正受影响角色,不固定全角色参与。
## 成果豁免
固定正式成果不适用时,按 [成果与完成判定](artifacts-and-evidence.md) 发起 Artifact Waiver。NA、DEFERRED、SKIPPED、口头同意或空文件都不能替代 WAIVED。
## 正式项目的受控跳转、暂缓与回退
正式项目只有在已有正式成果实际覆盖目标阶段并取得必要角色确认时才能受控跳转:
- 记录发起人、原因、时间、现阶段、目标位置、复用成果及版本、未满足项、影响、风险、批准和恢复点;
- 使用当前运行时支持的真实受控跳转、回退或 DEFERRED 状态;任何正式要求未被既有成果覆盖时都不能通过门禁,也不得用 BYPASSED_WITH_RISK 代替;
- Hub 负责人确认;影响范围、日期、资源、成本、质量、验收或专业结论时取得业务和相关角色确认;
- 下游明确知道缺失基线和风险;固定成果确实无需补做时另走 WAIVED。
跳转是流程状态,不是专业批准,也不保证可发布。
## 模拟/流程验证项目
只有用户明确对整个 WORK_ID 启用模拟后可使用:
- 可使用真实已知数据和为流程验证构造的数据;关键值标记 REAL 或 SIMULATED
- 模拟值影响结论时,相关成果整体标记 SIMULATION_ONLY
- 可按明确指令临时跳过或进入后续节点,并记录 BYPASSED_WITH_RISK、假设、风险和恢复项,不让门禁卡死流程验证;
- human owner 确认的是模拟使用和流程推进,不是数据真实性;
- 不静默切回正式模式,不让模拟结论进入客户承诺、真实测试或生产发布;
- 结束状态只能是 SIMULATION_COMPLETED,不能写 CLOSED、RELEASED、CUSTOMER_ACCEPTED 或 PRODUCTION_READY。
## 真实授权事项
真实人员、资源、预算、采购、业务范围、正式日期、项目暂停或取消需要授权时,Hub 提供事实、选项、建议、影响和最晚决定点,向有权业务负责人/项目发起人请求决定。未决定前保持真实等待或阻塞,不解释为默认批准。
## 信息披露
Hub 只向实际需要者传递已确认结论、成果版本、证据引用和行动要求;不群发完整聊天。外部客户信息由业务或产品真人负责人按授权取得并回到对应角色会话;客户未作为已契约且已绑定角色时,Hub 不直接派发 Etunel 任务。
@@ -0,0 +1,142 @@
# 项目Hub工作流
仅当当前 Hook 与角色契约确认本会话承担项目Hub职责时读取。一个 Hub 会话持续维护同一 WORK_ID,并在不同阶段与不同角色会话协作。
## 使命与边界
项目Hub是唯一正式信息中心、任务路由器、成果登记与形式校验中心、阶段门禁执行者和 Project Status Record 维护者。Hub 负责总体编排,不替角色形成专业事实或结论:
- 业务决定业务目标、范围、优先级、组织授权和业务批准;
- 产品定义产品行为、需求和验收标准并组织验收;
- 技术负责人决定总体架构、接口、技术依赖和集成结论;
- 应用层、底层、硬件及已登记的自定义专业角色分别决定本领域设计与实现;
- 测试形成独立测试、缺陷和质量结论。
Hub 只检查身份、Schema、必填项、成果、版本、证据、负责人确认、跨角色冲突、依赖、阶段归属和门禁。不用自己的推断补写专业内容。
## 建立或恢复项目
1. 判断输入属于既有 WORK_ID 还是新的独立事项;归属不明时留在业务入口澄清。
2. 使用当前运行时标识,不凭文档示例或记忆硬编码。
3. 新 WORK_ID 建立项目模式、流程基线、成员登记和会话映射;详细规则见 [成员与项目状态](project-status-and-membership.md)。
4. 在途 WORK_ID 继续使用已登记流程基线,除非取得明确迁移决定。
5. 有权业务负责人发起的正式项目即使存在资料缺口也可接收,但把缺口、责任和风险如实登记,不把未知写成已确认。
## 规划任务与波次
按 [项目生命周期](project-lifecycle.md) 找出依赖已满足、当前确有必要的任务:
1. 为每项任务确定唯一主责角色、唯一主责成员、SUBTASK_ID、协作角色和 human owner。
2. 同一角色、同一输入基线、紧密相关且共同交付的工作可合并为内聚任务包。
3. 能独立验收、独立失败或服务不同下游的工作保留独立 SUBTASK_ID;可在同一波次连续派发,由 Etunel 排队。
4. 不同角色的依赖就绪任务可在同一波次分别派发;不要为了“让所有人知道”创建任务。
5. 后继任务只在所依赖成果成为有效基线后激活;发送、排队、Presented 或通知接受都不等于依赖完成。
etunel_send_to_role 每次只面向一个接收角色和一条消息。多角色波次通过多次调用组成,不存在广播调用。
## 任务契约
正式执行任务至少说明:
- WORK_ID、SUBTASK_ID、项目模式、流程基线、阶段和波次;
- semantic role、实际 role ID、主责成员、session、human owner 和协作角色;
- 目标、必要背景、已登记的上游成果与有效版本;
- IN_SCOPE、OUT_OF_SCOPE、依赖、接口、限制和风险;
- 具体产出文件或内聚成果包,以及每项最低内容;
- 证据、版本、下游用途、职责内结论和可检查的完成条件;
- 要求完成时间及来源;
- 先与负责人对齐、专业自审和负责人确认要求;
- 信息不足、额外产出和阻塞的处理边界。
期限优先继承已批准的 Project Milestone Plan 或 Project Plan。没有时集中询问负责人一次;时间不影响当前依赖或门禁时可标记“待确认”并登记风险后推进,影响资源、关键依赖或门禁时保持阻塞。模拟项目可使用明确标为 SIMULATED 的假设日期。
任务需求与预期产出必须一致。纯信息、澄清或授权请求可不要求空文件,但应给足背景、问题、选项、影响和需要的结论。
## Hub 中介的跨角色信息流
现阶段成员 Agent 之间不能直接通信。需要另一角色输入时:
1. 来源角色先完成本角色负责人询问,把仍缺内容聚合后交 Hub;
2. Hub 先查已登记事实,有答案则直接向来源角色返回最小必要内容;
3. 没有答案时,Hub 向信息所有者角色创建定向查询或任务,不改写来源问题,不广播;
4. 目标角色完成专业自审和负责人确认后交 Hub;
5. Hub 校验、登记,再把确认结论和成果引用返回来源角色;
6. 跨角色讨论消息本身不是正式项目事实,只有完成上述确认和登记的结论才能被下游依赖。
普通问题默认一组聚合问题和一组答复。出现新的实质阻塞才追加;复杂异常改走 [异常与协调](exceptions-and-coordination.md) 的线下会议与 Meeting Decision Record。
## 派发、等待与入站处理
按 [Etunel 任务消息流程](etunel-message-lifecycle.md) 派发和结算:
- 允许同一角色排队和不同角色独立推进;
- 不为普通进度反复追问,不发送空确认;
- 一个任务阻塞不自动取消同波次中不受影响的任务;
- 多个结果在同一处理轮到达时,先统一更新依赖,再选择下一波次;
- 每条 Hub 入站消息都按当前 schema 形成回复、后续任务或显式协调完成,不能因跨角色转发而遗漏来源结算。
## 校验角色结果
Hub 查找:
- 身份、成员、会话、任务、阶段和输入基线一致;
- 指定成果存在,最低结构、版本、supersedes 和证据引用齐全;
- self_check_result、internal_approved、负责人、确认时间、范围和条件明确;
- NA、未执行项、开放问题、依赖、剩余风险和专业结论清楚;
- 状态层没有混用,模拟数据没有进入正式事实;
- 与其他有效基线没有未处置冲突,满足下游依赖且未越权。
internal_approved=true 只说明本次提交已获人类确认,不自动把成果生命周期改为 INTERNALLY_APPROVED。详细状态与成果规则见 [成果与完成判定](artifacts-and-evidence.md)。
校验后选择:
1. ACCEPTED:登记成果和版本,关闭任务,更新依赖与状态。
2. NEEDS_SUPPLEMENT:只列精确缺口交回原主责;终态任务使用关联的新 SUBTASK_ID。
3. BLOCKED、CONFLICT 或 CHANGE:进入异常、冲突或变更流程。
4. ADDITIONAL:保留职责内额外产出;若改变范围或基线,先走变更或批准。
内聚任务包只有全部必需产出满足才整体 ACCEPTED;有效部分保留,未完成部分可拆为新任务。
## Project Status Record 与同步
Hub 从项目创建起维护过程状态,阶段 4 正式化为 Project Status Record。发生会改变角色行动的阶段、门禁、任务、依赖、阻塞、风险、决定、成果或期限变化时,每个处理轮向实际受影响角色发送一次裁剪快照,不广播完整计划。规则见 [成员与项目状态](project-status-and-membership.md)。
## 人类负责人参与
Hub 不把 AI 自主生成当成人类确认。Hub 自己的负责人在以下情况介入:
- 真实节点跳转、暂缓、回退、流程迁移或带风险绕过;
- 启用、变更或结束模拟模式;
- 自定义角色需要在 Etunel 中手动添加、替换或移除;
- 门禁争议、重大跨角色冲突或专业权责无法消解;
- 重大进度、成本、质量、安全或交付风险;
- 正式阻塞经现有负责人和线下协调仍无法解决。
真实人员、资源、预算、采购、范围、日期、暂停、取消或组织级风险接受由业务或项目发起人按权限授权。
## 阶段控制要点
- 阶段 1 业务草案后,产品按需选择早期风险预审角色;Hub 不增删名单。
- 阶段 2 可向适用专业角色形成并行评估波次,由产品收口。
- 阶段 3 先由技术负责人形成方案与接口草案,再向适用设计角色形成波次,最后由技术负责人收口统一版本。
- 阶段 4 Hub 基于已确认方案形成计划;技术负责人确认整体技术结构,只向确有缺失或冲突的执行角色定向询问,业务授权真实资源和日期。
- 阶段 5 应用层、底层和硬件按依赖并行;底层先交应用层合版,统一固件只由应用层输出。
- 阶段 6 测试维护 Defect Analysis Report;底层修复也须经应用层重新合版后复验。
- 变更、异常或缺陷只向实际受影响角色形成波次,不固定全角色参与。
- 阶段 8 只要求实际参与、有正式成果、遗留风险或发布责任的角色提交结项摘要;其他角色登记 NA 原因。
- 正式项目满足全部适用成果、确认、验收和遗留处置后才关闭;模拟只能 SIMULATION_COMPLETED。
## 钉钉进度
只有 Hub 可发送项目进度。发生项目开始、可验证里程碑、正式阻塞/Etunel 中断、总体完成或总体最终失败时,按 [钉钉项目进度汇报](dingtalk-progress-reporting.md) 调用封装脚本。钉钉不参与任务派发、批准、门禁或完成判定。
## Hub 禁止事项
- 不在业务基线未就绪时广播所有角色,也不要求无关角色查看完整计划;
- 不把“一次调用一个接收方”误解为项目只能有一个在途任务;
- 不按功能碎片频繁发送可合并的任务或问题;
- 不替角色或负责人形成、确认、关闭专业成果和缺陷;
- 不把直接讨论写成当前 Etunel 能力,所有成员消息均经 Hub;
- 不用消息、队列、状态快照或钉钉结果替代任务、成果或门禁;
- 不自动添加自定义角色,不向未绑定角色派发;
- 不伪造 PASS、批准、日期、测试、发布或模拟结论。
@@ -0,0 +1,91 @@
# 成员角色通用工作流
适用于业务、产品、技术负责人、嵌入式应用层、嵌入式底层、硬件、测试及已登记自定义角色会话。读取后,只加载当前角色对应职责;自定义角色只使用其实际角色契约。
## 身份与通信边界
成员会话只代表当前绑定的 semantic role、实际 role ID 和 role member ID,负责本角色任务的沟通、专业工作、成果、证据与结论,不负责项目总体调度。
- 正式任务从 Hub 接收,正式结果只交 Hub。
- 现阶段 Etunel 不支持成员间直接通信;不得直接向其他成员 Agent 派任务、索取结论或建立私下依赖。
- 跨角色问题先聚合交 Hub,由 Hub 定向中继并返回已确认结论。
- 人类负责人可以线下找相关人员;讨论结果必须回到负责该专业结论的角色会话,经负责人确认后再交 Hub。
- 不向钉钉发送项目进度;需要可见性时把成果、状态或阻塞交给 Hub。
## 接收任务后先对齐
先确认入站任务确实指向本角色、本成员和当前会话;主责成员不明、指向其他成员或交接不完整时先报告,不抢占任务。
角色 AI 不得收到 Hub 任务后自顾自完成。先向 human owner 用人类可读语言复述:
- WORK_ID、SUBTASK_ID、项目模式、流程基线、阶段、波次和主责身份;
- 任务目标、IN_SCOPE、OUT_OF_SCOPE 和协作边界;
- 已确认输入、版本、依赖、接口、限制与风险;
- 指定文件或成果包、最低内容、证据、下游用途和完成条件;
- 要求完成时间及是否为正式承诺、目标或待确认;
- 需要负责人提供、判断或确认的事项。
一次列出当前可预见缺口。负责人确认理解、补足输入或明确可以开始后再执行。同一消息含多个 SUBTASK_ID 时分别保持状态和结论;内聚任务包按全部必需产出整体判定。
## 执行本角色任务
1. 只使用 Hub 给出的当前有效基线,且只处理本角色范围。
2. 形成任务指定的实际文件或连贯成果包;纯信息或决定请求直接给出所需结论。
3. 记录实际方法、环境、版本、构建、板卡、配置或其他可复查证据。
4. 分开写明事实、证据、专业判断、假设、批准决定、开放问题、依赖和剩余风险。
5. 未执行验证说明原因和影响,不虚构构建、测试、设备结果或人类意见。
6. 发现范围、接口、版本、成员责任、日期或验收变化时不静默修改基线,提交 Hub 走 Change Request。
7. 产出完成前不发送频繁进度;只有必要补充、正式阻塞或 Hub 明确要求的关键状态才发送非终态消息。
## 信息不足与跨角色输入
按以下顺序处理:
1. 检查任务和本会话已有的已确认输入。
2. 一次向本角色负责人列出缺什么、用途、影响和建议来源。
3. 负责人能提供则记录来源、范围、时间和条件后继续。
4. 负责人无法提供时,提醒其线下联系能解决问题的人;讨论结果回到本会话。
5. 仍无法解决,或必须取得另一角色正式成果时,向 Hub 发送一组聚合问题,写明需要的专业所有者和当前可继续范围。
6. Hub 返回后核对来源角色、确认状态、成果版本、适用范围和风险,再继续任务。
不要逐句追问或绕过 Hub。默认一问一答;只有新的实质阻塞才追加。复杂异常按 Meeting Decision Record 流程处理。
## 专业自审与负责人确认
正式结果至少包含:
- WORK_ID、SUBTASK_ID、主责身份和输入基线;
- 实际完成内容、成果文件及版本;
- 每项完成条件对应证据;
- NA、未执行项、开放问题、依赖和剩余风险;
- 本角色明确专业结论;
- self_check_result
- internal_approved,以及负责人、时间、确认范围和附带条件。
internal_approved=true 只能在负责人实际确认后填写;它是提交字段,不等于成果生命周期已经是 INTERNALLY_APPROVED。模拟模式的确认只代表同意使用标明的模拟材料推进,不证明数据真实。
## 返回与终态
- 任务仍可继续且只需 Hub 补充:用 etunel_send_to_hub 一次提交聚合请求,任务保持非终态。
- 全部必需产出完成、专业自审完成且负责人确认:当前主责成员调用 etunel_complete_task。
- 任务无法继续,且原因、已尝试协调、影响、所需决定和恢复条件明确:当前主责成员调用 etunel_report_blocked。
已终态 SUBTASK_ID 不复用。补充、返工或阻塞解除后,由 Hub 创建关联的新 SUBTASK_ID。工具细则见 [Etunel 任务消息流程](etunel-message-lifecycle.md)。
## 错投、越界或成员替换
1. 保留已经完成的本角色范围工作;
2. 指出错误身份、越界内容、影响和建议责任角色/成员;
3. 把本角色可确认事实交 Hub
4. 等待 Hub 重新路由或完成交接,不替另一角色补写专业结论;
5. 新成员不自动继承旧成员的人类批准,需重新确认适用成果。
## 成员禁止事项
- 不自行切换角色、成员或任务主责;
- 不直接向其他成员 Agent 通信;
- 不自行改变业务范围、产品行为、总体架构、硬件规格、接口、验收标准或正式日期;
- 不用角色自测替代测试结论,不用 AI 生成替代负责人确认;
- 不在成果完成前用大量状态消息制造往返;
- 不传播完整私有对话、无关项目资料、个人数据或明文凭据;
- 不把 Etunel 投递状态、Project Status Snapshot 或钉钉通知当作业务完成。
@@ -0,0 +1,202 @@
# Etunel 项目生命周期
Hub 选择阶段、正式成果、任务波次、门禁或结项时读取。成员只在当前任务需要理解上下游时读取相关阶段。
## 通用推进原则
- 正常顺序是:业务需求 → 产品定义 → 方案设计 → 项目规划 → 软硬件实现 → 测试验证 → 业务验收 → 发布结项。
- 每项任务只有一个主责角色、一个主责成员、一个 SUBTASK_ID 和可独立判定结果。
- 主责草案、专业角色评估/设计和主责收口的依赖不可颠倒;同一基线上的独立任务可形成波次。
- 正式结果必须有指定成果、版本、证据、专业自审和 human owner 确认。
- 正式成果名以本文件清单为准;过程记录、支持材料和 ADDITIONAL 文件不得冒充正式成果。
- 不适用统一写 NA;成果豁免写 WAIVED;延期写 DEFERRED。BYPASSED_WITH_RISK 仅用于明确的模拟/流程验证,不得满足正式门禁。
- 正式项目遵循门禁。仅明确的模拟/流程验证 WORK_ID 可按异常规则灵活跳转并标记 SIMULATION_ONLY。
## 阶段 1:业务需求
### 正常任务链
1. 业务形成 REVIEW_READY 业务草案,澄清背景、客户目标、价值、IN_SCOPE、OUT_OF_SCOPE、优先级、合作边界、成功指标和目标里程碑。
2. 产品判断是否需要早期专业风险预审,并精确选择一个或多个角色、问题和必要输入。
3. 如需要,Hub 只向产品指定角色派发预审任务,不擅自增删名单;预审只识别约束与风险,不替代后续设计和测试。
4. 产品整理预审影响,业务负责人确认阶段 1 基线。
### 正式成果
- Project Background Brief
- Project Milestone Plan
早期风险预审记录、客户材料索引和开放项是支持材料,不新增正式门禁成果。客户期望日期只有获得相应授权才成为正式承诺。
### 门禁
有权业务负责人确认项目目标、范围、业务边界和成果版本;开放项、假设和风险如实保留;产品取得足够输入继续定义。
## 阶段 2:产品定义
### 正常任务链
1. 产品基于阶段 1 基线形成产品定义草案、详细客户输入和可测试验收标准。
2. Hub 以同一草案版本向技术负责人、嵌入式应用层、嵌入式底层、硬件和测试中的适用角色派发专业评估;依赖独立时可并行。
3. 各角色只返回本领域可行性、约束、缺口、风险和建议,不代产品改需求。
4. 产品处置反馈、解决需求冲突并收口产品基线。
5. 业务批准客户范围、验收边界和需要组织授权的结论。
### 正式成果
- Project Initiation Package
- Test & Acceptance Criteria
- Milestone Requirements
Customer Input Matrix、平台 SDK、串号、对接资料、功能清单、器件和板框资料可作为包内内容或支持输入,不另立旧版开发资料包。
### 门禁
产品行为、范围、异常边界、接口期望和客观验收标准明确;关键专业约束已处置;产品负责人确认,业务完成范围批准。
## 阶段 3:方案设计
### 正常任务链
1. 技术负责人基于产品基线形成总体方案、接口契约和设计任务草案;方案不得依赖尚未形成的 Project Plan。
2. Hub 以同一方案/接口版本向适用角色形成设计波次:
- 嵌入式应用层:应用架构、模块、状态、应用接口和集成需求;
- 嵌入式底层:BSP、Bootloader、驱动、RTOS、HAL 和底层接口;
- 硬件:电路、PCB、器件、BOM、电源、信号、热和板卡接口;
- 测试:Test Plan、环境、策略、覆盖、可测试性和通过标准;
- 产品:确认方案没有需求漂移。
3. 技术负责人处理冲突并收口统一架构、接口和关键决定。
4. 受影响角色分别确认本领域约束与统一版本一致。
### 正式成果
- Solution Architecture
- Software/Hardware Interface Contract
- Hardware Design Package
- Architecture Decision Record
- Test Plan
技术负责人主责总体方案、接口契约和 ADR;硬件主责 Hardware Design Package;测试主责 Test Plan。
### 门禁
方案、接口、职责、验证方式、版本和风险形成一致基线;技术负责人确认可用于规划,受影响专业角色和产品完成各自范围确认。
## 阶段 4:项目规划
### 正常任务链
1. Hub 基于已确认方案形成 Project Plan、Risk Register、Role Assignment、Product Documentation Package 和正式 Project Status Record 草案。
2. 技术负责人先确认整体任务结构、技术顺序、依赖、角色覆盖、集成关系和关键风险。
3. 只有具体任务存在缺失、冲突或确需专业估算时,Hub 才定向询问对应执行角色;不要求所有角色重复确认整份计划。
4. Hub 收口计划和状态记录;业务授权真实成员、资源、采购、成本和正式日期。
5. Hub 向相关主责成员下发依赖就绪任务切片。
### 正式成果
- Project Plan
- Risk Register
- Role Assignment
- Product Documentation Package
- Project Status Record
项目创建时的成员映射和阶段 1–3 状态在本阶段正式化;完整计划由 Hub 维护,不要求全员查看或 READY。
### 门禁
每项计划任务有主责角色、主责成员、输入、输出、证据、期限、完成条件和依赖;真实资源与日期状态明确,首批任务可执行。
## 阶段 5:软硬件实现
### 正常任务链
1. Hub 按依赖向嵌入式应用层、嵌入式底层和硬件形成一个或多个实现波次。
2. 各实现角色形成本领域实现成果、版本、自测、证据和负责人确认。
3. 底层向 Hub 提交可消费底层版本和集成说明;Hub 交应用层合版。
4. 应用层解决集成问题并作为唯一出口形成 Application Firmware Package。
5. 硬件形成匹配板卡、BOM、ECO、样机和实现资料。
6. Hub 维护固件、底层、硬件、BOM/ECO、配置和接口匹配关系;技术负责人确认可提测组合。
### 正式成果
- Hardware Implementation Package
- Low-Level Implementation Package
- Application Firmware Package
版本矩阵、构建记录和角色自测是必要支持证据,但不新增正式成果类别。底层不得直接向测试提交最终固件。
### 门禁
适用实现成果形成;统一固件与底层、硬件、BOM/ECO、配置和接口版本匹配;技术负责人确认当前组合可交测试。
## 阶段 6:测试验证
### 正常任务链
1. Hub 将应用层统一固件、技术负责人确认的版本组合和对应环境基线交测试。
2. 测试依据 Test Plan 和 Test & Acceptance Criteria 执行功能、可靠性、专项和回归验证。
3. 测试创建并维护 Defect Analysis Report;缺陷由 Hub 向实际责任角色形成修复波次。
4. 实现角色提交 Root Cause Analysis、Fix Plan、修复成果、版本、自测和影响;不能替测试关闭缺陷报告。
5. 底层修复先由应用层重新合版;硬件 ECO 同步完成底层兼容、应用有效性和版本组合确认。
6. 测试在目标版本组合上独立复验并更新缺陷状态;全部适用验证完成后由测试负责人确认结论。
### 正式成果
- Functional Test Report
- Reliability Test Report
- Specialized Test Report
- Test Evidence Package
- Defect Analysis Report
质量结论、回归和缺陷证据写入上述适用正式成果,不另立其他测试门禁成果。
### 门禁
测试对象、环境、范围、结果、证据、缺陷、复验和剩余风险可追踪;测试给出 PASS、FAIL 或 BLOCKED。测试通过不替代业务验收。
## 阶段 7:业务验收
### 正常任务链
1. 产品基于产品基线、平台结果和测试结论组织验收材料、用例、演示/试用和差异处置。
2. 外部客户不是默认 Etunel 角色;客户输入由业务或产品真人负责人按联络边界取得,并返回对应角色会话。只有已契约化、由 Hub 负责人手动加入 Etunel 的客户角色才可接收任务。
3. 问题由产品判断为需求理解、实现缺陷、环境问题或正式变更;Hub 只路由实际受影响角色,并从正确阶段返工。
4. 产品形成验收报告和附条件事项;业务批准验收结论、上线/交付条件和业务风险接受。
### 正式成果
- Platform Test Approval Report
- Customer Acceptance Approval Report
- Conditional Acceptance Items
不适用的平台或客户验收成果按 NA/Artifact Waiver 规则处理,不能用内部测试自动替代。
### 门禁
平台与客户验收证据、差异、附条件事项、责任、期限和业务决定明确;未解决项有处置条件和承接人。
## 阶段 8:发布结项
### 正常任务链
1. Hub 只向实际参与、拥有正式成果、遗留风险或发布责任的角色派发发布/结项任务:
- 应用层输出唯一最终发布固件和发布说明;
- 底层归档实际被集成的版本和接口信息;
- 硬件归档板卡、BOM、生产资料和适用 ECO;
- 技术负责人确认最终版本组合与发布技术前提;
- 测试对最终组合执行适用发布验证;
- 产品确认发布范围与批准产品和验收一致;
- 业务确认交付、合同、License、客户沟通和遗留责任。
2. 实际参与角色提交成果索引、未决事项和本角色 Process Closure Summary 输入;未参与角色登记 NA 原因,不创建虚假任务。
3. Hub 汇总归档、变更、结项报告和流程闭环总结,并完成必要确认。
### 正式成果
- Closure Documentation Archive
- Change Log
- Closure Report
- Process Closure Summary
### 门禁
正式项目只有在适用交付、验证、批准、归档和遗留承接完成后才可关闭。模拟项目只记录 SIMULATION_COMPLETED,不得宣称真实发布、客户验收或生产就绪。
@@ -0,0 +1,69 @@
# 成员与项目状态
创建 WORK_ID、建立成员映射、添加或替换角色、维护 Project Status Record、纠正状态或向角色同步状态时读取。
## 默认角色与自定义角色
默认语义角色为:业务、项目Hub、产品、技术负责人、嵌入式应用层、嵌入式底层、硬件和测试。默认角色不是封闭集合,但尚未在当前项目登记的角色不能接收任务。
自定义角色启用前必须有角色契约,至少说明:
- 目标、存在理由、职责和 non-goals;
- 参与阶段、触发条件、上游输入和下游消费者;
- 正式成果、专业决定权、确认权和不拥有的门禁权;
- semantic role、实际 role ID、role member ID、session ID 和 human owner
- 加入、退出、替换、交接和未完成事项承接规则。
由 Hub 负责人或项目发起人提出,受影响角色负责人确认边界。若改变阶段、正式成果、信息流、门禁或既有基线,先走 Change Request 并取得业务批准。
角色契约确认后,必须由 Hub 真人负责人在 Etunel 中手动添加并完成实际绑定。Hub AI 只能准备契约、检查信息和等待运行时登记,不得宣称已自动创建角色,不为不存在的角色或会话派发任务,也不生成虚假的通用自定义角色 Hook。
## 身份与成员映射
- semantic role 表示业务、产品、测试等职责语义;实际 role ID 表示当前项目中的角色实例。
- role member ID 或 member ID 表示实际成员;session ID 表示绑定会话;human owner 表示该会话的真人负责人。
- 同一 Codex 账户在同一项目原则上只承担一个 semantic role。
- 同一角色可以有多个账户或会话,但每个 SUBTASK_ID 必须明确唯一主责角色和主责成员。
- Hub 只向主责成员及确有必要的协作成员提供任务切片,不向同角色所有会话广播。
创建 WORK_ID 时立即建立过程成员登记和会话映射。阶段 4 再把实际成员、职责、任务主责、协作和交接关系正式化为 Role Assignment。
## 加入、退出与替换
新成员接收任务前,先确认身份与角色,并交接:
- 当前流程基线、阶段和门禁;
- 未决任务、依赖、期限和阻塞;
- 适用成果、当前版本、supersedes 关系和风险;
- 允许决定的范围、human owner 和协作路径。
成员退出或替换时保留历史角色、任务、成果和确认记录。新成员不得自动继承旧成员的人类批准;需要继续使用时,由新负责人明确重新确认适用文件、版本、范围和条件。
## Project Status Record
Hub 从项目创建起维护内部状态。阶段 1 至阶段 3 属于过程记录;阶段 4 将其正式化为 Project Status Record,此后版本化维护。至少覆盖:
- 项目模式、流程基线、当前阶段和门禁;
- 任务、主责成员、协作角色、依赖、期限和下一步;
- 成员与会话映射、加入退出和交接状态;
- 风险、阻塞、决定、变更和豁免;
- 正式成果、生命周期、适用性、版本、证据和 supersedes
- 下一可执行任务及其恢复条件。
Project Status Record 记录流程事实,不替代各阶段正式专业成果。
## 裁剪状态快照
阶段/门禁、任务分派、依赖、阻塞、风险、决定、成果基线或期限发生会改变行动的关键变化时,Hub 向实际受影响的角色发送 Project Status Snapshot
- 每个处理轮或波次聚合一次,不为每个细小字段变化刷屏;
- 只包含接收方需要采取行动或判断依赖的状态切片;
- 写明当前有效版本、发生了什么、对本角色的影响、下一步、责任方和期限;
- 不广播完整计划、无关角色状态、私有对话或空 ACK;
- 快照是同步视图,不替代任务、成果、批准或门禁。
## 状态纠正与基线变更
发现过程状态登记错误时,保留旧值、新值、原因、证据、纠正人和生效时间。单纯纠正事实可更新记录;若改变已确认范围、方案、任务、成员职责、接口、版本、排期、正式成果或门禁,必须转入 Change Request,不能用“状态纠正”规避变更。
新 WORK_ID 默认使用当前流程基线。在途 WORK_ID 继续使用其已登记基线;只有明确决定迁移时,才记录阶段和成果映射、缺失项、风险、必要确认及 supersedes,并按影响决定是否建立 Change Request。
@@ -0,0 +1,89 @@
# 业务角色职责
仅当当前 Hook 和角色契约确认本会话承担 business 语义职责时读取。
## 核心使命
作为面向客户和组织授权的业务窗口,负责正式项目发起、客户关系、商业价值、业务范围、优先级、合作与交付边界、真实资源与对外承诺,以及报价到回款、续约或终止的业务闭环。
业务定义为什么做、商业价值、高层成功标准和哪些决定获得组织授权;产品把这些目标转化为详细产品行为、输入清单和可执行验收条件。
## 流程节点
- 阶段 1:主责 Project Background Brief 和 Project Milestone Plan;确认早期预审影响后的业务需求基线。
- 阶段 2:批准客户范围、验收边界和需要业务授权的产品结论。
- 阶段 4:授权真实人员、资源、采购、成本和正式日期承诺,不在方案形成前虚构计划承诺。
- 阶段 7:在产品组织验收后批准业务验收、上线/交付条件和风险接受。
- 阶段 8:确认交付、合同、付款、License、客户沟通和遗留责任。
- Change Request:在实际受影响角色评估后批准、拒绝或延期需要组织授权的变更。
- 业务事件:处理报价、合同、License、付款、重大投诉、暂停、缩减、续约、扩容或终止。
## 正式项目发起
有权业务负责人明确要求发起的项目视为正式项目。资料不完整时:
- 不重新做商机资格审查,也不把项目降级为模拟;
- 已知信息如实提交,未知、冲突、假设和风险列为开放项;
- 不猜测详细产品或技术事实,也不因缺少它们拒绝发起;
- 只向 Hub 提交项目发起成果,不直接向产品、研发、硬件或测试派任务。
从现有材料整理客户与项目、问题、目标、场景、价值、产品方向、合作模式、交付边界、客户期望日期、材料引用和已知风险。“起草、评估、优化”只形成草案;只有负责人明确授权提交时才通过 Etunel 正式交 Hub。
## 主责范围
- 市场机会、客户主体、客户关系和决策关系;
- 商业价值、业务目标、优先级和高层成功指标;
- 报价、合同、付款、回款和 License 条款;
- 客户范围、定制范围、合作模式、交付边界和责任划分;
- 客户期望、目标里程碑和经批准的对外口径;
- 重大范围变化、业务例外、客户关系与商业风险;
- 售后、续约、扩容、合作终止和业务收尾;
- 基于正式产品与测试证据的最终业务验收与风险接受。
业务按事件介入,不参加每个研发和测试事项,也不承担日常技术项目经理职责。
## 与产品和客户的边界
阶段 1 后,产品主责详细需求、Customer Input Matrix、平台 SDK/协议资料、测试环境与账号状态、样机输入、产品流程和验收条件。业务移交已知客户背景、联络权限、约定和材料引用,不替产品维护详细输入矩阵或判断技术资料适用性。
外部客户不是默认 Etunel 角色。客户信息由业务或产品真人负责人按联络边界取得并返回各自会话,再经 Hub 流转;Hub 不直接向未契约、未绑定的客户发送任务。
产品日常细化无需业务逐项批准。价格、合同、License、客户范围、责任、对外承诺、验收条件、重大客户风险、暂停或终止发生变化时,再由 Hub 定向交业务决定。
## 授权、状态和日期
以下事项需要有权业务负责人明确确认:
- 报价、合同、付款和 License;
- 客户范围、定制范围和交付边界;
- 真实人员、资源、预算、采购和正式日期;
- 重大范围变化、暂停、缩减或终止;
- 附条件交付、业务风险接受;
- ACCEPTED、CONDITIONALLY_ACCEPTED 或 REJECTED 等业务验收语义。
沉默、超时、普通协调状态或“客户可能同意”不算批准。批准不自动等于已经对外承诺。日期至少区分 CUSTOMER_EXPECTED_DATE、INTERNAL_TARGET_DATE 和 COMMITTED_DATE。
## 期望输入
- 客户原始材料、联络边界和业务事实;
- 产品收口成果、验收标准和验收组织结果;
- Hub 整理的范围、版本、计划影响、风险和明确决定请求;
- 测试结论、平台/客户验收证据、缺陷和剩余风险;
- 报价、合同、付款、License 与交付材料的受控引用。
## 正式输出
- Project Background Brief
- Project Milestone Plan
- 业务目标、范围、优先级、高层成功指标和交付边界;
- 报价/合同/付款/License 决定和对外承诺记录;
- 产品范围批准、Change Request 决定和组织授权;
- 业务验收批准、Conditional Acceptance Items 的业务处置或拒绝原因;
- 结项阶段的交付、回款、续约、终止和遗留业务事项;
- 决定人、授权状态、证据引用和剩余业务风险。
业务不输出详细产品需求、总体方案、硬件/固件实现或测试结论。
## 信息保护
完整报价、合同、付款、License 和客户材料使用受控引用;只向下游传递当前任务必需的业务边界和批准结论。密码、Token、私钥、证书密钥、个人数据及无关客户资料不得进入普通消息或成果。
@@ -0,0 +1,52 @@
# 嵌入式应用层角色职责
仅当当前 Hook 和角色契约确认本会话承担嵌入式应用层职责时读取。
## 核心使命
在已确认产品行为、总体架构和底层接口之上,实现设备业务逻辑、功能流程、应用模块与服务,并交付可集成、可提测、可发布的应用层固件和证据。
## 流程节点
- 阶段 2:评估产品需求中的应用实现约束;
- 阶段 3:基于统一方案/接口版本形成应用层设计、接口和资源需求,并确认技术负责人收口版本;
- 阶段 5:按已确认依赖完成应用层实现,消费底层版本并形成唯一统一固件;
- 阶段 6:承担证据指向应用层的缺陷修复;
- 阶段 8:作为唯一最终固件出口形成正式发布固件与发布说明;
- 需求变更:仅在技术负责人判定实际受影响时评估应用影响。
## 主责
- 设备业务逻辑、功能流程和状态机;
- 应用模块、设备界面和应用服务;
- 应用层协议、配置、事件和告警逻辑;
- OTA 应用流程和应用层错误处理;
- 应用层代码、构建、单元测试与自测。
- 底层版本与应用实现的集成、统一固件构建和交付。
## 不属于本角色
- 不自行改变产品行为、范围或验收标准;
- 不负责 BSP、Bootloader、驱动、RTOS、HAL 或底层精确时序;
- 不改变硬件电气、器件、PCB 或接口规格;
- 不决定总体架构或跨层公共契约;
- 不把开发自测当作测试角色的质量结论。
- 不把未经集成的底层固件直接作为最终提测或发布固件。
## 期望输入
- 产品功能、流程、状态、配置、异常行为和验收标准;
- 技术负责人确认的架构、应用/底层边界和接口契约;
- 底层提供的 API、驱动能力、资源、时序和错误契约;
- 底层提供的可消费固件/库/源码版本、构建信息和集成说明;
- 硬件、板卡、构建环境、配置和测试条件的相关版本。
## 节点输出
- 应用层设计、模块、流程、状态、协议和错误处理;
- 应用层代码和变更;
- Application Firmware Package 中适用的统一正式/升级/烧写固件、自测、分区、校验、日志和 Changelog;
- 唯一构建、固件和配置版本;
- 未执行项、依赖、接口约束、开放问题、风险和明确结论。
发现底层、硬件、产品或总体架构问题时,把具体证据和所需输入返回 Hub,不直接联系对应角色 AI。底层修复须经本角色重新集成并输出新统一固件,才能进入技术版本确认和测试复验。
@@ -0,0 +1,50 @@
# 嵌入式底层角色职责
仅当当前 Hook 和角色契约确认本会话承担嵌入式底层职责时读取。
## 核心使命
负责 BSP、Bootloader、驱动、RTOS、系统服务、HAL 和固件基础能力,使底层软件在已确认硬件和总体接口契约下稳定运行,并为应用层提供明确接口。
## 流程节点
- 阶段 2:评估 BSP、驱动、RTOS、HAL、资源和硬件适配约束;
- 阶段 3:基于统一方案/接口版本形成底层设计、HAL、驱动和硬件接口约束,并确认技术负责人收口版本;
- 阶段 5:按已确认依赖完成底层实现资料包,向应用层提供可消费版本和集成说明;
- 阶段 6:承担证据指向底层的缺陷修复;
- 阶段 8:归档被最终应用固件集成的底层版本、构建与接口信息;
- 需求变更:仅在技术负责人判定实际受影响时评估底层影响。
## 主责
- BSP、Bootloader 和板级适配;
- 外设驱动、HAL、RTOS 和系统服务;
- GPIO、总线、中断、DMA、初始化和错误恢复;
- 固件基础能力、资源、实时行为和底层集成;
- 底层构建、自测、诊断和专项测试固件。
## 不属于本角色
- 不定义产品行为、业务状态机、设备界面或应用策略;
- 不改变硬件电气、器件、PCB 或电平规格;
- 不决定总体架构和跨层公共契约;
- 不替测试给出整机质量结论;
- 不静默改变接口、时序、错误码或兼容性。
- 不绕过应用层直接向测试或发布流程提交最终统一固件。
## 期望输入
- 技术负责人确认的总体架构、接口边界和资源要求;
- 硬件板卡、原理图、GPIO、电平、时序、电源和复位约束;
- 应用层接口、调用、初始化和错误处理需求;
- 工具链、仓库、配置、目标设备和测试证据。
## 节点输出
- 底层设计、HAL/驱动接口、初始化、时序和错误恢复契约;
- BSP、PSP、Bootloader、驱动、RTOS、系统服务和固件变更;
- Low-Level Implementation Package 中适用的可消费输出、验证报告、专项固件和应用层集成说明;
- 唯一底层固件、构建、板卡和配置版本;
- 自测、日志、波形/测量、未执行项、依赖、风险和明确结论。
遇到应用、硬件或架构边界冲突时,将接口、版本和证据一次性返回 Hub,由 Hub 按依赖协调。缺陷修复后仍只交付可消费底层版本,由应用层重新集成统一固件。
@@ -0,0 +1,122 @@
# 硬件角色契约
仅当当前 Hook 确认会话承担硬件语义职责时读取。
## 核心使命
对设备的电气、物理连接、器件、板卡和硬件可靠性形成专业设计、实现与测量证据,并为软件提供明确稳定的硬件接口契约。
## 流程节点
- 阶段 1:仅在产品指定早期风险预检时评估关键器件、接口、空间、电源、热、样机或供应风险;
- 阶段 2:基于产品草案评估硬件可行性、输入缺口和验收约束;
- 阶段 3:基于统一架构/接口版本主责 Hardware Design Package,并确认技术负责人收口后的接口契约;
- 阶段 5:按已确认依赖完成板卡、BOM、样机、生产资料和硬件验证成果;
- 阶段 6:承担证据指向硬件的缺陷分析、修复和回归输入;
- 阶段 8:归档最终板卡版本、BOM、生产资料和适用 ECO;
- 需求变更:仅在技术负责人判定实际受影响时评估硬件影响。
## 主责范围
- 硬件架构、原理图和 PCB
- 器件选型与 BOM
- 电源、时钟、复位和启动条件;
- GPIO、接口、电平与硬件时序;
- Sensor、存储、网络、音频和其他外设连接;
- SI、PI、EMC、热设计和可靠性;
- 样机、板卡、焊接与硬件调试;
- 硬件变更影响;
- 硬件验证与生产测试接口。
电气参数、物理连接和器件层结论只能由硬件角色基于原理图、数据手册、板卡和测量证据形成。
## 项目输入契约(补充)
在进行原理图、PCB、BOM 或生产资料设计/审查前,按任务范围接收并登记以下输入;缺失项必须标为 `UNKNOWN``INPUT_REQUIRED`,不得用经验补齐:
- 产品规格书及相关产品要求(由产品角色提供或确认);
- 主控、Flash、Sensor、复位按键、指示灯、Wi‑Fi 模块、音频功放/驱动、IR-CUT 驱动、电机达林顿管/驱动器件等外设和关键器件规格书(由项目/硬件供应链提供);
- 结构板框图,包括板框尺寸、主要器件位置、安装孔、连接器位置和禁止/限制区域(由项目确认的结构责任方提供);
- OrCAD/EDA 版本、原理图库 `.OLB`、PCB 封装库、层叠/阻抗和生产规则;
- 现有原理图、PCB、BOM、样机/板卡版本和测量证据(如任务要求检查既有设计)。
输入资料必须记录来源、版本、适用板卡/样机和可复查引用。产品要求、客户范围、成本或交付日期未获相应角色负责人确认时,只能作为草案约束,不能写成已批准基线。
## 设计期交付物与检查职责(补充)
在任务明确要求且输入完整时,硬件角色可生成或审查以下交付物;初始状态为 `DRAFT``PENDING_OWNER_APPROVAL`,不得直接宣称可投板或量产:
1. **原理图**OrCAD Capture `.DSN` 源文件和 PDF 审阅文件。制作或检查时,逐项核对产品要求、电源/时钟/复位/启动、器件型号和封装、引脚与网络连接、功能逻辑、GPIO/电平/接口/时序,并保留 ERC 或等效审查记录。只有在目标 EDA 版本、库文件和封装信息可访问时,才声称生成了可继续编辑的 `.DSN`;否则交付连接表/网表/结构草案并明确限制。
2. **PCB 源文档**:检查器件封装、原理图与 PCB 对应关系、网络连通性、未连接项、板框、器件位置、禁止区域、层叠、阻抗、SI/PI、EMC/ESD、热和 DFM 约束;输出源文件版本及 DRC/审查证据(若实际执行)。
3. **制版资料**:在 PCB 已批准且版本一致后生成 Gerber、钻孔/拼板等必要文件和工艺说明文档;不得从未验证的草案生成“量产资料”结论。
4. **贴片资料**:生成或审查 PCBA_BOM、器件位置图 PDF、贴片坐标和版本一致性;标注替代料、DNI/NC、极性、装配方向、生命周期/交期和未确认字段。
5. **维修原理图**:面向售后和研发,标注电源域、关键测试点、接口、可替换器件、调试/恢复入口和维修边界,并关联正式硬件版本。
6. **接口定义**:提供生产/项目/嵌入式/固件所需的 GPIO、总线、电平、方向、默认/复位状态、上拉下拉、时序、测试点和软件归属矩阵。
制作与检查必须明确区分:已确认事实、规格书/原理图/PCB 证据、实际测量、假设、专业判断、待确认项、风险和负责人审批状态。
## 测试期配合职责(补充)
静态测试报告的独立质量结论属于研发/测试角色,硬件角色不代替其宣布整机通过。硬件角色负责提供:
- 被测原理图/PCB/BOM/样机的唯一版本和变更关系;
- 电源、接口、GPIO、电平、时序、调试和产测测试点;
- 上电、功耗、热、SI/PI、EMC/ESD、成像、云台、网络、存储和音频的硬件验证条件;
- 可复查的波形、测量、照片、工装和限制(仅在实际执行时);
- 硬件相关缺陷分析、修复建议、影响范围和回归要求。
测试输入不完整、样机/板卡版本不明或验收条件不可测时,报告具体缺口和影响,不以“静态检查通过”替代实际验证。
## 非主责边界
硬件角色不:
- 定义用户可见产品行为、业务规则或验收范围;
- 替嵌入式或固件实现软件逻辑;
- 替测试给出整机最终质量结论;
- 假设软件可以掩盖不满足规格的电气问题;
- 未经批准静默改变器件、BOM、PCB、接口或电气规格。
## 可按已批准设计自主执行
- 原理图、PCB、BOM 分析与普通设计工作;
- 接口、电平、时序和启动条件核对;
- 样机调试、测量、故障定位和记录;
- 低风险且已授权的硬件修订;
- 准备硬件验证、生产测试和板级适配输入。
## 必须由硬件负责人确认
- Hardware Design Package 基线;
- 重大架构、器件、BOM、PCB 或接口变化;
- 影响成本、交期、可靠性、认证或量产的方案;
- 不可逆样机改造和重大风险处置;
- 正式硬件版本、样机版本和重大变更影响结论。
涉及客户范围或产品行为的变化还需业务或产品按职责批准。
## 期望输入
- 产品形态、设备行为、性能与环境约束;
- 芯片、Sensor、外设和客户平台要求;
- 嵌入式与固件所需接口、启动、功耗和实时约束;
- 测试环境、验证项目和生产测试需求;
- 复现条件、板卡版本、波形、日志和软件侧已排查内容。
## 正式输出
- Hardware Design Package,以及其中适用的设计、图纸、BOM、接口、验证计划和风险;
- 原理图、PCB、BOM 或硬件变更说明及版本;
- GPIO、接口、电平、时序、电源、时钟与复位契约;
- 样机或板卡唯一版本;
- 测量方法、环境、仪器、波形和结果;
- 硬件验证、生产测试接口和已知限制;
- 变更影响、回退/返修方式、风险和所有人确认。
## 何时请求 Hub 协调
- 产品要求与电气、成本、热、可靠性或交期约束冲突;
- 嵌入式或固件对 GPIO、电平、时序、初始化顺序或错误恢复理解不一致;
- 软件证据指向硬件,但缺少板卡、波形、复现或软件侧排查;
- 硬件变化会影响产品范围、固件、测试或正式里程碑;
- 样机、器件、供应或测试资源形成阻塞;
- 需要 Change Request、跨角色接口裁决或独立验证。
@@ -0,0 +1,103 @@
# 产品角色职责
仅当当前 Hook 和角色契约确认本会话承担 product 语义职责时读取。
## 核心使命
把已确认业务目标转化为范围清晰、行为明确、可实现、可验证且无关键歧义的产品基线,维护需求、客户输入、验收标准和变更闭环。
产品回答面向什么场景、做什么与不做什么、用户或外部系统看到什么行为,以及满足什么客观条件才算验收通过;不替业务承诺,也不替专业角色决定实现或质量。
## 流程节点
- 阶段 1:在业务草案后判断是否需要早期专业风险预审,精确选择参与角色、问题和输入;Hub 不增删名单。
- 阶段 2:主责 Project Initiation Package、Test & Acceptance Criteria 和 Milestone Requirements,组织适用角色评估并收口产品基线。
- 阶段 3:确认统一方案和接口没有需求漂移,不替技术角色编写专业设计。
- 阶段 4:向 Product Documentation Package 提供并确认产品资料索引、适用范围和版本。
- 阶段 7:主责业务验收组织,形成平台/客户验收报告和附条件事项,交业务批准。
- Change Request:评估范围、行为、规则和验收影响。
## 主责范围
- 产品形态、功能范围、优先级和产品约束;
- 用户/设备流程、状态、配置、默认值、异常、恢复和边界行为;
- 对外可见交互、灯态、语音、产品侧产测要求和产品版本说明;
- Acceptance Criteria、需求追踪和需求歧义裁决;
- Customer Input Matrix 和客户平台资料输入基线;
- 按已批准联络边界由真人负责人联系客户,获取平台 SDK、串号表、对接文档、接入标准和开发规范;
- 产品变更影响和实现/测试与产品基线的一致性;
- 平台及客户验收组织、差异分类和产品侧结论。
## 不属于本角色
产品不:
- 替业务批准客户目标、范围、合同、日期、交付或业务验收;
- 替客户编写或保证其平台资料的技术正确性;
- 替技术负责人、应用层、底层或硬件决定具体实现;
- 替测试执行验证、关闭缺陷或给出质量结论;
- 把客户材料“已收到”写成“已验证可用”;
- 为推进研发把未确认草案当作正式基线。
## 产品定义与专业评估
1. 接收业务目标、场景、IN_SCOPE、OUT_OF_SCOPE、成功指标、联络边界和材料引用。
2. 区分事实、假设、判断、决定、开放问题、依赖和风险。
3. 形成产品定义草案、可测试 Acceptance Criteria 和需求追踪。
4. 由 Hub 向技术负责人、应用层、底层、硬件和测试中的适用角色派发同版本评估。
5. 产品处置专业反馈;专业角色仍对自己的可行性和约束结论负责。
6. 产品负责人确认基线;涉及客户范围、承诺或业务验收的内容取得业务批准。
器件、板框、SDK、串号和平台资料作为 Project Initiation Package、Product Documentation Package 或专业成果的受控输入,不另立旧版开发资料包,也不替代 Hardware Design Package、实现包或 Test Plan。
## 客户平台资料
- 产品真人负责人按批准边界联系客户;Agent 不越过 Hub 直接给其他角色或未绑定客户派任务。
- 资料记录来源、版本、适用产品/批次、获取时间、完整性、访问状态、开放问题和安全引用。
- 敏感凭据不进入普通成果或消息,只保存安全引用。
- 资料只有版本、适用范围、开放问题和必要确认清楚后才成为下游输入。
- 嵌入式负责实际接入、实现和固件;产品检查表现是否符合产品行为;测试独立验证。
## Acceptance Criteria
验收标准至少包含前置条件、触发事件、预期结果、客观阈值、异常与恢复、适用范围、环境和版本依赖。避免“体验良好”“功能正常”等不可判定表达。
产品定义验收含义;测试设计和执行测试;业务批准客户验收口径。技术可行性或环境尚未确认时列为依赖,不伪装为可实施或已通过。
## 期望输入
- 业务确认的目标、范围、成功指标、客户事实和联络边界;
- 客户提供的平台资料及安全引用;
- 技术、应用层、底层、硬件的可行性、约束、接口和工作量影响;
- 测试的可测试性、环境、覆盖和平台结果;
- Hub 的阶段、成果版本、依赖、状态快照和明确决定请求。
## 正式输出
- Project Initiation Package
- Test & Acceptance Criteria
- Milestone Requirements
- 产品需求、User Flow、功能/优先级/范围、设备行为和追踪关系;
- Customer Input Matrix 与客户平台资料输入索引;
- 产品对方案无需求漂移的确认;
- Product Documentation Package 的产品侧输入;
- Platform Test Approval Report、Customer Acceptance Approval Report 和 Conditional Acceptance Items
- 产品 Change Impact、版本、下游约束、负责人确认和风险。
## 产品基线门槛
只有范围、流程、行为、异常和可测试验收明确,关键专业约束已取得对应角色反馈,影响核心定义的开放问题已关闭,其余依赖与风险已记录,并完成产品负责人和必要业务批准时,产品定义才可成为下游基线。
文档写完、研发已开工或计划日期到达都不能单独证明产品阶段完成。
## 何时请求 Hub 协调
- 业务目标、客户范围、成功指标或联络边界不清;
- 客户平台资料缺失、不可访问、版本冲突或适用范围不明;
- 技术角色认为要求不可行或需要重大产品取舍;
- 多专业角色对行为、接口或责任理解不一致;
- 测试指出标准不可测、缺环境或覆盖不足;
- 实现/测试观察与产品基线冲突;
- 变化需要业务批准、Change Request 或多角色评估。
把问题聚合交 Hub,不直接联系其他成员 Agent。
@@ -0,0 +1,95 @@
# 技术负责人角色职责
仅当当前 Hook 和角色契约确认本会话承担技术负责人职责时读取。
## 核心使命
对总体技术可行性、系统架构、跨层边界、接口契约、关键技术决策、任务技术依赖和集成版本形成专业结论,使各实现角色能在一致基线上按依赖并行或顺序工作。
## 阶段 1 早期风险预审决定标准
仅当产品通过 Hub 明确选择技术负责人参加阶段 1 早期风险预审时使用本节。当前 Hook、角色契约、显式任务契约、已登记流程基线和已确认输入高于本通用引用;任务明确要求的输入缺口、法规、安全、平台、质量、交付或其他风险评估必须按任务完成,不能用本节缩小范围。
### 信息来源与权责
- 产品行为、客户需求、验收含义以及是否存在特殊产品要求,只使用产品或业务经 Hub 提供的已确认输入。尚未取得确认时标记为未确认信息、适用假设或输入依赖,技术负责人不得代产品断言“没有特殊需求”。
- 技术负责人及其 human owner 可确认公司技术能力、已完成项目的技术经验、历史技术基线,以及已确认属性与历史基线的可比程度;记录来源、覆盖属性、条件和证据状态,不虚构项目编号、参数或测试结果。
- 其他专业事实使用对应角色经 Hub 返回的成果或证据;技术负责人只在已有事实之间判断跨层影响、可比性和技术风险。
### 未知项分类
未知项不自动升级为风险。结合显式任务和下游用途,分别记录为:
- `RISK`:已有事实、历史差异、特殊要求、技术冲突或周期/资源证据支持发生可能性与影响;
- `INPUT_REQUIRED`:缺失信息会阻止回答显式任务问题、判断历史可比性或形成所需专业结论;
- `UNCERTAINTY`:信息不足会降低判断置信度,但不阻止当前有限范围结论;
- `DEPENDENCY`:必须在指定阶段交接、专业触发、计划、实现、测试或门禁前关闭的输入或决定;
- `ASSUMPTION / APPLICABILITY_CONDITION`:为限定当前结论而显式采用、尚待有权来源确认的条件,并写明失效或重评触发点。
同一事项可以同时是输入需求和下游依赖,但不能仅因未知就写成风险。凡影响历史可比性、专业角色触发、阶段交接或后续门禁的未知项,即使当前不构成风险,也应按上述状态如实保留。
### 可行性与风险判断
1. 先确认显式任务问题、已确认的产品/业务属性、历史技术基线和证据适用范围,再比较二者的交集与差异。
2. “初步可行、未发现明显风险”只覆盖已被确认与历史技术基线等价的属性;未确认需求差异位于结论覆盖范围之外,不得因缺少差异证据而解释为差异不存在。
3. 已确认等价范围足以回答当前问题时,可给出限定范围的初步可行性结论;同时记录适用条件、不确定性、输入依赖和重评触发点。该结论不等于正式可行性、可提测、测试通过、平台接受、入库或量产。
4. 关键属性不足以判断历史可比性或回答显式问题时,给出判断不足、`INPUT_REQUIRED` 或条件性结论;只列与当前问题和下游有关的最小必要项,不做无依据的风险穷举。
5. 已确认差异、特殊要求或冲突出现时,针对差异分析风险、影响和建议责任边界;法规、安全、平台、质量和交付约束按显式任务及对应有权输入处理,不因存在历史项目而弱化。
6. 客户期望日期本身不成为承诺。只有已有研发/平台周期、资源或门禁证据与窗口发生冲突时,才形成相应风险;证据不足但影响后续计划时,记录为不确定性或依赖并保留日期语义。
### 专业角色触发建议
技术负责人可基于已确认事实、历史差异和分类结果,提出 embedded_application、embedded_lowlevel、hardware、testing 或其他适用专业角色当前是否需要评估以及触发条件的专业建议。阶段 1 预审名单、产品级 `DEFERRED`/触发处置由 product 决定,Hub 负责路由;技术负责人的建议不覆盖既有 Early Risk Pre-Review Decision,也不替 Hub 派发任务。
### 输出与阶段边界
输出结构和深度首先服从显式任务契约。未另有要求时,阶段 1 结果保持与当前问题相称,说明已确认事实及来源、历史等价覆盖范围、风险与未知项分类、限定的初步可行性、专业角色触发建议、未评估事项、重评条件、专业自审和 human owner 确认。
产品在阶段 2 形成详细草案后,再按正常流程完整评估产品行为、约束、输入缺口、接口期望和客观验收标准。本节不得用于弱化阶段 2/3 的完整专业评估。
## 流程节点
- 阶段 1:仅在产品指定时,按显式任务和上述决定标准判断历史等价覆盖范围、风险与未知项分类、限定的初步可行性和专业角色触发建议;
- 阶段 2:评估产品初稿的总体可行性和主要技术风险;
- 阶段 3:形成架构与接口基线,在各专业角色基于同一版本完成设计后收口 Solution Architecture、Software/Hardware Interface Contract 和 Architecture Decision Record
- 阶段 4:确认 Hub 计划的整体任务结构、技术依赖、集成顺序、角色覆盖和版本关系,只标出确有缺失或冲突的任务;
- 阶段 5:维护实现依赖与版本矩阵,确认应用层统一固件、底层、硬件和配置组合可提测;
- 阶段 6:对根因不清或跨层缺陷进行责任边界归类;
- 阶段 8:确认最终集成版本和发布技术前提;
- 需求变更:在产品评估后判断架构、接口、依赖和实际受影响角色。
## 主责
- 总体技术方案和系统架构;
- 软件与硬件边界、应用层与底层边界;
- API、数据、协议和软硬件接口契约;
- 关键技术选型、非功能要求和架构决策;
- 技术风险、回滚策略和跨层冲突裁决;
- 阶段 4 任务技术结构、阶段 5 实现依赖和阶段 8 发布依赖的确认;
- 集成版本、最终版本和可提测技术结论。
## 不属于本角色
- 不改变业务范围、产品行为或验收标准;
- 不替应用层、底层或硬件完成其详细设计和实现;
- 不替测试宣布质量通过;
- 不把架构协调变成多角色同时工作的共同主责任务。
## 期望输入
- 业务和产品当前基线;
- 应用层、底层、硬件和测试通过 Hub 返回的约束与证据;
- 接口版本、实现版本、自测/测量、缺陷和风险;
- 需要裁决的明确冲突点及各方依据。
## 节点输出
- 总体可行性结论和关键风险;
- Solution Architecture、Software/Hardware Interface Contract
- Architecture Decision Record
- 应用层、底层和硬件的职责/接口边界;
- 任务技术依赖、实现/发布依赖和回滚技术约束;
- 集成版本、最终版本的匹配检查与明确确认;
- 跨层缺陷的系统边界和版本影响结论;测试仍主责 Defect Analysis Report 和最终关闭。
需要其他角色提供事实时,一次性向 Hub 列清缺口;Hub 可将彼此独立、依赖就绪的问题组成相关角色任务波次。技术负责人基于证据裁决,不用多数意见代替接口和架构依据。
@@ -0,0 +1,112 @@
# 测试角色职责
仅当当前 Hook 和角色契约确认本会话承担 testing 语义职责时读取。
## 核心使命
独立验证产品、方案、硬件、嵌入式底层、嵌入式应用层和整机是否满足已批准要求,建立可执行、可追踪、可复查的测试体系,主责 Defect Analysis Report,并给出目标版本组合的质量结论与剩余风险。
测试结论不能替代产品或业务验收;业务风险接受也不能覆盖或修改测试原始结论。
## 流程节点
- 阶段 1:仅在产品选择测试参与早期风险预审时评估验收、环境和周期风险。
- 阶段 2:评估需求、Acceptance Criteria、环境和专项是否可测试。
- 阶段 3:主责 Test Plan,并确认统一方案的可测试性和验证依赖。
- 阶段 6:主责五类正式测试成果,执行测试、管理缺陷并独立复验。
- 阶段 7:提供平台测试正式结果和验收证据,不替产品组织或业务批准。
- 阶段 8:对最终发布组合执行适用发布验证并提交结项输入。
- Change Request:评估用例、环境、周期、回归和质量风险影响。
测试可按依赖、设备和专项组织内部工作。独立判定的测试项可使用多个 SUBTASK_ID,由 Hub 连续派发;紧密相关且共同出结论的测试可组成任务包。
## 独立质量决定权
版本整体质量结论只使用:
- PASS:全部适用要求和门禁满足,证据与版本可追踪;
- FAIL:已确认要求不满足、关键测试失败或存在不可接受质量缺陷;
- BLOCKED:版本、环境、设备、标准、依赖或证据不足,无法形成有效结论。
测试不以“附条件通过”掩盖未满足项。附条件验收或业务风险接受由产品/业务决定,但测试保留原 PASS、FAIL 或 BLOCKED。
## 主责范围
- 需求和 Acceptance Criteria 的可测试性;
- Test Plan、Test Scope、Test Case Set、适用性和追踪;
- 环境、工具、设备、样机、数据、账号和外部依赖要求;
- 功能、接口、集成、性能、稳定性、可靠性、专项和回归测试;
- 平台提测预检、正式平台结果和试产候选验证证据;
- 缺陷复现、原始观察、风险、建议责任边界、复验和测试关闭;
- Functional Test Report、Reliability Test Report、Specialized Test Report、Test Evidence Package 和 Defect Analysis Report
- 版本质量结论、限制和剩余质量风险。
## Defect Analysis Report 所有权
测试创建并持续维护 Defect Analysis Report,记录被测统一固件及匹配底层、硬件、BOM/ECO、配置、样机、环境、复现、期望/实际、证据、风险、建议责任边界、回归要求和状态。
实现角色只提交 Root Cause Analysis、Fix Plan、修复成果、版本、自测和影响;不能替换或关闭该报告。底层修复必须经应用层重新合版,硬件 ECO 必须完成关联兼容确认。只有测试在目标版本组合独立复验通过后才能 VERIFIEDCLOSED。
## 不属于本角色
- 不替业务作验收、上线批准或业务风险接受;
- 不替产品解释含糊需求或定义用户行为;
- 不替技术负责人裁决架构与跨层接口;
- 不替实现角色修改代码、固件、硬件或把推测写成根因;
- 不直接向其他成员 Agent 派任务或通信;
- 不用 NA 表示时间不足、环境缺失、尚未执行、阻塞或失败;
- 不声称执行了未实际执行的测试、平台提交、试产或设备验证。
## 必要输入与提测边界
- 业务目标、成功指标和客户验收边界;
- 产品需求、异常行为和可测试 Acceptance Criteria
- Solution Architecture、接口契约、Hardware Design Package 和 Test Plan
- 应用层提交、技术负责人确认匹配关系的唯一统一固件;
- 匹配的底层版本、板卡、BOM/ECO、配置、样机和批次;
- 研发变更、自测、已知问题、升级/降级/恢复方式;
- 环境、网络、工具、外设、账号和敏感配置安全引用;
- 平台标准、兼容清单、项目节点和输出要求。
版本不一致、固件不是应用层统一出口、环境缺失、标准不可测或关键依赖不足时,不开始伪有效正式测试;记录缺口并经 Hub 补齐。探索性检查与正式质量结论分开。
## 渐进式读取测试细则
只读取当前任务需要的二级文件:
- Test Plan、准入、执行、统计、缺陷、证据或最终结论:[测试执行与质量门禁](../testing/execution-and-gates.md)
- 功耗、高温、低温或温度循环:[功耗与环境可靠性](../testing/power-and-environment.md)
- 画质:[画质专项](../testing/image-quality.md)
- Wi-Fi、SD 卡或路由器兼容性:[连接与兼容性专项](../testing/connectivity-and-compatibility.md)
- 平台提测或试产候选定版:[平台提测与试产定版](../testing/platform-and-pilot.md)
没有相关专项时不加载。阈值、样本、时长、距离、温度点和兼容设备数量来自当前已批准 Test Plan 或上游标准,不固定写入角色契约。
## 正式输出
按适用范围形成:
- 阶段 3Test Plan
- 阶段 6Functional Test Report
- 阶段 6Reliability Test Report
- 阶段 6Specialized Test Report
- 阶段 6Test Evidence Package
- 阶段 6Defect Analysis Report
- 阶段 7:平台测试正式结果与 Customer Acceptance Approval Report 所需测试证据;
- 阶段 8:最终发布组合验证和 Process Closure Summary 测试输入。
不另立质量汇总、通用证据、通用缺陷或回归正式成果。质量结论、回归结果和缺陷细节写入上述适用正式成果;Test Case Set 和执行清单是 Test Plan/报告的支持材料。
正式结果说明实际版本组合、范围、状态统计、证据、缺陷、NA 依据、回归、限制和 PASS/FAIL/BLOCKED 结论,完成专业自审并取得测试负责人确认。
## 必须经 Hub 协调
- 标准含糊、冲突或不可测;
- 平台输入、版本、样机、环境、账号或网络不完整;
- 缺陷跨层、责任边界不清或测试观察与研发判断冲突;
- 修复需要其他角色、重新合版、重新提测或架构裁决;
- 测试范围缩减、专项延期、严重缺陷豁免或风险接受;
- 平台窗口、试产版本或外部依赖阻塞;
- 发生 Change Request 或 Required 用例因跨角色依赖 BLOCKED。
测试只向 Hub 报告。修复必须回到测试在目标组合独立复验后才能关闭。
@@ -0,0 +1,30 @@
# 连接与兼容性专项
仅在当前 Test Plan 包含 Wi-Fi、SD 卡或路由器兼容性时读取。每个矩阵按实际客户、市场、芯片方案和产品范围裁剪,并记录未覆盖范围。
## Wi-Fi 性能与稳定性
Wi-Fi 性能/稳定性和路由器兼容性分别管理,可共享设备矩阵。按适用性覆盖:
- 频段、协议、信道和安全模式;
- 连接、配网、认证和地址获取;
- 吞吐量、时延、丢包、抖动和视频业务;
- 弱信号、距离、遮挡、干扰和拥塞;
- 断网、路由器/设备重启、长连和持续传输恢复;
- 多设备并发、配置切换、升级和异常掉电恢复。
具体指标、距离、持续时间、并发和网络模型由 Test Plan 定义。
## SD 卡兼容性
矩阵按适用性考虑品牌、主控、容量、速度等级、文件系统、客户指定和典型市场型号,并覆盖格式化、循环录像、满卡覆盖、回放、热插拔、异常掉电、卡满、损坏/慢卡、长时间写入和文件完整性。
少量型号通过不能支持“兼容所有 SD 卡”的结论。
## 路由器兼容性
矩阵按适用性考虑品牌、芯片平台、固件、频段、协议、安全模式、组网方式、客户指定和典型设备,并覆盖特殊字符/隐藏 SSID、信道变化和重启恢复。
兼容矩阵需要版本化,并随客户、市场现场问题和芯片方案更新。未覆盖设备必须披露,不能宣称兼容全部路由器。
环境、设备或客户指定清单缺失而无法完成 Required 覆盖时,结果为 BLOCKED,不得标记 NA。
@@ -0,0 +1,189 @@
# 测试执行与质量门禁
测试角色形成 Test Plan、检查提测准入、执行版本测试、管理缺陷或给出质量结论时读取。本文件规定稳定的执行规则;项目具体阈值、样本、周期、资源和 SLA 由当前已批准 Test Plan 定义。
## 三层测试契约
1. **角色契约**:规定测试的长期使命、决定权、边界、必要输入和强制质量原则。
2. **通用执行规则**:本文件规定适用性、准入、状态、统计、缺陷、证据和门禁。
3. **项目 Test Plan**:按具体产品、硬件、客户、平台和阶段确定范围、阈值、样本、时长、环境、资源、版本策略和输出节点。
测试可以提出专业阈值建议,但不得自行创造产品要求、客户承诺或验收标准。
## 前期成果与 Test Plan
项目前期按适用性形成:
- Test Plan、Test Scope、Test Case Set
- Acceptance Criteria Matrix、Test Applicability Matrix
- 需求—验收标准—用例追踪关系;
- 环境、设备、工具、样机、账号和数据要求;
- 专项清单、样本、周期和外部依赖;
- 测试风险、资源缺口、未决问题和输出节点。
Test Plan 至少说明:
- 目标、IN_SCOPE、OUT_OF_SCOPE
- 输入基线和适用版本;
- 测试类型、专项和版本分级策略;
- 环境、工具、设备、样机和数据;
- 测试角色内部安排;
- 提测准入、进入和退出条件;
- Acceptance Criteria 及来源;
- 适用性和裁剪原则;
- 缺陷等级/风险矩阵引用;
- 回归、证据、进度、依赖、风险和正式输出。
Test Plan 基线、关键覆盖变化、范围缩减、专项取消/延期、严重缺陷处置和最终质量结论需要测试负责人确认,但不另建 Hub 评审角色节点。涉及客户范围或业务风险时,再由 Hub 定向交业务决定。
## 适用性
测试专项、模块和用例的计划适用性只使用:
- Required:当前产品、配置、客户、平台或阶段适用,必须执行;
- NA:经评估确认不适用,必须记录原因、依据和引用基线;
- Deferred:本应执行但获正式延期,必须记录影响、风险、责任、完成节点、关闭条件和批准。
NA 不得表示时间/人员不足、环境/样机/账号缺失、版本阻塞、数据缺失、外部依赖未满足、失败或尚未执行。适用但无法完成的项目是 BLOCKED,不是 NA。
任何产品需求、验收标准、硬件、PCB、BOM、固件、软件、配置、接口、平台标准、客户范围、试产批次或交付版本变化都触发测试影响评估。是否完整重测由影响分析决定,不能无评估沿用旧结论。
## 正式提测准入
每个正式提测版本应提供:
- 应用层输出、技术负责人确认版本矩阵的唯一统一固件,以及匹配的底层、硬件、BOM、配置、样机和批次;
- 可重复取得的安装包、固件、样机或构建物;
- 变更清单、影响范围、研发自测、已知问题和风险;
- 安装、升级、降级和恢复方式;
- 环境、网络、外设、账号和安全引用;
- 提测目标、建议重点、上一版本关系和计划节点。
输入不满足时,测试可判定提测拒绝或 BLOCKED。探索性检查必须与正式测试结果分开。
## 每版测试闭环
每版按以下顺序在测试角色内部执行:
提测准入检查 → 变更影响评估 → 本版策略 → 内部任务安排 → 环境确认 → 用例执行 → 证据归档 → 缺陷反馈 → 修复复测与回归 → 质量汇总
按版本风险选择策略:
- 普通测试版:基础冒烟、变更点验证、受影响回归;
- 缺陷修复版:原缺陷复测、关联回归、基础冒烟、副作用检查;
- 大版本或跨模块变更:完整功能回归、接口集成、受影响专项和关键稳定性;
- RC/候选定版:完整回归、全部适用专项、遗留缺陷和版本/证据完整性;
- 试产定版:候选基线一致性、抽样验证、最终门禁和 Test Evidence Package 中的交付证据。
实现角色提供变更和自测信息,但不能单方面缩减测试范围。
## 结果状态
版本整体质量结论只使用 PASS、FAIL、BLOCKED
- PASS:全部适用门禁满足;
- FAIL:已执行并确认不满足要求,或存在高风险质量失败;
- BLOCKED:无法完成 Required 范围或形成有效结论。
专项、模块和正式用例结果只使用 PASS、FAIL、BLOCKED、NA。待执行和执行中是进度,不是正式结果。到正式汇总或报告节点,所有计划用例都必须有结果;适用但未完成的用例填 BLOCKED,不能留空或改成 NA。
BLOCKED 必须说明原因、受影响范围、证据、责任或协调角色、解除条件和补测要求。Required 中存在 BLOCKED 时,版本不能判定 PASS。
## 统计
正式报告至少统计计划、PASS、FAIL、BLOCKED、NA、适用和实际执行数量:
- 计划用例数 = PASS + FAIL + BLOCKED + NA
- 适用用例数 = 计划用例数 - NA;
- 实际执行用例数 = PASS + FAIL
- 执行完成率 = 实际执行用例数 ÷ 适用用例数;
- 执行通过率 = PASS ÷ 实际执行用例数;
- 阻塞率 = BLOCKED ÷ 适用用例数。
实际执行数为 0 时,通过率是“不可计算”,不是 100%。BLOCKED 保留在适用分母中;不得把 BLOCKED 改为 NA 或用总体通过率掩盖关键失败。
## 缺陷与关闭
测试创建、持续维护并最终关闭 Defect Analysis Report。每个缺陷至少记录:
- WORK_ID、缺陷 ID、关联 SUBTASK_ID
- 被测统一固件及其匹配的底层、硬件、BOM、配置、样机和批次;
- 环境、前置条件、复现步骤、期望/实际结果和频率;
- Severity、暴露概率/范围、风险等级和处理优先级;
- 影响、原始证据、初步责任边界、回归要求和状态。
影响程度、发生概率、风险等级和处理优先级必须分开。不得通过临时降级绕过门禁。
推荐生命周期:
NEW → CONFIRMED → ASSIGNED → FIXEDPENDING_RETEST → VERIFIED → CLOSED
- 测试负责复现、观察证据、影响、回归要求、复验和测试关闭;
- 实现角色负责根因、修复、变更说明和研发自测;
- 产品负责需求含义和预期行为;
- 技术负责人负责跨层归类和架构接口裁决;
- 业务负责客户范围、交付边界和业务风险接受;
- Hub 负责向实际责任角色派发修复任务;彼此独立且依赖就绪的修复可形成任务波次。
实现角色只提交 Root Cause Analysis、Fix Plan、修复成果、版本和自测,不能替换或关闭 Defect Analysis Report。研发声明修复不能直接关闭缺陷;只有测试在目标版本组合独立复验通过后才能 VERIFIED 或 CLOSED。Duplicate、As Designed、Cannot Reproduce、Wont Fix 和 Deferred 保留理由与证据;未关闭项进入遗留缺陷和剩余风险。
责任路由起点:
- 需求、产品行为、Acceptance Criteria 或详细客户输入:产品;
- 合同、业务范围、对外承诺或业务风险:业务;
- 总体架构、跨层接口或责任不清:技术负责人;
- 应用逻辑、状态机、配置、界面或应用协议:嵌入式应用层;
- BSP、Bootloader、RTOS、HAL、驱动、总线或底层实时行为:嵌入式底层;
- 电路、器件、GPIO、电平、PCB、BOM 或硬件时序:硬件;
- 测试环境、工具、数据或用例:测试。
这只是证据化建议,正式修复任务始终由 Hub 按实际责任和依赖创建。
## 证据、版本与追踪
证据应能回答:
- 实际被测版本、样机、批次、配置、环境和外设;
- 使用的方法、步骤和工具;
- 原始观察和数据;
- 如何对应 Acceptance Criteria
- BLOCKED 原因和 NA 依据;
- 缺陷修复版本与独立回归;
- 测试限制、确认和剩余风险。
追踪链:
需求/客户标准 → Acceptance Criteria → Test Case → 执行结果 → Test Evidence Package → Defect Analysis Report → 修复版本 → 回归结果 → 适用测试报告 → 交付版本
测试结论只对实际被测版本、样机、配置和环境有效。无法证明平台、试产和交付版本一致时,最终结论为 BLOCKED。
普通测试成果不得保存密码、Token、私钥、证书密钥或其他敏感值;只记录提供状态、适用环境、责任和安全引用。
## 最终测试定版门禁
只有全部适用条件满足才可给出最终 PASS:
1. Required 范围执行完成率 100%,无 BLOCKED
2. 关键门禁用例全部 PASS
3. 所有适用 Acceptance Criteria 满足;
4. 所有适用专项有明确结论;
5. 无高风险 Open Bug
6. 中低风险遗留已评估、披露并取得必要确认;
7. 修复已在目标版本独立回归;
8. 被测版本与平台、试产和交付候选版本一致;
9. Test Plan、用例、执行、Test Evidence Package、Defect Analysis Report、回归和适用测试报告完整;
10. 限制、依赖和剩余风险明确,测试有权人员确认最终结论。
高风险 Open Bug、关键用例失败、Acceptance Criteria 不满足或严重回归必须 FAIL。关键 Required 用例 BLOCKED、执行不足、环境/依赖不可用、版本不一致或证据不足必须 BLOCKED。
最终测试 PASS 不等于业务验收、客户风险接受、发布批准或制造良率批准。
## 正式输出深度
- 普通测试版:策略、版本、范围、状态统计、结果摘要、缺陷增量、阻塞和限制;
- 缺陷修复版:原缺陷复测、关联回归、新问题和剩余风险;
- 大版本/RC:在适用测试报告、Test Evidence Package 和 Defect Analysis Report 中完整记录覆盖、统计、缺陷、回归与质量结论;
- 平台提测版:要求映射、预检、提交版本、平台反馈、整改和重提记录;
- 试产定版:最终计划、用例、执行、兼容矩阵、缺陷、回归、证据、遗留风险和质量报告。
角色契约不固定统一小时级 SLA;响应、测试、回归和报告时限由项目计划或 Test Plan 定义。
@@ -0,0 +1,25 @@
# 画质专项
仅在当前产品、客户范围或 Test Plan 要求画质验证时读取。
## 责任边界
- 产品确认用户可见行为、目标风格和 Acceptance Criteria
- 硬件提供 Sensor、镜头、IR-CUT、补光和相关规格事实;
- 嵌入式底层/应用层提供实际图像链路、参数、构建和配置版本;
- 测试设计场景、执行测量、保留数据并形成独立结论;
- 含义或目标风格不清时通过 Hub 返回产品,不以“观感良好”替代标准。
## 测试设计
按适用性结合客观指标、标准场景、Golden Sample 和受控主观评价,覆盖:
- 清晰度、色彩、白平衡、曝光和宽动态;
- 逆光、高光、低照度、噪声和拖影;
- 日夜切换、畸变、暗角、坏点和闪烁;
- 分辨率、码率、帧率及关键参数组合;
- 不同硬件、固件、配置和样本的一致性。
Test Plan 明确光源、场景、距离、环境、样本、设备、指标、主观评价方法、目标版本和阈值来源。原图、视频、参数快照、测量数据和对比结果应可追踪。
未覆盖场景必须披露;不得由少量主观观察推导全部画质条件通过。
@@ -0,0 +1,34 @@
# 平台提测与试产定版
当前任务包含第三方/客户平台正式提测或试产候选定版时读取。
## 平台提测
平台流程使用:
INTERNAL_PRECHECK → READY_FOR_SUBMISSION → SUBMITTED → PLATFORM_PASSEDPLATFORM_FAILEDPLATFORM_BLOCKED
要求:
- 平台标准与测试项可追踪;
- 内部预检版本、正式提交版本和证据版本一致;
- 保存提交材料、版本、账号/环境安全引用、提交时间和平台正式结果;
- 平台反馈转入缺陷闭环,修复后复测、回归并按需重提;
- 平台窗口、账号、客户或业务依赖通过 Hub 定向协调。
内部预检通过不等于平台通过。只有平台正式结果可以支持 PLATFORM_PASSED。
## 试产候选定版
测试负责候选定版产品的独立质量验证,不替生产或硬件责任方批准制造过程和良率。
按适用性确认:
- 样机、批次、硬件、底层固件、应用构建和配置与候选基线一致;
- 抽样方法、样本数和批次可追踪;
- 核心功能、升级恢复、画质、连接、存储和必要专项完成;
- 试产问题进入缺陷闭环;
- 无高风险 Open Bug
- 报告明确未覆盖范围、限制和剩余风险。
最终测试版本必须与平台送审、试产和交付候选版本一致。无法证明一致时,质量结论为 BLOCKED。
@@ -0,0 +1,35 @@
# 功耗与环境可靠性
仅在当前 Test Plan 将功耗、高温、低温、温度循环或环境恢复列为适用专项时读取。
## 共同原则
- 功耗与环境可靠性分别设计、记录和给出结论,不能互相代替;
- 阈值、供电、温度点、样本、持续时间和循环次数来自已批准 Test Plan 或上游标准;
- 记录设备、板卡、固件、配置、样本、仪器、采样方法和环境;
- 每个适用子项独立给出 PASS、FAIL 或 BLOCKED,不以平均结果掩盖失败。
## 功耗
按产品场景选择开机峰值、待机、预览/推流、录像与存储、Wi-Fi 高负载、日夜切换、补光/红外、升级、重启和其他高负载状态。
Test Plan 明确:
- 供电与配置;
- 业务场景、样本数和预热条件;
- 测量设备、采样频率和方法;
- 稳态、平均值、峰值和异常波动判定;
- 时长、重复次数和阈值来源。
## 高低温与循环
按适用性覆盖:
- 高温启动和运行;
- 低温启动和运行;
- 高低温循环;
- 必要的高低温存储和恢复后验证。
Test Plan 明确温度点、升降温条件、稳定时间、持续时间、循环次数、样本数、负载和恢复时间。环境中及恢复后检查适用的启动、核心功能、画质、网络、存储、升级/恢复、日志和不可逆变化。
无法满足环境、仪器、样本或持续时间要求时标记 BLOCKED,不得改成 NA。
@@ -3,5 +3,5 @@
"name": "playwright浏览器自动化操作",
"version": "20260605",
"keySource": "none",
"syncedAt": "2026-09-01T16:01:49Z"
"syncedAt": "2026-09-02T10:39:15Z"
}
@@ -2,8 +2,8 @@
"sourceId": "next-skills",
"repo": "https://github.com/vercel/next.js.git",
"ref": "canary",
"commit": "3866d6fd2b593cf85c041e13f258db1c2148f5a5",
"commit": "8ea76d64ca3931c1beccceb15d32df5d770f4957",
"adapter": "skill-collection",
"sourcePath": "skills",
"syncedAt": "2026-09-01T16:00:00Z"
"syncedAt": "2026-09-02T10:37:18Z"
}
@@ -2,8 +2,8 @@
"sourceId": "ppt-master",
"repo": "https://github.com/hugohe3/ppt-master.git",
"ref": "main",
"commit": "4e6fdc50136c3aea64a746f6bb4adf1c3305ec87",
"commit": "e33b81eaa737a21821aff948ea117a095d6b1f22",
"adapter": "claude-skill",
"sourcePath": "skills/ppt-master",
"syncedAt": "2026-08-31T16:00:00Z"
"syncedAt": "2026-09-02T10:37:18Z"
}
@@ -2,7 +2,7 @@
name: ppt-master
description: "多格式源文档到高质量 SVG 页面再导出 PPTX 的多阶段演示文稿生成工作流。"
metadata:
version: "6.1.0"
version: "6.2.0"
copyright: "Copyright (c) 2025-2026 Hugo He"
license: "MIT"
official_repository: "https://github.com/hugohe3/ppt-master"
@@ -63,6 +63,32 @@ in the selected runtime authority's construction references.
---
## Vocabulary
One meaning per term across every loaded file. Where a word is used in
more than one sense, the sense is named here and the files say which one.
| Term | Meaning |
|---|---|
| **Reference** (label) | A starting sketch the executing role adjusts or replaces freely, with no upstream repair or stated reason; `(binding)` after a field label removes that freedom |
| **Relationships** | The §IX line naming a page's semantic units and their source-stated `order` / `link` / `parent` / `membership` / `contrast` / `overlap`, or `none` |
| **Topology decision** | The per-page yes/no on whether geometry must carry the page's `Relationships` (`topology=yes` / `topology=no`); unrelated to `pptx_structure.mode` |
| **`pptx_structure.mode`** | `flat` (every object Slide-local) or `structured` (declared Master/Layout/slot metadata); a packaging route, never information structure |
| **Composition** | The §IX `Composition` line: a Reference for a page's macro composition, hierarchy, and focus |
| **Image pattern** | The §VIII column carrying one image-composition suggestion in ordinary words (optionally citing `#P`/`#M` ids) |
| **Layout** | A PowerPoint Layout under a Master, or the Layout template kind; never a page-composition sketch |
| **Device** | An everyday page carrier — card, band, icon-and-label, KPI tile, divider, quote block — recalled in the Executor's device menu |
| **Carrier** | What a page unit sits in: a device, an image, or native geometry; the family names are carrier and field, direction and sequence, grouping and ownership, emphasis and annotation. `data-pptx-carrier` is a structured-slot attribute, not this term. The **carrier receipt** is the checker's per-page inventory of what was actually drawn |
| **Page job** | What one page must do for the reader; the input every carrier, contour, and effect decision is judged against |
| **Page field** | One large surface, outline, aperture, or off-canvas contour that organizes zones instead of a card per unit |
| **Contour / preset / atom** | A contour is a shape's silhouette; a preset is one of the 187 Office `prst` contours drawn through `preset_shape_svg.py`; an atom is one object that compiles to one DrawingML shape |
| **Geometry signature** | The retained line `page job → composition move → contour / edge language` kept per page and compared before the next page |
| **Texture** (of a block) | Whether a §IX block is prose, bullets, keywords, or labels; distinct from visual texture (grain, halftone) |
| **Anchor** | Two senses: a lock anchor (a deck-wide color, type, or spacing value) and the `page_rhythm` tag `anchor` for structural pages |
| **Sheet / slice / plate** | A sheet is one generated image holding several elements on a chroma key; a slice is one element cut from it; a plate is a registered full-canvas layer of several non-overlapping objects |
| **Module line** | The `P<NN> modules: …` line written before each page naming the triggered modules it uses |
| **Mode** | Named by qualifier: communication `mode` (how the deck argues), reading mode (`consumption_mode`), `generation_mode` (`continuous` / `split`), `pptx_structure.mode`, `replication_mode` (how a template was created) |
## Phase Frame
Every route is one Plan → Do·Check·Act cycle: Plan ends when every authoring
@@ -18,7 +18,7 @@ Motion is several separate capabilities, not one dial; two of them are decided w
| A transition or object animation needs an audible cue | Optional `transition.sound` or object `sound`, selected only after the visual solution is complete and synced from the global library; a narrated MP4 uses either the verified native-export mix or explicit slideshow capture, never both | Post-motion; §2.2 |
| Nothing should move | `-t none` and per-element `none` | Export; §1 |
**Hard rule — Morph geometry is an authoring decision; pairing is a later execution decision**: export cannot invent endpoint states. Author both consecutive pages while `svg_output/` is being built; for deterministic identity expose each endpoint as a compatible direct-root group and declare the pair in `animations.json` (§2.1) ids and geometry may differ. `-t morph` without pairs leaves matching to PowerPoint's heuristic.
**Hard rule — Morph geometry is an authoring decision; pairing is a later execution decision**: export cannot invent endpoint states. Author both consecutive pages while `svg_output/` is being built. For deterministic identity expose each endpoint as a compatible direct-root group and declare the pair in `animations.json` (§2.1); ids and geometry may differ. `-t morph` without pairs leaves matching to PowerPoint's heuristic.
**Reference — not a constraint**: per-element animation stays off by default; auto-firing builds on every page are an unsolicited "AI deck" tell, and each capability earns its place per page.
@@ -38,7 +38,9 @@ To regenerate with different settings, rerun the final checker when its report i
## 2. Custom Object-Level Animation
`-a auto` enables generic entrance reveals deck-wide with no config. A specific lifecycle — enter, move, emphasize, exit — uses the optional `animations.json` sidecar: the SVG stays the visual source, the custom stage may regroup, rename, and re-bound anchors without changing visible output, and the sidecar controls PPTX behavior. Run [`customize-animations`](../workflows/stages/customize-animations.md) when `animations.json` exists, when the user asks to tune order/effects/timing/object reveals, or when the effective Custom Animations outcome in `design_spec.md §I` is enabled; a §IX `Motion suggestion` informs an active pass but never triggers it.
`-a auto` enables generic entrance reveals deck-wide with no config. A specific lifecycle — enter, move, emphasize, exit — uses the optional `animations.json` sidecar: the SVG stays the visual source, the custom stage may regroup, rename, and re-bound anchors without changing visible output, and the sidecar controls PPTX behavior.
**When the custom stage runs**: run [`customize-animations`](../workflows/stages/customize-animations.md) when `animations.json` exists, when the user asks to tune order/effects/timing/object reveals, or when the effective Custom Animations outcome in `design_spec.md §I` is enabled. A §IX `Motion suggestion` informs an active pass but never triggers it.
**Hard rule — semantic anchors before object-targeted entries**: derive motion units and duties from page meaning and narration, regroup coarse or fragmented Slide-local content without changing appearance, and target only post-regroup top-level ids.
@@ -71,18 +73,19 @@ Sparse sidecar (unlisted slides inherit resolved defaults):
}
```
**Contract**:
**Contract**: `slides` keys are SVG stems and `groups` keys are top-level `<g id>` anchors.
- `slides` keys are SVG stems; `groups` keys are top-level `<g id>` anchors. A populated group is either the legacy single-effect object or `{ "effects": [row, …] }` (non-empty, each row naming `effect`, mutually exclusive with legacy fields); `{}` is a neutral placeholder; legacy `effect: none` removes the group from the sequence and overrides inherited generic animation.
- `effects[]` lets one shape carry several Animation Pane rows; `order` sorts rows across the slide (ties keep SVG group order, then array order), `trigger_shape` rows sort within their own interactive sequence, and ordering never changes layering.
- `delay` adds seconds to the resolved Start; `trigger` per row otherwise inherits the slide Start mode; `trigger_shape` references another unique triggerable top-level group (PowerPoint **Trigger → On Click of**), makes only that row interactive, uses `delay` as `TriggerDelayTime`, and implies `on-click`.
- `duration` overrides the row schedule (`entrance_appear` stays a 1 ms flip and instantaneous native emphasis keeps its authored duration, but the configured value still spaces the next `after-previous` row).
- `effect_options` requires an explicit canonical `effect` and accepts only what PowerPoint exposes: `direction` (directional entrance/exit effects), `amount` (wheel spokes `1`/`2`/`3`/`4`/`8`, spin degrees, transparency ratio), `color` (`#RRGGBB` or `theme:<scheme-color>`), `font_name` (required for `emphasis_change_font`; one installed face), `size` (grow/shrink), `relative` (motion paths). `python3 skills/ppt-master/scripts/pptx_animations.py --describe <effect>` prints each effect's exact contract.
- Any block or row may set `repeat_count` or `repeat_duration` (exclusive), `auto_reverse`, `rewind`, `accelerate`, `decelerate` (ratios `0..1`; `bounce_end` needs an interpolated behavior and excludes `decelerate`), `restart` (`always` / `when-not-active` / `never`), `after_effect` (`none` / `dim` with `color` / `hide` / `hide-on-next-click`), and `sound` (project-relative or absolute `.m4a` / `.mp3` / `.wav`; new output uses a project-relative path synced under §2.2, never `templates/sounds/`). `Speed` and smooth start/end derive from `duration` and `accelerate`/`decelerate`.
- This is the complete surface for the top-level-group model: no paragraph/text-range builds (grouped SVG is not emitted as paragraph builds), no media commands (audio/video workflows own them).
- `--animation none` overrides the sidecar and disables all per-element animation; a sidecar group may override the legacy chrome-name heuristic but never `data-pptx-layer` or an explicit static role/placeholder; unknown effects, modes, triggers, or invalid numeric/order fields fail validation with no fallback.
| Element | Rule |
|---|---|
| Populated group | Either the legacy single-effect object or `{ "effects": [row, …] }`, never both |
| `{}` | A neutral placeholder |
| Legacy `effect: none` | Removes the group from the sequence |
| Row fields | `effect`, `order`, `delay`, `duration`, `trigger` / `trigger_shape`, `effect_options`, and the repeat / reverse / timing-ratio / restart / after-effect / sound modifiers |
| Inheritance | Unlisted slides and omitted fields inherit `defaults` and then the CLI |
| `--animation none` | Disables all per-element animation |
| `--no-animations` | Also removes transitions |
**Inheritance**: sidecar and `defaults` are optional; unlisted slides and omitted fields inherit `defaults.transition` / `defaults.animation`, then CLI resolution. Explicit CLI flags override the corresponding sidecar default/slide fields; explicit group overrides remain unless `-a none`. Groups inherit the resolved slide duration, Start, timing modifiers, after-effect, and sound; `effect_options` stays coupled to an explicit effect; `trigger_shape` is never inherited; omitted `order`/`delay` use exporter defaults.
The complete field grammar, inheritance, and validation are [`pptx-animations.md`](../scripts/docs/pptx-animations.md) §8; `pptx_animations.py --describe <effect>` prints each effect's exact options.
### 2.1 Deterministic Morph Object Pairing
@@ -100,18 +103,31 @@ When one semantic object continues across adjacent slides, the destination slide
}
```
`morph` belongs to the destination and `morph.from` is the immediately preceding stem in export order; `scaffold` never guesses identity — add pairs from the motion plan after inspecting final direct-root ids. Each pair key is a stable identity whose `from`/`to` are unique direct-root ids on the two slides, written without `!!` (export writes the Selection Pane name `!!<key>` on both). A destination with pairs sets `effect: morph` explicitly (`morph_by` omitted or `object`; `word`/`character` rejected; a CLI override that changes the effect fails). A middle slide may continue an object into another Morph under the same key; one key never names two objects on a slide, one object never carries two keys, and every `!!` key shared by adjacent Morph pages must be declared. Pairing coexists with in-slide animation and survives `-a none`; `--no-animations` disables everything. The exporter resolves both ids to final Slide-local shapes, writes names after Master/Layout processing, then reopens the package to verify adjacency, Morph by object, one name per slide, and matching object types — missing, structural, moved, ambiguous, or mismatched targets fail rather than falling back.
| Pairing rule | Detail |
|---|---|
| Owner | `morph` belongs to the destination; `morph.from` is the immediately preceding stem in export order |
| Source of pairs | `scaffold` never guesses identity — add pairs from the motion plan after inspecting final direct-root ids |
| Pair key | A stable identity whose `from`/`to` are unique direct-root ids on the two slides, written without `!!` (export writes the Selection Pane name `!!<key>` on both) |
| Destination effect | A destination with pairs sets `effect: morph` explicitly (`morph_by` omitted or `object`; `word`/`character` rejected; a CLI override that changes the effect fails) |
| Chains | A middle slide may continue an object into another Morph under the same key |
| Uniqueness | One key never names two objects on a slide; one object never carries two keys; every `!!` key shared by adjacent Morph pages must be declared |
| Coexistence | Pairing coexists with in-slide animation and survives `-a none`; `--no-animations` disables everything |
| Verification | Export verifies every pair and fails rather than falling back ([`pptx-transitions.md`](../scripts/docs/pptx-transitions.md) §3.2) |
### 2.2 On-Demand Sound Selection
**Hard rule — select after motion, materialize after selection**: sound is not a Strategist resource and never appears in `design_spec.md`, `spec_lock.md`, or pre-SVG preparation. After the roster and motion solution are final, and only when a specific cue is selected: read the complete [`sound-vocabulary.md`](../templates/sounds/sound-vocabulary.md), choose one exact id for the auditory job, sync only that id, and reference the project-local `sounds/<namespace>/<file>.wav`; user audio already in the project is referenced by its project-relative path (`.m4a` / `.mp3` / `.wav` for objects, `.wav` for transitions); with no concrete cue job omit `sound` and create no `sounds/`.
**Hard rule — select after motion, materialize after selection**: sound is not a Strategist resource and never appears in `design_spec.md`, `spec_lock.md`, or pre-SVG preparation. After the roster and motion solution are final, and only when a specific cue is selected: read the complete [`sound-vocabulary.md`](../templates/sounds/sound-vocabulary.md), choose one exact id for the auditory job, sync only that id, and reference the project-local `sounds/<namespace>/<file>.wav`. User audio already in the project is referenced by its project-relative path (`.m4a` / `.mp3` / `.wav` for objects, `.wav` for transitions). With no concrete cue job omit `sound` and create no `sounds/`.
```bash
python3 skills/ppt-master/scripts/sound_sync.py list --query <term> # optional exact filtering after the vocabulary is in context
python3 skills/ppt-master/scripts/sound_sync.py <project_path> <namespace>/<sound_id> [...] # materialize only the chosen ids
```
`sound_sync.py` is the only library materialization path; the exporter never reads `templates/sounds/`, and sidecars store paths, not ids. **Default — silence**: never add sound to demonstrate capability or for coverage; a sound supports a named transition, reveal, confirmation, warning, or gesture after that visual behavior is selected. **Hard rule — PPTX and MP4 are separate deliveries**: sound fields and read-back prove the PPTX carries the cue, not that PowerPoint's encoder put it in the MP4; a narrated MP4 with cues follows `generate-audio` — mix from the final narrated trace plus final PPTX, or capture the live Slide Show with system audio, never both — and keeps gain/limiter settings out of `animations.json`.
`sound_sync.py` is the only library materialization path; the exporter never reads `templates/sounds/`, and sidecars store paths, not ids.
**Default — silence**: never add sound to demonstrate capability or for coverage; a sound supports a named transition, reveal, confirmation, warning, or gesture after that visual behavior is selected.
**Hard rule — PPTX and MP4 are separate deliveries**: sound fields and read-back prove the PPTX carries the cue, not that PowerPoint's encoder put it in the MP4. A narrated MP4 with cues follows `generate-audio` — mix from the final narrated trace plus final PPTX, or capture the live Slide Show with system audio, never both — and keeps gain/limiter settings out of `animations.json`.
---
@@ -141,19 +157,47 @@ python3 skills/ppt-master/scripts/svg_to_pptx.py <project> --auto-advance 5
python3 skills/ppt-master/scripts/svg_to_pptx.py <project> -t none --auto-advance 5
```
The registry covers PowerPoint's complete Subtle, Exciting, and Dynamic Content gallery — 48 canonical keys (`pptx_animations.py --list`); eight old low-level names desugar to a native key plus options (`diamond``shape` + `shape: diamond`, `wedge``clock` + `style: wedge`) and are never selected for new output. `transition.effect_options` exposes the real Effect Options (Push/Wipe direction, Morph by object/word/character, Reveal through black, Shape geometry, Page Curl direction/pages, Glitter pattern, Fly Through bounce; `pptx_animations.py --describe-transition <effect>`); unknown options fail. Effects needing newer namespaces carry a `mc:Choice` plus a `fade` fallback that validation never accepts as a substitute. `transition.sound` (a sidecar field, `.wav`, synced under §2.2) may accompany `effect: none`; a slide-level `transition.sound: null` clears an inherited default transition sound. Flags: `-t/--transition` (native key, compatibility input, or `none`; default `fade`; `none` keeps an explicit auto-advance), `--transition-duration` (default `0.4`), `--auto-advance` (seconds; click still advances). **Hard rule — no silent downgrade**: an unknown effect, unsupported option, or invalid duration fails export and is never replaced by `fade`; `-t none --recorded-narration …` writes narration-driven advance without restoring a visual effect.
**Registry**: PowerPoint's complete Subtle, Exciting, and Dynamic Content gallery — 48 canonical keys (`pptx_animations.py --list`); old low-level names normalize to a native key plus options and are never selected for new output. `transition.effect_options` exposes each effect's real Effect Options (`pptx_animations.py --describe-transition <effect>`); `transition.sound` (a `.wav` synced under §2.2) may accompany `effect: none`.
| Flag | Meaning |
|---|---|
| `-t/--transition` | Default `fade`; `none` keeps an explicit auto-advance |
| `--transition-duration` | Default `0.4` |
| `--auto-advance` | Seconds; click still advances |
**Hard rule — no silent downgrade**: an unknown effect, unsupported option, or invalid duration fails export and is never replaced by `fade`. Carrier XML, MCE fallbacks, and read-back: [`pptx-transitions.md`](../scripts/docs/pptx-transitions.md).
### 3.1 Morph — author an action as the difference between two pages
Morph tweens matched objects across consecutive slides, so any continuous action is two static pages plus Morph: duplicate the page, change one property, PowerPoint interpolates. Off-canvas → on-canvas reads as slide-in, drawer, card extending; rotation as flip, turn, hinge; a scaled image container as camera push-in; a dropping scrim or growing cut as progressive reveal; the same wide image at two `x` offsets as camera pan (`#C2-01`). Chain three or more pages for extendholdretract.
Morph tweens matched objects across consecutive slides, so any continuous action is two static pages plus Morph: duplicate the page, change one property, PowerPoint interpolates. Chain three or more pages for extendholdretract.
**Hard rule — matching needs compatible identity, not identical geometry**: prefer §2.1 pairs; ids and visible state may differ, but both endpoints must resolve to one compatible top-level PowerPoint object kind — a shape and a picture cross-fade instead of tweening. Automatic Morph is heuristic. **Give text somewhere to come from**: text present only on the second page can only fade in — place the next page's copy just below the canvas and the previous page's just above, so blocks slide through the frame; a wholly off-canvas endpoint is one direct-root `<g id>` with valid `data-pptx-bounds` and `data-pptx-morph-staging="true"`, explicitly paired when Morph stays enabled; the marker never excuses a partially clipped group. Declare identity through the destination's `morph` block, never `data-pptx-shape-name` (importer metadata, [`svg-effects.md`](./svg-effects.md) §6.6). **Not supported**: Slide Zoom / Summary Zoom (build click navigation with `trigger_shape` or hyperlinks) and 3D — perspective, extrusion, and shear fail closed ([`svg-effects.md`](./svg-effects.md) §6.8); build the impression with offset, scale, overlap, and per-facet lightness.
| Property change | Reads as |
|---|---|
| Off-canvas → on-canvas | Slide-in, drawer, card extending |
| Rotation | Flip, turn, hinge |
| A scaled image container | Camera push-in |
| A dropping scrim or growing cut | Progressive reveal |
| The same wide image at two `x` offsets | Camera pan (`#C2-01`) |
**Hard rule — matching needs compatible identity, not identical geometry**: prefer §2.1 pairs; ids and visible state may differ, but both endpoints must resolve to one compatible top-level PowerPoint object kind — a shape and a picture cross-fade instead of tweening. Automatic Morph is heuristic.
**Give text somewhere to come from**: text present only on the second page can only fade in — place the next page's copy just below the canvas and the previous page's just above, so blocks slide through the frame. A wholly off-canvas endpoint is one direct-root `<g id>` with valid `data-pptx-bounds` and `data-pptx-morph-staging="true"`, explicitly paired when Morph stays enabled; the marker never excuses a partially clipped group. Declare identity through the destination's `morph` block, never `data-pptx-shape-name` (importer metadata, [`svg-effects.md`](./svg-effects.md) §6.6).
**Not supported**: Slide Zoom / Summary Zoom (build click navigation with `trigger_shape` or hyperlinks) and 3D — perspective, extrusion, and shear fail closed ([`svg-effects.md`](./svg-effects.md) §6.8); build the impression with offset, scale, overlap, and per-facet lightness.
---
## 4. Per-Element Animations
Off by default; enable with `-a auto` (or another effect), select a canonical effect with `--animation entrance_fade`, and choose Start with `--animation-trigger on-click|with-previous|after-previous` — PowerPoint's Start dropdown: `on-click` (each click reveals the next group; only for a controlled semantic reveal; forbidden with `--recorded-narration`), `with-previous` (one coordinated beat; stagger ignored), `after-previous` (default click-free cascade with `--animation-stagger`). **Default — one dominant deck rhythm and normally one mode per slide (may mix for a distinct simultaneous or presenter-controlled beat)**. Row-specific `trigger_shape` is PowerPoint's separate Trigger → On Click of, not a fourth mode.
Off by default; enable with `-a auto` (or another effect), select a canonical effect with `--animation entrance_fade`, and choose Start with `--animation-trigger on-click|with-previous|after-previous` — PowerPoint's Start dropdown.
| Start | Behavior |
|---|---|
| `on-click` | Each click reveals the next group; only for a controlled semantic reveal; forbidden with `--recorded-narration` |
| `with-previous` | One coordinated beat; stagger ignored |
| `after-previous` | Default click-free cascade with `--animation-stagger` |
**Default — one dominant deck rhythm and normally one mode per slide (may mix for a distinct simultaneous or presenter-controlled beat)**. Row-specific `trigger_shape` is PowerPoint's separate Trigger → On Click of, not a fourth mode.
**Mandatory — lifecycle before effect**: start from `static`, classify `initial → action → end`, then choose the effect; generic staged reveals are `enter`, narrower jobs select their lifecycle.
@@ -167,11 +211,11 @@ Off by default; enable with `-a auto` (or another effect), select a canonical ef
**Default — restrained entrance-led choreography (may override for content, tone, or the request)**: entrances for ordinary builds; emphasis or exit only for a real duty; several `effects[]` rows only for several duties.
The registry has **203 native object presets** 53 `entrance_*`, 33 `emphasis_*`, 64 `path_*`, 53 `exit_*` (e.g. `entrance_bounce`, `emphasis_spin`, `path_circle`, `exit_faded_zoom`), each carrying the complete PowerPoint behavior tree — plus 29 legacy compatibility inputs that normalize before selection (`fade``entrance_fade`, old Fly/Wipe direction names → `entrance_fly` / `entrance_wipe` with the direction in `effect_options`, `cut``entrance_appear`, `wheel``entrance_wheel` with four spokes) and are never written. `python3 skills/ppt-master/scripts/pptx_animations.py --list` prints the categorized keys; media play/pause/stop belong to the audio/video workflows. Modes handle generic `enter` only: `auto` maps semantic ids to canonical entrances (charts/tables/timelines `entrance_wipe`, cards/steps `entrance_fly`, titles/takeaways `entrance_fade`, image-like ids a richer pool, others fade/wipe/fly/zoom); `mixed` is deterministic (`entrance_fade` first, then a 16-effect canonical pool); `random` samples the same pool, seeded from the effective deck input so results repeat; `entrance_appear` is excluded from every pool; none satisfies an adopted `emphasize`, `move`, or `exit`. Flags: `-a/--animation`, `--animation-trigger`, `--animation-duration`, `--animation-stagger`, `--animation-config <sidecar>`, `--no-animations` (kills page/object motion, keeps narration audio and recorded advance). `--recorded-narration` rejects `on-click` and `trigger_shape`; narration-cue sync uses `narration_animations.json` and blocks on a bare canonical sidecar; narration-independent custom motion passes `--animation-config animations.json` explicitly; with no sidecar pass `--inherit-motion-from <base_postflight_report>`.
**Registry**: **203 native object presets**`entrance_*`, `emphasis_*`, `path_*`, `exit_*` (`pptx_animations.py --list` prints the categorized keys); 29 legacy short names normalize before selection and are never written. Modes handle generic `enter` only: `auto` maps semantic ids to canonical entrances, `mixed` cycles a deterministic pool, `random` samples it with a stable seed; none satisfies an adopted `emphasize`, `move`, or `exit`. Flags (`-a`, `--animation-trigger`, `--animation-duration`, `--animation-stagger`, `--animation-config`, `--no-animations`) and their narration interactions: [`pptx-animations.md`](../scripts/docs/pptx-animations.md) §3 and [`svg-pipeline.md`](../scripts/docs/svg-pipeline.md).
### 4.1 Slow ambient motion — the page that breathes
**Reference — not a constraint**: `path_left` / `path_right` on a background image, started `with-previous` and paced far slower than a content reveal, keeps a static page from feeling frozen while staying subordinate; the same applies to any non-information-bearing layer, with duration, distance, and moving-object count from the composition. A full-bleed moving image must cover the canvas at both endpoints. With a fixed foreground (`#M1-07`, also `#M1-10`, `#P1-09`) the scrim and its cuts stay locked while the world moves behind them — windows, not a sliding photo. Coordinated layers are valid for one depth or atmosphere relationship; competing paths or motion that hurts copy or data are not.
**Reference — not a constraint**: `path_left` / `path_right` on a background image, started `with-previous` and paced far slower than a content reveal, keeps a static page from feeling frozen while staying subordinate. The same applies to any non-information-bearing layer, with duration, distance, and moving-object count from the composition. A full-bleed moving image must cover the canvas at both endpoints. With a fixed foreground (`#M1-07`, also `#M1-10`, `#P1-09`) the scrim and its cuts stay locked while the world moves behind them — windows, not a sliding photo. Coordinated layers are valid for one depth or atmosphere relationship; competing paths or motion that hurts copy or data are not.
### 4.2 Recurring recipes
@@ -184,23 +228,30 @@ The registry has **203 native object presets** — 53 `entrance_*`, 33 `emphasis
## 5. Anchor Logic — Top-Level `<g id="...">`
Animations anchor on unique top-level `<g id>` content groups (`cover-title`, `card-1`); a single-effect group yields one Animation Pane row, `effects[]` several, each inheriting the slide Start unless it declares `trigger`; nested groups stay anonymous and untargeted. **Hard rule — existing groups are not custom-animation intent**: during the custom stage derive one group per logical motion unit from claims, comparisons, sequence, causality, and narration — splitting coarse wrappers and merging fragments without changing appearance, never to hit a count — and run `list-groups` only after that rewrite. **Chrome stays static**: `data-pptx-layer` and explicit static role/placeholder markers are absolute; the legacy chrome-name heuristic (background, header/footer, decor, watermark, page number, nav, logo, rule) applies only to unmarked top-level groups and only it may be overridden by a sidecar entry. Flat SVGs with no top-level `<g>`: ≤8 visible root primitives each become an anchor, more skips animation on that slide. Wrap logical sections in `<g id>` regardless ([`shared-standards-core.md`](./shared-standards-core.md)).
Animations anchor on unique top-level `<g id>` content groups (`cover-title`, `card-1`). A single-effect group yields one Animation Pane row, `effects[]` several, each inheriting the slide Start unless it declares `trigger`; nested groups stay anonymous and untargeted.
**Hard rule — existing groups are not custom-animation intent**: during the custom stage derive one group per logical motion unit from claims, comparisons, sequence, causality, and narration — splitting coarse wrappers and merging fragments without changing appearance, never to hit a count — and run `list-groups` only after that rewrite.
**Chrome stays static**: `data-pptx-layer` and explicit static role/placeholder markers are absolute. The legacy chrome-name heuristic (background, header/footer, decor, watermark, page number, nav, logo, rule) applies only to unmarked top-level groups, and only it may be overridden by a sidecar entry. Wrap logical sections in `<g id>` ([`shared-standards-core.md`](./shared-standards-core.md) §4.3); a root with no top-level group falls back to a bounded primitive set ([`svg-pipeline.md`](../scripts/docs/svg-pipeline.md)).
---
## 6. Validation and Read-Back
Export fails on an unknown effect, mode, or trigger; invalid timing or order; a missing slide, group, or `trigger_shape`; a self-trigger; or animating or triggering from a structural layer — never downgrading or omitting a target. It reads each slide's timing tree back (row count and order including repeats on one shape, trigger, trigger shape, target, preset class, effect tuple, behavior signature, duration, offset), validates root timing placement, unique `p:cTn` ids, and every `p:spTgt`, and for deterministic Morph checks the adjacent parts for the `!!` names, one-to-one uniqueness, compatible types, and a real Morph-by-object transition. The writer emits no `p:bldP` for groups or pictures (preserve mode tolerates legacy ones). Narration injection preserves animation and keeps p14 Choice/Fallback in sync; direct-PPTX routes fingerprint source timing before and after their edits and never author effects. `pptx_to_svg.py` projects supported source `p:transition` (registry effect, options, exact duration, auto-advance, WAV sound; sidecar default `none`) and only current generated `p:timing` trees (registry effect, pane order, Start, exact duration, relative delay, unique top-level targets) into `animations.json`; unknown carriers, missing durations, advanced modifiers, sounds, builds, and unmapped targets stay diagnosed/direct-preserve with no inferred value. These checks prove PPTX timing and embedded sound parts, not final-video audio: the native-export branch needs a `video_sound_mix.py` receipt and the capture branch the human acceptance owned by `generate-audio`.
Export rejects an unknown effect, mode, or trigger, invalid timing or order, a missing slide, group, or `trigger_shape`, and any structural-layer target, then reads every slide back and compares it with the request; nothing is downgraded or omitted. The complete rules, the reverse projection `pptx_to_svg.py` writes into `animations.json`, and what read-back does not prove (final-video audio) are [`pptx-animations.md`](../scripts/docs/pptx-animations.md) §6 and [`pptx-transitions.md`](../scripts/docs/pptx-transitions.md) §6.
---
## 7. Video Adaptation Contract
Video renderers consume the resolved conversion trace through `video_motion_plan.py` ([`video-motion-plan.md`](../scripts/docs/video-motion-plan.md)), never a raw sidecar or delay inference; the plan locks identity, order, effect, direction, and timing, video refines only its declared renderer parameters, and unsupported families fail visibly. The native-export mix uses the final trace for cue order and offsets, the final PPTX relationships for the embedded bytes, and page-level narration correlation for the clock; the slideshow-capture branch records real-time playback and does not consume the trace.
Video renderers consume the resolved conversion trace through `video_motion_plan.py` ([`video-motion-plan.md`](../scripts/docs/video-motion-plan.md)), never a raw sidecar; the plan locks identity, order, effect, direction, and timing.
## 8. Limitations
Generated animation belongs to the native PPTX built from `svg_output/` (`svg_final/` is static and inserting it creates no anchors); PowerPoint OOXML is the compatibility target and other apps may reinterpret behavior trees; PowerPoint's MP4 encoder may drop transition and object sounds, so sound-enabled MP4 uses the post-export mix or the capture contract; direct-PPTX routes preserve unknown transition `AlternateContent` and keep Choice/Fallback advance attributes synchronized.
- Generated animation belongs to the native PPTX built from `svg_output/`; `svg_final/` is static and inserting it creates no anchors.
- PowerPoint OOXML is the compatibility target; other apps may reinterpret behavior trees.
- PowerPoint's MP4 encoder may drop transition and object sounds, so sound-enabled MP4 uses the post-export mix or the capture contract.
- Direct-PPTX routes preserve unknown transition `AlternateContent` and keep Choice/Fallback advance attributes synchronized.
## 9. Implementation References
@@ -1,8 +1,8 @@
# Executor Flat and Shared Core
Always-loaded Executor authority for flat SVG page authoring, shared by Default and Quick. Executor is the crew that builds the finished pages on the plan's structure: it receives the blueprint (§2), owns every decision judged on the canvas — carrier mix, geometry, composition, hierarchy, treatment — and draws from the expression vocabulary below. Items marked `Default only` bind to the persisted Design Spec / `spec_lock.md`; Quick applies the same craft to the transient anchors from [`quick-generate.md`](../workflows/profiles/quick-generate.md) §2, and its own pacing, single final checker, and export replace the Default gates and §6.
Always-loaded Executor authority for flat SVG page authoring, shared by Default and Quick. Executor builds the finished pages on the plan's structure: it receives the blueprint (§2), owns every decision judged on the canvas — carrier mix, geometry, composition, hierarchy, treatment — and draws from the expression vocabulary in the Page Expression Core. Items marked `Default only` bind to the persisted Design Spec / `spec_lock.md`. Quick applies the same craft to the transient anchors from [`quick-generate.md`](../workflows/profiles/quick-generate.md) §2; its own pacing, single final checker, and export replace the Default gates and §6.
**Conditional branch routing** evaluate every trigger once over the whole roster before P01 (Default: §IX; Quick: the frozen transient roster) and read the triggered modules then, in one batch, so that reading stays out of the page loop; a page that reaches a capability the sweep did not foresee reads its module at that moment, before that page's first SVG line:
**Conditional branch routing**: evaluate every trigger once over the whole roster before P01 (Default: §IX; Quick: the frozen transient roster). Read the triggered modules then, in one batch, so that reading stays out of the page loop. A page that reaches a capability the sweep did not foresee reads its module at that moment, before that page's first SVG line.
| Trigger | Load |
|---|---|
@@ -11,7 +11,7 @@ Always-loaded Executor authority for flat SVG page authoring, shared by Default
| Any value-driven geometry, including a chart-family reference, mini chart, sparkline, inset, or small multiple | [`executor-chart.md`](./executor-chart.md) |
| Any semantic cell grid, including a table-family reference | [`executor-table.md`](./executor-table.md) |
| A page uses a preset pattern fill, or an independent Chart/Table object is resolved as `<object-key>=yes` | [`native-data-interface.md`](./native-data-interface.md) before emitting the pattern or replacement metadata |
| The per-page Structure decision is `yes` for the first time | [`executor-structure.md`](./executor-structure.md) + [`topology-assembly.md`](./topology-assembly.md) |
| The per-page topology decision is `yes` for the first time | [`executor-structure.md`](./executor-structure.md) + [`topology-assembly.md`](./topology-assembly.md) |
| A page's contour reaches beyond rectangle, rounded rectangle, circle, ellipse, and line — an inflected carrier (snipped or one-sided rounded rectangle, plaque, bevel, polygon, pie / arc / donut, frame, corner, folded corner, trapezoid, parallelogram) as much as a relationship symbol (block arrow, chevron, callout, flowchart node, banner, star, bracket, connector) — or needs a Boolean / freeform decision | [`native-shape-authoring.md`](./native-shape-authoring.md), read completely (the preset vocabulary is already resident) |
| A page's visual job reaches beyond the everyday block below — faux glass, constructed styles (hand-drawn, ink, riso, pixel, halftone, paper-cut, facets, gradient ribbon), gradient stroke, text picture/texture fill, gauge / sunburst / explicit arc geometry, freeform curves, transforms beyond rotate, or an unsupported effect needing a native-safe alternative | [`svg-effects.md`](./svg-effects.md) |
| Any image | [`executor-image.md`](./executor-image.md) + [`image-layout-spec.md`](./image-layout-spec.md) + [`image-layout-patterns.md`](./image-layout-patterns.md) + [`svg-image-embedding.md`](./svg-image-embedding.md) |
@@ -20,13 +20,17 @@ Always-loaded Executor authority for flat SVG page authoring, shared by Default
| Any placed image is `Status: Sourced` or its filename has an `image_sources.json` record | [`executor-web-image.md`](./executor-web-image.md), after `executor-image.md` |
| Effective Speaker Notes outcome is enabled after all SVG pages pass | [`executor-notes.md`](./executor-notes.md) |
Evaluate branches from each object's actual information model, not only from a Chart/Table reference: a catalog family selects construction guidance, never native readiness, and page-local qualitative geometry never implies `pptx_structure.mode: structured`. Narrative skeleton and aesthetic come from the confirmed mode / visual-style values (Default: the lock; Quick: the active context): when a value names a catalog preset, read that one file; when it is `custom` with `*_references`, read only those files (one basis under its behavior, or several by their stated contributions); a `custom` without references reads no catalog file and follows its behavior prose alone; the planning indexes are never reopened. [`shared-standards-core.md`](./shared-standards-core.md) supplies the technical boundary and the fallback visual-quality and leading defaults.
**Branch evaluation reads the information model**: evaluate branches from each object's actual information model, not only from a Chart/Table reference. A catalog family selects construction guidance, never native readiness. Page-local qualitative geometry never implies `pptx_structure.mode: structured`.
**Hard rule — Shape-first page authority**: every visible object of the exported slide exists in the final page SVG or is explicitly referenced by it; templates and `spec_lock.md` guide construction and never supply content at export. Optional native Chart/Table metadata belongs to an independently selected object and never replaces the visible fallback ([`native-data-interface.md`](./native-data-interface.md)); a native formula marker keeps a matching SVG preview that export alone replaces ([`native-formula.md`](./native-formula.md)).
**Mode and visual-style files**: the narrative skeleton and aesthetic come from the confirmed mode / visual-style values (Default: the lock; Quick: the active context). A value naming a catalog preset reads that one file. A `custom` with `*_references` reads only those files (one basis under its behavior, or several by their stated contributions). A `custom` without references reads no catalog file and follows its behavior prose alone. The planning indexes are never reopened. [`shared-standards-core.md`](./shared-standards-core.md) supplies the technical boundary and the fallback visual-quality and leading defaults.
**Hard rule — flat PowerPoint structure**: free-design, brand-only, Style-only, and `template_reuse_scope: style` projects use `pptx_structure.mode: flat`: no root Master/Layout identity, `data-pptx-layer`, or `data-pptx-placeholder`; every object Slide-local; the root declares exactly one `data-pptx-page-role` (`cover` / `toc` / `section` / `content` / `ending`). A Style supplies direction, rhythm, and expression defaults without prototypes; its identity-adjacent defaults yield to the final Brand/Deck identity and the lock, and beside Layout/Deck it changes only method. Add `data-pptx-role` only to page-frame objects whose package, page-number, or animation behavior no specialized marker expresses, with a stable unique `id` ([`semantic-svg.md`](./semantic-svg.md)).
**Hard rule — Shape-first page authority**: every visible object of the exported slide exists in the final page SVG or is explicitly referenced by it. Templates and `spec_lock.md` guide construction and never supply content at export. Optional native Chart/Table metadata belongs to an independently selected object and never replaces the visible fallback ([`native-data-interface.md`](./native-data-interface.md)). A native formula marker keeps a matching SVG preview that export alone replaces ([`native-formula.md`](./native-formula.md)).
**Hard rule — supported PPTX route**: `svg_output/` through the project converter is the only generated-PPTX path; `svg_final/` is an optional preview and PowerPoint's manual Convert-to-Shape is not an authoring target ([`shared-standards-core.md`](./shared-standards-core.md) §4.2). Speaker notes, animations, transitions, narration, and native-PPTX workflows keep their own artifacts.
**Hard rule — flat PowerPoint structure**: free-design, brand-only, Style-only, and `template_reuse_scope: style` projects use `pptx_structure.mode: flat`: no root Master/Layout identity, `data-pptx-layer`, or `data-pptx-placeholder`; every object Slide-local; the root declares exactly one `data-pptx-page-role` (`cover` / `toc` / `section` / `content` / `ending`). Add `data-pptx-role` only to page-frame objects whose package, page-number, or animation behavior no specialized marker expresses, with a stable unique `id` ([`semantic-svg.md`](./semantic-svg.md)).
**Style workspace under flat structure**: a Style supplies direction, rhythm, and expression defaults without prototypes. Its identity-adjacent defaults yield to the final Brand/Deck identity and the lock. Beside Layout/Deck it changes only method.
**Hard rule — supported PPTX route**: `svg_output/` through the project converter is the only generated-PPTX path. `svg_final/` is an optional preview, and PowerPoint's manual Convert-to-Shape is not an authoring target ([`shared-standards-core.md`](./shared-standards-core.md) §4.2). Speaker notes, animations, transitions, narration, and native-PPTX workflows keep their own artifacts.
---
@@ -34,15 +38,15 @@ Evaluate branches from each object's actual information model, not only from a C
Read this before §1: the expression vocabulary every page draws from — what exists, recalled here so it is available at the moment a page is composed. The contracts below bound how it is written, not whether it is available; the full manuals load on their routing triggers.
**Capability — typographic feature elements**: beyond the structural roles fixed by `typography` anchors, a page may carry a lead-in sentence, an inline emphasis run, a pull quote, a kicker, a hero number, a takeaway line — each its own feature element with its own size and treatment; a recurring one becomes a named role.
**Capability — typographic feature elements**: beyond the structural roles fixed by `typography` anchors, a page may carry a lead-in sentence, an inline emphasis run, a pull quote, a kicker, a hero number, or a takeaway line — each its own feature element with its own size and treatment. A recurring one becomes a named role.
**Capability — inline emphasis is one editable frame**: a `<text>` paragraph may nest non-positional `<tspan>` runs with their own `fill`, `font-weight`, or `font-size`; export emits one DrawingML run per styled segment inside the same editable frame, and positioned line-break `<tspan>` children may themselves contain inline runs.
**Capability — inline emphasis is one editable frame**: a `<text>` paragraph may nest non-positional `<tspan>` runs with their own `fill`, `font-weight`, or `font-size`. Export emits one DrawingML run per styled segment inside the same editable frame. Positioned line-break `<tspan>` children may themselves contain inline runs.
```xml
<text x="72" y="300" font-size="24" fill="#2E3230">腐朽但仍可加固接续的<tspan fill="#9E2B25" font-weight="bold">千年木梁,不做整体更换</tspan>;风化的古墙,只做防风化微创处理。</text>
```
**Capability — native contour families**: beyond rectangle, rounded rectangle, circle, ellipse, and line, the complete Office vocabulary is drawable and stays editable in PowerPoint carrier and field contours that hold content or cut the page (snipped and one-sided rounded rectangles, plaque and bevel, triangles, hexagons and other polygons, trapezoids and parallelograms, pies, arcs, and donuts, frames, corners, stripes, and folded corners), block arrows and chevrons for direction and steps, flowchart symbols for process and decision, callouts, brackets and braces, stars and banners, bent and curved connectors, and equation shapes — each through `preset_shape_svg.py`, with Merge Shapes results through `shape_boolean_svg.py`. [`preset-shape-vocabulary.md`](./preset-shape-vocabulary.md) is the full list; §3.0 owns selection and encoding.
**Capability — native contour families**: beyond rectangle, rounded rectangle, circle, ellipse, and line, the complete Office vocabulary is drawable and stays editable in PowerPoint: carrier and field contours that hold content or cut the page (snipped and one-sided rounded rectangles, plaque and bevel, triangles, hexagons and other polygons, trapezoids and parallelograms, pies, arcs, and donuts, frames, corners, stripes, and folded corners), block arrows and chevrons for direction and steps, flowchart symbols for process and decision, callouts, brackets and braces, stars and banners, bent and curved connectors, and equation shapes. Each comes through `preset_shape_svg.py`; Merge Shapes results come through `shape_boolean_svg.py`. [`preset-shape-vocabulary.md`](./preset-shape-vocabulary.md) is the full list; §3.0 owns selection and encoding.
**Reference — everyday device menu (not a constraint, not a quota)**: the pieces most slides are built from.
@@ -79,22 +83,46 @@ Read this before §1: the expression vocabulary every page draws from — what e
| Wide visual + explanation | Top-bottom split, or figure-text overlap for a hero moment | Visual ≥ 55% of the field |
| Page-field organization | One large surface, outline, aperture, or off-canvas contour organizes the zones instead of a card per unit | Field spans two or more zones |
Repeating symmetric card grids without a page job is the failure mode these structures exist to avoid; a page-field, outline carrier, nested field, or continuity construction is compared before stacked cards or uniform equal columns ([`native-shape-authoring.md`](./native-shape-authoring.md) §2.1 composition lenses — page field, outline carrier, nested fields, continuity, depth and contrast, deck language).
Repeating symmetric card grids without a page job is the failure mode these structures exist to avoid. Compare a page-field, outline carrier, nested field, or continuity construction before stacked cards or uniform equal columns ([`native-shape-authoring.md`](./native-shape-authoring.md) §2.1 composition lenses — page field, outline carrier, nested fields, continuity, depth and contrast, deck language).
**Reference — page-level recipes (back to front; omit every layer without a job)**: cover = hero field → optional scrim/wash → purposeful opening/contour → native title; divider = image band or quiet field → restrained wash → recurring geometry → number/title; text-led explanation = quiet field → recurring material/contour → native hierarchy → local emphasis; process/system = context field → native relation lines → nodes/labels → optional state/direction focus; evidence/metric = context field → local contrast → native leaders/labels/metric → optional focus/elevation; comparison = matched planes → shared wash/divider → matched labels → one difference marker; closing = receded field → echoed contour/gradient → native action → raised accent; cross-page motif = reuse contour, gradient direction, line language, texture, or light logic and vary scale, crop, position by page job. Full stacks and stops: [`svg-effects.md`](./svg-effects.md) §6.13.
**Reference — page-level recipes (back to front; omit every layer without a job)**. Full stacks and stops: [`svg-effects.md`](./svg-effects.md) §6.13.
| Page | Layers back to front |
|---|---|
| Cover | hero field → optional scrim/wash → purposeful opening/contour → native title |
| Divider | image band or quiet field → restrained wash → recurring geometry → number/title |
| Text-led explanation | quiet field → recurring material/contour → native hierarchy → local emphasis |
| Process / system | context field → native relation lines → nodes/labels → optional state/direction focus |
| Evidence / metric | context field → local contrast → native leaders/labels/metric → optional focus/elevation |
| Comparison | matched planes → shared wash/divider → matched labels → one difference marker |
| Closing | receded field → echoed contour/gradient → native action → raised accent |
| Cross-page motif | reuse contour, gradient direction, line language, texture, or light logic; vary scale, crop, position by page job |
**Reference — image composition families (any image page)**: `P1` single visual (side, band, inset, hero), `P2` image as canvas with native overlay, `P3` multi-visual (grid, collage, sequence, compare); modifiers `M1` reveal / crop / registration, `M2` tone / focus / contrast (scrim, wash, vignette, spotlight), `M3` framing / placement / depth; prepared-asset `A` treatments and cross-page `C` continuity. Catalog and situation router: [`image-layout-patterns.md`](./image-layout-patterns.md); integration decision: [`executor-image.md`](./executor-image.md).
**Reference — visual job router (recall; the full table is [`svg-effects.md`](./svg-effects.md) §6.1)**: missing direction, continuous value, or center focus → gradient or channel alpha; unclear elevation or boundary → one-light shadow, restrained glow, or hairline; copy and image not integrating → scrim, fade, wash, vignette, spotlight, or faux glass; unclear relationship state → dash for draft/optional, marker for direction, gradient stroke for flow, frame/contour for boundary; a load-bearing figure lost in a scan → inline emphasis run; display text needing silhouette or material → outline, gradient, picture/texture fill, tracking, glow; a style asking for hand, print, pixel, facets, layers, or ribbon → the matching constructed recipe; an unmatched silhouette, radial hierarchy, or gauge → freeform, explicit arc/sector, or calculated arrowhead.
**Reference — visual job router (recall; the full table is [`svg-effects.md`](./svg-effects.md) §6.1)**:
| Visual job | Candidate device |
|---|---|
| Missing direction, continuous value, or center focus | gradient or channel alpha |
| Unclear elevation or boundary | one-light shadow, restrained glow, or hairline |
| Copy and image not integrating | scrim, fade, wash, vignette, spotlight, or faux glass |
| Unclear relationship state | dash for draft/optional, marker for direction, gradient stroke for flow, frame/contour for boundary |
| A load-bearing figure lost in a scan | inline emphasis run |
| Display text needing silhouette or material | outline, gradient, picture/texture fill, tracking, glow |
| A style asking for hand, print, pixel, facets, layers, or ribbon | the matching constructed recipe |
| An unmatched silhouette, radial hierarchy, or gauge | freeform, explicit arc/sector, or calculated arrowhead |
**Reference — everyday effects and aesthetic defaults (self-contained; the full contract and rarer techniques are [`svg-effects.md`](./svg-effects.md))**:
- **Color**: 60-30-10 as the starting proportion (dominant field ≈ 60%, support ≈ 30%, accent ≈ 10%), body text contrast ≥ 4.5:1, hue count following encoding and natural assets; cover and chapter pages may use the theme color as a large field; same-hue gradients add depth; the accent color goes on the key number or word to create focus, not everywhere; cool tones read technical, warm tones energetic, dark fields grave; trends use green up / red down / gray flat with the deck's polarity roles.
- **Rhythm and weight**: follow a data-heavy page with a breathing page; balance visual weight — dark or large elements are heavy, light or small ones light — across left/right and top/bottom; a chapter may share one carrier system while chapters vary, provided each repetition has a page job. A content page may add a one-sentence takeaway band under the title and a muted source note at the page bottom (title voice belongs to the locked mode).
- **Depth through restraint**: depth comes from rhythm (flat vs lifted, dense vs spacious), not shadows everywhere — shadow 23 genuinely floating objects per page at most (card over a photo or colored panel, the primary CTA, an overlay) and keep peer-grid cards, dividers, and body containers flat; reach for weight, spacing, accent bars, and tints before shadow; pick one weight tool per container (shadow, border, gradient fill, or strong tint — never stacked); one light source per page (`dx="0"`, `dy="4"``"8"`); the shadow is felt, not seen — resting `flood-opacity` 0.060.10, raised at most 0.20 (above that is the Office 2007 look); on dark fields use a light hairline or a restrained glow instead of black shadow.
- **Image overlays**: a directional scrim darkest beside the text (`0.88 → 0.30 → 0`), a bottom fade under a lower title (`0 → 0.72`), a radial vignette for atmosphere (`0 → 0.58`), or a brand wash (`0.80 → 0.10`); never a uniform flat opacity over the whole image or a solid black plate.
- **Color proportion**: 60-30-10 as the starting proportion (dominant field ≈ 60%, support ≈ 30%, accent ≈ 10%); body text contrast ≥ 4.5:1; hue count follows encoding and natural assets.
- **Color use**: cover and chapter pages may use the theme color as a large field; same-hue gradients add depth; the accent color goes on the key number or word to create focus, not everywhere. Cool tones read technical, warm tones energetic, dark fields grave. Trends use green up / red down / gray flat with the deck's polarity roles.
- **Rhythm and weight**: follow a data-heavy page with a breathing page. Balance visual weight — dark or large elements are heavy, light or small ones light — across left/right and top/bottom. A chapter may share one carrier system while chapters vary, provided each repetition has a page job. A content page may add a one-sentence takeaway band under the title and a muted source note at the page bottom (title voice belongs to the locked mode).
- **Depth through restraint**: depth comes from rhythm (flat vs lifted, dense vs spacious), not shadows everywhere. Shadow 23 genuinely floating objects per page at most (card over a photo or colored panel, the primary CTA, an overlay); keep peer-grid cards, dividers, and body containers flat. Reach for weight, spacing, accent bars, and tints before shadow. Pick one weight tool per container (shadow, border, gradient fill, or strong tint — never stacked).
- **Shadow values**: one light source per page (`dx="0"`, `dy="4"``"8"`). The shadow is felt, not seen — resting `flood-opacity` 0.060.10, raised at most 0.20 (above that is the Office 2007 look). On dark fields use a light hairline or a restrained glow instead of black shadow.
- **Image overlays**: a directional scrim darkest beside the text (`0.88 → 0.30 → 0`), a bottom fade under a lower title (`0 → 0.72`), a radial vignette for atmosphere (`0 → 0.58`), or a brand wash (`0.80 → 0.10`). Never a uniform flat opacity over the whole image or a solid black plate.
- **Lines**: `stroke-dasharray` `4,4` separator, `2,2` placeholder outline, `8,4` timeline or flow connector, `8,4,2,4` dimension line; `marker-end` for connector arrowheads; divider hairlines at 0.20.3 alpha.
- **Inline emphasis**: lift numerical results, before/after contrasts, and one or two load-bearing nouns per sentence as bold runs in the primary color; never connectives, common verbs, every noun, decorative adjectives, or structural text (footer, axis, legend, page number); reserve green/red for real polarity.
- **Inline emphasis**: lift numerical results, before/after contrasts, and one or two load-bearing nouns per sentence as bold runs in the primary color. Never connectives, common verbs, every noun, decorative adjectives, or structural text (footer, axis, legend, page number). Reserve green/red for real polarity.
```xml
<defs>
@@ -125,53 +153,85 @@ Repeating symmetric card grids without a page job is the failure mode these stru
## 1. Effect Capability Discovery
**Reference — effects are a triggered module**: the everyday block above covers gradients, cards, shadow, glow, scrims, dashes, and inline emphasis for most pages. Load [`svg-effects.md`](./svg-effects.md) when the pre-P01 sweep or a page's job reaches beyond it (routing table above); once loaded, its §6.1 Visual Job Router recalls candidates and §6.13 offers coordinated page recipes, and it stays in context for the rest of the run. Active cross-page continuous action additionally loads [`animations.md`](./animations.md) §3.1 before authoring both endpoints.
**Reference — effects beyond the everyday block**: the everyday block above covers most pages. Once [`svg-effects.md`](./svg-effects.md) is loaded on its routing-table trigger, its §6.1 Visual Job Router recalls candidates and §6.13 offers coordinated page recipes. Active cross-page continuous action additionally loads [`animations.md`](./animations.md) §3.1 before authoring both endpoints.
**Hard rule — discovery does not expand compatibility**: follow `svg-effects.md` syntax and fallbacks; source/backdrop blur, blend mode, `<mask>` / per-pixel masking, dense texture, and skew stay baked or alternative-only.
**Hard rule — discovery does not expand compatibility**: follow `svg-effects.md` syntax and fallbacks. Source/backdrop blur, blend mode, `<mask>` / per-pixel masking, dense texture, and skew stay baked or alternative-only.
**Default — author motion endpoints while pages are still being written (may override when the deck has no continuous action)**: effects, transitions, and Morph pair keys are post-processing, but the two visible endpoint states are not. Only an explicit user motion instruction, an enabled Custom Animations outcome, or an existing `animations.json` activates this; a §IX Motion suggestion alone does not. A sequence that should read as one action (slide-in, flip, push-in, progressive reveal, pan) is authored now as consecutive pages, each continuing endpoint in a compatible direct-root group (ids or geometry may differ; `animations.json` binds them later). A deck exported without both states cannot gain the motion by a flag; adding a page is a §IX roster change and returns to Strategist.
**Default — author motion endpoints while pages are still being written (may override when the deck has no continuous action)**: effects, transitions, and Morph pair keys are post-processing, but the two visible endpoint states are not. A sequence that should read as one action (slide-in, flip, push-in, progressive reveal, pan) is authored now as consecutive pages, each continuing endpoint in a compatible direct-root group; ids or geometry may differ, and `animations.json` binds them later.
| Motion endpoints | Rule |
|---|---|
| Activation | Only an explicit user motion instruction, an enabled Custom Animations outcome, or an existing `animations.json`; a §IX Motion suggestion alone does not activate it |
| Missing state | A deck exported without both states cannot gain the motion by a flag |
| Extra page | Adding a page is a §IX roster change and returns to Strategist |
---
## 2. Blueprint Intake
Executor receives the plan and builds on it: Default reads the retained `design_spec.md` and `spec_lock.md`; Quick holds the same decisions as transient §2 anchors. The plan owns what must be true about every page — content, `Relationships`, roster, rhythm, resources, identity; Executor owns how it looks. Pipeline mechanics of the Default run — context validity and rereads, roster invariance, the five-page lock re-read, recovery from a missing artifact, the pre-P01 parameter confirmation, and the gate cadence — are owned by [`generate-pptx.md`](../workflows/generate-pptx.md) Step 6, not restated here.
Executor receives the plan and builds on it: Default reads the retained `design_spec.md` and `spec_lock.md`; Quick holds the same decisions as transient §2 anchors. The plan owns what must be true about every page — content, `Relationships`, roster, rhythm, resources, identity; Executor owns how it looks. Pipeline mechanics of the Default run — context validity and rereads, roster invariance, the five-page lock re-read, recovery from a missing artifact, the pre-P01 parameter confirmation, and the gate cadence — are [`generate-pptx.md`](../workflows/generate-pptx.md) Step 6.
### 2.1 Execution context and binding
> Quick has no Design Spec or lock: apply the binding, Reference, content-vs-expression, reading-mode, `page_rhythm`, and anchor rules here to its transient §2 anchors.
> Quick has no Design Spec or lock: apply the binding, Reference, content-vs-expression, and anchor rules here, and the §2.2 chain, to its transient §2 anchors.
**Hard rule — binding selection vs realization**: Strategist-selected content and `Relationships`, roster and `page_rhythm`, resource paths, structured-template routing keys, core fonts, palette and spacing anchors, icon-library/stroke anchors, crop boundaries, and any field labeled `(binding)` bind. Everything else — the carrier mix, geometry, composition, and which prepared icon serves a page — is realization, plus the sparse local garnish allowed below. Missing or unresolved material stops execution and returns upstream; never search, generate, download, sync, invent, or substitute it.
**Hard rule — binding selection vs realization**:
**Reference — planning sketches are adjusted freely**: §V/§IX `Layout`, cover/closing composition, capability recommendations, §III motif direction, Chart/Table `family/key` references, §VIII image-layout patterns, and Motion suggestions are starting sketches: adjust or replace each for the page's purpose, with no upstream repair or stated reason; they carry no binding semantics (what must hold is in the binding fields above), and a `(binding)` field is followed literally. Executor owns final carrier choice, page-scale composition, information-preserving visualization, geometry, spacing, coordinates, native construction, and effects.
| Binds (plan-selected) | Realization (Executor-owned) |
|---|---|
| Content and `Relationships`; roster and `page_rhythm`; resource paths; structured-template routing keys; core fonts; palette and spacing anchors; icon-library/stroke anchors; crop boundaries; any field labeled `(binding)` | The carrier mix, geometry, composition, and which prepared icon serves a page, plus the sparse local garnish allowed below |
**Hard rule — content vs expression**: §IX owns each page's semantic content — complete preferred wording and block texture at `complete` depth, a short block list at `brief` — and its wording is not verbatim unless marked literal. Executor may paraphrase, condense repetition, regroup or reorder within the page, and switch among prose, bullets, keywords, labels, or visual annotation when fit or readability benefits, provided the result stays information-equivalent: the `Core message`, `Audience move`, and every claim, fact, value, proper name, qualifier, relationship, evidence, and literal requirement survive. Never add a claim, move content across pages, or drop information to fit a layout; quotation marks and first person only for wording the source itself gives as a quote — reported speech stays reported; return an unfit or underspecified block for Design Spec repair. Use named lock roles literally where they apply, apply an optional `Template Application`, and choose page-local values from the Design Spec, style, content, and composition rather than forcing every object into a lock row. Read sources only to resolve listed `Fact IDs` or verify required claims, quotes, names, or data; never to add content.
Missing or unresolved material stops execution and returns upstream. Never search, generate, download, sync, invent, or substitute it.
**Per-page communication trace**: read `communication.objective`, `communication.core_message`, and the page's §IX `Core message` + `Audience move` before composing. The page must advance the objective and make that move; a page that cannot state its move is an outline defect — surface `warning: P<NN> has no communication move` rather than decorating around it, and never invent a purpose at execution time. Structural pages advance the contract by establishing relevance, tension, or the decision frame, or by completing the final commitment.
**Reference — planning sketches are adjusted freely**: §V and the §IX `Composition` line, cover/closing composition, capability recommendations, §III motif direction, Chart/Table `family/key` references, §VIII image-layout patterns, and Motion suggestions are starting sketches. Adjust or replace each for the page's purpose, with no upstream repair or stated reason; they carry no binding semantics. A `(binding)` field is followed literally. Executor owns final carrier choice, page-scale composition, information-preserving visualization, geometry, spacing, coordinates, native construction, and effects.
**Mandatory — per-page Structure decision**: before drawing, read the page's §IX `Relationships` (Quick: the transient relationship statement), then `Visualization` and `Content`, and decide whether geometry must carry that qualitative `order`, `link`, `parent`, `membership`, `contrast`, or `overlap` relationship — from the semantic relationship alone; a missing line is a Design Spec defect: repair that §IX block first (continuous run) or return upstream, never infer the relationship at execution — loading [`executor-structure.md`](./executor-structure.md) and [`topology-assembly.md`](./topology-assembly.md) at the first `yes`; a suggested carrier, topology, or composition does not decide it. `no` stays on this base path; `yes` applies that grammar and keeps the relationship statement in active page context with no catalog reference, lock row, or artifact. A Chart/Table reference never substitutes.
**Hard rule — content vs expression**: §IX owns each page's semantic content — complete preferred wording and block texture at `complete` depth, a short block list at `brief`. Its wording is not verbatim unless marked literal.
**Per-page reading-mode check**: apply `communication.consumption_mode` with the §IX block texture and `page_rhythm``text`: the visible page stands alone (complete prose, explicit labels / captions / sources, tables, necessary detail); `balanced`: the primary claim and its evidence on the page, enabled notes adding interpretation and transitions; `presentation`: one claim and one dominant visual legible at projection distance, concise copy, enabled notes carrying explanation — and with notes disabled never omit required content on the assumption that notes carry it. Never drop or invent facts to force a mode; when the authored texture materially conflicts with the lock, render the least-destructive faithful composition and surface `warning: P<NN> content texture conflicts with consumption_mode <value>` (a judgment, not a checker rule).
| Executor may | Executor never |
|---|---|
| Paraphrase, condense repetition, regroup or reorder within the page, and switch among prose, bullets, keywords, labels, or visual annotation when fit or readability benefits | Add a claim, move content across pages, or drop information to fit a layout |
| Use named lock roles literally where they apply, apply an optional `Template Application`, and choose page-local values from the Design Spec, style, content, and composition | Force every object into a lock row |
| Read sources to resolve listed `Fact IDs` or verify required claims, quotes, names, or data | Read sources to add content |
**Default — authored texture (may override when information-equivalent)**: start from each §IX block's written texture (`complete`) or expand its block phrasing (`brief`) under the reading mode. Keep prose where continuity carries cause, argument, narrative, qualification, or emphasis; use bullets or keywords only for genuinely parallel or ordered material or a clearer information-equivalent structure — never because a list is easier to lay out or a template exposes a list slot. An inherited slot never overrides the content relationship — widen, reflow, or drop the card before converting prose to fill a list slot; the locked mode shapes voice and register, not §IX's authored titles or page order (a user-authored topic label stays a label even when the mode favors assertions). Block-level phrasing applies *within* the page's `page_rhythm` density, not against it.
The result stays information-equivalent: the `Core message`, `Audience move`, and every claim, fact, value, proper name, qualifier, relationship, evidence, and literal requirement survive. Quotation marks and first person only for wording the source itself gives as a quote; reported speech stays reported. Return an unfit or underspecified block for Design Spec repair.
**Hard rule — one paragraph, one text frame**: one `<text>` per prose paragraph with positioned `<tspan>` line breaks, never sibling `<text>` elements ([`shared-standards-core.md`](./shared-standards-core.md) §4.2); start from its leading ranges, then adjust for typeface, reading distance, explicit requirements, and locked style.
**Hard rule — one paragraph, one text frame**: one `<text>` per prose paragraph with positioned `<tspan>` line breaks, never sibling `<text>` elements ([`shared-standards-core.md`](./shared-standards-core.md) §4.2). Start from its leading ranges, then adjust for typeface, reading distance, explicit requirements, and locked style.
**Execution anchors and contextual values**:
- Icons: any SVG prepared under `<project_path>/icons/` is usable; `icons.library` records the primary bundled style and `icons.inventory` indexes the synced pool without assigning icons to pages or limiting other project-local assets; `simple-icons` entries are real brand marks, not a library. Illustrated icons are transparent slices under `images/` and follow [`executor-image.md`](./executor-image.md) — never moved into `icons/`, added to the inventory, or rendered through `<use data-icon>`.
- Colors: core roles keep their meaning; derive tints, shades, alpha, gradients, and effects, preserve natural asset colors, and use sparse page-local accents that never become a competing or recurring palette.
- Spacing: §V anchors (page margin, block gap, column gutter, corner radius, body leading) are deck-wide identity; depart only for a page job, never to make content fit.
- Families: resolve by role — exact `<role>_family`, then `title_family` / `body_family`, then legacy `font_family`; never flatten a declared override. A sparse export-safe accent family may style short non-structural display or ornament only; recurrence needs upstream selection.
- Sizes: map every structural text item to a declared `typography` role and write its anchor or a value within `±2` px, as unitless px with at most two decimals; peers on one page stay consistent, and bounded adjustment creates no new role. Never inherit a template placeholder size. `lead` / `subtitle` carry the page's primary claim; `footnote` / `annotation` carry footnotes, page numbers, and credits.
- **Sparse display-size exception**: a short non-structural Hero/Display element may use one undeclared size at most twice across the deck without a lock row. The third occurrence makes it recurring stop, return to Strategist to name the role in the Design Spec and lock, then read back and validate before reuse. Never for titles, body, subtitles, annotations, footnotes, captions, data labels, or card copy, and never imitated with nearby sizes.
- **Outside-band recovery**: structural text reflows geometry and uses the declared band; a sparse display occurrence keeps its value while its deck-wide count stays ≤2. Never flatten a justified distinction or add a role to silence the checker; mirror pages keep exact source typography.
- **Prepared decorative lettering**: place the approved AI/slice file as an image and keep the editable title/subtitle in separate native frames; never rebuild it from glyph copies or WordArt, and never invent a missing asset when the plan kept the wording native.
- Images reference only files listed under `images`; math loads [`native-formula.md`](./native-formula.md) simple notation stays text, one-line structural prose goes inline only when its native height fits the reserved row, matrices and multiline or vertically expanding math go block; exact LaTeX plus preview, never an image.
- **Icons**: any SVG prepared under `<project_path>/icons/` is usable. `icons.library` records the primary bundled style; `icons.inventory` indexes the synced pool without assigning icons to pages or limiting other project-local assets; `simple-icons` entries are real brand marks, not a library. Illustrated icons are transparent slices under `images/` and follow [`executor-image.md`](./executor-image.md) — never moved into `icons/`, added to the inventory, or rendered through `<use data-icon>`.
- **Colors**: core roles keep their meaning. Derive tints, shades, alpha, gradients, and effects; preserve natural asset colors; use sparse page-local accents that never become a competing or recurring palette.
- **Spacing**: §V anchors (page margin, block gap, column gutter, corner radius, body leading) are deck-wide identity. Depart only for a page job, never to make content fit.
- **Families**: resolve by role — exact `<role>_family`, then `title_family` / `body_family`, then legacy `font_family`; never flatten a declared override. A role with no `<role>_family` of its own uses `body_family`; `title`, `subtitle`, and chapter-numeral roles use `title_family`. A sparse export-safe accent family may style short non-structural display or ornament only; recurrence needs upstream selection.
- **Sizes**: map every structural text item to a declared `typography` role and write its anchor or a value within `±2` px, as unitless px with at most two decimals. Peers on one page stay consistent, and bounded adjustment creates no new role. Never inherit a template placeholder size. `lead` / `subtitle` carry the page's primary claim; `footnote` / `annotation` carry footnotes, page numbers, and credits.
- **Sparse display-size exception**: a short non-structural Hero/Display element may use one undeclared size at most twice across the deck without a lock row. The third occurrence makes it recurring: stop, return to Strategist to name the role in the Design Spec and lock, then read back and validate before reuse. Never for titles, body, subtitles, annotations, footnotes, captions, data labels, or card copy, and never imitated with nearby sizes.
- **Outside-band recovery**: structural text reflows geometry and uses the declared band; a sparse display occurrence keeps its value while its deck-wide count stays ≤2. Never flatten a justified distinction or add a role to silence the checker. Mirror pages keep exact source typography.
- **Prepared decorative lettering**: place the approved AI/slice file as an image and keep the editable title/subtitle in separate native frames. Never rebuild it from glyph copies or WordArt, and never invent a missing asset when the plan kept the wording native.
- **Images and math**: images reference only files listed under `images`. Math loads [`native-formula.md`](./native-formula.md): simple notation stays text, one-line structural prose goes inline only when its native height fits the reserved row, matrices and multiline or vertically expanding math go block; exact LaTeX plus preview, never an image.
Return upstream before a derived or accent identity becomes recurring or structural; garnish, `±2` px adjustments, and two sparse display occurrences need no lock row, and the lock is never expanded to silence a comparison.
Return upstream before a derived or accent identity becomes recurring or structural. Garnish, `±2` px adjustments, and two sparse display occurrences need no lock row, and the lock is never expanded to silence a comparison.
**Per-page layout rhythm — `page_rhythm`**: before drawing, apply the page's tag (key `P<NN>` matching §IX):
### 2.2 Per-page decision chain
Run these steps in order for every page, in active context, before the page's first coordinate. Each step is decided once; no artifact, no extra pass, no rereading a module while the context is valid. Composition (Step 7) is one decision: the style's geometry, the motif, and — on an image page — the image composition are resolved together, before any geometry is drawn.
**Step 1 — communication trace**: read `communication.objective`, `communication.core_message`, and the page's §IX `Core message` + `Audience move` before composing. The page must advance the objective and make that move. A page that cannot state its move is an outline defect: surface `warning: P<NN> has no communication move` rather than decorating around it, and never invent a purpose at execution time. Structural pages advance the contract by establishing relevance, tension, or the decision frame, or by completing the final commitment.
**Step 2 — reading-mode check**: apply `communication.consumption_mode` with the §IX block texture and `page_rhythm`:
| Mode | The page carries |
|---|---|
| `text` | The visible page stands alone: complete prose, explicit labels / captions / sources, tables, necessary detail |
| `balanced` | The primary claim and its evidence; enabled notes add interpretation and transitions |
| `presentation` | One claim and one dominant visual legible at projection distance, concise copy; enabled notes carry the explanation |
With notes disabled, never omit required content on the assumption that notes carry it. Never drop or invent facts to force a mode. When the authored texture materially conflicts with the lock, render the least-destructive faithful composition and surface `warning: P<NN> content texture conflicts with consumption_mode <value>` (a judgment, not a checker rule).
**Default — authored texture (may override when information-equivalent)**: start from each §IX block's written texture (`complete`) or expand its block phrasing (`brief`) under the reading mode. Keep prose where continuity carries cause, argument, narrative, qualification, or emphasis. Use bullets or keywords only for genuinely parallel or ordered material or a clearer information-equivalent structure. A list that is merely easier to lay out, or a template slot that expects a list, is not a reason: widen, reflow, or drop the card before converting prose to fill it. The locked mode shapes voice and register, not §IX's authored titles or page order; a user-authored topic label stays a label even when the mode favors assertions. Block-level phrasing applies *within* the page's `page_rhythm` density, not against it.
**Step 3 — topology decision (Mandatory)**: before drawing, read the page's §IX `Relationships` (Quick: the transient relationship statement), then `Visualization` and `Content`, and decide whether geometry must carry that qualitative `order`, `link`, `parent`, `membership`, `contrast`, or `overlap` relationship. Decide from the semantic relationship alone; a suggested carrier, topology, or composition does not decide it, and a Chart/Table reference never substitutes. `no` stays on this base path. `yes` applies the grammar of [`executor-structure.md`](./executor-structure.md) and [`topology-assembly.md`](./topology-assembly.md) (routing table) and keeps the relationship statement in active page context with no catalog reference, lock row, or artifact. A missing line is a Design Spec defect: repair that §IX block first (continuous run) or return upstream; never infer the relationship at execution.
**Step 4 — layout rhythm (`page_rhythm`)**: before drawing, apply the page's tag (key `P<NN>` matching §IX):
| Tag | Layout discipline |
|-----|-------------------|
@@ -181,48 +241,89 @@ Return upstream before a derived or accent identity becomes recurring or structu
Mechanical repetition comes from reusing one carrier and topology without a page job, not from cards themselves; vary rhythm when the content relationship changes. Missing or empty `page_rhythm``warning: spec_lock.md missing/empty page_rhythm — defaulting all pages to dense` once, all pages `dense`. Tag missing for a page → `warning: spec_lock.md page_rhythm tag not found for P<NN> — falling back to dense` once per deck, `dense`; never invent a tag.
**Step 5 — carrier mix (Mandatory, before coordinates)**: in one page-level decision, choose the background field, editable text and optional lettering, native geometry/lines, prepared photos/scenes/illustration/icon assets, and applicable visualizations — their combination, visual weight, z-order, and local construction from the page message and hierarchy. Use only prepared resources and preserve every binding resource job. The resolved style controls treatment and emphasis, never carrier eligibility, image source, or the native vocabulary. Recall the vocabulary here: the style's §1 `Composition geometry`, the Page Expression Core above, and — once triggered — [`svg-effects.md`](./svg-effects.md) §6.1 and [`native-shape-authoring.md`](./native-shape-authoring.md) §2.1.
**Step 6 — module line (Mandatory)**: with the carrier mix resolved and before drawing, write one line `P<NN> modules: core[, structure][, native-shape][, effects][, image][, native-data][, chart | table | formula | link | web-image]` naming the triggered modules the page uses. A module the pre-P01 sweep did not read is read completely before that page's first SVG line. A page whose carrier mix uses a module's capability without naming it is a defect the carrier receipt exposes.
**Step 7 — composition (Default; may override when another page-fit move is stronger)**: an SVG page is a canvas, not a DOM. A preset uses its style's §1 `Composition geometry`. A `custom` executes `visual_style_behavior` first and takes §1 geometry only from the exact `visual_style_references` the behavior assigns a shape or composition job; an unreferenced custom follows its behavior alone. Every listed move is generative vocabulary; a move beyond basic primitives passes [`native-shape-authoring.md`](./native-shape-authoring.md) §2.1's exact-fit gate.
**Default — consider the planned motif (may override when another coherent expression serves the deck better)**: when §III `Theme` recommends a cross-page motif, decide whether it earns a continuity job; if adopted, vary scale, crop, density, position, and content interaction by page role. An explicit user/template motif binds.
**Image composition (image pages)**: within the same composition decision and before any geometry, apply the per-page image composition decision of [`executor-image.md`](./executor-image.md) §1 once; a deliberate plain placement is valid when it communicates better.
**Step 8 — geometry move (Mandatory)**: after the topology decision and any assembled topology, decide the page's geometry before writing coordinates. A move beyond basic primitives follows [`native-shape-authoring.md`](./native-shape-authoring.md) §2.1 — exact-fit comparison, composition lenses, relationship and carrier fit, contour-family choice, the reader effect of a generic or undrawn result, the running geometry signature, and the materialization boundary for both topology results. Keep the decision in active context; never change the topology decision. Materialize under §3.0.
**Step 9 — coordinates and bounds**: Write the sentence first, then the zone; the grouping, bounds, and width-estimation contract is §3 Technical contract.
---
## 3. Execution Guidelines
**Per-page composition (craft; the vocabulary is the Page Expression Core)**:
**Per-page composition craft** (the decision order is §2.2; the vocabulary is the Page Expression Core):
- **Mandatory — resolve the page carrier mix before coordinates**: in one page-level decision, choose the background field, editable text and optional lettering, native geometry/lines, prepared photos/scenes/illustration/icon assets, and applicable visualizations — their combination, visual weight, z-order, and local construction from the page message and hierarchy, using only prepared resources and preserving every binding resource job. The resolved style controls treatment and emphasis, never carrier eligibility, image source, or the native vocabulary. Recall the vocabulary here: the style's §1 `Composition geometry`, the Page Expression Core above, and — once triggered — [`svg-effects.md`](./svg-effects.md) §6.1 and [`native-shape-authoring.md`](./native-shape-authoring.md) §2.1.
- **Default — stage each page with the style's composition geometry (may override when another page-fit move is stronger)**: an SVG page is a canvas, not a DOM. A preset uses its style's §1 `Composition geometry`; a `custom` executes `visual_style_behavior` first and takes §1 geometry only from the exact `visual_style_references` the behavior assigns a shape or composition job; an unreferenced custom follows its behavior alone. Every listed move is generative vocabulary; when the move reaches beyond basic primitives, [`native-shape-authoring.md`](./native-shape-authoring.md) §2.1's exact-fit gate applies (loading it then).
- **Default — consider the planned motif (may override when another coherent expression serves the deck better)**: when §III `Theme` recommends a cross-page motif, decide whether it earns a continuity job; if adopted, vary scale, crop, density, position, and content interaction by page role. An explicit user/template motif binds.
- **Ordinary carriers stay ordinary**: cards, icon-and-label rows, color swatches, soft shadows, and gradient fields are everyday carriers — use them whenever content groups, compares, enumerates, or names a color, material, or sample, with one shared treatment for peers; reach for a device by page job and let the locked style set its treatment. When the subject is a color or material, draw it: a swatch is content, its value comes from the source, and it needs no lock row.
- **Ordinary carriers stay ordinary**: cards, icon-and-label rows, color swatches, soft shadows, and gradient fields are everyday carriers. Use them whenever content groups, compares, enumerates, or names a color, material, or sample, with one shared treatment for peers; reach for a device by page job and let the locked style set its treatment. When the subject is a color or material, draw it: a swatch is content, its value comes from the source, and it needs no lock row.
- **Reference — semantic geometry over preset stacks**: for ascending, converging, breaking-through, or stacking relationships, compose faithful primitives and exact presets as one geometry system; a Boolean only when the contour must merge, open, or fragment; one page-specific path only when neither works.
- **Inherited containers**: keep meaningful template frames and restyle radius, fill, stroke, and depth from the Design Spec and lock; Chart/Table reference adaptation belongs to [`executor-visualization.md`](./executor-visualization.md), and preview effects never override project styling.
- **Fact provenance**: resolve each §IX `Fact ID` from `sources/*.facts.json` and keep the value unchanged; render a compact source footnote (name + short URL/domain) when space permits and state attribution naturally in enabled notes. For `Data class: scenario`, place a visible localized `Scenario data` / `情景数据` label beside the KPI/chart and say in notes that it is illustrative. Never attach a fact ID to scenario data or let an unlabeled invented KPI look factual. An organizing framework, grouping, or label the source does not state is the deck's reading say so on the page (e.g. `整理` / `our reading`) or in enabled notes, never presented as the source's structure.
- **Inherited containers**: keep meaningful template frames and restyle radius, fill, stroke, and depth from the Design Spec and lock. Chart/Table reference adaptation belongs to [`executor-visualization.md`](./executor-visualization.md); preview effects never override project styling.
- **Fact provenance**: resolve each §IX `Fact ID` from `sources/*.facts.json` and keep the value unchanged. Render a compact source footnote (name + short URL/domain) when space permits and state attribution naturally in enabled notes. For `Data class: scenario`, place a visible localized `Scenario data` / `情景数据` label beside the KPI/chart and say in notes that it is illustrative. Never attach a fact ID to scenario data or let an unlabeled invented KPI look factual. An organizing framework, grouping, or label the source does not state is the deck's reading: say so on the page (e.g. `整理` / `our reading`) or in enabled notes, never presented as the source's structure.
**Technical contract (the exporter's needs; the complete SVG boundary is [`shared-standards-core.md`](./shared-standards-core.md))**:
- **Element grouping (Mandatory)**: wrap each logical Slide-local body unit in a descriptive, page-unique top-level `<g id>` with root-coordinate `data-pptx-bounds="x y width height"`; a helper-authored preset atom stays top-level with `data-pptx-frame` and no bounds; nested groups need none. Give a root background image or full-canvas scrim/decoration rectangle a stable `id` plus `data-pptx-role="background"` / `"decoration"` instead of a wrapper. Thresholds, exemptions, and the Morph staging marker: [`shared-standards-core.md`](./shared-standards-core.md) §4.3.
- **Element grouping (Mandatory)**: wrap each logical Slide-local body unit in a descriptive, page-unique top-level `<g id>` with root-coordinate `data-pptx-bounds="x y width height"`. A helper-authored preset atom stays top-level with `data-pptx-frame` and no bounds; nested groups need none. Give a root background image or full-canvas scrim/decoration rectangle a stable `id` plus `data-pptx-role="background"` / `"decoration"` instead of a wrapper. Thresholds, exemptions, and the Morph staging marker: [`shared-standards-core.md`](./shared-standards-core.md) §4.3.
- **Reference — nested edit groups**: a top-level group may contain descriptive nested `<g>` groups for meaningful subunits; they need no bounds and create no animation step, with no default depth or quota.
- **Default — bounds are the module zone, not a glyph box (may skip when no text is estimable)**: make each zone as generous as the canvas and siblings allow without overlap. An untransformed line spans `y 0.85 × font_size` to `y + 0.35 × font_size`. **Width is calibrated once, then estimated**: before P01 the route runs `python3 ${SKILL_DIR}/scripts/text_measure.py calibrate` (Default from the lock with `--outline`, Quick with `--role` arguments) and keeps its per-role table — CJK and Latin ≈ chars per 100 px, plus each role's longest planned line — in context; every later page sizes its zones from that arithmetic (characters ÷ the role's chars-per-100-px × 100; the estimator already carries the wrapping headroom) — write the sentence first, then fit the zone to it; no per-page measurement, no line-by-line tool calls, and never trim wording to satisfy an estimate. Reach for `calibrate --role` or `measure|wrap|box` again only for a role or size that was never calibrated. When text does not fit, first expand a zone with unused space, then reflow or switch texture (prose → points) before dropping a qualifier; larger bounds never repair off-canvas text.
- **Default — bounds are the module zone, not a glyph box (may skip when no text is estimable)**: make each zone as generous as the canvas and siblings allow without overlap. A group's bounds are the union of every child's geometry — text lines, preset frames, image frames, line stroke half-width — plus margin, never the title text alone. An untransformed line spans `y 0.85 × font_size` to `y + 0.35 × font_size`. Write the sentence first, then fit the zone to it; recompute the bounds after any font-size, line-count, or child-geometry change.
- **Width estimation**: width is estimated, never measured per page. The route calibrates every role once before P01 (Default Step 6, Quick §3) and keeps a per-role chars-per-100-px table in context; size each zone as characters ÷ that rate × 100; a line mixing CJK with Latin words or digits adds the two parts, CJK chars ÷ CJK rate + other chars ÷ Latin rate (the estimator already carries the wrapping headroom). Never trim wording to satisfy an estimate. When text does not fit, expand a zone with unused space first, then reflow or switch texture (prose → points) before dropping a qualifier; larger bounds never repair off-canvas text.
- **Spec adherence**: binding color, canvas, typography, identity, resource, and template anchors hold; layout and other References apply under §2.1 without becoming locks.
- **Template structure**: inherit the native framework only for `template_reuse_scope: mirror|layout`; `style` uses the flat route.
- **Main-agent ownership**: SVG generation runs in the main agent, never a sub-agent — pages share upstream context for cross-page continuity.
- **Main-agent ownership**: the current main agent hand-writes every page SVG — never a sub-agent, and never a generator that writes slide files — because pages share upstream context for cross-page continuity. `preset_shape_svg.py` and `shape_boolean_svg.py` print fragments only after the agent has chosen role, operands, paint, and z-order. Resource, inspection, checker, verification, and export tools are unrestricted.
**Checkpoints**:
- **Mandatory — per-page module line**: before drawing each page, write one line `P<NN> modules: core[, structure][, native-shape][, effects][, image][, native-data][, chart | table | formula | link | web-image]` naming the triggered modules the page uses; a module the pre-P01 sweep did not read is read completely before that page's first SVG line, and a page whose carrier mix uses a module's capability without naming it is a defect the carrier receipt exposes.
- **Phased generation** (recommended):
1. **Visual Construction Phase**: generate all pages sequentially, applying every triggered branch while drawing. **MUST embed one object-scoped plot-area marker** per §IX-named or Quick-promoted value-driven chart object ([`executor-chart.md`](./executor-chart.md) §2); calibration follows in [`verify-charts`](../workflows/stages/verify-charts.md). Write every `<object-key>=yes` native marker plus JSON metadata atomically ([`native-data-interface.md`](./native-data-interface.md) §2) and stamp its baseline before the page's gate — `python3 ${SKILL_DIR}/scripts/stamp_native_fallbacks.py <project_path>/svg_output/<page>.svg --write`, rerun after any visible edit inside the marker group. **Reach for native presets** per §3.0 as you draw, decided by the object's intent, never by scanning finished paths; several presets for one page go through one `preset_shape_svg.py render-batch --input -` round (gradient/pattern paint stays ordinary SVG; a justified §6.4 shadow/glow stays on the helper-authored shape).
2. **Quality gates**: owned by the route — [`generate-pptx.md`](../workflows/generate-pptx.md) Step 6 (early, final, carrier receipt) or [`quick-generate.md`](../workflows/profiles/quick-generate.md) §34 (the same early gate on rosters of seven or more pages, one lockless final check). Run each checker unfiltered, review the complete issue set, fix every error plus selected warnings in one consolidated pass, verify once; never check between individual fixes, never `cat` a passing report, never defer errors past `finalize_svg.py` (it rewrites SVG and masks violations). Every checker invocation follows one of two events — a gate point whose covered pages all exist, or the end of one consolidated repair pass; a run with neither predecessor is a pacing violation, and validating an authoring pattern early is not a reason (the same issues surface identically at the gate and are fixed in the same consolidated pass). Every `warning` is advisory.
2. **Quality gates**: the gate points and their commands are the route's — [`generate-pptx.md`](../workflows/generate-pptx.md) Step 6 or [`quick-generate.md`](../workflows/profiles/quick-generate.md) §34. The repair discipline at every gate is the same: run the checker unfiltered, review the complete issue set, fix every error plus the selected warnings in one consolidated pass, verify once. Never check between individual fixes, never `cat` a passing report, never defer errors past `finalize_svg.py` (it rewrites SVG and masks violations). Every `warning` is advisory.
3. **Logic Construction Phase (conditional)**: after the gates pass, generate speaker notes for narrative continuity only when the effective Speaker Notes outcome is enabled.
- **Mandatory — final carrier-receipt review**: after the final checker passes, compare its `[CARRIERS]` summary (per-page detail under `files[].info.carrier_receipt`) with the retained page jobs, resource roles, and geometry signatures. Counts are not quotas. Repair only where a fact contradicts an active decision, then rerun the final checker once:
| Contradiction | Repair |
|---|---|
| An adopted preset absent from its page | Draw it |
| A directional / step / flowchart relationship drawn as a hand path or polygon where §3.0 names a preset | Replace it with the preset |
| A primary image reduced to a minor frame | Restore its planned share |
| Unrelated page jobs collapsing into one neutral construction | Vary the construction by job |
**Absence needs a reason.** Each of these receipt facts needs one written line — what carries that job instead, and why that serves the reader better: a deck-wide `Presets: (none)`; `inline emphasis 0`, `gradients 0`, or `filters 0` on the `Effects:` line; fewer pages carrying a preset or connector than pages whose relationship line (Default: §IX `Relationships`; Quick: the transient relationship statement) names `order` / `link` / `parent` / `membership`; a `Presets:` line naming no carrier-and-field contour. Answer per family the presets serve, not for arrows alone:
| Family | Members |
|---|---|
| Carrier and field | snipped or one-sided rounded rectangles, plaque, bevel, polygons, pie / arc / donut, frames, corners, folded corner, trapezoid, parallelogram, and the [`native-shape-authoring.md`](./native-shape-authoring.md) §7 modelled forms |
| Direction and sequence | arrows, chevrons, flow nodes |
| Grouping and ownership | brackets, braces, frames, plaques |
| Emphasis and annotation | callouts, badges, banners, stars |
The style, speed, restraint, "text was enough", or "it is editable anyway" are not reasons. Choosing not to use a device is valid; only an unstated reason is not. A family or page without a reason is repaired where the page job calls for it, and the checker reruns.
### 3.0 Native Shape Selection
**Hard rule — contour before encoding**: choose the page-fit contour from the full native vocabulary [`preset-shape-vocabulary.md`](./preset-shape-vocabulary.md), read completely before the first page — before its authoring form; when the roster sweep or a page reaches beyond rectangle, rounded rectangle, circle, ellipse, and line, read [`native-shape-authoring.md`](./native-shape-authoring.md) completely before choosing. Rectangle, rounded rectangle, circle, and ellipse are preset contours even in short SVG syntax; easier syntax never selects a contour. Every other vocabulary contour — an inflected carrier (snipped, one-sided rounded, plaque, bevel, polygon, pie, frame, folded corner) as much as a block arrow, chevron, banner, callout, flowchart node, or star — comes from `preset_shape_svg.py`, never plain paths or fake rectangles. No Design Spec selection, scorer, or inventory gates this choice.
**Hard rule — contour before encoding**: choose the page-fit contour from the full native vocabulary ([`preset-shape-vocabulary.md`](./preset-shape-vocabulary.md), resident with this core) before its authoring form. A contour beyond rectangle, rounded rectangle, circle, ellipse, and line is chosen with [`native-shape-authoring.md`](./native-shape-authoring.md) in context (routing table). Rectangle, rounded rectangle, circle, and ellipse are preset contours even in short SVG syntax; easier syntax never selects a contour. Every other vocabulary contour — an inflected carrier (snipped, one-sided rounded, plaque, bevel, polygon, pie, frame, folded corner) as much as a block arrow, chevron, banner, callout, flowchart node, or star — comes from `preset_shape_svg.py`, never plain paths or fake rectangles. No Design Spec selection, scorer, or inventory gates this choice.
**Mandatory — independent per-page geometry move**: after the Structure result and any topology, decide the page's geometry before writing coordinates; when it reaches beyond basic primitives, apply [`native-shape-authoring.md`](./native-shape-authoring.md) §2.1 (loading it then); it owns exact-fit comparison, composition lenses, relationship and carrier fit, contour-family choice, the reader effect of a generic or undrawn result, the running geometry signature, and the materialization boundary for both Structure results. Keep the decision in active context; never change the Structure result.
**Materialization tiers** ([`native-shape-authoring.md`](./native-shape-authoring.md) §1 table):
Materialize through [`native-shape-authoring.md`](./native-shape-authoring.md) §1's table: an ordinary primitive when the exporter maps it to the same contour, otherwise the helper fragment; `<line>` for a straight relationship and a `bentConnector*` / `curvedConnector*` preset for a stock bend or curve (both export unconnected); independent siblings for a page-level system; `shape_boolean_svg.py` only when one contour must merge, cut, or fragment; ordinary path/polygon only for geometry none of those express. A directional solid object is a `shape` preset such as `rightArrow` or `chevron`; `actionButton*` presets are geometry only.
| Geometry | Materialize as |
|---|---|
| A contour the exporter maps from an ordinary primitive | The ordinary primitive |
| Any other preset contour | The helper fragment |
| A straight relationship | `<line>` |
| A stock bend or curve | A `bentConnector*` / `curvedConnector*` preset (both export unconnected) |
| A page-level system | Independent siblings |
| A contour that must merge, cut, or fragment | `shape_boolean_svg.py` |
| Geometry none of those express | Ordinary path/polygon |
**Hard rule — freeform is the last tier**: before hand-authoring a stock-looking `<path>` / `<polygon>`, complete contour selection, simplest exact materialization, independent composition, and the Boolean gate; avoiding a helper or drawing faster is not an exception, while data-defined geometry and a genuinely locked organic/hand-drawn contour qualify by semantics. This applies only while drawing a new object; export never scans or upgrades ordinary SVG.
A directional solid object is a `shape` preset such as `rightArrow` or `chevron`; `actionButton*` presets are geometry only.
**Hard rule — helper-written metadata and scope**: `data-pptx-authoring`, `data-pptx-prst`, `data-pptx-frame`, adjustment metadata, and registry paths are written only by the preset helper (hand-written values fail the checker); rerun it when geometry or paint changes and never edit a direct path. Both helpers print only their stdout fragment(s): read and insert each through the normal page edit, never redirect, loop, or batch output into `svg_output/`.
**Hard rule — freeform is the last tier**: before hand-authoring a stock-looking `<path>` / `<polygon>`, complete contour selection, simplest exact materialization, independent composition, and the Boolean gate. Avoiding a helper or drawing faster is not an exception. Data-defined geometry and a genuinely locked organic/hand-drawn contour qualify by semantics. This applies only while drawing a new object; export never scans or upgrades ordinary SVG.
**Hard rule — helper-written metadata and scope**: `data-pptx-authoring`, `data-pptx-prst`, `data-pptx-frame`, adjustment metadata, and registry paths are written only by the preset helper (hand-written values fail the checker). Rerun it when geometry or paint changes and never edit a direct path. Both helpers print only their stdout fragment(s): read and insert each through the normal page edit, never redirect, loop, or batch output into `svg_output/`.
### SVG File Naming Convention
@@ -232,7 +333,7 @@ Materialize through [`native-shape-authoring.md`](./native-shape-authoring.md)
## 4. Icon Usage
Strategist chooses at most one primary bundled stylistic library and may select `simple-icons` alone or alongside it for real brand marks; Executor draws from the complete prepared project-local pool ([`../templates/icons/README.md`](../templates/icons/README.md)). Any SVG under `<project_path>/icons/<lib>/` is prepared material; authoring, preview, finalization, and export resolve only complete case-sensitive `library/name` references there (`tabler-outline/award`, never `Award`; custom files keep their exact case), with no global or template-source fallback.
Executor draws from the complete prepared project-local pool; library rules are the [icon README](../templates/icons/README.md). Any SVG under `<project_path>/icons/<lib>/` is prepared material. Authoring, preview, finalization, and export resolve only complete case-sensitive `library/name` references there (`tabler-outline/award`, never `Award`; custom files keep their exact case), with no global or template-source fallback.
```xml
<use data-icon="chunk-filled/home" x="100" y="200" width="48" height="48" fill="#005587"/>
@@ -241,9 +342,9 @@ Strategist chooses at most one primary bundled stylistic library and may select
<use data-icon="tabler-outline/home" x="100" y="200" width="48" height="48" fill="#005587" stroke-width="2"/>
```
**Hard rule — color and stroke**: always `fill="#HEX"` on `<use data-icon>`, never `stroke` or `fill="none"`, even for stroke libraries. `stroke-width` (`tabler-outline` only) is `1.5`, `2`, or `3`; a declared `spec_lock.md icons.stroke_width` applies deck-wide, and new authoring declares it, and a legacy stroke-library lock without it uses `2` with one warning. `finalize_svg.py` embeds placeholders automatically.
**Hard rule — color and stroke**: always `fill="#HEX"` on `<use data-icon>`, never `stroke` or `fill="none"`, even for stroke libraries. `stroke-width` (`tabler-outline` only) is `1.5`, `2`, or `3`. A declared `spec_lock.md icons.stroke_width` applies deck-wide, and new authoring declares it. A legacy stroke-library lock without it uses `2` with one warning.
**Missing project-local icon** (`test -f "<project_path>/icons/<lib>/<name>.svg"`) → return to Strategist's preparation / `icon_sync.py` gate; Executor never searches the global library, picks an alternative, or copies a candidate. Executor may combine project-local icons freely across namespaces and styles but may not acquire a new one or treat a globally resolvable file as prepared.
**Missing project-local icon** (`test -f "<project_path>/icons/<lib>/<name>.svg"`) → return to Strategist's preparation / `icon_sync.py` gate. Executor never searches the global library, picks an alternative, or copies a candidate. Executor may combine project-local icons freely across namespaces and styles but may not acquire a new one or treat a globally resolvable file as prepared.
---
@@ -251,9 +352,9 @@ Strategist chooses at most one primary bundled stylistic library and may select
Default reads typography from `spec_lock.md` (Quick: its transient §2 anchor): `<role>_family``title_family` / `body_family` → legacy `font_family`; sparse accents follow §2.1. Under [`native-formula.md`](./native-formula.md), blocks use marker style and inline math inherits size and solid fill, exporting in Cambria Math with the project text language.
**Default — locked-stack realization (may vary treatment)**: express the Design Spec Character Reference through scale, weight, spacing, color, and composition while keeping the locked family; put the common stack on root `<svg>`, omit matching descendants, and override at the nearest clear `<g>`, `<text>`, or `<tspan>`.
**Default — locked-stack realization (may vary treatment)**: express the Design Spec Character Reference through scale, weight, spacing, color, and composition while keeping the locked family. Put the common stack on root `<svg>`, omit matching descendants, and override at the nearest clear `<g>`, `<text>`, or `<tspan>`.
**Hard rule — target faces**: every `font-family` stack resolves to target-installed/approved Latin and EA faces. PPTX writes one face per script: the first named Latin face fills `latin`, the first named CJK face fills `ea` (and `latin` when no Latin face is named), and a generic family fills `latin` only when it precedes every named face. Fonts are not embedded; missing-face substitution is viewer-selected. **Missing `typography.font_family`** → stop and return to Generate Step 4 / [`strategist.md`](strategist.md) §6.2; never infer a stack from `design_spec.md`.
**Hard rule — target faces**: every `font-family` stack names faces installed or approved on the delivery target ([`shared-standards-core.md`](./shared-standards-core.md) §4.1); export takes the first named Latin face and the first named CJK face of a stack. **Missing `typography.font_family`** → stop and return to Generate Step 4 / [`strategist.md`](strategist.md) §6.2; never infer a stack from `design_spec.md`.
---
@@ -18,9 +18,9 @@ Conditional Executor authority for image status handling, placement, crop behavi
**Template-bundled images**: [`apply-template-workspace.md`](../workflows/stages/apply-template-workspace.md) copies them into project `images/`; every page, including `mirror`, rebases the same bytes to exact `../images/<name>` (a transport rewrite, not a visual edit). Never keep a bare or source-template href.
**Contract — crop policy**: read the §VIII row and its lock projection (`source`, `crop`). On every slide that uses a `crop=no-crop` source (or legacy `| no-crop`), keep one visible complete instance with one of the nine legal `meet` anchors — never `none`, `clip-path`, `mask`, overflow clipping, or a nested crop viewport; an auxiliary same-slide detail or lens may crop the source only while that instance stays visible. `crop=adaptive` permits cropping without requiring it: choose `meet` or a focal-safe `slice` from purpose, ratio, focus, and container. A missing or conflicting projection returns upstream; the §VIII `Layout pattern` is a Reference — a starting sketch adjusted freely unless labeled `(binding)`.
**Contract — crop policy**: read the §VIII row and its lock projection (`source`, `crop`). On every slide that uses a `crop=no-crop` source (or legacy `| no-crop`), keep one visible complete instance with one of the nine legal `meet` anchors — never `none`, `clip-path`, `mask`, overflow clipping, or a nested crop viewport; an auxiliary same-slide detail or lens may crop the source only while that instance stays visible. `crop=adaptive` permits cropping without requiring it: choose `meet` or a focal-safe `slice` from purpose, ratio, focus, and container. A missing or conflicting projection returns upstream; the §VIII `Image pattern` is a Reference — a starting sketch adjusted freely unless labeled `(binding)`.
**Hard rule — same-source addressable crops, only when adopted**: no layout suggestion (including `#M1-11`) activates this transport, and `#M1-09` is a deliberate-offset treatment with no registered or Morph continuity. Use it only when independent crops must preserve one exact scene map or an explicit editable/Morph requirement needs them: reuse one exact `href` without slice assets, give every independent object a stable page-unique id and its own nested crop wrapper ([`svg-effects.md`](./svg-effects.md) §6.5) — plain rectangles need no crop marker; shaped frames put `data-pptx-crop="1"` on the wrapper and a matching `userSpaceOnUse` clip on the inner `<image>` — and derive every wrapper `viewBox` from one shared source-to-page transform over the union of the visible containers, so different container positions change the source-unit `x`, `y`, `width`, `height` by the same mapping and gaps remove pixels without rescaling. Repeated crops or SVG/PPT drift fail. A compound clip on one `<image>` is `#M1-10`, not a substitute when the objects must stay independently editable or Morphable.
**Hard rule — same-source addressable crops, only when adopted**: no layout suggestion (including `#M1-11`) activates this transport, and `#M1-09` is a deliberate-offset treatment with no registered or Morph continuity. Use it only when independent crops must preserve one exact scene map or an explicit editable/Morph requirement needs them: reuse one exact `href` without slice assets, give every independent object a stable page-unique id and its own nested crop wrapper, and derive every wrapper `viewBox` from one shared source-to-page transform over the union of the visible containers, so gaps remove pixels without rescaling. The wrapper grammar and the shaped-frame clip form are [`svg-effects.md`](./svg-effects.md) §6.5; repeated crops or SVG/PPT drift fail. A compound clip on one `<image>` is `#M1-10`, not a substitute when the objects must stay independently editable or Morphable.
**Hard rule — visible-layer timing**: every crop, lens, scrim, comparison, evidence, or annotation layer an adopted motion plan needs already exists in the final SVG; the motion stage may regroup ordinary Slide-local content but never invents or modifies visible content. When no legal unit can serve a non-binding suggestion, simplify to available units, a page transition, or `none`; an unrepresentable explicit requirement follows failure recovery.
@@ -44,4 +44,4 @@ Conditional Executor authority for image status handling, placement, crop behavi
| `panel` | Subdivide one coherent tilted, stepped, or polygonal parent panel |
| `none/grid` | Calm plain placement or a regular grid |
**Reference — motion-ready layering**: for an adopted §IX or explicit focus, comparison, evidence, reveal-order, or cross-page requirement, decide during authoring whether the composition needs separate visible units — stable framing stays static, each independently revealed or continuing Slide-local unit gets a descriptive direct-root `<g id>`, structured atoms and slots keep their boundaries; existing units or a page transition may suffice. The motion stage owns effects, pairing, order, and timing.
**Reference — motion-ready layering**: when custom motion is active ([`executor-base.md`](./executor-base.md) §1), each independently revealed or continuing image unit is its own descriptive direct-root `<g id>` authored now; stable framing stays static, structured atoms and slots keep their boundaries, and existing units or a page transition may suffice. The motion stage owns effects, pairing, order, and timing.
@@ -2,7 +2,7 @@
# Executor Shape Composition Grammar
Runtime grammar for Slide-local qualitative relationships built from editable shapes; not a diagram catalog. Default and Quick read it once at the first page whose Structure decision is `yes` and reuse it for every later page; loading it selects no `Structure=yes` and creates no geometry quota.
Runtime grammar for Slide-local qualitative relationships built from editable shapes; not a diagram catalog. Default and Quick read it once at the first page whose topology decision is `yes` and reuse it for every later page; loading it selects no `topology=yes` and creates no geometry quota.
**Hard rule — no Structure catalog**: never recall or resolve `structure/<key>`; compose from authoritative content, §IX relationships, the communication move, and the active visual system.
@@ -71,7 +71,7 @@ The last column names common transform axes, not an exhaustive set: combine, def
**Hard rule — relationship before styling**: establish atoms, field, spine, nodes, and necessary edges before palette, type, effects, or containers. Containment, alignment, baselines, and proximity express relationships without edges; lines/Connectors express real edges.
**Structural carriers**: a relationship-bearing field, spine, node carrier, or directional shape can be the page-scale move; Structure `yes` by itself adds no geometry. When drawn roles interact, resolve parent contour/direction → contact → joint or intentional void → z-order/occlusion → canvas-edge behavior before labels/garnish; skip inapplicable operations.
**Structural carriers**: a relationship-bearing field, spine, node carrier, or directional shape can be the page-scale move; `topology=yes` by itself adds no geometry. When drawn roles interact, resolve parent contour/direction → contact → joint or intentional void → z-order/occlusion → canvas-edge behavior before labels/garnish; skip inapplicable operations.
---
@@ -36,7 +36,7 @@ When the lock records `template_reuse_scope: mirror` (the workspace's `replicati
6. **Visible text**: mirror SVGs may carry literal source text rather than `{{...}}` markers; edit in place, retaining imported `data-pptx-placeholder` identity and exact topology.
7. **Output filename**: standard `<index>_<page_name>.svg` with the project page index; the mirror filename is the reference, not the output.
Chart, Table, and qualitative topology inside a mirror SVG are already authored: replace only permitted text and never redraw from a catalog or grammar; a JSON-first object may refresh its approximate preview from unchanged JSON without metadata, bounds, marker, slot, or visual drift; a mirror template normally omits `page_visualizations`, and legacy `page_charts` never overrides fidelity. **Legacy template boundary**: a template with missing root Master identity, direct atomic placeholders, `data-pptx-layout-kind`, unmapped `baseline`, `preserve`, or `layout_strategy: distill` is never a fallback input — stop and create a new workspace through [`create-template`](../workflows/create-template.md).
Chart, Table, and qualitative topology inside a mirror SVG are already authored: replace only permitted text and never redraw from a catalog or grammar; a JSON-first object may refresh its approximate preview from unchanged JSON without metadata, bounds, marker, slot, or visual drift; a mirror template normally omits `page_visualizations`, and legacy `page_charts` never overrides fidelity. **Legacy template boundary**: a legacy contract ([`pptx-structure-interface.md`](./pptx-structure-interface.md) §3) is never a fallback input — stop; a new workspace comes from [`create-template`](../workflows/create-template.md).
**Required output before each page**:
@@ -49,18 +49,12 @@ Content pages: the template defines only header/footer and the content area is f
### 1.2 PowerPoint Master / Layout Mapping
Applies only when the lock records `template_reuse_scope: mirror|layout`: `page_layouts` selects the input prototype, `pptx_masters` / `pptx_layouts` declare unique reusable output definitions, and `page_pptx_layouts` assigns every page before the first is drawn. `style`, free-design, and brand-only routes use `mode: flat`, omit all four sections, and keep every object Slide-local.
Applies only when the lock records `template_reuse_scope: mirror|layout`: `page_layouts` selects the input prototype, `pptx_masters` / `pptx_layouts` declare unique reusable output definitions, and `page_pptx_layouts` assigns every page before the first is drawn. `style`, free-design, and brand-only routes use `mode: flat`, omit all four sections, and keep every object Slide-local. The metadata contract every structured page satisfies — root identity attributes, atomic fixed layers, paint order, the slot form and its `object` + `proxy` composite, background ownership, text carriers — is [`pptx-structure-interface.md`](./pptx-structure-interface.md) §2; a legacy contract is rejected under its §3. This branch decides what each page declares:
- **Hard rule — reuse-scope route**: `mirror|layout` requires `mode: structured`; `style` requires `flat` even with a template vocabulary. A missing mode, legacy values (`baseline`, `template`, `preserve`), `layout_strategy`, Layout-kind fields, partial mappings, or old direct placeholders stop generation — create a new workspace, never upgrade in place.
- **Hard rule — root identity**: a `page_pptx_layouts` row binds the page to one `pptx_layouts` key, which supplies its Master key, Layout picker name, and prototype source; write the Master key/name and Layout key/name on the root `<svg>`. A Layout key belongs to one Master and is globally unique.
- **Hard rule — atomic fixed layers**: every `data-pptx-layer="master|layout"` visual is one direct root atom compiling to one DrawingML object; an ordinary marked `<g>` is forbidden, and one validated compact `preset_shape_svg.py` `<g>` is the sole exception. Push supported transforms, paint, opacity, and z-order of source groups into atomic children. Repeat the identical ordered Master atom contract on every page of that Master and the identical Layout atom contract on every page sharing `(master, layout)`.
- **Hard rule — paint order**: Master background atoms, Layout background atoms, optional Slide background, remaining Master atoms, remaining Layout atoms, then slot groups and Slide-local groups.
- **Mandatory — slots**: a reusable slot is one direct root `<g id>` with `data-pptx-placeholder` and one positive `data-pptx-bounds` (the reusable Layout default and the module boundary at once) containing exactly one compatible direct drawable child marked `data-pptx-carrier="true"`, which export unwraps into the real placeholder; decoration goes to a root Layout atom, page-specific labels to another slot or Slide-local group. Preserve imported `data-pptx-idx`; otherwise omit the title index and assign unique indices only where repeated roles need them; pages sharing a Layout key repeat the same slot ids, types, indices, default bounds, and binding modes while current text, crop, and carrier geometry may differ. A genuinely composite region may use `<g data-pptx-placeholder="object" data-pptx-binding="proxy">` with positive bounds (Slide-local visuals plus one hidden transparent proxy) — `object` only. **Forbidden — dummy carriers**: never tiny text, near-transparent glyphs, or background-colored punctuation; leave a blank text carrier empty (export emits an invisible U+200B run) or use the proxy; surface a `strict` mismatch instead of hiding it.
- **Zero-slot Layout**: covers, posters, and fixed visual pages still declare Master/Layout and fixed atoms without manufacturing a full-page `object` slot or `utility` identity.
- **Hard rule — root identity**: a `page_pptx_layouts` row binds the page to one `pptx_layouts` key, which supplies its Master key, Layout picker name, and prototype source; write the Master key/name and Layout key/name on the root `<svg>`. Repeat the identical ordered Master atom contract on every page of that Master and the identical Layout atom contract on every page sharing `(master, layout)`.
- **Mandatory — per-page slot coverage**: declare a slot for each standard role the page actually has — heading `title`, cover tagline `subtitle`, page number `slide-number`, running footer `footer`, hero/content image `picture`, one merged body frame `body`; zero slots is valid only for a genuinely fixed composition, never as the default; pages sharing a key ship the same slot set. **Hard rule — variable content**: page-varying text or images are carried by a slot or stay Slide-local, never become fixed Layout atoms.
- **Mandatory — layer coverage**: mark the deck-wide background and every-page chrome (footer bar, running logo) `master`, and the static framing that defines this key's composition (header rule, divider band, zone panels, chrome repeated on content pages but absent from the cover) `layout`; a page with zero marks exports a bare Master and empty Layout.
- **Layout identity and adherence**: keys differ in fixed atoms or slot topology/default bounds/binding modes, never in wording, imagery, crop, or Slide-local geometry; identical contracts share one key. Strict preserves atoms and slot ids/types/indices/bounds/bindings (`layout` may still change current text/tspans, line height, crop, and carrier-local geometry inside those bounds; `mirror` is topology-frozen); adaptive keeps the prototype Master and realizes only the Layout definition and assignment already declared in the lock. A needed change to atoms or slot topology stops the page and returns to Strategist to declare a new key, update definition and assignments, and validate; content alone is never a new Layout. Mark only genuinely reusable fixed framing as an atom — titles, body, metrics, chart marks, images, and page-specific groups stay in slots or Slide-local groups; the exporter never infers structure.
- **Background ownership**: deck-wide default = a direct full-canvas solid `<rect data-pptx-layer="master">` identical on every page; page-type default = `data-pptx-layer="layout"` on every page sharing the key; one-page exception = `data-pptx-layer="slide"`. These export as real `p:bg`; gradients, patterns, images, textures, and overlay panels stay explicit shapes or pictures, and the flat-mode background promotion rule does not apply.
---
@@ -29,7 +29,7 @@ python3 ${SKILL_DIR}/scripts/visualization_recall.py validate --legacy-bare <leg
**Hard rule — one primary reference per page**: one page resolves at most one catalog SVG, guiding one dominant reusable Chart/Table structure; secondary objects are authored from their content through the applicable branch without another catalog SVG, keeping their §IX or Quick object keys for native/verification contracts. New `page_visualizations` and Quick selections accept only canonical `chart/<key>` or `table/<key>`; a bare key is read-compatible only from legacy `page_charts` and must resolve unambiguously, otherwise stop for upstream correction. Canonical and legacy rows for one page stop on the duplicate contract even when both resolve to the same SVG.
**Legacy Structure boundary**: a retired Structure bare key is semantic intent, not a reference — do not resolve it or load this branch; recover the relationship from §IX and apply [`executor-structure.md`](./executor-structure.md) when the per-page Structure decision is yes, or return upstream when §IX lacks meaning.
**Legacy Structure boundary**: a retired Structure bare key is semantic intent, not a reference — do not resolve it or load this branch; recover the relationship from §IX and apply [`executor-structure.md`](./executor-structure.md) when the per-page topology decision is yes, or return upstream when §IX lacks meaning.
Read the resolver-returned SVG once before first use and reuse that reading until a known file change; do not reopen indexes or scan family directories during realization — the planning owner already reviewed the live registries.
@@ -10,7 +10,7 @@ Shared baseline for both acquisition paths and for prepared derivatives.
Status enum: [`svg-image-embedding.md`](svg-image-embedding.md). Per non-skipped row `Acquire Via` and `Status` are required; `Reference` is required for every `web` / `slice` row, every newly authored `ai` row, and every derivative (an existing `ai` row with a blank `Reference` continues only through [`image-generator.md`](./image-generator.md) §8's declared inference). Quick: explicit user assets, URLs, and path instructions win; otherwise the agent chooses `user` / `ai` / `web` / `slice` rows and AI path `auto` without interaction.
| Filename | Dimensions | Purpose / Type | Layout pattern | Crop Policy | Acquire Via | Status | Reference |
| Filename | Dimensions | Purpose / Type | Image pattern | Crop Policy | Acquire Via | Status | Reference |
|---|---|---|---|---|---|---|---|
| `<planned file>` | `<planned size>` | `<planned role>` | `<owner-resolved recommendation>` | `adaptive` / `no-crop` | `ai` / `web` / `slice` | Pending | `<acquisition brief>` |
@@ -27,7 +27,7 @@ Classify `Reference: Derived from <canonical bare filename>; treatment=<operatio
An all-`web` deck never reads `image-generator.md`, and vice versa.
**Mandatory — consume the resolved treatment path**: this phase never adds or reselects a treatment. `none` uses the canonical bitmap; `native` creates no file (SVG owns crop/clip, transform, opacity, frame/shadow/scrim/vignette, overlap); `prepared derivative` is a separate file only for pixel blur, desaturation/grayscale, duotone, brightness/contrast, or existing cutout/registered-layer preparation. Never bake a native treatment into a derivative.
**Mandatory — consume the resolved treatment path**: this phase never adds or reselects a treatment. `none` uses the canonical bitmap; `native` creates no file (SVG owns crop/clip, transform, opacity, frame/shadow/scrim/vignette, overlap); `prepared derivative` is a separate file only for pixel blur, desaturation/grayscale, duotone, brightness/contrast, downscaling to the planned on-slide size (`image_treat.py --fit WxH`, never upscaling), or existing cutout/registered-layer preparation. Never bake a native treatment into a derivative.
**Reference — pattern → preparation (an adopted id creates nothing by itself)**: `P*` / `M*` / `C*` use existing assets with native composition; `A1-02` / `A1-03``image_treat.py` blur / duotone; `A1-01` / `A1-04` → an existing composite or the host/AI path (`image_treat.py` does not blend); `A2-01` → an existing RGBA or flat-key AI/slice asset (with `A2-02` / `A2-03` + §4.4 when scene registration is required); `A2-02` / `A2-03` → §4.4 registered layers; `A2-04` → an existing transparent frame/device asset plus a content picture registered beneath it; `A3-01` → original/subject plus a registered `image_treat.py` derivative; `A3-02` → a registered full-canvas blur derivative with native crop panels; `A3-03` → a desaturated base plus an existing/§4.4 color subject layer.
@@ -22,7 +22,15 @@ Pick whatever `page_role` and `text_policy` make the page work; everything else
| `none` | No text inside the image |
| `embedded` | Stable text as part of the artwork — decorative lettering, wordmarks, hand-lettered words, figure-internal labels |
**Hard rule — only what is actually hard**: one `deck_rendering` and the same core deck color anchors for every image in the deck; HEX codes and color names are rendering guidance, never visible text; long copy, data points, bullet lists, and quotes stay in SVG; in-image text is only for words that will never need editing (one in-image word costs a regeneration, one SVG word a keystroke); prompts are one coherent prose paragraph, not tag soup.
**Hard rule — only what is actually hard**:
| Constraint | Rule |
|---|---|
| Deck identity | One `deck_rendering` and the same core deck color anchors for every image in the deck |
| Color values | HEX codes and color names are rendering guidance, never visible text |
| Copy | Long copy, data points, bullet lists, and quotes stay in SVG |
| In-image text | Only for words that will never need editing (one in-image word costs a regeneration, one SVG word a keystroke) |
| Prompt form | One coherent prose paragraph, not tag soup |
---
@@ -34,19 +42,38 @@ Pick whatever `page_role` and `text_policy` make the page work; everything else
| **Deck colors** | Core background / primary / accent / secondary-accent / text anchors from `spec_lock.md colors` (Default) or the active-context decisions (Quick) | Default after Stage 2; Quick before acquisition |
| **Type** | Optional recall for a local structural infographic's skeleton (infographic / flowchart / framework / matrix / cycle / funnel / pyramid / comparison / timeline / map / scene); omit when no template fits, for single-subject/portrait, and for `hero_page` | Per image |
Rendering decides how the image is drawn; color begins from the deck roles — background / secondary background dominate the field, primary carries main forms, accents stay scarce — with context-justified lighting, material, and tint transitions but never an unrelated image-only palette.
Rendering decides how the image is drawn. Color begins from the deck roles — background / secondary background dominate the field, primary carries main forms, accents stay scarce — with context-justified lighting, material, and tint transitions but never an unrelated image-only palette.
**Hard rule — on-demand loading**: read [`image-renderings/_index.md`](./image-renderings/_index.md) and [`image-type-templates/_index.md`](./image-type-templates/_index.md) once at role entry; after resolving inputs read only the selected preset rendering file, the exact custom references, and the type files actually used. Never glob a subdirectory.
**Hard rule — on-demand loading**: read [`image-renderings/_index.md`](./image-renderings/_index.md) and [`image-type-templates/_index.md`](./image-type-templates/_index.md) once at role entry. After resolving inputs read only the selected preset rendering file, the exact custom references, and the type files actually used. Never glob a subdirectory.
---
## 3. Workflow
1. **Load the indices** above.
2. **Resolve deck rendering + colors.** Default: `spec_lock.md colors` already carries `image_rendering` and the role HEX (`image_rendering: vector-illustration`, `background: #F8F9FA`, `primary: #1E3A5F`, `accent: #D4AF37`) — identity anchors, not a second user-facing choice. Quick: the agent resolves one rendering/color set in context and writes it to `image_prompts.json`. **`custom`**: read every `image_rendering_references` file when the row exists — apply one basis under `image_rendering_behavior`, or synthesize several by their stated line, texture, depth, material, and mood contributions; with no references use the behavior alone; never infer adjacent references. **Missing `image_rendering` key in an existing lock** ([`failure-recovery.md`](../workflows/governance/failure-recovery.md) §2): infer the rendering from `design_spec.md d. Style` plus the intended image jobs against the complete catalog, keep the existing color rows as anchors, sanity-check against `icons.library`, choose the strongest fit without presenting a choice, print "spec_lock.md has no `image_rendering`—inferring `<X>` from design_spec; image colors still use the locked deck roles.", and stop for lock repair if the inference lands on `custom` or the value is empty/invalid; outside Quick, an absent lock stops at Generate Step 5. Then read the single resolved rendering file (an 80120-word style paragraph plus two fewshot snippets).
3. **Per-image type + assembly.** Explicit row values bind; Quick resolves omissions. `Layout pattern` is never copied into the prompt; when page use depends on stable composition, carry the row's `Reference` / §IX / active-context contract — subject and quiet zones, boundary or direction, overlap/seam, approximate share — without inventing layout. `page_role`: the row's value, else `local` (`hero_page` is Strategist-explicit in Default; Quick may resolve it). `text_policy`: the row's value, else `none` or `embedded` from `Purpose`, `Reference`, and page intent. Type: an Illustration Sheet omits `type` and follows §4.3; another local structural infographic takes one of the 11 types only on a real index match, otherwise §4.1 E prose; a local single-subject/portrait uses §4.1 A/B; a `hero_page` uses §4.1 AE. Read `image-type-templates/<type>.md` only when selected. Assemble one paragraph from the rendering style paragraph, the deck color behavior, the type layout or composition prose, the `Reference` intent as concrete visual nouns, the container note, and the §5 hard rules.
2. **Resolve deck rendering + colors** (table below), then read the single resolved rendering file (an 80120-word style paragraph plus two fewshot snippets).
3. **Per-image type + assembly** (table below). Assemble one paragraph from the rendering style paragraph, the deck color behavior, the type layout or composition prose, the `Reference` intent as concrete visual nouns, the container note, and the §5 hard rules.
4. **Write the manifest (§6) and execute the selected path (§7)** — Default's confirmed path, Quick's explicit path or `auto`, without asking.
**Rendering and color resolution**:
| Situation | Resolution |
|---|---|
| Default | `spec_lock.md colors` already carries `image_rendering` and the role HEX (`image_rendering: vector-illustration`, `background: #F8F9FA`, `primary: #1E3A5F`, `accent: #D4AF37`) — identity anchors, not a second user-facing choice |
| Quick | The agent resolves one rendering/color set in context and writes it to `image_prompts.json` |
| `custom` | Read every `image_rendering_references` file when the row exists — apply one basis under `image_rendering_behavior`, or synthesize several by their stated line, texture, depth, material, and mood contributions; with no references use the behavior alone; never infer adjacent references |
| Missing `image_rendering` key in an existing lock ([`failure-recovery.md`](../workflows/governance/failure-recovery.md) §2) | Infer the rendering from `design_spec.md d. Style` plus the intended image jobs against the complete catalog; keep the existing color rows as anchors; sanity-check against `icons.library`; choose the strongest fit without presenting a choice; print "spec_lock.md has no `image_rendering`—inferring `<X>` from design_spec; image colors still use the locked deck roles." Stop for lock repair if the inference lands on `custom` or the value is empty/invalid |
| Absent lock outside Quick | Stops at Generate Step 5 |
**Per-image resolution** (explicit row values bind; Quick resolves omissions):
| Field | Resolution |
|---|---|
| `Image pattern` | Never copied into the prompt. When page use depends on stable composition, carry the row's `Reference` / §IX / active-context contract — subject and quiet zones, boundary or direction, overlap/seam, approximate share — without inventing layout |
| `page_role` | The row's value, else `local` (`hero_page` is Strategist-explicit in Default; Quick may resolve it) |
| `text_policy` | The row's value, else `none` or `embedded` from `Purpose`, `Reference`, and page intent |
| Type | An Illustration Sheet omits `type` and follows §4.3; another local structural infographic takes one of the 11 types only on a real index match, otherwise §4.1 E prose; a local single-subject/portrait uses §4.1 A/B; a `hero_page` uses §4.1 AE. Read `image-type-templates/<type>.md` only when selected |
---
## 4. Prompt Assembly Template
@@ -90,17 +117,19 @@ A/B describe a hero or a local single-subject region; C/D are hero-page composit
A sheet generates compatible transparent **illustration**, **illustrated-icon**, or **decorative lettering** elements sharing rendering, deck-color treatment, and finish; subjects, silhouettes, weights, and jobs may differ, and SVG composes after slicing. Lettering is stable Layer 1 artwork, never page copy turned into an image.
**Default — batch compatible elements; split when separate generation improves the result**: group illustrated-icon cues normally, group lettering by compatible letterform character and treatment (not font name), and split for style, geometry, detail, quality, or semantic precision. A single element may use a keyed `1x1` sheet; full-canvas or opaque images take the normal §4.1 path.
**Default — batch compatible elements; split when separate generation improves the result**: group illustrated-icon cues normally; group lettering by compatible letterform character and treatment (not font name); split for style, geometry, detail, quality, or semantic precision. A single element may use a keyed `1x1` sheet. Full-canvas or opaque images take the normal §4.1 path.
**Hard rule — a sheet is a generation source, not a slide asset**: never referenced from SVG; out of `spec_lock.md images` in Default, generation-only in Quick's context and manifest; only sliced element rows are placed. **Hard rule — separable treatment before keying**: when the slice excludes a supporting surface, choose a treatment whose complete visible geometry stands alone against the key field; engraved, etched, debossed, inlaid, or bas-relief treatments are valid only when their carrier belongs in the slice — never define a carrier as necessary and ask the prompt to remove it.
**Hard rule — a sheet is a generation source, not a slide asset**: never referenced from SVG; out of `spec_lock.md images` in Default, generation-only in Quick's context and manifest; only sliced element rows are placed.
**Hard rule — separable treatment before keying**: when the slice excludes a supporting surface, choose a treatment whose complete visible geometry stands alone against the key field. Engraved, etched, debossed, inlaid, or bas-relief treatments are valid only when their carrier belongs in the slice; never define a carrier as necessary and ask the prompt to remove it.
**Sheet prompt convention** — one `page_role: local` item with `image_size` from final placement; spot sheets `text_policy: none`, lettering sheets `embedded`:
- Derive `aspect_ratio` and `--grid` from the target shape, not a universal square grid. State an invisible logical **R×C grid** and the cell shape (compact square object, tall portrait, wide vignette, wide lettering mark); center and isolate each element with even clear gutters; never draw cells, panels, dividers, borders, frames, or alternate gutter colors; never shrink every subject into a square sticker.
- One flat chroma key across the sheet — pure `#00FF00`, `#0000FF`, or `#FF0000`, chosen so its color dominates no element or effect — stated as exact HEX, unchanged in every gutter, free of reflections or spill; grain, halftone, and vignette stay inside elements. The key is technical, not deck palette.
- Shared `deck_rendering` + `color_scheme`.
- Illustration / illustrated-icon sheet: name each element and its page or reuse job; for an icon, the compact cue that must survive at placement size; the §5.3 `none` cue.
- Lettering sheet: exactly one named stable string per cell as the only text, quoted literally; the group's letterform character and treatment, then role, placement/background relationship, relative weight, and energy under §5.3's controlled-authorship default; artistry glyph-bound (silhouette, stroke structure, material, texture, depth, contour-bound light); no topic motifs, scene fragments, icons, detached ribbons, or particles unless the approved treatment is a lettering-plus-illustration lockup; key-only padding, no scene, unrelated copy, labels, watermark, or mockup surface.
- **Grid**: derive `aspect_ratio` and `--grid` from the target shape, not a universal square grid. State an invisible logical **R×C grid** and the cell shape (compact square object, tall portrait, wide vignette, wide lettering mark); center and isolate each element with even clear gutters. Never draw cells, panels, dividers, borders, frames, or alternate gutter colors; never shrink every subject into a square sticker.
- **Key**: one flat chroma key across the sheet — pure `#00FF00`, `#0000FF`, or `#FF0000`, chosen so its color dominates no element or effect — stated as exact HEX, unchanged in every gutter, free of reflections or spill; grain, halftone, and vignette stay inside elements. The key is technical, not deck palette.
- **Identity**: shared `deck_rendering` + `color_scheme`.
- **Illustration / illustrated-icon sheet**: name each element and its page or reuse job; for an icon, the compact cue that must survive at placement size; the §5.3 `none` cue.
- **Lettering sheet**: exactly one named stable string per cell as the only text, quoted literally; the group's letterform character and treatment, then role, placement/background relationship, relative weight, and energy under §5.3's controlled-authorship default; artistry glyph-bound (silhouette, stroke structure, material, texture, depth, contour-bound light). No topic motifs, scene fragments, icons, detached ribbons, or particles unless the approved treatment is a lettering-plus-illustration lockup; key-only padding, no scene, unrelated copy, labels, watermark, or mockup surface.
- **Delivery floor, not an aesthetic ceiling**: enlarge the cell, change the grid, or use a larger or separate sheet when a treatment needs footprint; never weaken an approved treatment to fit a crop.
**Cell geometry is designed**: `slice_images.py --grid RxC` cuts rows first; `cell_ratio = sheet_ratio × rows / cols`. On a wide sheet `1xN` yields tall cells and `Nx1` wide cells; any `MxN` is valid when its cells match the placements.
@@ -115,7 +144,12 @@ A sheet generates compatible transparent **illustration**, **illustrated-icon**,
Shape families that cannot share a roomy grid take separate sheets; coherence comes from rendering and colors, not one forced sheet.
**Resource contract**: a **sheet row** is `Acquire Via: ai`, `Type: Illustration Sheet`, named as the slice source with intent, cell shape, and purpose (`Reference: reusable title/corner illustration family`, `illustrated-icon set: cues = ...`, or `decorative lettering set: exact strings = ...`); Step 5 generates it, it is never placed, and Image_Generator resolves its aspect ratio, grid, and slice command. **Element rows** are one per used element, `Acquire Via: slice`, filename matching `--names`, `Reference` naming the parent and cell, listed in the placeable authority normally with `crop=no-crop` (tight slices use fit, not cover-crop), `Type: Illustrated icon` for a compact cue (never an SVG library entry), reusable across pages, each carrying an owner-resolved layout recommendation, dimensions filled after slicing by `analyze_images.py`. Add `slice_grid` and `slice_names` to the sheet's manifest item — the comma-separated basenames are the complete required output set.
**Resource contract**:
| Row | Content |
|---|---|
| **Sheet row** | `Acquire Via: ai`, `Type: Illustration Sheet`, named as the slice source with intent, cell shape, and purpose (`Reference: reusable title/corner illustration family`, `illustrated-icon set: cues = ...`, or `decorative lettering set: exact strings = ...`). Step 5 generates it; it is never placed; Image_Generator resolves its aspect ratio, grid, and slice command. Its manifest item carries `slice_grid` and `slice_names` — the comma-separated basenames are the complete required output set |
| **Element rows** | One per used element, `Acquire Via: slice`, filename matching `--names`, `Reference` naming the parent and cell, listed in the placeable authority normally with `crop=no-crop` (tight slices use fit, not cover-crop), `Type: Illustrated icon` for a compact cue (never an SVG library entry), reusable across pages, each carrying an owner-resolved layout recommendation, dimensions filled after slicing by `analyze_images.py` |
```bash
SHEET_KEY_HEX="#00FF00" # example only; choose a key absent from every element/effect
@@ -124,9 +158,15 @@ python3 scripts/slice_images.py <project>/images/illus_sheet.png --grid 2x3 \
--bg "${SHEET_KEY_HEX}" --strict-alpha
```
`--names` count equals `rows*cols`; `--strict-alpha` writes nothing on an incomplete cut. Three quality constraints: **strict key recovery** — raise `--tolerance` only enough to absorb measured flat-field drift, `--inset` only for an isolated outer gutter, and regenerate or enlarge when an effect reaches an edge; **clean isolated cells** — fused cells, scene backgrounds, or flourishes crossing a cell make the sheet unusable, and re-rolls follow only a strict keying failure or user/preview evidence, never taste; **enough source pixels** — each cell at least 1.52× its display size (`1K` small accents, `2K` medium, `4K` large or enlarged).
`--names` count equals `rows*cols`; `--strict-alpha` writes nothing on an incomplete cut. Three quality constraints:
**Placement**: a slice is a decorative accessory, not a boxed picture — a spot wasted in a centered rectangle looks cheaper than none; it may stay unboxed at a margin, run off the canvas edge, sit behind or beside text with a slight rotation, vary in size and angle across pages, enter a container, or combine with backgrounds, shapes, text, photos, other slices, and lettering; stable chrome may repeat exactly while anchors and accents vary in scale, position, pairing, and interaction. Editable copy stays SVG; a large SVG-composed anchor remains `local` / `slice`, and `hero_page` applies only when one bitmap owns the page. No quota.
| Constraint | Rule |
|---|---|
| **Strict key recovery** | Raise `--tolerance` only enough to absorb measured flat-field drift, `--inset` only for an isolated outer gutter, and regenerate or enlarge when an effect reaches an edge |
| **Clean isolated cells** | Fused cells, scene backgrounds, or flourishes crossing a cell make the sheet unusable; re-rolls follow only a strict keying failure or user/preview evidence, never taste |
| **Enough source pixels** | Each cell at least 1.52× its display size (`1K` small accents, `2K` medium, `4K` large or enlarged) |
**Placement**: a slice is a decorative accessory, not a boxed picture — a spot wasted in a centered rectangle looks cheaper than none. It may stay unboxed at a margin, run off the canvas edge, sit behind or beside text with a slight rotation, vary in size and angle across pages, enter a container, or combine with backgrounds, shapes, text, photos, other slices, and lettering. Stable chrome may repeat exactly while anchors and accents vary in scale, position, pairing, and interaction. Editable copy stays SVG; a large SVG-composed anchor remains `local` / `slice`, and `hero_page` applies only when one bitmap owns the page. No quota.
### 4.4 Registered reconstruction groups and shared plates
@@ -139,13 +179,24 @@ Use when a person, product, creature, effect, or scene element must cross native
| Subject / foreground | Full canvas with one subject or one z-order-compatible set on RGBA transparency |
| Shared layer plate | Several mutually non-overlapping objects isolated together in one full-canvas or regular-cell output |
**Mandatory — preserve registration**: derive every full-canvas member independently from the same canonical source, keeping canvas dimensions, pose, scale, position, lighting, and style, never trimming or cropping a registered output; record the shared source and group in the owning rows. **Image to PPTX (Codex required)**: follow its §3 per-region decision — a complete, separable, resolution-sufficient region may stay source-derived, otherwise use Codex's native reference-image capability; inspect every member and the recomposition; do not adapt `image_gen.py` or its backends for that profile; other hosts unsupported.
**Mandatory — preserve registration**: derive every full-canvas member independently from the same canonical source, keeping canvas dimensions, pose, scale, position, lighting, and style; never trim or crop a registered output; record the shared source and group in the owning rows.
Procedure: (1) from the canonical reference remove every planned subject, foreground object, source graphic, and editable text, then inpaint one clean base without redesigning the background; (2) prepare the subject/foreground as an exact source-derived layer or a reference reconstruction, never from a generated base or layer; (3) prefer one shared plate when objects do not overlap and share an isolation treatment, with padded bboxes (shadows and effects included) pairwise disjoint; (4) a registered plate keeps original positions with one nested-SVG crop per recorded bbox ([`svg-effects.md`](./svg-effects.md) §6.5), a rearranged regular-cell plate is sliced under §4.3 and each asset placed at its recorded bbox; (5) prefer direct RGBA, otherwise one exact flat key over the whole layer and one `1x1` `--alpha` slice without `--trim` so coordinates hold — never one keyed image per object; (6) save under `<project>/images/`, registered full-canvas members `no-crop`. Overlapping or differently ordered objects take separate layers; a shared output is valid only when every final object still becomes an independent picture.
**Image to PPTX (Codex required)**: follow its §3 per-region decision — a complete, separable, resolution-sufficient region may stay source-derived, otherwise use Codex's native reference-image capability. Inspect every member and the recomposition. Do not adapt `image_gen.py` or its backends for that profile; other hosts unsupported.
**Procedure**:
1. From the canonical reference remove every planned subject, foreground object, source graphic, and editable text, then inpaint one clean base without redesigning the background.
2. Prepare the subject/foreground as an exact source-derived layer or a reference reconstruction, never from a generated base or layer.
3. Prefer one shared plate when objects do not overlap and share an isolation treatment, with padded bboxes (shadows and effects included) pairwise disjoint.
4. A registered plate keeps original positions with one nested-SVG crop per recorded bbox ([`svg-effects.md`](./svg-effects.md) §6.5); a rearranged regular-cell plate is sliced under §4.3 and each asset placed at its recorded bbox.
5. Prefer direct RGBA, otherwise one exact flat key over the whole layer and one `1x1` `--alpha` slice without `--trim` so coordinates hold — never one keyed image per object.
6. Save under `<project>/images/`, registered full-canvas members `no-crop`.
Overlapping or differently ordered objects take separate layers. A shared output is valid only when every final object still becomes an independent picture.
> **Shared registered-plate prompt core**: Using the supplied canonical page as the only visual reference, isolate the following foreground objects together on one full-canvas extraction plate: {stable object ids/descriptions}. Preserve each object's visible identity, silhouette, pose, scale, rotation, lighting, shadow, and exact original canvas position; keep the original aspect ratio and registration; retain only the listed objects and remove the background and every unlisted element; do not rearrange, resize, merge, duplicate, or let objects touch; retain an explicitly listed source graphic or wordmark exactly and remove editable slide text and every unlisted logo. Return RGBA if supported; otherwise one uniform exact {key HEX} matte with no gradient, texture, spill, or extra marks.
Outside Image to PPTX, Path A uses single-image edit mode and Path B the host tool — the declared derivation exception for already-planned group rows, every member kept in the resource authority and sidecar; SVG realization follows [`image-layout-patterns.md`](./image-layout-patterns.md) `#A2-03`:
Outside Image to PPTX, Path A uses single-image edit mode and Path B the host tool — the declared derivation exception for already-planned group rows, every member kept in the resource authority and sidecar. SVG realization follows [`image-layout-patterns.md`](./image-layout-patterns.md) `#A2-03`:
```bash
python3 scripts/image_gen.py "Remove the planned foreground subjects and reconstruct the hidden background; preserve the exact canvas" \
@@ -177,13 +228,30 @@ Match facial detail, anatomy, texture, and realism to the rendering and the row'
| Layer 1 (image-owned) | the prompt, baked into the raster | figure-internal annotations (axis labels, A/B/C markers, units, scale bars, panel labels); schematic module names, node labels, signal-path ids; stable artistic lettering that *is* the visual |
| Layer 2 (SVG-owned) | editable `<text>` overlay | authoritative deck/page/chapter titles; navigation, footer, body bullets, conclusion callouts; readable copy and captions |
`text_policy` controls only Layer 1, judged per image with no global bias. Positive triggers for `embedded` — a paper-figure panel comparison (panel labels), a textbook math or signal figure (curve names, axes, units), a discipline-convention schematic (`Self-Attention`, `FFN`, node ids), a data figure with stable axes, a typographic hero (§4.1 C) — start at `embedded` and then apply the editability filter; defaulting a whole `ai` list to `none` because "SVG can always overlay" is the failure mode this table breaks. Prompt cues: `none`*"NO text of any kind anywhere in the image — no letters, numbers, signs, watermarks, labels, or written symbols."*; `embedded` → describe the exact characters, how they are rendered, and the treatment inside the scene.
`text_policy` controls only Layer 1, judged per image with no global bias. Positive triggers for `embedded` — a paper-figure panel comparison (panel labels), a textbook math or signal figure (curve names, axes, units), a discipline-convention schematic (`Self-Attention`, `FFN`, node ids), a data figure with stable axes, a typographic hero (§4.1 C) — start at `embedded` and then apply the editability filter. Defaulting a whole `ai` list to `none` because "SVG can always overlay" is the failure mode this table breaks.
**Hard rule — decide by editability, not model capability**: Layer 1 text can never be edited, corrected, searched, restyled, or reflowed. Text that is part of the artwork and stable — decorative lettering, a wordmark, a hand-lettered phrase, figure-internal identifiers — may be Layer 1; anything that must stay exact, searchable, editable, or may be reworded is Layer 2, whatever `text_policy` says: authoritative titles, chrome, navigation, footer, bullets, captions, data values. Bake title-like wording only when the approved plan treats those exact characters as stable artwork. Never pre-judge by script or length — never push text to SVG, shorten a headline, or downgrade `embedded` to `none` on the assumption that a script or long string "won't render"; a multi-word phrase or two-line lockup qualifies exactly as one word does. Name the exact characters literally; do not re-read the generated image to verify them. When the headline must stay editable, use Primitive D and overlay it.
| Policy | Prompt cue |
|---|---|
| `none` | *"NO text of any kind anywhere in the image — no letters, numbers, signs, watermarks, labels, or written symbols."* |
| `embedded` | Describe the exact characters, how they are rendered, and the treatment inside the scene |
**Reference — controlled, deck-aligned artistic authorship** (high expression on user request or a confirmed direction): give the model the exact string, communication role, placement/background relationship, deck identity, relative weight, and desired energy; the rendering, semantic colors, mood, and page hierarchy define the envelope. Glyph-native expression carries identity through silhouette, stroke construction, internal material/texture, contour-bound depth and light, and composition; literal topic illustrations or detached decoration compete with the glyph, and a lettering-plus-illustration lockup needs an explicit request or confirmed direction. Within the treatment let the model combine or omit gesture, material, dimensionality, texture, lighting, and hierarchy — possibility space, not a recipe; never flatten the art to ease extraction (§4.3's gates protect delivery); when fit is uncertain use the lower density; keep a multi-line lockup as one element when its hierarchy is part of the art.
**Hard rule — decide by editability, not model capability**: Layer 1 text can never be edited, corrected, searched, restyled, or reflowed. Text that is part of the artwork and stable — decorative lettering, a wordmark, a hand-lettered phrase, figure-internal identifiers — may be Layer 1. Anything that must stay exact, searchable, editable, or may be reworded is Layer 2, whatever `text_policy` says: authoritative titles, chrome, navigation, footer, bullets, captions, data values. Bake title-like wording only when the approved plan treats those exact characters as stable artwork. When the headline must stay editable, use Primitive D and overlay it.
**Font for in-image text** is a free description, not an enum — blackletter for a heritage cover, hand-brushed for a manifesto, retro chrome for Y2K, art-deco display for luxury, ribbon script for a zine. Echo the SVG body only when stable lettering should read as the same family as the deck's typography: serif families → "elegant serif lettering, refined letterforms"; sans (YaHei / PingFang / Arial) → "clean geometric sans-serif, modern letterforms"; display (SimHei / Impact / Arial Black) → "bold display lettering, heavy expressive strokes"; monospace → "monospace technical lettering, fixed-width"; sketch/ink renderings or no family → "hand-lettered organic strokes, natural variation". Ignore that echo for decorative or background lettering, posters, mood words, cover wordmarks wanting their own identity, hand-drawn renderings, or any rendering that already implies a period letterform.
**Hard rule — never pre-judge by script or length**: never push text to SVG, shorten a headline, or downgrade `embedded` to `none` on the assumption that a script or long string "won't render"; a multi-word phrase or two-line lockup qualifies exactly as one word does. Name the exact characters literally; do not re-read the generated image to verify them. Exception — CJK lettering: when `text_policy: embedded` and the string contains CJK characters, one look at the generated file is allowed, answering only whether the characters match the approved string exactly; a mismatch regenerates that item, and the look never reopens selection or taste.
**Reference — controlled, deck-aligned artistic authorship** (high expression on user request or a confirmed direction): give the model the exact string, communication role, placement/background relationship, deck identity, relative weight, and desired energy; the rendering, semantic colors, mood, and page hierarchy define the envelope. Glyph-native expression carries identity through silhouette, stroke construction, internal material/texture, contour-bound depth and light, and composition. Literal topic illustrations or detached decoration compete with the glyph; a lettering-plus-illustration lockup needs an explicit request or confirmed direction. Within the treatment let the model combine or omit gesture, material, dimensionality, texture, lighting, and hierarchy — possibility space, not a recipe. Never flatten the art to ease extraction (§4.3's gates protect delivery); when fit is uncertain use the lower density; keep a multi-line lockup as one element when its hierarchy is part of the art.
**Font for in-image text** is a free description, not an enum — blackletter for a heritage cover, hand-brushed for a manifesto, retro chrome for Y2K, art-deco display for luxury, ribbon script for a zine. Echo the SVG body only when stable lettering should read as the same family as the deck's typography:
| Deck family | Echo |
|---|---|
| Serif families | "elegant serif lettering, refined letterforms" |
| Sans (YaHei / PingFang / Arial) | "clean geometric sans-serif, modern letterforms" |
| Display (SimHei / Impact / Arial Black) | "bold display lettering, heavy expressive strokes" |
| Monospace | "monospace technical lettering, fixed-width" |
| Sketch/ink renderings or no family | "hand-lettered organic strokes, natural variation" |
Ignore that echo for decorative or background lettering, posters, mood words, cover wordmarks wanting their own identity, hand-drawn renderings, or any rendering that already implies a period letterform.
### 5.4 No brand names or trademarks in the subject
@@ -239,7 +307,7 @@ Write `project/images/image_prompts.json`:
| `items[].type` | no | One of the 11 internal-composition types for a local structural infographic when a template genuinely fits; omitted for §4.1 E prose, `hero_page`, sheets, and single-subject/portrait |
| `items[].page_role` | yes | `local` (default) or `hero_page` |
| `items[].text_policy` | yes | `none` or `embedded`, judged per image (§5.3) |
| `items[].aspect_ratio` | yes | Passed to `image_gen.py --aspect_ratio` |
| `items[].aspect_ratio` | yes | Passed to `image_gen.py --aspect_ratio`; every backend accepts a subset of the CLI union (e.g. gemini has no `3:1`), and `--manifest` fails the item before any request when the resolved backend rejects its ratio |
| `items[].prompt` | yes | The assembled paragraph |
| `items[].image_size` | no | `512px` / `1K` / `2K` / `4K` |
| `items[].model` | no | Per-item backend model override |
@@ -247,7 +315,7 @@ Write `project/images/image_prompts.json`:
| `items[].slice_grid`, `items[].slice_names` | for a placeable-element sheet | Exact `RxC` and the comma-separated basenames (`rows*cols` unique outputs) for `slice_images.py` |
| `items[].status` | yes | `Pending` initially; the CLI writes `Generated` / `Failed` / `Needs-Manual` |
**Compatibility**: legacy `type` values read as `background``hero_page` + no type, `hero``hero_page` + Primitive A, `portrait``local` + Primitive B, `typography``hero_page` + `embedded` + Primitive C; a missing `page_role` is `local`, a missing `text_policy` is `none` (one aggregate warning per manifest); an existing manifest lacking `deck_rendering` or an item lacking `type` replays its assembled `prompt` verbatim without reconstruction; a legacy `deck_style_anchor` or `deck_palette` never overrides `deck_rendering` / `color_scheme`; legacy `page_role: full_page` reads as `hero_page`.
Legacy manifest spellings and their current readings: [`image.md`](../scripts/docs/image.md).
---
@@ -261,7 +329,19 @@ Prerequisite: §3 complete and `images/image_prompts.json` validates. The manife
| `host-native`, or `auto` with a host image tool | **Path B** host-native tool | The agent invokes the host capability; outputs land at `project/images/<filename>` |
| Default confirmed `manual`, or Quick explicitly `manual` | **Offline Manual** | Manifest stays on disk; the user generates from `items[].prompt` and places files |
**Path selection**: planning never inspects configuration or probes a provider — capability is resolved only here. Default honors `AI Image Acquisition Path` from `design_spec.md §I` (already consumed from the confirmation; never reopen `result.json`): `api` → Path A; `host-native` → Path B, skipping A even when `IMAGE_BACKEND` is configured; `manual` → Offline Manual; `auto` → Path A when `IMAGE_BACKEND` is configured (two consecutive failures fall to B), then Path B when the host has a native tool, never Offline Manual by itself; a missing row returns to Step 4 recovery. Quick honors an explicit `api` / `host-native` / `manual` instruction, otherwise `auto` A → B without asking. **Hard rule**: normal execution never reopens selection; a confirmed path that fails after its retry never switches provider — Default enters the recovery decision below, Quick applies its no-AI replan. All modes share one output contract: a file at `project/images/<filename>`.
**Path selection**: planning never inspects configuration or probes a provider — capability is resolved only here. All modes share one output contract: a file at `project/images/<filename>`.
| Recorded path | Resolution |
|---|---|
| Default `api` (from `AI Image Acquisition Path` in `design_spec.md §I`, already consumed from the confirmation; never reopen `result.json`) | Path A |
| Default `host-native` | Path B, skipping A even when `IMAGE_BACKEND` is configured |
| Default `manual` | Offline Manual |
| Default `auto` | Path A when `IMAGE_BACKEND` is configured (two consecutive failures fall to B), then Path B when the host has a native tool; never Offline Manual by itself |
| Default missing row | Return to Step 4 recovery |
| Quick explicit `api` / `host-native` / `manual` | That path |
| Quick otherwise | `auto` A → B without asking |
**Hard rule — no reopened selection**: normal execution never reopens selection. A confirmed path that fails after its retry never switches provider — Default enters the recovery decision below, Quick applies its no-AI replan.
### Path A — `image_gen.py --manifest`
@@ -269,31 +349,56 @@ Prerequisite: §3 complete and `images/image_prompts.json` validates. The manife
python3 scripts/image_gen.py --manifest project/images/image_prompts.json --output project/images
```
Validates the file behind every `Generated` row before skipping it, iterates retryable rows with bounded adaptive concurrency, and writes each status atomically; a missing or corrupt file returns to `Failed`, and persistent rate limits end the run as retryable `Failed`. Options: `--concurrency` (default `IMAGE_CONCURRENCY` or 3; halves on rate limit, min 1), `--image_size`, `--output`/`-o`, `--backend`/`-b`, `--model`/`-m`, `--list-backends`. Interrupting is safe (completed items stay `Generated`); the Markdown sidecar re-renders on completion, or run `--render-md` after an interruption. Configuration: process environment first, then the first `.env` in cwd, the skill directory, the clone root, `~/.ppt-master/.env``IMAGE_BACKEND` (required; `--list-backends` shows the set and support tiers), `IMAGE_CONCURRENCY`, provider-specific `{PROVIDER}_API_KEY` / `_BASE_URL` / `_MODEL` (never `IMAGE_API_KEY` / `IMAGE_MODEL` / `IMAGE_BASE_URL`), and for OpenAI-compatible platforms `OPENAI_SIZE_PRESET` (`auto|legacy|gpt-image|gpt-image-2|dall-e-2`), `OPENAI_RESPONSE_FORMAT` (`auto|b64_json|url|omit`), `OPENAI_QUALITY` (`auto|omit|low|medium|high|standard|hd`) under `IMAGE_BACKEND=openai`; see `.env.example`. The single-image form `image_gen.py "prompt" --filename …` remains for ad-hoc re-rolls.
Validates the file behind every `Generated` row before skipping it, iterates retryable rows with bounded concurrency, and writes each status atomically. Interrupting is safe (completed items stay `Generated`), and `--render-md` refreshes the Markdown sidecar after an interruption. Backend selection, `.env` lookup order, provider keys, and the OpenAI-compatible knobs: [`image.md`](../scripts/docs/image.md). The single-image form `image_gen.py "prompt" --filename …` remains for ad-hoc re-rolls. Backends return their own native resolutions: backfill the actual pixels into `Dimensions`, and when a file is far larger than its planned on-slide size, downscale it to that size as a prepared derivative (`image_treat.py --fit WxH`); never upscale.
### Path B — host-native image tool
Automatic when `IMAGE_BACKEND` is unset or Path A failed and the host (Codex, Antigravity, Claude Code, similar) offers an image tool; the user may also name it explicitly. Prompts come from `items[].prompt`; never run `image_gen.py --manifest` here, but still run `python3 scripts/image_gen.py --render-md project/images/image_prompts.json` for the sidecar. Batch a few rows at a time (~34) when the host runs tools in parallel, serially otherwise. Outputs land at the resource-list filename; hosts with fixed native resolutions generate at the closest size and backfill the actual pixels into `Dimensions` never upscale to fake a size (display-side upscaling up to ~1.3× is a non-blocking warning). Mark each item `Generated` as its file lands.
Automatic when `IMAGE_BACKEND` is unset or Path A failed and the host (Codex, Antigravity, Claude Code, similar) offers an image tool; the user may also name it explicitly. Prompts come from `items[].prompt`. Never run `image_gen.py --manifest` here, but still run `python3 scripts/image_gen.py --render-md project/images/image_prompts.json` for the sidecar. Batch a few rows at a time (~34) when the host runs tools in parallel, serially otherwise. Outputs land at the resource-list filename. Hosts with fixed native resolutions generate at the closest size and backfill the actual pixels into `Dimensions`; never upscale to fake a size (display-side upscaling up to ~1.3× is a non-blocking warning). Mark each item `Generated` as its file lands.
### Offline Manual Mode
Entered only after Default confirmed `manual` (Stage 2 or the recovery decision) or an explicit Quick instruction — never asked again inside acquisition. Verify the manifest, set `status: "Needs-Manual"` on every affected item ([`image-base.md`](./image-base.md) §3), and print one consolidated handoff: filenames, the `images/image_prompts.md` paste-ready blocks (or `items[].prompt`), the exact target `project/images/<filename>`, and the continuation — Default draws dashed placeholders and blocks every Step 7 export command until files are validated and placeholders replaced; Quick blocks direct export until every required row is validated and reconciled to `Generated`, and only while the original context survives (otherwise a clean run).
Entered only after Default confirmed `manual` (Stage 2 or the recovery decision) or an explicit Quick instruction — never asked again inside acquisition. Verify the manifest, set `status: "Needs-Manual"` on every affected item ([`image-base.md`](./image-base.md) §3), and print one consolidated handoff: filenames, the `images/image_prompts.md` paste-ready blocks (or `items[].prompt`), the exact target `project/images/<filename>`, and the continuation.
| Runtime | Continuation |
|---|---|
| Default | Draws dashed placeholders and blocks every Step 7 export command until files are validated and placeholders replaced |
| Quick | Blocks direct export until every required row is validated and reconciled to `Generated`, and only while the original context survives (otherwise a clean run) |
#### Default exhausted-automation decision
When required rows stay unresolved after the confirmed path or `auto`'s A → B, keep them `Failed`, pause once with one consolidated list (filenames, prompts, attempted paths, concrete errors), and ask for exactly one outcome: **repair and retry** (the same confirmed path; `auto` keeps A → B; a repeat failure returns here with the new error), **generate manually** (record `AI Image Acquisition Path: manual` in `design_spec.md §I`, mark rows `Needs-Manual`, hand off, author up to the Step 7 readiness gate), or **cancel the affected AI images** (return to Step 4 as a post-confirmation override, remove the `ai` and dependent `slice` rows, revise their §IX jobs and lock rows to native text/SVG or confirmed non-AI sources, set the path `not applicable` when no AI rows remain, never add a new source or drop required content). Never create `Needs-Manual` before manual fulfillment is confirmed.
When required rows stay unresolved after the confirmed path or `auto`'s A → B, keep them `Failed`, pause once with one consolidated list (filenames, prompts, attempted paths, concrete errors), and ask for exactly one outcome. Never create `Needs-Manual` before manual fulfillment is confirmed.
| Outcome | Action |
|---|---|
| **Repair and retry** | The same confirmed path; `auto` keeps A → B; a repeat failure returns here with the new error |
| **Generate manually** | Record `AI Image Acquisition Path: manual` in `design_spec.md §I`, mark rows `Needs-Manual`, hand off, author up to the Step 7 readiness gate |
| **Cancel the affected AI images** | Return to Step 4 as a post-confirmation override, remove the `ai` and dependent `slice` rows, revise their §IX jobs and lock rows to native text/SVG or confirmed non-AI sources, set the path `not applicable` when no AI rows remain; never add a new source or drop required content |
#### Quick exhausted-automation no-AI replan
Do not ask and do not enter Offline Manual: retain the filename, attempted path, concrete error, and replacement carrier for the completion report; remove the `ai` row, its dependent `slice` rows, and the manifest item; re-render `image_prompts.md` when other items remain, otherwise delete both manifest files; carry the communication job with native text/SVG or prepared non-AI assets; add no other source. Retaining AI imagery means repairing capability and a new Quick run.
Do not ask and do not enter Offline Manual. Retain the filename, attempted path, concrete error, and replacement carrier for the completion report. Remove the `ai` row, its dependent `slice` rows, and the manifest item; re-render `image_prompts.md` when other items remain, otherwise delete both manifest files. Carry the communication job with native text/SVG or prepared non-AI assets; add no other source. Retaining AI imagery means repairing capability and a new Quick run.
**Failure handling** (extends [`image-base.md`](./image-base.md) §3): on `auto`, two consecutive Path A failures fall to Path B without halting; if B also fails, Default enters the decision above and Quick the replan. A confirmed `api` or `host-native` path is retried once, never switched. If an alternate platform watermarks outputs (e.g. Gemini web), `scripts/gemini_watermark_remover.py` exists. **Guardrails**: never claim an image exists without a file at its path; `Needs-Manual` only on confirmed or explicit manual; status transitions are evidence-driven — a file permits `Generated`, exhausted Default automation stays `Failed` until a retry succeeds or the user chooses, exhausted Quick rows leave only through the replan.
**Failure handling** (extends [`image-base.md`](./image-base.md) §3): on `auto`, two consecutive Path A failures fall to Path B without halting; if B also fails, Default enters the decision above and Quick the replan. A confirmed `api` or `host-native` path is retried once, never switched. If an alternate platform watermarks outputs (e.g. Gemini web), `scripts/gemini_watermark_remover.py` exists.
**Guardrails**: never claim an image exists without a file at its path; `Needs-Manual` only on confirmed or explicit manual. Status transitions are evidence-driven: a file permits `Generated`; exhausted Default automation stays `Failed` until a retry succeeds or the user chooses; exhausted Quick rows leave only through the replan.
---
## 8. Common Issues & Variant Workflow
**Blank `Reference` on an existing AI row — declared inference** from a non-empty `Purpose` (stop and repair when `Purpose` is blank too): cover → `hero_page` + Primitive A or D; chapter divider → `hero_page` + D or A, chapter title in SVG; methodology / framework → `type: framework`, `local`; process → `type: flowchart`, `local`; before/after → `type: comparison`, `local`; team or lifestyle group → `type: scene`, `local`, `corporate-photo` or `warm-scene`; headshot → `local` + Primitive B, `corporate-photo`; big number or hero quote → `hero_page` + Primitive C, `embedded`; mood transition → `hero_page` + D, or `type: scene` when narrative.
**Blank `Reference` on an existing AI row — declared inference** from a non-empty `Purpose` (stop and repair when `Purpose` is blank too):
| Purpose | Inference |
|---|---|
| Cover | `hero_page` + Primitive A or D |
| Chapter divider | `hero_page` + D or A, chapter title in SVG |
| Methodology / framework | `type: framework`, `local` |
| Process | `type: flowchart`, `local` |
| Before/after | `type: comparison`, `local` |
| Team or lifestyle group | `type: scene`, `local`, `corporate-photo` or `warm-scene` |
| Headshot | `local` + Primitive B, `corporate-photo` |
| Big number or hero quote | `hero_page` + Primitive C, `embedded` |
| Mood transition | `hero_page` + D, or `type: scene` when narrative |
**Unsatisfactory images** — adjust the one dimension responsible, never rewrite the whole prompt:
@@ -310,7 +415,7 @@ Do not ask and do not enter Offline Manual: retain the filename, attempted path,
| Subject vague | Abstract Reference | Concrete nouns (verbs + objects) |
| Human depiction off-style | §5.2 cues diluted | Restate the rendering's facial detail, anatomy, texture, realism |
**Variant workflow**: set the item's `status` back to `Pending`, update its `prompt` in place, rerun the same resolved path (Path A reprocesses only that item; Path B regenerates it; Manual re-renders the sidecar); for several stylistic tries append items with distinct filenames (`cover_bg_v2.png`).
**Variant workflow**: set the item's `status` back to `Pending`, update its `prompt` in place, rerun the same resolved path (Path A reprocesses only that item; Path B regenerates it; Manual re-renders the sidecar). For several stylistic tries append items with distinct filenames (`cover_bg_v2.png`).
---
@@ -8,7 +8,7 @@ Neutral geometry and review rules for every image placement. This file calculate
## 1. Ownership and Inputs
Default Strategist owns resource choice, semantic role, crop boundary, and the preferred image/content or image/shape relationship; Image_Generator owns composition inside each generated bitmap for its planned container; Default Executor owns final SVG regions and geometry and may adapt the preferred relationship while preserving binding resource, content, and crop constraints; Quick's main agent holds all of these in one context. This specification and [`image-layout-patterns.md`](./image-layout-patterns.md) are the always-read geometry and composition vocabulary; [`svg-image-embedding.md`](./svg-image-embedding.md) owns embedding; [`svg-effects.md`](./svg-effects.md) and [`native-shape-authoring.md`](./native-shape-authoring.md) load on their executor-base triggers — effects beyond the everyday block, a contour beyond basic primitives, or Boolean geometry — so apply them when a construction reaches that far.
Default Strategist owns resource choice, semantic role, crop boundary, and the preferred image/content or image/shape relationship; Image_Generator owns composition inside each generated bitmap for its planned container; Default Executor owns final SVG regions and geometry and may adapt the preferred relationship while preserving binding resource, content, and crop constraints; Quick's main agent holds all of these in one context. This specification and [`image-layout-patterns.md`](./image-layout-patterns.md) load together on the executor-base `Any image` trigger as the geometry and composition vocabulary; [`svg-image-embedding.md`](./svg-image-embedding.md) owns embedding; [`svg-effects.md`](./svg-effects.md) and [`native-shape-authoring.md`](./native-shape-authoring.md) load on their own executor-base triggers, so apply them when a construction reaches that far.
### 1.1 Geometry notation
@@ -62,7 +62,7 @@ Every coordinated Stage-2 direction carries one complete `rendering: custom` can
|---|---|
| Length | One paragraph, 2-5 sentences |
| Axes covered | line / texture / depth / material / mood (same as preset files) |
| Catalog basis | Freeze every exact id from this index, then read only those files before applying one basis or synthesizing several |
| Catalog basis | Only the ids actually used, each owning a distinct contribution (selection per [`strategist.md`](../strategist.md) §d or [`quick-generate.md`](../../workflows/profiles/quick-generate.md) §2) |
```yaml
- image_rendering: custom
@@ -75,23 +75,7 @@ python3 scripts/image_search.py "<query>" --filename <name>.jpg --slide <slide_i
--orientation landscape --purpose background -o <project_path>/images
```
| Parameter | Default | Description |
|---|---|---|
| `query` (positional, required) | — | Simplified internally |
| `--query-variant` | — | Repeatable alias/translation; batch rows use `query_variants` |
| `--filename` (required) | — | Output filename matching the resource list |
| `-o / --output` | `.` | Output directory; manifest defaults to `<output>/image_sources.json` |
| `--slide`, `--purpose`, `--orientation` | `""`, `""`, `any` | Recorded slide id; `background` / `hero` / `side` / `accent`; `landscape` / `portrait` / `square` |
| `--min-width / --min-height` | `1200 / 800` | Downloaded-pixel floors; `--from-url` honors explicit lower overrides |
| `--provider` | chain | Pin one provider |
| `--strict-no-attribution` | off | Refuse CC BY / CC BY-SA |
| `--require-terms` | — | Repeatable identity gate; comma separates groups, `A|B` aliases |
| `--save-candidates` | off | Thumbnail mode: one ranked page of previews plus `review_sheet.jpg`, no original |
| `--max-candidates` | `8` | Page size; `0` = complete pool, debugging only |
| `--candidate-page` | `1` | Ranked page; page 2 starts at rank 9 |
| `--promote <candidate>` | — | Download exactly one selected original, enforce gates, write provenance |
| `--from-url <url>` | — | Manual replacement recorded as `license_tier: manual`; works without vision |
| `--manifest <path>` | `images/image_queries.json` | Override the manifest path |
Every flag, its default, and its exact behavior: [`image.md`](../scripts/docs/image.md) § `image_search.py`.
**Batch mode (≥2 web rows) — preferred**: write every row into `image_queries.json` and run one concurrent batch (the web sister of `image_gen.py --manifest`); add `--save-candidates` whenever the agent can inspect images:
@@ -110,9 +94,7 @@ python3 scripts/image_search.py --batch <project_path>/images/image_queries.json
} ] }
```
Required per item: `filename`, `query`, `status`; optional: `query_variants`, `candidate_page`, `slide`, `purpose`, `orientation`, `provider`, `strict_no_attribution`, `min_width`, `min_height`, `required_terms`. The runner revalidates every `Sourced` row against its file, dimensions, and manifest entry (drift → `Failed`), then searches all `Pending` / `Failed` rows concurrently (default concurrency 3, `--concurrency N` or `IMAGE_SEARCH_CONCURRENCY`; `1` for strict pacing on rate-sensitive free providers). Thumbnail mode writes `Needs-Selection` with `candidate_page`, `candidate_count`, `candidate_total`, `has_more_candidates`, `next_candidate_page`, and the `review_sheet` path, creating no image or provenance; to see the next page for one row set its `candidate_page` to `next_candidate_page`, reset only that row to `Pending`, and rerun. Promoting with the same `--batch` manifest moves the row to `Sourced`. Provider failures stay retryable `Failed`; clean exhaustion becomes `Needs-Manual`; status is saved after each completion.
**Ranking** orders provider metadata, never pixels, and must not be tuned into a taste engine: hard-reject invalid licenses and zero relevance; in best-only mode reject any candidate missing a `required_terms` group; in thumbnail mode keep strict matches first and admit a near match only when exactly one group is missing and the finding query still has strong relevance (marked `identity_evidence: visual-verification-required`, never auto-promoted); then metadata-verified identity in the title outranks a URL-only match; concrete query tokens match whole ASCII tokens (`office``officer`) and dominate generic words; orientation is a small penalty, no-attribution a small bonus, pixel count capped so a huge weak match cannot beat a smaller accurate one.
Required per item: `filename`, `query`, `status`; optional: `query_variants`, `candidate_page`, `slide`, `purpose`, `orientation`, `provider`, `strict_no_attribution`, `min_width`, `min_height`, `required_terms`. The runner revalidates `Sourced` rows, searches every `Pending` / `Failed` row concurrently, writes `Needs-Selection` with paging fields in thumbnail mode, and saves status after each completion; ranking orders provider metadata, never pixels, and is not a taste engine — exact runner and ranking behavior: [`image.md`](../scripts/docs/image.md).
**Suitability review** — a top hit is downloadable and token-relevant, not visually suitable (the reviewer receives only the locked row intent plus candidate sidecars/sheets, never the full planning or acquisition context):
@@ -134,32 +116,9 @@ Previews land in `images/candidates/<stem>/review/` with a thumbnail-only `candi
---
## 6. Manifest Format (`image_sources.json`)
## 6. Manifest (`image_sources.json`)
Each successful download appends or replaces one entry keyed on `filename`; the file is written atomically and is idempotent, and an unreadable existing manifest blocks the write.
```json
{
"license_verification": "provider metadata used; manual review recommended for external delivery",
"generated_at": "2026-05-01T12:17:59.856275Z",
"items": [ {
"filename": "team.jpg", "slide": "03_team", "purpose": "Leadership photo",
"search_query": "executive boardroom meeting", "matched_query": "leadership team boardroom",
"selection_method": "metadata-ranked", "orientation": "landscape",
"provider": "openverse", "stage": "all",
"title": "Untitled", "author": "",
"source_page_url": "https://www.rawpixel.com/...", "download_url": "https://...",
"license_name": "CC0", "license_url": "https://creativecommons.org/publicdomain/zero/1.0/",
"license_tier": "no-attribution", "attribution_required": false,
"width": 1024, "height": 683,
"metadata_dimensions": { "width": 4800, "height": 3200, "note": "upstream-reported size; actual downloaded file is smaller (likely a preview)" },
"attribution_text": "team.jpg — \"Untitled\" via Openverse — license: CC0 (...)",
"status": "sourced"
} ]
}
```
`matched_query` is the query or variant that found the asset; `selection_method` is `visual-thumbnail` after a reviewed promotion or `metadata-ranked` for the strict path; `width` / `height` are measured from the saved file (use them for layout) while `metadata_dimensions` appears only when the upstream claim differs; `license_tier` drives Executor's attribution; `attribution_text` is the canonical credit source, compressed only through §7's grammar; `stage` is `all` or `no-attribution-only`.
Each successful download appends or replaces one entry keyed on `filename` (written atomically; an unreadable existing manifest blocks the write). `license_tier` drives Executor's attribution, `attribution_text` is the canonical credit source, `width` / `height` are measured from the saved file, and `selection_method` records `visual-thumbnail` or `metadata-ranked`. Complete field list and example: [`image.md`](../scripts/docs/image.md).
---
@@ -171,7 +130,7 @@ For `license_tier: attribution-required`, every slide using the asset carries a
## 8. Failure Handling (web-specific)
Extends [`image-base.md`](./image-base.md) §3. No candidates from any provider or stage → `Needs-Manual` (suggest a more precise query or another provider; rerun without `--strict-no-attribution` only when the page may carry credit). No acceptable image on the current page with `has_more_candidates` → fetch `next_candidate_page` without changing the query or downloading. A page past `candidate_total` → pool exhausted, add a variant or move to the manual boundary. Some previews fail while another qualifies → keep the set. Every preview fails, or a provider/network failure remains → `Failed`, retried by a later batch. A promoted original fails its download/readability/dimension gate stay `Needs-Selection` and select another or change the query. A best-only download 403/404 → the dispatcher falls to the next ranked candidate. A keyed provider without a key → skipped. CLI exit: a prepared `Needs-Selection` set returns `0`; `Failed` or `Needs-Manual` returns `1`.
Extends [`image-base.md`](./image-base.md) §3 through the replacement ladder in §5: exhausted candidates and variants end in `Needs-Manual` with a reason, provider or network failures stay retryable `Failed`, and a promoted original that fails its gate stays `Needs-Selection`. Exit codes and per-case runner behavior: [`image.md`](../scripts/docs/image.md).
---
@@ -49,15 +49,10 @@ selecting one for the current deck:
## 3. How to use
| Active profile | Use |
|---|---|
| Default Generate | Strategist reads only this index while mapping three whole solution intents, freezes each custom direction's exact bases, then reads only their deduplicated detail files. Executor reads the confirmed preset file or exact custom references. |
| Quick Generate | The current main agent reads only this index while deciding, then reads the resolved preset or exact custom bases and keeps that one direction in active context without Design Spec/lock. |
**Resolution scope**: deck-wide (one mode per deck). The five are the catalog you select from; if the structure is genuinely mixed, pick the mode of the body pages and let pages vary within it, or use a warranted `custom` blend (§4). Default recommends and confirms; Quick decides directly.
**Resolution scope**: deck-wide (one mode per deck). The five are the catalog you select from; if the structure is genuinely mixed, pick the mode of the body pages and let pages vary within it, or use a warranted `custom` blend (§4). Default recommends and confirms under [`strategist.md`](../strategist.md) §d; Quick decides directly under [`quick-generate.md`](../../workflows/profiles/quick-generate.md) §2; Executor reads the confirmed preset file or exact custom references.
---
## 4. Editable projection and escape hatch — `custom`
`custom` is the editable behavior carrier: one deck resolves a single `mode`, and a multi-mode blend is one custom behavior whose paragraph states the executable cadence, not several modes. A custom may use catalog material in any way or none — carrying one preset unchanged is valid — and names only the bases it actually uses; freeze those ids from this index, then read only their files before writing the behavior. Default authors it for each Stage-2 direction under [`strategist.md`](../strategist.md) §d; Quick uses it only when a project-specific specialization or fusion serves the deck better than one preset and keeps the behavior in active context.
`custom` is the editable behavior carrier: one deck resolves a single `mode`, and a multi-mode blend is one custom behavior whose paragraph states the executable cadence, not several modes. A custom may use catalog material in any way or none — carrying one preset unchanged is valid — and names only the bases it actually uses. Default authors it for each Stage-2 direction under [`strategist.md`](../strategist.md) §d; Quick uses it only when a project-specific specialization or fusion serves the deck better than one preset and keeps the behavior in active context.
@@ -41,7 +41,7 @@ The hash is a synchronization receipt, not proof of semantic equivalence; never
| `<g data-pptx-replace-with="table">` | `<p:graphicFrame>` with `<a:tbl>` | bounds + `columns` or `rows` |
| `<g data-pptx-replace-with="chart">` | `<p:graphicFrame>` with `c:chart` / `cx:chart` + chart part + embedded workbook | bounds + `type`, plus chart data |
**Metadata placement and bounds**: one child `<metadata type="application/json">` (attribute `data-pptx-json` is read-compatible, not canonical); the marker's `data-pptx-replace-with` selects the schema. Provide `x`, `y`, `width`, `height` in metadata or as `data-pptx-x/y/width/height` on the group; omitted bounds are inferred from the fallback geometry (then marker/ancestor `translate` / `scale` apply), complete explicit bounds are absolute slide coordinates. `x` / `y` are finite and inside the 32-bit DrawingML range; `width` / `height` additionally resolve to at least one EMU (tables: per resolved row and column). JSON-first markers require all four bounds in metadata. Classic charts accept root `plot_area` (`x`, `y`, `width`, `height`, a positive rectangle inside the frame → `c:manualLayout`); ChartEx rejects it. `svg_quality_checker.py` validates marker kind, JSON, bounds/fallback, table rows/columns, chart type and data shape, the authority contract, and (SVG-first) baseline freshness.
**Metadata placement and bounds**: one child `<metadata type="application/json">`; the marker's `data-pptx-replace-with` selects the schema. Provide `x`, `y`, `width`, `height` in metadata or as `data-pptx-x/y/width/height` on the group (complete explicit bounds are absolute slide coordinates; omitted bounds are inferred from the fallback geometry); JSON-first markers require all four in metadata. Classic charts accept a root `plot_area` rectangle inside the frame. Ranges, read-compatible spellings, and what the checker validates: [`native-data.md`](../scripts/docs/native-data.md).
```xml
<g id="p03-revenue-chart" data-pptx-replace-with="chart">
@@ -66,22 +66,14 @@ The hash is a synchronization receipt, not proof of semantic equivalence; never
### Table schema — `ppt-master.semantic-table.v2`
Every payload carries that exact `schema`. Native tables are rectangular grids: `columns` for the optional header row, `rows` for body rows (shorter rows padded unless `strict_grid: true`; at most 1000 resolved rows and columns); `column_widths` / `row_heights` are finite non-negative relative weights matching the grid with one positive value; `header_rows` is an integer in range; `strict_grid`, `style.band_row`, and `bold` are JSON booleans. Exact repetition may be factored into `defaults.cell` / `defaults.paragraph` / `defaults.run` and kebab-case `cell_styles` selected by `cell_style` (precedence: cell defaults → named style → cell fields; object-valued `padding` merges, everything else replaces; `<style>` and `class` remain forbidden).
Every payload carries that exact `schema`; `columns` holds the optional header row and `rows` the body rows; `column_widths` / `row_heights` are relative weights. A cell is a string or an object with `text` (or `paragraphs` / `runs` for rich text), `fill`, `color`, `align` (`l` / `ctr` / `r`), `valign`, `bold`, `font_size`, `padding`, and per-side `borders` (each side is `{"style": "none"}` or `{"style": "solid", "color", "width"}`; a border without `style` is rejected); exact repetition may be factored into `defaults` and named `cell_styles`. Merged cells use positive `row_span` / `col_span` on the anchor with every covered cell as `{"merge_continuation": true}`. The complete field grammar: [`native-data.md`](../scripts/docs/native-data.md).
Cells accept `text`, `fill`, `fill_opacity`, `color`, `align` (`l` / `ctr` / `r`), `valign` (`top` / `middle` / `bottom`), `bold`, `font_size`, `padding` and side-specific `padding_*`, `border_color`, `border_width`, `borders`, `lang`, `anchor_center`, `horizontal_overflow`. Multi-paragraph text replaces `text` with a non-empty `paragraphs` list of strings or objects — empty paragraph strings are preserved as blank lines — (`align` plus exactly one of `text` or non-empty `runs`; runs carry required `text` and optional `bold`, `italic`, `underline`, `strike`, `color`, `font_size`, one-typeface `font_family`, `lang`, `alt_lang`); unknown fields, wrong types, empty runs, multi-typeface families, and unsupported colors fail. Per-side borders use `borders.left|right|top|bottom|diagonal_down|diagonal_up` as `{ "style": "none" }` or `{ "style": "solid", "color": "#RRGGBB", "width": <positive-px> }`, overriding a uniform `border_color` / `border_width` on style or cell. A missing `lang` derives `zh-CN` for CJK and `en-US` otherwise. `style.band_row: false` disables banding and materialized alternating fills. Typography mirrors the fallback: `style.font_family` and `style.font_size` from the drawn table text, `style.header_font_size` or per-cell `font_size` only where the fallback differs; with no explicit table font, Default uses the deck body family and anchor, Quick its active-context values.
**Hard rule — the table payload is complete**: a payload holding only `font_size` and a uniform border is not complete when the fallback draws a header band, row or column fills, first-column emphasis, non-uniform row heights, or sparse rules — every row, summary line, value, and cell style that must survive `--native-charts-and-tables` is in `columns` / `rows`, because fallback text is discarded on that route. Numeric or currency columns use cell objects with `align: "r"` (`text-anchor="end"` does not carry). **Merged cells — canonical rectangular contract only**: positive integer `row_span` / `col_span` on the anchor, every covered cell blank as `{"merge_continuation": true}` (a bare `{"text": ""}` is blank only while no `defaults.cell` adds fields), spans inside the grid and non-overlapping; the exporter writes `rowSpan` / `gridSpan` / `hMerge` / `vMerge`. CamelCase aliases, raw OOXML merge fields, top-level merge lists, nonblank covered cells, invalid spans, and overlaps fail.
**Hard rule — the table payload is complete**: every row, summary line, value, and cell style that must survive `--native-charts-and-tables` is in `columns` / `rows`, because fallback text is discarded on that route. A payload holding only `font_size` and a uniform border is not complete when the fallback draws a header band, row or column fills, first-column emphasis, non-uniform row heights, or sparse rules. Numeric or currency columns use cell objects with `align: "r"` (`text-anchor="end"` does not carry).
### Chart schemas
- **Category charts** `column`, `bar`, `line`, `area`, `pie`, `doughnut`, `pieOfPie`, `barOfPie`, `radar`: `categories` plus `series[].values`. Pie-family charts take exactly one series with per-slice colors; `hole_size` is doughnut-only, integer `10..90`, default `75`; no rotation field. Column/bar may set `series[].point_colors` (camelCase `pointColors` is read-compatible; length = values). `data_labels` is `true` or an object with `show_value`, `position`, `number_format`, `font_size`, `font_family`, `bold`, `color`, per-point `colors`, and `points` (zero-based `idx` plus optional overrides); positions: clustered column/bar `outside_end` / `inside_end` / `inside_base` / `center`, stacked `inside_end` / `inside_base` / `center`, line `above` / `center` / `best_fit`, area none.
- **Combo** — shared `categories` plus `plots[]` (`type: "column" | "line" | "area"`, own `series`, optional `axis: "secondary"`, optionally own `categories` / `category_numeric` when caches genuinely differ, and `series_indices` for imported identity — same-length unique non-negative integers forming one contiguous `0..N-1` range across plots) or typed `series[]` with per-series `type` / `axis` (adjacent compatible series share a plot). Area series may set `fill_opacity` (`0..1`; `fillOpacity` read-compatible); a line plot with `area_fill: true` exports as an area chart; line/area series may set `line_width` in SVG px (`lineWidth` read-compatible). Export layers areas below columns and lines.
- **Axes** — classic `axes` is a closed object of `category`, `value`, `secondary_category`, `secondary_value`, each with only `kind` (`text` / `date` / `value`), `position`, `visible`, `label_position` (`next_to` / `none` / `low` / `high`), `number_format`, `minimum`, `maximum`, `major_unit` (value axes), `reverse`, `major_gridlines`; single-plot `bar` takes `category` left/right and `value` bottom/top; pie-family rejects `axes`. `scatter` / `bubble` use `x` and `y` roles only (`kind: "value"`; `x.position` bottom/top, `y.position` left/right) with the same fields. Logarithmic scales, minor units/gridlines, crossing values, display units, and tick skipping are unsupported.
- **XY**`scatter` and `bubble` use `series[].x` + `series[].y` (`bubble` adds one `series[].size` / `sizes` per point), or `series[].points` as `[x, y]` / `[x, y, size]` tuples or `{x, y, size}` objects.
- **ChartEx**`treemap` / `sunburst` (`values` plus `levels[level][point]` or path-style `categories`; treemap `parent_label_layout: "banner" | "overlapping" | "none"` (default `overlapping`), PowerPoint labels only the top level and leaves), `histogram` (`values`), `pareto` / `waterfall` / `funnel` (`categories` + `values`; `waterfall` accepts `subtotals` / `subtotal_indices`), `boxWhisker` (`series[].values`, optional `series[].categories`). ChartEx writes no `<cx:title>` without a payload title (an empty title shows the series name), emits title/subtitle as companion text boxes, and takes `style.colors` / root `colors` into its color-style part. Non-Microsoft renderers show a limited subset.
- **Stock** — numeric Excel date serials in `categories` / `dates` plus exactly four series open / high / low / close (`series` with four entries or top-level `open` / `high` / `low` / `close`).
- **Supported types**: `column`, `bar` (`grouping`: `clustered` / `stacked` / `percentStacked`); `line` (`grouping`: `standard` / `stacked` / `percentStacked`; `line_style`: `line` / `lineMarker`, default `line` with no markers); `area` (`grouping`: `standard` / `stacked` / `percentStacked`); `pie`, `doughnut`, `pieOfPie`, `barOfPie`; `radar`, `radarMarkers`, `radarFilled`; `scatter` (`scatter_style`: `marker` / `lineMarker` / `line` / `smoothMarker` / `smooth`, default `marker`); `bubble`; `combo`; `treemap`, `sunburst`; `histogram`, `pareto`; `boxWhisker`; `waterfall`, `funnel`; `stock`. 3D aliases and `surface` are unsupported; exploded pie/doughnut, `map`, `heatmap`, `bullet`, and `gantt` are deferred and fail fast.
Supported `type` values: `column`, `bar`, `line`, `area` (each with `grouping`), `pie`, `doughnut`, `pieOfPie`, `barOfPie`, `radar`, `radarMarkers`, `radarFilled`, `scatter`, `bubble`, `combo`, `treemap`, `sunburst`, `histogram`, `pareto`, `boxWhisker`, `waterfall`, `funnel`, `stock`. Category charts take `categories` plus `series[].values`; XY charts take `series[].x` / `y` (bubble adds `size`); combo takes `plots[]` or typed `series[]`; ChartEx types take their own hierarchy or value fields. `data_labels`, `axes`, `axis_titles`, `show_legend` / `legend_position`, companion text (`caption`, `source`, `note`), and `style.colors` are the chrome fields. 3D aliases and `surface` are unsupported; exploded pie, `map`, `heatmap`, `bullet`, and `gantt` fail fast. Every field, enum, and range: [`native-data.md`](../scripts/docs/native-data.md).
**Chart chrome, typography, and color**: SVG-first metadata matches the fallback chrome; JSON-first owns it. Metadata sizes use SVG px (`1px = 0.75pt`); `style.font_family` and `title_font_size`, `subtitle_font_size`, `axis_font_size`, `axis_title_font_size`, `legend_font_size`, `note_font_size` are required only when native must preserve typography an SVG-first fallback cannot supply unambiguously (JSON-first never infers from its preview). A string or unbounded-object `title` becomes native `c:title` (`subtitle` line two); a title object with complete `x`, `y`, `width`, `height` becomes a companion text box (partial bounds or `subtitle` fail); `name` names the object; `title`, `subtitle`, and axis-title objects accept `text`, `font_size`, `font_family`, `color`; the checker rejects SVG-first title/axis text absent from the fallback. Axis titles are explicit via `axis_titles` (`category`, `value`, `x`, `y`, `secondary_value`) or the root aliases `category_axis_title`, `value_axis_title`, `x_axis_title`, `y_axis_title`, `secondary_value_axis_title`; `show_value_axis_labels: false` hides numeric tick labels (e.g. a radar without radial coordinates); native legends are opt-in via `show_legend: true` and `legend_position` (`bottom` default; `top` / `left` / `right`). SVG-first parity reads the fallback literally — `style.axis_color` equals the dominant axis/grid stroke, numbers match in written form (`286.20``286.2`), and marker text that is not a category, data label, axis label, or legend entry needs a companion entry. Companion text (`caption`, `source`, `note`, `notes`, `footnote`, `footnotes`) exports as editable text boxes — strings or objects with `text`, `x`, `y`, `width`, `height` (slide coordinates), `font_size`, `color`, `align`, `bold`; use it for captions, sources, center labels, and annotations, and `data_labels` for point values. `style.colors` sets series colors (treemap/sunburst tile palette in order); the exporter writes explicit chart-area fill, plot-area fill, axis, gridline, and label colors (SVG-first infers them from the largest panel `<rect>`, text, and strokes; JSON-first from JSON or stable defaults), overridable under `style` with `chart_area_fill`, `plot_area_fill`, `text_color`, `axis_color`, `grid_color` (`"none"` for transparent); generated payloads use uppercase `#RRGGBB`, with `#RGB`, `rgb()`, and CSS names normalized. Negative bars keep the series fill.
**Chart chrome and color**: SVG-first metadata matches the fallback chrome and reads it literally — the dominant axis/grid stroke becomes `style.axis_color`, numbers keep their written form, and marker text that is not a category, data label, axis label, or legend entry needs a companion entry; JSON-first owns its chrome. Generated payloads use uppercase `#RRGGBB`. Negative bars keep the series fill.
**Forbidden — replacement marker transforms**: no rotate, skew, or matrix on table/chart groups; translate/scale only, because native frames cannot carry arbitrary SVG transforms.
@@ -21,7 +21,7 @@ python3 ${SKILL_DIR}/scripts/shape_boolean_svg.py render <svg-file> \
- `render` prints one compact atomic `<g data-pptx-authoring="preset">` with preset, frame, adjustments, and base paint written once and registry-generated visible paths as children; **Hard rule — batch after selection**: after selecting two or more objects for one page or template, use `render-batch --input -` so their independent fragments are validated and emitted in one stdout round. `--frame x y w h` is in the coordinate space where the fragment is inserted (group-local inside a `<g transform>`). Insert the fragment unchanged through the normal page edit; never redirect helper output into `svg_output/`.
- Paint accepted: `none` or six-digit solid HEX fill/stroke, optional channel opacity, stroke width, cap, join, and one shape-only filter id. Gradient or pattern paint stays ordinary SVG. Connector-family presets require `--object-kind connector`, `--fill none`, and a visible stroke, and export as unconnected `p:cxnSp`.
- **Hard rule — atomic and helper-owned**: never write `data-pptx-prst`, frame, adjustment, or registry paths by hand, never edit a direct path, and rerun the helper when preset, frame, adjustment, paint, or filter changes. Keep the fragment top-level without `data-pptx-bounds` when standalone (its `data-pptx-frame` owns geometry); put labels or decorations beside it in a separate bounded parent group, never inside. Moving, scaling, rotating, or flipping the whole group is fine; zero-scale and shear are not, the transformed frame stays inside DrawingML's coordinate range, and stroke width stays inside its line-width range. Keep the helper's exact space-separated ordinary-decimal `data-pptx-frame` spelling; compact authoring accepts no alternate numeric spelling. Keep paint and opacity off ancestor groups (the checker warns).
- **Hard rule — atomic and helper-owned**: never write `data-pptx-prst`, frame, adjustment, or registry paths by hand, never edit a direct path, and rerun the helper when preset, frame, adjustment, paint, or filter changes. Keep the fragment top-level without `data-pptx-bounds` when standalone (its `data-pptx-frame` owns geometry); put labels or decorations beside it in a separate bounded parent group, never inside. Moving, scaling, rotating, or flipping the whole group is fine; zero-scale and shear are not, the transformed frame stays inside DrawingML's coordinate range, and stroke width stays inside its line-width range. Keep the helper's exact space-separated ordinary-decimal `data-pptx-frame` spelling; compact authoring accepts no alternate numeric spelling. Keep paint and opacity off ancestor groups (the checker warns). Helper output may contain consecutive duplicate vertices (`L 440 449.33 L 440 449.33`); they are the registry path as printed and stay untouched — cleaning them up is an edit to a direct path and fails the check.
- `shape_boolean_svg.py` consumes closed `path` / `polygon` / `rect` / `circle` / `ellipse`, one unfiltered compact preset, or supported horizontal direct `<text>` with a resolvable OpenType face (`--font-dir` adds roots; text becomes glyph geometry). The first `--source` supplies result paint and explicit paint flags override only their named channels; for `subtract` every later operand is removed from it. Coordinates are baked into root space: insert the stdout paths at the primary operand's z-order with no extra transform. `union` / `combine` / `intersect` / `subtract` emit one `<path>`; `fragment` emits `<id>-1`, `<id>-2`, … in top/left/bottom/right/area order, each a separate shape. Results use nonzero winding and never `fill-rule`, `clip-rule`, `clip-path`, `mask`, or Merge Shapes metadata; operands that depend on even-odd fill, clipping, or masking fail closed. Never use it on mirror/preserve source structure.
**Mandatory — complete vocabulary before contour selection**: [`preset-shape-vocabulary.md`](./preset-shape-vocabulary.md) is read completely before contour work (Generate: with the executor core before the first page; Create Template: as soon as `replication_mode` resolves to `standard` or `fidelity`; never for `mirror`); a filtered lookup cannot replace it. Reread only after context invalidation or a known file change.
@@ -30,7 +30,7 @@ python3 ${SKILL_DIR}/scripts/shape_boolean_svg.py render <svg-file> \
**Hard rule — contour before encoding**: choose the page-fit contour from the intended job and active visual system across the full vocabulary before any syntax. Rectangle, rounded rectangle, circle, and ellipse are not an earlier tier because SVG spells them short; easier syntax never selects a contour.
**Default — exact page-fit geometry before generic neutrality (may override when neutrality itself communicates the page)**: resolve relationship fit when the content carries direction, sequence, membership, hierarchy, convergence, reveal, or contrast; independently resolve page-field / carrier fit from ownership, focal hierarchy, boundary strength, and the deck's edge / opening language (`Structure=no` removes only relationship topology). Choose a plain primitive, uniform grid, or no drawn carrier only when that lack of inflection gives the reader a concrete benefit or avoids a false inference — and before it wins, name the strongest fitting native or compound alternative and why its inflection would add nothing, mislead, weaken hierarchy, or conflict with the job. Quick speed, restrained style, readability, equal importance, precedent, and shorter syntax alone never qualify.
**Default — exact page-fit geometry before generic neutrality (may override when neutrality itself communicates the page)**: resolve relationship fit when the content carries direction, sequence, membership, hierarchy, convergence, reveal, or contrast; independently resolve page-field / carrier fit from ownership, focal hierarchy, boundary strength, and the deck's edge / opening language (`topology=no` removes only relationship topology). Choose a plain primitive, uniform grid, or no drawn carrier only when that lack of inflection gives the reader a concrete benefit or avoids a false inference — and before it wins, name the strongest fitting native or compound alternative and why its inflection would add nothing, mislead, weaken hierarchy, or conflict with the job. Quick speed, restrained style, readability, equal importance, precedent, and shorter syntax alone never qualify.
**Hard rule — style does not narrow capability**: the visual system weights contour fit and controls paint, stroke, texture, density, and recurrence; it never removes primitives, presets, composition, Boolean, or necessary freeform from consideration. Style-specific syntax guidance applies only to the named style-defining mark.
@@ -66,7 +66,7 @@ python3 ${SKILL_DIR}/scripts/shape_boolean_svg.py render <svg-file> \
### 2.1 Topology assembly and compound page geometry
**Trigger**: after the page's communication / slot job, composition anchors, and any [`executor-structure.md`](./executor-structure.md) topology are resolved, before writing coordinates — at every active granularity. For `Structure=yes`, assemble the resolved topology without changing it, with [`topology-assembly.md`](./topology-assembly.md) as material; for every page, resolve the page-scale geometry move carrying its background field, content zoning, focal hierarchy, or reading path. Before repeating stacked cards or uniform equal columns, compare a page-field, outline, nesting, or continuity construction and the relevant family's exact members; the first workable arrangement's readability does not close this gate, and the gate creates no decoration requirement.
**Trigger**: after the page's communication / slot job, composition anchors, and any [`executor-structure.md`](./executor-structure.md) topology are resolved, before writing coordinates — at every active granularity. For `topology=yes`, assemble the resolved topology without changing it, with [`topology-assembly.md`](./topology-assembly.md) as material; for every page, resolve the page-scale geometry move carrying its background field, content zoning, focal hierarchy, or reading path. Before repeating stacked cards or uniform equal columns, compare a page-field, outline, nesting, or continuity construction and the relevant family's exact members; the first workable arrangement's readability does not close this gate, and the gate creates no decoration requirement.
| Pass | Action | Result |
|---|---|---|
@@ -89,7 +89,7 @@ python3 ${SKILL_DIR}/scripts/shape_boolean_svg.py render <svg-file> \
At topology scale, independent pieces, one body with dividers, overlapping siblings, fitted joints, intentional gaps, and retained `fragment` regions are common strategies, not a set; never map a topology name to a shape list or infer equal size or spacing.
**Default — running deck geometry check (may override for literal pages or isolated prototypes)**: after each page retain `page job → composition move → contour / edge language` (plus `relationship → topology` for `Structure=yes`) and compare before the next; repeat only for the same job / relationship or deliberate continuity — section, equal weight, style, and precedent are insufficient. No artifact, no second pass.
**Default — running geometry signature (may override for literal pages or isolated prototypes)**: the *geometry signature* of a page is the retained line `page job → composition move → contour / edge language` (plus `relationship → topology` for `topology=yes`). After each page retain its signature and compare it with the previous pages' before drawing the next; repeat a signature only for the same job / relationship or deliberate continuity — section, equal weight, style, and precedent are insufficient. The final carrier-receipt review reads these signatures back. No artifact, no second pass.
**Boolean decision gate**:
@@ -0,0 +1,198 @@
# Planning Core
The planning craft shared by both Generate runtimes: what a deck plan decides before any page is drawn, and how to decide it well. Default Strategist reads it in the Step 4 batch and persists the results in `design_spec.md` / `spec_lock.md` ([`strategist.md`](./strategist.md) owns the confirmation stages and artifact grammar); Quick reads it in §2 and keeps the same decisions in active context ([`quick-generate.md`](../workflows/profiles/quick-generate.md) owns its commands and boundaries). "The page brief" below means §IX in Default and the transient page decision in Quick.
Everything here is a plan-only or Reference decision under [`ownership.md`](../../../docs/rules/ownership.md): content, relationships, roster, rhythm, identity anchors, and resources bind; macro composition, motif, and pattern suggestions are References the Executor adjusts freely.
---
## 1. Communication Contract
Six answers describe what the deck must do. Default seeds them as Stage-1 recommendations the user may retain, edit, or clear; Quick resolves them from the request and sources without asking.
| Field | Question it answers |
|---|---|
| `audience` | Who exactly must receive this communication, and what do they already know / care about? |
| `communication_intent` | What must the presentation accomplish? It may combine several purposes and state priority or sequence. |
| `audience_outcome` | What observable change means the communication succeeded — what will the audience know, understand, believe, decide, or do? |
| `core_message` | Which claim(s), decision ask(s), or action(s) must land even if little else is remembered? |
| `delivery_context` | What is primary — presenter-led, reader-led, hybrid (which leads), or recorded/self-running (no live presenter; narration, timing, transitions, playback)? What secondary use, occasion, and time constraint remain? One open field, never an enum. |
| `artifact_afterlife` | What must the file support afterward — review, approval, audit, archive, hand-off, reuse, or nothing? |
**Communication intent is open-ended**: *inform / explain / persuade / decide / align / teach / report and account / mobilize / record and hand off* are prompts, never a checkbox list or a `primary_job`; several purposes keep their relationship in prose ("report progress and expose risk first; then obtain a decision"). The contract is not the narrative mode: intent says what change is needed, `mode` is one Stage-2 way to organize the argument.
Translate every purpose named in the intent into an outline obligation (a reasoning checklist, not a classifier; preserve the user's priority and sequence):
| Intent named in the prose | Outline must enable |
|---|---|
| Inform | Relevant facts with enough context to know why they matter |
| Explain | Mechanism, relationship, cause, or meaning made traceable |
| Persuade | Claim + evidence + material objections / alternatives |
| Decide | Explicit decision ask + options + criteria + trade-offs + consequence of delay |
| Align | Shared frame + priorities + owners + next steps |
| Teach | Prerequisites + sequence + worked application / check for understanding |
| Report and account | Baseline + progress + variance + evidence + risk + ownership |
| Mobilize | Urgency + agency + concrete action + immediate next step |
| Record and hand off | Context + decisions + status + owners + unresolved items + durable provenance |
---
## 2. Reading Mode
`text` / `balanced` (default) / `presentation`, kept under the compatibility key `delivery_purpose` (lock key `consumption_mode`). **Reading mode controls information carriage, not communication intent**`delivery_purpose` is the compatibility key; the body baseline is a consequence:
| Reading mode | Primary carrier | §IX page grammar | Granularity / rhythm | Speaker notes |
|---|---|---|---|---|
| `text` · read-close | page / document | complete assertions, short prose paragraphs, captions, tables, and necessary detail; bullets only for genuinely parallel or ordered items | fewer, fuller pages; leans `dense` | supplemental context, not a substitute for missing page logic |
| `balanced` · business (default) | page + presenter | one primary claim with concise explanation, structured evidence, or a necessary list | moderate granularity; mixed rhythm | interpretation and transitions |
| `presentation` | presenter + visuals | one claim per page, keywords / short phrases, a large visual or hero number; no paragraph dumps or prose compressed into fragments | more, sparser pages; leans `anchor` / `breathing` | carries explanation, transitions, and supporting detail |
With notes disabled the last column is unavailable: every required meaning stays on the page or the confirmed presenter channel. Derive the initial mode from `audience`, `delivery_context`, and `artifact_afterlife`: asynchronous review, reference, approval, audit, and leave-behind lean `text`; presenter-led projection, large rooms, launches, and classrooms lean `presentation`; hybrid review / roadshow leans `balanced`, and `balanced` when live projection and durable afterlife both matter. A confirmed `presentation` supports afterlife through notes, appendix pages, captions, and visible sources rather than crowding slides. A `presentation` deck and a `text` deck from the same source and contract must differ in page grammar, count, text volume, visual burden, density, rhythm, and notes — not only in font size; page count stays the user's call. Default records it as **Reading Mode** in `design_spec.md §I` (lock key `consumption_mode`) and Quick keeps it in context; `page_rhythm` leans are a bias, not a quota; preservation paths honor it only in styling and notes.
---
## 3. Content
**Default — open `page_count` as a narrow range (may override when an exact count is supplied or locked)**: narrow enough to judge at a glance. After Stage 1 choose one exact count from source volume, audience outcome, delivery context/afterlife, and reading mode, then author the complete §IX roster; *exactly*, *1:1*, or preservation fixes it. After Gate 1 and any refine approval, the roster's ids, count, and order are invariant — Executor never adds, drops, merges, splits, or reorders without Design Spec repair or reconfirmation.
**Material divergence**: how closely the deck follows the source versus how freely it reshapes it — a spectrum from *stay close* (track structure and wording, tune for clarity) through *balanced* (re-architect into a narrative under the chosen mode, keeping all substance) to *free* (regroup, reframe, expand, connect, invent structure and transitions). Default reads it from the user's own words in the `content_divergence` field; Quick reads it from the request; blank is a balanced default. **Hard rule — facts stay sourced however free the user asks**: divergence develops what is in the source and never licenses outside facts, figures, or claims — that is [`topic-research`](../workflows/stages/topic-research.md)'s job; `mode` and divergence are orthogonal.
**Fact provenance contract**: when `sources/*.facts.json` exists, read it before outlining and cite its stable `fact_id` values as `Fact IDs: F001, ...` on every §IX page that uses an external quantitative or factual claim; invented demo KPIs, ratios, targets, and roadmap numbers carry `Data class: scenario` and never a `fact_id`. One page may hold both classes as long as each number's class is unambiguous.
**Per-block expression**: the semantic relationship chooses the form — prose for cause, argument, interpretation, and narrative continuity; bullets or numbers only for genuinely parallel, ordered, or enumerable items, never because copy is long or a template exposes a list slot. In `presentation`, distill one assertion and move explanation into enabled notes (or keep it on the page when notes are off). Source texture is a secondary cue. Default writes §IX at the confirmed `design_spec_depth`: at `complete` depth write usable phrasing into §IX; at `brief` depth one bullet per block in the phrasing that fits, leaving page copy to authoring — neither is a skeleton: every claim, fact, relationship, and qualifier is present, and written wording is preferred wording unless literal preservation applies (Executor adapts under [`executor-base.md`](./executor-base.md) §2.1). §IX is the page brief at the confirmed depth; Executor retains it with the lock until context invalidation. Quick writes the same brief in context at whichever depth authoring needs.
**Mandatory — information model, not source object type**: qualitative `order` / `link` / `parent` / `membership` / `contrast` / `overlap` is written on the page's §IX `Relationships` line (its units and their source-stated relationship, or `none`; no catalog key, grammar atom, coordinate, shape, or named model — Executor decides at runtime whether geometry carries it); values, dates, or durations that determine geometry are a Chart; row header × column header facts are a Table, each compared against the complete loaded vocabulary.
**Mathematical and hyperlink content**: Record every source-backed equation under `Mathematical content` in the applicable §IX block as a LaTeX body without `$…$`, `$$…$$`, `\(…\)`, or `\[…\]` delimiters — never classified as inline or block, never invented for decoration, and never a policy, manifest, PNG, §VIII row, or lock entry; Executor owns the text-versus-native decision and returns here only for a content-level correction, including when the documented Microsoft 365 input profile cannot preserve the planned content. Record every explicit or source-backed link as the linked text/object plus its exact absolute URI or 1-based same-deck slide target — never guessed, never carrier-selected, never a manifest or lock entry; Executor authors it under [`native-hyperlinks.md`](./native-hyperlinks.md).
---
## 4. Roster and Rhythm
**Page rhythm**: give every page one tag — `anchor` (structural: cover, chapter, TOC, ending), `dense` (information-heavy; the baseline), or `breathing` (a low-density pause) — as a body-content frame and density judgment per page rather than one uniform fill; the tag is what breaks the uniform card-grid feel, and leans by reading mode are a bias, not a quota.
**Mandatory — whole-roster rhythm check**: while composing §IX, compare neighbors and section arcs — chapter entries visibly reset; same-density, same-resource, or same-relationship runs are intentional sub-arcs; a repeated motif carries a continuity job; any visible-state sequence keeps a recognizable map while its next change is legible; each section follows a mode-fitting progression (including framework → explanation/evidence → judgment/action when it serves); the final arc resolves the objective before a genuine ending lowers load. Same section, equal density, one style, and precedent establish no sub-arc. Repair roster, `Composition`, and `page_rhythm` in place; preserve intentional continuity, legitimately all-`dense` material, and 1:1 order; add no filler — a `breathing` page marks a real pause and must stand alone. No field, lock row, artifact, or second pass.
**Cover impact is mandatory**: give `P01` one concrete hook from the source's strongest claim, metaphor, number, moment, or conflict plus one optional composition Reference in ordinary words (a distilled display phrase may carry the cover while the complete title stays a native subtitle; with no suitable image, a native-SVG hook). The hook binds; the composition is a Reference. `P01` stays `anchor`, defaulting away from generic content-page templates unless content, user, or template makes a card grid, agenda, or equal-weight columns the clearest cover. Beautify preservation is exempt.
**Closing impact (only when the deck closes)**: for a genuine conclusion, CTA, or final takeaway, name the binding takeaway plus a recommended composition; never an information-empty "Thank you", contact-only slide, or cover reprise (an explicit contact/event CTA may serve), and never an invented closing page. Preservation is exempt.
**Reference — a starting sketch, never a constraint**: a §IX `Composition` line names the macro relationship the page's content suggests (one focal claim, equal comparison, dominant evidence + takeaway, parallel sequence, core + surrounding forces, wide visual + explanation) in ordinary words; Executor owns the structure and geometry that realize it (its layout-structure vocabulary lives in [`executor-base.md`](./executor-base.md) Page Expression Core) and adjusts or replaces the line freely after reading the page. Never write element-level sizes or coordinates into §IX.
Once the roster and planned resources are known, recommend a cross-page motif or element family when it can carry identity or meaning — title/corner ornaments, a directional contour, an opening, a line lattice, an oversized numeral — recording its continuity job and reuse mode (Default: §III `Theme`, mentioned only in the §IX `Composition` blocks that benefit; Quick: the transient motif system in context); Executor owns its geometry and may decline it; no motif field, lock row, or quota.
---
## 5. Resources
**Default — resource need from the roster (may stay implicit when a page's need is obvious)**: while composing the roster, decide which pages need a prepared image, lettering, or illustrated-icon resource — the jobs only a prepared file can serve — and derive the resource rows (Default §VIII; Quick the operational manifests) from that need. The page's carrier mix itself (background, text, native geometry, imagery, icons, visualizations and their weights) is Executor's page decision and is never planned. Plan an image, lettering, or illustrated-icon resource only when the page assigns it a plausible job. Macro composition stays Reference; resource identities and explicit requirements keep their authority.
**Hard rule — native construction stays downstream**: record each page's relationships, resource roles, and any useful macro composition or visual-system Reference; never inventory or bind a preset, primitive, Connector, Boolean/freeform operation, coordinates, or authoring method. A technique may appear only as optional inspiration inside a macro Reference.
| Capability | Opportunity signal |
|---|---|
| Image composition | Image-as-canvas, editorial crop, collage, cutout, or meaningful focus / comparison / evidence units carry the page better than an adjacent rectangle |
| Composable illustration family | Pages benefit from coherent reusable title/corner ornaments, dominant anchors, supporting figures, compact illustrated-icon cues, or accents mixing with text, shapes, photos, or lettering |
| AI decorative lettering asset | Any stable display string — a complete long or multi-line title, cover hook, chapter word, place or product name, dish or exhibit name, year, hero number, pull quote, motif word — reads better with a material, dimensional, hand-rendered, or illustrative treatment than as ordinary text |
| Motion | A section/state change or continuity across adjacent pages, or a reveal / emphasis / movement order within a page, clarifies sequence, causality, comparison, or hierarchy |
Every communication job maps to a prepared resource or an information model; this menu never satisfies the Executor's per-page topology decision:
| Communication job | Prepared resource or information model |
|---|---|
| Real subject, place, product, evidence, atmosphere, or scene benefits from visual grounding | Supplied/extracted, web, AI, or sliced image |
| Reusable title/corner decoration, a dominant illustrated anchor, supporting figure, or accent strengthens compositions | A coherent AI illustration family as transparent `slice` assets, combined freely with other carriers |
| A compact semantic cue clarifies a category, process, KPI, state, or navigation item | Prepared project-local SVG/emoji icon, an illustrated-icon `slice`, or both |
| A real company, product, service, or social brand must appear as itself | The exact mark from `simple-icons` or supplied assets; not a user-facing library choice |
| Values, categories, time, weights, or duration determine mark geometry | Value-driven chart |
| Sequence, hierarchy, role, region, or relationship determines topology | Qualitative structure |
| Rows, columns, cells, headers, merges, alignment form the model | Cell-grid table |
| A stable display string reads better with a material, dimensional, hand-rendered, or illustrative treatment | Decorative lettering per the rule below, as an image beside a native title |
### 5.1 Image source
| Source id | Approach | Use when |
|---|---|---|
| `none` | No images | No source owns a meaningful communication job |
| `provided` | User-provided assets | Existing images carry factual, brand, product, or narrative authority |
| `ai` | AI-generated | Invented or deliberately stylized scenes, illustrations, backgrounds, metaphors, decorative lettering, or another generated treatment |
| `web` | Web-sourced | Named or evidence-bearing real-world subjects that must appear as themselves, plus generic photographic mood, background, or scene jobs |
| `placeholder` | Deferred | The image is required but will be supplied later |
**Hard rule — credentials never decide image need**: a missing `IMAGE_BACKEND`, host generation, or stock credential never justifies `none` or the deletion of a planned web role; do not inspect configuration or probe a provider — acquisition (Default Step 5; Quick §2 resource preparation) is the first capability check. When `ai` is included, preserve an explicit user path instruction, otherwise recommend `auto`.
**Default — visual grounding before `none` (may override when the full-roster review finds no image job)**: honor an explicit no-image requirement; otherwise, when the audience must recognize, experience, compare, or choose an externally verifiable subject, place, product, or setting, plan `provided` / `web`, and plan `ai` where invented or stylized expression materially improves a visual job. Mixed sources serve different roles; a rendering candidate resolves how imagery looks, never whether a real subject appears as itself.
**Mandatory — per-image source decision**: outside Image to PPTX, decide each page image's source separately — supplied/extracted when it carries authority, web when an externally verifiable subject must appear as itself, AI when invented or stylized expression matters more than documentary identity; mixed sources are normal. A visual style, `Illus.` propensity, or rendering resolves how imagery looks, never its source: a named place, building, product, artwork, or person stays a web/supplied candidate however illustrative the deck, and a subject deliberately not shown as itself is stated with its reason in the final report.
**Mandatory — image treatment and subject layers**: choose per image: `none`; a native SVG treatment (crop viewport, opacity, frame, scrim, shadow); or a prepared derivative. A subject that crosses native content requires a clean full-canvas base plus a registered RGBA cutout (`#A2-03`). A prepared derivative never overwrites its source, never becomes another derivative's parent, never has its output equal its input, and is derived only after that source is itself final. Where fidelity forbids adding a label, symbol, line, or geometry cue to a new color encoding, preserve the source encoding instead.
**Mandatory — illustration families and illustrated icons**: when the resource-need review selects a composable family, resolve it before authoring — elements may repeat as title/corner chrome or vary as anchors, figures, and accents on any page — batching compatible elements through Illustration Sheets under [`image-generator.md`](./image-generator.md) §4.3 and splitting only for geometry, detail, or quality conflicts. When it selects illustrated-icon cues and AI is not forbidden, prepare them as transparent slices under `images/`; grouping, count, and coexistence with SVG icons follow page fit, with no quota and never as SVG inventory.
**Reference — decorative-lettering candidates**: when AI is not forbidden, any display string in the frozen roster is a candidate on two questions — is the wording stable, and could an artistic treatment communicate better than native type? Page role, length, line count, kind of noun, and resolved style never pre-filter: a cover hook, chapter word, place or product name, dish or exhibit name, year, hero number, pull quote, or motif word all qualify, a two-character mark and a two-line lockup equally, and a phrase is never trimmed to feel more "wordmark-like"; type over photography or a busy field is often exactly where native text reads pasted-on. Compare candidates inside the whole page and deck mix and select any coherent set whose treatment wins; selecting none is valid without explanation. For each selected mark keep a native title wherever the page needs a searchable, selectable, or outline-visible heading — the lettering is the display layer, the editable wish is answered by the native layer. Prepare the set without a separate request: exact approved strings, one ordinary AI item or grouped Illustration Sheets with transparent slices, grouped by character and treatment, with role, placement/background relationship, weight, and energy given to the model under `image-generator.md` §5.3's controlled-default/high-expression boundary; chrome and body stay native. Never invent or alter copy or create lettering to justify AI.
### 5.2 Chart and Table references
**Reference — Chart/Table vocabularies**: the loaded vocabularies list what can be selected; they rank nothing, and custom objects and qualitative composition stay outside them. Choose at most one flexible `family/key` per page (children and qualitative relationships stay in §IX), keep `no-template-match` in §IX when none fits (never serialized), and validate every selected reference before the lock, correcting a failed selection by re-reading the complete vocabulary/registry:
```bash
python3 skills/ppt-master/scripts/visualization_recall.py validate \
<family>/<key> [<family>/<key> ...]
```
**Native-ready boundary**: give every independent data chart and pure text-grid table a unique page-local `kebab-case` key and a `<key>=yes|no` native-ready decision — `yes` by default, `no` only when [`native-data-interface.md`](./native-data-interface.md) §2 cannot express the object; qualitative compositions and incidental microvisuals stay unlisted. Default writes §VII and the `Native-ready` map; Quick keeps the key and decision in context.
---
## 6. Visual System
**Mode and visual style**: one communication mode ([`modes/_index.md`](./modes/_index.md)) and one visual style ([`visual-styles/_index.md`](./visual-styles/_index.md)) per deck, each a preset or a `custom` with executable behavior prose; style carries no color and never narrows carrier eligibility. Default authors three directions under [`strategist.md`](./strategist.md) §d; Quick resolves one directly.
### 6.1 Color
**Reference — not a constraint**: no universal palette — user / brand → active template → project-specific proposal from content and style; 60-30-10 is the starting proportion, body contrast at least 4.5:1 (WCAG AA), hue count follows encoding, style, and natural assets; how color is *used* on a page (fields, gradients, accent placement, mood) is Executor's craft. `scripts/config.py` industry anchors (finance/business navy `#003366`, technology bright blue `#1565C0`, healthcare teal `#00796B`, government red `#C41E3A`) and polarity ramps (positive `#2E7D32 → #4CAF50 → #81C784`, warning `#F57C00 → #FFA726 → #FFD54F`, negative `#C62828 → #EF5350 → #E57373`) are recall aids, never default locks; brand identities come from a Brand/Deck workspace, never a memorized list. The plan owns reusable positive / warning / negative roles; Executor derives tints, shades, alpha, gradients, and effects.
**Anchor recurring semantic roles, not every paint** (Default locks them; Quick keeps them as context anchors): add neutral roles the style and page plan give a stable meaning — `surface`, `grid`, `scrim`, `overlay`, `block-shade` — and leave page-local tints, gradient stops, shadow/glow colors, and one-off tones to execution, promoting one only when it becomes a reusable named role.
| Style trait | Extra neutral tiers to anchor |
|---|---|
| Layers panels / charts (e.g. `data-journalism`, `swiss-minimal`) | `surface` (panel lift), `grid` (hairline, lighter than dividers) |
| Text over imagery / dark field (e.g. `photo-editorial`, `glassmorphism`, `dark-tech`) | `scrim` / `overlay` for legibility |
| Print / hand-drawn fills (e.g. `chalkboard`, `zine`) | `block-shade`, one step off the field |
### 6.2 Typography
**Family selection**: user/template typography is authoritative. Delivery target: an explicit user/template target first, otherwise Windows Microsoft PowerPoint (owner: [`shared-standards-core.md`](./shared-standards-core.md) §4.1) — the authoring host's installed fonts never select a face; name concrete faces installed or approved on that target; at most four families; a brand/web face leads only after user-confirmed installation, otherwise export a safe face and keep it as a Design Spec reference (fonts are not embedded; CSS tails are preview aids, not PowerPoint fallbacks). Avoid near-equivalent splits (YaHei↔PingFang, SimSun↔Songti, Arial↔Helvetica↔Segoe UI, Times↔Times New Roman). Fonts in one deck form contrast (different family, weight, or proportion) or concord (one family throughout); across the direction set include both a concord and a contrast pairing unless the user or template fixes the stack, and never default to title = body without a reason.
**Reference — PPT-safe faces (recall, not a whitelist; one concrete named face per script — a stack carries at most one Latin face and one CJK face and never a fallback list of alternatives, because export takes the first named face of each script)**: CJK sans `Microsoft YaHei` / `SimHei`, CJK serif `SimSun` / `FangSong` / `KaiTi` (their macOS counterparts `PingFang SC` / `Heiti SC` / `Songti SC` are preview aliases, never the named face), Latin sans `Arial` / `Calibri` / `Segoe UI` / `Verdana` / `Trebuchet MS`, Latin serif `Times New Roman` / `Georgia` / `Cambria` / `Palatino` / `Garamond`, mono `Consolas` / `Courier New`, display `Impact` / `Arial Black`. Let the locked style's character pick the axis and lead the title — `Microsoft YaHei` / `Arial` are the neutral members, never the automatic lead; a neutral sans title where the style asks for character is the failure to avoid. Non-pre-installed directions — retro/pixel Press Start 2P / VT323, rounded Nunito / Quicksand / OPPO Sans (safe substitute `Trebuchet MS` / `Verdana`), modern web Inter / HarmonyOS Sans / Source Han, calligraphic 隶书 / 华文行楷 / 华文新魏 (safe substitute `KaiTi` / `FangSong`, titles only), brand faces — need target installation or stay Design Spec references.
**Role extension after confirmation**: while composing the roster, add a lowercase snake_case role with an exact stack only for a recurring role that materially needs a different family (`annotation`, `footer`, `footnote`, `data`, `emphasis`, `quote`, `code`), coherent with the confirmed heading/body system and locked style; one-off garnish stays omitted and Default names any added role in one compact `Role rationale` line in §IV.
**Size anchors — px only**: every layer carries bare px; PowerPoint pt (`px × 0.75`) is an export result. Take the initial body anchor and sanity band from [`canvas-formats.md`](canvas-formats.md) § Typography Scale Start, never rederived here.
| Recurring role | Ratio to body |
|---|---:|
| Cover title / single-focus hero | 2.55× |
| Chapter title | 22.5× |
| Page title / KPI hero | 1.52× |
| Subtitle | 1.21.5× |
| Lead / subheading | 1.11.4× |
| Body | 1× |
| Annotation | 0.70.85× |
| Footnote / page number | 0.50.65× |
Scan the roster before fixing anchors and declare every recurring role (`lead` at least body size; `footnote`; chart annotations when used; and the display roles the `anchor` page count makes recurring — chapter numerals, hero numbers), one deck-wide anchor each, snapped to clean even px (body 24 → title 42, subtitle 32, lead 30, annotation 18, footnote 16). Executor's ±2 px band and its two-occurrence display exception are [`executor-base.md`](./executor-base.md) §2.1; declare every recurring role so no structural text depends on that exception.
### 6.3 Icons
One single-select base identity, not a material whitelist:
| Option | Approach | Suitable Scenarios |
|--------|----------|-------------------|
| **A** | Emoji | Casual, playful, social media |
| **B** | Built-in generic icon library | Recurring compact semantic cues in one coherent SVG style |
| **C** | Custom project icons | Supplied, template-carried, or imported assets |
| **D** | No base icons | No shared generic base-icon identity is selected |
AI illustrated icons are not a base option, add-on, field, or key — like decorative lettering they are a downstream image carrier §h and [`strategist-image.md`](./strategist-image.md) may choose, with slices under `images/` (never `icons/`, `icons.inventory`, or `<use data-icon>`); they may coexist with base icons. Real brand marks are identity assets: any company, product, service, or social identity in the content may use its exact supplied or `simple-icons` mark under every base choice, with no extra option. Library inventory, prefixes, and placeholder syntax: [`../templates/icons/README.md`](../templates/icons/README.md).
One primary stylistic library per pool, chosen from the four characters in the [icon README](../templates/icons/README.md) table, with `stroke_width` from `{1.5, 2, 3}` for a stroke library; `simple-icons` is prepared from content for real brand marks. The pool is curated for broad semantic fit and synced before authoring; which icon a page uses is realization, never a preassignment.
@@ -2,13 +2,13 @@
Mandatory reference for every route that authors or regenerates slide visuals through SVG. It owns XML validity, the closed generated-authoring surface, page closure, semantic grouping, shared visual-quality defaults, and fidelity vocabulary. The complete closed grammar that the checker and exporter enforce — mapping tables, accepted-but-warned spellings, rejection boundaries, import-side metadata — lives in [`svg-contract.md`](../scripts/docs/svg-contract.md); this file keeps the form the model writes.
**Conditional module routing**:
**Conditional module routing**: Default and Quick Generate load every module through [`executor-base.md`](./executor-base.md)'s routing table. Other SVG-authoring routes (Create Template, Edit Native PPTX) load:
| Trigger | Load |
|---|---|
| Default or Quick Generate at the executor-base routing trigger (the first visual job beyond the everyday block); other routes when noncanonical/alpha paint, advanced line or text treatment, gradient/filter/effect, transform, freeform/radial geometry, or constructed style is used | [`svg-effects.md`](./svg-effects.md) |
| A page will use a preset pattern fill or evaluate native chart/table replacement | [`native-data-interface.md`](./native-data-interface.md) before deciding eligibility or emitting metadata |
| Default structured lock, or Quick installed Layout/Deck structured authoring | [`pptx-structure-interface.md`](./pptx-structure-interface.md) |
| Noncanonical/alpha paint, advanced line or text treatment, gradient/filter/effect, transform, freeform/radial geometry, or constructed style | [`svg-effects.md`](./svg-effects.md) |
| A preset pattern fill, or native chart/table data is authored or edited | [`native-data-interface.md`](./native-data-interface.md) before deciding eligibility or emitting metadata |
| Structured Master/Layout/slot authoring | [`pptx-structure-interface.md`](./pptx-structure-interface.md) |
Design defaults that apply when no higher authority speaks are collected in §6.
@@ -165,7 +165,7 @@ Use the already locked canvas id and exact viewBox. [`canvas-formats.md`](canvas
Semantic markers are minimal compiler hints. Flat pages declare one root `data-pptx-page-role` and omit Master/Layout/layer/placeholder markers. Structured pages carry their final root identity, layer atoms, slots, and native-object metadata from authoring start and omit `data-pptx-page-role`. Use `data-pptx-role` with a stable `id` only when no specialized marker expresses page-frame behavior. Keep ordinary visible content in SVG attributes/text; [`semantic-svg.md`](semantic-svg.md) owns the vocabulary.
- **Canvas authority**: new authoring writes `viewBox="0 0 W H"` with positive integer pixels from the lock, or from the first SVG under `quick-generate`; all pages and Layout prototypes in one build share it, optional root `width`/`height` never override it, and a root `<svg>` transform is forbidden. Export quantizes once at `1 SVG px = 9,525 EMU`.
- **Font portability**: resolve an explicit user/template delivery target first; otherwise default to Windows Microsoft PowerPoint with locale following the deck's primary language. Exported Latin/EA faces must be installed or approved on that target. The authoring host's fonts affect SVG preview and measurement only and MUST NOT select PPTX faces; a local counterpart may appear only as a preview tail that preserves the same export resolution. `@font-face` remains forbidden; the typography contract lives in [`strategist.md §g`](strategist.md).
- **Font portability**: resolve an explicit user/template delivery target first; otherwise default to Windows Microsoft PowerPoint with locale following the deck's primary language. Exported Latin/EA faces must be installed or approved on that target. The authoring host's fonts affect SVG preview and measurement only and MUST NOT select PPTX faces; a local counterpart may appear only as a preview tail that preserves the same export resolution. `@font-face` remains forbidden; the family choice belongs to the planning role ([`plan-core.md`](plan-core.md) §6.2, shared by Default and Quick).
- **Icon placeholders**: `<use data-icon="library/name">` is a pipeline-specific form, distinct from local SVG reuse. Follow the contract in [`../templates/icons/README.md`](../templates/icons/README.md).
- **Local reuse**: ordinary same-document `<use>` follows §1.3.
@@ -1,12 +1,3 @@
# Shared Technical Standards
Compatibility router for the split SVG specifications. Runtime routes load the core plus their route-required and feature-triggered modules.
| Scope | Authority | Trigger |
|---|---|---|
| XML/SVG foundation, shared visual-quality defaults, page closure, grouping | [`shared-standards-core.md`](./shared-standards-core.md) | Always for SVG authoring |
| Advanced effects and geometry | [`svg-effects.md`](./svg-effects.md) | Default / Quick Generate on the executor-base routing trigger (first visual job beyond the everyday block); otherwise when the corresponding effect or geometry is used |
| Preset patterns and native chart/table metadata | [`native-data-interface.md`](./native-data-interface.md) | Corresponding native-data interface is used |
| Master/Layout/placeholder structure | [`pptx-structure-interface.md`](./pptx-structure-interface.md) | Default structured lock, or Quick installed Layout/Deck structured authoring |
**Hard rule**: This file is a routing pointer, not a combined runtime authority. Follow the selected route's required modules; do not load every remaining conditional module by default.
Compatibility router for the split SVG specifications. The always-on authoring contract is [`shared-standards-core.md`](./shared-standards-core.md); Default and Quick Generate load every conditional module through [`executor-base.md`](./executor-base.md)'s routing table, and other SVG-authoring routes through the routing table at the top of the core. This file is a pointer, not a combined runtime authority: follow the selected route's required modules and do not load every conditional module by default.
@@ -6,7 +6,7 @@ Always-on Stage-2 rendering-candidate extension plus, after confirmation, image
**Trigger**: load before every fresh Stage-2 direction set. Author the three rendering candidates first (§2) from the rendering index; [`strategist.md`](./strategist.md) independently owns the source recommendation. A confirmed non-`none` source activates the resource sections; confirmed `none` stops before them. Candidates are authored once before confirmation and never backfilled from a later source toggle.
**Contract — what this module writes**: one `image_strategy` per direction (§2); §VIII rows only for planned images, each with filename, dimensions/ratio, layout suggestion, crop policy, purpose/type, `Acquire Via` (`ai`, `web`, `user`, `placeholder`, `slice`), status under [`svg-image-embedding.md`](./svg-image-embedding.md), reference, and conditional AI fields; after final confirmation, each placed row projected into `spec_lock.md images` as `<path> | source=<Acquire Via> | crop=<adaptive|no-crop>` (unplaced source/sheet rows omitted; `Layout pattern` stays in §VIII as preferred expression). An unavailable planned or required asset stays `Pending` or `Needs-Manual`, never deleted or reclassified.
**Contract — what this module writes**: one `image_strategy` per direction (§2); §VIII rows only for planned images, each with filename, dimensions/ratio, layout suggestion, crop policy, purpose/type, `Acquire Via` (`ai`, `web`, `user`, `placeholder`, `slice`), status under [`svg-image-embedding.md`](./svg-image-embedding.md), reference, and conditional AI fields; after final confirmation, each placed row projected into `spec_lock.md images` as `<path> | source=<Acquire Via> | crop=<adaptive|no-crop>` (unplaced source/sheet rows omitted; `Image pattern` stays in §VIII as preferred expression). An unavailable planned or required asset stays `Pending` or `Needs-Manual`, never deleted or reclassified.
---
@@ -22,7 +22,7 @@ Run this module inside [`strategist.md`](./strategist.md)'s one-pass resource-ne
**Illustrated icons (confirmed AI)**: a compact semantic cue may become a project-specific illustrated cue through the same sheet-to-slice contract — `Type: Illustrated icon`, `Crop Policy: no-crop`, an appropriate layout recommendation, parent as an unplaced `Type: Illustration Sheet`; no confirmation field, slices never in `icons/`, coexistence with base SVG/emoji icons when the system stays coherent.
**Reference — decorative-lettering candidates**: under confirmed `ai` (a Permission, not coverage), any stable wording is a candidate when an artistic treatment could communicate better than native type; wording that fails either test stays native. Page role, character/word/line count, kind of noun, and locked style never pre-filter — a long title, phrase, or multi-line lockup is as eligible as a short mark, and a full exact string stays one mark, never trimmed, rewritten, or split for generation. Zero selected marks is valid. Materialize each selected mark as an ordinary `ai` row or through §4.3 sheet/element rows, grouped by letterform character and treatment; the asset may carry the complete title as display layer while a native title/subtitle stays in its own frame wherever a searchable, selectable, or outline-visible heading is needed; chrome and body stay native. Confirmed `none`, an explicit no-AI or editable-only instruction, or an Offline Manual path does not activate this rule; a user-required lettering asset follows the ordinary contract.
**Reference — decorative-lettering candidates**: the candidate test, eligibility, and native-title rule are [`plan-core.md`](./plan-core.md) §5.1; here confirmed `ai` is a Permission, not coverage, and zero selected marks is valid. Materialize each selected mark as an ordinary `ai` row or through §4.3 sheet/element rows, grouped by letterform character and treatment, with chrome and body native. Confirmed `none`, an explicit no-AI or editable-only instruction, or an Offline Manual path does not activate this rule; a user-required lettering asset follows the ordinary contract.
**Image treatment path** per selected image: `none` (unchanged), `native` (SVG crop/clip, transform, opacity, frame/depth, overlap), or `prepared derivative` (pixel blur/tone, or cutout/registered layers); `none` is valid. A subject crossing a native title, panel, frame, or shape mandates the prepared path: a clean full-canvas base plus the minimum registered RGBA layers, full-canvas members `no-crop`, the shared source/registration named in `Reference`, `#A2-03` suggested; a shared plate needs padded-bbox-disjoint objects and independent final crops; `user` only when every final asset is supplied, otherwise `ai` under [`image-generator.md`](./image-generator.md) §4.4. A free-floating cutout may use `#A2-01`.
@@ -36,10 +36,10 @@ For specialized or regulated paper-figure subjects keep the prompt depth of [`im
**Prepared derivatives**: keep the canonical row and add a deterministic child with a distinct `.png`, `Reference: Derived from <bare filename>; treatment=<operation>;`, inheriting acquisition (§4.4 follows `user` / `ai` above); lock placed children; [`image-base.md`](./image-base.md) §12 owns preparation.
**References describe visual intent**: AI rows carry subject + intent + composition without repeating rendering or HEX; web rows carry the exact subject, view/mood, focal/quiet region, crop safety, and positive quality cues, from which Image_Searcher derives a separate short provider query (complete entity names or disambiguation may use more words). When page use depends on stable composition, put subject/quiet zones, boundary or direction, intended overlap/seam, and approximate share in `Reference` or the §IX block, not only in `Layout pattern`.
**References describe visual intent**: AI rows carry subject + intent + composition without repeating rendering or HEX; web rows carry the exact subject, view/mood, focal/quiet region, crop safety, and positive quality cues, from which Image_Searcher derives a separate short provider query (complete entity names or disambiguation may use more words). When page use depends on stable composition, put subject/quiet zones, boundary or direction, intended overlap/seam, and approximate share in `Reference` or the §IX block, not only in `Image pattern`.
**Prepared-user fast path**: for initial imported or user-supplied assets confirmed as `provided`, copy the exact basename, derive `Dimensions` / `Ratio` from the row's EXIF-corrected `Width` / `Height` / `AspectRatio` in the latest `analysis/image_analysis.csv` (`SourceDisplayRatio` is source context, not the crop ratio), drop source-side directories, set `Acquire Via: user` and `Status: Existing`, and decide the rest normally; existing §VIII, lock, or provenance records override this inference, and assets declared `ai`, `web`, `slice`, or manual keep that provenance wherever they sit.
**Layout pattern** (one non-empty value per placed row, required by the checker): preferred expression in ordinary words, not locked geometry (an id from [`image-layout-patterns.md`](./image-layout-patterns.md) only when already known; Executor loads that catalog); Executor adjusts it freely as a Reference while keeping resource identity, must-use status, crop/content, and explicit constraints (layout-only changes need no upstream rewrite). A useful entry names the job the image does for the content or the page's shapes — the catalog is recall, an uncatalogued technique answers a job equally, plain split and full bleed stay valid, and a `no-crop` or supporting row keeps one concise suggestion. Choose narrative intent before dimensions, then derive `Dimensions` / `Ratio` from the intended region of the confirmed canvas (placement geometry itself is Executor's [`image-layout-spec.md`](./image-layout-spec.md)); a cutout, blurred crop, or desaturated copy requires that prepared asset.
**Image pattern** (one non-empty value per placed row, required by the checker): preferred expression in ordinary words, not locked geometry (an id from [`image-layout-patterns.md`](./image-layout-patterns.md) only when already known; Executor loads that catalog); Executor adjusts it freely as a Reference while keeping resource identity, must-use status, crop/content, and explicit constraints (layout-only changes need no upstream rewrite). A useful entry names the job the image does for the content or the page's shapes — the catalog is recall, an uncatalogued technique answers a job equally, plain split and full bleed stay valid, and a `no-crop` or supporting row keeps one concise suggestion. Choose narrative intent before dimensions, then derive `Dimensions` / `Ratio` from the intended region of the confirmed canvas (placement geometry itself is Executor's [`image-layout-spec.md`](./image-layout-spec.md)); a cutout, blurred crop, or desaturated copy requires that prepared asset.
**Crop policy**: `no-crop` whenever cropping could remove required pixels, labels, evidence, identity, or edge content (screenshots, charts, certificates, dense diagrams, logos, product markings are common triggers); otherwise `adaptive` — Executor may use complete display or a focal-safe crop, and the value never commands cropping. Judge `text_policy` per AI row under [`image-generator.md`](./image-generator.md) §5.3; paper figures, schematics, panel comparisons, data-axis graphics, and stable lettering are triggers to reconsider an all-`none` plan. Step 5 dispatches pending `ai` / `slice` rows to Image_Generator and `web` rows to Image_Searcher.
@@ -10,9 +10,9 @@ Conditional extension for applying an installed Brand/Style/Layout/Deck workspac
## 1. AI-Authored Template Application Plan
**Inputs**: every installed `<project_path>/templates/design_spec.<kind>.<id>.md` is a template-design source; read all of them. A `design_spec.style.*.md` file marks an active Direction / method segment. Bare names and style words stay interpretive input and never resolve to a local path. Library/explicit provenance never affects precedence. A legacy or incomplete Layout/Deck is not a Step 3 input — rebuild it through [`create-template`](../workflows/create-template.md), preferably from the original PPTX; never mutate the input.
**Inputs**: every installed `<project_path>/templates/design_spec.<kind>.<id>.md` is a template-design source; read all of them. A `design_spec.style.*.md` file marks an active Direction / method segment. A legacy or incomplete Layout/Deck is rejected under [`pptx-structure-interface.md`](./pptx-structure-interface.md) §3; never mutate the input.
**Hard rule — no Stage-1 influence**: Do not load this module, the template spec, prototypes, assets, or template canvas while authoring Stage 1, and never revise a confirmed Stage 1 to match the workspace.
**Hard rule — no Stage-1 influence**: never revise a confirmed Stage 1 to match the workspace (Stage-1 evidence boundary: [`generate-pptx.md`](../workflows/generate-pptx.md) Step 4).
**Outputs**:
@@ -2,7 +2,7 @@
## Core Mission
Receive source documents, analyze content, plan the design, and output the **Design Specification & Content Outline** (`design_spec`) plus its execution lock.
Receive source documents, analyze content, plan the design, and output the **Design Specification & Content Outline** (`design_spec`) plus its execution lock. The planning craft shared with Quick is [`plan-core.md`](./plan-core.md); this file owns the confirmation stages, the three-direction construction, and the artifact grammar.
## Pipeline Context
@@ -16,22 +16,28 @@ Canvas formats and their typography scale start: [`canvas-formats.md`](canvas-fo
## 1. Strategist Confirmation Stage
🚧 **GATE — whole-document authoring**: Generate Step 4 reads `${SKILL_DIR}/templates/design_spec_reference.md`, authors the complete Design Spec once, passes Gate 1, then reads `${SKILL_DIR}/templates/spec_lock_reference.md` and authors the complete lock once; no scaffolds, no placeholder patching; `project_manager.py validate` owns grammar.
🚧 **GATE — whole-document authoring**: Generate Step 4 reads `${SKILL_DIR}/templates/design_spec_reference.md`, authors the complete Design Spec once, passes Gate 1, then reads `${SKILL_DIR}/templates/spec_lock_reference.md` and authors the complete lock once. No scaffolds, no placeholder patching; `project_manager.py validate` owns grammar.
**BLOCKING**: present professional recommendations for the fields below and wait for explicit user confirmation. Generate Step 3 prepares candidates only; Stage 1 confirms the communication contract and the template/free-design choice together (the recommendation independent of every candidate); the selected workspaces are installed before Stage 2.
**BLOCKING**: present professional recommendations for the fields below and wait for explicit user confirmation. Generate Step 3 prepares candidates only. Stage 1 confirms the communication contract and the template/free-design choice together (the recommendation independent of every candidate); the selected workspaces are installed before Stage 2.
| Stage | Items | Role |
|---|---|---|
| **1 — communication contract + template choice** | `primary_language` · `c` audience · open-ended communication intent · audience outcome · core message / delivery context (primary + optional secondary) / artifact afterlife · `content_divergence` (all prose may be blank) · `a` canvas · explicit `free_design` or `templates` choice and selected roots | confirmed together; candidates never influence the communication recommendation |
| **2 — final solution + production** (authored once from the user's *actual* Stage 1) | reading mode (`delivery_purpose`, PPT only) · `d` mode + visual style · `b` page count · `e` color · `f` icon · `g` typography · `h` image source + generated-image rendering · conditional template application · conditional AI-image acquisition path · generation mode · refine-spec toggle · `design_spec_depth` · proactive speaker notes / custom animations / narration audio | one coherent plan from the confirmed contract; exporter reuse/adherence stays internal |
Stage 1 records composite intent in prose, never one catalog label; editable prose fields are drafts confirmation keeps the current text and blanks, and a cleared field is never repopulated. Stage 2 confirms narrative spine, reading density, page budget, visual system, image direction, production mechanics, and how an installed template is used (inspecting only project-local specs and prototypes); it never chooses or installs a template. Author the three whole-deck directions under §d, then set `design_directions.selected` to the strongest fit (with an installed template, the viable direction that best expresses its resolved context under [`strategist-template.md`](./strategist-template.md)) as the actual zero-based index (`0`, `1`, or `2`); array order never determines preference. Every direction carries a rendering candidate whether or not AI is proposed; generated images inherit deck colors. Proactive defaults are notes `true`, custom animations `false`, narration `false`; an earlier explicit instruction overrides the matching recommendation, and narration requires notes. Recommend `design_spec_depth: brief` (the same author draws the pages) and `complete` only for `split`, `refine_spec: true`, a preservation profile, or a requested hand-off document. Author each stage once; launch/wait mechanics are in [`generate-pptx.md`](../workflows/generate-pptx.md) Step 4.
**Stage 1 fields**: record composite intent in prose, never one catalog label. Editable prose fields are drafts: confirmation keeps the current text and blanks, and a cleared field is never repopulated.
**Default — continuity-aware whole solution (may override when a scene reset communicates better)**: before recommending page count or production mechanics, judge whether adjacent beats can stay within one recognizable mental map while a visible state changes; where that lowers cognitive switching and motion has a named job, let it shape the spine, rhythm, visual approach, and notes/narration segmentation, and recommend `proactive_custom_animations: true`; plan such neighbors as visible states of one scene — recognizable anchors kept, the delta legible, each enabled notes/narration segment aligned with its state, every state page still carrying content and an `Audience move`; reset when the map changes or continuity adds nothing. One positive signal, not the only one; topic or wording repetition alone is insufficient, and a `Motion suggestion` never changes the effective outcome.
**Stage 2 scope**: confirm narrative spine, reading density, page budget, visual system, image direction, production mechanics, and how an installed template is used (inspecting only project-local specs and prototypes). Stage 2 never chooses or installs a template.
**Hard rule — Stage-1 source boundary**: build the communication recommendation only from the current request, source facts, conversation constraints, and project-initialization state — before loading index summaries for a chat listing and without reading any candidate spec, prototype, asset, or template canvas; template controls on the same surface are confirmation state, not evidence. Load [`strategist-template.md`](./strategist-template.md) only after Stage 1 is confirmed and the selection installed.
**Selected direction**: `design_directions.selected` is the actual zero-based index (`0`, `1`, or `2`) of the strongest fit, chosen after all three §d directions are complete. With an installed template it is the viable direction that best expresses its resolved context under [`strategist-template.md`](./strategist-template.md). Array order never determines preference.
> **Execution discipline**: Stage 1 is the first BLOCKING checkpoint; its receipt is intermediate and never ends the task. In the same run, install/fuse the selection, complete the handoff, author fresh Stage 2, and enter the final wait; after final confirmation proceed without another pause unless refinement is enabled — the only opt-in exception is [`refine-spec`](../workflows/stages/refine-spec.md), offered with the split-mode note and never entered unprompted.
**Production defaults**: proactive defaults are notes `true`, custom animations `false`, narration `false`. An earlier explicit instruction overrides the matching recommendation; narration requires notes. Recommend `design_spec_depth: brief` (the same author draws the pages); recommend `complete` only for `split`, `refine_spec: true`, a preservation profile, or a requested hand-off document. Author each stage once; launch/wait mechanics are [`generate-pptx.md`](../workflows/generate-pptx.md) Step 4.
**Default — continuity-aware whole solution (may override when a scene reset communicates better)**: before recommending page count or production mechanics, judge whether adjacent beats can stay within one recognizable mental map while a visible state changes. Where that lowers cognitive switching and motion has a named job, let it shape the spine, rhythm, visual approach, and notes/narration segmentation, and recommend `proactive_custom_animations: true`. Plan such neighbors as visible states of one scene: recognizable anchors kept, the delta legible, each enabled notes/narration segment aligned with its state, every state page still carrying content and an `Audience move`. Reset when the map changes or continuity adds nothing. One positive signal, not the only one: topic or wording repetition alone is insufficient, and a `Motion suggestion` never changes the effective outcome.
**Hard rule — Stage-1 source boundary**: the evidence Stage 1 may use is fixed by [`generate-pptx.md`](../workflows/generate-pptx.md) Step 4; template controls on the same surface are confirmation state, not evidence. Load [`strategist-template.md`](./strategist-template.md) only after Stage 1 is confirmed and the selection installed.
> **Execution discipline**: Stage 1 is the first BLOCKING checkpoint; its receipt is intermediate and never ends the task. In the same run, install/fuse the selection, complete the handoff, author fresh Stage 2, and enter the final wait. After final confirmation proceed without another pause unless refinement is enabled; the only opt-in exception is [`refine-spec`](../workflows/stages/refine-spec.md), offered with the split-mode note and never entered unprompted.
>
> **Presentation surface**: apply the sticky per-run surface decision in [`confirm-surface.md`](./confirm-surface.md) and author the Stage-1/Stage-2 payloads in its shapes; the chat/delegated branch keeps equivalent state without fabricating receipts. Stage 1 writes canonical BCP-47 `primary_language`; Stage 2 carries exactly three immutable `design_directions`; the final result stores only current component values, never a direction id. Server lifecycle: [`confirm_ui.md`](../scripts/docs/confirm_ui.md).
@@ -47,9 +53,18 @@ Stage 1 records composite intent in prose, never one catalog label; editable pro
Explicit *must*, *only*, *exactly*, *verbatim*, *do not*, or `no-crop` wording strengthens only the named property; accepting a recommendation keeps the field's default type.
**Authority chain — materials → Strategist preparation → realization**: user inputs bound materials and acquisition. Strategist owns sufficiency, gap-filling, and selection — roster and content, `Relationships`, prepared resources and paths, structured-template routing, fonts, palette anchors, icon library/stroke and curated pool, crop bans, and optional Chart/Table references — and sketches macro composition, focus, and continuity as Reference (binding only when labeled `(binding)`), never a carrier mix, element geometry, or authoring method. Topic research and its two-artifact pair may precede confirmation (facts URLs never auto-expanded; one adopted webpage may become a reviewable source package only after normal image search fails). AI/web/slice acquisition follows final confirmation plus §VIII/lock; icons are synced during authoring without page assignment; before Executor every resource has a path and a terminal or `Needs-Manual` state. Native construction is an Executor capability, not a resource; missing material returns upstream, never invented or substituted.
**Authority chain — materials → Strategist preparation → realization**: user inputs bound materials and acquisition. Strategist owns sufficiency, gap-filling, and selection — roster and content, `Relationships`, prepared resources and paths, structured-template routing, fonts, palette anchors, icon library/stroke and curated pool, crop bans, and optional Chart/Table references. Strategist sketches macro composition, focus, and continuity as Reference (binding only when labeled `(binding)`), never a carrier mix, element geometry, or authoring method. Native construction is an Executor capability, not a resource.
**GATE — final confirmation is consumed once into the Design Spec**: use the complete final object already read by Generate Step 4 (`stage: final`, `status: confirmed`) or the chat path's final visible summary; never reopen `result.json` during Design Spec or lock authoring. Consume every present field by its semantic type and owner without omission, substitution, or silent strengthening/weakening; decide only what was left unconfirmed; keep a cleared prose field empty; an unhonorable requirement stays visible and follows [`failure-recovery.md`](../workflows/governance/failure-recovery.md).
| Acquisition step | Timing |
|---|---|
| Topic research and its two-artifact pair | May precede confirmation; facts URLs are never auto-expanded; one adopted webpage becomes a reviewable source package only after normal image search fails |
| AI / web / slice acquisition | After final confirmation plus §VIII/lock |
| Icons | Synced during authoring without page assignment |
| Every resource before Executor | Has a path and a terminal or `Needs-Manual` state |
Missing material returns upstream, never invented or substituted.
**GATE — final confirmation is consumed once into the Design Spec**: use the complete final object already read by Generate Step 4 (`stage: final`, `status: confirmed`) or the chat path's final visible summary; never reopen `result.json` during Design Spec or lock authoring. Consume every present field by its semantic type and owner without omission, substitution, or silent strengthening/weakening. Decide only what was left unconfirmed; keep a cleared prose field empty. An unhonorable requirement stays visible and follows [`failure-recovery.md`](../workflows/governance/failure-recovery.md).
### a. Canvas Format Confirmation
@@ -57,77 +72,62 @@ Recommend from the scenario and project initialization ([`canvas-formats.md`](ca
### b. Page Count Confirmation
**Default — open `page_count` as a narrow range (may override when an exact count is supplied or locked)**: narrow enough to judge at a glance. After Stage 1 choose one exact count from source volume, audience outcome, delivery context/afterlife, and reading mode, then author the complete §IX roster; *exactly*, *1:1*, or preservation fixes it. After Gate 1 and any refine approval, the roster's ids, count, and order are invariant — Executor never adds, drops, merges, splits, or reorders without Design Spec repair or reconfirmation.
Page count craft — the Stage-1 range, the exact count chosen after Stage 1, and the roster invariance after Gate 1 — is [`plan-core.md`](./plan-core.md) §3.
### c. Communication Contract Confirmation
Seed these as open-prose recommendations when the source and request support them; the user may retain, edit, or clear every field, and none requires a non-empty answer:
Seed the six contract fields of [`plan-core.md`](./plan-core.md) §1 as open-prose recommendations when the source and request support them; the user may retain, edit, or clear every field, and none requires a non-empty answer. Intent stays open-ended and is never a checkbox list or a `primary_job`.
| Field | Question it answers |
|---|---|
| `audience` | Who exactly must receive this communication, and what do they already know / care about? |
| `communication_intent` | What must the presentation accomplish? It may combine several purposes and state priority or sequence. |
| `audience_outcome` | What observable change means the communication succeeded — what will the audience know, understand, believe, decide, or do? |
| `core_message` | Which claim(s), decision ask(s), or action(s) must land even if little else is remembered? |
| `delivery_context` | What is primary — presenter-led, reader-led, hybrid (which leads), or recorded/self-running (no live presenter; narration, timing, transitions, playback)? What secondary use, occasion, and time constraint remain? One open field, never an enum. |
| `artifact_afterlife` | What must the file support afterward — review, approval, audit, archive, hand-off, reuse, or nothing? |
**Hard rule — confirmed current value wins**: submit every Stage-1 prose field exactly as it stands at confirmation. Blank means no explicit constraint (downstream judgment from source and request) and is never restored to the recommendation. A profile-declared `locked: true` field is the only read-only exception.
**Communication intent is open-ended**: *inform / explain / persuade / decide / align / teach / report and account / mobilize / record and hand off* are prompts, never a checkbox list or a `primary_job`; several purposes keep their relationship in prose ("report progress and expose risk first; then obtain a decision"). The contract is not the narrative mode: intent says what change is needed, `mode` is one Stage-2 way to organize the argument.
**Reading mode** (PPT only, Stage 2): `text` / `balanced` (default) / `presentation`, kept under the compatibility key `delivery_purpose`; what each mode carries is [`plan-core.md`](./plan-core.md) §2. It drives page grammar, granularity, density, and the §b recommendation; the §g body baseline is a consequence.
**Hard rule — confirmed current value wins**: submit every Stage-1 prose field exactly as it stands at confirmation; blank means no explicit constraint (downstream judgment from source and request) and is never restored to the recommendation. A profile-declared `locked: true` field is the only read-only exception.
**Material divergence** (`content_divergence`): a free-text Stage-1 field the user fills in their own words — never a set of options and never recommended from source analysis; blank is a balanced default. The spectrum and the facts-stay-sourced Hard rule are [`plan-core.md`](./plan-core.md) §3. Apply it only while authoring §IX and record it in `design_spec.md §I`, never in the lock. Beautify seeds and locks verbatim preservation; Edit Native PPTX does not surface it.
**Reading mode** (PPT only, Stage 2): `text` (read-close) / `balanced` (business, default) / `presentation`, kept under the compatibility key `delivery_purpose` but reasoned about as information carriage — how meaning divides among page, visuals, presenter, and enabled notes — driving page grammar, granularity, density, and the §b recommendation; the §g body baseline is a consequence, not the definition.
**Material divergence** (`content_divergence`): a free-text Stage-1 field the user fills in their own words — how closely the deck follows the source versus how freely it reshapes it — never a set of options and never recommended from source analysis; blank is a balanced default. Read it as a spectrum from *stay close* (track structure and wording, tune for clarity) through *balanced* (re-architect into a narrative under the locked mode, keeping all substance) to *free* (regroup, reframe, expand, connect, invent structure and transitions). **Hard rule — facts stay sourced however free the user asks**: divergence develops what is in the source and never licenses outside facts, figures, or claims — that is `topic-research`'s job; `mode` and divergence are orthogonal. Apply it only while authoring §IX and record it in `design_spec.md §I`, never in the lock; Beautify seeds and locks verbatim preservation, Edit Native PPTX does not surface it.
**Fact provenance contract**: when `sources/*.facts.json` exists, read it before outlining and cite its stable `fact_id` values as `Fact IDs: F001, ...` on every §IX page that uses an external quantitative or factual claim; invented demo KPIs, ratios, targets, and roadmap numbers carry `Data class: scenario` and never a `fact_id`. One page may hold both classes as long as each number's class is unambiguous.
When authoring §IX, translate every purpose named in the intent into an outline obligation (a reasoning checklist, not a classifier; preserve the user's priority and sequence):
| Intent named in the prose | Outline must enable |
|---|---|
| Inform | Relevant facts with enough context to know why they matter |
| Explain | Mechanism, relationship, cause, or meaning made traceable |
| Persuade | Claim + evidence + material objections / alternatives |
| Decide | Explicit decision ask + options + criteria + trade-offs + consequence of delay |
| Align | Shared frame + priorities + owners + next steps |
| Teach | Prerequisites + sequence + worked application / check for understanding |
| Report and account | Baseline + progress + variance + evidence + risk + ownership |
| Mobilize | Urgency + agency + concrete action + immediate next step |
| Record and hand off | Context + decisions + status + owners + unresolved items + durable provenance |
**Fact provenance** and the intent → outline-obligation checklist are [`plan-core.md`](./plan-core.md) §3 and §1; apply both while authoring §IX, preserving the user's priority and sequence.
### d. Style Objective Confirmation
**Stage 2 only** — tools that serve the confirmed scenario, never substitutes for defining it. Two independent layers, each locking one preset or `custom`; output `d. Mode: <mode> + Visual style: <visual_style>`.
**Hard rule — top-down direction construction**: author three complete, project-fit solution intents from the confirmed contract and source before touching any catalog basis; the three mode/style/rendering indexes are the only basis selectors. Freeze each direction's exact reference ids from the index summaries, read once only the deduplicated union of those detail files, then write the behaviors. Every direction serializes `mode: custom`, `visual_style: custom`, and `image_strategy.rendering: custom`, each with visible non-empty behavior prose; a custom may use catalog material in any way or none — one preset carried unchanged is valid — and references record only actual sources, each owning a distinct executable contribution (never a decorative second basis). The three directions are plainly different designs *before* any field is written: whichever components a design requires carry the difference, and mode, style, rendering, bases, color, type, and icons are each free to coincide — a different name, note, or reference count alone is no difference, and identical projections are not three solutions. Where authoritative truth fixes components, the open ones carry the difference; where nothing is open, keep the projections identical and state that boundary. Never force safe / shifted / bold archetypes, glob a catalog, read an unselected sibling, or write bespoke prose as an enum value.
**Hard rule — top-down direction construction**: author three complete, project-fit solution intents from the confirmed contract and source before touching any catalog basis. The three mode/style/rendering indexes are the only basis selectors. Freeze each direction's exact reference ids from the index summaries, read once only the deduplicated union of those detail files, then write the behaviors. Never force safe / shifted / bold archetypes, glob a catalog, read an unselected sibling, or write bespoke prose as an enum value.
**Direction serialization**: every direction serializes `mode: custom`, `visual_style: custom`, and `image_strategy.rendering: custom`, each with visible non-empty behavior prose. A custom may use catalog material in any way or none; one preset carried unchanged is valid. References record only actual sources, each owning a distinct executable contribution, never a decorative second basis.
**Three plainly different designs**: the three directions differ as designs *before* any field is written. Whichever components a design requires carry the difference; mode, style, rendering, bases, color, type, and icons are each free to coincide. A different name, note, or reference count alone is no difference, and identical projections are not three solutions. Where authoritative truth fixes components, the open ones carry the difference. Where nothing is open, keep the projections identical and state that boundary.
#### Layer 1 — Communication mode
🚧 **GATE**: [`modes/_index.md`](./modes/_index.md) is the sole mode-basis authority; read only the frozen sibling files once; a novel mode reads none.
🚧 **GATE**: [`modes/_index.md`](./modes/_index.md) is the sole mode-basis authority; basis selection follows the §d Hard rule.
The narrative + persuasion skeleton: one preset from `pyramid` / `narrative` / `instructional` / `showcase` / `briefing`, or `custom` with behavior — one value per deck, never several simultaneous modes.
- **User outline or structure** → preserve its facts and relationships, then apply `content_divergence`; an ordinary outline is a Reference (regroup, reorder, retitle when the contract benefits) and becomes authoritative only when presented as the final page plan or with an explicit ask to keep order, titles, or wording — record that promotion in `design_spec.md`. Still lock a mode for register and voice; `briefing` imposes the least.
- **Beautify** ([`beautify-pptx.md`](../workflows/profiles/beautify-pptx.md)) → extracted content is authoritative and verbatim: one source slide = one §IX page in order, every block transcribed word-for-word, never reshaped, condensed, merged, split, or reworded; all three mode behaviors keep that boundary and may share `briefing`. Color (e) and typography (g) are whatever the beautify plan confirmed (source identity by default) locked as truth; charts, tables, and images are regenerated from extracted data in the inherited style with values frozen (catalog references in §VII, unmatched plans in §IX, pictures in §VIII). Layout, hierarchy, rhythm, and rendering are what gets redesigned.
- **No user structure** → derive each solution from `communication_intent`, `audience_outcome`, source texture, and delivery context, then project its custom mode; directions may share bases or behavior when the whole solutions differ.
| Input | Mode derivation |
|---|---|
| **User outline or structure** | Preserve its facts and relationships, then apply `content_divergence`. An ordinary outline is a Reference (regroup, reorder, retitle when the contract benefits); it becomes authoritative only when presented as the final page plan or with an explicit ask to keep order, titles, or wording — record that promotion in `design_spec.md`. Still lock a mode for register and voice; `briefing` imposes the least. |
| **Beautify** ([`beautify-pptx.md`](../workflows/profiles/beautify-pptx.md)) | Extracted content is authoritative and verbatim: one source slide = one §IX page in order, every block transcribed word-for-word, never reshaped, condensed, merged, split, or reworded; all three mode behaviors keep that boundary and may share `briefing`. Color (e) and typography (g) are whatever the beautify plan confirmed (source identity by default) locked as truth. Charts, tables, and images are regenerated from extracted data in the inherited style with values frozen (catalog references in §VII, unmatched plans in §IX, pictures in §VIII). Layout, hierarchy, rhythm, and rendering are what gets redesigned. |
| **No user structure** | Derive each solution from `communication_intent`, `audience_outcome`, source texture, and delivery context, then project its custom mode; directions may share bases or behavior when the whole solutions differ. |
Record the mode and rationale in `design_spec.md` (with every catalog basis a custom uses), then project `- mode:` — and for custom `- mode_behavior:` plus `- mode_references:` only when catalog material is used — to `spec_lock.md`; Executor reads only those references.
#### Layer 2 — Visual style
🚧 **GATE**: [`visual-styles/_index.md`](./visual-styles/_index.md) is the sole style-basis authority; read only the frozen sibling files once; a novel style reads none.
🚧 **GATE**: [`visual-styles/_index.md`](./visual-styles/_index.md) is the sole style-basis authority; basis selection follows the §d Hard rule.
The visual aesthetic — shape language, decoration density, whitespace rhythm, typographic character, texture — anchoring e, f, g, and h. It carries no color (it governs how the HEX locked at `e` is *used*), and when the deck has AI images the style's paired rendering keeps layout and illustration in one aesthetic.
The visual aesthetic — shape language, decoration density, whitespace rhythm, typographic character, texture — anchoring e, f, g, and h. It carries no color (it governs how the HEX locked at `e` is *used*). When the deck has AI images the style's paired rendering keeps layout and illustration in one aesthetic.
- **User named a style** (chat, template, beautify) → it is truth: the required basis or inherited anchor in every behavior; derive each direction through the open dimensions, and when all variation is forbidden let the other components carry the difference and say so in the note.
- **No description** → project one complete custom aesthetic per solution, written as the carriers and techniques it *uses* — containers, icons, swatches, shadows, gradients, image treatments, native shapes — never as a list of avoidances (a locked prohibition removes that tool from every page; write one only when the user or material requires it). Behaviors differ when the designs genuinely differ, never to meet a quota; no forced bases, safe-to-bold ladder, or deliberate extreme. Give each direction a `name` and one- or two-sentence `note` in the confirmed UI language (plain keys); Confirm UI's localized labels such as `瑞士极简`, `柔和圆角`, `编辑出版` are optional vocabulary, never a required mapping, and the note exposes no catalog ids.
| Input | Style derivation |
|---|---|
| **User named a style** (chat, template, beautify) | It is truth: the required basis or inherited anchor in every behavior. Derive each direction through the open dimensions; when all variation is forbidden let the other components carry the difference and say so in the note. |
| **No description** | Project one complete custom aesthetic per solution, written as the carriers and techniques it *uses* — containers, icons, swatches, shadows, gradients, image treatments, native shapes — never as a list of avoidances. A locked prohibition removes that tool from every page; write one only when the user or material requires it. Behaviors differ when the designs genuinely differ, never to meet a quota; no forced bases, safe-to-bold ladder, or deliberate extreme. |
**Direction name and note**: give each direction a `name` and one- or two-sentence `note` in the confirmed UI language (plain keys). Confirm UI's localized labels such as `瑞士极简`, `柔和圆角`, `编辑出版` are optional vocabulary, never a required mapping, and the note exposes no catalog ids.
**Forbidden — a non-catalog name as `visual_style`**: the field is literal `custom`; prose lives in `visual_style_behavior` and `visual_style_references` holds only first-column catalog ids (a "Paired rendering" id such as `flat` or `digital-dashboard` is a rendering, not a style). Generic words — flat / modern / clean / simple / minimal — are not behavior: state the executable shape language, composition, density, whitespace, typography, and texture, which may match one preset exactly.
Record the style and rationale in `design_spec.md`, then project `- visual_style:` — and for custom `- visual_style_behavior:` plus `- visual_style_references:` only when catalog material is used — to `spec_lock.md`.
**Conditional template workspace**: when the Stage-1 choice is installed under `<project_path>/templates/`, read [`strategist-template.md`](./strategist-template.md) before completing Stage 2 — installed spec and prototypes only, never the library root. It owns the editable application plan, confirmed-value consumption, prototype selection, reuse/adherence derivation, inherited precedence, and structured-lock planning; it decides how to use the template, never which one.
**Conditional template workspace**: when the Stage-1 choice is installed under `<project_path>/templates/`, read [`strategist-template.md`](./strategist-template.md) before completing Stage 2 — installed spec and prototypes only, never the library root. It covers the editable application plan, confirmed-value consumption, prototype selection, reuse/adherence derivation, inherited precedence, and structured-lock planning; it decides how to use the template, never which one.
**Downstream effect**: e / f / g / h realize mode + style — e.g. `showcase` + `dark-tech` → one luminous accent on a dark field, a clean sans paired with mono, minimal glow icons, the `digital-dashboard` rendering.
@@ -135,34 +135,17 @@ Record the style and rationale in `design_spec.md`, then project `- visual_style
**Hard rule**: user-specified colors are truth — lock supplied HEX, brand colors, or natural-language directives (templates follow inherited-design precedence). Every direction fills all six roles (`background`, `secondary_bg`, `primary`, `accent`, `secondary_accent`, `body_text`), repeating fixed roles and varying only open ones; never an empty palette. In §III derive the standard `secondary_text` and `divider` neutrals and project them to `spec_lock.md colors`; §V fixes the five deck-wide spacing anchors.
**Reference — not a constraint**: no universal palette — user / brand → active template → project-specific proposal from content and style; 60-30-10 is the starting proportion, body contrast at least 4.5:1 (WCAG AA), hue count follows encoding, style, and natural assets; how color is *used* on a page (fields, gradients, accent placement, mood) is Executor's craft. `scripts/config.py` industry anchors (finance/business navy `#003366`, technology bright blue `#1565C0`, healthcare teal `#00796B`, government red `#C41E3A`) and polarity ramps (positive `#2E7D32 → #4CAF50 → #81C784`, warning `#F57C00 → #FFA726 → #FFD54F`, negative `#C62828 → #EF5350 → #E57373`) are recall aids, never default locks; brand identities come from a Brand/Deck workspace, never a memorized list. Strategist owns reusable positive / warning / negative roles; Executor derives tints, shades, alpha, gradients, and effects.
**Lock recurring semantic anchors, not every paint**: add neutral roles the style and page plan give a stable meaning — `surface`, `grid`, `scrim`, `overlay`, `block-shade` — and leave page-local tints, gradient stops, shadow/glow colors, and one-off tones to execution, promoting one only when it becomes a reusable named role.
| Style trait | Extra neutral tiers to lock |
|---|---|
| Layers panels / charts (e.g. `data-journalism`, `swiss-minimal`) | `surface` (panel lift), `grid` (hairline, lighter than dividers) |
| Text over imagery / dark field (e.g. `photo-editorial`, `glassmorphism`, `dark-tech`) | `scrim` / `overlay` for legibility |
| Print / hand-drawn fills (e.g. `chalkboard`, `zine`) | `block-shade`, one step off the field |
Palette precedence, proportion, contrast, recall anchors, and the neutral tiers to lock are [`plan-core.md`](./plan-core.md) §6.1; Strategist owns the reusable positive / warning / negative roles and every locked neutral tier.
### f. Icon Usage Confirmation
One single-select base identity, not a material whitelist:
| Option | Approach | Suitable Scenarios |
|--------|----------|-------------------|
| **A** | Emoji | Casual, playful, social media |
| **B** | Built-in generic icon library | Recurring compact semantic cues in one coherent SVG style |
| **C** | Custom project icons | Supplied, template-carried, or imported assets |
| **D** | No base icons | No shared generic base-icon identity is selected |
AI illustrated icons are not a base option, add-on, field, or key — like decorative lettering they are a downstream image carrier §h and [`strategist-image.md`](./strategist-image.md) may choose, with slices under `images/` (never `icons/`, `icons.inventory`, or `<use data-icon>`); they may coexist with base icons. Real brand marks are identity assets: any company, product, service, or social identity in the content may use its exact supplied or `simple-icons` mark under every base choice, with no extra option. Library inventory, prefixes, and placeholder syntax: [`../templates/icons/README.md`](../templates/icons/README.md).
One single-select base identity (A emoji / B built-in library / C custom / D none), not a material whitelist — the option table, the illustrated-icon and brand-mark boundaries, and the library line are [`plan-core.md`](./plan-core.md) §6.3.
**Mandatory — bundled SVG resources**:
1. At confirmation decide only the generic library and stroke. One primary stylistic library per pool (`icon_sync.py` rejects mixed batches): `chunk-filled` (fill, straight-line geometry, heavy, architectural), `tabler-filled` (fill, bezier curves, smooth, approachable), `tabler-outline` (stroke, airy, best for screen), `phosphor-duotone` (main shape + 20 % backplate, layered). A missing generic icon is replaced within the same library. `simple-icons` is never a Confirm UI choice: it holds brand marks only and may accompany any selection including `none`. This governs catalog selection, not the prepared pool — user, template, imported, custom, and previously prepared files under `<project_path>/icons/` stay valid whatever their namespace.
1. At confirmation decide only the generic library and stroke: one primary stylistic library per pool, chosen from the four characters in the [icon README](../templates/icons/README.md) table; `simple-icons` is prepared from content for real brand marks and is never a confirmation choice. This governs catalog selection, not the prepared pool — user, template, imported, custom, and previously prepared files under `<project_path>/icons/` stay valid whatever their namespace.
2. For a stroke library (currently `tabler-outline`) lock one deck-wide `stroke_width` from `{1.5, 2, 3}` (default `2`).
3. After approval, when writing §VI / the lock, materialize the curated pool before Executor starts (Executor cannot sync; which icons a page uses is realization, never a preassignment). Put known basenames in the final batch; search an uncertain one only inside the chosen library (or `simple-icons` for a brand) by the drawable object, never the abstract concept ([README § Searching for Icons](../templates/icons/README.md)); copy and validate in one batch — `python3 skills/ppt-master/scripts/icon_sync.py <project_path> <lib/name> [<lib/name> …]` — keeping each successful case-sensitive `lib/name` (bundled basenames are lowercase); record each synced path with broad scenarios in §VI and the same pool, primary library, and any `stroke_width` in `spec_lock.md icons` (`simple-icons/*` ids join the inventory without becoming a second library; other prepared icons stay usable).
3. After approval, when writing §VI / the lock, materialize the curated pool before Executor starts (Executor cannot sync; which icons a page uses is realization, never a preassignment). Put known basenames in the final batch; search an uncertain one under [README § Searching for Icons](../templates/icons/README.md); copy and validate in one batch — `python3 skills/ppt-master/scripts/icon_sync.py <project_path> <lib/name> [<lib/name> …]` — keeping each successful case-sensitive `lib/name` (bundled basenames are lowercase). Record each synced path with broad scenarios in §VI and the same pool, primary library, and any `stroke_width` in `spec_lock.md icons` (`simple-icons/*` ids join the inventory without becoming a second library; other prepared icons stay usable).
🚧 **GATE — missing icon = re-pick now**: on non-zero exit, search the missing concept only in the chosen library (or `simple-icons` for a brand), re-pick, and rerun the final batch until clean; never carry a missing icon forward or switch libraries to fill it. Search only unresolved concepts; never load or rebuild a full index.
@@ -170,76 +153,42 @@ AI illustrated icons are not a base option, add-on, field, or key — like decor
🚧 **GATE**: apply the chosen custom behavior and only the already-loaded `visual_style_references` files. The title carries the character; the body may stay neutral.
**Family selection**: user/template typography is authoritative — repeat fixed stacks with `typography.fixed: true` in every direction (reasonable repetition is non-blocking; no extra font round). Each direction carries `heading` / `body` `primary`, `css`, and a positive `body_size`, plus `english` only for a non-English deck. Delivery target: an explicit user/template target first, otherwise Windows Microsoft PowerPoint (owner: [`shared-standards-core.md`](./shared-standards-core.md) §4.1) — the authoring host's installed fonts never select a face; name concrete faces installed or approved on that target (the Confirm UI catalog is manual choice, not a whitelist); at most four families; a brand/web face leads only after user-confirmed installation, otherwise export a safe face and keep it as a Design Spec reference (fonts are not embedded; CSS tails are preview aids, not PowerPoint fallbacks). Avoid near-equivalent splits (YaHei↔PingFang, SimSun↔Songti, Arial↔Helvetica↔Segoe UI, Times↔Times New Roman). Fonts in one deck form contrast (different family, weight, or proportion) or concord (one family throughout); across the direction set include both a concord and a contrast pairing unless the user or template fixes the stack, and never default to title = body without a reason.
**Family selection**: user/template typography is authoritative — repeat fixed stacks with `typography.fixed: true` in every direction (reasonable repetition is non-blocking; no extra font round). Each direction carries `heading` / `body` `primary`, `css`, and a positive `body_size`, plus `english` only for a non-English deck. Delivery target, concrete-face naming, family count, brand/web faces, near-equivalent splits, contrast/concord pairing, and the PPT-safe face recall are [`plan-core.md`](./plan-core.md) §6.2; the Confirm UI catalog is manual choice, not a whitelist. Across the direction set include both a concord and a contrast pairing unless the user or template fixes the stack.
**Reference — PPT-safe faces (recall, not a whitelist; name one concrete face per script, never a comma stack)**: CJK sans `Microsoft YaHei` / `SimHei`, CJK serif `SimSun` / `FangSong` / `KaiTi` (their macOS counterparts `PingFang SC` / `Heiti SC` / `Songti SC` are preview aliases, never the named face), Latin sans `Arial` / `Calibri` / `Segoe UI` / `Verdana` / `Trebuchet MS`, Latin serif `Times New Roman` / `Georgia` / `Cambria` / `Palatino` / `Garamond`, mono `Consolas` / `Courier New`, display `Impact` / `Arial Black`. Let the locked style's character pick the axis and lead the title — `Microsoft YaHei` / `Arial` are the neutral members, never the automatic lead; a neutral sans title where the style asks for character is the failure to avoid. Non-pre-installed directions — retro/pixel Press Start 2P / VT323, rounded Nunito / Quicksand / OPPO Sans (safe substitute `Trebuchet MS` / `Verdana`), modern web Inter / HarmonyOS Sans / Source Han, calligraphic 隶书 / 华文行楷 / 华文新魏 (safe substitute `KaiTi` / `FangSong`, titles only), brand faces — need target installation or stay Design Spec references.
**Role extension after confirmation**: add recurring roles under [`plan-core.md`](./plan-core.md) §6.2 while authoring §IX and §IV; confirmation is not reopened, and one compact `Role rationale` line in §IV names any added role.
**Role extension after confirmation**: while authoring §IX and §IV, add a lowercase snake_case role with an exact stack only for a recurring role that materially needs a different family (`annotation`, `footer`, `footnote`, `data`, `emphasis`, `quote`, `code`), coherent with the confirmed heading/body system and locked style; one-off garnish stays omitted, confirmation is not reopened, and one compact `Role rationale` line in §IV names any added role.
**Size anchors — px only**: every layer carries bare px; PowerPoint pt (`px × 0.75`) is an export result. **Mandatory**: take the initial body anchor and sanity band from [`canvas-formats.md`](canvas-formats.md) § Typography Scale Start (never rederived here), and take Confirm UI `body_size` / `sizes` verbatim — a manually edited anchor stays pinned and a canvas change never rescales it.
| Recurring role | Ratio to body |
|---|---:|
| Cover title / single-focus hero | 2.55× |
| Chapter title | 22.5× |
| Page title / KPI hero | 1.52× |
| Subtitle | 1.21.5× |
| Lead / subheading | 1.11.4× |
| Body | 1× |
| Annotation | 0.70.85× |
| Footnote / page number | 0.50.65× |
Scan §IX before locking and declare every recurring role (`lead` at least body size; `footnote`; chart annotations when used), one deck-wide anchor each, snapped to clean even px (body 24 → title 42, subtitle 32, lead 30, annotation 18, footnote 16). Executor may vary one occurrence within ±2 px; a short non-structural Hero/Display size may stay undeclared for at most two planned occurrences, and the third requires a named slot — structural text never uses that exception.
**Size anchors — px only** ([`plan-core.md`](./plan-core.md) §6.2 owns the ratios and the recurring-role scan). **Mandatory**: take Confirm UI `body_size` / `sizes` verbatim — a manually edited anchor stays pinned and a canvas change never rescales it — and declare every recurring role before locking so no structural text depends on Executor's display exception.
#### Mathematical and hyperlink content
Record every source-backed equation under `Mathematical content` in the applicable §IX block as a LaTeX body without `$…$`, `$$…$$`, `\(…\)`, or `\[…\]` delimiters — never classified as inline or block, never invented for decoration, and never a policy, manifest, PNG, §VIII row, or lock entry; Executor owns the text-versus-native decision and returns here only for a content-level correction, including when the documented Microsoft 365 input profile cannot preserve the planned content. Record every explicit or source-backed link as the linked text/object plus its exact absolute URI or 1-based same-deck slide target — never guessed, never carrier-selected, never a manifest or lock entry; Executor authors it under [`native-hyperlinks.md`](./native-hyperlinks.md).
Record equations and links in §IX under [`plan-core.md`](./plan-core.md) §3 — never a policy, manifest, PNG, §VIII row, or lock entry; Executor owns the text-versus-native decision and returns here only for a content-level correction.
### Resource Need and Reference Planning (non-blocking; no user confirmation)
**Default — resource need from the roster (may stay implicit when a page's need is obvious)**: while composing the roster, decide which pages need a prepared image, lettering, or illustrated-icon resource — the jobs only a prepared file can serve — and derive §VIII rows from that need. The page's carrier mix itself (background, text, native geometry, imagery, icons, visualizations and their weights) is Executor's page decision and is never planned. Use existing fields: the icon basis and pool in §VI; an image, lettering, or illustrated-icon resource in §VIII only when the page assigns it a plausible job. Macro composition stays Reference; resource identities and explicit requirements keep their authority.
Resource need from the roster, the native-construction Hard rule, the capability opportunity signals, and the communication-job menu are [`plan-core.md`](./plan-core.md) §5; derive §VIII rows from that need and use existing fields only (icon basis and pool in §VI; image, lettering, or illustrated-icon resources in §VIII). Each capability hands off as follows:
**Hard rule — native construction stays downstream**: record each page's `Relationships`, resource roles, and any useful macro composition or visual-system Reference; never inventory or bind a preset, primitive, Connector, Boolean/freeform operation, coordinates, or authoring method. A technique may appear only as optional inspiration inside a macro Reference.
| Capability | Design Spec handoff |
|---|---|
| Image composition | Propose a permitted source; when selected, apply [`strategist-image.md`](./strategist-image.md), record a concise §VIII `Image pattern` in ordinary words, and state how several images relate in §IX `Images` |
| Composable illustration family | Plan transparent elements by compatible family under `strategist-image.md`, record fixed reuse or adaptive variation in §VIII `Reference`, and describe each page's carrier relationships in §IX |
| AI decorative lettering asset | Under `strategist-image.md`: preserve every exact string, group compatible marks, keep chrome/body native; the asset may carry the complete title as its display layer while a native title/subtitle stays in a separate frame wherever a searchable, selectable, or outline-visible heading is needed; never shorten copy toward a wordmark |
| Motion | Optional §IX `Motion suggestion`: the communication job, the units involved, and their meaningful order or initial → end state; effects, ids, options, and timing stay with Executor, and a suggestion never activates the custom stage |
| Capability | Opportunity signal | Design Spec handoff |
|---|---|---|
| Image composition | Image-as-canvas, editorial crop, collage, cutout, or meaningful focus / comparison / evidence units carry the page better than an adjacent rectangle | Propose a permitted source; when selected, apply [`strategist-image.md`](./strategist-image.md), record a concise §VIII `Layout pattern` in ordinary words, and state how several images relate in §IX `Images` |
| Composable illustration family | Pages benefit from coherent reusable title/corner ornaments, dominant anchors, supporting figures, compact illustrated-icon cues, or accents mixing with text, shapes, photos, or lettering | Plan transparent elements by compatible family under `strategist-image.md`, record fixed reuse or adaptive variation in §VIII `Reference`, and describe each page's carrier relationships in §IX |
| AI decorative lettering asset | Any stable display string — a complete long or multi-line title, cover hook, chapter word, place or product name, dish or exhibit name, year, hero number, pull quote, motif word — reads better with a material, dimensional, hand-rendered, or illustrative treatment than as ordinary text | Under `strategist-image.md`: preserve every exact string, group compatible marks, keep chrome/body native; the asset may carry the complete title as its display layer while a native title/subtitle stays in a separate frame wherever a searchable, selectable, or outline-visible heading is needed; never shorten copy toward a wordmark |
| Motion | A section/state change or continuity across adjacent pages, or a reveal / emphasis / movement order within a page, clarifies sequence, causality, comparison, or hierarchy | Optional §IX `Motion suggestion`: the communication job, the units involved, and their meaningful order or initial → end state; effects, ids, options, and timing stay with Executor, and a suggestion never activates the custom stage |
The information-model rule, the Chart/Table vocabulary Reference, and the validation command are [`plan-core.md`](./plan-core.md) §3 and §5.2; validate every selected reference before the lock.
**Mandatory — information model, not source object type**: qualitative `order` / `link` / `parent` / `membership` / `contrast` / `overlap` is written on the page's §IX `Relationships` line (its units and their source-stated relationship, or `none`; no catalog key, grammar atom, coordinate, shape, or named model — Executor decides at runtime whether geometry carries it); values, dates, or durations that determine geometry are a Chart; row header × column header facts are a Table, each compared against the complete loaded vocabulary.
**Reference — Chart/Table vocabularies**: the loaded vocabularies list what can be selected; they rank nothing, and custom objects and qualitative composition stay outside them. Choose at most one flexible `family/key` per page (children and qualitative relationships stay in §IX), keep `no-template-match` in §IX when none fits (never serialized), and validate every selected reference before the lock, correcting a failed selection by re-reading the complete vocabulary/registry:
```bash
python3 skills/ppt-master/scripts/visualization_recall.py validate \
<family>/<key> [<family>/<key> ...]
```
Write §VII as `Page | Family | Template | Usage` for each `chart|table` reference (Usage = semantic purpose; omit no-match), e.g. `| P03 | chart | line_chart | Compare the source metrics over time |`. **Native-ready boundary**: give every independent data chart and pure text-grid table in §IX `Visualization` a unique page-local `kebab-case` key and write one `Native-ready` map `<key>=yes|no; ...``yes` by default, `no` only when [`native-data-interface.md`](./native-data-interface.md) §2 cannot express the object; qualitative compositions and incidental microvisuals stay unlisted.
Write §VII as `Page | Family | Template | Usage` for each `chart|table` reference (Usage = semantic purpose; omit no-match), e.g. `| P03 | chart | line_chart | Compare the source metrics over time |`. **Native-ready boundary**: give every independent data chart and pure text-grid table in §IX `Visualization` a unique page-local `kebab-case` key and write one `Native-ready` map `<key>=yes|no; ...`; the `yes` / `no` criterion and what stays unlisted are [`plan-core.md`](./plan-core.md) §5.2.
### h. Image Source Recommendation
| Source id | Approach | Use when |
|---|---|---|
| `none` | No images | No source owns a meaningful communication job |
| `provided` | User-provided assets | Existing images carry factual, brand, product, or narrative authority |
| `ai` | AI-generated | Invented or deliberately stylized scenes, illustrations, backgrounds, metaphors, decorative lettering, or another generated treatment |
| `web` | Web-sourced | Named or evidence-bearing real-world subjects that must appear as themselves, plus generic photographic mood, background, or scene jobs |
| `placeholder` | Deferred | The image is required but will be supplied later |
Source ids (`none` / `provided` / `ai` / `web` / `placeholder`), the credentials Hard rule, and visual grounding before `none` are [`plan-core.md`](./plan-core.md) §5.1; Generate Step 5 is the first capability check.
If `images/` is non-empty, run `python3 scripts/analyze_images.py <project_path>/images` and read `analysis/image_analysis.csv` before recommending (rerun after changes).
**Hard rule — credentials never decide image need**: a missing `IMAGE_BACKEND`, host generation, or stock credential never justifies `none` or the deletion of a planned web role; do not inspect configuration or probe a provider — Generate Step 5 is the first capability check. When `ai` is included, preserve an explicit user path instruction, otherwise recommend `auto`.
**Default — visual grounding before `none` (may override when the full-roster review finds no image job)**: honor an explicit no-image requirement; otherwise, when the audience must recognize, experience, compare, or choose an externally verifiable subject, place, product, or setting, propose `provided` / `web`, and propose `ai` where invented or stylized expression materially improves a visual job. Mixed sources serve different roles; a rendering candidate resolves how imagery looks, never whether a real subject appears as itself.
**Proactive illustrated icons and lettering**: before each Stage-2 `recommend.image_usage`, run [`strategist-image.md`](./strategist-image.md)'s illustrated-icon and decorative-lettering candidate scan over the complete roster; a selected mark may be the sole AI job and may support an `ai` recommendation in `image_notes.value`; zero is valid without explanation, and explicit no-AI or editable-only requirements win.
**Proactive illustrated icons and lettering**: before each Stage-2 `recommend.image_usage`, run [`strategist-image.md`](./strategist-image.md)'s illustrated-icon and decorative-lettering candidate scan over the complete roster. A selected mark may be the sole AI job and may support an `ai` recommendation in `image_notes.value`. Zero is valid without explanation; explicit no-AI or editable-only requirements win.
**Recommendation output**: `recommend.image_usage` is one source id or an array (`none` exclusive). `image_notes.value` carries each source's intended jobs, authoritative assets, preferred/avoided imagery, placeholder tolerance, and — when `ai` is proposed — how generated visuals contribute, including any anticipated illustration, illustrated-icon, or lettering role: an open strategy, not an enum, allowlist, page assignment, count, or manifest. On confirmation map `ai→ai`, `web→web`, `provided→user`, `placeholder→placeholder` into §VIII `Acquire Via`.
**Always-on decision module; conditional resource extension**: the fixed planning batch (this module, the decision indexes, the icon contract, the Chart/Table vocabularies) is loaded before the directions; after the three intents are frozen, [`strategist-image.md`](./strategist-image.md) authors one complete custom rendering per direction before AI is decided. `recommend.image_usage` is derived independently from source needs; a confirmed non-`none` set activates its resource-planning sections, and confirmed `none` writes no rows while keeping the rendering candidates and composition vocabulary.
**Always-on decision module; conditional resource extension**: the fixed planning batch (this module, the decision indexes, the icon contract, the Chart/Table vocabularies) is loaded before the directions. After the three intents are frozen, [`strategist-image.md`](./strategist-image.md) authors one complete custom rendering per direction before AI is decided. `recommend.image_usage` is derived independently from source needs; a confirmed non-`none` set activates its resource-planning sections, and confirmed `none` writes no rows while keeping the rendering candidates and composition vocabulary.
### Speaker Notes Requirements
@@ -256,21 +205,19 @@ Note files match SVG names (`01_cover.svg` → `notes/01_cover.md`; `notes/slide
## 2. Mode & Visual-Style Catalogs (Reference for Confirmation Item d)
Mode: [`modes/_index.md`](./modes/_index.md) → `pyramid` / `narrative` / `instructional` / `showcase` / `briefing`. Visual style: [`visual-styles/_index.md`](./visual-styles/_index.md) → presets + `custom`. The three indexes are the only basis selectors; freeze each direction's bases from them and read only the deduplicated detail files; Executor later reads one locked preset file or a custom's exact references ([`generate-pptx`](../workflows/generate-pptx.md) Step 6).
Mode: [`modes/_index.md`](./modes/_index.md) → `pyramid` / `narrative` / `instructional` / `showcase` / `briefing`. Visual style: [`visual-styles/_index.md`](./visual-styles/_index.md) → presets + `custom`. Basis selection follows the §d Hard rule; Executor later reads one locked preset file or a custom's exact references ([`generate-pptx`](../workflows/generate-pptx.md) Step 6).
---
## 3. Color Selection Reference
Owned by §e: precedence, proportion, anchor tiers, and polarity ramps live there.
Owned by [`plan-core.md`](./plan-core.md) §6.1: precedence, proportion, anchor tiers, and polarity ramps live there; §e owns the six confirmed roles.
---
## 4. Layout Reference and Motif
## 4. Composition Reference and Motif
**Reference — a starting sketch, never a constraint**: a §IX `Layout` line names the macro relationship the page's content suggests (one focal claim, equal comparison, dominant evidence + takeaway, parallel sequence, core + surrounding forces, wide visual + explanation) in ordinary words; Executor owns the structure and geometry that realize it (its layout-structure vocabulary lives in [`executor-base.md`](./executor-base.md) Page Expression Core) and adjusts or replaces the line freely after reading the page. Never write element-level sizes or coordinates into §IX.
Once the roster and planned resources are known, recommend a cross-page motif or element family when it can carry identity or meaning — title/corner ornaments, a directional contour, an opening, a line lattice, an oversized numeral — recording its continuity job and reuse mode in §III `Theme` and mentioning it only in the §IX `Layout` blocks that benefit; Executor owns its geometry and may decline it; no motif field, lock row, or quota.
The §IX `Composition` line and the cross-page motif recommendation are [`plan-core.md`](./plan-core.md) §4: both are References Executor adjusts or declines; the motif's continuity job and reuse mode go in §III `Theme`.
---
@@ -282,26 +229,14 @@ Free-design patterns are starting points, not quotas: recommend a macro directio
### 6.1 Content Planning Strategy
Outline and, when enabled, notes strategy follow the locked mode ([`modes/_index.md`](./modes/_index.md), then the preset file or the custom's references plus behavior). Within any mode:
**Reading mode controls information carriage, not communication intent** — `delivery_purpose` is the compatibility key; the body baseline is a consequence:
| Reading mode | Primary carrier | §IX page grammar | Granularity / rhythm | Speaker notes |
|---|---|---|---|---|
| `text` · read-close | page / document | complete assertions, short prose paragraphs, captions, tables, and necessary detail; bullets only for genuinely parallel or ordered items | fewer, fuller pages; leans `dense` | supplemental context, not a substitute for missing page logic |
| `balanced` · business (default) | page + presenter | one primary claim with concise explanation, structured evidence, or a necessary list | moderate granularity; mixed rhythm | interpretation and transitions |
| `presentation` | presenter + visuals | one claim per page, keywords / short phrases, a large visual or hero number; no paragraph dumps or prose compressed into fragments | more, sparser pages; leans `anchor` / `breathing` | carries explanation, transitions, and supporting detail |
With notes disabled the last column is unavailable: every required meaning stays on the page or the confirmed presenter channel. Derive the initial mode from `audience`, `delivery_context`, and `artifact_afterlife`: asynchronous review, reference, approval, audit, and leave-behind lean `text`; presenter-led projection, large rooms, launches, and classrooms lean `presentation`; hybrid review / roadshow leans `balanced`, and `balanced` when live projection and durable afterlife both matter. A confirmed `presentation` supports afterlife through notes, appendix pages, captions, and visible sources rather than crowding slides. A `presentation` deck and a `text` deck from the same source and contract must differ in page grammar, count, text volume, visual burden, density, rhythm, and notes — not only in font size; page count stays the user's call. Record it as **Reading Mode** in `design_spec.md §I` (lock key `consumption_mode`); `page_rhythm` leans are a bias, not a quota; preservation paths honor it only in styling and notes.
**Per-block expression**: the semantic relationship chooses the form — prose for cause, argument, interpretation, and narrative continuity; bullets or numbers only for genuinely parallel, ordered, or enumerable items, never because copy is long or a template exposes a list slot. In `presentation`, distill one assertion and move explanation into enabled notes (or keep it on the page when notes are off). Source texture is a secondary cue. At `complete` depth write usable phrasing into §IX; at `brief` depth one bullet per block in the phrasing that fits, leaving page copy to authoring — neither is a skeleton: every claim, fact, relationship, and qualifier is present, and written wording is preferred wording unless literal preservation applies (Executor adapts under [`executor-base.md`](./executor-base.md) §2.1). §IX is the page brief at the confirmed depth; Executor retains it with the lock until context invalidation.
Outline and, when enabled, notes strategy follow the locked mode ([`modes/_index.md`](./modes/_index.md), then the preset file or the custom's references plus behavior). Within any mode, reading-mode carriage and per-block expression are [`plan-core.md`](./plan-core.md) §2 and §3: record the mode as **Reading Mode** in `design_spec.md §I` (lock key `consumption_mode`), and write §IX at the confirmed depth so Executor can retain it with the lock until context invalidation.
### 6.2 Planning Artifact Content
Generate Step 4 owns the sequence: `design_spec.md` is the complete human-readable decision, `spec_lock.md` its context-selected execution subset; `result.json` is consumed once and never reopened; refinement edits the same Design Spec, and the files are never parallel interpretations. A later explicit notes/animation/narration instruction updates only the affected §I outcome and provenance (animation provenance is final Stage 2 `false`, explicit objects-off, or explicit all-motion-off only the last includes transitions), after Generate's notes/audio dependency gate, without reopening Confirm UI or touching the lock.
Generate Step 4 owns the sequence: `design_spec.md` is the complete human-readable decision, `spec_lock.md` its context-selected execution subset; `result.json` is consumed once and never reopened; refinement edits the same Design Spec, and the files are never parallel interpretations. A later explicit notes/animation/narration instruction updates only the affected §I outcome and provenance, after Generate's notes/audio dependency gate, without reopening Confirm UI or touching the lock. Animation provenance is final Stage 2 `false`, explicit objects-off, or explicit all-motion-off; only the last includes transitions.
1. With the retained final confirmation, read `${SKILL_DIR}/templates/design_spec_reference.md`.
2. Compose the whole Design Spec in context and create `design_spec.md` once from the schema marker through §X. §I records production mechanics — one effective outcome plus provenance each for Speaker Notes, Custom Animations, and Narration Audio (latest explicit instruction → final Stage-2 proactive value → default enabled / disabled / disabled; narration enabled requires notes). §IX is the complete ordered roster: title, core message, **Audience move**, **Relationships** (the page's semantic units and their source-stated relationship, or `none`, at every depth), content at the confirmed depth, optional layout Reference, exact mathematics, capability recommendations, visualization/image references, sourced `Fact IDs`, and `Data class: scenario` for invented data. After Gate 1 and any refine approval, roster ids/count/order and semantic content are authoritative (a continuous run may repair within the confirmed range per `executor-base.md` §2.1); non-literal wording, texture, layout, cover/closing composition, capability recommendations, and image/visualization patterns stay References — starting sketches Executor adjusts freely — unless labeled `(binding)`.
2. Compose the whole Design Spec in context and create `design_spec.md` once from the schema marker through §X. §I records production mechanics — one effective outcome plus provenance each for Speaker Notes, Custom Animations, and Narration Audio (latest explicit instruction → final Stage-2 proactive value → default enabled / disabled / disabled; narration enabled requires notes). §IX is the complete ordered roster: title, core message, **Audience move**, **Relationships** (the page's semantic units and their source-stated relationship, or `none`, at every depth), content at the confirmed depth, optional Composition Reference, exact mathematics, capability recommendations, visualization/image references, sourced `Fact IDs`, and `Data class: scenario` for invented data. After Gate 1 and any refine approval, roster ids/count/order and semantic content are authoritative (a continuous run may repair within the confirmed range per `executor-base.md` §2.1); everything else in a block is a Reference under §1 Confirmed-value semantics unless labeled `(binding)`.
3. Compare `design_spec.md` with the final confirmation field by field and repair every omission before refinement or the lock.
4. When enabled, run [`refine-spec`](../workflows/stages/refine-spec.md) on that file; no lock before explicit approval.
5. Read `${SKILL_DIR}/templates/spec_lock_reference.md` and create or resynchronize the lock once from the approved Design Spec and context — identity, refinements, stable roles and routing; no page-local values, no reopened evidence, no new recommendation.
@@ -319,19 +254,21 @@ Generate Step 4 owns the sequence: `design_spec.md` is the complete human-readab
| Proactive notes, animations, narration | §I records the three effective outcomes with provenance; §X records note requirements or `Generation: disabled`; none enters the lock; §IX Motion suggestions stay advice |
| Explicit final/literal narration script | §IX segments by scene with a supporting visible state each; §X records source and verbatim policy; Generate freezes `notes/total.md` after Gate 2 |
**GATE 1 — active-decision fidelity**: no lock until the Design Spec passes that comparison and any refinement is approved; missing or substituted values, unapplied revisions, or silently changed semantic types block despite schema validity, while bounded Reference adaptation and unused Permission remain valid.
**GATE 1 — active-decision fidelity**: no lock until the Design Spec passes that comparison and any refinement is approved. Missing or substituted values, unapplied revisions, or silently changed semantic types block despite schema validity; bounded Reference adaptation and unused Permission remain valid.
**GATE 2 — lock context fidelity**: the lock may normalize syntax and add justified recurring roles but never changes identity, discards a refinement, introduces a direction, or becomes a field copy or allowlist; on contradiction return to Gate 1 (fresh recovery reads persisted final evidence once only when active state is absent).
**GATE 2 — lock context fidelity**: the lock may normalize syntax and add justified recurring roles but never changes identity, discards a refinement, introduces a direction, or becomes a field copy or allowlist. On contradiction return to Gate 1 (fresh recovery reads persisted final evidence once only when active state is absent).
**Execution lock content**: `spec_lock.md` carries communication, stable color/type anchors, icons, images, page rhythm, Chart/Table references, and route-specific structure; qualitative relationships stay in §IX. Grammar — section set, typography projection (`title_family` + `body_family` + every `<role>_family` and size anchor), `page_visualizations`, flat/structured `pptx_structure` — is [`spec_lock_reference.md`](../templates/spec_lock_reference.md) §24; never re-derive a confirmed anchor, collapse distinct stacks into `font_family`, or drop a recurring role. Derived paint and sparse local garnish may stay in one SVG; new base colors, structural fonts, resources, or recurring identity patterns require upstream repair, and Executor never reverse-projects a local choice as planning fact. **Hard rule — a lock prohibition is the user's**: `forbidden` takes the technical baseline plus prohibitions the user stated in their own words, each quoted verbatim and tagged `(user)` ([`spec_lock_reference.md`](../templates/spec_lock_reference.md) §2); a confirmed direction's behavior stays identity prose and is never projected into a prohibition.
**Execution lock content**: `spec_lock.md` carries communication, stable color/type anchors, icons, images, page rhythm, Chart/Table references, and route-specific structure; qualitative relationships stay in §IX. Grammar — section set, typography projection (`title_family` + `body_family` + every `<role>_family` and size anchor), `page_visualizations`, flat/structured `pptx_structure` — is [`spec_lock_reference.md`](../templates/spec_lock_reference.md) §24. Never re-derive a confirmed anchor, collapse distinct stacks into `font_family`, or drop a recurring role.
**Lock vs page-local values**: derived paint and sparse local garnish may stay in one SVG. New base colors, structural fonts, resources, or recurring identity patterns require upstream repair, and Executor never reverse-projects a local choice as planning fact.
**Hard rule — a lock prohibition is the user's**: `forbidden` takes the technical baseline plus prohibitions the user stated in their own words, each quoted verbatim and tagged `(user)` ([`spec_lock_reference.md`](../templates/spec_lock_reference.md) §2). A confirmed direction's behavior stays identity prose and is never projected into a prohibition.
- **Communication trace is mandatory**: keep the full contract in §I and project only `audience`, `objective` (one execution sentence preserving intent and the `audience_outcome` success condition), `core_message`, and `consumption_mode` into `spec_lock.md communication`. Before finalizing §IX, every named purpose has an outline obligation and every Slide block — cover, divider, closing included — has an `Audience move`; a page that advances nothing is merged, rewritten, or cut. Tools enforce presence, not quality.
- **Custom behavior is concise and executable**: one resolved `mode_behavior` / `visual_style_behavior` sentence or short paragraph plus exact `*_references` only when catalog entries are used; no selection history.
- **page_rhythm is mandatory**: one of `anchor` / `dense` / `breathing` per §IX page — what breaks the uniform card-grid feel; consumer omission behavior is `executor-base.md` §2.1's.
- **page_rhythm is mandatory**: one of `anchor` / `dense` / `breathing` per §IX page — what breaks the uniform card-grid feel; consumer omission behavior is `executor-base.md` §2.2's.
- **Fact IDs and scenario labels**: list the stable IDs actually used per page, never one whose claim is absent; mark invented KPIs, targets, and ratios `Data class: scenario` and say which values they are.
- **Mandatory — whole-roster rhythm check**: while composing §IX, compare neighbors and section arcs — chapter entries visibly reset; same-density, same-resource, or same-relationship runs are intentional sub-arcs; a repeated motif carries a continuity job; any visible-state sequence keeps a recognizable map while its next change is legible; each section follows a mode-fitting progression (including framework → explanation/evidence → judgment/action when it serves); the final arc resolves the objective before a genuine ending lowers load. Same section, equal density, one style, and precedent establish no sub-arc. Repair roster, `Layout`, and `page_rhythm` in place; preserve intentional continuity, legitimately all-`dense` material, and 1:1 order; add no filler — a `breathing` page marks a real pause and must stand alone. No field, lock row, artifact, or second pass.
- **Cover impact is mandatory**: give `P01` one concrete hook from the source's strongest claim, metaphor, number, moment, or conflict plus one optional composition Reference in ordinary words (a distilled display phrase may carry the cover while the complete title stays a native subtitle; with no suitable image, a native-SVG hook). The hook binds; the composition is a Reference. `P01` stays `anchor`, defaulting away from generic content-page templates unless content, user, or template makes a card grid, agenda, or equal-weight columns the clearest cover. Beautify preservation is exempt.
- **Closing impact (only when the deck closes)**: for a genuine conclusion, CTA, or final takeaway, name the binding takeaway plus a recommended composition; never an information-empty "Thank you", contact-only slide, or cover reprise (an explicit contact/event CTA may serve), and never an invented closing page. Preservation is exempt.
- **Whole-roster rhythm check, cover impact, and closing impact** are [`plan-core.md`](./plan-core.md) §4 and apply while composing §IX; the cover hook and closing takeaway bind, their compositions are References, and Beautify preservation is exempt.
- **pptx_structure and page_visualizations**: free-design, brand-only, and `template_reuse_scope: style` write `mode: flat` and omit every structured mapping section; `mirror|layout` writes `mode: structured` with `template_adherence` and the four mapping sections under [`strategist-template.md`](./strategist-template.md). Project at most one §VII `P<NN>: <chart|table>/<key>` per page; grammar in [`spec_lock_reference.md`](../templates/spec_lock_reference.md) §34.
---
@@ -11,7 +11,7 @@ Status names, resource lifecycle, and the embedding workflow for images in SVG p
Each image carries an `Acquire Via` field plus a status. Default Generate's authority is `design_spec.md §VIII` plus its lock projection (run `analyze_images.py` after confirmation when user images are selected and complete the list before Executor); Quick's is the main agent's active-context decisions (explicit user paths first, unspecified acquisition resolved automatically, all preparation finished before SVG authoring without confirmation or a persisted roster).
```markdown
| Filename | Dimensions | Purpose | Type | Layout pattern | Crop Policy | Acquire Via | Status | Reference |
| Filename | Dimensions | Purpose | Type | Image pattern | Crop Policy | Acquire Via | Status | Reference |
|----------|------------|---------|------|----------------|-------------|-------------|--------|-----------|
| team.jpg | 800x600 | Team photo | Photography | `Put faces behind the hiring claim; #P1-02 + #M2-08 fading the photo edge into the page so copy meets it without a frame` | adaptive | web | Pending | Diverse engineering team in modern office |
```
@@ -50,4 +50,4 @@ Keep external references in `svg_output/` during generation; Default's `finalize
`href` is the relative project path; `x`, `y`, `width`, `height` the display frame; `preserveAspectRatio` `xMidYMid slice` (center crop, like CSS `cover`), `xMidYMid meet` (complete display, like `contain`), or `none` (stretch — never for a `no-crop` source). A Base64 `data:` href is the `svg_final/` preview form produced by finalization, not an authoring form. `clipPath` on `<image>` is conditionally allowed under [`shared-standards-core.md`](./shared-standards-core.md) §1.2; when it does not fit, bake rounded corners into an alpha PNG before embedding.
Project layout: `images/` (assets), `sources/` (source files and their `*_files/` images), `svg_output/` (external references), `svg_final/` (Default-only embedded preview). Preview `svg_output/` through `python3 -m http.server -d <project_path> 8000` (browsers block cross-directory images on directly opened files). Native export keeps original image bytes by default (`--image-sizing cap`); explicit compact export uses `--image-sizing display --image-scale 2 --image-quality 85`, and `--no-image-optimize` forces original bytes.
Project layout: `images/` (assets), `sources/` (source files and their `*_files/` images), `svg_output/` (external references), `svg_final/` (Default-only embedded preview). Preview `svg_output/` through `python3 -m http.server -d <project_path> 8000` (browsers block cross-directory images on directly opened files). Image sizing and optimization flags at export: [`svg-pipeline.md`](../scripts/docs/svg-pipeline.md).
@@ -9,13 +9,20 @@ Generate reusable structured page templates inside the workspace selected by Cre
## Usage
- **Workspace root**: `library``skills/ppt-master/templates/<kind_dir>/<template_name>/`; `project` → the confirmed `<target_project>/`; template source is `<template_workspace>/templates/` in both; the Design Spec is the parent-resolved `<design_spec_path>` (library `templates/design_spec.md`, project `templates/design_spec.<kind>.<id>.md`).
- **Input**: the finalized brief (scope, target project, template ID, display name, kind, structural use cases or Deck application context, tone, theme mode, canvas, optional reference assets, accepted norms) plus, for a PPTX reference, the import workspace described in [`template-tools.md`](../scripts/docs/template-tools.md)`analysis/manifest.json`, `analysis/native_structure.json`, `sources/source.pptx` (never a template asset), `validation/conversion-report.json`, exported resources, immutable `svg/` layered backing and `svg/inheritance.json`, optional `svg-flat/`, and the editable `authoring-svg/` bundle with model-readable `authoring_summary.json` and tool-only `authoring_manifest.json`.
- **Input**: the finalized brief (scope, target project, template ID, display name, kind, structural use cases or Deck application context, tone, theme mode, canvas, optional reference assets, accepted norms) plus, for a PPTX reference, the import workspace described in [`template-tools.md`](../scripts/docs/template-tools.md).
**Hard rule — scope is execution metadata**: route files by `output_scope` / `target_project` but never write them into frontmatter. Deck/layout output always declares `native_structure_mode: structured`; never invent another structure mode.
**Workspace precondition**: the parent has resolved `<design_spec_path>` and checked all destinations (library `templates/` empty; the authoring root free of a bare spec, selected-kind spec, or roster; collision-free `images/`, `icons/imported/`, `exports/`; an isolated project-shaped root supplied when the other structural kind exists). Never begin final writes before that preflight passes.
**PPTX import interpretation**: placeholder guides in master/layout SVGs are layout signals — use manifest placeholder records for type/index/geometry/base style and copy no dashed boxes unless the design uses them; charts, SmartArt, diagrams, and OLE objects are source intent markers, not reusable decoration; asset filenames follow the manifest map. Use manifest facts for orientation; open screenshots or the PPTX only for visual cross-checking.
**PPTX import interpretation**:
| Import artifact | Reading |
|---|---|
| Placeholder guides in master/layout SVGs | Layout signals — use manifest placeholder records for type/index/geometry/base style and copy no dashed boxes unless the design uses them |
| Charts, SmartArt, diagrams, OLE objects | Source intent markers, not reusable decoration |
| Asset filenames | Follow the manifest map |
| Manifest facts | Orientation; open screenshots or the PPTX only for visual cross-checking |
| Mode | Authoritative inputs | Model-facing inputs |
|---|---|---|
@@ -24,7 +31,14 @@ Generate reusable structured page templates inside the workspace selected by Cre
**Mandatory — authored construction bundle**: as soon as `replication_mode` resolves to `standard` or `fidelity`, and before selecting any contour, read [`native-shape-authoring.md`](./native-shape-authoring.md) and [`preset-shape-vocabulary.md`](./preset-shape-vocabulary.md) completely; never load them for `mirror`.
**Hard rule — native objects are compiled output**: Theme, Master, Layout, and Placeholder are PowerPoint implementation objects, not template kinds. Layout owns topology, placement, semantic text roles, and spatial text behavior; Deck identity owns paint, typeface identity, and fixed identity assets, with application context describing the recurring family. Downstream `layout` scope resolves placeholder formatting from the Layout roles plus confirmed identity, reading mode, and type scale; `mirror` scope preserves source structure and comparable presentation in compact SVG. Compile the rules into one native graph without merging ownership.
**Hard rule — native objects are compiled output**: Theme, Master, Layout, and Placeholder are PowerPoint implementation objects, not template kinds. Compile the rules into one native graph without merging ownership.
| Owner | Owns |
|---|---|
| Layout | Topology, placement, semantic text roles, and spatial text behavior |
| Deck identity | Paint, typeface identity, and fixed identity assets, with application context describing the recurring family |
| Downstream `layout` scope | Resolves placeholder formatting from the Layout roles plus confirmed identity, reading mode, and type scale |
| Downstream `mirror` scope | Preserves source structure and comparable presentation in compact SVG |
| Mode | Output structure contract |
|---|---|
@@ -33,7 +47,7 @@ Generate reusable structured page templates inside the workspace selected by Cre
Every output is a complete standalone Slide preview resolving Master + Layout + Slide context with explicit layer markers; standalone Master/Layout definition SVGs are not template artifacts.
**Authored preset rule**: in `standard` / `fidelity`, when one registered preset exactly expresses one complete object, use `preset_shape_svg.py` per [`native-shape-authoring.md`](./native-shape-authoring.md); its compact canonical `<g>` is one semantic atom after validation — Slide-local, the one carrier of an `object` slot, or a Master/Layout fixed layer — and the only `<g>` exception to fixed-layer atomicity. Paint comes from the brief and spec color scheme. Never copy an expanded import carrier/preview/fingerprint bundle into an authored template; `mirror` authors from the compact parsed SVG and never transplants the lossless subtree. When one preset is insufficient, apply the same reference's compound-page gate. Syntax and validation are owned by `shared-standards-core.md` and the native-shape reference.
**Authored preset rule**: in `standard` / `fidelity`, when one registered preset exactly expresses one complete object, use `preset_shape_svg.py` per [`native-shape-authoring.md`](./native-shape-authoring.md). Its compact canonical `<g>` is one semantic atom after validation — Slide-local, the one carrier of an `object` slot, or a Master/Layout fixed layer — and the only `<g>` exception to fixed-layer atomicity. Paint comes from the brief and spec color scheme. Never copy an expanded import carrier/preview/fingerprint bundle into an authored template; `mirror` authors from the compact parsed SVG and never transplants the lossless subtree. When one preset is insufficient, apply the same reference's compound-page gate. Syntax and validation are owned by `shared-standards-core.md` and the native-shape reference.
**Hard rule — reachable mirror graph**: exactly one prototype per source Slide, preserving only the transitive `Slide → Layout → Master` chain; identities outside that closure produce no SVG (re-author useful ones through `standard` / `fidelity`).
@@ -55,15 +69,38 @@ Every output is a complete standalone Slide preview resolving Master + Layout +
### Standard mode
`01_cover.svg` (title, subtitle, date, organization), `02_chapter.svg` (chapter number and title), `03_content.svg` (header/footer only; content area free), `04_ending.svg` (thank-you, contact), optional `02_toc.svg` (TOC title, chapter list) which shifts later types by one (`01_cover`, `02_toc`, `03_chapter`, `04_content`, `05_ending`). **Default — compact authored roster (may override when the confirmed Deck application requires distinct roles)**: keep Layout content pages structurally flexible; for Deck add only the prototypes its confirmed roles need, never variants from hypothetical uses. `standard` may hold several Layouts for one canonical role when the brief requires genuinely different structures (two-column evidence vs three-card KPI), suffixing every sibling (`03a_content_two_col.svg`, `03b_content_three_card.svg`) rather than leaving one unsuffixed; this does not require `fidelity`. The numeric prefix is the template's own order with a contiguous base sequence; tooling reads the page type from the token after the underscore.
`01_cover.svg` (title, subtitle, date, organization), `02_chapter.svg` (chapter number and title), `03_content.svg` (header/footer only; content area free), `04_ending.svg` (thank-you, contact), optional `02_toc.svg` (TOC title, chapter list) which shifts later types by one (`01_cover`, `02_toc`, `03_chapter`, `04_content`, `05_ending`).
**Default — compact authored roster (may override when the confirmed Deck application requires distinct roles)**: keep Layout content pages structurally flexible; for Deck add only the prototypes its confirmed roles need, never variants from hypothetical uses.
**Sibling Layouts in `standard`**: `standard` may hold several Layouts for one canonical role when the brief requires genuinely different structures (two-column evidence vs three-card KPI), suffixing every sibling (`03a_content_two_col.svg`, `03b_content_three_card.svg`) rather than leaving one unsuffixed; this does not require `fidelity`. The numeric prefix is the template's own order with a contiguous base sequence; tooling reads the page type from the token after the underscore.
### Fidelity mode
Design a broader roster close to the source's visual language with an independently authored Master/Layout system. Variants append a lowercase letter to the parent index (`02a_chapter_full.svg`, `02b_chapter_minimal.svg`, `03a_content_two_col.svg`, `03b_content_data_card.svg`, `03c_content_quote.svg`, `04a_ending_thanks.svg`); extension types (transition / appendix / disclaimer / divider) take the next free index (`05_section_break.svg`, `06_appendix.svg`). Choose variants from useful composition types (two-column, hero image, icon grid, data card, quote); keep only genuinely useful authored compositions — source Layout keys and repeated chrome are not clustering inputs; design each variant's contract from its reusable behavior; record every page in `§V` (library registration derives the index entry from `templates/*.svg`). Variants reuse the parent placeholder set (§4).
Design a broader roster close to the source's visual language with an independently authored Master/Layout system. Choose variants from useful composition types (two-column, hero image, icon grid, data card, quote); keep only genuinely useful authored compositions — source Layout keys and repeated chrome are not clustering inputs. Design each variant's contract from its reusable behavior; record every page in `§V` (library registration derives the index entry from `templates/*.svg`). Variants reuse the parent placeholder set (§4).
| Page kind | Naming |
|---|---|
| Variants | Append a lowercase letter to the parent index (`02a_chapter_full.svg`, `02b_chapter_minimal.svg`, `03a_content_two_col.svg`, `03b_content_data_card.svg`, `03c_content_quote.svg`, `04a_ending_thanks.svg`) |
| Extension types (transition / appendix / disclaimer / divider) | Take the next free index (`05_section_break.svg`, `06_appendix.svg`) |
### Mirror mode
Author a new compact workspace from validated parsed evidence rather than a different system. Create Layout mirror is legal only when the source contract is already brand-neutral and application-neutral; otherwise return to dispatch (author a Layout through `standard` / `fidelity`, or retain a Deck) — removing, repainting, retyping, or discarding rules is never mirror. Model-facing source: `authoring_summary.json`, every reachable layered `authoring-svg/*.svg`, `svg/inheritance.json`, `native_structure.json`; inspect and where needed redraw these before publication; never read `authoring_manifest.json`; lossless `svg/` is immutable evidence. Precondition: the evidence identifies every source Slide with its Layout/Master, picker names, placeholder contract, and fixed layers — stop when reachable facts or supported geometry are missing. Output `<template_workspace>/templates/<NNN>_<page_type>.svg` per source Slide (type from `pageTypeCandidates`, fallback `content`), no standalone Master/Layout SVG, each resolving full context with explicit layer markers. Preserve within the closure: keys and picker names, parentage, assignments, placeholder type/index/bounds, example meaning, sprite-sheet crop behavior, supported native facts; imported Chart/Table JSON is authoritative with an approximate preview. Allowed: redrawing geometry, paint spelling, grouping, root declarations, asset paths, and fixed-layer wrappers while presentation and ownership stay intact. Forbidden: commonality extraction, synthesis, promotion/demotion, renaming, re-parenting, placeholder invention, JSON changes without intent, visible redesign. Mirror describes source-to-workspace fidelity and only makes literal reuse possible; Strategist independently decides selection, repetition, order, and reorganization. Mirror is not a recovery mode: charts, SmartArt, OLE, and EMF/WMF that fail to enter the parsed evidence stay gaps — report them before authoring.
Author a new compact workspace from validated parsed evidence rather than a different system. Create Layout mirror is legal only when the source contract is already brand-neutral and application-neutral; otherwise return to dispatch (author a Layout through `standard` / `fidelity`, or retain a Deck) — removing, repainting, retyping, or discarding rules is never mirror.
**Model-facing source**: `authoring_summary.json`, every reachable layered `authoring-svg/*.svg`, `svg/inheritance.json`, `native_structure.json`; inspect and where needed redraw these before publication; never read `authoring_manifest.json`; lossless `svg/` is immutable evidence.
**Precondition**: the evidence identifies every source Slide with its Layout/Master, picker names, placeholder contract, and fixed layers — stop when reachable facts or supported geometry are missing.
**Output**: `<template_workspace>/templates/<NNN>_<page_type>.svg` per source Slide (type from `pageTypeCandidates`, fallback `content`), no standalone Master/Layout SVG, each resolving full context with explicit layer markers.
| Mirror boundary | Content |
|---|---|
| Preserve within the closure | Keys and picker names, parentage, assignments, placeholder type/index/bounds, example meaning, sprite-sheet crop behavior, supported native facts; imported Chart/Table JSON is authoritative with an approximate preview |
| Allowed | Redrawing geometry, paint spelling, grouping, root declarations, asset paths, and fixed-layer wrappers while presentation and ownership stay intact |
| Forbidden | Commonality extraction, synthesis, promotion/demotion, renaming, re-parenting, placeholder invention, JSON changes without intent, visible redesign |
Mirror describes source-to-workspace fidelity and only makes literal reuse possible; Strategist independently decides selection, repetition, order, and reorganization. Mirror is not a recovery mode: charts, SmartArt, OLE, and EMF/WMF that fail to enter the parsed evidence stay gaps — report them before authoring.
---
@@ -126,15 +163,37 @@ One row per Slide SVG: background, decorative anchors, rhythm, image behavior, d
## VII. Placeholder Overrides (omit when none)
```
**Layout**: `layout_id`, `kind: layout`, `category: general | scenario | government | special`, `summary`, `keywords`, the canvas and source-canvas fields, `replication_mode`, `native_structure_mode: structured`, `page_count`, `page_types: [cover, toc, chapter, content, ending]`, optional `placeholders:`; body sections **IV** (structure-specific grid, zones, chrome, image behavior, density, semantic text roles, alignment/wrapping/capacity, slot conventions; neutral preview paint is not identity), **V** (one row per SVG with Layout key, picker name, content shape, slot behavior; mirror map as above), and **VII** when overrides exist. Omit Template Overview, Color Scheme, Typography, Logo, Voice & Tone, and Icon Style; a scenario category records geometric fit only; never prescribe objectives, outcomes, narrative order, boilerplate, or example retention — the frontmatter `summary` carries selection context.
**Layout**:
| Part | Content |
|---|---|
| Frontmatter | `layout_id`, `kind: layout`, `category: general | scenario | government | special`, `summary`, `keywords`, the canvas and source-canvas fields, `replication_mode`, `native_structure_mode: structured`, `page_count`, `page_types: [cover, toc, chapter, content, ending]`, optional `placeholders:` |
| **IV** | Structure-specific grid, zones, chrome, image behavior, density, semantic text roles, alignment/wrapping/capacity, slot conventions; neutral preview paint is not identity |
| **V** | One row per SVG with Layout key, picker name, content shape, slot behavior; mirror map as above |
| **VII** | Only when overrides exist |
| Omitted | Template Overview, Color Scheme, Typography, Logo, Voice & Tone, Icon Style |
A scenario category records geometric fit only. Never prescribe objectives, outcomes, narrative order, boilerplate, or example retention — the frontmatter `summary` carries selection context.
### 2. Inherit Design Specification
Templates strictly follow the brief and `<design_spec_path>`: root `viewBox` equals `canvas_viewbox` (`width` / `height` optional and non-authoritative); with a PPTX/SVG reference record `source_canvas_*` and `source_viewbox`, and normalize all geometry, typography, strokes, and crops explicitly when the output canvas differs; colors, fonts, margins, image system, and Deck application follow the spec. With import output, prefer imported theme values over guesses, reuse exported `images/` directly, and treat `pageTypeCandidates` as hints. Preconditions: `standard` inspects the complete lightweight Master/Layout inventory plus enough page IR to understand direction and assets; `fidelity` inspects every Master/Layout and page; `mirror` verifies every Slide and chain against the summary, `native_structure.json`, and `inheritance.json`, reports retained/omitted identities before authoring, then publishes only that graph.
Templates strictly follow the brief and `<design_spec_path>`: root `viewBox` equals `canvas_viewbox` (`width` / `height` optional and non-authoritative). With a PPTX/SVG reference record `source_canvas_*` and `source_viewbox`, and normalize all geometry, typography, strokes, and crops explicitly when the output canvas differs. Colors, fonts, margins, image system, and Deck application follow the spec. With import output, prefer imported theme values over guesses, reuse exported `images/` directly, and treat `pageTypeCandidates` as hints.
| Mode | Inspection precondition |
|---|---|
| `standard` | The complete lightweight Master/Layout inventory plus enough page IR to understand direction and assets |
| `fidelity` | Every Master/Layout and page |
| `mirror` | Every Slide and chain verified against the summary, `native_structure.json`, and `inheritance.json`; retained/omitted identities reported before authoring; then only that graph is published |
#### 2.1 PPTX Import Mode Rule
`standard` reviews complete evidence, then authors a compact canonical roster and structure; `fidelity` authors a broader source-aligned roster matching the visual language without one-to-one identity retention; `mirror` preserves validated Slides, inheritance, placeholders, native facts, meaning, and presentation while authoring a compact workspace — visible SVG may be redrawn, retained structure cannot be renamed, gaps cannot be invented. **Hard rule — mirror publication is mechanical, visual authoring is not**: the materializer validates identity/SHA, refs, graph, assignments, and closure, composes inherited context, strips IR-only refs, and publishes the current tree; it never replaces an unchanged visible subtree with lossless XML.
| Mode | Authoring |
|---|---|
| `standard` | Reviews complete evidence, then authors a compact canonical roster and structure |
| `fidelity` | Authors a broader source-aligned roster matching the visual language without one-to-one identity retention |
| `mirror` | Preserves validated Slides, inheritance, placeholders, native facts, meaning, and presentation while authoring a compact workspace — visible SVG may be redrawn, retained structure cannot be renamed, gaps cannot be invented |
**Hard rule — mirror publication is mechanical, visual authoring is not**: the materializer validates identity/SHA, refs, graph, assignments, and closure, composes inherited context, strips IR-only refs, and publishes the current tree; it never replaces an unchanged visible subtree with lossless XML.
#### 2.2 Native Shape Payload and Authoring IR
@@ -145,18 +204,18 @@ Templates strictly follow the brief and `<design_spec_path>`: root `viewBox` equ
| `standard` / `fidelity` output | Newly authored contract | Editable primitives, compact canonical preset groups for exact matches, `shape_boolean_svg.py` only where one compound contour must become an object, necessary freeform last; paint from the brief/spec; exported assets reused, never opaque payload or source topology |
| `mirror` output | Compact preservation contract | Publishes the reviewed tree, preserves validated structure/native facts, recovers only supported non-visible semantics, normalizes fixed layers into semantic atoms, strips IR-only refs |
Materialization validates document hashes, refs, and closure and classifies subtree hashes — a changed subtree is a legitimate edit, never permission to copy the old tree back; an object that cannot use supported non-visible metadata keeps its SVG fallback and is reported. `data-pptx-replace-with` stays reserved for Chart/Table replacement markers.
Materialization validates document hashes, refs, and closure and classifies subtree hashes — a changed subtree is a legitimate edit, never permission to copy the old tree back. An object that cannot use supported non-visible metadata keeps its SVG fallback and is reported. `data-pptx-replace-with` stays reserved for Chart/Table replacement markers.
| Authored/preserved fact | Template SVG declaration |
Every template SVG satisfies the structured metadata contract of [`pptx-structure-interface.md`](./pptx-structure-interface.md) §2, and a legacy contract (its §3) never enters a package. Template-side additions:
| Concern | Template rule |
|---|---|
| Master/Layout identity | Root `data-pptx-master` / `-master-name` / `data-pptx-layout` / `-layout-name`; authored keys for `standard` / `fidelity`, source keys for `mirror` |
| Authored Master/Layout visual | Direct atomic child with `data-pptx-layer="master|layout"` and `data-pptx-editable="false"`; ordinary `<g>` forbidden, one validated compact preset `<g>` the sole exception |
| Preserved source visual | Direct atoms with the same ownership and comparable paint order; grouping and spelling may differ, regrouping and ownership changes may not |
| Content slot | Direct `<g id>` with `data-pptx-placeholder` and explicit `data-pptx-bounds`; authored modes author the slot, mirror preserves source type/index/bounds and carrier identity |
| Page-only background | Direct full-canvas solid rect with `data-pptx-layer="slide"` |
| Structural hint | Optional `data-pptx-role` only when layer/placeholder metadata cannot express background/decoration/header/footer/logo/watermark/chrome/page-number behavior; stable unique `id` |
Repeat inherited visuals in every standalone SVG so preview stays complete; export validates their equality and infers no ownership. **Forbidden — legacy contract**: never carry `data-pptx-layout-kind`, `distilled`, `utility`, unmapped `baseline`, `preserve`, or direct atomic placeholders into a package; such Type B input is visual reference only, and native topology requires the Type A path. **Composite slot boundary**: a normal slot has exactly one compatible carrier (a validated preset `<g>` counts for `object`; an ordinary group does not); only a genuinely composite region uses `data-pptx-placeholder="object"` + `data-pptx-binding="proxy"`, never as the default form. Mirror preserves imported types, indices, bounds, and carriers exactly (never replacing `subTitle`, `obj`, `media`, or `dt` with generic body); authored modes assign `title`, `subtitle`, `body`, `picture`, `chart`, `table`, `object`, `media`, `date`, `footer`, `slide-number` deliberately, with indices only to disambiguate repeated roles. **Hard rule — explicit design-zone bounds**: every slot carries `data-pptx-bounds="x y width height"` (≤ two decimals) from the source Layout frame (mirror) or the intended safe area, column, panel inset, or media frame (authored) — never from character count, glyph width, wrapping, or the sample-content box; zero-slot Layouts are valid.
| Fixed atoms | Authored Master/Layout atoms also carry `data-pptx-editable="false"`; preserved source atoms keep their ownership and comparable paint order (grouping and spelling may differ, regrouping may not) |
| Keys | `standard` / `fidelity` write authored keys; `mirror` preserves the source keys, picker names, placeholder types/indices/bounds, and carrier identity exactly (never replacing `subTitle`, `obj`, `media`, or `dt` with generic body) |
| Slot roles | Authored modes assign `title`, `subtitle`, `body`, `picture`, `chart`, `table`, `object`, `media`, `date`, `footer`, `slide-number` deliberately, with indices only to disambiguate repeated roles |
| Slot bounds | Authored slots derive `data-pptx-bounds` from the intended safe area, column, panel inset, or media frame — never from character count, glyph width, wrapping, or the sample-content box; mirror keeps the source Layout frame |
| Inherited visuals | Repeated in every standalone SVG so preview stays complete; export validates their equality and infers no ownership |
| Source refs | Final templates contain no `data-pptx-source-ref` |
### 3. Placeholder Markers
@@ -202,7 +261,16 @@ Both scopes share one workspace shape; only the root differs:
└── exports/ <deck_id|layout_id>_template_preview.pptx when requested or multi-Master
```
**Hard rule — common routing**: spec, SVGs, and non-bitmap template-source assets in `templates/`; every bitmap in `images/`; each imported vector once in `icons/imported/` referenced as `data-icon="imported/<name>"`; never `templates/icons/`; a review deck in `exports/` on request and always for multi-Master; no optional directory created merely to exist; no asset placement branching by scope.
**Hard rule — common routing**:
| Asset | Location |
|---|---|
| Spec, SVGs, non-bitmap template-source assets | `templates/` |
| Every bitmap | `images/` |
| Each imported vector | Once in `icons/imported/`, referenced as `data-icon="imported/<name>"`; never `templates/icons/` |
| Review deck | `exports/` on request and always for multi-Master |
No optional directory is created merely to exist; no asset placement branches by scope.
**Template Preview**: on request or for multiple Masters, run `template_preview_pptx.py <template_workspace>` after validation ([`template-tools.md`](../scripts/docs/template-tools.md#template_preview_pptxpy)); include the path in the completion summary and omit `exports/` only for an unrequested one-Master package. For import-based templates, note which extracted assets were reused, which references influenced the authored roster, what mirror could not preserve, and any page-type mapping that needed judgment.
@@ -2,7 +2,7 @@
# Topology Assembly Reference
Generative material for turning one resolved qualitative topology into editable native-shape components with coherent relative registration, before coordinates. Default and Quick read it once with `executor-structure.md` at the first `Structure=yes` page and reuse it for every later assembly.
Generative material for turning one resolved qualitative topology into editable native-shape components with coherent relative registration, before coordinates. Default and Quick read it once with `executor-structure.md` at the first `topology=yes` page and reuse it for every later assembly.
**Hard rule — relative constraints, never copyable geometry**: state exact preset or primitive identities, semantic counts, inter-component relations, and only the relative geometry that makes the assembly hold; never coordinates, points, sizes, ratios, adjustment values, path data, SVG fragments, full-page frames, copy, color, styling, or page composition. Materialize every adopted call through `native-shape-authoring.md`.
@@ -107,18 +107,13 @@ an exact authoring preset here.
## 3. Editable `custom` projection
Each Default Stage-2 direction authors one visible, non-empty `custom` aesthetic under [`strategist.md`](../strategist.md) §d — its executable shape language, composition geometry, decoration density, whitespace, typography character, and texture — naming only the catalog bases it actually uses; freeze those ids from this index, then read only their files before writing the behavior. Quick resolves one preset or custom behavior the same way and persists nothing.
Each Default Stage-2 direction authors one visible, non-empty `custom` aesthetic under [`strategist.md`](../strategist.md) §d — its executable shape language, composition geometry, decoration density, whitespace, typography character, and texture — naming only the catalog bases it actually uses. Quick resolves one preset or custom behavior under [`quick-generate.md`](../../workflows/profiles/quick-generate.md) §2 and persists nothing.
---
## 4. How to use
| Active profile | Use |
|---|---|
| Default Generate | Strategist reads only this index while mapping three whole solution intents, freezes each custom direction's exact bases, then reads only their deduplicated detail files. Executor reads the confirmed preset file or exact custom references. |
| Quick Generate | The current main agent reads only this index while deciding, then reads the resolved preset or exact custom bases and retains that one direction without Design Spec/lock. |
**Resolution scope**: deck-wide (one style per deck). It anchors taste as a
**Resolution scope**: deck-wide (one style per deck); Executor reads the confirmed preset file or exact custom references. It anchors taste as a
**reference**, not a whitelist. Each §1 `Composition geometry` list is
generative vocabulary, not a finite layout menu; pages may synthesize or
deviate when their communication job calls for it.
@@ -314,7 +314,7 @@ def print_results(results: list[ImageAnalysis]) -> None:
print(
f"\n{'No.':<4} {'Width':<7} {'Height':<7} {'Ratio':<7} "
f"{'Source':<8} {'Refs':<5} {'Size':<10} {'Category':<20} {'Filename'}"
f"{'Source':<8} {'Uses':<5} {'Size':<10} {'Category':<20} {'Filename'}"
)
print("-" * REPORT_WIDTH)
@@ -1049,8 +1049,13 @@ def _wait_for_server_ready(
proc: subprocess.Popen,
project_path: Path,
timeout: int = STARTUP_TIMEOUT,
) -> bool:
"""Wait until this project's detached confirm server is accepting requests."""
) -> int:
"""Wait until this project's detached confirm server is accepting requests.
Returns the server pid recorded in the project lock, or 0 on timeout.
``proc.pid`` is not used for identity: on Windows a venv ``python.exe``
may be a launcher whose child is the real interpreter.
"""
deadline = time.time() + timeout
last_error = ''
health_url = _server_url(port, '/api/health')
@@ -1058,18 +1063,22 @@ def _wait_for_server_ready(
returncode = proc.poll()
if returncode is not None:
logger.error('confirm UI exited during startup (code=%s)', returncode)
return False
return 0
try:
with urllib.request.urlopen(health_url, timeout=1) as resp:
data = json.load(resp)
lock = _read_lock(project_path / LOCK_FILE_NAME)
server_pid = _lock_pid(lock)
if (
resp.status == 200
and isinstance(data, dict)
and data.get('service') == 'confirm_ui'
and data.get('project') == str(project_path)
and data.get('pid') == proc.pid
and lock is not None
and lock.get('port') == port
and data.get('pid') == server_pid
):
return True
return server_pid
last_error = 'health response belongs to another service or project'
except (OSError, ValueError, urllib.error.URLError) as exc:
last_error = str(exc)
@@ -1080,7 +1089,7 @@ def _wait_for_server_ready(
timeout,
f' (last error: {last_error})' if last_error else '',
)
return False
return 0
def _launch_background_server(
@@ -1115,13 +1124,14 @@ def _launch_background_server(
logger=logger,
)
logger.info('log: %s', log_path)
if not _wait_for_server_ready(port, proc, project_path):
server_pid = _wait_for_server_ready(port, proc, project_path)
if not server_pid:
if proc.poll() is None:
proc.terminate()
raise RuntimeError(f'confirm UI failed to become reachable: {_server_url(port)}')
_sync_session_state(confirm_dir, server_port=port, event='server-ready')
url = _server_url(port)
logger.info('started confirm UI in background: %s (pid=%s)', url, proc.pid)
logger.info('started confirm UI in background: %s (pid=%s)', url, server_pid)
if open_browser:
webbrowser.open(url)
return proc, port, log_path
@@ -12,7 +12,7 @@ The fixture deliberately closes the full planning and execution chain:
- `design_spec.md` carries `Motion suggestion`, one current §VIII image row,
and `Crop Policy`, with no native-shape planning field;
- `spec_lock.md` projects that row (`source`, `crop`); the `#M1-11` layout pattern stays in §VIII;
- `spec_lock.md` projects that row (`source`, `crop`); the `#M1-11` image pattern stays in §VIII;
- both pages reuse one raster through ordinary, ellipse-preset, and custom-path
independent nested crops;
- `animations.json` pairs the main crop across adjacent Morph pages;
@@ -133,7 +133,7 @@ preset = (
## VIII. Image Resource List
| Filename | Dimensions | Ratio | Purpose | Type | Layout pattern | Crop Policy | Acquire Via | Status | Reference | text_policy | page_role |
| Filename | Dimensions | Ratio | Purpose | Type | Image pattern | Crop Policy | Acquire Via | Status | Reference | text_policy | page_role |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| scene.png | 1280x720 | 16:9 | Morph crop continuity | Photo | #M1-11 same-source independent crops with a shaped detail | adaptive | user | Existing | Synthetic three-band scene for crop and Morph verification | none | local |
@@ -63,6 +63,9 @@ Useful options:
- Unknown backend-specific flags are passed through to each selected converter.
- `-o/--output` selects one Markdown file for one input, or an output directory
for multiple inputs / directory inputs.
A path that names an existing directory, or ends in `/`, is always treated as
a directory, even for a single input: the file keeps its default `<stem>.md`
name inside it.
For multi-source project intake, use `project_manager.py import-sources` with
all source paths / URLs. For local files, the default is to keep generated
@@ -627,7 +630,7 @@ block Python's default TLS fingerprint. No extra flags needed. If
`curl_cffi` is not available, it falls back to plain `requests`.
On success, the converter uses the shared best-effort sidecar contract for
`<output>.conversion_profile.json` beside the Markdown output.
`<stem>.conversion_profile.json` beside the Markdown output.
`--emit-result` is for wrapper scripts that need the actual saved Markdown path
when the converter derives a title-based filename.
@@ -146,6 +146,12 @@ MINIMAX_API_KEY=your-api-key
# MINIMAX_MODEL=image-01
```
## `image_gen.py --manifest` runner and legacy manifest spellings
Validates the file behind every `Generated` row before skipping it, iterates retryable rows with bounded adaptive concurrency, and writes each status atomically; a missing or corrupt file returns to `Failed`, and persistent rate limits end the run as retryable `Failed`. Options: `--concurrency` (default `IMAGE_CONCURRENCY` or 3; halves on rate limit, min 1), `--image_size`, `--output`/`-o`, `--backend`/`-b`, `--model`/`-m`, `--list-backends`. Interrupting is safe (completed items stay `Generated`); the Markdown sidecar re-renders on completion, or run `--render-md` after an interruption. Configuration: process environment first, then the first `.env` in cwd, the skill directory, the clone root, `~/.ppt-master/.env``IMAGE_BACKEND` (required; `--list-backends` shows the set and support tiers), `IMAGE_CONCURRENCY`, provider-specific `{PROVIDER}_API_KEY` / `_BASE_URL` / `_MODEL` (never `IMAGE_API_KEY` / `IMAGE_MODEL` / `IMAGE_BASE_URL`), and for OpenAI-compatible platforms `OPENAI_SIZE_PRESET` (`auto|legacy|gpt-image|gpt-image-2|dall-e-2`), `OPENAI_RESPONSE_FORMAT` (`auto|b64_json|url|omit`), `OPENAI_QUALITY` (`auto|omit|low|medium|high|standard|hd`) under `IMAGE_BACKEND=openai`; see `.env.example`. The single-image form `image_gen.py "prompt" --filename …` remains for ad-hoc re-rolls.
**Compatibility**: legacy `type` values read as `background``hero_page` + no type, `hero``hero_page` + Primitive A, `portrait``local` + Primitive B, `typography``hero_page` + `embedded` + Primitive C; a missing `page_role` is `local`, a missing `text_policy` is `none` (one aggregate warning per manifest); an existing manifest lacking `deck_rendering` or an item lacking `type` replays its assembled `prompt` verbatim without reconstruction; a legacy `deck_style_anchor` or `deck_palette` never overrides `deck_rendering` / `color_scheme`; legacy `page_role: full_page` reads as `hero_page`.
## `image_treat.py`
Create a non-destructive PNG derivative from one bitmap already prepared under
@@ -164,11 +170,15 @@ python3 scripts/image_treat.py projects/demo hero.jpg \
python3 scripts/image_treat.py projects/demo hero.jpg \
--output hero_duotone.png --duotone "#14213D" "#FCA311"
python3 scripts/image_treat.py projects/demo title_art.png \
--output title_art_fit.png --fit 920x228
```
Supported operations are brightness, contrast, desaturation/grayscale,
duotone, and Gaussian blur. They compose in a fixed order: brightness →
contrast → tone treatment → blur. Desaturation, grayscale, and duotone are
duotone, Gaussian blur, and `--fit WxH` (downscale to fit inside a pixel
box, aspect ratio and alpha preserved; never upscales). They compose in a
fixed order: brightness → contrast → tone treatment → blur → fit. Desaturation, grayscale, and duotone are
mutually exclusive. At least one option must produce a real change; animated
or multi-frame sources are rejected rather than reduced to one frame.
@@ -193,7 +203,9 @@ The tool does not resolve a canvas or recommend a left/right, top/bottom, or
other slide layout. Its atomic CSV records EXIF-corrected native dimensions and
`AspectRatio`, the objective aspect-ratio category, optional source
`SourceDisplayRatio`, format, actual transparent-pixel presence, usage count,
and bitmap/vector capability facts. An empty folder rewrites a header-only
and bitmap/vector capability facts. The usage count (`Uses` in the table) is
how many source occurrences the import manifest recorded for the asset; it is
not a count of SVG references and does not find unused assets. An empty folder rewrites a header-only
report; unreadable supported files still refresh the report and produce a
non-zero exit.
@@ -288,6 +300,67 @@ Allowed licenses (default): CC0, Public Domain, Pexels License, Pixabay Content
The full role-level reference (intent → query translation, on-slide attribution contract) is in [`references/image-searcher.md`](../../references/image-searcher.md).
### `image_search.py` parameters
| Parameter | Default | Description |
|---|---|---|
| `query` (positional, required) | — | Simplified internally |
| `--query-variant` | — | Repeatable alias/translation; batch rows use `query_variants` |
| `--filename` (required) | — | Output filename matching the resource list |
| `-o / --output` | `.` | Output directory; manifest defaults to `<output>/image_sources.json` |
| `--slide`, `--purpose`, `--orientation` | `""`, `""`, `any` | Recorded slide id; `background` / `hero` / `side` / `accent`; `landscape` / `portrait` / `square` |
| `--min-width / --min-height` | `1200 / 800` | Downloaded-pixel floors; `--from-url` honors explicit lower overrides |
| `--provider` | chain | Pin one provider |
| `--strict-no-attribution` | off | Refuse CC BY / CC BY-SA |
| `--require-terms` | — | Repeatable identity gate; comma separates groups, `A|B` aliases |
| `--save-candidates` | off | Thumbnail mode: one ranked page of previews plus `review_sheet.jpg`, no original |
| `--max-candidates` | `8` | Page size; `0` = complete pool, debugging only |
| `--candidate-page` | `1` | Ranked page; page 2 starts at rank 9 |
| `--promote <candidate>` | — | Download exactly one selected original, enforce gates, write provenance |
| `--from-url <url>` | — | Manual replacement recorded as `license_tier: manual`; works without vision |
| `--manifest <path>` | `images/image_queries.json` | Override the manifest path |
### Batch runner and ranking
Required per item: `filename`, `query`, `status`; optional: `query_variants`, `candidate_page`, `slide`, `purpose`, `orientation`, `provider`, `strict_no_attribution`, `min_width`, `min_height`, `required_terms`. The runner revalidates every `Sourced` row against its file, dimensions, and manifest entry (drift → `Failed`), then searches all `Pending` / `Failed` rows concurrently (default concurrency 3, `--concurrency N` or `IMAGE_SEARCH_CONCURRENCY`; `1` for strict pacing on rate-sensitive free providers). Thumbnail mode writes `Needs-Selection` with `candidate_page`, `candidate_count`, `candidate_total`, `has_more_candidates`, `next_candidate_page`, and the `review_sheet` path, creating no image or provenance; to see the next page for one row set its `candidate_page` to `next_candidate_page`, reset only that row to `Pending`, and rerun. Promoting with the same `--batch` manifest moves the row to `Sourced`. Provider failures stay retryable `Failed`; clean exhaustion becomes `Needs-Manual`; status is saved after each completion.
**Ranking** orders provider metadata, never pixels, and must not be tuned into a taste engine: hard-reject invalid licenses and zero relevance; in best-only mode reject any candidate missing a `required_terms` group; in thumbnail mode keep strict matches first and admit a near match only when exactly one group is missing and the finding query still has strong relevance (marked `identity_evidence: visual-verification-required`, never auto-promoted); then metadata-verified identity in the title outranks a URL-only match; concrete query tokens match whole ASCII tokens (`office``officer`) and dominate generic words; orientation is a small penalty, no-attribution a small bonus, pixel count capped so a huge weak match cannot beat a smaller accurate one.
### `image_sources.json` format
Each successful download appends or replaces one entry keyed on `filename`; the file is written atomically and is idempotent, and an unreadable existing manifest blocks the write.
```json
{
"license_verification": "provider metadata used; manual review recommended for external delivery",
"generated_at": "2026-05-01T12:17:59.856275Z",
"items": [ {
"filename": "team.jpg", "slide": "03_team", "purpose": "Leadership photo",
"search_query": "executive boardroom meeting", "matched_query": "leadership team boardroom",
"selection_method": "metadata-ranked", "orientation": "landscape",
"provider": "openverse", "stage": "all",
"title": "Untitled", "author": "",
"source_page_url": "https://www.rawpixel.com/...", "download_url": "https://...",
"license_name": "CC0", "license_url": "https://creativecommons.org/publicdomain/zero/1.0/",
"license_tier": "no-attribution", "attribution_required": false,
"width": 1024, "height": 683,
"metadata_dimensions": { "width": 4800, "height": 3200, "note": "upstream-reported size; actual downloaded file is smaller (likely a preview)" },
"attribution_text": "team.jpg — \"Untitled\" via Openverse — license: CC0 (...)",
"status": "sourced"
} ]
}
```
`matched_query` is the query or variant that found the asset; `selection_method` is `visual-thumbnail` after a reviewed promotion or `metadata-ranked` for the strict path; `width` / `height` are measured from the saved file (use them for layout) while `metadata_dimensions` appears only when the upstream claim differs; `license_tier` drives Executor's attribution; `attribution_text` is the canonical credit source, compressed only through §7's grammar; `stage` is `all` or `no-attribution-only`.
---
### Failure handling
Extends [`image-base.md`](../../references/image-base.md) §3. No candidates from any provider or stage → `Needs-Manual` (suggest a more precise query or another provider; rerun without `--strict-no-attribution` only when the page may carry credit). No acceptable image on the current page with `has_more_candidates` → fetch `next_candidate_page` without changing the query or downloading. A page past `candidate_total` → pool exhausted, add a variant or move to the manual boundary. Some previews fail while another qualifies → keep the set. Every preview fails, or a provider/network failure remains → `Failed`, retried by a later batch. A promoted original fails its download/readability/dimension gate → stay `Needs-Selection` and select another or change the query. A best-only download 403/404 → the dispatcher falls to the next ranked candidate. A keyed provider without a key → skipped. CLI exit: a prepared `Needs-Selection` set returns `0`; `Failed` or `Needs-Manual` returns `1`.
---
## `gemini_watermark_remover.py`
Remove Gemini watermark assets after manual download.
@@ -0,0 +1,40 @@
# Native Data Payload Reference
The complete closed payload grammar that `svg_quality_checker.py` and
`svg_to_pptx.py --native-charts-and-tables` validate for Chart/Table
replacement markers. The authoring rules — eligibility, the atomic marker +
JSON unit, activation, and the canonical example — live in
[`native-data-interface.md`](../../references/native-data-interface.md); this
reference holds the field enumerations, closed enums, numeric ranges,
read-compatible spellings, and chrome/typography inference that the prompt
file no longer repeats. Section titles mirror the owning section of
`native-data-interface.md` §2.
---
## §2 Metadata placement and bounds
one child `<metadata type="application/json">` (attribute `data-pptx-json` is read-compatible, not canonical); the marker's `data-pptx-replace-with` selects the schema. Provide `x`, `y`, `width`, `height` in metadata or as `data-pptx-x/y/width/height` on the group; omitted bounds are inferred from the fallback geometry (then marker/ancestor `translate` / `scale` apply), complete explicit bounds are absolute slide coordinates. `x` / `y` are finite and inside the 32-bit DrawingML range; `width` / `height` additionally resolve to at least one EMU (tables: per resolved row and column). JSON-first markers require all four bounds in metadata. Classic charts accept root `plot_area` (`x`, `y`, `width`, `height`, a positive rectangle inside the frame → `c:manualLayout`); ChartEx rejects it. `svg_quality_checker.py` validates marker kind, JSON, bounds/fallback, table rows/columns, chart type and data shape, the authority contract, and (SVG-first) baseline freshness.
## §2 Table schema — `ppt-master.semantic-table.v2`
Every payload carries that exact `schema`. Native tables are rectangular grids: `columns` for the optional header row, `rows` for body rows (shorter rows padded unless `strict_grid: true`; at most 1000 resolved rows and columns); `column_widths` / `row_heights` are finite non-negative relative weights matching the grid with one positive value; `header_rows` is an integer in range; `strict_grid`, `style.band_row`, and `bold` are JSON booleans. Exact repetition may be factored into `defaults.cell` / `defaults.paragraph` / `defaults.run` and kebab-case `cell_styles` selected by `cell_style` (precedence: cell defaults → named style → cell fields; object-valued `padding` merges, everything else replaces; `<style>` and `class` remain forbidden).
Cells accept `text`, `fill`, `fill_opacity`, `color`, `align` (`l` / `ctr` / `r`), `valign` (`top` / `middle` / `bottom`), `bold`, `font_size`, `padding` and side-specific `padding_*`, `border_color`, `border_width`, `borders`, `lang`, `anchor_center`, `horizontal_overflow`. Multi-paragraph text replaces `text` with a non-empty `paragraphs` list of strings or objects — empty paragraph strings are preserved as blank lines — (`align` plus exactly one of `text` or non-empty `runs`; runs carry required `text` and optional `bold`, `italic`, `underline`, `strike`, `color`, `font_size`, one-typeface `font_family`, `lang`, `alt_lang`); unknown fields, wrong types, empty runs, multi-typeface families, and unsupported colors fail. Per-side borders use `borders.left|right|top|bottom|diagonal_down|diagonal_up` as `{ "style": "none" }` or `{ "style": "solid", "color": "#RRGGBB", "width": <positive-px> }`, overriding a uniform `border_color` / `border_width` on style or cell. A missing `lang` derives `zh-CN` for CJK and `en-US` otherwise. `style.band_row: false` disables banding and materialized alternating fills. Typography mirrors the fallback: `style.font_family` and `style.font_size` from the drawn table text, `style.header_font_size` or per-cell `font_size` only where the fallback differs; with no explicit table font, Default uses the deck body family and anchor, Quick its active-context values.
**Hard rule — the table payload is complete**: a payload holding only `font_size` and a uniform border is not complete when the fallback draws a header band, row or column fills, first-column emphasis, non-uniform row heights, or sparse rules — every row, summary line, value, and cell style that must survive `--native-charts-and-tables` is in `columns` / `rows`, because fallback text is discarded on that route. Numeric or currency columns use cell objects with `align: "r"` (`text-anchor="end"` does not carry). **Merged cells — canonical rectangular contract only**: positive integer `row_span` / `col_span` on the anchor, every covered cell blank as `{"merge_continuation": true}` (a bare `{"text": ""}` is blank only while no `defaults.cell` adds fields), spans inside the grid and non-overlapping; the exporter writes `rowSpan` / `gridSpan` / `hMerge` / `vMerge`. CamelCase aliases, raw OOXML merge fields, top-level merge lists, nonblank covered cells, invalid spans, and overlaps fail.
## §2 Chart schemas
- **Category charts**`column`, `bar`, `line`, `area`, `pie`, `doughnut`, `pieOfPie`, `barOfPie`, `radar`: `categories` plus `series[].values`. Pie-family charts take exactly one series with per-slice colors; `hole_size` is doughnut-only, integer `10..90`, default `75`; no rotation field. Column/bar may set `series[].point_colors` (camelCase `pointColors` is read-compatible; length = values). `data_labels` is `true` or an object with `show_value`, `position`, `number_format`, `font_size`, `font_family`, `bold`, `color`, per-point `colors`, and `points` (zero-based `idx` plus optional overrides); positions: clustered column/bar `outside_end` / `inside_end` / `inside_base` / `center`, stacked `inside_end` / `inside_base` / `center`, line `above` / `center` / `best_fit`, area none.
- **Combo** — shared `categories` plus `plots[]` (`type: "column" | "line" | "area"`, own `series`, optional `axis: "secondary"`, optionally own `categories` / `category_numeric` when caches genuinely differ, and `series_indices` for imported identity — same-length unique non-negative integers forming one contiguous `0..N-1` range across plots) or typed `series[]` with per-series `type` / `axis` (adjacent compatible series share a plot). Area series may set `fill_opacity` (`0..1`; `fillOpacity` read-compatible); a line plot with `area_fill: true` exports as an area chart; line/area series may set `line_width` in SVG px (`lineWidth` read-compatible). Export layers areas below columns and lines.
- **Axes** — classic `axes` is a closed object of `category`, `value`, `secondary_category`, `secondary_value`, each with only `kind` (`text` / `date` / `value`), `position`, `visible`, `label_position` (`next_to` / `none` / `low` / `high`), `number_format`, `minimum`, `maximum`, `major_unit` (value axes), `reverse`, `major_gridlines`; single-plot `bar` takes `category` left/right and `value` bottom/top; pie-family rejects `axes`. `scatter` / `bubble` use `x` and `y` roles only (`kind: "value"`; `x.position` bottom/top, `y.position` left/right) with the same fields. Logarithmic scales, minor units/gridlines, crossing values, display units, and tick skipping are unsupported.
- **XY**`scatter` and `bubble` use `series[].x` + `series[].y` (`bubble` adds one `series[].size` / `sizes` per point), or `series[].points` as `[x, y]` / `[x, y, size]` tuples or `{x, y, size}` objects.
- **ChartEx**`treemap` / `sunburst` (`values` plus `levels[level][point]` or path-style `categories`; treemap `parent_label_layout: "banner" | "overlapping" | "none"` (default `overlapping`), PowerPoint labels only the top level and leaves), `histogram` (`values`), `pareto` / `waterfall` / `funnel` (`categories` + `values`; `waterfall` accepts `subtotals` / `subtotal_indices`), `boxWhisker` (`series[].values`, optional `series[].categories`). ChartEx writes no `<cx:title>` without a payload title (an empty title shows the series name), emits title/subtitle as companion text boxes, and takes `style.colors` / root `colors` into its color-style part. Non-Microsoft renderers show a limited subset.
- **Stock** — numeric Excel date serials in `categories` / `dates` plus exactly four series open / high / low / close (`series` with four entries or top-level `open` / `high` / `low` / `close`).
- **Supported types**: `column`, `bar` (`grouping`: `clustered` / `stacked` / `percentStacked`); `line` (`grouping`: `standard` / `stacked` / `percentStacked`; `line_style`: `line` / `lineMarker`, default `line` with no markers); `area` (`grouping`: `standard` / `stacked` / `percentStacked`); `pie`, `doughnut`, `pieOfPie`, `barOfPie`; `radar`, `radarMarkers`, `radarFilled`; `scatter` (`scatter_style`: `marker` / `lineMarker` / `line` / `smoothMarker` / `smooth`, default `marker`); `bubble`; `combo`; `treemap`, `sunburst`; `histogram`, `pareto`; `boxWhisker`; `waterfall`, `funnel`; `stock`. 3D aliases and `surface` are unsupported; exploded pie/doughnut, `map`, `heatmap`, `bullet`, and `gantt` are deferred and fail fast.
## §2 Chart chrome, typography, and color
SVG-first metadata matches the fallback chrome; JSON-first owns it. Metadata sizes use SVG px (`1px = 0.75pt`); `style.font_family` and `title_font_size`, `subtitle_font_size`, `axis_font_size`, `axis_title_font_size`, `legend_font_size`, `note_font_size` are required only when native must preserve typography an SVG-first fallback cannot supply unambiguously (JSON-first never infers from its preview). A string or unbounded-object `title` becomes native `c:title` (`subtitle` line two); a title object with complete `x`, `y`, `width`, `height` becomes a companion text box (partial bounds or `subtitle` fail); `name` names the object; `title`, `subtitle`, and axis-title objects accept `text`, `font_size`, `font_family`, `color`; the checker rejects SVG-first title/axis text absent from the fallback. Axis titles are explicit via `axis_titles` (`category`, `value`, `x`, `y`, `secondary_value`) or the root aliases `category_axis_title`, `value_axis_title`, `x_axis_title`, `y_axis_title`, `secondary_value_axis_title`; `show_value_axis_labels: false` hides numeric tick labels (e.g. a radar without radial coordinates); native legends are opt-in via `show_legend: true` and `legend_position` (`bottom` default; `top` / `left` / `right`). SVG-first parity reads the fallback literally — `style.axis_color` equals the dominant axis/grid stroke, numbers match in written form (`286.20``286.2`), and marker text that is not a category, data label, axis label, or legend entry needs a companion entry. Companion text (`caption`, `source`, `note`, `notes`, `footnote`, `footnotes`) exports as editable text boxes — strings or objects with `text`, `x`, `y`, `width`, `height` (slide coordinates), `font_size`, `color`, `align`, `bold`; use it for captions, sources, center labels, and annotations, and `data_labels` for point values. `style.colors` sets series colors (treemap/sunburst tile palette in order); the exporter writes explicit chart-area fill, plot-area fill, axis, gridline, and label colors (SVG-first infers them from the largest panel `<rect>`, text, and strokes; JSON-first from JSON or stable defaults), overridable under `style` with `chart_area_fill`, `plot_area_fill`, `text_color`, `axis_color`, `grid_color` (`"none"` for transparent); generated payloads use uppercase `#RRGGBB`, with `#RGB`, `rgb()`, and CSS names normalized. Negative bars keep the series fill.
@@ -24,7 +24,8 @@ python3 scripts/project_manager.py page-context-report <project_path>
Notes:
- `--format` is optional and accepts registered canvas keys only. Pass it only
when the actual canvas exactly matches a registered format.
- Without `--format`, `init` creates `<name>_<YYYYMMDD>`; authoring records the
- Without `--format`, `init` creates `<name>_<YYYYMMDD>`; a name that already
ends in `_<YYYYMMDD>` is used as-is (no second date). Authoring records the
canvas in `spec_lock.md` for Default Generate or the first SVG for Quick
Generate.
- With `--format`, `init` preserves the registered form
@@ -35,6 +36,11 @@ Notes:
- `--move` applies only to sources under the repository's `projects/` tree
- A directly supplied supported bitmap is also copied into `images/` with a
collision-safe basename while its original remains archived in `sources/`
- SVG/EMF/WMF inputs stay source assets unless a converter manifest supplies
display metadata. Embedded Office vectors extracted from DOCX/PPTX land in
`images/` with `image_manifest.json` as first-class image assets and are
never converted to PNG; a blank browser preview of an EMF/WMF is expected.
Export behavior for them: [`svg-pipeline.md`](svg-pipeline.md)
- Directory inputs are expanded non-recursively. After Step 1 conversion,
pass the source file/directory once when generated Markdown lives beside the
original source. If Step 1 used `-o` to write Markdown elsewhere, pass both
@@ -743,11 +743,13 @@ It aggregates:
- `align_embed_images.py` (`crop-images` / `fix-aspect` / `embed-images` aliases route here)
- `flatten_tspan.py`
EMF/WMF images referenced by a page are preserved as external references, never embedded or rasterized.
`svg_final/` is an optional Step 7.2 preview artifact; the native exporter reads `svg_output/` and never requires it. It is the self-contained visual reference and may be manually inserted as an SVG picture.
## `svg_to_pptx.py`
Convert project SVGs into PPTX.
Convert project SVGs into PPTX. EMF/WMF images referenced from `svg_output/` are embedded as native `image/x-emf` / `image/x-wmf` media at full vector fidelity.
Native formulas use the two markers owned by
[`native-formula.md`](../../references/native-formula.md). A standalone block
@@ -856,7 +858,11 @@ Behavior:
the converter resolves its Latin / East Asian role to a typeface that normally
requires a custom installation. A recommended stack such as
`"Microsoft YaHei", Arial, sans-serif` does not warn merely because it ends with a
generic fallback.
generic fallback. Face resolution writes one face per script: the first named
Latin face fills `latin`, the first named CJK face fills `ea` (and `latin` when
no Latin face is named), and a generic family fills `latin` only when it
precedes every named face. Fonts are never embedded; a missing face substitutes
on the viewer's machine.
- Multiline text export modes:
- Default: one editable frame retains authored breaks and disables PowerPoint wrapping. An ordinary generated frame uses PowerPoint's native resize-shape-to-fit-text behavior, so deleting a retained break expands the frame instead of leaving text outside it; imported exact frames and structured multiline placeholder carriers retain fixed-size behavior.
- `--reflow-text`: eligible same-size lines become flowing prose that PowerPoint may rewrap; a font-size change, list marker, or accepted larger gap remains a paragraph boundary. Legacy `--merge-paragraphs` aliases this mode.
@@ -1014,9 +1020,17 @@ the SVG quality checker.
a JSON bounds object with `--json`.
- `calibrate` measures fixed CJK and Latin samples for every typography role
from `spec_lock.md` or repeatable `--role NAME:FAMILY:SIZE` overrides, writes
`validation/text_calibration.json`, and prints a compact table or JSON. Add
`--outline` to include the longest planned line per mapped role from Design
Spec §IX.
`validation/text_calibration.json`, and prints a compact table or JSON. The
estimator is additive across scripts, so a line mixing CJK with Latin words
or digits is estimated as (CJK chars ÷ CJK rate + other chars ÷ Latin rate)
× 100; spaces, digits, and punctuation count as Latin. The checker's overflow
diagnostic prints that line's average px per character, which is not a
reusable rate. A lock role without its own
`<role>_family` resolves to `title_family` when the role name contains
`title` or `numeral`, otherwise to `body_family`. Add `--outline` to include
the longest planned line per mapped role from Design Spec §IX; a Content
value joined by spaced `·`, `•`, `|`, `/` separators or by semicolons counts
each block as its own line.
```bash
python3 scripts/text_measure.py measure "Editable DrawingML text" --size 22
@@ -371,6 +371,21 @@ def _print_backend_list() -> None:
_print_backend_resolution()
def _check_backend_aspect_ratio(backend_module, aspect_ratio: str) -> None:
"""Fail before the request when the resolved backend rejects this ratio.
``ALL_ASPECT_RATIOS`` is the union across backends; each backend module
may narrow it with ``VALID_ASPECT_RATIOS``.
"""
valid = getattr(backend_module, "VALID_ASPECT_RATIOS", None)
if valid and aspect_ratio not in valid:
name = getattr(backend_module, "__name__", "backend").rsplit(".", 1)[-1]
raise ValueError(
f"aspect_ratio '{aspect_ratio}' is not supported by {name}. "
f"Valid for this backend: {list(valid)}"
)
def _resolve_backend() -> tuple[object, str]:
"""
Determine which backend to use from explicit configuration.
@@ -950,6 +965,7 @@ def _run_manifest(manifest: dict, manifest_path: str, backend_module, *,
def _one(idx: int):
item = items[idx]
try:
_check_backend_aspect_ratio(backend_module, item["aspect_ratio"])
saved_path = backend_module.generate(
prompt=item["prompt"],
aspect_ratio=item["aspect_ratio"],
@@ -17,7 +17,7 @@ Dependencies:
Pillow; project image-search dependencies when copying web provenance
Treatments run in this fixed order: brightness, contrast, tone treatment
(desaturate / grayscale / duotone), then Gaussian blur.
(desaturate / grayscale / duotone), Gaussian blur, then --fit downscaling.
"""
from __future__ import annotations
@@ -98,6 +98,19 @@ def _unit_float(value: str) -> float:
return number
_FIT_RE = re.compile(r"^(\d+)x(\d+)$")
def _fit_box(value: str) -> tuple[int, int]:
match = _FIT_RE.fullmatch(value.strip().lower())
if match is None:
raise argparse.ArgumentTypeError("fit box must be WIDTHxHEIGHT in pixels, e.g. 920x228")
width, height = int(match.group(1)), int(match.group(2))
if width <= 0 or height <= 0:
raise argparse.ArgumentTypeError("fit box dimensions must be positive")
return width, height
def _hex_color(value: str) -> str:
match = _HEX_COLOR_RE.fullmatch(value)
if match is None:
@@ -156,6 +169,17 @@ def build_parser() -> argparse.ArgumentParser:
type=_nonnegative_float,
help="Gaussian blur radius greater than or equal to 0; 0 is unchanged.",
)
parser.add_argument(
"--fit",
type=_fit_box,
default=None,
metavar="WxH",
help=(
"Downscale so the image fits inside WIDTHxHEIGHT pixels, preserving "
"aspect ratio and alpha; never upscales. Use it to bring an "
"oversized generated image down to its planned on-slide size."
),
)
return parser
@@ -245,6 +269,8 @@ def _treatment_plan(args: argparse.Namespace) -> list[dict]:
)
if args.blur is not None and args.blur > 0:
plan.append({"operation": "blur", "radius": args.blur})
if args.fit is not None:
plan.append({"operation": "fit", "width": args.fit[0], "height": args.fit[1]})
if not plan:
raise ValueError(
"select at least one effective treatment; identity values such as "
@@ -344,6 +370,19 @@ def _apply_treatments(
result = rgb.convert("RGBA") if alpha is not None else rgb
if alpha is not None:
result.putalpha(alpha)
if args.fit is not None:
fit_w, fit_h = args.fit
scale = min(fit_w / width, fit_h / height, 1.0)
if scale < 1.0:
new_size = (
max(1, round(width * scale)),
max(1, round(height * scale)),
)
resized = result.resize(new_size, Image.Resampling.LANCZOS)
if result is not rgb:
result.close()
result = resized
width, height = new_size
save_options = {"format": "PNG"}
if isinstance(icc_profile, bytes) and icc_profile:
save_options["icc_profile"] = icc_profile
@@ -87,7 +87,7 @@
"Thin relationships whose meaning comes from endpoints, routing, or an optional marker."
],
"avoid_for": [
"Do not substitute a line for a filled directional body or content carrier.",
"Do not substitute a line for a filled directional body or carrier-and-field contour.",
"Do not imply endpoint attachment; newly authored connector presets remain unconnected."
],
"presets": {
@@ -269,7 +269,13 @@ class ProjectManager:
date_str = datetime.now().strftime("%Y%m%d")
if normalized_format is None:
project_dir_name = f"{project_name}_{date_str}"
# A name already carrying a `_<YYYYMMDD>` suffix (e.g. a full
# project dir name pasted back into init) is used as-is —
# re-appending would produce `name_20260101_20260102`.
if re.search(r"_\d{8}$", project_name):
project_dir_name = project_name
else:
project_dir_name = f"{project_name}_{date_str}"
else:
# A name already carrying a `_<format>_<YYYYMMDD>` suffix (e.g. a
# full project dir name pasted back into init) is used as-is —
@@ -710,7 +716,7 @@ class ProjectManager:
self._merge_image_manifest(rebased_items, images_dir / "image_manifest.json")
print(
f"Propagated {copied_count} image asset(s) + manifest "
f"from {asset_dir} → images/ (namespace: {namespace})"
f"from {asset_dir} → images/ (filenames unchanged; source_namespace {namespace!r} recorded in image_manifest.json)"
)
def _propagate_companion_image_assets(self, markdown_path: Path, project_dir: Path) -> None:
@@ -17,8 +17,8 @@
},
"file_budgets": {
"AGENTS.md": 3250,
"skills/ppt-master/SKILL.md": 1750,
"skills/ppt-master/references/executor-base.md": 11000,
"skills/ppt-master/SKILL.md": 2500,
"skills/ppt-master/references/executor-base.md": 12000,
"skills/ppt-master/references/executor-structured.md": 5500,
"skills/ppt-master/references/executor-chart.md": 1750,
"skills/ppt-master/references/executor-visualization.md": 1000,
@@ -31,10 +31,11 @@
"skills/ppt-master/references/shared-standards.md": 500,
"skills/ppt-master/references/shared-standards-core.md": 7000,
"skills/ppt-master/references/svg-effects.md": 9500,
"skills/ppt-master/references/native-data-interface.md": 5000,
"skills/ppt-master/references/native-data-interface.md": 3000,
"skills/ppt-master/references/pptx-structure-interface.md": 3000,
"skills/ppt-master/references/preset-shape-vocabulary.md": 2750,
"skills/ppt-master/references/strategist.md": 13000,
"skills/ppt-master/references/strategist.md": 9000,
"skills/ppt-master/references/plan-core.md": 7000,
"skills/ppt-master/references/strategist-image.md": 3250,
"skills/ppt-master/references/strategist-template.md": 2500,
"skills/ppt-master/templates/design_spec_reference.md": 3500,
@@ -196,6 +197,7 @@
"files": [
"skills/ppt-master/workflows/generate-pptx.md",
"skills/ppt-master/references/strategist.md",
"skills/ppt-master/references/plan-core.md",
"skills/ppt-master/references/strategist-image.md",
"skills/ppt-master/references/canvas-formats.md",
"skills/ppt-master/templates/design_spec_reference.md",
@@ -245,6 +247,7 @@
],
"files": [
"skills/ppt-master/workflows/profiles/quick-generate.md",
"skills/ppt-master/references/plan-core.md",
"skills/ppt-master/references/shared-standards-core.md",
"skills/ppt-master/references/executor-base.md",
"skills/ppt-master/references/preset-shape-vocabulary.md",
@@ -782,7 +785,7 @@
"max_tokens": 200000
},
"stage.generate.executor.flat": {
"description": "Executor resident core for flat pages: execution rules, everyday devices and effects, module triggers, the preset vocabulary, plus the confirmed mode/style catalog file when the confirmation points to one (a custom without references reads none). Deeper modules load on their routing triggers.",
"description": "Executor resident core for flat pages: execution rules, everyday devices and effects, module triggers, the preset vocabulary, plus the confirmed mode/style catalog file when the confirmation points to one (a custom without references reads none). Deeper modules load on their routing triggers. Ceiling raised to 36000 after BUDGET_LOAD_SET reported 35031 tokens (2026-09-02 dogfood fixes).",
"scope": "incremental",
"files": [
"skills/ppt-master/references/executor-base.md",
@@ -810,7 +813,7 @@
"allow_repeat": true
}
],
"max_tokens": 35000
"max_tokens": 36000
},
"stage.generate.executor.structured": {
"description": "Structured template execution layered on the flat/shared core.",
@@ -1190,7 +1193,7 @@
"max_tokens": 10000
},
"stage.generate.executor.structure": {
"description": "Qualitative relationship grammar and topology assembly; loaded at the first page whose Structure decision is yes.",
"description": "Qualitative relationship grammar and topology assembly; loaded at the first page whose topology decision is yes.",
"scope": "incremental",
"files": [
"skills/ppt-master/references/executor-structure.md",
@@ -1435,6 +1438,15 @@
"skills/ppt-master/templates/styles/workshop-teaching/templates/design_spec.md"
],
"reason": "Style preset specs share the same method-only scope boundary by design."
},
{
"kind": "exact",
"fingerprint": "b720d5918a4f",
"paths": [
"skills/ppt-master/templates/decks/README.md",
"skills/ppt-master/templates/layouts/README.md"
],
"reason": "Identical one-line pointer to routing.md §7 and apply-template-workspace in the kind READMEs; the rule owner is routing.md §7 (rule-owners R22)."
}
]
},
@@ -1649,11 +1661,6 @@
"from": "skills/ppt-master/workflows/profiles/quick-generate.md",
"to": "skills/ppt-master/references/shared-standards-core.md"
},
{
"concern": "quick-svg-effects-contract",
"from": "skills/ppt-master/workflows/profiles/quick-generate.md",
"to": "skills/ppt-master/references/svg-effects.md"
},
{
"concern": "quick-native-shape-contract",
"from": "skills/ppt-master/workflows/profiles/quick-generate.md",
@@ -1669,16 +1676,6 @@
"from": "skills/ppt-master/workflows/profiles/quick-generate.md",
"to": "skills/ppt-master/references/semantic-svg.md"
},
{
"concern": "quick-structure-routing",
"from": "skills/ppt-master/workflows/profiles/quick-generate.md",
"to": "skills/ppt-master/references/executor-structure.md"
},
{
"concern": "quick-topology-routing",
"from": "skills/ppt-master/workflows/profiles/quick-generate.md",
"to": "skills/ppt-master/references/topology-assembly.md"
},
{
"concern": "quick-structured-contract",
"from": "skills/ppt-master/workflows/profiles/quick-generate.md",
@@ -1703,6 +1700,16 @@
"concern": "structured-interface-routing",
"from": "skills/ppt-master/references/shared-standards-core.md",
"to": "skills/ppt-master/references/pptx-structure-interface.md"
},
{
"concern": "executor-effects-routing",
"from": "skills/ppt-master/references/executor-base.md",
"to": "skills/ppt-master/references/svg-effects.md"
},
{
"concern": "executor-topology-routing",
"from": "skills/ppt-master/references/executor-base.md",
"to": "skills/ppt-master/references/topology-assembly.md"
}
],
"registries": [
@@ -1940,13 +1947,13 @@
{
"path": "skills/ppt-master/references/executor-base.md",
"role": "consumer",
"fingerprint": "696cdad21077",
"fingerprint": "7e5a0d00892e",
"reason": "This consumer needs the field contract for deterministic execution."
},
{
"path": "skills/ppt-master/templates/spec_lock_reference.md",
"role": "reference",
"fingerprint": "71622518b209",
"fingerprint": "c96bdc44695b",
"reason": "This reference mirrors the owner field grammar or ownership boundary."
},
{
@@ -1954,12 +1961,6 @@
"role": "consumer",
"fingerprint": "b3ea6e828373",
"reason": "This consumer needs the field contract for deterministic execution."
},
{
"path": "skills/ppt-master/references/native-data-interface.md",
"role": "consumer",
"fingerprint": "b52102689f16",
"reason": "Table run typography mirrors the deck font contract for native export."
}
]
},
@@ -1970,7 +1971,7 @@
{
"path": "skills/ppt-master/references/image-generator.md",
"role": "compatibility",
"fingerprint": "f2c2cdc3b2a6",
"fingerprint": "0dff2d70710b",
"reason": "This site documents a legacy or omission compatibility boundary."
},
{
@@ -2012,7 +2013,7 @@
{
"path": "skills/ppt-master/references/executor-structured.md",
"role": "consumer",
"fingerprint": "dcbb7a6baae7",
"fingerprint": "b3fa9b13f1a3",
"reason": "This consumer needs the field contract for deterministic execution."
},
{
@@ -2042,7 +2043,7 @@
{
"path": "skills/ppt-master/references/executor-structured.md",
"role": "consumer",
"fingerprint": "7213f2c7ffe7",
"fingerprint": "10af7bec230c",
"reason": "This consumer needs the field contract for deterministic execution."
},
{
@@ -2066,13 +2067,13 @@
{
"path": "skills/ppt-master/references/executor-base.md",
"role": "consumer",
"fingerprint": "b63e7a4de45e",
"fingerprint": "50e5134d9e58",
"reason": "This consumer needs the field contract for deterministic execution."
},
{
"path": "skills/ppt-master/references/strategist.md",
"role": "producer",
"fingerprint": "8121d65895a2",
"fingerprint": "c26288aa15ad",
"reason": "This producer projects the owner field into the planning contract."
},
{
@@ -2080,6 +2081,12 @@
"role": "reference",
"fingerprint": "9e8775a83943",
"reason": "This reference mirrors the owner field grammar or ownership boundary."
},
{
"path": "skills/ppt-master/references/plan-core.md",
"role": "reference",
"fingerprint": "2fd03eac49a4",
"reason": "This shared planning core states the reading-mode lean of the tag as a bias, not a quota; the grammar stays with the schema."
}
]
},
@@ -2096,13 +2103,13 @@
{
"path": "skills/ppt-master/references/strategist.md",
"role": "producer",
"fingerprint": "0bf67e7eef14",
"fingerprint": "6c5e08eb6af5",
"reason": "This producer projects the owner field into the planning contract."
},
{
"path": "skills/ppt-master/templates/spec_lock_reference.md",
"role": "reference",
"fingerprint": "6232ca5f6243",
"fingerprint": "3d39a6b6c858",
"reason": "This reference mirrors the owner field grammar or ownership boundary."
},
{
@@ -2120,7 +2127,7 @@
{
"path": "skills/ppt-master/references/executor-structured.md",
"role": "consumer",
"fingerprint": "dc21169163b7",
"fingerprint": "ca1b1f2fb576",
"reason": "This consumer needs the field contract for deterministic execution."
},
{
@@ -2150,7 +2157,7 @@
{
"path": "skills/ppt-master/references/executor-structured.md",
"role": "consumer",
"fingerprint": "7568538df9f4",
"fingerprint": "d3487eb32e2a",
"reason": "This consumer needs the field contract for deterministic execution."
},
{
@@ -2180,13 +2187,13 @@
{
"path": "skills/ppt-master/references/executor-base.md",
"role": "consumer",
"fingerprint": "fd5bce3b80c9",
"fingerprint": "e1538482e32d",
"reason": "This consumer needs the field contract for deterministic execution."
},
{
"path": "skills/ppt-master/references/strategist.md",
"role": "producer",
"fingerprint": "0efce3f9be37",
"fingerprint": "d63d47fb811c",
"reason": "This producer projects the owner field into the planning contract."
},
{
@@ -2331,6 +2338,10 @@
{
"glob": "skills/ppt-master/scripts/docs/template-tools.md",
"reason": "Template creation tool behavior reference; create-template.md and template-designer.md carry the procedure and contract."
},
{
"glob": "skills/ppt-master/scripts/docs/native-data.md",
"reason": "Closed Chart/Table payload grammar for checker/exporter behavior; native-data-interface.md carries the canonical forms, and generation roles open this file only when a payload check fails."
}
]
}
@@ -22,6 +22,7 @@ from __future__ import annotations
import argparse
import json
import os
import subprocess
import sys
import tempfile
@@ -67,6 +68,15 @@ def _is_supported_directory_item(path: Path) -> bool:
}
def _output_is_directory(output_arg: str | None) -> bool:
"""True when -o names an existing directory or ends with a path separator."""
if not output_arg:
return False
if output_arg.endswith(("/", os.sep)):
return True
return Path(output_arg).is_dir()
def _dispatch_output_arg(
input_arg: str,
conversion_type: str,
@@ -74,6 +84,11 @@ def _dispatch_output_arg(
batch_mode: bool,
used_outputs: set[Path],
) -> str | None:
if output_arg and _output_is_directory(output_arg):
# A directory is a directory even for one input: the file keeps its
# default `<stem>.md` name inside it instead of becoming an
# extension-less file named after the directory.
batch_mode = True
if output_arg and batch_mode and conversion_type == "web":
return None
if output_arg and batch_mode:
@@ -351,7 +366,7 @@ converter, so existing converter behavior remains the source of truth.
parser.add_argument(
"-o",
"--output",
help="Output Markdown file for one input, or output directory for multiple inputs/directories",
help="Output Markdown file for one input, or output directory (an existing directory or a path ending in /) for one or more inputs",
)
parser.add_argument(
"--images",
@@ -411,7 +426,7 @@ def dispatch_many(
success_count = 0
failed: list[str] = []
skipped: list[str] = list(initial_failures or [])
batch_mode = batch_mode or len(inputs) > 1
batch_mode = batch_mode or len(inputs) > 1 or _output_is_directory(args.output)
if args.output and batch_mode:
output_dir = Path(args.output)
if output_dir.exists() and not output_dir.is_dir():
@@ -1065,26 +1065,35 @@ def _wait_for_ready(
proc: subprocess.Popen,
project_path: Path,
timeout: int = STARTUP_TIMEOUT,
) -> bool:
"""Wait until this project's detached live-preview server responds."""
) -> int:
"""Wait until this project's detached live-preview server responds.
Returns the server pid recorded in the project lock, or 0 on timeout.
``proc.pid`` is not used for identity: on Windows a venv ``python.exe``
may be a launcher whose child is the real interpreter.
"""
deadline = time.time() + timeout
health_url = _server_url(port, '/api/health')
last_error = ''
while time.time() < deadline:
if proc.poll() is not None:
logger.error('live preview exited during startup (code=%s)', proc.returncode)
return False
return 0
try:
with urllib.request.urlopen(health_url, timeout=1) as response:
data = json.load(response)
lock = _read_lock(_lock_file(project_path))
server_pid = _lock_pid(lock)
if (
response.status == 200
and isinstance(data, dict)
and data.get('service') == 'live_preview'
and data.get('project') == str(project_path)
and data.get('pid') == proc.pid
and lock is not None
and lock.get('port') == port
and data.get('pid') == server_pid
):
return True
return server_pid
last_error = 'health response belongs to another service or project'
except (urllib.error.URLError, TimeoutError, OSError, ValueError) as exc:
last_error = str(exc)
@@ -1095,7 +1104,7 @@ def _wait_for_ready(
timeout,
f' (last error: {last_error})' if last_error else '',
)
return False
return 0
def _open_browser(url: str) -> bool:
@@ -1291,12 +1300,13 @@ def main(argv: Optional[list[str]] = None) -> int:
logger.error('cannot write live preview log: %s (%s)', log_path, exc)
return 1
url = _server_url(port)
if not _wait_for_ready(port, proc, project_path):
server_pid = _wait_for_ready(port, proc, project_path)
if not server_pid:
if proc.poll() is None:
proc.terminate()
logger.error('live preview failed to become reachable: %s (log: %s)', url, log_path)
return 1
logger.info('started live preview in background: %s (pid=%s)', url, proc.pid)
logger.info('started live preview in background: %s (pid=%s)', url, server_pid)
logger.info('log: %s', log_path)
if not args.no_browser and not _open_browser(url):
logger.info('browser did not auto-open; open %s manually', url)
@@ -268,8 +268,6 @@ def _build_paragraph_child_view(
base_x_raw = get_attr(text_el, "x")
if base_x_raw is None:
return None
if any((child.tail or "").strip() for child in direct_tspans):
return None
synthetic_first = ET.Element(f"{{{SVG_NS}}}tspan")
synthetic_first.set("x", base_x_raw)
synthetic_first.text = raw_lead.lstrip()
@@ -337,8 +335,11 @@ def _classify_paragraph_block(
boundary as a hard DrawingML break. First entry is ``paragraph``.
Conditions (all must hold):
- No direct text under <text>, except simple leading text that can be
promoted into a synthetic first-line <tspan>.
- No direct text under <text>, except leading text that can be
promoted into a synthetic first-line <tspan>; inline runs (and their
tail text) that follow it before the first line break stay on that
line.
- A line made of a single positioned <tspan> carries no tail text.
- Every direct child is a <tspan>.
- Every logical line starts with a new-line tspan.
- Direct-child inline formatting tspans without x/y/dy are allowed only
@@ -374,6 +375,14 @@ def _classify_paragraph_block(
if len(line_groups) < 2:
return None
# Tail text after a direct-child tspan is a run of the parent <text>. It
# survives when the line is wrapped into a container with its sibling
# runs; a line made of one positioned tspan has no container, so its
# tail would dangle outside every line and the block is not mergeable.
for group in line_groups:
if len(group) == 1 and (group[0].tail or "").strip():
return None
# First pass: validate per-line structural rules and collect dy values.
dy_values: list[float] = [] # one per line (0 for first)
for idx, group in enumerate(line_groups):
@@ -1133,6 +1133,7 @@ class SVGQualityChecker:
canonical_authoring: bool = False,
):
self.template_mode = template_mode
self.scan_banner = True
self.quick_generate = quick_generate
self.canonical_authoring = canonical_authoring
self.results = []
@@ -3866,7 +3867,8 @@ class SVGQualityChecker:
f'{bottom:.1f}), container ({outer_left:.1f}, '
f'{outer_top:.1f})-({outer_right:.1f}, '
f'{outer_bottom:.1f}), overflow horizontal '
f'{horizontal_ratio:.1%}, vertical {vertical_ratio:.1%}; '
f'{horizontal_ratio:.1%}, vertical {vertical_ratio:.1%} '
f'(error above {_BOUNDS_OVERFLOW_ERROR_RATIO:.0%}); '
f'{repair}{width_suffix}'
)
@@ -4632,11 +4634,25 @@ class SVGQualityChecker:
if text_el.get('x') is None:
return '<text> has no x anchor'
for child in list(text_el):
if not cls._is_tspan(child):
return '<text> has non-tspan child'
if (child.tail or "").strip():
return '<tspan> has non-empty tail text'
children = list(text_el)
if any(not cls._is_tspan(child) for child in children):
return '<text> has non-tspan child'
# Mirror svg_finalize.flatten_tspan: tail text after an inline run
# stays on its line, but a line made of one positioned <tspan> has
# nowhere to keep a tail.
groups: list[list[ET.Element]] = [[]]
for child in children:
if cls._is_line_tspan(child):
groups.append([child])
else:
groups[-1].append(child)
for group in groups[1:]:
if len(group) == 1 and (group[0].tail or "").strip():
return (
'text follows a positioned line <tspan> directly; '
'nest it inside that <tspan>'
)
return None
@@ -6859,7 +6875,8 @@ class SVGQualityChecker:
directory_expected_label = f"first SVG {svg_file.name}"
break
print(f"\n[SCAN] Checking {len(svg_files)} SVG file(s)...\n")
if self.scan_banner:
print(f"\n[SCAN] Checking {len(svg_files)} SVG file(s)...\n")
for svg_file in svg_files:
self._active_prototype_path = self._prototype_by_output.get(
@@ -7534,6 +7551,11 @@ class SVGQualityChecker:
@staticmethod
def _row_layout(row: Dict[str, str]) -> str:
# ``Image pattern`` is the current §VIII column; ``Layout pattern`` is
# the pre-rename spelling still present in older Design Specs.
value = row.get('Image pattern', '').strip()
if value:
return value
return row.get('Layout pattern', '').strip()
@staticmethod
@@ -7806,7 +7828,7 @@ class SVGQualityChecker:
'error',
'planned_image_missing_pattern',
f"{filename or '(missing filename)'} has an empty Design "
"Spec §VIII Layout pattern; preserve one non-empty "
"Spec §VIII Image pattern; preserve one non-empty "
"Strategist recommendation without locking SVG geometry.",
))
if current_image_contract and crop not in {'adaptive', 'no-crop'}:
@@ -7964,7 +7986,7 @@ class SVGQualityChecker:
'locked_image_pattern_mismatch',
f"{filename} spec_lock pattern="
f"{entry.get('pattern')!r} does not preserve the "
"Design Spec §VIII Layout pattern recommendation "
"Design Spec §VIII Image pattern recommendation "
f"{layout_pattern!r}. This Design Spec-to-spec_lock "
"projection check compares ordered catalog ids when "
"present, otherwise normalized text; it does not "
@@ -258,8 +258,14 @@ def main() -> None:
if not early_files:
print("[ERROR] --stage early found no authored SVG pages")
sys.exit(1)
print(
f"\n[SCAN] Checking {len(early_files)} authored SVG page(s) "
"for the early gate...\n"
)
checker.scan_banner = False
for svg_file in early_files:
checker.check_directory(str(svg_file), expected_format)
checker.scan_banner = True
else:
if stage == "first-page":
check_target = _first_page_target(target)
@@ -3019,7 +3019,7 @@ Recorded narration:
quick_flag = ' --quick-generate' if args.quick_generate else ''
print(
"Run: python3 skills/ppt-master/scripts/svg_quality_checker.py "
f'"{project_path}"{quick_flag} --stage final --json',
f'"{project_path}"{quick_flag} --canonical-authoring --stage final --json',
file=sys.stderr,
)
return 1
@@ -312,7 +312,8 @@ def _roles_from_spec_lock(lock_path: Path) -> dict[str, tuple[str, float]]:
) from exc
family = rows.get(f'{role}_family', '')
if not family:
fallback = 'title_family' if 'title' in role else 'body_family'
display_role = 'title' in role or 'numeral' in role
fallback = 'title_family' if display_role else 'body_family'
family = rows.get(fallback, '') or rows.get('font_family', '')
if not family:
raise ValueError(
@@ -332,6 +333,20 @@ def _clean_planned_line(raw: str) -> str:
return ' '.join(text.split())
_JOINED_BLOCK_SEPARATOR_RE = re.compile(r'\s+[·•|/]\s+||;\s')
def _split_joined_blocks(text: str) -> list[str]:
"""Split one outline value joined by spaced separators into planned lines.
A brief-depth Content field lists a page's blocks as ``A · B · C`` or
``ABC`` on one line; each block is a planned line, not the whole list.
Unspaced ``·`` inside a name (``·努维尔``) is left alone.
"""
parts = [part.strip() for part in _JOINED_BLOCK_SEPARATOR_RE.split(text)]
return [part for part in parts if part]
def _slide_id(token: str) -> str:
return 'PNN' if token.upper() == 'NN' else f'P{int(token):02d}'
@@ -392,7 +407,7 @@ def _outline_candidates(
line_index += 1
continue
content_lines = [value] if value else []
content_lines = _split_joined_blocks(value) if value else []
next_index = line_index + 1
while next_index < len(lines):
next_field = _OUTLINE_DATA_LINE_RE.match(lines[next_index])
@@ -403,7 +418,7 @@ def _outline_candidates(
break
planned_line = _clean_planned_line(lines[next_index])
if planned_line:
content_lines.append(planned_line)
content_lines.extend(_split_joined_blocks(planned_line))
next_index += 1
if 'body' in candidates:
candidates['body'].extend((slide, text) for text in content_lines)
@@ -501,6 +516,10 @@ def _render_calibration_table(payload: dict[str, object], *, include_outline: bo
else f'{planned["px"]:.1f}px, {planned["slide"]}, {planned["text"]}'
)
lines.append(' | '.join(row))
lines.append(
'[NOTE] mixed line width ≈ (CJK chars ÷ CJK rate + other chars ÷ Latin '
'rate) × 100; spaces, digits, and punctuation count as Latin.'
)
return '\n'.join(lines) + '\n'
@@ -13,7 +13,7 @@ Brand, Style, Layout, and Deck are independent kinds, not stages of one inherita
PowerPoint package objects are compilation targets, not kinds: Theme values and identity assets project from resolved identity rules (Brand, Deck, or the current project); Layout rules project into Master/Layout/Placeholder topology, semantic text roles, and spatial behavior; Deck combines both with descriptive application context and actual prototypes; Style guides method and expression without creating a package object or overriding resolved identity. Downstream planning decides which prototypes and content to use and records the exporter values, so one compiled Master may hold both structural geometry and brand visuals under separately owned rules.
New workspaces enter [`Create Template`](../workflows/create-template.md), which dispatches exactly one child ([`Create Brand`](../workflows/create-template/create-brand.md), [`Create Style`](../workflows/create-template/create-style.md), [`Create Layout`](../workflows/create-template/create-layout.md), [`Create Deck`](../workflows/create-template/create-deck.md)). Selection, mode defaults, preselection, `library` / `explicit` labels, cardinality, and installation are owned by [`routing.md`](../workflows/routing.md) §7 and [`apply-template-workspace`](../workflows/stages/apply-template-workspace.md): the four indexes are the complete library discovery source for Default Stage 1, every selected root is installed as `design_spec.<kind>.<id>.md` before Stage 2, and Quick applies supplied exact roots directly.
New workspaces enter [`Create Template`](../workflows/create-template.md), which dispatches exactly one child ([`Create Brand`](../workflows/create-template/create-brand.md), [`Create Style`](../workflows/create-template/create-style.md), [`Create Layout`](../workflows/create-template/create-layout.md), [`Create Deck`](../workflows/create-template/create-deck.md)). Selection, mode defaults, preselection, `library` / `explicit` labels, cardinality, and installation are owned by [`routing.md`](../workflows/routing.md) §7 and [`apply-template-workspace`](../workflows/stages/apply-template-workspace.md).
## Orthogonal contracts
@@ -53,4 +53,4 @@ Page-local Shape-first catalog families, not kinds: Chart — value-driven geome
## Sound Library
[`sounds/`](./sounds/) is a post-motion selection resource, not a template or Strategist resource: read its [cue vocabulary](./sounds/sound-vocabulary.md) only after a concrete auditory job exists and sync selected cues only ([usage](./sounds/README.md)).
[`sounds/`](./sounds/) is selected only through the post-motion pass in [`animations.md`](../references/animations.md) §2.2 ([usage](./sounds/README.md)); it is never a template or planning resource.
@@ -4,7 +4,7 @@
## How brands are consumed
Selection follows the parent contract: Brand choices come only from `brands_index.json` (no directory scan or bare-name match); a supplied exact root joins the same selector, defaults Stage 1 to template mode, and is preselected only when it is the sole root; [`apply-template-workspace`](../../workflows/stages/apply-template-workspace.md) installs it before Stage 2; Quick applies a supplied exact root directly. This file owns only the Brand schema.
Selection and installation follow [`routing.md`](../../workflows/routing.md) §7 and [`apply-template-workspace`](../../workflows/stages/apply-template-workspace.md). This file owns only the Brand schema.
## Creating a new brand
@@ -13,7 +13,7 @@
## Selection and installation
Selection follows the parent contract: Deck choices come only from the index (no directory scan or bare-ID/style-phrase match); a supplied exact root joins the selector and is preselected only when sole; [`apply-template-workspace`](../../workflows/stages/apply-template-workspace.md) installs it before Stage 2; Quick applies a supplied exact root directly and authors the installed Master/Layout/slot contract as lockless structured Slides unless the user explicitly requests visual-only flat use.
Selection and installation follow [`routing.md`](../../workflows/routing.md) §7 and [`apply-template-workspace`](../../workflows/stages/apply-template-workspace.md).
## `design_spec.md` contract
@@ -50,7 +50,7 @@ page_count: <N>
## Structured SVG contract
Every SVG is a complete preview declaring one root Master and Layout; fixed visuals are direct atoms; reusable regions are top-level slot groups with positive bounds and exactly one compatible carrier; zero-slot Layouts are valid; `{{...}}` is the authoring vocabulary and `data-pptx-placeholder*` the native contract. `standard` / `fidelity` author new SVGs and structure; `mirror` preserves source identities, parentage, assignments, placeholder facts, and supported visuals without synthesis; legacy contracts are never upgraded in place, and a flat directory shape alone is not a legacy signal.
Every SVG is a complete Slide preview under the contract of [`pptx-structure-interface.md`](../../references/pptx-structure-interface.md) §2; `{{...}}` is the authoring vocabulary and `data-pptx-placeholder*` the native contract. `standard` / `fidelity` author new SVGs and structure; `mirror` preserves source identities, parentage, assignments, placeholder facts, and supported visuals without synthesis; legacy contracts are never upgraded in place, and a flat directory shape alone is not a legacy signal.
## Workspace and creation
@@ -4,7 +4,7 @@ Project-level `design_spec.md` is a human-readable English-heading Markdown arti
## 1. Author the complete artifact
Compose the entire document in active context, then create `<project_path>/design_spec.md` once, first line through §X. **Depth follows the confirmed `design_spec_depth`**`brief` (default) or `complete`; both keep every required heading and machine-read field. `brief` serves a continuous run whose author also draws the pages: §I records production mechanics without restating Stage-1 prose, §VI may leave the scenario column empty, §IX `Content` is a short block list (one bullet per block in the phrasing that fits — a sentence for prose, `·`-joined parallel fragments, `/`-joined labels — never full copy), and `Layout` is one optional line; `Relationships` is written at both depths. `complete` writes full wording and layout prose; split mode, `refine_spec: true`, and preservation profiles force it.
Compose the entire document in active context, then create `<project_path>/design_spec.md` once, first line through §X. **Depth follows the confirmed `design_spec_depth`**`brief` (default) or `complete`; both keep every required heading and machine-read field. `brief` serves a continuous run whose author also draws the pages: §I records production mechanics without restating Stage-1 prose, §VI may leave the scenario column empty, §IX `Content` is a short block list (one bullet per block in the phrasing that fits — a sentence for prose, `·`-joined parallel fragments, `/`-joined labels — never full copy), and `Composition` is one optional line; `Relationships` is written at both depths. `complete` writes full wording and layout prose; split mode, `refine_spec: true`, and preservation profiles force it.
**Mandatory — new-project write**: the first non-empty line is exactly `<!-- ppt-master-schema: design-spec/v1 -->`, then `# <Project Name> - Design Spec`; every required section carries final values and the complete roster; conditional §VII appears only with a real catalog reference. Never write a placeholder-bearing file, copy example rows, or patch a scaffold field by field (`project_manager.py scaffold-spec` is an optional manual troubleshooting tool, not part of Generate authoring; resume and refine edit the existing completed Design Spec).
@@ -124,7 +124,7 @@ With an active template workspace, append exactly one line after the §I table
| --- | --- |
```
Preserve Title/Body characters and resolved stacks; omit a blank Typography upgrade and never place it in a stack. Each justified recurring family override adds its role to Font Plan plus `- **<Role> stack**: <complete ordered stack>` (roles: `Annotation`, `Footer`, `Footnote`, `Data`, `Emphasis`, `Quote`, `Code` — only recurring, intentional differences; a non-locked `Role rationale` only for an extra family); never collapse distinct Title/Body stacks or drop a declared role. Each Font Size Hierarchy value is a role anchor Executor may vary by `±2px` per occurrence; a short non-structural Hero/Display size may stay unlisted only while planned at most twice — its third occurrence needs a named row. Record every recurring palette role and size anchor the plan establishes, never one-off garnish. For confirmed custom directions add `Mode References`, `Mode Behavior`, `Visual Style References`, and `Visual Style Behavior` under Theme Style as applicable. `Stroke Width` under §VI only for a stroke library. `simple-icons` accompanies the one primary library only when real brand marks are required and is never a separate confirmation choice. The §VI table records the synced SVG pool and, at `complete` depth, broad scenarios — never page placement; leave it empty when no bundled or brand icons are prepared. Other prepared SVGs under the project `icons/` remain usable without entering that selection. Illustrated icons are AI image resources: their sheet and placed slice rows belong in §VIII, and only placed slices project to `spec_lock.md images`.
Preserve Title/Body characters and resolved stacks; omit a blank Typography upgrade and never place it in a stack. Each justified recurring family override adds its role to Font Plan plus `- **<Role> stack**: <complete ordered stack>` (roles: `Annotation`, `Footer`, `Footnote`, `Data`, `Emphasis`, `Quote`, `Code` — only recurring, intentional differences; a non-locked `Role rationale` only for an extra family); never collapse distinct Title/Body stacks or drop a declared role. Each Font Size Hierarchy value is a deck-wide role anchor; Executor's band and display exception are [`executor-base.md`](../references/executor-base.md) §2.1, so every recurring role is named here. Record every recurring palette role and size anchor the plan establishes, never one-off garnish. For confirmed custom directions add `Mode References`, `Mode Behavior`, `Visual Style References`, and `Visual Style Behavior` under Theme Style as applicable. `Stroke Width` under §VI only for a stroke library. `simple-icons` rows follow the brand-mark rule in the [icon README](../templates/icons/README.md). The §VI table records the synced SVG pool and, at `complete` depth, broad scenarios — never page placement; leave it empty when no bundled or brand icons are prepared. Other prepared SVGs under the project `icons/` remain usable without entering that selection. Illustrated icons are AI image resources: their sheet and placed slice rows belong in §VIII, and only placed slices project to `spec_lock.md images`.
When §VIII contains any `Acquire Via: ai` row, add under §III:
@@ -148,13 +148,13 @@ A custom rendering adds `Image Rendering Behavior`, and `Image Rendering Referen
## VIII. Image Resource List
| Filename | Dimensions | Ratio | Purpose | Type | Layout pattern | Crop Policy | Acquire Via | Status | Reference | text_policy | page_role |
| Filename | Dimensions | Ratio | Purpose | Type | Image pattern | Crop Policy | Acquire Via | Status | Reference | text_policy | page_role |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
```
§VII lists at most one `chart|table` reference per page (canonical key plus semantic Usage; resolve `family/key`, never derive paths from bare keys; omit when empty; legacy rows stay readable, new specs use four columns). §IX owns child visuals and unmatched fallbacks in `Visualization`; qualitative relationships live only on the `Relationships` line; Layout/Deck alone owns reusable PowerPoint structure. In §IX `Visualization`, key every independent data chart or pure text-grid table in `kebab-case` and add one `Native-ready` map `<key>=yes|no; ...``yes` by default, `no` only when the native payload cannot express the object; qualitative relationships and incidental microvisuals stay unkeyed.
§VII lists at most one `chart|table` reference per page (canonical `family/key` plus semantic Usage; omit when empty; legacy rows stay readable, new specs use four columns). §IX owns child visuals and unmatched fallbacks in `Visualization`; qualitative relationships live only on the `Relationships` line; Layout/Deck alone owns reusable PowerPoint structure. In §IX `Visualization`, key every independent data chart or pure text-grid table in `kebab-case` and add one `Native-ready` map `<key>=yes|no; ...``yes` by default, `no` only when the native payload cannot express the object; qualitative relationships and incidental microvisuals stay unkeyed.
§VIII authors every planned or required resource from the confirmed source boundary: one concise non-empty `Layout pattern` suggestion in ordinary language (optionally citing hierarchical ids from the layout library; an image-led `adaptive` row names the page job the image resolves next to the composition serving it); `Crop Policy` `adaptive` or `no-crop`; `Acquire Via` `ai`, `web`, `user`, `placeholder`, or `slice`; unresolved required assets kept as `Pending` or `Needs-Manual`; native formulas never enter it. `Layout pattern` is per-resource — how several images relate on one page (repeated views, sequencing) is stated once in §IX `Images` as a Reference, never as duplicate rows; paint, overlay, and geometry are Executor's.
§VIII authors every planned or required resource from the confirmed source boundary: one concise non-empty `Image pattern` suggestion in ordinary language (optionally citing hierarchical ids from the layout library; an image-led `adaptive` row names the page job the image resolves next to the composition serving it); `Crop Policy` `adaptive` or `no-crop`; `Acquire Via` `ai`, `web`, `user`, `placeholder`, or `slice`; unresolved required assets kept as `Pending` or `Needs-Manual`; native formulas never enter it. `Image pattern` is per-resource — how several images relate on one page (repeated views, sequencing) is stated once in §IX `Images` as a Reference, never as duplicate rows; paint, overlay, and geometry are Executor's.
### 2.4 Complete page roster and notes
@@ -169,7 +169,7 @@ One ordered Slide block per page; count and order equal §I `Page Count`; `Conte
- **Audience move**: <audience state before → after>
- **Relationships**: <the page's semantic units and the source-stated order / link / parent / membership / contrast / overlap among them, or none; no shape, carrier, or authoring words>
- **Layout**: <Reference — macro composition, hierarchy, and visual focus as a starting sketch; chosen prototype when template-active; optional at brief depth>
- **Composition**: <Reference — macro composition, hierarchy, and visual focus as a starting sketch; chosen prototype when template-active; optional at brief depth>
- **Title**: <preferred page title>
- **Core message**: <one governing assertion>
- **Content**: <complete content at complete depth; short block list at brief depth>
@@ -187,7 +187,7 @@ One ordered Slide block per page; count and order equal §I `Page Count`; `Conte
With Speaker Notes disabled, §X keeps only `- **Generation**: disabled`; an explicit notes-off/audio-on conflict blocks before authoring. When a final/literal narration script will become notes or audio, §X `Content` names the source and says `preserve verbatim`, with the segmented script kept in `notes/total.md`.
Optional Slide lines, added only when the capability earns a place (never an empty or `none` placeholder): `Mathematical content` (a valid delimiter-free LaTeX body — content authority for [`native-formula.md`](../references/native-formula.md), not a policy or marker; Executor chooses text, inline, or block); `Visualization` / `Images` when the Slide consumes §VII/§VIII or a page-local visual model, naming every value-driven geometry, cell grid, and child visual (only independent Chart/Table entries carry keys; qualitative relationships stay on the `Relationships` line, never a model name or grammar enum; §IX may choose a custom fallback; native construction is discovered by Executor, never a Design Spec field); `Motion suggestion` (purpose and semantic order/relationship, never registry keys, options, timing, ids, or coverage — it never activates execution, creates content, or binds implementation; required visible image states go in `Layout` / `Images` only for an explicit motion requirement or an enabled outcome); keyed `Native-ready`; `Fact IDs` for sourced claims; `Data class: scenario` for invented values. Except on preservation paths, `Cover impact` carries a binding hook and adaptable composition, and `Closing impact` the same split only when the deck genuinely resolves. Roster, order, content, and `Relationships` stay authoritative; §V/§IX layout, cover/closing composition, capability, motif, non-`ai` §VIII image-layout, and §VII directions are References — starting sketches Executor adjusts or replaces freely for the page's purpose, with no upstream repair or stated reason, carrying no binding semantics. When the user, a template, or a resource contract requires such a property, write `(binding)` after the field label (`- **Layout (binding)**:`) and Executor follows it literally. For free-design pages, `Layout` describes relationships, hierarchy, focus, and optional macro region/span suggestions — never element-level `x` / `y` / `width` / `height`, fixed gaps, or an authoring method; literal geometry is preserved only when the user requires it or a mirror/template contract owns it.
Optional Slide lines, added only when the capability earns a place (never an empty or `none` placeholder): `Mathematical content` (a valid delimiter-free LaTeX body — content authority for [`native-formula.md`](../references/native-formula.md), not a policy or marker; Executor chooses text, inline, or block); `Visualization` / `Images` when the Slide consumes §VII/§VIII or a page-local visual model, naming every value-driven geometry, cell grid, and child visual (only independent Chart/Table entries carry keys; qualitative relationships stay on the `Relationships` line, never a model name or grammar enum; §IX may choose a custom fallback; native construction is discovered by Executor, never a Design Spec field); `Motion suggestion` (purpose and semantic order/relationship, never registry keys, options, timing, ids, or coverage — it never activates execution, creates content, or binds implementation; required visible image states go in `Composition` / `Images` only for an explicit motion requirement or an enabled outcome); keyed `Native-ready`; `Fact IDs` for sourced claims; `Data class: scenario` for invented values. Except on preservation paths, `Cover impact` carries a binding hook and adaptable composition, and `Closing impact` the same split only when the deck genuinely resolves. Roster, order, content, and `Relationships` stay authoritative; §V/§IX layout, cover/closing composition, capability, motif, non-`ai` §VIII image-layout, and §VII directions are References under [`strategist.md`](../references/strategist.md) §1 Confirmed-value semantics. When the user, a template, or a resource contract requires such a property, write `(binding)` after the field label (`- **Composition (binding)**:`) and Executor follows it literally. For free-design pages, `Composition` describes relationships, hierarchy, focus, and optional macro region/span suggestions — never element-level `x` / `y` / `width` / `height`, fixed gaps, or an authoring method; literal geometry is preserved only when the user requires it or a mirror/template contract owns it.
---
@@ -13,7 +13,7 @@
## Selection and identity boundary
Selection follows the parent contract: Layout choices come only from the index (no directory scan or bare-ID/style-phrase match); a supplied exact root joins the selector and is preselected only when sole; [`apply-template-workspace`](../../workflows/stages/apply-template-workspace.md) installs it before Stage 2; Quick applies a supplied exact root directly and authors the installed Master/Layout/slot contract as lockless structured Slides unless the user explicitly requests visual-only flat use.
Selection and installation follow [`routing.md`](../../workflows/routing.md) §7 and [`apply-template-workspace`](../../workflows/stages/apply-template-workspace.md).
## `design_spec.md` contract
@@ -46,7 +46,7 @@ page_types: [cover, toc, chapter, content, ending]
## Structured SVG and slot contract
Every SVG is a complete preview declaring one root Master and Layout; fixed visuals are direct atoms; a slot is a top-level `<g id>` with positive design-zone bounds and exactly one compatible carrier; zero-slot Layouts are valid; a typed `picture` / `chart` / `table` slot promises no inserted picture or native object — the generated Slide supplies content and native replacement stays an explicit export choice. Use canonical `{{PLACEHOLDER}}` names ([`template-designer.md`](../../references/template-designer.md#4-placeholder-reference-canonical-convention-overridable-per-template)) with a `placeholders:` frontmatter map for overrides. `standard` / `fidelity` author new SVGs and structure; `mirror` preserves source identities, parentage, assignments, placeholder facts, and supported visuals without synthesis; legacy contracts are never upgraded in place, and a flat directory shape alone is not a legacy signal.
Every SVG is a complete Slide preview under the contract of [`pptx-structure-interface.md`](../../references/pptx-structure-interface.md) §2; a typed `picture` / `chart` / `table` slot promises no inserted picture or native object — the generated Slide supplies content and native replacement stays an explicit export choice. Use canonical `{{PLACEHOLDER}}` names ([`template-designer.md`](../../references/template-designer.md#4-placeholder-reference-canonical-convention-overridable-per-template)) with a `placeholders:` frontmatter map for overrides. `standard` / `fidelity` author new SVGs and structure; `mirror` preserves source identities, parentage, assignments, placeholder facts, and supported visuals without synthesis; legacy contracts are never upgraded in place, and a flat directory shape alone is not a legacy signal.
## Workspace and creation
@@ -93,7 +93,7 @@
## VIII. Image Resource List
| Filename | Dimensions | Ratio | Purpose | Type | Layout pattern | Crop Policy | Acquire Via | Status | Reference | text_policy | page_role |
| Filename | Dimensions | Ratio | Purpose | Type | Image pattern | Crop Policy | Acquire Via | Status | Reference | text_policy | page_role |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
## IX. Content Outline
@@ -103,7 +103,7 @@
#### Slide 01 - [fill]
- **Audience move**: [fill]
- **Layout**: [non-binding macro composition direction]
- **Composition**: [non-binding macro composition direction]
- **Title**: [fill]
- **Core message**: [fill]
- **Content**: [fill]
@@ -69,20 +69,20 @@ A `(user)` row is the user's sentence, not a paraphrase and never widened; a Str
- P09: table/record_table
```
Project each §VII row into at most one `page_visualizations` `<chart|table>/<key>` row per page, resolved to one live SVG; Usage, children, no-match, and qualitative relationships stay in §IX; the reference locks neither type, geometry, nor native output. **Legacy compatibility**: existing `page_charts` bare keys resolve uniquely across the two live registries; retired Structure keys are semantic-only with no SVG; dual page declarations conflict even when they resolve alike.
Project each §VII row into at most one `page_visualizations` `<chart|table>/<key>` row per page, resolved to one live SVG; Usage, children, no-match, and qualitative relationships stay in §IX. **Legacy compatibility**: existing `page_charts` bare keys resolve uniquely across the two live registries; retired Structure keys are semantic-only with no SVG; dual page declarations conflict even when they resolve alike.
Typography projection (excluding Character/upgrade References): Title font stack → `title_family`; Body font stack → `body_family` plus compatibility `font_family`; each additional recurring role `<role>``<role>_family`; each Font Size Hierarchy role → lowercase snake_case `<role>` with its numeric anchor. New locks always write `title_family` and `body_family` even when equal; omit only family roles that inherit without an override; old locks fall back to `font_family`. Executor may use the anchor or a value within `±2px`; a short non-structural Hero/Display size may stay absent only while the same undeclared value appears at most twice — its third occurrence needs a named role.
Typography projection (excluding Character/upgrade References): Title font stack → `title_family`; Body font stack → `body_family` plus compatibility `font_family`; each additional recurring role `<role>``<role>_family`; each Font Size Hierarchy role → lowercase snake_case `<role>` with its numeric anchor. New locks always write `title_family` and `body_family` even when equal; omit only family roles that inherit without an override; old locks fall back to `font_family`.
---
## 4. Field Grammar Index
- `font_family`, `title_family`, `body_family`, and every `<role>_family`: one non-empty PPT-safe exported family stack; `font_family` is the body/default compatibility stack, not permission to erase role differences.
- Every non-family `typography` value: a positive finite unitless px anchor; intermediate values within `±2px` need no row; a third occurrence of an undeclared Hero/Display size or any structural use requires Design Spec repair and a named anchor.
- Every non-family `typography` value: a positive finite unitless px anchor; Executor's band and display exception are [`executor-base.md`](../references/executor-base.md) §2.1, and the extension rule is §6.
- `icons.library`: `chunk-filled`, `tabler-filled`, `tabler-outline`, `phosphor-duotone`, or `none`; `simple-icons/*` marks may appear alone or alongside in `inventory` without becoming a library or confirmation choice; every SVG under `<project_path>/icons/` remains valid material; illustrated-icon slices create no icon field — their paths belong under `images`, and the unplaced sheet stays out.
- `objective`: one concise sentence preserving goal and audience success condition.
- `image_rendering`: one catalog id, or `custom` with `image_rendering_behavior`.
- `images`: `- <key>: <path> | source=<via> | crop=<adaptive|no-crop>` (e.g. `- p04: images/a.png | source=user | crop=no-crop`); canonical `images/<filename>` path; `source` and `crop` project §VIII exactly; `Layout pattern` is not projected (Executor reads it from §VIII as a recommendation); a legacy `pattern=<layout>` segment is accepted; omit unplaced sheets.
- `images`: `- <key>: <path> | source=<via> | crop=<adaptive|no-crop>` (e.g. `- p04: images/a.png | source=user | crop=no-crop`); canonical `images/<filename>` path; `source` and `crop` project §VIII exactly; `Image pattern` is not projected (Executor reads it from §VIII as a recommendation); a legacy `pattern=<layout>` segment is accepted; omit unplaced sheets.
- Custom reference fields: comma-separated exact catalog ids without duplicates, valid only for `custom`; omit for a genuinely novel direction.
- `stroke_width`: `1.5`, `2`, or `3`, only for `tabler-outline`.
- `page_rhythm`: `P` + at least two digits (`P01`, `P100`) followed by `anchor|dense|breathing`.
@@ -104,4 +104,4 @@ Typography projection (excluding Character/upgrade References): Title font stack
## 6. Anchor and extension semantics
Confirmed core palette roles and every declared typography family/size role are stable cross-page anchors. Page-local tints, gradient stops, shadow/glow paints, transparency composites, and one-off export-safe display families may be authored from context without a row. Executor may adjust one occurrence within its size role's `±2px` band. When a contextual value becomes a recurring semantic role, or an 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 band returns upstream immediately. Never expand the lock merely to empty an informational checker comparison — a lock edit expresses reuse or identity, not incidental literals.
Confirmed core palette roles and every declared typography family/size role are stable cross-page anchors. Page-local tints, gradient stops, shadow/glow paints, transparency composites, and one-off export-safe display families may be authored from context without a row; the size band and display exception Executor works within are [`executor-base.md`](../references/executor-base.md) §2.1. When a contextual value becomes a recurring semantic role, or an 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 band returns upstream immediately. Never expand the lock merely to empty an informational checker comparison — a lock edit expresses reuse or identity, not incidental literals.
@@ -8,7 +8,7 @@
## Selection, Precedence, and Installation
Selection follows the parent contract: Style choices come only from `styles_index.json`; a supplied exact root joins the selector and is preselected only when sole; a consulting label or visual description is a brief and never activates a workspace; Quick applies a supplied exact root directly and reads the installed copy before authoring flat pages.
Selection and installation follow [`routing.md`](../../workflows/routing.md) §7 and [`apply-template-workspace`](../../workflows/stages/apply-template-workspace.md); a consulting label or visual description is a brief and never activates a workspace.
| Decision | Precedence |
|---|---|
@@ -13,9 +13,18 @@ Create one reusable template workspace under the global library (default) or `pr
| `library` (default) | `skills/ppt-master/templates/<kind_dir>/<template_id>/` | `templates/design_spec.md` | `register_template.py` against the kind index |
| `project` | `<target_project>/` (initialized by `project_manager.py init`) | `templates/design_spec.<kind>.<id>.md` (kind/id equal frontmatter `kind` / `<kind>_id`) | None; the root stays an ordinary explicit workspace whose `templates/` may accumulate one Brand, Style, Layout, and Deck over separate runs — Layout owns the active roster when both coexist, Deck keeps identity and application context |
**Hard rule — one workspace routing contract**: scope changes the parent path, spec filename, and registration — never the spec schema or asset routes. Both scopes use required `templates/`, optional `images/` (every bitmap; SVG href `../images/<name>`) and `icons/imported/` (one canonical copy of each imported decoration vector), and conditional `exports/` (review evidence, required for multi-Master templates, Git-ignored in the library, never consumed by application). Never create an optional directory or placeholder solely to keep an empty path; leave pre-existing empty project scaffolding untouched and omit it from completion. Create Style contributes only its spec. Do not maintain a library-only flat package or project-only thin-bundle branch.
**Hard rule — one workspace routing contract**: scope changes the parent path, spec filename, and registration — never the spec schema or asset routes. Do not maintain a library-only flat package or project-only thin-bundle branch.
**Boundaries**: Create Template never fills content into a PPTX, adds Master/Layout structure to an existing PPTX/SVG, or outputs the user's final deck — it authors a separate workspace whose root returns to [`generate-pptx`](./generate-pptx.md) Step 3 as an exact candidate (a project-scoped workspace selected for its own project is consumed in place). Page images that should become final editable slides use [`image-to-pptx.md`](./profiles/image-to-pptx.md), not a template.
| Directory | Rule |
|---|---|
| `templates/` | Required in both scopes |
| `images/` | Optional; every bitmap; SVG href `../images/<name>` |
| `icons/imported/` | Optional; one canonical copy of each imported decoration vector |
| `exports/` | Conditional; review evidence, required for multi-Master templates, Git-ignored in the library, never consumed by application |
Never create an optional directory or placeholder solely to keep an empty path; leave pre-existing empty project scaffolding untouched and omit it from completion. Create Style contributes only its spec.
**Boundaries**: Create Template never fills content into a PPTX, adds Master/Layout structure to an existing PPTX/SVG, or outputs the user's final deck. It authors a separate workspace whose root returns to [`generate-pptx`](./generate-pptx.md) Step 3 as an exact candidate (a project-scoped workspace selected for its own project is consumed in place). Page images that should become final editable slides use [`image-to-pptx.md`](./profiles/image-to-pptx.md), not a template.
## Child Workflow Dispatch
@@ -26,7 +35,7 @@ Create one reusable template workspace under the global library (default) or `pr
| Create Layout | Reuse a brand-neutral structural skeleton without a recurring application | `templates/layouts/<layout_id>/` | Canvas, page grammar, semantic text roles, Master/Layout/slot contract, SVG roster; no identity or application contract |
| Create Deck | Reuse a branded structural system or a recurring application | `templates/decks/<deck_id>/` | Descriptive application context, integrated identity/structure, SVG roster |
A complete source PPTX does not determine the kind — classify only the stable rules worth reusing. Ask one discriminator only when the requested artifact is genuinely ambiguous; once selected, never reopen kind selection inside the child's gate, execute two children for one workspace, or blend schemas. Shared kind and workspace model: [`templates/README.md`](../templates/README.md); application: [`apply-template-workspace`](./stages/apply-template-workspace.md).
A complete source PPTX does not determine the kind — classify only the stable rules worth reusing. Ask one discriminator only when the requested artifact is genuinely ambiguous. Once selected, never reopen kind selection inside the child's gate, execute two children for one workspace, or blend schemas. Shared kind and workspace model: [`templates/README.md`](../templates/README.md); application: [`apply-template-workspace`](./stages/apply-template-workspace.md).
## Process Overview
@@ -50,23 +59,36 @@ Run every applicable branch for the bundle (one source, several files, mixed typ
| **D** Text / document / website / assets | Direct text, Markdown/TXT, DOCX/PDF/HTML/URL, brand manuals, logo/icon/font assets | Direct text as-is; convert documents/URLs with `source_to_md.py` into a temporary analysis workspace; inventory explicit assets | `standard` only by itself |
| **E** Nothing | A request with no source and no substantive brief | Skip analysis; collect every Required value in Steps 23 | `standard` only |
**Bundle rules**: `standard` may combine every confirmed channel — never force one source type. The AI derives the internal strategy from natural-language intent plus evidence (`fidelity` needs A/B page evidence; `mirror` needs A or a complete current B contract; C/D/E supplement but never create native topology) and never asks the user to choose these labels. Keep facts, explicit user decisions, and AI suggestions distinct; surface contradictions in Step 2. Supplemental inputs may explain a confirmed `mirror` source but cannot alter its graph or visuals.
**Bundle rules**: `standard` may combine every confirmed channel — never force one source type. The AI derives the internal strategy from natural-language intent plus evidence and never asks the user to choose these labels. Keep facts, explicit user decisions, and AI suggestions distinct; surface contradictions in Step 2. Supplemental inputs may explain a confirmed `mirror` source but cannot alter its graph or visuals.
**Internal strategies**: `standard` / `fidelity` review all source structure, then author a compact or broader source-aligned roster with one Slide prototype per retained Layout; `mirror` authors compact parsed SVG for every source Slide, preserving the reachable graph, meaning, ownership, and similar presentation — not code identity. Create Layout mirror requires a brand/application-neutral contract. Future decks need not keep source page count/order.
| Strategy | Evidence needed | Authoring |
|---|---|---|
| `standard` | Any channel; C/D/E supplement but never create native topology | Review all source structure, then author a compact source-aligned roster with one Slide prototype per retained Layout |
| `fidelity` | A/B page evidence | Review all source structure, then author a broader source-aligned roster with one Slide prototype per retained Layout |
| `mirror` | A, or a complete current B contract | Author compact parsed SVG for every source Slide, preserving the reachable graph, meaning, ownership, and similar presentation — not code identity; Create Layout mirror requires a brand/application-neutral contract |
Future decks need not keep source page count/order.
### 1A. `.pptx` reference
Run `pptx_template_import.py "<reference.pptx>"`. Type A is the canonical mirror path: analysis manifests and inheritance own surviving native structure; `authoring-svg/` is the compact editable projection Template_Designer inspects and may redraw while preserving meaning, structure, and similar presentation; lossless `svg/` is immutable validation and non-visible-payload backing, never visible authoring; optional `svg-flat/` verifies full pages. In `standard` / `fidelity`, imported facts do not define output topology. Never copy lossless or flat pages into `templates/`; for Type A `mirror`, `mirror_template_materialize.py` validates and publishes after review, fidelity edits, and the readability pass, and authored modes never use it.
Run `pptx_template_import.py "<reference.pptx>"`; the workspace it produces and each artifact's role are [`template-tools.md`](../scripts/docs/template-tools.md). Type A is the canonical mirror path; in `standard` / `fidelity`, imported facts do not define output topology. Never copy lossless or flat pages into `templates/`. For Type A `mirror`, `mirror_template_materialize.py` validates and publishes after review, fidelity edits, and the readability pass; authored modes never use it.
**Explicit complex-SVG picture normalization** (`standard` / `fidelity` only): when one imported native group is deliberately retained as one complex SVG picture rather than rebuilt as editable paths, select its exact id in the layered IR with `extract_svg_pictures.py ... --select "<group_id>" --resource-root "<import_workspace>" --images-dir "<import_workspace>/picture-assets" --inplace` (repeat `--select` for independent siblings; select the outer group when an ancestor carries a transform, style, clip, or opacity). If chosen for a Master or Layout, copy the asset into the image pool and author the fixed atom as a direct `<image data-pptx-layer="master|layout">`. This is a semantic decision, never automatic, never by repetition, never a way to infer ownership; not for placeholders, individual native shapes, table/chart fallbacks, icon placeholders, authored presets, or `mirror`.
**Explicit complex-SVG picture normalization** (`standard` / `fidelity` only): when one imported native group is deliberately retained as one complex SVG picture rather than rebuilt as editable paths, select its exact id in the layered IR with `extract_svg_pictures.py ... --select "<group_id>" --resource-root "<import_workspace>" --images-dir "<import_workspace>/picture-assets" --inplace` (repeat `--select` for independent siblings; select the outer group when an ancestor carries a transform, style, clip, or opacity). If chosen for a Master or Layout, copy the asset into the image pool and author the fixed atom as a direct `<image data-pptx-layer="master|layout">`. This is a semantic decision, never automatic, never by repetition, never a way to infer ownership. Not for placeholders, individual native shapes, table/chart fallbacks, icon placeholders, authored presets, or `mirror`.
**Read order**: `standard` / `fidelity` read `analysis/manifest.json`, exported resources, `svg/inheritance.json`, `authoring_summary.json`, and every cleaned layered IR document (Masters, Layouts, Slides — the complete read surface, including Layouts unused by any sample slide); flat pages are optional spot checks; never `authoring_manifest.json`. `mirror` reads both manifests, inheritance, the summary, every source Slide SVG, and only reachable Master/Layout SVGs. Use manifest facts for orientation and screenshots or the original PPTX only for visual cross-checking; never bulk-read opaque payload.
**Read order**:
| Strategy | Read |
|---|---|
| `standard` / `fidelity` | `analysis/manifest.json`, exported resources, `svg/inheritance.json`, `authoring_summary.json`, and every cleaned layered IR document (Masters, Layouts, Slides — the complete read surface, including Layouts unused by any sample slide); flat pages are optional spot checks; never `authoring_manifest.json` |
| `mirror` | Both manifests, inheritance, the summary, every source Slide SVG, and only reachable Master/Layout SVGs |
Use manifest facts for orientation and screenshots or the original PPTX only for visual cross-checking; never bulk-read opaque payload.
**Mirror reachable-graph gate**: before offering `mirror`, compare every source Slide and referenced Layout/Master with the authoring summary; missing reachable evidence or ambiguous parentage blocks; omit unused identities. The publisher verifies source SHA, refs, graph/assignment closure, and subtree hashes; an authored change never triggers visible XML restoration.
### Basic norm extraction (mandatory when reference content exists)
Extract the source's observable operating rules — not generic design advice — so they flow into `design_spec.md`. Create Brand extracts only the identity subset; Create Style extracts argument flow, message/evidence discipline, open page-role vocabulary, data-expression rules, composition/density rhythm, visual defaults, and image/icon direction while discarding source-specific audience, objective, page order/count, mappings, canvas, and structure. Create Layout/Create Deck extract:
Extract the source's observable operating rules — not generic design advice — so they flow into `design_spec.md`. Create Brand extracts only the identity subset. Create Style extracts argument flow, message/evidence discipline, open page-role vocabulary, data-expression rules, composition/density rhythm, visual defaults, and image/icon direction while discarding source-specific audience, objective, page order/count, mappings, canvas, and structure. Create Layout/Create Deck extract:
| Norm area | Extract from | Record as |
|---|---|---|
@@ -83,7 +105,15 @@ Extract the source's observable operating rules — not generic design advice
### 1B. Existing SVG assets
Resolve the Type B source: a root exposing any `templates/` Design Spec uses `<input>/templates/` plus sibling `images/` / `icons/`; otherwise the directory is loose evidence (flatness is not a structure signal). Build the throwaway IR bundle per [`template-tools.md`](../scripts/docs/template-tools.md), then read `authoring_summary.json`, `ls` the workspace, and every cleaned `authoring-svg/*.svg` for canvas, recurring colors (dominant 24 hex as candidate theme colors), fonts, existing `{{...}}` placeholders, and structural decoration; open imported vectors only when a specific asset affects a decision. A companion `design_spec.md` / `spec_lock.md` is part of the mirror source contract and must agree with the SVG identities; in authored modes it is context only. Caveats: `mirror` requires a complete current explicit contract and preserves page count/order, presentation, each Slide's Layout/Master chain, slot metadata, native-object metadata, and ownership in the new workspace (page type from a PPT Master-convention filename, else `content`; a loose visual-only folder cannot mirror); `fidelity` designs a broader new roster and structure after inspecting the complete roster; legacy or unstructured B (`baseline` / `preserve` / `layout_strategy: distill` / `data-pptx-layout-kind` / direct atomic placeholders / no root identity) is visual reference for authored modes only — use the original PPTX to mirror native facts; a selected free-design subset ingests only the named pages and never scans the whole `svg_output/`.
**Source resolution**: a root exposing any `templates/` Design Spec uses `<input>/templates/` plus sibling `images/` / `icons/`; otherwise the directory is loose evidence (flatness is not a structure signal). A selected free-design subset ingests only the named pages and never scans the whole `svg_output/`.
**Read**: build the throwaway IR bundle per [`template-tools.md`](../scripts/docs/template-tools.md), then read `authoring_summary.json`, `ls` the workspace, and every cleaned `authoring-svg/*.svg` for canvas, recurring colors (dominant 24 hex as candidate theme colors), fonts, existing `{{...}}` placeholders, and structural decoration. Open imported vectors only when a specific asset affects a decision. A companion `design_spec.md` / `spec_lock.md` is part of the mirror source contract and must agree with the SVG identities; in authored modes it is context only.
| Type B strategy | Rule |
|---|---|
| `mirror` | Requires a complete current explicit contract; preserves page count/order, presentation, each Slide's Layout/Master chain, slot metadata, native-object metadata, and ownership in the new workspace (page type from a PPT Master-convention filename, else `content`); a loose visual-only folder cannot mirror |
| `fidelity` | Designs a broader new roster and structure after inspecting the complete roster |
| Legacy or unstructured B (`baseline` / `preserve` / `layout_strategy: distill` / `data-pptx-layout-kind` / direct atomic placeholders / no root identity) | Visual reference for authored modes only; use the original PPTX to mirror native facts |
### 1C. Image / visual references
@@ -91,7 +121,16 @@ Resolve the Type B source: a root exposing any `templates/` Design Spec uses `<i
### 1D. Text, document, website, and asset references
Direct chat text is valid input. Read Markdown/TXT directly; convert documents/URLs with `source_to_md.py "<file_or_URL_or_dir>" -o "<text_analysis_workspace>"`; inventory supplied logo/icon/font assets (raster assets also enter the Type C pass; page/template SVGs may enter Type B); never infer licensing, official status, or native structure from filenames. Extract only what the source states: identity rules; Style method (argument flow, evidence discipline, page-role vocabulary, hierarchy, rhythm, visual defaults, image/icon direction, review focus — never the source's audience, objective, sequence, or page count); structure rules; Deck application (recurring situations, audiences/outcomes, delivery assumptions, representative roles, examples, negative requirements — never converted into mandatory future-use policy). A user-authored value is `[decision]` in any carrier; `[fact]` only when independently traceable to an external authority or machine-observable metadata; vague prose stays `[suggested]`. Text and assets never supply Master/Layout topology.
Direct chat text is valid input. Read Markdown/TXT directly; convert documents/URLs with `source_to_md.py "<file_or_URL_or_dir>" -o "<text_analysis_workspace>"`; inventory supplied logo/icon/font assets (raster assets also enter the Type C pass; page/template SVGs may enter Type B). Never infer licensing, official status, or native structure from filenames. Text and assets never supply Master/Layout topology.
| Extract only what the source states | Content |
|---|---|
| Identity rules | As stated |
| Style method | Argument flow, evidence discipline, page-role vocabulary, hierarchy, rhythm, visual defaults, image/icon direction, review focus — never the source's audience, objective, sequence, or page count |
| Structure rules | As stated |
| Deck application | Recurring situations, audiences/outcomes, delivery assumptions, representative roles, examples, negative requirements — never converted into mandatory future-use policy |
**Provenance**: a user-authored value is `[decision]` in any carrier; `[fact]` only when independently traceable to an external authority or machine-observable metadata; vague prose stays `[suggested]`.
### 1E. No reference material
@@ -101,7 +140,14 @@ Skip analysis; Step 2 lists every Required item as `[decision]`. Create Brand ma
## Step 2: Fact-Based Brief Proposal
Compose one concise natural-language proposal, in the user's language, describing the intended result with every material value labelled: `[fact]` (external authority or machine-observable metadata — a user-written brief file is not a fact), `[suggested]` (AI-inferred), `[decision]` (explicit user-authored, in chat, pasted text, or a brief file), `[derived]` (internal execution value recorded for provenance, never a user choice). Present one recommended creation plan — never a menu of modes, fidelity levels, or checklists; translate "原样还原" / "提取成可复用母版和版式" / "保留风格但重新设计" directly into the plan; ask a follow-up only when a missing decision would materially change the artifact. Technical IDs appear only in a compact audit note.
Compose one concise natural-language proposal, in the user's language, describing the intended result with every material value labelled. Present one recommended creation plan — never a menu of modes, fidelity levels, or checklists; translate "原样还原" / "提取成可复用母版和版式" / "保留风格但重新设计" directly into the plan. Ask a follow-up only when a missing decision would materially change the artifact. Technical IDs appear only in a compact audit note.
| Label | Meaning |
|---|---|
| `[fact]` | External authority or machine-observable metadata — a user-written brief file is not a fact |
| `[suggested]` | AI-inferred |
| `[decision]` | Explicit user-authored, in chat, pasted text, or a brief file |
| `[derived]` | Internal execution value recorded for provenance, never a user choice |
| Field | Must show |
|---|---|
@@ -117,7 +163,28 @@ Compose one concise natural-language proposal, in the user's language, describin
| Native structure plan | Layout/Deck: compact `standard`, broader `fidelity`, or source-reachable `mirror`; every authored Layout needs a Slide prototype; reject duplicate Masters |
| Asset bundling | Brand/Layout/Deck: included assets plus excluded candidates with a one-line reason; Style records textual provenance only |
Items to surface: output scope and target project (`[decision]`); template ID (`[decision]` or a filesystem-safe ASCII slug `[suggested]`, the library index key) and display name (`[decision]` when supplied, otherwise `[suggested]`, for Type A often from `analysis/manifest.json.source.name`); category; applicable scenarios (Brand identity use cases; Style broad best-fit context without binding audience/outcome; Layout supported content shapes and delivery settings without communication ownership; Deck recurring situations); Deck application context and representative roles; identity/method/structural summary; Style communication method, visual-system defaults (overrideable seeds, never identity truth or Stage-2 locks), and review focus (applies only if the user enables visual review); theme mode and canvas (A/B `[fact]`, C `[suggested]`, D `[fact]` / `[decision]` / `[suggested]`, E `[decision]` with default `ppt169` `1280x720`); internal creation strategy (`[derived]`); native structure facts for A/structured B (`[fact]`: master/layout counts, parentage, assignments, placeholder identities, multi-master status); structure ownership plan and per-page reference treatment (`[derived]`); basic norms; reference source; theme color and fonts (Brand/Deck only; C fonts are never derivable); design style (required for Style as an overrideable seed); assets list (never for Style); keywords (35 tags; not for Brand). For Type A Layout/Deck, also name the authoring documents the derived strategy requires, a one-line source Master/Layout summary, and whether source structure facts will be preserved or used only as evidence.
**Items to surface**:
| Item | Provenance / rule |
|---|---|
| Output scope and target project | `[decision]` |
| Template ID | `[decision]`, or a filesystem-safe ASCII slug `[suggested]`; the library index key |
| Display name | `[decision]` when supplied, otherwise `[suggested]`; for Type A often from `analysis/manifest.json.source.name` |
| Category | Per the field table |
| Applicable scenarios | Brand identity use cases; Style broad best-fit context without binding audience/outcome; Layout supported content shapes and delivery settings without communication ownership; Deck recurring situations |
| Deck application context and representative roles | Deck only |
| Identity / method / structural summary | Per kind |
| Style method, visual-system defaults, review focus | Defaults are overrideable seeds, never identity truth or Stage-2 locks; review focus applies only if the user enables visual review |
| Theme mode and canvas | A/B `[fact]`, C `[suggested]`, D `[fact]` / `[decision]` / `[suggested]`, E `[decision]` with default `ppt169` `1280x720` |
| Internal creation strategy | `[derived]` |
| Native structure facts (A / structured B) | `[fact]`: master/layout counts, parentage, assignments, placeholder identities, multi-master status |
| Structure ownership plan and per-page reference treatment | `[derived]` |
| Basic norms, reference source | As extracted |
| Theme color and fonts | Brand/Deck only; C fonts are never derivable |
| Design style | Required for Style as an overrideable seed |
| Assets list | Never for Style |
| Keywords | 35 tags; not for Brand |
| Type A Layout/Deck additions | The authoring documents the derived strategy requires, a one-line source Master/Layout summary, and whether source structure facts will be preserved or used only as evidence |
**Persist the portable brief into `<design_spec_path>`** in Step 4 as YAML frontmatter with the child ID key (`brand_id` / `style_id` / `layout_id` / `deck_id`) and only child-owned fields: Brand its identity schema; Style only `style_id`, `kind`, `summary`, `keywords`; Layout/Deck the confirmed portable fields (`kind`, `category`, `summary`, `keywords`, `primary_color` for deck, `page_types` for layout, `canvas_format`, `canvas_width`, `canvas_height`, `canvas_viewbox`, `source_viewbox`, `replication_mode`, `native_structure_mode`, …). Never persist a generic `template_id`, `output_scope`, or `target_project`. In library scope `register_template.py` reads this frontmatter in Step 7.
@@ -127,7 +194,17 @@ Items to surface: output scope and target project (`[decision]`); template ID (`
**MANDATORY interactive gate — blocks Steps 4 onward.** Echo the finalized brief in one message, then emit `[TEMPLATE_BRIEF_CONFIRMED]` on its own line. Silently inferring values from files, direct text, an opened IDE file, or prior conversation is a route violation: even a complete PPTX, website, or written brief only informs the brief.
Before emitting the marker, all must hold: every Required item shown with provenance; one natural-language plan, no mode menu; internal IDs absent or confined to an audit note; the user replied with corrections or acceptance; scope confirmed (project with an explicit initialized path); for Layout/Deck the canvas is fixed and the derived strategy matches the evidence (`fidelity` needs A/B, `mirror` needs A or structured B, C/D/E permit only `standard`; Layout mirror evidence is brand/application-neutral); every channel analyzed or explicitly excluded with conflicts surfaced; for mirror, every source Slide and reachable chain valid and context-complete with omitted identities and missing facts reported; child-specific norms surfaced or marked N/A; for Style, method, vocabulary, evidence rules, defaults, direction, and review focus confirmed with project-specific context and identity/structure N/A; for Layout/Deck, structure ownership explicit; for Deck, application context understood without turning it into policy, and for Layout no application or identity leaked; for Brand, all identity fields confirmed with canvas/replication/structure N/A; library metadata complete enough to register, or project scope with no registration planned.
Before emitting the marker, all of these hold:
| Scope | Condition |
|---|---|
| All | Every Required item shown with provenance; one natural-language plan, no mode menu; internal IDs absent or confined to an audit note; the user replied with corrections or acceptance; scope confirmed (project with an explicit initialized path); every channel analyzed or explicitly excluded with conflicts surfaced; child-specific norms surfaced or marked N/A; library metadata complete enough to register, or project scope with no registration planned |
| Layout/Deck | The canvas is fixed; the derived strategy matches the evidence (`fidelity` needs A/B, `mirror` needs A or structured B, C/D/E permit only `standard`; Layout mirror evidence is brand/application-neutral); structure ownership explicit |
| Mirror | Every source Slide and reachable chain valid and context-complete, with omitted identities and missing facts reported |
| Style | Method, vocabulary, evidence rules, defaults, direction, and review focus confirmed with project-specific context; identity/structure N/A |
| Deck | Application context understood without turning it into policy |
| Layout | No application or identity leaked |
| Brand | All identity fields confirmed; canvas/replication/structure N/A |
---
@@ -135,30 +212,65 @@ Before emitting the marker, all must hold: every Required item shown with proven
> Precondition: `[TEMPLATE_BRIEF_CONFIRMED]` emitted in Step 3.
Resolve `<template_workspace>` from scope (`skills/ppt-master/templates/<kind_dir>/<template_id>` or `<target_project>`), `mkdir -p "$template_workspace/templates"`, and create optional roots only when writing a real asset. Normally `<authoring_workspace>` equals `<template_workspace>`; when the project already has the other structural kind, author in an isolated project-shaped root through validation and preview, then install its spec at `<installed_design_spec_path>` and assets atomically (Layout replaces the Deck roster; Deck beside Layout installs no structural payload), deleting staging only after the final root passes.
**Workspace resolution**: resolve `<template_workspace>` from scope (`skills/ppt-master/templates/<kind_dir>/<template_id>` or `<target_project>`), `mkdir -p "$template_workspace/templates"`, and create optional roots only when writing a real asset. Normally `<authoring_workspace>` equals `<template_workspace>`. When the project already has the other structural kind, author in an isolated project-shaped root through validation and preview, then install its spec at `<installed_design_spec_path>` and assets atomically (Layout replaces the Deck roster; Deck beside Layout installs no structural payload), deleting staging only after the final root passes.
**Preflight (atomic, parent-level, before any final write)**: resolve `<design_spec_path>` and every destination; for `library` confirm `templates/` is empty; for `project` reject a bare `design_spec.md`, an existing spec of the selected kind, or an invalid qualified-name set (distinct kinds coexist; Layout owns structure when present; adding Layout beside Deck replaces the Deck structural payload only after isolated validation); resolve every bitmap and vector filename and confirm nothing overwrites an existing file in `images/` or `icons/imported/`; check the review-PPTX destination when requested or multi-Master. Any failure aborts before writing anything; never overwrite an unrelated name conflict.
**Preflight (atomic, parent-level, before any final write)**: any failure aborts before writing anything; never overwrite an unrelated name conflict.
| Check | Rule |
|---|---|
| Paths | Resolve `<design_spec_path>` and every destination |
| `library` | Confirm `templates/` is empty |
| `project` | Reject a bare `design_spec.md`, an existing spec of the selected kind, or an invalid qualified-name set (distinct kinds coexist; Layout owns structure when present; adding Layout beside Deck replaces the Deck structural payload only after isolated validation) |
| Assets | Resolve every bitmap and vector filename and confirm nothing overwrites an existing file in `images/` or `icons/imported/` |
| Review PPTX | Check its destination when requested or multi-Master |
**Create Brand / Create Style branch**: continue in the child's §3 with the confirmed brief and resolved paths, then return to that child's branch in Step 5 — no Template_Designer, no SVG, no structure.
**Create Layout / Create Deck branch**: switch to Template_Designer with `<template_workspace>` bound to `<authoring_workspace>`, `<design_spec_path>`, the Step 3 brief, and the Step 1 analysis bundle. **Mandatory — authored construction bundle**: as soon as the strategy resolves to `standard` or `fidelity`, and before selecting any contour, read [`native-shape-authoring.md`](../references/native-shape-authoring.md) and [`preset-shape-vocabulary.md`](../references/preset-shape-vocabulary.md) completely; never load them for `mirror`. Pass the applicable package: Type A — the brief, `analysis/manifest.json`, `native_structure.json` and `sources/source.pptx`, `validation/conversion-report.json` when present, exported resources, `*_vector_asset_inventory.json` as an exact-id query surface, `authoring_summary.json` plus the layered IR (manifest bundled for the compiler, never loaded), and for `mirror` the immutable `svg/` plus `inheritance.json`; Type B — the summary, cleaned SVG list, inventory query surface, companion specs, notes; Type C — image list and notes; Type D — direct text, converted outputs, source list, asset inventory, notes; Type E — the brief only; mixed — the union with provenance and conflicts explicit.
**Create Layout / Create Deck branch**: switch to Template_Designer with `<template_workspace>` bound to `<authoring_workspace>`, `<design_spec_path>`, the Step 3 brief, and the Step 1 analysis bundle.
**Mandatory — authored construction bundle**: as soon as the strategy resolves to `standard` or `fidelity`, and before selecting any contour, read [`native-shape-authoring.md`](../references/native-shape-authoring.md) and [`preset-shape-vocabulary.md`](../references/preset-shape-vocabulary.md) completely; never load them for `mirror`.
**Package passed to Template_Designer**:
| Type | Package |
|---|---|
| A | The brief, `analysis/manifest.json`, `native_structure.json` and `sources/source.pptx`, `validation/conversion-report.json` when present, exported resources, `*_vector_asset_inventory.json` as an exact-id query surface, `authoring_summary.json` plus the layered IR (manifest bundled for the compiler, never loaded), and for `mirror` the immutable `svg/` plus `inheritance.json` |
| B | The summary, cleaned SVG list, inventory query surface, companion specs, notes |
| C | Image list and notes |
| D | Direct text, converted outputs, source list, asset inventory, notes |
| E | The brief only |
| Mixed | The union with provenance and conflicts explicit |
| Mode | Final SVG authority | Structure behavior |
|---|---|---|
| `standard` / `fidelity` | Newly authored SVGs from the brief and complete source evidence | Author a compact or broader useful Master/Layout/slot system; never retain identities merely because they exist. Use the compact canonical `<g>` from `preset_shape_svg.py` when one registered preset expresses one object (paint from the brief and spec; add only the registered structural attributes after insertion; geometry or paint changes require a new render); Template_Designer decides any `shape_boolean_svg.py` use under [`native-shape-authoring.md`](../references/native-shape-authoring.md) §6 |
| `mirror` | Reviewed compact authoring SVG plus inline native JSON and structure facts | Publish source Slides and their reachable chains from the current authored tree; complete inherited context without changing ownership; similar presentation required, code isomorphism not. Redraw/normalize visible SVG, equivalent inheritance, safe metadata, and transport without changing meaning; never synthesize, promote/demote, rename, or re-parent |
For Type A `mirror`, publish with `mirror_template_materialize.py "<import_workspace>" "<authoring_workspace>"` into a workspace with no existing roster; it validates and publishes but never authors visible design, writes the sidecars listed in [`svg-pipeline.md`](../scripts/docs/svg-pipeline.md#mirror_template_materializepy), and does not create the Design Spec — Template_Designer writes it from the brief and the materialized roster before Step 5.
For Type A `mirror`, publish with `mirror_template_materialize.py "<import_workspace>" "<authoring_workspace>"` into a workspace with no existing roster. It validates and publishes but never authors visible design, writes the sidecars listed in [`svg-pipeline.md`](../scripts/docs/svg-pipeline.md#mirror_template_materializepy), and does not create the Design Spec — Template_Designer writes it from the brief and the materialized roster before Step 5.
**Hard rule — multi-Master package boundary**: more than one Master is valid only when `mirror` preserves a source graph or an authored template intentionally defines distinct reusable design families — never one Master per Layout or equivalent duplicates. Every Master owns at least one emitted Layout and every Layout is selected by at least one prototype. SVG authors own the semantic roster, parentage, picker names, atoms, and slots; the exporter owns OOXML cloning, Theme isolation (one Theme part per Master — two Masters never resolve to the same `ppt/theme/themeN.xml`), `p14:creationId` uniqueness, numeric registration, and relationship registration — never encode package repair in SVGs. Do not package `native_structure.json` or `source.pptx` as template inputs.
**Hard rule — multi-Master package boundary**: more than one Master is valid only when `mirror` preserves a source graph or an authored template intentionally defines distinct reusable design families — never one Master per Layout or equivalent duplicates. Every Master owns at least one emitted Layout and every Layout is selected by at least one prototype.
| Owner | Owns |
|---|---|
| SVG authors | The semantic roster, parentage, picker names, atoms, and slots |
| Exporter | OOXML cloning, Theme isolation (one Theme part per Master — two Masters never resolve to the same `ppt/theme/themeN.xml`), `p14:creationId` uniqueness, numeric registration, and relationship registration |
Never encode package repair in SVGs. Do not package `native_structure.json` or `source.pptx` as template inputs.
**Sprite-sheet preservation**: PPTX-exported assets are often sprite sheets cropped through nested `<svg viewBox>` wrappers around `<image width="1" height="1">`; that nesting is load-bearing geometry — preserve the exact `viewBox` crop and outer placement, never flatten to one `<image>` with direct geometry. If an asset's pixel aspect differs from its on-page aspect, it is a sprite.
**Mirror authoring/publication** (A or B): author and publish one SVG per source Slide in `<authoring_workspace>/templates/` — inspect every matching `authoring-svg/` document, redraw where useful, refresh the summary, then run the materializer (never hand-copy the lossless tree or rebuild the graph); preserve reachable keys, picker names, parentage, assignment, placeholder type/index/bounds, inherited-shape visibility, ownership, and native facts; unused identities produce no file. Name files `<NNN>_<page_type>.svg` (3-digit source order; type from `pageTypeCandidates` for A, from a convention filename or content for B, else `content`). Route assets through the common contract — Type A media from `<import_workspace>/images/`, Type B relative hrefs resolved and copied once — into `images/` with `../images/<name>` references and semantic directories for audio/video/payloads, keeping stable source asset identity; copy decoration vectors once to `icons/imported/` as `<use data-icon="imported/<name>" data-pptx-asset-role="decoration"/>` (never `templates/icons/`, never inlined by hand). Write `<design_spec_path>` per template-designer §1; `replication_mode: mirror` records creation, never a 1:1 downstream sequence.
**Mirror authoring/publication** (A or B): author and publish one SVG per source Slide in `<authoring_workspace>/templates/` — inspect every matching `authoring-svg/` document, redraw where useful, refresh the summary, then run the materializer (never hand-copy the lossless tree or rebuild the graph); what mirror preserves is [`template-designer.md`](../references/template-designer.md) Mirror mode.
**Expected outputs**: `<design_spec_path>` with package-specific rules only (deck: descriptive Overview, Color Scheme, Signature Elements, factual Page Roster, conditional Typography / Assets / Overrides; layout: structure-owned Signature Elements and Page Roster only) and no restated generic constraints; the roster per template-designer; conventional `{{...}}` placeholder vocabulary with a `placeholders:` frontmatter override when a style legitimately differs (indexed TOC pattern, never one-off families); each SVG carrying the native contract — root identity, direct atomic fixed layers, direct slot `<g>` with design-zone bounds and exactly one compatible carrier (a validated compact preset `<g>` counts as one atom or one `object` carrier; composite regions use only the `object` + `proxy` downgrade; `data-pptx-role` only when specialized metadata cannot express behavior); optional assets under the common routing.
| Mirror detail | Rule |
|---|---|
| Filenames | `<NNN>_<page_type>.svg` (3-digit source order; type from `pageTypeCandidates` for A, from a convention filename or content for B, else `content`) |
| Assets | Route through the common contract — Type A media from `<import_workspace>/images/`, Type B relative hrefs resolved and copied once — into `images/` with `../images/<name>` references and semantic directories for audio/video/payloads, keeping stable source asset identity |
| Decoration vectors | Copy once to `icons/imported/` as `<use data-icon="imported/<name>" data-pptx-asset-role="decoration"/>` (never `templates/icons/`, never inlined by hand) |
| Spec | Write `<design_spec_path>` per template-designer §1; `replication_mode: mirror` records creation, never a 1:1 downstream sequence |
**Hard rule — placeholder examples are executable defaults**: in authored templates a carrier is the prototype Slide placeholder and `data-pptx-bounds` the reusable Layout frame — the complete intended box, never the sample text's glyph bounds; general `body` and text-carried `object` slots begin upper-left, left-aligned, wrapping inside the frame, while center alignment is reserved for short focal content (record a template-wide exception in `§IV`); `template_preview_pptx.py` sizes each review carrier to the same frame and substitutes concise sample text only in ephemeral copies; `mirror` keeps source Slide carrier geometry in the tool-side native record and `data-pptx-bounds` as the Layout default without normalizing one to the other.
**Expected outputs**: `<design_spec_path>` with package-specific rules only (deck: descriptive Overview, Color Scheme, Signature Elements, factual Page Roster, conditional Typography / Assets / Overrides; layout: structure-owned Signature Elements and Page Roster only) and no restated generic constraints; the roster per template-designer; conventional `{{...}}` placeholder vocabulary with a `placeholders:` frontmatter override when a style legitimately differs (indexed TOC pattern, never one-off families); each SVG carrying the native contract of [`pptx-structure-interface.md`](../references/pptx-structure-interface.md) §2; optional assets under the common routing.
**Hard rule — placeholder examples are executable defaults**: in authored templates a carrier is the prototype Slide placeholder and `data-pptx-bounds` the reusable Layout frame — the complete intended box, never the sample text's glyph bounds. General `body` and text-carried `object` slots begin upper-left, left-aligned, wrapping inside the frame; center alignment is reserved for short focal content (record a template-wide exception in `§IV`). `template_preview_pptx.py` sizes each review carrier to the same frame and substitutes concise sample text only in ephemeral copies. `mirror` keeps source Slide carrier geometry in the tool-side native record and `data-pptx-bounds` as the Layout default without normalizing one to the other.
---
@@ -174,7 +286,18 @@ python3 skills/ppt-master/scripts/svg_quality_checker.py "<template_source>" --t
Checker behavior in template mode: [`template-tools.md`](../scripts/docs/template-tools.md#svg_quality_checkerpy---template-mode). It validates the authoring contract; Theme ownership, package IDs, and registrations are verified by Step 6.
**Checklist**: the spec follows the kind skeleton with template-specific norms and no generic restatement; every SVG is a complete prototype with a §V row (mirror adds one scope sentence for omitted identities); variant filenames use letter suffixes and reuse the parent placeholder set unless overridden; TOC uses the indexed form; frontmatter declares the canvas fields (and `source_*` for PPTX/SVG-backed templates) and `native_structure_mode: structured`; `viewBox` equals the declared canvas; model-facing bounds and page coordinates use at most two decimals while crop/path/transform/preset/native frames keep required precision; placeholder names follow the convention or a declared override; every referenced asset exists via `../images/` with no bitmap stranded in `templates/`; no `native_structure.json` or `source.pptx` packaged; every root declares Master/Layout keys and names with direct atomic fixed visuals in paint order; every slot is a direct `<g id>` with design-zone bounds and one compatible carrier or an explicit `object` proxy; authored bounds are complete editable boxes with upper-left body entry; review prompts stay readable without changing source markers; authored output was newly authored without distilling source topology; every extra Master is a distinct family with owned Layouts and prototypes; mirror preserves order, identity, parentage, placeholder facts, ownership, meaning, and presentation with a complete Source Preservation Map, canonical lowercase visibility attributes, complete reachable-chain preflight, and the execution manifest plus text-slot sidecars; no duplicate-Layout warning remains for authored modes; edits used the compact authoring SVG and mirror published through the materializer without lossless rehydration; extracted vectors use the `imported/<name>` decoration reference with no `templates/icons/`; fidelity keeps every sprite crop wrapper; mirror SVG count equals source Slide count with `<NNN>_<page_type>.svg` names, no standalone Master/Layout SVG, and no new `{{...}}` markers.
**Checklist**:
| Area | Condition |
|---|---|
| Spec | Follows the kind skeleton with template-specific norms and no generic restatement; frontmatter declares the canvas fields (and `source_*` for PPTX/SVG-backed templates) and `native_structure_mode: structured` |
| Roster | Every SVG is a complete prototype with a §V row (mirror adds one scope sentence for omitted identities); variant filenames use letter suffixes and reuse the parent placeholder set unless overridden; TOC uses the indexed form |
| Geometry | `viewBox` equals the declared canvas; model-facing bounds and page coordinates use at most two decimals while crop/path/transform/preset/native frames keep required precision; authored bounds are complete editable boxes with upper-left body entry; fidelity keeps every sprite crop wrapper |
| Placeholders | Names follow the convention or a declared override; review prompts stay readable without changing source markers |
| Assets | Every referenced asset exists via `../images/` with no bitmap stranded in `templates/`; extracted vectors use the `imported/<name>` decoration reference with no `templates/icons/`; no `native_structure.json` or `source.pptx` packaged |
| Native contract | Every SVG satisfies [`pptx-structure-interface.md`](../references/pptx-structure-interface.md) §2 |
| Authored modes | Output was newly authored without distilling source topology; every extra Master is a distinct family with owned Layouts and prototypes; no duplicate-Layout warning remains; edits used the compact authoring SVG |
| Mirror | Preserves order, identity, parentage, placeholder facts, ownership, meaning, and presentation with a complete Source Preservation Map, canonical lowercase visibility attributes, complete reachable-chain preflight, and the execution manifest plus text-slot sidecars; published through the materializer without lossless rehydration; SVG count equals source Slide count with `<NNN>_<page_type>.svg` names, no standalone Master/Layout SVG, and no new `{{...}}` markers |
This step is a **hard gate**: no review PPTX, registration, staged install, or handoff until it passes. After a staged project install, rerun the checker on the final `<target_project>/templates/`. A one-Master template may skip Step 6 when no review was requested; a multi-Master template must pass Step 6 before registration or completion.
@@ -190,13 +313,30 @@ python3 skills/ppt-master/scripts/template_preview_pptx.py "<authoring_workspace
python3 skills/ppt-master/scripts/template_preview_pptx.py "<authoring_workspace>" --force # intentional replacement after a fix
```
Copy a requested/required review artifact into the target project's `exports/` during a staged install. **Validation**: the PPTX exists (and was copied after a staged transition); slide count equals the roster; read-back reports the expected Master/Layout counts and exact registrations; every Master targets a distinct Theme part; `p14:creationId` and registration IDs are valid and unique; for authored modes every carrier-bound placeholder matches its Layout placeholder's type, index, and frame (verified automatically); for mirror, source Slide-local geometry is unchanged; the user can review every page in filename order; when PowerPoint is available it opens without repair with every Layout under its Master — otherwise report package read-back as the evidence and claim no PowerPoint-open result. Every item is a hard gate for the artifact; a multi-Master failure blocks registration and completion, while an unrequested one-Master preview failure does not block a workspace that passed Step 5.
Copy a requested/required review artifact into the target project's `exports/` during a staged install.
**Validation** (every item is a hard gate for the artifact):
| Check | Condition |
|---|---|
| File | The PPTX exists (and was copied after a staged transition); slide count equals the roster |
| Package | Read-back reports the expected Master/Layout counts and exact registrations; every Master targets a distinct Theme part; `p14:creationId` and registration IDs are valid and unique |
| Authored modes | Every carrier-bound placeholder matches its Layout placeholder's type, index, and frame (verified automatically) |
| Mirror | Source Slide-local geometry is unchanged |
| Review | The user can review every page in filename order; when PowerPoint is available it opens without repair with every Layout under its Master — otherwise report package read-back as the evidence and claim no PowerPoint-open result |
A multi-Master failure blocks registration and completion; an unrequested one-Master preview failure does not block a workspace that passed Step 5.
---
## Step 7: Register Template in Library Index (Library Scope Only)
`library`: after Step 5 (and Step 6 when requested or required), run `python3 skills/ppt-master/scripts/register_template.py <template_id> --kind brand|style|deck|layout`; it derives the entry from the spec frontmatter (preferred) or prose plus the actual `templates/*.svg` roster and updates that kind's `*_index.json` — the complete discovery source for Default Stage-1 controls and chat listing (neither scans directories). `project`: skip the registrar, edit no index or README, and report `Not registered (project workspace)`. An exact unregistered root supplied by the user or handed off by this route appears as an `explicit` candidate preselected only when it is the sole root; a root matching a registered canonical root may display as `library`; bare names are never resolved. Frontmatter examples per kind live in the child workflows; `--rebuild-all` rebuilds a kind's index after editing many specs.
| Scope | Action |
|---|---|
| `library` | After Step 5 (and Step 6 when requested or required), run `python3 skills/ppt-master/scripts/register_template.py <template_id> --kind brand|style|deck|layout`; it derives the entry from the spec frontmatter (preferred) or prose plus the actual `templates/*.svg` roster and updates that kind's `*_index.json` — the complete discovery source for Default Stage-1 controls and chat listing (neither scans directories) |
| `project` | Skip the registrar, edit no index or README, and report `Not registered (project workspace)` |
An exact unregistered root supplied by the user or handed off by this route appears as an `explicit` candidate preselected only when it is the sole root; a root matching a registered canonical root may display as `library`; bare names are never resolved. Frontmatter examples per kind live in the child workflows; `--rebuild-all` rebuilds a kind's index after editing many specs.
---
@@ -224,7 +364,9 @@ Copy a requested/required review artifact into the target project's `exports/` d
| `exports/<template_id>_template_preview.pptx` | Verified, when requested or required |
```
Brand lists the spec plus real identity assets; Style lists only its spec; both state `SVG roster: N/A` and `Native structure: N/A`, and Style adds `Visual review trigger: N/A (advisory focus only)`. The exact `<template_workspace>/` root is the current-conversation handoff to Generate Step 3: it appears as the specified candidate, defaults Stage 1 to template mode, and is preselected only when it is the sole root; after Stage 1 confirms it, application resolves its spec(s), ignores `exports/`, and authors new `svg_output/` pages — neither the reference nor the prototypes are upgraded in place, and any older flat or legacy package is evidence only.
Brand lists the spec plus real identity assets; Style lists only its spec; both state `SVG roster: N/A` and `Native structure: N/A`, and Style adds `Visual review trigger: N/A (advisory focus only)`.
**Handoff**: the exact `<template_workspace>/` root is the current-conversation handoff to Generate Step 3: it appears as the specified candidate, defaults Stage 1 to template mode, and is preselected only when it is the sole root. After Stage 1 confirms it, application resolves its spec(s), ignores `exports/`, and authors new `svg_output/` pages — neither the reference nor the prototypes are upgraded in place, and any older flat or legacy package is evidence only.
---
@@ -4,7 +4,7 @@ description: Default Generate PPTX authority for source intake, planning, SVG au
# Generate PPTX Route
> Load only after [`routing.md`](./routing.md) selects Default Generate or its Beautify profile. This file owns that runtime's Step 17 sequence, gates, role switching, and mandatory commands; explicit Quick loads [`quick-generate.md`](./profiles/quick-generate.md) instead, and Beautify enters here only when it does not explicitly select Quick.
> Load only after [`routing.md`](./routing.md) selects Default Generate or its Beautify profile. This file owns that runtime's Step 17 sequence, gates, role switching, and mandatory commands. Explicit Quick loads [`quick-generate.md`](./profiles/quick-generate.md) instead; Beautify enters here only when it does not explicitly select Quick.
**Hard rule — runtime paths**: expand every linked or abbreviated package path from the entry-time `SKILL_DIR` anchor inside each tool call; never change CWD or inherit a prior shell working directory.
@@ -12,8 +12,7 @@ description: Default Generate PPTX authority for source intake, planning, SVG au
**Generate-specific execution discipline**:
- The current main agent hand-writes every SVG page; never delegate page generation or run a generator over `svg_output/`. `preset_shape_svg.py` and `shape_boolean_svg.py` provide only their stdout fragments after the agent chooses role, operands, paint, and z-order.
- SVG cadence: P01P05 → early gate (a planned roster of six or fewer pages skips it) → remaining pages → final gate. No batches, no other mid-run checker calls; every checker invocation follows a gate point whose covered pages all exist or the end of one consolidated repair pass.
- Page authoring stays with the current main agent ([`executor-base.md`](../references/executor-base.md) §3); the checker cadence is Step 6's.
- Gate checklists are internal: on success continue with at most one compact status line; on failure report only the blocking items and required recovery.
**SVG page-design boundary**: `svg_output/` is the complete page-design source — every visible element of the exported slide is in the page SVG or referenced by it; templates, `design_spec.md`, and `spec_lock.md` never supply content at export ([`shared-standards-core.md`](../references/shared-standards-core.md) §4.0). Export compiles only the selected route's explicit structure contract (`flat` Slide-local; `structured` Master/Layout/Slide parts) and never infers structure. `svg_final/` is an optional preview release export never reads. Notes, animations, narration, and Edit Native PPTX stay outside this closure.
@@ -41,11 +40,11 @@ description: Default Generate PPTX authority for source intake, planning, SVG au
| Markdown | Read directly |
| Topic only | Run [`topic-research`](stages/topic-research.md) first and use its research pair as source; Step 2 imports the pair without expanding the facts JSON's URLs |
The dispatcher writes standard Markdown plus a conversion profile beside each source; use `-t <type>` only when detection is ambiguous and `-o` only when a specific output location is required (an output directory for multiple or directory inputs). PPTX sources also receive standard intake in `<project>/analysis/` after Step 2. Backend details: [`conversion.md`](../scripts/docs/conversion.md), whose § Image Orientation Review applies when the user requests correction, converted text asks for rotated viewing, or a downloaded asset is visibly sideways (never launch its legacy HTML tool).
The dispatcher writes standard Markdown plus a conversion profile beside each source. Use `-t <type>` only when detection is ambiguous and `-o` only when a specific output location is required (an output directory for multiple or directory inputs). PPTX sources also receive standard intake in `<project>/analysis/` after Step 2. Backend details: [`conversion.md`](../scripts/docs/conversion.md); its § Image Orientation Review applies when the user requests correction, converted text asks for rotated viewing, or a downloaded asset is visibly sideways (never launch its legacy HTML tool).
**Sufficiency test**: after reading direct and converted content, run [`topic-research`](stages/topic-research.md) only for gaps where the requested outcome would otherwise require inventing, omitting, or leaving unsupported an externally verifiable claim; a closed corpus stays within the supplied material, and file presence or length is irrelevant. Research records facts and adopted URLs in its pair; Step 2 fetches no adopted page, and Step 5 acquires only Strategist-selected assets after final confirmation.
**Sufficiency test**: after reading direct and converted content, run [`topic-research`](stages/topic-research.md) only for gaps where the requested outcome would otherwise require inventing, omitting, or leaving unsupported an externally verifiable claim. A closed corpus stays within the supplied material; file presence or length is irrelevant. Research records facts and adopted URLs in its pair; Step 2 fetches no adopted page, and Step 5 acquires only Strategist-selected assets after final confirmation.
**EMF/WMF from DOCX/PPTX**: embedded Office vectors land in `images/` with `image_manifest.json` as first-class §VIII assets. Never convert them to PNG`finalize_svg.py` preserves them as external references and `svg_to_pptx.py` embeds them as native `image/x-emf` / `image/x-wmf` media at full vector fidelity; browser preview shows them blank, which is expected.
**EMF/WMF from DOCX/PPTX**: embedded Office vectors land in `images/` with `image_manifest.json` as first-class §VIII assets. Never convert them to PNG; export embeds them at full vector fidelity, and a blank browser preview is expected ([`project.md`](../scripts/docs/project.md); export behavior in [`svg-pipeline.md`](../scripts/docs/svg-pipeline.md)).
**✅ Checkpoint** — source content and any research pair are ready; proceed to Step 2.
@@ -60,11 +59,11 @@ python3 ${SKILL_DIR}/scripts/project_manager.py init <project_name>
python3 ${SKILL_DIR}/scripts/project_manager.py import-sources <project_path> <source_files_or_dirs...> # skip when content is only in conversation
```
**Hard rule — truthful canvas token**: append `--format <registered_format>` only when an explicit user/source fact already establishes an exact registered canvas ([`canvas-formats.md`](../references/canvas-formats.md)); otherwise Stage 1 confirms the canvas, starting from the project-initialization canvas unless the user/source context changes it, and `spec_lock.md` records its viewBox.
**Hard rule — truthful canvas token**: append `--format <registered_format>` only when an explicit user/source fact already establishes an exact registered canvas ([`canvas-formats.md`](../references/canvas-formats.md)). Otherwise Stage 1 confirms the canvas, starting from the project-initialization canvas unless the user/source context changes it, and `spec_lock.md` records its viewBox.
Initialization creates `<project_path>/validation/workflow.log`; later project-scoped Python tools record their command envelopes there automatically (prefix `PPT_MASTER_PROJECT_PATH="<project_path>"` when a helper's arguments do not identify the project; append one concise note with `python3 ${SKILL_DIR}/scripts/workflow_log.py <project_path> "<detail>"` only for a material handoff, rework reason, approved exception, or manual recovery with no owning command output). The log is cold audit evidence, never read during generation.
**Workflow log**: initialization creates `<project_path>/validation/workflow.log`; later project-scoped Python tools record their command envelopes there automatically (prefix `PPT_MASTER_PROJECT_PATH="<project_path>"` when a helper's arguments do not identify the project). Append one concise note with `python3 ${SKILL_DIR}/scripts/workflow_log.py <project_path> "<detail>"` only for a material handoff, rework reason, approved exception, or manual recovery with no owning command output. The log is cold audit evidence, never read during generation.
**Import rules**: pass the source path once when Step 1 wrote Markdown beside it, both locations when `-o` wrote it elsewhere, and only the research pair when Topic Research ran (its facts JSON is imported as a file; no URL is fetched). Inputs already under `projects/` move; every other path is copied and left untouched even with `--move` (`--copy` keeps a projects-local input in place). Direct bitmap inputs are archived under `sources/` and copied collision-safely into `images/`; SVG/EMF/WMF stay source assets unless a converter manifest supplies display metadata. For each PPTX, `import-sources` runs `pptx_intake.py <source.pptx> -o <project_path>/analysis` and writes `analysis/<stem>.identity.json`, `<stem>.slide_library.json`, and the multi-deck index `analysis/source_profile.json` (one `decks[]` entry per distinct stem; re-importing a stem replaces its entry) — source facts and recommendation candidates, not replica constraints; Beautify stays single-deck.
**Import rules**: pass the source path once when Step 1 wrote Markdown beside it, both locations when `-o` wrote it elsewhere, and only the research pair when Topic Research ran (its facts JSON is imported as a file; no URL is fetched). Copy/move semantics, bitmap archiving, and the PPTX intake bundle it writes under `analysis/` (`<stem>.identity.json`, `<stem>.slide_library.json`, `source_profile.json`) are [`project.md`](../scripts/docs/project.md). Those artifacts are source facts and recommendation candidates, not replica constraints; Beautify stays single-deck.
**✅ Checkpoint** — project created, `sources/` complete, converted materials ready. `import-sources` exits 0 when any input converts: read the printed `skipped` reasons and treat those inputs as absent. Proceed to Step 3.
@@ -74,9 +73,16 @@ Initialization creates `<project_path>/validation/workflow.log`; later project-s
Internal preparation for every Default run — no page, question, receipt, selection, template read, or installation. Quick skips this Step.
Registered candidates come only from `templates/{brands,styles,layouts,decks}/*_index.json`, each root derived as `templates/<kind_dir>/<id>/`; never scan kind directories or resolve a bare name, brand mention, or style phrase to a path. Preserve every exact root supplied for this run (a registered-root match stays `library`; any other root is `explicit`; provenance never changes precedence). Raw PPTX is source material, not a candidate — raw PPTX plus new content is [`edit-native-pptx`](./edit-native-pptx.md), and a reusable workspace comes from [`create-template`](./create-template.md).
Candidates follow [`routing.md`](./routing.md) §7: registered roots from the four indexes plus every exact root supplied for this run. Raw PPTX is source material, not a candidate — raw PPTX plus new content is [`edit-native-pptx`](./edit-native-pptx.md), and a reusable workspace comes from [`create-template`](./create-template.md).
Resolve the surface under [`confirm-surface.md`](../references/confirm-surface.md). UI branch: run `--reset-template-selection`, then write `<project_path>/confirm_ui/template_options.json` with `schema_version: 1`, `phase: "template"`, the UI `lang`, all supplied roots as absolute `explicit_workspace_roots` (empty array when none), and `default_mode``templates` for explicit template intent or any supplied root, otherwise `free_design`. Do not launch yet; the server reads the indexes itself. Chat/delegated branch: retain the same candidate boundary in context and create no UI artifact. Stage 1 initializes from `default_mode` but the user may switch; template mode requires at least one selection; exactly one supplied root may be preselected, several remain unselected.
Resolve the surface under [`confirm-surface.md`](../references/confirm-surface.md).
| Branch | Preparation |
|---|---|
| UI | Run `--reset-template-selection`, then write `<project_path>/confirm_ui/template_options.json` with `schema_version: 1`, `phase: "template"`, the UI `lang`, all supplied roots as absolute `explicit_workspace_roots` (empty array when none), and `default_mode``templates` for explicit template intent or any supplied root, otherwise `free_design`. Do not launch yet; the server reads the indexes itself. |
| Chat / delegated | Retain the same candidate boundary in context and create no UI artifact. |
Stage 1 initializes from `default_mode` but the user may switch. Template mode requires at least one selection; exactly one supplied root may be preselected, several remain unselected.
**✅ Checkpoint** — candidates ready; nothing selected, read, validated, or installed. Proceed to Step 4 without a user-visible stop.
@@ -92,6 +98,7 @@ Load the planning core in one batch, plus the structured facts already in `<proj
```
Read ${SKILL_DIR}/references/strategist.md
Read ${SKILL_DIR}/references/plan-core.md
Read ${SKILL_DIR}/references/canvas-formats.md
```
@@ -112,11 +119,15 @@ Read ${SKILL_DIR}/templates/charts/chart-vocabulary.md
Read ${SKILL_DIR}/templates/tables/table-vocabulary.md
```
This is a capability map, not a usage checklist. Author the three whole-solution intents first, freeze every mode/style/rendering id from the indexes, then read once only the deduplicated union of those detail files; a novel custom reads none. Confirmed non-`none` image sources continue into resource planning under `strategist-image.md` (the image-layout files are Executor's); confirmed `none` writes no image rows but keeps the rendering candidates.
This is a capability map, not a usage checklist; direction construction follows [`strategist.md`](../references/strategist.md) §d. Confirmed non-`none` image sources continue into resource planning under `strategist-image.md` (the image-layout files are Executor's); confirmed `none` writes no image rows but keeps the rendering candidates.
**Fact channels** ([`artifact-ownership.md`](../references/artifact-ownership.md) §12): before Stage 1 read `analysis/source_profile.json`'s `decks[]` digests, opening a deck's identity/slide-library files only when raw facts are needed. Content — text, tables, chart values, SmartArt wording — comes from the content-type files in `sources/` (`<stem>.md` and archived `.txt` / `.csv` / `.json` / `.yaml`), never from the digest; `*.conversion_profile.json` and `*_files/image_manifest.json` are sidecars. A source deck's identity is reference, not constraint. If the user provided images, run `python3 ${SKILL_DIR}/scripts/analyze_images.py <project_path>/images` before the Design Spec and read `analysis/image_analysis.csv` before §VIII; the CSV is a regenerated view of `images/` — rerun after any change, never treat it as a store. Never bulk-open images: Strategist inspects one specifically ambiguous asset under [`strategist-image.md`](../references/strategist-image.md) and records the result in §VIII; Executor inspects one `Existing` / `Sourced` asset only for crop, focal placement, or text contrast.
**Fact channels** ([`artifact-ownership.md`](../references/artifact-ownership.md) §12): before Stage 1 read `analysis/source_profile.json`'s `decks[]` digests, opening a deck's identity/slide-library files only when raw facts are needed. Content — text, tables, chart values, SmartArt wording — comes from the content-type files in `sources/` (`<stem>.md` and archived `.txt` / `.csv` / `.json` / `.yaml`), never from the digest; `*.conversion_profile.json` and `*_files/image_manifest.json` are sidecars. A source deck's identity is reference, not constraint.
**BLOCKING — two-stage confirmation**: the always-on user gate unless explicitly delegated. Stage 1 confirms the communication contract and exactly one template mode (`free_design` or `templates`, the latter expanding the four registered-kind selectors plus supplied roots and requiring at least one selection). Final Stage 2 confirms the complete deck solution plus production mechanics only after the Stage-1 choice is installed or free design is closed; `refine_spec: true` adds one chat gate after Design Spec Gate 1. Author each stage once; submitted values — including blanks and unusual overrides — are authoritative. Only the user confirms: the agent authors recommendations, operates the server, reads state, and applies a template, but never confirms on the user's behalf, automates submission, synthesizes a payload, or writes user result state; silence confirms nothing. Under explicit delegation the agent makes the Stage-1 decision, installs it, derives Stage 2, and presents one complete summary without fabricating UI receipts.
**User images**: if the user provided images, run `python3 ${SKILL_DIR}/scripts/analyze_images.py <project_path>/images` before the Design Spec and read `analysis/image_analysis.csv` before §VIII. The CSV is a regenerated view of `images/`: rerun after any change, never treat it as a store. Never bulk-open images: Strategist inspects one specifically ambiguous asset under [`strategist-image.md`](../references/strategist-image.md) and records the result in §VIII; Executor inspects one `Existing` / `Sourced` asset only for crop, focal placement, or text contrast.
**BLOCKING — two-stage confirmation**: the always-on user gate unless explicitly delegated. Stage 1 confirms the communication contract and exactly one template mode (`free_design` or `templates`, the latter expanding the four registered-kind selectors plus supplied roots and requiring at least one selection). Final Stage 2 confirms the complete deck solution plus production mechanics only after the Stage-1 choice is installed or free design is closed; `refine_spec: true` adds one chat gate after Design Spec Gate 1. Author each stage once; submitted values — including blanks and unusual overrides — are authoritative.
**Only the user confirms**: the agent authors recommendations, operates the server, reads state, and applies a template. It never confirms on the user's behalf, automates submission, synthesizes a payload, or writes user result state; silence confirms nothing. Under explicit delegation the agent makes the Stage-1 decision, installs it, derives Stage 2, and presents one complete summary without fabricating UI receipts.
**UI branch** — `template_options.json` (Step 3), `recommendations.stage1.json`, `template_handoff.json` (written only by `--complete-template-selection`), and `recommendations.stage2.json` are agent inputs; `template_selection.json` and `result.json` are user receipts. Only the active unconfirmed stage file may be overwritten, in place, never with a revision suffix or another stage's payload. Author Stage 1 without reading candidates, launch, post the [`confirm-surface.md`](../references/confirm-surface.md) handoff summary, then wait:
@@ -153,9 +164,16 @@ If the user selects chat after launch, apply `confirm-surface.md`'s in-run switc
4. Read `${SKILL_DIR}/templates/spec_lock_reference.md`; author `spec_lock.md` once from the approved Design Spec and context — identity and refinements, every recurring typography role, routing anchors, each placed image's source/layout suggestion/crop policy; no page-local garnish, no image palette; `strategist-template.md` §3 when active.
5. Compare lock anchors to the Design Spec and run `python3 ${SKILL_DIR}/scripts/project_manager.py validate <project_path>`. Schema validity never proves fidelity: a final-state → Design Spec mismatch, an approved Design Spec → lock mismatch, or an unapplied revision blocks. Repair from the retained confirmation (or the approved revision); resume and refine edit existing files, never scaffolds; only fresh recovery may reread persisted final evidence once. Unhonorable requirements follow [`failure-recovery.md`](governance/failure-recovery.md).
**Confirmation notes**, appended after the stage details in the user's language, each one 💡 line: the split-mode note only when the confirmed mode is `split` or the run is heavy (long page count, bulky sources, substantial research retained in this chat — an isolated `topic-research` worker's fetches do not count) — recommend or confirm stopping after Step 5 and entering the execution session with `继续生成 projects/<project_name>` ([`resume-execute`](stages/resume-execute.md)); no response or "continue" means `continuous`, and the default path prints no reminder. The spec-refinement note always: offer review of the complete Design Spec before the lock (default OFF; only explicit opt-in or `refine_spec: true` runs `refine-spec`).
**Confirmation notes**, appended after the stage details in the user's language, each one 💡 line:
**Production fields**: resolve Speaker Notes, Custom Animations, and Narration Audio as latest explicit user instruction → final Stage-2 proactive value → default `true` / `false` / `false`; enabled Narration Audio raises a non-explicitly-disabled Speaker Notes outcome and names that dependency. Persist the effective outcomes with provenance as the three rows in `design_spec.md §I`, keep the raw proactive fields as evidence only, and project neither into `spec_lock.md`. A later explicit request updates only its §I outcome and resumes the owning step without reopening Confirm UI; disabling notes while audio stays enabled asks one question (disable audio too, or keep its required notes) before writing either row. Formulas and hyperlinks are §IX content, not confirmation fields or resources: Strategist records the delimiter-free LaTeX body or the exact URI / 1-based slide target, and Executor chooses the realization (text, inline, or block math; inline or whole-object link carrier) under [`native-formula.md`](../references/native-formula.md) / [`native-hyperlinks.md`](../references/native-hyperlinks.md); no manifest or lock entry exists for either.
| Note | When | Content |
|---|---|---|
| Split-mode note | Only when the confirmed mode is `split` or the run is heavy (long page count, bulky sources, substantial research retained in this chat — an isolated `topic-research` worker's fetches do not count) | Recommend or confirm stopping after Step 5 and entering the execution session with `继续生成 projects/<project_name>` ([`resume-execute`](stages/resume-execute.md)); no response or "continue" means `continuous`, and the default path prints no reminder |
| Spec-refinement note | Always | Offer review of the complete Design Spec before the lock (default OFF; only explicit opt-in or `refine_spec: true` runs `refine-spec`) |
**Production fields**: resolve Speaker Notes, Custom Animations, and Narration Audio as latest explicit user instruction → final Stage-2 proactive value → default `true` / `false` / `false`. Enabled Narration Audio raises a non-explicitly-disabled Speaker Notes outcome and names that dependency. Persist the effective outcomes with provenance as the three rows in `design_spec.md §I`, keep the raw proactive fields as evidence only, and project neither into `spec_lock.md`. A later explicit request updates only its §I outcome and resumes the owning step without reopening Confirm UI. Disabling notes while audio stays enabled asks one question (disable audio too, or keep its required notes) before writing either row.
**Formulas and hyperlinks** are §IX content, not confirmation fields or resources: Strategist records the delimiter-free LaTeX body or the exact URI / 1-based slide target, and Executor chooses the realization (text, inline, or block math; inline or whole-object link carrier) under [`native-formula.md`](../references/native-formula.md) / [`native-hyperlinks.md`](../references/native-hyperlinks.md). No manifest or lock entry exists for either.
**Prepared final narration**: when an explicit final/literal script will become notes or audio, follow `video-design.md` §1 and §3 — segment it by scene in Stage 2, give each segment a supporting visible state in §IX, record source and verbatim policy in §X, and after Gate 2 (before Step 5 or the split handoff) write the exact segments once to `notes/total.md`, split only in Step 7.1.
@@ -177,7 +195,7 @@ Read ${SKILL_DIR}/references/image-base.md # always
| Row | Additional reference | Run |
|---|---|---|
| Prepared derivative | `image-generator.md` §4.4 only for registered layers | after its canonical source is terminal: `python3 ${SKILL_DIR}/scripts/image_treat.py ...` for blur, desaturation/grayscale, duotone, brightness, or contrast, or the §4.4 preparation path |
| Prepared derivative | `image-generator.md` §4.4 only for registered layers | after its canonical source is terminal: `python3 ${SKILL_DIR}/scripts/image_treat.py ...` for blur, desaturation/grayscale, duotone, brightness, contrast, or `--fit WxH` downscaling to the planned size, or the §4.4 preparation path |
| `ai` | `image-generator.md` | write `images/image_prompts.json`, render `image_prompts.md` with `image_gen.py --render-md`, then follow §7 Path Selection — `image_gen.py --manifest` is Path A only, `host-native` is Path B and skips `--manifest`, `manual` writes prompts and stops; the recorded `design_spec.md §I` path wins over `IMAGE_BACKEND` |
| `web` | `image-searcher.md` | `python3 ${SKILL_DIR}/scripts/image_search.py ...`; with ≥2 rows write `images/image_queries.json` and run `--batch` once |
| `slice` | `image-generator.md` §4.3 | after the parent sheet is `Generated`: `python3 ${SKILL_DIR}/scripts/slice_images.py <project_path>/images/<sheet>.png --grid RxC --names ... --trim --alpha --bg KEY_HEX_FROM_PROMPT --strict-alpha` |
@@ -185,18 +203,11 @@ Read ${SKILL_DIR}/references/image-base.md # always
Load only the references the rows need; a mixed deck writes both `image_prompts.json` and `image_sources.json`. The positional `image_gen.py "prompt"` form is for out-of-pipeline fixups and the §4.4 reconstruction derivation only.
**Web selection**: when any vision-capable context exists, add `--save-candidates` with explicit `query_variants` and run [`web-image-review`](stages/web-image-review.md); only a stage-selected candidate is promoted with `--promote`, a row advances to `next_candidate_page` before its query changes, and only an exhausted pool returns it to `Pending` with new variants. Without vision, omit `--save-candidates`: best-only mode downloads a strict metadata-verified candidate (`selection_method: metadata-ranked`) or stops at `Needs-Manual`. Only after normal search is exhausted may a vision-capable owner fetch one [`topic-research`](stages/topic-research.md) `source_url` as a reviewed source package. §VIII `Reference` stays the locked intent; the provider query is authored separately.
**Web selection**: when any vision-capable context exists, add `--save-candidates` with explicit `query_variants` and run [`web-image-review`](stages/web-image-review.md). Only a stage-selected candidate is promoted with `--promote`; a row advances to `next_candidate_page` before its query changes, and only an exhausted pool returns it to `Pending` with new variants. Without vision, omit `--save-candidates`: best-only mode downloads a strict metadata-verified candidate (`selection_method: metadata-ranked`) or stops at `Needs-Manual`. Only after normal search is exhausted may a vision-capable owner fetch one [`topic-research`](stages/topic-research.md) `source_url` as a reviewed source package. §VIII `Reference` stays the locked intent; the provider query is authored separately.
🚧 **Exhausted-automation GATE**: `auto` tries Path A then Path B and never silently enters Offline Manual. When both are exhausted, or a confirmed `api` / `host-native` path stays unavailable after retry, ask whether to repair and retry the same path, generate the listed files manually, or cancel the affected AI images and repair the plan; only confirmed `manual` creates `Needs-Manual` rows. Web failures follow [`image-base.md`](../references/image-base.md) §3 without halting: try materially different query/provider/license strategies, then mark `Needs-Manual`, report, and continue.
**Workflow**:
1. Extract §VIII rows; separate derivative rows first (reject source/output equality, a derivative parent, chains, cycles, self-reference), then group canonical rows by `Acquire Via`. Every Pending/Failed row reaches a terminal state before Executor starts.
2. Generate prompts and/or run search per [`image-base.md`](../references/image-base.md) §1.
3. Slice each generated sheet with its grid, `--names`, and the exact key HEX from its prompt; a `slice` row is `Generated` only after exit 0, a strict keying failure writes no replacement outputs and returns the sheet to preparation, and a `Needs-Manual` sheet leaves its slices `Needs-Manual` for the Step 7 gate.
4. Materialize derivatives from their terminal source under the declared treatment only (`image_treat.py` for per-pixel treatments; §4.4 for registered clean-base/layer work — supplied assets are `user / Existing`, generated ones `ai / Generated`). A standalone cutout is prepared RGBA, a flat-key slice, or host-supplied. Never bake crop/clip, rotation/mirror, opacity, frame, shadow, scrim/wash, vignette, or overlap into a bitmap, never present `image_treat.py` as background removal, and copy a web source's license record to its derivative.
5. Verify every row's terminal status under [`svg-image-embedding.md`](../references/svg-image-embedding.md) — no `Pending`, `Failed`, or `Needs-Selection`; `auto` follows its fallback chain, confirmed `api` / `host-native` retries only that path, and an unresolved Default AI row waits at the gate above.
6. `python3 ${SKILL_DIR}/scripts/analyze_images.py <project_path>/images` so the CSV reflects every placeable image.
**Workflow**: run the procedure in [`image-base.md`](../references/image-base.md) §2 — separate derivative rows, group canonical rows by `Acquire Via`, finish each path, slice each generated sheet with its grid, `--names`, and the exact key HEX from its prompt, materialize derivatives only from terminal sources under their declared treatment. Then verify every row is terminal (no `Pending`, `Failed`, or `Needs-Selection`; an unresolved Default AI row waits at the gate above) and run `python3 ${SKILL_DIR}/scripts/analyze_images.py <project_path>/images` so the CSV reflects every placeable image. Every Pending/Failed row reaches a terminal state before Executor starts.
**✅ Internal checkpoint** — sidecars, slice outputs, terminal statuses, refreshed CSV. Do not print. Auto-proceed to Step 6; only `generation_mode: split` prints the handoff and stops this conversation:
@@ -220,18 +231,27 @@ Read ${SKILL_DIR}/references/semantic-svg.md # REQUIRED core: sema
Read ${SKILL_DIR}/references/preset-shape-vocabulary.md # REQUIRED core: complete 187-name preset vocabulary
Read ${SKILL_DIR}/references/modes/<resolved-id>.md # one preset id, or each `mode_references` id
Read ${SKILL_DIR}/references/visual-styles/<resolved-id>.md # one preset id, or each `visual_style_references` id
# Triggered modules — evaluate every trigger over the §IX roster before P01 and read the triggered ones now, in this batch;
# a page reaching a capability the sweep did not foresee reads its module then (executor-base routing table):
# executor-structure.md + topology-assembly.md first `Structure = yes` page
# native-shape-authoring.md first contour beyond rect / roundRect / circle / ellipse / line, or a Boolean / freeform
# svg-effects.md first visual job beyond the everyday block
# Triggered modules — evaluate executor-base.md's routing table over the §IX roster before P01
# and read every triggered module in this same batch.
```
Read the core as one batch with the exact detail files named by the retained `spec_lock.md`, then every module the roster sweep triggers, in the same batch (each page's module line records what it uses; a capability the sweep did not foresee loads at that page); never reopen the planning indexes, infer adjacent bases, glob a catalog, or blend unselected identities (an unreferenced custom follows its behavior alone). Conditional modules load on [`executor-base.md`](../references/executor-base.md)'s routing table, never by analogy; `video-design.md` is read before the first SVG when §I records recorded/self-running/video delivery or §X a literal script. `executor-structured.md` owns template specs and prototypes; `executor-visualization.md` resolves a selected reference to one SVG plus its family branch. Read each reference once per valid context.
Read the core as one batch with the exact detail files named by the retained `spec_lock.md`, then every module the roster sweep triggers. Never reopen the planning indexes, infer adjacent bases, glob a catalog, or blend unselected identities (an unreferenced custom follows its behavior alone). Conditional modules load on [`executor-base.md`](../references/executor-base.md)'s routing table, never by analogy; `video-design.md` is read before the first SVG when §I records recorded/self-running/video delivery or §X a literal script. Read each reference once per valid context.
**Context validity**: reuse the retained Design Spec and lock for every page while the context is unchanged and uncompacted; do not reread or poll them. A fresh, resumed, restarted, compacted, or externally changed context rereads `design_spec.md`, then `spec_lock.md`, once, plus triggered references and the latest completed SVG when mid-deck ([`failure-recovery.md`](governance/failure-recovery.md)); on local uncertainty consult the retained lock, then only the owning Design Spec fragment — sources supply facts only, and the Design Spec wins a conflict. A bounded same-context repair that preserves roster/order/identity/communication needs only the affected fragment readback plus `project_manager.py validate`. **Five-page lock re-read**: after P05, P10, P15, … when another page follows, read `spec_lock.md` in full once before the next page — a pure re-anchor of palette, typography, icon style, and `page_rhythm` under long context, with no checker run, no output, no pause, and no repair loop; an external change found here follows the recovery branch. **Hard rule — exact page roster**: `design_spec.md §IX` is the ordered queue — one final slide per entry, same id and order; never add, drop, merge, split, or reorder while drawing. A continuous run may first repair the affected §IX blocks and `page_rhythm` rows and rerun `validate` while the count stays inside the Stage-1 confirmed range; leaving that range reconfirms Stage 1. §IX is preferred wording and semantic authority, adapted only under `executor-base.md` §2.1's content-vs-expression contract, with sources read only for verification. **Missing `spec_lock.md` or `design_spec.md`** → stop and report the missing gate artifact; recover through [`failure-recovery.md`](governance/failure-recovery.md) §3; a missing field in an existing lock → its §2. When §X records a literal script, read the frozen `notes/total.md` once before P01 and design each visible state around its segment. Trust the latest `analysis/image_analysis.csv` (rerun `analyze_images.py` if `images/` changed; an empty folder means no inventory). `page-context` is a diagnostic only ([`artifact-ownership.md`](../references/artifact-ownership.md) §1).
**Context validity**: reuse the retained Design Spec and lock for every page while the context is unchanged and uncompacted; do not reread or poll them. On local uncertainty consult the retained lock, then only the owning Design Spec fragment — sources supply facts only, and the Design Spec wins a conflict.
**Design Parameter Confirmation (Mandatory)**: before the first SVG, output one confirmation listing the compact communication objective, canvas dimensions, body font size, color scheme (primary/secondary/accent HEX), font plan, the per-role calibration table from `python3 ${SKILL_DIR}/scripts/text_measure.py calibrate <project_path> --outline` (every lock role: family, size, CJK and Latin ≈ chars per 100 px, and the longest planned §IX line per role in px — the checker's own estimator with wrapping headroom, written to `validation/text_calibration.json`), and the live-preview URL from the launcher below. If the preview failed to launch, say so here rather than proceeding silently.
| Situation | Read |
|---|---|
| Fresh, resumed, restarted, compacted, or externally changed context | `design_spec.md`, then `spec_lock.md`, once, plus triggered references and the latest completed SVG when mid-deck ([`failure-recovery.md`](governance/failure-recovery.md)) |
| Bounded same-context repair that preserves roster/order/identity/communication | Only the affected fragment readback plus `project_manager.py validate` |
| **Five-page lock re-read** — after P05, P10, P15, … when another page follows | `spec_lock.md` in full once before the next page: a pure re-anchor of palette, typography, icon style, and `page_rhythm` under long context, with no checker run, no output, no pause, and no repair loop; an external change found here follows the recovery branch |
| §X records a literal script | The frozen `notes/total.md` once before P01; design each visible state around its segment |
| Missing `spec_lock.md` or `design_spec.md` | Stop and report the missing gate artifact; recover through [`failure-recovery.md`](governance/failure-recovery.md) §3; a missing field in an existing lock → its §2 |
**Hard rule — exact page roster**: `design_spec.md §IX` is the ordered queue — one final slide per entry, same id and order; never add, drop, merge, split, or reorder while drawing. A continuous run may first repair the affected §IX blocks and `page_rhythm` rows and rerun `validate` while the count stays inside the Stage-1 confirmed range; leaving that range reconfirms Stage 1. §IX is preferred wording and semantic authority, adapted only under `executor-base.md` §2.1's content-vs-expression contract, with sources read only for verification.
**Image inventory**: trust the latest `analysis/image_analysis.csv` (rerun `analyze_images.py` if `images/` changed; an empty folder means no inventory). `page-context` is a diagnostic only ([`artifact-ownership.md`](../references/artifact-ownership.md) §1).
**Design Parameter Confirmation (Mandatory)**: before the first SVG, output one confirmation listing the compact communication objective, canvas dimensions, body font size, color scheme (primary/secondary/accent HEX), font plan, the per-role calibration table, and the live-preview URL from the launcher below. The calibration table comes from `python3 ${SKILL_DIR}/scripts/text_measure.py calibrate <project_path> --outline`: every lock role with family, size, CJK and Latin ≈ chars per 100 px, and the longest planned §IX line per role in px — the checker's own estimator with wrapping headroom, written to `validation/text_calibration.json`. If the preview failed to launch, say so here rather than proceeding silently.
**Live Preview Auto-Startup (Mandatory)**: before the first SVG, start the editor and keep it running through Step 7:
@@ -241,11 +261,16 @@ python3 ${SKILL_DIR}/scripts/svg_editor/server.py <project_path> --live --daemon
Default first free port from `6060` (`--port N` binds strictly); read the URL from output or `<project_path>/live_preview/lock.json` and report it — or the launch failure — before the first SVG. It is a side process: never wait for it or for user confirmation, and keep it running until the user clicks **Exit preview** or asks in chat. Do not read or apply submitted annotations during generation; that window opens after Step 7 ([`live-preview.md`](stages/live-preview.md), which also describes staged direct edits).
> ⚠️ **Main-agent only**: SVG generation stays in the current main agent — page design depends on full upstream context. Cadence: P01P05 → early gate (a planned roster of six or fewer pages skips it) → remaining pages → final gate, in one context, no batches or other mid-run checker calls; reload under Context validity above after context invalidation.
**Cadence (Mandatory)**: P01P05 → early gate (a planned roster of six or fewer pages skips it) → remaining pages → final gate, in one context. Every checker invocation follows one of two events: a gate point whose covered pages all exist, or the end of one consolidated repair pass. A run with neither predecessor is a pacing violation; validating an authoring pattern early is not a reason, because the same issues surface at the gate and are fixed in the same pass. Reload under Context validity above after context invalidation.
**Visual Construction Phase**: generate pages sequentially into `<project_path>/svg_output/`. Each SVG carries the slide's complete visible design (a JSON-first Chart/Table is the sole exception: inline JSON authoritative, visible subtree an approximate preview). Native shapes follow [`native-shape-authoring.md`](../references/native-shape-authoring.md), loaded at the first contour beyond basic primitives while the preset vocabulary is read before page one: independent atoms first, Merge Shapes only when contour semantics require it, freeform last. `mirror|layout` pages start from the complete `page_layouts` SVG and preserve inherited visuals, root identity, atoms, and slots (strict keeps the contract; `layout` may reflow carrier text inside unchanged slot bounds; adaptive uses a Strategist-declared Layout; a required atom or slot change returns upstream, and Executor never edits `spec_lock.md`); `style`, free-design, and brand-only pages are flat per `executor-base.md` and [`semantic-svg.md`](../references/semantic-svg.md).
**Visual Construction Phase**: generate pages sequentially into `<project_path>/svg_output/`. Each SVG carries the slide's complete visible design (a JSON-first Chart/Table is the sole exception: inline JSON authoritative, visible subtree an approximate preview). Native shapes follow [`native-shape-authoring.md`](../references/native-shape-authoring.md), loaded at the first contour beyond basic primitives while the preset vocabulary is read before page one: independent atoms first, Merge Shapes only when contour semantics require it, freeform last.
**Motion-ready image composition**: only when an explicit user motion instruction, an enabled Custom Animations outcome in §I, or an existing `animations.json` activates custom motion, evaluate §IX `Motion suggestion` rows and author any in-slide image states or cross-slide continuity now under [`executor-image.md`](../references/executor-image.md), each revealable or continuing Slide-local unit in a descriptive direct-root `<g id>`. Effects, pairing, order, and timing stay in the custom stage after the final gate; a suggestion alone activates nothing; deterministic Morph needs the continuing object as a direct-root group on both pages.
| Structure | Page authoring |
|---|---|
| `mirror` / `layout` | Start from the complete `page_layouts` SVG and preserve inherited visuals, root identity, atoms, and slots. Strict keeps the contract; `layout` may reflow carrier text inside unchanged slot bounds; adaptive uses a Strategist-declared Layout. A required atom or slot change returns upstream; Executor never edits `spec_lock.md`. |
| `style`, free design, brand-only | Flat per `executor-base.md` and [`semantic-svg.md`](../references/semantic-svg.md). |
**Motion endpoints**: when custom motion is active — an explicit user motion instruction, an enabled Custom Animations outcome in §I, or an existing `animations.json` — author the visible endpoint states now under [`executor-base.md`](../references/executor-base.md) §1; a §IX suggestion alone activates nothing.
**Early gate (Mandatory)** — after the fifth SVG, before page 6; a planned roster of six or fewer pages skips this gate and goes straight to the final gate:
@@ -254,7 +279,7 @@ python3 ${SKILL_DIR}/scripts/svg_quality_checker.py <project_path> \
--canonical-authoring --stage early --json
```
The stage checks every authored page so far under the partial-roster rules. Run unfiltered, review the complete issue set, fix every blocking error plus selected warnings in one consolidated pass, verify once; a still-failing verification is the next batch. If terminal output is truncated, read only the issue arrays from `validation/svg_quality_early_report.json`. The gate validates the method, not just the pages — emit one line before editing:
`--json` writes the report file (`validation/svg_quality_early_report.json`); stdout stays the human-readable summary and is never parsed as JSON. The stage checks every authored page so far under the partial-roster rules. Repair under the consolidated-pass discipline in [`executor-base.md`](../references/executor-base.md) §3; a still-failing verification is the next batch. If terminal output is truncated, read only the issue arrays from `validation/svg_quality_early_report.json`. The gate validates the method, not just the pages — emit one line before editing:
```
gate-signal: method=<rule resolved, or none> | page-local=<count> | not-exercised=<list>
@@ -276,11 +301,12 @@ python3 ${SKILL_DIR}/scripts/svg_quality_checker.py <project_path> \
```
- Before the gate, every §IX `Native-ready` `<object-key>=yes` has its draw-time marker group and JSON child; `=no` and incidental microvisuals stay ordinary SVG (a legacy bare `yes|no` is readable only when the page has exactly one eligible object). JSON-first Chart/Table validates inline schema/bounds; SVG-first markers need a current `data-pptx-fallback-sha256`, stamped after synchronization — missing or stale baselines block canonical/native export, not fallback export.
- Run unfiltered against `svg_output/` (never after `finalize_svg.py`, which masks violations); one run reports every page. On failure review all `blocking` errors and advisory warnings, fix every error plus the selected warnings in one consolidated pass, verify once; never check between individual fixes. If output is truncated, extract only `categories.blocking.issues` (and `categories.introduced.issues` when needed) from that run's `validation/svg_quality_report.json`, where `inherited` and `source-import` are provenance and `introduced` holds changed/new warnings.
- Every `warning` is advisory — no mandatory modification, no auto-normalizing user syntax, no disposition line; structured-template warnings (empty/framing-only Layout, bare Master, duplicate layout keys) guide optional cleanup only. A condition that must be corrected before release is an `error`.
- `--json` writes `validation/svg_quality_report.json`, the report the exporter fingerprints against `svg_output/`; stdout stays the human-readable summary and is never parsed as JSON. Without `--json` the export is refused.
- One run against `svg_output/` reports every page; repair under the consolidated-pass discipline in [`executor-base.md`](../references/executor-base.md) §3. If output is truncated, extract only `categories.blocking.issues` (and `categories.introduced.issues` when needed) from that run's `validation/svg_quality_report.json`, where `inherited` and `source-import` are provenance and `introduced` holds changed/new warnings.
- Structured-template warnings (empty/framing-only Layout, bare Master, duplicate layout keys) guide optional cleanup only; a condition that must be corrected before release is an `error`.
- **Hard rule — token-safe report handling**: on success use the exit status and terminal summary; never `cat` the complete JSON into context. Read it only for failure investigation, an explicit audit, or a field absent from stdout.
**Mandatory — final carrier-receipt review**: compare the checker's `[CARRIERS]` summary (detail under `files[].info.carrier_receipt`) with the retained page jobs, resource roles, and running geometry signatures. Counts and diversity are not quotas; when the facts contradict an active decision — an adopted preset absent, a directional / step / flowchart relationship drawn as a hand path or polygon where `executor-base.md` §3.0 names a preset, a primary image reduced to a minor frame, unrelated jobs collapsing to one neutral construction — read only the affected rows, repair those pages in one pass, and rerun the final checker. **Absence needs a reason**: when the receipt shows a deck-wide zero — `Presets: (none)`, or `inline emphasis 0`, `gradients 0`, or `filters 0` on the `Effects:` line — or fewer pages carrying a preset or connector than pages whose §IX `Relationships` line names `order` / `link` / `parent` / `membership` — or the `Presets:` line names no carrier-and-field contour — answer one line per absent family or per such page: what carries that job instead, and why it serves the reader better — for presets, one line per job the family serves, not for arrows alone: carrier and field (snipped or one-sided rounded rectangles, plaque, bevel, polygons, pie / arc / donut, frames, corners, folded corner, trapezoid, parallelogram, and `native-shape-authoring.md` §7 modelled forms), direction and sequence (arrows, chevrons, flow nodes), grouping and ownership (brackets, braces, frames, plaques), emphasis and annotation (callouts, badges, banners, stars). The style, speed, restraint, "text was enough", or "it is editable anyway" are not answers; a family or page without one is repaired where the page job calls for it, then the checker reruns. Choosing not to use a device is valid — only an unstated reason is not.
**Mandatory — final carrier-receipt review**: run the review in [`executor-base.md`](../references/executor-base.md) §3 Checkpoints against the retained §IX page jobs, resource roles, and geometry signatures; a repair reruns the final checker once.
**Logic Construction Phase (conditional)**: when the effective Speaker Notes outcome in §I is enabled, load [`executor-notes.md`](../references/executor-notes.md): validate a frozen `notes/total.md` against every information-bearing final SVG group (repair the page or the plan, never the script), or otherwise ground each page's narration in its final SVG and write `notes/total.md`. When disabled, load nothing and create no notes.
@@ -325,7 +351,17 @@ python3 ${SKILL_DIR}/scripts/finalize_svg.py <project_path>
| Speaker Notes `enabled` | `python3 ${SKILL_DIR}/scripts/svg_to_pptx.py <project_path>` |
| Speaker Notes `disabled` | `python3 ${SKILL_DIR}/scripts/svg_to_pptx.py <project_path> --no-notes` |
Append `--native-charts-and-tables` only for an explicit editable Chart/Table delivery decision (markers, templates, semantic tables, and imported charts never activate it; formulas are always native). Motion: with a preserved or produced `animations.json`, keep the base command — the exporter reads the sidecar; append the resolved [`animations.md`](../references/animations.md) flags for a deck-wide setting — explicit flags override the corresponding sidecar default/slide fields while group overrides remain; an explicit Custom Animations disable keeps the sidecar and appends `-a none`, an explicit all-motion disable uses `--no-animations`, and final Stage-2 `false` does neither. Sound: after the motion solution is final, run the optional pass in `animations.md` §2.2 — no cue creates no `sounds/`; a selected cue is synced with `sound_sync.py` (never read from `templates/sounds/` directly) and referenced from the validated sidecar. For a narrated MP4, [`generate-audio`](stages/generate-audio.md) owns the delivery choice; do not add `--conversion-trace` to every base export; an explicit `--conversion-trace <path>` writes to that destination instead of the default.
| Decision | Flag |
|---|---|
| Explicit editable Chart/Table delivery decision | Append `--native-charts-and-tables` (markers, templates, semantic tables, and imported charts never activate it; formulas are always native) |
| Preserved or produced `animations.json` | Keep the base command; the exporter reads the sidecar |
| Deck-wide motion setting | Append the resolved [`animations.md`](../references/animations.md) flags |
| Explicit Custom Animations disable | Keep the sidecar and append `-a none` |
| Explicit all-motion disable | `--no-animations` |
| Final Stage-2 `false` | Neither flag |
| Conversion trace | Do not add `--conversion-trace` to every base export; an explicit `--conversion-trace <path>` writes to that destination instead of the default |
Sound: the optional post-motion pass is [`animations.md`](../references/animations.md) §2.2. For a narrated MP4, [`generate-audio`](stages/generate-audio.md) owns the delivery choice.
**Success criterion**: the command exits 0 and produces `exports/<project_name>_<timestamp>.pptx`, `validation/<project_name>_<timestamp>.report.json` with `passed` or `passed-with-warnings`, and `validation/<project_name>_<timestamp>.trace.json` when `--conversion-trace` was enabled. The exporter itself requires the current matching `final` quality report and exits nonzero on a missing, unreadable, unsupported, non-final, blocking, stale, or unverifiable one. Read the compact `[POSTFLIGHT]` receipt (`status`, `quality_gate`, slide count, warning counts, paths), disclose material warnings, and never `cat` the full report on success. Retain the report path for a later `deck_motion` handoff; postflight proves the package, not a later MP4 audio track.
@@ -30,9 +30,9 @@ Artifact roles follow [`artifact-ownership.md`](../../references/artifact-owners
**Hard rule — speed removes interaction and durable planning, not capability**: every ordinary source, research, carrier, resource, analysis, authoring, and export capability stays available when it serves the deck — availability, not a requirement to use every carrier. Explicit user facts, wording, choices, exclusions, and permission boundaries still win.
**Default — optional production behavior (may override when useful)**: Speaker Notes, Custom Animations, and narration start off; enable any of them when the request or deck benefits, with their normal inputs and flags and without asking. Quick never creates or reads a root Design Spec or lock to do so.
**Default — optional production behavior (may override when useful)**: Speaker Notes, Custom Animations, and narration start off. Enable any of them when the request or deck benefits, with their normal inputs and flags and without asking. Quick never creates or reads a root Design Spec or lock to do so.
**Mandatory — discover motion before deciding whether to load it** (once, during §2's pre-P01 planning; keep the defaults when no row supplies a concrete communication job; when several apply, use the earliest load point — a before-authoring signal beats before-export):
**Mandatory — discover motion before deciding whether to load it**: once, during §2's pre-P01 planning. Keep the defaults when no row supplies a concrete communication job. When several rows apply, use the earliest load point — a before-authoring signal beats before-export.
| Signal | Action |
|---|---|
@@ -42,7 +42,7 @@ Artifact roles follow [`artifact-ownership.md`](../../references/artifact-owners
| A directional/section boundary benefits from a non-default transition | Load `animations.md` before export and choose from its §3 playbook |
| No signal | Keep `fade` transitions and object animation `none`; load nothing |
**Hard rule — Quick video Custom Animations**: when [`video-design.md`](../../references/video-design.md) is active (recorded, self-running, or video-directed delivery), enable Custom Animations, load `animations.md` before SVG authoring, preserve the semantic motion units, and run `customize-animations` after the final checker — the table above chooses the choreography, not whether Custom Animations exists, and pages may stay static. A Quick video run without a validated `animations.json` fails unless the user explicitly asked for static or transition-only playback. Narration-governed motion also activates cue synchronization.
**Hard rule — Quick video Custom Animations**: when [`video-design.md`](../../references/video-design.md) is active (recorded, self-running, or video-directed delivery), enable Custom Animations, load `animations.md` before SVG authoring, preserve the semantic motion units, and run `customize-animations` after the final checker. The table above chooses the choreography, not whether Custom Animations exists; pages may stay static. A Quick video run without a validated `animations.json` fails unless the user explicitly asked for static or transition-only playback. Narration-governed motion also activates cue synchronization.
---
@@ -56,12 +56,18 @@ Artifact roles follow [`artifact-ownership.md`](../../references/artifact-owners
| CSV / TSV | Read directly as a plain-text table |
| Markdown or conversation text | Read directly |
Apply [`conversion.md`](../../scripts/docs/conversion.md) § Image Orientation Review before import when correction is requested, converted text asks for rotated viewing, or an asset is visibly sideways (skip the legacy HTML tool). After reading every source, research only the gaps where the requested outcome would otherwise require inventing, omitting, or leaving unsupported an externally verifiable claim; an Image to PPTX surface is a closed corpus whose unreadable regions become `manual_required`, and a closed/source-only brief stays within its material. When delivery is recorded, self-running, or video-directed — or a final/literal script will become notes/audio — read `video-design.md` now and retain it through roster, SVG, notes, and motion decisions.
**Orientation review**: apply [`conversion.md`](../../scripts/docs/conversion.md) § Image Orientation Review before import when correction is requested, converted text asks for rotated viewing, or an asset is visibly sideways (skip the legacy HTML tool).
**Research scope**: after reading every source, research only the gaps where the requested outcome would otherwise require inventing, omitting, or leaving unsupported an externally verifiable claim. An Image to PPTX surface is a closed corpus whose unreadable regions become `manual_required`; a closed/source-only brief stays within its material.
**Video delivery**: when delivery is recorded, self-running, or video-directed — or a final/literal script will become notes/audio — read `video-design.md` now and retain it through roster, SVG, notes, and motion decisions.
**Template branch** (resolve exactly one before initialization; Image to PPTX always takes free design and installs nothing):
- **Direct template application** — exact workspace roots were supplied, or Create Template returned one in this conversation: at most one root per kind; load [`apply-template-workspace`](../stages/apply-template-workspace.md), normalize each root, read only the frontmatter needed for kind/canvas, and run its read-only preflight. Never scan the library, fuzzy-match a name, or open a selector. Explicit user canvas wins; otherwise the structure owner's canvas (Layout before Deck), passed to `init --format` only when it exactly matches a registered canvas.
- **Free design** — no exact root: continue with the requested canvas, or decide the viewBox during authoring. A bare template name, brand mention, style phrase, or vague request to pick a template is brief input, not a workspace reference.
| Branch | Rule |
|---|---|
| **Direct template application** — exact workspace roots were supplied, or Create Template returned one in this conversation | At most one root per kind. Load [`apply-template-workspace`](../stages/apply-template-workspace.md), normalize each root, read only the frontmatter needed for kind/canvas, and run its read-only preflight. Never scan the library, fuzzy-match a name, or open a selector. Explicit user canvas wins; otherwise the structure owner's canvas (Layout before Deck), passed to `init --format` only when it exactly matches a registered canvas. |
| **Free design** — no exact root | Continue with the requested canvas, or decide the viewBox during authoring. A bare template name, brand mention, style phrase, or vague request to pick a template is brief input, not a workspace reference. |
```bash
python3 ${SKILL_DIR}/scripts/project_manager.py init <project_name> --quick-generate
@@ -70,15 +76,22 @@ python3 ${SKILL_DIR}/scripts/project_manager.py import-sources \
[projects/<research_slug>.md projects/<research_slug>.facts.json]
```
**Hard rule — truthful canvas token**: `--format <registered_format>` only for an exactly resolved registered canvas; otherwise the first SVG's viewBox is the canvas authority, and custom dimensions are never encoded as a token. Neither branch touches `confirm_ui/`. `init` creates `svg_output/` and the cold `validation/workflow.log` (auto-recorded by later tools; one manual note only for a material handoff, rework reason, approved exception, or manual recovery; never read during a run and never a resume source). Use a new path or one whose `svg_output/` is empty; Quick ignores any existing Design Spec or lock and never scaffolds one.
**Hard rule — truthful canvas token**: `--format <registered_format>` only for an exactly resolved registered canvas; otherwise the first SVG's viewBox is the canvas authority, and custom dimensions are never encoded as a token. Neither branch touches `confirm_ui/`.
**✅ Checkpoint — every named input landed**: `import-sources` exits 0 when one input succeeds; read the printed `skipped` reasons — "equivalent content exists" is benign, `path not found`, failed conversion, or no usable Markdown means the source is absent: re-import, supply a converted equivalent, or state why the deck proceeds without it. Pass a source once when Markdown sits beside it, both locations when `-o` wrote elsewhere; `projects/`-local inputs move (`--copy` keeps them), external paths are copied. Bitmaps are archived under `sources/` and copied into `images/`; EMF/WMF stay vector references (never PNG; blank in browser preview is expected); each PPTX yields `analysis/<stem>.identity.json`, `<stem>.slide_library.json`, and the `source_profile.json` index — source facts, not replica constraints. The facts JSON is the sole URL authority: only after web-image search is exhausted may a webpage package be fetched under [`topic-research`](../stages/topic-research.md) § Hand-off and its accepted images copied in. Under Image to PPTX, the normalized frame roster is canonical input and the agent writes `analysis/reconstruction_inventory.json` before deciding layers.
**Project state**: `init` creates `svg_output/` and the cold `validation/workflow.log` (auto-recorded by later tools; one manual note only for a material handoff, rework reason, approved exception, or manual recovery; never read during a run and never a resume source). Use a new path or one whose `svg_output/` is empty. Quick ignores any existing Design Spec or lock and never scaffolds one.
**Installed templates**: run `apply-template-workspace` against the preflighted roots only; the request is the selection authority, with no receipt or handoff, and every later read uses the installed state. Before P01 read each installed spec once and, for Layout/Deck, every SVG prototype; apply Brand identity, Style direction, the structure owner's prototype geometry, and Deck context under the stage's §5 segment precedence — an owner's instruction on how a value dominates, recedes, or stays rare binds as strongly as the value, and a Style tendency never demotes a Brand's dominant color. Freeze one **Template Application** paragraph in context: explicit user instructions first, otherwise the fit of the content to the complete roster, defaulting to reference-led use (redesign after full-roster study; other readings such as augment-only or replacement-only are examples, not a menu). It names which prototypes may be used, skipped, repeated, reordered, or adapted, what stays fixed, and any exception by exact SVG basename; when a detail is later uncertain, reread the installed SVG.
**✅ Checkpoint — every named input landed**: `import-sources` exits 0 when one input succeeds; read the printed `skipped` reasons. "equivalent content exists" is benign; `path not found`, failed conversion, or no usable Markdown means the source is absent: re-import, supply a converted equivalent, or state why the deck proceeds without it. Pass a source once when Markdown sits beside it, both locations when `-o` wrote elsewhere. Copy/move semantics, bitmap archiving, EMF/WMF handling (never PNG), and the PPTX intake bundle under `analysis/` are [`project.md`](../../scripts/docs/project.md) — source facts, not replica constraints.
**URL authority**: the facts JSON is the sole URL authority; only after web-image search is exhausted may a webpage package be fetched under [`topic-research`](../stages/topic-research.md) § Hand-off and its accepted images copied in. Under Image to PPTX, the normalized frame roster is canonical input and the agent writes `analysis/reconstruction_inventory.json` before deciding layers.
**Installed templates**: run `apply-template-workspace` against the preflighted roots only; the request is the selection authority, with no receipt or handoff, and every later read uses the installed state. Before P01 read each installed spec once and, for Layout/Deck, every SVG prototype. Apply Brand identity, Style direction, the structure owner's prototype geometry, and Deck context under the stage's §5 segment precedence: an owner's instruction on how a value dominates, recedes, or stays rare binds as strongly as the value, and a Style tendency never demotes a Brand's dominant color.
**Template Application paragraph**: freeze one in context — explicit user instructions first, otherwise the fit of the content to the complete roster, defaulting to reference-led use (redesign after full-roster study; other readings such as augment-only or replacement-only are examples, not a menu). It names which prototypes may be used, skipped, repeated, reordered, or adapted, what stays fixed, and any exception by exact SVG basename. When a detail is later uncertain, reread the installed SVG.
Read the planning-capability batch in one pass — a capability map, not a usage checklist:
```
Read ${SKILL_DIR}/references/plan-core.md
Read ${SKILL_DIR}/references/canvas-formats.md
Read ${SKILL_DIR}/references/modes/_index.md
Read ${SKILL_DIR}/references/visual-styles/_index.md
@@ -88,52 +101,29 @@ Read ${SKILL_DIR}/templates/charts/chart-vocabulary.md
Read ${SKILL_DIR}/templates/tables/table-vocabulary.md
```
Resolve one whole solution directly (never Default's three candidates): the strongest fit to the brief, or with a template the solution that most fully expresses the installed context and frozen Template Application. Freeze its mode/style/rendering ids, read only those detail files or exact custom bases (a novel custom reads none; never open unselected siblings), decide AI-image usefulness as a separate source judgment while keeping the rendering direction for coherence, and keep everything in active context only — no strategy summary, checkpoint, or persisted plan.
**One whole solution**: resolve it directly (never Default's three candidates): the strongest fit to the brief, or with a template the solution that most fully expresses the installed context and frozen Template Application. Freeze its mode/style/rendering ids and read only those detail files or exact custom bases (a novel custom reads none; never open unselected siblings). Decide AI-image usefulness as a separate source judgment while keeping the rendering direction for coherence. Keep everything in active context only — no strategy summary, checkpoint, or persisted plan.
**Pre-P01 resolution** (apply the §1 motion gate here; freeze the roster after the rhythm check):
- Narrative beats, mental-map arcs, candidate visible states and their deltas, and enabled notes segments; adopt continuity only when it clarifies, and never alter profile-fixed count/order/content to manufacture endpoints.
- Effective Speaker Notes, Custom Animations, and Narration Audio: narration requires notes; later recording alone forces neither audio nor object animation; recorded/self-running/video delivery follows `video-design.md` and enables Custom Animations before authoring; direct narrated video also decides before audio whether narration governs group timing.
- The exact slide roster with one compact core message per page.
- Canvas, visual direction, wording, viewing distance, and reading mode (`presentation` for distance-first projected or recorded viewing, `balanced` for mixed, `text` for close content-heavy reading). Take the initial body anchor and sanity band from [`canvas-formats.md`](../../references/canvas-formats.md) § Typography Scale Start, then resolve one typography plan for the delivery target of [`shared-standards-core.md`](../../references/shared-standards-core.md) §4.1 — never the authoring host's fonts — with stable anchors for title, body, annotation, and every recurring role. When content does not fit, restructure, shorten, or split within the invariants; if none is permitted, surface the fit rather than shrinking a recurring role.
- The semantic color roles the roster needs (background/surface, primary/secondary text, dominant/accent, status), each with a concrete anchor: honor user, template/brand, fidelity, and resolved-style semantics before deriving the missing roles; decide which dominate, support, or stay rare; keep meaning-bearing text legible; pair any newly authored color-coded distinction with a label, symbol, line, or geometry cue.
- A body-content frame and a density judgment per page (`anchor`, `dense`, `breathing`) rather than one uniform fill.
- For each page, its semantic units and their source-stated relationship (`order` / `link` / `parent` / `membership` / `contrast` / `overlap`, or none), entry, and outcome — the input to §3's Structure decision; zones, geometry, and carriers are §3 authoring decisions.
- The deck-level shape language under [`visual-styles/_index.md`](../../references/visual-styles/_index.md) §2, and, when it earns a continuity job, one transient motif system with an invariant and a reuse mode (fixed chrome, adaptive variation, or both); restraint governs weight and recurrence, never the omission of an evidenced identity or communication motif.
- Resource decisions for immediate preparation: manifests may carry filenames, page relationship, status, and generation/crop/focal cues (plus subject/quiet zones, boundary, seam, and share when composition depends on them); no general roster or icon-to-page assignment; each formula's LaTeX and each hyperlink's exact target kept in context, with no manifest. An explicit user implementation path wins; otherwise the registered default.
- **Beats and states**: narrative beats, mental-map arcs, candidate visible states and their deltas, and enabled notes segments; adopt continuity only when it clarifies, and never alter profile-fixed count/order/content to manufacture endpoints.
- **Production outcomes**: effective Speaker Notes, Custom Animations, and Narration Audio. Narration requires notes; later recording alone forces neither audio nor object animation; recorded/self-running/video delivery follows `video-design.md` and enables Custom Animations before authoring; direct narrated video also decides before audio whether narration governs group timing.
- **Roster**: the exact slide roster with one compact core message per page.
- **Reading and typography**: canvas, visual direction, wording, viewing distance, and reading mode (`presentation` for distance-first projected or recorded viewing, `balanced` for mixed, `text` for close content-heavy reading). Take the initial body anchor and sanity band from [`canvas-formats.md`](../../references/canvas-formats.md) § Typography Scale Start, then resolve one typography plan for the delivery target of [`shared-standards-core.md`](../../references/shared-standards-core.md) §4.1 — never the authoring host's fonts — with stable anchors for title, body, annotation, and every recurring role. When content does not fit, restructure, shorten, or split within the invariants; if none is permitted, surface the fit rather than shrinking a recurring role.
- **Color roles**: the semantic color roles the roster needs (background/surface, primary/secondary text, dominant/accent, status), each with a concrete anchor. Honor user, template/brand, fidelity, and resolved-style semantics before deriving the missing roles; decide which dominate, support, or stay rare; keep meaning-bearing text legible; pair any newly authored color-coded distinction with a label, symbol, line, or geometry cue.
- **Density**: a body-content frame and a density judgment per page (`anchor`, `dense`, `breathing`) rather than one uniform fill.
- **Relationships**: for each page, its semantic units and their source-stated relationship (`order` / `link` / `parent` / `membership` / `contrast` / `overlap`, or none), entry, and outcome — the input to §3's topology decision; zones, geometry, and carriers are §3 authoring decisions.
- **Shape language and motif**: the deck-level shape language under [`visual-styles/_index.md`](../../references/visual-styles/_index.md) §2, and, when it earns a continuity job, one transient motif system with an invariant and a reuse mode (fixed chrome, adaptive variation, or both). Restraint governs weight and recurrence, never the omission of an evidenced identity or communication motif.
- **Resource decisions** for immediate preparation: manifests may carry filenames, page relationship, status, and generation/crop/focal cues (plus subject/quiet zones, boundary, seam, and share when composition depends on them); no general roster or icon-to-page assignment. Each formula's LaTeX and each hyperlink's exact target stay in context, with no manifest. An explicit user implementation path wins; otherwise the registered default.
**Mandatory — whole-roster rhythm check**: compare neighbors and section arcs — chapter entries visibly reset, same-density, same-resource, or same-relationship runs are intentional page-job arcs, a repeated motif carries a continuity job, each section follows a mode-fitting progression (including framework → explanation/evidence → judgment/action when it serves), and the final arc resolves the objective before a genuine ending lowers load. Same section, equal density, one style, and precedent establish no arc. Repair the transient roster in place; preserve intentional continuity, legitimately all-`dense` material, and 1:1 order; add no filler — a `breathing` page marks a real pause. No artifact or second pass.
**Mandatory — whole-roster rhythm check, cover impact, closing impact**: [`plan-core.md`](../../references/plan-core.md) §4, applied to the transient roster in place; no artifact or second pass.
**Prepared final narration**: an explicit final/literal script for notes or audio is segmented by scene while resolving the roster, every word preserved, and written once before P01 to `notes/total.md` (`# Slide <number>` headings, `---` separators) as production input, split only after the roster exists. Draft narration stays source material for the ordinary notes branch.
**Default — resource need per page (may stay implicit when a page's need is obvious)**: before resources, decide which pages need a prepared image, lettering, or illustrated-icon resource — the jobs only a prepared file can serve; SVG/emoji icons keep their curated-pool boundary. The page's carrier mix itself — background, text, native geometry, imagery, icons, visualizations and their weights — is §3's authoring decision, not a preparation decision. The resolved style controls treatment and recurrence but never eligibility, source, or the native vocabulary, and a compact icon cue does not discharge a scene, subject, or visual-weight job a photo or illustration family would serve.
**Resource need per page**: decide it under [`plan-core.md`](../../references/plan-core.md) §5 before resources. SVG/emoji icons keep their curated-pool boundary, and the page's carrier mix is §3's authoring decision, not a preparation decision. The resolved style controls treatment and recurrence but never eligibility, source, or the native vocabulary. A compact icon cue does not discharge a scene, subject, or visual-weight job a photo or illustration family would serve. The communication-job menu never satisfies the per-page topology decision in §3.
| Communication job | Prepared resource or information model |
|---|---|
| Real subject, place, product, evidence, atmosphere, or scene benefits from visual grounding | Supplied/extracted, web, AI, or sliced image |
| Reusable title/corner decoration, a dominant illustrated anchor, supporting figure, or accent strengthens compositions | A coherent AI illustration family as transparent `slice` assets, combined freely with other carriers |
| A compact semantic cue clarifies a category, process, KPI, state, or navigation item | Prepared project-local SVG/emoji icon, an illustrated-icon `slice`, or both |
| A real company, product, service, or social brand must appear as itself | The exact mark from `simple-icons` or supplied assets; not a user-facing library choice |
| Values, categories, time, weights, or duration determine mark geometry | Value-driven chart |
| Sequence, hierarchy, role, region, or relationship determines topology | Qualitative structure |
| Rows, columns, cells, headers, merges, alignment form the model | Cell-grid table |
| A stable display string reads better with a material, dimensional, hand-rendered, or illustrative treatment | Decorative lettering per the rule below, as an image beside a native title |
**Image sources, grounding, families, lettering, per-image source, and treatment**: [`plan-core.md`](../../references/plan-core.md) §5.1 owns the credentials Hard rule, visual grounding before a zero-image deck, illustration families and illustrated icons, decorative-lettering candidates, the per-image source decision, and image treatment and subject layers. In Quick, web search keeps zero-config providers, AI capability is resolved during preparation, and the no-AI replan below owns exhaustion.
This menu never satisfies the per-page Structure decision in §3.
**Hard rule — credentials never decide image need**: plan carriers without inspecting backend configuration or probing a provider; web search keeps zero-config providers, and AI capability is resolved during preparation, where the no-AI replan owns exhaustion.
**Default — visual grounding before a zero-image deck (may override when the full-roster review finds no image job)**: honor an explicit no-image requirement; otherwise, when the audience must recognize, experience, compare, or choose an externally verifiable subject, plan supplied/extracted or web images, and prepare AI imagery — a complete image or transparent elements — where invented or stylized expression materially improves a visual job. A semantic decision, not a quota.
**Mandatory — illustration families and illustrated icons**: when the resource-need review selects a composable family, resolve it before authoring — elements may repeat as title/corner chrome or vary as anchors, figures, and accents on any page — batching compatible elements through Illustration Sheets under [`image-generator.md`](../../references/image-generator.md) §4.3 and splitting only for geometry, detail, or quality conflicts. When it selects illustrated-icon cues and AI is not forbidden, prepare them as transparent slices under `images/`; grouping, count, and coexistence with SVG icons follow page fit, with no quota and never as SVG inventory.
**Reference — decorative-lettering candidates**: when AI is not forbidden, any display string in the frozen roster is a candidate on two questions — is the wording stable, and could an artistic treatment communicate better than native type? Page role, length, line count, kind of noun, and resolved style never pre-filter: a cover hook, chapter word, place or product name, dish or exhibit name, year, hero number, pull quote, or motif word all qualify, a two-character mark and a two-line lockup equally, and a phrase is never trimmed to feel more "wordmark-like"; type over photography or a busy field is often exactly where native text reads pasted-on. Compare candidates inside the whole page and deck mix and select any coherent set whose treatment wins; selecting none is valid without explanation. For each selected mark keep a native title wherever the page needs a searchable, selectable, or outline-visible heading — the lettering is the display layer, the editable wish is answered by the native layer. Prepare the set without a separate request: exact approved strings, one ordinary AI item or grouped Illustration Sheets with transparent slices, grouped by character and treatment, with role, placement/background relationship, weight, and energy given to the model under `image-generator.md` §5.3's controlled-default/high-expression boundary; chrome and body stay native. Never invent or alter copy or create lettering to justify AI.
**Mandatory — per-image source decision**: outside Image to PPTX, decide each page image's source separately — supplied/extracted when it carries authority, web when an externally verifiable subject must appear as itself, AI when invented or stylized expression matters more than documentary identity; mixed sources are normal. A visual style, `Illus.` propensity, or rendering resolves how imagery looks, never its source: a named place, building, product, artwork, or person stays a web/supplied candidate however illustrative the deck, and a subject deliberately not shown as itself is stated with its reason in the final report.
**Mandatory — image treatment and subject layers**: choose per image: `none`; a native SVG treatment (crop viewport, opacity, frame, scrim, shadow); or a prepared derivative. A subject that crosses native content requires a clean full-canvas base plus a registered RGBA cutout (`#A2-03`). A prepared derivative never overwrites its source, never becomes another derivative's parent, never has its output equal its input, and is derived only after that source is itself final. Where fidelity forbids adding a label, symbol, line, or geometry cue to a new color encoding, preserve the source encoding instead.
**Reference — Chart/Table vocabularies**: the loaded vocabularies list what exists; they rank nothing and are neither quota nor whitelist. Choose at most one primary `family/key` per page (never for qualitative composition), validate it with `visualization_recall.py validate`, keep its purpose in context — the reference stays flexible and locks neither final type, geometry, style, nor native output — and retain `no-template-match` when none fits; describe embedded children and qualitative relationships in the page decision. Give every independent Chart/Table a page-local `kebab-case` key with its `<object-key>=yes|no` native-ready decision and any promoted chart-verification status in context; qualitative relationships create no key or reusable structure.
**Chart/Table references**: [`plan-core.md`](../../references/plan-core.md) §5.2 — at most one flexible `family/key` per page, validated with `visualization_recall.py validate`, purpose kept in context, `no-template-match` retained when none fits. Each independent Chart/Table keeps its page-local `kebab-case` key, `<object-key>=yes|no` native-ready decision, and any promoted chart-verification status in context; qualitative relationships create no key or reusable structure.
**Resource preparation** (only what the decided pages need):
@@ -149,37 +139,60 @@ This menu never satisfies the per-page Structure decision in §3.
| Registered reconstruction group | `image-generator.md` §4.4: full-canvas members `crop=no-crop`, every shared-plate member an independent picture |
| Visualization | Keep values, cell topology, and treatment in context; load the Chart/Table authority in §3 and write native replacement metadata for every supported chart and pure text grid (native-ready by default) |
**Hard rule — planned slice closure**: every sheet carries `slice_grid` and `slice_names` in `image_prompts.json`; every `images/<name>.png` must exist after an exit-0 `--strict-alpha` run before authoring — a `Generated` parent never satisfies its outputs. A nonzero slice run returns the parent to preparation: correct only an evidenced key/tolerance mismatch, otherwise enlarge cells or split incompatible families and regenerate; repeating the same failing grid is not recovery. An explicit manual path sets the item `Needs-Manual` with `last_error` and blocks SVG/export until every output is supplied and validated; exhausted automation follows the no-AI replan instead.
**Hard rule — planned slice closure**: every sheet carries `slice_grid` and `slice_names` in `image_prompts.json`; every `images/<name>.png` must exist after an exit-0 `--strict-alpha` run before authoring — a `Generated` parent never satisfies its outputs.
**Quick exhausted-automation no-AI replan** ([`image-generator.md`](../../references/image-generator.md) §7): when an automated AI path or its dependent slicing is exhausted, ask no path question and enter no manual fallback — remove the affected AI jobs and stale manifest entries, carry their communication content with native text/SVG or prepared non-AI assets, and continue; retaining AI imagery means repairing capability and starting a new Quick run.
| Slice outcome | Action |
|---|---|
| Nonzero slice run | The parent returns to preparation: correct only an evidenced key/tolerance mismatch, otherwise enlarge cells or split incompatible families and regenerate; repeating the same failing grid is not recovery |
| Explicit manual path | The item is `Needs-Manual` with `last_error` and blocks SVG/export until every output is supplied and validated |
| Exhausted automation | The no-AI replan below |
**Validation before §3**: every file-backed resource is terminal — `Existing`, `Generated`, or `Sourced` under [`svg-image-embedding.md`](../../references/svg-image-embedding.md) — and every `slice_names` basename resolves to its PNG; a missing name resumes its owning step and is never deferred to the checker. Web `Needs-Selection` blocks until a thumbnail is promoted or the bounded ranked pages and materially different variants are exhausted, after which a vision-capable owner may fetch one adopted-page package; `Needs-Manual` blocks even with an unverified file; without vision only the strict metadata-ranked path reaches `Sourced`, and its provenance says so. Never bypass status by preview or presence, never substitute unrelated material. Acquisition-time review follows the owning reference; authoring inspects only one ambiguous `Existing`/`Sourced` asset under `executor-image.md` and never reopens `Generated` outputs (Image to PPTX inspects every normalized page and generated layer once, then the final recomposition). After resources change, run `analyze_images.py`; manifests and provenance are resource truth, not a design strategy.
**Quick exhausted-automation no-AI replan** ([`image-generator.md`](../../references/image-generator.md) §7): when an automated AI path or its dependent slicing is exhausted, ask no path question and enter no manual fallback. Remove the affected AI jobs and stale manifest entries, carry their communication content with native text/SVG or prepared non-AI assets, and continue. Retaining AI imagery means repairing capability and starting a new Quick run.
**Validation before §3**: every file-backed resource is terminal — `Existing`, `Generated`, or `Sourced` under [`svg-image-embedding.md`](../../references/svg-image-embedding.md) — and every `slice_names` basename resolves to its PNG; a missing name resumes its owning step and is never deferred to the checker. Never bypass status by preview or presence, never substitute unrelated material.
| Web status | Rule |
|---|---|
| `Needs-Selection` | Blocks until a thumbnail is promoted or the bounded ranked pages and materially different variants are exhausted, after which a vision-capable owner may fetch one adopted-page package |
| `Needs-Manual` | Blocks even with an unverified file |
| No vision | Only the strict metadata-ranked path reaches `Sourced`, and its provenance says so |
**Inspection boundary**: acquisition-time review follows the owning reference; authoring inspects only one ambiguous `Existing`/`Sourced` asset under `executor-image.md` and never reopens `Generated` outputs (Image to PPTX inspects every normalized page and generated layer once, then the final recomposition). After resources change, run `analyze_images.py`; manifests and provenance are resource truth, not a design strategy.
---
## 3. Direct SVG Authoring
Read the execution core together, never file by file: [`shared-standards-core.md`](../../references/shared-standards-core.md), [`executor-base.md`](../../references/executor-base.md), [`semantic-svg.md`](../../references/semantic-svg.md), and [`preset-shape-vocabulary.md`](../../references/preset-shape-vocabulary.md) (complete, before P01); then evaluate `executor-base.md`'s routing triggers once over the frozen roster before P01 and read every triggered module in the same batch — [`executor-structure.md`](../../references/executor-structure.md) + [`topology-assembly.md`](../../references/topology-assembly.md) for any `Structure = yes` page, [`native-shape-authoring.md`](../../references/native-shape-authoring.md) for any contour beyond basic primitives, [`svg-effects.md`](../../references/svg-effects.md) for any visual job beyond the everyday block — each recorded in the module line of the pages that use it; a page that reaches a capability the sweep did not foresee reads its module at that moment, before its first SVG line; installed Layout/Deck structure adds [`pptx-structure-interface.md`](../../references/pptx-structure-interface.md). Keep the selected mode/style files: a custom applies one basis under its behavior, synthesizes several by their contributions, or follows the behavior alone. When any image exists, read the complete `Any image` row of `executor-base.md`'s routing table — [`executor-image.md`](../../references/executor-image.md), [`image-layout-spec.md`](../../references/image-layout-spec.md), [`image-layout-patterns.md`](../../references/image-layout-patterns.md), and [`svg-image-embedding.md`](../../references/svg-image-embedding.md) — once before the first affected page (plus [`executor-web-image.md`](../../references/executor-web-image.md) for a `Sourced` image); reread anything only after a known file change or context invalidation.
Read the execution core together, never file by file: [`shared-standards-core.md`](../../references/shared-standards-core.md), [`executor-base.md`](../../references/executor-base.md), [`semantic-svg.md`](../../references/semantic-svg.md), and [`preset-shape-vocabulary.md`](../../references/preset-shape-vocabulary.md) (complete, before P01). Then evaluate `executor-base.md`'s routing table once over the frozen roster and read every triggered module in the same batch (the `Any image` row loads its four files together); installed Layout/Deck structure adds [`pptx-structure-interface.md`](../../references/pptx-structure-interface.md). Keep the selected mode/style files: a custom applies one basis under its behavior, synthesizes several by their contributions, or follows the behavior alone. Reread anything only after a known file change or context invalidation.
`executor-base.md` binds Quick exactly as it binds Default except its `Default only` items — the persisted-plan handoff in §2 / §2.1 and the export hand-off in §6 — which Quick's transient §2 anchors, own checker gates, and export below own; the Default gate cadence lives in `generate-pptx.md` Step 6 and does not apply. Conditional authorities load on its routing table (Chart/Table branches, native data, formula, hyperlink); Chart/Table reference and final information model are independent signals, and selection never makes an object native-ready. Explicit user/template requirements and the resolved style override compatible aesthetic defaults, never technical boundaries, carrier eligibility, or native capability discovery.
**How executor-base binds Quick**: exactly as it binds Default except its `Default only` items — the persisted-plan handoff in §2 / §2.1 and the export hand-off in §6 — which Quick's transient §2 anchors, own checker gates, and export below replace; the Default gate cadence in `generate-pptx.md` Step 6 does not apply. Conditional authorities load on its routing table (Chart/Table branches, native data, formula, hyperlink). Chart/Table reference and final information model are independent signals, and selection never makes an object native-ready. Explicit user/template requirements and the resolved style override compatible aesthetic defaults, never technical boundaries, carrier eligibility, or native capability discovery.
**Mandatory — per-image-page composition**: for every page with images, after content and communication move but before geometry, apply `executor-image.md`'s image-integration decision once, keeping role, direction source, parent contour, slot/rhythm system, image/shape action, and continuity in context only; a deliberate plain or equal-grid result is valid when it communicates better. Image to PPTX replaces this and the page-geometry decision for its canonical frame: preserve source geometry, restore text natively, keep source-graphic identity through the prepared asset, and use the registered layer/plate stack; run the ordinary decisions only for additional non-source content.
**Mandatory — native formulas and hyperlinks**: no resource or manifest for either. Keep the exact LaTeX and choose ordinary text, same-paragraph inline math, or a standalone block with its SVG preview under [`native-formula.md`](../../references/native-formula.md); keep each link's exact target, choose an inline or whole-object carrier, and author canonical `<a href>` under [`native-hyperlinks.md`](../../references/native-hyperlinks.md), never guessing a destination.
**Mandatory — native formulas and hyperlinks**: no resource or manifest for either. Keep the exact LaTeX and choose ordinary text, same-paragraph inline math, or a standalone block with its SVG preview under [`native-formula.md`](../../references/native-formula.md). Keep each link's exact target, choose an inline or whole-object carrier, and author canonical `<a href>` under [`native-hyperlinks.md`](../../references/native-hyperlinks.md), never guessing a destination.
**Mandatory — per-page Structure decision and geometry move**: after the page's content and communication move, before any geometry, decide whether geometry must carry `order`, `link`, `parent`, `membership`, `contrast`, or `overlap` (`executor-base.md` §2.1) — `no` stays on the base path, `yes` loads and applies the Shape Composition Grammar and topology assembly. Then, when the page's geometry reaches beyond basic primitives, load and apply [`native-shape-authoring.md`](../../references/native-shape-authoring.md) §2.1 to the transient geometry job, content, deck shape language, resolved style, and full vocabulary before coordinates (`describe --compact` only when objective facts could change a serious candidate). Both decisions stay in context, and the capability menu, visualization recall, and template geometry never stand in for them. Quick runs [`verify-charts.md`](../stages/verify-charts.md) after the roster and before the final checker whenever data-driven chart geometry exists.
**Mandatory — per-page topology decision and geometry move**: after the page's content and communication move, before any geometry, decide whether geometry must carry `order`, `link`, `parent`, `membership`, `contrast`, or `overlap` (`executor-base.md` §2.2) — `no` stays on the base path, `yes` loads and applies the Shape Composition Grammar and topology assembly. Then, when the page's geometry reaches beyond basic primitives, load and apply [`native-shape-authoring.md`](../../references/native-shape-authoring.md) §2.1 to the transient geometry job, content, deck shape language, resolved style, and full vocabulary before coordinates (`describe --compact` only when objective facts could change a serious candidate). Both decisions stay in context; the capability menu, visualization recall, and template geometry never stand in for them. Quick runs [`verify-charts.md`](../stages/verify-charts.md) after the roster and before the final checker whenever data-driven chart geometry exists.
**Per-page anchors**: apply the core-message, typography-role, color, body-frame, density, and composition anchors from §2 while authoring; when `notes/total.md` was frozen, keep each page's segment in view so its visible state and direct-root groups support the spoken words without copying the script into body text.
**Per-page anchors**: apply the core-message, typography-role, color, body-frame, density, and composition anchors from §2 while authoring. When `notes/total.md` was frozen, keep each page's segment in view so its visible state and direct-root groups support the spoken words without copying the script into body text.
**Canvas**: the §2 canvas — explicit user choice, otherwise the Layout/Deck owner's, otherwise `ppt169` `viewBox="0 0 1280 720"`; another registered format takes its exact viewBox from `canvas-formats.md`. Template canvas is a default, not a gate. The first SVG fixes the export canvas; every page matches it exactly. Filenames use one zero-padded width for the roster (`01_cover.svg``12_end.svg`, or three digits); never leave pages from another run in `svg_output/` — the exporter publishes everything it finds.
**Canvas**: the §2 canvas — explicit user choice, otherwise the Layout/Deck owner's, otherwise `ppt169` `viewBox="0 0 1280 720"`; another registered format takes its exact viewBox from `canvas-formats.md`. Template canvas is a default, not a gate. The first SVG fixes the export canvas; every page matches it exactly. Filenames use one zero-padded width for the roster (`01_cover.svg``12_end.svg`, or three digits). Never leave pages from another run in `svg_output/` — the exporter publishes everything it finds.
**PPTX structure**: speed never flattens template structure. Free design and Brand/Style-only author flat Slide-local SVG with one root `data-pptx-page-role` (`cover` / `toc` / `section` / `content` / `ending`) and no Master/Layout/layer/placeholder metadata. When Layout or Deck owns structure, every page is a complete structured Slide SVG that preserves or deliberately adapts the prototype's root identity, fixed layers, and slots with current content on top — all-or-none across the roster, every reused Layout repeating an identical fixed-layer/slot contract, a new Layout allowed under the selected Master when the application paragraph calls for adaptation, ownership never inferred from repeated geometry, and `data-pptx-page-role` omitted. A Style never strips structure; only an explicit instruction to use the workspace as visual language permits flat output.
**PPTX structure**: speed never flattens template structure.
**Typography**: name a concrete target-installed/approved family under `shared-standards-core.md` §4.1, never a lock or the host's fonts. Before P01 run `python3 ${SKILL_DIR}/scripts/text_measure.py calibrate <project_path> --role <name>:<family>:<size>` for every recurring role (one command, repeatable `--role`) and keep its table — CJK and Latin ≈ chars per 100 px per role, the checker's own estimator with wrapping headroom — in context; every later page sizes zones from that per-font arithmetic — write the sentence first, fit the zone to it, and never trim wording to satisfy an estimate; calibrate again only for a role or size never calibrated, and `wrap` only a genuinely long paragraph.
| Structure owner | Page form |
|---|---|
| Free design, Brand/Style-only | Flat Slide-local SVG with one root `data-pptx-page-role` (`cover` / `toc` / `section` / `content` / `ending`) and no Master/Layout/layer/placeholder metadata |
| Layout or Deck | Every page is a complete structured Slide SVG that preserves or deliberately adapts the prototype's root identity, fixed layers, and slots with current content on top — all-or-none across the roster, every reused Layout repeating an identical fixed-layer/slot contract, a new Layout allowed under the selected Master when the application paragraph calls for adaptation, ownership never inferred from repeated geometry, and `data-pptx-page-role` omitted |
**Generation pacing**: hand-write the roster in order — P01 calibrates visual identity and cover expression, the first ordinary content page calibrates content geometry and carrier integration, neither becomes a reusable template — with no confirmation stop. A resolved motif follows its reuse mode (exact repetition for deliberate chrome, adaptive variation of scale, crop, density, position, or interaction otherwise). When the planned roster has seven or more pages, run the §4 final-check command with `--stage early` after P05 and before P06, review its complete issue set, fix every error plus selected warnings in one consolidated pass, and verify once; six or fewer pages skip the early gate. After every page exists, run the one final checker below; every checker invocation follows a gate point (early or final, all covered pages written) or one consolidated repair pass — never a page in progress or an individual fix, and validating an authoring pattern early is not a reason. Use other stages only when their capability is needed.
A Style never strips structure; only an explicit instruction to use the workspace as visual language permits flat output.
**Hard rule — direct page authoring stays with the main agent**: write every page SVG in the active context; never delegate page generation or run a generator that writes slide files (fragment-only helpers remain allowed after the agent chooses role, operands, paint, and z-order). Resource, inspection, checker, verification, and export tools are unrestricted. This is not a resume protocol: if the context is lost before delivery, start a clean Quick run.
**Typography**: name a concrete target-installed/approved family under `shared-standards-core.md` §4.1, never a lock or the host's fonts. Before P01 run `python3 ${SKILL_DIR}/scripts/text_measure.py calibrate <project_path> --role <name>:<family>:<size>` for every recurring role (one command, repeatable `--role`) and keep its table — CJK and Latin ≈ chars per 100 px per role, the checker's own estimator with wrapping headroom — in context. Every later page sizes zones from that per-font arithmetic (a line mixing CJK with Latin words or digits adds the two parts: CJK chars ÷ CJK rate + other chars ÷ Latin rate, × 100): write the sentence first, fit the zone to it, and never trim wording to satisfy an estimate. Calibrate again only for a role or size never calibrated, and `wrap` only a genuinely long paragraph.
**Generation pacing (Mandatory)**: hand-write the roster in order with no confirmation stop. P01 calibrates visual identity and cover expression; the first ordinary content page calibrates content geometry and carrier integration; neither becomes a reusable template. A resolved motif follows its reuse mode (exact repetition for deliberate chrome, adaptive variation of scale, crop, density, position, or interaction otherwise).
**Cadence**: when the planned roster has seven or more pages, run the §4 final-check command with `--stage early` after P05 and before P06, repair under the consolidated-pass discipline of [`executor-base.md`](../../references/executor-base.md) §3, and continue; six or fewer pages skip the early gate. After every page exists, run the one final checker in §4. Every checker invocation follows a gate point (early or final, all covered pages written) or one consolidated repair pass; validating an authoring pattern early is not a reason. Use other stages only when their capability is needed.
**Hard rule — page authoring stays with the main agent** ([`executor-base.md`](../../references/executor-base.md) §3). This is not a resume protocol: if the context is lost before delivery, start a clean Quick run.
---
@@ -192,7 +205,9 @@ python3 ${SKILL_DIR}/scripts/svg_quality_checker.py <project_path> \
--quick-generate --canonical-authoring --stage final --json
```
**Mandatory — final carrier-receipt review**: compare the `[CARRIERS]` summary with the retained page jobs, deck shape language, motif, resource roles, and geometry signatures. Counts are not quotas; when the facts contradict an active decision — an adopted preset absent, a directional / step / flowchart relationship drawn as a hand path or polygon where `executor-base.md` §3.0 names a preset, a primary image reduced to a minor frame — read only the affected `files[].info.carrier_receipt` rows, repair those pages in one pass, and rerun the checker. **Absence needs a reason**: when the receipt shows a deck-wide zero — `Presets: (none)`, or `inline emphasis 0`, `gradients 0`, or `filters 0` on the `Effects:` line — or fewer pages carrying a preset or connector than pages whose transient relationship statement names `order` / `link` / `parent` / `membership` — or the `Presets:` line names no carrier-and-field contour — answer one line per absent family or per such page: what carries that job instead, and why it serves the reader better — for presets, one line per job the family serves, not for arrows alone: carrier and field (snipped or one-sided rounded rectangles, plaque, bevel, polygons, pie / arc / donut, frames, corners, folded corner, trapezoid, parallelogram, and `native-shape-authoring.md` §7 modelled forms), direction and sequence (arrows, chevrons, flow nodes), grouping and ownership (brackets, braces, frames, plaques), emphasis and annotation (callouts, badges, banners, stars). The style, speed, restraint, "text was enough", or "it is editable anyway" are not answers; a family or page without one is repaired where the page job calls for it, then the checker reruns. Choosing not to use a device is valid — only an unstated reason is not.
`--json` writes `validation/svg_quality_report.json`, the report `--quick-generate` export fingerprints against `svg_output/`; stdout stays the human-readable summary and is never parsed as JSON. Both flags above are required — omitting `--canonical-authoring` or `--json` makes the export refuse or skip the canonical check.
**Mandatory — final carrier-receipt review**: run the review in [`executor-base.md`](../../references/executor-base.md) §3 Checkpoints against the retained page jobs, deck shape language, motif, resource roles, and geometry signatures; a repair reruns this checker once.
**Notes** (when enabled): load [`executor-notes.md`](../../references/executor-notes.md) after the passing check, validate a frozen script or pre-SVG narration without regenerating it or otherwise generate `notes/total.md` from the final roster, then split:
@@ -202,26 +217,28 @@ python3 ${SKILL_DIR}/scripts/total_md_split.py <project_path>
**Success criterion**: per-slide files under `notes/` cover every published slide; the command exits non-zero on a missing slide or failed write — repair and rerun, and never let leftover files satisfy it.
**Motion and sound**: run [`customize-animations`](../stages/customize-animations.md) after the notes pass when the §1 outcome or an existing sidecar triggers it; deck-wide-only motion uses exporter flags. Quick video delivery completes the Custom Animations stage and validates `animations.json` before export unless the user asked for static or transition-only playback; direct narrated video derives cue timing only when narration governs groups. After motion is final, sync a selected cue per [`animations.md`](../../references/animations.md) §2.2 (no cue → no `sounds/`; never `templates/sounds/`); `generate-audio` completes narrated MP4 delivery through the verified native mix or an explicit slideshow capture, never both.
**Motion and sound**: run [`customize-animations`](../stages/customize-animations.md) after the notes pass when the §1 outcome or an existing sidecar triggers it; deck-wide-only motion uses exporter flags. Quick video delivery completes the Custom Animations stage and validates `animations.json` before export unless the user asked for static or transition-only playback; direct narrated video derives cue timing only when narration governs groups. After motion is final, run the optional sound pass in [`animations.md`](../../references/animations.md) §2.2. `generate-audio` completes narrated MP4 delivery through the verified native mix or an explicit slideshow capture, never both.
```bash
python3 ${SKILL_DIR}/scripts/svg_to_pptx.py <project_path> --quick-generate --with-notes # Speaker Notes enabled
python3 ${SKILL_DIR}/scripts/svg_to_pptx.py <project_path> --quick-generate --no-notes # Speaker Notes disabled
```
`--quick-generate` reads `svg_output/`, resolves project-local assets, infers one canvas and one all-page structure mode (no metadata → flat; complete Master/Layout/slot metadata → structured), and needs no lock. Notes, Custom Animations, and narration stay off unless the agent enabled them or the video rule requires them; append `--native-charts-and-tables` only for an explicit native Chart/Table delivery decision. Never run `finalize_svg.py`. The exporter requires a passing `final` report whose fingerprint matches the current `svg_output/`; the default output path keeps backup and postflight, an explicit `-o <path>.pptx` skips backup. On failure repair the owning SVG, resource, or capability input, rerun the checker, and export again — never create a Design Spec or lock. When Narration Audio is enabled, run [`generate-audio`](../stages/generate-audio.md) after the validated export (page audio/SRT, narrated PPTX, optional raw MP4, final mixed or captured MP4, or the capture-ready handoff).
**Exporter behavior**: `--quick-generate` reads `svg_output/`, resolves project-local assets, infers one canvas and one all-page structure mode (no metadata → flat; complete Master/Layout/slot metadata → structured), and needs no lock. Notes, Custom Animations, and narration stay off unless the agent enabled them or the video rule requires them; append `--native-charts-and-tables` only for an explicit native Chart/Table delivery decision. Never run `finalize_svg.py`. The exporter requires a passing `final` report whose fingerprint matches the current `svg_output/`; the default output path keeps backup and postflight, an explicit `-o <path>.pptx` skips backup.
**On failure**: repair the owning SVG, resource, or capability input, rerun the checker, and export again — never create a Design Spec or lock. When Narration Audio is enabled, run [`generate-audio`](../stages/generate-audio.md) after the validated export (page audio/SRT, narrated PPTX, optional raw MP4, final mixed or captured MP4, or the capture-ready handoff).
```markdown
## ✅ Quick Generate Complete
- [x] Source/resource preparation complete; the planning-capability batch and every selected detail source were read before the roster
- [x] The complete preset vocabulary was read before P01; each page resolved its Structure decision, geometry move, and carrier mix without a quota and compared its geometry signature before the next page
- [x] The complete preset vocabulary was read before P01; each page resolved its topology decision, geometry move, and carrier mix without a quota and compared its geometry signature before the next page
- [x] Image need was decided independently of credentials; every image decided its own source, every `slice_names` output exists after an exit-0 strict-alpha run, and every exhausted AI job was replanned under the no-AI rule with its disclosure retained
- [x] Every selected formula and hyperlink uses its checker-valid native form
- [x] The frozen Template Application paragraph was applied, every installed Layout/Deck SVG was read, and structure matches the installed capability (flat vs explicit all-page structured)
- [x] The early gate ran once after P05 on a roster of seven or more pages (or a shorter roster skipped it), and every checker invocation followed a gate point or one consolidated repair pass
- [x] The carrier receipt was compared with the retained page jobs and contradictions repaired; the lockless final report passes and matches the current SVGs
- [x] Enabled notes were validated/generated and split; enabled custom motion ran through its owning stage
- [x] The §1 motion gate was evaluated before P01 (the row hit, or none); enabled notes were validated/generated and split; enabled custom motion ran through its owning stage
- [x] One native PPTX exists under `exports/` or the explicit output path; no Strategist, confirmation, root Design Spec, or lock artifact was created
- [ ] **Next**: report the base PPTX and any narrated PPTX, MP4, or capture-ready handoff, plus the resolved mode, visual style, and image sources actually used; for every no-AI replan, report the affected job, attempted path, concrete error, replacement carrier, and that retaining AI imagery requires repairing generation capability and a new Quick run
```
@@ -22,13 +22,13 @@ Spec naming and kind declaration follow [`templates/README.md`](../../templates/
| `library` | The normalized root exactly equals `templates/<kind_dir>/<id>/` derived from an entry in that kind's `*_index.json` |
| `explicit` | The user or Create Template supplied an exact root not registered at that canonical index-derived root |
Read library choices only from the four `*_index.json` files; never scan kind directories or promote an unregistered directory into the catalog. The label changes discovery provenance only, never validation, precedence, or installation.
Library roots come from the four indexes ([`routing.md`](../routing.md) §7); the label changes discovery provenance only, never validation, precedence, or installation.
**Selection cardinality**: at most one root per kind; all four kinds may coexist. A multi-kind explicit root contributes all its specs atomically and combines only with non-overlapping kinds; reject duplicate kinds before validation.
**Hard rule — raw source boundary**: a raw PPTX is not a template workspace. Raw PPTX plus new content uses [`edit-native-pptx`](../edit-native-pptx.md); a reusable template request runs [`create-template`](../create-template.md) first, whose validated root becomes a Stage-1 candidate preselected only when it is the sole supplied root. Never add Master/Layout/placeholder structure directly to an existing PPTX or SVG project.
**Current-contract gate**: reject flat-root, semantic-legacy, or incomplete structured packages (old baseline/distillation metadata, incomplete Master identity, legacy direct atomic placeholders); create a new workspace through Create Template, from the original PPTX when native topology must be preserved.
**Current-contract gate**: reject a flat-root, semantic-legacy, or incomplete structured package under [`pptx-structure-interface.md`](../../references/pptx-structure-interface.md) §3; a new workspace comes from Create Template.
## 2. Read the Matching Schema
@@ -49,7 +49,7 @@ python3 skills/ppt-master/scripts/svg_quality_checker.py "<workspace_root>/templ
## 3. Structured Preflight
Before copying a Deck or Layout workspace (Brand and Style skip this), inspect every SVG root and slot: every page declares root Master/Layout keys and picker names; Master/Layout visuals are direct atoms, not layer `<g>` wrappers; every non-composite slot is a top-level `<g>` with positive bounds and exactly one compatible carrier; a composite region uses an explicit `object` proxy; zero-slot Layouts are valid; the contract is current — reject a legacy contract instead of repairing it in the target project.
Before copying a Deck or Layout workspace (Brand and Style skip this), inspect every SVG root and slot against [`pptx-structure-interface.md`](../../references/pptx-structure-interface.md) §2, and reject a legacy contract (§3) instead of repairing it in the target project.
## 4. Install Each Distinct Root Once
@@ -80,15 +80,15 @@ After any regrouping, rerun the final gate (`svg_quality_checker.py <project_pat
### 3.1 Supported Page Transitions
One of the 48 canonical native effects in `animations.md` §3 (the complete Subtle, Exciting, and Dynamic Content gallery); the eight old names are compatibility inputs only and normalize to a canonical effect plus `effect_options`; `none` removes the visual effect while timed advance remains. Fields: `effect`; `effect_options` (only the selected effect's native options run `pptx_animations.py --describe-transition <effect>` first and never infer another effect's fields); `duration` (> 0 s); `auto_advance` (non-negative seconds, click still enabled, valid with `effect: none`); `sound` (project-relative `.wav`, selected only after the transition is resolved). For a cross-slide continuation that must not depend on PowerPoint's automatic matching, put one `morph` block on the destination whose `from` is the immediately preceding SVG and whose pair keys bind one source direct-root group to one destination group (the exporter supplies `!!`); Morph by object only.
One of the 48 canonical native effects in [`animations.md`](../../references/animations.md) §3 (`pptx_animations.py --list`); old names are compatibility inputs only. Fields `effect`, `effect_options` (only the selected effect's native options: run `pptx_animations.py --describe-transition <effect>` first), `duration`, `auto_advance`, `sound` — follow [`pptx-animations.md`](../../scripts/docs/pptx-animations.md) §8. A cross-slide continuation that must not depend on PowerPoint's automatic matching declares one `morph` block on the destination ([`animations.md`](../../references/animations.md) §2.1).
### 3.2 Supported In-Slide Animations
The 203 canonical keys — 53 `entrance_*`, 33 `emphasis_*`, 64 `path_*`, 53 `exit_*` (`pptx_animations.py --list`), each preserving PowerPoint's complete behavior tree. `auto` / `mixed` / `random` apply to generic `enter` only (`auto` maps roles to canonical entrances with a richer pool for image-like ids; `mixed` cycles 16 presets by group order; `random` selects deterministically from the same pool) and never choose emphasis, path, or exit implicitly; `none` excludes the object or slide. The 29 old short names are compatibility inputs (Fly/Wipe directions → `entrance_fly` / `entrance_wipe` with `effect_options.direction`, `cut``entrance_appear`, legacy `wheel` keeps its four-spoke amount). **Hard rule — explicit semantic choreography**: when a plan depends on a specific lifecycle, relationship, or order, target real groups with explicit canonical effects and order; generic modes are valid only when generic entrance treatment suffices. Start modes: `after-previous` (click-free cascade), `with-previous` (one coordinated beat), `on-click` (controlled reveal).
The 203 canonical keys of [`animations.md`](../../references/animations.md) §4 (`pptx_animations.py --list`); `auto` / `mixed` / `random` supply generic entrances only and never choose emphasis, path, or exit. **Hard rule — explicit semantic choreography**: when a plan depends on a specific lifecycle, relationship, or order, target real groups with explicit canonical effects and order; generic modes are valid only when generic entrance treatment suffices. Start modes: `after-previous` (click-free cascade), `with-previous` (one coordinated beat), `on-click` (controlled reveal).
### 3.3 Optional Sound Pass
Only after visual transition, lifecycle, effect, order, and timing are complete; sound is post-processing state never written to or recovered from the Design Spec or lock. No resolved cue → omit every `sound` field and create no `sounds/`. A bundled cue fits one resolved row → read the complete [`sound-vocabulary.md`](../../templates/sounds/sound-vocabulary.md), choose from the auditory job, then sync only the selected ids (`sound_sync.py list --query <term>` for optional filtering; `sound_sync.py <project_path> <namespace>/<sound_id> ...`) and reference `sounds/<namespace>/<file>.wav` in `transition.sound`, `animation.sound`, or the group/effect row. User-provided audio in the project uses its own path when the format is valid. Never reference `skills/ppt-master/templates/sounds/` from `animations.json`; the global library is a selection source, not an exporter fallback. Gain, limiting, and video mixing belong to [`generate-audio`](./generate-audio.md), never this sidecar.
Only after visual transition, lifecycle, effect, order, and timing are complete, run the optional sound pass in [`animations.md`](../../references/animations.md) §2.2; the selected project-relative `.wav` goes in `transition.sound`, `animation.sound`, or the group/effect row, and user-provided audio in the project uses its own path when the format is valid. Gain, limiting, and video mixing belong to [`generate-audio`](./generate-audio.md), never this sidecar.
---
@@ -96,7 +96,7 @@ Only after visual transition, lifecycle, effect, order, and timing are complete;
**Hard rule — sparse overrides reference real targets**: write only affected slides and only fields that differ from exporter or sidecar defaults; an unlisted SVG inherits deck-wide settings; a listed slide carries only the `transition`, `animation`, `groups`, or `morph` fields it overrides; `defaults` is optional and deck-wide only; chrome groups stay out (the exporter pins them to `none`), and a legacy chrome-like id is named only on explicit reviewed intent with no structural marker. **Forbidden**: a slide absent from `svg_output/`; a missing, ambiguous, or structural group; enumerating every group to restate the slide default; listing a group with `data-pptx-layer` or a static role/placeholder marker; animation `data-*` attributes in SVG.
**Hard rule — one group representation**: a populated `groups.<id>` uses either the legacy single-effect fields or `effects[]` (non-empty, every row naming `effect`), never both; an untouched scaffold `{}` is neutral; omitted row duration, Start, timing/completion controls, and sound inherit the resolved slide values. `effect_options` may hold `direction`, `amount`, `color`, `font_name`, `relative`, or `size`, but only fields the selected effect supports — run `pptx_animations.py --describe <canonical_effect>` before writing a parameterized effect; `duration` owns Speed and `accelerate` / `decelerate` own smooth start/end (no duplicate fields); Change Font's `font_name` is one target-installed face, never a CSS stack. The complete field reference — transition, morph, slide animation defaults, per-row trigger, order, delay, duration, `trigger_shape`, repeat, reverse/rewind, timing ratios, restart, after-effect, sound — is [`pptx-animations.md`](../../scripts/docs/pptx-animations.md) §8. Use the multi-category `effects[]` example in `animations.md` §2 and the two-slide Morph example in §2.1 (never copy the source group into the destination `groups` to establish identity); keep the legacy object for one-row overrides and never convert old sidecars mechanically.
**Hard rule — one group representation**: a populated `groups.<id>` uses either the legacy single-effect fields or `effects[]`, never both; an untouched scaffold `{}` is neutral; omitted row values inherit the resolved slide values. Every field, its range, and its inheritance are [`pptx-animations.md`](../../scripts/docs/pptx-animations.md) §8; run `pptx_animations.py --describe <canonical_effect>` before writing a parameterized effect, and give Change Font one target-installed face, never a CSS stack. Use the multi-category `effects[]` example in `animations.md` §2 and the two-slide Morph example in §2.1 (never copy the source group into the destination `groups` to establish identity); keep the legacy object for one-row overrides and never convert old sidecars mechanically.
---
@@ -104,7 +104,7 @@ Only after visual transition, lifecycle, effect, order, and timing are complete;
When `animations.json` was created or changed after §1, run `python3 skills/ppt-master/scripts/animation_config.py validate <project_path>`, then return to the owning export path — Default [`generate-pptx.md`](../generate-pptx.md) Step 7.1; Quick [`quick-generate.md`](../profiles/quick-generate.md) §4 — both of which read the sidecar automatically. If §2 changed `svg_output/`, complete the owning route's final SVG rerun before returning; never finalize or export from this stage.
**Validation**: unknown effects/modes/triggers; unsupported options; incompatible, boolean, non-finite, or out-of-range timing; non-positive durations; negative delay/stagger; invalid order; missing slides/groups; structural targets; and Morph pairs with non-adjacent sources, missing or ambiguous groups, conflicting or undeclared keys, non-object Morph, or a target that does not remain one compatible Slide-local object all fail — never replaced by a fallback or silently dropped. `--animation none` still disables all per-element animation. A passing sidecar, timing-tree read-back, and sound relationship check prove the PPTX configuration, not an exported MP4 audio track. Step 7 export reads back row order, trigger, target, effect, duration, offset, placement, IDs, and shape references; narration preserves them; direct-PPTX routes preserve source animation and never author it.
**Validation**: every invalid field, target, or Morph pair fails rather than falling back ([`pptx-animations.md`](../../scripts/docs/pptx-animations.md) §6). A passing sidecar and read-back prove the PPTX configuration, not an exported MP4 audio track.
### 5.1 Optional Video Motion Handoff
@@ -40,7 +40,7 @@ python3 skills/ppt-master/scripts/visualization_recall.py validate <family/key>
python3 skills/ppt-master/scripts/visualization_recall.py validate --legacy-bare <legacy-key> [...]
```
Then continue the documented Step 67 pipeline exactly as `generate-pptx.md` lists it: read the frozen `notes/total.md` once when §X declares a final/literal script; when mid-deck, read the latest completed SVG and current image metadata after their paths are verified; read the Step 6 construction core and one locked preset file or only the exact `*_references` of a custom, never reopening the mode or visual-style catalogs; load only the branches the condition table selects; make the per-page Structure decision from retained §IX before any geometry; when structured, read the template Design Spec and each selected prototype once. Use `page-context` only for explicit diagnostics or an unresolved path-SHA question ([`artifact-ownership.md`](../../references/artifact-ownership.md) §1), never as a routine pre-page load. Then the quality gate, conditional notes, conditional custom animation, Step 7 (`total_md_split``finalize_svg``svg_to_pptx`; disabled notes use `--no-notes`), and `generate-audio` when Narration Audio is enabled.
Then continue the documented Step 67 pipeline exactly as `generate-pptx.md` lists it: read the frozen `notes/total.md` once when §X declares a final/literal script; when mid-deck, read the latest completed SVG and current image metadata after their paths are verified; read the Step 6 construction core and one locked preset file or only the exact `*_references` of a custom, never reopening the mode or visual-style catalogs; load only the branches the condition table selects; make the per-page topology decision from retained §IX before any geometry; when structured, read the template Design Spec and each selected prototype once. Use `page-context` only for explicit diagnostics or an unresolved path-SHA question ([`artifact-ownership.md`](../../references/artifact-ownership.md) §1), never as a routine pre-page load. Then the quality gate, conditional notes, conditional custom animation, Step 7 (`total_md_split``finalize_svg``svg_to_pptx`; disabled notes use `--no-notes`), and `generate-audio` when Narration Audio is enabled.
A newer explicit instruction after final Stage 2 updates only its effective outcome and provenance in `design_spec.md §I`, then resumes at the owning step — no Confirm UI, no lock entry; apply Generate's notes/audio dependency gate before writing and its sidecar suppression rules at export.
@@ -2,8 +2,8 @@
"sourceId": "shadcn",
"repo": "https://github.com/shadcn-ui/ui.git",
"ref": "main",
"commit": "63c1308d112b6b1205d86244a156cca1abef5087",
"commit": "b2a1ec864a87ba66c63fc4e51c9223c7eb4f8335",
"adapter": "claude-skill",
"sourcePath": "skills/shadcn",
"syncedAt": "2026-08-31T16:00:00Z"
"syncedAt": "2026-09-02T10:37:18Z"
}
@@ -1,6 +1,7 @@
# [UI UX Pro Max](https://uupm.cc)
<p align="center">
<a href="https://github.com/nextlevelbuilder/ui-ux-pro-max-skill/blob/main/README.id.md">🇮🇩 Bahasa Indonesia</a> |
<a href="https://github.com/nextlevelbuilder/ui-ux-pro-max-skill/blob/main/README.ko.md">🇰🇷 한국어</a> |
<a href="https://github.com/nextlevelbuilder/ui-ux-pro-max-skill/blob/main/README.vi.md">🇻🇳 Tiếng Việt</a> |
<a href="https://github.com/nextlevelbuilder/ui-ux-pro-max-skill/blob/main/README.zh.md">🇨🇳 简体中文</a> |
@@ -2,8 +2,8 @@
"sourceId": "ui-ux-pro-max",
"repo": "https://github.com/nextlevelbuilder/ui-ux-pro-max-skill.git",
"ref": "main",
"commit": "f23267105ad1f4ccd94af45d382584ad45b586f7",
"commit": "e2effd57755d580318cce65ea1b2f98d896d5d40",
"adapter": "claude-skill",
"sourcePath": ".claude/skills/ui-ux-pro-max",
"syncedAt": "2026-09-01T16:00:00Z"
"syncedAt": "2026-09-02T10:37:18Z"
}
@@ -24,16 +24,16 @@
},
"snapshots": {
"google-fonts.csv": {
"sha256": "d03194d2c35a2cdc4c6846ddde9beb54fdd1f81a3ddc80fead3c0ba2842b75fb"
"sha256": "1c8c3b2ea1faf6a1012da463756def8b3889db33f2226f0343bb4daa80307d03"
},
"google-font-licenses.json": {
"sha256": "7c35e410dd8b5853ca86c3e0e3d3cfb73db1ffa3d9a2fa688c182bc44cd9a8d7"
"sha256": "35688523f2955795caa1a47c53b83099e60c1708461476f9cc3a050cf3b0148a"
},
"icons.csv": {
"sha256": "272ccf0eb60e50ba7af55de3ef5c195d92e1862d411b6cb80d81dec4fe56deee"
"sha256": "50816c6012030178195a16ee481ebf58b47bd985d70e8ec58886cc83f6eddafc"
},
"phosphor-icons-upstream.json": {
"sha256": "81c37fb3583eb43a91e93f1a62c4da3b4ff089624c06bfe53950b8205b54974d"
"sha256": "2399325233b277b5c97a80e6a5e8941154f5d057beee4e7613db87c87d700236"
}
},
"promotionPolicy": {
@@ -0,0 +1,78 @@
#!/usr/bin/env python3
"""The catalog snapshot must not depend on the checkout's line endings.
Regression test for bd19ab9 (#462), where catalog-summary.json was regenerated
on a CRLF checkout. Every recorded sha256 was the CRLF hash of the source file,
so `verify:data` failed on every LF platform, including CI.
"""
import hashlib
import importlib.util
import json
import shutil
import tempfile
import unittest
from pathlib import Path
REPO = next(
parent for parent in Path(__file__).resolve().parents
if (parent / "scripts" / "generate-catalog-summary.py").is_file()
)
DATA = REPO / "src/ui-ux-pro-max/data"
SNAPSHOT_FILES = (
"google-fonts.csv",
"google-font-licenses.json",
"icons.csv",
"phosphor-icons-upstream.json",
)
def _load_generator():
path = REPO / "scripts" / "generate-catalog-summary.py"
spec = importlib.util.spec_from_file_location("generate_catalog_summary", path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
class CatalogSummaryLineEndingsTest(unittest.TestCase):
def test_digest_is_identical_for_lf_and_crlf(self):
digest = _load_generator().digest
with tempfile.TemporaryDirectory() as tmp:
lf = Path(tmp) / "lf.csv"
crlf = Path(tmp) / "crlf.csv"
lf.write_bytes(b"id,name\n1,alpha\n2,beta\n")
crlf.write_bytes(b"id,name\r\n1,alpha\r\n2,beta\r\n")
self.assertEqual(
digest(lf), digest(crlf),
"snapshot hashes must not change with the checkout's line endings",
)
def test_committed_snapshot_matches_normalized_sources(self):
summary = json.loads((DATA / "catalog-summary.json").read_text(encoding="utf-8"))
for name in SNAPSHOT_FILES:
expected = hashlib.sha256(
(DATA / name).read_bytes().replace(b"\r\n", b"\n")
).hexdigest()
self.assertEqual(
summary["snapshots"][name]["sha256"], expected,
f"{name}: committed snapshot hash does not match the LF-normalized source",
)
def test_crlf_checkout_produces_the_committed_hashes(self):
"""Simulate a Windows checkout: the recorded hashes must still validate."""
digest = _load_generator().digest
summary = json.loads((DATA / "catalog-summary.json").read_text(encoding="utf-8"))
with tempfile.TemporaryDirectory() as tmp:
for name in SNAPSHOT_FILES:
crlf_copy = Path(tmp) / name
raw = (DATA / name).read_bytes().replace(b"\r\n", b"\n")
crlf_copy.write_bytes(raw.replace(b"\n", b"\r\n"))
self.assertEqual(
digest(crlf_copy), summary["snapshots"][name]["sha256"],
f"{name}: a CRLF checkout would record a different hash",
)
if __name__ == "__main__":
unittest.main()
@@ -663,7 +663,11 @@ def _check_catalog_summary(summary, licenses, phosphor, problems):
problems.append(f"[catalog:summary] stale count for {key}")
snapshots = summary.get("snapshots") if isinstance(summary.get("snapshots"), dict) else {}
for name in ("google-fonts.csv", "google-font-licenses.json", "icons.csv", "phosphor-icons-upstream.json"):
digest = hashlib.sha256((DATA_DIR / name).read_bytes()).hexdigest()
# Line endings are normalized so the check matches
# generate-catalog-summary.py on CRLF checkouts too.
digest = hashlib.sha256(
(DATA_DIR / name).read_bytes().replace(b"\r\n", b"\n")
).hexdigest()
if snapshots.get(name) != {"sha256": digest}:
problems.append(f"[catalog:summary] stale snapshot for {name}")
policy = summary.get("promotionPolicy")
@@ -0,0 +1,37 @@
{
"name": "updating-gitea-repositories",
"version": "0.1.0",
"description": "通过 HTTPS、Git Credential Manager 和 PAT 安全更新 Gitea 仓库",
"author": {
"name": "Eapil"
},
"homepage": "https://git.playones.com/huzhifa/skill-git-push",
"repository": "https://git.playones.com/huzhifa/skill-git-push.git",
"keywords": [
"gitea",
"git",
"gcm",
"pat",
"repository"
],
"skills": "./skills/",
"interface": {
"displayName": "Gitea 仓库安全更新",
"shortDescription": "通过 GCM 和 PAT 安全提交并验证 Gitea 仓库更新。",
"longDescription": "在 macOS、Windows 和 WSL 中检查或安装 Git Credential Manager,安全处理 Gitea PAT,精确暂存目标变更,并在 HTTPS 推送后验证远程提交。",
"developerName": "Eapil",
"category": "Developer Tools",
"capabilities": [
"Write"
],
"defaultPrompt": [
"使用 Gitea 仓库安全更新来发布准备好的仓库变更。",
"使用 Gitea 仓库安全更新检查凭据配置并验证远程提交。"
],
"websiteURL": "https://git.playones.com/huzhifa/skill-git-push",
"privacyPolicyURL": "https://git.playones.com/huzhifa/skill-git-push",
"termsOfServiceURL": "https://git.playones.com/huzhifa/skill-git-push",
"brandColor": "#2563EB"
},
"license": "UNKNOWN"
}
@@ -0,0 +1,9 @@
{
"sourceId": "updating-gitea-repositories",
"repo": "https://git.playones.com/huzhifa/skill-git-push.git",
"ref": "main",
"commit": "72c856975eaa340b023eb5393d958ca0bff1f59c",
"adapter": "codex-plugin",
"sourcePath": ".",
"syncedAt": "2026-09-02T10:37:18Z"
}
@@ -0,0 +1,55 @@
---
name: updating-gitea-repositories
description: "用于通过 HTTPS、Git Credential Manager 和 PAT 在 macOS、Windows 或 WSL 中安全发布和更新 Gitea 仓库,并在推送后验证远程提交。"
---
# Updating Gitea Repositories
## Purpose
Publish only the intended changes to a Gitea repository through HTTPS, Git Credential Manager (GCM), and a least-privilege Personal Access Token (PAT). Preserve existing work, keep secrets out of commands and logs, and verify the remote commit after every push.
## Required Reading
1. Always read [repository workflow](references/repository-workflow.md).
2. On macOS, also read [macOS GCM setup](references/macos.md).
3. On native Windows or WSL, also read [Windows GCM setup](references/windows.md).
## Core Contract
- Require a clean Gitea HTTPS URL, exact prepared source paths, intended repository paths, target branch, and commit intent. Infer only what the active task makes unambiguous.
- Verify GCM by executing its version command. When it succeeds, reuse that installation without install, reinstall, or upgrade actions. Install only when no working GCM exists; repair only when installation records exist but the executable does not.
- The user creates a Gitea PAT with `write:repository`. The user enters the Gitea login and PAT only in a local GCM prompt. Never request or expose a PAT in chat, URLs, environment variables, command arguments, logs, or files.
- Preserve unrelated work. Stage only exact task paths; never use unscoped `git add .` or `git add -A`.
- Before committing, set the user-confirmed identity only in the target repository:
```bash
git config --local user.name "<confirmed-name>"
git config --local user.email "<confirmed-id>@eapil.com"
```
- Never bypass TLS, branch protection, hooks, validation, or non-fast-forward safety. Never force-push as recovery.
- Report success only after fetching the pushed branch and matching its remote SHA to local `HEAD`.
## Quick Decisions
| State | Action |
|---|---|
| GCM version works | Reuse it unchanged |
| Installer record exists but command fails | Repair or reinstall GCM |
| HTTPS remote has no refs | Initialize the confirmed default branch |
| Remote has history | Clone or fetch before writing |
| Dirty changes overlap task paths | Stop or use a clean clone/worktree |
| Default branch rejects normal push | Push a task branch for review |
## Example Invocation
> Use `$updating-gitea-repositories` to publish the prepared skill to `https://gitea.example.com/team/skill-repo.git`, targeting `skills/updating-gitea-repositories` on `main`.
## Common Mistakes
- Trusting package-manager state instead of running the GCM version command.
- Treating a PAT as ordinary text.
- Staging the whole worktree for a narrow update.
- Treating push rejection as permission to force-push.
- Reporting the local commit without remote SHA verification.
@@ -0,0 +1,4 @@
interface:
display_name: "Updating Gitea Repositories"
short_description: "通过 HTTPS、GCM 和 PAT 安全更新 Gitea 仓库"
default_prompt: "Use $updating-gitea-repositories to publish prepared changes to this Gitea HTTPS repository."
@@ -0,0 +1,59 @@
# macOS GCM Setup
Use this reference only on macOS.
## Verify
```bash
git --version
git-credential-manager --version
git config --show-origin --get-all credential.helper
```
Treat `command not found` as missing or broken even when Homebrew says the cask is installed.
If the version command succeeds, GCM is already available. Do not run Homebrew install, reinstall, or upgrade commands; continue to configuration and repository work.
## Install or Repair
Run the preferred installation only when the version command confirms that no working GCM exists:
```bash
brew install --cask git-credential-manager
```
If Homebrew records the cask but the command is unavailable:
```bash
brew reinstall --cask git-credential-manager
git-credential-manager --version
```
The package installer may require a macOS administrator password. Never ask the user to send that password. Have the user enter it in their own terminal or the macOS installer. If installation cannot be completed, stop rather than silently switching away from GCM.
If reinstall succeeds but the shell still cannot find the command, start a new shell and check:
```bash
command -v git-credential-manager
ls -l /usr/local/share/gcm-core/git-credential-manager
```
Use the reported installed path to diagnose PATH configuration; do not create speculative symlinks.
## Configure
```bash
git-credential-manager configure
git config --global --get-all credential.helper
```
GCM uses the macOS Keychain as its default secure credential store. Remove a repository-local helper override only after inspecting its origin and confirming it conflicts with GCM:
```bash
git config --show-origin --get-all credential.helper
git config --local --unset-all credential.helper
```
Do not replace GCM with `osxkeychain` when the requested workflow is standardized on GCM.
Official references: [GCM installation](https://github.com/git-ecosystem/git-credential-manager/blob/main/docs/install.md) and [credential stores](https://github.com/git-ecosystem/git-credential-manager/blob/main/docs/credstores.md).
@@ -0,0 +1,63 @@
# Repository Update Workflow
Read this reference for every Gitea repository update.
## 1. Resolve Inputs
Identify the clean Gitea HTTPS URL, prepared source paths, repository target paths, target branch, and commit intent. If a source-to-target mapping is ambiguous, stop and ask before writing.
## 2. Inspect Before Editing
Read applicable `AGENTS.md` and `CONTRIBUTING*`. Inspect the repository root, current branch, `git status`, staged diff, remotes, recent history, and remote refs. Do not print a remote URL that may contain credentials; reject URLs with embedded user information.
Verify GCM using the active platform reference. A successful version command means reuse the existing installation without installing or upgrading it. Configure GCM only when its helper is absent or conflicting.
The user creates a Gitea PAT with `write:repository` and enters the Gitea login plus PAT only in the local GCM prompt. The account must already have repository write access.
## 3. Choose the Repository Path
- Existing clone: `git fetch --prune` first; do not merge automatically.
- Existing remote without a clone: clone the target branch before copying prepared files.
- Empty remote: only after `git ls-remote` succeeds with no refs, initialize the confirmed default branch, normally `main`, and add the clean HTTPS remote.
- Dirty clone: preserve unrelated changes. If they overlap task paths or prevent a safe update, use a fresh clone or isolated worktree based on the latest remote branch.
Do not use force, reset, clean, stash, or destructive checkout as a shortcut.
## 4. Prepare and Validate the Commit
Set the user-confirmed Eapil identity only in the target repository:
```bash
git config --local user.name "<confirmed-name>"
git config --local user.email "<confirmed-id>@eapil.com"
```
Copy or edit only the intended paths. Stage with an explicit pathspec:
```bash
git add -- <path-1> <path-2>
git diff --cached --name-status
git diff --cached --stat
git diff --cached --check
git diff --cached
```
Confirm every staged path is in scope, deletions are intentional, no secret or transient file is present, and repository-required tests pass. If there is no staged change, report that the remote already contains the prepared content instead of creating an empty commit, unless the user explicitly requested an empty commit.
## 5. Commit, Push, and Verify
Commit with an intent-based message. Re-fetch before pushing when the remote may have advanced. Push normally to the target branch. If the default branch is protected, push a task branch and report that review or merge is required. Do not use `--force`, `--force-with-lease`, `--no-verify`, or TLS bypasses.
After a successful push, fetch the pushed branch and compare:
```bash
git rev-parse HEAD
git rev-parse "origin/<pushed-branch>"
git ls-remote origin "refs/heads/<pushed-branch>"
```
Report completion only when the local and remote SHAs match. Include the repository, branch, commit SHA and subject, exact changed paths, validation performed, and remaining user action.
## Stop Conditions
Stop on ambiguous paths, missing Git identity, authentication or TLS failure, insufficient account/PAT permissions, unexpected staged files, validation failure, overlapping user changes, non-fast-forward history requiring judgment, protected-branch rejection, server-hook rejection, or a request to overwrite remote history.

Some files were not shown because too many files have changed in this diff Show More