# Nova — Requirements ## v1 ### Category: Repos & Org - **REQ-01:** All demo code lives under the `continuous-intelligence` Gitea org at `https://git.cloudinit.dev`. - **REQ-09:** Three repos exist: `acdl` (platform + stubs + reusable workflows), `acdl-contracts` (developer surface), `acdl-evidence` (Pages audit timeline). ### Category: L1 Modules - **REQ-02:** 8 L1 module folders exist under `acdl/modules/l1/`: `l1-eks-fargate`, `l1-iam-role`, `l1-lambda`, `l1-api-gateway`, `l1-eventbridge`, `l1-sqs`, `l1-s3`, `l1-cloudwatch`. - **REQ-03:** Each L1 module has a `manifest.yaml` (declaring inputs) and a `mock_apply.sh` that echoes success, sleeps 1s, and exits 0. ### Category: L2 Modules - **REQ-04:** 4 L2 modules exist under `acdl/modules/l2/`: `l2-invoice-service`, `l2-commodity-price-feed`, `l2-energy-analytics-api`, `l2-regulatory-reporting`, each composing the specified L1s. - **REQ-05:** L2 modules compose L1 primitives into deployable shapes with a maximum depth of 5. ### Category: Core Scripts - **REQ-06:** `mock_executor.sh` reads an L2 composition, invokes each L1 `mock_apply.sh`, and writes `state.json`. - **REQ-07:** `policy_checker.py` reads `contract.yaml` and fails with `POLICY_VIOLATION:PUBLIC_INGRESS` on `public-ingress: true`; otherwise passes. - **REQ-08:** `confidence_signal.py` returns a base score of 0.90 and drops to 0.40 (with reason code) when policy fails; gate threshold is ≥ 0.50. ### Category: Evidence Stream - **REQ-11:** `evidence_writer.py` appends events to `audit.json` and links each event to the previous via a SHA-256 hash chain (`prev_hash` + own `hash`). - **REQ-13:** `acdl-evidence` is Pages-enabled and serves `audit.json` plus `index.html`. ### Category: Pipeline - **REQ-10:** The reusable pipeline runs Dev (autonomous), pauses at QA (manual approval), pauses at Prod (manual approval), then finalizes by committing `audit.json` to `acdl-evidence`. - **REQ-12:** Opening an Issue in `acdl-contracts` runs `l3b_agent_stub.py`, commits a generated `contract.yaml` to a new branch, closes the Issue, and triggers the main pipeline. ### Category: Demo Acts - **REQ-14:** `index.html` uses vanilla JS to fetch `audit.json` from the Pages URL and render events as a timeline. - **REQ-15:** All four demo acts (Friction, Developer Self-Service, Citizen Developer, Safety Net) reproduce deterministically in a dry run. ## v2 (None — v1 covers the complete demo.) ## v1.1 (Prior milestone — architecture finalization + v1 spike, complete) ### Category: Architecture Finalization - **REQ-16:** Architecture reaches v1.0 — all 11 open decisions in `docs/architecture.md` §13 are resolved and recorded in `PROJECT.md` (W1.A, W1.B, W2.A, W3.D, W3.E, BA.A–F, OpenTofu timing). - **REQ-17:** Target Stack IR is defined as a JSON Schema under `schemas/ir.schema.json`; engine-agnostic (resources, relationships, composition max-depth-5, policy hooks). - **REQ-18:** `PolicyCheckResult` normalized schema is defined under `schemas/policy_check_result.schema.json`; a Checkov adapter translates Checkov JSON to this schema. - **REQ-19:** Six-input confidence signal is specified under `platform/confidence_signal.py` with per-env thresholds (dev 0.50 / qa 0.75 / prod 0.90 / dr 0.95) and severity→penalty mapping (critical=hard override, high=-0.2, medium=-0.05, low=-0.01, info=0.0). - **REQ-20:** Tiered audit ledger design is authored: S3 Object Lock (compliance mode, 7-yr) + DynamoDB outbox (RPO=0, JWS detached signatures, `prev_event_hash` chain, daily checkpoints). - **REQ-21:** Full 8-concern HITL matrix + separation-of-duties design is authored (CODEOWNERS routing + DynamoDB identity-distinctness check; pre-execution gate model; 1d warn / 2d freeze timeout). - **REQ-22:** Contract schema (JSON Schema draft 2020-12) is defined under `schemas/contract.schema.json` with per-env mandatory/optional inputs (W3.E) and `profile: agentic` marker for L3B fields. ### Category: AWS OIDC Bootstrap - **REQ-23:** AWS auth bootstrap + state backend for the spike: an S3 state bucket + DynamoDB lock/outbox table + an IAM user with a minimal scoped policy (S3 + DynamoDB + plan-only). The temporary long-lived key is used once (waiver D-034) then rotated via `scripts/rotate_spike_key.sh` after each spike run (D-039). **Real OIDC federation is deferred to v1.2** — Gitea Actions does not support `id-token: write` (RESEARCH TARGET 1, conf 0.95), blocked on go-gitea/gitea#36988. ### Category: v1 Spike — IR, L1, Adapter - **REQ-24:** One real L1 module `l1-s3` exists under `modules-ir/l1/l1-s3/` with an IR-typed interface (typed inputs/outputs/NFRs) registered in the L1 registry. - **REQ-25:** One real L2 thin-composition `l2-static-assets` exists under `modules-ir/l2/l2-static-assets/` referencing `l1-s3` only (depth 1, within max-depth-5). - **REQ-26:** The Terraform adapter (`adapters/terraform/`) compiles the IR-typed L1 interface to Terraform `variable`/`output` blocks and the L2 thin-composition tree to a Terraform root module; it emits a real `terraform plan` against AWS via OIDC; state is stored in S3 + DynamoDB. ### Category: v1 Spike — End-to-End - **REQ-27:** One end-to-end contract submission (`contracts/spike.yaml` for `l2-static-assets`) flows through: contract schema validation → contract→IR resolution → `terraform plan` (real AWS) → Checkov `PolicyCheckResult` → confidence signal → evidence event written to the DynamoDB outbox. - **REQ-28:** Spike verification (`scripts/verify_phase10.sh`) proves the IR-shaped commitments hold: the adapter is the only engine-specific code; no polyglot mess; the L1 content, contract YML, and thin-composition tree are engine-agnostic. ## Out of Scope (v1.1) | Feature | Reason | |---------|--------| | Full HITL matrix wiring (qa/prod/dr) | Spike is dev-only (`terraform plan`); HITL wiring is v1.2. | | Kyverno + OPA policy engines | Spike uses Checkov only; Kyverno/OPA are v1.2. | | MCP skill catalog + real L3B agent | L3B spike = a single stub contract submission; the 5-skill catalog is v1.2. | | GitOps reconciler (ArgoCD/Flux) | v1.2. | | Multi-region state / outbox | Single-region in v1 (§9, §12.3). | | Prod/dr environments | v1.2. | | Terraform `apply` (real provisioning) | Spike runs `plan` only; `apply` is gated by HITL in v1.2. | ## v1.2 (Prior milestone — platform hardening + first real consumer deployment, complete, tag `v1.3.0`) ### Category: Documentation & Simplification - **REQ-29:** `README.md` is fully rewritten to reflect the v1.1-complete platform: the actual spike flow (contract → IR → `terraform plan` → Checkov → confidence signal → outbox), how to run it (`scripts/run_platform.sh`), the real repo layout (`acdl_platform/`, `schemas/`, `adapters/`, `terraform/`, `modules-ir/`, `contracts/`, `demo/`), and the v1.2 objective. No stale "v1.1 (active)" framing. - **REQ-30:** NFR hardening of the v1.1 spike: (a) `terraform/bootstrap/spike_runner_policy.json` audited to least-privilege (S3 + DynamoDB + ECS + ECR + ELB + IAM plan-only, no wildcards beyond the documented exceptions); (b) `create_state_backend.py` and `create_iam_user.py` are idempotent (re-running exits 0 without duplicating resources); (c) `run_spike_plan.sh` + `run_spike_e2e.sh` consolidated into a single `scripts/run_platform.sh` with proper exit codes and error handling; (d) P1-1 carried forward from the v1.1 audit — the two AWS access key IDs in `.ciagent/VERIFY.md` Phase 09 narrative are redacted to placeholders; (e) any remaining stale `platform/` paths in `.ciagent/` are corrected to `acdl_platform/`. ### Category: L1 Catalog Expansion (ECS Fargate) - **REQ-31:** Six new IR-typed L1 modules exist under `modules-ir/l1/` and are registered in `modules-ir/registry.json`: `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` (application load balancer + listener + target group), `l1-ecr` (ECR repository). Each has an `interface.json` valid against `schemas/ir.schema.json` and produces a valid `terraform plan` fragment via the Terraform adapter. The adapter `TYPE_MAP` is expanded to cover all six IR resource types. ### Category: L2 Composition & Contract Schema - **REQ-32:** `l2-microservice` thin-composition exists under `modules-ir/l2/l2-microservice/` referencing the six ECS L1s (depth ≤ 5, within max-depth-5). `schemas/contract.schema.json` is extended with microservice inputs (`image: string`, `port: integer`, `env: map`, `healthcheck: object`) and validates a `contracts/microservice.yaml` submission. Contract→IR resolution (`acdl_platform/contract_resolver.py`) yields a complete target stack for `l2-microservice`. ### Category: Real Provisioning - **REQ-33:** The platform runs `terraform apply` (not just `plan`) for the `dev` environment, autonomous per §10 (confidence ≥ 0.50, no HITL). The apply creates real AWS resources (VPC, ECS cluster, ECR repo, ALB, ECS service) and the result is captured in the evidence stream. `apply` for qa/prod/dr remains HITL-gated and out of scope for v1.2. ### Category: Consumer Repo - **REQ-34:** A new Gitea repo `acdl-consumer-microservice` exists under the `continuous-intelligence` org, containing: a basic HTTP microservice (e.g., a tiny Python/Go server returning 200), a `Dockerfile`, an ECR push step, and a `contracts/microservice.yaml` submission for `l2-microservice` (dev environment). ### Category: End-to-End Verification - **REQ-35:** One end-to-end flow: consumer commit to `acdl-consumer-microservice` → pipeline triggered → contract→IR resolution → `terraform plan` → `terraform 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. `scripts/verify_phase16.sh` proves the full flow green. ## v1.3 (Prior — module documentation + thin-composition removal, complete) ### Category: Thin-Composition Removal - **REQ-36:** The L2 thin-composition layer is removed completely: `composition.json` files, `acdl_platform/contract_resolver.py`, `schemas/contract.schema.json`, `contracts/spike.yaml`, `contracts/microservice.yaml`, and L2 entries in `modules-ir/registry.json` are deleted. The L2 directories are kept as placeholders with READMEs. The downstream pipeline (adapter → checkov → confidence → outbox) is patched to load a pre-existing IR instance instead of resolving a contract. - **REQ-37:** A `modules-ir/README-TEMPLATE.md` exists that works for both L1 and L2 modules, written in plain language (no jargon), with sections for Overview, Resources, Inputs, Outputs, Usage, Compliance extension points, and Versioning. - **REQ-38:** Every module has a `README.md`: the 7 L1 modules have full READMEs with Resources/Inputs/Outputs/Usage/Compliance-extension-points/Versioning sections derived from their `interface.json`; the 2 L2 modules have placeholder READMEs noting the composition is under redesign. A `modules-ir/README.md` catalog index lists all modules with one-line descriptions and links. ### Category: Testing - **REQ-39:** A pytest test suite exists under `tests/` covering the platform components offline (no AWS, no Checkov, no DynamoDB): the Terraform adapter (`adapters/terraform/adapter.py`), the confidence signal (`acdl_platform/confidence_signal.py`), the Checkov adapter (`adapters/terraform/policy/checkov_adapter.py`), and the outbox writer (`acdl_platform/outbox_writer.py`). The suite validates the IR schema, registry, spike_instance, and adapter output structure. `pyproject.toml` + `requirements-test.txt` pin test dependencies (pytest, jsonschema, pyyaml, boto3-stubs or moto for outbox mocking). ### Category: Shell Reproducibility - **REQ-40:** `scripts/run_platform.sh` has a `--check-only` mode that runs offline: loads the pre-existing IR instance, runs the adapter to emit Terraform, validates the JSON structure — without AWS credentials, Checkov, or DynamoDB. The existing `--plan-only` and full modes continue to require AWS. The `--check-only` mode is what CI pipelines run. ### Category: CI/CD Pipelines - **REQ-41:** Identical CI/CD pipelines exist for both Gitea Actions (`.gitea/workflows/ci.yml`, dev environment) and GitHub Actions (`.github/workflows/ci.yml`, production). Both run the same three stages: (1) lint — `py_compile` all Python files, (2) test — `pytest`, (3) check-only — `bash scripts/run_platform.sh --check-only`. Both trigger on push to main + pull request. Both use `ubuntu-latest`. Identical outcomes — the only difference is the runner environment. - **REQ-42:** `pyproject.toml` exists at the repo root with pytest configuration (testpaths, markers) and the project metadata. `requirements-test.txt` pins test-only dependencies separate from runtime dependencies. ## v1.4 (Active — central pipeline contract + shell reproducibility + streaming) ### Category: Central Pipeline Contract - **REQ-43:** A central pipeline contract exists as `schemas/pipeline.schema.json` (JSON Schema draft 2020-12) + `pipelines/ci.yaml` (YAML instance). The contract declares the pipeline name, triggers (push/PR branches), runner, Python version, and stages (name + command + required + install + description). Both `.gitea/workflows/ci.yml` (Gitea Actions, dev) and `.github/workflows/ci.yml` (GitHub Actions, production) implement the same stages, commands, triggers, and runner as declared in the contract. A test (`tests/test_pipeline_contract.py`) validates the contract against the schema and asserts both workflows conform (same jobs, same commands, same triggers, same runner, byte-identical). ### Category: Shell Reproducibility - **REQ-44:** `scripts/run_ci.sh` reproduces the CI pipeline locally — runs the same 3 stages (lint, test, check-only) in sequence with proper exit codes, failing on first error. The script exits 0 with "CI PIPELINE OK" on success. A `--quiet` flag suppresses per-stage banners. The script mirrors the central pipeline contract (`pipelines/ci.yaml`) so the shell and CI environments produce identical outcomes. ### Category: Pipeline Streaming - **REQ-45:** `scripts/run_platform.sh` streams output by default: terraform init/validate/plan output is piped to stdout via `tee` (visible to the user and logged), Checkov results are printed in human-readable form, and PolicyCheckResult records are displayed with severity, rule ID, and pass/fail status per record. The `--check-only` mode streams the emitted Terraform file content. A `--quiet` flag suppresses streaming (output to log files only) for backwards compatibility. Both gitea and github workflows are byte-identical (identical outcomes — the only difference is the forge runtime). ## v1.5 (Prior — consumer happy path + zero-trust docs + reusable deploy workflow, complete) ### Category: Consumer Happy Path Documentation - **REQ-46:** `README.md` is rewritten so the consumer model is unambiguous: this repo is the platform source; a consumer never clones it. A consumer repo contains only app code + `contract.yaml` referencing the central pipeline + contract. The platform-flow diagram is a mermaid `flowchart TD` (replacing the ASCII art). "L3A"/"L3B" nomenclature is removed from README (single-surface model). "spike" nomenclature is removed from prose (code paths in bash blocks are kept verbatim). - **REQ-47:** `docs/CONSUMER_GUIDE.md` (all-caps) replaces `docs/consumer-guide-static-assets.md`. It is generic across all L2 modules (`static-assets` as the worked example), uses mermaid diagrams (model + pipeline flow), documents versioned `uses:` references (floating MAJOR+MINOR tags — bare/`@main` discouraged), scopes prerequisites to consumer-repo bootstrap only (no Terraform/Checkov/boto3/runner-key — those are platform-repo concerns), and documents that the pipeline fetches the ACDL repo at run time via a reusable workflow (consumers never invoke `scripts/run_platform.sh` locally for the happy path). - **REQ-48:** `README.md` Credentials section is rewritten to express the zero-trust target model: consumer repos use OIDC federation (no long-lived keys) with attribute-based authorization (ABAC) — IAM roles + session policies scoped by repository identity and resource-creation tags so a consumer can only view/update resources it created (blast-radius containment). A documented override allows a static key in GitHub Secrets (consumer repo) or `.env.secrets` (local testing), rotated by a platform-managed scheduled pipeline on a daily cadence; when `.env.secrets` is used locally, rotating out of band is the consumer's responsibility. ### Category: Reusable Deploy Workflow - **REQ-49:** A reusable deploy workflow exists as byte-identical `.gitea/workflows/deploy.yml` (Gitea, dev) and `.github/workflows/deploy.yml` (GitHub, production), implementing the central deployment pipeline contract (`pipelines/deploy.yaml` validated against `schemas/deploy-pipeline.schema.json`). It is invoked by consumer repos via `uses: acdl/.gitea/workflows/deploy.yml@vMAJOR.MINOR` (versioned tag). The workflow checks out the consumer repo, checks out the ACDL platform repo into the runner workspace, installs runtime deps (Python, Terraform, Checkov), and invokes `scripts/run_platform.sh` against the consumer's contract path (passed as a workflow input). OIDC is the default auth (`permissions: id-token: write`); a static-key override reads from repository secrets. - **REQ-50:** `contracts/static-assets.yaml` uses a versioned `uses:` reference (`@v1.4`, MAJOR+MINOR) — not bare `@v1` or `@main` — as the canonical example the consumer guide points at. - **REQ-51:** `tests/test_pipeline_contract.py` is extended to validate the new deploy workflows: both files exist, are byte-identical, and conform to `schemas/deploy-pipeline.schema.json` (stages present, names match `pipelines/deploy.yaml` stage names). The existing CI-workflow conformance tests continue to pass unchanged. ## v1.6 (Active — consumer-facing docs restructure + terminology normalization + environments concept) ### Category: Internal-surface scrub - **REQ-52:** No consumer-facing documentation (README.md, docs/**, modules/**/README.md, contracts/**) references `.ciagent/` — it is local CIAgent metadata, never visible to platform engineers or consumers. The README repository-layout table has no `.ciagent/` row. No `.gitea/` references appear in consumer-facing docs (consumers use GitHub only); the README repository-layout table has no `.gitea/workflows/` row. - **REQ-53:** `acdl_platform/` is renamed to `core/` across the directory, all imports in tests/scripts/pipelines/workflows, and all doc references. (`platform/` was the original target but shadows Python's stdlib `platform` module — `core/` was chosen to stay importable.) `grep -R "acdl_platform" .` (excluding `.ciagent/`, `demo/`, `.git/`) returns 0 hits. The test suite passes after the rename. ### Category: Docs site restructure - **REQ-54:** `docs/` is restructured into a Jekyll-style GitHub Pages site: `docs/_config.yml`, `docs/index.md` (landing), `docs/modules/` (catalog + per-module Pages-friendly copies), `docs/contracts/index.md`, `docs/pipeline/index.md` + `docs/pipeline/versioning.md`, `docs/environments/index.md`, `docs/consumer-guide.md`, `docs/architecture.md` (consolidated from architecture.md + architecture-v1.0.md, current-architecture only), `docs/vision.md`. No `.ciagent/` links anywhere in `docs/`. Consumer-facing content (modules, contracts, pipeline, versioning) lives in Pages. ### Category: Terminology normalization - **REQ-55:** Consumer-facing docs drop the "L2" nomenclature — L2 modules are referred to as "modules". "L1" label is dropped in consumer-facing docs — L1 primitives are referred to as "primitives". The "composition" terminology is changed to "pattern" for modules in prose (the on-disk `composition.json` files and code references are unchanged this phase). A roadmap entry records that "composition" will later describe the thin orchestration where consumers dynamically create a module directly from the contract file (future implementation, not implemented now). - **REQ-56:** The term "forge" is replaced in consumer-facing docs with "platform runners" / "platform-managed" as appropriate. The term "forge" remains only in internal architecture docs. ### Category: README rewrite - **REQ-57:** README.md repository-roles section is restated to match reality: a consumer repo contains (a) its application code, (b) one or more contracts (`.acdl/contract.yaml`), and (c) one or more CI definitions (a thin `.github/workflows/deploy.yml` that `uses:` the central reusable workflow, pointing at the appropriate environment + contract). The platform repo (this one) owns modules/adapters/schemas/pipelines/scripts/workflows. A consumer never clones the platform repo. - **REQ-58:** README.md Status section is replaced with a Features list (referenceable by consumers and platform engineers) and a Roadmap subsection listing only planned future features (no internal CIAgent status, no version-by-version changelog). - **REQ-59:** README.md "How the platform works" mermaid diagram is revised so all node text is visible (no overflow): labels are split with `
`, boxes widened as needed. A security-checks stage is added before the policy-checks stage. Specific tools (Checkov, Terraform) are not named — they are "security checks (adapter)", "policy checks (adapter)", "infrastructure plan". An "infrastructure apply" stage is added at the appropriate level (dev only, after confidence). - **REQ-60:** README.md Credentials & zero-trust section removes the "go-gitea/gitea#36988 blocked" mention and the "waivers D-039/D-047" language (not consumer/platform-engineer facing). It states: default OIDC + ABAC; alternative is a static AWS key (GitHub Secrets for platform-runner runs, or `.env.secrets` locally) with the expectation of daily rotation (platform-managed for runner runs) or out-of-band rotation (consumer-managed for local `.env.secrets`). ### Category: Environments concept + onboarding - **REQ-61:** The concept of platform-managed environments is introduced: consumers are not required to provide an AWS account, VPC, subnet, S3 state bucket, or runner key. `docs/environments/index.md` documents that a named environment is a platform-owned AWS account + network + state backend + IAM role surfaced to the consumer via ABAC, selected by name in the contract. The old README environments table (dev/qa/prod/dr) is removed completely. A minimal onboarding scaffold exists: `platform/environments/` with a sample `dev.json` + README, `platform/environment_check.py`, a wire-in at the top of `scripts/run_platform.sh`, a friendly first-run onboarding message when no environment is defined for the repo, and `tests/test_environment_check.py` covering the missing-env and present-env cases. ## v1.7 (Active — production platform + contract ingestion + pipeline maturation) ### Category: Rename + production-ready stack - **REQ-62:** `static-assets` is renamed to `static-assets` everywhere (D-048 — including `.ciagent/` historical narrative: verbatim phase descriptions, REQ-25/27/50 text, D-036, RESEARCH.md). `grep -R "static-assets[^s]" .` (excluding `.git/`) returns 0 hits. The module dir `modules/l2/static-assets/` → `modules/l2/static-assets/`; `contracts/static-assets.yaml` → `contracts/static-assets.yaml`; the registry key is renamed; all scripts, tests, docs, and `.ciagent/` files use `static-assets`. The reconstruction test is updated to expect `static-assets` throughout. - **REQ-63:** Two new primitives exist: `cloudfront` (distribution + OAC, stack types `aws:cloudfront:distribution` + `aws:cloudfront:originaccesscontrol`) and `waf` (WAFv2 web ACL, stack type `aws:wafv2:webacl`), each with an `interface.json` valid against `schemas/stack.schema.json` and a full README (Resources/Inputs/Outputs/Usage/Compliance/Versioning). Both are registered in `modules/registry.json`. The Terraform adapter `TYPE_MAP`/`INPUT_MAP`/`OUTPUT_MAP` covers the new stack types. - **REQ-64:** The `static-assets` module is augmented to a production-ready stack referencing s3 + cloudfront + waf (depth 1, D-049). `composition.json` wires the s3 bucket regional domain name to the CloudFront origin, and the WAF web ACL ARN to the CloudFront distribution. `schemas/contract.schema.json` is extended for the new module inputs (`price_class`, `viewer_protocol_policy`, `waf_enabled`, `default_ttl`, `max_ttl`). The `uses:`/`ref:` tag advances from `@v1.4` to `@v1.6` (D-056/D-057); floating git tags `v1.6` + `v1` are created pointing at `v1.6.0`. ### Category: Tagging standards + security adapters - **REQ-65:** A required-tag set is defined in `schemas/tagging-standard.json` (`acdl:owner`, `acdl:contract`, `acdl:environment`, `acdl:cost-center`). A Checkov custom YAML rule at `adapters/terraform/policy/custom_rules/acdl_tagging.yaml` fails (severity `medium`) when required tags are missing on taggable resources. `checkov_adapter.py` removes the `_emit_tag_naming_skipped()` placeholder (D-043 closure) and maps `ACDL_TAG_NAMING` as a real rule. `scripts/run_platform.sh` Step 5 passes `--external-checks-dir` to load the custom rule. - **REQ-66:** A Wiz adapter stub exists at `adapters/wiz/wiz_adapter.py` translating Wiz API issues → `PolicyCheckResult` records (`engine: "wiz"`, D-052). It degrades gracefully when unconfigured (emits a single `SKIPPED` `WIZ_NOT_CONFIGURED` record). `tests/test_wiz_adapter.py` passes offline with a fixture response. The pipeline invokes it optionally (Step 5b) when `WIZ_API_TOKEN` is set. - **REQ-67:** A Kyverno K8s-native adapter exists at `adapters/kyverno/kyverno_adapter.py` translating Kyverno `PolicyReport` results → `PolicyCheckResult` records (`engine: "kyverno"`, D-053). Sample policies exist at `adapters/kyverno/policies/` (disallow-privileged, require-labels, require-image-digests). `tests/test_kyverno_adapter.py` passes offline. The adapter is inactive for Terraform-only stacks (the platform emits Terraform, not K8s manifests); it is ready for the GitOps reconciler roadmap item. `schemas/policy_check_result.schema.json` engine enum includes `checkov | kyverno | opa | wiz`. ### Category: Platform Lambda + contract ingestion - **REQ-68:** A platform Lambda (`core/lambda/contract_ingestor.py`) is invoked via a Function URL (IAM auth) and accepts `{ consumerRepo, contractId, contract, environment, action }`. It writes contracts to a DynamoDB table `acdl-contracts` (PK `consumerRepo`, SK `contractId#submittedAt`, SSE via a customer-managed CMK, point-in-time recovery) (D-051). `terraform/platform/main.tf` defines the table, Lambda, Function URL, KMS key, Secrets Manager secret (`acdl/github-token`), and Lambda execution role. `terraform/platform/consumer_invoke_policy.json` grants the consumer's deploy role `lambda:InvokeFunctionUrl` on the Lambda ARN, scoped via ABAC (cross-account). Onboarding grants the Lambda-invoke permission; `docs/environments/index.md` documents this. `tests/test_contract_ingestor.py` passes offline (moto-mocked DynamoDB). ### Category: Deploy outputs + error reporting + stage comments - **REQ-69:** `scripts/run_platform.sh` has a `publish-outputs` step (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). `core/output_publisher.py` implements the SSM write + GitHub comment formatting. `tests/test_output_publisher.py` passes offline (moto + mocked GitHub API). `pipelines/deploy.yaml` + both deploy workflow YAMLs declare the new stages (byte-identical). - **REQ-70:** The Lambda `report_error` action (`core/lambda/contract_ingestor.py`) creates a GitHub issue on the platform repo (`acdl/acdl`) via the GitHub API using a token from Secrets Manager (D-055). Idempotent (comments on an existing open issue rather than duplicating). `.github/workflows/deploy.yml` + `.gitea/workflows/deploy.yml` (byte-identical) have an `if: failure()` error-report step invoking the Lambda via `aws lambda invoke-function-url` (SigV4-signed). Gitea is excluded (only the CIAgent uses it; platform engineers and consumers use GitHub). - **REQ-71:** `.github/workflows/deploy.yml` + `.gitea/workflows/deploy.yml` (byte-identical) post a PR comment after every successful pipeline stage (validate-contract, resolve-stack, plan, checkov, confidence, apply, publish-outputs) via `scripts/post_stage_comment.sh` (uses `GITHUB_TOKEN` + `gh api`; no-op when not in a PR context). The comment includes the stage name, status (pass), and key metrics (plan counts, confidence score, outputs published). ### Category: Platform pipelines + release automation - **REQ-72:** Three platform pipelines exist: (1) `.github/workflows/platform-test.yml` (PR, stages: lint, unit-test, integration-test — runs `run_platform.sh --check-only` for every sample contract, schema-validation — validates all `schemas/*.json` + `modules/**/interface.json` + `modules/**/composition.json` + `modules//examples/*.yaml` against their schemas); (2) `.github/workflows/primitives-plan.yml` (PR, plan-only for all L1 primitives via matrix, `scripts/run_primitive_plan.sh`); (3) `.github/workflows/patterns-plan.yml` (PR, plan-only for all L2 modules via matrix, `scripts/run_pattern_plan.sh`). - **REQ-73:** `.github/workflows/release.yml` 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, and creates a GitHub release with an auto-generated body (D-057). `tests/test_release_logic.py` passes (unit test the semver computation + tag-update logic with a mocked `git describe`). ### Category: Remove legacy consumer-repos + module examples + RDS primitive - **REQ-74:** The legacy consumer-repos directory is deleted entirely (a v1.2 artifact removed in v1.7; references in `.ciagent/` historical narrative are rewritten per D-048). A recursive grep for the legacy directory name (excluding `.git/`) returns 0 hits. - **REQ-75:** A new RDS primitive (`modules/l1/rds/`) with an `engine` input (enum: postgres, mysql, etc.) demonstrates multi-engine variation (D-059). Every module (primitives + patterns) has a `modules//examples/` directory with `simple.yaml` + `complex.yaml` (+ variation files) validated against `schemas/contract.schema.json` in the platform-test pipeline schema-validation stage (D-058). Each module's `README.md` `## Examples` section references + excerpts the validated files. `docs/modules/index.md` + `docs/consumer-guide.md` + `docs/contracts/index.md` are updated with the new module names + examples. ## v1.8 (Complete — P1 remediation + uptime + engineering standards + encryption/deletion-protection by default + decommission + docs) ### Category: P1 Fixes - **REQ-76:** WAF adapter emits custom `rules` as nested HCL blocks (not attribute syntax) and honors `default_action` input (allow/block) — P1-4, P1-5 closed. - **REQ-77:** L2 composition `outputs[]` array is resolved by `contract_resolver.py` into `stack.outputs`; the adapter emits corresponding `output` blocks — P1-7 closed. - **REQ-78:** SSM publisher fails loud when `ACDL_KMS_KEY_ID` is unset (no silent AWS-managed-key fallback); `ACDL_ALLOW_DEFAULT_KMS=1` escape hatch for local testing — P1-3 closed. - **REQ-79:** `consumer_invoke_policy` is rendered via Terraform with the caller's live account ID (no `000000000000` placeholder) — P1-6 closed. - **REQ-80:** `run_platform.sh` emits adapter output to a per-run temp dir, not committed `terraform/spike/*.tf`; the committed files are removed — P1-8 closed. - **REQ-81:** `contract_ingestor.py` reads `GITHUB_API_BASE` env for forge-agnostic API URLs (GitHub + Gitea) — P1-9 closed. - **REQ-82:** Deploy workflow static-key override is wired to `configure-aws-credentials` inputs (`access-key`/`secret-key`), not inert env vars — S1 closed. ### Category: Encryption by Default - **REQ-83:** A per-stack CMK primitive (`kms-key`) exists with 90-day rotation enabled at creation; one key per L2 deployment; no shared keys across stacks. - **REQ-84:** All primitives have encryption by default (`encryption_enabled` NFR, default true) + optional `kms_key_arn` input. CMK is prioritized; managed KMS is the fallback when no CMK is provided. - **REQ-85:** L2 modules wire a per-stack CMK child + connect its `kms_key_arn` output to each child's `kms_key_arn` input. ### Category: Deletion Protection by Default - **REQ-86:** `deletion_protection` NFR (boolean, default true) on every L1 primitive; the adapter emits `prevent_destroy` lifecycle meta-arg when true. - **REQ-87:** L2 modules expose a `features.deletion_protection` flag (default true); consumers can disable via contract `inputs.deletion_protection: false`. ### Category: Uptime Monitoring - **REQ-88:** An uptime-kuma L1 primitive exists (ECS Fargate) with: `feature_flag_enabled` (boolean, default true), `monitored_endpoints` (array of HTTP/DNS/TCP checks), `static_checks` (pre-defined health checks), `alert_channels` (Teams webhook, email, SMS, GitHub issues). - **REQ-89:** Uptime is deployed by default after any L2 module deploy (separate terraform state, separate terraform run); L2 module outputs (endpoints) are passed to the uptime deployment as `monitored_endpoints`. The uptime URL is published to the consumer via PR comment. - **REQ-90:** The `feature_flag_enabled` input (set from consumer contract `inputs.uptime_enabled`, default true) disables the uptime deployment entirely (no resources emitted). - **REQ-91:** A `deploy-uptime` pipeline stage is declared in `pipelines/deploy.yaml` + both deploy workflow YAMLs (byte-identical). ### Category: Decommission + CMDB - **REQ-92:** A decommission mode on the deploy pipeline (`mode: decommission`) implements a 2-step pipeline: (1) plan/apply to disable deletion protection with an HITL SRE gate, (2) plan/apply with all counts set to 0 with a second HITL SRE gate. Uses the existing deploy pipeline with different behavior. - **REQ-93:** A DynamoDB `acdl-change-requests` table serves as the CMDB. The decommission alias accepts a `changeRequestId` input validated via a `validate_change_request` Lambda action (CR status must be `approved`). - **REQ-94:** The decommission flow is documented in `docs/CONSUMER_GUIDE.md` (how to request a CR, trigger decommission, HITL gates, what happens). ### Category: Engineering Standards - **REQ-95:** `modules/STANDARDS.md` exists with comprehensive L1 + L2 authoring + code review standards (scanned from current modules): required files, interface schema, input/output/NFR conventions, encryption + deletion protection as mandatory NFRs, naming, adapter extension pattern, code review checklist. - **REQ-96:** `modules/README.md` catalog index includes all primitives (rds + uptime + kms-key added); `modules/README-TEMPLATE.md` updated with `## NFRs` section. ### Category: Path Documentation - **REQ-97:** `schemas/README.md` documents how to write a schema, wire it into the platform, test it in CI, where to write tests, dependencies, and the existing schema catalog. - **REQ-98:** `pipelines/README.md` documents how to write a pipeline contract, wire it into workflows, test it, dependencies, and the existing pipeline catalog. - **REQ-99:** `adapters/README.md` documents how to write an adapter, wire it into the platform, test it, dependencies, and the existing adapter catalog. ## Out of Scope (v1.2) | REQ | Original criterion | Clarified criterion (effective) | Decision | |-----|--------------------|----------------------------------|----------| | REQ-09 | Three repos exist | Three repos exist (`acdl`, `acdl-contracts`, `acdl-evidence`) under `continuous-intelligence`; new repos use `default_branch: "main"`, `auto_init: true` | D-015 | | REQ-10 | "Pages returns 200 with placeholder `index.html`" on `acdl-evidence` | Gitea has no Pages; substitute: an HTTP GET against the raw file URL `https://git.cloudinit.dev/continuous-intelligence/acdl-evidence/raw/branch/main/index.html` returns 200 with the placeholder HTML body | D-012, D-016 | | REQ-10 | "`qa` and `prod` environments exist on `acdl-contracts`" | Gitea has no environments API and ignores `environment:` blocks; substitute: the reusable workflow defines `qa-gate` and `prod-gate` jobs gated by `workflow_dispatch` approval inputs (D-004 fallback); a `qa` and `prod` branch may be created on `acdl-contracts` as a visible stand-in for environments | D-013 | ## Out of Scope (v1.0 demo — retained for history) | Feature | Reason | |---------|--------| | Real cloud provisioning (AWS/GCP/Azure) | Demo explicitly stubs all infrastructure; no cloud access available. | | Real LLM inference / external AI APIs | Spec forbids external AI; L3B is a keyword parser. | | Production-grade infrastructure | Demo target is a 30-minute executive show, not a production system. | | Adversarial tamper-proofing of evidence | Hash chain is demonstrative; not cryptographically secure against a determined attacker. | | Multi-tenant isolation | Out of demo scope. | ## v1.9 (complete — design doc refresh + contract interpolation + per-env CI jobs + stub implementation + P1-1 remediation, tag `v1.9.0`) ### Category: Design Doc Refresh - **REQ-100:** `core/hitl_matrix_design.md` is up to date: the "dev-only spike" framing is replaced with the v1.9 wired-gates reality (qa/prod/dr `workflow_dispatch` approval gates + CODEOWNERS routing + outbox-based SoD); the 8-concern attestation matrix is marked implemented (offline-testable subset) with operator-supplied concerns noted; the spike-scope note is updated. No stale "v1.2 wires the gates" language remains. - **REQ-101:** `core/audit_ledger_design.md` is up to date: the hash-chain + DynamoDB-outbox path is marked shipped + production (since v1.8); the S3 Object Lock + JWS + async worker + DLQ + daily checkpoints build-out is clearly labeled "Deferred to a future milestone" (D-083); the RPO/RTO table reflects the v1.9 state. ### Category: P1-1 Remediation - **REQ-102:** The adapter (`adapters/terraform/adapter.py`) contains no resource-type-specific hardcoded defaults for ECS/ALB/VPC resources — `desired_count`, `launch_type`, `target_type`, `load_balancer_type`, `family`, and `Name` tag values are read from L1 `interface.json` inputs (with defaults declared in the interface). The adapter is a thin translator. An L1 with an overridden `desired_count: 3` emits `desired_count = 3`; the default emits `desired_count = 1` via the interface default, not an adapter hardcode (P1-1 closed). ### Category: Contract Interpolation - **REQ-103:** The contract resolver (`core/contract_resolver.py`) expands `${env.}` and `${contract.}` tokens in contract string values (including dotted paths like `${env.state_backend.bucket}`) after schema validation and before IR resolution. The `env` context is the loaded `core/environments/.json`; the `contract` context is the contract dict. Unresolved tokens raise `ValueError` (fail loud). Sample contracts use naming patterns that include region, account id, and environment (e.g. `acdl-${env.environment}-${contract.module}-${env.account_id}-${env.region}`). - **REQ-104:** An environment JSON schema `schemas/environment.schema.json` (draft 2020-12) defines the environment file shape (`name`, `account_id`, `region`, `state_backend`, `network`, `runner_role_arn`, `autonomy`, `confidence_threshold`). `core/environments/dev.json` validates against it. `qa.json`, `prod.json`, `dr.json` placeholder bindings exist (autonomy `attested`, thresholds 0.75/0.90/0.95). ### Category: Per-Environment CI Jobs - **REQ-105:** Per-environment contract files exist for each sample module (`contracts/static-assets.{dev,qa,prod,dr}.yaml` and `contracts/microservice.{dev,qa,prod,dr}.yaml`), each setting `environment:` to its own name and using interpolation for env-specific values. The existing `contracts/static-assets.yaml` + `contracts/microservice.yaml` remain as the dev default for backwards compatibility. - **REQ-106:** The reusable deploy workflow (`.github/workflows/deploy.yml` + `.gitea/workflows/deploy.yml`, byte-identical) declares an `environment` `workflow_call` input (enum dev/qa/prod/dr, default empty). When non-empty, `scripts/run_platform.sh --environment ` overrides the contract's `environment` field at load time (before interpolation). A consumer repo's caller workflow has one job per environment, each pointing at its respective contract (or the same contract + the env input). Promotion = running the matching job; no `environment:` field editing. `docs/CONSUMER_GUIDE.md` documents the per-env caller workflow pattern. ### Category: Stub Implementation - **REQ-107:** `core/separation_of_duties.py` `route_halt_artifact` is a real implementation: publishes to an SNS topic `acdl-sod-halt` (ARN from `ACDL_SOD_HALT_TOPIC_ARN`); when unset, falls back to a structured stderr emission + a `SEPARATION_OF_DUTIES_VIOLATION` event write to the DynamoDB outbox via `outbox_writer.write_event`. No silent print-only stub. The SNS topic is defined in `terraform/platform/main.tf`. - **REQ-108:** HITL qa/prod/dr pre-execution attestation gates are wired via `core/hitl_gates.py` (`attest(contract_id, env, approver, evidence)`). The gate records the approver (`gitea.actor` / `github.actor`) to the outbox (`approver_qa` / `approver_prod` / `approver_dr` attributes per `audit_ledger_design.md`), runs the separation-of-duties check on prod, and returns `(ok, reason)`. `scripts/run_platform.sh` calls `hitl_gates.attest` before apply for qa/prod/dr (dev skips). The workflow's `workflow_dispatch` approval input is the trigger. - **REQ-109:** The full 8-concern attestation matrix from `hitl_matrix_design.md` §10.4 is implemented in `core/attestation_matrix.py`. Offline-testable concerns (contract NFRs, schema validity, policy pass) run for real; operator-supplied concerns (k6 load test, DR drill, FinOps forecast) accept an uploaded signed evidence artifact validated for freshness + schema, failing loud if missing/expired for prod/dr. `hitl_gates.attest` invokes the matrix for the target env and blocks on any failing concern. - **REQ-110:** The Wiz adapter (`adapters/wiz/wiz_adapter.py`) is a real API client: a `WizClient` queries the Wiz GraphQL API (`WIZ_API_TOKEN` + `WIZ_API_URL`) and translates issues → `PolicyCheckResult` records. It degrades gracefully (existing `WIZ_NOT_CONFIGURED` SKIPPED record) when env unset. Offline tests use a recorded GraphQL fixture. - **REQ-111:** The Kyverno adapter (`adapters/kyverno/kyverno_adapter.py`) translator is fleshed out: full `PolicyReport` → `PolicyCheckResult` mapping with severity + skip handling. It remains inactive for Terraform-only stacks (guard preserved); a `--kube-version` stub is added for future GitOps. Sample policies already exist. ## v1.10 (active — pipeline regression fix + capability re-verification + verified-reality rewrite, tag `v1.10.0`) ### Category: Pipeline Regression Fix - **REQ-112:** The CIAgent VERIFY stage supports a `regression` mode that re-runs capability checks (not just diff checks), triggered at minimum on milestone completion. The regression run executes the local-emulator tier (REQ-113) for every capability marked Verified in prior milestones; any capability that fails the regression run blocks milestone completion. Regression results are recorded in `---ci---` blocks as `regression: { capability: , status: Verified|Decayed|Broken }`. Existing diff-scoped VERIFY behavior is preserved for non-regression invocations. A regression run against the current codebase surfaces at least one Decayed/Broken capability (proving the gate catches decay, not just passes). `tests/test_verify_regression_mode.py` passes. ### Category: Local Emulating Adapters - **REQ-113:** Local emulating adapters exist so the platform is fully locally testable without cloud credentials: (a) a flat-file DynamoDB outbox adapter that writes evidence events to flat files in a temp folder with a valid hash chain, same write/read interface as the live DynamoDB outbox adapter; (b) a local ECS Fargate emulator that records the service definition and returns a synthetic HTTP 200 from a local shell process, same interface as the live ECS adapter; (c) a local S3 state backend (flat-file tfstate in a temp folder); (d) a local Lambda stub that invokes the handler in-process with no AWS Lambda call. The headline E2E (contract submission → service live → evidence event) runs end-to-end against the local tier with no cloud credentials. `tests/test_local_emulating_adapters.py` passes. `run_platform.sh --local` (or equivalent) runs the full pipeline locally. ### Category: Capability Re-Verification Sweep - **REQ-114:** Every capability advertised in v1.1→v1.8 PROJECT/ROADMAP is enumerated in `.ciagent/CAPABILITY_INVENTORY.md` with a unique ID per capability (v1.0 demo excluded as archived/superseded). Each capability is re-verified: the headline E2E (contract → ECS Fargate → evidence event) runs both live-AWS and local-emulator tiers, both must pass; all other capabilities run the local tier via emulating adapters (REQ-113). Each capability is tagged Verified / Decayed / Broken in `CAPABILITY_INVENTORY.md`. Every Decayed/Broken capability is fixed in-sweep (D-090: no cap) until Verified, with per-capability commits `verify(P54): ` and `fix(P54): `. All v1.1→v1.8 advertised capabilities end Verified. The regression run (REQ-112) is clean against the re-verified state. ### Category: Verified-Reality Rewrite - **REQ-115:** PROJECT.md, ROADMAP.md, and both leadership decks are rewritten to match `CAPABILITY_INVENTORY.md` exactly. PROJECT.md gains a "Capability Status (Re-Verified 2026-07-27)" section listing every v1.1→v1.8 capability with its Verified tag and the tier(s) tested, plus a decay disclosure: capabilities marked complete in v1.1–v1.8 ran at the time of tagging; as of 2026-07-27 they were not reproducible and were re-verified in v1.10. ROADMAP.md v1.9.x entries note deck-freeze and superseded-by-reverification status. Both leadership decks reflect the re-verified status; any claim that cannot be demonstrated live is removed. HTML is re-rendered; PPTX is uploaded to the v1.10.0 release. Decks are unfrozen only after this lands. `ci-doc-verifier` confirms no stale capability claims remain. v1.10.0 is tagged; the Gitea release is published. ## Out of Scope (v1.9) | Feature | Reason | |---------|--------| | S3 Object Lock + JWS + async worker + DLQ + daily checkpoints (audit ledger build-out) | Requires non-offline-testable AWS infra (Object Lock bucket, KMS signing key, SQS DLQ, Lambda worker). Deferred to a future milestone (D-083). The hash-chain + DynamoDB-outbox path remains the v1.9 production audit record. | | Live k6/Gatling load test execution, live DR drill, live FinOps forecast | Operator-supplied evidence artifacts (signed blobs) are accepted + validated; the platform does not run these inline. | | Self-service environment provisioning | Adding an environment remains a platform-team action (per `core/environments/README.md`). v1.9 adds the env files + schema, not self-service provisioning. | ## Traceability ### v1.0 (prior — demo) | Requirement | Phase | Status | |-------------|-------|--------| | REQ-01 | 1 | complete (v1.0.1) | | REQ-02 | 2 | complete (v1.0.2) | | REQ-03 | 2 | complete (v1.0.2) | | REQ-04 | 3 | complete (v1.0.3) | | REQ-05 | 3 | complete (v1.0.3) | | REQ-06 | 3 | complete (v1.0.3) | | REQ-07 | 3 | complete (v1.0.3) | | REQ-08 | 3 | complete (v1.0.3) | | REQ-09 | 1 | complete (v1.0.1) | | REQ-10 | 4 | complete (v1.0.4) | | REQ-11 | 3 | complete (v1.0.3) | | REQ-12 | 4 | complete (v1.0.4) | | REQ-13 | 5 | complete (v1.0.5) | | REQ-14 | 5 | complete (v1.0.5) | | REQ-15 | 5 | complete (v1.0.5) | ### v1.1 (prior — architecture finalization + v1 spike, complete) | Requirement | Phase | Status | |-------------|-------|--------| | REQ-16 | 07 | complete (v1.1.2) | | REQ-17 | 07 | complete (v1.1.2) | | REQ-18 | 07 | complete (v1.1.2) | | REQ-19 | 07 | complete (v1.1.2) | | REQ-20 | 07 | complete (v1.1.2) | | REQ-21 | 07 | complete (v1.1.2) | | REQ-22 | 07 | complete (v1.1.2) | | REQ-23 | 08 | complete (v1.1.3) | | REQ-24 | 09 | complete (v1.1.4) | | REQ-25 | 10 | complete (v1.1.5) | | REQ-26 | 09 | complete (v1.1.4) | | REQ-27 | 10 | complete (v1.1.5) | | REQ-28 | 10 | complete (v1.1.5) | ### v1.2 (prior — platform hardening + first real consumer deployment, complete) | Requirement | Phase | Status | |-------------|-------|--------| | REQ-29 | 11 | complete (v1.2.1) | | REQ-30 | 12 | complete (v1.2.2) | | REQ-31 | 13 | complete (v1.2.3) | | REQ-32 | 14 | complete (v1.2.4) | | REQ-33 | 15 | partial (v1.2.5, IAM-blocked) | | REQ-34 | 15 | complete (v1.2.5) | | REQ-35 | 16 | partial (v1.2.6, IAM-blocked) | ### v1.3 (prior — module documentation + thin-composition removal, complete) | Requirement | Phase | Status | |-------------|-------|--------| | REQ-36 | 17 | complete (v1.3.1) | | REQ-37 | 17 | complete (v1.3.1) | | REQ-38 | 17 | complete (v1.3.1) | | REQ-39 | 18 | complete (v1.3.2) | | REQ-40 | 18 | complete (v1.3.2) | | REQ-41 | 18 | complete (v1.3.2) | | REQ-42 | 18 | complete (v1.3.2) | ### v1.4 (prior — central pipeline contract + shell reproducibility + streaming) | Requirement | Phase | Status | |-------------|-------|--------| | REQ-43 | 19 | complete (v1.4.1) | | REQ-44 | 19 | complete (v1.4.1) | | REQ-45 | 19 | complete (v1.4.1) | ### v1.5 (prior — consumer happy path + zero-trust docs + reusable deploy workflow, complete) | Requirement | Phase | Status | |-------------|-------|--------| | REQ-46 | 20 | complete (v1.5.0) | | REQ-47 | 20 | complete (v1.5.0) | | REQ-48 | 20 | complete (v1.5.0) | | REQ-49 | 20 | complete (v1.5.0) | | REQ-50 | 20 | complete (v1.5.0) | | REQ-51 | 20 | complete (v1.5.0) | ### v1.6 (complete — consumer-facing docs restructure + terminology normalization + environments concept, tag `v1.6.0`) | Requirement | Phase | Status | |-------------|-------|--------| | REQ-52 | 21 | complete (v1.6.0) | | REQ-53 | 21 | complete (v1.6.0) | | REQ-54 | 21 | complete (v1.6.0) | | REQ-55 | 21 | complete (v1.6.0) | | REQ-56 | 21 | complete (v1.6.0) | | REQ-57 | 21 | complete (v1.6.0) | | REQ-58 | 21 | complete (v1.6.0) | | REQ-59 | 21 | complete (v1.6.0) | | REQ-60 | 21 | complete (v1.6.0) | | REQ-61 | 21 | complete (v1.6.0) | ### v1.7 (complete — production platform + contract ingestion + pipeline maturation, tag `v1.7.0`) | Requirement | Phase | Status | |-------------|-------|--------| | REQ-62 | 22 | complete (v1.7.0) | | REQ-63 | 22 | complete (v1.7.0) | | REQ-64 | 22 | complete (v1.7.0) | | REQ-65 | 23 | complete (v1.7.0) | | REQ-66 | 23 | complete (v1.7.0) | | REQ-67 | 23 | complete (v1.7.0) | | REQ-68 | 24 | complete (v1.7.0) | | REQ-69 | 25 | complete (v1.7.0) | | REQ-70 | 25 | complete (v1.7.0) | | REQ-71 | 25 | complete (v1.7.0) | | REQ-72 | 26 | complete (v1.7.0) | | REQ-73 | 26 | complete (v1.7.0) | | REQ-74 | 27 | complete (v1.7.0) | | REQ-75 | 27 | complete (v1.7.0) | ### v1.8 (complete — P1 remediation + uptime + standards + encryption/deletion-protection by default + decommission + docs, tag `v1.8.0`) | Requirement | Phase | Status | |-------------|-------|--------| | REQ-76 | 28 | complete (v1.8.0) | | REQ-77 | 28 | complete (v1.8.0) | | REQ-78 | 29 | complete (v1.8.0) | | REQ-79 | 29 | complete (v1.8.0) | | REQ-80 | 30 | complete (v1.8.0) | | REQ-81 | 30 | complete (v1.8.0) | | REQ-82 | 30 | complete (v1.8.0) | | REQ-83 | 31 | complete (v1.8.0) | | REQ-84 | 31 | complete (v1.8.0) | | REQ-85 | 31 | complete (v1.8.0) | | REQ-86 | 32 | complete (v1.8.0) | | REQ-87 | 32 | complete (v1.8.0) | | REQ-88 | 33 | complete (v1.8.0) | | REQ-89 | 33 | complete (v1.8.0) | | REQ-90 | 33 | complete (v1.8.0) | | REQ-91 | 33 | complete (v1.8.0) | | REQ-92 | 34 | complete (v1.8.0) | | REQ-93 | 34 | complete (v1.8.0) | | REQ-94 | 34 | complete (v1.8.0) | | REQ-95 | 35 | complete (v1.8.0) | | REQ-96 | 35 | complete (v1.8.0) | | REQ-97 | 36 | complete (v1.8.0) | | REQ-98 | 36 | complete (v1.8.0) | | REQ-99 | 36 | complete (v1.8.0) | ### v1.9 (complete — design doc refresh + contract interpolation + per-env CI jobs + stub implementation + P1-1 remediation, tag `v1.9.0`) | Requirement | Phase | Status | |-------------|-------|--------| | REQ-100 | 39 | complete (v1.9.0) | | REQ-101 | 39 | complete (v1.9.0) | | REQ-102 | 39 | complete (v1.9.0) | | REQ-103 | 40 | complete (v1.9.0) | | REQ-104 | 40 | complete (v1.9.0) | | REQ-105 | 41 | complete (v1.9.0) | | REQ-106 | 41 | complete (v1.9.0) | | REQ-107 | 42 | complete (v1.9.0) | | REQ-108 | 42 | complete (v1.9.0) | | REQ-109 | 42 | complete (v1.9.0) | | REQ-110 | 42 | complete (v1.9.0) | | REQ-111 | 42 | complete (v1.9.0) | ### v1.10 (active — pipeline regression fix + capability re-verification + verified-reality rewrite, tag `v1.10.0`) | Requirement | Phase | Status | |-------------|-------|--------| | REQ-112 | 52 | complete (v1.9.9) | | REQ-113 | 53 | complete (v1.9.10) | | REQ-114 | 54 | complete (v1.9.11) | | REQ-115 | 55 | complete (v1.9.12) | ## v1.11 (active — RESTART: stateless adapter + pipeline-driven module lifecycle testing, tag `v1.11.0`) The v1.11 milestone closes G-005 (CAP-017..022 deploy-unverified) and G-008 (no cost docs) via a corrected architecture. The first v1.11 attempt is abandoned (branches `phase/56-iam-re-bootstrap` + `phase/57-live-deploy-microservice`); the restart branches off `v1.10.2`. ### Category: Stateless Adapter - **REQ-123** — The terraform adapter (`adapters/terraform/adapter.py`) is rewritten from a 918-line monolith (3 constant tables `TYPE_MAP`/`INPUT_MAP`/`OUTPUT_MAP` + 39 type-specific branches) to a ~80-line stateless assembler. Each L1 module ships a real `terraform/` module dir owning its resource shape, nested blocks, and defaults. The adapter reads the registry and emits `module "x" { source = ... }` blocks. No type-specific logic in the adapter. (Phase P56a) ### Category: Per-Module Terraform - **REQ-124** — All 12 L1 modules have a `terraform/` subdir (`versions.tf`/`variables.tf`/`locals.tf`/`main.tf`/`outputs.tf`) with defaults centralized in `locals.tf` (heavy interpolation of vars against sensible defaults). `interface.json` stays engine-agnostic. The registry has a `terraform_dir` field per entry. (Phase P56b) ### Category: Shell Lifecycle Modes - **REQ-125** — `scripts/run_platform.sh` gains `--apply` and `--destroy` modes; the shell owns all terraform lifecycle. Python never runs terraform. `scripts/verify_deploy_microservice.py` is deleted. (Phase P57) ### Category: Single Platform VPC + Deterministic State - **REQ-126** — `terraform/platform/main.tf` owns ONE VPC; the microservice composition references it via `data` source (no inline VPC). State keys are deterministic and env-aware (`spike/{id}/{env}/terraform.tfstate`), stable across apply/modify/destroy. (Phase P58) ### Category: L1 Lifecycle Pipeline - **REQ-127** — 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. The "test" = the pipeline cell going green. (Phases P59–P60) ### Category: L2 Lifecycle Pipeline - **REQ-128** — The lifecycle pipeline extends to L2 modules (static-assets, microservice). L2 = composition only (no L2 terraform files); the composition is deterministic (same contract → same stack → same state key). (Phases P61–P62) ### Category: Operating Model + G-005/G-008 Closure - **REQ-116** — CAP-017..022 marked Verified in CAPABILITY_INVENTORY + PROJECT + decks with "Verified live-aws via lifecycle pipeline; torn down to zero-cost" note. (Phase P65) - **REQ-118** — Both leadership decks rewritten to reflect verified-then-torn-down status; no stale "deploy-unverified" claims. (Phase P65) - **REQ-119** — `.ciagent/COST.md` documents the v1.0→v1.10 AWS spend window (Cost Explorer query). (Phase P63) - **REQ-120** — `.ciagent/PRE_MORTEM.md` documents the v1.10 decay root cause + forward pre-mortem. (Phase P64) - **REQ-121** — CAP-017..022 added to the regression registry (evidence = lifecycle pipeline green). (Phase P63) - **REQ-122** — All deployed stacks torn down via `--decommission` (D-070 two-step, CR CHG0680001); zero live ACDL resources remain. (Phase P64) ### v1.11 Traceability | Requirement | Phase | Status | |-------------|-------|--------| | REQ-123 | P56a | complete | | REQ-124 | P56b | complete | | REQ-125 | P57 | complete | | REQ-126 | P58 | complete | | REQ-127 | P59, P60 | complete | | REQ-128 | P61, P62 | complete | | REQ-116 | P65 | complete | | REQ-118 | P65 | complete | | REQ-119 | P63 | complete | | REQ-120 | P64 | complete | | REQ-121 | P63 | complete | | REQ-122 | P64 | complete | ### Out of Scope (v1.11) - OIDC act_runner adoption (pending go-gitea/gitea#36988). - Per-phase regression (G-007: milestone-level regression gate is correct). - Audit ledger build-out (D-083). - Operator-supplied evidence. - Pilot onboarding (G-001). - Boto3 post-deploy verification probes (CAP-017..022 live-verify via boto3) — deferred to a future QA milestone. The lifecycle pipeline apply→destroy IS the verification for v1.11. --- ## Milestone v1.12 — Presentation Refinement (REQ-129..REQ-133) **Objective:** Refine the leadership presentation decks to reflect the verified reality after v1.11 — the stateless adapter, pipeline-driven lifecycle testing, the cost operating model, the pre-mortem, and the teardown to zero-cost. The v1.11 P65 deck-rewrite task did not fully land on the deck artifacts: the rendered HTML still claims 6 cloud capabilities are "deploy-unverified (IAM drift)", the road-to-north-star diagram still shows v1.10 as "NEXT", and the v1.11 architecture stories are absent. The v1.10 decay lesson (PRE_MORTEM.md FM-3) requires decks to match verified reality exactly, not outrun it. The v1.12 regression gate run (Phase 66) surfaced 3 Broken capabilities — one real adapter defect (CAP-013) and two regression-probe bugs (CAP-017, CAP-018) — that must be fixed before the decks can honestly claim 22/22 Verified. **Surface:** leadership decks only (`docs/presentations/`) — both decks across all four layers (source markdown, Marp deck, rendered HTML, talking points) + diagrams + README. Plus the one real adapter fix and two probe fixes required to make the deck claims true. ### Requirements - **REQ-129** — The adapter's module-call dedup logic (`adapters/terraform/adapter.py`) is fixed so multi-resource L1s with stack outputs (e.g. `ecs-service`, `alb`) produce valid Terraform: `terraform validate` succeeds for the microservice stack (CAP-013 Verified live-aws). The regression gate re-runs and confirms 22/22 Verified. (Phase 67) - **REQ-130** — The two regression-probe bugs are fixed: CAP-017's probe no longer requires `locals.tf` for modules that legitimately omit it (`core/regression_verify.py`); CAP-018's probe instantiates `LocalLambdaStub` with the required `outbox` arg. The regression gate re-runs clean (19 Verified + 3 fixed → 22/22 Verified). (Phase 67) - **REQ-131** — Both leadership decks' capability claims match `CAPABILITY_INVENTORY.md` exactly: 22/22 Verified, no "deploy-unverified" / "IAM drift" / "design-verified" framing. The decks reflect "Verified live-aws via lifecycle pipeline; torn down to zero-cost." A grep-based doc verification (successor to the planned `ci-doc-verifier`) confirms zero stale claims across `docs/presentations/`. (Phase 68, Phase 70) - **REQ-132** — Both decks reflect v1.11's architecture as leadership-relevant stories: (a) the stateless adapter (918→~80 lines, defaults centralized in per-module `terraform/` dirs, the adapter is an assembler); (b) pipeline-driven lifecycle testing (a `modules-lifecycle` pipeline matrix-runs each module apply→modify→destroy against live AWS — the green cell IS the verification). The `road-to-north-star` diagram + both decks' roadmap appendix slides reflect v1.11 complete (v1.10 no longer "NEXT"). Version refs in deck examples bump from `@v1.10` → `@v1.11` (and `@v1.12` at Phase 70 complete after the tag exists). (Phase 68) - **REQ-133** — Both decks' "Operating Model & Cost" appendix slide carries the real `COST.md` figures ($0.001883 / 8 days, ~$0.007/mo, S3-dominated, zero BAU compute) + the zero-cost-steady-state / D-096 teardown claim, and references the pre-mortem (`PRE_MORTEM.md`: v1.10 decay root cause + four forward failure modes + structural mitigations). Both rendered HTML decks re-rendered and committed; both talking-points files re-distilled to match the updated Marp structure (including the A6 Operating Model & Cost section that was missing from the talking points). PPTX exported to the v1.12.0 release. (Phase 69, Phase 70) - **REQ-134** — The `modules-lifecycle` pipeline defaults to **plan-only** (fast, no AWS mutation) so it runs on every PR without cost or AWS credentials. A CI variable `ACDL_LIFECYCLE_MODE` (workflow input `lifecycle_mode`, default `plan`) overrides to `full` for the real apply→modify→destroy against live AWS. The four lifecycle scripts (`run_lifecycle_test.sh`, `run_lifecycle_destroy.sh`, `run_l2_lifecycle_test.sh`, `run_l2_lifecycle_destroy.sh`) read the flag and dispatch to `--plan-only` (plan mode) or `--apply`/`--destroy` (full mode). Both forge workflows (`.github` + `.gitea`, byte-identical) expose `lifecycle_mode` as a `workflow_dispatch` input and pass it via `env:` to every lifecycle step; the CI VPC apply/destroy jobs are skipped in plan mode. `pipelines/modules-lifecycle.yml` + the schema document the `default_mode: plan` field. Tests assert the plan-only default, the override path, the byte-identity of both workflows, and the CI VPC skip in plan mode. (Phase 67b) ### v1.12 Traceability | Requirement | Phase | Status | |-------------|-------|--------| | REQ-129 | P67 | complete | | REQ-130 | P67 | complete | | REQ-134 | P67b | complete | | REQ-131 | P68, P70 | complete | | REQ-132 | P68 | complete | | REQ-133 | P69, P70 | complete | ### Out of Scope (v1.12) - docs/ site, README.md, consumer-guide, module READMEs (decks only). - Structural deck rework (re-ordering, adding/removing main slides) — v1.12 keeps the 10 main + 6 appendix structure to avoid the backwards-sequencing failure mode (PRE_MORTEM.md FM-3). - New capability claims beyond what v1.11 verified. - Per-phase regression hardening (G-007, unchanged). --- ## Milestone v1.14 — NFR Refinement (REQ-135..REQ-154) **Objective:** Bug fixes, security posture improvements, stub/missing- functionality identification + implementation, and documentation + NFR refinement across the entire codebase. **No new features.** NFR milestone — the final phase's patch IS the deliverable. The v1.11 multi-persona review left 5 P1 + 4 P2 findings open; the codebase has 6+ swallowed-error sites, 15+ hardcoded account-ID references, 7 untested scripts, an offline-proxy regression gate, ARCHITECTURE.md with no v1.11–v1.13 addendum, and consumer-facing docs referencing stale `@v1.6`–`@v1.9` workflow tags. v1.14 clears all of it in a 20-phase sweep. ### Requirements - **REQ-135** — The adapter dedup loop raises `ValueError` for unregistered-module resources instead of silently dropping them (P1-1). (Phase P1) - **REQ-136** — The static-assets L2 composition wires `default_ttl`/ `max_ttl`/`price_class`/`viewer_protocol_policy` and makes WAF conditional via `waf_enabled`, so `complex.yml` is a real modify (P1-2). (Phase P2) - **REQ-137** — The L2 lifecycle scripts' usage strings no longer advertise the vestigial `[ci-vpc-outputs.json]` arg, or document the remote-state design (P1-3). (Phase P3) - **REQ-138** — The regression gate's CAP-017..022 checks run `terraform validate` (not just file-existence + resolver); the offline-proxy caveat is documented honestly (P1-5). (Phase P4) - **REQ-139** — Unit tests for adapter dedup merge behavior + `ACDL_REMOTE_STATE_KEY` override exist and pass (P2-2). (Phase P5) - **REQ-140** — The ALB target group `name_prefix` derives from `var.name` (P2-1). (Phase P6) - **REQ-141** — 6 over-broad `except ...: pass` sites narrowed to specific exceptions; errors logged with context. (Phase P7) - **REQ-142** — The hardcoded account ID `581513795199` is externalized to `ACDL_AWS_ACCOUNT_ID` env / `data.aws_caller_identity` across 15+ sites. (Phase P8) - **REQ-143** — 6 `Resource: "*"` IAM statements scoped to `acdl-*` ARNs; regression test asserts the scoping. (Phase P9) - **REQ-144** — The contract ingestor validates `contractId`/`environment`/ `error`; ABAC reliance documented; spoofing-resistance test passes. (Phase P10) - **REQ-145** — `contract.schema.json` + `environment.schema.json` reject undocumented fields (`additionalProperties: false`); format validation for bucket/ARN/CIDR. (Phase P11) - **REQ-146** — `.gitignore` has a credential-pattern catch-all; `test_no_secrets_tracked.py` passes. (Phase P12) - **REQ-147** — The Kyverno `--kube-version` flag is either implemented or removed with a documented deferral rationale. (Phase P13) - **REQ-148** — Orphan bytecode + dead config cleaned (orphan `.pyc`, stale coverage source, stale version, dead JS allowlist). (Phase P14) - **REQ-149** — 7 untested scripts have unit test coverage (≥1 test each). (Phase P15) - **REQ-150** — Gitea workflow parity resolved; `rotate_spike_key.sh` + `sync_to_gl.sh` have `set -euo pipefail`. (Phase P16) - **REQ-151** — `config.json` persona block + branching strategy + ollama-cloud backend aligned with PERSONAS.md + actual runtime. (Phase P17) - **REQ-152** — `modules/STANDARDS.md` internally consistent; no stale `TYPE_MAP` reference. (Phase P18) - **REQ-153** — ARCHITECTURE.md has v1.11–v1.14 addenda; stale `@v1.6–1.9` → `@v1.13`; GRILL G-005/G-008 resolved; COST.md window covers v1.11–v1.14; D-083 deferral recorded. (Phase P19) - **REQ-154** — Platform VPC CIDR is a variable; subnet count is data-driven; `0.0.0.0/0` ingress documented. (Phase P20) ### v1.14 Traceability | Requirement | Phase | Status | |-------------|-------|--------| | REQ-135 | P1 | complete | | REQ-136 | P2 | complete | | REQ-137 | P3 | complete | | REQ-138 | P4 | complete | | REQ-139 | P5 | complete | | REQ-140 | P6 | complete | | REQ-141 | P7 | complete | | REQ-142 | P8 | complete | | REQ-143 | P9 | complete | | REQ-144 | P10 | complete | | REQ-145 | P11 | complete | | REQ-146 | P12 | complete | | REQ-147 | P13 | complete | | REQ-148 | P14 | complete | | REQ-149 | P15 | complete | | REQ-150 | P16 | complete | | REQ-151 | P17 | complete | | REQ-152 | P18 | complete | | REQ-153 | P19 | complete | | REQ-154 | P20 | complete | ### Out of Scope (v1.14) - New features (feat phases). v1.14 is NFR-only. - D-083 audit ledger build-out (S3 Object Lock + JWS + SQS DLQ + async worker) — remains deferred; documented explicitly in ARCHITECTURE.md. - Real OIDC federation (blocked on go-gitea/gitea#36988). - Per-phase regression hardening (G-007, unchanged). - Boto3 post-deploy verification probes (deferred to a future QA milestone). --- ## v1.15 — Nova (Rebrand) **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` (P1–P4) → `v1.15.4` (P5 final = milestone release). (G-104 binding: the v1.14.x patch line is the NFR convention; a Major milestone ships on its own minor.) A full rebrand from **ACDL** / "Agentic Cloud Delivery Platform" → **Nova** / "The New Dawn of DevSecOps — security as a seamless enabler of fast deployments." The new tagline is added alongside 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. The rebrand applies across docs, decks, code, configs, CI, env vars, consumer conventions, SSM paths, AWS tag keys, and AWS resource names — with a staged infrastructure migration to avoid breakage. Ideation source: `--ideate` flag (user-directed scope; the survey found 1,465 occurrences of `ACDL`/`acdl` across 205 files and zero existing `nova` references — no collision risk). Accepted ideas become IDEATE-01..IDEATE-10, mapped to REQ-155..REQ-164. ### Requirements - **REQ-155** — (IDEATE-01) All prose, titles, headers, and comments across `README.md`, `docs/**`, `.ciagent/*.md`, deck markdown sources, `pyproject.toml` name/description, and `release.yml` release-title prefix are rebranded `ACDL`/`Agentic Cloud Delivery Platform` → `Nova`. Illustrative URLs in docs (`github.com/acdl/...`, `git.cloudinit.dev/continuous-intelligence/acdl*`) are updated to `nova` for prose consistency. Gitea release titles going forward read `Nova vX.Y.Z` (past releases keep their names). (Phase P1) - **REQ-156** — (IDEATE-02) All Marp deck markdown sources (`docs/presentations/*-marp.md`, `*.md`, `*-talking-points.md`) and mermaid source `.mmd` files are rebranded `ACDL` → `Nova`; the deck title-slide subtitle becomes `Nova — The New Dawn of DevSecOps`. The `.mmd` sources are edited and the rendered PNG diagrams are re-exported so the committed PNGs match the new labels. The S&P visual theme (`sp-theme.json`) is unchanged. HTML decks are re-rendered. (Phase P1) - **REQ-157** — (IDEATE-03) The Nova tagline ("The New Dawn of DevSecOps — security as a seamless enabler of fast deployments") is added to the README header, both deck title slides, and `docs/vision.md` — alongside (not replacing) the existing "North Star" / "consumers declare intent" framing. (Phase P1) - **REQ-158** — (IDEATE-04) `adapters/terraform/policy/custom_rules/acdl_tagging.py` is renamed `nova_tagging.py` with its Checkov custom-rule registration updated (`schemas/tagging-standard.json` line 5 + adapter config). The Checkov rule enforces `nova:*` tag keys. (Phase P2) - **REQ-159** — (IDEATE-05) All 21 `ACDL_*` env var prefixes are renamed to `NOVA_*` across `scripts/`, `core/`, `adapters/`, `tests/`, workflows (`.gitea/`, `.github/`), `.env`, `.env.secrets` (key names only — values/secret material stay), and consumer docs. A **dual-read fallback** (`NOVA_X` preferred, fall back to `ACDL_X`) is implemented in the config/env loader so deployments do not break during the transition window; the fallback is removed in the final phase once all consumers are migrated. Gitea repo secrets are rotated via API. (Phase P2) - **REQ-160** — (IDEATE-06) The consumer on-disk contract path `.acdl/contract.yml` (and `.acdl/static-assets.*.yml`, `.acdl/contract.yaml`) becomes `.nova/contract.yml` across the contract resolver, deploy workflow checkout path, consumer docs, and the contract schema description. A consumer migration guide is shipped with P1 docs. (Phase P2) - **REQ-161** — (IDEATE-07) The SSM parameter path prefix `/acdl/{env}/{contractId}/{output}` becomes `/nova/{env}/{contractId}/{output}` across `core/output_publisher`, the contract resolver, and consumer docs. A migration script copies existing `/acdl/...` parameters → `/nova/...`, readers are updated, then old parameters are deleted. (Phase P3) - **REQ-162** — (IDEATE-08) AWS tag keys `acdl:owner`, `acdl:environment`, `acdl:contract`, `acdl:cost-center`, `acdl:ref` become `nova:owner`, `nova:environment`, `nova:contract`, `nova:cost-center`, `nova:ref` across terraform tagging, the Checkov custom rule (`nova_tagging.py`), and ABAC session policies. A **parallel-tag period** adds `nova:*` tags to all resources first, updates the ABAC session policies to match `nova:*`, then removes the `acdl:*` tags once consumers are verified. (Phase P3) - **REQ-163** — (IDEATE-09) All `acdl-*` AWS resource names are renamed to `nova-*` via terraform: KMS alias `alias/acdl-platform` → `alias/nova-platform`, SNS `acdl-sod-halt` → `nova-sod-halt`, SG `acdl-ecs-sg` → `nova-ecs-sg`, Lambda `acdl-contract-ingestor` → `nova-contract-ingestor`, DynamoDB `acdl-contracts`/`acdl-change-requests` → `nova-contracts`/`nova-change-requests` (scan+copy data migration, verify row counts, keep old tables until verified), ECR `acdl-microservice` → `nova-microservice` (re-push images), IAM user/policy `acdl-spike-runner` → `nova-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-alb` → `nova-alb` (recreate, brief downtime). A maintenance window + rollback runbook is published with the migration. (Phase P4) - **REQ-164** — (IDEATE-10) The dual-read env var fallback (`ACDL_*`→`NOVA_*`) and any `ACDL_*`-only references are removed once all consumers are migrated; the consumer migration guide is finalized; `nova_tagging.py` no longer accepts `acdl:*` tag keys. (Phase P5) ### v1.15 Traceability | Requirement | Phase | Status | |-------------|-------|--------| | REQ-155 | P1 | complete | | REQ-156 | P1 | complete | | REQ-157 | P1 | complete | | REQ-158 | P2 | complete | | REQ-159 | P2 | complete | | REQ-160 | P2 | complete | | REQ-161 | P3 | complete | | REQ-162 | P3 | complete | | REQ-163 | P4 | complete | | REQ-164 | P5 | complete | ### Out of Scope (v1.15) - Renaming the real Gitea org/repo (`continuous-intelligence/acdl`) or GitHub org `acdl` — config.json `release.gitea.repo` stays `acdl`; URLs in docs are illustrative and updated to `nova` for prose only. - Renaming the S&P Global Energy visual theme (`sp-theme.json`, deck CSS) — that is client branding, not the Nova product brand. - Past Gitea release titles — existing releases keep their `ACDL vX.Y.Z` names; only future releases use `Nova vX.Y.Z`. - Git branch/tag naming — branches use `milestone/v*` / `phase/*` and tags use `v*` semver; no brand name present, no change needed. --- ## v1.16 — Nova Simplification (NFR) **Milestone type:** NFR (all phases fix/chore/docs/refactor/test). The final phase's patch IS the deliverable — no separate milestone tag. Tags run on the v1.15.x line: `v1.15.5` (P0) → `v1.15.6..v1.15.25` (P1–P20) → `v1.15.26` (P21 final = milestone release). **Objective:** A 20-phase NFR sweep (no new features) themed around five user-directed axes: Simplify without regressions, Security, Maintainability, User/Developer Experience, and No Humans Onboarding Flow. The v1.15 rebrand left a fresh debt layer (stale brand strings, a state-bucket drift, a Kyverno policy contradicting the Nova tagging standard, dead code) that this milestone clears, alongside genuine simplification and the first self-service onboarding request path. ### Requirements - **REQ-165** — The adapter-emitted terraform backend references `nova-tfstate-*` (not `acdl-tfstate-*`); the Kyverno `require-resource-labels.yml` policy enforces `nova:*` labels (not `acdl:*`). Correctness regression fix from the v1.15 rebrand. (Phase P1) - **REQ-166** — All user-facing "ACDL" strings rebranded to Nova: onboarding message, Lambda alert title/body, PR-stage comments, CI banner, module docstrings (contract_resolver/confidence_signal/adapter/ kyverno/wiz + adapters README). (Phase P2) - **REQ-167** — Dead `ACDL_ENVIRONMENT_OVERRIDE` export removed; stale dual-read comments dropped; `acdl_*` temp-dir prefixes → `nova_*`. (Phase P3) - **REQ-168** — `migrate_ssm_paths.py` `except Exception: pass` narrowed to `ParameterNotFound` + structured log. (Phase P4) - **REQ-169** — `regression_verify.py` duplicated live-plan/resolver/ lifecycle-resolve blocks extracted into shared helpers (~70 lines saved). (Phase P5) - **REQ-170** — `run_platform.sh` dead export removed; HITL attestation block extracted to a shell function; hardcoded UUID/`v18` work-dir stamp replaced with config. (Phase P6) - **REQ-171** — `contract_resolver.py` imports the env loader from `environment_check` (dedup); registry entries carry a `kind` field; fragile `is_l2` path-string heuristic replaced. (Phase P7) - **REQ-172** — `scripts/sync_workflows.py` generates the 3 byte-identical workflow pairs from one source; the byte-identity test is replaced with a generator-output test. (Phase P8) - **REQ-173** — `run_platform.sh` decommission + uptime blocks extracted into `scripts/run_decommission.sh` + `scripts/run_uptime.sh`. (Phase P9) - **REQ-174** — `contract_ingestor.py` fails closed (not silent `pass`) when IAM identity is absent; the env enum is derived from `core/environments/` (not hardcoded). (Phase P10) - **REQ-175** — The contract blob payload is size-capped + schema- validated before the DynamoDB write; error/stackTrace caps are consistent. (Phase P11) - **REQ-176** — `contract_resolver.py` (638 lines) split into resolve / decommission-transform / cli modules. (Phase P12) - **REQ-177** — `regression_verify.py` (670 lines) split into capability checks / live-plan helpers / cli modules. (Phase P13) - **REQ-178** — `SAFE_OUTPUT_NAMES` is schema-driven (from interface.json `sensitive` annotations); loaded schemas are cached in the resolver. (Phase P14) - **REQ-179** — `run_platform.sh` has a real `--help`; `--deploy-uptime` is documented; `--local` is surfaced in the README. (Phase P15) - **REQ-180** — `.github/workflows/README.md` catalogs all 7 workflows' triggers, inputs, required secrets, and reusable-workflow contracts. (Phase P16) - **REQ-181** — A single getting-started section in the README: offline happy path (`run_ci.sh` + `run_platform.sh --check-only`/ `--local`) first, AWS path second. (Phase P17) - **REQ-182** — `schemas/onboarding.schema.json` defines the onboarding request; `contract_ingestor.py` gains an `onboard_consumer` action that writes a `pending` CMDB row. (Phase P18) - **REQ-183** — `core/onboarding.py` generates a `.json` from a consumer request + emits a PR; the onboarding message is rebranded to Nova and no longer routes to "contact the platform team" for the request step. (Phase P19) - **REQ-184** — Terraform for the consumer deploy-role + `nova:owner` ABAC tag grant, offline-proven (`terraform validate` + `--check-only` only; no live apply). (Phase P20) ### v1.16 Traceability | Requirement | Phase | Status | |-------------|-------|--------| | REQ-165 | P1 | complete | | REQ-166 | P2 | complete | | REQ-167 | P3 | complete | | REQ-168 | P4 | complete | | REQ-169 | P5 | complete | | REQ-170 | P6 | complete | | REQ-171 | P7 | complete | | REQ-172 | P8 | complete | | REQ-173 | P9 | complete | | REQ-174 | P10 | complete | | REQ-175 | P11 | complete | | REQ-176 | P12 | complete | | REQ-177 | P13 | complete | | REQ-178 | P14 | complete | | REQ-179 | P15 | complete | | REQ-180 | P16 | complete | | REQ-181 | P17 | complete | | REQ-182 | P18 | complete | | REQ-183 | P19 | complete | | REQ-184 | P20 | complete | ### Out of Scope (v1.16) - New features (feat phases). v1.16 is NFR-only. - Real AWS account/network/state provisioning (self-service) — the onboarding request path is implemented (D-113); actual cloud resource creation stays a future feature milestone. - Live apply of the cross-account role Terraform (D-114) — offline-proven only; live apply deferred. - D-083 audit ledger build-out (carries forward; unchanged). - Real OIDC federation (carries forward; blocked on go-gitea/gitea#36988). - Re-proposing v1.14 NFR categories already closed (D-117): over-broad excepts (REQ-141), hardcoded account-ID (REQ-142), IAM `Resource:"*"` scoping (REQ-143), contractId/env validation (REQ-144), `.gitignore` catch-all (REQ-146), `--kube-version` removal (REQ-147), orphan cleanup (REQ-148), `set -euo pipefail` parity (REQ-150). ## v1.17 — Strategic Direction, Leadership Metrics & Unified Story **Milestone type:** Feature (P1–P3 feat; P4 docs; P5 docs+test; P6 test; P7 review+audit+ship). Progressive patches; the final phase's patch IS the milestone release. Tags run on the v1.16.x line: `v1.16.0` (P0) → `v1.16.1..v1.16.7` (P1–P7) → `v1.16.8` (P8 final = milestone release). **Objective:** Three pillars. (A) Encode the PO's strategic direction in a durable `NORTH_STAR.md` read by CIAgent in every future `/ci-run`. (B) Instrument Nova to collect, aggregate, and surface leadership-grade metrics that prove the "no-humans" autonomous-infrastructure value proposition — grounded in signals Nova actually emits, derived via documented formulas, or explicitly deferred with a decision ID — flowing into PowerBI-ready views. (C) Merge the two existing decks into one unified narrative deck with the "tell them x3" arc at deck + slide level, per-slide benefit callouts, and fluid transitions. **Hard constraint:** DO NOT make anything up. Every metric carries a `grounded` / `derived` / `deferred` status with a source file or decision ID. Deferred metrics ship as empty PowerBI placeholder views with documented schemas. ### Requirements **Pillar A — Strategic Direction** - **REQ-185** — `.ciagent/NORTH_STAR.md` is PO-authored with Vision, Strategic Objectives (4), Anti-Goals (5), Non-Goals (v1.17 scope), 12–18mo Targets (with grounding column), and Success Criteria. The attestation clarification is reflected: human attestation required at stage gates (QA for production, SRE for operational readiness); autonomy in operations, not in accountability. (Phase P0) - **REQ-186** — CIAgent reads `NORTH_STAR.md` in context-loading for all future milestones; the file is referenced from PROJECT.md and ARCHITECTURE.md so the strategic direction survives across milestones. (Phase P4) **Pillar B — Leadership Metrics + PowerBI** - **REQ-187** — Event emitters: a CloudEvents 1.0 envelope is adopted; a per-run manifest writer emits structured events (run_id, contractId, env, stages×durations, exit, confidence, HITL block count) to `metrics/runs/`; existing ephemeral `$WORK/*.json` (pcr, signal, event, outbox, stack) are persisted as durable artifacts; pytest `addopts` gains `--junitxml`+`--json-report`; Infracost runs as a plan post-processor emitting `cost.estimated{delta_usd}` (offline). (Phase P1) - **REQ-188** — Decision Ledger: `outbox_writer.py` is extended to emit to a SQLite append-only table with hash chain; `ai.decision.made` events are modeled from Nova's real decision points (decision_id=run_id, chosen_action=band outcome, confidence=score, alternatives=perInput breakdown, human_override=HITL block) with outcome backfill from apply.completed; `attestation.recorded` events capture qa/prod/dr sign-offs (approver, env, concerns, result). Honors D-083 (no S3 Object Lock/JWS). (Phase P1) - **REQ-189** — Metrics collector: `core/metrics/collector.py` + `schemas/metrics_*.schema.json` read all grounded signals (REGRESSION_REPORT.json, per-run manifests, junit XML, pcr.json, signal.json, COST.md, decision ledger) → normalized SQLite cold store at `metrics/nova_metrics.db`; idempotent re-runs. (Phase P2) - **REQ-190** — PowerBI export: `core/metrics/powerbi_export.py` emits CSV/JSON views to `metrics/powerbi/` (fact_run, fact_capability, fact_policy_check, fact_confidence, fact_test, fact_decision, fact_cost_estimate, dim_capability, dim_milestone + 8 empty placeholder views for deferred metrics with documented schemas) + `docs/METRICS_VIEWS.md` schema doc. (Phase P3) - **REQ-191** — Zero-touch efficiency metrics: Autonomous Resolution Rate (runs without operational HITL block ÷ total; attestation gates excluded), Human Escalation Frequency (operational HITL blocks only), AI Decision Accuracy (decisions not followed by apply.failed/incident within 5min), MTTD/MTTR (platform-run: apply.failed → successful retry). (Attestation Coverage is owned by REQ-194, not here.) (Phase P4) - **REQ-192** — Velocity metrics: Provisioning Lead Time (apply.completed.time − intent.received.time), Deployment Frequency (count(apply.completed) per day). Self-Healing Velocity deferred (no auto-remediator). (Phase P4) - **REQ-193** — Financial & cost-ROI metrics: FTE Hours Saved (derived: run count × manual baseline), Cost Savings via Infracost estimates (grounded), Cost Efficiency Ratio (derived), Platform ROI (derived formula). Live CUR reconciliation deferred (D-096). (Phase P4) - **REQ-194** — Reliability, security & compliance metrics: Zero-Trust Policy Compliance Rate (from pcr.json), Attestation Coverage (prod/dr promotions attested by a human ÷ total prod/dr promotions; grounded in hitl_gates.py + outbox approver_* attributes; canonical owner of this metric). Uptime, Patch Remediation, SLA/downtime deferred (D-096). (Phase P4) - **REQ-195** — Metrics catalog doc: `docs/METRICS.md` catalogs every executive KPI with `grounded`/`derived`/`deferred` status, source file or decision ID, and a per-KPI definition-of-success doc in `docs/metrics/.md`. (Phase P4) **Pillar C — Unified Narrative Deck** - **REQ-196** — The two existing decks (`how-the-platform-works` + `the-developer-experience`) are merged into one unified narrative deck "Nova — The No-Humans Infrastructure Platform" with a single arc: Problem → Vision/Direction (NORTH_STAR) → How it works → Proof (metrics) → Roadmap/Ask. The x3 structure ("tell them what you're going to tell them → tell them → tell them what you told them") applies at deck level (opening = arc; body = tell them; closing = recap + ask). Both old decks are retired (all derived artifacts deleted). (Phase P5) - **REQ-197** — Each slide has the x3 structure (opens with what it covers, delivers, closes with an explicit "benefit of this stage" callout) + fluid transitions between slides (no disjointed jumps). The 4-step deck process (source `.md` → Marp → HTML → talking-points) is re-run for the unified deck. (Phase P5) **Cross-cutting** - **REQ-198** — Regression capability: CAP-023 (metrics collector runs, emits expected schema) + CAP-024 (deck structure: slide count, x3 present, per-slide benefit present) added to `core/regression_verify.py`. (Phase P6) **Ideation enhancements (REQ-199..213 — additive, within D-120..D-132)** - **REQ-199** — Metrics schema validation in CI: `run_ci.sh` validates `metrics/powerbi/*.json` + a sample `metrics/events.jsonl` against their schemas; exits 0. (Phase P3) - **REQ-200** — Idempotent collector re-run test: `test_metrics_collector_idempotent` passes (two runs → identical row counts + chain verified). (Phase P2) - **REQ-201** — Metrics store backup/restore doc: `metrics/README.md` documents regenerable vs append-only artifacts + restore procedure. (Phase P2) - **REQ-202** — Metrics glossary appendix slide: the unified deck has a "Metrics Glossary" appendix slide with one-line KPI definitions + grounding badges. (Phase P5) - **REQ-203** — "What's Deferred — and Why" slide: the unified deck has a slide pairing each of 8 deferred metrics with its blocking decision ID. (Phase P5) - **REQ-204** — NORTH_STAR diff-check in CI: `run_ci.sh` includes `check_north_star_diff` that fails when Vision/Objectives/Anti-Goals/ Targets sections change without a `NORTH_STAR-CHANGE:` commit trailer. (Phase P4) - **REQ-205** — Per-module lifecycle success-rate report: each lifecycle run writes `metrics/lifecycle/-.json`; collector projects into `fact_lifecycle`; PowerBI "Module Lifecycle Health" view. (Phase P1 emitter + P2 collector + P3 view) - **REQ-206** — Code coverage trend emission: `pyproject.toml` addopts gains `--cov=core --cov=adapters --cov-report=json:metrics/coverage.json`; collector ingests; `fact_test` carries a coverage column. (Phase P1 + P2) - **REQ-207** — Decision Ledger CLI: `core/metrics/decision_ledger_cli.py` supports `query`, `verify-chain`, `stats`, `export`, `replay`; `verify-chain` detects broken hashes; `replay` prints ordered events; tests pass offline. (Phase P2) - **REQ-208** — PowerBI starter dashboard README: `metrics/powerbi/NOVA_DASHBOARD_README.md` documents folder-connector import + starter visual model + reference screenshot. (Phase P3) - **REQ-209** — PowerBI column-level data dictionary: `docs/METRICS_VIEWS.md` has a per-column data-dictionary table (column, type, source/formula, unit, grounded/derived/deferred status). (Phase P3/P4) - **REQ-210** — Deferred-metrics activation roadmap: `docs/METRICS_DEFERRED_ROADMAP.md` lists 8 deferred metrics + onboarding-grant half with {blocking decision, unblock requirement, candidate milestone} + a "Hot-Path Activation (post-D-096)" section (Nova-native only, D-120) + "Re-evaluation Triggers" section. (Phase P4) - **REQ-211** — Trust-snapshot report: `core/metrics/trust_snapshot.py` emits `metrics/TRUST_SNAPSHOT.md` with 5 trust metrics (Decision Ledger Coverage, Attestation Coverage, Capability Health, AI Decision Accuracy, Confidence-Gate Halt Rate) + chain-integrity verdict + snapshot hash; runs offline. (Phase P4) - **REQ-212** — Confidence-Gate Halt Rate metric: `docs/METRICS.md` + trust snapshot include "Confidence-Gate Halt Rate" (signal.json band=halt ÷ total runs); PowerBI view includes it. (Phase P4) - **REQ-213** — "No-humans" thesis defensibility brief: `docs/NO_HUMANS_THESIS.md` defines the thesis, grounded proof metrics, deferred proof metrics, and explicit anti-claims (incl. D-122 honesty); the unified deck's Vision act cites it. (Phase P4/P5) ### v1.17 Traceability | Requirement | Phase | Status | |-------------|-------|--------| | REQ-185 | P0 | complete | | REQ-186 | P4 | complete | | REQ-187 | P1 | complete | | REQ-188 | P1 | complete | | REQ-189 | P2 | complete | | REQ-190 | P3 | complete | | REQ-191 | P4 | complete | | REQ-192 | P4 | complete | | REQ-193 | P4 | complete | | REQ-194 | P4 | complete | | REQ-195 | P4 | complete | | REQ-196 | P5 | complete | | REQ-197 | P5 | complete | | REQ-198 | P6 | complete | | REQ-199 | P3 | complete | | REQ-200 | P2 | complete | | REQ-201 | P2 | complete | | REQ-202 | P5 | complete | | REQ-203 | P5 | complete | | REQ-204 | P4 | complete | | REQ-205 | P1+P2+P3 | complete | | REQ-206 | P1+P2 | complete | | REQ-207 | P2 | complete | | REQ-208 | P3 | complete | | REQ-209 | P3/P4 | complete | | REQ-210 | P4 | complete | | REQ-211 | P4 | complete | | REQ-212 | P4 | complete | | REQ-213 | P4/P5 | complete | ### Out of Scope (v1.17) - Live AWS re-provisioning (D-096) — metrics requiring live infrastructure ship as placeholder views. - Onboarding auto-grant (D-113/D-114/D-119) — only the request-path metric is grounded. - ML anomaly-forecasting / predictive remediation — no emitter today; Predictive-vs-Reactive metric ships as a placeholder. - Drift detection scheduled job (D-096 + no scheduler) — drift metrics ship as placeholders. - Live cost CUR reconciliation (D-096) — Infracost pre-apply estimates are grounded; actuals are not. - S3 Object Lock / JWS tamper-evident ledger (D-083) — Decision Ledger uses a local SQLite hash-chain this milestone. - Multi-cloud support (Azure/GCP/K8s) — Nova is AWS-only this milestone. - A third deck — the two existing decks merge into one; no new standalone metrics deck. - A Nova web UI — dashboards are PowerBI, not a Nova-built frontend. --- ## v1.18 — Citizen Developer & Production-Grade Guidance > **Milestone type:** Feature. Tags run on the v1.17.x patch line (previous > minor per branch-strategy). `v1.17.0` (P0) → `v1.17.1..v1.17.6` (P1–P6) → > `v1.17.7` (P7 final = milestone release). > **Active milestone:** v1.18. **Branch:** > `milestone/v1.18-citizen-developer-guidance`. ### Requirements - **REQ-214** — S&P Global Energy Marp theme restored in the unified deck (`docs/presentations/nova-no-humans-platform-marp.md`). The `style:` block from commit `ae0cb58` (v1.9.2 / P45) is ported: H1/H2 `#D6002A` (S&P red-core), title-slide bg `#1B1B1B` (grey-90) with 8px `#D6002A` top accent bar, body text `#1B1B1B`, blockquote border `#D6002A`, table headers `#F0F0F0`, font `'Akkurat Pro'` with web-safe fallbacks. The current Nova header/footer text is preserved (rebrand is not touched — only the visual theme is restored). HTML re-rendered with the S&P theme. - **REQ-215** — RACI matrix authored in `PROJECT.md` (new `## RACI Matrix` section) and `docs/raci.md` (citizen-developer-facing copy). Three roles: **Citizen Developer** (Responsible for all Functional Requirements + User Acceptance Testing — via their AI coding agent / upstream agentic SDLC / upstream development platform; the source does not matter as all are subject to the same compliance standards), **Platform** (Responsible for all NFRs + Infrastructure + QA + Production deployments to cloud), **Release Management** (co-owned: QA + SRE attestations required by the actual release, performed agentically but overseen & triggered by the Citizen Developer). Rendered as a table: rows = work categories (FRs, UAT, NFRs, Infra, QA, Prod deploy, Release attestation), columns = R/A/C/I per role. Includes the compliance-standard-equivalence note. - **REQ-216** — PDLC-upstream scope statement made explicit in `PROJECT.md` (new `## Scope: Nova is Downstream of PDLC` subsection under Domain Boundaries) and `docs/scope.md`. States that the PDLC (Product Development Lifecycle — product backlog, code authorship, IDE) is upstream of Nova; Nova governs infra + delivery only; integration is through the validated contract boundary. Promotes Core Tenet #2 + Anti-Goal #1 from buried tenets to a dedicated, unmissable scope statement. - **REQ-217** — `schemas/submission-readiness.schema.json` (JSON Schema draft 2020-12) defines what is acceptable to start — a superset gate *above* `contract.schema.json` validity. Required fields: `contractId` (non-empty), `environment` (dev/qa/prod/dr) with the W3.E per-env mandatory table enforced (dev: stack+environment; qa: +validation.e2eSuite +validation.loadTest; prod: +runbook+dashboard+oncall; dr: +drDrillRef), `tags` (the 5 required Nova tags per D-054: `nova:owner`, `nova:contract`, `nova:environment`, `nova:cost-center`, `nova:ref`), `policyPreconditions` (declared policy expectations the platform will enforce, e.g., `public-ingress: false`), `profile` (`developer` or `agentic`; if `agentic`, requires `naturalLanguageIntent`, `confidenceAtSubmission`, `agentTrace` per REQ-22 / W3.E), `appSource` (repo + ref pointer for runtime fetch). - **REQ-218** — `core/submission_readiness.py` validator, invoked as `contract_ingestor.py --check-readiness` subcommand (decision D-133). Returns a structured `ReadinessResult` (pass/fail per check, with reason codes). On fail → the ingestor rejects with a citizen-developer-facing error (not a stack trace). On pass → proceeds to existing contract ingestion. Calls `contract.schema.json` validation first, then the readiness checks. Reason codes: `MISSING_TAGS`, `ENV_MISSING_MANDATORY::`, `AGENTIC_MISSING_INTENT`, `MISSING_APP_SOURCE`, `POLICY_PRECONDITION_MISSING`. - **REQ-219** — `docs/submission-readiness.md` citizen-developer-facing doc explaining what is acceptable to start, with good + rejected examples and the reason-code catalog. References `schemas/submission-readiness.schema.json` as the source of truth. - **REQ-220** — `tests/test_submission_readiness.py` covers: good contract passes; missing tags fail with `MISSING_TAGS`; missing env mandatory fails with `ENV_MISSING_MANDATORY::`; agentic profile missing intent fails with `AGENTIC_MISSING_INTENT`; missing appSource fails with `MISSING_APP_SOURCE`. - **REQ-221** — `skills/` directory with 9 Atelier-derived skill files mapped to the BA.A citizen-developer catalog: `skills/api.md` (domains/api/), `skills/security.md` (domains/security/), `skills/data.md` (domains/data/), `skills/testing.md` (domains/testing/), `skills/observability.md` (domains/observability/), `skills/errors.md` (domains/errors/), `skills/devops.md` (domains/devops/), `skills/infrastructure-as-code.md` (domains/infrastructure-as-code/), `skills/compliance.md` (domains/compliance/). Each names the Atelier source path, distills the first-principles to the citizen-developer-relevant subset, links to agent-checklist triggers, and maps to the BA.A 5-skill catalog (web API, worker, scheduled job, static asset, basic observability bootstrap). - **REQ-222** — `docs/skills.md` index page listing the skill catalog, the Atelier provenance, and how the citizen developer's AI agent consumes them (read before completing a task; run `review/agent-checklist.md` before finishing). `PROJECT.md` BA.A decision extended with the Atelier-derived skill catalog reference. - **REQ-223** — `mcp/atelier/server.py` MCP server (stdio transport, decision D-135) with a **plugin-registry architecture** (decision D-140): `plugins/.py` modules each expose `register(mcp: MCPServer) -> None` and call `@mcp.tool()` for their tools; `server.py` scans `plugins/` and calls `register` on each. Initial plugins: `principles.py` (`atelier.lookup_principle`, `atelier.list_domains`, `atelier.matrix_lookup`) and `validation.py` (`atelier.validate_against_principles` — agentic validation against the Atelier agent-checklist, beyond Wiz/Checkmarx/Mend). Uses the MCP Python SDK v2 (`modelcontextprotocol/python-sdk`). - **REQ-224** — `mcp/atelier/vendor/` vendored Atelier snapshot (pinned tag, decision D-136) for audit reproducibility. `mcp/atelier/vendor/VERSION.md` records the pinned tag + a `scripts/update_atelier_vendor.sh` helper for intentional upgrades. `mcp/atelier/README.md` documents the server: how to run, transport, tool catalog, plugin-authoring guide, vendoring policy. - **REQ-225** — `tests/test_atelier_mcp.py` covers: tool registration (all 4 tools discoverable via `tools/list`), `atelier.lookup_principle` returns the principle text + core C-rule, `atelier.validate_against_principles` catches a planted C1 (correctness) + C7 (observability) violation in a known-bad snippet and passes a known-good snippet, `atelier.matrix_lookup` returns the domain→core mapping, plugin discovery loads all plugins in `plugins/`. - **REQ-226** — 3 new deck slides added to the unified deck (`docs/presentations/nova-no-humans-platform-marp.md`) → 21 slides total: Slide 19 "Scope: Downstream of PDLC", Slide 20 "RACI: Who Owns What", Slide 21 "Production-Grade Guidance via Atelier". Arc Preview slide updated to reflect 21-slide count. Talking points (`nova-no-humans-platform-talking-points.md`) synced for the 3 new slides. S&P theme preserved (regression check vs P1). CAP-024 deck structure regression passes. - **REQ-227** — `docs/presentations/README.md` slide count + deck table updated to reflect 21 slides + the 3 new slide titles. - **REQ-228** — `scripts/render_deck.sh` (renders HTML + PPTX from a Marp deck, commits both to git) and `scripts/attach_release_asset.py` (uploads a file to a Gitea release via the API). Any phase modifying `docs/presentations/*-marp.md` or `docs/presentations/assets/` MUST re-render HTML + PPTX, commit the PPTX binary to `docs/presentations/`, and attach it to the phase's Gitea release. PPTX is stored as a committed binary (no LFS, decision D-141). ### Out of Scope (v1.18) - **Streamable HTTP transport for the MCP server** — stdio ships now; HTTP is a future milestone (the SDK supports it on the same server object, so adding it later is a transport-only change, not a rewrite). - **A Nova-built frontend / dashboard** — observability stays PowerBI / external; no Nova web UI. - **Replacing the existing BA.A 5-skill catalog** — the Atelier-derived skills extend it, not replace it. - **Live AWS re-provisioning** (D-096, still deferred) — submission-readiness validates the contract shape, not a live AWS deployment. - **A second forge adapter** (GitLab) — BA.F cross-platform evolution is future work. - **Atelier live-fetch mode** — vendoring is the only mode this milestone; live-fetch (with its reproducibility trade-offs) is not implemented. ### v1.18 Traceability | REQ | Phase | Status | |-----|-------|--------| | REQ-214 | P1 | complete | | REQ-215 | P2 | complete | | REQ-216 | P2 | complete | | REQ-217 | P3 | complete | | REQ-218 | P3 | complete | | REQ-219 | P3 | complete | | REQ-220 | P3 | complete | | REQ-221 | P4 | complete | | REQ-222 | P4 | complete | | REQ-223 | P5 | complete | | REQ-224 | P5 | complete | | REQ-225 | P5 | complete | | REQ-226 | P6 | complete | | REQ-227 | P6 | complete | | REQ-228 | P1/P2/P6 | complete | ## v1.19 — Nova 2nd-Release Sync (GitLab consumer mirror) > **NFR-only chore milestone.** A single execution phase shipping a patch on > the v1.18.x line (tag `v1.18.0`). Establishes the manual-only "2nd release" > pipeline from `~/acdl` (CIAgent-managed source of truth) into `~/nova` > (GitLab `jonathanchery/nova` — a separate repo, separate history, consumer / > platform-team audience). `~/acdl` retains the full CIAgent audit trail; > `~/nova` receives only the consumer subset, committed with real > conventional commits per domain (no kitchen-sink "sync from source mirror"). - **REQ-229** — `scripts/sync_to_nova.sh` replaces `scripts/sync_to_gl.sh`. The script: (1) refuses to run without `--release` / `RELEASE_CONFIRMED=1` (manual-only — never triggerable by CI); (2) rsyncs the consumer subset of `~/acdl` into `~/nova`, excluding `.ciagent/`, `.gitea/`, `.env*`, `terraform/`, `demo/`, runtime metrics artifacts, and internal-only scripts (full list in `EXCLUDE_SCRIPTS`), while protecting `~/nova/.git` history via rsync `--filter=P .git`; (3) commits changes domain-by-domain in a fixed order (config → core → adapters → modules → contracts → schemas → pipelines → mcp → skills → scripts → tests → docs → workflows) using one conventional-commit message per changed domain passed via repeated `-m` flags (positional mapping over changed domains only — no kitchen-sink commit); (4) validates conventional-commit format (`feat|fix|docs|chore|…`) unless `--no-verify-format`; (5) pushes to the branch upstream unless `--no-push`. `--list-domains`, `--dry-run`, `-v` supported. The old `sync_to_gl.sh` is removed. (Phase P1) ### Out of Scope (v1.19) - **coreci / Atelier review gate on the synced tree** — deferred; the sync ships consumer contents as-is. A future milestone may run a vendored-Atelier review pass before commit and block on P0 findings. - **Tagging releases on the `~/nova` side** — could add `--tag ` later. - **Deleting `~/gl`** — the old GitLab `acdl` mirror is left on disk; only the sync script targeting it is removed. ### v1.19 Traceability | REQ | Phase | Status | |-----|-------|--------| | REQ-229 | P1 | complete | ## v1.20 — Consumer Cleanup + Transparent Terraform + Slide Pipeline > **Multi-concern milestone.** Four user-directed inputs spanning consumer > cleanup, infrastructure transparency, and presentation automation. Tags > run on the v1.19.x line (milestone v1.20 → tags v1.19.0, v1.19.1, …). > > **Input 1 — Gitea/GitLab removal:** Remove all mentions of `gitea` / `gitlab` > (case-insensitive) from every file synced to `~/nova`. The platform team > (consumer of `~/nova`) must never know about the dev forge or the GitLab > mirror. Genericize forge-detection code to `forge` / `generic_forge`. > > **Input 2 — Documentation simplification:** Radically simplify all synced > documentation. Anything the CIAgent needs to reference for itself lives in > `.ciagent/`. Everything else is tailored to the Platform Team audience. > Strip ciagent-internal provenance (REQ-/D-/P-/CAP- IDs, milestone headers, > `.ciagent/PROJECT.md` citations) from synced docs. Delete completed > migration guides. Move internal artifacts to `.ciagent/`. > > **Input 3 — Transparent terraform:** Move terraform `init` / `validate` / > `plan` / `apply` / `output` into native workflow steps (transparent, visible > in CI logs). Split `run_platform.sh` into `run_codegen.sh` (pre-TF) + > `run_postapply.sh` (post-TF). Add `var.enabled` feature flags to every L1 > module + L2 composition toggles. Wire forge repo variables as per-client > feature flags — different clients test different functionality without > version upgrades. > > **Input 4 — Slide pipeline + product roadmap:** The slides have not adopted > the S&P Global theme fully. Create a dedicated render pipeline that builds > the slides (mermaid PNGs + Marp HTML/PPTX) with the S&P theme applied to all > slide chrome. Add a 12-month product roadmap (high-level, product-oriented > vs the technical roadmap in `.ciagent/ROADMAP.md`) to the deck. - **REQ-230** — No `gitea` / `gitlab` string literal (case-insensitive) appears in any file synced to `~/nova`. Verified by `tests/test_no_forge_mentions.py` which scans the synced subset (same path rules as `sync_to_nova.sh`'s `DOMAINS` / `EXCLUDES`). Forge-detection code (`contract_ingestor.py`, `hitl_gates.py`, `run_platform.sh`) is genericized: `gitea` → `forge` / `generic_forge`, `GITEA_ACTOR` → `FORGE_ACTOR` (with `GITHUB_ACTOR` primary). (Phase P1) - **REQ-231** — Synced documentation is tailored to the Platform Team audience. Ciagent-internal provenance (`v1.XX — Strategic Direction` headers, `REQ-NNN` / `D-NNN` / `P-NNN` / `CAP-NNN` IDs, `.ciagent/PROJECT.md` "source of truth" citations) is stripped from synced docs. (Phase P1) - **REQ-232** — Completed/historical migration docs (`docs/NOVA_MIGRATION.md`, `docs/NOVA_AWS_MIGRATION.md`) removed from the synced tree. `docs/NO_HUMANS_THESIS.md` moved to `.ciagent/` (internal thesis-defense artifact). (Phase P1) - **REQ-233** — Terraform `init` / `validate` / `plan` / `apply` / `output` run as native workflow steps in `deploy.yml` (transparent, named steps visible in CI logs), not buried inside `run_platform.sh`. (Phase P4) - **REQ-234** — `run_platform.sh` is split: `run_codegen.sh` (pre-TF: env check, validate, resolve, adapt) + `run_postapply.sh` (post-TF: Checkov, confidence, HITL, outbox, SSM, comment, uptime). A thin `run_platform.sh` shim preserves backward compat for local-dev usage. (Phase P4) - **REQ-235** — Every L1 module has `variable "enabled" { type = bool, default = true }` + `count = var.enabled ? 1 : 0` on its primary resource(s); declared in `interface.json`. The `uptime` module's `feature_flag_enabled` is renamed to `enabled` (with backward-compat alias). (Phase P4) - **REQ-236** — L2 `composition.json` supports per-child `enabled` toggles driven by contract `inputs.enable_`. The resolver skips children with `enabled: false`. (Phase P4) - **REQ-237** — `deploy.yml` reads feature flags from forge repository variables (`vars.ENABLE_*`) and passes them as `-var` flags to terraform, enabling per-client feature toggles without version upgrades. (Phase P4) - **REQ-238** — Stale artifact path `/tmp/acdl_platform_run_v18` in `deploy.yml` fixed to use `NOVA_WORK_DIR`. (Phase P4) - **REQ-239** — A dedicated S&P Global theme CSS file (`docs/presentations/assets/nova-sp-theme.css`) is the Marp theme for all Nova presentation decks. The theme applies the S&P Red/Black/White palette (`#D6002A`, `#1B1B1B`, `#FFFFFF`) to all slide chrome (background, header/footer, pagination, tables, blockquotes), not just headings. (Phase P2) - **REQ-240** — A dedicated render pipeline (`scripts/render_slides.sh`) builds the presentation deck end-to-end: (1) renders all `assets/mmd/*.mmd` → `assets/png/*.png` via `mermaid-cli --configFile sp-theme.json`; (2) renders the Marp deck → HTML + PPTX via `marp-cli`; (3) stages all rendered artifacts to git. Supersedes `render_deck.sh`. (Phase P2) - **REQ-241** — A CI workflow (`workflows-src/slides.yml` + `.github/workflows/slides.yml`) runs `render_slides.sh` on any change to `docs/presentations/**` and commits the rendered HTML/PPTX/PNGs back. No manual re-render step; no artifact drift. (Phase P2) - **REQ-242** — `tests/test_slides_pipeline.py` validates: (1) the Marp deck frontmatter references `nova-sp-theme.css`; (2) the CSS contains the S&P colors; (3) every `.mmd` has a corresponding `.png`; (4) the HTML exists and is newer than the Marp `.md`. (Phase P2) - **REQ-243** — `docs/presentations/README.md` directory layout is updated to remove retired decks (`how-the-platform-works-*`, `the-developer-experience-*`) and document the render pipeline + theme CSS. (Phase P2) - **REQ-244** — A 12-month product roadmap (4 quarters, product-outcome oriented, grounded in NORTH_STAR strategic objectives + deferred-metric candidate milestones) is added to the presentation deck as Slide 20 + Slide 21. The roadmap is distinct from Slide 15's deferred-metric unblock paths. A matching talking-points section is added. (Phase P3) ### Out of Scope (v1.20) - **Multi-cloud (Azure/GCP) implementation** — deferred; only the product roadmap references it as a Q4 aspiration. - **ML anomaly-forecasting service** — deferred; only the product roadmap references it as a Q4 aspiration. - **Actual pilot estate activation** — deferred (requires live AWS re-provisioning, D-096 lift); the product roadmap references it as Q1. - **Token rotation for `NOVA_GITEA_TOKEN`** — out of scope; the `.env` files are correctly excluded from sync. Flagged for awareness only. ### v1.20 Traceability | REQ | Phase | Status | |-----|-------|--------| | REQ-230 | P1 | complete | | REQ-231 | P1 | complete | | REQ-232 | P1 | complete | | REQ-233 | P4 | complete | | REQ-234 | P4 | complete | | REQ-235 | P4 | complete | | REQ-236 | P4 | complete | | REQ-237 | P4 | complete | | REQ-238 | P4 | complete | | REQ-239 | P2 | complete | | REQ-240 | P2 | complete | | REQ-241 | P2 | complete | | REQ-242 | P2 | complete | | REQ-243 | P2 | complete | | REQ-244 | P3 | complete | ## v1.21 — Nova Deck Refinement & Pipeline Hardening > Leadership-deck refinement based on 33 review notes on the v1.20 deck > (v1.20 shipped as `nova-no-humans-platform*`). This milestone renames the > deck to the professional "Autonomous Cloud Delivery Platform" framing, > restructures the narrative (Problem → Solution → Proof → Roadmap + Ask), > removes internal provenance from audience-facing slides, hardens the > policy pipeline (Checkov before plan, Wiz-or-Checkov on plan), and moves > the strategic integration objective into the North Star. > > Tags run on the v1.20.x line (milestone v1.21 → tags v1.20.0, v1.20.1, …). ### REQ-245 — Deck rename + restructure The deck files are renamed from `nova-no-humans-platform*` to `nova-autonomous-cloud-delivery*` across all five artifacts (source `.md`, `-marp.md`, `.html`, `.pptx`, `-talking-points.md`). The in-deck title becomes "Nova — The Autonomous Cloud Delivery Platform" (professional, conveys autonomy without the provocative "no-humans" wording). The narrative restructures to 18 main + 1 appendix slides: 1. The Problem (merged old 1+2; broader problem framing; no "arc"; no "18 capabilities verified"; not "humans are the problem"; add tribal knowledge / rockstar-operator framing) 2. Nova's Vision 3. Strategic Objectives + Anti-Goals 4. Scope: Downstream of PDLC (moved up) 5. RACI: Who Owns What (moved up) 6. The Platform Pipeline 7. The Decision Ledger 8. The Attestation Matrix 9. Telemetry & Live Ops 10. Decision Ledger + Attestation Coverage 11. Cost & ROI 12. What's Deferred — and Why 13. Roadmap to the North Star 14. 12-Month Product Roadmap 15. Quarter-by-Quarter Outcomes 16. Production-Grade Guidance via Atelier (1/2) 17. Production-Grade Guidance via Atelier (2/2) 18. Recap + Ask A1. Metrics Glossary Removed: old Slide 10 (Capability Health), old Slide 12 (Zero-Touch Efficiency), old Appendix A2 (Operating Model & Cost). Slide 5's first table removed. ### REQ-246 — Thesis rename + reframe `.ciagent/NO_HUMANS_THESIS.md` is renamed (git mv) to `.ciagent/AUTONOMY_THESIS.md`. Content reframes from "removing humans" to "autonomy in operations, human at stage gates" — professional, not provocative. The operator-bottleneck framing is softened; the attestation model + provable trust are emphasized. Anti-claims are retained and reworded for a tech-leadership audience. All references across the repo are updated to the new filename + framing. ### REQ-247 — Strategic-docs sync (NORTH_STAR + PROJECT) `NORTH_STAR.md` is updated: - Vision polished for a technical audience concerned about security, security remediation velocity, and reliability; "infrastructure operations become visible" is preserved as a recurring theme. - Strategic Objective #2 (provable trust) is reworded: trust is established by deterministic scripts that calculate a score, not by AI. The platform functions without AI. "AI decisions" are really automated decisions. - Strategic Objective #3 (ROI) is reworded with four CTO-grade metrics: Lead Time (PR → Production), Infrastructure Vulnerability Count (downward trend), MTTR, Cloud Spend Reduction. All flow into PowerBI views and are captured by the telemetry pipeline. - Strategic Objective #4 is replaced: integrate with externally owned PDLC, SDLC, Agentic, and Citizen Developer platforms regardless of source; Nova provides skills + MCP endpoints to make applications production-grade; all intents to deploy to production go through the same rigorous controls and quality gates. - Anti-goals #1 (hyperscaler competitor), #4 (legacy untagged), and #5 (sold to operators) are removed. Two new anti-goals added: not an upstream development platform; not a replacement for the Product Lifecycle (PDLC). - Anti-goal #3 reworded to remove the "removes humans" framing. `PROJECT.md` mission statement + scope are synchronized with the integration objective and the reworded strategic objectives. ### REQ-248 — RACI restructure (Quality Engineering + SRE) The RACI matrix (slide + `docs/raci.md`) is restructured: - A **Quality Engineering** column is added. - The Platform column no longer holds the **A** for release attestation; accountability is reassigned to QA or SRE as appropriate. - "Release Management" is renamed to **SRE**. - "Release attestation" is split into two rows: the SRE part is **Production Readiness** (operational readiness sign-off). - The slide is sized to fit (text shrunk / low-impact rows dropped). ### REQ-249 — Atelier split (2 slides) Slide 19 (Production-Grade Guidance via Atelier) is split into two slides: - **16 (1/2):** Skills + MCP server overview (the 9 skills, the 4 MCP tools, the plugin-registry + stdio surface). - **17 (2/2):** Agentic validation beyond deterministic scanners + vendored Atelier for audit reproducibility. The benefit wording is improved; the same spirit is retained. ### REQ-250 — Pipeline hardening (Checkov before plan; Wiz-or-Checkov on plan) `scripts/run_platform.sh` (and `scripts/run_postapply.sh` where relevant) implement the two-stage policy scan: 1. **Checkov runs on static code** (the generated `main.tf` / TF directory) **before** `terraform plan` — fail-fast, quick developer feedback on policy violations in the authored code. 2. **After `terraform plan`:** if `WIZ_API_TOKEN` + `WIZ_API_URL` are set, run **Wiz against the plan**; otherwise run **Checkov against the plan** as a drop-in replacement. **Wiz and Checkov are never both run on the plan.** `adapters/wiz/wiz_adapter.py` is updated if needed for plan-mode input. Slide 6 + `docs/scope.md` reflect the new flow. Tests (`tests/test_pipeline.py`, `tests/test_pipeline_contract.py`, and any checkov/wiz tests) are updated and pass. ### REQ-251 — Theme CSS fix (Appendix A1) + footer cleanup `docs/presentations/assets/nova-sp-theme.css` is fixed so the Appendix A1 Metrics Glossary table is readable (the table background color is corrected). The Marp footer no longer shows the version (`v1.20`) or the `Act %{page}/5` artifact. The title-slide subtitle no longer shows `v1.18 — Citizen Developer & Production-Grade Guidance`; it becomes "Product Development & Citizen Developer Overview" (or similar) to convey the audience for the platform. ### REQ-252 — Global citation + badge + version removal Across all audience-facing slides (the Marp deck, the source-of-truth markdown, and the talking points): - All internal citations are removed: `D-###` decision IDs, `REQ-###` requirement IDs, and internal file paths (e.g. `outbox_writer.py`, `confidence_signal.py`). - All `Planned` badges are removed. - The version is removed from the footer and the title slide. Every benefit callout is rewritten for a tech-leadership audience (security, remediation velocity, reliability, lead time). A "less is more / no fluff" final prose pass is applied; the story stays clear. ### REQ-253 — Render + verify + ship Changed/new mermaid diagrams are re-rendered (slide 1 new diagram, slide 9 expand, Atelier split). HTML + PPTX are re-rendered via `scripts/render_slides.sh`. `tests/test_slides_pipeline.py` passes: asserts 18 main + 1 appendix slides, no badge spans, no version in the footer, no `D-###`/`REQ-###`/`.py` paths in audience-facing slides, and filename refs updated in render scripts + CI workflow + README. `tests/test_no_forge_mentions.py` passes. Full `pytest` passes (pipeline-hardening tests green). `run_platform.sh --check-only` passes. Milestone ship: tag the final phase on the v1.20.x line; create a release; attach the PPTX. ### Out of Scope (v1.21) - **Live pilot estate activation** — still deferred (D-096). - **ML anomaly-forecasting service** — still deferred. - **Multi-cloud (Azure/GCP) implementation** — still deferred. - **Tamper-evident ledger (S3 Object Lock + JWS)** — still deferred (D-083); the deck describes it as a roadmap item without citing the decision ID in the audience-facing slides. ### v1.21 Traceability | REQ | Phase | Status | |-----|-------|--------| | REQ-245 | P2 | complete | | REQ-246 | P1 | complete | | REQ-247 | P1 | complete | | REQ-248 | P2 | complete | | REQ-249 | P2 | complete | | REQ-250 | P4 | complete | | REQ-251 | P3 | complete | | REQ-252 | P2 | complete | | REQ-253 | P5 | complete | ## v1.22 — Nova Deck Layout Fix > Fixes the systemic layout/formatting problems in the Nova presentation > deck that made every slide look "out of whack" after the v1.21 P5 > re-render. Root cause (per investigation): `nova-sp-theme.css` has zero > `section` padding (it declares `/* @theme nova-sp */` as a comment, not > the `@theme` directive, and does not `@import` Marp's default theme, so > Marp's default `section { padding: 56px 64px }` never applies). Combined > with `overflow:hidden` (silent clip), a blunt `img { max-height: 320px }` > rule, header+footer chrome on every slide, and two new P5 diagrams with > extreme aspect ratios (13.52× and 0.63×), 8 of 19 slides overflow and > the rest look jammed against the edges. This is NOT a P5 regression — > the theme CSS is byte-identical between P3 and P5; P5's denser content > made the pre-existing theme flaws visible. > > Comprehensive fix across four layers: theme CSS, render scripts, mermaid > diagrams, deck content. Adds the layout/aspect-ratio/theme-structural > tests that were missing (the gap that let this through). > > Tags run on the v1.21.x line (milestone v1.22 → tags v1.21.0, v1.21.1, …). ### REQ-254 — Theme CSS: section padding + overflow handling `docs/presentations/assets/nova-sp-theme.css` adds a `section` padding rule so content is not jammed against the slide edges. The padding reserves space for the header (top) and footer (bottom) chrome: e.g. `section { padding: 48px 56px 40px; }`. The theme also adds explicit overflow handling on `section` so dense content is not silently clipped by the marpit base `overflow:hidden` — either `overflow: auto` as an authoring-time signal, or a documented shrink-to-fit rule. The fix does NOT re-introduce Marp's default theme via `@import` (the theme remains standalone); it explicitly sets the padding the default would have provided. ### REQ-255 — Theme CSS: aspect-ratio-aware image rules The blunt `img { max-height: 320px }` rule is replaced with an aspect-ratio-aware rule that does not break the Marp `w:`/`h:` directives: `img { max-width: 100%; max-height: 380px; object-fit: contain; }`. A `.wide` / `.tall` class convention is added for diagrams (wide diagrams: `max-height: 280px`; tall diagrams: `max-height: 480px`) so authors can opt into the right bound per diagram instead of fighting a single blunt rule. The `w:900` directive on a tall image (slide 9) no longer gets silently overridden by `max-height`. ### REQ-256 — Theme CSS: title-slide chrome + spacing tightening - `section.title header, section.title footer { display: none; }` — the title slide and appendix slide no longer render header/footer chrome that collides with content (the `` + `` directives only suppress the page number, not the chrome). - `section h2 + p { margin-top: 0.2em; }` — tightens the spacing between the `## Slide N — Title` heading and the bold lead paragraph that follows it on every content slide (reclaims ~22px per slide). - `section p { margin: 0.4em 0; }` — reduces default `

` margins (~1em top/bottom) that waste vertical space on dense slides. - `ol` styling added (matches `ul`/`li`). - Table cell padding reduced to `4px 8px` for tables with ≥8 rows (via a `table.dense` class or a `:nth-child` heuristic) so 10-13 row tables (slides 8, 12, A1) fit. - `@media print` overrides added for PPTX export fidelity. ### REQ-257 — Render scripts: delete render_deck.sh + pin CLI versions `scripts/render_deck.sh` is **deleted** (it omits `--theme`, relying on the frontmatter `theme: nova-sp` which Marp cannot resolve as a custom theme without `--theme-set` — it falls back to the default theme, producing unthemed output). The README already documents `render_slides.sh` as the canonical script. Both `render_slides.sh` and the deleted `render_deck.sh` references are removed from any docs/tests. `render_slides.sh` pins marp-cli and mermaid-cli to specific versions (replace `@latest` with pinned versions) to prevent uncontrolled boilerplate-CSS drift like the P3→P5 HTML diff. ### REQ-258 — render_slides.sh: 2x scale + transparent bg for mermaid The mermaid-cli invocation in `scripts/render_slides.sh` (lines 51-55) adds `-s 2 -b transparent` to match the README spec (line 193). This produces crisp 2x PNGs with transparent backgrounds instead of the current 1x renders (e.g. `platform-pipeline.png` is only 1568px wide instead of the 3136px a 2x render would produce). ### REQ-259 — Re-layout telemetry-live-ops.mmd to LR `docs/presentations/assets/mmd/telemetry-live-ops.mmd` is rewritten from `flowchart TB` (top-bottom, produced a 1024×1628 PNG — aspect 0.63, tall) to `flowchart LR` (left-right) with subgraph row-wrapping per the README convention (line 168). The re-rendered PNG (at 2x transparent, per REQ-258) has an aspect ratio in [1.2, 2.5] suitable for a 16:9 slide. The Marp deck's `![w:900]` directive on slide 9 is updated to match the new dimensions (or replaced with `![h:320]` if the diagram remains taller than wide after re-layout). ### REQ-260 — Re-layout platform-pipeline.mmd to 2-row wrap `docs/presentations/assets/mmd/platform-pipeline.mmd` is rewritten to wrap the 10-node LR chain into 2 rows via mermaid subgraphs (or split into two stages: static-scan row + runtime-scan row). The current 1568×116 PNG (aspect 13.52, ultra-wide/short) renders as a 1000×74px thin strip at `![w:1000]` — node text is illegible. The re-rendered PNG (at 2x transparent) has an aspect ratio in [1.2, 2.5] suitable for a 16:9 slide. ### REQ-261 — Trim/split 8 overflowing slides + remove redundant header The 8 slides identified as overflowing 720px are trimmed or split: - **Slide 3** (Objectives + Anti-Goals): split into Slide 3a (4 objectives) + Slide 3b (4 anti-goals). Main slide count 18 → 19. - **Slide 5** (RACI): apply `table.dense` class (from REQ-256) to reduce cell padding; keep 8 rows. - **Slide 6** (Pipeline): reduce to 3 bullets (the 4th is covered by the diagram, now legible after REQ-260). - **Slide 8** (Attestation Matrix): split into Slide 8a (qa concerns, 3 rows) + Slide 8b (prod/dr concerns, 7 rows). Main slide count 19 → 20. - **Slide 9** (Telemetry): reduce to 3 bullets; image now legible after REQ-259. - **Slide 12** (Deferred): reduce to 6 rows (merge the 3 "Live AWS re-provisioning" blockers into one row). - **Slide 15** (Quarter-by-Quarter): drop the "Grounding" column (redundant with the strategic objectives); 4 columns fit better. - **Appendix A1** (Glossary): apply `table.dense` class (16px font); keep 13 rows. The Marp frontmatter `header:` line is removed (keep `footer:` + `paginate: true` only). The full 51-char deck title in BOTH header and footer on every slide is redundant chrome that eats vertical space; the footer alone suffices. The title slide and appendix already use `` which (after REQ-256) suppresses chrome. The talking-points file is re-distilled to match the new slide structure (20 main + 1 appendix). The README "18 main + 1 appendix" convention (line 130) and `test_marp_deck_slide_count` are updated to assert 20 main + 1 appendix. ### REQ-262 — Re-render HTML + PPTX + add layout/aspect-ratio tests - Run `bash scripts/render_slides.sh nova-autonomous-cloud-delivery` → re-render all mermaid PNGs (2x transparent) + HTML + PPTX. Verify slide count (20 main + 1 appendix = 21) and media embedding. - Add tests to `tests/test_slides_pipeline.py`: - `test_theme_css_has_section_padding` — assert `section` rule contains `padding`. - `test_theme_css_suppresses_title_chrome` — assert `section.title header` / `section.title footer` `display: none`. - `test_png_aspect_ratios_sane` — for every PNG in `assets/png/`, assert aspect ratio ∈ [1.2, 2.5] (catches the 13.52× and 0.63× outliers). - `test_render_slides_has_2x_scale` — assert `render_slides.sh` contains `-s 2` and `-b transparent`. - `test_render_deck_removed` — assert `render_deck.sh` does not exist. - `test_html_embeds_theme` — assert committed HTML contains `--sp-red` and `padding` in the inline `