| 1 | # Project Tools |
| 2 | |
| 3 | > **Import boundary**: move only sources already under the repository's |
| 4 | > `projects/` tree. Copy every other local path, even when `--move` is supplied. |
| 5 | > Use `--copy` to preserve a projects-local source. |
| 6 | |
| 7 | Project tools create, validate, and inspect the standard PPT Master workspace. |
| 8 | |
| 9 | ## `project_manager.py` |
| 10 | |
| 11 | Main entry point for project setup and validation. |
| 12 | |
| 13 | ```bash |
| 14 | python3 scripts/project_manager.py init <project_name> --format ppt169 |
| 15 | python3 scripts/project_manager.py import-sources <project_path> <source1_or_dir> [<source2_or_dir> ...] |
| 16 | python3 scripts/project_manager.py scaffold-spec <project_path> # optional manual helper |
| 17 | python3 scripts/project_manager.py scaffold-lock <project_path> # optional manual helper |
| 18 | python3 scripts/project_manager.py validate <project_path> |
| 19 | python3 scripts/project_manager.py info <project_path> |
| 20 | python3 scripts/project_manager.py page-context <project_path> P07 [--pretty] [--record-usage] |
| 21 | python3 scripts/project_manager.py page-context-report <project_path> |
| 22 | ``` |
| 23 | |
| 24 | Notes: |
| 25 | - `init --quick-generate`: `svg_output/` plus |
| 26 | `validation/workflow.log`; no README |
| 27 | - Files outside `projects/` are always copied into `sources/` |
| 28 | - `--move` applies only to sources under the repository's `projects/` tree |
| 29 | - A directly supplied supported bitmap is also copied into `images/` with a |
| 30 | collision-safe basename while its original remains archived in `sources/` |
| 31 | - Directory inputs are expanded non-recursively. After Step 1 conversion, |
| 32 | pass the source file/directory once when generated Markdown lives beside the |
| 33 | original source. If Step 1 used `-o` to write Markdown elsewhere, pass both |
| 34 | the original source path/directory and the Markdown output path/directory. |
| 35 | - A projects-local supplied source directory left strictly empty after import |
| 36 | (or empty from the start) is removed; every directory outside `projects/` |
| 37 | remains untouched. `--copy` never removes directories. |
| 38 | - Files already under `projects/` move into `sources/` by default. Pass `--copy` |
| 39 | to preserve them in place. |
| 40 | - `--move` and `--copy` are mutually exclusive. |
| 41 | - Normal Generate authoring reads `templates/design_spec_reference.md`, writes |
| 42 | the complete `design_spec.md` from scratch, then reads |
| 43 | `templates/spec_lock_reference.md` and writes the complete lock projection. |
| 44 | It does not call either scaffold command. |
| 45 | - Optional `scaffold-spec` creates `design_spec.md` from |
| 46 | `templates/scaffolds/design_spec.md`; `scaffold-lock` creates `spec_lock.md` |
| 47 | from `templates/scaffolds/spec_lock.md`. Both substitute project/canvas |
| 48 | metadata deterministically and refuse to overwrite an existing artifact. |
| 49 | - `validate` parses the existing Markdown artifacts against |
| 50 | `templates/schemas/design_spec.schema.json` and |
| 51 | `templates/schemas/spec_lock.schema.json`. It reports missing sections and |
| 52 | fields, illegal enums, malformed page keys, and unmet conditional sections. |
| 53 | When optional custom reference lists are present, it also requires every id |
| 54 | to resolve to the matching mode, visual-style, or image-rendering catalog, |
| 55 | rejects duplicates, and rejects reference rows on non-custom selections; |
| 56 | it does not rewrite either artifact or compare their values for textual |
| 57 | equality. It also does not prove final-confirmation → Design Spec fidelity or |
| 58 | Design Spec/context → lock semantic fidelity; Generate Step 4 owns those two |
| 59 | gates before this structural validation. Validation reads the planning |
| 60 | artifacts only and never reopens `confirm_ui/result.json`; the final result is |
| 61 | consumed once into the Design Spec before validation begins. The design schema is structural lint for |
| 62 | the human-readable brief; the lock schema owns machine execution values. For |
| 63 | structured template use, strict input prototypes must match their assigned |
| 64 | Master/Layout; adaptive input prototypes retain the assigned Master while a |
| 65 | new output Layout already declared by Strategist is cross-validated after its |
| 66 | generated SVG exists. Versioned |
| 67 | Direct-authored current artifacts and optional scaffolds carry the schema |
| 68 | marker. Markerless legacy artifacts are left on |
| 69 | their prior validation path with a warning; |
| 70 | malformed or unsupported markers are errors. |
| 71 | - PPTX-family inputs are enriched automatically under `analysis/` with |
| 72 | per-deck `<stem>.identity.json` / `<stem>.slide_library.json` plus the shared |
| 73 | multi-deck index `source_profile.json` (`decks[]`). |
| 74 | Multi-deck per project: several PPTX imports each get their own `<stem>.*` |
| 75 | artifacts and a `decks[]` entry; re-importing the same stem replaces its entry. |
| 76 | |
| 77 | ### On-demand page execution view |
| 78 | |
| 79 | `page-context` projects `design_spec.md` and `spec_lock.md` into one compact |
| 80 | current-page view on stdout. The default command is read-only; `--pretty` |
| 81 | changes JSON formatting only. Before projection it revalidates the machine lock |
| 82 | and selected template-root identities; design-brief values are not treated as |
| 83 | a second lock. Slide headings at H3–H6 remain readable by the projector. Normal |
| 84 | generation retains the complete planning artifacts once per valid execution |
| 85 | context and does not invoke this command before every page; use it only for an |
| 86 | explicit diagnostic, routing check, or context-usage measurement. |
| 87 | |
| 88 | Each invocation deliberately includes the bounded `global` anchor set as a |
| 89 | cross-page continuity view, not a color/font allowlist. `lock_source` binds that projection to the current |
| 90 | `spec_lock.md` SHA. `page_context` contains the current §IX brief, rhythm, |
| 91 | resources, and conditional template/chart assignment. `reference_set` contains |
| 92 | `kind`, scoped path, SHA, and `once-per-execution-context` policy for the |
| 93 | project/template Design Specs and selected prototype/chart SVGs. The project |
| 94 | Design Spec additionally carries |
| 95 | `same_context_edit_policy: targeted-readback-and-rebind`: when the current main |
| 96 | agent makes a bounded repair in a valid uncompacted context that preserves |
| 97 | roster/order/identity/communication, it reads back only the exact changed |
| 98 | fragments and validates them before continuing. Fresh, compacted, external, |
| 99 | unknown, or mismatched changes require one complete Design Spec and lock read. |
| 100 | |
| 101 | The deprecated `--bundle` flag remains accepted as a compatibility no-op. It |
| 102 | never appends a Design Spec, prototype SVG, chart SVG, manifest, or text-slot |
| 103 | sidecar to stdout. |
| 104 | |
| 105 | The projection keeps project-specific forbidden rules; universal SVG and icon |
| 106 | rules remain in the always-loaded execution core. Image rows are selected from |
| 107 | the current §IX brief, explicit §VIII page assignments, and mirror prototype |
| 108 | references. When those sources assign images elsewhere but not to the current |
| 109 | page, the view excludes those assigned images. Any still-unassigned legacy |
| 110 | image remains in a compatibility subset; `confirmed-none` is emitted only when |
| 111 | all locked images have a deterministic assignment elsewhere. |
| 112 | |
| 113 | Mirror materialization may publish deterministic |
| 114 | `ppt-master.template-text-slots.v2-min` diagnostics. They are not page-context |
| 115 | or model inputs. The complete SVG remains the sole template authority; checker |
| 116 | and structured export validate output attributes, text/tspan topology, and |
| 117 | referenced-resource hashes against it internally. |
| 118 | |
| 119 | `--record-usage` writes a derived snapshot to |
| 120 | `analysis/page-context/P<NN>.usage.json`. It hashes every input, measures the |
| 121 | exact compact stdout, and records the reference fingerprints. `tiktoken` is |
| 122 | loaded lazily with `o200k_base`; when unavailable, the command still succeeds |
| 123 | and records bytes, characters, hashes, and `tokens: null`. |
| 124 | `page-context-report` summarizes only fresh snapshots and identifies stale or |
| 125 | token-unavailable pages plus unique referenced files. Telemetry may be partial; |
| 126 | it does not measure once-loaded references, source reads, or other session |
| 127 | context. |
| 128 | |
| 129 | Common formats: |
| 130 | - `ppt169` |
| 131 | - `ppt43` |
| 132 | - `xiaohongshu` |
| 133 | - `moments` |
| 134 | - `story` |
| 135 | - `banner` |
| 136 | - `a4` |
| 137 | |
| 138 | Examples: |
| 139 | |
| 140 | ```bash |
| 141 | python3 scripts/project_manager.py init my_presentation --format ppt169 |
| 142 | python3 scripts/project_manager.py scaffold-spec projects/my_presentation_ppt169_20251116 # optional |
| 143 | python3 scripts/project_manager.py scaffold-lock projects/my_presentation_ppt169_20251116 # optional |
| 144 | python3 scripts/project_manager.py validate projects/my_presentation_ppt169_20251116 |
| 145 | python3 scripts/project_manager.py info projects/my_presentation_ppt169_20251116 |
| 146 | python3 scripts/project_manager.py page-context projects/my_presentation_ppt169_20251116 P07 --record-usage |
| 147 | python3 scripts/project_manager.py page-context-report projects/my_presentation_ppt169_20251116 |
| 148 | ``` |
| 149 | |
| 150 | ## `workflow_transcript.py` and `workflow_log.py` |
| 151 | |
| 152 | Project initialization creates `validation/workflow.log` and records its own |
| 153 | milestone. Run later project-scoped Python tools normally: |
| 154 | |
| 155 | ```bash |
| 156 | python3 scripts/<tool>.py <project_path> <args...> |
| 157 | ``` |
| 158 | |
| 159 | Their shared CLI bootstrap discovers the existing project log from the working |
| 160 | directory or command arguments. `workflow_transcript.py` records a UTC command |
| 161 | envelope plus explicit error/failure and receipt/report lines, bounded |
| 162 | warning/OK/stderr samples, limited summary context, and per-run omission counts; |
| 163 | no outer launcher or second Python process is used. It leaves full output on |
| 164 | the original console instead of copying it into the audit log. Commands before |
| 165 | project initialization are not backfilled. Binary-buffer writes, hidden child |
| 166 | output, and detached service activity are not recorded; Confirm UI and live |
| 167 | preview retain detailed output in their component `server.log` files. Their |
| 168 | shared detached-process launcher disables automatic workflow recording in the |
| 169 | long-running child while preserving the short foreground launcher's own record. |
| 170 | |
| 171 | For a Python helper whose arguments and working directory do not identify the |
| 172 | active project, set the routing signal on the same command: |
| 173 | |
| 174 | ```bash |
| 175 | PPT_MASTER_PROJECT_PATH="<project_path>" python3 scripts/<helper>.py <args...> |
| 176 | ``` |
| 177 | |
| 178 | This variable selects only the destination transcript; it does not authorize |
| 179 | the helper to read project artifacts or change its ownership. |
| 180 | |
| 181 | Append a manual note only when an important audit detail has no owning command |
| 182 | output: |
| 183 | |
| 184 | ```bash |
| 185 | python3 scripts/workflow_log.py <project_path> "<material audit detail>" |
| 186 | ``` |
| 187 | |
| 188 | Suitable notes include a material stage handoff or rework reason, a |
| 189 | user-approved exception, or a manual recovery choice. Do not duplicate |
| 190 | artifact contents, routine page progress, or private reasoning. |
| 191 | |
| 192 | The log is append-only audit evidence. It is not a complete console transcript, |
| 193 | stage, quality, or artifact authority and is not read during normal generation |
| 194 | or resume. Inspect it only when the user explicitly requests a run review. An |
| 195 | automatic recording failure emits a warning but does not change the Python |
| 196 | tool's result; an explicit manual entry that cannot be written exits non-zero. |
| 197 | |
| 198 | ## `project_utils.py` |
| 199 | |
| 200 | Shared helper module used by other scripts. |
| 201 | |
| 202 | Typical use: |
| 203 | |
| 204 | ```python |
| 205 | from project_utils import get_project_info, validate_project_structure |
| 206 | ``` |
| 207 | |
| 208 | You can also run it directly for quick checks: |
| 209 | |
| 210 | ```bash |
| 211 | python3 scripts/project_utils.py <project_path> |
| 212 | ``` |
| 213 | |
| 214 | ## `batch_validate.py` |
| 215 | |
| 216 | Batch-check project structure and compliance. |
| 217 | |
| 218 | ```bash |
| 219 | python3 scripts/batch_validate.py examples |
| 220 | python3 scripts/batch_validate.py examples projects |
| 221 | python3 scripts/batch_validate.py --all |
| 222 | python3 scripts/batch_validate.py examples --export |
| 223 | ``` |
| 224 | |
| 225 | Use this for repository-wide health checks before release or cleanup. |
| 226 | |
| 227 | ## `generate_examples_index.py` |
| 228 | |
| 229 | Rebuild `examples/README.md` automatically. |
| 230 | |
| 231 | ```bash |
| 232 | python3 scripts/generate_examples_index.py |
| 233 | python3 scripts/generate_examples_index.py examples |
| 234 | ``` |
| 235 | |
| 236 | ## `pptx_template_import.py` |
| 237 | |
| 238 | Unified PPTX preparation entry point for `/create-template`. |
| 239 | |
| 240 | ```bash |
| 241 | python3 scripts/pptx_template_import.py <template.pptx> |
| 242 | python3 scripts/pptx_template_import.py <template.pptx> -o <output_dir> |
| 243 | python3 scripts/pptx_template_import.py <template.pptx> --manifest-only |
| 244 | python3 scripts/pptx_template_import.py <template.pptx> --skip-manifest |
| 245 | python3 scripts/pptx_template_import.py <template.pptx> --embed-images |
| 246 | python3 scripts/pptx_template_import.py <template.pptx> --inheritance-mode both |
| 247 | python3 scripts/pptx_template_import.py <template.pptx> --inheritance-mode flat |
| 248 | python3 scripts/pptx_template_import.py <template.pptx> --inheritance-mode layered |
| 249 | ``` |
| 250 | |
| 251 | Notes: |
| 252 | - Extracts reusable media assets from `ppt/media/` |
| 253 | - Summarizes slide size, theme colors, font metadata, and per-master theme metadata |
| 254 | - Resolves slide / layout / master relationships from OOXML relationships; every master and layout is included even when no sample slide currently references it |
| 255 | - Generates `manifest.json` (single source of truth for slide size, theme, per-master themes, assets, layouts, masters, placeholders, slides, SVG file paths, and page-type candidates), `native_structure.json`, `source_template.pptx`, `assets/`, `conversion-report.json`, and shape-level SVGs under `svg/` |
| 256 | - **SVG output defaults to the layered authoring source** (`--inheritance-mode layered`): |
| 257 | - `svg/` — layered template view for designers: every master and layout in the deck rendered once as `svg/master_*.svg` / `svg/layout_*.svg` (including ones no sample slide currently references); `svg/slide_NN.svg` contains only that slide's own shapes; `svg/inheritance.json` records parentage plus source-owned `showInheritedShapes` / `showMasterShapes` booleans. |
| 258 | - `svg-flat/` — optional verification view emitted only by `--inheritance-mode both`: each `slide_NN.svg` is self-contained (the effective visible Master/Layout contributions plus Slide-local content painted into one file), so opening any slide in isolation shows the full page like PowerPoint would. Background inheritance remains independent of inherited-shape visibility. Useful for previews, screenshots, and "did this slide actually render correctly" sanity checks. |
| 259 | - `manifest.json` records `svgFile` for slides / layouts / masters, `flatSvgFile` for slides when `svg-flat/` exists, placeholder type / index / geometry / base style, an asset map used by SVG `href` values, and common assets reused through slide / layout / master inheritance. Placeholder semantics keep `subTitle`, `obj`, `media`, and `dt` distinct as `subtitle`, `object`, `media`, and `date`. |
| 260 | - `conversion-report.json` owns tolerant source-recovery diagnostics; it is not a cache or a duplicate of the structural manifests |
| 261 | - Layered slide SVGs keep only the slide's own background; inherited master / layout backgrounds stay in the corresponding master / layout SVGs |
| 262 | - Placeholder guides are intentionally lightweight in `svg/` master / layout files; `svg-flat/` hides those guides and is the visual preview source |
| 263 | - Charts, SmartArt, diagrams, and OLE objects become typed placeholders in `svg/`; `svg-flat/` shows a preview image with a corner badge when one exists, otherwise a visible placeholder. Tables are converted into real SVG content. |
| 264 | - Pass `--inheritance-mode both` to add `svg-flat/`, or `--inheritance-mode flat` for the legacy round-trip view (single self-contained `svg/` tree without master/layout/inheritance files). |
| 265 | - SVG export reads OOXML directly via `pptx_to_svg` — no PowerPoint or Keynote dependency, runs on any platform |
| 266 | - `<image>` elements in `svg/` reference files in `assets/` directly; pass `--embed-images` to inline as data URIs instead |
| 267 | - External linked images and missing media are strict failures. Office vector media such as EMF / WMF are converted to PNG previews when the local toolchain can do so; otherwise the import fails instead of silently dropping content. |
| 268 | - Required in `/create-template` whenever the reference source is `.pptx` |
| 269 | - Default output directory is `<pptx_stem>_template_import/` |
| 270 | - Use `--manifest-only` when you explicitly want only the lightweight import output without slide SVG export |
| 271 | - Intended for template reference preparation, not for final 1:1 template delivery |
| 272 | |
| 273 | Implementation note: |
| 274 | - Internal helpers for this workflow live under `scripts/template_import/` |
| 275 | |
| 276 | ## `error_helper.py` |
| 277 | |
| 278 | Show standardized fixes for common project errors. |
| 279 | |
| 280 | ```bash |
| 281 | python3 scripts/error_helper.py |
| 282 | python3 scripts/error_helper.py missing_readme |
| 283 | python3 scripts/error_helper.py missing_readme project_path=my_project |
| 284 | ``` |
| 285 |