Files
acdl/.ciagent/REQUIREMENTS.md
T
Jon Chery ab7171236a
acdl-ci / Lint (push) Successful in 10s
acdl-ci / Test (push) Failing after 24s
acdl-ci / Platform check-only (offline) (push) Successful in 23s
Nova Slides Render / render (push) Failing after 23s
docs(milestone): complete v1.24 — Consumer Guide Accuracy & Env-Promotion Lifecycle Enforcement
---ci---
project: acdl
phase: 4
milestone: v1.24
status: complete
requirements:
  covered: [REQ-276,REQ-277,REQ-278,REQ-279,REQ-280,REQ-281,REQ-282,REQ-283,REQ-284,REQ-285,REQ-286,REQ-287,REQ-288,REQ-289,REQ-290]
  partial: []
---/ci---
2026-08-12 14:36:15 +00:00

142 KiB
Raw Blame History

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.AF, 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 planterraform apply (dev) → a live ECS Fargate service serving HTTP 200 on its ALB → evidence event written to the DynamoDB outbox → the event renders on the acdl-evidence timeline. 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.yamlcontracts/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 PolicyReportPolicyCheckResult 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.1v1.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-125scripts/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-126terraform/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 P59P60)

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 P61P62)

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.11v1.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-145contract.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-151config.json persona block + branching strategy + ollama-cloud backend aligned with PERSONAS.md + actual runtime. (Phase P17)
  • REQ-152modules/STANDARDS.md internally consistent; no stale TYPE_MAP reference. (Phase P18)
  • REQ-153 — ARCHITECTURE.md has v1.11v1.14 addenda; stale @v1.61.9@v1.13; GRILL G-005/G-008 resolved; COST.md window covers v1.11v1.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 (P1P4) → 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 PlatformNova. 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 ACDLNova; 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-platformalias/nova-platform, SNS acdl-sod-haltnova-sod-halt, SG acdl-ecs-sgnova-ecs-sg, Lambda acdl-contract-ingestornova-contract-ingestor, DynamoDB acdl-contracts/acdl-change-requestsnova-contracts/nova-change-requests (scan+copy data migration, verify row counts, keep old tables until verified), ECR acdl-microservicenova-microservice (re-push images), IAM user/policy acdl-spike-runnernova-spike-runner (re-bootstrap with new key), state bucket acdl-tfstate-...nova-tfstate-... (terraform init -migrate-state to new backend, state JSON backed up first), ALB name prefix acdl-albnova-alb (recreate, brief downtime). 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 (P1P20) → 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-168migrate_ssm_paths.py except Exception: pass narrowed to ParameterNotFound + structured log. (Phase P4)
  • REQ-169regression_verify.py duplicated live-plan/resolver/ lifecycle-resolve blocks extracted into shared helpers (~70 lines saved). (Phase P5)
  • REQ-170run_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-171contract_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-172scripts/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-173run_platform.sh decommission + uptime blocks extracted into scripts/run_decommission.sh + scripts/run_uptime.sh. (Phase P9)
  • REQ-174contract_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-176contract_resolver.py (638 lines) split into resolve / decommission-transform / cli modules. (Phase P12)
  • REQ-177regression_verify.py (670 lines) split into capability checks / live-plan helpers / cli modules. (Phase P13)
  • REQ-178SAFE_OUTPUT_NAMES is schema-driven (from interface.json sensitive annotations); loaded schemas are cached in the resolver. (Phase P14)
  • REQ-179run_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-182schemas/onboarding.schema.json defines the onboarding request; contract_ingestor.py gains an onboard_consumer action that writes a pending CMDB row. (Phase P18)
  • REQ-183core/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 (P1P3 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 (P1P7) → 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), 1218mo 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 (P1P6) → 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-217schemas/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-218core/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-219docs/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-220tests/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-221skills/ 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-222docs/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-223mcp/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-224mcp/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-225tests/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-227docs/presentations/README.md slide count + deck table updated to reflect 21 slides + the 3 new slide titles.

  • REQ-228scripts/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-229scripts/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: giteaforge / generic_forge, GITEA_ACTORFORGE_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-234run_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-237deploy.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/*.mmdassets/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-242tests/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-243docs/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.

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-sptheme: 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: devenvironment: 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 complete
REQ-277 P1 complete
REQ-278 P1 complete
REQ-279 P1 complete
REQ-280 P1 complete
REQ-281 P1 complete
REQ-282 P2 complete
REQ-283 P2 complete
REQ-284 P2 complete
REQ-285 P2 complete
REQ-286 P2 complete
REQ-287 P2 complete
REQ-288 P3 complete
REQ-289 P3 complete
REQ-290 P1 complete