Files
acdl/.ciagent/ROADMAP.md
T
Jon Chery 787a6490a5
acdl-ci / Lint (push) Successful in 10s
acdl-ci / Platform check-only (offline) (push) Successful in 23s
acdl-ci / Test (push) Successful in 5m53s
docs(audit): v1.15 post-milestone audit — PASS (rebrand header fixes + 6 checks)
Audit of v1.15-Nova milestone: reconstruction PASS (27 commits, 20 with
ci blocks, 7 merges per convention, state matches checkpoint). File
discipline: 10 auto-fixed rebrand-completeness gaps — 9 .ciagent/*.md
headers still said ACDL (PROJECT/REQUIREMENTS/ROADMAP/RESEARCH/AUDIT/
REVIEW/COST/IAM_POLICY/CAPABILITY_INVENTORY → Nova) + config.json
projects[].name → Nova. Active v1.15 sections already Nova; historical
v1.1-v1.14 narratives left as-is. Branch hygiene PASS (6 phases + 1
milestone all merged, 0 orphans). Commit discipline PASS (0 non-merge
commits without ci blocks, 0 unresolved escalations). 6 audit checks
all PASS. Verdict: PASS.

---ci---
project: acdl
phase: 5
milestone: v1.15
status: complete
phase_role: final
audit: pass
---/ci---
2026-07-30 14:37:58 +00:00

125 KiB
Raw Blame History

Nova — Roadmap

Overview

  • v1.0 (demo): complete — tag v1.1.0, 2026-07-21. All 5 phases shipped + audited PASS.
  • v1.1 (complete): architecture finalization + v1 spike. 5 phases (0610). Tag v1.2.0, 2026-07-21. All 5 phases shipped + verified; review READY TO SHIP (0 P0); audit CLEAN. Gitea release id 202.
  • v1.2 (complete): platform hardening + first real consumer deployment. 6 phases (1116). Tag v1.3.0, 2026-07-21. All 6 phases shipped + verified; review READY TO SHIP (1 P0 operator action, 1 P1 deferred); audit CLEAN.
  • v1.3 (complete): module documentation + thin-composition removal. The L2 composition layer is removed; module READMEs are built out. Tag v1.3.2.
  • v1.4 (complete): central pipeline contract + shell reproducibility + output streaming. A declarative pipeline contract (schemas/pipeline.schema.json + pipelines/ci.yaml) binds the Gitea and GitHub workflows to a single source of truth. scripts/run_ci.sh mirrors the CI pipeline locally. scripts/run_platform.sh streams terraform/checkov output by default.
  • v1.5 (complete, tag v1.5.0): consumer happy path + zero-trust docs + reusable deploy workflow. README rewritten so the consumer model is unambiguous (consumer owns only contract + app code; the rest is the platform source). Platform-flow + consumer-guide diagrams converted to mermaid. Legacy surface + implementation nomenclature removed from docs. Credentials section rewritten for zero-trust OIDC + ABAC (with a static-key override + daily rotation). A generic docs/CONSUMER_GUIDE.md (all L2 modules, versioned uses:, consumer-scoped prereqs, run-time platform fetch) replaces the module-specific guide. A byte-identical reusable deploy.yml workflow (Gitea + GitHub) implements pipelines/deploy.yaml and is invoked by consumer repos via a versioned tag.
  • v1.6 (complete, tag v1.6.0): consumer-facing docs restructure + terminology normalization + environments concept. docs/ becomes a Jekyll-style GitHub Pages site. acdl_platform/ is renamed to core/. L2 → "modules", L1 → "primitives", "composition" → "pattern" in prose. README restructured: Features + Roadmap (no internal status), repository roles restated (consumer = app code + contracts + CI definitions), mermaid fixed (visible text, security-checks + infrastructure-apply stages, no tool names), credentials section minus go-gitea/waivers. Platform-managed environments concept + a minimal onboarding scaffold. .ciagent/ + .gitea/ references removed from all consumer-facing docs.
  • v1.7 (complete, tag v1.7.0): production platform + contract ingestion + pipeline maturation. Rename static-assetsstatic-assets (D-048 — incl. .ciagent/ historical narrative). Author cloudfront + waf primitives; augment static-assets to a production-ready S3 + CloudFront (OAC) + WAF stack (D-049). Tagging-standard enforcement (Checkov custom rule, D-043 closure, D-054). Wiz adapter stub (D-052) + Kyverno K8s-native adapter (D-053). Platform Lambda + DynamoDB acdl-contracts table for contract ingestion (D-051) + cross-account IAM. Deploy outputs via SSM SecureString + GitHub PR comment (D-050). Uniform error reporting via the Lambda report_error action → GitHub issue on the platform repo (D-055); Gitea excluded. Stage comments after every successful pipeline stage. Three platform pipelines (platform-test unit+integration, primitives-plan, patterns-plan). Release job with semver + MAJOR.MINOR/MAJOR tag maintenance (D-057). uses:/ref: bumped to @v1.6; floating v1.6 + v1 tags created in Phase 22. Remove the legacy consumer-repos directory (a v1.2 artifact, removed in v1.7); add validated per-module examples (modules/<name>/examples/, D-058) including a new RDS primitive demonstrating multi-engine variation (D-059).
  • v1.8 (complete, tag v1.8.0): P1 remediation + uptime monitoring + engineering standards + encryption/deletion-protection by default + decommission alias + path documentation. Clears 8 pending P1 issues (P1-3..P1-9 + S1). Adds per-stack CMK + encryption-by-default for all primitives. Adds deletion-protection-by-default + L2 feature flag. Adds uptime-kuma primitive (ECS Fargate, deployed by default after L2, separate state, feature flag, alert channels). Adds decommission mode (2-step pipeline with HITL SRE gates + CMDB-validated change request). Adds modules/STANDARDS.md (L1+L2 authoring + review standards). Adds schemas/README.md, pipelines/README.md, adapters/README.md.
  • v1.9.1 (complete, tag v1.9.1): leadership presentation decks. Two leadership-facing presentation decks (How the Platform Works + The Developer Experience) for senior leadership (CTO, Head of Cloud, Head of Infrastructure, Head of DevOps). Each deck has a full markdown source of truth (with speaker notes + mermaid diagrams) and a lean Marp deck (no speaker notes, embedded PNG diagrams). A README documents the 3-step slide creation process (full markdown → Marp synthesis → PPTX export). Docs-only NFR patch.
  • v1.9.2 (complete, tag v1.9.2): S&P Global Energy theme for presentation decks. Applies the S&P Global Energy brand visual identity (red-core #D6002A, grey-90 #1B1B1B, Akkurat Pro font) to both Marp decks. Title headers changed to full platform name. Footer 'Confidential' → 'Internal'. Title slide subtitle removed. Last DX slide renamed to 'The Desired Outcomes'. Docs-only NFR patch.
  • v1.9.3 (complete, tag v1.9.3): rendered presentation decks. HTML renderings of both Marp decks committed to docs/presentations/ (self-contained, base64-embedded images, S&P Global Energy theme). PPTX files uploaded to the Gitea release as downloadable attachments. README updated to document HTML as committed artifacts and PPTX as release attachments. Docs-only NFR patch.
  • v1.9.4 (complete, tag v1.9.4): presentation slide updates + complete removal of a specific compliance framework from all docs. Title slide redesigned (deck title as H1, 'Agentic Cloud Delivery Platform' as subtitle). DX deck: removed Local Reproducibility slide, redesigned Safe Promotion Path with side-by-side layout, 'an agent' → 'an AI agent', What a Developer Does diagram floated right. All references to that framework removed from 25 files (presentations, module READMEs, docs). Compliance lists now: GDPR, SOX, SOC2, DORA. HTML re-rendered. PPTX uploaded to release. Docs-only NFR patch.
  • v1.9.5 (complete, tag v1.9.5): vision gaps + Testing badge + engine terminology + agentic tags + CR format. 9 requirements: (1) DX closing slide strengthened with 'infrastructure as a utility' vision bullet; (2) 'moving' → 'promoting'; (3) added red tape + scalability bullets to Problem slide; (4) Roadmap slide redesigned side-by-side; (5) new 'What This Platform Is — and Isn't' slide (PW deck 16 slides); (6) 'shipped'/'Available today' → 'Testing' (0 consumer adoption); (7) global 'substrate' → 'engine' (88 matches, 30+ files); (8) 'forge' → 'VCS' in presentation files only; (9) new Agentic badge (purple) on agentic features. CR format changed to CHG0678912. HTML re-rendered. PPTX uploaded to release. Docs-only NFR patch.
  • v1.9.6 (complete, tag v1.9.6): consolidate both Marp decks to 10 high-impact slides. PW deck 16 → 10 (merged Problem+North Star+Anti-goals, merged Policy+Secure by Default, merged Audit+HITL, folded Observability/Environments/Portability into existing slides, added Vision Realized closing). DX deck 15 → 10 (merged What Dev Does+Contract+No Platform Code, merged Feedback+Deploy Outputs, merged Promotion+Rising Bar, cut Citizen Developer standalone, kept Versioned Releases/Onboarding/Decommission). Removed '5-line YAML' claim from both decks. Source markdown unchanged. Docs-only NFR patch.
  • v1.9.7 (complete, tag v1.9.7): talking points files + 4-step process. Created two talking points markdown files (one per deck) distilling the source of truth into presenter-ready cues indexed by the Marp deck's 10-slide structure. Each file has 3-6 talking point bullets + key takeaway per slide. README updated from 3-step to 4-step process (added Step 4: talking points). Directory layout, checklist, and decks table updated. Docs-only NFR patch.
  • v1.9.8 (complete, tag v1.9.8): full presentation rework — scope, story arc, visuals, appendix. 6 new mermaid diagrams (scope boundary x2, confidence signal, attestation flow, promotion journey, road to north star). Both decks restructured to 10 main + 6 appendix slides. NEW scope slide clarifying ACDL is infrastructure only. Story beat lines on every slide. Contract examples fixed (image: removed, infra inputs instead). QA attestation reclassified (Design tested → Planned). Confidence signal + attestation flow + promotion journey visuals added. Road to the North Star phased timeline in appendix. Full Testing vs. Planned inventory + glossary in appendix. Source markdown + talking points + README all updated. Docs-only NFR patch. Last deck-polish phase before the v1.10 deck-freeze.
  • v1.10 (complete, tag v1.10.0): pipeline regression fix + capability re-verification + verified-reality rewrite. The v1.9.1v1.9.8 deck work is superseded-by-reverification: the decks presented advertised capability as current without disclosing that the platform had decayed (7 adapter defects prevented terraform init/validate/plan against live AWS). v1.10 re-verified every advertised capability, fixed all 7 defects in-sweep (D-090: no cap), and rewrote PROJECT/ROADMAP/decks to match verified reality. Decks unfrozen only after Phase 55 lands. See the v1.10 section below for the 4-phase breakdown.
  • v1.10.1 (complete, tag v1.10.1): post-v1.10 NFR patch — adversarial grill review (12 challenges, 10 binding decisions, 2 escalations: G-005 risks, G-008 budget), 4-layer verify gate (PASS), multi-persona code review (1 P1 auto-fixed: mis-citation PROJECT.md:6 → PROJECT.md:487). ACDL reclassified as OSS reference implementation (G-003). Docs-only; 518 tests pass; regression gate 16/16 Verified. Gitea release id 236.
  • v1.10.2 (complete, tag v1.10.2): contract surface redesign + rename + .yml repo-wide + deck polish. Breaking contract schema change: new top-level fields id/name/infrastructure; dropped uses:/module:/inputs:. All 44 .yaml.yml. Code review: 3 P0 auto-fixed, 2 P1+ flagged. 494 tests pass. Gitea release id 237.
  • v1.11 (complete, tag v1.11.0): RESTART — stateless adapter + pipeline-driven module lifecycle testing. Closes G-005 (CAP-017..022 deploy-unverified) and G-008 (no cost docs) via a corrected architecture, not the failed v1.11 first attempt (which produced 4 drifted VPCs, ran terraform apply from Python, and had no module lifecycle tests). The restart branches off v1.10.2 and rebuilds v1.11 on three corrections: (1) the terraform adapter becomes a stateless assembler — each L1 module ships a real terraform/ module dir (variables/locals/main/outputs) owning its resource shape, nested blocks, and defaults; the adapter deletes TYPE_MAP/INPUT_MAP/OUTPUT_MAP and all 39 type-specific branches, becoming a ~80-line assembler that emits module "x" { source = ... } blocks; (2) lifecycle is owned by terraform via the shell orchestrator (run_platform.sh --apply/--destroy), never by Python — verify_deploy_microservice.py is deleted; (3) testing is pipeline-driven — a modules-lifecycle pipeline (Gitea + GitHub, byte-identical) matrix-runs each L1 module's examples/{simple,complex}.yml contracts through apply→modify→destroy against live AWS; no per-module Python. A single platform VPC (terraform/platform) is shared by all stacks via data source — no per-contract VPC. State keys are deterministic and env-aware (spike/{id}/{env}/terraform.tfstate), stable across lifecycle changes. 13 phases (P56aP65). See the v1.11 section below for the phase breakdown.
  • v1.12 (complete, tag v1.12.0): Presentation Refinement — the leadership decks synced to the v1.11-verified reality (22/22 Verified, stateless adapter, lifecycle pipeline, cost figures, pre-mortem). Includes the CAP-013 adapter dedup fix + 2 probe fixes (required to make the deck claims true) + the ACDL_LIFECYCLE_MODE CI flag (lifecycle tests default to plan-only, full on override). 6 phases (P66P70). See the v1.12 section below.
  • v1.13 (complete, tag v1.13.0): Presentation Polish — both leadership decks polished across all 4 pipeline layers (source .md → -marp.md → .html → -talking-points.md). Action headlines replace category names; story-arc restructure (Intro ~10% / Body ~80% / Conclusion ~10%); removed all transition story lines; bullets ≤12 words, 34 per main slide; larger fonts (body 26px, h1 40px, h2 32px); 6 new mermaid diagrams (frictions 2×2, north-star before/after, zero-trust flow, catalog primitives→modules, decommission gates, semver timeline). Code review: 0 P0, 2 P1 auto-fixed (slide-count metadata + README directory layout). 522 tests pass. Docs-only NFR patch. 1 phase (P71). See the v1.13 section below.
  • v1.13.1 (complete, tag v1.13.1): config.json schema migration — regenerate .ciagent/config.json to the updated CIAgent v2 config structure (drop removed fields, migrate gitearelease.gitea, add secrets/ship/backend/ideation/personas/logging/telemetry sections). Code review: 0 P0, 2 P1/P2 auto-fixed. Docs-only NFR patch (no code changes). Gitea release id 253.
  • v1.13.2 (complete, tag v1.13.2): presentation badge cleanup + platform architecture diagram — removed all testing/agentic maturity badges from both decks (only planned retained); added a new Slide 3 "The platform at a glance" with a shared high-level logical architecture diagram (consumer surfaces → contract → central pipeline → cross-cutting components → AWS) to both decks; renumbered subsequent slides 411; synced talking points + README. Docs-only NFR patch (no code changes).
  • v1.0 demo URL: https://git.cloudinit.dev/continuous-intelligence/acdl-evidence/raw/branch/main/index.html

v1.0 (Prior — the demo, complete)

Five-phase breakdown that took ACDL from empty repo to a reproducible 4-act executive demo. Milestone v1.0-initial covered the full demo build. Each phase produced a runnable increment and ended with a phase-completion commit

  • tag. All phases complete; demo archived to demo/ in v1.1 Phase 06.

Phases

Phase 01 — repo-scaffolding

  • Description: Create the three repos under continuous-intelligence (acdl-contracts, acdl-evidence; acdl already exists), seed directory layouts, configure Pages on acdl-evidence, add environment protection for qa and prod on acdl-contracts.
  • Status: complete (v1.0.1)
  • Depends on:
  • Requirements: REQ-01, REQ-09, REQ-10
  • Success Criteria:
    • acdl-contracts and acdl-evidence exist and are pushable.
    • acdl-evidence Pages returns 200 with placeholder index.html.
    • qa and prod environments exist on acdl-contracts.

Phase 02 — l1-modules

  • Description: Create all 8 L1 module folders under acdl/modules/l1/, each with manifest.yaml (declared inputs) and mock_apply.sh (uniform echo + 1s sleep + exit 0).
  • Status: complete (v1.0.2)
  • Depends on: [1]
  • Requirements: REQ-02, REQ-03
  • Success Criteria:
    • All 8 L1s present; mock_apply.sh runs and exits 0 for each.
    • manifest.yaml validates against the L1 schema.

Phase 03 — l2-modules-and-core-scripts

  • Description: Create the 4 L2 compositions under acdl/modules/l2/ referencing L1s, plus the 5 core scripts in acdl/scripts/ (mock_executor.sh, policy_checker.py, confidence_signal.py, evidence_writer.py, l3b_agent_stub.py).
  • Status: complete (v1.0.3)
  • Depends on: [2]
  • Requirements: REQ-04, REQ-05, REQ-06, REQ-07
  • Success Criteria:
    • mock_executor.sh applies each L1 in an L2 and writes state.json.
    • policy_checker.py fails on public-ingress: true with POLICY_VIOLATION:PUBLIC_INGRESS.
    • confidence_signal.py returns 0.90 (pass) / 0.40 (fail).
    • evidence_writer.py appends an event with a valid hash chain.
    • l3b_agent_stub.py maps the Act 3 example issue to l2-commodity-price-feed.

Phase 04 — pipeline-and-approval-gates

  • Description: Build the reusable pipeline workflow in acdl/.gitea/workflows/ (Dev → QA → Prod → Finalize) plus the issue-triggered L3B workflow in acdl-contracts/.gitea/workflows/. Wire environment protection for QA and Prod.
  • Status: complete (v1.0.4)
  • Depends on: [3]
  • Requirements: REQ-08, REQ-09, REQ-10, REQ-12
  • Success Criteria:
    • Pushing a valid contract.yaml runs Dev automatically and pauses at QA.
    • Approving QA moves to Prod; approving Prod finalizes.
    • Opening an Issue with the Act 3 text generates a contract.yaml commit and triggers the pipeline.

Phase 05 — evidence-ui-and-demo-dry-run

  • Description: Build index.html (vanilla JS, fetches audit.json, renders timeline) and run all four acts end-to-end as a dry run.
  • Status: complete (v1.0.5)
  • Depends on: [4]
  • Requirements: REQ-11, REQ-13, REQ-14, REQ-15
  • Success Criteria:
    • Pages timeline renders events from audit.json.
    • Act 2: valid contract passes through all gates; timeline shows the full flow.
    • Act 3: Issue text produces the expected l2-commodity-price-feed contract and triggers the pipeline.
    • Act 4: malicious public-ingress: true contract halts in Dev with confidence < 0.50 and a visible rejection reason on the timeline.

v1.1 (Complete — architecture finalization + v1 spike, 2026-07-21, tag v1.2.0)

Five-phase breakdown to finalize the architecture to v1.0 and prove the locked commitments with one end-to-end implementation spike. Milestone v1.1-spike covered the real platform's first materialization. Ship tag at milestone COMPLETE: v1.2.0 (feature milestone, next minor per ship.md). Status: COMPLETE — all 5 phases shipped (v1.1.1..v1.1.5) + verified; review READY TO SHIP (0 P0); audit CLEAN; Gitea release id 202. D-034 closed (root key deactivated by user).

Phase 06 — archive-demo-and-reorient

  • Description: Move the v1.0 demo (modules/, scripts/, evidence-ui/, contracts/, demo .gitea/workflows/) to demo/. Establish the new repo layout (platform/, schemas/, adapters/, terraform/, modules-ir/). Rewrite README to reflect the real platform. Verify the demo still runs from demo/ (regression check).
  • Status: complete (v1.1.1)
  • Depends on:
  • Requirements: (no new REQ; repo hygiene)
  • Success Criteria:
    • demo/ contains the full v1.0 demo; demo/scripts/run_demo.sh --no-upload still exits 0.
    • New top-level dirs exist and are empty-but-scaffolded: platform/, schemas/, adapters/, terraform/, modules-ir/.
    • README reflects the real platform (vision + architecture links, new layout).

Phase 07 — architecture-v1-finalization

  • Description: Resolve the 11 open decisions in docs/architecture.md §13 (already recorded in PROJECT.md). Author the locked schemas + designs: schemas/ir.schema.json (REQ-17), schemas/policy_check_result.schema.json (REQ-18), schemas/contract.schema.json (REQ-22), platform/confidence_signal.py spec (REQ-19), platform/audit_ledger_design.md (REQ-20), platform/hitl_matrix_design.md (REQ-21). Mark architecture v1.0.
  • Status: complete (v1.1.2)
  • Depends on: [06]
  • Requirements: REQ-16, REQ-17, REQ-18, REQ-19, REQ-20, REQ-21, REQ-22
  • Success Criteria:
    • All 11 open decisions resolved and recorded in PROJECT.md.
    • All 6 schema/design files exist and validate (ajv / python -m jsonschema).
    • docs/architecture.md status note updated to v1.0 (or a docs/architecture-v1.0.md snapshot).

Phase 08 — aws-oidc-bootstrap

  • Description: Re-scoped per RESEARCH TARGET 1 + D-039. Gitea Actions does not support id-token: write (conf 0.95), so real OIDC is deferred to v1.2. This phase instead: uses the temporary long-lived key (waiver D-034) once to create an S3 state bucket, a DynamoDB lock/outbox table, and an IAM user with a minimal scoped policy (S3 + DynamoDB + plan-only); stores the key as a Gitea Actions secret; implements scripts/rotate_spike_key.sh to rotate the key after each spike run. Real OIDC federation is tracked via go-gitea/gitea#36988 for v1.2.
  • Status: complete (v1.1.3)
  • Depends on: [07]
  • Requirements: REQ-23 (re-interpreted: AWS auth bootstrap + state backend; OIDC deferred to v1.2 per D-039)
  • Success Criteria:
    • S3 state bucket + DynamoDB lock/outbox table exist.
    • An IAM user with a minimal scoped policy exists; its access key is stored as a Gitea Actions secret.
    • scripts/rotate_spike_key.sh rotates the key (deactivates old, creates new, updates the secret) and is idempotent.
    • A workflow step authenticates to AWS with the rotated secret and runs aws sts get-caller-identity successfully.
    • D-034 is closed: the bootstrap long-lived key is rotated/deactivated (logged in PROJECT.md).

Phase 09 — v1-spike-ir-and-l1-and-adapter

  • Description: Implement the Target Stack IR, one real L1 l1-s3 (IR-typed interface, registered), and the Terraform adapter that compiles the IR → Terraform variable/output + root module and emits a real terraform plan against AWS (via the rotated-key secret per D-039; OIDC is v1.2). State in S3 + DynamoDB.
  • Status: complete (v1.1.4)
  • Depends on: [08]
  • Requirements: REQ-24, REQ-26
  • Success Criteria:
    • schemas/ir.schema.json is satisfied by modules-ir/l1/l1-s3/ interface.
    • The Terraform adapter translates l1-s3 to a valid terraform plan (real AWS).
    • terraform validate + terraform plan succeed; no long-lived credential in the workflow.

Phase 10 — v1-spike-l2-and-contract-e2e

  • Description: Implement l2-static-assets (thin-composition referencing l1-s3), the contract schema + contract→IR resolution, and one end-to-end contract submission (contracts/spike.yaml for l2-static-assets) flowing through schema validation → IR resolution → terraform plan → Checkov PolicyCheckResult → confidence signal → evidence event to the DynamoDB outbox. Verify the IR commitments hold (no polyglot mess).
  • Status: complete (v1.1.5)
  • Depends on: [09]
  • Requirements: REQ-25, REQ-27, REQ-28
  • Success Criteria:
    • l2-static-assets references l1-s3 only (depth 1).
    • One contract submission completes the full pipeline end-to-end.
    • scripts/verify_phase10.sh proves the adapter is the only engine-specific code.
    • Evidence event is written to the DynamoDB outbox.

After Phase 10: COMPLETE gate — review → ship v1.2.0 → audit. DONE.


v1.2 (Complete — platform hardening + first real consumer deployment, 2026-07-21, tag v1.3.0)

Six-phase breakdown to harden the v1.1 spike, simplify the setup, update the docs, and prove the platform delivers real value by deploying a basic microservice to AWS ECS Fargate end-to-end. Ship tag at milestone COMPLETE: v1.3.0 (feature milestone, next minor per ship.md — v1.1 shipped v1.2.0). Phase patches v1.2.1..v1.2.6. Status: COMPLETE — all 6 phases shipped (v1.2.1..v1.2.6) + verified; review READY TO SHIP (1 P0 operator action, 1 P1 deferred to v1.3); audit CLEAN. The terraform apply is blocked by the live IAM policy (P0-IAM, operator action); the platform flow is verified end-to-end up to terraform plan (13 to add).

Phase 11 — v1.2-research-and-readme

  • Description: Re-evaluate go-gitea/gitea#36988 (OIDC for Gitea Actions) — confirm still open (re-checked 2026-07-21: open, last updated 2026-05-27, not merged) and record the decision to extend D-039 as D-047. Audit the v1.1 spike for NFR gaps (least-privilege IAM, idempotency, error handling, rotation hygiene) and simplification opportunities (script consolidation, dead code, stale paths). Rewrite README.md to reflect v1.1 complete + the actual spike flow + how to run + the real repo layout + the v1.2 objective.
  • Status: complete (v1.2.1)
  • Depends on:
  • Requirements: REQ-29
  • Success Criteria:
    • RESEARCH.md has a v1.2 addendum with the #36988 re-check + NFR audit + simplification findings.
    • README.md reflects v1.1 complete; documents the spike flow, scripts/run_platform.sh, the repo layout, and the v1.2 objective; no stale "v1.1 (active)" framing.
    • D-047 is recorded in PROJECT.md.

Phase 12 — nfr-harden-and-simplify

  • Description: Apply Phase 11's findings. Tighten terraform/bootstrap/spike_runner_policy.json to least-privilege (add ECS + ECR + ELB + IAM plan-only permissions for v1.2; audit for wildcards). Make create_state_backend.py and create_iam_user.py idempotent. Consolidate run_spike_plan.sh + run_spike_e2e.sh into a single scripts/run_platform.sh with proper exit codes and error handling. Redact P1-1 (the two AWS access key IDs in .ciagent/VERIFY.md Phase 09 narrative). Fix any remaining stale platform/ paths in .ciagent/. The v1.1 spike still runs e2e after the refactor.
  • Status: complete (v1.2.2)
  • Depends on: [11]
  • Requirements: REQ-30
  • Success Criteria:
    • scripts/run_platform.sh runs the full v1.1 spike e2e and exits 0.
    • create_state_backend.py / create_iam_user.py re-runs are idempotent (no duplicate resources; exit 0).
    • spike_runner_policy.json passes a least-privilege audit (no * actions beyond documented exceptions).
    • .ciagent/VERIFY.md Phase 09 narrative has no live AWS access key IDs.
    • No stale platform/ paths remain in .ciagent/.

Phase 13 — l1-catalog-for-ecs

  • Description: Author six IR-typed L1 modules for an ECS Fargate microservice: l1-vpc (VPC + subnets + route tables), l1-ecs-cluster (ECS Fargate cluster), l1-ecs-service (ECS service + task definition), l1-iam-role (task execution + task role), l1-alb (ALB + listener + target group), l1-ecr (ECR repository). Each has an interface.json valid against schemas/ir.schema.json. Register all six in modules-ir/registry.json. Expand the Terraform adapter TYPE_MAP to cover the new IR resource types. Each L1 produces a valid terraform plan fragment.
  • Status: complete (v1.2.3)
  • Depends on: [12]
  • Requirements: REQ-31
  • Success Criteria:
    • All six L1s exist under modules-ir/l1/ with interface.json valid against schemas/ir.schema.json.
    • modules-ir/registry.json lists all six.
    • The adapter TYPE_MAP covers all six IR resource types.
    • Each L1 produces a valid terraform plan fragment.

Phase 14 — l2-microservice-and-contract-schema

  • Description: Author l2-microservice thin-composition under modules-ir/l2/l2-microservice/ referencing the six ECS L1s (depth ≤ 5). Extend schemas/contract.schema.json with microservice inputs (image: string, port: integer, env: map, healthcheck: object). Verify contract→IR resolution yields a complete target stack.
  • Status: complete (v1.2.4)
  • Depends on: [13]
  • Requirements: REQ-32
  • Success Criteria:
    • l2-microservice references the six ECS L1s only (depth ≤ 5).
    • schemas/contract.schema.json validates a contracts/microservice.yaml with the new inputs.
    • Contract→IR resolution yields a complete target stack (all six L1 instances + relationships).

Phase 15 — consumer-repo-and-terraform-apply

  • Description: Create a new Gitea repo acdl-consumer-microservice under the continuous-intelligence org containing a basic HTTP microservice (tiny Python/Go server returning 200), a Dockerfile, an ECR push step, and a contracts/microservice.yaml submission for l2-microservice (dev environment). Lift the platform from plan to apply for the dev environment (autonomous per §10, confidence ≥ 0.50, no HITL). Submit the contract → pipeline → IR → plan → apply → a real ECS Fargate service running.
  • Status: complete (v1.2.5, PARTIAL — terraform apply blocked by IAM P0)
  • Depends on: [14]
  • Requirements: REQ-33 (partial), REQ-34
  • Success Criteria:
    • acdl-consumer-microservice repo exists under continuous-intelligence.
    • The microservice builds into a Docker image and is pushed to ECR.
    • terraform apply (dev) creates real AWS resources (VPC, ECS cluster, ECR repo, ALB, ECS service).
    • The apply result is captured in the evidence stream.

Phase 16 — v1.2-capstone-e2e

  • Description: End-to-end verification: consumer commit to acdl-consumer-microservice triggers the pipeline → contract→IR resolution → terraform planterraform apply (dev) → a live ECS Fargate service serving HTTP 200 on its ALB → evidence event written to the DynamoDB outbox → the event renders on the acdl-evidence timeline. Verify the NFR improvements from Phase 12 hold, the setup is simpler (one scripts/run_platform.sh), and the README is accurate. scripts/verify_phase16.sh proves the full flow green.
  • Status: complete (v1.2.6, capstone — terraform apply blocked by IAM P0, verified up to plan)
  • Depends on: [15]
  • Requirements: REQ-35 (partial — IAM-blocked)
  • Success Criteria:
    • One consumer commit produces a live ECS service serving HTTP 200.
    • An evidence event for the apply is in the DynamoDB outbox and renders on the timeline.
    • scripts/verify_phase16.sh exits 0.
    • README accurately documents the v1.2 platform flow.

After Phase 16: COMPLETE gate — review → ship v1.3.0 → audit.


v1.3 (Complete — module documentation + thin-composition removal)

The v1.3 milestone starts with simplification: removing the unsatisfactory thin-composition layer and building out proper module documentation. The L2 composition mechanism will be redesigned in a later phase.

Phase 17 — remove-thin-composition-and-module-readmes

  • Description: Remove the L2 thin-composition layer completely (composition.json files, contract_resolver.py, contract schema, sample contracts) and build out proper module READMEs. Create a README template for both L1 and L2 modules, rewrite all 7 L1 module READMEs in plain language (no jargon, with Resources/Inputs/Outputs/Usage/Compliance-extension-points/Versioning sections), write 2 L2 placeholder READMEs noting the composition is under redesign, create a catalog index, and patch run_platform.sh to load a pre-existing IR instance instead of resolving a contract. Prune L2 entries from the registry.
  • Status: complete (v1.3.1)
  • Depends on:
  • Requirements: REQ-36, REQ-37, REQ-38
  • Success Criteria:
    • The thin-composition layer is fully removed (composition.json, contract_resolver.py, contract schema, contracts/).
    • run_platform.sh loads a pre-existing IR instance; the downstream adapter/checkov/confidence/outbox pipeline still works.
    • A README-TEMPLATE.md exists for both L1 and L2 modules.
    • Every L1 module has a README.md with Resources/Inputs/Outputs/Usage/Compliance-extension-points/Versioning.
    • Every L2 module has a placeholder README.md noting the composition is under redesign.
    • A modules-ir/README.md catalog index exists.

Phase 18 — testing-and-cicd-pipelines

  • Description: Create a pytest test suite that reproduces the platform pipeline offline (adapter, confidence_signal, checkov_adapter, outbox_writer). Add an offline --check-only mode to run_platform.sh that runs the pipeline up to adapter emission without AWS/Checkov/outbox. Create identical CI/CD pipelines for both Gitea Actions (.gitea/workflows/ci.yml, dev environment) and GitHub Actions (.github/workflows/ci.yml, production) that run: lint, pytest, run_platform.sh --check-only. Add pyproject.toml + requirements-test.txt for dependency pinning.
  • Status: complete (v1.3.2)
  • Depends on: [17]
  • Requirements: REQ-39, REQ-40, REQ-41, REQ-42
  • Success Criteria:
    • pytest runs and passes offline (no AWS, no Checkov, no DynamoDB).
    • run_platform.sh --check-only runs offline and exits 0.
    • .gitea/workflows/ci.yml and .github/workflows/ci.yml exist with identical job stages (lint, test, check-only).
    • pyproject.toml + requirements-test.txt pin test dependencies.

After Phase 18: COMPLETE gate — review → ship v1.3.2 → audit.


v1.4 (Active — central pipeline contract + shell reproducibility + streaming)

The v1.4 milestone makes the CI/CD pipeline a declarative contract rather than duplicated workflow copies, enables full shell reproducibility of the CI pipeline, and streams terraform/checkov output so users can see what the platform is doing.

Phase 19 — central-pipeline-contract-and-shell-reproducibility

  • Description: Create a central pipeline contract (schemas/pipeline.schema.json JSON Schema + pipelines/ci.yaml YAML instance) that both .gitea/workflows/ci.yml (Gitea Actions, dev) and .github/workflows/ci.yml (GitHub Actions, production) implement. Create scripts/run_ci.sh that mirrors the CI pipeline locally (lint → test → check-only). Update scripts/run_platform.sh to stream terraform init/validate/plan output, Checkov compliance results, and PolicyCheckResult records to stdout by default (with --quiet for log-only mode). Add tests/test_pipeline_contract.py validating the contract schema, workflow conformance, and run_ci.sh. Update both workflow YAMLs with contract reference headers (staying byte-identical).
  • Status: complete (v1.4.1)
  • Depends on: [18]
  • Requirements: REQ-43, REQ-44, REQ-45
  • Success Criteria:
    • pipelines/ci.yaml validates against schemas/pipeline.schema.json.
    • Both .gitea/workflows/ci.yml and .github/workflows/ci.yml are byte-identical.
    • A test parses both workflows and asserts their stages/commands match the contract.
    • scripts/run_ci.sh exits 0 and outputs "CI PIPELINE OK".
    • scripts/run_platform.sh --check-only streams the emitted Terraform to stdout.
    • scripts/run_platform.sh --check-only --quiet suppresses the Terraform stream.
    • pytest total count increases from 90 to 122 (32 new contract/streaming tests).

After Phase 19: COMPLETE gate — review → ship v1.4.1 → audit.


v1.5 (Complete — consumer happy path + zero-trust docs + reusable deploy workflow, tag v1.5.0)

The v1.5 milestone makes the consumer happy path self-evident, documents the zero-trust credential model, and provides a reusable deploy workflow so consumer repos never need to clone the platform repo or invoke its scripts locally.

Phase 20 — consumer-happy-path-and-reusable-deploy-workflow

  • Description: Rewrite README.md so the consumer model is unambiguous (this repo is the platform source; a consumer owns only contract.yaml + app code). Convert the platform-flow diagram to a mermaid flowchart TD. Remove "L3A"/"L3B" + "spike" nomenclature from README prose. Rewrite the Credentials section for zero-trust OIDC + ABAC (with a static-key override + daily rotation; consumer rotates out of band when using .env.secrets locally). Replace docs/consumer-guide-static-assets.md with a generic docs/CONSUMER_GUIDE.md (all L2 modules, mermaid diagrams, versioned uses: floating MAJOR+MINOR, consumer-scoped prerequisites, run-time platform fetch via a reusable workflow). Create byte-identical .gitea/workflows/deploy.yml + .github/workflows/deploy.yml implementing pipelines/deploy.yaml — a reusable workflow invoked by consumer repos via uses: acdl/.gitea/workflows/deploy.yml@v1.4 that checks out the consumer repo + the ACDL platform repo and runs scripts/run_platform.sh. Update contracts/static-assets.yaml to uses: acdl/pipelines/deploy.yaml@v1.4. Extend tests/test_pipeline_contract.py to validate the new deploy workflows (byte-identical, schema-conformant).
  • Status: complete (v1.5.0)
  • Depends on: [19]
  • Requirements: REQ-46, REQ-47, REQ-48, REQ-49, REQ-50, REQ-51
  • Success Criteria:
    • README.md states the platform-source vs consumer-repo distinction up front; platform flow is a mermaid flowchart TD; grep L3B README.md returns 0 hits; grep -i spike README.md returns 0 prose hits (code paths in bash blocks allowed).
    • docs/CONSUMER_GUIDE.md exists; docs/consumer-guide-static-assets.md is deleted; grep -R consumer-guide-static-assets returns 0 dangling references; guide is generic (static-assets is the worked example, not the scope); diagrams are mermaid; uses: references use @v1.4.
    • README.md Credentials section describes OIDC + ABAC zero-trust as the default and the static-key override + daily rotation + consumer out-of-band rotation duty for local .env.secrets.
    • .gitea/workflows/deploy.yml and .github/workflows/deploy.yml exist, are byte-identical, conform to schemas/deploy-pipeline.schema.json, and are reusable (on: workflow_call with a contract input).
    • contracts/static-assets.yaml uses uses: acdl/pipelines/deploy.yaml@v1.4.
    • tests/test_pipeline_contract.py validates the deploy workflows (exist, byte-identical, schema-conformant); the extended test suite passes; bash scripts/run_ci.sh exits 0.

After Phase 20: COMPLETE gate — review → ship v1.5.0 → audit.


v1.6 (Active — consumer-facing docs restructure + terminology normalization + environments concept)

The v1.6 milestone restructures the consumer-facing documentation into a real GitHub Pages site, normalizes the terminology (L2 → "modules", L1 → "primitives", "composition" → "pattern", "forge" → "platform runners"), renames acdl_platform/ to core/ (platform/ shadows stdlib), rewrites the README (Features + Roadmap, restated repository roles, fixed mermaid, cleaned credentials section), removes all .ciagent/ + .gitea/ references from consumer surfaces, and introduces the concept of platform-managed environments with a minimal first-run onboarding scaffold.

Phase 21 — docs-restructure-and-terminology-normalization

  • Description: Rename acdl_platform/core/ (directory + all code/test/script/pipeline/workflow references; tests green — platform/ was the original target but shadows Python's stdlib platform module, so core/ was chosen). Restructure docs/ into a Jekyll-style GitHub Pages site (_config.yml, index.md, modules/, contracts/, pipeline/, environments/, consumer-guide.md, consolidated architecture.md, vision.md). Rewrite README.md: remove .ciagent/ + .gitea/workflows/ rows; restate consumer repo model (app code + 1+ contracts + CI definitions uses:-ing the central workflow); replace Status with Features + Roadmap (planned only); fix the mermaid (visible text, add security-checks stage before policy, no tool names, add infrastructure-apply stage); remove the environments table; clean the credentials section (no go-gitea/waivers, keep daily/out-of-band rotation); forge → platform runners/platform-managed. Update docs/consumer-guide.md: drop L2 (→ modules), composition → pattern (prose), remove .gitea/ (GitHub only), forge → platform runners, mermaid updated. Update modules/ READMEs: L1 → primitives, L2 → modules, composition → pattern (prose only, files kept); bump stale @v1@v1.4. Consolidate docs/architecture.md + docs/architecture-v1.0.md into a single current-architecture docs/architecture.md. Add docs/environments/index.md (platform-managed AWS account/network/state/runner; consumer provides none). Add a minimal onboarding scaffold: core/environments/ dir + sample dev.json + README, core/environment_check.py, wire-in at the top of scripts/run_platform.sh, friendly onboarding message when no environment is defined, tests/test_environment_check.py. Add a roadmap entry: "composition" will later describe the thin orchestration where consumers dynamically create a module directly from the contract file (future implementation, not this phase).
  • Status: complete (v1.6.0)
  • Depends on: [20]
  • Requirements: REQ-52, REQ-53, REQ-54, REQ-55, REQ-56, REQ-57, REQ-58, REQ-59, REQ-60, REQ-61
  • Success Criteria:
    • grep -R "\.ciagent" docs/ README.md returns 0 hits; grep -R "\.gitea" docs/ README.md modules/ contracts/ returns 0 hits.
    • grep -R "acdl_platform" . (excluding .ciagent/, demo/, .git/) returns 0 hits; the test suite passes after the rename.
    • docs/ has the Jekyll structure (_config.yml, index.md, modules/, contracts/, pipeline/, environments/); no .ciagent/ links in docs/.
    • Consumer-facing docs have no "L2"/"L1" labels (modules/primitives) and no "forge" term; "composition" → "pattern" in prose.
    • README.md has Features + Roadmap (no version changelog); repository roles restated; mermaid visible + security-checks + infrastructure-apply stages + no tool names; no environments table; credentials section has no go-gitea/waivers.
    • docs/environments/index.md exists; core/environments/ + dev.json + environment_check.py + run_platform.sh wire-in + tests/test_environment_check.py exist and pass.
    • bash scripts/run_ci.sh exits 0; python3 -m pytest tests/ -v passes (154 + new environment-check tests).

After Phase 21: COMPLETE gate — review → ship v1.6.0 → audit. DONE.


v1.7 (Complete — production platform + contract ingestion + pipeline maturation, tag v1.7.0)

The v1.7 milestone takes the platform from a documented, environments-aware foundation to a production-grade platform with a production-ready static-assets stack (CloudFront + WAF), a contract-ingestion Lambda + DynamoDB store for historical/impact analysis, a uniform error-reporting pathway via the same Lambda, DX-friendly deploy outputs (SSM + PR comments), three dedicated platform pipelines (unit+integration, primitives plan, patterns plan), a release job with MAJOR.MINOR/MAJOR tag maintenance, new security adapters (Wiz, Kyverno), real tagging-standard enforcement (closing D-043), removal of the legacy consumer-repos directory (removed in v1.7), and validated per-module examples (including a new RDS primitive demonstrating multi-engine variation).

The uses:/ref: tag advances from @v1.4 to @v1.6; the floating v1.6 + v1 tags are created in Phase 22 (pointing at the v1.6.0 release) so the reference is never broken, and the release job (Phase 26) owns ongoing updates.

Phase 22 — rename-and-production-static-assets-stack

  • Description: Rename static-assetsstatic-assets everywhere (D-048 — including .ciagent/ historical narrative, overriding the v1.6 preservation precedent). Author two new primitives: cloudfront (distribution + OAC, stack types aws:cloudfront:distribution + aws:cloudfront:originaccesscontrol) and waf (WAFv2 web ACL, stack type aws:wafv2:webacl). Augment the static-assets module to a production-ready stack referencing s3 + cloudfront + waf (depth 1, D-049). Expand the Terraform adapter TYPE_MAP/INPUT_MAP/OUTPUT_MAP for the new stack types. Bump uses:/ref: from @v1.4 to @v1.6 (D-056/D-057); create the floating v1.6 + v1 git tags pointing at v1.6.0 so the reference resolves immediately.
  • Status: complete (v1.7.0)
  • Depends on: [21]
  • Requirements: REQ-62, REQ-63, REQ-64
  • Success Criteria:
    • grep -R "static-assets[^s]" . (excluding .git/) returns 0 hits; modules/l2/static-assets/ is renamed to modules/l2/static-assets/; contracts/static-assets.yamlcontracts/static-assets.yaml; registry key renamed; all .ciagent/ references (incl. verbatim phase descriptions, REQ-25/27/50 text, D-036) rewritten to static-assets.
    • modules/l1/cloudfront/ + modules/l1/waf/ exist with interface.json valid against schemas/stack.schema.json; registered in modules/registry.json.
    • modules/l2/static-assets/composition.json references s3 + cloudfront + waf (depth 1).
    • adapters/terraform/adapter.py TYPE_MAP covers aws:cloudfront:distribution, aws:cloudfront:originaccesscontrol, aws:wafv2:webacl.
    • contracts/static-assets.yaml + .github/workflows/deploy.yml + .gitea/workflows/deploy.yml use @v1.6; git tags v1.6 + v1 exist pointing at v1.6.0.
    • bash scripts/run_ci.sh exits 0; python3 -m pytest tests/ -v passes; bash scripts/run_platform.sh --check-only exits 0.

Phase 23 — tagging-standards-and-security-adapters

  • Description: Define a required-tag set (acdl:owner, acdl:contract, acdl:environment, acdl:cost-center) in schemas/tagging-standard.json (D-054). Author a Checkov custom YAML rule at adapters/terraform/policy/custom_rules/acdl_tagging.yaml that fails when required tags are missing on taggable resources. Remove the _emit_tag_naming_skipped() placeholder in checkov_adapter.py (D-043 closure) and add ACDL_TAG_NAMING to RULE_MAP as a real rule. Author a Wiz adapter stub (adapters/wiz/wiz_adapter.py) translating Wiz API issues → PolicyCheckResult records (engine: "wiz"), degrading gracefully when unconfigured (D-052). Author a Kyverno K8s-native adapter (adapters/kyverno/kyverno_adapter.py) translating Kyverno PolicyReport results → PolicyCheckResult records (engine: "kyverno"), with sample policies as documentation; inactive for Terraform-only stacks, ready for the GitOps reconciler roadmap item (D-053). Add wiz + kyverno to the schemas/policy_check_result.schema.json engine enum.
  • Status: complete (v1.7.0)
  • Depends on: [22]
  • Requirements: REQ-65, REQ-66, REQ-67
  • Success Criteria:
    • adapters/terraform/policy/custom_rules/acdl-tagging.yaml exists; Checkov loads it; checkov_adapter.py no longer emits a SKIPPED ACDL_TAG_NAMING placeholder (D-043 closed).
    • adapters/wiz/wiz_adapter.py + tests/test_wiz_adapter.py exist; tests pass offline (not-configured graceful degradation).
    • adapters/kyverno/kyverno_adapter.py + sample policies + tests/test_kyverno_adapter.py exist; tests pass offline.
    • schemas/policy_check_result.schema.json engine enum includes checkov | kyverno | opa | wiz.
    • bash scripts/run_ci.sh exits 0; python3 -m pytest tests/ -v passes.

Phase 24 — platform-lambda-and-contract-ingestion

  • Description: Author a platform Lambda (core/lambda/contract_ingestor.py) invoked via a Function URL (IAM auth) that accepts { consumerRepo, contractId, contract, environment, action } and writes contracts to a DynamoDB table acdl-contracts (PK consumerRepo, SK contractId#submittedAt, SSE via a customer-managed CMK) (D-051). Define the Terraform (terraform/platform/main.tf) for the table, Lambda, Function URL, KMS key, Secrets Manager secret (acdl/github-token), and Lambda execution role. Define the cross-account consumer-invoke IAM policy (terraform/platform/consumer_invoke_policy.json) granting the consumer's deploy role lambda:InvokeFunctionUrl on the Lambda ARN, scoped via ABAC. The report_error action (Phase 25) is prepared but not yet implemented. Update docs/environments/index.md to document that onboarding now also grants Lambda-invoke permission.
  • Status: complete (v1.7.0)
  • Depends on: [23]
  • Requirements: REQ-68
  • Success Criteria:
    • core/lambda/contract_ingestor.py exists; handler writes contracts to DynamoDB (tested offline with moto).
    • terraform/platform/main.tf defines acdl-contracts DynamoDB table, acdl-contract-ingestor Lambda, Function URL (IAM auth), KMS CMK, Secrets Manager secret, Lambda execution role.
    • terraform/platform/consumer_invoke_policy.json exists (cross-account invoke policy template).
    • tests/test_contract_ingestor.py passes offline.
    • bash scripts/run_ci.sh exits 0.

Phase 25 — deploy-pipeline-dx-outputs-and-error-reporting

  • Description: Add a publish-outputs step to scripts/run_platform.sh (after apply) that writes deploy outputs to SSM Parameter Store as SecureString (KMS-encrypted, namespaced /acdl/{env}/{contractId}/{output_name}) for runtime-injectable values, and a comment-outputs step that posts a structured GitHub PR comment / job summary with human-readable connection strings (D-050). Implement core/output_publisher.py (SSM write + GitHub comment formatting). Implement the Lambda report_error action (core/lambda/contract_ingestor.py) that creates a GitHub issue on the platform repo (acdl/acdl) via the GitHub API using a token from Secrets Manager; idempotent (comments on existing open issue rather than duplicating) (D-055). Add an if: failure() error-report step to .github/workflows/deploy.yml that invokes the Lambda via aws lambda invoke-function-url (SigV4-signed). Add a PR comment after every successful pipeline stage (D-055 extension) via scripts/post_stage_comment.sh (uses GITHUB_TOKEN + gh api; no-op when not in a PR context). Update pipelines/deploy.yaml + both deploy workflow YAMLs with the new stages (byte-identical).
  • Status: complete (v1.7.0)
  • Depends on: [24]
  • Requirements: REQ-69, REQ-70, REQ-71
  • Success Criteria:
    • scripts/run_platform.sh has a publish-outputs step (SSM SecureString, tested offline with moto) + a comment-outputs step (GitHub PR comment formatting, tested offline).
    • core/lambda/contract_ingestor.py report_error action creates a GitHub issue (tested with mocked API); idempotent.
    • .github/workflows/deploy.yml + .gitea/workflows/deploy.yml (byte-identical) have an if: failure() error-report step invoking the Lambda + stage comments after each successful stage (PR context).
    • pipelines/deploy.yaml declares the new stages.
    • bash scripts/run_ci.sh exits 0; python3 -m pytest tests/ -v passes.

Phase 26 — platform-pipelines-and-release-automation

  • Description: Author three platform pipelines (D-057): (1) .github/workflows/platform-test.yml (PR, lint + unit + integration + schema-validation — replaces ci.yml for PRs); (2) .github/workflows/primitives-plan.yml (PR, plan-only for all L1 primitives via matrix); (3) .github/workflows/patterns-plan.yml (PR, plan-only for all L2 modules via matrix). Author scripts/run_primitive_plan.sh + scripts/run_pattern_plan.sh (with --check-only mode for CI). Author the release job (.github/workflows/release.yml) that runs on merge to main, computes the next semver (PATCH per phase, MINOR on milestone COMPLETE), creates the MAJOR.MINOR.PATCH tag, force-moves the MAJOR.MINOR + MAJOR floating tags, creates a GitHub release with an auto-generated body. This is the mechanism that lets consumers on @v1 or @v1.7 receive updates.
  • Status: complete (v1.7.0)
  • Depends on: [25]
  • Requirements: REQ-72, REQ-73
  • Success Criteria:
    • .github/workflows/platform-test.yml exists, runs lint + unit + integration + schema-validation on PR.
    • .github/workflows/primitives-plan.yml + .github/workflows/patterns-plan.yml exist, run plan-only (matrix) on PR.
    • .github/workflows/release.yml exists, computes next semver, creates + updates MAJOR.MINOR.PATCH / MAJOR.MINOR / MAJOR tags on merge.
    • scripts/run_primitive_plan.sh + scripts/run_pattern_plan.sh exit 0 in --check-only mode.
    • bash scripts/run_ci.sh exits 0; python3 -m pytest tests/ -v passes.

Phase 27 — remove-legacy-consumer-repos-and-module-documentation-examples

  • Description: Delete the legacy consumer-repos directory entirely (a v1.2 artifact removed in v1.7; references in .ciagent/ historical narrative are rewritten per D-048). Author a new RDS primitive (modules/l1/rds/) with an engine input (enum: postgres, mysql, etc.) demonstrating multi-engine variation (D-059). Expand the adapter TYPE_MAP for aws:rds:instanceaws_db_instance. For each module (primitives + patterns), add a modules/<name>/examples/ directory with simple.yaml + complex.yaml (+ variation files) validated against schemas/contract.schema.json in the platform-test pipeline (Phase 26 schema-validation stage) (D-058). Each module's README.md ## Examples section references + excerpts the validated files. Update docs/modules/index.md + docs/consumer-guide.md + docs/contracts/index.md with the new module names + examples.
  • Status: complete (v1.7.0)
  • Depends on: [26]
  • Requirements: REQ-74, REQ-75
  • Success Criteria:
    • The legacy consumer-repos directory does not exist; a recursive grep for the legacy directory name (excluding .git/) returns 0 hits.
    • modules/l1/rds/ exists with interface.json (engine enum) + examples/; registered; adapter emits aws_db_instance.
    • Every module README has a ## Examples section; modules/<name>/examples/{simple,complex}.yaml exist and validate against schemas/contract.schema.json.
    • docs/modules/index.md links to all module READMEs (including cloudfront, waf, rds).
    • bash scripts/run_ci.sh exits 0; python3 -m pytest tests/ -v passes.

After Phase 27: COMPLETE gate — review → ship v1.7.0 → audit. DONE.


v1.8 (Complete — P1 remediation + uptime + engineering standards + encryption/deletion-protection by default + decommission + docs)

The v1.8 milestone clears all pending P1 issues from v1.5v1.7 verify reviews AND delivers three user-directed tracks: encryption + deletion protection by default (with a decommission alias), uptime monitoring (uptime-kuma primitive deployed by default after L2 modules), and engineering standards + path documentation. Ship tag at milestone COMPLETE: v1.8.0 (feature milestone, next minor per run.md — v1.7 shipped v1.7.0). Phase patches v1.7.1..v1.7.9.

Phase 28 — adapter-waf-and-resolver-outputs

  • Description: Fix WAF HCL emission: custom rules input emits nested rules { ... } blocks (not rules = [...] attribute syntax — P1-4). Honor default_action input (allow/block) instead of hardcoding allow {} (P1-5). Implement L2 composition outputs[] processing in resolve_l2() — build stack.outputs dict + adapter emits output blocks (P1-7). Tests for all three fixes.
  • Status: complete (v1.8.0)
  • Depends on:
  • Requirements: REQ-76, REQ-77
  • Success Criteria:
    • WAF with custom rules emits nested rules { blocks, not rules = [.
    • WAF with default_action: block emits block {}; default (absent) emits allow {}.
    • L2 resolution of static-assets yields stack.outputs.distribution_domain_name, bucket_arn, web_acl_arn.
    • Adapter emits output "distribution_domain_name" { value = ... } blocks.
    • pytest passes; run_platform.sh --check-only exits 0.

Phase 29 — ssm-kms-and-invoke-policy

  • Description: SSM publisher fails loud (RuntimeError) when ACDL_KMS_KEY_ID unset; ACDL_ALLOW_DEFAULT_KMS=1 escape hatch for local testing (P1-3). Convert consumer_invoke_policy.json to a Terraform-rendered template using data.aws_caller_identity + templatestring — no 000000000000 placeholder (P1-6). Tests for both.
  • Status: complete (v1.8.0)
  • Depends on: [28]
  • Requirements: REQ-78, REQ-79
  • Success Criteria:
    • SSM publisher raises RuntimeError when ACDL_KMS_KEY_ID unset; succeeds with ACDL_ALLOW_DEFAULT_KMS=1.
    • Rendered invoke policy contains the caller's live account ID, not 000000000000.
    • pytest passes; run_ci.sh exits 0.

Phase 30 — run-platform-isolation-and-api-portability

  • Description: run_platform.sh emits adapter output to $WORK/tf (per-run temp dir), not terraform/spike/; remove committed terraform/spike/*.tf (P1-8). contract_ingestor.py reads GITHUB_API_BASE env for forge-agnostic API URLs (GitHub + Gitea); _forge_type() branches search URL (P1-9). Deploy workflow configure-aws-credentials step restructured as single conditional step: OIDC when no static key, access-key/secret-key inputs when static key present (S1). Both deploy workflows remain byte-identical.
  • Status: complete (v1.8.0)
  • Depends on: [29]
  • Requirements: REQ-80, REQ-81, REQ-82
  • Success Criteria:
    • run_platform.sh --check-only writes to a temp dir; no terraform/spike/*.tf committed.
    • contract_ingestor.py uses GITHUB_API_BASE; Gitea base URL produces correct API paths.
    • Deploy workflow static-key override wired to configure-aws-credentials inputs.
    • Both deploy workflows byte-identical; pytest + run_ci.sh green.

Phase 31 — encryption-by-default-and-per-stack-cmk

  • Description: Create kms-key L1 primitive (type aws:kms:key, inputs: description/region/deletion_window_days, outputs: kms_key_arn/kms_key_id, NFRs: enable_rotation default true, deletion_protection default true). Adapter emits aws_kms_key + aws_kms_alias + enable_key_rotation = true. Add encryption_enabled NFR (default true) + kms_key_arn input to all primitives. L2 modules wire a kms-key child + connect its output to all children. Managed KMS fallback when no CMK provided (with stderr warning).
  • Status: complete (v1.8.0)
  • Depends on: [30]
  • Requirements: REQ-83, REQ-84, REQ-85
  • Success Criteria:
    • Every primitive has encryption_enabled NFR (default true) + optional kms_key_arn input.
    • L2 resolution wires per-stack CMK to all children.
    • Adapter emits encryption blocks (SSE, storage_encrypted, encryption_configuration) referencing the CMK.
    • enable_key_rotation = true on the CMK; no shared keys across stacks.
    • pytest + run_ci.sh green.

Phase 32 — deletion-protection-by-default-and-l2-feature-flag

  • Description: Add deletion_protection NFR (boolean, default true) to every L1 primitive. Adapter emits lifecycle { prevent_destroy = true } when true; omits it when false. L2 modules expose features.deletion_protection flag (default true); resolver propagates to each child's NFR. Consumers can set inputs.deletion_protection: false in contract. Update contract schema.
  • Status: complete (v1.8.0)
  • Depends on: [31]
  • Requirements: REQ-86, REQ-87
  • Success Criteria:
    • Every primitive has deletion_protection NFR defaulting to true.
    • Adapter emits prevent_destroy = true when true; omits when false.
    • L2 feature flag propagates to all children.
    • pytest + run_ci.sh green.

Phase 33 — uptime-kuma-primitive

  • Description: Create uptime L1 primitive (ECS Fargate running louislam/uptime-kuma:1). Inputs: container_image, region, monitored_endpoints (array of {name, url, type, interval, timeout}), static_checks, alert_channels ({teams_webhook, email_addresses, sms_numbers, github_issue_repo}), feature_flag_enabled (default true), cpu, memory. Outputs: uptime_url, service_arn, task_definition_arn. NFRs: deletion_protection, encryption_enabled. Adapter emits ECS service + ALB + log group; no resources when feature_flag_enabled=false. Register in registry. Add deploy-uptime pipeline stage (separate state, after publish-outputs) to pipelines/deploy.yaml + both deploy workflows. run_platform.sh constructs synthetic uptime contract from L2 outputs + runs second terraform apply. Uptime URL published via PR comment. Feature flag from inputs.uptime_enabled (default true).
  • Status: complete (v1.8.0)
  • Depends on: [32]
  • Requirements: REQ-88, REQ-89, REQ-90, REQ-91
  • Success Criteria:
    • Uptime primitive exists with feature flag, monitored endpoints, alert channels.
    • Deployed by default after L2 module (separate state); endpoints passed from L2 outputs.
    • Uptime URL published via PR comment.
    • Feature flag disables deployment (no resources emitted).
    • deploy-uptime stage in deploy contract + byte-identical workflows.
    • pytest + run_ci.sh green.

Phase 34 — decommission-alias-and-cmdb-validation

  • Description: Add mode: decommission to deploy pipeline. Stages: validate-change-request (Lambda validate_change_request action queries DynamoDB acdl-change-requests table, asserts status=approved) → disable-deletion-protection (resolve contract with deletion_protection=false, terraform plan/apply, HITL SRE gate) → zero-counts (resolver decommission_transform zeroes all counts, terraform plan/apply, second HITL SRE gate) → confirm-decommission. Add acdl-change-requests DynamoDB table to terraform/platform/main.tf. Add validate_change_request to contract_ingestor.py. Document in docs/CONSUMER_GUIDE.md.
  • Status: complete (v1.8.0)
  • Depends on: [33]
  • Requirements: REQ-92, REQ-93, REQ-94
  • Success Criteria:
    • Decommission mode works via existing deploy pipeline with 2-step HITL SRE gates.
    • CR ID validated against DynamoDB CMDB (status must be approved).
    • decommission_transform zeroes all counts.
    • Documented in consumer guide.
    • pytest + run_ci.sh green.

Phase 35 — module-engineering-standards

  • Description: Scan all current modules to generate modules/STANDARDS.md — comprehensive L1+L2 authoring + code review standards: required files, interface schema, input/output/NFR conventions, encryption + deletion protection as mandatory NFRs, naming, multi-resource pattern, adapter extension pattern (TYPE_MAP + INPUT_MAP + OUTPUT_MAP + specialized branches), code review checklist. Fix modules/README.md catalog index (add rds + uptime + kms-key). Update modules/README-TEMPLATE.md with ## NFRs section. Add tests/test_module_standards.py for automated enforcement.
  • Status: complete (v1.8.0)
  • Depends on: [34]
  • Requirements: REQ-95, REQ-96
  • Success Criteria:
    • modules/STANDARDS.md exists with L1+L2 authoring + review standards.
    • Catalog index includes all primitives; template has NFRs section.
    • Automated standards test passes for all modules.
    • pytest + run_ci.sh green.

Phase 36 — schemas-adapters-pipelines-readmes

  • Description: Author schemas/README.md (how to write schemas, wire into platform, test in CI, dependencies, existing catalog), pipelines/README.md (how to write pipeline contracts, wire into workflows, test, dependencies, catalog), adapters/README.md (how to write adapters, wire into platform, test, dependencies, catalog). Add tests/test_docs_coverage.py to validate presence + required sections.
  • Status: complete (v1.8.0)
  • Depends on: [35]
  • Requirements: REQ-97, REQ-98, REQ-99
  • Success Criteria:
    • All 3 READMEs exist with comprehensive documentation.
    • CI validates their presence.
    • pytest + run_ci.sh green.

Phase 37 — verify

  • Description: 4-layer verification (structural, behavioral, security, quality) of all v1.8 phases. Re-verify each P1 (P1-3..P1-9 + S1) is resolved. Verify all new features (encryption, deletion protection, uptime, decommission, standards, docs) have dedicated tests.
  • Status: complete (v1.8.0)
  • Depends on: [36]
  • Requirements:
  • Success Criteria:
    • All 4 layers pass; each P1 fix + each new feature has a dedicated test.
    • pytest passes (~358 tests); run_ci.sh exits 0; run_platform.sh --check-only exits 0.

Phase 38 — review-audit-complete

  • Description: Multi-persona code review across the full v1.8 diff. Audit (reconstruction, file discipline, branch hygiene, commit discipline). Complete: update REQUIREMENTS.md (REQ-76..99), ROADMAP.md (v1.8 complete), PROJECT.md. Tag v1.8.0. Update floating v1.8 + v1 tags. Bump uses:/ref: from @v1.6 to @v1.8.
  • Status: complete (v1.8.0)
  • Depends on: [37]
  • Requirements:
  • Success Criteria:
    • Review: 0 new P0/P1; all P1-3..P1-9 + S1 resolved; 3 new requirements delivered.
    • Audit: clean; 0 outstanding issues.
    • Tag v1.8.0 created; floating tags updated.

After Phase 38: COMPLETE gate — review → ship v1.8.0 → audit.


v1.9 (complete — design doc refresh + contract interpolation + per-env CI jobs + stub implementation + P1-1 remediation, tag v1.9.0)

The v1.9 milestone closes four gaps left by v1.8 (user-directed, 2026-07-23): stale design docs, no contract interpolation, promotion requires editing the environment field, and unimplemented stubs. It also closes P1-1 (adapter hardcoded defaults, deferred from v1.2).

Phase 39 — design-doc-refresh-and-p1-1-parameterization

  • Description: Refresh core/hitl_matrix_design.md (no stale "dev-only spike"/"v1.2 wires the gates" framing; v1.9 wiring section; 8-concern matrix marked implemented offline-testable subset) + core/audit_ledger_design.md (outbox marked shipped+production since v1.8; S3 Object Lock + JWS + worker + DLQ + checkpoints deferred D-083). P1-1: move adapter ECS/ALB/VPC hardcoded defaults (desired_count, launch_type, family, target_type, load_balancer_type, Name tags) into L1 interface.json inputs with defaults; the adapter reads from inputs; the resolver routes wires to the sub-resource that declares the input.
  • Status: complete (v1.8.1)
  • Depends on:
  • Requirements: REQ-100, REQ-101, REQ-102
  • Success Criteria:
    • Both design docs refreshed; no stale framing; test_design_docs_current.py passes.
    • Adapter has no hardcoded ECS/ALB/VPC defaults; overrides flow through; test_p1_1_adapter_parameterization.py passes.
    • v1.1 S3 regression passes; pytest 371 (was 350, +21); run_ci.sh exits 0; run_platform.sh --check-only exits 0.

Phase 40 — contract-interpolation

  • Description: ${env.<field>} + ${contract.<field>} resolver expansion from environment onboarding JSON (D-081). Environment JSON schema (schemas/environment.schema.json) + qa/prod/dr placeholder bindings. core/environment_check.py gains load(). Sample contracts use naming patterns that include region, account id, environment (e.g. acdl-${env.environment}-${contract.module}-${env.account_id}-${env.region}). Expansion is recursive (D-087), post-schema-validation, pre-IR-resolution; unknown tokens raise ValueError. resolve() accepts environment_override (D-088).
  • Status: complete (v1.8.2)
  • Depends on: [39]
  • Requirements: REQ-103, REQ-104
  • Success Criteria:
    • schemas/environment.schema.json exists; 4 env files validate; load() works.
    • _expand_vars in resolver; unknown tokens raise; recursive over dicts/lists/strings.
    • Sample contracts use ${env.*} + ${contract.*} naming patterns; resolve to concrete values.
    • tests/test_environment_schema.py + tests/test_interpolation.py + tests/test_sample_contracts_interpolate.py pass.
    • pytest 406 (was 371, +35); run_ci.sh exits 0; run_platform.sh --check-only exits 0.

Phase 41 — per-environment-ci-jobs

  • Description: Per-env contract files (static-assets + microservice × dev/qa/prod/dr, REQ-105) using interpolation. Deploy workflow (.github + .gitea, byte-identical) declares an environment workflow_call input (REQ-106); run_platform.sh --environment <name> overrides the contract's environment at load time (D-088, before schema validation + interpolation). resolve() accepts environment_override. Consumer guide documents the per-env caller-workflow pattern (4 jobs, one per environment) + HITL gate structure (approve_qa/approve_prod/approve_dr, D-042) + interpolation reference table. Promotion = running the matching job; no environment field editing.
  • Status: complete (v1.8.3)
  • Depends on: [40]
  • Requirements: REQ-105, REQ-106
  • Success Criteria:
    • 8 per-env contract files exist + validate + resolve to correct env.
    • Deploy workflow has environment input (byte-identical Gitea + GitHub); run_platform.sh --environment overrides; resolver supports environment_override.
    • Consumer guide documents per-env caller workflows + promotion-without-editing + HITL gates + interpolation reference.
    • tests/test_per_env_contracts.py + tests/test_deploy_workflow_env_input.py + tests/test_consumer_guide_per_env_section.py pass.
    • pytest 446 (was 406, +40); run_ci.sh exits 0; both deploy workflows byte-identical.

Phase 42 — stub-implementation

  • Description: route_halt_artifact real (SNS publish + outbox fallback, REQ-107) + SNS topic acdl-sod-halt in terraform/platform/main.tf. HITL attestation gates (core/hitl_gates.py, REQ-108) — records approver to outbox, runs SoD on prod, invokes the attestation matrix; run_platform.sh calls attest before apply for qa/prod/dr (dev skips). 8-concern attestation matrix (core/attestation_matrix.py, REQ-109, D-084) — offline-testable concerns run for real; operator-supplied concerns accept signed evidence artifacts validated for freshness + schema; signature skip when ACDL_ATTESTATION_SIGNING_KEY_ID unset (D-089). Wiz real API client (WizClient, REQ-110) — GraphQL queries + pagination + graceful degrade. Kyverno translator fleshed out (REQ-111) — full PolicyReport mapping + skip-with-reason + inactive-for-TF guard + --kube-version stub.
  • Status: complete (v1.8.4)
  • Depends on: [41]
  • Requirements: REQ-107, REQ-108, REQ-109, REQ-110, REQ-111
  • Success Criteria:
    • route_halt_artifact publishes to SNS when ARN set; outbox fallback when unset; SNS topic in Terraform.
    • hitl_gates.attest records approver; SoD blocks on identity equality; dev skips; run_platform.sh has the HITL step.
    • attestation_matrix.check runs 8 concerns; offline concerns pass; operator-supplied missing → block for prod; expired → block; signature skip when key unset.
    • Wiz WizClient real client + pagination + graceful degrade; fetch_and_adapt translates.
    • Kyverno full mapping (pass/fail/skip/warn + severity + skip-with-reason + resource construction); inactive guard preserved; --kube-version parsed.
    • tests/test_route_halt_artifact.py + test_hitl_gates.py + test_attestation_matrix.py + test_wiz_adapter_real_client.py + expanded test_kyverno_adapter.py pass.
    • pytest 493 (was 446, +47); run_ci.sh exits 0; run_platform.sh --check-only exits 0.

Phase 43 — verify-review-audit-complete

  • Description: 4-layer verify (structural, behavioral, security, quality) of all v1.9 phases. Multi-persona review (0 P0, 0 P1). Audit (reconstruction, file discipline, branch hygiene, commit discipline — all clean). REVIEW.md reconstructed (D-086). Complete: update REQUIREMENTS.md (REQ-100..111), ROADMAP.md, PROJECT.md. Tag v1.9.0; update floating v1.9 + v1 tags. Bump uses:/ref: from @v1.6@v1.9.
  • Status: complete (v1.9.0)
  • Depends on: [42]
  • Requirements:
  • Success Criteria:
    • 4-layer verify PASS; 493 tests; run_ci.sh + run_platform.sh --check-only green.
    • Review: 0 P0, 0 P1; REVIEW.md reconstructed with v1.9 content (D-086).
    • Audit: clean; all 12 v1.9 commits have ---ci--- blocks.
    • Tag v1.9.0 created; floating tags updated; uses: bumped to @v1.9.

After Phase 43: COMPLETE gate — review → ship v1.9.0 → audit. DONE.


v1.10 (complete — pipeline regression fix + capability re-verification + verified-reality rewrite, tag v1.10.0)

The v1.10 milestone corrects a structural defect and a credibility gap surfaced in the 2026-07-27 CLARIFY/RESEARCH stages:

  1. VERIFY is diff-scoped — it checks the phase diff only, never re-runs underlying capability. 8 NFR-patch phases (v1.9.1→v1.9.8) passed VERIFY while the platform decayed underneath.
  2. Advertised capability is not currently reproducible — v1.2 ECS E2E and v1.7 pipelines ran once historically but decayed; decks presented them as current without disclosing the decay.
  3. Deck work was sequenced backwards — re-verify → rewrite → polish is the honest order; v1.9.x did it backwards for 8 phases.

User decisions: D-090 (no cap on sweep; fix everything; unbounded risk accepted), D-091 (regression-class VERIFY), D-092 (local emulating adapters), D-093 (re-verify v1.1→v1.8; v1.0 demo excluded), D-094 (rewrite docs/decks to verified reality; unfreeze decks).

Phase 52 — pipeline-regression-verify-fix

  • Description: Add a regression-class VERIFY that re-runs capability checks (not just diff checks), at minimum on milestone completion. Regression run executes the local-emulator tier for every capability marked Verified in prior milestones; any failure blocks milestone completion. Records regression: { capability, status } in ---ci--- blocks.
  • Status: complete (v1.9.9)
  • Depends on:
  • Requirements: REQ-112
  • Success Criteria:
    • VERIFY supports regression mode; milestone completion requires a clean regression run.
    • A regression run against current code surfaces decay (fails closed).
    • tests/test_verify_regression_mode.py passes.

Phase 53 — local-emulating-adapters

  • Description: Build local emulating adapters so the platform is fully locally testable without cloud credentials: flat-file DynamoDB outbox, local ECS emulator (synthetic HTTP 200 from local shell), local S3 state backend (flat-file tfstate), local Lambda stub (in-process handler invocation). Same interfaces as the live adapters.
  • Status: complete (v1.9.10)
  • Depends on: [52]
  • Requirements: REQ-113
  • Success Criteria:
    • All local adapters exist; headline E2E runs end-to-end against the local tier with no cloud credentials.
    • tests/test_local_emulating_adapters.py passes.
    • run_platform.sh --local runs the full pipeline locally.

Phase 54 — v1.1-v1.8 capability-reverification-sweep

  • Description: Enumerate every capability advertised in v1.1→v1.8 PROJECT/ROADMAP to .ciagent/CAPABILITY_INVENTORY.md. Re-verify each: headline E2E at both tiers (live AWS + local emulator, both must pass); all other capabilities at the local tier via emulating adapters. Tag each Verified/Decayed/Broken. Fix every Decayed/Broken capability in-sweep (D-090: no cap; all must end Verified) until Verified. v1.0 demo excluded as archived/superseded.
  • Status: complete (v1.9.11)
  • Depends on: [53]
  • Requirements: REQ-114
  • Success Criteria:
    • Every v1.1→v1.8 advertised capability is tagged Verified in CAPABILITY_INVENTORY.md.
    • Headline E2E passes at both tiers.
    • Regression run (Phase 52) is clean against the re-verified state.

Phase 55 — rewrite-to-verified-reality

  • Description: Rewrite PROJECT.md (add "Capability Status (Re-Verified 2026-07-27)" section + decay disclosure), ROADMAP.md (v1.9.x entries noted as deck-freeze / superseded-by-reverification), and both leadership decks so every capability claim reflects the re-verified status. Remove any claim that cannot be demonstrated live. Re-render HTML; upload PPTX to the v1.10.0 release. Decks unfrozen only after this lands.
  • Status: complete (v1.9.12)
  • Depends on: [54]
  • Requirements: REQ-115
  • Success Criteria:
    • PROJECT/ROADMAP/decks match CAPABILITY_INVENTORY.md exactly.
    • ci-doc-verifier confirms no stale capability claims remain.
    • Decks unfrozen; v1.10.0 tagged; Gitea release published.

After Phase 55: COMPLETE gate — review → ship v1.10.0 (next minor; fix/test/docs, not a breaking schema change) → audit. DONE.


v1.11 (complete — RESTART: stateless adapter + pipeline-driven module lifecycle testing, tag v1.11.0)

The v1.11 milestone closes the two GRILL escalations blocking the leadership pitch: G-005 (6 IAM-gated cloud capabilities CAP-017..022 deploy-unverified) and G-008 (no cost documentation despite live AWS resources).

Why a restart. The first v1.11 attempt (P56 IAM re-bootstrap + P57 live-deploy-microservice, branches phase/56-iam-re-bootstrap + phase/57-live-deploy-microservice, now abandoned) produced five defects: (1) 4 VPCs created when 1 should have — the adapter emitted per-contract state keys with no VPC sharing; (2) Python scripts made lifecycle changes directly to the cloud (verify_deploy_microservice.py ran terraform apply -auto-approve); (3) no L1 module lifecycle testing — tests/test_adapter.py only string-validated HCL, never ran terraform apply/modify/destroy; (4) no L2 integration testing; (5) lifecycle was managed by Python, not terraform. The restart branches off v1.10.2 and rebuilds v1.11 on three corrections.

The three corrections.

  1. Stateless adapter. adapters/terraform/adapter.py (918 lines, 3 hardcoded constant tables TYPE_MAP/INPUT_MAP/OUTPUT_MAP, 39 type-specific branches) is rewritten to a ~80-line stateless assembler. Each L1 module ships a real terraform/ module dir (versions.tf/variables.tf/locals.tf/main.tf/outputs.tf) owning its resource shape, nested HCL blocks, and defaults. The adapter reads the registry, emits a root main.tf instantiating each L1 as module "x" { source = "..." ... } with resolved inputs and wired refs. interface.json stays engine-agnostic; the terraform dir is the engine binding. Defaults move into locals.tf (heavy interpolation of vars against sensible defaults).
  2. Terraform owns lifecycle. scripts/run_platform.sh gains --apply and --destroy modes. Python never runs terraform. scripts/verify_deploy_microservice.py is deleted. The shell owns all apply/modify/destroy; Python only orchestrates the shell (and may use boto3 for read-only verify probes in a future QA milestone, not this one).
  3. Pipeline-driven testing. A modules-lifecycle pipeline (Gitea + GitHub, byte-identical) matrix-runs each L1 module's examples/{simple,complex}.yml contracts through apply→modify→destroy against live AWS. No per-module Python/pytest. The "test" = the pipeline cell going green (terraform apply exit 0 → modify exit 0 → destroy exit 0).

Single platform VPC. terraform/platform/main.tf owns ONE VPC; the microservice composition drops its vpc child and references the platform VPC via data source. The standalone vpc L1 module stays (consumers deploy their own VPCs). State keys are deterministic and env-aware (spike/{contract.id}/{contract.environment}/terraform.tfstate), stable across apply/modify/destroy — the same contract+env always hits the same state key, so terraform modifies rather than duplicates.

L2 = composition only. L2 modules keep composition.json only (no L2 terraform files). The composition must be deterministic: same contract → same resolved stack → same state key, every time.

Versioning. Feature milestone (P56a/P56b/P57/P58/P59/P60/P61/P62 are feat). Ship tag at milestone COMPLETE: v1.11.0 (v1.10.2 → v1.11.0).

Wave ordering. Wave 1 (P56a → P56b → P57 → P58) is sequential — the stateless adapter, shell lifecycle modes, and platform VPC are prerequisites for all testing. Wave 2 (P59 → P60) authors then runs the L1 lifecycle pipeline. Wave 3 (P61 → P62) authors then runs the L2 lifecycle pipeline. Wave 4 (P63 → P64 → P65) closes G-005/G-008 + teardown + deck rewrite.

Phase P56a — stateless-adapter-rewrite (Wave 1)

  • Description: Rewrite adapters/terraform/adapter.py from a 918-line monolith (3 constant tables + 39 type-specific branches) to a ~80-line stateless assembler. Author modules/l1/s3/terraform/ (versions.tf/variables.tf/locals.tf/main.tf/outputs.tf) as the reference module proving the assembly path end-to-end. Extend modules/registry.json with a terraform_dir field. Rewrite modules/STANDARDS.md §8 from "three tables + specialized branches" to "stateless assembler + per-module terraform dir". Rewrite tests/test_adapter.py to assert module-instantiation assembly (root main.tf contains module "x" { source = ... } blocks with correct inputs + refs), not HCL string matching.
  • Status: active
  • Depends on:
  • Requirements: REQ-123
  • Success Criteria:
    • grep -n "TYPE_MAP\|INPUT_MAP\|OUTPUT_MAP\|rtype ==" adapters/terraform/adapter.py returns nothing.
    • wc -l adapters/terraform/adapter.py < 100.
    • modules/l1/s3/terraform/ passes terraform init + validate standalone.
    • Adapter, given the s3 instance, emits a root main.tf that terraform init + validate accepts.

Phase P56b — l1-module-terraform-authoring (Wave 1)

  • Description: Author the remaining 11 L1 module terraform subdirs (vpc, ecs-cluster, ecs-service, iam-role, alb, ecr, cloudfront, waf, rds, kms-key, uptime) with the full versions.tf/variables.tf/locals.tf/main.tf/outputs.tf split. Defaults currently hardcoded in the adapter (CIDR blocks, assume_role_policy JSON, ECR/logs inline policy, Fargate requires_compatibilities, assign_public_ip, listener/target ports) move into locals.tf as heavy interpolation of vars against sensible defaults. Multi-resource modules get the full split; trivial single-resource modules (kms-key, ecr) may inline locals in main.tf. Each module's interface.json stays engine-agnostic. Add terraform_dir to each registry entry.
  • Status: pending
  • Depends on: [P56a]
  • Requirements: REQ-124
  • Success Criteria:
    • All 12 terraform/ subdirs pass terraform init + validate standalone.
    • No defaults remain in the adapter.
    • Each registry entry has a terraform_dir field.

Phase P57 — shell-orchestrator-lifecycle-modes (Wave 1)

  • Description: scripts/run_platform.sh gains --apply <contract.yml> and --destroy <contract.yml> modes. --apply runs resolve → adapter → terraform initterraform apply -auto-approve (HITL gate for qa/prod/dr). --destroy runs resolve → adapter → terraform destroy -auto-approve (gated behind --decommission + CR validation, D-070 two-step). --modify is implicit (a second --apply with a changed contract produces a terraform diff). Delete scripts/verify_deploy_microservice.py (the offending script that ran terraform apply from Python).
  • Status: pending
  • Depends on: [P56b]
  • Requirements: REQ-125
  • Success Criteria:
    • run_platform.sh --apply and --destroy modes exist and are the ONLY path to terraform apply/destroy.
    • grep -rn "terraform apply\|terraform destroy" scripts/*.py returns nothing.
    • verify_deploy_microservice.py no longer exists.

Phase P58 — single-platform-vpc-deterministic-state (Wave 1)

  • Description: Add a single VPC (aws_vpc.acdl_shared 10.0.0.0/16, 2 public subnets, IGW, route table, ECS security group) to terraform/platform/main.tf; output vpc_id, public_subnet_ids, ecs_security_group_id. modules/l2/microservice/composition.json drops the vpc child and references the platform VPC via a data_sources block. core/contract_resolver.py resolves data:platform/vpc references. The adapter emits data "terraform_remote_state" "platform" + data "aws_vpc"/data "aws_subnets" blocks, never an inline aws_vpc for the microservice stack. State key fix: spike/{contract.id}/{contract.environment}/terraform.tfstate (deterministic, env-aware, stable across lifecycle). Add state_key derivation to schemas/contract.schema.json.
  • Status: pending
  • Depends on: [P57]
  • Requirements: REQ-126
  • Success Criteria:
    • terraform/platform apply creates exactly ONE VPC.
    • contracts/microservice.yml resolution produces NO aws:ec2:vpc resource.
    • Two contract applies (dev + prod) → ONE VPC, two state keys, two ECS services.
    • Same contract+env re-applied → same state key → terraform modifies, never duplicates.

Phase P59 — l1-lifecycle-pipeline-author (Wave 2)

  • Description: Author pipelines/modules-lifecycle.yml (declarative contract: validate → resolve → apply → modify → destroy) + byte-identical .gitea/workflows/modules-lifecycle.yml + .github/workflows/modules-lifecycle.yml. Matrix over 12 L1 modules × {simple, complex} example contracts. Each cell: run_platform.sh --apply examples/simple.ymlrun_platform.sh --apply examples/complex.yml (same state key → terraform modifies) → run_platform.sh --destroy examples/complex.yml. VPC-dependent L1s (alb, ecs-service, rds, uptime) reference the platform VPC applied by a prerequisite job; standalone vpc L1 applies its own. Trigger: pull_request: [main] + workflow_dispatch. Author schemas/modules-lifecycle-pipeline.schema.json. Extend tests/test_pipeline_contract.py (offline: validate schema + byte-identical).
  • Status: pending
  • Depends on: [P58]
  • Requirements: REQ-127
  • Success Criteria:
    • Pipeline YAML validates against its schema.
    • Gitea + GitHub workflows are byte-identical.
    • test_pipeline_contract.py passes (offline).
    • Matrix lists all 12 L1 modules × 2 examples.

Phase P60 — l1-lifecycle-pipeline-live-run (Wave 2)

  • Description: Run the P59 pipeline against live AWS; fix every module whose apply/modify/destroy fails. Each failing cell is a module defect: bad terraform/ subdir (resource shape, nested blocks, defaults), bad example contract, or bad adapter assembly. Fixes land in modules/l1/<module>/terraform/*.tf, modules/l1/<module>/examples/*.yml, and rarely the adapter assembler. No new Python files.
  • Status: pending
  • Depends on: [P59]
  • Requirements: REQ-127
  • Success Criteria:
    • Full L1 lifecycle matrix green: 12 modules × 2 examples = 24 cells, each apply→modify→destroy exit 0.
    • No live resources remain after the run (destroy enforced).
    • primitives-plan.yml (plan-only) still passes.

Phase P61 — l2-lifecycle-pipeline-author (Wave 3)

  • Description: Extend pipelines/modules-lifecycle.yml + both forge workflows with an L2 matrix: static-assets × contracts/static-assets.yml (apply → modify: add WAF rule → destroy) and microservice × contracts/microservice.yml (apply → modify: desired_count 1→2 → destroy, references platform VPC). Author modules/l2/static-assets/examples/complex.yml + modules/l2/microservice/examples/complex.yml (modify variants, defined within the modules). L2 = composition only (no L2 terraform files); the composition must be deterministic (same contract → same resolved stack → same state key, every time).
  • Status: pending
  • Depends on: [P60]
  • Requirements: REQ-128
  • Success Criteria:
    • L2 matrix lists both modules with apply→modify→destroy cells.
    • Composition resolution is deterministic (same contract → same stack, byte-identical).

Phase P62 — l2-lifecycle-pipeline-live-run (Wave 3)

  • Description: Run the L2 lifecycle pipeline live; fix composition wiring + adapter assembly until green. This replaces the deleted verify_deploy_microservice.py — the pipeline IS the verify. CAP-017..022 boto3 probes are deferred to a future QA milestone. Fixes land in modules/l2/<module>/composition.json, modules/l2/<module>/examples/*.yml, core/contract_resolver.py, and rarely the adapter. No new Python files.
  • Status: pending
  • Depends on: [P61]
  • Requirements: REQ-128
  • Success Criteria:
    • L2 matrix green: static-assets + microservice, each apply→modify→destroy exit 0.
    • Microservice apply creates NO inline VPC (references platform VPC).
    • Same state key across apply/modify/destroy (deterministic).
    • patterns-plan.yml (plan-only) still passes.

Phase P63 — regression-registry-cost-docs (Wave 4)

  • Description: Add CAP-017..022 to core/regression_verify.py registry (evidence = lifecycle pipeline green, not boto3 probes). Author .ciagent/COST.md (AWS Cost Explorer 6-day window query: v1.0 ship 2026-07-21 → v1.10 complete 2026-07-27; document monthly + per-day if available). Closes G-008.
  • Status: pending
  • Depends on: [P62]
  • Requirements: REQ-119, REQ-121
  • Success Criteria:
    • Regression registry includes CAP-017..022 with "lifecycle pipeline green" evidence.
    • COST.md documents the v1.0→v1.10 spend window.

Phase P64 — pre-mortem-teardown (Wave 4)

  • Description: Author .ciagent/PRE_MORTEM.md (v1.10 decay root cause + forward pre-mortem for the OSS reference + leadership pitch). run_platform.sh --decommission with CR CHG0680001 — tears down ALL deployed stacks INCLUDING the 4 drifted VPCs from the failed first attempt. HITL SRE gates (D-070 two-step). D-096 enforced (live resources do not persist past v1.11).
  • Status: pending
  • Depends on: [P63]
  • Requirements: REQ-120, REQ-122
  • Success Criteria:
    • PRE_MORTEM.md documents the decay root cause + forward pre-mortem.
    • All deployed stacks torn down; zero live ACDL resources remain.

Phase P65 — rewrite-caps-decks (Wave 4)

  • Description: Rewrite CAPABILITY_INVENTORY.md, PROJECT.md §Capability Status, and both leadership decks: CAP-017..022 → "Verified live-aws via lifecycle pipeline ; torn down to zero-cost steady state." Remove the IAM-drift framing. Add the cost appendix slide (P63) + pre-mortem reference (P64). Re-render HTML; upload PPTX to the v1.11.0 release. ci-doc-verifier confirms no stale "deploy-unverified" claims remain.
  • Status: pending
  • Depends on: [P64]
  • Requirements: REQ-116, REQ-118
  • Success Criteria:
    • CAPABILITY_INVENTORY + PROJECT + decks all reflect "Verified live-aws via lifecycle pipeline; torn down to zero-cost."
    • ci-doc-verifier confirms no stale "deploy-unverified" claims.
    • HTML re-rendered; PPTX uploaded to v1.11.0 release.

After Phase P65: COMPLETE gate — review → ship v1.11.0 (next minor; feature milestone) → audit. DONE.

v1.12 (complete — Presentation Refinement, tag v1.12.0)

The v1.12 milestone refines the leadership presentation decks to reflect the verified reality after v1.11. The v1.11 P65 deck-rewrite task did not fully land on the deck artifacts: the rendered HTML still claimed 6 cloud capabilities were "deploy-unverified (IAM drift)", the road-to-north-star diagram still showed v1.10 as "NEXT", and the v1.11 architecture stories (stateless adapter, pipeline-driven lifecycle testing) were absent. The v1.10 decay lesson (PRE_MORTEM.md FM-3) requires decks to match verified reality exactly, not outrun it.

Scope: leadership decks only (docs/presentations/) across all four layers (source markdown, Marp deck, rendered HTML, talking points) + diagrams + README. Plus one real adapter fix + two probe fixes required to make the deck claims true, and a CI lifecycle-mode flag (REQ-134) that defaults the lifecycle tests to plan-only.

Why the code fixes. The v1.12 regression gate run (Phase 66) found CAP-013 (a real adapter dedup defect — multi-resource L1s produced invalid Terraform) + CAP-017/018 (two regression-probe bugs). The inventory's "22/22 Verified" claim was overstated until CAP-013 was fixed. The pre- mortem mitigation (verified-only claims) made the fixes mandatory.

Why the lifecycle flag. The lifecycle pipeline defaulted to full apply→modify→destroy, which requires AWS credentials + cost on every PR. REQ-134 adds the ACDL_LIFECYCLE_MODE CI variable (workflow_dispatch input lifecycle_mode, default plan) so the pipeline runs plan-only on every PR (fast, no AWS mutation, no cost) and full only on override.

Phase breakdown (6 phases)

  • P66 — init + research. Drift audit (9 items) comparing docs/presentations/* against v1.11-verified reality. Regression gate (D-091) re-run surfaced 3 Broken capabilities; root-cause analysis classified CAP-013 (real adapter defect), CAP-017/018 (probe bugs). REQ-129..133 added.
  • P67 — fix adapter dedup + 2 probe bugs (REQ-129/130). The adapter's module-call dedup logic rewritten: multi-resource L1s (ecs-service, alb) now emit ONE module block named by the composition child id, with expanded sub-ids rewritten via id_remap (stack outputs + cross-module ref: inputs). terraform validate succeeds for the microservice; adapter 192 lines (< 200 gate). CAP-017 probe: locals.tf conditional on local.* usage. CAP-018 probe: LocalLambdaStub constructed with the required outbox arg. Regression gate: 22/22 Verified.
  • P67b — lifecycle tests plan-only default + ACDL_LIFECYCLE_MODE flag (REQ-134). The four lifecycle scripts dispatch to --plan-only (plan mode, default) or --apply/--destroy (full mode). Both workflows (byte-identical) expose lifecycle_mode as a workflow_dispatch input; CI VPC jobs skipped in plan mode. 24 new tests.
  • P68 — sync decks source .md (REQ-131/132). Re-verification headers → 22/22 Verified. De-duplicated story-beat lines. Version refs @v1.10 → @v1.11. road-to-north-star.mmd re-rendered. New A6 (real COST.md figures + pre-mortem) + A7 (stateless adapter + lifecycle pipeline + plan-only default) in both decks.
  • P69 — Marp + talking points + HTML render (REQ-133). Re-synthesized both Marp decks (10 main + 7 appendix = 17 slides). Re-distilled both talking-points files (added the missing A6/A7 sections). Re-rendered both HTML (committed). Exported both PPTX (held for the v1.12.0 release).
  • P70 — verify + review + complete. Multi-persona code review: no P0; 2 P1 testing gaps remediated (6 CAP-013 regression tests added — terraform validate + dedup unit assertions). Audit clean. 522 tests pass. Ship v1.12.0.

Outcome: the decks now honestly claim 22/22 Verified (backed by the regression gate), reflect the v1.11 architecture (stateless adapter + lifecycle pipeline), carry the real cost figures + pre-mortem, and the lifecycle pipeline defaults to plan-only. The v1.10 "deploy-unverified (IAM drift)" framing is disclosed as closed, not hidden.

Ship tag at milestone COMPLETE: v1.12.0 (v1.11.0 → v1.12.0; feature milestone — includes the adapter fix + lifecycle flag). DONE.

v1.13 (complete — Presentation Polish, tag v1.13.0)

The v1.13 milestone polishes both leadership decks for clarity, impact, and storytelling best practices. It is a docs-only NFR patch — no code, no capability claims changed, no schema changes.

Why. The v1.12 decks were factually correct but rhetorically flat: category-name headlines ("The Contract-Driven Model", "Zero-Trust by Default"), dense 56 bullet slides, formulaic italic transition lines on every slide, and body fonts at 22px (below the 24pt readability floor). v1.13 applies the storytelling + design best practices the leadership audience requires.

What changed. Both decks (how-the-platform-works + the-developer-experience) across all 4 pipeline layers (source .md-marp.md.html-talking-points.md):

  • Action headlines replace category names — each slide title states the takeaway, not the topic ("One YAML file. The platform owns everything else." not "The Contract-Driven Model").
  • Story-arc restructure — Intro ~10% / Body ~80% (35 points) / Conclusion ~10%. Before/after 2-slide sequence on Problem → North Star.
  • Removed all <em class="story"> transition lines — flow now carried by action headlines + talking points (saved ~1520 words × 17 slides).
  • Bullets ≤12 words, 34 per main slide (was 56). Cut parentheticals, sub-clauses, redundant restatements.
  • Larger fonts — body 22→26px, h1 34→40px, h2 26→32px, blockquote 20→24px. High contrast preserved, no animations, maturity badges intact.
  • 6 new mermaid diagrams → PNGs:
    • platform-works-02-frictions (2×2 quadrant of the four frictions)
    • platform-works-03-north-star (before/after: today's queue vs. ACDL)
    • platform-works-07-zero-trust (OIDC + ABAC flow)
    • developer-experience-05-catalog (primitives → composed modules)
    • developer-experience-07-decommission (6-node gate flow with 2 SRE gates)
    • developer-experience-08-semver (floating/pinned/major-only timeline)
  • Appendix expanded — "Security by Construction" (formerly a dense main slide) moved to appendix A3; platform deck now 10 main + TOC + 8 appendix (19 slides); developer deck 10 main + TOC + 7 appendix (18 slides).

Phases:

  • P71 — deck polish (single phase). Restructured both decks across all 4 layers. Created 6 new .mmd + 6 new .png files. Re-rendered both HTML. Re-distilled both talking-points to match the new slide structure. Multi-persona code review: 0 P0, 2 P1 auto-fixed (slide-count metadata in source .md headers + README.md directory layout drifted — both synced). 522 tests pass. No code files touched.

Outcome: the decks now read as a story (problem → solution → evidence), each slide has one idea with an action headline, the body is scannable in 2 seconds, and the visuals carry the mechanism where bullets undersold it. 22/22 Verified framing, badge statuses, and capability claims preserved verbatim from v1.12. No factual drift.

Ship tag at milestone COMPLETE: v1.13.0 (v1.12.0 → v1.13.0; docs-only NFR patch — final patch IS the deliverable, no separate milestone tag). DONE.

v1.13.1 (complete, tag v1.13.1): config.json schema migration

NFR patch: regenerated .ciagent/config.json to the updated CIAgent v2 config structure. The old config used the pre-v2 schema (mode field, projects[].milestone/status/branch/tag, top-level gitea block, missing secrets/release/ship/backend/ideation/personas/logging/telemetry sections). The new config conforms to CIAgentConfig (config.ts:156) and passes validateConfig() + loadConfig() deep-merge.

Multi-persona code review: 0 P0, 2 P1/P2 auto-fixed (.ciagent/logs/ gitignored, trailing newline restored). Gitea release id 253. Docs-only NFR patch (no code changes).

v1.13.2 (complete, tag v1.13.2): presentation badge cleanup + platform architecture diagram

NFR patch (docs-only). Two presentation changes across both leadership decks (how-the-platform-works + the-developer-experience):

  1. Badge cleanup — removed all testing and agentic maturity badges from every deck layer (source .md, Marp -marp.md, rendered .html, talking-points). Only the planned badges are retained where relevant. The Marp inline style: CSS dropped the .testing / .agentic rules (kept .planned). The README maturity-framing section updated to describe only the Planned badge. Empty table cells (dev environment Maturity row) normalized to .
  2. Platform architecture diagram — added a new Slide 3 "The platform at a glance" to both decks, right after the problem statement. A shared mermaid source (assets/mmd/platform-architecture.mmd) renders to assets/png/platform-architecture.png and is embedded in both Marp decks. The diagram shows the full logical topology: consumer surfaces (technical dev
    • citizen dev) → contract schema → central pipeline (8 fixed stages) → cross-cutting components (module catalog, stateless engine adapter, platform-managed environments, HITL gates, hash-chained evidence stream) → downstream AWS resources. All subsequent slides renumbered 411; talking points + README directory layout + slide counts (10→11 main, 19→20 / 18→19 total) synced. Both HTML decks re-rendered via Marp.

Docs-only NFR patch (no code changes).


v1.14 (complete — NFR Refinement: bug fixes, security, stubs, tests, docs, tag v1.13.24)

The v1.14 milestone is a 20-phase NFR sweep — no new features. It clears the open P1/P2 backlog from the v1.11 review, hardens the security posture (swallowed errors, hardcoded account ID, IAM wildcards, schema validation, credential hygiene), resolves stub/missing functionality (Kyverno --kube-version, orphan artifacts), adds test coverage for 7 untested scripts, and refines all documentation (ARCHITECTURE.md v1.11v1.14 addenda, stale @v1.61.9@v1.13 refs, COST.md/GRILL/ IAM_POLICY.md sync, STANDARDS.md reconciliation).

Milestone type: NFR (all phases fix/test/docs/chore/refactor). The final phase's patch IS the release — no separate milestone tag. Tags run on the v1.13.x line: v1.13.3 (P0) → v1.13.4..v1.13.23 (P1P20) → v1.13.24 (P21 final = milestone release).

Wave ordering:

  • Wave 1 (P1P6): bug fixes — P1 before P2 (composition depends on dedup correctness); P3P6 independent.
  • Wave 2 (P7P12): security — P8 before P9 (externalized account ID for IAM ARNs); rest independent.
  • Wave 3 (P13P17): stub/test/CI/hygiene — P15 benefits from P7 landing first; P17 after P14 (both touch config.json).
  • Wave 4 (P18P20): standards/docs/VPC — P19 last (reflects all prior phases).

Phase P1 — adapter-dedup-diagnostic (Wave 1)

  • Description: Fix P1-1 from the v1.11 review. The adapter dedup loop (adapters/terraform/adapter.py:159-170) silently drops resources whose module is not in the registry — a typo'd module field vanishes without diagnostic. Raise ValueError (preserving the pre-dedup contract) so the misconfiguration surfaces instead of being silently omitted.
  • Status: pending
  • Depends on:
  • Requirements: REQ-135
  • Success Criteria:
    • A resource with module: nonexistent@1.0.0 raises ValueError with a descriptive message, not a silent drop.
    • Existing registered-module dedup behavior preserved (multi-resource L1s still merge into one module "x" { ... } block).
    • pytest passes; run_ci.sh exits 0.

Phase P2 — static-assets-wiring-fix (Wave 1)

  • Description: Fix P1-2. modules/l2/static-assets/composition.json drops default_ttl/max_ttl/price_class/viewer_protocol_policy (accepted by cloudfront/interface.json but never wired) and WAF is unconditionally present (no features/conditional). Wire the cloudfront inputs; make WAF conditional via a waf_enabled feature flag so examples/complex.yml is a real modify (adds CDN + WAF), not a no-op re-apply.
  • Status: pending
  • Depends on: [P1]
  • Requirements: REQ-136
  • Success Criteria:
    • complex.yml resolves to a resource set that differs from simple.yml (WAF + CDN TTLs present when waf_enabled: true, absent when false).
    • The L2 static-assets lifecycle cell's "modify" step exercises a real terraform diff, not idempotent re-apply.
    • pytest passes; run_ci.sh exits 0.

Phase P3 — lifecycle-script-arg-cleanup (Wave 1)

  • Description: Fix P1-3. scripts/run_l2_lifecycle_test.sh and run_l2_lifecycle_destroy.sh advertise [ci-vpc-outputs.json] ($3) in their usage strings but never read it (the L2 path uses terraform_remote_state, not the file). Remove the vestigial arg or document that the L2 path uses remote state and the arg is accepted-but-ignored for workflow-argument parity with the L1 scripts.
  • Status: pending
  • Depends on:
  • Requirements: REQ-137
  • Success Criteria:
    • Usage strings no longer advertise a feature the scripts don't provide, OR a comment explains the L2-uses-remote-state design + parity reason.
    • pytest passes; run_ci.sh exits 0.

Phase P4 — regression-gate-evidence-hardening (Wave 1)

  • Description: Fix P1-5. core/regression_verify.py:432-519 CAP-017..022 checks are offline proxies (files exist + contracts resolve) — a module with broken HCL would pass as long as files exist. Add a terraform validate step to _check_lifecycle_module_terraform so at least HCL syntax is verified at the gate. Tighten the CAPABILITY_INVENTORY wording to "offline proxy; live apply/modify/destroy verified by the modules-lifecycle workflow run, not by this gate."
  • Status: pending
  • Depends on:
  • Requirements: REQ-138
  • Success Criteria:
    • _check_lifecycle_module_terraform runs terraform validate (or documents why it's too slow + falls back to a syntax probe).
    • CAPABILITY_INVENTORY + docstrings reflect the offline-proxy caveat honestly.
    • pytest passes; run_ci.sh exits 0.

Phase P5 — adapter-behavior-tests (Wave 1)

  • Description: Fix P2-2. Add test_adapter_dedup_merges_same_module (two resources with the same module collapse to one module "<first_id>" { ... } block with merged inputs) and test_adapter_remote_state_key_override (ACDL_REMOTE_STATE_KEY overrides the default platform/terraform.tfstate key in the emitted data terraform_remote_state block).
  • Status: pending
  • Depends on: [P1]
  • Requirements: REQ-139
  • Success Criteria:
    • Both unit tests exist in tests/test_adapter.py and pass.
    • pytest count increases; run_ci.sh exits 0.

Phase P6 — alb-name-prefix-fix (Wave 1)

  • Description: Fix P2-1. modules/l1/alb/terraform/main.tf:9 uses name_prefix = "tg-ci-" (hardcoded literal) which discards var.name entirely — the target group name is non-configurable and inconsistent with the LB name. Change to name_prefix = "${var.name}-" so the consumer's name prefixes the target group while preserving uniqueness.
  • Status: pending
  • Depends on:
  • Requirements: REQ-140
  • Success Criteria:
    • Target group name_prefix derives from var.name.
    • terraform validate passes for the alb module standalone.
    • pytest passes; run_ci.sh exits 0.

Phase P7 — swallowed-error-hardening (Wave 2)

  • Description: Narrow 6 over-broad except ...: pass/except Exception: sites: core/local_emulators.py:374 (fake_urlopen swallow → network egress risk if patching fails), core/lambda/contract_ingestor.py:157 (GitHub search failure → duplicate issues), terraform/bootstrap/create_state_backend.py:51 (over-broad → spurious create_bucket), core/output_publisher.py:100,168, terraform/bootstrap/apply_iam_baseline.py:78. Catch specific ClientError/NoSuch* exceptions; log + re-raise where silent failure masks a real defect.
  • Status: pending
  • Depends on:
  • Requirements: REQ-141
  • Success Criteria:
    • No bare except Exception: pass remains in the targeted files (grep clean for the 6 sites).
    • Specific exception types caught; errors logged with context.
    • pytest passes; run_ci.sh exits 0.

Phase P8 — account-id-externalization (Wave 2)

  • Description: Externalize the hardcoded account ID 581513795199 from 15+ sites: adapters/terraform/adapter.py:125,140, terraform/bootstrap/apply_iam_baseline.py:33, terraform/bootstrap/create_state_backend.py:33,35, scripts/push_consumer_image.py:32, terraform state-bucket names, ECR image refs. Read from ACDL_AWS_ACCOUNT_ID env (code) / data.aws_caller_identity (terraform); fall back to env for offline. Keep the COST.md account ID (accepted exposure per P2-4) but centralize the code-side.
  • Status: pending
  • Depends on:
  • Requirements: REQ-142
  • Success Criteria:
    • grep -rn "581513795199" adapters/ scripts/ terraform/ core/ returns 0 hits (excluding tests + docs).
    • ACDL_AWS_ACCOUNT_ID env read with a clear default/fallback.
    • pytest passes; run_ci.sh exits 0.

Phase P9 — iam-policy-least-privilege (Wave 2)

  • Description: Scope 6 Resource: "*" statements in terraform/bootstrap/spike_runner_policy.json (cloudfront, wafv2, kms, iam) to acdl-* ARNs. Scope iam:CreateRole etc. to arn:aws:iam::...:role/acdl-*; scope KMS to arn:aws:kms:...:key/acdl-*; narrow CloudFront/WAF where possible. Add a regression test asserting no new Resource:"*" on non-global actions.
  • Status: pending
  • Depends on: [P8]
  • Requirements: REQ-143
  • Success Criteria:
    • Resource: "*" remains only on actions that require it (sts, ce).
    • IAM/KMS/CloudFront/WAF scoped to acdl-* ARNs.
    • Regression test in tests/test_iam_policy_baseline.py asserts the scoping.
    • pytest passes; run_ci.sh exits 0.

Phase P10 — contract-ingestor-identity-validation (Wave 2)

  • Description: Harden core/lambda/contract_ingestor.py:221-245 _validate_caller_identity — currently best-effort (validates consumerRepo format only, doesn't verify the caller owns the repo). Add contractId format validation, environment enum validation, error length cap. Document the ABAC reliance explicitly. Add a spoofing-resistance test.
  • Status: pending
  • Depends on:
  • Requirements: REQ-144
  • Success Criteria:
    • contractId, environment, error validated; malformed input rejected with 400.
    • ABAC reliance documented in the function docstring + ARCHITECTURE.md.
    • Spoofing-resistance test in tests/test_contract_ingestor.py passes.
    • pytest passes; run_ci.sh exits 0.

Phase P11 — schema-input-validation-hardening (Wave 2)

  • Description: Add additionalProperties: false to schemas/contract.schema.json + schemas/environment.schema.json (currently allows undocumented fields silently). Add maxItems/ maxProperties bounds. Validate state_backend.bucket S3 naming rules, runner_role_arn ARN format, vpc_cidr CIDR format. Add tests asserting rejection of malformed input.
  • Status: pending
  • Depends on:
  • Requirements: REQ-145
  • Success Criteria:
    • Both schemas reject undocumented top-level fields.
    • Format validation (bucket/ARN/CIDR) rejects malformed values.
    • New tests in tests/test_environment_schema.py + tests/test_contract_schema.py pass.
    • pytest passes; run_ci.sh exits 0.

Phase P12 — gitignore-credential-hygiene (Wave 2)

  • Description: .gitignore covers .env*/*.tfstate* but lacks a credential-pattern catch-all (*.pem/*.key/*.p12/*.pfx). Add credential patterns. Add tests/test_no_secrets_tracked.py asserting no credential-looking file is tracked by git.
  • Status: pending
  • Depends on:
  • Requirements: REQ-146
  • Success Criteria:
    • .gitignore has credential-pattern catch-all.
    • test_no_secrets_tracked.py passes (grep git ls-files for credential patterns → 0 hits).
    • pytest passes; run_ci.sh exits 0.

Phase P13 — kyverno-kube-version-resolution (Wave 3)

  • Description: Resolve the discarded --kube-version flag in adapters/kyverno/kyverno_adapter.py:11,115-116 (_ = kube_version). Either implement version-aware policy selection (select policies by k8s version) or remove the flag and document why it's deferred to the GitOps reconciler roadmap. Resolve the ambiguity either way.
  • Status: pending
  • Depends on:
  • Requirements: REQ-147
  • Success Criteria:
    • --kube-version is either used (version-aware policy selection) or removed with a documented deferral rationale.
    • tests/test_kyverno_adapter.py updated to match.
    • pytest passes; run_ci.sh exits 0.

Phase P14 — orphan-artifact-and-dead-config-cleanup (Wave 3)

  • Description: Clean up orphan artifacts + dead config: the orphan scripts/__pycache__/verify_deploy_microservice.cpython-312.pyc (source deleted in v1.11); stale pyproject.toml coverage source acdl_platformcore (renamed in v1.6); pyproject.toml version 1.3.0 → current; dead JS allowlist entries in config.json (npm/node/jest/eslint/tsc — no package.json).
  • Status: pending
  • Depends on:
  • Requirements: REQ-148
  • Success Criteria:
    • No orphan .pyc for a deleted source file.
    • pyproject.toml coverage source = core; version = current.
    • config.json bash_allowlist has no JS-only entries.
    • pytest passes; run_ci.sh exits 0.

Phase P15 — untested-scripts-coverage (Wave 3)

  • Description: Add unit tests for 7 scripts with no test coverage: scripts/seed_uptime_monitors.py, scripts/push_consumer_image.py, scripts/sync_to_gl.sh, scripts/post_stage_comment.sh, scripts/rotate_spike_key.sh, terraform/bootstrap/create_state_backend.py, terraform/bootstrap/create_iam_user.py. Mock boto3/subprocess for offline-testable coverage. Add --check-only/dry-run modes where missing.
  • Status: pending
  • Depends on: [P7]
  • Requirements: REQ-149
  • Success Criteria:
    • Each of the 7 scripts has a corresponding test file with ≥1 passing test.
    • pytest count increases by ≥7; run_ci.sh exits 0.

Phase P16 — workflow-parity-and-script-flags (Wave 3)

  • Description: 4 GitHub-only workflows (patterns-plan, platform-test, primitives-plan, release) have no Gitea mirror — either mirror them or document the Gitea limitation. Fix scripts/rotate_spike_key.sh (only set -u, no -e/pipefail) and scripts/sync_to_gl.sh (no set flags at all) — add set -euo pipefail.
  • Status: pending
  • Depends on:
  • Requirements: REQ-150
  • Success Criteria:
    • Gitea workflow parity resolved (mirrored or documented).
    • rotate_spike_key.sh + sync_to_gl.sh have set -euo pipefail.
    • pytest passes; run_ci.sh exits 0.

Phase P17 — config-and-persona-hygiene (Wave 3)

  • Description: Fix config.json hygiene: branching_strategy: "phase" mismatch with flat-workflow practice; empty ollama-cloud base_url (no glm model configured); frontend-engineer persona active: false in config.json (PERSONAS.md:80 already says inactive). Align config.json with PERSONAS.md + actual runtime.
  • Status: pending
  • Depends on: [P14]
  • Requirements: REQ-151
  • Success Criteria:
    • config.json persona block matches PERSONAS.md (frontend-engineer inactive).
    • branching_strategy reflects actual practice (or documented).
    • ollama-cloud backend configured or documented as intentionally unset.
    • pytest passes; run_ci.sh exits 0.

Phase P18 — module-standards-consistency (Wave 4)

  • Description: 3 L1 modules (ecr, ecs-cluster, rds) lack locals.tf; modules/STANDARDS.md §9.4 requires the full 5-file split but §489-492 allows inlining — internally inconsistent. Either add locals.tf to all 3 or reconcile STANDARDS §9.4 with the inline allowance. Remove the stale TYPE_MAP reference in §8 (deleted in the v1.11 stateless rewrite).
  • Status: pending
  • Depends on:
  • Requirements: REQ-152
  • Success Criteria:
    • STANDARDS.md internally consistent (§8 + §9.4 agree).
    • No stale TYPE_MAP reference.
    • pytest passes; run_ci.sh exits 0.

Phase P19 — documentation-sync-v1.14 (Wave 4)

  • Description: ARCHITECTURE.md: add v1.11/v1.12/v1.13/v1.14 addenda (stateless adapter, platform VPC, ACDL_LIFECYCLE_MODE, all v1.14 changes; record D-083 deferral explicitly). Bump stale @v1.61.9@v1.13 across README.md, docs/consumer-guide.md (12 sites), docs/architecture.md, docs/pipeline/. Sync decks to v1.13.2 reality. Update COST.md window to v1.11v1.14. Resolve G-005/G-008 in GRILL.md (CAP-017..022 now Verified via lifecycle pipeline; COST.md now exists + covers v1.11+). Update IAM_POLICY.md for v1.12/v1.13/v1.14.
  • Status: pending
  • Depends on: [P1-P18]
  • Requirements: REQ-153
  • Success Criteria:
    • ARCHITECTURE.md has v1.11v1.14 addenda; D-083 deferral recorded.
    • grep -rn "@v1\.[6-9]" docs/ README.md returns 0 hits (bumped to @v1.13).
    • GRILL G-005/G-008 marked resolved with evidence.
    • COST.md window covers v1.11v1.14.
    • pytest passes; run_ci.sh exits 0.

Phase P20 — platform-vpc-parameterization (Wave 4)

  • Description: terraform/platform/main.tf:255 hardcodes cidr_block = "10.0.0.0/16" (not var.vpc_cidr); count = 2 subnets hardcoded (not data-driven AZs). Parameterize; document the 0.0.0.0/0 ingress on port 80 (ALB-fronted, acceptable but should be explicit).
  • Status: pending
  • Depends on:
  • Requirements: REQ-154
  • Success Criteria:
    • VPC CIDR is a variable (default 10.0.0.0/16); subnet count is data-driven (length(data.aws_availability_zones.available)).
    • 0.0.0.0/0 ingress documented.
    • terraform validate passes; pytest passes; run_ci.sh exits 0.

Phase P21 — final-review-ship (Final Phase)

  • Description: Multi-persona code review across all v1.14 phases. Audit (reconstruction test, file discipline, branch hygiene, commit discipline). Complete: update REQUIREMENTS.md (REQ-135..154 marked complete), ROADMAP.md (v1.14 complete), PROJECT.md. Tag final patch v1.13.24 (IS the milestone release). Merge milestone/v1.14main.
  • Status: pending
  • Depends on: [P1-P20]
  • Requirements:
  • Success Criteria:
    • Review: 0 new P0; all P1-1..P1-5 + P2-1..P2-4 resolved.
    • Audit: clean; reconstruction test passes.
    • Tag v1.13.24 created; milestone merged to main.

After Phase P21: milestone COMPLETE — v1.13.24 IS the v1.14 release.


v1.15 (complete — Nova Rebrand, tag v1.15.4)

A full rebrand from ACDL / "Agentic Cloud Delivery Platform" → Nova / "The New Dawn of DevSecOps — security as a seamless enabler of fast deployments." The rebrand applies across docs, decks, code, configs, CI, env var prefixes, the consumer contract path, SSM parameter paths, AWS tag keys, and AWS resource names — with a staged infrastructure migration to avoid breakage. The Nova tagline is added alongside (not replacing) the existing "North Star" / "consumers declare intent" framing; the S&P Global Energy visual theme (sp-theme.json) is a client brand and is not touched.

Milestone type: Major (breaking — consumer-facing path, env var prefixes, SSM path, AWS tag keys, and AWS resource names all change). Per the branch-strategy precedent (breaking/feature milestones tag on their OWN minor line), v1.15 tags run on the v1.15.x minor line: v1.15.0 (P0) → v1.15.1..v1.15.4 (P1P4) → v1.15.4 (P5 final = milestone release). (G-104 binding.)

Brand mapping:

  • Name: ACDL / Agentic Cloud Delivery PlatformNova
  • Tagline (added): "The New Dawn of DevSecOps — security as a seamless enabler of fast deployments"
  • Env var prefix: ACDL_*NOVA_* (dual-read fallback in P2; removed in P5)
  • Consumer path: .acdl/contract.yml.nova/contract.yml
  • SSM path: /acdl/{env}/{contractId}/{output}/nova/{env}/{contractId}/{output}
  • AWS tag keys: acdl:owner|environment|contract|cost-center|refnova:*
  • AWS resource names: acdl-*nova-* (with migration, P4)
  • Illustrative URLs in docs: github.com/acdl/...github.com/nova/... (prose only; real repo name unchanged)
  • Gitea release titles going forward: ACDL vX.Y.ZNova vX.Y.Z
  • S&P visual theme: unchanged (client branding)

Wave ordering:

  • Wave 1 (P1): docs/decks/prose — no runtime impact; establishes new vocabulary. REQ-155, REQ-156, REQ-157.
  • Wave 2 (P2): code + env vars + consumer path — rename in code with a dual-read env fallback so deployments don't break during the transition window. REQ-158, REQ-159, REQ-160.
  • Wave 3 (P3): SSM path + tag keys — SSM: copy /acdl/.../nova/..., update readers, delete old. Tag keys: parallel-tag period (nova:* added, ABAC policy swapped, acdl:* removed). REQ-161, REQ-162.
  • Wave 4 (P4): AWS resource names — the big migration (KMS alias, SNS, SG, Lambda, DynamoDB data migration, ECR re-push, IAM re-bootstrap, state bucket migration, ALB recreate). Maintenance window + rollback runbook. REQ-163.
  • Wave 5 (P5): final-review-ship — remove dual-read fallback, consumer migration guide finalized, review + audit + milestone ship. REQ-164.

Phase P1 — docs-decks-prose (Wave 1)

  • Description: Rebrand all prose, titles, headers, comments, deck markdown sources, mermaid .mmd sources, pyproject.toml name/description, and release.yml release-title prefix from ACDL/Agentic Cloud Delivery PlatformNova. Add the Nova tagline ("The New Dawn of DevSecOps — security as a seamless enabler of fast deployments") to the README header, both deck title slides, and docs/vision.md — alongside the existing "North Star" framing. Re-export the mermaid PNG diagrams so committed PNGs match new labels. Re-render the deck HTML. Update illustrative URLs in docs (github.com/acdl/...github.com/nova/..., git.cloudinit.dev/continuous-intelligence/acdl*.../nova* for prose). Ship a consumer migration guide (docs/NOVA_MIGRATION.md) announcing the .acdl/.nova/ path, ACDL_*NOVA_* env vars, /acdl//nova/ SSM path, acdl:*nova:* tag keys, and acdl-*nova-* AWS resource names changes coming in P2P4.
  • Status: complete (v1.15.1)
  • Depends on:
  • Requirements: REQ-155, REQ-156, REQ-157
  • Success Criteria:
    • grep -rni "ACDL\|Agentic Cloud Delivery" README.md docs/ .ciagent/*.md returns 0 hits (except historical narrative marked as historical).
    • pyproject.toml name = nova; description mentions Nova.
    • release.yml release title prefix is Nova .
    • Both decks' title-slide subtitle is Nova — The New Dawn of DevSecOps; mermaid .mmd sources use Nova; PNGs re-exported; HTML re-rendered.
    • docs/vision.md and README header carry the Nova tagline alongside the North Star.
    • docs/NOVA_MIGRATION.md exists and lists the 5 breaking changes.
    • pytest passes; run_ci.sh exits 0.

Phase P2 — code-envvars-consumer-path (Wave 2)

  • Description: Rename adapters/terraform/policy/custom_rules/acdl_tagging.pynova_tagging.py (+ Checkov custom-rule registration in schemas/tagging-standard.json + adapter config). Rename all 21 ACDL_* env var prefixes → NOVA_* across scripts/, core/, adapters/, tests/, workflows (.gitea/, .github/), .env, .env.secrets (key names only — values stay), and consumer docs. Implement a dual-read fallback (NOVA_X preferred, fall back to ACDL_X) in the env/config loader so deployments don't break during the transition window. Rename the consumer on-disk contract path .acdl/contract.yml.nova/contract.yml (and .acdl/static-assets.*.yml, .acdl/contract.yaml) across the contract resolver, deploy workflow checkout path, consumer docs, and the contract schema description. Rotate Gitea repo secrets via API (rename keys ACDL_*NOVA_*, values stay).
  • Status: complete (v1.15.2)
  • Depends on: [P1]
  • Requirements: REQ-158, REQ-159, REQ-160
  • Success Criteria:
    • nova_tagging.py exists; acdl_tagging.py removed; Checkov registration updated; rule enforces nova:* tag keys (tag-key enforcement of nova:* lands here; existing resources still carry acdl:* until P3 parallel-tag — rule warns during P2).
    • No ACDL_ env var references remain in code/scripts/workflows/tests except the dual-read fallback in the loader + .env.secrets legacy comment.
    • Dual-read fallback implemented and unit-tested.
    • Contract resolver reads .nova/contract.yml; deploy workflow checks out .nova/; docs updated.
    • pytest passes; run_ci.sh exits 0.

Phase P3 — ssm-tagkeys (Wave 3)

  • Description: SSM path migration: rename the parameter path prefix /acdl/{env}/{contractId}/{output}/nova/{env}/{contractId}/{output} across core/output_publisher, the contract resolver, and consumer docs. Add a migration script (scripts/migrate_ssm_paths.py) that copies existing /acdl/... parameters → /nova/..., then readers are updated, then old parameters are deleted. Tag key migration: add nova:* tags to all AWS resources (parallel-tag period), update the ABAC session policies to match nova:*, update nova_tagging.py to enforce nova:* (hard, no warn), then remove acdl:* tags once consumers are verified. Terraform tagging updated to emit nova:*.
  • Status: complete (v1.15.3)
  • Depends on: [P2]
  • Requirements: REQ-161, REQ-162
  • Success Criteria:
    • SSM readers use /nova/...; migration script copies + deletes; test asserts new path.
    • nova_tagging.py enforces nova:* (hard fail on acdl:*).
    • ABAC session policies match nova:*; terraform emits nova:* tags.
    • acdl:* tags removed from all resources (verified via aws CLI or documented deferred if no live AWS access).
    • pytest passes; run_ci.sh exits 0.

Phase P4 — aws-resource-migration (Wave 4)

  • Description: Rename all acdl-* AWS resources → nova-* via terraform with a staged migration: KMS alias alias/acdl-platformalias/nova-platform (repoint), SNS acdl-sod-haltnova-sod-halt (recreate), SG acdl-ecs-sgnova-ecs-sg (recreate), Lambda acdl-contract-ingestornova-contract-ingestor (recreate), DynamoDB acdl-contracts/ acdl-change-requestsnova-contracts/nova-change-requests (scan+copy data migration, verify row counts, keep old tables until verified), ECR acdl-microservicenova-microservice (re-push images), IAM user/policy acdl-spike-runnernova-spike-runner (re-bootstrap with new key), state bucket acdl-tfstate-...nova-tfstate-... (terraform init -migrate-state to new backend, state JSON backed up first), ALB name prefix acdl-albnova-alb (recreate, brief downtime). Publish a maintenance window + rollback runbook (docs/NOVA_AWS_MIGRATION.md). For the offline/local tier, the terraform name/resource labels change so terraform validate passes; live apply/modify/destroy is exercised by the modules-lifecycle workflow when ACDL_LIFECYCLE_MODE (now NOVA_LIFECYCLE_MODE) is set to full.
  • Status: complete (v1.15.4)
  • Depends on: [P3]
  • Requirements: REQ-163
  • Success Criteria:
    • All terraform resource names/labels use nova-*; terraform validate passes for platform/microservice/ci-vpc.
    • State bucket name → nova-tfstate-...; terraform init -migrate-state documented + tested offline.
    • DynamoDB data-migration script exists (scan+copy, row-count verify).
    • docs/NOVA_AWS_MIGRATION.md runbook exists (maintenance window, rollback steps).
    • grep -rn "acdl-" terraform/ returns 0 hits.
    • pytest passes; run_ci.sh exits 0.

Phase P5 — final-review-ship (Final Phase)

  • Description: Multi-persona code review across all v1.15 phases. Audit (reconstruction test, file discipline, branch hygiene, commit discipline). Remove the dual-read env var fallback (ACDL_*NOVA_*) once all consumers are migrated; finalize the consumer migration guide; nova_tagging.py no longer accepts acdl:* tag keys. Complete: update REQUIREMENTS.md (REQ-155..164 marked complete), ROADMAP.md (v1.15 complete), PROJECT.md. Tag final patch v1.14.5 (IS the milestone release). Merge milestone/v1.15-novamain.
  • Status: complete (v1.15.4, milestone release)
  • Depends on: [P1-P4]
  • Requirements: REQ-164
  • Success Criteria:
    • Review: 0 new P0; all P1+ flagged or auto-fixed.
    • Audit: clean; reconstruction test passes.
    • Dual-read fallback removed; nova_tagging.py hard-fails acdl:*.
    • Tag v1.15.4 created; milestone merged to main.

After Phase P5: milestone COMPLETE — v1.15.4 IS the v1.15 release.