docs(P00): create phase plans — v1.24 (4 phases, 4 waves)
---ci--- project: acdl phase: 0 milestone: v1.24 status: plan ---/ci---
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
{
|
||||
"phase": 0,
|
||||
"stage": "research",
|
||||
"stage": "plan",
|
||||
"milestone": "v1.24",
|
||||
"phase_role": "pre_execution",
|
||||
"attempts": 0,
|
||||
"updated_at": "2026-08-12T02:10:00Z",
|
||||
"updated_at": "2026-08-12T02:15:00Z",
|
||||
"project": "acdl",
|
||||
"milestone_complete": false,
|
||||
"tag_line": "v1.23.x",
|
||||
"requirements": ["REQ-276","REQ-277","REQ-278","REQ-279","REQ-280","REQ-281","REQ-282","REQ-283","REQ-284","REQ-285","REQ-286","REQ-287","REQ-288","REQ-289","REQ-290"],
|
||||
"decisions": ["D-201","D-202","D-203","D-204","D-205","D-206","D-207","D-208"]
|
||||
"phases": ["P1:consumer-guide-fixes","P2:env-transition-detect-and-destroy","P3:env-transition-tests","P4:final-review-ship"],
|
||||
"waves": 4
|
||||
}
|
||||
+169
-467
@@ -1,478 +1,180 @@
|
||||
# PLAN — v1.23 (Nova Deck Cleanup & Python PPTX)
|
||||
# PLAN — v1.24 (Consumer Guide Accuracy & Env-Promotion Lifecycle Enforcement)
|
||||
|
||||
> NFR milestone (docs/render/test only). Tags on v1.22.x line:
|
||||
> v1.22.0 (P0) → v1.22.1..v1.22.4 (P1–P4) → v1.22.5 (P5 final = milestone
|
||||
> release). 13 requirements (REQ-263..275), 6 phases.
|
||||
>
|
||||
> **GRILL revisions applied** (G-001..G-004, conf 0.78-0.85):
|
||||
> - G-001: "penetrate" purge covers the whole repo (`docs/` +
|
||||
> `.ciagent/`), not just `docs/presentations/`.
|
||||
> - G-002: P3→P4 serialized (not parallel) — P4's parser depends on
|
||||
> P3's stable `render_slides.sh`; P4's trimmed deck is what P3b's
|
||||
> parser consumes.
|
||||
> - G-003: P3 split into P3a (inline_images + render_slides.sh +
|
||||
> pyproject — low-risk) + P3b (render_pptx.py + parser +
|
||||
> attach_release_asset.py — high-risk, isolated).
|
||||
> - G-004: P5+P6 merged — NFR docs milestone; dedicated review/ship
|
||||
> phase is ceremonial overhead. P5 absorbs review/audit/ship. Tag
|
||||
> v1.22.5 = milestone release.
|
||||
> Feature milestone (one `feat` phase: env-transition destroy enforcement;
|
||||
> the rest are `fix`/`docs`/`test`). Tags on the **v1.23.x** line:
|
||||
> v1.23.0 (P0) → v1.23.1 (P1) → v1.23.2 (P2) → v1.23.3 (P3) → v1.23.4 (P4
|
||||
> final = milestone release). 15 requirements (REQ-276..290), 4 phases +
|
||||
> P0 pre-execution.
|
||||
|
||||
## Wave Ordering
|
||||
## Phase breakdown
|
||||
|
||||
### Phase P1 — consumer-guide-fixes (Wave 1, lead-developer)
|
||||
|
||||
**Type:** `docs` + `fix` + `test` (consumer guide accuracy + guide test updates)
|
||||
|
||||
**Requirements:** REQ-276, REQ-277, REQ-278, REQ-279, REQ-280, REQ-281, REQ-290
|
||||
|
||||
**Must-haves:**
|
||||
- `docs/consumer-guide.md` Step 3 contract fields table corrected (REQ-276)
|
||||
- `docs/consumer-guide.md` Step 4 caller consistent with Step 2 (REQ-277)
|
||||
- `docs/consumer-guide.md` Step 5 stage 8 "(dev only)" → "(autonomous in dev; higher environments apply after HITL attestation)" (REQ-278)
|
||||
- `docs/consumer-guide.md` Step 8 rewritten with destroy-then-rebuild semantics + cross-ref to Shape B (REQ-279)
|
||||
- `docs/consumer-guide.md` Per-env section gains Shape B lead sentence (REQ-280)
|
||||
- `docs/consumer-guide.md` Reference table `@v1.19` wording corrected (REQ-281)
|
||||
- `tests/test_consumer_guide_per_env_section.py` updated: rename `test_consumer_guide_states_no_field_editing` → `test_consumer_guide_documents_both_promotion_shapes`; add `test_consumer_guide_documents_destroy_on_env_change` (REQ-290)
|
||||
|
||||
**Vertical slice:** A reader of `docs/consumer-guide.md` can promote via
|
||||
either shape (A: edit environment + platform destroys prior; B: per-env
|
||||
caller workflow) without contradiction. The guide's field table, caller
|
||||
examples, and stage descriptions match the actual schema and platform
|
||||
behavior. All consumer-guide tests pass.
|
||||
|
||||
**Files touched:**
|
||||
- `docs/consumer-guide.md`
|
||||
- `tests/test_consumer_guide_per_env_section.py`
|
||||
|
||||
**Verification:** `pytest tests/test_consumer_guide_per_env_section.py -v`
|
||||
(all 7 tests pass). Manual read of `docs/consumer-guide.md` end-to-end
|
||||
for internal consistency.
|
||||
|
||||
---
|
||||
|
||||
### Phase P2 — env-transition-detect-and-destroy (Wave 2, backend-engineer)
|
||||
|
||||
**Type:** `feat` (new platform feature: env-transition detect-and-destroy)
|
||||
|
||||
**Requirements:** REQ-282, REQ-283, REQ-284, REQ-285, REQ-286, REQ-287
|
||||
|
||||
**Must-haves:**
|
||||
- `core/env_transition.py` new module: `detect_prior_env()` + `record_applied_env()` with boto3 DynamoDB queries (REQ-282, REQ-283)
|
||||
- `scripts/run_platform.sh` Step 0b: environment-transition check — detect prior env, re-resolve with `environment_override=prior_env` + `deletion_protection=false`, `terraform init -reconfigure` + `terraform destroy -auto-approve` against prior state key, emit `nova.env.destroyed` evidence event, fail closed on destroy failure (REQ-284)
|
||||
- `scripts/run_platform.sh` records applied env after successful apply (REQ-285)
|
||||
- `.github/workflows/deploy.yml` passes `NOVA_CONSUMER_REPO=${{ github.repository }}` to `run_platform.sh` (REQ-286)
|
||||
- `adapters/terraform/adapter.py` state-key block gains doc comment (REQ-287)
|
||||
|
||||
**Vertical slice:** When a consumer changes `environment:` on a stable
|
||||
`contract.id`, the pipeline detects the prior env from DynamoDB, destroys
|
||||
the prior env's Terraform state (with `deletion_protection=false`), emits
|
||||
an evidence event, and only then applies the new env. If the destroy
|
||||
fails, the pipeline exits non-zero (no orphan path). If no prior env
|
||||
exists (first deploy or Shape B), the pipeline proceeds normally.
|
||||
|
||||
**Files touched:**
|
||||
- `core/env_transition.py` (NEW)
|
||||
- `scripts/run_platform.sh`
|
||||
- `.github/workflows/deploy.yml`
|
||||
- `adapters/terraform/adapter.py` (doc comment only)
|
||||
|
||||
**Verification:** `python3 -m py_compile core/env_transition.py`.
|
||||
`pytest tests/test_pipeline.py tests/test_deploy_workflow_env_input.py -v`
|
||||
(existing tests still pass). The new tests in P3 validate the behavior.
|
||||
|
||||
**Key implementation notes (from RESEARCH §5 pitfalls):**
|
||||
1. The destroy step must re-resolve with `environment_override=prior_env`
|
||||
so the emitted TF matches the prior env's resources.
|
||||
2. `terraform init -reconfigure` is required when switching state backends.
|
||||
3. `deletion_protection: false` must be injected (same as decommission
|
||||
Step 2 in `scripts/run_decommission.sh:34-37`) or `prevent_destroy`
|
||||
blocks the destroy.
|
||||
4. DynamoDB unreachable in local/CI → log warning + return `None`
|
||||
(conservative, no prior env assumed).
|
||||
5. The state key `spike/{id}/{env}/terraform.tfstate` stays as-is — the
|
||||
env segment is what lets the destroy target the prior env.
|
||||
|
||||
---
|
||||
|
||||
### Phase P3 — env-transition-tests (Wave 3, backend-engineer + lead-developer)
|
||||
|
||||
**Type:** `test` (new test coverage for env-transition + pipeline integration)
|
||||
|
||||
**Requirements:** REQ-288, REQ-289
|
||||
|
||||
**Must-haves:**
|
||||
- `tests/test_env_transition.py` (NEW): `detect_prior_env` returns `None` when no record; returns prior env when record differs; returns `None` when record matches; `record_applied_env` writes record. Uses moto for DynamoDB (REQ-288)
|
||||
- `tests/test_run_platform_env_transition.py` (NEW): asserts `run_platform.sh` has Step 0b; calls `env_transition.py detect`; calls `terraform destroy` on prior env; fails closed on destroy failure; records applied env after success (REQ-289)
|
||||
|
||||
**Vertical slice:** The env-transition detect-and-destroy behavior is
|
||||
fully covered by automated tests. The DynamoDB query logic is unit-tested
|
||||
with moto. The pipeline orchestration is tested via shell-text assertions
|
||||
(pattern from `tests/test_pipeline.py:79-95`).
|
||||
|
||||
**Files touched:**
|
||||
- `tests/test_env_transition.py` (NEW)
|
||||
- `tests/test_run_platform_env_transition.py` (NEW)
|
||||
|
||||
**Verification:** `pytest tests/test_env_transition.py tests/test_run_platform_env_transition.py -v` (all new tests pass). Full suite: `pytest tests/ -k "env_transition or consumer_guide or pipeline or adapter or deploy_workflow" -v`.
|
||||
|
||||
---
|
||||
|
||||
### Phase P4 — final-review-ship (Wave 4, lead-developer)
|
||||
|
||||
**Type:** `docs` (review + audit + milestone ship)
|
||||
|
||||
**Requirements:** (none new — milestone completion)
|
||||
|
||||
**Must-haves:**
|
||||
- Multi-persona code review across P1-P3 changes (ci-code-reviewer)
|
||||
- Project health audit (ci-doc-verifier + ci-audit)
|
||||
- Milestone ship: tag v1.23.4 (final phase patch = milestone release), merge to main, Gitea release
|
||||
- Update REQUIREMENTS.md traceability (all REQ-276..290 → complete)
|
||||
- Update ROADMAP.md (v1.24 → complete)
|
||||
|
||||
---
|
||||
|
||||
## 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 (P3a): inline-images (inline_images.py + render_slides.sh
|
||||
↓ step + pyproject — low-risk, mechanical)
|
||||
↓
|
||||
Wave 4 (P3b): python-pptx-generator (render_pptx.py + parser +
|
||||
↓ attach_release_asset.py — high-risk, isolated)
|
||||
↓
|
||||
Wave 5 (P4): trim-wordcount + remove "penetrate" (edits -marp.md +
|
||||
↓ talking-points.md + docs/scope.md + docs/vision.md +
|
||||
↓ .ciagent/*.md "penetrate" purge)
|
||||
↓
|
||||
Wave 6 (P5): ci-tests-readme + review + audit + milestone ship
|
||||
(merged P5+P6 per G-004)
|
||||
Wave 1 (P1): consumer-guide-fixes [lead-developer]
|
||||
↓
|
||||
Wave 2 (P2): env-transition-detect-and-destroy [backend-engineer]
|
||||
↓
|
||||
Wave 3 (P3): env-transition-tests [backend-engineer + lead-developer]
|
||||
↓
|
||||
Wave 4 (P4): final-review-ship [lead-developer]
|
||||
```
|
||||
|
||||
**Rationale (C8 revised by G-002/G-003/G-004):** P1→P2 serial (both
|
||||
edit `-marp.md`). P3a→P3b serial (P3b's parser benefits from P3a's
|
||||
stable `render_slides.sh`). P4 serial after P3b (P4's trimmed deck is
|
||||
what P3b's parser must handle; P4's verify render depends on P3a's
|
||||
stable script). P5 final (merged review/audit/ship per G-004 — NFR docs
|
||||
milestone doesn't warrant a dedicated P6).
|
||||
**Dependencies:**
|
||||
- P2 depends on P1: the Step 8 rewrite in P1 documents the destroy
|
||||
semantics that P2 implements. Doing P1 first ensures the docs and code
|
||||
land in the right order (docs describe the intended behavior, then code
|
||||
implements it).
|
||||
- P3 depends on P2: the tests validate the env-transition module and
|
||||
pipeline Step 0b that P2 creates.
|
||||
- P4 depends on P1+P2+P3: the final review covers all changes.
|
||||
|
||||
---
|
||||
**Parallelization:** P1 and P2 could run in parallel (different
|
||||
territories: docs vs code), but the wave ordering is sequential for
|
||||
safety — if P1's Step 8 rewrite reveals a design issue, P2's
|
||||
implementation should follow the corrected design. With
|
||||
`parallelization.enabled=true` and `min_plans_for_parallel=2`, the
|
||||
orchestrator *could* run them concurrently; however, the dependency
|
||||
(P2 follows P1's design) makes sequential the safer choice. P3 must
|
||||
follow P2 (tests validate the code). P4 must follow all.
|
||||
|
||||
## Phase P1 — consolidate-docs (tag v1.22.1)
|
||||
## Requirement → Phase mapping
|
||||
|
||||
**Requirements:** REQ-263, REQ-264
|
||||
**Persona:** lead-developer (deck markdown + .ciagent)
|
||||
**Branch:** `phase/01-consolidate-docs`
|
||||
| REQ | Phase | Type | Description |
|
||||
|-----|-------|------|-------------|
|
||||
| REQ-276 | P1 | docs | Contract fields table corrected |
|
||||
| REQ-277 | P1 | docs | Step 4 caller consistent with Step 2 |
|
||||
| REQ-278 | P1 | docs | Step 5 stage 8 "dev only" corrected |
|
||||
| REQ-279 | P1 | docs | Step 8 rewritten with destroy semantics |
|
||||
| REQ-280 | P1 | docs | Per-env section Shape B lead sentence |
|
||||
| REQ-281 | P1 | docs | Reference table @v1.19 wording corrected |
|
||||
| REQ-282 | P2 | feat | env_transition.py detect_prior_env() |
|
||||
| REQ-283 | P2 | feat | env_transition.py record_applied_env() |
|
||||
| REQ-284 | P2 | feat | run_platform.sh Step 0b detect-and-destroy |
|
||||
| REQ-285 | P2 | feat | run_platform.sh records applied env |
|
||||
| REQ-286 | P2 | feat | deploy.yml passes NOVA_CONSUMER_REPO |
|
||||
| REQ-287 | P2 | docs | adapter.py state-key doc comment |
|
||||
| REQ-288 | P3 | test | test_env_transition.py |
|
||||
| REQ-289 | P3 | test | test_run_platform_env_transition.py |
|
||||
| REQ-290 | P1 | test | consumer guide test updates |
|
||||
|
||||
### Tasks
|
||||
## Tag plan
|
||||
|
||||
1. **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 — Title` section, 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.
|
||||
|
||||
2. **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.md` header (line 4): change "distilled
|
||||
from the source of truth (`nova-autonomous-cloud-delivery.md`)" →
|
||||
"mirrors the `<!-- Talking points: -->` comments in
|
||||
`nova-autonomous-cloud-delivery-marp.md` (the sole source of
|
||||
truth)".
|
||||
|
||||
3. **Delete the plain `.md`** (REQ-263):
|
||||
- `git rm docs/presentations/nova-autonomous-cloud-delivery.md`.
|
||||
|
||||
4. **Verify** (must-have):
|
||||
- `bash scripts/render_slides.sh` still 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.md`
|
||||
returns ≥20 (one per main slide).
|
||||
- `grep -c "<!-- Talking points:" ...` returns ≥20.
|
||||
- The plain `.md` no longer exists.
|
||||
- `talking-points.md` still 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
|
||||
|
||||
1. **Revert frontmatter to `theme: default` + inline `style:`** (REQ-265):
|
||||
- In `nova-autonomous-cloud-delivery-marp.md` frontmatter:
|
||||
- `theme: nova-sp` → `theme: default`.
|
||||
- Add `style: |` block porting the S&P visual language (from the
|
||||
research-extracted reference CSS + `nova-sp-theme.css`):
|
||||
```yaml
|
||||
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:`, no `header:`.
|
||||
|
||||
2. **Retire `nova-sp-theme.css` from 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 Marp `default` theme + inline `style:`
|
||||
block in the -marp.md frontmatter. Not loaded at render time."
|
||||
- `scripts/render_slides.sh`: remove `THEME_CSS` variable usage and
|
||||
the `--theme "$THEME_CSS"` argument from both marp-cli invocations
|
||||
(lines 70, 73). Keep `--allow-local-files`.
|
||||
|
||||
3. **Restyle benefit callouts** (REQ-267):
|
||||
- In `nova-autonomous-cloud-delivery-marp.md`, convert every
|
||||
`**Benefit:** text` line → `<div class="benefit">text</div>`.
|
||||
- This applies to all 20 main slides + appendix (21 callouts).
|
||||
- The `**Benefit:**` prefix is removed; the `.benefit` class (defined
|
||||
in the inline `style:` block) provides the visual emphasis.
|
||||
|
||||
4. **Verify** (must-have):
|
||||
- `bash scripts/render_slides.sh` renders; 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.md`
|
||||
returns 1.
|
||||
- `grep -c "theme: nova-sp" ...` returns 0.
|
||||
- `grep -c 'class="benefit"' ...` returns ≥21.
|
||||
- `grep -c "\\*\\*Benefit:\\*\\*" ...` returns 0.
|
||||
- `nova-sp-theme.css` still exists (reference).
|
||||
- `grep "Not loaded at render" nova-sp-theme.css` returns a match.
|
||||
|
||||
---
|
||||
|
||||
## Phase P3a — inline-images (tag v1.22.3)
|
||||
|
||||
**Requirements:** REQ-268
|
||||
**Persona:** backend-engineer (scripts + pyproject)
|
||||
**Branch:** `phase/03a-inline-images`
|
||||
**Depends on:** P2 (render_slides.sh `--theme` drop)
|
||||
|
||||
### Tasks
|
||||
|
||||
1. **`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 `src` with
|
||||
`data:image/<mime>;base64,<base64>`.
|
||||
- MIME by extension: `.png`→`image/png`, `.svg`→`image/svg+xml`,
|
||||
`.jpg/.jpeg`→`image/jpeg`, `.gif`→`image/gif`; fallback
|
||||
`application/octet-stream`.
|
||||
- Writes HTML back in place; prints count inlined to stderr.
|
||||
- Usage: `python scripts/inline_images.py <html-path>`.
|
||||
|
||||
2. **`scripts/render_slides.sh`** (REQ-268):
|
||||
- After Step 2 (MARP render), add Step 3: inline images into HTML
|
||||
(`python scripts/inline_images.py "$HTML"`).
|
||||
- Update Step 5 (stage): no change yet (python-pptx is P3b).
|
||||
- Order now: Step 1 mermaid → Step 2 MARP HTML+PPTX → Step 3 inline
|
||||
images → Step 4 stage.
|
||||
|
||||
3. **Verify** (must-have):
|
||||
- `bash scripts/render_slides.sh` produces `.html` with inlined
|
||||
base64 images.
|
||||
- Open the HTML from a different directory (no `assets/` folder) —
|
||||
images display.
|
||||
- `grep -c 'src="assets/' nova-autonomous-cloud-delivery.html`
|
||||
returns 0 (all inlined).
|
||||
- `grep -c 'data:image' nova-autonomous-cloud-delivery.html`
|
||||
returns ≥2 (the deck's 2 images).
|
||||
|
||||
---
|
||||
|
||||
## Phase P3b — python-pptx-generator (tag v1.22.4)
|
||||
|
||||
**Requirements:** REQ-269, REQ-270
|
||||
**Persona:** backend-engineer (scripts + pyproject) + lead-developer
|
||||
(deck structure consultation)
|
||||
**Branch:** `phase/03b-python-pptx`
|
||||
**Depends on:** P3a (stable render_slides.sh with inline step)
|
||||
|
||||
### Tasks
|
||||
|
||||
1. **`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).
|
||||
- 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).
|
||||
- Output: `docs/presentations/nova-autonomous-cloud-delivery-python.pptx`.
|
||||
- Usage: `python scripts/render_pptx.py [deck-name]` (defaults to
|
||||
`nova-autonomous-cloud-delivery`).
|
||||
|
||||
2. **`pyproject.toml`** (REQ-269):
|
||||
- Add to `[project.optional-dependencies]`:
|
||||
```toml
|
||||
slides = ["python-pptx>=0.6.23"]
|
||||
```
|
||||
|
||||
3. **`scripts/render_slides.sh`** (REQ-270):
|
||||
- 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.
|
||||
|
||||
4. **`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).
|
||||
|
||||
5. **Verify** (must-have):
|
||||
- `bash scripts/render_slides.sh` produces 3 artifacts: `.html`
|
||||
(with inlined base64 images), `.pptx` (MARP), `-python.pptx`
|
||||
(structured).
|
||||
- Open `-python.pptx` — 16:9, title slide black with red bar, content
|
||||
slides with red titles + bullets + tables + images.
|
||||
- `-python.pptx` is a valid zip (PPTX signature).
|
||||
|
||||
---
|
||||
|
||||
## Phase P4 — trim-wordcount + repo-wide "penetrate" purge (tag v1.22.5)
|
||||
|
||||
**Requirements:** REQ-271, REQ-272
|
||||
**Persona:** lead-developer (deck markdown + talking-points + docs +
|
||||
.ciagent)
|
||||
**Branch:** `phase/04-trim-wordcount`
|
||||
**Depends on:** P3b (stable render_slides.sh; trimmed deck is what P3b's
|
||||
parser already handles — P4 does not break P3b's parser because the
|
||||
parser handles the pre-trim structure and P4 trims prose, not
|
||||
structure)
|
||||
|
||||
### Tasks
|
||||
|
||||
1. **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).
|
||||
|
||||
2. **Remove "penetrate" — repo-wide purge** (REQ-272, G-001):
|
||||
- `docs/presentations/nova-autonomous-cloud-delivery-marp.md` slide 5:
|
||||
"Nova never penetrates it. Integration is through one validated
|
||||
contract." → "Integration is through one validated contract."
|
||||
- `docs/presentations/nova-autonomous-cloud-delivery-talking-points.md:40`:
|
||||
"Nova never penetrates it" → match slide 5's trimmed wording.
|
||||
- `docs/scope.md`: reword "Nova never penetrates the PDLC" →
|
||||
"Nova never reaches into the PDLC" (or restructure — the scope
|
||||
boundary is already established by "downstream of PDLC").
|
||||
- `docs/vision.md`: reword "It does not penetrate upstream product or
|
||||
software development lifecycles" → "It does not reach into upstream
|
||||
product or software development lifecycles".
|
||||
- `.ciagent/PROJECT.md`: reword the 3 "penetrate" occurrences in the
|
||||
Core Tenets #2 + Scope sections.
|
||||
- Note: `.ciagent/RESEARCH.md` + `.ciagent/PLAN.md` meta-references
|
||||
to "penetrate removal" are NOT purged (they describe the removal;
|
||||
purging them would erase the decision history).
|
||||
|
||||
3. **Verify** (must-have):
|
||||
- `grep -ri penetrat docs/ .ciagent/PROJECT.md .ciagent/CLARIFY.md`
|
||||
returns nothing (the term is gone from all audience-facing +
|
||||
project-spec docs; RESEARCH.md/PLAN.md/GRILL.md meta-references
|
||||
are exempt as decision-history).
|
||||
- Slide count unchanged (22).
|
||||
- `bash scripts/render_slides.sh` renders; no broken slides.
|
||||
- Word count of trimmed slides reduced ~20-30% (manual spot-check).
|
||||
|
||||
---
|
||||
|
||||
## Phase P5 — ci-tests-readme + review + audit + ship (Final Phase, tag v1.22.6)
|
||||
|
||||
**Requirements:** REQ-273, REQ-274, REQ-275 (+ review/audit/ship for all REQ-263..275)
|
||||
**Persona:** backend-engineer (CI + tests) + lead-developer (README + review coordination)
|
||||
**Branch:** `phase/05-ci-tests-readme-ship`
|
||||
**Depends on:** P1, P2, P3a, P3b, P4 (asserts the final state; merged
|
||||
P5+P6 per G-004 — NFR docs milestone doesn't warrant a dedicated
|
||||
review/ship phase)
|
||||
|
||||
### Tasks
|
||||
|
||||
1. **CI workflows** (REQ-273):
|
||||
- `workflows-src/slides.yml`: add `setup-python` step + `pip install
|
||||
-e .[slides]` (or `pip 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). Update `git add` commit list: add
|
||||
`*-python.pptx`.
|
||||
- Sync to `.github/workflows/slides.yml` + `.gitea/workflows/slides.yml`
|
||||
via `scripts/sync_workflows.py`.
|
||||
|
||||
2. **Tests** (REQ-274):
|
||||
- `tests/test_slides_pipeline.py` updates (per research finding 5):
|
||||
- Delete/invert `test_marp_deck_not_using_default_theme` (we now
|
||||
USE `theme: default`).
|
||||
- `test_marp_deck_uses_sp_theme` → rewrite to assert the inline
|
||||
`style:` block has S&P properties (`#D6002A`, `#1B1B1B`,
|
||||
`section.title`).
|
||||
- `test_theme_css_*` trio → retarget from standalone CSS file to
|
||||
inline `style:` 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 `.md` is gone).
|
||||
- `test_render_slides_pins_cli_versions` → keep, extend to assert
|
||||
`python-pptx` is in `pyproject.toml`.
|
||||
- `test_no_penetrate_term` (new, G-001): assert
|
||||
`grep -ri penetrat docs/ .ciagent/PROJECT.md .ciagent/CLARIFY.md`
|
||||
returns nothing (RESEARCH.md/PLAN.md/GRILL.md meta-references
|
||||
exempt as decision-history).
|
||||
- `test_html_images_inlined_as_base64` (new): assert rendered
|
||||
HTML has zero `src="assets/` references and ≥1
|
||||
`data:image/png;base64` per image the deck uses.
|
||||
- `test_python_pptx_exists` (new): assert
|
||||
`nova-autonomous-cloud-delivery-python.pptx` exists + 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.md` has
|
||||
`class="benefit"` and no `**Benefit:**` prefix.
|
||||
- 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.
|
||||
|
||||
3. **README** (REQ-275):
|
||||
- Rewrite `docs/presentations/README.md` process 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 `.md` row from the decks table.
|
||||
- Add `inline_images.py` + `render_pptx.py` + `-python.pptx` rows
|
||||
to the tooling section.
|
||||
- Note `nova-sp-theme.css` retired (reference only; inline `style:`
|
||||
is the live styling).
|
||||
- Document the dual-PPTX output (MARP image-of-slide primary +
|
||||
python structured for comparison/editing).
|
||||
|
||||
4. **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.
|
||||
|
||||
5. **Audit** (`ciagent-audit`):
|
||||
- Reconstruction test: git log matches `.ciagent/` files.
|
||||
- `.ciagent/` file discipline + branch hygiene + commit discipline.
|
||||
|
||||
6. **Ship** (`ciagent-ship` — milestone ship):
|
||||
- Merge `phase/05` → `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.
|
||||
|
||||
7. **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`.
|
||||
|
||||
8. **Verify** (must-have):
|
||||
- `pytest tests/test_slides_pipeline.py tests/test_pptx_generator.py`
|
||||
all pass.
|
||||
- CI workflow YAML is valid.
|
||||
- README reflects the new pipeline.
|
||||
|
||||
---
|
||||
|
||||
## Versioning
|
||||
|
||||
- NFR milestone → progressive patches on v1.22.x line.
|
||||
- `v1.22.0` (P0) → `v1.22.1` (P1) → `v1.22.2` (P2) → `v1.22.3` (P3a) →
|
||||
`v1.22.4` (P3b) → `v1.22.5` (P4) → `v1.22.6` (P5 final = milestone
|
||||
release). No separate minor tag. 6 phases total (was 7; P5+P6 merged
|
||||
per G-004, P3 split into P3a+P3b per G-003).
|
||||
|
||||
## Risk Mitigations (from RESEARCH + GRILL)
|
||||
|
||||
1. **Default theme padding** — explicitly set
|
||||
`section { padding: 48px 56px 40px }` in the inline `style:` block
|
||||
(don't rely on default's `56px 64px` which doesn't reserve
|
||||
header/footer space).
|
||||
2. **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.
|
||||
3. **Marp version drift** — marp-cli pinned at 4.5.0 (already).
|
||||
4. **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).
|
||||
5. **`test_html_embeds_theme`** — update to assert literal `#D6002A`
|
||||
(not `--sp-red`).
|
||||
6. **P3b parser overflow** (G-003) — isolated in its own phase so a
|
||||
parser setback doesn't block inline-images (P3a) or trim (P4).
|
||||
7. **"penetrate" purge scope** (G-001) — repo-wide, not just
|
||||
`docs/presentations/`; RESEARCH.md/PLAN.md/GRILL.md exempt as
|
||||
decision-history.
|
||||
- P0 (this phase): `v1.23.0` — pre-execution patch
|
||||
- P1: `v1.23.1` — consumer guide fixes
|
||||
- P2: `v1.23.2` — env-transition detect-and-destroy
|
||||
- P3: `v1.23.3` — env-transition tests
|
||||
- P4: `v1.23.4` — final review + ship = **milestone release**
|
||||
Reference in New Issue
Block a user