a7a93d95d1
---ci--- project: acdl phase: 0 milestone: v1.24 status: specify ---/ci---
2199 lines
142 KiB
Markdown
2199 lines
142 KiB
Markdown
# 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 `<br/>`, 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/<name>/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/<name>/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.<field>}` and `${contract.<field>}` 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/<contract.environment>.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 <name>` 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: <id>, 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): <id> — <status>` and `fix(P54): <id> — <summary>`. 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 `<env>.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/<kpi>.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/<module>-<env>.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:<env>:<field>`,
|
||
`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:<env>:<field>`; 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/<name>.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 <semver>` 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_<child>`. 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 `<span class="badge planned">Planned</span>` 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 `<!-- _class: title -->` +
|
||
`<!-- _paginate: false -->` 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 `<p>` 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
|
||
`<!-- _class: title -->` 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 `<style>`.
|
||
- `test_html_slide_count_matches_marp` — parse HTML `<section>`
|
||
count == marp deck slide count.
|
||
- Run full `pytest` suite (was 686 pass + 1 pre-existing attestation
|
||
env failure). `run_platform.sh --check-only` exits 0.
|
||
- Milestone ship: tag the final phase on the v1.21.x line; create a
|
||
release; attach the PPTX.
|
||
|
||
### Out of Scope (v1.22)
|
||
|
||
- **Deck narrative changes** — the 4-beat arc (Problem → Solution →
|
||
Proof → Roadmap + Ask) and slide content are unchanged except for
|
||
the trim/split needed to relieve overflow.
|
||
- **Re-introduction of badges, version strings, or internal citations**
|
||
— v1.21 removed these; v1.22 does not re-add them.
|
||
- **Live pilot estate activation** — still deferred.
|
||
- **ML anomaly-forecasting service** — still deferred.
|
||
- **Multi-cloud (Azure/GCP) implementation** — still deferred.
|
||
- **Tamper-evident ledger (S3 Object Lock + JWS)** — still deferred.
|
||
|
||
### v1.22 Traceability
|
||
|
||
| REQ | Phase | Status |
|
||
|-----|-------|--------|
|
||
| REQ-254 | P1 | complete |
|
||
| REQ-255 | P1 | complete |
|
||
| REQ-256 | P1 | complete |
|
||
| REQ-257 | P2 | complete |
|
||
| REQ-258 | P2 | complete |
|
||
| REQ-259 | P3 | complete |
|
||
| REQ-260 | P3 | complete |
|
||
| REQ-261 | P4 | complete |
|
||
| REQ-262 | P5 | complete |
|
||
|
||
## v1.23 — Nova Deck Cleanup & Python PPTX
|
||
|
||
> **NFR milestone** (docs/render/test only; no features). Tags run on the
|
||
> **v1.22.x** line (milestone v1.23 → tags v1.22.0..v1.22.6). Final patch
|
||
> `v1.22.6` = milestone release.
|
||
>
|
||
> Consolidates the deck to a single source-of-truth markdown document,
|
||
> restores the clean S&P visual style (Marp `default` theme + inline
|
||
> `style:` block, matching the old `the-developer-experience.html`),
|
||
> embeds images as base64 in the HTML for redistribution, builds a
|
||
> parallel structured python-pptx PPTX generator, and trims verbose
|
||
> slides. `nova-sp-theme.css` is retained as a styling reference but
|
||
> retired from the render path.
|
||
|
||
### Category: Consolidate Docs
|
||
- **REQ-263:** `nova-autonomous-cloud-delivery-marp.md` becomes the sole
|
||
source of truth. Speaker notes + talking points from the plain `.md`
|
||
are folded into the deck as Marp HTML comments (`<!-- Speaker notes:
|
||
... -->`, `<!-- Talking points: ... -->`). The plain
|
||
`nova-autonomous-cloud-delivery.md` is deleted.
|
||
- **REQ-264:** `nova-autonomous-cloud-delivery-talking-points.md` is kept
|
||
as a standalone presenter aid, synced from the deck's `<!-- Talking
|
||
points: -->` comments. Header note documents the mirror relationship.
|
||
|
||
### Category: Restore Clean Style
|
||
- **REQ-265:** Revert deck frontmatter `theme: nova-sp` → `theme:
|
||
default` and add an inline `style:` block porting the S&P visual
|
||
language (palette #D6002A/#1B1B1B, Akkurat Pro font, black title slide
|
||
with red top border, tables, blockquotes, code, aspect-ratio-aware
|
||
images). Keep current structure (H2 + bold-lead, no header, no badges).
|
||
- **REQ-266:** `nova-sp-theme.css` is retained as a styling reference
|
||
(header comment documents its retired status). `render_slides.sh`
|
||
drops the `--theme "$THEME_CSS"` argument; the inline `style:` block in
|
||
frontmatter is the sole styling source at render time.
|
||
- **REQ-267:** Benefit callouts on every slide are restyled: the
|
||
`**Benefit:**` prefix is removed; the callout becomes a styled
|
||
element (red top-rule + black italic text; white on title slides)
|
||
using a `.benefit` class in the inline style block.
|
||
|
||
### Category: Inline Images
|
||
- **REQ-268:** New `scripts/inline_images.py` (stdlib only: `base64`,
|
||
`re`, `mimetypes`) post-processes the rendered HTML: finds all
|
||
`<img src="assets/...">` relative paths, replaces each `src` with a
|
||
`data:image/<mime>;base64,...` URI. HTML becomes self-contained
|
||
(redistributable without the `assets/` folder). `render_slides.sh`
|
||
invokes it after the MARP HTML render, before staging.
|
||
|
||
### Category: Python PPTX Generator
|
||
- **REQ-269:** New `scripts/render_pptx.py` parses the consolidated
|
||
`*-marp.md` and produces a structured, editable, S&P-themed PPTX
|
||
(`nova-autonomous-cloud-delivery-python.pptx`) using `python-pptx`.
|
||
16:9 slides; title slide (black bg, red top bar, white H1); content
|
||
slides (red H2 title, bold lead, bullets, blockquote, embedded PNGs,
|
||
native PPTX tables, benefit callouts). HTML-comment speaker
|
||
notes/talking points are skipped. `python-pptx` added to
|
||
`pyproject.toml`. `render_slides.sh` invokes it as a new step.
|
||
- **REQ-270:** Both PPTX outputs (MARP image-of-slide + python
|
||
structured) are produced by `render_slides.sh` and staged. CI
|
||
workflows install `python-pptx` and commit both. `attach_release_asset.py`
|
||
attaches both to the release.
|
||
|
||
### Category: Trim Word Count
|
||
- **REQ-271:** Targeted word-count trim on ~8 verbose slides (1, 5, 7,
|
||
8, 13, 14, 20, plus the appendix) — ~20-30% reduction on trimmed
|
||
slides. Tables and short slides are untouched. The spirit of each
|
||
slide is preserved.
|
||
- **REQ-272:** The term "penetrate" (and derivatives) is removed from
|
||
all presentation files. Slide 5's "Nova never penetrates it" phrase is
|
||
removed with no replacement (slide 4 Anti-Goals already excludes the
|
||
PDLC from scope). `grep -ri penetrat docs/presentations/` returns
|
||
nothing.
|
||
|
||
### Category: CI, Tests, README
|
||
- **REQ-273:** CI workflows (`workflows-src/slides.yml` + synced
|
||
`.github`/`.gitea` copies) install `python-pptx`, run `render_slides.sh`
|
||
(which produces HTML + both PPTX + inlined images), and commit all
|
||
rendered artifacts. README documents the new pipeline.
|
||
- **REQ-274:** `tests/test_slides_pipeline.py` is updated for the
|
||
consolidated doc (no plain `.md`), default theme + inline style
|
||
assertions (S&P visual properties, not theme filename),
|
||
`nova-sp-theme.css` retained-as-reference assertion, image-inlining
|
||
assertions (zero `src="assets/` references, ≥1 base64 per image),
|
||
python-pptx output existence, benefit callout class, "penetrate"
|
||
absence. New `tests/test_pptx_generator.py` asserts slide count, title
|
||
colors, table rendering, image embedding.
|
||
- **REQ-275:** `docs/presentations/README.md` is rewritten to document
|
||
the single-document process (author `*-marp.md` → render HTML + both
|
||
PPTX → talking points mirrored), inline `style:` approach,
|
||
`nova-sp-theme.css` reference status, image inlining, and dual PPTX
|
||
output.
|
||
|
||
### Out of Scope (v1.23)
|
||
|
||
- **Deck narrative / 4-beat arc changes** — the Problem → Solution →
|
||
Proof → Roadmap + Ask structure is unchanged; only word count is
|
||
trimmed.
|
||
- **Re-introduction of badges, version strings, or internal citations**
|
||
— v1.21 removed these; v1.23 does not re-add them.
|
||
- **Removal of MARP** — MARP stays for HTML + PPTX; python-pptx runs in
|
||
parallel for comparison.
|
||
- **Removal of orphaned `developer-experience-*` assets** — deferred to
|
||
a future cleanup phase (optional in v1.23 Phase 6 only if time
|
||
permits).
|
||
- **Mermaid render scoping** — the mermaid render step continues to
|
||
render all `.mmd` files; scoping to referenced-only is deferred.
|
||
|
||
### v1.23 Traceability
|
||
|
||
| REQ | Phase | Status |
|
||
|-----|-------|--------|
|
||
| REQ-263 | P1 | complete |
|
||
| REQ-264 | P1 | complete |
|
||
| REQ-265 | P2 | complete |
|
||
| REQ-266 | P2 | complete |
|
||
| REQ-267 | P2 | complete |
|
||
| REQ-268 | P3a | complete |
|
||
| REQ-269 | P3b | complete |
|
||
| REQ-270 | P3b | complete |
|
||
| REQ-271 | P4 | complete |
|
||
| REQ-272 | P4 | complete |
|
||
| REQ-273 | P5 | complete |
|
||
| REQ-274 | P5 | complete |
|
||
| REQ-275 | P5 | complete |
|
||
|
||
## v1.24 — Consumer Guide Accuracy & Env-Promotion Lifecycle Enforcement
|
||
|
||
> **Feature milestone** (one `feat` phase: env-transition destroy enforcement;
|
||
> the rest are `fix`/`docs`/`test`). Tags run on the **v1.23.x** line
|
||
> (milestone v1.24 → tags v1.23.0..v1.23.N). Final patch = milestone release.
|
||
>
|
||
> Two problems, one milestone:
|
||
> 1. **Consumer guide accuracy.** A review of `docs/consumer-guide.md`
|
||
> found 5 issues: (a) Step 8 tells consumers to change `environment:` in
|
||
> their contract to promote, which (b) contradicts the same doc's
|
||
> "Per-environment deployment" section (lines 396-477) that says
|
||
> "promotion-without-editing," (c) the Step 3 contract-fields table
|
||
> lists stale fields (`uses`, `module`) that no longer exist in the
|
||
> schema (real fields: `id`, `name`, `environment`, `infrastructure`),
|
||
> (d) Step 4 caller example is inconsistent with Step 2, and (e) Step 5
|
||
> stage 8 says "(dev only)" when higher envs do apply after attestation.
|
||
> 2. **Environment-promotion lifecycle enforcement.** When a consumer
|
||
> edits `environment:` on a stable `contract.id` (Shape A promotion),
|
||
> the Terraform state key
|
||
> `spike/{stack_name}/{environment}/terraform.tfstate` (adapter.py:129)
|
||
> changes — creating a fresh state file in the new env while the prior
|
||
> env's resources remain live in AWS with no destroy ever running. This
|
||
> **orphans resources** and violates the platform's full-lifecycle-
|
||
> management mission. The platform must detect the env change and
|
||
> destroy the prior env's resources before building the new env. There
|
||
> must be **no path that orphans resources** — fail closed if the
|
||
> destroy fails.
|
||
>
|
||
> The per-environment caller-workflow path (Shape B: one caller workflow
|
||
> per env, `environment` passed as a workflow input) remains a fully
|
||
> supported alternative with no destroy needed (each env has its own state
|
||
> from day one). Both shapes are documented.
|
||
|
||
### Category: Consumer Guide Fixes (docs)
|
||
- **REQ-276:** `docs/consumer-guide.md` Step 3 "Contract fields" table is
|
||
corrected to list the real schema-enforced fields: `id`, `name`,
|
||
`environment`, `infrastructure` (matching `schemas/contract.schema.json`
|
||
`required` and the worked examples). The stale `uses` and `module` rows
|
||
are removed. The `uses` row's note about versioned tags moves to the
|
||
Step 2 caller-workflow section (where the version pin actually lives).
|
||
- **REQ-277:** `docs/consumer-guide.md` Step 4 caller workflow example is
|
||
made consistent with Step 2 — both show `environment` in `with:` or both
|
||
omit it with a "dev is the default" note. The two canonical caller
|
||
snippets no longer disagree.
|
||
- **REQ-278:** `docs/consumer-guide.md` Step 5 stage 8 "(dev only)" is
|
||
corrected to "(autonomous in dev; higher environments apply after HITL
|
||
attestation)" to match `docs/environments/index.md` autonomy table.
|
||
- **REQ-279:** `docs/consumer-guide.md` Step 8 "Promote to qa / prod" is
|
||
rewritten. It documents that editing `environment:` on a stable
|
||
`contract.id` (Shape A) **is a supported promotion path** and that the
|
||
platform **destroys the prior environment's resources before building
|
||
the new environment** — there is no orphan path; if the destroy fails,
|
||
the pipeline fails closed. It includes the worked qa example with a
|
||
note: "Changing `environment: dev` → `environment: qa` triggers a
|
||
destroy of the dev stack (state key `spike/{id}/dev/`) then an apply
|
||
against the qa stack (state key `spike/{id}/qa/`). Both emit evidence
|
||
events." It cross-references the "Per-environment deployment" section
|
||
(Shape B) as the alternative.
|
||
- **REQ-280:** `docs/consumer-guide.md` "Per-environment deployment"
|
||
section (lines 396-477) gains a lead sentence clarifying it is **Shape
|
||
B** (the alternative to Shape A's edit-and-destroy path in Step 8), and
|
||
that it avoids the destroy step because each env has its own state from
|
||
first deploy. The existing table, interpolation reference, and HITL
|
||
gate docs are preserved.
|
||
- **REQ-281:** `docs/consumer-guide.md` Reference table "sample contracts
|
||
use `@v1.19`" wording is corrected — the sample contracts no longer
|
||
carry `uses:` (the version pin lives in the caller workflow). Reword to
|
||
"used with caller workflow `@v1.19`" or the current tag.
|
||
|
||
### Category: Env-Transition Detect-and-Destroy (feat)
|
||
- **REQ-282:** New module `core/env_transition.py` provides:
|
||
`detect_prior_env(contract_id, consumer_repo, new_env) -> Optional[str]`
|
||
— queries the `nova-contracts` DynamoDB table (PK `consumerRepo`, SK
|
||
`contractId#submittedAt`, written by `core/lambda/contract_ingestor.py`)
|
||
for the last-applied environment for this consumer+contract. Returns
|
||
the prior env name if it differs from `new_env`, else `None`. Failures
|
||
to reach DynamoDB log a warning and return `None` (conservative — Shape
|
||
B legitimately has no prior record). Uses boto3 with the ABAC-scoped
|
||
deploy role; respects `core/env.py` for config.
|
||
- **REQ-283:** `core/env_transition.py` provides
|
||
`record_applied_env(contract_id, consumer_repo, env)` — called after a
|
||
successful apply to upsert the last-applied env record in the
|
||
`nova-contracts` table (SK suffix `#LAST_APPLIED`). Idempotent.
|
||
- **REQ-284:** `scripts/run_platform.sh` gains a new **Step 0b:
|
||
environment-transition check** (after Step 0 env onboarding, before
|
||
Step 1 contract validation). It reads `CONTRACT_ID` + `CONSUMER_REPO`
|
||
(from `GITHUB_REPOSITORY` / `NOVA_CONSUMER_REPO`), calls
|
||
`env_transition.py detect`, and if a prior env is returned that differs
|
||
from the new env: (a) re-resolves the contract with
|
||
`environment_override=$PRIOR_ENV` to emit the prior TF config + state
|
||
backend; (b) runs `terraform init -reconfigure` + `terraform destroy
|
||
-auto-approve` against the prior env's state key
|
||
(`spike/{id}/{prior_env}/terraform.tfstate`); (c) emits a
|
||
`nova.env.destroyed` evidence event via `core/outbox_writer.py`; (d)
|
||
**fails closed** — if the destroy exits non-zero, the pipeline exits
|
||
non-zero and no apply runs (no orphan path). If no prior env exists
|
||
(first deploy or Shape B), proceeds normally.
|
||
- **REQ-285:** `scripts/run_platform.sh` records the applied env after a
|
||
successful apply (calls `env_transition.py record` with the resolved
|
||
env). This is the source of truth for the next run's detect step.
|
||
- **REQ-286:** `.github/workflows/deploy.yml` passes
|
||
`NOVA_CONSUMER_REPO=${{ github.repository }}` to `run_platform.sh` so
|
||
`env_transition.py` can query DynamoDB with the correct PK.
|
||
- **REQ-287:** `adapters/terraform/adapter.py` state-key block
|
||
(lines 127-133) gains a doc comment clarifying the key
|
||
`spike/{stack_name}/{environment}/terraform.tfstate` is **env-scoped
|
||
precisely to support destroy-on-env-change** — the env segment lets the
|
||
detect-and-destroy step target the prior env's state without affecting
|
||
the new env. No behavior change.
|
||
|
||
### Category: Tests (test)
|
||
- **REQ-288:** `tests/test_env_transition.py` covers:
|
||
`detect_prior_env` returns `None` when no record exists (first deploy);
|
||
returns the prior env when a record exists and differs; returns `None`
|
||
when the record matches `new_env` (re-apply same env);
|
||
`record_applied_env` writes the record. Uses moto for DynamoDB mocking
|
||
(pattern from `tests/test_contract_ingestor.py`).
|
||
- **REQ-289:** `tests/test_run_platform_env_transition.py` asserts:
|
||
`run_platform.sh` has a "Step 0b: environment-transition check" block;
|
||
it calls `env_transition.py detect`; it calls `terraform destroy`
|
||
against the prior env when a transition is detected; it fails closed on
|
||
destroy failure (no apply runs); it records the applied env after a
|
||
successful apply. Pattern: `tests/test_pipeline.py:79-95` (read the
|
||
script text + assert substrings).
|
||
- **REQ-290:** `tests/test_consumer_guide_per_env_section.py`
|
||
`test_consumer_guide_states_no_field_editing` is renamed to
|
||
`test_consumer_guide_documents_both_promotion_shapes` and asserts both
|
||
shapes are present (Shape A: edit environment with destroy semantics;
|
||
Shape B: per-environment caller workflows). The other 5 assertions in
|
||
the file are preserved. A new test
|
||
`test_consumer_guide_documents_destroy_on_env_change` asserts the guide
|
||
states the platform destroys the prior env's resources when the
|
||
environment field is changed and that there is no orphan path.
|
||
|
||
### Out of Scope (v1.24)
|
||
- **Cross-account destroy.** If the prior and new envs are in different
|
||
AWS accounts (per `docs/environments/index.md`), the destroy step needs
|
||
the prior env's role credentials. The current scaffold
|
||
(`core/environments/dev.json`) uses one account. Cross-account destroy
|
||
is deferred to a future milestone; v1.24 targets the same-account case
|
||
and documents the cross-account limitation.
|
||
- **Decommission pipeline integration.** The env-transition destroy is a
|
||
direct `terraform destroy` (not the 2-step HITL decommission). The
|
||
decommission pipeline remains for explicit stack teardown with SRE
|
||
gates; env-transition is an automated lifecycle step.
|
||
- **Removing Shape B.** Both shapes stay supported. Shape B is not
|
||
deprecated.
|
||
|
||
### v1.24 Traceability
|
||
|
||
| REQ | Phase | Status |
|
||
|-----|-------|--------|
|
||
| REQ-276 | P1 | pending |
|
||
| REQ-277 | P1 | pending |
|
||
| REQ-278 | P1 | pending |
|
||
| REQ-279 | P1 | pending |
|
||
| REQ-280 | P1 | pending |
|
||
| REQ-281 | P1 | pending |
|
||
| REQ-282 | P2 | pending |
|
||
| REQ-283 | P2 | pending |
|
||
| REQ-284 | P2 | pending |
|
||
| REQ-285 | P2 | pending |
|
||
| REQ-286 | P2 | pending |
|
||
| REQ-287 | P2 | pending |
|
||
| REQ-288 | P3 | pending |
|
||
| REQ-289 | P3 | pending |
|
||
| REQ-290 | P3 | pending |
|