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-08-21 14:43:26 +08:00
parent 2d4895bba6
commit dc35e1cbf3
55 changed files with 1299 additions and 421 deletions
+10 -10
View File
@@ -15,8 +15,8 @@
"repo": "https://github.com/AreChen/superpowers-zh.git", "repo": "https://github.com/AreChen/superpowers-zh.git",
"ref": "main", "ref": "main",
"adapter": "codex-plugin", "adapter": "codex-plugin",
"commit": "e1f21a28e5a32b94d35fdaaa98e298ef73260545", "commit": "e6ae7ddf5da1b5f7ec0388ce053c894d23a64857",
"syncedAt": "2026-07-24T06:18:20Z" "syncedAt": "2026-08-21T06:41:32Z"
}, },
{ {
"id": "oh-my-codex", "id": "oh-my-codex",
@@ -42,8 +42,8 @@
"repo": "https://github.com/JuliusBrussee/caveman.git", "repo": "https://github.com/JuliusBrussee/caveman.git",
"ref": "main", "ref": "main",
"adapter": "codex-plugin", "adapter": "codex-plugin",
"commit": "a42ef766cedef6160407418a359a52939b2d20b9", "commit": "2f49f0e1a352aa810e70056b7930aeb0b3d219b4",
"syncedAt": "2026-08-20T16:00:00Z" "syncedAt": "2026-08-21T06:41:32Z"
}, },
{ {
"id": "taste-skill", "id": "taste-skill",
@@ -60,8 +60,8 @@
"repo": "https://github.com/shadcn-ui/ui.git", "repo": "https://github.com/shadcn-ui/ui.git",
"ref": "main", "ref": "main",
"adapter": "claude-skill", "adapter": "claude-skill",
"commit": "4e88ab81ae1d1550165db949a903c691a04f699c", "commit": "19b67204fb80b7a7c233c967e4cf3aed73810f80",
"syncedAt": "2026-08-20T16:00:00Z" "syncedAt": "2026-08-21T06:41:32Z"
}, },
{ {
"id": "frontend-slides", "id": "frontend-slides",
@@ -96,8 +96,8 @@
"repo": "https://github.com/hugohe3/ppt-master.git", "repo": "https://github.com/hugohe3/ppt-master.git",
"ref": "main", "ref": "main",
"adapter": "claude-skill", "adapter": "claude-skill",
"commit": "fe9ae086ab33d5a384f691ffd432aeb04ba0f96f", "commit": "fb6e5ac969bb066f1f6fa5dcd14349f0813e9e7a",
"syncedAt": "2026-08-20T16:00:00Z" "syncedAt": "2026-08-21T06:41:32Z"
}, },
{ {
"id": "grill-me", "id": "grill-me",
@@ -114,8 +114,8 @@
"repo": "https://github.com/vercel/next.js.git", "repo": "https://github.com/vercel/next.js.git",
"ref": "canary", "ref": "canary",
"adapter": "skill-collection", "adapter": "skill-collection",
"commit": "605425e139855c2664732bb814d0447512c05d00", "commit": "14a69ef78b94c9bdb68b2f1d5d1a55599ff8022c",
"syncedAt": "2026-08-20T16:00:00Z" "syncedAt": "2026-08-21T06:41:32Z"
} }
] ]
} }
@@ -2,8 +2,8 @@
"sourceId": "caveman", "sourceId": "caveman",
"repo": "https://github.com/JuliusBrussee/caveman.git", "repo": "https://github.com/JuliusBrussee/caveman.git",
"ref": "main", "ref": "main",
"commit": "a42ef766cedef6160407418a359a52939b2d20b9", "commit": "2f49f0e1a352aa810e70056b7930aeb0b3d219b4",
"adapter": "codex-plugin", "adapter": "codex-plugin",
"sourcePath": "plugins/caveman", "sourcePath": "plugins/caveman",
"syncedAt": "2026-08-20T16:00:00Z" "syncedAt": "2026-08-21T06:41:32Z"
} }
@@ -3,5 +3,5 @@
"name": "playwright浏览器自动化操作", "name": "playwright浏览器自动化操作",
"version": "20260605", "version": "20260605",
"keySource": "none", "keySource": "none",
"syncedAt": "2026-08-20T16:01:54Z" "syncedAt": "2026-08-21T06:43:26Z"
} }
@@ -2,8 +2,8 @@
"sourceId": "next-skills", "sourceId": "next-skills",
"repo": "https://github.com/vercel/next.js.git", "repo": "https://github.com/vercel/next.js.git",
"ref": "canary", "ref": "canary",
"commit": "605425e139855c2664732bb814d0447512c05d00", "commit": "14a69ef78b94c9bdb68b2f1d5d1a55599ff8022c",
"adapter": "skill-collection", "adapter": "skill-collection",
"sourcePath": "skills", "sourcePath": "skills",
"syncedAt": "2026-08-20T16:00:00Z" "syncedAt": "2026-08-21T06:41:32Z"
} }
@@ -2,8 +2,8 @@
"sourceId": "ppt-master", "sourceId": "ppt-master",
"repo": "https://github.com/hugohe3/ppt-master.git", "repo": "https://github.com/hugohe3/ppt-master.git",
"ref": "main", "ref": "main",
"commit": "fe9ae086ab33d5a384f691ffd432aeb04ba0f96f", "commit": "fb6e5ac969bb066f1f6fa5dcd14349f0813e9e7a",
"adapter": "claude-skill", "adapter": "claude-skill",
"sourcePath": "skills/ppt-master", "sourcePath": "skills/ppt-master",
"syncedAt": "2026-08-20T16:00:00Z" "syncedAt": "2026-08-21T06:41:32Z"
} }
@@ -43,7 +43,7 @@ history, or resumable planning state. Context loss restarts the Quick run.
| `images/image_prompts.json`, `image_queries.json`, `image_sources.json` | Conditional resource contracts | AI/web execution status and provenance | Create only for a triggered path, including Quick. They guide preparation/attribution, never page design. | | `images/image_prompts.json`, `image_queries.json`, `image_sources.json` | Conditional resource contracts | AI/web execution status and provenance | Create only for a triggered path, including Quick. They guide preparation/attribution, never page design. |
| `icons/` | Prepared project icon pool | Bundled icons copied by `icon_sync.py` plus user-provided, template, imported, or custom icon SVGs | SVG authoring may choose any icon in this project-local pool per page; `spec_lock.icons.inventory` indexes the default plan's curated synced bundled pool rather than assigning page usage or defining an exhaustive whitelist. Exporter global fallback is legacy compatibility only. | | `icons/` | Prepared project icon pool | Bundled icons copied by `icon_sync.py` plus user-provided, template, imported, or custom icon SVGs | SVG authoring may choose any icon in this project-local pool per page; `spec_lock.icons.inventory` indexes the default plan's curated synced bundled pool rather than assigning page usage or defining an exhaustive whitelist. Exporter global fallback is legacy compatibility only. |
| `${SKILL_DIR}/templates/{brands,styles,layouts,decks}/*_index.json` | Library discovery indexes | The complete registered option source for Default Stage-1 template selection and chat listing | The UI server or chat branch reads these indexes only to populate the Stage-1 choice, after the communication recommendation is authored. Never scan kind directories to add options or use index summaries as Stage-1 planning evidence. Derive a library root from kind + entry id. Exact unregistered roots remain explicit inputs. Quick does not read the catalog. | | `${SKILL_DIR}/templates/{brands,styles,layouts,decks}/*_index.json` | Library discovery indexes | The complete registered option source for Default Stage-1 template selection and chat listing | The UI server or chat branch reads these indexes only to populate the Stage-1 choice, after the communication recommendation is authored. Never scan kind directories to add options or use index summaries as Stage-1 planning evidence. Derive a library root from kind + entry id. Exact unregistered roots remain explicit inputs. Quick does not read the catalog. |
| `templates/` | Project template reference | Stage-1-confirmed non-free selection or Quick direct-input installed specs, one file per selected workspace, optional Layout/Deck SVG prototypes, and non-image assets | Default template-aware Strategist work from Stage 2 onward, Quick's current agent before direct authoring, and every later role read this project-local state only, never the library/external installation root. The active planner reads every installed template Design Spec and an actual SVG roster only for Layout/Deck; Brand and Style are intentionally roster-free. Continuous Executor reuses that context; fresh Executor reads the Design Spec once and each selected complete SVG, when any, only before first use or after its SHA changes. | | `templates/` | Project template reference | Stage-1-confirmed non-free selection or Quick direct-input installed specs, one file per selected workspace, the effective structural SVG roster (Layout when present, otherwise Deck), and non-image assets | Default template-aware Strategist work from Stage 2 onward, Quick's current agent before direct authoring, and every later role read this project-local state only, never the library/external installation root. The active planner reads every installed template Design Spec and the effective structural SVG roster; Brand and Style are intentionally roster-free, and Deck structure is shadowed when Layout is present. Continuous Executor reuses that context; fresh Executor reads the Design Spec once and each selected complete SVG, when any, only before first use or after its SHA changes. |
| `templates/template_execution_manifest.json` (`v1`) + `templates/template_execution/*.text-slots.json` (`v2-min`) | Derived template index | Compact prototype/source-import summary plus per-prototype text-slot diagnostics; the sidecar integrity hash is tool-only | Materialization may publish these deterministic records, but page-context does not inject or require them and models do not read them during page authoring. The complete prototype SVG is the sole visual/template authority; never author from either JSON artifact. | | `templates/template_execution_manifest.json` (`v1`) + `templates/template_execution/*.text-slots.json` (`v2-min`) | Derived template index | Compact prototype/source-import summary plus per-prototype text-slot diagnostics; the sidecar integrity hash is tool-only | Materialization may publish these deterministic records, but page-context does not inject or require them and models do not read them during page authoring. The complete prototype SVG is the sole visual/template authority; never author from either JSON artifact. |
| `<import_workspace>/svg/` | Imported native-payload backing | Complete PPTX-derived metadata, hidden carriers, fallback evidence, and source structure | Keep immutable; create-template materialization may resolve a validated source ref against these files, but models do not edit or bulk-read them | | `<import_workspace>/svg/` | Imported native-payload backing | Complete PPTX-derived metadata, hidden carriers, fallback evidence, and source structure | Keep immutable; create-template materialization may resolve a validated source ref against these files, but models do not edit or bulk-read them |
| `<import_workspace>/svg-flat/` | Optional complete-page verification backing | Self-contained visual composition generated only by explicit `--inheritance-mode both` | Keep immutable when requested; never use as authoring or materialization input | | `<import_workspace>/svg-flat/` | Optional complete-page verification backing | Self-contained visual composition generated only by explicit `--inheritance-mode both` | Keep immutable when requested; never use as authoring or materialization input |
@@ -19,7 +19,7 @@ Always-loaded Executor authority for flat SVG page authoring and behavior shared
Evaluate branches from each object's actual information model, not only from a Chart/Table reference. A catalog family selects construction guidance but never native readiness; `Native-ready` is an independent object-level decision. Page-local qualitative geometry also never implies package-level `pptx_structure.mode: structured`. Evaluate branches from each object's actual information model, not only from a Chart/Table reference. A catalog family selects construction guidance but never native readiness; `Native-ready` is an independent object-level decision. Page-local qualitative geometry also never implies package-level `pptx_structure.mode: structured`.
> Narrative skeleton and visual aesthetic come from the locked values selected through the [`modes/`](./modes/_index.md) and [`visual-styles/`](./visual-styles/_index.md) planning indexes. Executor does not reopen those indexes: it reads one locked preset file or only the exact `*_references` of a custom synthesis; an unreferenced novel custom reads none. [`shared-standards-core.md`](./shared-standards-core.md) supplies the technical boundary plus the fallback visual-quality and leading defaults when those authorities are silent. > Narrative skeleton and visual aesthetic come from the locked values selected through the [`modes/`](./modes/_index.md) and [`visual-styles/`](./visual-styles/_index.md) planning indexes. Executor does not reopen those indexes: it reads one locked preset file or only the exact `*_references` of a custom, applying one basis under its behavior or synthesizing several by their stated contributions; an unreferenced custom reads none. [`shared-standards-core.md`](./shared-standards-core.md) supplies the technical boundary plus the fallback visual-quality and leading defaults when those authorities are silent.
**Hard rule — Shape-first page authority**: Every visible object intended for the exported slide MUST exist in the final page SVG or be explicitly referenced by it. Templates and `spec_lock.md` guide construction; they are not export-time overlays for missing visible content. Optional native Chart/Table metadata belongs to an independently selected object and never replaces this visible fallback during authoring; [`native-data-interface.md`](./native-data-interface.md) alone defines that metadata and its export activation. Native formula markers require a matching SVG preview; export replaces only it under [`native-formula.md`](./native-formula.md). **Hard rule — Shape-first page authority**: Every visible object intended for the exported slide MUST exist in the final page SVG or be explicitly referenced by it. Templates and `spec_lock.md` guide construction; they are not export-time overlays for missing visible content. Optional native Chart/Table metadata belongs to an independently selected object and never replaces this visible fallback during authoring; [`native-data-interface.md`](./native-data-interface.md) alone defines that metadata and its export activation. Native formula markers require a matching SVG preview; export replaces only it under [`native-formula.md`](./native-formula.md).
@@ -93,7 +93,7 @@ Use them as identity anchors. Do not create another user-facing image-color choi
**Quick Generate path**: the main agent resolves one active-context rendering/color set, honoring explicit user values and deciding the rest without interaction. Write it to `image_prompts.json`; create no planning artifacts. **Quick Generate path**: the main agent resolves one active-context rendering/color set, honoring explicit user values and deciding the rest without interaction. Write it to `image_prompts.json`; create no planning artifacts.
**Hard rule — `custom` catalog basis**: when `image_rendering` is `custom`, first inspect the optional `image_rendering_references` row. If present, read every exact `image-renderings/<id>.md` it lists and synthesize their line, texture, depth, material, and mood guidance under `image_rendering_behavior` before assembling prompts. If absent, the custom is genuinely novel: read no preset file and use `image_rendering_behavior` directly. Never infer or add adjacent references during execution. The deck color-role rows remain authoritative. **Hard rule — `custom` catalog basis**: when `image_rendering` is `custom`, first inspect the optional `image_rendering_references` row. If present, read every exact `image-renderings/<id>.md` it lists. Apply one basis under `image_rendering_behavior`, unchanged when that behavior carries it as-is; synthesize several only by their stated line, texture, depth, material, and mood contributions. If absent, read no preset file and use `image_rendering_behavior` directly. Never infer or add adjacent references during execution. The deck color-role rows remain authoritative.
**Declared-inference fallback — when an existing `spec_lock.md` omits the `image_rendering` key** (see [`failure-recovery.md`](../workflows/governance/failure-recovery.md) §2): **Declared-inference fallback — when an existing `spec_lock.md` omits the `image_rendering` key** (see [`failure-recovery.md`](../workflows/governance/failure-recovery.md) §2):
@@ -52,9 +52,9 @@ Each rendering keeps its own authoritative file with: style paragraph, line / te
| [`pixel-art`](./pixel-art.md) | 8-bit retro game aesthetic | Gaming / retro tech / nostalgic | | [`pixel-art`](./pixel-art.md) | 8-bit retro game aesthetic | Gaming / retro tech / nostalgic |
| [`nature`](./nature.md) | Organic earthy illustration | Environment / wellness / sustainability | | [`nature`](./nature.md) | Organic earthy illustration | Environment / wellness / sustainability |
### 1.5 Escape hatch — `custom` ### 1.5 Editable `custom` projection
Every coordinated Stage-2 direction carries one complete `rendering: custom` candidate even when `recommend.image_usage` does not include `ai`. The UI keeps rendering controls hidden until the current source selection includes AI, then exposes the three already-authored project candidates without another backend recommendation. The 20 fixed renderings remain lower-level single-select alternatives. A template-backed proposal must honor inherited identity and the confirmed template-application plan. Every coordinated Stage-2 direction carries one complete `rendering: custom` candidate even when `recommend.image_usage` does not include `ai`. The UI keeps rendering controls hidden until the current source selection includes AI, then exposes the three already-authored project candidates without another backend recommendation. `custom` is not constrained by its relationship to the catalog: it may use catalog material in any way or none, including carrying one fitting preset treatment unchanged. The three complete directions are plainly different designs, but no single component is required to carry that difference: rendering treatments and bases may coincide when other components express it, while a different name, note, or reference count alone is never a difference. The 20 fixed renderings remain lower-level single-select alternatives. A template-backed proposal must honor inherited identity and the confirmed template-application plan.
**Hard rule — `rendering_behavior` prose**: **Hard rule — `rendering_behavior` prose**:
@@ -62,7 +62,7 @@ Every coordinated Stage-2 direction carries one complete `rendering: custom` can
|---|---| |---|---|
| Length | One paragraph, 2-5 sentences | | Length | One paragraph, 2-5 sentences |
| Axes covered | line / texture / depth / material / mood (same as preset files) | | Axes covered | line / texture / depth / material / mood (same as preset files) |
| Catalog basis | Freeze every exact id from this index, then read only those named files before synthesis | | Catalog basis | Freeze every exact id from this index, then read only those files before applying one basis or synthesizing several |
```yaml ```yaml
- image_rendering: custom - image_rendering: custom
@@ -71,7 +71,7 @@ Every coordinated Stage-2 direction carries one complete `rendering: custom` can
**Hard rule**: three complete rendering candidates are mandatory in every fresh Stage-2 direction set; AI source recommendation remains independent. See [`strategist-image.md`](../strategist-image.md) for the Stage-2 carrier and downstream lock behavior. **Hard rule**: three complete rendering candidates are mandatory in every fresh Stage-2 direction set; AI source recommendation remains independent. See [`strategist-image.md`](../strategist-image.md) for the Stage-2 carrier and downstream lock behavior.
Write `image_rendering_references` only when the confirmed custom direction actually uses catalog material. A custom may use zero, one, or many renderings: keep one when it owns the whole specialized treatment, or include every rendering that contributes a distinct executable job across line, texture, depth, material, or mood. Reference count has no fixed cap; count is an outcome, not a target. A four-basis direction may assign `vector-illustration` to silhouette clarity, `minimalist-swiss` to negative-space composition, `screen-print` to restrained halftone texture, and `warm-scene` to light and mood; list all four ids. Omit every rendering whose contribution cannot be stated and never add a second merely to imply synthesis. A genuinely new rendering with no catalog source omits the field and proceeds from its standalone behavior; never invent a reference merely to legitimize `custom`. Write `image_rendering_references` only when the confirmed custom direction actually uses catalog material. One rendering may supply the complete treatment unchanged; when several are named, each contributes a distinct executable job across line, texture, depth, material, or mood. Reference count has no fixed cap; count is an outcome, not a target. A four-basis direction may assign `vector-illustration` to silhouette clarity, `minimalist-swiss` to negative-space composition, `screen-print` to restrained halftone texture, and `warm-scene` to light and mood; list all four ids. Omit every rendering whose contribution cannot be stated and never add a second merely to imply synthesis. A custom using no catalog source omits the field and proceeds from its standalone behavior; never invent a reference merely to legitimize `custom`.
--- ---
@@ -99,6 +99,6 @@ describes the intended treatment, use `custom` per §1.5.
1. Read the resolved visual system and the deck's intended AI image jobs. 1. Read the resolved visual system and the deck's intended AI image jobs.
2. Compare the complete catalog and choose the strongest whole-deck fit, or use a warranted `custom` treatment. 2. Compare the complete catalog and choose the strongest whole-deck fit, or use a warranted `custom` treatment.
3. For a preset, read `image-renderings/<chosen>.md`. For `custom`, read every file named in `image_rendering_references`, then synthesize them under the confirmed behavior; with no references, use the novel behavior directly. Apply the result when assembling prompts per [`image-generator.md`](../image-generator.md) §4. 3. For a preset, read `image-renderings/<chosen>.md`. For `custom`, read every file named in `image_rendering_references`: apply one basis under the confirmed behavior, or synthesize several by their stated contributions. With no references, use the behavior directly. Apply the result when assembling prompts per [`image-generator.md`](../image-generator.md) §4.
**Lock for the whole deck.** Don't change rendering between images in the same deck. **Lock for the whole deck.** Don't change rendering between images in the same deck.
@@ -58,18 +58,18 @@ selecting one for the current deck:
--- ---
## 4. Escape hatch — `custom` ## 4. Editable projection and escape hatch — `custom`
`custom` holds **any bespoke narrative direction the five don't give as-is** — and what *kind* of thing it is doesn't matter. It might be a nameable cadence (dialectic 正反合, myth-vs-reality, countdown / Top-N, Socratic), a deliberate multi-act fusion of several modes, or the user's own feel for how the deck should carry (confrontational here, detached there). Don't try to taxonomize it. `custom` is the editable behavior carrier, not a category defined by how it relates to the catalog. Default uses it for each coordinated direction even when one preset supplies the complete cadence unchanged. In Quick or a lower-level manual choice it remains the escape hatch for **a bespoke narrative direction the five don't give as-is**: a nameable cadence (dialectic 正反合, myth-vs-reality, countdown / Top-N, Socratic), a deliberate multi-act fusion, or the user's own posture shifts. Don't try to taxonomize those bespoke cases.
**Default candidates**: All three coordinated Stage-2 directions use literal `custom` plus a visible, non-empty `mode_behavior`. A direction may specialize one preset, fuse several modes, or define a novel cadence; it fits any installed template capacity. The fixed five remain lower-level single-select alternatives. Strategist crystallizes the confirmed current value in the Design Spec first, then projects its behavior and actual catalog basis to `spec_lock.md`. **Default candidates**: All three coordinated Stage-2 directions use literal `custom` plus a visible, non-empty `mode_behavior`. A custom may use catalog material in any way or none, including carrying one preset unchanged; it fits any installed template capacity. The three complete directions are plainly different designs, but no single component is required to carry that difference: mode behaviors and bases may coincide when other components express it, while a different name, note, or reference count alone is never a difference. The fixed five remain lower-level single-select alternatives. Strategist crystallizes the confirmed current value in the Design Spec first, then projects its behavior and actual catalog basis to `spec_lock.md`.
**Quick custom**: do not display a candidate set. Use `custom` only when a project-specific specialization or fusion serves the deck better than one preset; retain the behavior and exact bases in active context and persist nothing. **Quick custom**: do not display a candidate set. Use `custom` only when a project-specific specialization or fusion serves the deck better than one preset; retain the behavior and exact bases in active context and persist nothing.
**Mandatory — select before detail reading**: Use this index to freeze every catalog source actually used, then read only those exact files before writing the behavior. A custom may use zero, one, or many sources: keep one when it owns the whole specialized cadence, or include every mode that owns a distinct executable act, posture, title voice, rhythm, or register. Reference count has no fixed cap; count is an outcome, not a target. A three-basis direction may use `pyramid` for a conclusion-first opening, `narrative` for the risk-tension act, and `instructional` for the closing action sequence; it reads those three files and writes all three ids beside `mode_behavior`. Quick retains its bases only in active context. Omit every source whose contribution cannot be stated, never add a second merely to imply synthesis, and do not open candidates for comparison after this gate. A genuinely new cadence names and reads no catalog source. **Mandatory — select before detail reading**: Use this index to freeze every catalog source actually used, then read only those exact files before writing the behavior. One source may supply the complete cadence unchanged; when several are named, each owns a distinct executable act, posture, title voice, rhythm, or register. Reference count has no fixed cap; count is an outcome, not a target. A three-basis direction may use `pyramid` for a conclusion-first opening, `narrative` for the risk-tension act, and `instructional` for the closing action sequence; it reads those three files and writes all three ids beside `mode_behavior`. Quick retains its bases only in active context. Omit every source whose contribution cannot be stated, never add a second merely to imply synthesis, and do not open candidates for comparison after this gate. A custom using no catalog source names and reads none.
> **One value per deck — fusion is *one* `custom`, not several modes.** A deck always resolves a single `mode`. A multi-mode blend is expressed as **one** custom behavior whose paragraph describes the acts — never as several simultaneous modes. > **One value per deck — fusion is *one* `custom`, not several modes.** A deck always resolves a single `mode`. A multi-mode blend is expressed as **one** custom behavior whose paragraph describes the acts — never as several simultaneous modes.
> >
> **Custom need not mean fusion.** A Default recommendation can specialize one dominant preset for this project's act sequence, title voice, rhythm, and register. Quick or a lower-level manual choice may still use the fixed preset directly. > **Default custom need not mean fusion or deviation.** It may project one dominant preset unchanged into an editable behavior, or specialize it when the project actually calls for a delta. Quick or a lower-level manual choice still uses the fixed preset directly when no editable projection is needed.
**Forbidden — empty customization**: Do not relabel an index row as `custom`. The behavior must state the project-specific cadence, posture, title voice, page rhythm, or act sequence that the fixed preset alone does not encode. A user-stated direction remains authoritative the same way a user-supplied outline is — see the lens-not-mandate note in §1. **Forbidden — empty behavior**: Single-preset reuse is valid. When a Default direction carries an index row without changing its logic, name and read that exact basis, then state its executable cadence, posture, title voice, page rhythm, or act sequence in the editable behavior; do not add another mode merely to justify `custom`. A bare label with no executable behavior remains invalid. A user-stated direction remains authoritative the same way a user-supplied outline is — see the lens-not-mandate note in §1.
@@ -63,9 +63,9 @@ When a subject crosses a native title, panel, frame, or shape, the prepared path
## 2. AI Image Strategy — always propose three; lock only for confirmed `ai` ## 2. AI Image Strategy — always propose three; lock only for confirmed `ai`
Before any rendering detail, use the already-loaded [`image-renderings/_index.md`](./image-renderings/_index.md) as the sole rendering-basis catalog authority. First author exactly three complete, project-fit solution intents; use the index to freeze each intent's exact rendering bases, then read once only the deduplicated referenced sibling files. Project one complete `image_strategy` into each direction regardless of `recommend.image_usage`. Every candidate carries localized `name`, `rendering: custom`, `visual`, `mood`, and non-empty localized `behavior`. Mood includes a recognizable real-world analogy. All three must credibly serve their owning whole solution, but they need not use different bases or span artificial safe / shifted / bold extremes. Image colors always inherit that direction's deck HEX roles; never add an image palette or alter deck colors to rescue a rendering. Before any rendering detail, use the already-loaded [`image-renderings/_index.md`](./image-renderings/_index.md) as the sole rendering-basis catalog authority. First author exactly three complete, project-fit solution intents; use the index to freeze each intent's exact rendering bases, then read once only the deduplicated referenced sibling files. Project one complete `image_strategy` into each direction regardless of `recommend.image_usage`. Every candidate carries localized `name`, `rendering: custom`, `visual`, `mood`, and non-empty localized `behavior`. Mood includes a recognizable real-world analogy. All three must credibly serve their owning whole solution; rendering treatments and bases may coincide when other components express the direction difference. Do not force artificial safe / shifted / bold extremes. Image colors always inherit that direction's deck HEX roles; never add an image palette or alter deck colors to rescue a rendering.
Every direction is a `custom` rendering. It may use zero, one, or many index-selected bases: one may own a specialized treatment, while several must each own a distinct line, texture, depth, material, or mood contribution. Name every actual id in the visible behavior and read only those files after selection; reference count has no fixed cap, and a second basis is never required. If the direction is genuinely novel, name no basis and read none. Under a template it obeys inherited identity and application. Only a confirmed custom locks its edited behavior as `image_rendering_behavior`; when catalog material is actually used, also project the exact ids as `image_rendering_references`, otherwise omit that field. Unselected candidates remain recommendation-only. Do not write a separate fourth `custom_candidates.image_strategy`; ignore legacy `image_palette`. Every direction is a `custom` rendering, unconstrained by how it relates to the catalog. It may use catalog material in any way or none, including carrying one complete preset treatment unchanged. Name every actual id in the visible behavior and read only those files after selection; when several are named, each owns a distinct line, texture, depth, material, or mood contribution. Reference count has no fixed cap, and a second basis is never required. With no catalog basis, name none and read none. Under a template it obeys inherited identity and application. Only a confirmed custom locks its edited behavior as `image_rendering_behavior`; when catalog material is actually used, also project the exact ids as `image_rendering_references`, otherwise omit that field. Unselected candidates remain recommendation-only. Do not write a separate fourth `custom_candidates.image_strategy`; ignore legacy `image_palette`.
The UI hides these candidates while AI is not selected. If the user adds AI, it reveals the already-authored three without another backend recommendation; source selection never creates or rewrites rendering candidates. After confirmation, Image_Generator reads only the selected preset or exact custom references and must not blend unselected candidate identities. The UI hides these candidates while AI is not selected. If the user adds AI, it reveals the already-authored three without another backend recommendation; source selection never creates or rewrites rendering candidates. After confirmation, Image_Generator reads only the selected preset or exact custom references and must not blend unselected candidate identities.
@@ -21,7 +21,7 @@ Conditional extension for applying an installed Brand/Style/Layout/Deck workspac
Immediately before authoring the Stage-2 solution, load each relevant template Immediately before authoring the Stage-2 solution, load each relevant template
resource once per path + SHA and inspect: resource once per path + SHA and inspect:
- every installed `design_spec.<kind>.<id>.md`; for Layout/Deck only, also inspect the actual Page Roster and relevant SVG prototypes; - every installed `design_spec.<kind>.<id>.md`; inspect the actual Page Roster and relevant SVG prototypes from Layout when present, otherwise from Deck;
- the Identity, Structure, Reusable Application Context, and Direction / method segment owners, resolved here from the installed set under [`apply-template-workspace`](../workflows/stages/apply-template-workspace.md) §5; - the Identity, Structure, Reusable Application Context, and Direction / method segment owners, resolved here from the installed set under [`apply-template-workspace`](../workflows/stages/apply-template-workspace.md) §5;
- the confirmed current communication contract, source obligations, planned page count, and content shape of every planned page; - the confirmed current communication contract, source obligations, planned page count, and content shape of every planned page;
- the user's natural-language instructions, including any page names/numbers or elements they explicitly require. - the user's natural-language instructions, including any page names/numbers or elements they explicitly require.
@@ -68,7 +68,7 @@ When the communication contract conflicts with the workspace, choose and state t
> Internal note: `content_divergence` controls source reorganization; the AI-derived `template_reuse_scope` records the reused layer; `template_adherence` records whether a structured plan keeps or extends existing Layout identities. > Internal note: `content_divergence` controls source reorganization; the AI-derived `template_reuse_scope` records the reused layer; `template_adherence` records whether a structured plan keeps or extends existing Layout identities.
**Template design precedence**: Explicit current user instructions and final confirmation win. Brand identity overrides Deck identity, Layout structure overrides Deck structure, and Deck retains only its non-overridden integrated segments plus reusable application context. Style owns Direction / method only: its color, typography, icon, and image values are candidate defaults and never override resolved Brand/Deck identity or become official facts. Preferred Mode / Visual Style values seed Stage 2; the Style overlay must resolve into the final single `mode` and `visual_style` lock rather than create a parallel narrative or aesthetic authority. Style takes this segment ahead of ordinary Stage-2 defaults; actual Deck prototypes and Signature facts remain compatibility constraints, not a second method owner. Library/explicit provenance never changes this order. Each of the three directions still carries six palette roles and complete fonts: repeat fixed Brand/Deck values with `typography.fixed: true`; adapt Style candidates to that identity and vary only open roles. Keep resolved icon and image constraints. Style Review Focus never activates [`visual-review`](../workflows/stages/visual-review.md); only an explicit user request does. **Template design precedence**: Explicit current user instructions and final confirmation win. The installed set contains at most one contribution per kind, and all four kinds may coexist. Brand identity overrides Deck identity when both are present. Layout overrides only Deck structure; Deck still owns its reusable application context and any identity not overridden by Brand. Without Layout, Deck owns structure. Style owns Direction / method only: its color, typography, icon, and image values are candidate defaults and never override resolved Brand/Deck identity or become official facts. Preferred Mode / Visual Style values seed Stage 2; the Style overlay must resolve into the final single `mode` and `visual_style` lock rather than create a parallel narrative or aesthetic authority. Style takes this segment ahead of ordinary Stage-2 defaults; the active structural prototypes and Deck Signature facts remain compatibility constraints, not a second method owner. Library/explicit provenance never changes this order. Each of the three directions still carries six palette roles and complete fonts: repeat fixed Brand/Deck values with `typography.fixed: true`; adapt Style candidates to that identity and vary only open roles. Keep resolved icon and image constraints. Style Review Focus never activates [`visual-review`](../workflows/stages/visual-review.md); only an explicit user request does.
--- ---
@@ -36,7 +36,7 @@ solution + production gate:
| **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 fields may be blank) · `a` canvas · explicit `free_design` or `templates` choice and selected roots | confirmed together; candidate workspaces do not influence the communication recommendation | | **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 fields may be blank) · `a` canvas · explicit `free_design` or `templates` choice and selected roots | confirmed together; candidate workspaces do not 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 natural-language template application · conditional AI-image acquisition path · generation mode · refine-spec toggle · proactive speaker notes / custom animations / narration audio | derived as one coherent plan from the confirmed contract; internal template exporter modes remain hidden | | **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 natural-language template application · conditional AI-image acquisition path · generation mode · refine-spec toggle · proactive speaker notes / custom animations / narration audio | derived as one coherent plan from the confirmed contract; internal template exporter modes remain hidden |
Do not force communication intent into one catalog label; Stage 1 records composite intent in prose. Editable prose fields are recommendation drafts, not required inputs: confirmation preserves current text and blanks; never repopulate a cleared field. Stage 2 confirms narrative spine, reading density, page budget, visual system, image direction, production mechanics, and how any installed template should be used. It never chooses or installs a template. Inspect only project-local template spec/prototypes, present one editable application plan, and keep exporter reuse/adherence internal. First author exactly three complete, project-fit solution directions from the confirmed contract and source; only then project each direction into mode, visual style, color, type, icons, and generated-image rendering for lower-level adjustment. Every direction projects a project-specific `custom` mode, `custom` visual style, and `custom` generated-image rendering; the fixed catalogs remain conservative lower-level single-select alternatives. All three must be viable and distinguishable as whole solutions, but do not force safe / shifted / bold archetypes, different catalog bases, or artificial extremes. After all three bundles are complete, compare them against the confirmed contract and source, choose the strongest overall fit, and write its actual zero-based index as `design_directions.selected` (`0`, `1`, or `2`); array order never determines preference. Every direction carries a complete generated-image rendering candidate even when AI imagery is not recommended; `recommend.image_usage` independently decides whether AI is proposed. Generated images inherit deck colors—there is no second image palette. Proactive defaults are speaker notes `true`, custom animations `false`, and narration audio `false`; a prior explicit user instruction overrides the matching recommendation, and effective narration audio requires effective speaker notes. Author each stage once; same-stage edits update only visible browser state through documented deterministic dependencies, without another AI/backend recommendation. Launch/derive/wait mechanics live in [`generate-pptx.md`](../workflows/generate-pptx.md) Step 4; item specs keep `a``h`. Do not force communication intent into one catalog label; Stage 1 records composite intent in prose. Editable prose fields are recommendation drafts, not required inputs: confirmation preserves current text and blanks; never repopulate a cleared field. Stage 2 confirms narrative spine, reading density, page budget, visual system, image direction, production mechanics, and how any installed template should be used. It never chooses or installs a template. Inspect only project-local template spec/prototypes, present one editable application plan, and keep exporter reuse/adherence internal. First author exactly three complete, project-fit solution directions from the confirmed contract and source; only then project each direction into mode, visual style, color, type, icons, and generated-image rendering for lower-level adjustment. Every direction projects a project-specific `custom` mode, `custom` visual style, and `custom` generated-image rendering; the fixed catalogs remain conservative lower-level single-select alternatives. Each direction is one complete design authored top-down within the confirmed contract, never assembled bottom-up from catalog picks; three exist so a single recommendation cannot lock the user in, and the fixed catalogs stay the manual lower layer. Its custom projections are unrestricted by catalog relationship and may carry one preset unchanged. The three directions are plainly different designs at the whole-deck level before any field is written; that difference lives in the solutions, not in one designated field. Whichever components a direction's own design requires carry it — mode, visual style, rendering, color, type, or icons — any of them may, and none is required to differ. A different name, note, or reference count alone is not a difference, and projections identical on every component are not three solutions. Do not force safe / shifted / bold archetypes or artificial extremes. After all three bundles are complete, compare them against the confirmed contract and source, choose the strongest overall fit, and write its actual zero-based index as `design_directions.selected` (`0`, `1`, or `2`); array order never determines preference. Every direction carries a complete generated-image rendering candidate even when AI imagery is not recommended; `recommend.image_usage` independently decides whether AI is proposed. Generated images inherit deck colors—there is no second image palette. Proactive defaults are speaker notes `true`, custom animations `false`, and narration audio `false`; a prior explicit user instruction overrides the matching recommendation, and effective narration audio requires effective speaker notes. Author each stage once; same-stage edits update only visible browser state through documented deterministic dependencies, without another AI/backend recommendation. Launch/derive/wait mechanics live in [`generate-pptx.md`](../workflows/generate-pptx.md) Step 4; item specs keep `a``h`.
**Default — continuity-aware whole solution (may override when a scene reset communicates better)**: Within active-profile invariants and before recommending page count or production mechanics, judge whether adjacent explanation beats can remain within one recognizable mental map while a visible state changes. Where that choice lowers cognitive switching and motion has a named communication job, let it shape the solution's narrative spine, page rhythm, visual approach, and enabled notes/narration segmentation, and recommend the existing `proactive_custom_animations: true`. This is one positive signal, not the only reason to enable animation; absent it, retain the existing default or other valid evidence. Topic or wording repetition alone is insufficient. A `Motion suggestion` remains optional advice and never changes the effective outcome. **Default — continuity-aware whole solution (may override when a scene reset communicates better)**: Within active-profile invariants and before recommending page count or production mechanics, judge whether adjacent explanation beats can remain within one recognizable mental map while a visible state changes. Where that choice lowers cognitive switching and motion has a named communication job, let it shape the solution's narrative spine, page rhythm, visual approach, and enabled notes/narration segmentation, and recommend the existing `proactive_custom_animations: true`. This is one positive signal, not the only reason to enable animation; absent it, retain the existing default or other valid evidence. Topic or wording repetition alone is insufficient. A `Motion suggestion` remains optional advice and never changes the effective outcome.
@@ -125,7 +125,7 @@ When authoring §IX, translate every purpose named in `communication_intent` int
Two independent layers, each locks one preset or `custom`. Output: `d. Mode: <mode> + Visual style: <visual_style>`. Two independent layers, each locks one preset or `custom`. Output: `d. Mode: <mode> + Visual style: <visual_style>`.
> **Top-down custom direction construction.** Author three complete solution intents from the confirmed project contract and source before selecting any catalog basis; do not assemble three apparent solutions from independent mode/style/rendering picks. The fixed planning-capability batch may already be in context, but only the three mode/style/rendering indexes act as basis selectors. Use their summaries to freeze the exact reference ids for each direction, then read once only the deduplicated union of those referenced detail files and author the final behaviors. Every direction MUST serialize `mode: custom`, `visual_style: custom`, and `image_strategy.rendering: custom`, each with visible, non-empty behavior prose. A custom may use zero, one, or many catalog bases: one may specialize a strong dominant basis, several may divide distinct executable jobs, and a genuinely novel custom uses none. Reference count has no fixed cap and is an outcome, not a target; omit every basis whose contribution the behavior cannot state, and never add a second basis merely to make the result look synthesized. These three projections are the project-specific choices above the conservative fixed catalogs, not a fourth Custom proposal. Never glob a catalog, read an unselected sibling, or write bespoke prose as an enum value. > **Top-down custom direction construction.** Author three complete solution intents from the confirmed project contract and source before selecting any catalog basis; do not assemble three apparent solutions from independent mode/style/rendering picks. The fixed planning-capability batch may already be in context, but only the three mode/style/rendering indexes act as basis selectors. Use their summaries to freeze the exact reference ids for each direction, then read once only the deduplicated union of those referenced detail files and author the final behaviors. Every direction MUST serialize `mode: custom`, `visual_style: custom`, and `image_strategy.rendering: custom`, each with visible, non-empty behavior prose. `custom` is not constrained by a catalog relationship: it may use catalog material in any way or none, including carrying one exact preset unchanged. References record only actual sources; one may carry the complete preset behavior, while several must each own a distinct executable contribution. Omit every basis whose contribution the behavior cannot state, and never add a decorative second basis. The three whole-deck directions MUST be plainly different designs before any field is written; complete each one's detail, then project that detail onto the fields. No component is the designated proof: whichever ones a direction's design requires carry the difference, any of them may, and mode, style, rendering, catalog bases, color, type, and icons are each free to coincide. A different name, note, or reference count alone is not a difference, and projections identical on every component are not three solutions. Where authoritative truth fixes some components, the remaining open ones carry it; when nothing is open, keep the projections identical and state that boundary instead of inventing a false difference. These three projections are the project-specific choices above the conservative fixed catalogs, not a fourth Custom proposal. Never glob a catalog, read an unselected sibling, or write bespoke prose as an enum value.
#### Layer 1 — Communication mode #### Layer 1 — Communication mode
@@ -136,8 +136,8 @@ The deck's **narrative + persuasion skeleton** — how the argument is organized
**Source**: **Source**:
- User supplied their own outline / structure → preserve its facts and intended relationships, then apply the confirmed `content_divergence`. Treat an ordinary source outline as a Reference: regroup, reorder, or retitle when the communication contract benefits. Treat it as authoritative only when the user presents it as the final page plan or explicitly asks to preserve page order, titles, or wording; record that promoted boundary in `design_spec.md`. Still lock a mode for register, voice, and any permitted reshaping. `briefing` imposes the least if no particular "讲法" is intended. - User supplied their own outline / structure → preserve its facts and intended relationships, then apply the confirmed `content_divergence`. Treat an ordinary source outline as a Reference: regroup, reorder, or retitle when the communication contract benefits. Treat it as authoritative only when the user presents it as the final page plan or explicitly asks to preserve page order, titles, or wording; record that promoted boundary in `design_spec.md`. Still lock a mode for register, voice, and any permitted reshaping. `briefing` imposes the least if no particular "讲法" is intended.
- Beautify / re-layout profile ([`beautify-pptx.md`](../workflows/profiles/beautify-pptx.md)) → the extracted source content is authoritative and **verbatim**, one step stricter than the user-outline case above. Each source slide becomes exactly one `§IX` page in source order; transcribe every content block word-for-word — never reshape / re-primary / condense / merge / split / reword. All three custom mode behaviors preserve that 1:1 boundary and may share `briefing` as their sole basis; do not manufacture narrative variation. Color (e) and typography (g) are whatever the user confirmed in the beautify plan — the source identity (theme or observed) by default, or a content / brand-aware alternative the beautify plan offered and the user picked — locked as truth. Charts / tables / images are regenerated from their extracted data in the inherited style: record only selected catalog references in §VII, keep unmatched chart/table plans in their §IX page blocks, and route pictures to §VIII. Data values stay frozen and the rendering is the deck's own; visuals are never carried over verbatim. Layout, hierarchy, rhythm, and visual rendering are what gets redesigned. - Beautify / re-layout profile ([`beautify-pptx.md`](../workflows/profiles/beautify-pptx.md)) → the extracted source content is authoritative and **verbatim**, one step stricter than the user-outline case above. Each source slide becomes exactly one `§IX` page in source order; transcribe every content block word-for-word — never reshape / re-primary / condense / merge / split / reword. All three custom mode behaviors preserve that 1:1 boundary and may share `briefing` as their sole basis; do not manufacture narrative variation. Color (e) and typography (g) are whatever the user confirmed in the beautify plan — the source identity (theme or observed) by default, or a content / brand-aware alternative the beautify plan offered and the user picked — locked as truth. Charts / tables / images are regenerated from their extracted data in the inherited style: record only selected catalog references in §VII, keep unmatched chart/table plans in their §IX page blocks, and route pictures to §VIII. Data values stay frozen and the rendering is the deck's own; visuals are never carried over verbatim. Layout, hierarchy, rhythm, and visual rendering are what gets redesigned.
- Each direction crystallizes one project-specific cadence / posture in `mode_behavior`: it may specialize one preset, fuse several modes into a multi-act sequence, or be genuinely novel. A catalog-based direction retains only the exact ids it actually uses; a novel direction invents no basis. One deck locks one `custom` value, never several simultaneous modes. - Each direction crystallizes one editable cadence / posture in `mode_behavior`. It is unconstrained by its relationship to the catalog and may use catalog material in any way or none, including carrying one preset unchanged. A catalog-based direction retains only the exact ids it actually uses; a direction using no catalog material invents no basis. One deck locks one `custom` value, never several simultaneous modes.
- No user structure or cadence → derive each whole solution from the confirmed `communication_intent`, `audience_outcome`, source texture, and delivery context, then project its custom mode. The three directions may share a catalog basis when that is honestly best; distinguish them through project-specific behavior or other fields instead of forcing different bases. - No user structure or cadence → derive each whole solution from the confirmed `communication_intent`, `audience_outcome`, source texture, and delivery context, then project its custom mode. Directions may share catalog bases or the same mode behavior when their complete solutions remain plainly different; never force mode variation merely to separate the bundles.
Record the confirmed mode and rationale in `design_spec.md` first, including every exact catalog basis when a selected custom uses any. Then project `- mode:` to `spec_lock.md`; for `custom`, also project `- mode_behavior:` and, only when catalog material is actually used, `- mode_references: <id>[, <id> ...]`. Executor reads only those exact references; an unreferenced novel custom follows the behavior directly. Record the confirmed mode and rationale in `design_spec.md` first, including every exact catalog basis when a selected custom uses any. Then project `- mode:` to `spec_lock.md`; for `custom`, also project `- mode_behavior:` and, only when catalog material is actually used, `- mode_references: <id>[, <id> ...]`. Executor reads only those exact references; an unreferenced novel custom follows the behavior directly.
@@ -148,10 +148,10 @@ Record the confirmed mode and rationale in `design_spec.md` first, including eve
The deck's **visual aesthetic** — shape language, decoration density, whitespace rhythm, typographic character, texture. Anchors downstream fields e (Color), f (Icon), g (Typography), h (Image). Lock one preset from the catalog, or `custom`. The deck's **visual aesthetic** — shape language, decoration density, whitespace rhythm, typographic character, texture. Anchors downstream fields e (Color), f (Icon), g (Typography), h (Image). Lock one preset from the catalog, or `custom`.
**Source**: **Source**:
- User named a style (chat / template / beautify) → it is truth: retain it as the required basis or inherited anchor in every custom behavior. Keep the three whole solutions meaningful by varying only fields the user left open; when visual variation is forbidden, the three style behaviors may be identical. - User named a style (chat / template / beautify) → it is truth: retain it as the required basis or inherited anchor in every custom behavior. Derive each direction's application through the style dimensions left open. When the user or template forbids all visual variation, the three style behaviors may be identical and the remaining open components carry the direction difference; state that boundary in the direction note instead of fabricating difference.
- No user description → author three project-fit whole solutions first, then project one complete custom aesthetic for each. Directions may share catalog bases when their overall systems still differ meaningfully. Do not force different bases, a safe-to-bold ladder, or one deliberately extreme option merely to manufacture variety. Give each direction a localized name and use its localized note as a compact, user-facing style summary. The note may reuse localized display labels from Confirm UI's `visual_styles` catalog (for example, `瑞士极简`, `柔和圆角`, or `编辑出版`) when they concisely describe the result, but these labels are optional vocabulary, not a selection constraint or required mapping. Use concise natural language wherever the catalog wording does not fit, and never force the nearest label. Keep the summary to one or two short sentences without exposing catalog ids or reference mechanics. The Confirm UI exposes these three project-specific styles above all 18 fixed manual alternatives. - No user description → author three project-fit whole solutions first, then project one complete custom aesthetic for each. A custom aesthetic is not constrained by its relationship to the catalog; it may use catalog material in any way or none, including carrying one fitting style unchanged. Directions may share catalog bases, and their `visual_style_behavior` values differ whenever the three designs genuinely differ in aesthetic rather than to satisfy a variation quota. Do not force different bases, a safe-to-bold ladder, or one deliberately extreme option merely to manufacture variety. Give each direction a localized name and use its localized note as a compact, user-facing style summary. The note may reuse localized display labels from Confirm UI's `visual_styles` catalog (for example, `瑞士极简`, `柔和圆角`, or `编辑出版`) when they concisely describe the result, but these labels are optional vocabulary, not a selection constraint or required mapping. Use concise natural language wherever the catalog wording does not fit, and never force the nearest label. Keep the summary to one or two short sentences without exposing catalog ids or reference mechanics. The Confirm UI exposes these three project-specific styles above all 18 fixed manual alternatives.
**Forbidden — a non-catalog name as `visual_style`**: every direction recommendation uses literal `custom` for `visual_style`; bespoke prose belongs only in `visual_style_behavior`, while optional `visual_style_references` contain only first-column catalog ids. A name from the `_index` "Paired rendering" column (`flat`, `vector-illustration`, `digital-dashboard`, `3d-isometric`, `corporate-photo`, …) is an image-rendering id, not a style reference. Generic words such as flat / modern / clean / simple / minimal are also insufficient behavior: use the index to choose an exact basis when applicable, then state the project-specific shape language, composition, density, whitespace, typography, and texture. **Forbidden — a non-catalog name as `visual_style`**: every direction recommendation uses literal `custom` for `visual_style`; bespoke prose belongs only in `visual_style_behavior`, while optional `visual_style_references` contain only first-column catalog ids. A name from the `_index` "Paired rendering" column (`flat`, `vector-illustration`, `digital-dashboard`, `3d-isometric`, `corporate-photo`, …) is an image-rendering id, not a style reference. Generic words such as flat / modern / clean / simple / minimal are also insufficient behavior: use the index to choose an exact basis when applicable, then state the executable shape language, composition, density, whitespace, typography, and texture carried into this direction. Those rules may match one preset exactly; do not invent a difference merely to justify `custom`.
**Carries no color.** A visual style governs how the deck's HEX (locked at `e`) is *used* — never which colors, same discipline as [`image-renderings`](./image-renderings/_index.md). When the deck has AI images, prefer the style's paired rendering so layout and illustration share one aesthetic. **Carries no color.** A visual style governs how the deck's HEX (locked at `e`) is *used* — never which colors, same discipline as [`image-renderings`](./image-renderings/_index.md). When the deck has AI images, prefer the style's paired rendering so layout and illustration share one aesthetic.
@@ -598,7 +598,7 @@ includes transitions.
**Contextual extension**: derived paint or sparse local font/color garnish may stay in one SVG while non-structural and non-recurring. New base/semantic colors, structural/recurring fonts, resources, or recurring cross-page identity patterns require upstream repair; a page-local §VIII preferred image pattern follows [`executor-image.md`](./executor-image.md) and may change during realization. Executor never reverse-projects a local choice as planning fact. Promote recurring garnish upstream before reuse, read back and validate the affected planning fragments, and never add values to silence a comparison. **Contextual extension**: derived paint or sparse local font/color garnish may stay in one SVG while non-structural and non-recurring. New base/semantic colors, structural/recurring fonts, resources, or recurring cross-page identity patterns require upstream repair; a page-local §VIII preferred image pattern follows [`executor-image.md`](./executor-image.md) and may change during realization. Executor never reverse-projects a local choice as planning fact. Promote recurring garnish upstream before reuse, read back and validate the affected planning fragments, and never add values to silence a comparison.
- **Communication trace is mandatory**: Keep the full confirmed communication contract in `design_spec.md §I`, then project only `audience`, `objective`, `core_message`, and canonical `consumption_mode` into `spec_lock.md communication`. Write `objective` as one concise execution sentence that preserves both the confirmed `communication_intent` and the success condition in `audience_outcome`; do not copy `delivery_context`, `artifact_afterlife`, dates, provenance, or conflict-resolution commentary into the lock. Before finalizing §IX, check that every named purpose has at least one outline obligation and **every Slide block**, including cover / divider / closing pages, has an `Audience move` that advances the global outcome. A page that advances no purpose or outcome should be merged, rewritten, or cut. `project_manager.py validate` and `svg_quality_checker.py` enforce the compact lock fields and per-page move presence, not their subjective quality. - **Communication trace is mandatory**: Keep the full confirmed communication contract in `design_spec.md §I`, then project only `audience`, `objective`, `core_message`, and canonical `consumption_mode` into `spec_lock.md communication`. Write `objective` as one concise execution sentence that preserves both the confirmed `communication_intent` and the success condition in `audience_outcome`; do not copy `delivery_context`, `artifact_afterlife`, dates, provenance, or conflict-resolution commentary into the lock. Before finalizing §IX, check that every named purpose has at least one outline obligation and **every Slide block**, including cover / divider / closing pages, has an `Audience move` that advances the global outcome. A page that advances no purpose or outcome should be merged, rewritten, or cut. `project_manager.py validate` and `svg_quality_checker.py` enforce the compact lock fields and per-page move presence, not their subjective quality.
- **Custom behavior is concise and executable**: For confirmed `custom` mode or visual style, project one resolved `mode_behavior` / `visual_style_behavior` sentence or short paragraph. When the direction actually combines or borrows catalog entries, also project the exact, comma-separated `mode_references` / `visual_style_references`; omit the field for a genuinely novel direction and never fabricate a nearby reference. Preserve the confirmed direction, reference locked role names such as `colors.primary` when needed, and omit selection history, contradictions, precedence explanations, or other Design Spec provenance. Executor reads these fields from the retained lock and loads every referenced catalog entry once per valid context. - **Custom behavior is concise and executable**: For confirmed `custom` mode or visual style, project one resolved `mode_behavior` / `visual_style_behavior` sentence or short paragraph. When the direction actually uses catalog entries, also project the exact, comma-separated `mode_references` / `visual_style_references`; omit the field when it uses none and never fabricate a nearby reference. Preserve the confirmed direction, reference locked role names such as `colors.primary` when needed, and omit selection history, contradictions, precedence explanations, or other Design Spec provenance. Executor reads these fields from the retained lock and loads every referenced catalog entry once per valid context.
- **page_rhythm is mandatory**: Based on the page list in §IX Content Outline, assign each page one of `anchor` / `dense` / `breathing`. This is what breaks the uniform "every page is a card grid" feel. New locks may not omit the section; consumer omission behavior is owned by [`executor-base.md`](executor-base.md) §2.1. - **page_rhythm is mandatory**: Based on the page list in §IX Content Outline, assign each page one of `anchor` / `dense` / `breathing`. This is what breaks the uniform "every page is a card grid" feel. New locks may not omit the section; consumer omission behavior is owned by [`executor-base.md`](executor-base.md) §2.1.
- **Fact IDs and scenario labels are mandatory when applicable**: Read any `sources/*.facts.json`. For each §IX page, list the stable IDs actually used; never cite an ID whose claim is absent from the page. Mark invented KPIs/targets/internal ratios as `Data class: scenario` and state which values are scenario data. Executor carries external sources into notes/footnotes and renders a visible scenario label for scenario figures. - **Fact IDs and scenario labels are mandatory when applicable**: Read any `sources/*.facts.json`. For each §IX page, list the stable IDs actually used; never cite an ID whose claim is absent from the page. Mark invented KPIs/targets/internal ratios as `Data class: scenario` and state which values are scenario data. Executor carries external sources into notes/footnotes and renders a visible scenario label for scenario figures.
- **Mandatory — whole-roster rhythm check**: During the same §IX composition, compare neighbors and section arcs to judge whether chapter entries visibly reset, extended same-density runs are intentional, extended same-carrier or same-topology runs form an intentional semantic sub-arc, repeated dominant geometry carries a continuity job, any qualifying §6.1 visible-state sequence preserves a recognizable mental map while making its next semantic change legible, each section follows a mode-fitting progression—including framework → explanation/evidence → judgment/action when it serves the objective—and the final arc resolves the communication objective before a genuine ending lowers information load. Same section, equal weight or density, one style, and prior-page precedent do not establish a semantic sub-arc. Repair the existing roster, `Layout` recommendations, and `page_rhythm` choices in place. This is judgment, not quota; preserve intentional continuity, legitimately all-`dense` material, and 1:1/literal order. Do not invent filler pages to manufacture rhythm; a `breathing` page marks a meaningful pause—chapter transition, standalone emphasis, or SCQA bridge—and must stand alone. Create no field, lock row, artifact, or second review/execution pass. - **Mandatory — whole-roster rhythm check**: During the same §IX composition, compare neighbors and section arcs to judge whether chapter entries visibly reset, extended same-density runs are intentional, extended same-carrier or same-topology runs form an intentional semantic sub-arc, repeated dominant geometry carries a continuity job, any qualifying §6.1 visible-state sequence preserves a recognizable mental map while making its next semantic change legible, each section follows a mode-fitting progression—including framework → explanation/evidence → judgment/action when it serves the objective—and the final arc resolves the communication objective before a genuine ending lowers information load. Same section, equal weight or density, one style, and prior-page precedent do not establish a semantic sub-arc. Repair the existing roster, `Layout` recommendations, and `page_rhythm` choices in place. This is judgment, not quota; preserve intentional continuity, legitimately all-`dense` material, and 1:1/literal order. Do not invent filler pages to manufacture rhythm; a `breathing` page marks a meaningful pause—chapter transition, standalone emphasis, or SCQA bridge—and must stand alone. Create no field, lock row, artifact, or second review/execution pass.
@@ -4,20 +4,21 @@
## Core Mission ## Core Mission
Generate reusable structured page templates inside the workspace selected by Create Template's Create Layout or Create Deck child workflow, and write a concise `design_spec.md` that captures the source-derived rules that make the template reusable. For Deck, include descriptive recurring-application context; for Layout, keep structure brand-neutral and application-neutral. Generate reusable structured page templates inside the workspace selected by Create Template's Create Layout or Create Deck child workflow, and write the resolved Design Spec that captures the source-derived rules that make the template reusable. For Deck, include descriptive recurring-application context; for Layout, keep structure brand-neutral and application-neutral.
> This is a standalone role: only triggered by the Create Layout or Create Deck child workflow under `/create-template`. Create Brand never invokes it. Library and project outputs use one workspace shape; this is not the template selection step in the main PPT generation pipeline. > This is a standalone role: only triggered by the Create Layout or Create Deck child workflow under `/create-template`. Create Brand never invokes it. Library and project outputs share one spec schema and asset routing with scope-resolved spec filenames; this is not the template selection step in the main PPT generation pipeline.
## Usage ## Usage
- **Trigger**: `/create-template` → Create Layout or Create Deck child workflow - **Trigger**: `/create-template` → Create Layout or Create Deck child workflow
- **Workspace root**: `library` (default) → `skills/ppt-master/templates/<kind_dir>/<template_name>/`; `project` → the confirmed `<target_project>/` - **Workspace root**: `library` (default) → `skills/ppt-master/templates/<kind_dir>/<template_name>/`; `project` → the confirmed `<target_project>/`
- **Template source**: `<template_workspace>/templates/` in both scopes - **Template source**: `<template_workspace>/templates/` in both scopes
- **Design Spec**: use the parent-resolved `<design_spec_path>` — library `templates/design_spec.md`; project `templates/design_spec.<kind>.<id>.md`
- **Input**: finalized template brief (output scope, target project when project-scoped, template ID, display name, kind, structural use cases or Deck application context, tone, theme mode, canvas format, optional reference assets, accepted basic template norms) - **Input**: finalized template brief (output scope, target project when project-scoped, template ID, display name, kind, structural use cases or Deck application context, tone, theme mode, canvas format, optional reference assets, accepted basic template norms)
**Hard rule — scope is execution metadata**: Use `output_scope` and `target_project` to route files, but do not write either field into portable `design_spec.md` frontmatter. Do not create a new PPTX structure mode; deck/layout output declares `native_structure_mode: structured`. **Hard rule — scope is execution metadata**: Use `output_scope` and `target_project` to route files, but do not write either field into `<design_spec_path>` frontmatter. Do not create a new PPTX structure mode; deck/layout output declares `native_structure_mode: structured`.
**Workspace precondition**: The workflow has already resolved the selected root, confirmed an empty `<template_workspace>/templates/`, and checked collision-free destination filenames in `images/` and `icons/imported/`. Check `exports/` when review was requested or the confirmed roster contains multiple Masters. Optional directories may be absent until their first real file is written. Project scope additionally requires an initialized target project. Do not begin final writes before that all-at-once preflight passes. **Workspace precondition**: The workflow has already resolved `<design_spec_path>` and checked all destinations. Library `templates/` is empty. The active authoring root contains no bare spec, selected-kind spec, or SVG roster; unique qualified roster-free siblings may remain untouched. When the target project already has the other structural kind, the parent workflow supplies an isolated project-shaped authoring root and owns the later Layout-over-Deck atomic install. Check collision-free destinations in `images/`, `icons/imported/`, and `exports/` when applicable. Optional directories may be absent until their first real file is written. Project scope additionally requires an initialized target project. Do not begin final writes before that all-at-once preflight passes.
When the workflow provides a PPTX reference source, the effective input package comes from the unified `pptx_template_import.py` preparation workspace and becomes: When the workflow provides a PPTX reference source, the effective input package comes from the unified `pptx_template_import.py` preparation workspace and becomes:
@@ -77,7 +78,7 @@ canonical `<g>` is one semantic atom after validation: it may remain
Slide-local, serve as the one direct carrier of an `object` slot, or carry Slide-local, serve as the one direct carrier of an `object` slot, or carry
Master/Layout fixed-layer ownership. This is the only `<g>` exception to the Master/Layout fixed-layer ownership. This is the only `<g>` exception to the
fixed-layer atomicity rule; ordinary groups remain forbidden there. Preset fixed-layer atomicity rule; ordinary groups remain forbidden there. Preset
paint comes from the confirmed brief and this template's `design_spec.md` paint comes from the confirmed brief and `<design_spec_path>`
color scheme. Do not copy an expanded import carrier/preview/fingerprint color scheme. Do not copy an expanded import carrier/preview/fingerprint
bundle into an authored template. `mirror` instead preserves the supported bundle into an authored template. `mirror` instead preserves the supported
expanded lossless source representation. The exact syntax and validation expanded lossless source representation. The exact syntax and validation
@@ -100,7 +101,7 @@ Never silently drop or merge an identity, and never invent a carrier page.
**Downstream boundary**: Stage 1 independently confirms the current communication contract. Strategist then inspects the installed prototypes, the Deck's descriptive application context, and the current content to author one application plan. It records `mirror`, `layout`, or `style` and, where applicable, `strict` or `adaptive` only as internal exporter values. Explicit user language overrides AI judgment, but the confirmation UI never asks the user to choose these implementation labels. Template_Designer does not preselect that project-level plan. **Downstream boundary**: Stage 1 independently confirms the current communication contract. Strategist then inspects the installed prototypes, the Deck's descriptive application context, and the current content to author one application plan. It records `mirror`, `layout`, or `style` and, where applicable, `strict` or `adaptive` only as internal exporter values. Explicit user language overrides AI judgment, but the confirmation UI never asks the user to choose these implementation labels. Template_Designer does not preselect that project-level plan.
For `mirror`, `design_spec.md §V` must be followed by a `Source Preservation Map` that records each source slide's Master/Layout assignment and output file. The map is evidence of one-to-one preservation, not a design-decision log. `standard` and `fidelity` record only their newly authored output roster and structure; do not add a source-topology disposition table. For `mirror`, `<design_spec_path> §V` must be followed by a `Source Preservation Map` that records each source slide's Master/Layout assignment and output file. The map is evidence of one-to-one preservation, not a design-decision log. `standard` and `fidelity` record only their newly authored output roster and structure; do not add a source-topology disposition table.
--- ---
@@ -151,7 +152,7 @@ Extension page types beyond the canonical four (transition / appendix / disclaim
- Choose variants from useful visual composition types such as two-column content, hero image, icon grid, data card, and quote - Choose variants from useful visual composition types such as two-column content, hero image, icon grid, data card, and quote
- Keep only variants that add a genuinely useful authored composition; source Layout keys and repeated source chrome are not clustering inputs - Keep only variants that add a genuinely useful authored composition; source Layout keys and repeated source chrome are not clustering inputs
- Design each variant's Master/Layout/slot contract directly from its intended reusable behavior - Design each variant's Master/Layout/slot contract directly from its intended reusable behavior
- Record every emitted page in `design_spec.md §V Page Roster`; in library scope, `register_template.py` generates the corresponding index entry from `<template_workspace>/templates/*.svg`. Project scope skips registration - Record every emitted page in `<design_spec_path> §V Page Roster`; in library scope, `register_template.py` generates the corresponding index entry from `<template_workspace>/templates/*.svg`. Project scope skips registration
> Variants reuse the parent type's placeholder set — see §4 (Placeholder Reference) below. > Variants reuse the parent type's placeholder set — see §4 (Placeholder Reference) below.
@@ -166,7 +167,7 @@ When the derived implementation writes `replication_mode: mirror`, materialize a
- Required preservation: preserve source Master/Layout keys and picker names, Layout-to-Master parentage, slide assignments, placeholder type/index/bounds, supported native-object metadata, geometry, decoration, sprite-sheet wrappers, original example text, chart previews, fonts, effects, and paint order whenever the importer represents them. - Required preservation: preserve source Master/Layout keys and picker names, Layout-to-Master parentage, slide assignments, placeholder type/index/bounds, supported native-object metadata, geometry, decoration, sprite-sheet wrappers, original example text, chart previews, fonts, effects, and paint order whenever the importer represents them.
- Allowed normalization: add or normalize explicit root declarations and asset paths, and recursively expand fixed Master/Layout group wrappers into direct atoms. The mapping must remain one-to-one at the ownership level and must not change paint order or appearance. - Allowed normalization: add or normalize explicit root declarations and asset paths, and recursively expand fixed Master/Layout group wrappers into direct atoms. The mapping must remain one-to-one at the ownership level and must not change paint order or appearance.
- Forbidden: commonality extraction, semantic synthesis, merging, splitting, promotion, demotion, renaming, re-parenting, decorative simplification, placeholder invention, or replacement of supported source-native metadata / SVG fallback with a model-authored approximation. - Forbidden: commonality extraction, semantic synthesis, merging, splitting, promotion, demotion, renaming, re-parenting, decorative simplification, placeholder invention, or replacement of supported source-native metadata / SVG fallback with a model-authored approximation.
- `design_spec.md` §V Page Roster lists every emitted file and marks definition-only prototypes explicitly. `Source Preservation Map` records each source-slide assignment plus every unused Layout definition and its parent Master. - `<design_spec_path>` §V Page Roster lists every emitted file and marks definition-only prototypes explicitly. `Source Preservation Map` records each source-slide assignment plus every unused Layout definition and its parent Master.
**Mirror consumption boundary**: `replication_mode: mirror` describes source-to-workspace fidelity and only makes literal downstream reuse technically possible. Strategist independently derives the application plan from the current communication contract, content, actual prototype roster, and any explicit natural-language instruction. It may select, repeat, skip, reorder, or reorganize prototypes; no internal scope forces source page count, source order, or one output slide per source slide. **Mirror consumption boundary**: `replication_mode: mirror` describes source-to-workspace fidelity and only makes literal downstream reuse technically possible. Strategist independently derives the application plan from the current communication contract, content, actual prototype roster, and any explicit natural-language instruction. It may select, repeat, skip, reorder, or reorganize prototypes; no internal scope forces source page count, source order, or one output slide per source slide.
@@ -333,7 +334,7 @@ treatment, or page roster); do not preserve a generic technical-rules heading.
### 2. Inherit Design Specification ### 2. Inherit Design Specification
Templates must strictly follow the finalized template brief and the generated `design_spec.md`: Templates must strictly follow the finalized template brief and the generated `<design_spec_path>`:
- **Canvas dimensions**: `canvas_format` is not enough; root SVG `viewBox` matches `canvas_viewbox` in the design spec. Root `width` / `height` are optional compatibility attributes and are not PPT Master canvas authority. - **Canvas dimensions**: `canvas_format` is not enough; root SVG `viewBox` matches `canvas_viewbox` in the design spec. Root `width` / `height` are optional compatibility attributes and are not PPT Master canvas authority.
- **Source canvas**: when a PPTX/SVG reference is used, record `source_canvas_width`, `source_canvas_height`, and `source_viewbox`. If the output canvas differs from the source, normalize all geometry, typography, line heights, strokes, and image crop coordinates explicitly instead of relying on the shared aspect ratio. - **Source canvas**: when a PPTX/SVG reference is used, record `source_canvas_width`, `source_canvas_height`, and `source_viewbox`. If the output canvas differs from the source, normalize all geometry, typography, line heights, strokes, and image crop coordinates explicitly instead of relying on the shared aspect ratio.
- **Color scheme**: Uses primary, secondary, and accent colors from the spec - **Color scheme**: Uses primary, secondary, and accent colors from the spec
@@ -376,7 +377,7 @@ template.
|---|---|---| |---|---|---|
| Lossless import SVG | Native-payload backing | Retain complete imported metadata, native object boundaries, hidden carriers, and source-scope identity. Keep it immutable and resolve it only through validated source refs. | | Lossless import SVG | Native-payload backing | Retain complete imported metadata, native object boundaries, hidden carriers, and source-scope identity. Keep it immutable and resolve it only through validated source refs. |
| Authoring IR bundle | Editable template-creation source | Omit opaque native payload and duplicate hidden carriers from model context; retain visible shape intent and stable document-local source refs. Models read `authoring_summary.json`; tools read `authoring_manifest.json` for source paths and initial hashes. | | Authoring IR bundle | Editable template-creation source | Omit opaque native payload and duplicate hidden carriers from model context; retain visible shape intent and stable document-local source refs. Models read `authoring_summary.json`; tools read `authoring_manifest.json` for source paths and initial hashes. |
| `standard` / `fidelity` output | Newly authored contract | Use editable basic primitives directly and `preset_shape_svg.py` compact canonical `<g>` output for exact preset matches. Keep faithful atoms independently composed when one contour is unnecessary; use `shape_boolean_svg.py` only where one compound closed contour must become an object, then allow a necessary freeform only if neither construction is faithful. Paint comes from the confirmed brief / `design_spec.md`. Reuse exported image/vector assets, not opaque source shape payload or source topology. | | `standard` / `fidelity` output | Newly authored contract | Use editable basic primitives directly and `preset_shape_svg.py` compact canonical `<g>` output for exact preset matches. Keep faithful atoms independently composed when one contour is unnecessary; use `shape_boolean_svg.py` only where one compound closed contour must become an object, then allow a necessary freeform only if neither construction is faithful. Paint comes from the confirmed brief / `<design_spec_path>`. Reuse exported image/vector assets, not opaque source shape payload or source topology. |
| `mirror` output | Materialized preserved contract | Preserve currently supported imported metadata on unchanged Slide-local/slot refs, use the edited SVG fallback otherwise, and normalize fixed structural layers into semantic atoms. Strip IR-only source refs from final templates. | | `mirror` output | Materialized preserved contract | Preserve currently supported imported metadata on unchanged Slide-local/slot refs, use the edited SVG fallback otherwise, and normalize fixed structural layers into semantic atoms. Strip IR-only source refs from final templates. |
**Validation**: Mirror does not silently use stale metadata. Materialization **Validation**: Mirror does not silently use stale metadata. Materialization
@@ -456,7 +457,7 @@ Use clear placeholder markers for replaceable content:
This is the **default vocabulary** used across template packages. Newly created templates SHOULD prefer these names so downstream projects find familiar slots; designers MAY substitute or extend them when a style genuinely needs different vocabulary (e.g. consulting decks lead with `{{KEY_MESSAGE}}` instead of `{{PAGE_TITLE}}`; a brand cover may need `{{BRAND_LOGO}}`). This is the **default vocabulary** used across template packages. Newly created templates SHOULD prefer these names so downstream projects find familiar slots; designers MAY substitute or extend them when a style genuinely needs different vocabulary (e.g. consulting decks lead with `{{KEY_MESSAGE}}` instead of `{{PAGE_TITLE}}`; a brand cover may need `{{BRAND_LOGO}}`).
`svg_quality_checker.py --template-mode` emits **advisory warnings** when a page lacks the conventional placeholder for its type. To silence those warnings — and document the template's actual contract — declare a `placeholders:` map in `design_spec.md` frontmatter: `svg_quality_checker.py --template-mode` emits **advisory warnings** when a page lacks the conventional placeholder for its type. To silence those warnings — and document the template's actual contract — declare a `placeholders:` map in `<design_spec_path>` frontmatter:
```yaml ```yaml
placeholders: placeholders:
@@ -517,6 +518,7 @@ Standard mode (default):
<template_workspace>/ <template_workspace>/
├── templates/ ├── templates/
│ ├── design_spec.md │ ├── design_spec.md
│ │ # project scope uses design_spec.<kind>.<id>.md instead
│ ├── 01_cover.svg │ ├── 01_cover.svg
│ ├── 02_toc.svg # Optional; without it: 02_chapter, 03_content, 04_ending │ ├── 02_toc.svg # Optional; without it: 02_chapter, 03_content, 04_ending
│ ├── 03_chapter.svg │ ├── 03_chapter.svg
@@ -535,7 +537,7 @@ Fidelity mode changes only the roster under `templates/`, e.g.:
``` ```
<template_workspace>/templates/ <template_workspace>/templates/
├── design_spec.md ├── design_spec.md # project scope: design_spec.<kind>.<id>.md
├── 01_cover.svg ├── 01_cover.svg
├── 02_toc.svg ├── 02_toc.svg
├── 03a_chapter_full.svg ├── 03a_chapter_full.svg
@@ -551,7 +553,7 @@ Mirror mode emits one SVG per source slide, named by source order:
``` ```
<template_workspace>/templates/ <template_workspace>/templates/
├── design_spec.md ├── design_spec.md # project scope: design_spec.<kind>.<id>.md
├── 001_cover.svg ├── 001_cover.svg
├── 002_toc.svg ├── 002_toc.svg
├── 003_content.svg ├── 003_content.svg
@@ -565,7 +567,7 @@ Mirror mode emits one SVG per source slide, named by source order:
Filenames preserve the source slide order via the 3-digit prefix; `<page_type>` is derived from `manifest.json` `pageTypeCandidates`. Literal source text and validated native structure facts are preserved when the authoring IR is materialized into the new workspace; IR-only refs and its manifest are not copied into the template output. Filenames preserve the source slide order via the 3-digit prefix; `<page_type>` is derived from `manifest.json` `pageTypeCandidates`. Literal source text and validated native structure facts are preserved when the authoring IR is materialized into the new workspace; IR-only refs and its manifest are not copied into the template output.
**Hard rule — common routing**: Keep `design_spec.md`, template SVGs, and non-bitmap template-source assets in `templates/`; place every bitmap in `images/`; place each imported vector exactly once in `icons/imported/` and reference it as `data-icon="imported/<name>"`. Never create `templates/icons/`. Write a review deck to `exports/` when explicitly requested and always for a multi-Master package gate. Create Template must not create optional directories or placeholder files solely to retain empty paths. An initialized project may already contain empty scaffolding; leave it untouched and omit it from completion unless real template files were written or adopted there. Do not branch asset placement by output scope. **Hard rule — common routing**: Keep `<design_spec_path>`, template SVGs, and non-bitmap template-source assets in `templates/`; place every bitmap in `images/`; place each imported vector exactly once in `icons/imported/` and reference it as `data-icon="imported/<name>"`. Never create `templates/icons/`. Write a review deck to `exports/` when explicitly requested and always for a multi-Master package gate. Create Template must not create optional directories or placeholder files solely to retain empty paths. An initialized project may already contain empty scaffolding; leave it untouched and omit it from completion unless real template files were written or adopted there. Do not branch asset placement by output scope.
### Template Preview ### Template Preview
@@ -617,7 +619,7 @@ templates/
- [x] Read `references/template-designer.md` - [x] Read `references/template-designer.md`
- [x] Output scope confirmed: `library` | `project`; the common workspace preflight passed before final writes - [x] Output scope confirmed: `library` | `project`; the common workspace preflight passed before final writes
- [x] Internal creation strategy derived from the confirmed natural-language intent: `standard` | `fidelity` | `mirror`; Layout mirror source is already brand-neutral and application-neutral - [x] Internal creation strategy derived from the confirmed natural-language intent: `standard` | `fidelity` | `mirror`; Layout mirror source is already brand-neutral and application-neutral
- [x] Every page listed in `design_spec.md §V Page Roster` saved to `<template_workspace>/templates/` - [x] Every page listed in `<design_spec_path>` §V Page Roster saved to `<template_workspace>/templates/`
- [x] Naming convention applied (standard / fidelity: letter-suffix variants; mirror: `<NNN>_<page_type>.svg`) - [x] Naming convention applied (standard / fidelity: letter-suffix variants; mirror: `<NNN>_<page_type>.svg`)
- [x] Templates follow design spec (colors, fonts, layout) - [x] Templates follow design spec (colors, fonts, layout)
- [x] Deck Template Overview and factual Page Roster describe the recurring application and actual prototypes without mandatory use policy; Layout output contains no application or identity contract - [x] Deck Template Overview and factual Page Roster describe the recurring application and actual prototypes without mandatory use policy; Layout output contains no application or identity contract
@@ -625,7 +627,7 @@ templates/
- [x] Placeholder markers are clear and standardized for `standard` / `fidelity`; preview-only sample text remains readable without changing source markers, while mirror preserves literal source text plus source placeholder type/index/bounds - [x] Placeholder markers are clear and standardized for `standard` / `fidelity`; preview-only sample text remains readable without changing source markers, while mirror preserves literal source text plus source placeholder type/index/bounds
- [x] Every SVG is a complete preview with explicit root Master/Layout identity and `native_structure_mode: structured`; authored modes use canonical fixed layers/slots, while mirror preserves source ownership and mechanically expands fixed-layer groups into direct atoms - [x] Every SVG is a complete preview with explicit root Master/Layout identity and `native_structure_mode: structured`; authored modes use canonical fixed layers/slots, while mirror preserves source ownership and mechanically expands fixed-layer groups into direct atoms
- [x] Authored `standard` / `fidelity` Layout keys are non-duplicative; mirror keeps distinct source Layout identities even when their current visible contracts are equivalent - [x] Authored `standard` / `fidelity` Layout keys are non-duplicative; mirror keeps distinct source Layout identities even when their current visible contracts are equivalent
- [x] Template creation used the authoring IR; lossless expanded imports remained immutable payload backing for mirror materialization, while `standard` / `fidelity` used helper-generated compact canonical preset groups and `design_spec.md` paint - [x] Template creation used the authoring IR; lossless expanded imports remained immutable payload backing for mirror materialization, while `standard` / `fidelity` used helper-generated compact canonical preset groups and `<design_spec_path>` paint
- [x] Both scopes route bitmaps to `images/` and keep one canonical copy of every imported vector under `icons/imported/` - [x] Both scopes route bitmaps to `images/` and keep one canonical copy of every imported vector under `icons/imported/`
- [ ] **Next step**: Validate assets, export review evidence when requested or required for multiple Masters, then register only library scope - [ ] **Next step**: Validate assets, export review evidence when requested or required for multiple Masters, then register only library scope
``` ```
@@ -105,13 +105,13 @@ an exact authoring preset here.
--- ---
## 3. Escape hatch — `custom` ## 3. Editable `custom` projection
Each coordinated Default Stage-2 direction authors one visible, non-empty `custom` aesthetic whose paragraph names project-specific shape language, composition geometry, decoration density, whitespace, typographic character, and texture — **no HEX, no color names as values**. Use this index to freeze any catalog bases before reading their detail files. A template-backed synthesis stays inside the inherited identity and confirmed application plan. Record the confirmed current aesthetic in the Design Spec first, then project `- visual_style: custom` plus `- visual_style_behavior:`. The 18 fixed styles remain lower-level single-select alternatives; do not create a fourth AI-custom proposal. Each coordinated Default Stage-2 direction authors one visible, non-empty `custom` aesthetic whose paragraph names its executable shape language, composition geometry, decoration density, whitespace, typographic character, and texture — **no HEX, no color names as values**. `custom` is not constrained by its relationship to the catalog: it may use catalog material in any way or none, including carrying one fitting preset unchanged. The three complete directions are plainly different designs; this axis expresses that difference whenever their aesthetics genuinely differ, and catalog bases may coincide. A different name, note, reference count, or palette alone is not another aesthetic. Style behaviors may also coincide when other components carry the direction difference or authoritative user/template truth forbids visual variation; state that boundary in the direction note instead of fabricating difference. Use this index to freeze any catalog bases before reading their detail files. A template-backed direction stays inside the inherited identity and confirmed application plan. Record the confirmed current aesthetic in the Design Spec first, then project `- visual_style: custom` plus `- visual_style_behavior:`. The 18 fixed styles remain lower-level single-select alternatives; do not create a fourth AI-custom proposal.
Quick does not display a candidate spectrum. It reads this index, resolves one preset or custom behavior, then reads only the selected detail files and persists nothing. Quick does not display a candidate spectrum. It reads this index, resolves one preset or custom behavior, then reads only the selected detail files and persists nothing.
**Mandatory — select before detail reading**: Freeze every catalog source actually used from this index, then read only those exact files before writing the behavior. A custom may use zero, one, or many sources: keep one when it owns the whole specialized aesthetic, or include every style that contributes a distinct executable job across shape language, composition, decoration, whitespace, typography, or texture. Reference count has no fixed cap; count is an outcome, not a target. A coherent three-basis direction may assign `swiss-minimal` to grid and whitespace, `soft-rounded` to selective surface contours and elevation, and `editorial` to evidence hierarchy and rules. Default persists every actual id as `visual_style_references`; Quick retains them only in active context. Omit every source whose contribution cannot be stated, never add a second merely to imply synthesis, and do not open candidates for comparison after this gate. A genuinely new aesthetic names and reads no catalog source. **Mandatory — select before detail reading**: Freeze every catalog source actually used from this index, then read only those exact files before writing the behavior. One source may supply the complete aesthetic unchanged; when several are named, each contributes a distinct executable job across shape language, composition, decoration, whitespace, typography, or texture. Reference count has no fixed cap; count is an outcome, not a target. A coherent three-basis direction may assign `swiss-minimal` to grid and whitespace, `soft-rounded` to selective surface contours and elevation, and `editorial` to evidence hierarchy and rules. Default persists every actual id as `visual_style_references`; Quick retains them only in active context. Omit every source whose contribution cannot be stated, never add a second merely to imply synthesis, and do not open candidates for comparison after this gate. A custom using no catalog source names and reads none.
--- ---
@@ -114,7 +114,7 @@ python3 scripts/pptx_template_import.py <template.pptx> --inheritance-mode both
python3 scripts/svg_authoring_view.py <imported-svg-or-dir> -o <output-dir> --projection-kind layered python3 scripts/svg_authoring_view.py <imported-svg-or-dir> -o <output-dir> --projection-kind layered
python3 scripts/svg_authoring_view.py <authoring-dir> --refresh-summary python3 scripts/svg_authoring_view.py <authoring-dir> --refresh-summary
python3 scripts/compact_svg_coordinates.py <template_workspace>/templates --inplace --keep-native-frames python3 scripts/compact_svg_coordinates.py <template_workspace>/templates --inplace --keep-native-frames
python3 scripts/mirror_template_materialize.py <import_workspace> <empty_template_workspace> python3 scripts/mirror_template_materialize.py <import_workspace> <template_workspace>
python3 scripts/template_preview_pptx.py <template_workspace> python3 scripts/template_preview_pptx.py <template_workspace>
python3 scripts/template_preview_pptx.py <legacy_template_workspace> --visual-only python3 scripts/template_preview_pptx.py <legacy_template_workspace> --visual-only
``` ```
@@ -167,7 +167,7 @@ go to `images/`; other referenced source assets go to `templates/assets/`.
The destination must be empty, and the command does not write The destination must be empty, and the command does not write
`templates/design_spec.md`; Template_Designer owns that authored brief. `templates/design_spec.md`; Template_Designer owns that authored brief.
`template_preview_pptx.py` reads a template workspace, exports every public `templates/*.svg` prototype as one structured review slide, and verifies the resulting Master/Layout package. Canonical definition-only `layout_<layout_key>.svg` prototypes are registered as reusable Layouts through internal carrier slides that are removed before publication; they never increase the review deck's visible slide count. This is an on-demand review action: its default output is `exports/<template_id>_template_preview.pptx`, and that directory need not exist before the command runs. It refuses an existing output unless an intentional re-export passes `--force`. `--visual-only` is an explicit migration aid for legacy SVG rosters: it creates a slide-local visual review deck without validating or claiming a reusable Master/Layout contract. This diagnostic path does not require a project `spec_lock.md`; it may retain generic theme/text defaults inside its clean one-Master/one-Layout shell. New structured templates use the default mode when a review deck is requested. `template_preview_pptx.py` reads a template workspace, exports every public `templates/*.svg` prototype as one structured review slide, and verifies the resulting Master/Layout package. In a project root containing Layout and Deck specs, it previews the active Layout roster. Canonical definition-only `layout_<layout_key>.svg` prototypes are registered as reusable Layouts through internal carrier slides that are removed before publication; they never increase the review deck's visible slide count. This is an on-demand review action: its default output is `exports/<template_id>_template_preview.pptx`, and that directory need not exist before the command runs. It refuses an existing output unless an intentional re-export passes `--force`. `--visual-only` is an explicit migration aid for legacy SVG rosters: it creates a slide-local visual review deck without validating or claiming a reusable Master/Layout contract. This diagnostic path does not require a project `spec_lock.md`; it may retain generic theme/text defaults inside its clean one-Master/one-Layout shell. New structured templates use the default mode when a review deck is requested.
Template fill (direct PPTX, no SVG conversion): Template fill (direct PPTX, no SVG conversion):
@@ -275,7 +275,7 @@ python3 scripts/extract_svg_assets.py <layered_svg_dir> --icons-dir <icons_dir>
python3 scripts/extract_svg_assets.py <flat_svg_dir> --icons-dir <icons_dir> --icon-namespace imported --reuse-inventory <layered_inventory.json> --inplace --id-prefix flat python3 scripts/extract_svg_assets.py <flat_svg_dir> --icons-dir <icons_dir> --icon-namespace imported --reuse-inventory <layered_inventory.json> --inplace --id-prefix flat
python3 scripts/extract_svg_pictures.py "<svg_file>" --select "<group_id>" --resource-root "<workspace>" --images-dir "<picture_assets_dir>" --inplace # optional create-template normalization: one selected group -> one SVG picture python3 scripts/extract_svg_pictures.py "<svg_file>" --select "<group_id>" --resource-root "<workspace>" --images-dir "<picture_assets_dir>" --inplace # optional create-template normalization: one selected group -> one SVG picture
python3 scripts/compact_svg_coordinates.py <template_workspace>/templates --inplace --keep-native-frames python3 scripts/compact_svg_coordinates.py <template_workspace>/templates --inplace --keep-native-frames
python3 scripts/mirror_template_materialize.py <import_workspace> <empty_template_workspace> # Type A mirror only python3 scripts/mirror_template_materialize.py <import_workspace> <template_workspace> # Type A mirror only; destination owns no roster
``` ```
`extract_svg_assets.py` fingerprints each extracted subtree before generated-ID `extract_svg_assets.py` fingerprints each extracted subtree before generated-ID
@@ -198,22 +198,74 @@ def _safe_template_id(template_id: object) -> bool:
) )
def _template_design_spec_path(workspace_root: Path) -> Path: _TEMPLATE_SPEC_NAME_RE = re.compile(
"""Return the current or legacy Design Spec for one workspace root.""" r'design_spec\.(?P<kind>brand|style|layout|deck)\.(?P<id>[^/\\]+)\.md'
current = workspace_root / 'templates' / 'design_spec.md' )
def _template_design_specs(workspace_root: Path) -> list[Path]:
"""Return every Design Spec one template workspace root exposes.
A single-kind workspace keeps the exact ``templates/design_spec.md``, and a
compatible legacy-flat root keeps ``design_spec.md`` beside its pages. A
multi-kind workspace keeps one ``templates/design_spec.<kind>.<id>.md`` per
kind the same shape the apply stage installs into a consuming project so
one root can carry, for example, a Brand plus a Style. Order is stable so
candidate keys and the options digest do not depend on directory listing
order.
"""
templates_dir = workspace_root / 'templates'
current = templates_dir / 'design_spec.md'
multi = sorted(
path
for path in templates_dir.glob('design_spec.*.md')
if _TEMPLATE_SPEC_NAME_RE.fullmatch(path.name)
) if templates_dir.is_dir() else []
if current.is_file() and multi:
raise ValueError(
'template workspace mixes design_spec.md with kind-qualified specs '
f'({", ".join(path.name for path in multi)}): {workspace_root}; '
'rename the bare spec to design_spec.<kind>.<id>.md'
)
if current.is_file(): if current.is_file():
return current return [current]
if multi:
return multi
legacy = workspace_root / 'design_spec.md' legacy = workspace_root / 'design_spec.md'
if legacy.is_file(): if legacy.is_file():
return legacy return [legacy]
raise ValueError( raise ValueError(
'template workspace is missing templates/design_spec.md ' 'template workspace is missing templates/design_spec.md, '
f'or legacy design_spec.md: {workspace_root}' 'templates/design_spec.<kind>.<id>.md, or legacy design_spec.md: '
f'{workspace_root}'
) )
def _template_kind_from_spec(spec_path: Path) -> str: def _template_kind_from_spec(spec_path: Path) -> str:
"""Read one supported top-level ``kind`` from Design Spec frontmatter.""" """Read one supported top-level ``kind`` from Design Spec frontmatter.
Frontmatter stays the single truth. When the filename also carries a kind,
both its kind and id must agree; a mismatch is a corrupt workspace rather
than a precedence question.
"""
name_match = _TEMPLATE_SPEC_NAME_RE.fullmatch(spec_path.name)
if name_match is not None:
try:
from register_template import (
SpecParseError,
validate_qualified_spec_identity,
)
declared_kind, _filename_id, _frontmatter, _body = (
validate_qualified_spec_identity(spec_path)
)
except ImportError as exc:
raise ValueError(
f'Qualified Design Spec validator could not be imported: {exc}'
) from exc
except (OSError, SpecParseError) as exc:
raise ValueError(str(exc)) from exc
return declared_kind
try: try:
lines = spec_path.read_text(encoding='utf-8-sig').splitlines() lines = spec_path.read_text(encoding='utf-8-sig').splitlines()
except OSError as exc: except OSError as exc:
@@ -313,7 +365,7 @@ def _read_template_options_input(confirm_dir: Path) -> tuple[dict, list[Path]]:
) )
if not root.is_dir(): if not root.is_dir():
raise ValueError(f'explicit workspace root is not a directory: {canonical}') raise ValueError(f'explicit workspace root is not a directory: {canonical}')
_template_design_spec_path(root) _template_design_specs(root)
seen.add(canonical) seen.add(canonical)
roots.append(root) roots.append(root)
return data, roots return data, roots
@@ -404,25 +456,39 @@ def _build_template_options(confirm_dir: Path) -> tuple[dict, dict[str, dict]]:
suggested_keys.append(registered['key']) suggested_keys.append(registered['key'])
continue continue
digest = hashlib.sha256(canonical_root.encode('utf-8')).hexdigest() digest = hashlib.sha256(canonical_root.encode('utf-8')).hexdigest()
key = f'explicit:{digest}' root_specs = [
if key in candidates: (spec, _template_kind_from_spec(spec))
raise ValueError(f'duplicate template candidate key: {key}') for spec in _template_design_specs(root)
kind = _template_kind_from_spec(_template_design_spec_path(root)) ]
candidate = { root_kinds = [kind for _spec, kind in root_specs]
'key': key, duplicate_kinds = sorted({
'source': 'explicit', kind for kind in root_kinds if root_kinds.count(kind) > 1
'kind': kind, })
'label': root.name or canonical_root, if duplicate_kinds:
'workspace_root': canonical_root, raise ValueError(
} 'workspace root exposes the same kind more than once '
explicit.append(candidate) f'({", ".join(duplicate_kinds)}): {canonical_root}'
candidates[key] = candidate )
suggested_keys.append(key) for spec, kind in root_specs:
key = f'explicit:{digest}:{kind}'
if key in candidates:
raise ValueError(f'duplicate template candidate key: {key}')
candidate = {
'key': key,
'source': 'explicit',
'kind': kind,
'label': root.name or canonical_root,
'workspace_root': canonical_root,
}
explicit.append(candidate)
candidates[key] = candidate
suggested_keys.append(key)
# One supplied exact root is an unambiguous convenience default. Multiple # One supplied exact root is an unambiguous convenience default, including
# roots are candidates for the single-select controls, not an instruction # a multi-kind root whose kinds compose rather than compete. Several roots
# to select all of them. # are candidates for the single-select controls, not an instruction to
preselected_keys = suggested_keys if len(suggested_keys) == 1 else [] # select all of them.
preselected_keys = suggested_keys if len(explicit_roots) == 1 else []
response = { response = {
'schema_version': TEMPLATE_SCHEMA_VERSION, 'schema_version': TEMPLATE_SCHEMA_VERSION,
@@ -515,9 +581,9 @@ def _validate_template_selection(data: dict) -> None:
if not isinstance(selection_sha256, str) or not re.fullmatch(r'[0-9a-f]{64}', selection_sha256): if not isinstance(selection_sha256, str) or not re.fullmatch(r'[0-9a-f]{64}', selection_sha256):
raise ValueError(f'{TEMPLATE_SELECTION_NAME} selection_sha256 is invalid') raise ValueError(f'{TEMPLATE_SELECTION_NAME} selection_sha256 is invalid')
seen_roots = set() seen_root_kinds = set()
seen_library_kinds = set() seen_kinds: set[str] = set()
explicit_count = 0 explicit_roots_seen: dict[str, set[str]] = {}
for index, selection in enumerate(selections): for index, selection in enumerate(selections):
if not isinstance(selection, dict): if not isinstance(selection, dict):
raise ValueError( raise ValueError(
@@ -536,22 +602,16 @@ def _validate_template_selection(data: dict) -> None:
expected_keys = {'source', 'kind', 'workspace_root'} expected_keys = {'source', 'kind', 'workspace_root'}
if source == 'library': if source == 'library':
expected_keys.add('id') expected_keys.add('id')
if kind in seen_library_kinds:
raise ValueError(
'template selection allows at most one library workspace '
f'for kind {kind!r}'
)
seen_library_kinds.add(kind)
if not _safe_template_id(selection.get('id')): if not _safe_template_id(selection.get('id')):
raise ValueError( raise ValueError(
f'{TEMPLATE_SELECTION_NAME} selections[{index}] has invalid id' f'{TEMPLATE_SELECTION_NAME} selections[{index}] has invalid id'
) )
else: if kind in seen_kinds:
explicit_count += 1 raise ValueError(
if explicit_count > 1: 'template selection allows at most one workspace for kind '
raise ValueError( f'{kind!r}'
'template selection allows at most one explicit workspace' )
) seen_kinds.add(kind)
if set(selection) != expected_keys: if set(selection) != expected_keys:
raise ValueError( raise ValueError(
f'{TEMPLATE_SELECTION_NAME} selections[{index}] has invalid fields' f'{TEMPLATE_SELECTION_NAME} selections[{index}] has invalid fields'
@@ -568,12 +628,20 @@ def _validate_template_selection(data: dict) -> None:
f'{TEMPLATE_SELECTION_NAME} selections[{index}] ' f'{TEMPLATE_SELECTION_NAME} selections[{index}] '
'workspace_root must be a canonical absolute path' 'workspace_root must be a canonical absolute path'
) )
if workspace_root in seen_roots: if source == 'explicit':
# One explicit workspace root may contribute several kinds, so the
# cap counts roots rather than selections.
explicit_roots_seen.setdefault(workspace_root, set()).add(kind)
if len(explicit_roots_seen) > 1:
raise ValueError(
'template selection allows at most one explicit workspace'
)
if (workspace_root, kind) in seen_root_kinds:
raise ValueError( raise ValueError(
f'{TEMPLATE_SELECTION_NAME} contains duplicate workspace root: ' f'{TEMPLATE_SELECTION_NAME} contains duplicate workspace root '
f'{workspace_root}' f'for kind {kind!r}: {workspace_root}'
) )
seen_roots.add(workspace_root) seen_root_kinds.add((workspace_root, kind))
if not isinstance(data.get('confirmed_at'), str) or not data['confirmed_at']: if not isinstance(data.get('confirmed_at'), str) or not data['confirmed_at']:
raise ValueError( raise ValueError(
f'{TEMPLATE_SELECTION_NAME} confirmed_at must be a non-empty string' f'{TEMPLATE_SELECTION_NAME} confirmed_at must be a non-empty string'
@@ -587,6 +655,32 @@ def _validate_template_selection(data: dict) -> None:
raise ValueError(f'{TEMPLATE_SELECTION_NAME} selection_sha256 does not match') raise ValueError(f'{TEMPLATE_SELECTION_NAME} selection_sha256 does not match')
def _validate_explicit_root_closure(
selections: list[dict],
candidates: dict[str, dict],
) -> None:
"""Require every selected explicit root to contribute all exposed kinds."""
exposed: dict[str, set[str]] = {}
for candidate in candidates.values():
if candidate['source'] == 'explicit':
exposed.setdefault(candidate['workspace_root'], set()).add(
candidate['kind']
)
chosen: dict[str, set[str]] = {}
for selection in selections:
if selection['source'] == 'explicit':
chosen.setdefault(selection['workspace_root'], set()).add(
selection['kind']
)
for root, kinds in chosen.items():
missing = sorted(exposed.get(root, set()) - kinds)
if missing:
raise ValueError(
f'{TEMPLATE_SELECTION_NAME} selects workspace root {root} '
f'without every kind it exposes; missing: {", ".join(missing)}'
)
def _read_template_selection(selection_file: Path) -> dict: def _read_template_selection(selection_file: Path) -> dict:
"""Read a selection and revalidate it against current indexed options.""" """Read a selection and revalidate it against current indexed options."""
data = _read_json_object(selection_file) data = _read_json_object(selection_file)
@@ -611,6 +705,8 @@ def _read_template_selection(selection_file: Path) -> dict:
raise ValueError( raise ValueError(
f'{TEMPLATE_SELECTION_NAME} references an unavailable candidate' f'{TEMPLATE_SELECTION_NAME} references an unavailable candidate'
) )
_validate_explicit_root_closure(data['selections'], candidates)
return data return data
@@ -685,7 +781,7 @@ def _installed_template_specs(project_path: Path) -> list[Path]:
return sorted( return sorted(
path path
for path in (project_path / 'templates').glob('design_spec.*.md') for path in (project_path / 'templates').glob('design_spec.*.md')
if path.is_file() if path.is_file() and _TEMPLATE_SPEC_NAME_RE.fullmatch(path.name)
) )
@@ -890,6 +986,7 @@ def _resolve_template_confirmation(
'confirmed_at': time.strftime('%Y-%m-%dT%H:%M:%S'), 'confirmed_at': time.strftime('%Y-%m-%dT%H:%M:%S'),
} }
_validate_template_selection(receipt) _validate_template_selection(receipt)
_validate_explicit_root_closure(selections, candidates)
return receipt return receipt
@@ -24,6 +24,7 @@
btn_confirm_final_plan: "Confirm final plan →", btn_confirm_final_plan: "Confirm final plan →",
deriving: "Generating the downstream options from your choices…", deriving: "Generating the downstream options from your choices…",
template_selection_required: "Choose free design or use templates. When using templates, select at least one workspace.", template_selection_required: "Choose free design or use templates. When using templates, select at least one workspace.",
template_selection_conflict: "Choose at most one workspace per kind.",
connection_lost: "Connection to the confirm server was interrupted; retrying. If this keeps failing, return to the chat for confirmation.", connection_lost: "Connection to the confirm server was interrupted; retrying. If this keeps failing, return to the chat for confirmation.",
confirmed_title: "✓ Confirmed", confirmed_title: "✓ Confirmed",
confirmed_hint: "Your choices are saved. You can close this page and return to the chat.", confirmed_hint: "Your choices are saved. You can close this page and return to the chat.",
@@ -35,9 +36,9 @@
template_use_title: "Use templates", template_use_title: "Use templates",
template_use_desc: "Select one or more reusable Brand, Style, Layout, Deck, or specified workspaces.", template_use_desc: "Select one or more reusable Brand, Style, Layout, Deck, or specified workspaces.",
sec_template_library: "Template combination", sec_template_library: "Template combination",
template_library_hint: "Choose at most one registered template for each type. Brand, Style, Layout, and Deck can be combined.", template_library_hint: "Choose at most one workspace per kind. All four kinds can combine; Layout takes structural precedence over Deck.",
sec_template_explicit: "Specified templates", sec_template_explicit: "Specified templates",
template_explicit_hint: "Choose at most one exact workspace supplied for this run. Its source path is shown for verification.", template_explicit_hint: "Choose at most one exact workspace supplied for this run; every kind it contains is applied. Its source path is shown for verification.",
template_kind_brand: "Brand", template_kind_brand: "Brand",
template_kind_style: "Style", template_kind_style: "Style",
template_kind_layout: "Layout", template_kind_layout: "Layout",
@@ -206,6 +207,7 @@
btn_confirm_final_plan: "最終プランを確定 →", btn_confirm_final_plan: "最終プランを確定 →",
deriving: "選択内容をもとに後続の選択肢を生成しています…", deriving: "選択内容をもとに後続の選択肢を生成しています…",
template_selection_required: "自由デザインまたはテンプレート利用を選んでください。テンプレート利用時は、1つ以上のワークスペースを選択してください。", template_selection_required: "自由デザインまたはテンプレート利用を選んでください。テンプレート利用時は、1つ以上のワークスペースを選択してください。",
template_selection_conflict: "種類ごとにワークスペースを1件まで選択してください。",
connection_lost: "確認ページのサーバー接続が中断されました。再試行しています。失敗が続く場合はチャットで確認してください。", connection_lost: "確認ページのサーバー接続が中断されました。再試行しています。失敗が続く場合はチャットで確認してください。",
confirmed_title: "✓ 確定しました", confirmed_title: "✓ 確定しました",
confirmed_hint: "選択内容を保存しました。このページを閉じてチャットに戻ってください。", confirmed_hint: "選択内容を保存しました。このページを閉じてチャットに戻ってください。",
@@ -217,9 +219,9 @@
template_use_title: "テンプレートを使用", template_use_title: "テンプレートを使用",
template_use_desc: "Brand、Style、Layout、Deck、または指定ワークスペースから1つ以上選択します。", template_use_desc: "Brand、Style、Layout、Deck、または指定ワークスペースから1つ以上選択します。",
sec_template_library: "テンプレートの組み合わせ", sec_template_library: "テンプレートの組み合わせ",
template_library_hint: "登録済みテンプレートは種類ごとに1件まで選択でき、Brand、Style、LayoutDeck を組み合わせられます。", template_library_hint: "種類ごとにワークスペースを1件まで選択できます。4種類はすべて組み合わせ可能で、構造は LayoutDeck より優先されます。",
sec_template_explicit: "指定テンプレート", sec_template_explicit: "指定テンプレート",
template_explicit_hint: "この実行で指定された正確なワークスペースを1件まで選択できます。確認用に参照元パスを表示します。", template_explicit_hint: "この実行で指定された正確なワークスペースを1件まで選択でき、そこに含まれる種別はすべて適用されます。確認用に参照元パスを表示します。",
template_kind_brand: "Brand", template_kind_brand: "Brand",
template_kind_style: "Style", template_kind_style: "Style",
template_kind_layout: "Layout", template_kind_layout: "Layout",
@@ -388,6 +390,7 @@
btn_confirm_final_plan: "确认最终方案 →", btn_confirm_final_plan: "确认最终方案 →",
deriving: "正在根据你的选择生成下游选项…", deriving: "正在根据你的选择生成下游选项…",
template_selection_required: "请选择自由设计或使用模板;选择使用模板时,至少选择一个工作区。", template_selection_required: "请选择自由设计或使用模板;选择使用模板时,至少选择一个工作区。",
template_selection_conflict: "每种模板最多选择一个工作区。",
connection_lost: "确认页服务连接中断,正在重试;如果持续失败,请回到聊天窗口走聊天确认。", connection_lost: "确认页服务连接中断,正在重试;如果持续失败,请回到聊天窗口走聊天确认。",
confirmed_title: "✓ 已确认", confirmed_title: "✓ 已确认",
confirmed_hint: "选择已保存,可关闭此页并回到聊天窗口。", confirmed_hint: "选择已保存,可关闭此页并回到聊天窗口。",
@@ -399,9 +402,9 @@
template_use_title: "使用模板", template_use_title: "使用模板",
template_use_desc: "选择一个或多个 Brand、Style、Layout、Deck 或指定工作区。", template_use_desc: "选择一个或多个 Brand、Style、Layout、Deck 或指定工作区。",
sec_template_library: "模板组合", sec_template_library: "模板组合",
template_library_hint: "每种已注册模板最多选择一个Brand、Style、Layout、Deck 可以组合使用。", template_library_hint: "每种模板最多选择一个工作区;四种模板均可组合,结构由 Layout 优先于 Deck。",
sec_template_explicit: "指定模板", sec_template_explicit: "指定模板",
template_explicit_hint: "本次运行明确提供的精确工作区最多选择一个;显示来源路径供你核对。", template_explicit_hint: "本次运行明确提供的精确工作区最多选择一个,它包含的每一类都会被采用;显示来源路径供你核对。",
template_kind_brand: "Brand", template_kind_brand: "Brand",
template_kind_style: "Style", template_kind_style: "Style",
template_kind_layout: "Layout", template_kind_layout: "Layout",
@@ -570,6 +573,7 @@
btn_confirm_final_plan: "確認最終方案 →", btn_confirm_final_plan: "確認最終方案 →",
deriving: "正在根據你的選擇生成下游選項…", deriving: "正在根據你的選擇生成下游選項…",
template_selection_required: "請選擇自由設計或使用範本;選擇使用範本時,至少選擇一個工作區。", template_selection_required: "請選擇自由設計或使用範本;選擇使用範本時,至少選擇一個工作區。",
template_selection_conflict: "每種範本最多選擇一個工作區。",
connection_lost: "確認頁服務連線中斷,正在重試;如果持續失敗,請回到聊天視窗走聊天確認。", connection_lost: "確認頁服務連線中斷,正在重試;如果持續失敗,請回到聊天視窗走聊天確認。",
confirmed_title: "✓ 已確認", confirmed_title: "✓ 已確認",
confirmed_hint: "選擇已儲存,可關閉此頁並回到聊天視窗。", confirmed_hint: "選擇已儲存,可關閉此頁並回到聊天視窗。",
@@ -581,9 +585,9 @@
template_use_title: "使用範本", template_use_title: "使用範本",
template_use_desc: "選擇一個或多個 Brand、Style、Layout、Deck 或指定工作區。", template_use_desc: "選擇一個或多個 Brand、Style、Layout、Deck 或指定工作區。",
sec_template_library: "範本組合", sec_template_library: "範本組合",
template_library_hint: "每種已註冊範本最多選擇一個Brand、Style、Layout、Deck 可以組合使用。", template_library_hint: "每種範本最多選擇一個工作區;四種範本均可組合,結構由 Layout 優先於 Deck。",
sec_template_explicit: "指定範本", sec_template_explicit: "指定範本",
template_explicit_hint: "本次執行明確提供的精確工作區最多選擇一個;顯示來源路徑供你核對。", template_explicit_hint: "本次執行明確提供的精確工作區最多選擇一個,它包含的每一類都會被採用;顯示來源路徑供你核對。",
template_kind_brand: "Brand", template_kind_brand: "Brand",
template_kind_style: "Style", template_kind_style: "Style",
template_kind_layout: "Layout", template_kind_layout: "Layout",
@@ -1115,14 +1119,18 @@
if (!candidate || !slot) { if (!candidate || !slot) {
throw new Error("Invalid preselected template key: " + key); throw new Error("Invalid preselected template key: " + key);
} }
if (TEMPLATE_SELECTIONS[slot]) { var value = slot === "explicit" ? (candidate.workspace_root || "") : key;
if (TEMPLATE_SELECTIONS[slot] && TEMPLATE_SELECTIONS[slot] !== value) {
throw new Error("Multiple preselected templates for slot: " + slot); throw new Error("Multiple preselected templates for slot: " + slot);
} }
TEMPLATE_SELECTIONS[slot] = key; TEMPLATE_SELECTIONS[slot] = value;
}); });
// Publish options before syncing: expanding an explicit root into its
// kinds reads TEMPLATE_OPTIONS, so a preselected root would otherwise
// resolve to zero keys on first load.
TEMPLATE_OPTIONS = normalized;
syncTemplateSelectionState(); syncTemplateSelectionState();
TEMPLATE_MODE = normalized.default_mode; TEMPLATE_MODE = normalized.default_mode;
TEMPLATE_OPTIONS = normalized;
} }
function emptyTemplateSelections() { function emptyTemplateSelections() {
@@ -1146,11 +1154,42 @@
return null; return null;
} }
function explicitCandidatesForRoot(workspaceRoot) {
var root = String(workspaceRoot || "");
if (!root) return [];
return ((TEMPLATE_OPTIONS && TEMPLATE_OPTIONS.explicit) || [])
.filter(function (candidate) { return candidate.workspace_root === root; });
}
// One supplied path is one workspace, and its kinds compose rather than
// compete. Selecting that root therefore takes every kind it exposes.
function explicitRootOptions() {
var roots = [];
var seen = Object.create(null);
((TEMPLATE_OPTIONS && TEMPLATE_OPTIONS.explicit) || []).forEach(function (candidate) {
var root = candidate.workspace_root || "";
if (!root || seen[root]) return;
seen[root] = true;
var kinds = explicitCandidatesForRoot(root).map(function (item) {
return templateKindLabel(item.kind);
});
roots.push({
key: root,
label: candidate.label || root,
summary: kinds.join(" + "),
workspace_root: root
});
});
return roots;
}
function syncTemplateSelectionState() { function syncTemplateSelectionState() {
TEMPLATE_SELECTED_KEYS = TEMPLATE_KINDS.map(function (kind) { TEMPLATE_SELECTED_KEYS = TEMPLATE_KINDS.map(function (kind) {
return TEMPLATE_SELECTIONS[kind]; return TEMPLATE_SELECTIONS[kind];
}); });
TEMPLATE_SELECTED_KEYS.push(TEMPLATE_SELECTIONS.explicit); explicitCandidatesForRoot(TEMPLATE_SELECTIONS.explicit).forEach(function (candidate) {
TEMPLATE_SELECTED_KEYS.push(candidate.key);
});
TEMPLATE_SELECTED_KEYS = TEMPLATE_SELECTED_KEYS.filter(Boolean); TEMPLATE_SELECTED_KEYS = TEMPLATE_SELECTED_KEYS.filter(Boolean);
} }
@@ -1279,7 +1318,7 @@
grid.appendChild(renderTemplateSelectField( grid.appendChild(renderTemplateSelectField(
"explicit", "explicit",
t("template_source_explicit"), t("template_source_explicit"),
TEMPLATE_OPTIONS.explicit || [] explicitRootOptions()
)); ));
panel.appendChild(grid); panel.appendChild(grid);
sec.appendChild(panel); sec.appendChild(panel);
@@ -1291,8 +1330,7 @@
var path = document.getElementById("template-explicit-path"); var path = document.getElementById("template-explicit-path");
var value = document.getElementById("template-explicit-path-value"); var value = document.getElementById("template-explicit-path-value");
if (!path || !value) return; if (!path || !value) return;
var candidate = templateCandidateByKey(TEMPLATE_SELECTIONS.explicit); var workspaceRoot = TEMPLATE_SELECTIONS.explicit || "";
var workspaceRoot = candidate && candidate.workspace_root ? candidate.workspace_root : "";
path.hidden = !workspaceRoot; path.hidden = !workspaceRoot;
value.textContent = workspaceRoot; value.textContent = workspaceRoot;
value.title = workspaceRoot; value.title = workspaceRoot;
@@ -4231,8 +4269,22 @@
if (!valid) { if (!valid) {
document.getElementById("confirm-status").textContent = document.getElementById("confirm-status").textContent =
t("template_selection_required"); t("template_selection_required");
return false;
} }
return valid; if (TEMPLATE_MODE === "templates") {
var seenKinds = Object.create(null);
for (var i = 0; i < TEMPLATE_SELECTED_KEYS.length; i += 1) {
var candidate = templateCandidateByKey(TEMPLATE_SELECTED_KEYS[i]);
if (!candidate) continue;
if (seenKinds[candidate.kind]) {
document.getElementById("confirm-status").textContent =
t("template_selection_conflict");
return false;
}
seenKinds[candidate.kind] = true;
}
}
return true;
} }
function submitStage1() { function submitStage1() {
@@ -118,7 +118,7 @@ python3 scripts/confirm_ui/server.py <project_path> --shutdown # Step 4 clean
- Confirm UI and live preview prefer the same memorable base port but keep separate processes and project-local locks (`.confirm_ui.lock` vs `live_preview/lock.json`). Normal Step 4 cleanup releases the confirm port before Step 6; concurrent projects may use different ports. - Confirm UI and live preview prefer the same memorable base port but keep separate processes and project-local locks (`.confirm_ui.lock` vs `live_preview/lock.json`). Normal Step 4 cleanup releases the confirm port before Step 6; concurrent projects may use different ports.
- `--daemon` starts the Flask process in the background and returns after the health check. Every Default UI run launches directly into combined Stage 1 and keeps the same process live through final Stage 2. The wait budget defaults to **590 s** (`--wait-timeout`); on timeout the detached server remains live, and the caller re-checks both Stage-1 receipts before chat fallback. - `--daemon` starts the Flask process in the background and returns after the health check. Every Default UI run launches directly into combined Stage 1 and keeps the same process live through final Stage 2. The wait budget defaults to **590 s** (`--wait-timeout`); on timeout the detached server remains live, and the caller re-checks both Stage-1 receipts before chat fallback.
- `--wait-only` attaches to the page opened by `--daemon` and blocks until the requested receipt. If it is already persisted, the command returns before recovery, so a fast submit between launch, chat handoff, and wait is not lost. Otherwise, if the recorded server died, it restarts on the recorded/default port. Use `stage1` for the combined communication/template submission and the default/final wait for Stage 2. - `--wait-only` attaches to the page opened by `--daemon` and blocks until the requested receipt. If it is already persisted, the command returns before recovery, so a fast submit between launch, chat handoff, and wait is not lost. Otherwise, if the recorded server died, it restarts on the recorded/default port. Use `stage1` for the combined communication/template submission and the default/final wait for Stage 2.
- `--complete-template-selection` is agent-only. It validates the Stage-1 sidecar and writes the bound `template_handoff.json`; template mode additionally requires project-local `templates/design_spec.md`. Run it after installation/free-design closure and before writing Stage 2. `--reset-template-selection` removes exactly `template_options.json`, `template_selection.json`, and `template_handoff.json`; it does not alter Strategist files, installed template content, or `result.json`. The old `--*-template-phase` names are not aliases. - `--complete-template-selection` is agent-only. It validates the Stage-1 sidecar and writes the bound `template_handoff.json`; template mode additionally requires at least one project-local `templates/design_spec.<kind>.<id>.md`. Run it after installation/free-design closure and before writing Stage 2. `--reset-template-selection` removes exactly `template_options.json`, `template_selection.json`, and `template_handoff.json`; it does not alter Strategist files, installed template content, or `result.json`. The old `--*-template-phase` names are not aliases.
- `--shutdown` stops a confirm server left running for this project and exits — **idempotent** (a no-op when nothing is running). Tries a graceful `/api/shutdown`, falls back to killing the recorded pid, then clears the lock. Generate Step 4 runs this on every path so the selected port is released before live preview starts. - `--shutdown` stops a confirm server left running for this project and exits — **idempotent** (a no-op when nothing is running). Tries a graceful `/api/shutdown`, falls back to killing the recorded pid, then clears the lock. Generate Step 4 runs this on every path so the selected port is released before live preview starts.
- Every fresh UI run starts with `--reset-template-selection`, then writes valid `<project_path>/confirm_ui/template_options.json` and a newer `recommendations.stage1.json`; `explicit_workspace_roots` is an empty array when no exact root was supplied. Stage 1 writes the bound selection and communication result together. Stage 2 is exposed only when the matching handoff is newer than that selection and its recommendation is newer than the handoff. `--shutdown` needs neither input. - Every fresh UI run starts with `--reset-template-selection`, then writes valid `<project_path>/confirm_ui/template_options.json` and a newer `recommendations.stage1.json`; `explicit_workspace_roots` is an empty array when no exact root was supplied. Stage 1 writes the bound selection and communication result together. Stage 2 is exposed only when the matching handoff is newer than that selection and its recommendation is newer than the handoff. `--shutdown` needs neither input.
- Per-project lock at `<project_path>/.confirm_ui.lock` — duplicate launches are refused; stale locks (dead pid) are overwritten. - Per-project lock at `<project_path>/.confirm_ui.lock` — duplicate launches are refused; stale locks (dead pid) are overwritten.
@@ -165,8 +165,10 @@ separate artifact from the Strategist contract. Its files live under
Ordinary requests use `free_design`; explicit template intent or any supplied Ordinary requests use `free_design`; explicit template intent or any supplied
exact root uses `templates`. It initializes the UI but never locks the user. exact root uses `templates`. It initializes the UI but never locks the user.
- `explicit_workspace_roots` is required even when empty. Every item is a - `explicit_workspace_roots` is required even when empty. Every item is a
unique absolute path resolving to an existing directory with unique absolute path resolving to an existing directory with a library
`templates/design_spec.md` or compatible legacy `design_spec.md`. `templates/design_spec.md`, one or more project-qualified
`templates/design_spec.<kind>.<id>.md`, or compatible legacy
`design_spec.md`.
- The array supplies candidates for the one specified-root dropdown; it does - The array supplies candidates for the one specified-root dropdown; it does
not authorize selecting several explicit roots in one confirmation. not authorize selecting several explicit roots in one confirmation.
- Do not write library entries into this file. The server reads only - Do not write library entries into this file. The server reads only
@@ -222,10 +224,11 @@ candidate controls: Brand, Style, Layout, and Deck each have one registered
single-select dropdown, and Specified has one explicit-root single-select single-select dropdown, and Specified has one explicit-root single-select
dropdown. Every dropdown includes `None`; template mode cannot submit until at dropdown. Every dropdown includes `None`; template mode cannot submit until at
least one is non-empty. Free design clears all dropdowns. Registered kinds may least one is non-empty. Free design clears all dropdowns. Registered kinds may
be combined, but each contributes at most one root and the specified channel at be combined, and the complete selection contains at most one contribution per
most one. Because an explicit candidate carries its parsed kind, it may coexist kind. Layout and Deck may coexist; Layout takes structural precedence. The specified channel contributes at
with one registered root of that kind and enter the two-workspace same-kind most one root, selected atomically with every kind it exposes; it can coexist
conflict gate. Source provenance never grants priority. only with registered roots of non-overlapping kinds. Source provenance never
grants priority.
### Output — `template_selection.json` (written with Stage 1) ### Output — `template_selection.json` (written with Stage 1)
@@ -258,23 +261,27 @@ conflict gate. Source provenance never grants priority.
at least one selection. Roots are unique canonical absolute paths. A library at least one selection. Roots are unique canonical absolute paths. A library
selection contains exactly `source`, `kind`, `id`, and `workspace_root`; an selection contains exactly `source`, `kind`, `id`, and `workspace_root`; an
explicit selection contains exactly `source`, `kind`, and `workspace_root`. explicit selection contains exactly `source`, `kind`, and `workspace_root`.
There is at most one library selection per kind and at most one explicit There is at most one explicit workspace **root** overall. The unit of choice is
selection overall; cross-kind composition remains valid, and one explicit plus the root, not the kind: the browser's specified-path control lists roots, and
one library selection may share a kind. The browser selecting one emits a selection for every kind that root exposes. Across those
cannot submit arbitrary paths because the server resolves posted keys against emitted selections and all library choices, each kind appears at most once.
the catalog it just built. `options_sha256` binds the receipt to the current Layout and Deck may coexist; downstream installation gives Layout structural
input, four index files, and resolved candidates. `selection_sha256` binds the precedence. The browser cannot submit arbitrary paths
mode and canonical sorted selections to that option hash. Every receipt read because the server resolves posted keys against the catalog it just built.
rebuilds the catalog and rejects option/index drift. `options_sha256` binds the receipt to the current input, four index files, and
resolved candidates. `selection_sha256` binds the mode and canonical sorted
selections to that option hash. Every receipt read rebuilds the catalog and
rejects option/index drift or an incomplete explicit-root bundle.
The Stage-1 submission writes this receipt and the Stage-1 `result.json` The Stage-1 submission writes this receipt and the Stage-1 `result.json`
together. Generate reads both exactly once after `--wait-only --wait-stage together. Generate reads both exactly once after `--wait-only --wait-stage
stage1` returns. Free design skips installation. Template mode runs stage1` returns. Free design skips installation. Template mode runs
`apply-template-workspace` against all selected roots and waits for complete `apply-template-workspace` against all selected roots and waits for complete
project-local installation. Only then does the agent complete the project-local installation. Only then does the agent complete the
handoff below. Installation copies each selected spec separately; Stage 2 handoff below. Installation validates and maps each distinct root once while
resolves segment ownership and current-project fit from the installed set. Strategist never preserving its separate specs; Stage 2 resolves segment ownership and
reads the source roots. current-project fit from the installed set. Strategist never reads the source
roots.
### Agent handoff — `template_handoff.json` ### Agent handoff — `template_handoff.json`
@@ -313,11 +320,11 @@ template-selection receipt.
- **Closed enumerable** — PPT reading mode (`delivery_purpose` compatibility key), generation mode / refine spec, plus AI source only when image usage includes `ai`. These have no Custom box; out-of-catalog values snap back to the recommended option. - **Closed enumerable** — PPT reading mode (`delivery_purpose` compatibility key), generation mode / refine spec, plus AI source only when image usage includes `ai`. These have no Custom box; out-of-catalog values snap back to the recommended option.
- **Proactive execution booleans** — Final Stage 2 carries top-level `proactive_speaker_notes`, `proactive_custom_animations`, and `proactive_narration_audio` values. Defaults are `true`, `false`, and `false`, respectively. They control what the Agent does proactively only when the user has not explicitly instructed otherwise; the latest explicit user instruction always wins. These three values are raw confirmation evidence: the UI and server neither couple nor rewrite them, and every boolean combination is valid. When narration audio is enabled, Strategist later resolves the effective Speaker Notes outcome to enabled and records `Narration Audio dependency` as its Design Spec provenance. Disabling proactive custom animation does not suppress the Strategist's advisory motion recommendations. - **Proactive execution booleans** — Final Stage 2 carries top-level `proactive_speaker_notes`, `proactive_custom_animations`, and `proactive_narration_audio` values. Defaults are `true`, `false`, and `false`, respectively. They control what the Agent does proactively only when the user has not explicitly instructed otherwise; the latest explicit user instruction always wins. These three values are raw confirmation evidence: the UI and server neither couple nor rewrite them, and every boolean combination is valid. When narration audio is enabled, Strategist later resolves the effective Speaker Notes outcome to enabled and records `Narration Audio dependency` as its Design Spec provenance. Disabling proactive custom animation does not suppress the Strategist's advisory motion recommendations.
- **Open prose**`audience`, `communication_intent`, `audience_outcome`, `core_message`, `delivery_context`, `artifact_afterlife`, `content_divergence`, and `page_count`. `communication_intent` may carry several purposes plus priority / sequence; common paths appear only as help text. `delivery_context` states one primary presenter-led / reader-led / hybrid / recorded-self-running context plus optional secondary use; a hybrid recommendation names which context leads. `content_divergence` is the source-treatment axis. `page_count` may be a range here; Strategist resolves the exact §IX roster, leaving Executor no pagination latitude. - **Open prose**`audience`, `communication_intent`, `audience_outcome`, `core_message`, `delivery_context`, `artifact_afterlife`, `content_divergence`, and `page_count`. `communication_intent` may carry several purposes plus priority / sequence; common paths appear only as help text. `delivery_context` states one primary presenter-led / reader-led / hybrid / recorded-self-running context plus optional secondary use; a hybrid recommendation names which context leads. `content_divergence` is the source-treatment axis. `page_count` may be a range here; Strategist resolves the exact §IX roster, leaving Executor no pagination latitude.
- **Coordinated generative directions**`design_directions` carries exactly three complete candidates authored top-down from the project contract. Each has a unique stable id and bundles `custom` mode, `custom` visual style, color, typography, icon id, and `custom` generated-image rendering regardless of recommended image source. Its localized note is a compact, user-facing style summary. It may reuse localized display labels from `catalogs.visual_styles` when they describe the result concisely, but those labels are optional vocabulary rather than a selection constraint or required mapping. Otherwise it uses concise natural language and never forces the nearest label. The summary stays within one or two short sentences and does not expose catalog ids or reference mechanics. All three must be viable as whole solutions; they do not need different catalog bases or forced safe / shifted / bold archetypes. After completing all three bundles, Strategist compares them against the confirmed contract and source, then writes the strongest overall fit's zero-based index to `selected`; array position does not determine preference. That bundle becomes the initial default and applies its three custom projections coherently. The page can still render legacy top-level `color`, `typography`, and `image_strategy` candidates, but new staged recommendations use the coordinated bundle. - **Coordinated generative directions**`design_directions` carries exactly three complete candidates authored top-down from the project contract. Each has a unique stable id and bundles `custom` mode, `custom` visual style, color, typography, icon id, and `custom` generated-image rendering regardless of recommended image source. Its localized note is a compact, user-facing style summary. It may reuse localized display labels from `catalogs.visual_styles` when they describe the result concisely, but those labels are optional vocabulary rather than a selection constraint or required mapping. Otherwise it uses concise natural language and never forces the nearest label. The summary stays within one or two short sentences and does not expose catalog ids or reference mechanics. Each candidate is one complete design authored top-down within the confirmed contract, never assembled bottom-up from catalog picks; three exist so a single recommendation cannot lock the user in, while the fixed catalogs stay the manual lower layer. Its custom projections are unrestricted by catalog relationship and may carry one preset unchanged. The three candidates are plainly different designs at the whole-deck level, and that difference lives in the solutions rather than in one designated field: whichever components a candidate's design requires carry it, and mode, visual style, rendering, catalog bases, color, typography, and icons are each free to coincide. A different name, note, or reference count alone is not a difference, and candidates identical on every component are not three solutions. Do not force safe / shifted / bold archetypes. Where authoritative user/template truth fixes some components, the remaining open ones carry the difference; identical projections are valid only when nothing is open, stated as that boundary in the direction note. After completing all three bundles, Strategist compares them against the confirmed contract and source, then writes the strongest overall fit's zero-based index to `selected`; array position does not determine preference. That bundle becomes the initial default and applies its three custom projections coherently. The page can still render legacy top-level `color`, `typography`, and `image_strategy` candidates, but new staged recommendations use the coordinated bundle.
Direction-local custom projections apply to mode, visual style, and generated-image rendering; all three are editable after selection and a selected custom value cannot be blank. The original recommendation remains immutable so the active whole-direction card can explicitly restore every edited component without making an ordinary card click destructive. Legacy standalone `custom_candidates` remain readable but are optional and are not authored in new files. Color / typography keep their existing manual Custom cards. Image usage uses source ids plus `image_notes`; closed sets have no Custom path. Direction-local custom projections apply to mode, visual style, and generated-image rendering; all three are editable after selection and a selected custom value cannot be blank. The original recommendation remains immutable so the active whole-direction card can explicitly restore every edited component without making an ordinary card click destructive. Legacy standalone `custom_candidates` remain readable but are optional and are not authored in new files. Color / typography keep their existing manual Custom cards. Image usage uses source ids plus `image_notes`; closed sets have no Custom path.
**Stage-2 catalog read gate.** Before choosing component bases, Strategist reads only `modes/_index.md`, `visual-styles/_index.md`, and `image-renderings/_index.md`. It authors the three whole solution intents first, freezes every basis id from those indexes, and only then reads the deduplicated selected detail files before completing the custom behaviors. Unselected sibling files never enter context; a novel custom reads none. **Stage-2 catalog read gate.** Before choosing component bases, Strategist reads only `modes/_index.md`, `visual-styles/_index.md`, and `image-renderings/_index.md`. It authors the three whole solution intents first, freezes every basis id from those indexes, and only then reads the deduplicated selected detail files before completing the custom behaviors. `custom` has no required catalog relationship: one exact preset may supply an entire editable projection unchanged, several may contribute distinct jobs, or no preset may be used. These are examples, not a closed classification. The behavior remains non-empty; omit every source whose contribution it cannot state and never add a decorative second basis. Unselected sibling files never enter context.
**Stage-1 current-value contract.** Each editable prose box starts with the Strategist's recommendation, if one exists. The user may retain, revise, or clear it; no Stage-1 prose field has a non-empty validation gate. On confirmation, the browser submits the current strings and the server preserves them through every later stage and the final `result.json`, including `""`. Blank means no explicit user constraint and may cause downstream default judgment, but it never causes the initial recommendation to be restored. A profile-declared `locked: true` field is read-only and remains the sole exception. **Stage-1 current-value contract.** Each editable prose box starts with the Strategist's recommendation, if one exists. The user may retain, revise, or clear it; no Stage-1 prose field has a non-empty validation gate. On confirmation, the browser submits the current strings and the server preserves them through every later stage and the final `result.json`, including `""`. Blank means no explicit user constraint and may cause downstream default judgment, but it never causes the initial recommendation to be restored. A profile-declared `locked: true` field is read-only and remains the sole exception.
@@ -583,9 +590,9 @@ custom` + `visual_style_behavior`, or `image_strategy.rendering: custom` +
`behavior`. During Design Spec and lock authoring, Strategist projects optional `behavior`. During Design Spec and lock authoring, Strategist projects optional
`mode_references`, `visual_style_references`, or `mode_references`, `visual_style_references`, or
`image_rendering_references` only when that confirmed behavior actually uses `image_rendering_references` only when that confirmed behavior actually uses
named catalog sources. These lists have no fixed item limit; each item must own named catalog sources. These lists have no fixed item limit. One item may carry
a distinct executable contribution, while genuinely novel custom behavior has the complete preset behavior unchanged; with several, each owns a distinct
no reference list. executable contribution. Genuinely novel custom behavior has no reference list.
The Stage-1 intermediate write retains the communication contract for Stage 2. The Stage-1 intermediate write retains the communication contract for Stage 2.
**Final-result consumption contract.** A final result is the user-confirmed input contract for the Strategist's Design Spec, not another recommendation input. After the final wait, Generate Step 4 reads the complete final object exactly once and retains it while Strategist writes and audits `design_spec.md` against every explicitly present field. Normal lock authoring and downstream execution do not reopen `result.json`; the completed Design Spec is the durable authority. Only after that audit passes does Strategist author `spec_lock.md` from the Design Spec plus current execution context, selecting stable anchors and routing rather than copying every field or enumerating every legal color/font. Every value must be consumed at the semantic type owned by [`strategist.md`](../../references/strategist.md) §1 and its field owner: do not omit or substitute it, and do not silently strengthen or weaken its type. If a confirmed requirement cannot be honored, the owning workflow reports or pauses under failure recovery; it never deletes the requirement to keep the pipeline moving. **Final-result consumption contract.** A final result is the user-confirmed input contract for the Strategist's Design Spec, not another recommendation input. After the final wait, Generate Step 4 reads the complete final object exactly once and retains it while Strategist writes and audits `design_spec.md` against every explicitly present field. Normal lock authoring and downstream execution do not reopen `result.json`; the completed Design Spec is the durable authority. Only after that audit passes does Strategist author `spec_lock.md` from the Design Spec plus current execution context, selecting stable anchors and routing rather than copying every field or enumerating every legal color/font. Every value must be consumed at the semantic type owned by [`strategist.md`](../../references/strategist.md) §1 and its field owner: do not omit or substitute it, and do not silently strengthen or weaken its type. If a confirmed requirement cannot be honored, the owning workflow reports or pauses under failure recovery; it never deletes the requirement to keep the pipeline moving.
@@ -368,7 +368,7 @@ template after the layered authoring IR has been reviewed and edited:
```bash ```bash
python3 scripts/mirror_template_materialize.py \ python3 scripts/mirror_template_materialize.py \
<import_workspace> <empty_template_workspace> <import_workspace> <template_workspace>
``` ```
The command treats `<import_workspace>/authoring-svg/` as the sole editable The command treats `<import_workspace>/authoring-svg/` as the sole editable
@@ -376,8 +376,13 @@ source. It reads the tool-only layered authoring manifest internally and
validates it against immutable lossless SVG validates it against immutable lossless SVG
hashes, source PPTX hash, complete Master/Layout/Slide graph, inheritance hashes, source PPTX hash, complete Master/Layout/Slide graph, inheritance
visibility facts, source-ref closure, and extracted-vector inventory before it visibility facts, source-ref closure, and extracted-vector inventory before it
writes anything. It refuses a non-empty destination and stages the whole result writes anything. It accepts an absent/empty destination or a project
before atomic publication, so a failed preflight cannot leave a partial `templates/` containing unique qualified Brand/Style specs plus, for a
Layout-over-Deck transition, one qualified Deck spec with no staged roster. A
bare spec, active structural roster, SVG, Layout spec, or other template payload blocks direct
materialization; Create Template uses its isolated transition workspace when a
new Layout or Deck must be composed with the other structural kind. It stages the whole
result before atomic publication, so a failed preflight cannot leave a partial
template. template.
Materialization preserves source page order and emits one definition-only Materialization preserves source page order and emits one definition-only
@@ -2515,11 +2515,36 @@ def _preflight_output(
raise MirrorMaterializationError( raise MirrorMaterializationError(
f"Template output is not a directory: {templates_root}" f"Template output is not a directory: {templates_root}"
) )
existing = sorted(path for path in templates_root.iterdir()) # Brand/Style specs own no roster. During a Layout transition, one Deck
if existing: # spec may also remain after its lower-priority roster was withheld by
# the parent workflow. Any other payload would contend with this run.
existing = sorted(templates_root.iterdir())
coexisting_specs = [
path
for path in existing
if path.is_file()
and _MIRROR_COEXISTING_SPEC_NAME_RE.fullmatch(path.name)
]
blocking = [path for path in existing if path not in coexisting_specs]
if blocking:
raise MirrorMaterializationError( raise MirrorMaterializationError(
f"Template output must be empty before mirror materialization: " "Template output must hold no roster before mirror "
f"{templates_root}; first entry: {existing[0].name}" f"materialization: {templates_root}; blocking entry: "
f"{blocking[0].name}"
)
coexisting_kinds = [
_MIRROR_COEXISTING_SPEC_NAME_RE.fullmatch(path.name).group("kind")
for path in coexisting_specs
]
duplicate_kinds = sorted({
kind
for kind in coexisting_kinds
if coexisting_kinds.count(kind) > 1
})
if duplicate_kinds:
raise MirrorMaterializationError(
f"Template output declares the same kind more than once: "
+ ", ".join(duplicate_kinds)
) )
collisions = [ collisions = [
template_workspace / relative template_workspace / relative
@@ -2532,6 +2557,11 @@ def _preflight_output(
) )
_MIRROR_COEXISTING_SPEC_NAME_RE = re.compile(
r"design_spec\.(?P<kind>brand|style|deck)\.[^/\\]+\.md"
)
def _nearest_existing_directory(path: Path) -> Path: def _nearest_existing_directory(path: Path) -> Path:
candidate = path candidate = path
while not candidate.exists(): while not candidate.exists():
@@ -2910,7 +2940,11 @@ def build_parser() -> argparse.ArgumentParser:
parser.add_argument( parser.add_argument(
"template_workspace", "template_workspace",
type=Path, type=Path,
help="Empty template workspace destination (templates/ must be absent or empty)", help=(
"Template workspace destination (templates/ must own no roster; "
"qualified Brand/Style specs or one Deck spec staged for Layout "
"supersession may remain)"
),
) )
return parser return parser
@@ -1349,7 +1349,7 @@
}, },
{ {
"kind": "exact", "kind": "exact",
"fingerprint": "99d8baf1be58", "fingerprint": "272bdc60fa52",
"paths": [ "paths": [
"skills/ppt-master/workflows/create-template/create-brand.md", "skills/ppt-master/workflows/create-template/create-brand.md",
"skills/ppt-master/workflows/create-template/create-style.md" "skills/ppt-master/workflows/create-template/create-style.md"
@@ -336,15 +336,113 @@ def _summary_from_use_cases(use_cases: str | None) -> str | None:
return f"{cleaned}." return f"{cleaned}."
_SPEC_NAME_RE = re.compile(
r"design_spec\.(?P<kind>brand|style|layout|deck)\.(?P<id>[^/\\]+)\.md"
)
def _has_kind_qualified_spec(directory: Path) -> bool:
"""Report whether a directory holds any ``design_spec.<kind>.<id>.md``."""
if not directory.is_dir():
return False
return any(
_SPEC_NAME_RE.fullmatch(path.name)
for path in directory.glob("design_spec.*.md")
)
def _qualified_template_specs(directory: Path) -> list[tuple[Path, str]]:
"""Return kind-qualified specs and their filename-declared kinds."""
if not directory.is_dir():
return []
specs = []
for path in sorted(directory.glob("design_spec.*.md")):
match = _SPEC_NAME_RE.fullmatch(path.name)
if match is not None:
specs.append((path, match.group("kind")))
return specs
def validate_qualified_spec_identity(
spec_path: str | Path,
) -> tuple[str, str, dict, str]:
"""Match one qualified filename's kind and id to its frontmatter."""
path = Path(spec_path)
match = _SPEC_NAME_RE.fullmatch(path.name)
if match is None:
raise SpecParseError(
"qualified Design Spec must be named "
"design_spec.<kind>.<id>.md: "
f"{path.name}"
)
filename_kind = match.group("kind")
filename_id = match.group("id")
frontmatter, body = _read_spec(path)
fm = frontmatter or {}
declared_kind = str(fm.get("kind") or "").strip()
id_key = KIND_CONFIG[filename_kind]["id_key"]
declared_id = str(fm.get(id_key) or "").strip()
errors: list[str] = []
if declared_kind != filename_kind:
errors.append(
f"filename kind {filename_kind!r} must match frontmatter kind "
f"{declared_kind!r}"
)
if declared_id != filename_id:
errors.append(
f"filename id {filename_id!r} must match frontmatter {id_key} "
f"{declared_id!r}"
)
if errors:
details = "\n".join(f" - {error}" for error in errors)
raise SpecParseError(
f"invalid qualified Design Spec identity ({path.name}):\n{details}"
)
return filename_kind, filename_id, fm, body
def _validate_spec_shape(template_dir: Path) -> list[tuple[Path, str]]:
"""Reject ambiguous project-spec naming and duplicate kind ownership."""
exact = template_dir / "design_spec.md"
qualified = _qualified_template_specs(template_dir)
if exact.is_file() and qualified:
raise SpecParseError(
"design_spec.md and design_spec.<kind>.<id>.md cannot share "
f"{template_dir}; rename the bare spec to its kind-qualified name"
)
kinds = [kind for _path, kind in qualified]
duplicate_kinds = sorted({
kind for kind in kinds if kinds.count(kind) > 1
})
if duplicate_kinds:
raise SpecParseError(
f"{template_dir} declares the same kind more than once: "
+ ", ".join(duplicate_kinds)
)
for path, _kind in qualified:
validate_qualified_spec_identity(path)
return qualified
def _has_qualified_roster_spec(template_dir: Path) -> bool:
"""Return whether a project directory declares a structural kind."""
return any(
kind in {"layout", "deck"}
for _path, kind in _qualified_template_specs(template_dir)
)
def _template_content_dir(template_root: Path) -> Path: def _template_content_dir(template_root: Path) -> Path:
"""Resolve the canonical source directory, with legacy-flat compatibility.""" """Resolve the canonical source directory, with legacy-flat compatibility."""
nested = template_root / "templates" nested = template_root / "templates"
if (nested / "design_spec.md").is_file(): if (nested / "design_spec.md").is_file() or _has_kind_qualified_spec(nested):
return nested return nested
if (template_root / "design_spec.md").is_file(): if (template_root / "design_spec.md").is_file():
return template_root return template_root
raise SpecParseError( raise SpecParseError(
f"missing templates/design_spec.md or legacy design_spec.md in {template_root}" "missing templates/design_spec.md, templates/design_spec.<kind>.<id>.md, "
f"or legacy design_spec.md in {template_root}"
) )
@@ -472,7 +570,8 @@ def _validate_brand_spec(
+ ", ".join(unexpected_fields) + ", ".join(unexpected_fields)
) )
if pages: # Project pages are valid only when one sibling Layout or Deck owns them.
if pages and not _has_qualified_roster_spec(template_dir):
errors.append( errors.append(
"brand workspaces must not contain page SVGs under templates/: " "brand workspaces must not contain page SVGs under templates/: "
+ ", ".join(f"{page}.svg" for page in pages) + ", ".join(f"{page}.svg" for page in pages)
@@ -563,6 +662,7 @@ def _validate_style_spec(
template_dir: Path, template_dir: Path,
frontmatter: dict, frontmatter: dict,
body: str, body: str,
pages: list[str],
) -> None: ) -> None:
"""Reject Style workspaces outside the roster-free method contract.""" """Reject Style workspaces outside the roster-free method contract."""
errors: list[str] = [] errors: list[str] = []
@@ -632,19 +732,30 @@ def _validate_style_spec(
elif len({item.strip().casefold() for item in keywords}) != len(keywords): elif len({item.strip().casefold() for item in keywords}) != len(keywords):
errors.append("frontmatter keywords must be unique") errors.append("frontmatter keywords must be unique")
unexpected_source_entries = sorted( if pages and not _has_qualified_roster_spec(template_dir):
path.relative_to(template_dir).as_posix()
+ ("/" if path.is_dir() else "")
for path in template_dir.rglob("*")
if path.relative_to(template_dir).as_posix() != "design_spec.md"
)
if unexpected_source_entries:
errors.append( errors.append(
"style workspaces must contain only templates/design_spec.md; " "style workspaces must not contain page SVGs without a sibling "
"unexpected template entry(s): " "Layout or Deck owner: "
+ ", ".join(unexpected_source_entries) + ", ".join(f"{page}.svg" for page in pages)
) )
# The one-file packaging rule describes a workspace whose templates/ Style
# owns alone. A project root shares that directory with other kinds, so the
# rule there is only that Style itself contributes nothing but its spec.
if (template_dir / "design_spec.md").is_file():
unexpected_source_entries = sorted(
path.relative_to(template_dir).as_posix()
+ ("/" if path.is_dir() else "")
for path in template_dir.rglob("*")
if path.relative_to(template_dir).as_posix() != "design_spec.md"
)
if unexpected_source_entries:
errors.append(
"style workspaces must contain only templates/design_spec.md; "
"unexpected template entry(s): "
+ ", ".join(unexpected_source_entries)
)
if expected_template_id is not None: if expected_template_id is not None:
unexpected_workspace_entries = sorted( unexpected_workspace_entries = sorted(
path.relative_to(template_root).as_posix() path.relative_to(template_root).as_posix()
@@ -884,8 +995,10 @@ def _validate_svg_template_spec(
template_dir: Path, template_dir: Path,
frontmatter: dict, frontmatter: dict,
pages: list[str], pages: list[str],
*,
validate_payload: bool = True,
) -> None: ) -> None:
"""Reject Layout/Deck workspaces whose registry facts drift from SVGs.""" """Validate Layout/Deck metadata and, when active, its SVG payload."""
errors: list[str] = [] errors: list[str] = []
id_key = KIND_CONFIG[kind]["id_key"] id_key = KIND_CONFIG[kind]["id_key"]
declared_id = str(frontmatter.get(id_key) or "").strip() declared_id = str(frontmatter.get(id_key) or "").strip()
@@ -969,7 +1082,7 @@ def _validate_svg_template_spec(
) )
svg_paths = [template_dir / f"{page}.svg" for page in pages] svg_paths = [template_dir / f"{page}.svg" for page in pages]
if canvas is not None: if validate_payload and canvas is not None:
expected_viewbox = str(canvas["viewbox"]) expected_viewbox = str(canvas["viewbox"])
for svg_path in svg_paths: for svg_path in svg_paths:
try: try:
@@ -993,7 +1106,7 @@ def _validate_svg_template_spec(
f"{expected_canvas!r}" f"{expected_canvas!r}"
) )
if svg_paths: if validate_payload and svg_paths:
try: try:
from svg_to_pptx.pptx_package.template_structure import ( from svg_to_pptx.pptx_package.template_structure import (
TemplateStructureError, TemplateStructureError,
@@ -1012,6 +1125,30 @@ def _validate_svg_template_spec(
raise SpecParseError(f"invalid {kind} specification:\n{details}") raise SpecParseError(f"invalid {kind} specification:\n{details}")
def validate_shadowed_deck_spec(
spec_path: str | Path,
declared_pages: list[str],
) -> None:
"""Validate a Deck spec whose SVG roster is overridden by Layout."""
path = Path(spec_path)
match = _SPEC_NAME_RE.fullmatch(path.name)
if match is None or match.group("kind") != "deck":
raise SpecParseError(
"shadowed Deck validation requires design_spec.deck.<id>.md"
)
_kind, filename_id, frontmatter, _body = validate_qualified_spec_identity(
path
)
_validate_svg_template_spec(
"deck",
filename_id,
path.parent,
frontmatter,
declared_pages,
validate_payload=False,
)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Per-kind extraction # Per-kind extraction
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@@ -1029,7 +1166,14 @@ def _extract_entry(
"Style workspaces require templates/design_spec.md; " "Style workspaces require templates/design_spec.md; "
"legacy-flat design_spec.md is not supported" "legacy-flat design_spec.md is not supported"
) )
spec_path = template_dir / "design_spec.md" if template_id is not None and template_dir != template_root:
exact_spec = template_dir / "design_spec.md"
if not exact_spec.is_file():
raise SpecParseError(
"library workspaces require templates/design_spec.md; "
"kind-qualified specs belong only to shared project roots"
)
spec_path = _resolve_spec_path(template_dir, kind)
frontmatter, body = _read_spec(spec_path) frontmatter, body = _read_spec(spec_path)
fm = frontmatter or {} fm = frontmatter or {}
@@ -1079,6 +1223,7 @@ def _extract_entry(
template_dir, template_dir,
fm, fm,
body, body,
pages,
) )
entry = OrderedDict( entry = OrderedDict(
summary=summary, summary=summary,
@@ -1137,6 +1282,33 @@ def _extract_entry(
return {"entry": entry, "extras": extras} return {"entry": entry, "extras": extras}
def _resolve_spec_path(template_dir: Path, kind: str) -> Path:
"""Return the Design Spec one kind owns inside a template source directory.
A library workspace keeps the exact ``design_spec.md`` because
``<kind_dir>/<template_id>/`` already names its kind and id. A project
workspace root has no such parent, so it keeps
``design_spec.<kind>.<id>.md`` and may hold one spec per kind side by side.
"""
qualified = _validate_spec_shape(template_dir)
exact = template_dir / "design_spec.md"
if exact.is_file():
return exact
matches = sorted(
path for path, declared_kind in qualified if declared_kind == kind
)
if len(matches) == 1:
return matches[0]
if not matches:
raise SpecParseError(
f"missing design_spec.md or design_spec.{kind}.<id>.md in {template_dir}"
)
raise SpecParseError(
f"{template_dir} declares kind {kind!r} more than once: "
+ ", ".join(path.name for path in matches)
)
def validate_brand_workspace(template_root: str | Path) -> dict: def validate_brand_workspace(template_root: str | Path) -> dict:
"""Validate a portable Brand workspace without registering it. """Validate a portable Brand workspace without registering it.
@@ -792,13 +792,77 @@ SPARSE_UNDECLARED_FONT_SIZE_MAX_OCCURRENCES = 2
IMAGE_DOWNSIZE_WARN_RATIO = 4.0 IMAGE_DOWNSIZE_WARN_RATIO = 4.0
IMAGE_DOWNSIZE_WARN_MIN_BYTES = 1024 * 1024 IMAGE_DOWNSIZE_WARN_MIN_BYTES = 1024 * 1024
_TEMPLATE_SPEC_NAME_RE = re.compile(
r'design_spec\.(?P<kind>brand|style|layout|deck)\.(?P<id>[^/\\]+)\.md'
)
def _template_spec_paths(directory: Path) -> list[Path]:
"""Return every template Design Spec directly inside one directory.
A library workspace keeps the exact ``design_spec.md`` because its parent
directory already names the kind and id. A project workspace root shares one
``templates/`` across kinds, so it keeps ``design_spec.<kind>.<id>.md`` and
may hold one spec per kind side by side.
"""
if not directory.is_dir():
return []
exact = directory / 'design_spec.md'
qualified = sorted(
path
for path in directory.glob('design_spec.*.md')
if _TEMPLATE_SPEC_NAME_RE.fullmatch(path.name)
)
if exact.is_file():
# Mixing both shapes hides one of them from every reader that stops at
# the first match, so it is reported rather than silently resolved.
return [exact] + qualified
return qualified
def _spec_declared_kind(spec_path: Path) -> str | None:
"""Return one spec's kind, from its filename when it carries one."""
match = _TEMPLATE_SPEC_NAME_RE.fullmatch(spec_path.name)
if match is not None:
return match.group('kind')
return _design_spec_kind(spec_path)
def _roster_spec_paths(directory: Path) -> list[Path]:
"""Return every spec in one directory that owns an SVG roster."""
roster = []
for spec in _template_spec_paths(directory):
match = _TEMPLATE_SPEC_NAME_RE.fullmatch(spec.name)
if match is not None:
if match.group('kind') in {'layout', 'deck'}:
roster.append(spec)
elif _design_spec_kind(spec) not in {'brand', 'style'}:
roster.append(spec)
return roster
def _roster_spec_path(directory: Path) -> Path | None:
"""Return the effective spec that owns this directory's SVG roster.
A project root may carry both Layout and Deck. Layout owns reusable
structure when present; Deck owns it only when no Layout is installed.
"""
roster = _roster_spec_paths(directory)
for spec in roster:
if spec.name == 'design_spec.md':
return spec
for kind in ('layout', 'deck'):
for spec in roster:
if _spec_declared_kind(spec) == kind:
return spec
return None
def _design_spec_kind(spec_path: Path) -> str | None: def _design_spec_kind(spec_path: Path) -> str | None:
"""Return a roster-free ``kind`` declared in design_spec.md frontmatter. """Return ``kind`` declared in Design Spec frontmatter.
Lightweight detector that does not require PyYAML scans only the Lightweight detector that does not require PyYAML scans only the
frontmatter block (``---`` delimited). Used by ``check_directory`` to frontmatter block (``---`` delimited).
select schema-only validation for Brand and Style workspaces instead of
SVG-roster validation.
""" """
try: try:
text = spec_path.read_text(encoding='utf-8') text = spec_path.read_text(encoding='utf-8')
@@ -813,7 +877,8 @@ def _design_spec_kind(spec_path: Path) -> str | None:
for line in fm_block.splitlines(): for line in fm_block.splitlines():
stripped = line.strip() stripped = line.strip()
match = re.fullmatch( match = re.fullmatch(
r'''kind\s*:\s*(?:(['"])(brand|style)\1|(brand|style))''' r'''kind\s*:\s*(?:(['"])(brand|style|layout|deck)\1|'''
r'''(brand|style|layout|deck))'''
r'''(?:\s+#.*)?\s*''', r'''(?:\s+#.*)?\s*''',
stripped, stripped,
) )
@@ -825,7 +890,9 @@ def _design_spec_kind(spec_path: Path) -> str | None:
def _declared_template_structure_mode(target_path: Path) -> str | None: def _declared_template_structure_mode(target_path: Path) -> str | None:
"""Return a template directory's explicit native structure mode.""" """Return a template directory's explicit native structure mode."""
directory = target_path.parent if target_path.is_file() else target_path directory = target_path.parent if target_path.is_file() else target_path
spec_path = directory / 'design_spec.md' spec_path = _roster_spec_path(directory)
if spec_path is None:
return None
try: try:
text = spec_path.read_text(encoding='utf-8') text = spec_path.read_text(encoding='utf-8')
except OSError: except OSError:
@@ -846,7 +913,9 @@ def _declared_template_structure_mode(target_path: Path) -> str | None:
def _declared_template_canvas_viewbox(target_path: Path) -> str | None: def _declared_template_canvas_viewbox(target_path: Path) -> str | None:
"""Return a template design spec's locked root-canvas value.""" """Return a template design spec's locked root-canvas value."""
directory = target_path.parent if target_path.is_file() else target_path directory = target_path.parent if target_path.is_file() else target_path
spec_path = directory / 'design_spec.md' spec_path = _roster_spec_path(directory)
if spec_path is None:
return None
try: try:
text = spec_path.read_text(encoding='utf-8') text = spec_path.read_text(encoding='utf-8')
except OSError: except OSError:
@@ -5258,17 +5327,103 @@ class SVGQualityChecker:
# registration, while keeping project scope independent of global # registration, while keeping project scope independent of global
# indexes and directory names. # indexes and directory names.
if self.template_mode and dir_path.is_dir(): if self.template_mode and dir_path.is_dir():
nested_spec = dir_path / 'templates' / 'design_spec.md' nested = dir_path / 'templates'
spec = nested_spec if nested_spec.is_file() else dir_path / 'design_spec.md' spec_dir = nested if _template_spec_paths(nested) else dir_path
spec_kind = _design_spec_kind(spec) if spec.exists() else None specs = _template_spec_paths(spec_dir)
if spec_kind in {'brand', 'style'}: bare = [spec for spec in specs if spec.name == 'design_spec.md']
qualified = [spec for spec in specs if spec.name != 'design_spec.md']
if bare and qualified:
self._template_issues.append((
'error',
'spec_naming',
'design_spec.md and design_spec.<kind>.<id>.md cannot share '
f'{spec_dir}; rename the bare spec to its kind-qualified name',
))
return self.results
try:
from register_template import (
SpecParseError,
validate_qualified_spec_identity,
)
for spec in qualified:
validate_qualified_spec_identity(spec)
except ImportError as exc:
self._template_issues.append((
'error',
'spec_naming',
f'Qualified Design Spec validator could not be imported: {exc}',
))
return self.results
except (OSError, SpecParseError) as exc:
self._template_issues.append((
'error',
'spec_naming',
str(exc),
))
return self.results
declared_kinds = [
kind
for spec in qualified
for kind in [_spec_declared_kind(spec)]
if kind is not None
]
duplicate_kinds = sorted({
kind for kind in declared_kinds
if declared_kinds.count(kind) > 1
})
if duplicate_kinds:
self._template_issues.append((
'error',
'spec_naming',
f'{spec_dir} declares the same kind more than once: '
+ ', '.join(duplicate_kinds),
))
return self.results
active_roster_spec = _roster_spec_path(spec_dir)
shadowed_deck_specs = [
spec
for spec in _roster_spec_paths(spec_dir)
if spec != active_roster_spec
and _spec_declared_kind(spec) == 'deck'
]
for spec in shadowed_deck_specs:
try:
from register_template import (
SpecParseError,
validate_shadowed_deck_spec,
)
declared_pages = self._extract_spec_roster(
spec.read_text(encoding='utf-8')
)
validate_shadowed_deck_spec(spec, declared_pages)
except ImportError as exc:
self._template_issues.append((
'error',
'deck_contract',
f'Shadowed Deck validator could not be imported: {exc}',
))
return self.results
except (OSError, SpecParseError) as exc:
self._template_issues.append((
'error',
'deck_contract',
str(exc),
))
return self.results
roster_free = [
(spec, kind)
for spec in _template_spec_paths(spec_dir)
for kind in [_spec_declared_kind(spec)]
if kind in {'brand', 'style'}
]
for spec, spec_kind in roster_free:
self._spec_only_template_kind = spec_kind self._spec_only_template_kind = spec_kind
self.summary['total'] += 1 self.summary['total'] += 1
spec_valid = True spec_valid = True
pretty_kind = spec_kind.title() pretty_kind = spec_kind.title()
print( print(
f"[INFO] {pretty_kind} directory detected " f"[INFO] {pretty_kind} spec detected "
f"(kind: {spec_kind}) — " f"({spec.name}) — "
f"validating its portable workspace contract." f"validating its portable workspace contract."
) )
workspace_root = ( workspace_root = (
@@ -5303,6 +5458,9 @@ class SVGQualityChecker:
)) ))
if spec_valid: if spec_valid:
self.summary['passed'] += 1 self.summary['passed'] += 1
# A roster-bearing Layout/Deck spec may sit beside those in one
# project workspace; only then does SVG validation still apply.
if roster_free and _roster_spec_path(spec_dir) is None:
return self.results return self.results
# Find all SVG files # Find all SVG files
@@ -6791,8 +6949,12 @@ class SVGQualityChecker:
Issues are aggregated and printed in :py:meth:`print_summary` so the Issues are aggregated and printed in :py:meth:`print_summary` so the
per-file report stays focused on intrinsic SVG validity. per-file report stays focused on intrinsic SVG validity.
""" """
spec_path = dir_path / 'design_spec.md' spec_path = _roster_spec_path(dir_path)
spec_text = spec_path.read_text(encoding='utf-8') if spec_path.exists() else "" spec_text = (
spec_path.read_text(encoding='utf-8')
if spec_path is not None and spec_path.exists()
else ""
)
declared_structure_mode = _declared_template_structure_mode(dir_path) declared_structure_mode = _declared_template_structure_mode(dir_path)
mode_error_recorded = False mode_error_recorded = False
if declared_structure_mode != 'structured': if declared_structure_mode != 'structured':
@@ -6920,7 +7082,7 @@ class SVGQualityChecker:
'roster_missing', 'roster_missing',
f"design_spec.md Page Roster lists {page} but {page}.svg is missing on disk", f"design_spec.md Page Roster lists {page} but {page}.svg is missing on disk",
)) ))
elif spec_path.exists(): elif spec_path is not None and spec_path.exists():
# design_spec.md is present but the roster parser found nothing — # design_spec.md is present but the roster parser found nothing —
# reusable template workspaces always fail closed. # reusable template workspaces always fail closed.
self._template_issues.append(( self._template_issues.append((
@@ -6933,7 +7095,7 @@ class SVGQualityChecker:
self._template_issues.append(( self._template_issues.append((
'error', 'error',
'spec_missing', 'spec_missing',
f"{spec_path.name} not found — required for every library template", "one Layout or Deck Design Spec is required for every SVG roster",
)) ))
# Per-file placeholder coverage. Variants reuse the parent type's set # Per-file placeholder coverage. Variants reuse the parent type's set
@@ -160,22 +160,77 @@ def _partition_svg_prototypes(
return public_files, definition_files return public_files, definition_files
_TEMPLATE_SPEC_NAME_RE = re.compile(
r"design_spec\.(?P<kind>brand|style|layout|deck)\.[^/\\]+\.md"
)
def _roster_spec(directory: Path) -> Path | None:
"""Return the effective spec that owns this directory's SVG roster.
A library workspace keeps the exact ``design_spec.md``. A project workspace
shares one ``templates/`` across kinds. Layout owns structure when both
Layout and Deck are present; otherwise Deck owns it.
"""
if not directory.is_dir():
return None
exact = directory / "design_spec.md"
qualified = []
for item in sorted(directory.glob("design_spec.*.md")):
match = _TEMPLATE_SPEC_NAME_RE.fullmatch(item.name)
if match is not None:
qualified.append((item, match.group("kind")))
if exact.is_file() and qualified:
raise ValueError(
"design_spec.md and design_spec.<kind>.<id>.md cannot share "
f"{directory}; rename the bare spec to its kind-qualified name"
)
kinds = [kind for _item, kind in qualified]
duplicate_kinds = sorted({
kind for kind in kinds if kinds.count(kind) > 1
})
if duplicate_kinds:
raise ValueError(
f"{directory} declares the same kind more than once: "
+ ", ".join(duplicate_kinds)
)
try:
from register_template import (
SpecParseError,
validate_qualified_spec_identity,
)
for item, _kind in qualified:
validate_qualified_spec_identity(item)
except ImportError as exc:
raise ValueError(
f"Qualified Design Spec validator could not be imported: {exc}"
) from exc
except (OSError, SpecParseError) as exc:
raise ValueError(str(exc)) from exc
if exact.is_file():
return exact
for preferred_kind in ("layout", "deck"):
for item, kind in qualified:
if kind == preferred_kind:
return item
return None
def _resolve_workspace(path: Path) -> tuple[Path, Path]: def _resolve_workspace(path: Path) -> tuple[Path, Path]:
"""Resolve one workspace root and its canonical template-source directory.""" """Resolve one workspace root and its canonical template-source directory."""
candidate = path.expanduser().resolve() candidate = path.expanduser().resolve()
nested_spec = candidate / "templates" / "design_spec.md" if _roster_spec(candidate / "templates") is not None:
if nested_spec.is_file():
return candidate, candidate / "templates" return candidate, candidate / "templates"
direct_spec = candidate / "design_spec.md" if _roster_spec(candidate) is not None:
if direct_spec.is_file():
if candidate.name == "templates" and (candidate.parent / "exports").is_dir(): if candidate.name == "templates" and (candidate.parent / "exports").is_dir():
return candidate.parent, candidate return candidate.parent, candidate
return candidate, candidate return candidate, candidate
raise ValueError( raise ValueError(
"template workspace must contain templates/design_spec.md " "template workspace must contain templates/design_spec.md, "
"(current structure) or design_spec.md (legacy flat package)" "templates/design_spec.<layout|deck>.<id>.md, or a legacy flat "
"design_spec.md"
) )
@@ -382,7 +437,7 @@ def main(argv: list[str] | None = None) -> int:
f"SVG prototypes: {template_dir}" f"SVG prototypes: {template_dir}"
) )
spec_path = template_dir / "design_spec.md" spec_path = _roster_spec(template_dir)
template_id = _template_id(spec_path, workspace) template_id = _template_id(spec_path, workspace)
replication_mode = _replication_mode(spec_path) replication_mode = _replication_mode(spec_path)
locked_canvas = _canvas_viewbox(spec_path) locked_canvas = _canvas_viewbox(spec_path)
@@ -49,11 +49,13 @@ specified candidates. Ordinary requests default to free design; explicit
template intent or any supplied root defaults to template mode. Exactly one root template intent or any supplied root defaults to template mode. Exactly one root
may be preselected, while multiple roots remain unselected candidates. The user may be preselected, while multiple roots remain unselected candidates. The user
can always switch modes. The page accepts one registered choice per kind plus can always switch modes. The page accepts one registered choice per kind plus
one supplied-root choice. A registered exact root is `library`; any other exact one supplied-root choice, but the complete selection contains at most one
root is `explicit`. After that combined confirmation, contribution per kind. All four kinds may combine; Layout owns structure when
both Layout and Deck are present. A supplied multi-kind root is atomic. A registered exact root is `library`; any other exact root is
`explicit`. After that combined confirmation,
[`apply-template-workspace`](../workflows/stages/apply-template-workspace.md) [`apply-template-workspace`](../workflows/stages/apply-template-workspace.md)
validates and installs every selected workspace into the current validates and maps every distinct selected root once, preserving each
project as its own `design_spec.<kind>.<id>.md` before Stage 2 starts. Template-aware reading begins in final Stage 2 from contribution as `design_spec.<kind>.<id>.md` before Stage 2 starts. Template-aware reading begins in final Stage 2 from
that project-local copy. Quick skips the page, applies supplied exact roots, and that project-local copy. Quick skips the page, applies supplied exact roots, and
otherwise uses free design. otherwise uses free design.
@@ -79,28 +81,32 @@ initialized project:
```text ```text
<template_workspace>/ <template_workspace>/
├── templates/ # design_spec.md; optional Layout/Deck SVG prototypes and native_payloads.json.gz store ├── templates/ # the Design Spec (naming below); optional Layout/Deck SVGs and native_payloads.json.gz store
├── images/ # optional bitmaps ├── images/ # optional bitmaps
├── icons/ ├── icons/
│ └── imported/ # optional imported vectors, one canonical copy │ └── imported/ # optional imported vectors, one canonical copy
└── exports/ # optional review evidence; never a template input └── exports/ # optional review evidence; never a template input
``` ```
**Hard rule — the container disambiguates, the filename carries the rest**: one
schema serves both layers. A library root keeps `templates/design_spec.md`, since
`<kind_dir>/<template_id>/` already names its kind and id. A project root shares
one flat `templates/`, so it keeps one `design_spec.<kind>.<id>.md` per kind;
filename kind/id MUST equal frontmatter `kind`/`<kind>_id`. The shapes never
mix. One `templates/`
holds one active SVG roster: Layout when present, otherwise Deck. Both specs may
coexist because Layout overrides only Deck structure. Either shape is a
workspace root, and selecting it takes every kind it exposes.
Empty optional directories are omitted. Template SVGs reference bitmaps through Empty optional directories are omitted. Template SVGs reference bitmaps through
`../images/<name>` and imported vectors through `data-icon="imported/<name>"`. `../images/<name>` and imported vectors through `data-icon="imported/<name>"`.
Style narrows this shared routing shape to `templates/design_spec.md` only and Style contributes only its own Design Spec and no asset or review payload;
does not carry asset or review payloads; initialized-project sibling scaffolding sibling scaffolding and other kinds' files are not Style input.
may exist but is not Style input. Every kind ignores `exports/`. The conditional
The conditional [`apply-template-workspace`](../workflows/stages/apply-template-workspace.md) [`apply-template-workspace`](../workflows/stages/apply-template-workspace.md)
stage owns installation after a non-free Default Stage-1 selection or stage owns the rest: when installation runs, which roots each kind consumes,
on the Quick exact-root branch. Brand/Layout/Deck consume package-owned legacy-flat readability, and the boundary that every later consumer reads the
`templates/`, `images/`, and `icons/`; Style consumes only installed project-local files rather than the original root.
`templates/design_spec.md` and ignores sibling project scaffolding. Every kind
ignores `exports/`. Compatible legacy-flat Brand/Layout/Deck packages remain
readable; Style has no legacy-flat form, and directory shape alone does not
indicate legacy Master/Layout semantics. Default Strategist, Quick's current
agent, and all later consumers use the installed project-local files, never the
original library or explicit root.
## Design specification references ## Design specification references
@@ -19,7 +19,7 @@ specific candidate only when it is the sole supplied root.
Registered exact roots are `library`; other exact roots remain `explicit`. The conditional Registered exact roots are `library`; other exact roots remain `explicit`. The conditional
[`apply-template-workspace`](../../workflows/stages/apply-template-workspace.md) [`apply-template-workspace`](../../workflows/stages/apply-template-workspace.md)
stage owns path normalization, portable-root installation, per-workspace spec naming, stage owns path normalization, portable-root installation, per-workspace spec naming,
same-kind conflict resolution, and provenance after Stage 1 and before Stage 2. Template-aware selection-conflict rejection, and provenance after Stage 1 and before Stage 2. Template-aware
reading begins in final Stage 2 from the installed project-local copy. This file owns reading begins in final Stage 2 from the installed project-local copy. This file owns
only the Brand schema. Quick applies a supplied exact Brand root directly and only the Brand schema. Quick applies a supplied exact Brand root directly and
otherwise uses free design. otherwise uses free design.
@@ -35,7 +35,7 @@ installed copy before authoring flat pages.
| Current project communication contract, mode, visual style, palette, typography, images, and icons | Latest explicit user instruction and confirmed project values | | Current project communication contract, mode, visual style, palette, typography, images, and icons | Latest explicit user instruction and confirmed project values |
| Exact identity values | Brand, then Deck identity; both override overlapping Style fallback values | | Exact identity values | Brand, then Deck identity; both override overlapping Style fallback values |
| Reusable communication method and evidence discipline | Style, applied only where compatible with the current project contract | | Reusable communication method and evidence discipline | Style, applied only where compatible with the current project contract |
| Reusable structure | Compatible Layout, then Deck structure; Style never supplies structure | | Reusable structure | Layout when present, otherwise Deck; Style never supplies structure |
| Recurring application context | Deck, subordinate to the current project's Stage-1 communication contract | | Recurring application context | Deck, subordinate to the current project's Stage-1 communication contract |
Style fallback values seed the final Stage-2 solution when the corresponding decision remains open. They are not identity truth and do not bypass confirmation. If a Style method and a Deck application contract materially conflict, surface the mismatch; do not silently weaken either one. Style fallback values seed the final Stage-2 solution when the corresponding decision remains open. They are not identity truth and do not bypass confirmation. If a Style method and a Deck application contract materially conflict, surface the mismatch; do not silently weaken either one.
@@ -12,9 +12,9 @@ Create one reusable template workspace under either the **global template librar
**Default — library scope**: Write `skills/ppt-master/templates/<kind_dir>/<template_id>/` and register it in the matching discovery index. **Default — library scope**: Write `skills/ppt-master/templates/<kind_dir>/<template_id>/` and register it in the matching discovery index.
**Project scope**: Write the same portable workspace routing at `<project>/` and do not register any global index. **Project scope**: Write the same portable workspace routing at `<project>/` and do not register any global index. That project root stays an ordinary referenceable workspace root, and its `templates/` may accumulate one Brand, Style, Layout, and Deck over separate runs. When Layout and Deck coexist, Layout owns the active SVG roster; Deck retains identity and reusable application context.
**Hard rule — one workspace routing contract**: Output scope changes only the workspace parent and index registration. Both scopes use required `templates/`, optional `images/` / `icons/`, and optional on-demand `exports/`, with the same relative asset references and validation command. Create Template must not create an optional directory or placeholder file solely to retain an empty path. An initialized project may already contain empty `images/`, `icons/`, or `exports/` scaffolding; leave it untouched, do not count it as template output, and omit the path from completion unless this workflow wrote or adopted a real file there. Do not maintain a library-only self-contained-flat package branch or a project-only thin-bundle branch. **Hard rule — one workspace routing contract**: Output scope changes the workspace parent, Design Spec filename placement, and index registration—not the spec schema or asset routes. Both scopes use required `templates/`, optional `images/` / `icons/`, and optional on-demand `exports/`, with the same relative asset references and validation command. Create Template must not create an optional directory or placeholder file solely to retain an empty path. An initialized project may already contain empty `images/`, `icons/`, or `exports/` scaffolding; leave it untouched, do not count it as template output, and omit the path from completion unless this workflow wrote or adopted a real file there. Do not maintain a library-only self-contained-flat package branch or a project-only thin-bundle branch.
> **Boundary against template-fill and in-place structure edits**: Create Template does not fill content into a PPTX, add Master/Layout structure to an existing PPTX/SVG, or directly output the user's final generated deck. It authors a separate reusable workspace; an optional PPTX is review evidence only. To generate a deck, return the workspace root as an exact candidate to [`generate-pptx`](./generate-pptx.md) Step 3, confirm it with Stage 1, then author new SVG pages from the installed state. A project-scoped workspace selected for its own project is consumed in place after that confirmation. > **Boundary against template-fill and in-place structure edits**: Create Template does not fill content into a PPTX, add Master/Layout structure to an existing PPTX/SVG, or directly output the user's final generated deck. It authors a separate reusable workspace; an optional PPTX is review evidence only. To generate a deck, return the workspace root as an exact candidate to [`generate-pptx`](./generate-pptx.md) Step 3, confirm it with Stage 1, then author new SVG pages from the installed state. A project-scoped workspace selected for its own project is consumed in place after that confirmation.
@@ -45,36 +45,38 @@ workspace model. Downstream template application and installation remain owned b
Output scope is a shared Create Template execution choice, not a new template kind or PPTX structure mode. Surface it in the Step 2 brief; do not invent a CLI flag or persist `output_scope` / `target_project` into portable `design_spec.md` frontmatter. Output scope is a shared Create Template execution choice, not a new template kind or PPTX structure mode. Surface it in the Step 2 brief; do not invent a CLI flag or persist `output_scope` / `target_project` into portable `design_spec.md` frontmatter.
| Scope | `<template_workspace>` | Template source | Registration | | Scope | `<template_workspace>` | `<design_spec_path>` | Registration |
|---|---|---|---| |---|---|---|---|
| `library` (default) | `skills/ppt-master/templates/<kind_dir>/<template_id>/` | `<template_workspace>/templates/` | Run `register_template.py` against the matching global index | | `library` (default) | `skills/ppt-master/templates/<kind_dir>/<template_id>/` | `<template_workspace>/templates/design_spec.md` | Run `register_template.py` against the matching global index |
| `project` | `<target_project>/` | `<template_workspace>/templates/` | Do not update any global index | | `project` | `<target_project>/` | `<template_workspace>/templates/design_spec.<kind>.<id>.md` | Do not update any global index |
**Design Spec naming**: follow [`templates/README.md`](../templates/README.md): `library` writes `templates/design_spec.md`; `project` writes `templates/design_spec.<kind>.<id>.md`, whose kind/id MUST equal frontmatter `kind`/`<kind>_id`. One project root carries at most one spec per kind and later contributes every exposed kind.
Both scopes write this contract: Both scopes write this contract:
```text ```text
<template_workspace>/ <template_workspace>/
├── templates/ # design_spec.md; Create Layout/Create Deck also write SVGs ├── templates/ # library: design_spec.md; project: one qualified spec per kind plus the effective Layout-or-Deck SVG roster
├── images/ # optional; every bitmap; SVG href is ../images/<name> ├── images/ # optional; every bitmap; SVG href is ../images/<name>
├── icons/ ├── icons/
│ └── imported/ # optional; one canonical copy of imported vector assets │ └── imported/ # optional; one canonical copy of imported vector assets
└── exports/ # conditional; required package evidence for multi-Master templates └── exports/ # conditional; required package evidence for multi-Master templates
``` ```
Create Style narrows the shared root to `templates/design_spec.md` only. It Create Style narrows its contribution to the resolved `<design_spec_path>`. It
does not write or adopt images, icons, native payloads, or review exports; does not write or adopt images, icons, native payloads, or review exports;
pre-existing empty project scaffolding remains untouched and is not Style pre-existing empty project scaffolding remains untouched and is not Style
output. output.
The review PPTX is derived evidence, not a source template asset. Create `exports/` only when a review deck is requested or the template declares more than one Master; multi-Master templates require the package-level gate in Step 6. Brand/Layout/Deck application reads `templates/` plus any package-owned `images/` and `icons/`; Style reads only `templates/design_spec.md`. No kind copies or consumes `exports/`. Library `exports/` directories are Git-ignored. The review PPTX is derived evidence, not a source template asset. Create `exports/` only when a review deck is requested or the template declares more than one Master; multi-Master templates require the package-level gate in Step 6. Brand/Layout/Deck application reads `templates/` plus any package-owned `images/` and `icons/`; Style reads only its resolved Design Spec. No kind copies or consumes `exports/`. Library `exports/` directories are Git-ignored.
For `project`, `target_project` is required and must be an existing project initialized by `project_manager.py init`. Before the first final-output write, run one complete preflight. Apply the same collision checks to a library workspace; the only difference is that its root is under the global kind directory: For `project`, `target_project` is required and must be an existing project initialized by `project_manager.py init`. Before the first final-output write, run one complete preflight. Apply the same collision checks to a library workspace; the only difference is that its root is under the global kind directory:
1. Resolve `<template_workspace>` from the confirmed scope and confirm its required `templates/` destination plus any needed `images/` / `icons/` destinations. 1. Resolve `<template_workspace>` from the confirmed scope and confirm its required `templates/` destination plus any needed `images/` / `icons/` destinations.
2. Confirm `<template_workspace>/templates/` is empty. 2. For `library`, confirm `<template_workspace>/templates/` is empty. For `project`, reject a bare `design_spec.md`, any existing spec of the selected kind, or any invalid qualified-name set. All distinct kinds may coexist. Resolve active structure before writing: Layout when present, otherwise Deck. Adding Deck beside Layout leaves the Layout roster untouched; adding Layout beside Deck atomically replaces the active Deck structural payload only after the new Layout passes isolated validation.
3. Resolve every final bitmap and extracted-vector filename, then confirm none would overwrite an existing file in `images/` or `icons/imported/`. Check the review-PPTX destination when preview export was requested or a multi-Master template was confirmed. 3. Resolve every final bitmap and extracted-vector filename, then confirm none would overwrite an existing file in `images/` or `icons/imported/`. Check the review-PPTX destination when preview export was requested or a multi-Master template was confirmed.
Any failed check aborts before writing `design_spec.md`, SVGs, images, icons, or the review PPTX. Do not merge into a non-empty template source and do not overwrite a name conflict. Temporary Step 1 analysis workspaces remain allowed because they are not final outputs. Any failed check aborts before writing the Design Spec, SVGs, images, icons, or the review PPTX. A library source remains empty-before-write; a project source preserves every non-conflicting sibling kind and replaces only a lower-priority Deck structural payload when a validated Layout takes ownership. Never overwrite an unrelated name conflict. Temporary analysis and structural-transition workspaces remain allowed because they are not final outputs.
## Process Overview ## Process Overview
@@ -122,7 +124,7 @@ below are Create Layout/Create Deck concerns.
Type A is the canonical mirror path: `manifest.json`, `native_structure.json`, layered lossless `svg/`, and inheritance facts describe the native structure that still exists in the PPTX package. Optional `svg-flat/` files are complete-page verification views, never structure authority. In `standard` / `fidelity`, imported facts and visuals do not define output topology. Type A is the canonical mirror path: `manifest.json`, `native_structure.json`, layered lossless `svg/`, and inheritance facts describe the native structure that still exists in the PPTX package. Optional `svg-flat/` files are complete-page verification views, never structure authority. In `standard` / `fidelity`, imported facts and visuals do not define output topology.
**Type B source normalization**: when the supplied root contains `templates/design_spec.md`, use `<input>/templates/` as the SVG/spec source and resolve its workspace assets from sibling `<input>/images/` and `<input>/icons/`. Otherwise, use the supplied directory itself as the legacy-flat/loose SVG source. Directory flatness is not a semantic-structure signal. **Type B source normalization**: when the supplied root exposes any `templates/` Design Spec, use `<input>/templates/` as the SVG/spec source and resolve its workspace assets from sibling `<input>/images/` and `<input>/icons/`. Otherwise, use the supplied directory itself as the legacy-flat/loose SVG source. Directory flatness is not a semantic-structure signal.
Type B is supported with caveats: Type B is supported with caveats:
@@ -189,7 +191,7 @@ After any other direct IR edit, refresh it before the next analysis pass:
python3 skills/ppt-master/scripts/svg_authoring_view.py "<import_workspace>/authoring-svg" --refresh-summary python3 skills/ppt-master/scripts/svg_authoring_view.py "<import_workspace>/authoring-svg" --refresh-summary
``` ```
`authoring-svg/` is the canonical editable IR for template creation. The lossless trees are read only by materialization when an unchanged referenced object needs supported native payload or fallback evidence. Do not edit or copy the lossless SVGs directly. The IR is not a finished template directory and must be materialized into validated `<template_workspace>/templates/*.svg` before preview or export. `authoring-svg/` is the canonical editable IR for template creation. The lossless trees are read only by materialization when an unchanged referenced object needs supported native payload or fallback evidence. Do not edit or copy the lossless SVGs directly. The IR is not a finished template directory and must be materialized into the active authoring workspace's validated `templates/*.svg` before preview or export.
For a Type A `mirror`, final materialization is owned by For a Type A `mirror`, final materialization is owned by
`mirror_template_materialize.py`; never assemble the structured output by `mirror_template_materialize.py`; never assemble the structured output by
@@ -404,7 +406,7 @@ Compose one concise natural-language proposal that states the template the AI in
| Field | Must show | | Field | Must show |
|---|---| |---|---|
| Output scope | Recommended `library` (default) plus `project`; explain that both use the same portable workspace routing and only the parent path / global registration differ | | Output scope | Recommended `library` (default) plus `project`; explain that both use the same spec schema and asset routing, while parent path, spec filename placement, and global registration differ |
| Target project | Required only for `project`; show the exact initialized project workspace path, not a project nickname | | Target project | Required only for `project`; show the exact initialized project workspace path, not a project nickname |
| Selected child workflow | Echo the already-dispatched Create Brand, Create Style, Create Layout, or Create Deck workflow; do not reopen kind selection inside the brief | | Selected child workflow | Echo the already-dispatched Create Brand, Create Style, Create Layout, or Create Deck workflow; do not reopen kind selection inside the brief |
| Method and direction | Create Style only. Summarize the portable communication method, evidence discipline, page-role vocabulary, information design, visual defaults, image/icon direction, and advisory review focus. Do not include a current audience/outcome, page order/count, canvas, or prototype plan. | | Method and direction | Create Style only. Summarize the portable communication method, evidence discipline, page-role vocabulary, information design, visual defaults, image/icon direction, and advisory review focus. Do not include a current audience/outcome, page order/count, canvas, or prototype plan. |
@@ -420,7 +422,7 @@ Items to surface:
| Item | Required | Provenance by evidence channel | | Item | Required | Provenance by evidence channel |
|------|----------|--------------------------| |------|----------|--------------------------|
| Output scope | Yes | `[decision]``library` (default, globally reusable and indexed) or `project` (same portable workspace routing under one initialized project) | | Output scope | Yes | `[decision]``library` (default, globally reusable and indexed) or `project` (qualified Design Spec under one initialized shared project root) |
| Target project | Yes for `project`; N/A for `library` | `[decision]` — explicit path to the initialized target workspace; validate it during the Step 4 preflight | | Target project | Yes for `project`; N/A for `library` | `[decision]` — explicit path to the initialized target workspace; validate it during the Step 4 preflight |
| New template ID | Yes | `[decision]` when supplied; otherwise propose a filesystem-safe ASCII slug as `[suggested]`. In library scope it also becomes the matching index key | | New template ID | Yes | `[decision]` when supplied; otherwise propose a filesystem-safe ASCII slug as `[suggested]`. In library scope it also becomes the matching index key |
| Template display name | Yes | `[decision]` when supplied; otherwise `[suggested]`, often from `manifest.json.source.name` for type A | | Template display name | Yes | `[decision]` when supplied; otherwise `[suggested]`, often from `manifest.json.source.name` for type A |
@@ -453,7 +455,7 @@ When the bundle includes Type A for Create Layout/Create Deck, also include in t
The user replies with corrections, additions, or "all good". The user replies with corrections, additions, or "all good".
> **Persist the portable brief into `design_spec.md`**. In Step 4, declare a YAML frontmatter block with the child-specific ID key (`brand_id`, `style_id`, `deck_id`, or `layout_id`) and only fields owned by that child. Create Brand follows its identity schema. Create Style persists only `style_id`, `kind`, `summary`, and `keywords`; its method and direction live in the required body sections, and it writes no canvas, category, identity, application, replication, native-structure, page-count, or roster fields. Create Layout/Create Deck persist 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`, etc.). `replication_mode` is the AI-derived implementation record, not a user selection. A Deck writes descriptive application context in Template Overview and factual prototype descriptions in Page Roster rather than duplicating that prose into frontmatter. Do not persist a generic `template_id` field: it is the parent workflow's cross-kind name, not a registrar schema key. Do not persist the execution-only `output_scope` or `target_project` fields. In library scope, `register_template.py` reads this frontmatter in Step 7 so the brief flows directly into the index without the AI re-deriving it from prose. > **Persist the portable brief into `<design_spec_path>`**. In Step 4, declare a YAML frontmatter block with the child-specific ID key (`brand_id`, `style_id`, `deck_id`, or `layout_id`) and only fields owned by that child. Create Brand follows its identity schema. Create Style persists only `style_id`, `kind`, `summary`, and `keywords`; its method and direction live in the required body sections, and it writes no canvas, category, identity, application, replication, native-structure, page-count, or roster fields. Create Layout/Create Deck persist 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`, etc.). `replication_mode` is the AI-derived implementation record, not a user selection. A Deck writes descriptive application context in Template Overview and factual prototype descriptions in Page Roster rather than duplicating that prose into frontmatter. Do not persist a generic `template_id` field: it is the parent workflow's cross-kind name, not a registrar schema key. Do not persist the execution-only `output_scope` or `target_project` fields. In library scope, `register_template.py` reads this frontmatter in Step 7 so the brief flows directly into the index without the AI re-deriving it from prose.
--- ---
@@ -472,7 +474,7 @@ Skipping this gate — including silently inferring values from reference files,
- [ ] The user saw one concise natural-language creation plan rather than a mode menu or content-policy checklist - [ ] The user saw one concise natural-language creation plan rather than a mode menu or content-policy checklist
- [ ] User-facing language describes the intended result; internal enum IDs are absent or confined to an audit note - [ ] User-facing language describes the intended result; internal enum IDs are absent or confined to an audit note
- [ ] User has replied with corrections or explicit acceptance of the proposed result - [ ] User has replied with corrections or explicit acceptance of the proposed result
- [ ] Output scope is confirmed; both scopes use the same workspace shape, while `project` includes an explicit initialized target-project path - [ ] Output scope is confirmed; both scopes use the same spec schema and asset routing with their resolved Design Spec names, while `project` includes an explicit initialized target-project path
- [ ] For Create Layout/Create Deck, the canvas format is fixed before SVG generation - [ ] For Create Layout/Create Deck, the canvas format is fixed before SVG generation
- [ ] For Create Layout/Create Deck, the AI-derived internal strategy is consistent with the bundle evidence (`fidelity` requires A/B page evidence; `mirror` requires A or structured B; C/D/E channels alone permit only `standard`); Create Layout mirror evidence is already brand-neutral and application-neutral - [ ] For Create Layout/Create Deck, the AI-derived internal strategy is consistent with the bundle evidence (`fidelity` requires A/B page evidence; `mirror` requires A or structured B; C/D/E channels alone permit only `standard`); Create Layout mirror evidence is already brand-neutral and application-neutral
- [ ] Every supplied visual, textual, documentary, web, and asset channel has been analyzed or explicitly excluded; mixed-input conflicts are surfaced rather than silently resolved - [ ] Every supplied visual, textual, documentary, web, and asset channel has been analyzed or explicitly excluded; mixed-input conflicts are surfaced rather than silently resolved
@@ -506,18 +508,24 @@ template_workspace="<target_project>"
mkdir -p "$template_workspace/templates" mkdir -p "$template_workspace/templates"
``` ```
Normally `<authoring_workspace>` equals `<template_workspace>`. When the project
already has the other structural kind, use an isolated project-shaped root
through validation and preview. Its `<design_spec_path>` is temporary;
`<installed_design_spec_path>` is the final table path. Create its `templates/`
only after preflight.
| Scope | Workspace target | Required action before generation | | Scope | Workspace target | Required action before generation |
|---|---|---| |---|---|---|
| `library` | `skills/ppt-master/templates/<kind_dir>/<template_id>/` | Run the common workspace preflight; the directory name matches the final template ID used in the relevant index | | `library` | `skills/ppt-master/templates/<kind_dir>/<template_id>/` | Resolve `<design_spec_path>` to `templates/design_spec.md`; run the common workspace preflight; the directory name matches the final template ID used in the relevant index |
| `project` | `<target_project>/` | Run the same workspace preflight against the initialized project root | | `project` | `<target_project>/` | Resolve the final spec destination to `templates/design_spec.<kind>.<id>.md`; run the project coexistence preflight. Author directly unless Layout/Deck precedence requires isolated validation before atomic install |
The preflight is atomic at the Create Template parent level: discover and settle every output filename first, check all destinations together, then begin generation. Do not partially write a workspace and discover a later collision. The preflight is atomic at the Create Template parent level: settle every output filename and check all destinations before generation. Pass the active `<design_spec_path>` to the selected child. For a project structural transition, validate in the isolated root, then install its spec at `<installed_design_spec_path>` and its assets atomically: Layout replaces the Deck roster; Deck beside Layout installs no structural payload. Delete staging only after the final project root passes.
**Create Brand branch**: continue in [`create-brand.md`](./create-template/create-brand.md) §3 with the confirmed identity brief and resolved `<template_workspace>`. Then return to the Create Brand branch in Step 5. Do not invoke Template_Designer, create SVGs, or apply the Create Layout/Create Deck-only material below. **Create Brand branch**: continue in [`create-brand.md`](./create-template/create-brand.md) §3 with the confirmed identity brief and resolved `<template_workspace>` / `<design_spec_path>`. Then return to the Create Brand branch in Step 5. Do not invoke Template_Designer, create SVGs, or apply the Create Layout/Create Deck-only material below.
**Create Style branch**: continue in [`create-style.md`](./create-template/create-style.md) §3 with the confirmed method/direction brief and resolved `<template_workspace>`. Then return to the Create Style branch in Step 5. Do not invoke Template_Designer, create SVGs, retain source page topology, or apply the Create Layout/Create Deck-only material below. **Create Style branch**: continue in [`create-style.md`](./create-template/create-style.md) §3 with the confirmed method/direction brief and resolved `<template_workspace>` / `<design_spec_path>`. Then return to the Create Style branch in Step 5. Do not invoke Template_Designer, create SVGs, retain source page topology, or apply the Create Layout/Create Deck-only material below.
**Create Layout/Create Deck branch**: continue in the selected child workflow, switch to the Template_Designer role, and generate per role definition. The role input is the finalized brief from Step 3 plus the analysis bundle from Step 1, including the accepted basic template norms. **Create Layout/Create Deck branch**: continue in the selected child workflow, switch to the Template_Designer role, and generate per role definition. Bind the role's `<template_workspace>` to `<authoring_workspace>` and pass `<design_spec_path>`, the finalized brief from Step 3, and the Step-1 analysis bundle with accepted norms.
When the bundle includes Type A, pass the following internal package to the role: When the bundle includes Type A, pass the following internal package to the role:
@@ -544,19 +552,21 @@ The role interprets the package according to the AI-derived internal creation st
| `standard` / `fidelity` | Newly authored SVGs based on the confirmed brief and visual references | Design an intentional new Master/Layout/slot system. Source topology is neither preserved nor distilled into the output. | | `standard` / `fidelity` | Newly authored SVGs based on the confirmed brief and visual references | Design an intentional new Master/Layout/slot system. Source topology is neither preserved nor distilled into the output. |
| `mirror` | Editable `authoring-svg/` IR plus native-structure facts and lossless payload backing | Materialize source pages, Master/Layout identities and parentage, placeholder identity/bounds, ownership, and supported native-object metadata one-to-one in the new workspace. Materialization resolves unchanged source refs; it does not copy the lossless tree as the editable source. | | `mirror` | Editable `authoring-svg/` IR plus native-structure facts and lossless payload backing | Materialize source pages, Master/Layout identities and parentage, placeholder identity/bounds, ownership, and supported native-object metadata one-to-one in the new workspace. Materialization resolves unchanged source refs; it does not copy the lossless tree as the editable source. |
For Type A `mirror`, materialize the reviewed layered IR into an empty template For Type A `mirror`, materialize the reviewed layered IR into a workspace with
workspace with the deterministic compiler: no existing roster, using the deterministic compiler:
```bash ```bash
python3 skills/ppt-master/scripts/mirror_template_materialize.py \ python3 skills/ppt-master/scripts/mirror_template_materialize.py \
"<import_workspace>" "<template_workspace>" "<import_workspace>" "<authoring_workspace>"
``` ```
The destination `templates/` directory must be absent or empty. Before Destination `templates/` may be absent/empty or hold unique qualified
publication, the command verifies the layered manifest and source-ref closure, Brand/Style specs; a Layout-over-Deck stage may also hold one qualified Deck
lossless SVG and source-PPTX hashes, complete native/inheritance graph, and spec without its roster. A bare spec, Layout spec, active roster, or other
extracted-vector inventory. It then stages and publishes the entire roster in payload blocks materialization. Before atomic publication, the command verifies
one operation. It emits source-ordered page SVGs, unused-Layout definition the layered manifest/source refs, lossless SVG/source-PPTX hashes, complete
native/inheritance graph, and vector inventory. It emits source-ordered page
SVGs, unused-Layout definition
SVGs, `icons/imported/`, referenced `images/` / `templates/assets/`, and one SVGs, `icons/imported/`, referenced `images/` / `templates/assets/`, and one
deduplicated `templates/native_payloads.json.gz` store when supported native deduplicated `templates/native_payloads.json.gz` store when supported native
payload or repeated restoration metadata exists. It also writes payload or repeated restoration metadata exists. It also writes
@@ -573,16 +583,16 @@ topology checks. Template SVGs and imported
vectors keep content-hash payload references plus short vectors keep content-hash payload references plus short
`data-pptx-native-ref` attribute-record ids. Structural Master/Layout, `data-pptx-native-ref` attribute-record ids. Structural Master/Layout,
placeholder, layer, and editable-object fields remain inline. The command does placeholder, layer, and editable-object fields remain inline. The command does
not create `design_spec.md`. Template_Designer writes that file from the not create the Design Spec. Template_Designer writes `<design_spec_path>` from
confirmed brief and the materialized roster before Step 5. A rerun targets a the confirmed brief and the materialized roster before Step 5. A rerun targets
new empty workspace rather than overwriting a partially reviewed template. a workspace with no roster rather than overwriting a partially reviewed one.
**Hard rule — mode-specific authorship**: `standard` and `fidelity` author new **Hard rule — mode-specific authorship**: `standard` and `fidelity` author new
project-canonical SVG documents. When one registered PowerPoint preset exactly project-canonical SVG documents. When one registered PowerPoint preset exactly
expresses one complete object, they use the compact canonical expresses one complete object, they use the compact canonical
`<g>` emitted by `preset_shape_svg.py`, following `<g>` emitted by `preset_shape_svg.py`, following
[`native-shape-authoring.md`](../references/native-shape-authoring.md); its [`native-shape-authoring.md`](../references/native-shape-authoring.md); its
paint comes from the confirmed brief and template `design_spec.md`. After paint comes from the confirmed brief and `<design_spec_path>`. After
inserting the complete helper group, add only the registered structural inserting the complete helper group, add only the registered structural
attributes required by its Master/Layout or object-slot role; geometry and attributes required by its Master/Layout or object-slot role; geometry and
paint changes require a new helper render. When actual `standard` / `fidelity` paint changes require a new helper render. When actual `standard` / `fidelity`
@@ -608,7 +618,7 @@ SVG authors own the semantic roster, parentage, picker names, direct atoms, and
Do not package `native_structure.json` or `source_template.pptx` as template inputs. In `standard` / `fidelity`, author Master/Layout direct semantic atoms and bounded slot groups deliberately from the intended reusable behavior. A validated compact canonical authored-preset `<g>` compiles to one native shape and therefore counts as one semantic atom; it may own a Master/Layout fixed layer or serve as the one direct carrier of an `object` slot. Ordinary groups are not structural atoms or single-object carriers. In `mirror`, edit the layered authoring IR and use inheritance/native facts to preserve source ownership; the lossless trees remain payload backing. Recursively expand fixed Master/Layout group wrappers only because the structured contract requires semantic atoms; preserve transforms, styles, paint order, and appearance, and never flatten or regroup by semantic judgment. Do not package `native_structure.json` or `source_template.pptx` as template inputs. In `standard` / `fidelity`, author Master/Layout direct semantic atoms and bounded slot groups deliberately from the intended reusable behavior. A validated compact canonical authored-preset `<g>` compiles to one native shape and therefore counts as one semantic atom; it may own a Master/Layout fixed layer or serve as the one direct carrier of an `object` slot. Ordinary groups are not structural atoms or single-object carriers. In `mirror`, edit the layered authoring IR and use inheritance/native facts to preserve source ownership; the lossless trees remain payload backing. Recursively expand fixed Master/Layout group wrappers only because the structured contract requires semantic atoms; preserve transforms, styles, paint order, and appearance, and never flatten or regroup by semantic judgment.
`design_spec.md §V` records the newly authored roster for `standard` / `fidelity`. For `mirror`, add the `Source Preservation Map` required by [template-designer.md](../references/template-designer.md), with one row per source slide and its preserved Master/Layout assignment. Do not add a synthesis-decision table. `<design_spec_path> §V` records the newly authored roster for `standard` / `fidelity`. For `mirror`, add the `Source Preservation Map` required by [template-designer.md](../references/template-designer.md), with one row per source slide and its preserved Master/Layout assignment. Do not add a synthesis-decision table.
**Native-shape metadata boundary**: The authoring IR removes opaque payload **Native-shape metadata boundary**: The authoring IR removes opaque payload
from model context while retaining stable source refs. `standard` / `fidelity` from model context while retaining stable source refs. `standard` / `fidelity`
@@ -630,7 +640,7 @@ Downstream, Strategist inspects the installed workspace and current content, the
**Mirror materialization contract** (type A or B): when the derived implementation writes `replication_mode: mirror`, the Template_Designer role: **Mirror materialization contract** (type A or B): when the derived implementation writes `replication_mode: mirror`, the Template_Designer role:
1. **Materializes one output SVG per source page** in `<template_workspace>/templates/`. Edit and normalize the matching `authoring-svg/` IR document, then run `mirror_template_materialize.py`; the compiler consumes the tool-only authoring manifest together with native structure facts and immutable payload backing. Do not hand-copy or independently rebuild its graph. Preserve the source Master/Layout keys and picker names, Layout parentage, slide assignment, placeholder type/index/bounds, inherited-shape visibility, ownership, paint order, and supported native metadata that are present and validated. Mechanical namespace, root-declaration, asset-path, and fixed-layer group normalization is allowed only when source ownership and appearance remain unchanged. 1. **Materializes one output SVG per source page** in `<authoring_workspace>/templates/`. Edit and normalize the matching `authoring-svg/` IR document, then run `mirror_template_materialize.py`; the compiler consumes the tool-only authoring manifest together with native structure facts and immutable payload backing. Do not hand-copy or independently rebuild its graph. Preserve the source Master/Layout keys and picker names, Layout parentage, slide assignment, placeholder type/index/bounds, inherited-shape visibility, ownership, paint order, and supported native metadata that are present and validated. Mechanical namespace, root-declaration, asset-path, and fixed-layer group normalization is allowed only when source ownership and appearance remain unchanged.
- Type A model-facing source: `<import_workspace>/authoring-svg/authoring_summary.json` plus the editable SVGs; `<import_workspace>/svg/`, `svg/inheritance.json`, and `native_structure.json` provide payload and structural backing. The compiler alone reads `<import_workspace>/authoring-svg/authoring_manifest.json`. Optional `<import_workspace>/svg-flat/` is verification-only. - Type A model-facing source: `<import_workspace>/authoring-svg/authoring_summary.json` plus the editable SVGs; `<import_workspace>/svg/`, `svg/inheritance.json`, and `native_structure.json` provide payload and structural backing. The compiler alone reads `<import_workspace>/authoring-svg/authoring_manifest.json`. Optional `<import_workspace>/svg-flat/` is verification-only.
- Type B model-facing source: `<svg_analysis_workspace>/authoring-svg/authoring_summary.json` plus its editable SVGs; the complete explicit source SVG contract is immutable backing - Type B model-facing source: `<svg_analysis_workspace>/authoring-svg/authoring_summary.json` plus its editable SVGs; the complete explicit source SVG contract is immutable backing
- For every source Layout unused by all source slides, additionally materialize one definition-only SVG named `layout_<layout_key>.svg` from its layered authoring IR document and payload backing. It carries the exact root identity, fixed atoms, and placeholder contract but is not a generated page assignment. Use source placeholder prompts/carriers; do not invent business content. This definition SVG lets downstream export register the Layout and any otherwise-unused parent Master without retaining an internal carrier slide. - For every source Layout unused by all source slides, additionally materialize one definition-only SVG named `layout_<layout_key>.svg` from its layered authoring IR document and payload backing. It carries the exact root identity, fixed atoms, and placeholder contract but is not a generated page assignment. Use source placeholder prompts/carriers; do not invent business content. This definition SVG lets downstream export register the Layout and any otherwise-unused parent Master without retaining an internal carrier slide.
@@ -640,17 +650,17 @@ Downstream, Strategist inspects the installed workspace and current content, the
3. **Routes bundled assets through the common workspace contract** and rewrites every `<image href="...">` consistently. Keep stable source asset identity in mirror; do not rename, merge, or replace assets by semantic judgment. 3. **Routes bundled assets through the common workspace contract** and rewrites every `<image href="...">` consistently. Keep stable source asset identity in mirror; do not rename, merge, or replace assets by semantic judgment.
- Type A: assets come from `<import_workspace>/assets/` - Type A: assets come from `<import_workspace>/assets/`
- Type B: resolve relative paths in source `<image href="...">` against the source SVG location and copy each unique asset; if the source already follows PPT Master conventions (assets co-located with SVGs in the same directory), copy the whole asset set and then rewrite paths - Type B: resolve relative paths in source `<image href="...">` against the source SVG location and copy each unique asset; if the source already follows PPT Master conventions (assets co-located with SVGs in the same directory), copy the whole asset set and then rewrite paths
- Both scopes: write bitmaps to `<template_workspace>/images/`, point SVG references at `../images/<name>`, and keep non-bitmap template-source assets under `<template_workspace>/templates/`. - Both scopes: write bitmaps to `<authoring_workspace>/images/`, point SVG references at `../images/<name>`, and keep non-bitmap template-source assets under `<authoring_workspace>/templates/`.
4. **Copies imported vector assets once** to `<template_workspace>/icons/imported/` and rewrites their placeholders to `<use data-icon="imported/<name>"/>`. Never place a second copy under `templates/icons/`. Other explicitly adopted icon-library references keep their existing library namespace. Do not inline these assets manually in the template working SVGs; template validation, preview, and final export all resolve icons from the workspace-root `icons/` directory. 4. **Copies imported vector assets once** to `<authoring_workspace>/icons/imported/` and rewrites their placeholders to `<use data-icon="imported/<name>"/>`. Never place a second copy under `templates/icons/`. Other explicitly adopted icon-library references keep their existing library namespace. Do not inline these assets manually in the template working SVGs; template validation, preview, and final export all resolve icons from the workspace-root `icons/` directory.
5. Writes `design_spec.md` per [template-designer.md](../references/template-designer.md) §1. The §V Page Roster remains a factual prototype index; explicit SVG metadata is the native Master/Layout contract. `replication_mode: mirror` records how the workspace was created and only makes literal downstream reuse technically possible; it never selects that behavior or forces a 1:1 slide sequence. 5. Writes `<design_spec_path>` per [template-designer.md](../references/template-designer.md) §1. The §V Page Roster remains a factual prototype index; explicit SVG metadata is the native Master/Layout contract. `replication_mode: mirror` records how the workspace was created and only makes literal downstream reuse technically possible; it never selects that behavior or forces a 1:1 slide sequence.
Mirror mode does not simplify the visual target or synthesize layer ownership. The sprite-sheet preservation rule applies because crop wrappers carry visible geometry; preserve those wrappers and their source scope faithfully. Mirror mode does not simplify the visual target or synthesize layer ownership. The sprite-sheet preservation rule applies because crop wrappers carry visible geometry; preserve those wrappers and their source scope faithfully.
**Expected outputs from this step** (full spec → [template-designer.md](../references/template-designer.md)): **Expected outputs from this step** (full spec → [template-designer.md](../references/template-designer.md)):
1. `design_spec.md`**package-specific rules only**. A deck writes a descriptive Template Overview, Color Scheme, Signature Design Elements, and factual Page Roster; Typography / Assets / Placeholder Overrides are conditional. A layout writes only structure-owned Signature Design Elements and Page Roster; its frontmatter `summary` carries concise selection context, and it omits the deck-only Template Overview plus every identity section. The Page Roster must match the actual SVG files on disk and must not prescribe which pages or sample content a future project keeps. Declare portable brief frontmatter; `register_template.py` consumes it only in library scope. **Do not** restate generic SVG constraints, layout pattern libraries, font-size ratio bands, the canonical placeholder table, or content methodology — those are sourced from `shared-standards-core.md` / `pptx-structure-interface.md` / `strategist.md` and are already in the downstream reader's context. Full scope rule and skeleton: [template-designer.md §1](../references/template-designer.md#1-must-generate-design_specmd). 1. `<design_spec_path>`**package-specific rules only**. A deck writes a descriptive Template Overview, Color Scheme, Signature Design Elements, and factual Page Roster; Typography / Assets / Placeholder Overrides are conditional. A layout writes only structure-owned Signature Design Elements and Page Roster; its frontmatter `summary` carries concise selection context, and it omits the deck-only Template Overview plus every identity section. The Page Roster must match the actual SVG files on disk and must not prescribe which pages or sample content a future project keeps. Declare portable brief frontmatter; `register_template.py` consumes it only in library scope. **Do not** restate generic SVG constraints, layout pattern libraries, font-size ratio bands, the canonical placeholder table, or content methodology — those are sourced from `shared-standards-core.md` / `pptx-structure-interface.md` / `strategist.md` and are already in the downstream reader's context. Full scope rule and skeleton: [template-designer.md §1](../references/template-designer.md#1-must-generate-design_specmd).
2. Page roster — see [Page Roster](../references/template-designer.md#page-roster) for `standard` / `fidelity` / `mirror` mode rosters, variant naming, and TOC handling 2. Page roster — see [Page Roster](../references/template-designer.md#page-roster) for `standard` / `fidelity` / `mirror` mode rosters, variant naming, and TOC handling
3. Placeholder vocabulary — pages should adopt the conventional names (`{{TITLE}}`, `{{CONTENT_AREA}}`, ...) when they fit. Full reference: [Placeholder Reference](../references/template-designer.md#4-placeholder-reference-canonical-convention-overridable-per-template). When a template style legitimately needs different vocabulary (consulting → `{{KEY_MESSAGE}}`, branded cover → `{{BRAND_LOGO}}`), declare a `placeholders:` block in `design_spec.md` frontmatter so the registrar and quality checker treat it as the template's authoritative contract. **Avoid** one-off indexed families such as `{{CHAPTER_01_TITLE}}` — use the indexed TOC pattern instead. 3. Placeholder vocabulary — pages should adopt the conventional names (`{{TITLE}}`, `{{CONTENT_AREA}}`, ...) when they fit. Full reference: [Placeholder Reference](../references/template-designer.md#4-placeholder-reference-canonical-convention-overridable-per-template). When a template style legitimately needs different vocabulary (consulting → `{{KEY_MESSAGE}}`, branded cover → `{{BRAND_LOGO}}`), declare a `placeholders:` block in `<design_spec_path>` frontmatter so the registrar and quality checker treat it as the template's authoritative contract. **Avoid** one-off indexed families such as `{{CHAPTER_01_TITLE}}` — use the indexed TOC pattern instead.
- `{{...}}` placeholders are the authoring vocabulary used to generate final slide content. Each emitted SVG also carries the native structure contract: root Master/Layout key/name, direct atomic Master/Layout elements, and direct slot `<g>` elements with explicit design-zone bounds plus exactly one compatible carrier. A validated compact canonical authored-preset `<g>` counts as one semantic atom or one `object` carrier; ordinary groups do not. Composite regions use only the explicit `object` + `proxy` downgrade. Minimal structural `data-pptx-role` hints are added only when specialized metadata cannot express required behavior. Both strict and adaptive downstream set `mode: structured` and require complete `page_layouts`, `page_pptx_layouts`, `pptx_masters`, and `pptx_layouts` from planning onward. - `{{...}}` placeholders are the authoring vocabulary used to generate final slide content. Each emitted SVG also carries the native structure contract: root Master/Layout key/name, direct atomic Master/Layout elements, and direct slot `<g>` elements with explicit design-zone bounds plus exactly one compatible carrier. A validated compact canonical authored-preset `<g>` counts as one semantic atom or one `object` carrier; ordinary groups do not. Composite regions use only the explicit `object` + `proxy` downgrade. Minimal structural `data-pptx-role` hints are added only when specialized metadata cannot express required behavior. Both strict and adaptive downstream set `mode: structured` and require complete `page_layouts`, `page_pptx_layouts`, `pptx_masters`, and `pptx_layouts` from planning onward.
4. Template assets (optional) — both scopes apply the same `templates/` / `images/` / root `icons/imported/` routing defined above 4. Template assets (optional) — both scopes apply the same `templates/` / `images/` / root `icons/imported/` routing defined above
@@ -663,7 +673,7 @@ becomes the prototype Slide placeholder, while
|---|---| |---|---|
| Full editable frame | `data-pptx-bounds` describes the complete intended text, picture, chart, table, or object box. Never derive it from the sample text's glyph bounds or leave it as a one-line tight box. | | Full editable frame | `data-pptx-bounds` describes the complete intended text, picture, chart, table, or object box. Never derive it from the sample text's glyph bounds or leave it as a one-line tight box. |
| Generic text entry | General `body` and text-carried `object` slots begin at the upper-left, use left paragraph alignment, and wrap inside the full frame. Title/subtitle alignment follows the authored composition. | | Generic text entry | General `body` and text-carried `object` slots begin at the upper-left, use left paragraph alignment, and wrap inside the full frame. Title/subtitle alignment follows the authored composition. |
| Centered exceptions | Center alignment is reserved for semantically short focal content such as KPI values, short process nodes, hero statements, and compact takeaways. Record a template-wide exception in `design_spec.md §IV` when it is part of the layout grammar. | | Centered exceptions | Center alignment is reserved for semantically short focal content such as KPI values, short process nodes, hero statements, and compact takeaways. Record a template-wide exception in `<design_spec_path> §IV` when it is part of the layout grammar. |
| Review Slide binding | `template_preview_pptx.py` sizes each authored Slide carrier to the same complete frame as its registered Layout placeholder. A review deck whose Slide carrier is only the prompt text's tight box fails Step 6. | | Review Slide binding | `template_preview_pptx.py` sizes each authored Slide carrier to the same complete frame as its registered Layout placeholder. A review deck whose Slide carrier is only the prompt text's tight box fails Step 6. |
| Review prompt legibility | For `standard` / `fidelity`, the preview exporter substitutes concise sample text only in ephemeral review SVGs so long canonical markers such as `{{CHAPTER_NUM}}` or `{{PAGE_NUM}}` do not wrap. The source SVG markers, carrier font sizes, slot metadata, and Layout frames remain unchanged. | | Review prompt legibility | For `standard` / `fidelity`, the preview exporter substitutes concise sample text only in ephemeral review SVGs so long canonical markers such as `{{CHAPTER_NUM}}` or `{{PAGE_NUM}}` do not wrap. The source SVG markers, carrier font sizes, slot metadata, and Layout frames remain unchanged. |
| Mirror boundary | `mirror` preserves source Slide carrier geometry exactly in the tool-side native record referenced by its text carrier and keeps `data-pptx-bounds` as the reusable Layout default. Do not normalize one to the other when the source intentionally overrides that frame. | | Mirror boundary | `mirror` preserves source Slide carrier geometry exactly in the tool-side native record referenced by its text carrier and keeps `data-pptx-bounds` as the reusable Layout default. Do not normalize one to the other when the source intentionally overrides that frame. |
@@ -707,11 +717,11 @@ After Create Style validation passes, skip the Create Layout/Create Deck-only
remainder of this step and all of Step 6; continue at Step 7. Review Focus is remainder of this step and all of Step 6; continue at Step 7. Review Focus is
advisory content only and never activates the Generate visual-review stage. advisory content only and never activates the Generate visual-review stage.
**Create Layout/Create Deck branch**: set `<template_source>` to `<template_workspace>/templates/` in both scopes. **Create Layout/Create Deck branch**: set `<template_source>` to the active authoring root's `templates/`. This is `<template_workspace>/templates/` normally and the isolated project-shaped staging root during a structural precedence transition.
```bash ```bash
ls -la "<template_workspace>/templates" ls -la "<template_source>"
ls -la "<template_workspace>/images" "<template_workspace>/icons" ls -la "<authoring_workspace>/images" "<authoring_workspace>/icons"
``` ```
Compact safe page-space metadata and transform coordinates, then run SVG Compact safe page-space metadata and transform coordinates, then run SVG
@@ -719,16 +729,16 @@ validation on the template directory. Keep canonical authored-preset and native
record frames unchanged: record frames unchanged:
```bash ```bash
python3 skills/ppt-master/scripts/compact_svg_coordinates.py "<template_workspace>/templates" --inplace --keep-native-frames python3 skills/ppt-master/scripts/compact_svg_coordinates.py "<template_source>" --inplace --keep-native-frames
python3 skills/ppt-master/scripts/svg_quality_checker.py "<template_workspace>/templates" --template-mode --format <canvas_format> python3 skills/ppt-master/scripts/svg_quality_checker.py "<template_source>" --template-mode --format <canvas_format>
``` ```
`--template-mode` makes the checker: `--template-mode` makes the checker:
- glob `*.svg` in the template directory directly (templates do not live under `svg_output/`) - glob `*.svg` in the template directory directly (templates do not live under `svg_output/`)
- skip `spec_lock.md` drift checks (templates do not ship a spec_lock) - skip `spec_lock.md` drift checks (templates do not ship a spec_lock)
- enforce roster ↔ `design_spec.md` consistency as **errors** (orphan files / missing files break the template contract and, in library scope, the target kind's index) - enforce roster ↔ resolved Design Spec consistency as **errors** (orphan files / missing files break the template contract and, in library scope, the target kind's index)
- emit advisory **warnings** when a page lacks a conventional placeholder — these are hints, not failures. Declare a `placeholders:` block in `design_spec.md` frontmatter to silence them when your template intentionally uses a different vocabulary - emit advisory **warnings** when a page lacks a conventional placeholder — these are hints, not failures. Declare a `placeholders:` block in `<design_spec_path>` frontmatter to silence them when your template intentionally uses a different vocabulary
- require every SVG root to declare one output Master and Layout; zero-slot Layouts are valid - require every SVG root to declare one output Master and Layout; zero-slot Layouts are valid
- reject ordinary Master/Layout `<g>` elements, nested structure markers, missing slot bounds, and carrier-bound slots without exactly one compatible carrier; a validated compact canonical authored-preset `<g>` is the sole fixed-layer group exception and may be one `object` carrier - reject ordinary Master/Layout `<g>` elements, nested structure markers, missing slot bounds, and carrier-bound slots without exactly one compatible carrier; a validated compact canonical authored-preset `<g>` is the sole fixed-layer group exception and may be one `object` carrier
- validate cross-page Master equality plus same-key Layout atom/slot equality - validate cross-page Master equality plus same-key Layout atom/slot equality
@@ -738,16 +748,16 @@ This checker validates the authoring contract, not the compiled OOXML package. T
**Checklist**: **Checklist**:
- [ ] `design_spec.md` follows the kind-specific package skeleton: deck = descriptive Overview / Color / Signature / Page Roster plus conditional sections; layout = structure-owned Signature / Page Roster with no Overview, application contract, or identity sections. Generic constraints (SVG rules, pattern libraries, ratio bands, canonical placeholder table) are NOT restated. The source-derived basic norms are present as template-specific layout / image / density / asset rules, not generic advice. Deck Overview identifies recurring situations, audiences/outcomes, delivery assumptions, and representative narrative/page roles; §V Page Roster factually describes every emitted prototype without required/optional/repeatable or fixed/replaceable/example-only policy - [ ] `<design_spec_path>` follows the kind-specific package skeleton: deck = descriptive Overview / Color / Signature / Page Roster plus conditional sections; layout = structure-owned Signature / Page Roster with no Overview, application contract, or identity sections. Generic constraints (SVG rules, pattern libraries, ratio bands, canonical placeholder table) are NOT restated. The source-derived basic norms are present as template-specific layout / image / density / asset rules, not generic advice. Deck Overview identifies recurring situations, audiences/outcomes, delivery assumptions, and representative narrative/page roles; §V Page Roster factually describes every emitted prototype without required/optional/repeatable or fixed/replaceable/example-only policy
- [ ] Every page declared in `design_spec.md §V Page Roster` exists as an SVG file in the template directory (and vice versa — no orphan files) - [ ] Every page declared in `<design_spec_path> §V Page Roster` exists as an SVG file in the template directory (and vice versa — no orphan files)
- [ ] Variant filenames follow the letter-suffix convention (e.g. `03a_content_two_col.svg`); variants typically reuse the parent type's placeholder set unless the spec frontmatter declares otherwise - [ ] Variant filenames follow the letter-suffix convention (e.g. `03a_content_two_col.svg`); variants typically reuse the parent type's placeholder set unless the spec frontmatter declares otherwise
- [ ] If TOC exists, placeholder pattern uses the canonical indexed form - [ ] If TOC exists, placeholder pattern uses the canonical indexed form
- [ ] `design_spec.md` frontmatter declares `canvas_format`, `canvas_width`, `canvas_height`, and `canvas_viewbox`; PPTX/SVG-backed templates also declare `source_canvas_width`, `source_canvas_height`, and `source_viewbox` - [ ] `<design_spec_path>` frontmatter declares `canvas_format`, `canvas_width`, `canvas_height`, and `canvas_viewbox`; PPTX/SVG-backed templates also declare `source_canvas_width`, `source_canvas_height`, and `source_viewbox`
- [ ] SVG `viewBox` matches the declared canvas dimensions, not just the aspect ratio (for `ppt169`: `0 0 1280 720`; for `banner`: `0 0 1920 1080`); `width` / `height`, if written, equal it - [ ] SVG `viewBox` matches the declared canvas dimensions, not just the aspect ratio (for `ppt169`: `0 0 1280 720`; for `banner`: `0 0 1920 1080`); `width` / `height`, if written, equal it
- [ ] Model-facing placeholder bounds and transform page coordinates use at most two decimals; normalized crop/viewBox ratios, path geometry, transform scale/rotation coefficients, authored-preset frames, and tool-side native frames retain their required precision - [ ] Model-facing placeholder bounds and transform page coordinates use at most two decimals; normalized crop/viewBox ratios, path geometry, transform scale/rotation coefficients, authored-preset frames, and tool-side native frames retain their required precision
- [ ] Placeholder names follow the canonical convention where applicable; templates with intentionally different vocabularies (e.g. `{{KEY_MESSAGE}}` instead of `{{PAGE_TITLE}}`) should declare a `placeholders:` frontmatter block to silence advisory warnings - [ ] Placeholder names follow the canonical convention where applicable; templates with intentionally different vocabularies (e.g. `{{KEY_MESSAGE}}` instead of `{{PAGE_TITLE}}`) should declare a `placeholders:` frontmatter block to silence advisory warnings
- [ ] Asset files referenced by SVGs exist at their resolved paths. In both scopes, bitmap references resolve through `../images/`; no bitmap remains accidentally stranded in `templates/` - [ ] Asset files referenced by SVGs exist at their resolved paths. In both scopes, bitmap references resolve through `../images/`; no bitmap remains accidentally stranded in `templates/`
- [ ] `design_spec.md` frontmatter declares `native_structure_mode: structured`; no `native_structure.json` or `source_template.pptx` is packaged - [ ] `<design_spec_path>` frontmatter declares `native_structure_mode: structured`; no `native_structure.json` or `source_template.pptx` is packaged
- [ ] Every SVG root declares Master/Layout key and picker names; Master/Layout visuals are direct semantic atoms and obey the explicit paint-order contract. Ordinary `<g>` elements remain forbidden there; a validated helper-generated compact canonical preset `<g>` is the sole group exception because it compiles to one native shape. Structural `data-pptx-role` is used only when specialized metadata cannot express required package/page-number/animation behavior - [ ] Every SVG root declares Master/Layout key and picker names; Master/Layout visuals are direct semantic atoms and obey the explicit paint-order contract. Ordinary `<g>` elements remain forbidden there; a validated helper-generated compact canonical preset `<g>` is the sole group exception because it compiles to one native shape. Structural `data-pptx-role` is used only when specialized metadata cannot express required package/page-number/animation behavior
- [ ] Every slot is a direct `<g id>` with explicit design-zone bounds and exactly one compatible direct carrier, or an explicit composite `object` proxy. A validated compact canonical preset `<g>` may be the one carrier of an `object` slot; an ordinary multi-object group may not. Zero-slot Layouts remain valid - [ ] Every slot is a direct `<g id>` with explicit design-zone bounds and exactly one compatible direct carrier, or an explicit composite `object` proxy. A validated compact canonical preset `<g>` may be the one carrier of an `object` slot; an ordinary multi-object group may not. Zero-slot Layouts remain valid
- [ ] For `standard` / `fidelity`, every placeholder bound is the complete editable box rather than the current marker text's tight bounds; general body/object carriers begin at the upper-left and only intentional short focal roles remain centered - [ ] For `standard` / `fidelity`, every placeholder bound is the complete editable box rather than the current marker text's tight bounds; general body/object carriers begin at the upper-left and only intentional short focal roles remain centered
@@ -760,11 +770,11 @@ This checker validates the authoring contract, not the compiled OOXML package. T
- [ ] Mirror preflight covered the complete source graph; each unused Layout has one `layout_<layout_key>.svg` definition prototype and each otherwise-unused Master is retained through at least one such Layout - [ ] Mirror preflight covered the complete source graph; each unused Layout has one `layout_<layout_key>.svg` definition prototype and each otherwise-unused Master is retained through at least one such Layout
- [ ] For `standard` / `fidelity`, no duplicate-Layout-contract warning remains; mirror may keep equivalent source Layout identities when the preservation map explains them - [ ] For `standard` / `fidelity`, no duplicate-Layout-contract warning remains; mirror may keep equivalent source Layout identities when the preservation map explains them
- [ ] All template-creation edits used the authoring IR; Type A mirror used `mirror_template_materialize.py`, validated its manifest/hash/graph/source-ref closure before atomic publication, reused only converter-supported payload for hash-matching Slide-local/slot refs, deduplicated supported opaque payload and repeated native restoration attributes into `templates/native_payloads.json.gz`, stripped IR-only source-ref metadata, and kept fixed Master/Layout visuals as direct atoms - [ ] All template-creation edits used the authoring IR; Type A mirror used `mirror_template_materialize.py`, validated its manifest/hash/graph/source-ref closure before atomic publication, reused only converter-supported payload for hash-matching Slide-local/slot refs, deduplicated supported opaque payload and repeated native restoration attributes into `templates/native_payloads.json.gz`, stripped IR-only source-ref metadata, and kept fixed Master/Layout visuals as direct atoms
- [ ] If any SVG references an extracted vector, it uses `data-icon="imported/<name>"` and the sole SVG asset exists at `<template_workspace>/icons/imported/<name>.svg`; `templates/icons/` does not exist and no separate illustration embedding script was added - [ ] If any SVG references an extracted vector, it uses `data-icon="imported/<name>"` and the sole SVG asset exists at `<authoring_workspace>/icons/imported/<name>.svg`; `templates/icons/` does not exist and no separate illustration embedding script was added
- [ ] For `fidelity` mode: every sprite-sheet asset retains its nested `<svg viewBox=...>` crop wrapper; no image whose file aspect differs from its on-page aspect was flattened to a bare `<image>` - [ ] For `fidelity` mode: every sprite-sheet asset retains its nested `<svg viewBox=...>` crop wrapper; no image whose file aspect differs from its on-page aspect was flattened to a bare `<image>`
- [ ] For `mirror` mode: source-page SVG count equals source page count, while additional files are exactly the required `layout_<layout_key>.svg` definitions for unused source Layouts; source-page filenames follow the `<NNN>_<page_type>.svg` convention; **no new `{{...}}` authoring placeholders were inserted into materialized source-page SVGs**; §V Page Roster lists every emitted file and marks definition-only prototypes explicitly - [ ] For `mirror` mode: source-page SVG count equals source page count, while additional files are exactly the required `layout_<layout_key>.svg` definitions for unused source Layouts; source-page filenames follow the `<NNN>_<page_type>.svg` convention; **no new `{{...}}` authoring placeholders were inserted into materialized source-page SVGs**; §V Page Roster lists every emitted file and marks definition-only prototypes explicitly
This step is a **hard gate**. Do not generate a review PPTX, register, or hand the workspace to the main pipeline until validation passes. A one-Master template may skip Step 6 when no review was requested; a multi-Master template must continue to Step 6 and may not register or complete before that package gate passes. This step is a **hard gate**. Do not generate a review PPTX, register, install a staged structural transition, or hand the workspace to the main pipeline until validation passes. After a staged project install, rerun the checker on the final `<target_project>/templates/`; it validates the effective Layout roster when Layout and Deck coexist. A one-Master template may skip Step 6 when no review was requested; a multi-Master template must continue to Step 6 and may not register or complete before that package gate passes.
--- ---
@@ -775,20 +785,25 @@ This step is a **hard gate**. Do not generate a review PPTX, register, or hand t
Export the complete SVG roster, one prototype per slide, from the workspace root: Export the complete SVG roster, one prototype per slide, from the workspace root:
```bash ```bash
python3 skills/ppt-master/scripts/template_preview_pptx.py "<template_workspace>" python3 skills/ppt-master/scripts/template_preview_pptx.py "<authoring_workspace>"
``` ```
The default output is `<template_workspace>/exports/<template_id>_template_preview.pptx`; the command creates `exports/` on demand. The script consumes `templates/*.svg` directly, compiles the declared structured Master/Layout contract, and reopens the result. For `standard` / `fidelity`, it uses ephemeral SVG copies with concise preview-only placeholder samples so long `{{...}}` markers stay readable; canonical source SVGs and placeholder semantics are not modified. It does not require a project `spec_lock.md`, does not create a persistent intermediate project, and does not infer or distill structure. `<authoring_workspace>` is the final workspace normally and the isolated staging
root during a project structural transition. The default output is
`<authoring_workspace>/exports/<template_id>_template_preview.pptx`; the command
creates `exports/` on demand. Copy a requested/required successful review
artifact into the target project's `exports/` during the same atomic install.
The script consumes `templates/*.svg` directly, compiles the declared structured Master/Layout contract, and reopens the result. For `standard` / `fidelity`, it uses ephemeral SVG copies with concise preview-only placeholder samples so long `{{...}}` markers stay readable; canonical source SVGs and placeholder semantics are not modified. It does not require a project `spec_lock.md`, does not create a persistent intermediate project, and does not infer or distill structure.
The first export refuses an existing output. After intentionally fixing the template and replacing its prior review deck, rerun with `--force`; never rely on a silent overwrite: The first export refuses an existing output. After intentionally fixing the template and replacing its prior review deck, rerun with `--force`; never rely on a silent overwrite:
```bash ```bash
python3 skills/ppt-master/scripts/template_preview_pptx.py "<template_workspace>" --force python3 skills/ppt-master/scripts/template_preview_pptx.py "<authoring_workspace>" --force
``` ```
**Validation**: **Validation**:
- [ ] Review PPTX exists under `<template_workspace>/exports/` - [ ] Review PPTX exists under `<authoring_workspace>/exports/` and, after a staged project transition, was copied to the final project `exports/`
- [ ] PPTX slide count equals the template SVG roster count - [ ] PPTX slide count equals the template SVG roster count
- [ ] Package read-back reports the expected Master and Layout counts - [ ] Package read-back reports the expected Master and Layout counts
- [ ] The presentation registers the exact Master and Slide rosters; every Master registers exactly its owned Layouts; every Layout and Slide relationship resolves to its declared parent - [ ] The presentation registers the exact Master and Slide rosters; every Master registers exactly its owned Layouts; every Layout and Slide relationship resolves to its declared parent
@@ -855,7 +870,7 @@ library catalog. If an explicit root exactly matches a registered canonical
root, it may be displayed as `library`. Bare names and style phrases are never root, it may be displayed as `library`. Bare names and style phrases are never
resolved implicitly or used to preselect a template. resolved implicitly or used to preselect a template.
> **Recommended for new templates**: declare a YAML frontmatter block at the top of `design_spec.md`. The registrar prefers it over prose extraction: > **Recommended for new templates**: declare a YAML frontmatter block at the top of `<design_spec_path>`. The registrar prefers it over prose extraction:
> >
> ```yaml > ```yaml
> # style example > # style example
@@ -935,6 +950,7 @@ Produce one scope-aware, evidence-driven completion card for either location:
**Output Scope**: library | project **Output Scope**: library | project
**Workspace Path**: `<template_workspace>/` **Workspace Path**: `<template_workspace>/`
**Template Source**: `<template_workspace>/templates/` **Template Source**: `<template_workspace>/templates/`
**Design Spec**: `<installed_design_spec_path>`
**Bitmap Path**: `<template_workspace>/images/` ← omit when no bitmap was written or adopted **Bitmap Path**: `<template_workspace>/images/` ← omit when no bitmap was written or adopted
**Imported Vector Path**: `<template_workspace>/icons/imported/` ← omit when no imported vector was written or adopted **Imported Vector Path**: `<template_workspace>/icons/imported/` ← omit when no imported vector was written or adopted
**Review PPTX**: `<template_workspace>/exports/<template_id>_template_preview.pptx` ← Create Layout/Create Deck only; omit for Create Brand/Create Style and when an optional one-Master review was not requested **Review PPTX**: `<template_workspace>/exports/<template_id>_template_preview.pptx` ← Create Layout/Create Deck only; omit for Create Brand/Create Style and when an optional one-Master review was not requested
@@ -954,8 +970,8 @@ Produce one scope-aware, evidence-driven completion card for either location:
``` ```
For Create Brand, replace the SVG/review rows with For Create Brand, replace the SVG/review rows with
`templates/design_spec.md` plus only real identity assets. For Create Style, the Design Spec plus only real identity assets. For Create Style,
list only `templates/design_spec.md`. Both completion cards must explicitly list only that spec. Both completion cards must explicitly
state `SVG roster: N/A` and `Native structure: N/A`; Style must also state state `SVG roster: N/A` and `Native structure: N/A`; Style must also state
`Visual review trigger: N/A (advisory focus only)`. `Visual review trigger: N/A (advisory focus only)`.
@@ -963,10 +979,10 @@ The exact `<template_workspace>/` root in either scope is the
current-conversation handoff to Default Generate Step 3. It appears as the current-conversation handoff to Default Generate Step 3. It appears as the
specified candidate, defaults Stage 1 to template mode, and is preselected only specified candidate, defaults Stage 1 to template mode, and is preselected only
when it is the sole supplied root. After Stage 1 confirms it, the application when it is the sole supplied root. After Stage 1 confirms it, the application
stage resolves `templates/design_spec.md` and always ignores `exports/`. stage resolves the root's Design Spec(s) and always ignores `exports/`.
Brand/Layout/Deck copy or consume package-owned `templates/` plus any existing Brand/Layout/Deck copy or consume package-owned `templates/` plus any existing
`images/` and `icons/`; Style consumes only `templates/design_spec.md` and `images/` and `icons/`; Style consumes only its own spec and ignores sibling
ignores sibling project scaffolding. It then authors new `svg_output/` pages project scaffolding. It then authors new `svg_output/` pages
under the template contract and exports a new PPTX. Neither the reference under the template contract and exports a new PPTX. Neither the reference
PPTX/SVG nor the template prototypes are upgraded in place. A legacy-flat PPTX/SVG nor the template prototypes are upgraded in place. A legacy-flat
Brand/Layout/Deck package root remains readable only when it satisfies its Brand/Layout/Deck package root remains readable only when it satisfies its
@@ -20,7 +20,7 @@ Enter this child workflow only after [`Create Template`](../create-template.md)
## Invocation Points ## Invocation Points
1. Use §12 below for brand analysis and identity fields, then execute Create Template Steps 23 with those child-owned fields. 1. Use §12 below for brand analysis and identity fields, then execute Create Template Steps 23 with those child-owned fields.
2. After Create Template Step 4 resolves and preflights `<template_workspace>`, use §3 to materialize the confirmed identity. 2. After Create Template Step 4 resolves and preflights `<template_workspace>` and `<design_spec_path>`, use §3 to materialize the confirmed identity.
3. Run §4, then return its evidence to Create Template Steps 5, 7, and 8. Create Brand always skips shared Step 6. 3. Run §4, then return its evidence to Create Template Steps 5, 7, and 8. Create Brand always skips shared Step 6.
## 1. Brand Input Analysis ## 1. Brand Input Analysis
@@ -63,17 +63,17 @@ When the user explicitly requests an empty skeleton, all identity values remain
## 3. Materialize the Confirmed Brand ## 3. Materialize the Confirmed Brand
Create Template supplies an already resolved and collision-checked `<template_workspace>`. Write only: Create Template supplies an already resolved and collision-checked `<template_workspace>` and `<design_spec_path>`. Write only:
```text ```text
<template_workspace>/ <template_workspace>/
├── templates/ ├── templates/
│ └── design_spec.md │ └── design_spec.md # project scope: design_spec.brand.<brand_id>.md
├── images/ # optional; logo/photos/illustrations only when adopted ├── images/ # optional; logo/photos/illustrations only when adopted
└── icons/ # optional; branded icon overrides only when adopted └── icons/ # optional; branded icon overrides only when adopted
``` ```
Do not create optional directories or `exports/` solely to retain empty paths. An initialized project may already contain empty scaffolding; leave it untouched and do not report it as Brand output. Bitmap references from `templates/design_spec.md` use `../images/<name>`; branded icon references use `../icons/<name>`. Do not create optional directories or `exports/` solely to retain empty paths. An initialized project may already contain empty scaffolding; leave it untouched and do not report it as Brand output. Bitmap references from `<design_spec_path>` use `../images/<name>`; branded icon references use `../icons/<name>`.
Write this personality-only schema: Write this personality-only schema:
@@ -133,7 +133,7 @@ Preserve a supplied logo's extension. When multiple lockups exist, use descripti
Return these facts to Create Template: Return these facts to Create Template:
- `templates/design_spec.md` exists and contains `brand_id`, `kind: brand`, `summary`, and `primary_color`. - The Design Spec exists and contains `brand_id`, `kind: brand`, `summary`, and `primary_color`.
- `brand_id` matches the confirmed workspace ID in library scope. - `brand_id` matches the confirmed workspace ID in library scope.
- Required sections IVI exist; Page Roster and Signature Design Elements do not exist. - Required sections IVI exist; Page Roster and Signature Design Elements do not exist.
- No `*.svg`, `native_structure_mode`, Master/Layout, placeholder, canvas, or page-count fields were written. - No `*.svg`, `native_structure_mode`, Master/Layout, placeholder, canvas, or page-count fields were written.
@@ -20,7 +20,7 @@ Enter this child workflow only after [`Create Template`](../create-template.md)
## Invocation Points ## Invocation Points
1. Use §12 below while executing Create Template Steps 13. 1. Use §12 below while executing Create Template Steps 13.
2. After Create Template Step 4 preflights `<template_workspace>`, use §3 to author or materialize the deck workspace under the shared structured contract. 2. After Create Template Step 4 preflights `<template_workspace>` and `<design_spec_path>`, use §3 to author or materialize the deck workspace under the shared structured contract.
3. Apply §4 in addition to Create Template Step 5, then continue through shared Steps 68. 3. Apply §4 in addition to Create Template Step 5, then continue through shared Steps 68.
## 1. Deck Input Interpretation ## 1. Deck Input Interpretation
@@ -100,7 +100,7 @@ The output is:
```text ```text
<template_workspace>/ <template_workspace>/
├── templates/ # design_spec.md + SVG prototypes ├── templates/ # design_spec.md (project scope: design_spec.deck.<deck_id>.md) + SVG prototypes
├── images/ # optional adopted bitmaps ├── images/ # optional adopted bitmaps
├── icons/ ├── icons/
│ └── imported/ # optional imported vectors │ └── imported/ # optional imported vectors
@@ -113,7 +113,7 @@ Every SVG is a complete preview and declares one root Master and Layout under th
In addition to Create Template Steps 56, verify: In addition to Create Template Steps 56, verify:
- `templates/design_spec.md` contains `deck_id`, `kind: deck`, `summary`, `primary_color`, canvas fields, `replication_mode`, `native_structure_mode: structured`, and `page_count`; `summary` names the recurring presentation family/outcome rather than only visual tone. - The Design Spec contains `deck_id`, `kind: deck`, `summary`, `primary_color`, canvas fields, `replication_mode`, `native_structure_mode: structured`, and `page_count`; `summary` names the recurring presentation family/outcome rather than only visual tone.
- `deck_id` matches the confirmed workspace ID in library scope. - `deck_id` matches the confirmed workspace ID in library scope.
- Template Overview, Color Scheme, Signature Design Elements, and Page Roster exist; Template Overview describes the recurring application context, every roster row factually describes its prototype and slots without future-use policy, and conditional sections match real choices/assets. - Template Overview, Color Scheme, Signature Design Elements, and Page Roster exist; Template Overview describes the recurring application context, every roster row factually describes its prototype and slots without future-use policy, and conditional sections match real choices/assets.
- Every identity color is `#RRGGBB`; the primary table row matches frontmatter, and SVG paint follows the confirmed identity. - Every identity color is `#RRGGBB`; the primary table row matches frontmatter, and SVG paint follows the confirmed identity.
@@ -22,7 +22,7 @@ Neutral colors, safe fonts, and provisional sizes may appear in SVG prototypes s
## Invocation Points ## Invocation Points
1. Use §12 below while executing Create Template Steps 13. 1. Use §12 below while executing Create Template Steps 13.
2. After Create Template Step 4 preflights `<template_workspace>`, use §3 to author or materialize the layout workspace under the shared structured contract. 2. After Create Template Step 4 preflights `<template_workspace>` and `<design_spec_path>`, use §3 to author or materialize the layout workspace under the shared structured contract.
3. Apply §4 in addition to Create Template Step 5, then continue through shared Steps 68. 3. Apply §4 in addition to Create Template Step 5, then continue through shared Steps 68.
## 1. Layout Input Interpretation ## 1. Layout Input Interpretation
@@ -92,7 +92,7 @@ The output is:
```text ```text
<template_workspace>/ <template_workspace>/
├── templates/ # design_spec.md + SVG prototypes ├── templates/ # design_spec.md (project scope: design_spec.layout.<layout_id>.md) + SVG prototypes
├── images/ # optional structural/example bitmaps ├── images/ # optional structural/example bitmaps
├── icons/ ├── icons/
│ └── imported/ # optional imported vectors │ └── imported/ # optional imported vectors
@@ -105,7 +105,7 @@ Every SVG is a complete preview and declares one root Master and Layout under th
In addition to Create Template Steps 56, verify: In addition to Create Template Steps 56, verify:
- `templates/design_spec.md` contains `layout_id`, `kind: layout`, `summary`, canvas fields, `replication_mode`, `native_structure_mode: structured`, `page_count`, and `page_types`. - The Design Spec contains `layout_id`, `kind: layout`, `summary`, canvas fields, `replication_mode`, `native_structure_mode: structured`, `page_count`, and `page_types`.
- `layout_id` matches the confirmed workspace ID in library scope. - `layout_id` matches the confirmed workspace ID in library scope.
- Signature Design Elements and Page Roster exist; Template Overview, application-contract language, and all identity sections do not. - Signature Design Elements and Page Roster exist; Template Overview, application-contract language, and all identity sections do not.
- `primary_color`, brand palette, brand typeface/weight claims, final project type-scale claims, logo, voice, and icon-identity claims are absent; structural text roles and capacity rules may remain. - `primary_color`, brand palette, brand typeface/weight claims, final project type-scale claims, logo, voice, and icon-identity claims are absent; structural text roles and capacity rules may remain.
@@ -17,12 +17,12 @@ Enter this child workflow only after [`Create Template`](../create-template.md)
**Hard rule — method and defaults only**: A Style owns a reusable way to argue, express evidence, and coordinate non-binding design defaults. It owns no current-project communication contract, reusable brand identity, page geometry, canvas, SVG prototype, Master/Layout graph, placeholder contract, application contract, visible asset inventory, carrier eligibility, image source, or local authoring-capability whitelist. **Hard rule — method and defaults only**: A Style owns a reusable way to argue, express evidence, and coordinate non-binding design defaults. It owns no current-project communication contract, reusable brand identity, page geometry, canvas, SVG prototype, Master/Layout graph, placeholder contract, application contract, visible asset inventory, carrier eligibility, image source, or local authoring-capability whitelist.
**Hard rule — no page prototypes**: A Style workspace contains only `templates/design_spec.md`. Do not create page SVGs, a review PPTX, or empty `images/`, `icons/`, or `exports/` directories. **Hard rule — no page prototypes**: Style contributes only its own Design Spec. Do not create page SVGs, a review PPTX, or empty `images/`, `icons/`, or `exports/` directories. In a project workspace shared with another kind, files that kind owns are not Style output and are left untouched.
## Invocation Points ## Invocation Points
1. Use §12 below for Style analysis and brief fields, then execute Create Template Steps 23 with those child-owned fields. 1. Use §12 below for Style analysis and brief fields, then execute Create Template Steps 23 with those child-owned fields.
2. After Create Template Step 4 resolves and preflights `<template_workspace>`, use §3 to materialize the confirmed Style. 2. After Create Template Step 4 resolves and preflights `<template_workspace>` and `<design_spec_path>`, use §3 to materialize the confirmed Style.
3. Run §4, then return its evidence to Create Template Steps 5, 7, and 8. Create Style always skips the shared structured-preview step. 3. Run §4, then return its evidence to Create Template Steps 5, 7, and 8. Create Style always skips the shared structured-preview step.
## 1. Style Input Interpretation ## 1. Style Input Interpretation
@@ -149,12 +149,12 @@ necessary freeform. Explicit current-project requirements remain upstream.
## 3. Materialize the Confirmed Style ## 3. Materialize the Confirmed Style
Create Template supplies an already resolved and collision-checked `<template_workspace>`. Write only: Create Template supplies an already resolved and collision-checked `<template_workspace>` and `<design_spec_path>`. Write only:
```text ```text
<template_workspace>/ <template_workspace>/
└── templates/ └── templates/
└── design_spec.md └── design_spec.md # project scope: design_spec.style.<style_id>.md
``` ```
Do not create or adopt images, icons, SVGs, native payloads, or review exports. References remain textual provenance; they are not portable Style assets. Do not create or adopt images, icons, SVGs, native payloads, or review exports. References remain textual provenance; they are not portable Style assets.
@@ -163,7 +163,7 @@ Do not create or adopt images, icons, SVGs, native payloads, or review exports.
Return these facts to Create Template: Return these facts to Create Template:
- `templates/design_spec.md` contains non-empty `style_id`, `kind: style`, `summary`, and three-to-five `keywords`; no other frontmatter field exists. - The Design Spec contains non-empty `style_id`, `kind: style`, `summary`, and three-to-five `keywords`; no other frontmatter field exists.
- `style_id` matches the confirmed workspace ID in library scope. - `style_id` matches the confirmed workspace ID in library scope.
- Required sections IVII exist; preset seeds resolve to real catalog IDs, while custom seeds include behavior prose and only real comma-separated catalog references. - Required sections IVII exist; preset seeds resolve to real catalog IDs, while custom seeds include behavior prose and only real comma-separated catalog references.
- No `*.svg`, optional asset directory, review export, or native payload was created. - No `*.svg`, optional asset directory, review export, or native payload was created.
@@ -624,7 +624,7 @@ Read ${SKILL_DIR}/references/visual-styles/<resolved-id>.md # one preset id, or
Keep the core's shared visual-quality defaults and `svg-effects.md` §6.1 Visual Job Router active during page authoring; they are not passive compatibility reading. Explicit user/template requirements and the locked style override compatible aesthetic defaults, never technical Required / Forbidden boundaries. Keep the core's shared visual-quality defaults and `svg-effects.md` §6.1 Visual Job Router active during page authoring; they are not passive compatibility reading. Explicit user/template requirements and the locked style override compatible aesthetic defaults, never technical Required / Forbidden boundaries.
> Read only the role core, always-on construction references, exact locked detail files, and conditionally triggered modules below. The selection indexes remain planning-only. A preset reads its one locked file. For `custom`, read only the exact bases named by optional `mode_references` / `visual_style_references`, then synthesize them under the corresponding behavior. If absent, treat the direction as genuinely novel and read no preset file. Do not infer adjacent bases, glob a catalog, or blend unselected identities. > Read only the role core, always-on construction references, exact locked detail files, and conditionally triggered modules below. The selection indexes remain planning-only. A preset reads its one locked file. For `custom`, read only the exact bases named by optional `mode_references` / `visual_style_references`: apply one under the corresponding behavior, or synthesize several by their stated contributions. If absent, read no preset file and follow the behavior directly. Do not infer adjacent bases, glob a catalog, or blend unselected identities.
| Deterministic trigger | Additional references | | Deterministic trigger | Additional references |
|---|---| |---|---|
@@ -513,9 +513,9 @@ not route among them one file at a time:
[`semantic-svg.md`](../../references/semantic-svg.md), [`semantic-svg.md`](../../references/semantic-svg.md),
and [`executor-structure.md`](../../references/executor-structure.md). Retain and [`executor-structure.md`](../../references/executor-structure.md). Retain
only the mode/style detail files selected during one-pass design resolution and only the mode/style detail files selected during one-pass design resolution and
realize that chosen direction. Exact `*_references` define the complete basis realize that chosen direction. Exact `*_references` define the catalog material
of a custom synthesis; a genuinely novel custom follows its resolved behavior actually used by a custom: apply one basis under its behavior, synthesize several
without reading or inventing a nearby preset. by their stated contributions, or follow the behavior directly when none exist.
Do not load `executor-base.md`: it owns Default's persisted-plan handoff, Do not load `executor-base.md`: it owns Default's persisted-plan handoff,
first-page gate, and completion routing. Excluding that file is not a capability first-page gate, and completion routing. Excluding that file is not a capability
@@ -70,8 +70,11 @@ stays inside Generate PPTX but owns an explicit SVG → PPTX short circuit. Page
count alone never activates or blocks it. Conversion, bounded research, and count alone never activates or blocks it. Conversion, bounded research, and
project-local resources remain available. Package capabilities may be requested project-local resources remain available. Package capabilities may be requested
or agent-selected. Quick may consume exact Brand/Style/Layout/Deck workspaces as or agent-selected. Quick may consume exact Brand/Style/Layout/Deck workspaces as
flat authoring inputs; compiling reusable Master/Layout/placeholder structure flat authoring inputs, with at most one contribution per kind. All four kinds
still requires the default lock-backed Generate pipeline. Once selected, Quick may combine; Layout takes structural precedence over Deck. A multi-kind project
root contributes all of its specs atomically;
compiling reusable Master/Layout/placeholder structure still requires the
default lock-backed Generate pipeline. Once selected, Quick
is the complete runtime procedure and never loads `generate-pptx.md`; Default is the complete runtime procedure and never loads `generate-pptx.md`; Default
never loads `quick-generate.md`. Image to PPTX is the narrow profile-owned never loads `quick-generate.md`. Image to PPTX is the narrow profile-owned
Quick activation; Beautify may select either runtime, but never both. Quick activation; Beautify may select either runtime, but never both.
@@ -140,7 +143,7 @@ Object animation for generated SVG projects uses the animation stage. Native PPT
| User input | Behavior | | User input | Behavior |
|---|---| |---|---|
| Default Generate | Step 3 prepares candidates only; Stage 1 confirms one communication contract plus either free design or template use in the same interaction | | Default Generate | Step 3 prepares candidates only; Stage 1 confirms one communication contract plus either free design or template use in the same interaction |
| Explicit current workspace root containing `templates/design_spec.md` | Preserve it as a Stage-1 candidate and initialize template mode; preselect that specific candidate only when it is the sole supplied root. An exact registered-root match may be displayed as `library` | | Explicit current workspace root exposing at least one `templates/` Design Spec | Preserve it as a Stage-1 candidate and initialize template mode; preselect that specific candidate only when it is the sole supplied root. An exact registered-root match may be displayed as `library` |
| No exact workspace root and no explicit template intent | Initialize Stage 1 to free design; the user may switch to template mode and select an indexed workspace | | No exact workspace root and no explicit template intent | Initialize Stage 1 to free design; the user may switch to template mode and select an indexed workspace |
| Explicit template intent or any exact workspace root | Initialize Stage 1 to template mode; exactly one root may be preselected, while multiple roots remain unselected candidates | | Explicit template intent or any exact workspace root | Initialize Stage 1 to template mode; exactly one root may be preselected, while multiple roots remain unselected candidates |
| Bare template/brand name or style label without an explicit template-use request | Do not resolve it to a local path or preselect a template; treat it as a style brief. An explicit request to use templates still initializes template mode, but leaves the specific candidate for the user to choose | | Bare template/brand name or style label without an explicit template-use request | Do not resolve it to a local path or preselect a template; treat it as a style brief. An explicit request to use templates still initializes template mode, but leaves the specific candidate for the user to choose |
@@ -17,11 +17,11 @@ resolve to one of these current contracts:
| Input shape | Spec and SVG source | Asset source | | Input shape | Spec and SVG source | Asset source |
|---|---|---| |---|---|---|
| Current workspace root | `<root>/templates/design_spec.md` and `<root>/templates/` | Existing `<root>/images/` and `<root>/icons/` | | Current workspace root | `<root>/templates/design_spec.md`, or one `design_spec.<kind>.<id>.md` per kind, plus `<root>/templates/` | Existing `<root>/images/` and `<root>/icons/` |
| Compatible legacy-flat Brand/Layout/Deck root | `<root>/design_spec.md`; Layout/Deck also require current-contract SVGs under `<root>/` | Package-local files | | Compatible legacy-flat Brand/Layout/Deck root | `<root>/design_spec.md`; Layout/Deck also require current-contract SVGs under `<root>/` | Package-local files |
| Current Create Template handoff | Its exact validated library or project workspace root | Existing portable sibling `images/` and `icons/`; already installed only when the root is the target project | | Current Create Template handoff | Its exact validated library or project workspace root | Existing portable sibling `images/` and `icons/`; already installed only when the root is the target project |
The spec frontmatter MUST declare `kind: brand`, `kind: style`, `kind: layout`, or `kind: deck`. Do not accept only another project's inner `templates/` directory because that omits sibling assets. Spec naming and kind declaration follow [`templates/README.md`](../../templates/README.md); a root exposing several kind-qualified specs contributes all of them. Do not accept only another project's inner `templates/` directory because that omits sibling assets.
**Selection-source classification**: **Selection-source classification**:
@@ -37,11 +37,15 @@ valid without index membership; exact equality with a registered root may be
reported as `library`. The label changes discovery provenance only, never schema reported as `library`. The label changes discovery provenance only, never schema
validation, segment precedence, or installation behavior. validation, segment precedence, or installation behavior.
**Selection cardinality**: Default Stage 1 permits one registered root per kind plus one explicit root; its explicit root may pair with a same-kind library root under §5.2. Quick has no page or catalog selection and accepts at most one supplied exact root per declared kind (four roots total). Kinds compose freely in both profiles. Reject larger default receipts server-side; require an oversized or duplicate-kind Quick input to converge in chat before installation, never through Confirm UI. **Selection cardinality**: Select at most one root per kind; all four kinds may
coexist. A multi-kind explicit root contributes all its specs atomically and
may combine only with non-overlapping kinds. Default permits one explicit root
beside registered choices; Quick applies the same kind constraint. Reject
duplicate kinds before validation.
**Hard rule — raw source boundary**: A raw PPTX is not a template workspace. Raw PPTX plus new content uses [`template-fill-pptx`](../template-fill-pptx.md). When the user wants reusable SVG/template generation, run [`create-template`](../create-template.md) first; its validated workspace-root handoff becomes a Stage-1 candidate and is preselected only when it is the sole supplied root. Never add Master/Layout/placeholder structure directly to an existing PPTX or SVG project. **Hard rule — raw source boundary**: A raw PPTX is not a template workspace. Raw PPTX plus new content uses [`template-fill-pptx`](../template-fill-pptx.md). When the user wants reusable SVG/template generation, run [`create-template`](../create-template.md) first; its validated workspace-root handoff becomes a Stage-1 candidate and is preselected only when it is the sole supplied root. Never add Master/Layout/placeholder structure directly to an existing PPTX or SVG project.
**Compatibility gate**: Reject semantic-legacy or incomplete structured packages, including old baseline/distillation metadata, incomplete Master identity, or legacy direct atomic placeholders. Create a new current workspace through Create Template; use the original PPTX when native topology must be preserved. A legacy-flat Brand/Layout/Deck directory is readable only when it satisfies its current kind contract; Layout/Deck also require a current structured SVG contract. Style has no legacy-flat form and always requires `<root>/templates/design_spec.md`. **Compatibility gate**: Reject semantic-legacy or incomplete structured packages, including old baseline/distillation metadata, incomplete Master identity, or legacy direct atomic placeholders. Create a new current workspace through Create Template; use the original PPTX when native topology must be preserved. A legacy-flat Brand/Layout/Deck directory is readable only when it satisfies its current kind contract; Layout/Deck also require a current structured SVG contract. Style has no legacy-flat form.
## 2. Read the Matching Schema ## 2. Read the Matching Schema
@@ -58,8 +62,8 @@ A Layout created with `mirror` remains eligible only when its source contract is
Before mapping any current workspace, run its shared package validator from the Before mapping any current workspace, run its shared package validator from the
workspace root. This is the same schema authority used during creation and workspace root. This is the same schema authority used during creation and
library registration; Brand/Style pass without SVG, while Layout/Deck validate registration: Brand/Style are roster-free, the active structure validates its
their roster and structure: roster, and a shadowed Deck still validates its declared contract:
```bash ```bash
python3 skills/ppt-master/scripts/svg_quality_checker.py "<workspace_root>/templates" --template-mode python3 skills/ppt-master/scripts/svg_quality_checker.py "<workspace_root>/templates" --template-mode
@@ -78,45 +82,66 @@ Before copying a Deck or Layout workspace, inspect every SVG root and slot. Bran
- A composite region uses an explicit `object` proxy; a zero-slot Layout is valid. - A composite region uses an explicit `object` proxy; a zero-slot Layout is valid.
- The complete SVG contract is current. Reject a legacy semantic contract instead of repairing it in the target project. - The complete SVG contract is current. Reject a legacy semantic contract instead of repairing it in the target project.
## 4. Install Each Workspace Separately ## 4. Install Each Distinct Root Once
**Hard rule — one installed spec file per source workspace**: Never merge two Validate each normalized root once. Resolve the effective structural owner as
source specs into one file. Install each selected workspace's `design_spec.md` Layout when selected, otherwise Deck; install only its SVG/non-bitmap
as its own project-local file named `design_spec.<kind>.<id>.md`, where `<id>` structural payload, but install every selected spec. A library or
is that spec's frontmatter `brand_id` / `style_id` / `layout_id` / `deck_id`. compatible legacy-flat root contributes one bare `design_spec.md`; install it
Copy its body unchanged. Several workspaces of the same kind therefore coexist as `design_spec.<kind>.<id>.md`, where `<id>` comes from the matching
as separate files. Segment precedence is resolved by the consuming role while frontmatter id field. A current project root may contribute several qualified
reading (§5), never by rewriting spec content at install time. specs; preserve each validated qualified filename. Never merge spec bodies,
and never copy one multi-kind root's shared SVG or asset pool once per kind.
| Installed file | Meaning | | Installed file | Meaning |
|---|---| |---|---|
| `templates/design_spec.<kind>.<id>.md` | A template workspace installed into this project | | `templates/design_spec.<kind>.<id>.md` | A template contribution installed into or authored in this project |
| `templates/design_spec.md` | This project *is itself* a template workspace produced by project-scope Create Template; it is not an installed template and is never consumed as one | | `templates/design_spec.md` | Library or compatible legacy-flat source shape only; never valid beside qualified project specs |
Prepend exactly one provenance line under each installed file's H1, then leave For every copied spec, prepend exactly one provenance line under its H1, then
the rest of the document untouched: leave the rest of the document untouched. An in-place root is not rewritten:
```markdown ```markdown
> **Installed from**: `skills/ppt-master/templates/brands/mckinsey/` (library) > **Installed from**: `skills/ppt-master/templates/brands/mckinsey/` (library)
``` ```
| Kind | Install behavior | **Root mapping**:
- Copy every selected spec from the root to its resolved qualified destination.
- If the root contributes the effective structural owner, copy its declared
SVG roster and other non-bitmap structural files once. Do not copy a Deck
roster when Layout is selected; its structure is shadowed by design.
- Copy the root's real package-owned `images/` and `icons/` files once. A
Style-only root has none; reject a Style-only library package carrying asset
or review payloads.
- Ignore `exports/`; it contains review artifacts, not portable inputs.
After that root-level copy, kinds have these downstream effects:
| Kind | Consumption behavior |
|---|---| |---|---|
| `brand` | Install `templates/` plus existing `images/` and `icons/`; ignore `exports/`. Identity is constrained; structure remains free. | | `brand` | Identity is constrained; structure remains free unless the selected set also includes Layout or Deck. |
| `style` | Install its `design_spec.md` only. Ignore sibling project scaffolding and reject a library Style carrying asset/review payloads. Expose reusable direction/method without identity truth, page prototypes, or native structure. Default Style-only and Style + Brand derive `template_reuse_scope: style` and stay flat; Style + Layout/Deck follows the selected structure plan. Quick always realizes the resolved combination as flat pages. A Style workspace never activates visual review. | | `style` | Expose reusable direction/method without identity truth, page prototypes, or native structure. Default Style-only and Style + Brand derive `template_reuse_scope: style` and stay flat; Style + Layout/Deck follows the selected structure plan. Quick always realizes the resolved combination as flat pages. A Style workspace never activates visual review. |
| `layout` | Install the same portable roots. Expose the actual reusable structure; Default Strategist later inspects the prototypes, while Quick's current agent uses them for immediate flat authoring decisions in active context. | | `layout` | Expose the actual reusable structure and take structural precedence over Deck; Default Strategist later inspects these prototypes, while Quick's current agent uses them for immediate flat authoring decisions in active context. |
| `deck` | Install the same portable roots. Expose descriptive application context, identity, structure, and the actual prototype roster; Default Strategist or Quick's current agent compares them with the current communication contract and content, then derives the applicable plan. | | `deck` | Expose descriptive application context and identity. It also supplies structure and the actual prototype roster only when no Layout is selected. |
For a compatible legacy-flat package, route SVG/spec/non-bitmaps to project `templates/`, bitmaps to project `images/`, and declared icons to project `icons/`. Do not infer legacy Master/Layout semantics from the flat directory shape. For a compatible legacy-flat package, route SVG/spec/non-bitmaps to project `templates/`, bitmaps to project `images/`, and declared icons to project `icons/`. Do not infer legacy Master/Layout semantics from the flat directory shape.
**Atomic install preflight**: **Atomic install preflight**:
1. Resolve every source and destination path. 1. Resolve every source and destination path.
2. Enumerate the complete mapping across `templates/`, `images/`, and `icons/`. 2. Enumerate the union mapping across all distinct roots and across
3. Reject every destination collision before writing. `templates/`, `images/`, and `icons/`; map a source file at most once.
3. Reject every destination collision and every duplicate-kind selection
before writing. Resolve Layout-over-Deck structural precedence before
constructing the destination map, so the shadowed Deck roster never enters
that map.
4. Write the accepted mapping once; never use recursive copy as an implicit conflict policy. 4. Write the accepted mapping once; never use recursive copy as an implicit conflict policy.
If the normalized source root equals the target project root, consume it in place and copy nothing. An in-place workspace cannot be combined with other installed roots. Ignore source `exports/`; it contains review artifacts, not portable template inputs. Empty optional roots remain absent. Consume an input equal to the target project in place, mapping only other
roots. If a selected Layout supersedes its in-place Deck roster, stage the
accepted mapping and replace that roster atomically. Never mix rosters or write
piecemeal. Ignore `exports/`; empty optional roots remain absent.
**Hard rule — project-local consumer boundary**: After installation, **Hard rule — project-local consumer boundary**: After installation,
Default template-aware Strategist work in final Stage 2, Quick's current Default template-aware Strategist work in final Stage 2, Quick's current
@@ -154,7 +179,7 @@ current user instructions and the consuming plan still govern project use:
| Segment | Starting owner | | Segment | Starting owner |
|---|---| |---|---|
| Identity | Brand, otherwise Deck, otherwise unresolved until the consuming plan (Default final Stage 2 or Quick active context). Style color/type/icon/image values are direction candidates, never identity truth. | | Identity | Brand, otherwise Deck, otherwise unresolved until the consuming plan (Default final Stage 2 or Quick active context). Style color/type/icon/image values are direction candidates, never identity truth. |
| Structure | A compatible Layout, otherwise Deck, otherwise unresolved/free design until the consuming plan. Style owns no canvas, prototype, Master/Layout, slot, or page mapping. | | Structure | Layout when present, otherwise Deck, otherwise unresolved/free design until the consuming plan. Style owns no canvas, prototype, Master/Layout, slot, or page mapping. |
| Reusable application context | Deck only when present. Preserve it for the consuming comparison; it never becomes the current project's application contract. | | Reusable application context | Deck only when present. Preserve it for the consuming comparison; it never becomes the current project's application contract. |
| Direction / method | Style when present, otherwise unresolved until the consuming plan. Actual Deck prototypes and Signature facts may inform compatibility, but Deck does not own the Style-only method segment. | | Direction / method | Style when present, otherwise unresolved until the consuming plan. Actual Deck prototypes and Signature facts may inform compatibility, but Deck does not own the Style-only method segment. |
@@ -166,40 +191,38 @@ instruction carries the same authority as the value itself. A Style's
composition or whitespace tendency never demotes a Brand's declared dominant composition or whitespace tendency never demotes a Brand's declared dominant
color to an incidental accent. color to an incidental accent.
Before Layout overrides Deck structure, compare Deck's reusable roles with Layout roles, slots, and capacity. On mismatch, offer exactly three remedies: retain Deck structure, select another Layout, or omit Deck. Default resolves only this template-to-template conflict and must not reinterpret the confirmed Stage-1 communication contract; Quick compares against the current request/content and treats any unresolved material mismatch as a chat hard prerequisite. Before Style overlays Layout or Deck guidance, verify that its method fits the
selected structure and, for Deck, serves its reusable context. On mismatch,
Before Style overlays Deck guidance, verify that its method serves Deck's reusable context and fits the selected structure. On mismatch, require omitting Style or choosing a compatible Style/structure; never silently weaken a segment. Default final Stage 2 separately checks the result against the confirmed project contract; Quick checks it against the current request/content before authoring. require omitting Style or choosing a compatible Style/structure; never silently
weaken a segment. Default final Stage 2 separately checks the result against the
confirmed project contract; Quick checks it against the current request/content
before authoring.
Field-level micro-adjustments such as a primary-color override are not a workspace selection. Default carries them into the normal final Stage-2 confirmation fields; Quick treats explicit adjustments as direct active-context authoring constraints. Field-level micro-adjustments such as a primary-color override are not a workspace selection. Default carries them into the normal final Stage-2 confirmation fields; Quick treats explicit adjustments as direct active-context authoring constraints.
### 5.2 Same Kind ### 5.2 Selection Conflicts
Several roots of one kind install as separate files distinguished by their Duplicate kinds are selection errors. Layout plus Deck is valid: Layout owns
`<id>`, exactly like different kinds. Do not merge them and do not use path structure; Deck keeps its other segments. Default returns duplicates to Stage
order as priority. The consuming role reads all of them and decides which 1; Quick asks for narrower roots. Never split a multi-kind root, average
governs each part of the owned segment, following the latest explicit user same-kind specs, or choose by path order.
instruction first; where the user gave none and two same-kind specs make
materially incompatible claims over the same segment, surface the conflict in
chat rather than silently averaging them. Two Style workspaces contend over the
complete Direction / method segment; two Brand workspaces contend over
Identity.
### 5.3 Installed Set ### 5.3 Installed Set
Each installed file keeps its own frontmatter `kind` and `<id>` from its source Each installed file keeps its own frontmatter `kind` and `<id>` from its source
workspace; nothing is relabelled. There is no combined capability label and no workspace; nothing is relabelled. There is no combined capability label and no
merged spec: the installed set is exactly what was selected, and the routing merged spec: the installed set is exactly what was selected, and the routing
consequence is derived while reading — structure comes from an installed Layout consequence is derived while reading — structure comes from Layout when
or Deck, identity from an installed Brand or Deck, direction from an installed present, otherwise Deck; identity comes from Brand or Deck; direction comes
Style. A project-local Brand + Layout pair does not become a reusable library from Style. A project-local Brand + Layout pair does not become a reusable library
Deck; its application remains current-project context. Deck; its application remains current-project context.
**Completion receipt**: Report `roots=<normalized roots>; sources=<library|explicit per root>; kinds=<kind per root>; segments=identity:<owner>,structure:<owner>,application_context:<owner>,direction:<owner>; install=<in-place|copied>; installed_specs=<comma-separated design_spec.<kind>.<id>.md>`. **Completion receipt**: Report `roots=<unique normalized roots>; sources=<library|explicit per root>; kinds=<all contributed kinds per root>; segments=identity:<owner>,structure:<owner>,application_context:<owner>,direction:<owner>; active_roster=<layout|deck|none>:<source root>; install=<in-place|copied>; installed_specs=<comma-separated design_spec.<kind>.<id>.md>`.
## ✅ Template Workspace Applied ## ✅ Template Workspace Applied
- [x] Every selected input was an index-derived library root or an exact explicit/Create Template root satisfying a listed workspace contract - [x] Every selected input was an index-derived library root or an exact explicit/Create Template root satisfying a listed workspace contract
- [x] Every kind schema passed preflight; structured SVG checks ran only for Layout/Deck inputs - [x] Every kind schema passed preflight; structured SVG checks ran only for Layout/Deck inputs
- [x] All destination collisions were rejected before one atomic install; no two source specs were merged into one file - [x] Duplicate kinds and all destination collisions were rejected before one atomic install; Layout-over-Deck precedence selected exactly one active structural roster
- [x] `<project_path>/templates/` and any portable sibling assets are complete and are the only downstream template source - [x] `<project_path>/templates/` and any portable sibling assets are complete and are the only downstream template source
- [ ] **Next**: Default completes the template-selection handoff and continues [`generate-pptx.md`](../generate-pptx.md) Step 4 Stage 2; Quick returns to [`quick-generate`](../profiles/quick-generate.md) §2 - [ ] **Next**: Default completes the template-selection handoff and continues [`generate-pptx.md`](../generate-pptx.md) Step 4 Stage 2; Quick returns to [`quick-generate`](../profiles/quick-generate.md) §2
@@ -98,7 +98,7 @@ Then continue the documented pipeline:
- When §X records a final/literal narration script, read the verified frozen `notes/total.md` once and retain its page segments through SVG authoring and the late notes validation - When §X records a final/literal narration script, read the verified frozen `notes/total.md` once and retain its page segments through SVG authoring and the late notes validation
- If resuming mid-deck, read the latest completed SVG and current image metadata after their required paths have been verified - If resuming mid-deck, read the latest completed SVG and current image metadata after their required paths have been verified
- Read the remaining Step 6 construction core exactly as listed in [`generate-pptx.md`](../generate-pptx.md), then read one locked preset file or only the exact `*_references` of a custom synthesis; never reopen or glob the mode or visual-style catalogs, and load only the branches selected by the condition table - Read the remaining Step 6 construction core exactly as listed in [`generate-pptx.md`](../generate-pptx.md), then read one locked preset file or only the exact `*_references` of a custom; apply one basis under its behavior or synthesize several by their stated contributions. Never reopen or glob the mode or visual-style catalogs, and load only the branches selected by the condition table
- For each page, make the mandatory Structure decision from retained §IX after its content/communication move is established and before any geometry; a `yes` result loads `executor-structure.md` before realization and creates no artifact or lock row - For each page, make the mandatory Structure decision from retained §IX after its content/communication move is established and before any geometry; a `yes` result loads `executor-structure.md` before realization and creates no artifact or lock row
- Design Parameter Confirmation - Design Parameter Confirmation
- When structured, read the template Design Spec and each selected prototype once; retain unchanged references in the fresh context. A later bounded repair follows [`executor-base.md`](../../references/executor-base.md) §2.1 only while that context remains valid and uncompacted - When structured, read the template Design Spec and each selected prototype once; retain unchanged references in the fresh context. A later bounded repair follows [`executor-base.md`](../../references/executor-base.md) §2.1 only while that context remains valid and uncompacted
@@ -2,8 +2,8 @@
"sourceId": "shadcn", "sourceId": "shadcn",
"repo": "https://github.com/shadcn-ui/ui.git", "repo": "https://github.com/shadcn-ui/ui.git",
"ref": "main", "ref": "main",
"commit": "4e88ab81ae1d1550165db949a903c691a04f699c", "commit": "19b67204fb80b7a7c233c967e4cf3aed73810f80",
"adapter": "claude-skill", "adapter": "claude-skill",
"sourcePath": "skills/shadcn", "sourcePath": "skills/shadcn",
"syncedAt": "2026-08-20T16:00:00Z" "syncedAt": "2026-08-21T06:41:32Z"
} }
@@ -1,6 +1,6 @@
{ {
"name": "superpowers-zh", "name": "superpowers-zh",
"version": "6.2.0-zh.1", "version": "6.3.0-zh.1",
"description": "Superpowers 的简体中文本地化版本,提供规划、TDD、系统化调试、代码评审和交付工作流。", "description": "Superpowers 的简体中文本地化版本,提供规划、TDD、系统化调试、代码评审和交付工作流。",
"author": { "author": {
"name": "Jesse Vincent", "name": "Jesse Vincent",
+77 -23
View File
@@ -6,24 +6,40 @@ Superpowers 是一套面向编程 Agent 的完整软件开发方法论。它由
## 版本对齐 ## 版本对齐
- **当前中文发行版:** `v6.2.0-zh.1` - **当前中文发行版:** `v6.3.0-zh.1`
- **对齐的上游正式版:** [`obra/superpowers v6.2.0`](https://github.com/obra/superpowers/releases/tag/v6.2.0) - **对齐的上游正式版:** [`obra/superpowers v6.3.0`](https://github.com/obra/superpowers/releases/tag/v6.3.0)
- **上游基线提交:** [`3dcbd5c4b48e02263fbf4a3c01e3fe4f81d584d9`](https://github.com/obra/superpowers/commit/3dcbd5c4b48e02263fbf4a3c01e3fe4f81d584d9) - **上游基线提交:** [`b36e082`](https://github.com/obra/superpowers/commit/b36e082)
- **对齐日期:** 2026-07-24 - **对齐日期:** 2026-08-21
版本号中的 `zh.1` 表示:功能基线与上游 `v6.2.0` 对齐,这是该基线上的第 1 个中文发行版。后续同步新的上游版本时,会先更新前三段版本号,再从 `zh.1` 重新开始计数。 版本号中的 `zh.1` 表示:功能基线与上游 `v6.3.0` 对齐,这是该基线上的第 1 个中文发行版。后续同步新的上游版本时,会先更新前三段版本号,再从 `zh.1` 重新开始计数。
## 上游正在招聘 ## 目录
Superpowers 上游团队正在招聘一名全职工程师,协助社区运营与代码开发。 - [工作原理](#工作原理)
- [商业服务](#商业服务)
职位详情:https://primeradiant.com/jobs/superpowers-community-engineer/ - [安装](#安装)
- [Claude Code](#claude-code)
如果你认识合适的人选,欢迎推荐给上游团队。 - [Antigravity](#antigravity)
- [Codex App](#codex-app)
## 快速开始 - [Codex CLI](#codex-cli)
- [Cursor](#cursor)
为你的编程 Agent 安装 Superpowers 中文版:[Claude Code](#claude-code)、[Antigravity](#antigravity)、[Codex App](#codex-app)、[Codex CLI](#codex-cli)、[Cursor](#cursor)、[Factory Droid](#factory-droid)、[Gemini CLI](#gemini-cli)、[GitHub Copilot CLI](#github-copilot-cli)、[Kimi Code](#kimi-code)、[OpenCode](#opencode)、[Pi](#pi)。 - [Devin CLI](#devin-cli)
- [Factory Droid](#factory-droid)
- [Gemini CLI](#gemini-cli)
- [GitHub Copilot CLI](#github-copilot-cli)
- [Grok Build CLI](#grok-build-cli)
- [Kimi Code](#kimi-code)
- [OpenCode](#opencode)
- [Pi](#pi)
- [Hermes Agent](#hermes-agent)
- [基本工作流](#基本工作流)
- [社区](#社区)
- [包含内容](#包含内容)
- [核心理念](#核心理念)
- [参与贡献](#参与贡献)
- [更新](#更新)
- [许可证](#许可证)
- [Visual Companion 遥测](#visual-companion-遥测)
## 工作原理 ## 工作原理
@@ -128,6 +144,20 @@ codex plugin marketplace upgrade superpowers-dev
也可以在插件市场中搜索 `superpowers`。请确认安装详情显示的是 `Superpowers 中文版`;如果只看到上游英文版,可改用本仓库的本地插件方式。 也可以在插件市场中搜索 `superpowers`。请确认安装详情显示的是 `Superpowers 中文版`;如果只看到上游英文版,可改用本仓库的本地插件方式。
### Devin CLI
从本中文仓库安装插件:
```bash
devin plugins install AreChen/superpowers-zh
```
更新到最新版本:
```bash
devin plugins update superpowers
```
### Factory Droid ### Factory Droid
注册本中文仓库的插件市场: 注册本中文仓库的插件市场:
@@ -170,6 +200,20 @@ copilot plugin marketplace add AreChen/superpowers-zh
copilot plugin install superpowers@superpowers-dev copilot plugin install superpowers@superpowers-dev
``` ```
### Grok Build CLI
Superpowers 可通过 [Grok 官方插件市场](https://github.com/xai-org/plugin-marketplace)安装。当前官方市场对应上游插件:
```bash
grok plugin install superpowers@xai-official --trust
```
也可以在 TUI 中打开市场,搜索 Superpowers 并安装:
```text
/marketplace
```
### Kimi Code ### Kimi Code
可以直接从本中文仓库安装: 可以直接从本中文仓库安装:
@@ -228,6 +272,16 @@ pi -e /path/to/superpowers-zh
Pi 软件包会加载 Superpowers 技能,并通过一个小型扩展在会话启动和上下文压缩后注入 `using-superpowers` 引导。Pi 原生支持技能,因此不需要兼容性的 `Skill` 工具。子 Agent 和任务列表工具仍可作为可选的 Pi 配套软件包使用。 Pi 软件包会加载 Superpowers 技能,并通过一个小型扩展在会话启动和上下文压缩后注入 `using-superpowers` 引导。Pi 原生支持技能,因此不需要兼容性的 `Skill` 工具。子 Agent 和任务列表工具仍可作为可选的 Pi 配套软件包使用。
### Hermes Agent
从本中文仓库安装 Hermes 插件:
```bash
hermes plugins install AreChen/superpowers-zh --enable
```
安装后重启正在运行的 Hermes 会话。注意:Hermes 没有上下文压缩后的钩子;如果超长会话在第一轮之后发生压缩并导致技能停止触发,请启动新会话。
## 基本工作流 ## 基本工作流
1. **brainstorming** —— 在编写代码前触发。通过提问澄清初步想法、探索替代方案,分段展示设计供用户确认,并保存设计文档。 1. **brainstorming** —— 在编写代码前触发。通过提问澄清初步想法、探索替代方案,分段展示设计供用户确认,并保存设计文档。
@@ -246,6 +300,14 @@ Pi 软件包会加载 Superpowers 技能,并通过一个小型扩展在会话
**Agent 会在执行任何任务前检查是否存在相关技能。** 这些是必须遵循的工作流,而不是可选建议。 **Agent 会在执行任何任务前检查是否存在相关技能。** 这些是必须遵循的工作流,而不是可选建议。
## 社区
Superpowers 由 [Jesse Vincent](https://blog.fsck.com) 和 [Prime Radiant](https://primeradiant.com) 团队创建。本中文分叉由 [AreChen](https://github.com/AreChen) 维护。
- **Discord**[加入上游社区](https://discord.gg/35wsABTejz),获取支持、提出问题并分享你使用 Superpowers 构建的项目。
- **问题反馈**https://github.com/AreChen/superpowers-zh/issues
- **上游版本公告**[订阅通知](https://primeradiant.com/superpowers/)
## 包含内容 ## 包含内容
### 技能库 ### 技能库
@@ -314,11 +376,3 @@ Superpowers 的更新方式取决于你使用的编程 Agent。通过 Git 市场
该请求不包含你的项目、提示词或编程 Agent 的详细信息,也不会记录点击行为或你正在构建的内容。它只用于粗略了解使用人数和版本分布,并且完全可选。 该请求不包含你的项目、提示词或编程 Agent 的详细信息,也不会记录点击行为或你正在构建的内容。它只用于粗略了解使用人数和版本分布,并且完全可选。
如需关闭,请把环境变量 `SUPERPOWERS_DISABLE_TELEMETRY` 设置为任意真值。Superpowers 也会遵循 Claude Code 的 `DISABLE_TELEMETRY``CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` 退出设置。 如需关闭,请把环境变量 `SUPERPOWERS_DISABLE_TELEMETRY` 设置为任意真值。Superpowers 也会遵循 Claude Code 的 `DISABLE_TELEMETRY``CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` 退出设置。
## 社区
Superpowers 由 [Jesse Vincent](https://blog.fsck.com) 和 [Prime Radiant](https://primeradiant.com) 团队创建。本中文分叉由 [AreChen](https://github.com/AreChen) 维护。
- **Discord**[加入上游社区](https://discord.gg/35wsABTejz),获取支持、提出问题并分享你使用 Superpowers 构建的项目。
- **问题反馈**https://github.com/AreChen/superpowers-zh/issues
- **上游版本公告**[订阅通知](https://primeradiant.com/superpowers/)
@@ -2,8 +2,8 @@
"sourceId": "superpowers-zh", "sourceId": "superpowers-zh",
"repo": "https://github.com/AreChen/superpowers-zh.git", "repo": "https://github.com/AreChen/superpowers-zh.git",
"ref": "main", "ref": "main",
"commit": "e1f21a28e5a32b94d35fdaaa98e298ef73260545", "commit": "e6ae7ddf5da1b5f7ec0388ce053c894d23a64857",
"adapter": "codex-plugin", "adapter": "codex-plugin",
"sourcePath": ".", "sourcePath": ".",
"syncedAt": "2026-07-24T06:18:20Z" "syncedAt": "2026-08-21T06:41:32Z"
} }
@@ -7,20 +7,57 @@ description: "在进行任何创造性工作之前,你都必须使用此技能
通过自然的协作式对话,帮助将想法转化为完整成形的设计和规格说明。 通过自然的协作式对话,帮助将想法转化为完整成形的设计和规格说明。
首先了解当前项目的上下文,然后一次提出一个问题来完善想法。一旦你理解了要构建的内容,就展示设计并获得用户批准。 先判断请求需要多少流程,再沿着对应路径推进:了解上下文、完善想法、展示设计并获得人类伙伴的批准。
<HARD-GATE> <HARD-GATE>
在你展示设计并获得用户批准之前,不得调用任何实现技能、编写任何代码、搭建任何项目脚手架或采取任何实现行动。无论项目看起来多么简单,这都适用于每一个项目 在你告知人类伙伴打算做什么并获得批准之前,不得调用任何实现技能、编写任何代码、搭建任何项目脚手架或采取任何实现行动。以下每条路径上的每项任务都适用——流程仪式会随任务调整,但批准关卡永远不会取消
</HARD-GATE> </HARD-GATE>
## 反模式:“这太简单了,不需要设计” ## 三条路径
每个项目都要经过这一流程。待办事项列表、单函数实用工具、配置变更——无一例外。“简单”项目最容易因未经审视的假设而造成最多的工作浪费。设计可以很简短(对于真正简单的项目,只需几句话),但你必须展示设计并获得批准。 在提出第一个问题之前先分类,并大声说出分类——例如“这看起来是有边界的任务,所以我会在这里展示一个简短设计,而不是写规格说明”——让人类伙伴可以推翻你的判断:
- **探索(Spike**——可行性问题(“能不能……”“是否可能……”“快速粗糙地做也可以”),产出是答案而不是要保留的代码。用 2-3 句话说明问题和尝试方式,得到同意后,以正确性允许的最低成本进行探查。不写设计文档或规格文件。把发现报告为建议;构建的任何内容都必须标记为一次性产物。
- **有边界(Bounded**——对本仓库已有代码的范围明确的改动:新标志、小端点、单文件修复。仅仅理解应用类型还不够——有边界意味着要修改的流程已经存在且可供阅读。如果没有可修改的现有流程,任务就不是有边界的。提出关键澄清问题,在对话中展示简短设计(几句话到几段短文),然后停止。只有人类伙伴明确同意设计后才能实现;不写规格文件或实现计划文档。
- **架构性(Architectural**——新项目、新子系统、改变组件关系或其他人依赖的接口。走完整流程:提问、方案、分节设计、书面规格说明,然后调用 writing-plans 技能。
如果在两条路径之间犹豫,选择较重的路径。这个棘轮只能向上:任务中途发现隐藏复杂性时,停止、说明情况并升级路径;不会中途降级。
## 反模式:“太简单了,不需要批准”
每条路径都必须在人类伙伴批准意图后才能实现。待办事项列表、单函数工具、配置变更——设计可以只是聊天中的两句话,但仍必须展示并获得批准。“简单”任务最容易因未经审视的假设而浪费工作。随简单程度调整的是产物,不是批准。
## 危险信号
| 想法 | 事实 |
|---------|---------|
| “这太简单了,不需要设计” | 简单意味着设计简短,而不是没有设计。聊天中写两句话,然后获得批准。 |
| “我把它叫作有边界,就可以跳过规格” | 为了省事而贴标签本身就是疑点——选择更重的路径。 |
| “它有边界而且设计显而易见——他们阅读时我先开始” | 关卡是批准,不是设计长短。展示后停止,直到听到同意。 |
| “我了解这种应用,所以它有边界” | 有边界衡量的是仓库,而不是你的熟悉程度。新项目没有现有流程,属于架构性任务。 |
| “探索成功了,我就保留代码” | 探索的产出是答案。保留代码是新请求,需要重新分类。 |
| “它变复杂了,但我快做完了——不用重新分类” | 隐藏复杂性会在任务中途升级路径。停止并说明情况。 |
| “他们批准了探索,所以后续改动也获批了” | 每个任务都有自己的分类和自己的批准。 |
## 清单 ## 清单
你必须为以下每一项创建一项任务并按顺序完成它们: 先分类并宣布路径,然后为对应路径上的每一项创建任务并按顺序完成
**探索路径:**
1. **探索项目上下文**——获取足以界定探查范围的信息
2. **展示问题和探查计划**——2-3 句话
3. **获得批准**——得到同意即可
4. **进行调查**——以正确性允许的最低成本推进
5. **报告发现**——给出建议,并标记所有构建内容为一次性产物
**有边界路径:**
1. **探索项目上下文**——检查文件、文档和最近提交
2. **提出澄清问题**——一次一个,只问关键问题
3. **在聊天中展示简短设计**——方案、涉及文件和测试
4. **获得批准**——停止并等待明确的“是”;展示设计后立即开始就是跳过关卡
5. **实现**——使用正常开发流程推进(TDD 仍适用);不写计划文档
**架构性路径:**
1. **探索项目上下文**——检查文件、文档和最近的提交 1. **探索项目上下文**——检查文件、文档和最近的提交
2. **在恰当时机提供视觉伴侣**——不要预先提供。当某个问题第一次确实用展示比用描述更清楚时,就在那时提出使用它(用一条单独的消息);获得批准后,它的浏览器标签页会为你打开。如果始终没有出现视觉问题,就绝不要提出使用它。参见下方的“视觉伴侣”一节。 2. **在恰当时机提供视觉伴侣**——不要预先提供。当某个问题第一次确实用展示比用描述更清楚时,就在那时提出使用它(用一条单独的消息);获得批准后,它的浏览器标签页会为你打开。如果始终没有出现视觉问题,就绝不要提出使用它。参见下方的“视觉伴侣”一节。
3. **提出澄清问题**——一次一个,了解目的、约束和成功标准 3. **提出澄清问题**——一次一个,了解目的、约束和成功标准
@@ -28,13 +65,20 @@ description: "在进行任何创造性工作之前,你都必须使用此技能
5. **展示设计**——按复杂度划分并调整各节内容,每展示一节后都要获得用户批准 5. **展示设计**——按复杂度划分并调整各节内容,每展示一节后都要获得用户批准
6. **编写设计文档**——保存到 `docs/superpowers/specs/YYYY-MM-DD-<topic>-design.md` 并提交 6. **编写设计文档**——保存到 `docs/superpowers/specs/YYYY-MM-DD-<topic>-design.md` 并提交
7. **规格说明自审**——快速进行内联检查,查找占位符、矛盾、歧义和范围问题(见下文) 7. **规格说明自审**——快速进行内联检查,查找占位符、矛盾、歧义和范围问题(见下文)
8. **用户审查已写好的规格说明**请用户在继续之前审查规格说明文件 8. **用户审查已写好的规格说明**——请用户在继续之前审查规格说明文件
9. **过渡到实现**调用 writing-plans 技能来创建实现计划 9. **过渡到实现**——调用 writing-plans 技能来创建实现计划
## 流程 ## 流程
```dot ```dot
digraph brainstorming { digraph brainstorming {
"Classify: spike / bounded / architectural" [shape=diamond, label="分类:探索 / 有边界 / 架构性"];
"Present question + probe (2-3 sentences)" [shape=box, label="展示问题和探查(2-3 句话)"];
"Ask clarifying questions (bounded)" [shape=box, label="提出澄清问题(有边界)"];
"Present short design in chat" [shape=box, label="在聊天中展示简短设计"];
"Human approves?" [shape=diamond, label="人类批准了吗?"];
"Investigate; report recommendation" [shape=doublecircle, label="调查并报告建议"];
"Implement via normal workflow (no plan doc)" [shape=doublecircle, label="通过正常流程实现(无计划文档)"];
"Explore project context" [shape=box, label="探索项目上下文"]; "Explore project context" [shape=box, label="探索项目上下文"];
"Ask clarifying questions" [shape=box, label="提出澄清问题"]; "Ask clarifying questions" [shape=box, label="提出澄清问题"];
"Propose 2-3 approaches" [shape=box, label="提出 2-3 种方案"]; "Propose 2-3 approaches" [shape=box, label="提出 2-3 种方案"];
@@ -44,7 +88,17 @@ digraph brainstorming {
"Spec self-review\n(fix inline)" [shape=box, label="规格说明自审\n(内联修正)"]; "Spec self-review\n(fix inline)" [shape=box, label="规格说明自审\n(内联修正)"];
"User reviews spec?" [shape=diamond, label="用户审查规格说明了吗?"]; "User reviews spec?" [shape=diamond, label="用户审查规格说明了吗?"];
"Invoke writing-plans skill" [shape=doublecircle, label="调用 writing-plans 技能"]; "Invoke writing-plans skill" [shape=doublecircle, label="调用 writing-plans 技能"];
"Hidden complexity? Upgrade path" [shape=box, label="发现隐藏复杂性?升级路径"];
"Classify: spike / bounded / architectural" -> "Present question + probe (2-3 sentences)" [label="探索"];
"Classify: spike / bounded / architectural" -> "Ask clarifying questions (bounded)" [label="有边界"];
"Classify: spike / bounded / architectural" -> "Explore project context" [label="架构性"];
"Present question + probe (2-3 sentences)" -> "Human approves?";
"Ask clarifying questions (bounded)" -> "Present short design in chat";
"Present short design in chat" -> "Human approves?";
"Human approves?" -> "Investigate; report recommendation" [label="探索:是"];
"Human approves?" -> "Implement via normal workflow (no plan doc)" [label="有边界:是"];
"Hidden complexity? Upgrade path" -> "Classify: spike / bounded / architectural";
"Explore project context" -> "Ask clarifying questions"; "Explore project context" -> "Ask clarifying questions";
"Ask clarifying questions" -> "Propose 2-3 approaches"; "Ask clarifying questions" -> "Propose 2-3 approaches";
"Propose 2-3 approaches" -> "Present design sections"; "Propose 2-3 approaches" -> "Present design sections";
@@ -57,10 +111,12 @@ digraph brainstorming {
"User reviews spec?" -> "Invoke writing-plans skill" [label="已批准"]; "User reviews spec?" -> "Invoke writing-plans skill" [label="已批准"];
} }
``` ```
**终止状态是调用 writing-plans。** 绝不要调用 frontend-design、mcp-builder 或任何其他实现技能。在 brainstorming 之后,你调用的唯一技能是 writing-plans **终止状态取决于路径。** 架构性路径:brainstorming 之后唯一调用的技能是 writing-plans绝不要调用 frontend-design、mcp-builder 或其他实现技能。有边界路径:获批后直接使用正常开发流程实现,不写计划文档。探索路径:终止状态是报告建议
## 流程 ## 流程
下面的子节服务于有边界和架构性路径(探索路径在“展示探查、获得同意”处停止)。从**探索方案**开始的内容属于架构性深度;对有边界任务来说,上下文、几个问题和一份聊天中的简短设计就是完整流程。
**理解想法:** **理解想法:**
- 首先查看当前项目状态(文件、文档、最近的提交) - 首先查看当前项目状态(文件、文档、最近的提交)
@@ -98,7 +154,7 @@ digraph brainstorming {
- 如果现有代码存在影响这项工作的问题(例如,文件变得过大、边界不清晰、职责纠缠),应将有针对性的改进纳入设计——就像优秀的开发者会改进自己正在处理的代码一样。 - 如果现有代码存在影响这项工作的问题(例如,文件变得过大、边界不清晰、职责纠缠),应将有针对性的改进纳入设计——就像优秀的开发者会改进自己正在处理的代码一样。
- 不要提出无关的重构。始终专注于服务当前目标的内容。 - 不要提出无关的重构。始终专注于服务当前目标的内容。
## 设计之后 ## 设计之后(架构性路径)
**文档:** **文档:**
@@ -77,10 +77,10 @@ scripts/start-server.sh --project-dir /path/to/project --open --foreground
**Copilot CLI** **Copilot CLI**
```bash ```bash
# 使用 --foreground,并通过 bash 工具以 mode: "async" 启动服务器, # 使用 Copilot CLI 的非阻塞/后台 shell 机制启动,使服务器跨轮次持续运行。
# 使进程能够跨轮次持续运行。保存返回的 shellId,以便之后需要与其交互时 # 保留 --foreground,让运行平台而不是脚本负责后台化。启动脚本是 .sh,
# 用于 read_bash / stop_bash # 因此通过 bash 调用(Windows 上从 PowerShell 工具调用 Git Bash 的 bash.exe
scripts/start-server.sh --project-dir /path/to/project --open --foreground bash scripts/start-server.sh --project-dir /path/to/project --open --foreground
``` ```
**其他环境:**服务器必须在后台跨对话轮次持续运行。如果你的环境会清理已分离的进程,请使用 `--foreground`,并通过你所在平台的后台执行机制启动该命令。 **其他环境:**服务器必须在后台跨对话轮次持续运行。如果你的环境会清理已分离的进程,请使用 `--foreground`,并通过你所在平台的后台执行机制启动该命令。
@@ -165,6 +165,26 @@ git worktree remove "$WORKTREE_PATH"
git worktree prune # Self-healing: clean up any stale registrations git worktree prune # Self-healing: clean up any stale registrations
``` ```
**如果移除被拒绝**`contains modified or untracked files`):工作树中有其他位置不存在的文件——未提交的计划、笔记或临时工作。绝不要自行使用 `--force`。向人类伙伴展示风险并询问:
```bash
git -C "$WORKTREE_PATH" status --porcelain -uall
```
```
工作树移除被拒绝——这些文件从未提交:
<文件列表>
1. 在清理前将它们提交到 <branch>
2. 将它们移动到 <main repo root>
3. 删除它们(无法恢复)
选择哪一项?
```
执行选择,然后再移除工作树。
**否则:** 此工作区属于宿主环境——保留原位。如果你的平台提供 workspace-exit **否则:** 此工作区属于宿主环境——保留原位。如果你的平台提供 workspace-exit
工具,请使用它。 工具,请使用它。
@@ -187,6 +207,7 @@ git worktree prune # Self-healing: clean up any stale registrations
| “‘嗯,把它删掉吧’也算确认” | 只有精确输入 `discard` 才授权删除。 | | “‘嗯,把它删掉吧’也算确认” | 只有精确输入 `discard` 才授权删除。 |
| “PR 已经创建,所以工作树现在只是累赘” | PR 反馈需要在该工作树中修复。工作合入之前,它必须保留。 | | “PR 已经创建,所以工作树现在只是累赘” | PR 反馈需要在该工作树中修复。工作合入之前,它必须保留。 |
| “另一个工作树看起来陈旧——我顺便清理” | 只清理 `.worktrees/``worktrees/` 下的工作树。其他一切都属于宿主环境。 | | “另一个工作树看起来陈旧——我顺便清理” | 只清理 `.worktrees/``worktrees/` 下的工作树。其他一切都属于宿主环境。 |
| “移除被拒绝——`--force` 只是完成清理” | 拒绝意味着文件只存在于该工作树。`--force` 会永久销毁它们。展示给人类伙伴并询问。 |
| “合并结果失败可能只是偶发问题” | 合并结果一旦失败就停止一切。调查期间保留分支和工作树。 | | “合并结果失败可能只是偶发问题” | 合并结果一旦失败就停止一切。调查期间保留分支和工作树。 |
| “基础分支显然是 main” | 确认分叉点或询问。合并到错误基础分支的撤销成本很高。 | | “基础分支显然是 main” | 确认分叉点或询问。合并到错误基础分支的撤销成本很高。 |
| “推送被拒绝——强制推送就能解决” | 推送被拒绝说明远端已变化。先调查;只有你的人类伙伴明确要求时才强制推送。 | | “推送被拒绝——强制推送就能解决” | 推送被拒绝说明远端已变化。先调查;只有你的人类伙伴明确要求时才强制推送。 |
@@ -34,6 +34,10 @@
当前检出中的审查是只读的。不得以任何方式改动工作树、索引、HEAD 或分支状态。使用 `git show``git diff``git log` 等工具检查历史记录。如果你需要其他版本的工作副本,请将其检出到单独的临时目录中(例如 `git worktree add /tmp/review-[SHA] [SHA]`)——绝不要在当前检出中移动 HEAD。 当前检出中的审查是只读的。不得以任何方式改动工作树、索引、HEAD 或分支状态。使用 `git show``git diff``git log` 等工具检查历史记录。如果你需要其他版本的工作副本,请将其检出到单独的临时目录中(例如 `git worktree add /tmp/review-[SHA] [SHA]`)——绝不要在当前检出中移动 HEAD。
## 你不派遣子 Agent
独自完成这次审查。绝不派遣子 Agent 审查 diff 的一部分,也不要派遣另一名审查者征求第二意见。此流程已经提供了这项工作应有的全部审查席位;你派出的审查者会以完整成本重复其中一个席位,其结论不计入流程。如果 diff 对一次审查来说太大,就自行分段审查并在报告中说明。
## 检查内容 ## 检查内容
**计划一致性:** **计划一致性:**
@@ -14,7 +14,11 @@ description: 在当前会话中执行包含独立任务的实现计划时使用
**叙述:** 在工具调用之间,最多叙述一行简短内容—— **叙述:** 在工具调用之间,最多叙述一行简短内容——
记录由台账和工具结果承载。 记录由台账和工具结果承载。
**持续执行:** 不要在任务之间暂停下来向你的人类伙伴确认。不中断地执行计划中的所有任务。仅可因以下情况停止:出现你无法解决的 BLOCKED 状态、存在确实阻碍进展的歧义,或所有任务均已完成。询问“我应该继续吗?”以及提供进度摘要会浪费他们的时间——他们要求你执行计划,所以就执行它。 **持续执行:** 不要在任务之间暂停下来向你的人类伙伴确认。不中断地执行计划中的所有任务。仅可因下面列出的四类情况停止,或所有任务均已完成。询问“我应该继续吗?”以及提供进度摘要会浪费他们的时间——他们要求你执行计划,所以就执行它。
**裁决,而不是停滞。** 正在执行的计划不应等待人类。冲突、歧义、计划缺陷以及你原本想请求提高上限的情况,都由你作出决定。规格说明是约束性权威,计划是其论证,你的判断解决两者都没有回答的问题。把每项决定记录到账本中,格式为 `Ruling: <你的决定> — <原因> — <判断错误的代价>`,然后继续。错误裁决的代价是人类伙伴可以看见并撤销的返工;让会话停在问题上会耗费他们整天时间却一无所获。
只有四类事情会让你停止:不可逆或破坏性操作;安全敏感操作;规范要求先询问、且影响工作树之外的副作用(合并、推送共享分支、发布);以及计划糟糕到每条前进路径都只能猜测。遇到这些情况才停止并询问。
## 何时使用 ## 何时使用
@@ -57,14 +61,14 @@ digraph process {
"生成审查包,派遣任务审查者(./task-reviewer-prompt.md" [shape=box]; "生成审查包,派遣任务审查者(./task-reviewer-prompt.md" [shape=box];
"规格 ✅ 且质量通过?" [shape=diamond]; "规格 ✅ 且质量通过?" [shape=diamond];
"发现项与计划文本冲突?" [shape=diamond]; "发现项与计划文本冲突?" [shape=diamond];
"询问人类伙伴以哪个为准" [shape=box]; "针对冲突作出裁决并记录到账本" [shape=box];
"第 R 轮修复(共 5 轮):R≤3 时恢复实现者;R≥4 时派遣使用更强模型的新实现者" [shape=box]; "第 R 轮修复(共 5 轮):R≤3 时恢复实现者;R≥4 时派遣使用更强模型的新实现者" [shape=box];
"派遣作用域化复审(./re-review-prompt.md" [shape=box]; "派遣作用域化复审(./re-review-prompt.md" [shape=box];
"所有发现项都已解决?" [shape=diamond]; "所有发现项都已解决?" [shape=diamond];
"R = 5" [shape=diamond]; "R = 5" [shape=diamond];
"裁决每个未解决的发现项" [shape=box]; "裁决每个未解决的发现项" [shape=box];
"存在影响关键要求的发现项?" [shape=diamond]; "存在影响关键要求的发现项?" [shape=diamond];
"停止:向人类伙伴报告 BLOCKED" [shape=box]; "作出裁决并继续;只有所有路径都只能猜测时才停止" [shape=box];
"将发现项及裁决暂存到账本中" [shape=box]; "将发现项及裁决暂存到账本中" [shape=box];
"把完成记录追加到账本,标记待办已完成" [shape=box]; "把完成记录追加到账本,标记待办已完成" [shape=box];
} }
@@ -85,8 +89,8 @@ digraph process {
"生成审查包,派遣任务审查者(./task-reviewer-prompt.md" -> "规格 ✅ 且质量通过?"; "生成审查包,派遣任务审查者(./task-reviewer-prompt.md" -> "规格 ✅ 且质量通过?";
"规格 ✅ 且质量通过?" -> "把完成记录追加到账本,标记待办已完成" [label="是"]; "规格 ✅ 且质量通过?" -> "把完成记录追加到账本,标记待办已完成" [label="是"];
"规格 ✅ 且质量通过?" -> "发现项与计划文本冲突?" [label="否"]; "规格 ✅ 且质量通过?" -> "发现项与计划文本冲突?" [label="否"];
"发现项与计划文本冲突?" -> "询问人类伙伴以哪个为准" [label="是"]; "发现项与计划文本冲突?" -> "针对冲突作出裁决并记录到账本" [label="是"];
"询问人类伙伴以哪个为准" -> "第 R 轮修复(共 5 轮):R≤3 时恢复实现者;R≥4 时派遣使用更强模型的新实现者"; "针对冲突作出裁决并记录到账本" -> "第 R 轮修复(共 5 轮):R≤3 时恢复实现者;R≥4 时派遣使用更强模型的新实现者";
"发现项与计划文本冲突?" -> "第 R 轮修复(共 5 轮):R≤3 时恢复实现者;R≥4 时派遣使用更强模型的新实现者" [label="否"]; "发现项与计划文本冲突?" -> "第 R 轮修复(共 5 轮):R≤3 时恢复实现者;R≥4 时派遣使用更强模型的新实现者" [label="否"];
"第 R 轮修复(共 5 轮):R≤3 时恢复实现者;R≥4 时派遣使用更强模型的新实现者" -> "派遣作用域化复审(./re-review-prompt.md"; "第 R 轮修复(共 5 轮):R≤3 时恢复实现者;R≥4 时派遣使用更强模型的新实现者" -> "派遣作用域化复审(./re-review-prompt.md";
"派遣作用域化复审(./re-review-prompt.md" -> "所有发现项都已解决?"; "派遣作用域化复审(./re-review-prompt.md" -> "所有发现项都已解决?";
@@ -95,7 +99,7 @@ digraph process {
"R = 5" -> "第 R 轮修复(共 5 轮):R≤3 时恢复实现者;R≥4 时派遣使用更强模型的新实现者" [label="否——进入下一轮"]; "R = 5" -> "第 R 轮修复(共 5 轮):R≤3 时恢复实现者;R≥4 时派遣使用更强模型的新实现者" [label="否——进入下一轮"];
"R = 5" -> "裁决每个未解决的发现项" [label="是——触发熔断"]; "R = 5" -> "裁决每个未解决的发现项" [label="是——触发熔断"];
"裁决每个未解决的发现项" -> "存在影响关键要求的发现项?"; "裁决每个未解决的发现项" -> "存在影响关键要求的发现项?";
"存在影响关键要求的发现项?" -> "停止:向人类伙伴报告 BLOCKED" [label="是"]; "存在影响关键要求的发现项?" -> "作出裁决并继续;只有所有路径都只能猜测时才停止" [label="是"];
"存在影响关键要求的发现项?" -> "将发现项及裁决暂存到账本中" [label="否"]; "存在影响关键要求的发现项?" -> "将发现项及裁决暂存到账本中" [label="否"];
"将发现项及裁决暂存到账本中" -> "把完成记录追加到账本,标记待办已完成"; "将发现项及裁决暂存到账本中" -> "把完成记录追加到账本,标记待办已完成";
"把完成记录追加到账本,标记待办已完成" -> "还有任务?"; "把完成记录追加到账本,标记待办已完成" -> "还有任务?";
@@ -138,18 +142,17 @@ superpowers:using-git-worktrees 创建一个工作区,或验证现有工作区
发生这种情况,请从 `git log` 恢复。 发生这种情况,请从 `git log` 恢复。
通读计划一次,记下其上下文和全局约束,并为每项任务创建一个 通读计划一次,记下其上下文和全局约束,并为每项任务创建一个
待办事项。 待办事项。如果计划指明了 Spec,也要读取它:规格说明是计划论证所依据的权威,二者必须一起提供给执行者。找不到可读取的 Spec 时,在账本中记一条说明;没有规格说明时作出的裁决属于临时裁决。
在分派任务 1 之前,通读计划一次以检查冲突: 在分派任务 1 之前,通读计划一次以检查冲突,并在检查时写下检查内容
- 彼此矛盾或与计划的全局约束相矛盾的任务 - 彼此矛盾或与计划的全局约束相矛盾的任务
- 计划明确要求、但审查量规视为缺陷的任何事项(一个没有进行任何断言的 - 计划明确要求、但审查量规视为缺陷的任何事项(一个没有进行任何断言的
测试、逐字重复一个逻辑块) 测试、逐字重复一个逻辑块)
在执行开始前,将你发现的所有内容作为一个批量问题提交给你的人类伙伴—— 检查输出应是一张表,而不是一句结论。对每一对共享文件或接口的任务写一行:两个任务、一个任务产出的内容与另一个任务消费的内容,以及你的发现。对每个任务再写一行:任务自身是否自洽——它指定的测试是否对应指定的代码、创建的文件是否对应后续触及的文件。“检查干净”而没有这些行,不算执行过检查。
将每项发现与要求该事项的计划文本并列,并询问以哪一项为准——而不是在
计划执行途中每发现一项就中断一次。如果检查未发现问题,则不作说明,继续 把这张表写到账本中。在开始执行前对所有发现作出裁决——将每项发现与要求它的计划文本并列——并把每项裁决记录到账本。若检查干净,则无需说明,直接继续。对检查发现的每个冲突作出裁决:规格说明是约束性权威,计划是其论证;将裁决写在对应行旁边,然后分派任务 1。复审循环仍是实现过程中才出现的冲突的兜底机制。
执行。对于只有在实现过程中才显现的冲突,复审循环仍是兜底机制。
## 模型选择 ## 模型选择
@@ -177,8 +180,12 @@ superpowers:using-git-worktrees 创建一个工作区,或验证现有工作区
## 任务循环 ## 任务循环
**批量处理同形小任务。** 如果计划列出多个小型、相互独立且属于同一种编辑的任务——相同的一行修复、常量变更,或跨文件重复添加字段——不要为每项任务分派一个子 Agent。编写一份列出所有文件及其变更的批量简报,交给一个子 Agent,并把它的 diff 作为一个整体审查。只有需要各自判断、测试或独立审查面的工作,才按每项任务一次派发。
你粘贴到派遣提示中的所有内容——以及子 Agent 返回的所有输出——在会话余下的整个期间都会常驻于你的上下文中,并在之后的每一轮中被重新读取。请以文件形式交接产物。 你粘贴到派遣提示中的所有内容——以及子 Agent 返回的所有输出——在会话余下的整个期间都会常驻于你的上下文中,并在之后的每一轮中被重新读取。请以文件形式交接产物。
**等待已派遣的子 Agent:** 不要用短超时轮询等待接口,也不要一次沉默地进行无界等待。只要还有本地工作,就继续处理台账更新、下一份审查包或阅读报告;子 Agent 的结果会自行到达。真正空闲时,用有界时间段等待(平台允许时等待 5-10 分钟),并在每段等待之间发布一行状态、列出仍存活的子 Agent,并追查已完成却没有报告的子 Agent。有界等待保留长等待的大部分效率,同时能在数分钟内发现卡住或丢失的子 Agent。
### 1. 派遣实现者 ### 1. 派遣实现者
派遣前记录 BASE`git rev-parse HEAD`)——审查包和修复轮次的 diff 都需要它。 派遣前记录 BASE`git rev-parse HEAD`)——审查包和修复轮次的 diff 都需要它。
@@ -187,6 +194,7 @@ superpowers:using-git-worktrees 创建一个工作区,或验证现有工作区
`scripts/task-brief PLAN_FILE N`——它会将任务的完整文本提取到一个具有唯一名称的文件中,并打印该路径。组织派遣内容时,应让简报始终作为需求的唯一来源。你的派遣内容应包含:(1) 用一行说明此任务在项目中的位置;(2) 简报路径,并以“先阅读此文件——它就是你的需求,其中包含必须原样使用的精确值”引出;(3) 简报不可能知道的、来自先前任务的接口和决策;(4) 你对简报中所注意到的任何歧义的解决方案;(5) 报告文件路径和报告约定。精确值(数字、魔法字符串、签名、测试用例)只能出现在简报中。绝不要让子 Agent 阅读整个计划文件。 `scripts/task-brief PLAN_FILE N`——它会将任务的完整文本提取到一个具有唯一名称的文件中,并打印该路径。组织派遣内容时,应让简报始终作为需求的唯一来源。你的派遣内容应包含:(1) 用一行说明此任务在项目中的位置;(2) 简报路径,并以“先阅读此文件——它就是你的需求,其中包含必须原样使用的精确值”引出;(3) 简报不可能知道的、来自先前任务的接口和决策;(4) 你对简报中所注意到的任何歧义的解决方案;(5) 报告文件路径和报告约定。精确值(数字、魔法字符串、签名、测试用例)只能出现在简报中。绝不要让子 Agent 阅读整个计划文件。
- **报告文件:**以简报为实现者的报告文件命名(简报 `…/task-N-brief.md` → 报告 `…/task-N-report.md`),并将其写入派遣提示。实现者在该文件中写入完整报告,并且只返回状态、提交记录、一行测试摘要和关注事项。 - **报告文件:**以简报为实现者的报告文件命名(简报 `…/task-N-brief.md` → 报告 `…/task-N-report.md`),并将其写入派遣提示。实现者在该文件中写入完整报告,并且只返回状态、提交记录、一行测试摘要和关注事项。
- 一条派遣提示描述的是一个任务,而不是会话的历史。不要把累积的先前任务摘要(“任务 1-3 后的状态”)粘贴到后续派遣中——某个真实会话的派遣内容达到了 42k 个字符,其中 99% 都是粘贴的历史记录。一个全新的子 Agent 需要的是它的任务、它会涉及的接口以及全局约束。除此之外什么都不需要。 - 一条派遣提示描述的是一个任务,而不是会话的历史。不要把累积的先前任务摘要(“任务 1-3 后的状态”)粘贴到后续派遣中——某个真实会话的派遣内容达到了 42k 个字符,其中 99% 都是粘贴的历史记录。一个全新的子 Agent 需要的是它的任务、它会涉及的接口以及全局约束。除此之外什么都不需要。
- 派遣内容携带“不派遣子 Agent”的契约(该契约位于实现者模板中):实现者绝不派遣子 Agent——既不派助手,也绝不派审查者。审查会在它报告后由你负责派遣。真实会话中,实现者自行派出的每个审查者都重复了控制器已经派出的任务审查,等于每项任务多花一张完整审查席位。
- 如果先前的任务在本任务涉及的区域中暂存了一项发现,请在派遣内容中附上指向该账本条目的指针。 - 如果先前的任务在本任务涉及的区域中暂存了一项发现,请在派遣内容中附上指向该账本条目的指针。
- 从派遣结果中记录实现者的 Agent 身份——修复循环第 1-3 轮会恢复此 Agent。 - 从派遣结果中记录实现者的 Agent 身份——修复循环第 1-3 轮会恢复此 Agent。
- 绝不要并行派遣多个实现子 Agent(会产生冲突)。 - 绝不要并行派遣多个实现子 Agent(会产生冲突)。
@@ -207,7 +215,7 @@ superpowers:using-git-worktrees 创建一个工作区,或验证现有工作区
1. 如果是上下文问题,请提供更多上下文,并使用同一模型重新派遣 1. 如果是上下文问题,请提供更多上下文,并使用同一模型重新派遣
2. 如果任务需要更多推理,请使用能力更强的模型重新派遣 2. 如果任务需要更多推理,请使用能力更强的模型重新派遣
3. 如果任务过大,请将其拆分成更小的部分 3. 如果任务过大,请将其拆分成更小的部分
4. 如果计划本身有误,请上报给人类 4. 如果计划本身有误,请裁决修正、记录到账本,并携带该裁决重新派遣
**绝不**忽略上报,也绝不强迫同一模型在没有任何改变的情况下重试。如果实现者表示它卡住了,就必须做出改变。 **绝不**忽略上报,也绝不强迫同一模型在没有任何改变的情况下重试。如果实现者表示它卡住了,就必须做出改变。
@@ -265,7 +273,7 @@ superpowers:using-git-worktrees 创建一个工作区,或验证现有工作区
- 在推进过程中,将次要发现项记录到进度账本中 - 在推进过程中,将次要发现项记录到进度账本中
`Task <N>: minor (deferred): <one-liner>`),并让最终的全分支审查查看该列表,以便它判定其中哪些必须在合并前修复。无人阅读的汇总就是悄无声息的丢弃。次要发现项永不进入该循环。 `Task <N>: minor (deferred): <one-liner>`),并让最终的全分支审查查看该列表,以便它判定其中哪些必须在合并前修复。无人阅读的汇总就是悄无声息的丢弃。次要发现项永不进入该循环。
- 标记为计划强制要求的发现项——或任何与计划文本要求冲突的发现项——都应像任何计划矛盾一样,由人类决定:展示该发现项计划文本,并询问以哪一个为准。不要因为计划强制要求它就驳回该发现项,也不要在未询问的情况下派发与计划相冲突的修复。 - 标记为计划强制要求的发现项——或任何与计划文本要求冲突的发现项——由你裁决:将发现项计划文本权衡,以规格说明为约束性权威作出决定,并在行动前记录到账本。不要因为计划强制要求它就驳回该发现项,也不要在没有记录裁决的情况下派发与计划相冲突的修复。
其余一切都进入该循环。一轮修复包括一次修复派发,加上一次限定范围的复审。每个任务最多五轮: 其余一切都进入该循环。一轮修复包括一次修复派发,加上一次限定范围的复审。每个任务最多五轮:
**第 1-3 轮——恢复原实现者。** 将未解决的发现项逐字发送给它。它的上下文完好无损:它了解任务、代码以及它自己的选择。如果你的运行框架无法向仍在运行的子 Agent 再发送一条消息,则派发一个新的实现者,并向其提供简报路径、报告文件路径和这些发现项——无论哪种方式,报告文件都是持久记忆。 **第 1-3 轮——恢复原实现者。** 将未解决的发现项逐字发送给它。它的上下文完好无损:它了解任务、代码以及它自己的选择。如果你的运行框架无法向仍在运行的子 Agent 再发送一条消息,则派发一个新的实现者,并向其提供简报路径、报告文件路径和这些发现项——无论哪种方式,报告文件都是持久记忆。
@@ -284,10 +292,9 @@ superpowers:using-git-worktrees 创建一个工作区,或验证现有工作区
**熔断器。** 如果第 5 轮复审后仍有未解决的发现项,就停止派遣。由你亲自裁决每个未解决的发现项——你掌握审查者所缺少的计划和跨任务上下文: **熔断器。** 如果第 5 轮复审后仍有未解决的发现项,就停止派遣。由你亲自裁决每个未解决的发现项——你掌握审查者所缺少的计划和跨任务上下文:
- **审查者判断错误,或该问题存在争议:** 暂存它—— - **审查者判断错误,或该问题存在争议:** 暂存它——
`Task <N>: parked — <finding> — ruling: <why the code stands>`。最终审查会看到双方理由。 `Task <N>: parked — <finding> — Ruling: <why the code stands>`。最终审查会看到双方理由。
- **问题真实存在,但下游没有任何内容依赖它:** 以同样方式暂存,并在裁决中说明它确实存在但已延期。 - **问题真实存在,但下游没有任何内容依赖它:** 以同样方式暂存,并在裁决中说明它确实存在但已延期。
- **问题真实存在且影响关键要求**——后续任务会依赖它,或它揭示了计划缺陷:停止。追加 - **问题真实存在且影响关键要求**——后续任务会依赖它,或它揭示了计划缺陷:裁决能解除依赖工作的最小变更,以 `Task <N>: Ruling: <finding> — <what you decided and why>` 记入账本,并把它带入下一项任务的派遣。静默暂存结构性失败会让所有依赖任务继续在它之上构建。只有缺陷让所有前进路径都只能猜测时才停止。
`Task <N>: BLOCKED — <reason>`,并向你的人类伙伴报告该发现项、与之冲突的计划文本以及修复历史。暂存结构性失败会让所有依赖任务继续在它之上构建,也会把一个最终审查同样无法修复的问题留到最后。
只在达到轮次上限时进行裁决。提前裁决来结束循环,不过是换了名称的预判。每次裁决都必须写入账本——严禁无声丢弃。 只在达到轮次上限时进行裁决。提前裁决来结束循环,不过是换了名称的预判。每次裁决都必须写入账本——严禁无声丢弃。
@@ -304,10 +311,12 @@ superpowers:using-git-worktrees 创建一个工作区,或验证现有工作区
最终的整分支审查也要有一个审查包:运行 `scripts/review-package PLAN_FILE MERGE_BASE HEAD`MERGE_BASE = 该分支起始于的提交,例如 `git merge-base main HEAD`),并在派发最终审查时包含输出的路径,这样最终审查者只需读取一个文件,而不必使用 git 命令重新推导分支差异。使用最强的可用模型进行派发(参见模型选择),并使用 superpowers:requesting-code-review 的 [code-reviewer.md](../requesting-code-review/code-reviewer.md)。让它查看账本中的 deferred-minor 行和 parked 行,以便对哪些项目必须在合并前修复进行分诊。 最终的整分支审查也要有一个审查包:运行 `scripts/review-package PLAN_FILE MERGE_BASE HEAD`MERGE_BASE = 该分支起始于的提交,例如 `git merge-base main HEAD`),并在派发最终审查时包含输出的路径,这样最终审查者只需读取一个文件,而不必使用 git 命令重新推导分支差异。使用最强的可用模型进行派发(参见模型选择),并使用 superpowers:requesting-code-review 的 [code-reviewer.md](../requesting-code-review/code-reviewer.md)。让它查看账本中的 deferred-minor 行和 parked 行,以便对哪些项目必须在合并前修复进行分诊。
如果最终的整分支审查返回发现项,请派发一个且仅一个修复子 Agent,并向其提供完整的发现项列表——不要为每个发现项分别派一个修复者。按发现项分别安排的修复者都要重建上下文并重新运行套件;在一次真实会话中,最终审查的修复波次成本超过了其所有任务的总和。然后,对该修复波次恰好进行一次限定范围的复审(针对修复范围运行 `scripts/review-package PLAN_FILE FIX_BASE HEAD`[re-review-prompt.md](re-review-prompt.md))。按照任务循环中的熔断器方式裁决任何残留发现项:附裁定搁置,或在遇到承重性发现项停止。不存在第二个修复波次——当 finishing-a-development-branch 呈现选项时,残留的承重性发现项会提交给你的人类伙伴。 如果最终的整分支审查返回发现项,请派发一个且仅一个修复子 Agent,并向其提供完整的发现项列表——不要为每个发现项分别派一个修复者。按发现项分别安排的修复者都要重建上下文并重新运行套件;在一次真实会话中,最终审查的修复波次成本超过了其所有任务的总和。然后,对该修复波次恰好进行一次限定范围的复审(针对修复范围运行 `scripts/review-package PLAN_FILE FIX_BASE HEAD`[re-review-prompt.md](re-review-prompt.md))。按照任务循环中的熔断器方式裁决任何残留发现项:附裁定搁置,或裁决承重性发现项并记录你的决定。这里只能因上述四类情况停止。不存在第二个修复波次——当 finishing-a-development-branch 呈现选项时,残留的承重性发现项会提交给你的人类伙伴。
## 收尾 ## 收尾
在删除任何内容之前,收集账本中包含 `Ruling:` 的每一行——起飞前裁决、搁置发现项、熔断器裁决,全部包括——按作出顺序放进最终消息的“我作出的裁决”部分,每条都写明判断错误的代价。清单必须完整:账本有裁决,清单就必须有裁决。这是你替人类伙伴作出的决定传达给他们的唯一位置;他们会阅读并返工你判断错误的部分。随工作区一起消失的裁决,就是秘密作出的决定。
当最终的整分支审查无问题且其修复已合并后,删除此计划的工作区(`rm -rf <workspace>`)——现在 git 历史就是记录。同级目录属于其他计划;不要动它们。 当最终的整分支审查无问题且其修复已合并后,删除此计划的工作区(`rm -rf <workspace>`)——现在 git 历史就是记录。同级目录属于其他计划;不要动它们。
使用 superpowers:finishing-a-development-branch。 使用 superpowers:finishing-a-development-branch。
@@ -324,6 +333,7 @@ superpowers:using-git-worktrees 创建一个工作区,或验证现有工作区
| "修复很小,跳过复审吧" | 未经审查的修复正是回归问题混入的方式。每一轮都以限定范围的复审结束。 | | "修复很小,跳过复审吧" | 未经审查的修复正是回归问题混入的方式。每一轮都以限定范围的复审结束。 |
| "审查会拖慢循环" | 没有审查的循环只不过是未经验证的反复折腾。审查是循环的刹车和方向盘。 | | "审查会拖慢循环" | 没有审查的循环只不过是未经验证的反复折腾。审查是循环的刹车和方向盘。 |
| "账本记账是额外开销" | 账本是在压缩后仍能保留下来的东西。没有账本的控制器曾重新派发整个已完成的任务序列。 | | "账本记账是额外开销" | 账本是在压缩后仍能保留下来的东西。没有账本的控制器曾重新派发整个已完成的任务序列。 |
| "实现者自己派了审查者——免费获得额外保证" | 这是审查同一 diff 的重复席位;任务审查本身就是关卡。实现者派出的审查者是需要指出的缺陷,不是严谨性。 |
## 示例工作流 ## 示例工作流
@@ -47,6 +47,10 @@
迭代过程中,运行与你正在修改的内容对应的聚焦测试;完整测试套件只需在提交前 迭代过程中,运行与你正在修改的内容对应的聚焦测试;完整测试套件只需在提交前
运行一次,而不是每次编辑后都运行。 运行一次,而不是每次编辑后都运行。
## 你不派遣子 Agent
独自完成这项任务的全部工作。绝不派遣子 Agent 实现任务的一部分,更不能派遣审查者检查你的工作。下方的自我审查意味着阅读你自己的 diff。审查是控制器的职责:你报告后,它会针对你的 diff 派遣一名全新的审查者。你派出的审查者会以完整成本重复这次审查,其批准在流程中不计数。如果你开始想“独立审查会让我的报告更可靠”,请记住:审查已经安排好了。直接报告。
## 代码组织 ## 代码组织
当代码规模小到可以一次纳入上下文时,你能更好地推理;文件职责集中时,你的 当代码规模小到可以一次纳入上下文时,你能更好地推理;文件职责集中时,你的
@@ -39,6 +39,10 @@
在此检出目录中,你的审查是只读的。不得以任何方式修改工作树、索引、HEAD 在此检出目录中,你的审查是只读的。不得以任何方式修改工作树、索引、HEAD
或分支状态。 或分支状态。
## 你不派遣子 Agent
独自完成这次审查。绝不派遣子 Agent 审查 diff 的一部分,也不要派遣另一名审查者征求第二意见。此流程已经提供了这项工作应有的全部审查席位;你派出的审查者会以完整成本重复其中一个席位,其结论不计入流程。如果 diff 对一次审查来说太大,就自行分段审查并在报告中说明。
## 范围 ## 范围
你的范围是发现项列表和修复 diff。必须裁定每一个发现项。检查修复 diff, 你的范围是发现项列表和修复 diff。必须裁定每一个发现项。检查修复 diff,
@@ -47,6 +47,10 @@
在此检出目录中,你的审查是只读的。不得以任何方式修改工作树、索引、HEAD 在此检出目录中,你的审查是只读的。不得以任何方式修改工作树、索引、HEAD
或分支状态。 或分支状态。
## 你不派遣子 Agent
独自完成这次审查。绝不派遣子 Agent 审查 diff 的一部分,也不要派遣另一名审查者征求第二意见。此流程已经提供了这项工作应有的全部审查席位;你派出的审查者会以完整成本重复其中一个席位,其结论不计入流程。如果 diff 对一次审查来说太大,就自行分段审查并在报告中说明。
## 不要相信报告 ## 不要相信报告
把实现者的报告视为尚未验证的代码声明。它可能不完整、不准确或过于乐观。 把实现者的报告视为尚未验证的代码声明。它可能不完整、不准确或过于乐观。
@@ -64,6 +68,8 @@
实现者报告的测试输出中若有警告或其他噪声,也属于发现项——测试输出应当干净。 实现者报告的测试输出中若有警告或其他噪声,也属于发现项——测试输出应当干净。
看不见的证据不等于不存在证据。如果报告或测试证据看起来被截断,或找不到它声称的结果,请重新读取报告标明的文件路径;如果确实缺失或损坏,就把它作为缺口报告给控制器。为了重新生成你没读清的内容而重跑套件不算验证;证据难以阅读也不等于证据无效。
## 第 1 部分:规格符合度 ## 第 1 部分:规格符合度
将 diff 与“要求实现的内容”进行比较: 将 diff 与“要求实现的内容”进行比较:
@@ -72,6 +78,8 @@
- **Extra** 未要求的功能、过度工程、不必要的“锦上添花” - **Extra** 未要求的功能、过度工程、不必要的“锦上添花”
- **Misunderstood** 用错误方式构建了正确功能,或解决了错误的问题 - **Misunderstood** 用错误方式构建了正确功能,或解决了错误的问题
如果简报列出了多个各自有变更的文件(批量派遣),请逐文件对照 diff:列表中的每个文件都必须有对应的 hunk。列表中列出但 diff 从未触及的文件,无论其他批量内容多干净,都属于 Missing。
如果某项要求无法仅根据此 diff 验证(它位于未更改代码中,或跨越多个任务), 如果某项要求无法仅根据此 diff 验证(它位于未更改代码中,或跨越多个任务),
请将其报告为 ⚠️ 条目,不要扩大搜索范围。 请将其报告为 ⚠️ 条目,不要扩大搜索范围。
@@ -57,6 +57,7 @@ description: 在开始任何对话时使用——规定如何查找和使用技
- Gemini CLI`references/gemini-tools.md` - Gemini CLI`references/gemini-tools.md`
- Pi`references/pi-tools.md` - Pi`references/pi-tools.md`
- Antigravity`references/antigravity-tools.md` - Antigravity`references/antigravity-tools.md`
- Hermes Agent`references/hermes-tools.md`
## 用户指令 ## 用户指令
@@ -7,7 +7,32 @@
multi_agent = true multi_agent = true
``` ```
这将 `dispatching-parallel-agents``subagent-driven-development` 等技能启用 `spawn_agent``wait_agent``close_agent`。使用 subagent-driven-development 时,审查者返回审查结果后就关闭它。每个实现者子 Agent 应保持开启,直到其任务通过审查——修复循环会恢复该实现者——然后再关闭。如果你的运行平台无法向已派生的 Agent 再发送消息,则每一轮修复都派遣一个新的实现者,并向它提供简报、报告文件和发现项 这将启用 `dispatching-parallel-agents``subagent-driven-development` 等技能使用的多 Agent 工具。具体能获得哪些工具取决于模型预设选择的多 Agent 版本(当前预设运行 V2,旧预设运行 V1)。当实际工具列表与任何表格(包括本文件)不一致时,以实际工具列表为准
- **派生:** 使用 `spawn_agent {fork_turns: "none"}` 为子 Agent 提供干净上下文;默认的 `"all"` 会把完整对话复制给子 Agent。在 Codex 0.145+ 中,`~/.codex/agents/` 下的角色文件会通过 `agent_type` 附加到隔离分支。完整历史分支可接受 `model``reasoning_effort` 覆盖(只有 `agent_type` 会被拒绝);隔离分支是 SDD 默认方式,目的是保持上下文干净,而不是因为覆盖参数需要它。
- **修复轮次:** 使用 `followup_task` 恢复实现者——它会传递消息、触发一轮执行,并透明地重新加载被运行平台驱逐的子 Agent。不要因为“无法再次给派生 Agent 发消息”就派遣新的实现者;V2 始终支持这种恢复。
- **生命周期:** V2 没有 `close_agent`。需要槽位时,已完成的子 Agent 会自动被驱逐;不关闭它们没有成本。只有 V1 会话拥有 `close_agent`——在 V1 中,审查返回后关闭审查者,每项任务审查通过后关闭实现者。
- **模型名称:** 未检查当前 `spawn_agent` 允许列表前,绝不要从技能、表格或旧会话复制模型名称;V2 只接受兼容 V2 的预设,对其他名称会直接报错。
## 等待子 Agent
`wait_agent` 是事件订阅,不是轮询:长等待会在子 Agent 产生邮箱活动的瞬间唤醒,延迟与短等待相同。短超时轮询没有收益,每次超时都会多消耗一次工具调用和上下文计费;在实测会话中,约三分之二的等待调用都是超时的短轮询。
- 仍有本地工作时不要等待。已完成子 Agent 的最终答复会推送到邮箱,并在你的下一轮中到达。
- 真正空闲且仍有子 Agent 时,用有界时间段等待:`wait_agent``timeout_ms` 设为 300000-600000(5-10 分钟)。每段等待结束(唤醒或超时)后发布一行状态,运行 `list_agents`,并追查已完成却没有报告的子 Agent。绝不要堆叠短于 5 分钟的轮询;事件订阅会以同样速度唤醒有界等待。
- 完成邮件无法唤醒空闲控制器(它会送达但不会触发新一轮);覆盖这一空闲窗口是 `wait_agent` 唯一的用途。没有活动而超时,是你重新核对状态的信号,不是缩短下一段等待的理由。
## 派遣时的模型路由
每次调用 `spawn_agent`——包括你自己作为扇出任务中的子 Agent 时——都要根据正在执行的技能的模型选择规则显式设置 `model``reasoning_effort`。只设置 `model` 是陷阱:子 Agent 的思考强度会悄悄重置为该模型默认值,而不是继承你的设置。
请人类伙伴在 `~/.codex/config.toml` 中增加机器级兜底配置,确保遗漏的派遣仍会路由到明确的档位,而不会静默继承会话中最昂贵的模型:
```toml
[agents]
default_subagent_model = "<允许列表中的中档模型>"
default_subagent_reasoning_effort = "medium"
```
## 环境检测 ## 环境检测
@@ -0,0 +1,54 @@
# Hermes Agent 工具映射
技能会描述动作(“派遣子 Agent”“创建待办”“读取文件”)。在 Hermes Agent 上,这些动作对应以下工具。
## 工具
| 技能请求的动作 | Hermes 工具 |
|---|---|
| 读取文件 | `read_file` |
| 创建新文件 | `write_file` |
| 编辑文件(定向补丁) | `patch` |
| 运行 shell 命令 | `terminal` |
| 搜索文件内容 | `search_files` |
| 按名称查找文件 | 使用 `find``terminal` |
| 获取 URL / 读取网页 | `web_extract(urls=[...])` |
| 搜索网页 | `web_search(query=...)` |
| 派遣子 Agent | `delegate_task(goal=..., context=..., toolsets=[...], role="leaf")` |
| 任务跟踪 | `todo` 工具 |
| 调用技能 | `skill_view("skill-name")` |
## 指令文件
技能提到“你的指令文件”时,在 Hermes Agent 上指项目目录中的 **`AGENTS.md`**,或全局的 `~/.hermes/SOUL.md`
## 调用技能
Hermes Agent 提供包含 `skill_view``skills_list``skills` 工具集。调用 Superpowers 技能:
```
skill_view("brainstorming")
skill_view("test-driven-development")
```
如果 `skill_view` 找不到 Superpowers 技能(插件完全注册前,技能可能尚未出现在目录中),则直接读取 SKILL.md:
```
read_file(path="~/.hermes/plugins/superpowers/skills/<skill-name>/SKILL.md")
```
这是其他没有原生技能加载的运行平台所使用的相同回退机制。
## 派遣子 Agent
使用 `delegate_task` 为并行或串行工作流创建隔离的子 Agent:
```
delegate_task(goal="...", context="...", toolsets=[...], role="leaf")
```
如果 `delegate_task` 不可用,就在线完成工作,不要臆造工具调用。
## 任务跟踪
在会话内使用 `todo` 工具进行任务跟踪。对于多 Agent 任务板,如果可用则使用 `hermes kanban` CLI。将旧的 `TodoWrite` 引用视为任务跟踪动作。
@@ -60,6 +60,8 @@ description: 当你已有多步骤任务的规格说明或需求时,在接触
**技术栈:** [关键技术/库] **技术栈:** [关键技术/库]
**规格说明:** [本计划实现的规格/设计文档路径——计划以规格说明为依据,规格说明会随计划一起传递;执行者需要同时阅读二者]
## 全局约束 ## 全局约束
[规范中的项目级要求——最低版本、依赖限制、 [规范中的项目级要求——最低版本、依赖限制、
@@ -13,9 +13,9 @@
* Requires: graphviz (dot) installed on system * Requires: graphviz (dot) installed on system
*/ */
const fs = require('fs'); import * as fs from 'fs';
const path = require('path'); import * as path from 'path';
const { execSync } = require('child_process'); import { execFileSync } from 'child_process';
function extractDotBlocks(markdown) { function extractDotBlocks(markdown) {
const blocks = []; const blocks = [];
@@ -69,7 +69,7 @@ ${bodies.join('\n\n')}
function renderToSvg(dotContent) { function renderToSvg(dotContent) {
try { try {
return execSync('dot -Tsvg', { return execFileSync('dot', ['-Tsvg'], {
input: dotContent, input: dotContent,
encoding: 'utf-8', encoding: 'utf-8',
maxBuffer: 10 * 1024 * 1024 maxBuffer: 10 * 1024 * 1024
@@ -107,9 +107,10 @@ function main() {
process.exit(1); process.exit(1);
} }
// Check if dot is available // Check if dot is available. Run the binary directly rather than probing
// with `which`, which is not a command on Windows.
try { try {
execSync('which dot', { encoding: 'utf-8' }); execFileSync('dot', ['-V'], { stdio: 'ignore' });
} catch { } catch {
console.error('Error: graphviz (dot) not found. Install with:'); console.error('Error: graphviz (dot) not found. Install with:');
console.error(' brew install graphviz # macOS'); console.error(' brew install graphviz # macOS');