Files
nova-platform/.ciagent/PLAN.md
T
CIAgent 2443909362 docs(milestone): complete v1.0-nova-platform (release v0.1.6)
---ci---
project: nova-platform
milestone: v1.0
status: complete
requirements:
  covered: [REQ-01,REQ-02,REQ-03,REQ-04,REQ-05,REQ-06,REQ-07,REQ-08,REQ-09,REQ-10,REQ-11,REQ-12,REQ-13,REQ-14,REQ-15,REQ-16,REQ-17,REQ-18,REQ-19,REQ-20,REQ-21,REQ-22,REQ-23,REQ-24,REQ-25,REQ-26,REQ-27,REQ-28,REQ-29,REQ-30,REQ-31,REQ-32,REQ-33,REQ-34,REQ-35,REQ-36,REQ-37,REQ-38]
  partial: []
---/ci---

v1.0 milestone complete: simplified infrastructure-delivery platform
derived from Nova (acdl). 6 phases (P0-P5 + P6 final). 38 REQ-IDs.
38 decisions (D-001..D-038). 76 tests pass. Engine boundary holds.
Happy paths green (check-only + CI). 13 L1 + 2 L2 modules. 5 terraform
roots. Shell reproducibility. Zero OOS files.

Tags: v0.1.0 (P0) → v0.1.1..v0.1.5 (P1..P5) → v0.1.6 (P6 = milestone
release on v0.1 patch line).
2026-08-25 02:18:35 +00:00

24 KiB
Raw Blame History

PLAN — Nova Platform v1.0

Task-level, wave-ordered, persona-assigned plan for the 5 execution phases (P1..P5) + the final phase (P6). Consumed by the execute workflow. Derived from ROADMAP.md phase breakdown + REQUIREMENTS.md REQ coverage + PERSONAS.md assignments + CLARIFY.md D-011..D-035 + RESEARCH.md reference shapes.

User-Facing Surface

The platform's user-facing surfaces are entirely offline-runnable — no CI required, no AWS credentials required for the primary verification path:

  1. scripts/run_platform.sh --check-only — Offline validation entrypoint. bash scripts/run_platform.sh --check-only contracts/static-assets.yml → exit 0 + === PLATFORM CHECK OK === iff contract validates → resolves → stack is schema-valid → adapter compiles to structurally-valid HCL. No AWS calls.
  2. scripts/run_platform.sh (default mode) — Full apply path. Loads NOVA_AWS_*AWS_*, runs terraform init/validate/plan/apply, prints === PLATFORM APPLY OK ===. --plan-only stops before apply.
  3. scripts/run_ci.sh — Local CI mirror. lint (py_compile) → test (pytest) → check-only. Prints === CI PIPELINE OK ===.
  4. docs/consumer-guide.md — Consumer happy-path walkthrough.
  5. README.md quickstart — operator/dev quickstart.
  6. .feature-equivalent scenariostests/test_run_platform_check_only.py
    • tests/test_run_ci.py encode the happy path as executable pytest cases.

Happy Path

Two end-to-end scenarios, written BEFORE execute, verified by automated tests in P5:

Scenario A — Offline contract validation (primary gate)

bash scripts/run_platform.sh --check-only contracts/static-assets.yml
# expected: === PLATFORM CHECK OK === ; exit 0

Steps: load core/environments/dev.json → parse contract → validate against contract schema → resolve to stack (interpolation) → adapt to HCL → validate output structure → print banner → exit 0. No AWS SDK calls, no terraform binary, no network.

Scenario B — Local CI mirror

bash scripts/run_ci.sh
# expected: === CI PIPELINE OK === ; exit 0

Steps: (1) lint py_compile $(find core/ adapters/ scripts/ -name '*.py'); (2) test pytest; (3) check-only run_platform.sh --check-only. Print banner → exit 0.

UX Acceptance Criteria

v1.0 is accepted iff ALL hold:

  1. AC-1 (offline validation works): run_platform.sh --check-only contracts/static-assets.yml exits 0 + stdout contains === PLATFORM CHECK OK ===. (tests/test_run_platform_check_only.py)
  2. AC-2 (local CI works): run_ci.sh exits 0 + stdout contains === CI PIPELINE OK ===. (tests/test_run_ci.py)
  3. AC-3 (contract schema is the API): all 10 sample contracts validate against contract.schema.json. (tests/test_contract_schema.py)
  4. AC-4 (resolver pure + correct): resolve() returns stack validating against stack.schema.json; raises ModuleNotFoundError/ VersionNotFoundError. (tests/test_contract_resolver.py + test_stack_schema.py)
  5. AC-5 (adapter compiles + boundary holds): adapt(stack, repo_root) (C-1 fix) emits valid HCL; no .py outside adapters/terraform/ contains forbidden strings. (tests/test_terraform_adapter.py + test_engine_boundary.py)
  6. AC-6 (module catalog complete): registry.json has 13 L1 + 2 L2 = 15 entries; all interface.json + terraform/main.tf exist; L2 entries include terraform_dir (D-013).
  7. AC-7 (Terraform roots + bootstrap exist): terraform/{bootstrap, ci-vpc,platform,microservice,onboarding}/ per REQ-14..19 + D-022..D-025. Lock table nova-tfstate-locks; account parameterized.
  8. AC-8 (docs cover consumer journey): README + docs/{architecture, consumer-guide,modules/index,environments/index,contracts/index}.md exist, no OOS sections. Mechanically checked by grep for OOS section headings ("Security", "Compliance", "OIDC", "Attestation", "ABAC") inside docs/*.md + modules/*/README.md — zero matches (C-3 fix).
  9. AC-9 (reproducibility): requirements-test.txt pins 5 deps; pyproject.toml no [project.scripts]; rotate_spike_key.sh writes .env.secrets (0600); .gitignore covers .env*/terraform state.
  10. AC-10 (engine-agnostic invariant): engine-boundary test passes.

Phase 1 — Contract Surface + Schemas + Resolver

Goal: A contract can be validated, resolved to a stack, environment checked, stack validated — all offline, no apply, no engine terms in contract/core layer.

REQs: REQ-01, REQ-02, REQ-03, REQ-04, REQ-05, REQ-06, REQ-23, REQ-24, REQ-27, REQ-28.

Personas: backend-engineer (contract schema, resolver, environment_check, contracts, tests); data-engineer (stack schema, environment schema, dev.json).

Ships as: v0.1.1 on phase/01-contract-surface-schemas-resolver.

Wave 1 (parallel — schemas + env data)

Task Persona REQs Files Must-have
P1-W1-T1 backend REQ-01, D-015 schemas/contract.schema.json Draft 2020-12; required:[id,name,environment,infrastructure]; id pattern ^[a-z][a-z0-9-]{2,5}$; infrastructure ARRAY (D-015) items {module,version?,inputs}; no engine terms.
P1-W1-T2 data REQ-04, D-012 schemas/stack.schema.json Flat per D-012; required:[contract_id,contract_name,environment,resources]; resources {module,version,source,inputs}; no stack wrapper/relationships/nfrs.
P1-W1-T3 data D-017, D-018 schemas/environment.schema.json required:[name,account_id,region,state_backend,network]; no runner_role_arn/autonomy/confidence_threshold; additionalProperties:false.
P1-W1-T4 data REQ-06, D-018 core/environments/dev.json Validates against environment schema; name:"dev", placeholder account, us-east-1, state_backend, network.

Wave 2 (resolver + env_check — depends on W1)

Task Persona REQs Files Must-have
P1-W2-T1 backend REQ-03, D-011, D-016, D-037 core/contract_resolver.py resolve(contract, registry, modules_dir) -> dict (D-011). Interpolation kept (D-016). Named exceptions ModuleNotFoundError/VersionNotFoundError. L2 opaque (D-012). No source in stack (D-037/C-1 fix) — stack is engine-agnostic {contract_id, contract_name, environment, resources:[{module,version,inputs}]}. No engine terms.
P1-W2-T2 backend REQ-05, D-019 core/environment_check.py check(env_name, environments_dir) -> dict (D-019). Raises EnvironmentNotFoundError. No tuple/onboarding_message/CLI. No engine terms.

Wave 3 (sample contracts — depends on W1+W2)

Task Persona REQs Files Must-have
P1-W3-T1 backend REQ-02, D-033, D-035 contracts/static-assets.{yaml,dev.yml,qa.yml,prod.yml,dr.yml} Validate against contract schema; static-assets L2; inputs incl bucket_name/index_document (D-035); per-env differ only in environment (D-033); interpolation tokens.
P1-W3-T2 backend REQ-02, D-033 contracts/microservice.{yaml,dev.yml,qa.yml,prod.yml,dr.yml} Validate; microservice L2; per-env differ only in environment; interpolation.

Wave 4 (parallel — tests, depends on W1-W3)

Task Persona REQs Files Must-have
P1-W4-T1 backend REQ-23 tests/test_contract_resolver.py Happy path, ModuleNotFoundError, VersionNotFoundError, empty infra. Pass.
P1-W4-T2 backend REQ-24 tests/test_environment_check.py check("dev",...) returns dict; missing → EnvironmentNotFoundError; malformed. Pass.
P1-W4-T3 backend REQ-27 tests/test_contract_schema.py All 10 contracts validate; negative cases raise. Pass.
P1-W4-T4 backend REQ-28 tests/test_stack_schema.py resolve() stack validates; negative cases. Pass.

Must-haves

  • 3 schemas parse as valid JSON Schema draft 2020-12.
  • resolve() + check() exposed with named exceptions; no engine terms.
  • dev.json + 10 contracts validate.
  • pytest -q tests/test_contract_resolver.py tests/test_environment_check.py tests/test_contract_schema.py tests/test_stack_schema.py exit 0.

Phase 2 — Terraform Adapter + Engine Boundary

Goal: A resolved stack compiles to valid HCL via the stateless adapter; engine boundary enforced by grep test.

REQs: REQ-07, REQ-08, REQ-09, REQ-25, REQ-26.

Personas: backend-engineer (adapter + tests).

Ships as: v0.1.2 on phase/02-terraform-adapter-engine-boundary.

Dependency (C-4 fix): P2 depends on P3-W1 (registry.json). The adapter loads registry.json internally (C-1 fix). Reorder: run P3-W1 (registry.json only) before P2-W1, then continue P3-W2 (L1 terraform dirs) in parallel with P2.

Wave 1 (adapter — depends on P3-W1 registry.json)

Task Persona REQs Files Must-have
P2-W1-T1 backend REQ-07, REQ-08, D-013, D-037 adapters/terraform/adapter.py, adapters/terraform/__init__.py adapt(stack, repo_root) -> str (C-1/D-037 fix). Loads modules/registry.json internally to map moduleterraform_dir. Stateless, <250 lines. Emits module "x" { source; <inputs> } per resource. L2 terraform_dir from registry (D-013). __init__.py re-exports. ONLY place engine terms appear.

Wave 2 (parallel — tests)

Task Persona REQs Files Must-have
P2-W2-T1 backend REQ-25 tests/test_terraform_adapter.py Single/multi resource, input passthrough, HCL validity. Pass.
P2-W2-T2 backend REQ-09, REQ-26, D-034 tests/test_engine_boundary.py Grep .py in core/schemas/contracts/tests/scripts/root; exclude adapters/terraform/ + modules/ + .tf/.md/.json; zero matches for forbidden strings. Pass.

Must-haves

  • adapt() stateless, <250 lines, returns HCL.
  • __init__.py re-exports.
  • Both tests pass; boundary proven.

Phase 3 — L1 Primitives + Registry

Goal: Full module catalog — registry.json indexing 13 L1 + 2 L2, each L1 with interface.json + terraform/ (main/variables/outputs/versions/locals).

REQs: REQ-10, REQ-11, REQ-13.

Personas: data-engineer (registry, 13 L1 interface.json + terraform, READMEs, docs/modules/index); backend-engineer (registry test, conftest).

Ships as: v0.1.3 on phase/03-l1-primitives-registry.

Wave 1 (parallel — registry + 13 L1 interface.json + READMEs + docs index)

Task Persona REQs Files Must-have
P3-W1-T1 data REQ-10, D-013 modules/registry.json 15 entries; L1 {interface,terraform_dir,published_at,deprecated,kind:"l1"}; L2 includes terraform_dir (D-013).
P3-W1-T2..T14 data REQ-11, D-014 modules/l1/{s3,vpc,ecs-cluster,ecs-service,iam-role,alb,ecr,cloudfront,waf,rds,kms-key,dynamodb,uptime}/interface.json {name,version,kind:"l1",type,description,inputs,outputs} + resources[] for multi-resource. No nfrs/intra_refs (D-014). s3 stays ref interface (D-035).
P3-W1-T15 data REQ-13, D-029 modules/README.md, modules/README-TEMPLATE.md L1/L2 distinction, registry format, add-a-module. 13+2 tables. Trimmed of security/compliance. DROP NFRs + Compliance sections. No STANDARDS.md.
P3-W1-T16 data REQ-34, D-028 docs/modules/index.md Catalog table → links to modules/l1/<name>/README.md + modules/l2/<name>/README.md. 15 rows.

Wave 2 (parallel — 13 L1 terraform/ dirs)

Task Persona REQs Files Must-have
P3-W2-T1..T13 data REQ-11 modules/l1/<name>/terraform/{main,variables,outputs,versions,locals}.tf count = var.enabled ? 1 : 0; required_version = ">= 1.9, < 1.10"; aws ~> 5.0; variables match interface.json inputs.

Wave 3 (registry test + conftest)

Task Persona REQs Files Must-have
P3-W3-T1 backend REQ-10 tests/test_registry.py 15 entries, L2 has terraform_dir, interface paths resolve, terraform_dir/main.tf exist. Pass.
P3-W3-T2 backend (support) tests/conftest.py (partial) repo_root + registry fixtures. No stack_instance/policy_check_result_schema.

Must-haves

  • registry.json valid, 15 entries, L2 has terraform_dir.
  • 13 L1 interface.json + terraform dirs exist, conform to D-014.
  • READMEs trimmed; docs/modules/index links to all 15.
  • test_registry.py + conftest fixtures pass.

Phase 4 — L2 Patterns + Terraform Bootstrap + Platform

Goal: Two L2 patterns composing L1 internally; AWS bootstrap scripted; platform/ci-vpc/microservice/onboarding roots exist.

REQs: REQ-12, REQ-14, REQ-15, REQ-16, REQ-17, REQ-18, REQ-19.

Personas: data-engineer (L2 interfaces + terraform, bootstrap policy + README, 4 terraform roots); backend-engineer (bootstrap py scripts, rotate_spike_key.sh).

Ships as: v0.1.4 on phase/04-l2-patterns-bootstrap-platform.

Wave 1 (parallel — L2 interfaces + bootstrap policy + 4 roots + README)

Task Persona REQs Files Must-have
P4-W1-T1 data REQ-12, D-012, D-013 modules/l2/microservice/interface.json {name,version,kind:"l2",description,inputs,outputs} — L2-level only, no children/wires.
P4-W1-T2 data REQ-12, D-012, D-035 modules/l2/static-assets/interface.json Inputs incl bucket_name/index_document (D-035).
P4-W1-T3 data REQ-15, D-026 terraform/bootstrap/spike_runner_policy.json Account parameterized (NOT hardcoded). Grants S3/DynamoDB lock/ECS/ECR/ELB/IAM/EC2/CloudFront/WAF/KMS. DROP Lambda/Secrets/SNS/CostExplorer/OIDC.
P4-W1-T4 data REQ-16, D-024 terraform/ci-vpc/main.tf Short-lived test VPC; VPC+2 subnets+IGW+route table+ECS SG+cluster; 4 outputs; state key spike/ci-vpc/terraform.tfstate.
P4-W1-T5 data REQ-17, D-023 terraform/platform/main.tf ONLY shared VPC per D-023; VPC+2 subnets+IGW+route table+ECS SG; outputs vpc_id/subnet_ids/ecs_security_group_id. DROP Lambda/DynamoDB/KMS/Secrets/SNS.
P4-W1-T6 data REQ-18 terraform/microservice/main.tf Instantiates L2 module + data.terraform_remote_state to platform VPC. State key spike/microservice/<env>/terraform.tfstate.
P4-W1-T7 data REQ-19, D-025 terraform/onboarding/main.tf IAM ROLE (not user) per D-025. Cross-account sts:AssumeRole. NO OIDC. consumer_repo/owner_id vars. DROP lambda:InvokeFunctionUrl. Outputs role arn/name.
P4-W1-T8 data REQ-14, D-022 terraform/bootstrap/README.md Documents nova-tfstate-locks (D-022 — NOT nova-outbox), nova-spike-runner, parameterized account, NOVA_BOOTSTRAP_AWS_*.

Wave 2 (parallel — 2 L2 terraform composing L1, depends on W1 + P3)

Task Persona REQs Files Must-have
P4-W2-T1 data REQ-12, D-012, D-038 modules/l2/microservice/terraform/{main,variables,outputs,versions}.tf module "vpc"{source="../../l1/vpc/terraform"} + cluster/service/role/ecr/alb (6 L1s per D-038). Variables match L2 interface.
P4-W2-T2 data REQ-12, D-012, D-035, D-038 modules/l2/static-assets/terraform/{main,variables,outputs,versions}.tf module "s3"{source="../../l1/s3/terraform"} + cloudfront + kms (3 L1s per D-038, drops waf). index_document → s3 website.

Wave 3 (parallel — bootstrap py scripts + rotate, depends on W1 policy)

Task Persona REQs Files Must-have
P4-W3-T1 backend REQ-14, D-022 terraform/bootstrap/create_state_backend.py S3 nova-tfstate-<account>-<region> + DynamoDB nova-tfstate-locks. Idempotent. NOVA_BOOTSTRAP_AWS_*NOVA_AWS_*AWS_*. py_compile clean. No engine-boundary violation (boto3, not HCL).
P4-W3-T2 backend REQ-15, D-026 terraform/bootstrap/create_iam_user.py nova-spike-runner + policy + key. Prints NOVA_AWS_*. Idempotent. py_compile clean. No HCL strings.
P4-W3-T3 backend REQ-22, D-032 scripts/rotate_spike_key.sh Rotates key → .env.secrets (0600). NOVA_AWS_* (D-032). bash -n clean.

Must-haves

  • Both L2 interface.json + terraform exist; compose L1 via module blocks with ../../l1/....
  • bootstrap/ has 4 files; policy account-parameterized; lock table nova-tfstate-locks.
  • 4 terraform roots exist per D-023/D-024/D-025.
  • rotate_spike_key.sh syntax-valid.
  • Bootstrap py py_compile clean, no engine-boundary violation.

Phase 5 — Shell Reproducibility + Test Suite + Docs

Goal: Platform fully reproducible from shell — run_platform.sh --check-only + run_ci.sh exit 0 with banners; full test suite passes; docs complete. Happy path green.

REQs: REQ-20, REQ-21, REQ-22 (verify), REQ-29, REQ-30, REQ-31, REQ-32, REQ-33, REQ-34, REQ-35, REQ-36, REQ-37, REQ-38.

Personas: backend-engineer (shell scripts, shell tests, conftest final, pyproject, requirements); lead-developer (README, architecture, consumer-guide); data-engineer (docs/modules/index finalize, environments/index, contracts/index).

Ships as: v0.1.5 on phase/05-shell-reproducibility-tests-docs.

Wave 1 (parallel — scripts + deps + docs)

Task Persona REQs Files Must-have
P5-W1-T1 backend REQ-20, D-020, D-031, D-032 scripts/run_platform.sh Flags: --check-only/--plan-only/--quiet/--help. check-only: env_check→validate→resolve→adapter→validate output→=== PLATFORM CHECK OK ===. plan-only: +creds (NOVA_AWS_*AWS_* then unset)→init/validate/plan→=== PLATFORM PLAN OK ===. default: +apply→=== PLATFORM APPLY OK ===. bash -n clean. check-only exits 0 offline.
P5-W1-T2 backend REQ-21, D-021 scripts/run_ci.sh 3 stages: lint (glob py_compile)→test (pytest)→check-only. === CI PIPELINE OK ===. --quiet. bash -n clean.
P5-W1-T3 backend REQ-31, D-027 pyproject.toml, requirements-test.txt No [project.scripts], no nova/ dir. 5 test deps. addopts="-v --tb=short". markers=[offline,slow]. packages.find: core,core.*,adapters.*.
P5-W1-T4 backend REQ-38 .gitignore Verify/extend: .env*, terraform state, credentials, __pycache__/, .ciagent/logs/, nova_platform.egg-info/.
P5-W1-T5 lead REQ-32 README.md What platform is, run offline, run tests, run against AWS, repo layout, credentials (static-key only), consumer-guide pointer. No security/identity sections.
P5-W1-T6 lead REQ-33 docs/architecture.md Mirrors .ciagent/ARCHITECTURE.md. 4 layers + boundary + OOS list + catalog. No cross-cutting sections.
P5-W1-T7 lead REQ-37 docs/consumer-guide.md Infra-only: create repo, write contract, run check-only, run against AWS. Interpolation table. DROP OIDC/reusable-workflow/decommission/compliance.
P5-W1-T8 data REQ-34, D-028 docs/modules/index.md (finalize) Catalog table → 15 module READMEs.
P5-W1-T9 data REQ-36, D-018 docs/environments/index.md Env model: account/network/state backend — NO IAM/ABAC. Autonomy table: dev autonomous; qa/prod/dr manual. No HITL gates.
P5-W1-T10 data REQ-35, D-033 docs/contracts/index.md Array-based infrastructure schema (D-015) + samples + per-env variants (D-033). Interpolation table.

Wave 2 (parallel — shell tests + conftest, depends on W1)

Task Persona REQs Files Must-have
P5-W2-T1 backend REQ-29 tests/test_run_platform_check_only.py subprocess run_platform.sh --check-only contracts/static-assets.yml; assert exit 0 + === PLATFORM CHECK OK ===. Pass.
P5-W2-T2 backend REQ-30 tests/test_run_ci.py subprocess run_ci.sh; assert exit 0 + === CI PIPELINE OK ===. Pass.
P5-W2-T3 backend (support) tests/conftest.py (finalize) repo_root, registry, stack_schema, contract_schema fixtures. sys.path.insert for core/ + adapters/.

Wave 3 (full-suite green — depends on W1-W2)

Task Persona REQs Files Must-have
P5-W3-T1 backend (gate) none pytest -q all pass. bash scripts/run_ci.sh exit 0 + banner.

Must-haves (MVP/UX gate)

  • run_platform.sh --check-only contracts/static-assets.yml exit 0 + === PLATFORM CHECK OK ===.
  • run_ci.sh exit 0 + === CI PIPELINE OK ===.
  • Full pytest suite passes.
  • pyproject + requirements configure pytest/py_compile, no CLI.
  • .gitignore covers all patterns.
  • 6 docs exist, no OOS sections.

Phase 6 — Final Review + Ship

Goal: Review v1.0 against AC-1..AC-10, audit for boundary leaks + OOS-creep, ship: merge phase/06milestone/v1.0-nova-platformmain, tag v1.0.0 (major — initial release per D-001), Gitea release, delete branches.

REQs: none new.

Personas: lead-developer (review, audit, ship); backend/data consulted for fix-forward.

Ships as: v1.0.0 (major tag).

Wave 1 (review)

Task Persona REQs Files Must-have
P6-W1-T1 lead AC-1..AC-10 none Walk all 10 ACs. Record pass/fail. All must PASS before proceeding. Escalate on failure (supervised).

Wave 2 (fix-forward, conditional)

Task Persona REQs Files Must-have
P6-W2-T1..Tn backend/data (varies) (varies) Fix specific AC failures. Re-verify. Max 2 revision iterations.

Wave 3 (audit)

Task Persona REQs Files Must-have
P6-W3-T1 lead REQ-09, OOS list none (1) pytest -q tests/test_engine_boundary.py pass. (2) Grep repo for OOS file names (policy_engine, confidence_signal, outbox_writer, abac_, pat_, jws_, kms_signing, hitl_, attestation_, separation_, submission_, env_transition, decommission_, mode_resolver, onboarding.py, regression_verify*, metrics/, pipelines/, .github/workflows/, adapters/kyverno-json, adapters/wiz, adapters/checkov, schemas/pipeline*, schemas/deploy-pipeline*, schemas/policy_check_result*, schemas/metrics_*). ZERO matches. (3) No STANDARDS.md, no PPTX/marp.

Wave 4 (ship)

Task Persona REQs Files Must-have
P6-W4-T1 lead D-001, D-009 git refs Merge phase/06-final-review-shipmilestone/v1.0-nova-platform. Merge milestone→main. Tag v1.0.0 on main. confirm_before_ship=true per D-009 — escalate before tagging. Gitea release via NOVA_FORGE_TOKEN. Delete phase/0*+1* branches. Verify tag + release URL.

Must-haves

  • All 10 ACs PASS.
  • Engine boundary passes; zero OOS files.
  • v1.0.0 tag on main.
  • Gitea release v1.0.0 created.
  • All phase branches deleted.

Cross-phase invariants (hold after EVERY phase)

  1. Engine boundary: no .py outside adapters/terraform/ contains aws_/module "/terraform/provider "/resource " (REQ-09/D-034).
  2. No OOS-creep: no file from PROJECT.md/REQUIREMENTS.md OOS list created in any phase.
  3. Structural conventions: directory names, file roles, interface shape, registry shape, banner strings, state key, tag convention preserved without deviation.
  4. Tests stay green: once a test file exists, subsequent phases must not break it. pytest -q passes at end of every phase.
  5. Supervised escalation: ship (P6-W4-T1) + verification failures escalate to human per escalation_timeout_ms=300000.

Wave dependency graph

P1: W1(schemas+env) → W2(resolver+env_check) → W3(contracts) → W4(tests)
P3-W1(registry.json ONLY) → P2: W1(adapter loads registry) → W2(adapter tests + boundary)  [C-4 fix: P3-W1 before P2-W1]
P3: W1(registry+13 L1 interface+READMEs+docs) → W2(13 L1 terraform) → W3(registry test+conftest)  [W1 split: registry.json first, then rest]
P4: W1(L2 interfaces+bootstrap policy+4 roots+README) → W2(2 L2 terraform per D-038) → W3(2 bootstrap py+rotate)  [deps P3 L1 terraform]
P5: W1(2 scripts+pyproject+reqs+gitignore+README+arch+consumer-guide+3 docs) → W2(2 shell tests+conftest) → W3(full-suite green)  [deps P1-P4]
P6: W1(review AC-1..10) → [W2 fix-forward] → W3(audit + docs OOS grep C-3) → W4(ship v1.0.0)  [deps P5]

Concurrency note (C-5): P3-W1 (13 L1 interface.json tasks) + P3-W2 (13 L1 terraform tasks) + P4-W1 (8 tasks) exceed max_concurrent_agents=5. These waves batch-serialize into 3-5 rounds. Schedule estimate reflects ~2-3× wall-clock for P3.

Total: 6 phases, ~45 tasks across ~13 waves, 3 active personas (max concurrency 5). No wave has >5 parallel tasks.