Vertical-slice plan with wave ordering: - Wave 1 (P1): consolidate-docs (single -marp.md, delete plain .md, speaker notes + talking points as HTML comments). - Wave 2 (P2): restore-clean-style (theme:default + inline style, retire nova-sp-theme.css from render, benefit callout .benefit class). - Wave 3 (P3 + P4, parallel): inline-images + python-pptx-generator (new scripts, zero deck-markdown overlap) || trim-wordcount + remove 'penetrate' (deck markdown, zero script overlap). - Wave 4 (P5): ci-tests-readme (workflows, tests, README — depends on all above). - Wave 5 (P6): final review + audit + milestone ship. Tags on v1.22.x line: v1.22.0 (P0) -> v1.22.1..v1.22.5 (P1-P5) -> v1.22.6 (P6 final = milestone release). ---ci--- project: acdl phase: 0 milestone: v1.23 status: plan ---/ci---
19 KiB
PLAN — v1.23 (Nova Deck Cleanup & Python PPTX)
NFR milestone (docs/render/test only). Tags on v1.22.x line: v1.22.0 (P0) → v1.22.1..v1.22.5 (P1–P5) → v1.22.6 (P6 final = milestone release). 13 requirements (REQ-263..275), 7 phases.
Wave Ordering
Wave 1 (P1): consolidate-docs (edits -marp.md, deletes plain .md)
↓
Wave 2 (P2): restore-clean-style (edits -marp.md frontmatter +
↓ benefit callouts; edits render_slides.sh; retires
↓ nova-sp-theme.css from render)
↓
Wave 3 (P3 + P4, parallel):
P3: inline-images + python-pptx-generator (new scripts +
render_slides.sh step + pyproject; ZERO deck-markdown overlap)
P4: trim-wordcount + remove "penetrate" (edits -marp.md +
talking-points.md; ZERO script overlap with P3)
↓
Wave 4 (P5): ci-tests-readme (workflows, tests, README —
depends on all above)
↓
Wave 5 (P6): final-review-ship (review + audit + milestone ship)
Rationale (C8, conf 0.85): P1→P2 is serial (both edit -marp.md;
P1 establishes the single doc, P2 edits its frontmatter). P3+P4
parallelize: P3 owns scripts/inline_images.py + scripts/render_pptx.py
scripts/render_slides.sh+pyproject.toml+scripts/attach_release_asset.py; P4 ownsdocs/presentations/nova-autonomous-cloud-delivery-marp.md+*-talking-points.md— zero file overlap. P5 depends on all (tests assert the final state). P6 is the final gate.
Phase P1 — consolidate-docs (tag v1.22.1)
Requirements: REQ-263, REQ-264
Persona: lead-developer (deck markdown + .ciagent)
Branch: phase/01-consolidate-docs
Tasks
-
Fold speaker notes into the deck (REQ-263):
- Read
docs/presentations/nova-autonomous-cloud-delivery.md(the plain source-of-truth, 747 lines). - For each
## Slide N — Titlesection, extract the> **Speaker notes:**and> **Transition:**blockquote blocks. - In
docs/presentations/nova-autonomous-cloud-delivery-marp.md, insert<!-- Speaker notes: ... -->(and<!-- Transition: ... -->where present) as a Marp HTML comment immediately after the slide's content, before the next---separator. - The slide's visible content is unchanged.
- Read
-
Fold talking points into the deck (REQ-264):
- Read
docs/presentations/nova-autonomous-cloud-delivery-talking-points.md(145 lines, 3-6 bullets per slide + key takeaway). - For each slide, insert
<!-- Talking points: ... -->(the bullets joined) as a Marp HTML comment after the speaker-notes comment. - Update the
talking-points.mdheader (line 4): change "distilled from the source of truth (nova-autonomous-cloud-delivery.md)" → "mirrors the<!-- Talking points: -->comments innova-autonomous-cloud-delivery-marp.md(the sole source of truth)".
- Read
-
Delete the plain
.md(REQ-263):git rm docs/presentations/nova-autonomous-cloud-delivery.md.
-
Verify (must-have):
bash scripts/render_slides.shstill renders (22 slides: title + 20 main + 1 appendix — unchanged).- HTML slide count unchanged (test_marp_deck_slide_count passes).
grep -c "<!-- Speaker notes:" nova-autonomous-cloud-delivery-marp.mdreturns ≥20 (one per main slide).grep -c "<!-- Talking points:" ...returns ≥20.- The plain
.mdno longer exists. talking-points.mdstill exists with updated header.
Phase P2 — restore-clean-style (tag v1.22.2)
Requirements: REQ-265, REQ-266, REQ-267
Persona: lead-developer (deck markdown + CSS) + backend-engineer
(render_slides.sh)
Branch: phase/02-restore-clean-style
Depends on: P1 (consolidated doc)
Tasks
-
Revert frontmatter to
theme: default+ inlinestyle:(REQ-265):- In
nova-autonomous-cloud-delivery-marp.mdfrontmatter:theme: nova-sp→theme: default.- Add
style: |block porting the S&P visual language (from the research-extracted reference CSS +nova-sp-theme.css):style: | section { font-family: "Akkurat Pro", "Helvetica Neue", "Arial", sans-serif; font-size: 22px; color: #1B1B1B; padding: 48px 56px 40px; overflow: auto; } h1 { color: #D6002A; font-size: 34px; margin-bottom: 0.3em; } h2 { color: #D6002A; font-size: 26px; margin-bottom: 0.2em; } h3 { color: #D6002A; font-size: 22px; margin-bottom: 0.2em; } section.title { background: #1B1B1B; color: #fff; border-top: 8px solid #D6002A; } section.title h1, section.title h2 { color: #fff; } section.title header, section.title footer { display: none; } table { font-size: 18px; width: 100%; border-collapse: collapse; } th { background: #F0F0F0; border-bottom: 2px solid #D6002A; padding: 4px 8px; text-align: left; } td { border-bottom: 1px solid #F0F0F0; padding: 4px 8px; } blockquote { border-left: 4px solid #D6002A; color: #2E2E2E; font-size: 20px; padding-left: 12px; } pre { background: #1B1B1B; color: #fff; border-radius: 4px; padding: 12px; font-size: 16px; } code { background: #F0F0F0; color: #1B1B1B; border-radius: 2px; padding: 1px 4px; font-size: 18px; } pre code { background: transparent; color: inherit; } img { display: block; margin: 0 auto; max-width: 100%; max-height: 380px; object-fit: contain; } strong { color: #D6002A; } .benefit { margin-top: 0.6em; padding-top: 0.4em; border-top: 1px solid #D6002A; color: #1B1B1B; font-size: 20px; font-style: italic; } section.title .benefit { color: #fff; } @media print { section { overflow: hidden; } }
- Keep:
paginate: true,size: 16x9,footer:, noheader:.
- In
-
Retire
nova-sp-theme.cssfrom render (REQ-266):- Add header comment to
docs/presentations/assets/nova-sp-theme.css: "Retained as the S&P visual-language reference for future styling work. The live deck uses Marpdefaulttheme + inlinestyle:block in the -marp.md frontmatter. Not loaded at render time." scripts/render_slides.sh: removeTHEME_CSSvariable usage and the--theme "$THEME_CSS"argument from both marp-cli invocations (lines 70, 73). Keep--allow-local-files.
- Add header comment to
-
Restyle benefit callouts (REQ-267):
- In
nova-autonomous-cloud-delivery-marp.md, convert every**Benefit:** textline →<div class="benefit">text</div>. - This applies to all 20 main slides + appendix (21 callouts).
- The
**Benefit:**prefix is removed; the.benefitclass (defined in the inlinestyle:block) provides the visual emphasis.
- In
-
Verify (must-have):
bash scripts/render_slides.shrenders; HTML opens with S&P red h1s, black title slide with red top border, benefit callouts with red top-rule + italic.grep -c "theme: default" nova-autonomous-cloud-delivery-marp.mdreturns 1.grep -c "theme: nova-sp" ...returns 0.grep -c 'class="benefit"' ...returns ≥21.grep -c "\\*\\*Benefit:\\*\\*" ...returns 0.nova-sp-theme.cssstill exists (reference).grep "Not loaded at render" nova-sp-theme.cssreturns a match.
Phase P3 — inline-images + python-pptx-generator (tag v1.22.3)
Requirements: REQ-268, REQ-269, REQ-270
Persona: backend-engineer (scripts + pyproject) + lead-developer
(deck structure consultation)
Branch: phase/03-inline-images-pptx
Depends on: P2 (render_slides.sh --theme drop)
Parallel with: P4 (zero file overlap — P3 owns scripts, P4 owns
deck markdown)
Tasks
-
scripts/inline_images.py(REQ-268):- Stdlib only (
base64,re,mimetypes,sys,pathlib). - Reads the rendered HTML path (argv[1]).
- Finds all
<img ... src="(assets/...)" ...>(relative paths only; skip absolute/http(s)://). - Reads each referenced file, replaces
srcwithdata:image/<mime>;base64,<base64>. - MIME by extension:
.png→image/png,.svg→image/svg+xml,.jpg/.jpeg→image/jpeg,.gif→image/gif; fallbackapplication/octet-stream. - Writes HTML back in place; prints count inlined to stderr.
- Usage:
python scripts/inline_images.py <html-path>.
- Stdlib only (
-
scripts/render_pptx.py(REQ-269):- Dependency:
python-pptx>=0.6.23(import at module load; if absent, print "pip install -e .[slides]" and exit 1). - Parses
nova-autonomous-cloud-delivery-marp.md:- Frontmatter (skip YAML between
---markers). ---slide separators.#/##headings → slide title.<!-- ... -->HTML comments → skipped (speaker notes/talking points).-/*bullets → bullet list.**bold lead**(first paragraph after title) → bold lead.> blockquote→ blockquote-styled paragraph.```lang ... ```→ code block (monospace text frame).→add_picture(embedded in ppt/media/).| ... |tables → native PPTX table (add_table).<div class="benefit">text</div>→ benefit callout (italic text frame with red top border accent).
- Frontmatter (skip YAML between
- Produces 16:9 PPTX (
prs.slide_width = Inches(13.333),prs.slide_height = Inches(7.5)):- Title slide: black background, red top bar
(
MSO_SHAPE.RECTANGLE, fill#D6002A, height ~0.4"), white H1 (Arial — Akkurat Pro not installed; PowerPoint does OS substitution). - Content slides: blank layout; red H2 title text box at top;
bold lead paragraph (red
**strong**); bullets; blockquote (indent + red left accent via thin rectangle); embedded PNGs (centered, scaled to fit content area); native tables (grey header, red bottom border); benefit callout (italic, red top-rule accent). - Font: "Akkurat Pro" (PowerPoint falls back to OS default if absent — acceptable; the HTML is the pixel-perfect artifact).
- Title slide: black background, red top bar
(
- Output:
docs/presentations/nova-autonomous-cloud-delivery-python.pptx. - Usage:
python scripts/render_pptx.py [deck-name](defaults tonova-autonomous-cloud-delivery).
- Dependency:
-
pyproject.toml(REQ-269):- Add to
[project.optional-dependencies]:slides = ["python-pptx>=0.6.23"]
- Add to
-
scripts/render_slides.sh(REQ-268, REQ-270):- After Step 2 (MARP render), add Step 3: inline images into HTML.
- Add Step 4: python-pptx render →
*-python.pptx. - Update Step 5 (stage): add
*-python.pptx. - Final order: Step 1 mermaid → Step 2 MARP HTML+PPTX → Step 3 inline images → Step 4 python-pptx → Step 5 stage.
-
scripts/attach_release_asset.py(REQ-270):- Extend to accept multiple asset paths (both
.pptx+-python.pptx). Backward-compatible (single arg still works; or accept a list). MARP PPTX is the primary attachment (first).
- Extend to accept multiple asset paths (both
-
Verify (must-have):
bash scripts/render_slides.shproduces 3 artifacts:.html(with inlined base64 images),.pptx(MARP),-python.pptx(structured).- Open the HTML from a different directory (no
assets/folder) — images display. - Open
-python.pptx— 16:9, title slide black with red bar, content slides with red titles + bullets + tables + images. grep -c 'src="assets/' nova-autonomous-cloud-delivery.htmlreturns 0 (all inlined).grep -c 'data:image' nova-autonomous-cloud-delivery.htmlreturns ≥2 (the deck's 2 images).
Phase P4 — trim-wordcount (tag v1.22.4)
Requirements: REQ-271, REQ-272
Persona: lead-developer (deck markdown + talking-points)
Branch: phase/04-trim-wordcount
Depends on: P1 (consolidated doc)
Parallel with: P3 (zero file overlap)
Tasks
-
Targeted word-count trim (REQ-271) on ~8 verbose slides:
- Slide 1 (The Problem): cut the "Every hour a developer spends..." restatement paragraph (lines 29-ish); tighten bullet sub-clauses. Target ~25% reduction.
- Slide 5 (Scope): collapse bullets 1 + 3 (both say "PDLC is upstream") to 3 bullets.
- Slide 7 (Pipeline): condense bullet 1's pipe-chain; deduplicate bullet 3's "Wiz on the plan" repetition.
- Slide 8 (Decision Ledger): tighten the "AI decisions" bullet from a paragraph to one sentence.
- Slide 13 (Cost & ROI): collapse the "Honest caveat" bullet to one line.
- Slide 14 (Deferred): cut the preamble paragraph to one line.
- Slide 20 (Recap + Ask): split the 60-word ask run-on into two short sentences.
- Appendix A1: tighten the benefit callout to one line.
- Tables (slides 6, 9, 10, 15, 16, 17, A1) untouched.
- Short slides (2, 3, 4, 11, 12, 18, 19) untouched.
- Benefit callouts (all slides): already restyled in P2; here just tighten each to one short sentence (preserve the spirit).
-
Remove "penetrate" (REQ-272):
- Slide 5 line 73: "Nova never penetrates it. Integration is through one validated contract." → "Integration is through one validated contract." (The "PDLC is upstream" bullet already conveys scope; slide 4 Anti-Goals explicitly excludes the PDLC.)
nova-autonomous-cloud-delivery-talking-points.md:40: "Nova never penetrates it" → match slide 5's trimmed wording.- The plain
.mdis already deleted (P1), so its:165"penetrate" line is gone.
-
Verify (must-have):
grep -ri penetrat docs/presentations/returns nothing (text files: .md, .html).- Slide count unchanged (22).
bash scripts/render_slides.shrenders; no broken slides.- Word count of trimmed slides reduced ~20-30% (manual spot-check).
Phase P5 — ci-tests-readme (tag v1.22.5)
Requirements: REQ-273, REQ-274, REQ-275
Persona: backend-engineer (CI + tests) + lead-developer (README)
Branch: phase/05-ci-tests-readme
Depends on: P1, P2, P3, P4 (asserts the final state)
Tasks
-
CI workflows (REQ-273):
workflows-src/slides.yml: addsetup-pythonstep +pip install -e .[slides](orpip install python-pptx>=0.6.23). Pin@marp-team/marp-cli@4.5.0+@mermaid-js/mermaid-cli@11.16.0(match render_slides.sh). Updategit addcommit list: add*-python.pptx.- Sync to
.github/workflows/slides.yml+.gitea/workflows/slides.ymlviascripts/sync_workflows.py.
-
Tests (REQ-274):
tests/test_slides_pipeline.pyupdates (per research finding 5):- Delete/invert
test_marp_deck_not_using_default_theme(we now USEtheme: default). test_marp_deck_uses_sp_theme→ rewrite to assert the inlinestyle:block has S&P properties (#D6002A,#1B1B1B,section.title).test_theme_css_*trio → retarget from standalone CSS file to inlinestyle:block (or delete if the inline-style assertion covers it).test_html_embeds_theme→ assert literal#D6002A(not--sp-red).test_source_md_*→ delete (plain.mdis gone).test_render_slides_pins_cli_versions→ keep, extend to assertpython-pptxis inpyproject.toml.test_no_penetrate_term(new): assertgrep -ri penetrat docs/presentations/returns nothing.test_html_images_inlined_as_base64(new): assert rendered HTML has zerosrc="assets/references and ≥1data:image/png;base64per image the deck uses.test_python_pptx_exists(new): assertnova-autonomous-cloud-delivery-python.pptxexists + is a valid zip (PPTX signature).test_nova_sp_theme_css_retained_as_reference(new): assert the file exists + has the "Not loaded at render" comment.test_benefit_callouts_use_class(new): assert-marp.mdhasclass="benefit"and no**Benefit:**prefix.
- Delete/invert
- New
tests/test_pptx_generator.py:test_slide_count: python PPTX slide count == 22 (title + 20 + appendix).test_title_slide_colors: title slide background black, red bar present.test_expected_slide_titles: spot-check 3-5 slide titles match the markdown.test_table_rendering: a slide with a table (e.g., RACI) has a native PPTX table shape.test_image_embedding: a slide with an image has a picture shape.test_benefit_callout_present: ≥1 slide has italic benefit text.
-
README (REQ-275):
- Rewrite
docs/presentations/README.mdprocess section:- 3-step process (was 4): 1) author
*-marp.md(sole source of truth, with<!-- Speaker notes: -->+<!-- Talking points: -->comments); 2) render HTML + dual PPTX (render_slides.sh: mermaid → MARP HTML+PPTX → inline images → python-pptx); 3) talking points (mirrored from deck comments). - Drop the plain
.mdrow from the decks table. - Add
inline_images.py+render_pptx.py+-python.pptxrows to the tooling section. - Note
nova-sp-theme.cssretired (reference only; inlinestyle:is the live styling). - Document the dual-PPTX output (MARP image-of-slide primary + python structured for comparison/editing).
- 3-step process (was 4): 1) author
- Rewrite
-
Verify (must-have):
pytest tests/test_slides_pipeline.py tests/test_pptx_generator.pyall pass.- CI workflow YAML is valid.
- README reflects the new pipeline.
Phase P6 — final-review-ship (Final Phase, tag v1.22.6)
Requirements: all (REQ-263..275)
Persona: lead-developer (review coordination)
Branch: phase/06-final-review-ship
Depends on: P1–P5
Tasks
-
Multi-persona code review (
ciagent-review):- Review all changes in
milestone/v1.23-deck-cleanup-python-pptx. - Auto-apply P0 fixes; flag P1+ for post-hoc review.
- If P1+ found: fix in this phase.
- Review all changes in
-
Audit (
ciagent-audit):- Reconstruction test: git log matches
.ciagent/files. .ciagent/file discipline + branch hygiene + commit discipline.
- Reconstruction test: git log matches
-
Ship (
ciagent-ship— milestone ship):- Merge
phase/06→milestone/v1.23-deck-cleanup-python-pptx. - Merge
milestone/v1.23-deck-cleanup-python-pptx→main. - Tag
v1.22.6(final patch = milestone release). - Create release with full milestone summary (all phases, all 13 requirements).
- Attach both PPTX files (MARP + python) to the release.
- Delete all milestone branches (local + remote). Tags preserve history.
- Merge
-
Complete the milestone:
- Update
REQUIREMENTS.md— mark all v1.23 requirements complete. - Update
ROADMAP.md— mark v1.23 complete. - Commit:
docs(milestone): complete v1.23 — Nova Deck Cleanup & Python PPTX.
- Update
Versioning
- NFR milestone → progressive patches on v1.22.x line.
v1.22.0(P0) →v1.22.1..v1.22.5(P1–P5) →v1.22.6(P6 final = milestone release). No separate minor tag.
Risk Mitigations (from RESEARCH)
- Default theme padding — explicitly set
section { padding: 48px 56px 40px }in the inlinestyle:block (don't rely on default's56px 64pxwhich doesn't reserve header/footer space). - python-pptx font fallback — use "Akkurat Pro" in the PPTX (PowerPoint does OS substitution); the HTML is the pixel-perfect artifact, the python PPTX is for comparison/editing.
- Marp version drift — marp-cli pinned at 4.5.0 (already).
- Speaker notes stripped — Marp strips HTML comments from rendered
slides but they persist in the source
-marp.md(acceptable; they're for authors, not the audience). test_html_embeds_theme— update to assert literal#D6002A(not--sp-red).