docs(P00): research findings — v1.25 kyverno-json engine surface, 4 policy targets, PolicyEngine swap boundary

RESEARCH.md: kyverno-json CLI (kj scan), ValidatingPolicy structure,
assertion trees + ~ modifier + JMESPath, output shape, severity-via-
annotation convention, 4 policy targets (contract/stack-IR/plan-JSON/
meta), PolicyEngine protocol + OPA-equivalent swap surface, latency
<1s (parallel with checkov), deterministic-not-AI tenet, ECS catalog
prior art, 5 logged assumptions (A1..A5).

PERSONAS.md: 4 active personas (lead-developer, backend-engineer,
new policy-engineer, data-engineer); frontend-engineer deactivated.
policy-engineer owns kyverno-json policies + engine translation +
STANDARDS.md policy-authoring section.

ARCHITECTURE.md §12.7: Policy Engine Registry — protocol, registry,
NullEngine fallback, engine enum reuse (D-116), defense-in-depth
critical-override (D-119), graceful degradation (D-120).

---ci---
project: acdl
phase: 0
milestone: v1.25
status: research
---/ci---
This commit is contained in:
Jon Chery
2026-08-12 18:09:12 +00:00
parent f020178c15
commit f753353ad4
4 changed files with 581 additions and 216 deletions
+108 -59
View File
@@ -1,83 +1,132 @@
---
project: acdl
milestone: v1.24
milestone: v1.25
generated_at: 2026-08-12
generator: lead-developer
verification_toolchain:
typecheck: "python3 -m py_compile core/env_transition.py tests/test_env_transition.py tests/test_run_platform_env_transition.py"
test: "pytest tests/test_env_transition.py tests/test_run_platform_env_transition.py tests/test_consumer_guide_per_env_section.py tests/test_adapter.py tests/test_contract_resolver.py tests/test_deploy_workflow_env_input.py tests/test_pipeline.py -v"
lint: "ruff check core/env_transition.py tests/test_env_transition.py tests/test_run_platform_env_transition.py 2>/dev/null || python3 -m py_compile core/env_transition.py"
typecheck: "python3 -m py_compile core/policy_engine.py adapters/kyverno-json/kyverno_json_engine.py tests/test_policy_engine.py tests/test_kyverno_json_engine.py"
test: "pytest tests/test_policy_engine.py tests/test_kyverno_json_engine.py tests/test_adapter.py tests/test_contract_resolver.py tests/test_confidence_signal.py tests/test_checkov_adapter.py tests/test_kyverno_adapter.py tests/test_pipeline.py -v"
lint: "ruff check core/policy_engine.py adapters/kyverno-json/ 2>/dev/null || python3 -m py_compile core/policy_engine.py"
note: |
v1.24 is the Consumer Guide Accuracy & Env-Promotion Lifecycle
Enforcement milestone — a mixed docs+feat+test milestone. Two active
personas: lead-developer (consumer-guide.md edits + guide test
updates), backend-engineer (core/env_transition.py + run_platform.sh
Step 0b + deploy.yml + adapter doc comment + env_transition tests +
pipeline tests). frontend-engineer stays deactivated (no UI). No
data-engineer (no schema changes — the nova-contracts table already
exists). No new personas.
v1.25 is the kyverno-json Unified Policy Engine milestone — a feat
milestone. Four active personas: lead-developer (coordination +
docs + ARCHITECTURE.md §12.7), backend-engineer (core/policy_engine.py
protocol + registry + contract_resolver.py wiring + run_platform.sh
Step 5 + pipeline tests), policy-engineer (adapters/kyverno-json/
engine + policies across all 4 target dirs + meta-policies + policy
tests + adapter README + STANDARDS.md policy-authoring section),
data-engineer (config.json policy object + schemas/README.md note +
capability-inventory JSON fixture for regression policies).
frontend-engineer stays deactivated (no UI). The policy-engineer is a
new custom persona created for this milestone's policy domain (see
RESEARCH.md §4 — kyverno-json + JMESPath is a distinct framework from
backend-engineer's fastify/hono).
---
# ACDL — Persona Roster (v1.24 Consumer Guide Accuracy & Env-Promotion Lifecycle Enforcement)
# ACDL — Persona Roster (v1.25 kyverno-json Unified Policy Engine)
> v1.24 roster. Two active personas + two deactivated. This is a mixed
> docs+feat+test milestone: the work is consumer-guide accuracy fixes
> (lead-developer), a new env-transition detect-and-destroy platform
> feature (backend-engineer), and test coverage for both (split).
> v1.25 roster. Four active personas + one deactivated. This is a feat
> milestone: the work is a swappable policy-engine protocol + a new
> adapter + policies across 4 Nova artifacts + pipeline wiring + docs.
> The policy-engineer is a new custom persona — kyverno-json + JMESPath
> is a specialized domain that doesn't fit backend-engineer's
> fastify/hono frameworks or data-engineer's drizzle/postgresql.
## Active personas
### lead-developer
- **Domain:** coordination + docs
- **Frameworks:** []
- **Constraints:** ["pragmatic", "battle-tested defaults", "docs match code"]
- **Constraints:** ["pragmatic", "battle-tested defaults", "docs match code", "swap boundary is the moat"]
- **Territory:**
- `docs/consumer-guide.md`
- `tests/test_consumer_guide_per_env_section.py`
- `.ciagent/*.md` (PLAN.md, RESEARCH.md, etc.)
- **Reason:** Owns the consumer guide narrative — the 5 accuracy fixes
(stale fields table, inconsistent caller, "dev only" phrasing, Step 8
rewrite with destroy semantics, reference table wording) and the
consumer-guide test updates (rename + new destroy-on-env-change test).
No UI work (frontend-engineer deactivated). No Python/bash platform
code (backend-engineer territory).
- `.ciagent/ARCHITECTURE.md` (§12.7 Policy Engine Registry — NEW)
- `.ciagent/PROJECT.md` (v1.25 section)
- `.ciagent/REQUIREMENTS.md` (v1.25 section)
- `.ciagent/ROADMAP.md` (v1.25 section)
- `.ciagent/PLAN.md`, `.ciagent/RESEARCH.md`, `.ciagent/CLARIFY.md`,
`.ciagent/GRILL.md`, `.ciagent/PERSONAS.md`
- `docs/METRICS.md` (swappable engine narrative — REQ-307)
- **Reason:** Owns the milestone coordination + the architecture
narrative. The swap boundary (PolicyEngine protocol) is the moat per
Strategic Objective #2 — the lead-developer owns the boundary
description in ARCHITECTURE.md §12.7 and the docs/METRICS.md note.
No Python policy code (backend-engineer + policy-engineer territory).
No UI (frontend-engineer deactivated).
### backend-engineer
- **Domain:** backend (Python + bash + YAML)
- **Domain:** backend (Python + bash + pipeline wiring)
- **Frameworks:** ["boto3", "terraform"]
- **Constraints:** ["api-first", "fail-closed", "no orphan paths", "state-key determinism"]
- **Constraints:** ["api-first", "strict-typing", "engine-agnostic confidence signal", "fail-soft when kj absent"]
- **Territory:**
- `core/env_transition.py` (NEW)
- `scripts/run_platform.sh` (Step 0b insert + record-applied-env)
- `.github/workflows/deploy.yml` (NOVA_CONSUMER_REPO env)
- `adapters/terraform/adapter.py` (doc comment only)
- `tests/test_env_transition.py` (NEW)
- `tests/test_run_platform_env_transition.py` (NEW)
- **Reason:** Owns the env-transition detect-and-destroy feature: the new
`core/env_transition.py` module (DynamoDB query + record), the
`run_platform.sh` Step 0b orchestrator (re-resolve + terraform destroy +
evidence event + fail-closed), the deploy.yml env var passthrough, and
the two new test files. Uses boto3 (DynamoDB) + terraform (destroy) +
bash (pipeline orchestration).
- `core/policy_engine.py` (NEW — PolicyEngine Protocol + PolicyEngineRegistry + NullEngine)
- `core/contract_resolver.py` (MODIFIED — invoke registry pre/post resolve)
- `scripts/run_platform.sh` (MODIFIED — Step 5 kyverno-json parallel pass)
- `scripts/install-kyverno-json.sh` (NEW)
- `tests/test_policy_engine.py` (NEW — protocol conformance, registry, NullEngine)
- `tests/test_run_platform_plan_json_policies.py` (NEW — script-substring assertion)
- `.github/workflows/ci.yml` + `.gitea/workflows/ci.yml` (MODIFIED — Go + kj install)
- **Reason:** Owns the Python protocol layer + the pipeline wiring. The
`PolicyEngine` Protocol + `PolicyEngineRegistry` are Python structural-
typing constructs (PEP 544) — backend-engineer's strict-typing
constraint. The `contract_resolver.py` wiring + `run_platform.sh`
Step 5 are backend territory. Does NOT write kyverno-json policy
files (policy-engineer territory) — only the Python that *invokes* the
engine. Does NOT modify the confidence signal (it already consumes
`list[PolicyCheckResult]` engine-agnostically — PROJECT.md hard-
constraint).
### policy-engineer
- **Domain:** policy (declarative compliance rules)
- **Frameworks:** ["kyverno-json", "jmespath", "kyverno ValidatingPolicy"]
- **Constraints:** ["declarative-policies", "no-imperative-rules", "schema-validated", "severity-via-annotation", "assertion-trees-not-foreach"]
- **Territory:**
- `adapters/kyverno-json/` (NEW — engine impl + __init__.py + README)
- `adapters/kyverno-json/kyverno_json_engine.py` (NEW — KyvernoJsonEngine)
- `adapters/kyverno-json/policies/` (NEW — all 4 target dirs: contract/, stack-ir/, plan-json/, meta/, regression/)
- `adapters/kyverno-json/policies/_smoke.json` (NEW)
- `adapters/README.md` (MODIFIED — new adapter row + PolicyEngine Protocol section)
- `tests/test_kyverno_json_engine.py` (NEW — PCR schema validity, defensive parsing)
- `tests/test_stack_ir_policies.py` (NEW)
- `tests/test_plan_json_policies.py` (NEW)
- `tests/test_meta_policies.py` (NEW)
- `tests/test_regression_policies.py` (NEW)
- `tests/fixtures/stack_ir/`, `tests/fixtures/plan_json/`, `tests/fixtures/capability_inventory.json` (NEW)
- `modules/STANDARDS.md` (MODIFIED — Policy authoring standard section — REQ-307)
- **Reason:** The policy-engineer owns the declarative policy artifacts.
kyverno-json's `ValidatingPolicy` + assertion trees + JMESPath is a
distinct framework from backend-engineer's fastify/hono and requires
its own constraints: no imperative rules (everything is an assertion
tree), severity via the `nova.cloudinit.dev/severity` annotation (not
in the engine adapter), no `forEach` (use the `~` modifier). The
adapter pattern (engine ↔ protocol ↔ registry) is backend-engineer
territory, but the policy *content* and the engine *translation*
(`_to_pcr()`) are policy-engineer territory because they require
kyverno-json output-shape knowledge. Created per RESEARCH.md §4 — this
is a phase-spanning persona (active for P1..P4), not phase-specific.
### data-engineer
- **Domain:** data (config schema + structured fixtures)
- **Frameworks:** ["jsonschema", "yaml"]
- **Constraints:** ["schema-first", "type-safe config", "backward-compatible additions"]
- **Territory:**
- `.ciagent/config.json` (MODIFIED — new `policy` object: engine + policy_root)
- `schemas/policy_check_result.schema.json` (READ-ONLY — no change per D-116)
- `schemas/README.md` (MODIFIED — note engine: "kyverno" shared by K8s adapter + kj)
- `tests/fixtures/capability_inventory.json` (NEW — clean + drifted inventory fixtures for regression policies)
- **Reason:** The `config.json.policy` object is a schema-first addition
(new top-level key with `engine` + `policy_root` fields). The
capability-inventory JSON fixtures for the regression-gate policies
(REQ-304) are structured data — the data-engineer owns the fixture
shape. The `policy_check_result.schema.json` is read-only (D-116 — no
enum change); the data-engineer documents the `engine: "kyverno"`
sharing in `schemas/README.md`. No migrations (no database). No Python
(backend-engineer + policy-engineer territory).
## Deactivated personas
### frontend-engineer
- **Active:** false
- **Reason:** No UI work in v1.24. The consumer guide is markdown docs
(lead-developer territory). Deactivated per v1.17/v1.18/v1.22/v1.23
precedent.
### data-engineer
- **Active:** false
- **Reason:** No schema changes in v1.24. The `nova-contracts` DynamoDB
table already exists with the right shape (PK `consumerRepo`, SK
`contractId#submittedAt`). The env-transition module only adds a new
`#LAST_APPLIED` SK suffix — no schema migration, no ORM, no new tables.
The backend-engineer handles the boto3 queries.
## Phase-specific notes
- No phase-specific personas. Both active personas span P1-P3.
- P4 (final review + audit + ship) is lead-developer territory
(orchestration + docs completion).
- **active:** false
- **Reason:** ACDL has no frontend (no package.json — confirmed in
config.json personas.personas[frontend-engineer].reason). v1.25 adds
no UI work — the policy engine is backend + policy artifacts only.
Deactivated per the v1.15+ convention.