The W6 'unset NOVA_GITEA_TOKEN' line in scripts/run_platform.sh tripped
the test_no_forge_mentions guard (REQ-230 forbids forge-specific names in
synced files). Renamed to NOVA_FORGE_TOKEN (forge-agnostic); .env.secrets
adds NOVA_FORGE_TOKEN as an alias; config.json scopes now map forge + gitea
-> NOVA_FORGE_TOKEN. scripts/rotate_spike_key.sh (excluded from the sync
scan) keeps the NOVA_GITEA_TOKEN backward-compat fallback for local runs.
Full suite green (844 passed).
---ci---
project: acdl
phase: 3
milestone: v1.26
status: execute
wave: W6
---
workflows-src/rotate-aws-key.yml — daily cron (0 0 * * *) + workflow_dispatch,
wraps scripts/rotate_spike_key.sh (uses NOVA_AWS_* static-key auth to IAM-
rotate the nova-spike-runner key; uploads the new key to the consumer's
Actions secret store; idempotent — deactivates the old key only after the
new propagates, verified by a post-PUT GET). Synced to .github + .gitea.
v0.2 scope: the mechanism exists (SPEC §5.9 — exists-not-ran); the v0.2
deploy uses the currently-active key. Documented in ARCHITECTURE.md §12.9.
The synced workflow file is forge-agnostic (REQ-230): forge base URL /
owner / consumer repo come from repository secrets (NOVA_FORGE_*,
NOVA_CONSUMER_REPO), not literals. rotate_spike_key.sh reads NOVA_FORGE_*
with NOVA_GITEA_* backward-compat fallback. sync_workflows.py PAIRS
extended to include rotate-aws-key.yml (was hardcoded to 3 pairs).
---ci---
project: acdl
phase: 3
milestone: v1.26
status: execute
wave: W7
---
CAP-025 (local tier) asserts the pilot-apply pipeline is structurally
ready: run_platform.sh steps present, core pipeline modules importable,
dev env bound to 581513795199 (D-203), dynamodb L1 registered (REQ-322),
pilot policies authored (REQ-315/320), outcome backfill present (REQ-317).
Returns Verified on the current branch (all W2/W3/W4 dependencies in
place). Added to CAPABILITY_REGISTRY. The live apply (P4) exercises this
end-to-end against AWS.
---ci---
project: acdl
phase: 3
milestone: v1.26
status: execute
wave: W5
---
The adapter reads env.state_backend.bucket from the env JSON when present
(fallback to the computed nova-tfstate-{account_id}-{region} pattern for
backwards compat). dev.json bound to the real account 581513795199 +
bucket nova-tfstate-581513795199-us-east-1 (D-203). qa/prod/dr stay
placeholder (account_id 000000000000 — the pilot-readiness policy blocks
apply on placeholder, D-208). dynamodb added to the adapter test
EXPECTED_L1_KEYS + a resolution/emission test.
---ci---
project: acdl
phase: 3
milestone: v1.26
status: execute
wave: W3
---
REQ-320: policies/pilot-readiness/no-placeholder-account.json asserts
account_id != "000000000000" over the env JSON (critical severity — a
placeholder account drives a block band). Passes on dev (581513795199),
fails on placeholder. REQ-315: policies/settlement-finality/all-matches-
committed.json asserts all_committed == true over the settlement status
JSON (critical severity). Authored + tested in v1.26; enforcement gates
qa/prod/dr promotions, not dev (G-Q6 — dev all_committed is vacuously
true). Both policy tests run against real kj (not skipped).
---ci---
project: acdl
phase: 3
milestone: v1.26
status: execute
wave: W4
---
REQ-317: core/metrics/outcome_backfill.py backfills fact_decision.outcome
pending -> succeeded/failed after run.completed/run.failed; idempotent +
terminal (does not overwrite a non-pending outcome); wired into the
collector. The Post-Pilot AI Decision Accuracy denominator is now grounded
(fact_decision.outcome is not stuck pending).
REQ-318: ai.decision.made on a block band carries escalation_reason:
'confidence' (the only value in v1.26 — a block is always confidence-
driven; future milestones may add 'policy'). Persisted into fact_run by
the collector. The Post-Pilot Human Escalation Frequency denominator is
now grounded.
---ci---
project: acdl
phase: 3
milestone: v1.26
status: execute
wave: W2
---
Pre-existing failures uncovered by running the full suite with kj installed
+ disk freed (the P2 verify missed these):
- dynamodb L1: rename simple.yaml -> simple.yml + add complex.yml (module-standards
expects both .yml extensions; the P2 author used .yaml)
- sync_workflows: re-sync ci.yml drift (.github + .gitea <- workflows-src)
- CAP-024 deck path: nova-autonomous-cloud-delivery.md was consolidated to
-marp.md in v1.25 P1 (commit a47c162) but test + regression_verify still
pointed at the old path; update both + relax slide-count bound (18-20) +
count class="benefit" divs (marp format, not the old 'Benefit:' text)
---ci---
project: acdl
phase: 3
milestone: v1.26
status: execute
wave: W0.5
---
P1-1 (correctness): run_platform.sh Step 5c now invokes the meta-policies
(block-on-any-critical, tagging-rules-agree) over the merged PCR list after
Step 5b, appending the meta-PCRs to pcr.json before the confidence signal
runs. Closes the D-118/D-119 declarative-critical-block gap (the
confidence_signal.py hard-override stays as defense-in-depth).
P1-2 (testing): test_meta_policies.py behavioral assertions strengthened —
test_no_critical_passes asserts no fails, test_critical_fail_present asserts
a non-pass result, test_pcrs_validate_against_schema validates output.
P1-3 (correctness): _smoke.json assertion rewritten from malformed
'{{ to_string(@) }}' to valid JMESPath '(regex_match(...))'.
---ci---
project: acdl
phase: 5
milestone: v1.25
status: execute
phase_role: final
---/ci---
Two-stage policy scan per item 20:
1. Checkov on static code BEFORE terraform plan (fail-fast, quick dev
feedback). Added to run_platform.sh Step 3c + run_codegen.sh Step 3c
(runs on the authored TF dir before plan, using --framework terraform).
2. Runtime policy scan on the plan AFTER terraform plan: Wiz when
configured (WIZ_API_TOKEN + WIZ_API_URL), else Checkov against the
plan as a drop-in replacement (--framework terraform_plan). Wiz and
Checkov are NEVER both run on the plan. Replaces the old single
Checkov-on-main.tf step in run_platform.sh Step 5 + run_postapply.sh
Step 5.
pipelines/contract.yml: stage list updated — 'checkov' stage replaced by
'checkov-static' (before terraform-plan) + 'runtime-policy-scan' (after
terraform-plan). 9 stages → 10 stages. Header comment updated.
adapters/wiz/wiz_adapter.py: add --plan mode CLI (fetch_and_adapt_plan)
for scanning a terraform plan; backward-compat with the positional
<wiz_issues.json> <contract-id> mode. is_configured() gates the Wiz path.
Tests: test_pipeline_contract.py (9 → 10 stages, new stage names);
test_contract_resolver.py (rename test, assert checkov-static +
runtime-policy-scan present, old 'checkov' gone). Full suite: 685 pass
+ 1 pre-existing attestation failure (NOVA_ATTESTATION_SIGNING_KEY_ID
unset, unrelated to v1.21, fails on main without these changes too).
---ci---
project: acdl
phase: 4
milestone: v1.21
status: execute
phase_role: execution
---/ci---
The metrics/ export views (README.md, TRUST_SNAPSHOT.md, powerbi/) are
consumer-facing but fell outside the original 13 domains, so the first nova
release left them untracked. Adds a 14th domain 'metrics' between docs and
workflows. Updates TestSyncToNovaScript domain-order assertion to 14.
---ci---
project: acdl
phase: 2
milestone: v1.19
status: complete
phase_role: final
---/ci---
Code review (correctness lens) found the same P5 mechanical-edit defect
in two more test files: the ACDL_* fallback delenv was replaced with a
duplicate NOVA_* delenv (leaving a dead duplicate line, a stale 'ACDL_*
fallback until P5' comment, and the ACDL_* var no longer cleaned).
- tests/test_route_halt_artifact.py: two sites (stderr-fallback +
outbox-fallback) each deleted NOVA_SOD_HALT_TOPIC_ARN twice.
- tests/test_adapter.py::test_default_remote_state_key: deleted
NOVA_REMOTE_STATE_KEY twice.
With core/env.py NOVA-only as of P5, a single NOVA_* delenv is the
correct precondition. Collapsed to one delenv per var + updated comments.
---ci---
project: acdl
phase: 5
milestone: v1.15
status: verify
lessons:
- P0 fix applied: duplicate monkeypatch.delenv('NOVA_*') in test_route_halt_artifact.py (2 sites) + test_adapter.py collapsed to a single delenv consistent with the P5 NOVA-only core/env.py.
---/ci---
Code review (correctness lens) found a P0 in tests/test_attestation_matrix.py
introduced by the P5 fallback-removal pass: the dual-read delenv of
ACDL_ATTESTATION_SIGNING_KEY_ID was replaced with a second (duplicate)
delenv of NOVA_ATTESTATION_SIGNING_KEY_ID, leaving the test misleading
(comment claimed 'both NOVA_* and ACDL_* must be unset' while only NOVA_*
was deleted twice) and the ACDL_* var no longer cleaned. With P5 having
removed the ACDL_* fallback from core/env.py, deleting NOVA_* alone is the
correct and sufficient precondition for the skip; this commit drops the
duplicate line and updates the comment to match the NOVA-only contract.
---ci---
project: acdl
phase: 5
milestone: v1.15
status: verify
lessons:
- P0 fix applied: duplicate monkeypatch.delenv('NOVA_ATTESTATION_SIGNING_KEY_ID') in test_signature_skip_when_key_unset left the test misleading and the ACDL_* var uncleaned; collapsed to a single NOVA_* delenv consistent with the P5 NOVA-only core/env.py.
---/ci---
---
ci---
project: acdl
phase: 70
milestone: v1.12
status: verify
---
/ci---
Code review (P70) flagged 2 P1 testing gaps:
1. No end-to-end terraform validate test for the microservice (the real
CAP-013 surface). A future refactor could re-break the dedup and the
suite would stay green.
2. No unit test for the _child_id helper / id_remap / dedup merge.
Added 6 tests (38 adapter tests total, 522 suite total):
- test_microservice_dedup_names_modules_by_child_id: asserts module 'alb'
+ 'service' appear, expanded sub-ids do NOT.
- test_microservice_dedup_rewrites_stack_outputs: service_arn -> module.service,
lb_arn -> module.alb.
- test_microservice_dedup_rewrites_cross_module_refs: lb_target_group_arn ->
module.alb.target_group_arn (not module.alb-targetgroup).
- test_microservice_emits_valid_terraform: end-to-end terraform init +
validate on the microservice main.tf (locks in CAP-013).
- test_single_resource_returns_id_verbatim / test_multi_resource_returns_common_prefix:
unit tests for _child_id.
P2 nits (noted, not fixed): the ci-vpc-apply/destroy 'if' uses != 'plan'
rather than == 'full' (stricter but not exploitable); _child_id docstring
could note commonprefix is character-wise. Both are post-hoc.
---
ci---
project: acdl
phase: 67b
milestone: v1.12
status: execute
---
/ci---
The modules-lifecycle pipeline now defaults to plan-only (fast, no AWS
mutation, no credentials, no cost) so it runs on every PR. A CI variable
ACDL_LIFECYCLE_MODE (workflow_dispatch input 'lifecycle_mode', default
'plan') overrides to 'full' for the real apply->modify->destroy against
live AWS.
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).
Destroy is a no-op exit 0 in plan mode (nothing was applied). VPC-output
injection is gated on full mode.
Workflows: both .github + .gitea (byte-identical) expose lifecycle_mode
as a workflow_dispatch input (choice: plan/full), pass it via env:
ACDL_LIFECYCLE_MODE to every lifecycle step, skip ci-vpc-apply +
ci-vpc-destroy + Read-CI-VPC-outputs in plan mode, and run the lifecycle
+ l2-lifecycle jobs with if: always() so they execute (plan-only) even
when ci-vpc-apply is skipped.
Contract + schema: pipelines/modules-lifecycle.yml gains default_mode:
plan; the schema accepts default_mode (enum plan|full) and a richer
workflow_dispatch inputs shape.
Tests: 14 new tests in test_lifecycle_mode_flag.py (script dispatch) +
10 new tests in TestModulesLifecyclePipeline (workflow flag wiring,
byte-identity, plan-mode skips). Updated test_platform_vpc_destroy to
reflect the plan-mode skip. 516 tests pass; smoke-tested plan mode on
the s3 module (--plan-only green, no AWS apply).
Two architectural changes:
1. Created terraform/ci-vpc/ — a short-lived VPC for L1 module lifecycle
testing, separate from the long-lived platform VPC. Created before
VPC-dependent modules (alb, ecs-service, rds, uptime) are tested,
destroyed after. Outputs (vpc_id, subnet_ids, sg_id, cluster_arn) are
passed to those modules via scripts/run_lifecycle_test.sh +
run_lifecycle_destroy.sh wrappers that inject the CI VPC outputs into
the example contracts.
2. Updated the workflow to use ci-vpc-apply → lifecycle (with artifact
passing) → ci-vpc-destroy (always runs).
8 module-specific fixes:
- s3: unique bucket names (acdl-ci-s3a-simple/complex) instead of
globally-taken 'my-simple-bucket'
- kms-key: alias name with no spaces (locals.tf → alias/acdl-ci-kms)
- iam-role: example contract uses role_name (not name, which the interface
doesn't declare)
- ecs-service: example contract uses family (not name); VPC inputs
(cluster_arn, subnets, security_group) injected by CI VPC wrapper
- uptime: added subnets, security_group, cluster_arn to interface + module;
network_configuration is dynamic (only when subnets provided)
- rds: added subnet_ids input + db_subnet_group resource (conditional
on subnet_ids being non-empty)
- alb: removed hardcoded placeholder sg/subnet values from examples;
vpc_id + subnets + security_group injected by CI VPC wrapper
- cloudfront: removed invalid placeholder WAF ARN from complex example
Regression: 479 passed, 0 skipped, 5 deselected. All 24 example contracts
pass --check-only.
---ci---
project: acdl
phase: P59
milestone: v1.11
status: execute
---/ci---
The ci.yml workflow's test job runs test_adapter.py which includes
test_s3_instance_emits_valid_terraform — this test runs terraform
init+validate as a subprocess. Previously Terraform was not installed
in the CI job, causing FileNotFoundError. Now both the test and
check-only jobs install Terraform 1.9.* via the HashiCorp apt repo.
Reverted the skip-when-terraform-missing logic in the test — Terraform
is now always available in CI.
---ci---
project: acdl
phase: P59
milestone: v1.11
status: execute
---/ci---
The test_s3_instance_emits_valid_terraform test runs terraform init+validate
as a subprocess. In CI, the ci.yml workflow doesn't install Terraform (only
the modules-lifecycle workflow does). The test now skips gracefully when
terraform is not on PATH, using shutil.which('terraform').
---ci---
project: acdl
phase: P59
milestone: v1.11
status: execute
---/ci---