feat(pptx): add ShapeFragment safety system and validation engine#14
Merged
simongdavies merged 1 commit intohyperlight-dev:mainfrom Mar 26, 2026
Merged
Conversation
22719b3 to
a61e3a3
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
This PR introduces a PPTX “safety spec” layer across the builtin PPTX stack by moving slide composition from raw OOXML strings to a branded ShapeFragment type, adding pre-export validation, and updating docs/tests to match the new API expectations.
Changes:
- Introduces branded
ShapeFragment+fragmentsToXml()inha:ooxml-core, and migrates PPTX/table/chart builders to returnShapeFragment. - Tightens slide composition by validating inputs in
pres.addBody()/customSlide()and adding abuildZip()validation pass. - Adds/updates extensive Vitest coverage + updates module hints and the
pptx-expertskill docs for the new rules.
Reviewed changes
Copilot reviewed 13 out of 15 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/pptx-validation.test.ts | Updates assertions to handle ShapeFragment results via toXml() helper. |
| tests/pptx-safety.test.ts | New safety-spec test suite covering fragment branding, addBody rejection, chart caps, notes sanitization, and validation integration. |
| tests/pptx-readability.test.ts | Adjusts readability tests to stringify ShapeFragment outputs consistently. |
| tests/docgen-modules.test.ts | Updates docgen tests to stringify ShapeFragment outputs for XML assertions. |
| skills/pptx-expert/SKILL.md | Documents new ShapeFragment rules + anti-patterns (no +, no chart .toString()). |
| builtin-modules/src/types/ha-modules.d.ts | Updates public typings to reflect ShapeFragment returns/inputs and chart cap constants. |
| builtin-modules/src/shared-state.ts | Formatting-only change to stats() signature layout. |
| builtin-modules/src/pptx.ts | Core migration to ShapeFragment, adds validation engine + notes sanitization, adjusts slide builders and composition APIs. |
| builtin-modules/src/pptx-tables.ts | Tables now return ShapeFragment via _createShapeFragment(). |
| builtin-modules/src/pptx-charts.ts | Adds chart complexity caps; embedChart() returns { shape: ShapeFragment } and makes .toString() throw. |
| builtin-modules/src/ooxml-core.ts | Adds ShapeFragment brand implementation (_createShapeFragment, isShapeFragment, fragmentsToXml). |
| builtin-modules/*.json | Updates module hint metadata/hashes and safety guidance strings. |
- Introduce ShapeFragment branded type to prevent raw XML injection - addBody() now validates ShapeFragment, rejects raw strings - Hide _createShapeFragment from LLM discovery (underscore prefix) - Add validation engine: relationship caps, NaN/Infinity detection, cross-slide duplicate shape ID checks, notes sanitization - Chart complexity caps: 50 charts/deck, 24 series, 100 categories - Deduplicate MAX constants (single source in pptx-charts.ts) - Update hints/prompts and SKILL.md with ShapeFragment API docs - Add 59 safety tests covering all shape builders and edge cases Signed-off-by: Simon Davies <simongdavies@users.noreply.github.com>
a61e3a3 to
54608d0
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements the PPTX Safety Spec — a comprehensive defence layer that prevents LLM-generated code from injecting raw XML into PowerPoint output.
Key Changes
ShapeFragment Branded Type System
ShapeFragment(branded opaque type) instead of raw stringsaddBody()validatesShapeFragmentinput — raw strings are rejected with a helpful error_createShapeFragment()hidden from LLM discovery via underscore prefix_addBodyRaw()for pre-validated XMLValidation Engine
Chart Complexity Caps
pptx-charts.tsTest Coverage
pptx-safety.test.ts:ShapeFragmentaddBodyrejection tests (raw string, string array, fake object, real ShapeFragment)Documentation Updates
skills/pptx-expert/SKILL.mdupdated with new API docs and anti-patternsQuality Gate
just fmt— all code formattedjust lint— zero TypeScript errorsjust test— 1742/1742 tests pass (31 files)