Folds SPEC §5.1/§5.2/§5.9 + §10 Q1 (resolved by evidence — Gitea Actions
rejects cross-repo uses:) into one P3 round (D-022 intent: cover all
platform gaps to avoid a second clarify round). W0 is the highest-
priority gap; W0.5 (already done) fixes the v1.25 skip-masked kj bug;
W6 fixes deploy.yml drifts (AWS_DEFAULT_REGION, ref v1.25, no raw
NOVA_AWS_*); W7 adds the rotation scheduled workflow (mechanism must
exist per SPEC §5.9). Must-haves updated: full suite green (the '170
baseline holds' claim was inaccurate — 7 pre-existing P2 failures
uncovered by W0.5, all fixed).
---ci---
project: acdl
phase: 0
milestone: v1.26
status: plan
---
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
---
The v1.25 kyverno-json engine adapter and policies were authored but never
validated against the real `kj` binary — the test suite
`pytest.skip("kj not installed")` when `kj` was absent, masking the bug.
With `kj` v0.0.3 now installed, the 3 failing-fixture tests
(stack-ir/plan-json/regression) showed 0 fails (all passed falsely). Root
causes (3 substrate bugs) and fixes:
1. ENGINE — bare-list output format. `kj scan --output json` emits a bare
JSON LIST at the top level (NOT `{"results": [...]}`); each entry has
`resource` + `results[].rules[]` with `violations[]` (fail) / `error`
string (eval error) / neither (pass). The v1.25 `_translate` did
`out.get("results", [])` on a dict → `out` is a list → returned `[]` →
emitted a single KJ_NO_RESULTS pass PCR. Rewrote `_translate` to parse
the real v0.0.3 nested shape (policy.metadata.name, rule.name,
violations[].errors[].field/detail/value). Future-proofs to also accept
the legacy dict shape. Preserves RESULT_MAP, severity-from-annotation,
is_configured(), _skipped_not_configured, _error_pcr, the temp-file
payload write, and the subprocess invocation.
2. ENGINE — `.json` policies not loaded by `kj`. The upstream loader
(pkg/policy/load.go) uses fileinfo.IsYaml() which only matches
`.yaml`/`.yml` — `.json` files are silently skipped (0 policies).
Nova policies are authored as `.json` (TestPolicyFilesExist asserts the
filenames). Added `_materialize_yaml_policy_dir`: mirrors the source
tree to a temp dir, copying every `.json` policy to a `.yaml` twin
(JSON is a valid YAML subset, verified against kj v0.0.3). Source
`.json` files remain untouched.
3. POLICIES — `validate` wrapper + check syntax. Removed the `validate`
wrapper from all 16 policies (kj v0.0.3 ignores `validate`-wrapped
rules — `assert` goes directly under the rule). Fixed the check syntax:
a check entry is `expression: expected_value` (e.g.
`(regex_match(..., @)): true`), not `field: (expression)` (which
compared a bool to nothing → "types not comparable"). For per-resource
checks over stack-IR/plan-JSON, `~.resources` (descendant anchor) is
required for per-element iteration; a plain path applies to the whole
array. For type-scoped rules (s3/ebs encryption, iam/db/kms), the type
guard is folded into the expression (`type == '...' && !<has-prop>`)
so non-matching resources short-circuit to false. cap-013 dedup uses
`max(map(&length(@), values(group_by(adapters, &@)))) == `1`` (no
`duplicates` JMESPath fn exists). Preserved all policy metadata
(apiVersion, kind, metadata.name, severity + title annotations) —
TestPolicyValidity/TestPolicyFilesExist still pass.
INSTALL SCRIPT — the v1.25 `go install .../cmd/kj@latest` failed: the
`cmd/kj` path does not exist in v0.0.3 (upstream produces a binary named
`kyverno-json`). Fixed to `go install github.com/kyverno/kyverno-json@latest`
+ symlink `kyverno-json` → `kj` (GOBIN and /usr/local/bin fallbacks).
Idempotent: short-circuits when `kj` is already on PATH and working.
Verification: `which kj` → /usr/local/bin/kj; `kj version` → v0.0.3.
test_kyverno_json_engine + test_stack_ir_policies + test_plan_json_policies
+ test_meta_policies + test_regression_policies: 36 passed, 0 skips
(_require_kj no longer skips). Full suite (excluding pre-existing hang in
test_verify_regression_mode.py): 776 passed, 6 failed — all 6 failures are
pre-existing (confirmed by stashing this commit's diff and re-running);
the only in-scope-acceptable failure is
test_module_standards.py::test_all_l1_have_required_files (dynamodb
extension drift, data-engineer's later wave).
---ci---
project: acdl
phase: 3
milestone: v1.26
status: execute
wave: W0.5
---
Relocate completed-milestone history to .ciagent/archive/ (byte-identical
snapshots of PROJECT/REQUIREMENTS/ROADMAP/ARCHITECTURE pre-compression +
verbatim moves of REVIEW/AUDIT/VERIFY/PRE_MORTEM). Slim the in-place files
to retain only active-milestone (v1.26) + immediate-predecessor (v1.25)
context + durable vision/tenets/scope/RACI/capability-status/load-bearing
decisions. REGRESSION_REPORT.{json,md} stay in place (live read/write
targets of core/metrics/collector.py + core/regression_verify.py).
Working context: 11,164 → 4,152 lines (~63% reduction). Archive preserves
8,615 lines. Lossless via relocation + git history. No test regressions
(761 passed; same 3 pre-existing failures as baseline).
---ci---
project: acdl
phase: 2
milestone: v1.26
status: execute
lessons:
- REGRESSION_REPORT.{json,md} are live operational files (read by
core/metrics/collector.py + core/regression_verify.py) — must NOT be
archived. Pre-flight grep for code references to candidate archive
paths before any move.
- test_no_purged_loaded_term scans .ciagent/PROJECT.md + CLARIFY.md +
docs/ for 'penetrat' — slimmed files must not reintroduce it. Historical
description of the purge ('removed the term ...') is safe in ROADMAP.
- Git rename detection (R) works for pure file moves; snapshot-then-slim
shows as A + M. Both preserve history.
---/ci---
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---
The Step 5b kyverno-json block used a single-quoted heredoc (<<'PY') but
referenced $WORK and $CONTRACT_ID inside the Python body as literal
strings — neither variable expanded, so kj scan ran against the literal
filename "$WORK/tfshow.json" (FileNotFoundError) and recorded contractId
"$CONTRACT_ID" verbatim. The entire Step 5b plan-JSON policy pass was
silently broken whenever kj was installed (it only "worked" in the
kj-absent skip path, which the tests exercise).
Fix: pass the two values as argv (python3 - "$WORK/tfshow.json"
"$CONTRACT_ID" <<'PY') and read them via sys.argv. This preserves the
single-quoted heredoc (no shell expansion into Python source — avoids a
payload-injection vector if $CONTRACT_ID ever contained a quote) while
correctly threading the values into the engine.
---ci---
project: acdl
phase: 5
milestone: v1.25-kyverno-json
status: verify
lessons:
- P0 fix applied: Step 5b heredoc <<'PY' prevented $WORK/$CONTRACT_ID
expansion → kj scan read literal filename, Step 5b silently broken
whenever kj installed. Re-threaded via sys.argv (also closes a
payload-injection vector vs naively unquoting the heredoc).
---/ci---