From 81f111d462bfd2446266ccdccb3229c73769d3fb Mon Sep 17 00:00:00 2001 From: Jon Chery Date: Wed, 29 Jul 2026 20:32:59 +0000 Subject: [PATCH] docs(P04): complete regression-gate-evidence-hardening phase (v1.13.7) ---ci--- project: acdl phase: 4 milestone: v1.14 status: complete requirements: covered: [REQ-138] partial: [] ---/ci--- --- .ciagent/CAPABILITY_INVENTORY.md | 15 ++++++++------ core/regression_verify.py | 34 ++++++++++++++++++++++---------- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/.ciagent/CAPABILITY_INVENTORY.md b/.ciagent/CAPABILITY_INVENTORY.md index 848ba4b..c9169eb 100644 --- a/.ciagent/CAPABILITY_INVENTORY.md +++ b/.ciagent/CAPABILITY_INVENTORY.md @@ -93,22 +93,25 @@ down to zero-cost steady state (P64, D-096). - **CAP-017 (Verified):** DynamoDB `acdl-contracts` table — Verified live-aws via L1 rds module lifecycle pipeline (apply/modify/destroy - exit 0). Evidence: regression registry CAP-017 (lifecycle-pipeline tier). + exit 0). Evidence: regression registry CAP-017 (offline proxy: terraform + files present + fmt -check passes + contracts resolve; live + apply/modify/destroy verified by the modules-lifecycle workflow run). - **CAP-018 (Verified):** Lambda contract-ingestor — Verified via local Lambda stub (CAP-011, Phase 53) + lifecycle pipeline. Evidence: - regression registry CAP-018. + regression registry CAP-018 (offline proxy). - **CAP-019 (Verified):** ECS cluster + service — Verified live-aws via L2 microservice lifecycle pipeline (apply/modify/destroy exit 0). - Evidence: regression registry CAP-019. + Evidence: regression registry CAP-019 (offline proxy). - **CAP-020 (Verified):** CloudFront + WAF production static-assets stack — Verified live-aws via L2 static-assets lifecycle pipeline - (apply/modify/destroy exit 0). Evidence: regression registry CAP-020. + (apply/modify/destroy exit 0). Evidence: regression registry CAP-020 + (offline proxy). - **CAP-021 (Verified):** uptime-kuma monitoring primitive — Verified live-aws via L1 uptime module lifecycle pipeline. Evidence: regression - registry CAP-021. + registry CAP-021 (offline proxy). - **CAP-022 (Verified):** OIDC role for act_runner — Verified live-aws via L1 iam-role module lifecycle pipeline. Evidence: regression - registry CAP-022. + registry CAP-022 (offline proxy). All CAP-017..022 are now in the regression registry (`core/regression_verify.py`) with "lifecycle-pipeline" tier evidence diff --git a/core/regression_verify.py b/core/regression_verify.py index 49afde2..81d1c18 100755 --- a/core/regression_verify.py +++ b/core/regression_verify.py @@ -431,13 +431,19 @@ def _check_s3_state_bucket() -> Tuple[Status, str]: def _check_lifecycle_module_terraform(module: str) -> Tuple[Status, str]: """Helper: verify an L1 module's terraform dir exists with the required - files + its example contracts resolve. This is the offline proxy for - 'lifecycle pipeline green' — the pipeline cell going green requires - terraform init+validate+apply+modify+destroy to succeed against live - AWS, which requires the terraform files to exist and contracts to - resolve first. We avoid terraform init here (too slow for the - regression gate); terraform validate is run by the lifecycle pipeline - itself.""" + files + its example contracts resolve + terraform fmt syntax check + passes. This is the offline proxy for 'lifecycle pipeline green' — the + pipeline cell going green requires terraform init+validate+apply+modify+ + destroy to succeed against live AWS, which requires the terraform files + to exist, contracts to resolve, and HCL syntax to be valid first. + + We run `terraform fmt -check` (fast, no init required) as a syntax probe. + We avoid `terraform validate` here (requires `terraform init`, which + downloads providers — too slow for the regression gate). Full + `terraform validate` is run by the lifecycle pipeline itself. This is + an offline proxy, not live pipeline evidence; the live apply/modify/ + destroy is verified by the modules-lifecycle workflow run, not by this + gate.""" tf_dir = ROOT / "modules" / "l1" / module / "terraform" if not tf_dir.is_dir(): return "Broken", f"modules/l1/{module}/terraform/ does not exist" @@ -450,6 +456,11 @@ def _check_lifecycle_module_terraform(module: str) -> Tuple[Status, str]: tf_text = "".join((tf_dir / f).read_text() for f in ["variables.tf", "main.tf", "outputs.tf"] if (tf_dir / f).is_file()) if "local." in tf_text and not (tf_dir / "locals.tf").is_file(): return "Broken", "missing terraform files: ['locals.tf'] (referenced by module)" + # terraform fmt -check: fast HCL syntax probe (no init required). + rc, out, err = _run_subprocess( + ["terraform", "fmt", "-check", "-diff", str(tf_dir)], timeout=30) + if rc != 0: + return "Broken", f"terraform fmt -check failed: {err.strip()[-200:]}" for ex in ["simple", "complex"]: contract = ROOT / "modules" / "l1" / module / "examples" / f"{ex}.yml" if not contract.is_file(): @@ -459,12 +470,15 @@ def _check_lifecycle_module_terraform(module: str) -> Tuple[Status, str]: ], timeout=30) if rc != 0: return "Broken", f"{ex}.yml resolver failed: {err.strip()[-200:]}" - return "Verified", f"terraform files present + simple/complex contracts resolve" + return "Verified", f"terraform files present + fmt -check passes + simple/complex contracts resolve" def _check_lifecycle_l2_module(module: str) -> Tuple[Status, str]: """Helper: verify an L2 module's composition resolves + its example - contracts resolve. Offline proxy for 'L2 lifecycle pipeline green'.""" + contracts resolve. Offline proxy for 'L2 lifecycle pipeline green'. + This is an offline proxy, not live pipeline evidence; the live + apply/modify/destroy is verified by the modules-lifecycle workflow + run, not by this gate.""" for ex in ["simple", "complex"]: contract = ROOT / "modules" / "l2" / module / "examples" / f"{ex}.yml" if not contract.is_file(): @@ -474,7 +488,7 @@ def _check_lifecycle_l2_module(module: str) -> Tuple[Status, str]: ], timeout=30) if rc != 0: return "Broken", f"{ex}.yml resolver failed: {err.strip()[-200:]}" - return "Verified", f"L2 composition resolves (simple + complex contracts)" + return "Verified", f"L2 composition resolves (simple + complex contracts; offline proxy)" def _check_cap_017_dynamodb() -> Tuple[Status, str]: