diff --git a/.ciagent/CHECKPOINT.json b/.ciagent/CHECKPOINT.json index 6d53ae7..c01c8bc 100644 --- a/.ciagent/CHECKPOINT.json +++ b/.ciagent/CHECKPOINT.json @@ -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 } \ No newline at end of file diff --git a/.ciagent/PLAN.md b/.ciagent/PLAN.md index a380082..04f9752 100644 --- a/.ciagent/PLAN.md +++ b/.ciagent/PLAN.md @@ -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 `` (and `` - 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 `` (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 `` 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 "` 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`). - - `