Files
acdl/.ciagent/PLAN.md
T
Jon Chery 804c52aa90 docs(P00): revise plan — add P3 W0 (Gitea adapter) + W0.5 (kj substrate) + W6 (drift) + W7 (rotation) per SPEC-aws-deploy-platform-gaps
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
---
2026-08-18 22:01:07 +00:00

510 lines
26 KiB
Markdown

# PLAN — v1.26 (Live Pilot Estate Activation)
> Feature milestone. Tags on the **v1.25.x** line: v1.25.0 (P0) →
> v1.25.1 (P1) → v1.25.2 (P2) → v1.25.3 (P3) → v1.25.4 (P4) → v1.25.5
> (P5 final = milestone release). 13 requirements (REQ-310..322),
> 5 phases (P0 pre-execution + 4 execution + 1 final). Multi-project:
> `acdl` (platform) + `nova-blockchain-exchange` (consumer). Tags run
> on the previous minor's patch line per `run.md` versioning logic
> (feature milestone — at least one feat phase; progressive patches per
> phase; the final phase's patch IS the milestone release; no separate
> minor tag).
---
## Phase 0 — Pre-Execution (complete, tag v1.25.0)
SPECIFY → CLARIFY → RESEARCH → IDEATE → PLAN → GRILL. All `.ciagent/`
MD, research, plans. Ships as `v1.25.0` on the v1.25.x line.
**Pre-run (Workstream A, on main before branch gate):**
- A1: flaky test fix (commit `8c68d68`, pushed).
- A2: ACDL_*→NOVA_* bootstrap migration (commit `f844fea`, pushed).
- A3: AWS bootstrap — S3 state bucket + DynamoDB outbox created.
- A4: `nova-blockchain-exchange` Gitea repo created + cloned.
**Phase 0 stages (on `phase/00-specify-clarify-research-plan`):**
- SPECIFY: v1.26 established in config.json + PROJECT.md + ROADMAP.md +
`.ciagent/nova-blockchain-exchange/{PROJECT,REQUIREMENTS,ROADMAP}.md`.
- CLARIFY: 10 ambiguities resolved (D-200..D-213).
- RESEARCH: PoA blockchain, deploy model, DynamoDB gap (REQ-322),
metric grounding, persona assessment (5 personas).
- IDEATE: 7 ideas accepted (I1..I7 → REQ-315..322), 3 deferred.
- PLAN: this file.
- GRILL: adversarial review (binding verdicts).
---
## Phase 1 — blockchain-core (tag v1.25.1)
**Goal:** The consumer repo has a working homegrown PoA blockchain +
order-matching engine + settlement service. All unit tests pass in the
consumer repo's own CI.
**Project:** `nova-blockchain-exchange` (consumer repo).
**Branch:** `nova-blockchain-exchange/phase/01-blockchain-core`.
**Persona:** blockchain-engineer (primary), lead-developer (coordination).
### Wave 1 — chain core (REQ-310)
- **Task 1.1** (blockchain-engineer): `chain/block.py` — Block dataclass
(index, timestamp, prev_hash, transactions, nonce, hash).
`compute_hash()` deterministic (SHA-256). Unit test: `test_block.py`.
- **Task 1.2** (blockchain-engineer): `chain/ledger.py` — Ledger class:
`append_block()`, `verify_chain()`, `get_block(index)`,
`get_latest_block()`. Genesis block on init. Unit test: `test_ledger.py`.
- **Task 1.3** (blockchain-engineer): `chain/validator.py` — PoA
validator: single validator (config-driven), `propose_block(transactions)`
→ Block, `commit_block(block)`. Unit test: `test_validator.py`.
### Wave 2 — order engine + settlement (REQ-311, REQ-312) — parallel with Wave 1 tail
- **Task 2.1** (blockchain-engineer): `engine/order.py` — Order
dataclass (id, side, symbol, price, size, timestamp).
- **Task 2.2** (blockchain-engineer): `engine/order_book.py`
OrderBook: `add_order(order)`, `match_orders()` → list of Match
(price-time priority, partial fills). Unit test: `test_order_book.py`.
- **Task 2.3** (blockchain-engineer): `settlement/service.py`
SettlementService: `settle(match)` → SettlementTransaction,
`submit(ledger)`. Idempotent (re-settling a match is a no-op once
final). Finality = block commit. Unit test: `test_settlement.py`.
### Wave 3 — consumer CI (cross-cutting)
- **Task 3.1** (blockchain-engineer): `.github/workflows/ci.yml` +
`.gitea/workflows/ci.yml` — lint + pytest on chain/engine/settlement.
- **Task 3.2** (lead-developer): `nova-blockchain-exchange/README.md`
repo overview + dev setup.
**Must-haves (verify before ship):**
- `pytest tests/` in the consumer repo passes (chain integrity, hash
determinism, genesis, append/verify, match priority, partial fills,
settlement idempotency, finality check).
- The chain is deterministic (replay produces the same hash chain).
- The consumer CI workflow runs on push.
**Ship:** tag `v1.25.1`, merge `phase/01``milestone/v1.26-pilot-activation`,
Gitea release (best-effort). Delete `phase/01`.
---
## Phase 2 — consumer-contract-and-deploy (tag v1.25.2)
**Goal:** The consumer repo declares its infrastructure via
`contract.yaml` (validated against the platform's schema) + invokes the
platform's `deploy.yml@v1.25` workflow. The contract references the
`microservice` (ECS), `dynamodb`, + `s3` modules.
**Project:** `nova-blockchain-exchange` (consumer repo) + `acdl`
(platform repo — for the `deploy.yml@v1.25` ref + the `v1.25` floating
tag).
**Branch:** `nova-blockchain-exchange/phase/02-contract-and-deploy`.
**Persona:** blockchain-engineer (contract authoring), data-engineer
(registry/DynamoDB dependency check), lead-developer (deploy.yml ref).
### Wave 1 — contract (REQ-313)
- **Task 1.1** (blockchain-engineer): `contract.yaml` — id
(`blkex`), name (`blockchain-exchange`), environment (dev),
infrastructure block (microservice + dynamodb + s3).
- **Task 1.2** (blockchain-engineer): `contracts/blockchain-exchange.dev.yml`,
`.qa.yml`, `.prod.yml` — per-env variants.
- **Task 1.3** (blockchain-engineer): `tests/test_contract_validates.py`
— schema validation against the platform's
`schemas/contract.schema.json`.
### Wave 2 — deploy invocation (REQ-314)
- **Task 2.1** (blockchain-engineer): `.github/workflows/deploy.yml`
`uses: acdl/.github/workflows/deploy.yml@v1.25` with
`with: { contract: contract.yaml, mode: full, environment: dev }`.
- **Task 2.2** (blockchain-engineer): `.gitea/workflows/deploy.yml`
byte-identical mirror.
- **Task 2.3** (blockchain-engineer): `tests/test_deploy_workflow_invocation.py`
— asserts the `uses:` ref + inputs.
### Wave 3 — platform floating tag (cross-cutting)
- **Task 3.1** (lead-developer, on `acdl` repo): verify the `v1.25`
floating tag exists (created by `release.yml` on merge to main). If
not, create it pointing at the `v1.25.0` tag (Phase 0 ship).
**Must-haves (verify before ship):**
- `contract.yaml` validates against `schemas/contract.schema.json`.
- The deploy workflow invocation asserts the correct `uses:` ref +
inputs.
- The `v1.25` floating tag resolves.
**Ship:** tag `v1.25.2`, merge `phase/02` → milestone, Gitea release.
Delete `phase/02`.
---
## Phase 3 — pilot-metrics-and-policies (tag v1.25.3)
**Goal:** The platform repo gains the metric-grounding emitters, the
kyverno-json pilot policies, the DynamoDB L1 primitive, the env-JSON
wiring reconciliation, + the pilot regression CAP. The Post-Pilot
metrics are grounded (outcome backfill + escalation reason); the pilot-
readiness + settlement-finality policies are in place.
**Project:** `acdl` (platform repo) + `nova-blockchain-exchange`
(consumer repo — the Gitea adapter rewrites the consumer's `deploy.yml`).
**Branch:** `acdl/phase/03-pilot-metrics-and-policies` (platform branch).
**Personas:** backend-engineer (emitters + adapter + regression),
data-engineer (DynamoDB primitive + env JSON + collector),
policy-engineer (kyverno-json policies), lead-developer (Gitea adapter
+ deploy.yml drift + rotation workflow).
### Wave 0 — Gitea reusable-workflow adapter (SPEC §10 Q1, resolved by evidence) — lead-developer + blockchain-engineer
> **Highest-priority gap.** The v0.2 P3 `workflow_dispatch` (Gitea
> Actions run id=6199) failed: Gitea Actions rejects cross-repo `uses:`
> (`acdl/.github/workflows/deploy.yml@v1.25`) with `expected format
> {owner}/{repo}/.{git_platform}/workflows/{filename}@{ref}`. The
> consumer's `deploy.yml` is frozen at the v0.1 byte-identical mirror;
> the platform adapts (option c — inline checkout-then-call), not
> vice-versa.
- **Task 0.1** (lead-developer): rewrite
`nova-blockchain-exchange/.gitea/workflows/deploy.yml` + byte-identical
`.github/workflows/deploy.yml` — drop the `uses:` indirection; single
`deploy` job on `ubuntu-latest` that `actions/checkout@v4` the consumer,
`actions/checkout@v4` `acdl/acdl` @ `ref: v1.25` into `platform/`,
setup-python 3.12, install deps (jsonschema/pyyaml/boto3 + checkov),
install Terraform 1.9.*, configure AWS (static-key path:
`aws-region: ${{ secrets.AWS_DEFAULT_REGION }}`, `access-key-id` +
`secret-access-key` from `NOVA_AWS_*` secrets; no OIDC token minted),
run `bash platform/scripts/run_platform.sh $MODE_FLAG $ENV_FLAG
contract.yaml`. Preserve `on: workflow_dispatch` inputs (mode choice
default full; environment choice default "") + `permissions: {id-token:
write, contents: read}` + `secrets: inherit`.
- **Task 0.2** (blockchain-engineer): update
`nova-blockchain-exchange/tests/test_deploy_workflow_invocation.py` +
`test_deploy_gitea_invocation.py` — assert no cross-repo `uses:`,
assert `ref: v1.25`, assert `secrets: inherit`, assert
`run_platform.sh` invoked, assert `AWS_DEFAULT_REGION` wired.
- **Task 0.3** (lead-developer): `acdl/.github/workflows/deploy.yml`
stays as the GitHub Actions reference impl (the `workflow_call`
reusable workflow — used by GitHub-hosted consumers); document in
`adapters/README.md` that Gitea consumers use the inline adapter, not
the reusable `uses:`.
### Wave 0.5 — kyverno-json substrate fix (v1.25 skip-masked bug) — backend-engineer
> The v1.25 kyverno-json engine + policies were never validated
> against the real `kj` binary (tests `pytest.skip("kj not installed")`
> when absent). With `kj` now installed (v0.0.3), 3 policy tests
> failed. Root cause: (a) `kj` v0.0.3 does not load `.json` policy
> files (only `.yaml`/`.yml`) — the engine now materializes `.yaml`
> twins at runtime; (b) the `validate` wrapper is not supported —
> `assert` goes directly under the rule; (c) the check syntax was
> inverted (`expression: expected_value`, not `key: expression`);
> (d) the engine `_translate` expected `{"results": [...]}` but `kj`
> returns a bare list with `results[].policy.metadata.name` +
> `results[].rules[].violations[]`. DONE (committed 59d837f). Also
> fixed `scripts/install-kyverno-json.sh` (the `cmd/kj@latest` path
> fails — the real binary is `kyverno-json`, symlinked as `kj`).
- **Task 0.5.1** (backend-engineer): rewrite
`adapters/kyverno-json/kyverno_json_engine.py` `_translate` for the
bare-list output format + add `_materialize_yaml_policy_dir` (DONE).
- **Task 0.5.2** (backend-engineer): remove the `validate` wrapper +
fix check syntax across all 16 existing policies (DONE).
- **Task 0.5.3** (backend-engineer): fix
`scripts/install-kyverno-json.sh` (DONE).
- **Task 0.5.4** (backend-engineer): resolve pre-existing P2 drift
uncovered by the full-suite run — dynamodb `examples/simple.yml` +
`complex.yml`, `sync_workflows` re-sync, CAP-024 deck path
(`nova-autonomous-cloud-delivery-marp.md`) + slide-count bound +
`class="benefit"` div count (DONE, committed 3735330).
### Wave 1 — DynamoDB primitive (REQ-322) — data-engineer — verify-only (done in P2 W0)
- **Task 1.1** (data-engineer): verify `modules/l1/dynamodb/` resolves
+ emits valid Terraform via `tests/test_adapter.py` (the primitive
shipped in P2 W0; this wave is a re-verify, not re-authoring).
### Wave 2 — metric grounding (REQ-317, REQ-318) — backend-engineer + data-engineer — parallel
- **Task 2.1** (backend-engineer): `core/metrics/outcome_backfill.py`
`backfill(decision_id, outcome)` updates `fact_decision.outcome` +
`backfilled_at`. Reads run-manifest events.
- **Task 2.2** (backend-engineer): `core/metrics/collector.py`
invokes backfill after run completion.
- **Task 2.3** (backend-engineer): `tests/test_outcome_backfill.py`.
- **Task 2.4** (backend-engineer): `core/confidence_signal.py`
`ai.decision.made` gains `escalation_reason: 'confidence'` when
`band == 'block'`.
- **Task 2.5** (backend-engineer): `core/metrics/collector.py`
persists `escalation_reason` into `fact_run`.
- **Task 2.6** (backend-engineer): `tests/test_confidence_escalation_reason.py`.
### Wave 3 — env-JSON wiring + adapter (REQ-319) — backend-engineer + data-engineer — parallel
- **Task 3.1** (backend-engineer): `adapters/terraform/adapter.py`
reads `env.state_backend.bucket` when present (fallback to computed
name for backwards compat).
- **Task 3.2** (data-engineer): `core/environments/dev.json`
`account_id``581513795199`, `state_backend.bucket`
`nova-tfstate-581513795199-us-east-1`.
- **Task 3.3** (data-engineer): `core/environments/{qa,prod,dr}.json`
`state_backend.bucket` updated; `account_id` stays placeholder
(pilot-readiness policy blocks apply on placeholder, D-208).
- **Task 3.4** (backend-engineer): `tests/test_adapter_state_backend.py`.
- **Task 3.5** (backend-engineer): `tests/test_adapter.py` — add
`dynamodb` to `EXPECTED_L1_KEYS` + a resolution + emission test
(cross-territory: data-engineer authored the module, backend-engineer
owns the test).
### Wave 4 — kyverno-json policies (REQ-315, REQ-320) — policy-engineer — parallel
- **Task 4.1** (policy-engineer):
`adapters/kyverno-json/policies/settlement-finality/all-matches-committed.json`
— kyverno-json policy over settlement-service status JSON (asserts
`all_committed: true`). **Note (G-Q6):** the policy is authored +
tested in v1.26; *enforcement* is deferred to the milestone that
binds qa/prod/dr (D-208 — the policy gates promotions, not dev
applies).
- **Task 4.2** (policy-engineer):
`adapters/kyverno-json/policies/pilot-readiness/no-placeholder-account.json`
— kyverno-json policy over env JSON (asserts
`account_id != "000000000000"`).
- **Task 4.3** (policy-engineer): `tests/test_settlement_finality_policy.py`
— passing + failing fixtures; **runs against real `kj`** (not skipped
`kj` is installed via `scripts/install-kyverno-json.sh`).
- **Task 4.4** (policy-engineer): `tests/test_pilot_readiness_policy.py`
— passing (real account) + failing (placeholder) fixtures; **runs
against real `kj`** (not skipped).
### Wave 5 — regression CAP (REQ-316) — backend-engineer
- **Task 5.1** (backend-engineer): `core/regression_verify.py`
CAP-025 (live-pilot-apply): the round-trip assertion.
- **Task 5.2** (backend-engineer): `tests/test_regression_pilot.py`.
### Wave 6 — deploy.yml drift fixes (SPEC §5.1/§5.2) — lead-developer + backend-engineer
> The platform reference `workflows-src/deploy.yml` (synced to
> `.github`+`.gitea`) has three drifts vs the SPEC: (a) `aws-region`
> hardcoded `us-east-1` (SPEC wants `NOVA_AWS_REGION`/`AWS_DEFAULT_REGION`
> from secret); (b) platform checkout `ref: v1.9` (SPEC wants `v1.25`);
> (c) the local `scripts/run_platform.sh` fallback exports raw
> `NOVA_AWS_*` names into shell env (SPEC §5.2 constraint: consume as
> workflow secrets, not shell env — `blocked_env_vars`).
- **Task 6.1** (lead-developer): `workflows-src/deploy.yml`
`aws-region: ${{ secrets.AWS_DEFAULT_REGION || 'us-east-1' }}`;
platform checkout `ref: v1.25`; re-sync to `.github`+`.gitea`.
- **Task 6.2** (backend-engineer): `scripts/run_platform.sh` — source
`AWS_DEFAULT_REGION` from `.env.secrets` for the local fallback (not
raw `NOVA_AWS_*`); the CI path already consumes secrets via the
`configure-aws-credentials` action.
- **Task 6.3** (backend-engineer): `tests/test_deploy_workflow_env_input.py`
— assert `AWS_DEFAULT_REGION` wired + `ref: v1.25` + no raw
`NOVA_AWS_*` in shell env.
### Wave 7 — secret rotation scheduled workflow (SPEC §5.9) — lead-developer
> SPEC §5.9: "the rotation mechanism must *exist* (not have run)."
> A platform-managed scheduled workflow wraps the existing
> `scripts/rotate_spike_key.sh` (manual today) on a daily cron.
- **Task 7.1** (lead-developer): `workflows-src/rotate-aws-key.yml`
`on: { schedule: [{cron: "0 0 * * *"}], workflow_dispatch:}`,
single job that checks out the platform repo + runs
`bash scripts/rotate_spike_key.sh` with `NOVA_AWS_*` bootstrap
secrets; sync to `.github`+`.gitea`.
- **Task 7.2** (lead-developer): verify `scripts/rotate_spike_key.sh`
is idempotent (deactivates old key only after the new key propagates
to the Gitea Actions secret store).
- **Task 7.3** (lead-developer): `tests/test_rotate_key_workflow.py`
structural test (the workflow file declares `schedule` + invokes
`rotate_spike_key.sh`); document in `.ciagent/ARCHITECTURE.md` §12.8
that the mechanism exists (v0.2 scope: exists-not-ran per SPEC §5.9).
**Must-haves (verify before ship):**
- `pytest tests/` in the platform repo passes (the 170 baseline held
inaccurately — the real P2 baseline had 7 pre-existing failures
uncovered by W0.5; all now fixed). Full suite green.
- `pytest tests/` in the consumer repo passes (deploy invocation tests
updated for the inline adapter).
- The kyverno-json substrate works against real `kj` (W0.5 — DONE).
- The Gitea adapter: consumer `deploy.yml` has no cross-repo `uses:`;
inline checkout `acdl@v1.25` + `run_platform.sh` (W0).
- The DynamoDB primitive resolves + emits valid Terraform (W1 verify).
- The outcome backfill updates `fact_decision.outcome` (not `pending`)
(W2).
- The `escalation_reason` field is emitted on `block` band (W2).
- The adapter reads `env.state_backend.bucket` from the env JSON (W3).
- The 2 new kyverno-json policies pass on valid fixtures + fail on
invalid fixtures, against real `kj` (W4 — not skipped).
- CAP-025 is in the regression gate (W5).
- The deploy.yml drifts fixed: `AWS_DEFAULT_REGION` wired, `ref:
v1.25`, no raw `NOVA_AWS_*` in shell env (W6).
- The rotation scheduled workflow exists (W7).
**Ship:** tag `v1.25.3`, merge `phase/03` → milestone, Gitea release.
Delete `phase/03`.
---
## Phase 4 — pilot-run-and-docs (tag v1.25.4)
**Goal:** The pilot estate runs end-to-end against live AWS
`581513795199` (contract resolve → adapter compile → terraform plan →
policy scan → confidence signal → attestation → outbox record). Docs +
adapter README + onboarding guide are complete.
**Project:** `nova-blockchain-exchange` (consumer repo — the run) +
`acdl` (platform repo — docs).
**Branch:** `acdl/phase/04-pilot-run-and-docs` (platform branch for
docs); the run happens via the consumer's `deploy.yml` invocation.
**Personas:** blockchain-engineer (the run), lead-developer (docs),
backend-engineer (regression CAP-025 verification).
### Wave 1 — the pilot run (REQ-316 verification, live)
- **Task 1.1** (blockchain-engineer): trigger the consumer's
`deploy.yml` with `mode: full, environment: dev` against
`581513795199`. The workflow checks out the consumer + platform
repos, runs `run_platform.sh`, applies the contract (ECS +
DynamoDB + S3), records the decision + attestation.
- **Task 1.2** (backend-engineer): verify CAP-025 (regression gate)
passes against the live run.
- **Task 1.3** (blockchain-engineer): capture the run's
`ai.decision.made` + `attestation.recorded` events from the Decision
Ledger → evidence for the milestone ship.
### Wave 2 — docs (REQ-321)
- **Task 2.1** (lead-developer): `adapters/README.md` — new consumer
row + fix the stale `TYPE_MAP` references (IDEATE I8).
- **Task 2.2** (lead-developer): `docs/METRICS.md` — Post-Pilot metrics
grounded note (the 3 targets now have non-zero denominators post-run).
- **Task 2.3** (lead-developer): `.ciagent/ARCHITECTURE.md` §12.8
(Pilot Estate).
- **Task 2.4** (lead-developer):
`.ciagent/nova-blockchain-exchange/README.md` — consumer onboarding
guide (how to invoke `deploy.yml@v1.25`, what secrets to set, what
the contract shape is).
**Must-haves (verify before ship):**
- The pilot run completes end-to-end (apply succeeds, decision recorded,
attestation recorded for dev — autonomous, no human approver).
- CAP-025 passes.
- The 3 Post-Pilot metrics have non-zero denominators (the run
contributed to `fact_run` + `fact_decision`).
- Docs are complete (adapter README, METRICS.md, ARCHITECTURE.md §12.8,
consumer onboarding guide).
**Ship:** tag `v1.25.4`, merge `phase/04` → milestone, Gitea release.
Delete `phase/04`.
---
## Phase 5 — final review + audit + milestone ship (tag v1.25.5)
**Goal:** Multi-persona code review across P1..P4. Audit (reconstruction
test, branch hygiene, commit discipline). Milestone ship: merge to main,
tag `v1.25.5` (= the v1.26 release), Gitea release with full milestone
summary, delete all milestone branches.
**Project:** both (`acdl` + `nova-blockchain-exchange`).
**Branch:** `phase/05-final-review-ship`.
**Personas:** lead-developer (review + audit + ship), backend-engineer
(review), data-engineer (review), policy-engineer (review),
blockchain-engineer (review — the chain core is reviewed).
### Wave 1 — review
- **Task 1.1** (lead-developer): `ciagent-review` — multi-persona code
review across P1..P4. Auto-fix P0; flag P1+ for post-hoc review.
- **Task 1.2** (all personas): fix P0 issues in this phase.
### Wave 2 — audit
- **Task 2.1** (lead-developer): `ciagent-audit` — reconstruction test
(git log ↔ `.ciagent/`), branch hygiene, commit discipline.
- **Task 2.2** (lead-developer): fix critical audit issues in this phase.
### Wave 3 — milestone ship
- **Task 3.1** (lead-developer): merge `phase/05` →
`milestone/v1.26-pilot-activation` → `main`.
- **Task 3.2** (lead-developer): tag `v1.25.5` (= the v1.26 release per
prev-minor tagging rule).
- **Task 3.3** (lead-developer): create Gitea release with full milestone
summary (all phases, all 13 requirements).
- **Task 3.4** (lead-developer): delete all milestone branches (local +
remote). Tags preserve all history.
- **Task 3.5** (lead-developer): update `.ciagent/nova-blockchain-exchange/REQUIREMENTS.md`
(mark REQ-310..322 complete), `.ciagent/ROADMAP.md` (mark v1.26
complete), `.ciagent/NORTH_STAR.md` (note Strategic Objectives #1 +
#3 — first real consumer estate; Post-Pilot denominators activated).
- **Task 3.6** (lead-developer): write checkpoint `stage: complete,
phase: 5, phase_role: final` + clear checkpoint (milestone complete).
**Must-haves (verify before ship):**
- Review: 0 P0 issues unfixed; P1+ flagged for post-hoc.
- Audit: reconstruction test passes; branch hygiene clean; commit
discipline clean.
- Ship: `v1.25.5` tag exists; Gitea release created; milestone branches
deleted; main has the milestone merge.
---
## Requirement → Phase Mapping
| REQ | Phase | Wave | Persona |
|---|---|---|---|
| REQ-310 (blockchain core) | P1 | W1 | blockchain-engineer |
| REQ-311 (order engine) | P1 | W2 | blockchain-engineer |
| REQ-312 (settlement) | P1 | W2 | blockchain-engineer |
| REQ-313 (contract.yaml) | P2 | W1 | blockchain-engineer |
| REQ-314 (deploy invocation) | P2 | W2 | blockchain-engineer |
| REQ-315 (settlement-finality policy) | P3 | W4 | policy-engineer |
| REQ-316 (pilot regression CAP) | P3 | W5 + P4 W1 | backend-engineer |
| REQ-317 (outcome backfill) | P3 | W2 | backend-engineer |
| REQ-318 (escalation reason) | P3 | W2 | backend-engineer |
| REQ-319 (env-JSON wiring) | P3 | W3 | backend + data-engineer |
| REQ-320 (pilot-readiness policy) | P3 | W4 | policy-engineer |
| REQ-321 (docs) | P4 | W2 | lead-developer |
| REQ-322 (DynamoDB primitive) | P3 | W1 | data-engineer |
---
## Wave Ordering Rationale
- **P1 W1 → W2:** the chain core (block + ledger + validator) must land
before the order engine + settlement (they submit transactions to the
ledger). W3 (CI) is cross-cutting + can land any time after W1.
- **P2 W1 → W2:** the contract must land before the deploy invocation
(the invocation references the contract). W3 (floating tag) is cross-
cutting.
- **P3 W1 (DynamoDB) first:** the contract (P2) references `dynamodb` —
the primitive must exist before P2's contract can resolve. **Risk:**
P2's contract references a module that doesn't exist until P3. Resolution: P2's contract is authored but the `test_contract_validates.py` test only checks schema validity (not registry resolution) — the registry resolution test is in P3 (after the primitive lands). The contract's `dynamodb` block is schema-valid (the schema is open); the registry resolution happens at apply time (P4).
- **Alternative:** move REQ-322 to P2 W0 (before the contract). This
avoids the P2→P3 dependency. **Decision: move REQ-322 to P2 W0.**
See revised mapping below.
### Revised: REQ-322 → P2 W0
REQ-322 (DynamoDB primitive) lands in P2 Wave 0 (before the contract)
so the contract's `dynamodb` block resolves at registry time, not just
schema time. This makes P2 self-contained: the primitive + the contract
+ the deploy invocation all land in P2.
| REQ | Phase | Wave | Persona |
|---|---|---|---|
| REQ-310 (blockchain core) | P1 | W1 | blockchain-engineer |
| REQ-311 (order engine) | P1 | W2 | blockchain-engineer |
| REQ-312 (settlement) | P1 | W2 | blockchain-engineer |
| REQ-322 (DynamoDB primitive) | P2 | W0 | data-engineer |
| REQ-313 (contract.yaml) | P2 | W1 | blockchain-engineer |
| REQ-314 (deploy invocation) | P2 | W2 | blockchain-engineer |
| REQ-315 (settlement-finality policy) | P3 | W4 | policy-engineer |
| REQ-316 (pilot regression CAP) | P3 | W5 + P4 W1 | backend-engineer |
| REQ-317 (outcome backfill) | P3 | W2 | backend-engineer |
| REQ-318 (escalation reason) | P3 | W2 | backend-engineer |
| REQ-319 (env-JSON wiring) | P3 | W3 | backend + data-engineer |
| REQ-320 (pilot-readiness policy) | P3 | W4 | policy-engineer |
| REQ-321 (docs) | P4 | W2 | lead-developer |
This revision is a binding plan decision (G-Q8 in the grill may
challenge it).
---
## Future Hardening Items (not in v1.26 scope, documented per grill G-Q9)
- **`NOVA_AWS_*` key-split:** v1.26 uses a single `NOVA_AWS_*` key with
root-equivalent permissions (D-207, confirmed empirically by the
bootstrap). A future hardening milestone should split this into a
`NOVA_BOOTSTRAP_AWS_*` root key (bootstrap only) + a least-privilege
`NOVA_AWS_*` runner key (the spike-runner pattern). The pilot scope
(single account, no production workloads, OIDC default) bounds the
risk.
- **Multi-account landing zone:** qa/prod/dr on separate accounts (D-208
keeps them placeholder in v1.26).
- **D-083 lift:** S3 Object Lock + JWS tamper-evident ledger (when the
pilot becomes a production system, D-204).
- **Multi-validator BFT consensus:** D-201.
- **Other security types:** bonds (T+2), derivatives, options (D-200).