aws-samples/spec-driven-presentation-maker
Spec-driven PowerPoint generation — design what to communicate first, then let the agent build the slides from templates.
Changelog
All notable changes to this project are documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning (while in 0.x, breaking changes may occur in MINOR releases).
Entries before v0.5.0 were written retroactively as summaries.
Unreleased
Added
- Mode entry points are back, as thin dispatchers —
skills/sdpm-vibe,skills/sdpm-specandskills/sdpm-stylelet users pick a mode explicitly (/sdpm-vibeand friends in clients that expose skills as slash commands). v0.5.0 removedskills/because each file had grown a full copy of the mode behavior that then drifted; these are ~20 lines each and contain no behavior text. They callstart_presentation(mode=...)and stop, sopersonas/*.mdremains the only definition. A test fails if any substantial persona line reappears in an entry point. - The repository root is an Agent Plugins 1.0.0 package —
plugin.jsonandmcp.jsonmake it loadable by Kiro (as a Power), Cursor, GitHub Copilot and VS Code without a client-specific installer.mcp.jsonpointsuvat${PLUGIN_ROOT}/servers/localand puts the virtualenv under${PLUGIN_DATA}, because clients copy the plugin into an install cache that may be read-only and is replaced on update. - Codex support —
.codex-plugin/plugin.json, a bundled MCP server definition in.mcp.json, and a repo marketplace at.agents/plugins/marketplace.json, socodex plugin marketplace add ./is enough to install the checkout locally. Codex was previously limited to the Layer 1 CLI path. - Claude Code exposes the same entry points —
.claude-plugin/plugin.jsongainedskills(bumped to 0.3.0). ItsagentsandmcpServersblocks are unchanged. clients/kiro/install.pygained--mode {auto,legacy,power},--kiro-homeand--replace-existing.
Fixed
make install-kirono longer hijacks another checkout's Kiro setup — the MCP registration was re-registered with--forcewhenever the existingsdpmentry pointed elsewhere, and the composer-agent cleanup deliberately deleted configs generated for any checkout. Running the installer from a second clone therefore repointed a working install. Every artifact the installer can write (MCP registration, skill symlinks, legacy composer agent) is now classified as own / stale / foreign / unknown against the current checkout; only own, stale and absent are written, foreign requires--replace-existing, and unknown is never touched. Conflicts exit non-zero with a report instead of succeeding quietly. Behavior change: a leftover pointing at a checkout that still exists is now left alone. One pointing at a moved checkout is still repaired, which was the staleness that cleanup existed for.clients/kiro/install.pyhonoursKIRO_HOME— it hardcoded~/.kiro, so installs into a non-default Kiro profile silently wrote to the wrong one.KIRO_HOMEis now also exported to thekiro-clichild process, sincemcp add --scope globalresolves "global" itself. Powers are global-scope only, so a separate profile is the only way to keep a Kiro CLI install and a Power install from colliding.
0.7.1 - 2026-08-05
Fixed
-
Nested styled-text notation no longer leaks raw tags onto slides — agents sometimes emit
{{bold:{{#FF0000:X}}}}instead of the canonical{{bold,#FF0000:X}}; the parser could not see through nesting and rendered the inner tag as literal text. A flatten pre-pass now normalizes nesting (any depth, partial nesting included) to the comma form, with inner attributes taking priority. Non-nested input is untouched. (#123) -
Builtin template download works from the Web UI — downloading blank-dark / blank-light did nothing: the download used a
fetch()+blob path that requires CORS, and the builtin resource bucket has no CORS configuration (user templates live in a different bucket that has one). Downloads now use the same direct-link navigation as deck PPTX downloads (no CORS involved), the presigned URL carriesContent-Disposition: attachment, and failures show an error toast instead of silently doing nothing. (#281) -
gridtool returns actionable errors and supports%/repeat()— unsupported CSS track syntax (auto,minmax(), previously also%andrepeat()) crashed with an uncaughtValueErrorinstead of an error message the agent can react to.%andrepeat(n, X)are now supported, unsupported syntax returns{"error": ...}naming the offending token, and the supported subset is documented in the tool docstring and grid guide. (#282) -
Live preview: icons relying on even-odd fill no longer render as solid boxes — LibreOffice's SVG export declares
fill-rule="evenodd"only on the root<svg>, which the per-component fragment split dropped, so multi-subpath line-art icons (many AWS resource icons) lost their cutouts and appeared as filled rectangles in the live preview (final PNGs were unaffected). Root inheritable attributes are now propagated onto each fragment. (#288) -
Architecture diagram box auto-height now works on non-16:9 templates and with CJK text — the engine used a fixed 16:9 pt-to-px ratio for text measurement, causing boxes to undersize on 4:3 and other aspect ratios, and did not account for fullwidth (CJK) character width.
analyze_templatenow reportsptPerPxinslide_size, the agent records it indeck.jsonslideSize, andarch_diagramaccepts apt_per_pxparameter for accurate calibration. (#285) -
Remote MCP:
analyze_templatenow includesslide_sizein cached results — the cached template analysis omitted theslide_sizefield, so subsequent calls returned an incomplete response and the agent could not populatedeck.jsonslideSize. (#285) -
Custom templates with non-16:9 slide sizes (4:3 etc.) now lay out correctly — the engine's px coordinate system followed the template width but assumed a fixed height of 1080, so 4:3 decks left the bottom quarter of every slide empty, reported false out-of-bounds warnings, mismatched placeholder coordinates, mis-measured text overflow, and rendered cropped previews in the Web UI. The canvas is now derived from the template's real dimensions (1920 px wide, height following the aspect ratio — 4:3 becomes 1920×1440), and
analyze_template/deck.jsoncarry the canvas size so slide composition uses the full slide. Behaviour for 16:9 templates is unchanged. Known limitation: architecture diagram boxes with an omittedbox.heightcan still under-estimate text height on non-16:9 templates — specifybox.heightexplicitly. (#208) -
Live slide preview: the first few slides now animate — animation was suppressed for 3 seconds after the slides tab appeared, and because a new deck switches to that tab as soon as slides arrive, the first slides were always shown instantly. Suppression is now based on whether the slides already existed when the view mounted, instead of a timer.
-
Live slide preview: the PNG fallback now actually appears — the error state was reset on every 1-second poll, so the fallback was unmounted before it could be seen; a failure to find the render container also marked the slide as permanently processed, leaving an empty black box. Slides with nothing to draw now fall back to the rendered PNG, and the fallback image retries expired signed URLs.
-
AWS: uploaded custom templates now apply to PPTX generation — the remote server's template resolution only searched builtin templates, so a deck referencing an uploaded user template silently fell back to
blank-dark.pptx. Generation now resolves user templates first (same order asanalyze_template), and an unresolvable template name raises an explicit error listing available templates instead of silently using the wrong design. (#206)
0.7.0 - 2026-08-03
Added
- Web UI: live design studio — full visual redesign. Light/Dark/System themes (default dark), 90–125% text scaling, studio color tokens (5 agent work colors, ink for deliverables, red reserved for errors), and a two-voice typography system (Bricolage Grotesque for UI chrome, Fraunces for document surfaces).
- Web UI: artifact-first review surfaces — chat tool activity as a compact agent work ledger; brief as a reviewable contract document with approval state; outline as single-column narrative slides (number rail, slim skeleton cards, enriched slide faces with an evidence/visual/notes spec sheet); art direction as per-slide style cards sharing the same rail grammar, with template and style sections on one alignment axis.
- Outline workflow now asks for
##section headings when a deck has distinct parts, so review surfaces can render the story arc as chapters.
Changed
- Style cover extraction is unified client-side: both
/stylesAPIs (cloud and local) now serve raw style HTML (htmlfield replacescoverHtml), and the style gallery opens previews with zero additional round-trips. - Style previews and thumbnails keep the style author's own canvas background instead of forcing transparency.
Fixed
- Style thumbnails rendered the first slide at 70% (standalone-viewing
body zoomwas not reset in the cloud cover path), leaving gutters around the cover; slides now fill thumbnails edge-to-edge. - Unpainted regions of style slides (rounded corners, frame decorations) showed as opaque white inside the dark UI.
- One deck slide always fits the viewport in the full-size carousel view.
- Prose art direction (
art-direction.md, no style selected) rendered as raw markdown inside an iframe; it is now typeset as a document.
0.6.0 - 2026-08-02
Breaking
- Stateless attachment pipeline —
upload_file,read_uploaded_file, and public MCPpptx_to_jsontools are removed. Useread_attachment(source)andimport_attachment(source, deck_id)instead. The new tools are stateless (no session storage, no uploadId) and accept local paths, S3 keys, or URLs directly. measure_slidesstandalone tool removed — measurement is now triggered exclusively viarun_python(measure_slides=[...]).list_asset_sourcestool removed — callsearch_assets(query="")for the same discovery listing (sources with counts).run_python/run_style_pythonsaveparameter removed — writes always persist; the deprecated flag is no longer accepted.run_pythonfilesparameter removed — useread_attachmentto access uploaded file content, then reference by path in code.- Session restart required — after
git pull, restart all Local Web UI / ACP sessions. The next spawn will pick up the updated agent definitions (agents-sync.tsre-derives fromacp-agents/).make install-kirois only needed for global MCP config cleanup, not for allowlist updates.
Changed
search_assetsnow supports discovery mode: calling with an empty query (query="") returns all asset sources with counts, replacing the removedlist_asset_sourcestool.diff_pptxnow accepts committed import bundle directories as input, enabling the hand-edit sync workflow without the publicpptx_to_jsontool.- Cloud file attachments use
POST /attachments/presign+ direct S3 PUT; Local Web UI usesPOST /api/attachments. The[Attached:...]marker format is now[Attached:{"v":1,"name":"...","source":"..."}].
Fixed
- Cloud and local ACP deck agents now expose
arch_diagram, as required by the composition workflow, so architecture, system, and flow diagrams use automatic routing and crossing minimization instead of silently falling back to manual placement. - Attachment presigned PUTs now use Signature Version 4 — S3 rejects the
conditional write (
If-None-Match) with legacy SigV2 URLs, which broke all browser uploads in some regions (e.g. ap-northeast-1). - The Web UI no longer sends a message when an attachment upload fails: input and attachments are kept for retry and the actual error (e.g. quota exceeded) is shown instead of a generic failure.
- Per-user raw attachment caps recalibrated for internal/team deployments
(1000 objects / 50GB, overridable via
ATTACHMENT_MAX_OBJECTS/ATTACHMENT_MAX_BYTES), and S3 lifecycle rules are prefix-only so attachment objects from pre-0.6 releases (which carry nosdpm-classtag) also expire. Deployments upgrading from the old upload pipeline should purge leftoveruploads/objects — they otherwise count toward the quota. servers/remote/constraints.txtregenerated viamake lock;cachetools/protobufare pinned byaws-opentelemetry-distroand are now excluded from Dependabot bumps until the distro itself is upgraded.
0.5.3 - 2026-08-01
Changed
- Kiro CLI: composer sub-agents are now self-spawned —
make install-kirono longer generates~/.kiro/agents/sdpm-composer.json; the orchestrating agent spawns composer workers itself and pulls the composer behavior throughstart_presentation(mode="composer"). Upgrading from v0.5.2 or earlier, re-runmake install-kiroonce: it removes the legacy generated agent file (only if unmodified; a customized file is left in place with a warning). start_presentationnow acceptsmode="single"(one agent handles dialogue and composition end-to-end), making every persona reachable through the port.
0.5.2 - 2026-08-01
Changed
run_pythonpersistence semantics unified: file writes now always persist — thesaveflag is deprecated and ignored (silent data loss when omittingsave=Trueon Cloud is no longer possible). The deck's PPTX artifact refreshes automatically whenever the deck changes;measure_slidesremains the trigger for the expensive verification pass (render, text overflow measurement, previews). Cloud sandbox write-back is now diff-based (changed/new files only), preventing a stale sandbox copy from overwriting newer S3 writes
Fixed
- Cloud: superseded PPTX artifacts are now deleted after each refresh — the
automatic artifact refresh no longer accumulates orphaned objects in S3
(
update_deckreturns previous values viaUPDATED_OLD)
0.5.1 - 2026-07-31
Added
make doctor— diagnoses local setup (uv / LibreOffice / poppler, checkout path anchors) with a moved-checkout hintmake smoke— boots the local MCP server over real stdio and verifies template/persona resolution (also runs in CI)- GitHub Releases are now created automatically on tag push (notes extracted from this changelog)
Fixed
- Cloud agent output-token limit: model profiles now set an explicit
max_tokens(Claude 32768, others 8192) — Bedrock's small default truncated long single-call outputs (e.g. writingspecs/brief.mdfrom a long article) and killed the turn with a generic error.MaxTokensReachedExceptionis also classified now (max_output) so the Web UI shows an actionable message instead of "something went wrong".
Changed
- L4 agent personas unified: the cloud agent (Strands) now fetches mode
behavior from
personas/*.mdthrough the samestart_presentation(mode=...)port as every other client, instead of carrying its own copies inagent/prompts/role/. Duplicated role/workflow prompt files were removed; only transport-specific wiring (attachment wire format,compose_slidesreport format) remains inagent/prompts/. Prompt changes now touch onlypersonas/for all layers. - Internal API move:
sdpm.engine.diff.diff_report/load_slides_json_or_pptxmoved tosdpm.api(dependency-rule fix;engine.diffnow exposes the purediff_slides(base, edit)). These were internal APIs — update imports if you consumed them directly.
0.5.0 - 2026-07-31
Breaking architecture cleanup. No changes to the slide JSON schema — existing decks and cloud data keep working. See the migration guide for upgrade steps.
Changed (breaking)
- Directory layout:
skill/→sdpm/,mcp-local/→servers/local/,mcp-server/→servers/remote/,agents/→clients/claude-code/agents/ - Engine split: the
sdpmpackage is now organised as two peer subpackages —sdpm.engine(json ↔ pptx) andsdpm.knowledge(references / assets) - Skill files removed: mode behavior now lives in
personas/*.mdand is served to any MCP client via the newstart_presentation(mode=...)tool. Claude Code plugin no longer installs skills; Kiro installer no longer symlinks skill directories - Single tool contract: every MCP tool is defined once in
sdpm.tools; both servers bind the same functions (local: 24 tools, remote: 22 tools) - Docs: English docs are canonical; Japanese docs reduced to README and getting-started
Added
start_presentation(mode=...)MCP tool — serves vibe / spec / style / composer / single personas to any MCP clientSDPM_SKILL_ROOTenvironment override for path anchors (used by the remote Docker image, gateway integrations)- Migration guide:
docs/en/migration-v0.5.md
Fixed
- Pinned
mcp>=1.28.1,<2across local server, remote server, and agent — mcp 2.0.0 removedmcp.server.fastmcpand crashed fresh container builds
0.4.0 - 2026-07-30
- Kiro CLI support: installer, composer agent, skill dispatch (#207)
- PPTX import: bring existing decks into the agent + edit flow, hand-edit sync
via
diff_pptx(#149, #215, #220) - Template notes (built-in and local), template picker in Art Direction pane (#203, #204)
- User-local styles, assets, config, and template directories with cross-platform paths (#96, #99)
- Per-user model switching via Settings (#100)
0.3.x - 2026-05-12 .. 2026-06-02
- 0.3.0: composer web fetch, image aspect-ratio fit, SVG color fixes (#139, #146)
- 0.3.1–0.3.8: stability fixes (template upload in local mode, template
analysis via
uv run), workshop content, one-click deploy buttons (#167, #168, #170, #171)
0.2.x - 2026-05-01 .. 2026-05-11
- 0.2.0: agent separation, parallel slide generation, model config refactor (#71)
- 0.2.1: fontSize token discipline check, Python 3.14 compatibility fixes (#133, #136)
0.1.0 - 2026-05-01
- Initial release: spec-driven slide generation (Engine json ↔ pptx, CLI, local/remote MCP servers, Strands Agent, React Web UI, CDK stacks)