diff --git a/.ciagent/CHECKPOINT.json b/.ciagent/CHECKPOINT.json index 731954d..424e4d7 100644 --- a/.ciagent/CHECKPOINT.json +++ b/.ciagent/CHECKPOINT.json @@ -1,13 +1,10 @@ { - "phase": 7, - "stage": "complete", - "milestone": "v1.17", - "phase_role": "final", + "phase": 0, + "stage": "plan", + "milestone": "v1.18", + "phase_role": "pre_execution", "attempts": 0, - "updated_at": "2026-08-04T22:30:00Z", - "milestone_complete": true, - "tag": "v1.16.7", - "release_id": null, - "requirements": ["REQ-185", "REQ-186", "REQ-187", "REQ-188", "REQ-189", "REQ-190", "REQ-191", "REQ-192", "REQ-193", "REQ-194", "REQ-195", "REQ-196", "REQ-197", "REQ-198", "REQ-199", "REQ-200", "REQ-201", "REQ-202", "REQ-203", "REQ-204", "REQ-205", "REQ-206", "REQ-207", "REQ-208", "REQ-209", "REQ-210", "REQ-211", "REQ-212", "REQ-213"], - "notes": "v1.17 milestone complete. 3 pillars: (A) NORTH_STAR.md authored + wired into CIAgent context-loading, (B) Leadership Metrics + PowerBI (CloudEvents envelope, SQLite cold store, Decision Ledger hash-chain, Infracost, 8 placeholder views, trust snapshot, metrics catalog), (C) Unified Narrative Deck (18 slides, x3 arc, per-slide benefits, old decks retired). 29 requirements satisfied. 94 tests pass. CAP-023 + CAP-024 Verified. Interactive GRILL: 12 binding decisions applied. 13 decisions locked (D-120..D-132). Hard constraint honored: DO NOT make anything up." + "updated_at": "2026-08-06T00:25:00Z", + "milestone_complete": false, + "notes": "v1.18 PLAN complete. 8 phases, 6 waves, 15 requirements. Sequential execution." } \ No newline at end of file diff --git a/.ciagent/PERSONAS.md b/.ciagent/PERSONAS.md index 3793226..652e384 100644 --- a/.ciagent/PERSONAS.md +++ b/.ciagent/PERSONAS.md @@ -1,33 +1,31 @@ --- project: acdl -milestone: v1.17 -generated_at: 2026-08-04 +milestone: v1.18 +generated_at: 2026-08-06 generator: lead-developer verification_toolchain: - typecheck: "terraform validate && python3 -m py_compile core/**/*.py && python3 -m jsonschema schemas/*.schema.json" - test: "bash scripts/run_regression.sh # 22-capability gate (D-091/D-118) + CAP-023/024 (v1.17)" - build: "bash scripts/run_ci.sh # full local CI reproduction (lint+test+check-only)" + typecheck: "python3 -m py_compile core/submission_readiness.py mcp/atelier/server.py && python3 -m jsonschema schemas/submission-readiness.schema.json" + test: "pytest tests/test_submission_readiness.py tests/test_atelier_mcp.py # REQ-220 + REQ-225" + build: "bash scripts/render_deck.sh docs/presentations/nova-no-humans-platform-marp.md # HTML + PPTX (D-142)" note: | - v1.17 adds a telemetry/observability layer (metrics emitters, SQLite - cold store, PowerBI export, Decision Ledger) + a unified narrative - deck + a durable NORTH_STAR.md. Three active personas: lead-developer - (coordination + deck narrative co-author), backend-engineer (event - emitters, outbox_writer extension, Infracost adapter), data-engineer - (SQLite store, schemas, PowerBI views, metrics collector). frontend- - engineer stays deactivated (no Nova web UI — dashboards are PowerBI, - not a Nova-built frontend; decks are markdown = lead-developer - territory). No new custom personas needed — the metrics domain maps - cleanly to data-engineer (schema/store/export) + backend-engineer - (emitters/instrumentation). + v1.18 adds the Citizen Developer & Production-Grade Guidance surface: + submission-readiness gate, Atelier-derived skills, the Atelier MCP server + (plugin-registry, stdio), and PPTX-as-first-class-artifact deck automation. + Three active personas: lead-developer (coordination + decks + RACI/scope + docs), backend-engineer (MCP server + submission-readiness validator + + render/attach scripts), data-engineer (submission-readiness schema if it + touches contract storage / DynamoDB shape). frontend-engineer stays + deactivated (v1.18 has no frontend; decks are markdown = lead-developer + territory). The MCP plugin-registry is a backend pattern, so a separate + mcp-engineer persona is NOT added — it folds into backend-engineer. --- -# ACDL — Persona Roster (project-level, v1.11 RESTART) +# ACDL — Persona Roster (v1.18 Citizen Developer & Production-Grade Guidance) -> v1.11 is a restart (D-097). The v1.9 roster is superseded. Three -> structural corrections: (1) stateless adapter (D-098), (2) terraform -> owns lifecycle (D-101), (3) pipeline-driven testing (D-102). The roster -> is simplified to the three active domains: data (terraform foundation), -> backend (adapter/resolver), general (pipelines/workflows). +> v1.18 roster. Three active personas + one deactivated. The MCP server +> plugin-registry (D-140) is a backend pattern, not a new persona — it +> folds into backend-engineer. v1.17 precedent (frontend-engineer +> deactivated, decks are markdown = lead-developer territory) is upheld. ## Active personas @@ -35,351 +33,104 @@ verification_toolchain: - **Domain:** coordination - **Active:** true - **Phase-specific:** false -- **Reason:** Owns CIAgent metadata, cross-phase verification scripts, the v1.11 phase orchestration (D-107: P56a + P56b split), and arbitrates persona conflicts. Resolves the milestone decomposition and the STANDARDS.md §8 rewrite (the adapter extension pattern is replaced by the per-module terraform subdir pattern). +- **Frameworks:** [] (no framework — owns process + narrative, not code) +- **Constraints:** ["pragmatic", "battle-tested defaults", "no fabrication (NORTH_STAR honesty model)"] +- **Territory:** + - `docs/presentations/**` (Step 1/2/4 markdown + the deck automation trigger) + - `.ciagent/**` (PROJECT, ROADMAP, REQUIREMENTS, RESEARCH, PLAN, GRILL, PERSONAS, REVIEW, CHECKPOINT) + - `PROJECT.md` (RACI matrix + PDLC-scope statement, REQ-215/216) + - `ROADMAP.md` + - `REQUIREMENTS.md` + - `docs/raci.md` (REQ-215) + - `docs/scope.md` (REQ-216) + - `docs/skills.md` (REQ-222 — the index page, not the skill files themselves) + - `docs/submission-readiness.md` (REQ-219 — citizen-developer-facing copy; co-owned with backend-engineer for the reason-code catalog) +- **Reason:** Owns CIAgent metadata, the milestone narrative, the RACI + + PDLC-scope statements (REQ-215/216), the deck (21 slides, S&P theme + regression check vs P1, CAP-024), the skills index page (REQ-222), and + the citizen-developer-facing submission-readiness doc (REQ-219). Is + the only persona that touches `.ciagent/**` and the deck markdown. +- **Phase-specific flag:** none (active for all of P0–P7). ### backend-engineer - **Domain:** backend - **Active:** true - **Phase-specific:** false -- **Reason:** Owns the adapter rewrite (D-098: stateless assembler — deletes TYPE_MAP/INPUT_MAP/OUTPUT_MAP + 39 type-specific branches, becomes a ~80-line assembler that emits `module "x" { source = "..." ... }` blocks) and the contract resolver env-aware state keys (D-106: `spike/{id}/{env}/terraform.tfstate`). The adapter holds no module content; the engine binding lives in the per-module `terraform/` subdir. Co-authoring expected on the adapter + `run_platform.sh` boundary (general adds `--apply`/`--destroy` modes that invoke the adapter). -- **Territory:** `adapters/terraform/adapter.py` (rewrite to stateless assembler), `core/contract_resolver.py` (env-aware state keys, deterministic composition), `schemas/stack.schema.json` (if the stack instance shape changes), `tests/test_adapter*.py` (regression baseline — the s3 instance.json round-trip must still pass). +- **Frameworks:** ["mcp (Python SDK v2)", "pydantic", "jsonschema", "urllib"] +- **Constraints:** ["api-first", "strict-typing", "plugin-registry extensible (D-140)", "stdio now / HTTP-ready (D-135)", "no stack traces to citizen developers (REQ-218)"] +- **Territory:** + - `mcp/atelier/server.py` (REQ-223) + - `mcp/atelier/plugins/**/*.py` (REQ-223 — principles.py, validation.py) + - `mcp/atelier/vendor/**` (REQ-224 — vendored Atelier snapshot) + - `mcp/atelier/VERSION.md` + `mcp/atelier/README.md` (REQ-224) + - `scripts/update_atelier_vendor.sh` (REQ-224) + - `core/submission_readiness.py` (REQ-218 — the validator, invoked as `contract_ingestor.py --check-readiness`) + - `scripts/render_deck.sh` (REQ-228 — HTML + PPTX render) + - `scripts/attach_release_asset.py` (REQ-228 — Gitea release asset upload) + - `tests/test_atelier_mcp.py` (REQ-225) + - `tests/test_submission_readiness.py` (REQ-220) + - `docs/submission-readiness.md` (REQ-219 — reason-code catalog section; co-owned with lead-developer for the narrative) +- **Reason:** Owns the MCP server (plugin-registry, stdio, vendored + Atelier), the submission-readiness validator (extends + `contract_ingestor.py --check-readiness`, D-133), the render/attach + scripts (D-142 trigger), and the two new test files. The MCP + plugin-registry (D-140) is a backend pattern — no separate + mcp-engineer persona is created; backend-engineer owns it. +- **Phase-specific flag:** none (active for P1 deck-render, P3 validator, + P5 MCP server, P6 scripts). ### data-engineer - **Domain:** data - **Active:** true - **Phase-specific:** false -- **Reason:** Reactivated for v1.11. Owns the heaviest territory: the per-module `terraform/` subdirs (D-098/D-099/D-100 — the engine binding) for all 12 L1 modules, plus the single platform VPC (D-105: `terraform/platform` owns ONE VPC; the microservice composition drops its `vpc` child and references the platform VPC via data source). Each L1 module ships a real terraform module dir (versions/variables/locals/main/outputs.tf) owning its resource shape, nested blocks, and defaults. `locals.tf` is used heavily to centralize default interpolation (D-099). Multi-resource modules get the full 5-file split; trivial single-resource modules may inline locals in main.tf. This is the binding constraint — the stateless adapter cannot be written until the reference s3 module exists (D-107: P56a proves the design with s3 first). -- **Territory:** `terraform/` (platform VPC, D-105), `modules/l1/*/terraform/` (per-module terraform subdirs — the engine binding), `modules/l1/*/interface.json` (defaults move from adapter to interface inputs), `modules/registry.json` (terraform_dir field), `modules/l2/microservice/composition.json` (drop the vpc child, D-105), `modules/STANDARDS.md` §8 (rewrite the adapter extension pattern → per-module terraform subdir pattern). - -### general (lead-developer + backend-engineer pipeline work) -- **Domain:** coordination + pipelines -- **Active:** true -- **Phase-specific:** false -- **Reason:** Owns the pipeline-driven testing (D-102/D-103/D-104) and the terraform lifecycle modes (D-101). The modules-lifecycle pipeline (Gitea + GitHub, byte-identical) matrix-runs each L1 module's `examples/{simple,complex}.yml` contracts through apply→modify→destroy against live AWS. `run_platform.sh` gains `--apply` and `--destroy` modes; Python never runs terraform. `verify_deploy_microservice.py` is deleted (D-101). Co-authoring expected on the `run_platform.sh` boundary (backend-engineer rewrites the adapter that `run_platform.sh` invokes). -- **Territory:** `pipelines/modules-lifecycle.yml`, `.gitea/workflows/modules-lifecycle.yml` + `.github/workflows/modules-lifecycle.yml` (byte-identical, D-102), `scripts/run_platform.sh` (`--apply`/`--destroy` modes, D-101), `scripts/run_primitive_plan.sh` (if extended for lifecycle), `scripts/run_pattern_plan.sh` (if extended), `pipelines/README.md` (document the new pipeline), `schemas/deploy-pipeline.schema.json` (if the lifecycle stages are added to the contract). - -## Deactivated personas - -### lambda-engineer (custom, v1.9 — deactivated for v1.11) -- **Domain:** serverless -- **Active:** false -- **Phase-specific:** false -- **Reason:** No per-module Python this milestone (D-102: testing is pipeline-driven, not pytest). The v1.9 Lambda (`core/lambda/contract_ingestor.py`) and the `terraform/platform/main.tf` Lambda/DynamoDB/KMS/Secrets definitions persist from v1.9 but are not touched in v1.11. The `acdl-sod-halt` SNS topic and the attestation matrix are out of scope. Removed from the roster for v1.11; reactivates if a future milestone touches the Lambda. - -### platform-engineer (custom, v1.9 — folded into data-engineer for v1.11) -- **Domain:** infra -- **Active:** false -- **Phase-specific:** false -- **Reason:** The v1.11 scope (D-097..D-107) is terraform module authoring + adapter rewrite + pipelines — not the v1.9-era L1/L2 IR-typed module authoring or the AWS OIDC bootstrap. The platform-engineer's v1.9 territory (`adapters/terraform/**`, `modules/**`, `terraform/**`) is split: the adapter goes to backend-engineer (rewrite), the per-module terraform subdirs + platform VPC go to data-engineer (the heaviest v1.11 work). Folded into data-engineer for v1.11; reactivates if a future milestone does IR-shaped module authoring or OIDC bootstrap work. - -### security-engineer (custom, v1.9 — deactivated for v1.11) -- **Domain:** security -- **Active:** false -- **Phase-specific:** false -- **Reason:** The v1.11 scope does not touch Wiz/Kyverno/Checkov adapters, the HITL matrix, separation-of-duties, or the audit ledger. The security-engineer's v1.9 territory persists but is not touched. Removed from the roster for v1.11; reactivates if a future milestone touches security adapters or HITL gates. - -### frontend-engineer -- **Domain:** frontend -- **Active:** false -- **Phase-specific:** false -- **Reason:** The evidence timeline UI (`evidence-ui/**`) is unchanged from v1.0 and not touched in v1.11. Removed from the active roster; reactivates if a future milestone touches the timeline UI. - -### data-engineer (v1.9 — was deactivated, reactivated for v1.11) -- **Domain:** data -- **Active:** true (reactivated) -- **Phase-specific:** false -- **Reason:** See the active `data-engineer` entry above. The v1.9 deactivation rationale ("No ORM/persistence framework") no longer applies — v1.11's data-engineer owns terraform module authoring, not a data persistence layer. - -### infra-stub-engineer (custom, v1.0 only) -- **Domain:** backend -- **Active:** false -- **Reason:** Owned L1 stub modules in the v1.0 demo. The demo is archived to `demo/`; real L1 modules are owned by data-engineer (v1.11). Not reactivated. - -## Phase-specific overrides - -| Phase | Personas active | Notes | -|-------|------------------|-------| -| 56a adapter-rewrite-and-s3-reference-module | data-engineer (lead: s3 reference terraform module — proves the design), backend-engineer (lead: stateless adapter rewrite — emits module blocks for s3), general (run_platform.sh --apply/--destroy skeleton) | security/lambda/frontend idle | -| 56b remaining-11-l1-module-terraform-subdirs | data-engineer (lead: author 11 L1 module terraform subdirs — vpc, ecs-cluster, ecs-service, iam-role, alb, ecr, cloudfront, waf, rds, kms-key, uptime), backend-engineer (adapter: confirm each module round-trips through the assembler), general (modules-lifecycle pipeline wiring) | security/lambda/frontend idle | -| (modules-lifecycle pipeline) | general (lead: byte-identical Gitea+GitHub workflow + matrix apply→modify→destroy), data-engineer (examples/{simple,complex}.yml contracts as the modify variants), backend-engineer (adapter confirms the lifecycle cells resolve) | security/lambda/frontend idle | -| (platform VPC + composition drop) | data-engineer (lead: terraform/platform VPC + microservice composition drops vpc child, D-105), backend-engineer (resolver: env-aware state keys, D-106) | general/security/lambda/frontend idle | -| verify | lead-developer (lead: 4-layer verification), all active personas (review their territory) | — | -| review-audit-complete | lead-developer (lead: review + audit + milestone completion), all active personas (review participation) | — | - -## Domain priority (used by TaskDecomposer) - -`data → backend → general` - -Rationale: in v1.11, the terraform foundation (per-module `terraform/` -subdirs + platform VPC) is the binding constraint — the stateless adapter -cannot be written until the reference s3 module exists (D-107: P56a -proves the design with s3 first). Backend (adapter/resolver) follows once -the module shape is proven. General (pipelines/workflows) wires the -lifecycle modes last, once the adapter + modules produce valid terraform. - -## Conflict resolutions (lead-developer arbitration) - -- `backend-engineer` vs `data-engineer` over `modules/l1/*/interface.json`: - data-engineer owns the interface defaults (defaults move from the - adapter to the interface inputs, D-100); backend-engineer owns the - adapter that reads them. Co-authoring is expected; conflict goes to - lead-developer. -- `backend-engineer` vs `general` over `scripts/run_platform.sh`: - backend-engineer rewrites the adapter that `run_platform.sh` invokes; - general adds the `--apply`/`--destroy` modes. The interface (the CLI - flags + the adapter invocation) is co-authored; conflicts go to - lead-developer. -- `data-engineer` vs `general` over `modules/l1/*/examples/`: - data-engineer owns the example contracts (the modify variants, - D-103); general owns the pipeline that matrix-runs them. Co-authoring - is expected; conflicts go to lead-developer. -- `lead-developer` vs any: lead-developer owns `.ciagent/**` + `docs/**` - meta + verification scripts + `modules/STANDARDS.md` §8 rewrite; persona - engineers do not edit CIAgent metadata or the vision/architecture - source docs. - -## Territory enforcement mode - -`warn` — config.json has no `personas.territory_enforcement` field, so the -default per execute.md is `warn`. Cross-territory edits are logged in the -commit message but do not fail the task. v1.11's scope means co-authoring -across territories is likely (e.g. backend + general on the adapter + -`run_platform.sh` boundary; data + general on the examples + pipeline -boundary); `warn` keeps it frictionless. ---- - -## v1.15 Persona Addendum — Nova Rebrand (2026-07-30) - -**Milestone:** v1.15-Nova. The roster carries forward from v1.11/v1.14 -unchanged — the rebrand touches existing territories, no new domains. -**frontend-engineer** remains deactivated (no UI; decks are markdown = -lead-developer territory). No **security-engineer** persona is activated -— the ABAC session-policy + tag-key migration (REQ-162) is data-engineer -territory (terraform IAM) with lead-developer review. - -### v1.15 territory assignments - -| Phase | Lead | Contributors | Territory | -|-------|------|---------------|-----------| -| P1 docs-decks-prose | lead-developer | — | `README.md`, `docs/**`, `.ciagent/*.md`, deck `.md`/`-marp.md`/`-talking-points.md`/`.html`, `docs/presentations/assets/mmd/*.mmd` (+ PNG re-export), `pyproject.toml`, `schemas/*.schema.json` `$id` (D-110), `docs/NOVA_MIGRATION.md`, `.github/workflows/release.yml` title, `modules/STANDARDS.md` | -| P2 code-envvars-consumer-path | backend-engineer | lead-developer (docs/runbook) | `core/env.py` (NEW dual-read helper, D-108), `core/*.py` (call-site migration), `scripts/*.py` + `*.sh`, `adapters/**`, `tests/**`, `.gitea/workflows/**` + `.github/workflows/**`, `.env` + `.env.secrets` (key rename), `schemas/tagging-standard.json`, `adapters/terraform/policy/custom_rules/acdl_tagging.py` → `nova_tagging.py` (D-109: warn mode) | -| P3 ssm-tagkeys | data-engineer | backend-engineer (readers) | `core/output_publisher.py` (SSM path `/nova/`), `core/contract_resolver.py` (SSM reads), `scripts/migrate_ssm_paths.py` (NEW), `terraform/**` (tag keys `nova:*`), `adapters/terraform/policy/custom_rules/nova_tagging.py` (D-109: hard mode), ABAC session-policy terraform | -| P4 aws-resource-migration | data-engineer | lead-developer (runbook) | `terraform/platform/main.tf`, `terraform/microservice/main.tf`, `terraform/ci-vpc/main.tf`, `terraform/bootstrap/**`, `modules/l1/alb/instance.json`, `scripts/migrate_dynamodb_data.py` (NEW), `docs/NOVA_AWS_MIGRATION.md` (NEW runbook), `core/lambda/contract_ingestor.py` (default table names → `nova-*`, D-111) | -| P5 final-review-ship | lead-developer | all active (review) | `.ciagent/**` (REQUIREMENTS/ROADMAP/PROJECT complete), `core/env.py` (remove dual-read fallback), `nova_tagging.py` (hard-fail `acdl:*`), review + audit | - -### v1.15 domain priority - -`lead → backend → data` (inverted from v1.11) - -Rationale: the rebrand is docs/prose-first (P1 establishes the -vocabulary, no runtime impact), then code/env-vars/consumer-path (P2), -then SSM/tag-keys (P3), then the heavy terraform/AWS migration (P4). -Lead-developer owns the docs + runbooks + verification + final ship; -backend-engineer owns the dual-read helper + call-site migration + -contract resolver; data-engineer owns the terraform resource/tag/SSM -migration (the heaviest terraform territory). Co-authoring expected at: -`core/env.py` + `core/*.py` boundary (backend + lead on the helper -design), `nova_tagging.py` + `schemas/tagging-standard.json` boundary -(backend authors the rule, data-engineer owns the tag-key schema), -`core/output_publisher.py` SSM path + `terraform` outputs boundary -(backend writes the reader, data-engineer owns the terraform that -produces the outputs). - -### v1.15 verification toolchain (unchanged from v1.14) - -``` -typecheck: terraform validate && python3 -m py_compile core/**/*.py adapters/**/*.py -test: bash scripts/run_regression.sh # 16-capability gate -build: bash scripts/run_ci.sh # full local CI reproduction -``` - -The regression gate (CAP-001..CAP-016) must stay **16/16 Verified** -throughout the rebrand — the rebrand must not regress any capability. -P2/P3/P4 update test fixtures that reference `ACDL`/`acdl` so the gate -stays green. - -## v1.16 Persona Addendum — Nova Simplification (2026-07-30) - -**Milestone:** v1.16-Nova-Simplification (NFR). Roster carries forward -unchanged — NFR work touches existing territories, no new domains. The -onboarding request-path (P18–P20) is backend-engineer (Lambda action + -onboarding.py) + data-engineer (cross-account Terraform) territory. -**frontend-engineer** remains deactivated. No **security-engineer** -persona — the ingestor defense-in-depth (P10) is backend-engineer with -lead-developer review; IAM/ABAC (P20) is data-engineer territory. - -### v1.16 territory assignments - -| Phase | Lead | Contributors | Territory | -|-------|------|---------------|-----------| -| P1 state-bucket+kyverno fix | backend-engineer | data-engineer (kyverno policy) | `adapters/terraform/adapter.py:117`, `adapters/kyverno/policies/require-resource-labels.yml` | -| P2 user-facing brand sweep | lead-developer | backend-engineer | `core/environment_check.py`, `core/lambda/contract_ingestor.py`, `scripts/post_stage_comment.sh`, `scripts/run_ci.sh`, module docstrings, `adapters/README.md` | -| P3 dead-code+stale-prefix | lead-developer | — | `scripts/run_platform.sh`, `core/local_emulators.py`, `core/regression_verify.py`, lifecycle scripts | -| P4 migrate-ssm except | backend-engineer | — | `scripts/migrate_ssm_paths.py` | -| P5 regression-verify dedup | backend-engineer | — | `core/regression_verify.py` | -| P6 run-platform deadcode+hitl-fn | lead-developer | — | `scripts/run_platform.sh` | -| P7 contract-resolver envloader+kind | backend-engineer | — | `core/contract_resolver.py`, `modules/registry.json` | -| P8 workflow generator | lead-developer | backend-engineer (test) | `scripts/sync_workflows.py` (NEW), `tests/test_pipeline_contract.py`, `.gitea/workflows/**`, `.github/workflows/**` | -| P9 run-platform split | lead-developer | — | `scripts/run_platform.sh`, `scripts/run_decommission.sh` (NEW), `scripts/run_uptime.sh` (NEW) | -| P10 ingestor defense-in-depth | backend-engineer | lead-developer (review) | `core/lambda/contract_ingestor.py`, `core/environments/` | -| P11 ingestor payload validation | backend-engineer | — | `core/lambda/contract_ingestor.py` | -| P12 split contract-resolver | backend-engineer | — | `core/contract_resolver.py` → `core/contract_resolve.py` + `core/decommission_transform.py` + `core/contract_resolver_cli.py` | -| P13 split regression-verify | backend-engineer | — | `core/regression_verify.py` → split modules | -| P14 schema-driven outputs+cache | backend-engineer | data-engineer (interface.json) | `core/output_publisher.py`, `core/contract_resolver.py`, `modules/l1/*/interface.json` | -| P15 run-platform --help+flags | lead-developer | — | `scripts/run_platform.sh`, `README.md` | -| P16 workflows README catalog | lead-developer | — | `.github/workflows/README.md` (NEW) | -| P17 getting-started consolidation | lead-developer | — | `README.md` | -| P18 onboarding schema+lambda | backend-engineer | lead-developer (schema) | `schemas/onboarding.schema.json` (NEW), `core/lambda/contract_ingestor.py` | -| P19 onboarding envfile autogen | backend-engineer | lead-developer (docs) | `core/onboarding.py` (NEW), `core/environment_check.py`, `core/environments/README.md` | -| P20 cross-account role offline | data-engineer | backend-engineer (ABAC) | `terraform/onboarding/` (NEW), `terraform/platform/main.tf` | -| P21 final-review-ship | lead-developer | all active (review) | `.ciagent/**`, review + audit + ship | - -### v1.16 domain priority - -`backend → lead → data` (the simplification + security + ingestor work -is backend-heavy; lead-developer owns docs/DX/splits; data-engineer owns -the P20 cross-account Terraform only). - -### v1.16 verification toolchain - -``` -typecheck: terraform validate && python3 -m py_compile core/**/*.py adapters/**/*.py -test: bash scripts/run_regression.sh # 22-capability gate (D-118: P9 + P21) -build: bash scripts/run_ci.sh # full local CI reproduction -``` - -The regression gate (22 capabilities) must stay **22/22 Verified** -throughout v1.16 — simplification must not regress any capability -(D-118). P9 (end of Wave 2) and P21 (milestone complete) run the gate; -P14 (end of Wave 3) is an offline mid-milestone checkpoint. - ---- - -# v1.17 Persona Roster — Strategic Direction, Leadership Metrics & Unified Story - -> v1.17 adds a telemetry/observability layer (P1–P3), a metrics catalog -> + NORTH_STAR integration (P4), a unified narrative deck (P5), a -> regression capability (P6), and a final review/ship (P7). Three -> active personas; frontend-engineer stays deactivated (no Nova web UI -> — dashboards are PowerBI, not a Nova-built frontend). - -## Active personas - -### lead-developer -- **Domain:** coordination + deck narrative -- **Active:** true -- **Phase-specific:** false -- **Reason:** Owns CIAgent metadata, the NORTH_STAR.md authoring - process (P0), the milestone decomposition, the unified narrative deck - co-authoring (P5 — the deck is markdown, which is lead-developer - territory per the established convention), and the final review/ship - (P7). Arbitrates persona conflicts (e.g., backend vs data on the - emitter/store boundary). -- **Territory:** `.ciagent/NORTH_STAR.md`, `.ciagent/PROJECT.md`, - `.ciagent/REQUIREMENTS.md`, `.ciagent/PLAN.md`, `.ciagent/RESEARCH.md`, - `.ciagent/ARCHITECTURE.md`, `docs/presentations/nova-no-humans-platform.md` - (NEW — unified deck source of truth), `docs/presentations/nova-no-humans-platform-marp.md`, - `docs/presentations/nova-no-humans-platform-talking-points.md`, - `docs/METRICS.md`, `docs/metrics/*.md` (per-KPI definition docs). - -### backend-engineer -- **Domain:** backend (event emitters + instrumentation) -- **Active:** true -- **Phase-specific:** false -- **Reason:** Owns the event emitters (P1): the CloudEvents envelope, - the per-run manifest writer, the `outbox_writer.py` extension to the - SQLite Decision Ledger, the Infracost post-processor, the - `hitl_gates.py` attestation event emission, the `confidence_signal.py` - decision event emission, the `checkov_adapter.py` policy event - emission, and the pytest `--junitxml` addopts change. Also owns the - `regression_verify.py` CAP-023/024 additions (P6). The emitter work - is the bridge between existing Nova components and the new metrics - layer — it touches the code paths that already exist. -- **Territory:** `core/metrics/event_envelope.py` (NEW), - `core/metrics/run_manifest.py` (NEW), - `core/metrics/infracost_adapter.py` (NEW), - `core/metrics/decision_ledger.py` (NEW — extends outbox_writer), - `core/outbox_writer.py` (extend to SQLite), - `core/hitl_gates.py` (emit attestation.recorded), - `core/confidence_signal.py` (emit ai.decision.made), - `adapters/terraform/policy/checkov_adapter.py` (emit policy.evaluated), - `scripts/run_platform.sh` (invoke manifest writer + Infracost), - `core/regression_verify.py` (CAP-023/024), - `pyproject.toml` (addopts --junitxml), - `tests/test_metrics_emitters.py` (NEW), - `tests/test_decision_ledger.py` (NEW). - -### data-engineer -- **Domain:** data (schema, SQLite store, PowerBI export) -- **Active:** true -- **Phase-specific:** false -- **Reason:** Reactivated with a new territory for v1.17: the metrics - collector (P2) and the PowerBI export (P3). Owns the schema design - (metrics_*.schema.json), the SQLite cold store (nova_metrics.db), the - fact/dimension table design, the 8 deferred placeholder views, and - the CSV/JSON export. The data-engineer's schema-first constraint - applies: all event types and fact/dim tables have JSON Schema - definitions before any code is written. The collector reads files + - events → SQLite; the export reads SQLite → CSV/JSON. This is the - heaviest data-territory work since v1.11's terraform modules. -- **Territory:** `core/metrics/collector.py` (NEW), - `core/metrics/powerbi_export.py` (NEW), - `schemas/metrics_*.schema.json` (NEW — event + fact/dim schemas), - `metrics/nova_metrics.db` (NEW — SQLite cold store), - `metrics/powerbi/` (NEW — CSV/JSON export dir), - `docs/METRICS_VIEWS.md` (NEW — schema doc for PowerBI views), - `tests/test_metrics_collector.py` (NEW), - `tests/test_powerbi_export.py` (NEW). +- **Frameworks:** ["jsonschema", "dynamodb (item shape)"] +- **Constraints:** ["schema-first", "superset-gate NOT duplicate (PROJECT.md hard constraint)", "W3.E per-env mandatory table is the source of truth"] +- **Territory:** + - `schemas/**` (REQ-217 — `submission-readiness.schema.json` is the new schema; existing schemas untouched) + - `core/lambda/contract_ingestor.py` (the `--check-readiness` subcommand wiring, D-133 — the validator is in `core/submission_readiness.py` but the ingestor dispatches to it; co-owned with backend-engineer) +- **Reason:** Owns the submission-readiness JSON Schema (REQ-217) — it + is a schema artifact, data-engineer territory. The schema is a + *superset gate above* `contract.schema.json`, not a duplicate (it + references contract fields, does not redefine them). The + per-env-mandatory table comes from W3.E (the locked decision). The + ingestor wiring is co-owned with backend-engineer (the dispatch point + is backend; the schema it validates against is data). +- **Phase-specific flag:** none (active for P3 schema + ingestor wiring). ## Deactivated personas ### frontend-engineer -- **Domain:** frontend - **Active:** false -- **Phase-specific:** false -- **Reason:** v1.17 has no Nova web UI. The leadership dashboards are - PowerBI (an external tool that ingests CSV/JSON files), not a - Nova-built frontend. The decks are markdown (lead-developer - territory). frontend-engineer stays deactivated, consistent with - v1.11–v1.16. Reactivates if a future milestone builds a Nova web UI. +- **Domain:** frontend +- **Frameworks:** ["react", "next.js"] (inert — no territory) +- **Constraints:** ["component-first", "server-components", "minimal-client-js"] (inert) +- **Territory:** [] (no territory in v1.18) +- **Reason:** v1.18 has no frontend; decks are markdown (lead-developer + territory); deactivated per PERSONAS.md v1.17 precedent. v1.18's + observability stays PowerBI / external (Out of Scope: "A Nova-built + frontend / dashboard"). The MCP server exposes tools to an AI agent, + not a web UI. No reactivation trigger in this milestone. -### lambda-engineer, platform-engineer, security-engineer -- **Active:** false (carried forward from v1.11) -- **Reason:** v1.17 does not touch the Lambda (beyond emitting events - from the existing hitl_gates/attestation_matrix), does not do IR- - shaped module authoring, and does not touch security adapters beyond - emitting policy.evaluated events. The existing components are - instrumented, not rewritten. +## Roster decisions -## v1.17 phase assignment +### D-143 (0.90): Fold mcp-engineer into backend-engineer +The MCP plugin-registry (D-140: `plugins/.py register(mcp)`) is a +backend code pattern — Python modules, type hints, stdio transport, +urllib for the Gitea asset API. It shares nothing with the data domain +(schemas/DynamoDB) and is not a new engineering discipline. Creating a +separate `mcp-engineer` persona would fragment ownership of the server + +its tests + the render/attach scripts (all backend). **Decision:** fold +into backend-engineer. backend-engineer's `frameworks` list gains +`mcp (Python SDK v2)`. Confidence 0.90 — the only counter-argument is +that MCP is a distinct protocol skill, but the SDK v2 API surface +(`@mcp.tool()` + type hints) is small and well within backend-engineer's +range (it's the same Pydantic/FastAPI-style pattern the persona already +knows). -| Phase | Primary persona | Supporting | Territory | -|-------|----------------|------------|-----------| -| P0 pre-execution | lead-developer | — | `.ciagent/NORTH_STAR.md`, `PROJECT.md`, `REQUIREMENTS.md`, `RESEARCH.md`, `ARCHITECTURE.md`, `PERSONAS.md`, `PLAN.md` | -| P1 event-emitters | backend-engineer | data-engineer (schemas) | `core/metrics/event_envelope.py`, `run_manifest.py`, `decision_ledger.py`, `infracost_adapter.py`, `outbox_writer.py`, `hitl_gates.py`, `confidence_signal.py`, `checkov_adapter.py`, `run_platform.sh`, `pyproject.toml` | -| P2 metrics-collector | data-engineer | backend-engineer (event formats) | `core/metrics/collector.py`, `schemas/metrics_*.schema.json`, `metrics/nova_metrics.db` | -| P3 powerbi-export | data-engineer | — | `core/metrics/powerbi_export.py`, `metrics/powerbi/`, `docs/METRICS_VIEWS.md` | -| P4 metrics-catalog + north-star-integration | lead-developer | data-engineer (metric definitions) | `docs/METRICS.md`, `docs/metrics/*.md`, `PROJECT.md`, `ARCHITECTURE.md`, `config.json` | -| P5 deck-rebuild | lead-developer | — | `docs/presentations/nova-no-humans-platform*.md`, retire old decks | -| P6 regression-capability | backend-engineer | data-engineer (CAP-023 schema) | `core/regression_verify.py` (CAP-023, CAP-024) | -| P7 final-review-ship | lead-developer | all active (review) | `.ciagent/**`, review + audit + ship | +### Territory-overlap resolution (co-ownership) -## v1.17 domain priority - -`backend → data → lead` (the emitter work in P1 is the foundation; -data-engineer's collector + export in P2–P3 depends on P1's event -formats; lead-developer's catalog + deck in P4–P5 depends on the -metrics being grounded). - -## v1.17 verification toolchain - -``` -typecheck: terraform validate && python3 -m py_compile core/**/*.py adapters/**/*.py -test: bash scripts/run_regression.sh # 22-capability gate + CAP-023/024 (v1.17) -build: bash scripts/run_ci.sh # full local CI reproduction -``` - -The regression gate (22 capabilities + CAP-023 metrics collector + -CAP-024 deck structure) must pass at P6 and P7. CAP-009 (offline pytest -suite) must remain Verified after the `--junitxml` addopts change -(assumption A5). +| Path | Primary | Co-owner | Why | +|------|---------|----------|-----| +| `docs/submission-readiness.md` | lead-developer (narrative + examples) | backend-engineer (reason-code catalog, REQ-218 codes) | The doc is citizen-developer-facing copy (lead) but the reason-code catalog (MISSING_TAGS, ENV_MISSING_MANDATORY, AGENTIC_MISSING_INTENT, MISSING_APP_SOURCE, POLICY_PRECONDITION_MISSING) is backend (it mirrors the validator's return codes). | +| `core/lambda/contract_ingestor.py` | backend-engineer (dispatch wiring) | data-engineer (the schema it validates against) | D-133 places the `--check-readiness` subcommand on the ingestor (backend dispatch), but the readiness schema it loads is data-engineer territory. | +| `schemas/submission-readiness.schema.json` | data-engineer (schema artifact) | backend-engineer (the validator must match it) | The schema is data-engineer's; the validator (REQ-218) is backend-engineer's and must stay in sync with it. | \ No newline at end of file diff --git a/.ciagent/PLAN.md b/.ciagent/PLAN.md index efe65e7..f799018 100644 --- a/.ciagent/PLAN.md +++ b/.ciagent/PLAN.md @@ -1,1182 +1,948 @@ ---- -phase: P0 -name: pre-execution -milestone: v1.17 -requirements: [REQ-185, REQ-186, REQ-187, REQ-188, REQ-189, REQ-190, REQ-191, REQ-192, REQ-193, REQ-194, REQ-195, REQ-196, REQ-197, REQ-198, REQ-199, REQ-200, REQ-201, REQ-202, REQ-203, REQ-204, REQ-205, REQ-206, REQ-207, REQ-208, REQ-209, REQ-210, REQ-211, REQ-212, REQ-213] -wave: 0 -depends_on: [] ---- +# Nova — Phase Plan v1.18 (Citizen Developer & Production-Grade Guidance) -# v1.17 — Strategic Direction, Leadership Metrics & Unified Story (Plan) +> **Milestone:** v1.18 — Citizen Developer & Production-Grade Guidance +> **Branch:** `milestone/v1.18-citizen-developer-guidance` +> **Tag line:** `v1.17.x` patch line — `v1.17.0` (P0) → `v1.17.1..v1.17.6` +> (P1–P6) → `v1.17.7` (P7 final = milestone release). Previous minor per +> branch-strategy (v1.17 shipped on the v1.16.x line; v1.18 is a Feature +> milestone → tags run on the previous minor's patch line = v1.17.x). +> **Phase count:** 8 (P0 pre-execution [DONE] + 6 execution + 1 final). +> **Source of truth for requirements:** `.ciagent/REQUIREMENTS.md` §v1.18 +> (REQ-214..228, 15 requirements). +> **Source of truth for decisions:** `.ciagent/PROJECT.md` §"Key Decisions +> (v1.18)" (D-133..D-142). +> **Source of truth for research:** `.ciagent/RESEARCH.md` §v1.18 (Atelier +> skill mapping, MCP SDK skeleton, submission-readiness gap analysis, Marp +> PPTX fidelity). -**Milestone:** v1.17 — Strategic Direction, Leadership Metrics & Unified Story -**Type:** Feature (P1–P3 feat; P4 docs; P5 docs+test; P6 test; P7 review+audit+ship; -P8 final). Progressive patches; the final phase's patch IS the milestone -release. Tags run on the v1.16.x line: `v1.16.0` (P0) → `v1.16.1..v1.16.7` -(P1–P7) → `v1.16.8` (P8 final = milestone release). -**Branch:** `milestone/v1.17-strategic-metrics-deck` (branched off the v1.16 -complete merge). Execution phases branch `phase/NN-*` → merge to milestone -branch → tag patch on the v1.16.x line. -**Tags:** `metrics`, `telemetry`, `decision-ledger`, `powerbi`, `deck`, -`north-star`, `no-humans-thesis`, `regression-capability` -**Decisions (locked, D-120..D-132 — do NOT re-open):** -D-120 Nova-native + Infracost, drift deferred · D-121 Decision Ledger = -outbox_writer → SQLite hash-chain · D-122 AI decision = confidence_signal + -HITL gate · D-123 8 deferred metrics ship as empty placeholder views · -D-125 Hybrid events/files · D-126 Cold-only SQLite · D-127 Per-KPI -definition-of-success docs · D-128 metrics/ at repo root · D-129 PowerBI = -CSV/JSON folder connector · D-130 Deck arc Problem→Vision→How→Proof→Roadmap, -both old decks retired · D-131 MTTR = platform-run only · D-132 Attestation -instrumentation = emit attestation.recorded events. +## Wave Ordering -**Objective (three pillars):** -- **(A) Strategic Direction** — encode the PO's strategic direction in a - durable `NORTH_STAR.md` read by CIAgent in every future `/ci-run`. -- **(B) Leadership Metrics + PowerBI** — instrument Nova to collect, - aggregate, and surface leadership-grade metrics that prove the "no-humans" - autonomous-infrastructure value proposition — grounded in signals Nova - actually emits, derived via documented formulas, or explicitly deferred - with a decision ID — flowing into PowerBI-ready views. -- **(C) Unified Narrative Deck** — merge the two existing decks into one - unified narrative deck with the "tell them x3" arc at deck + slide level, - per-slide benefit callouts, and fluid transitions. +All 6 execution phases are **sequenced** for this run (the repo uses a flat +`/ci-run` workflow — one phase at a time). The theoretical parallelism is +documented for future parallelization-enabled runs. -**Hard constraint:** DO NOT make anything up. Every metric carries a -`grounded` / `derived` / `deferred` status with a source file or decision -ID. Deferred metrics ship as empty PowerBI placeholder views with -documented schemas. +| Wave | Phases | Rationale | +|------|--------|-----------| +| Wave 1 | P1 | Theme restoration + render/attach scripts. P2/P6 depend on the render scripts existing. P6 depends on the S&P theme. Foundation — nothing else can ship a re-rendered deck without this. | +| Wave 2 | P2 | RACI + PDLC-scope docs + 2 deck slides → 20 slides. Depends on P1's `render_deck.sh` + `attach_release_asset.py` + restored S&P theme. Re-renders HTML+PPTX. | +| Wave 3 | P3, P4 (**parallelizable**) | P3 (submission-readiness schema+validator+doc+tests) and P4 (Atelier skills + index) have NO dependency on each other. P3 touches `schemas/`, `core/`, `tests/`, `docs/submission-readiness.md`. P4 touches `skills/`, `docs/skills.md`, `PROJECT.md` BA.A. Zero file overlap. In a parallelization-enabled run these two could execute concurrently. | +| Wave 4 | P5 | Atelier MCP server (plugin-registry, vendored Atelier, tests). Depends on P4's skill catalog being present (the MCP `atelier.list_domains` tool returns the Nova-relevance table that P4 codifies in `docs/skills.md`; the server reads the vendored Atelier snapshot that P5 itself vendors — but the skill provenance in `docs/skills.md` is the cross-reference). Strictly P5 vendors Atelier independently of P4; the dependency is narrative consistency (the MCP server's domain list should match the skills index). | +| Wave 5 | P6 | 3 new deck slides (scope/RACI/atelier) → 21 slides + README update + talking-points sync + HTML+PPTX re-render. Depends on P1 (theme + scripts), P2 (scope + RACI content + 2-slide precedent), P4 (atelier skills content for the Atelier slide), P5 (MCP server content for the Atelier slide). The deck slide that introduces Atelier must reflect what P4 + P5 actually shipped. | +| Wave 6 | P7 | Final review + audit + milestone ship (merge to main, tag v1.17.7, delete branches). | + +**Execution order for this run:** P1 → P2 → P3 → P4 → P5 → P6 → P7 +(sequential). The Wave 3 parallelism (P3‖P4) is noted for future runs but +NOT exercised here. --- -## Wave Overview +## Phase P1 — sp-theme-restoration (feat) -| Wave | Phases | Theme | Dependency rationale | -|------|--------|-------|----------------------| -| **Wave 1** | P1 | Event emitters — the foundation | Everything depends on events being emitted. P1 establishes the CloudEvents envelope, per-run manifests, Decision Ledger, Infracost adapter, and attestation/confidence/policy event emission. P2/P3/P4/P5 all consume P1's event formats. | -| **Wave 2** | P2, P3 | Collector + PowerBI export | P2 (collector) reads P1's events/files → SQLite cold store. P3 (export) reads P2's SQLite → CSV/JSON views. P2 + P3 can partially parallelize: P3's view schemas can be authored against P2's schemas before P2's collector code is complete, but P3's export code needs P2's SQLite to exist. | -| **Wave 3** | P4, P5 | Metrics catalog + deck rebuild | P4 (catalog + NORTH_STAR integration) depends on metrics being grounded (P2/P3 done). P5 (deck) depends on P4's `METRICS.md` for the Proof section's grounded citations. P4 + P5 can partially parallelize: P5's Problem/Vision/How acts don't need P4; P5's Proof act needs P4's catalog. | -| **Wave 4** | P6, P7 | Regression capability + final review/ship | P6 (CAP-023/024) depends on P2/P3 (collector) + P5 (deck) existing. P7 (review/audit/ship) depends on all prior phases. | -| **Final** | P8 | Milestone ship | Merge to main, tag `v1.16.8`, Gitea release, delete milestone branches. | +- **Wave:** 1 +- **Requirements covered:** REQ-214, REQ-228 +- **Persona assignment:** lead-developer (deck `style:` block restoration + + HTML re-render verification) + backend-engineer (`scripts/render_deck.sh` + + `scripts/attach_release_asset.py`) +- **Description:** Restore the S&P Global Energy Marp `style:` block (from + commit `ae0cb58`, v1.9.2 / P45) to the unified deck. The v1.17 P5 deck + rebuild lost the S&P visual identity when it consolidated the two decks + into one; the mermaid `sp-theme.json` survived but the Marp CSS theme was + replaced with a generic dark-navy theme. Create the deck-automation + scripts (`render_deck.sh` + `attach_release_asset.py`) that become the + reusable render+commit+attach pipeline for P2 and P6. Re-render HTML. + Commit the PPTX binary. Attach to the phase's Gitea release. -**Dependency chain (critical path):** -P1 → P2 → P3 → P4 → P5(Proof) → P6 → P7 → P8 +### Tasks -**Parallelization opportunities:** -- P2 schemas + P3 view schemas can be authored concurrently (Wave 2 entry). -- P4 `docs/metrics/*.md` per-KPI docs + P5 Problem/Vision/How acts can be - authored concurrently (Wave 3 entry); P5 Proof act waits for P4 `METRICS.md`. -- P6 CAP-023 (collector) test can be drafted while P5 finishes (the test - needs P2's collector to exist, which it does by Wave 4). +1. **Edit `docs/presentations/nova-no-humans-platform-marp.md`** — replace + the current `style: |` block (lines 8–15, the generic dark-navy theme: + `#1a1a2e` / `#16213e`) with the S&P Global Energy `style:` block from + commit `ae0cb58` (`docs/presentations/how-the-platform-works-marp.md` + frontmatter). The restored block must contain: + - `section { font-family: "Akkurat Pro", "Helvetica Neue", "Arial", sans-serif; font-size: 22px; color: #1B1B1B; }` + - `h1 { color: #D6002A; font-size: 34px; margin-bottom: 0.3em; }` + - `h2 { color: #D6002A; font-size: 26px; margin-bottom: 0.2em; }` + - `section.title { background: #1B1B1B; color: #fff; border-top: 8px solid #D6002A; }` + - `section.title h1 { color: #fff; }` + - `table { font-size: 18px; width: 100%; }` + - `th { background: #F0F0F0; }` + - `blockquote { border-left: 4px solid #D6002A; color: #2E2E2E; font-size: 20px; }` + - `img { display: block; margin: 0 auto; max-height: 320px; }` + - `.badge { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 14px; font-weight: 600; }` + - `.today { background: #c6f6d5; color: #22543d; }` + - `.planned { background: #fef3c7; color: #78350f; }` + - Preserve the current Nova header text (`Nova — The No-Humans + Infrastructure Platform`) and the `footer: 'Act %{page}/5 — v1.17'` + line — the rebrand is NOT touched (REQ-214: "the current Nova + header/footer text is preserved"). Only the visual theme (colors + + font + accent bar) is restored. +2. **Create `scripts/render_deck.sh`** (executable, `set -euo pipefail`) — + renders HTML + PPTX from a Marp deck markdown file. Usage: + `render_deck.sh `. Implementation per RESEARCH §4.1: + - Reads the deck path from `$1` (required; fails with usage message if + absent). + - Derives the output basename (strip `-marp.md` suffix → bare name; + e.g. `nova-no-humans-platform-marp.md` → `nova-no-humans-platform`). + - Output paths: `.html` and `.pptx` in the same + directory as the input deck. + - HTML render: `npx --yes @marp-team/marp-cli@latest --allow-local-files + -o .html` (self-contained HTML, base64-embedded + images). + - PPTX render: `CHROME_PATH= npx --yes + @marp-team/marp-cli@latest --allow-local-files -o + .pptx` (standard image-based PPTX, NOT `--pptx-editable` + — per RESEARCH §4.1 the inline `style:` CSS survives the + rasterization path). The `CHROME_PATH` is resolved from + `~/.cache/ms-playwright/chromium-*/chrome-linux64/chrome` (the + existing path documented in `docs/presentations/README.md` line 96). + - Exit 0 on success; non-zero on render failure (the `set -e` propagates). + - Prints `rendered: ` and `rendered: `. +3. **Create `scripts/attach_release_asset.py`** (executable Python, + stdlib-only per RESEARCH §3.5) — uploads a file to a Gitea release via + the API. Usage: `attach_release_asset.py --tag --file + [--name ]`. Implementation per RESEARCH §3.5: + - Reads `NOVA_GITEA_TOKEN` from `.env.secrets` (same source as + `scripts/ship_phase.sh` line 35) — load via a small helper that reads + `.env.secrets` key=value lines. + - Resolves tag → release ID: `GET + https://git.cloudinit.dev/api/v1/repos/continuous-intelligence/acdl/releases/tags/{tag}` + with `Authorization: token ` → response JSON `id`. + - Uploads the asset: `POST + https://git.cloudinit.dev/api/v1/repos/continuous-intelligence/acdl/releases/{id}/assets` + with `multipart/form-data` (`name` = display filename, `attachment` + = file binary) + `Authorization: token `. + - Constructs the multipart body manually via `urllib` (stdlib-only, + per RESEARCH §3.5 — a ~30-line `multipart_encode(fields, files)` + helper with a generated boundary; no `requests` dependency). + - Prints `asset_id: release: file: ` on success. + - Exits non-zero on API error (HTTP non-2xx) with a clear message (not + a stack trace — C2 Clarity). +4. **Run `scripts/render_deck.sh + docs/presentations/nova-no-humans-platform-marp.md`** — regenerates + `nova-no-humans-platform.html` (committed) + creates + `nova-no-humans-platform.pptx` (committed, D-141 — no LFS). +5. **Commit** the updated deck markdown, the regenerated HTML, and the new + PPTX binary to the phase branch. +6. **Attach** the PPTX to the phase's Gitea release (after `ship_phase.sh` + creates the `v1.17.1` tag + release): `python3 + scripts/attach_release_asset.py --tag v1.17.1 --file + docs/presentations/nova-no-humans-platform.pptx`. +7. **Update `docs/presentations/README.md`** — document the new + `render_deck.sh` + `attach_release_asset.py` scripts in the deck-build + process section; note that PPTX is now a committed binary (D-141) + + attached to every phase's release (D-142). + +### Must-haves (verification gate) + +- [ ] `docs/presentations/nova-no-humans-platform-marp.md` frontmatter + `style:` block contains `#D6002A` (S&P red-core), `#1B1B1B` (grey-90), + `8px solid #D6002A` (top accent bar), `'Akkurat Pro'` (font). A grep + for `#D6002A` in the deck markdown returns ≥4 hits (h1, h2, + title-bg border, blockquote border). +- [ ] The Nova header (`Nova — The No-Humans Infrastructure Platform`) and + footer (`Act %{page}/5 — v1.17`) text are UNCHANGED (rebrand + preserved — REQ-214). +- [ ] `scripts/render_deck.sh` exists, is executable, and exits 0 when run + against the unified deck. +- [ ] `scripts/attach_release_asset.py` exists, is executable, and + `python3 -m py_compile scripts/attach_release_asset.py` succeeds. +- [ ] `docs/presentations/nova-no-humans-platform.html` is regenerated + (mtime newer than the deck markdown) and opens in a browser showing + the S&P red accent bar + dark title-slide background. +- [ ] `docs/presentations/nova-no-humans-platform.pptx` exists (binary, + committed, no LFS) and is attached to the `v1.17.1` Gitea release. +- [ ] `docs/presentations/README.md` documents the two new scripts. +- [ ] CAP-024 deck structure regression passes (the S&P theme restoration + must not break the 18-slide structure — slide count, x3 arc, + per-slide benefit callouts all preserved). + +### Ship tag + +`v1.17.1` --- -## Per-Phase Vertical-Slice Plans +## Phase P2 — pdlc-scope-raci (docs) -### Phase P1 — event-emitters (Wave 1, feat) +- **Wave:** 2 +- **Requirements covered:** REQ-215, REQ-216, REQ-228 +- **Persona assignment:** lead-developer (RACI matrix + PDLC-scope + statement in PROJECT.md + `docs/raci.md` + `docs/scope.md` + 2 deck + slides + HTML/PPTX re-render) +- **Description:** Promote Core Tenet #2 + Anti-Goal #1 from buried tenets + to a dedicated, unmissable scope statement: the PDLC is upstream of + Nova; Nova governs infra + delivery only; integration is through the + validated contract boundary. Author a three-role RACI matrix clarifying + who owns what across the citizen-developer → platform → + release-management boundary. Add 2 deck slides (scope + RACI) → 20 + slides. Re-render HTML + PPTX using P1's scripts; commit PPTX; attach to + release. -**Goal:** Instrument every Nova decision point to emit structured CloudEvents -1.0 events + persist ephemeral `$WORK/*.json` as durable artifacts + extend -`outbox_writer.py` into the SQLite Decision Ledger. After P1, the metrics -layer has all the raw signals it needs — no downstream phase invents new -signals. +### Tasks -**Requirements covered:** REQ-187, REQ-188, REQ-205 (emitter half), -REQ-206 (emitter half). +1. **Edit `PROJECT.md`** — add a new `## Scope: Nova is Downstream of PDLC` + subsection under `## Domain Boundaries` (after the existing + "Interface:" bullet). Content (per REQ-216): + - State that the PDLC (Product Development Lifecycle — product backlog, + code authorship, IDE) is upstream of Nova. + - State that Nova governs infra + delivery only. + - State that integration is through the validated contract boundary + (the contract is the only ingress; Nova does not penetrate upstream + product/SDLC). + - Promote Core Tenet #2 ("The Delivery Lifecycle is a Sovereign + Boundary") + Anti-Goal #1 ("Not an upstream development platform") + from buried tenets to this dedicated, unmissable statement. +2. **Edit `PROJECT.md`** — add a new `## RACI Matrix` section (after the + `## Scope: Nova is Downstream of PDLC` subsection, before `## Core + Tenets` or at the end of the Domain Boundaries cluster). Content (per + REQ-215, D-139): + - Three roles (columns): **Citizen Developer**, **Platform**, + **Release Management** (co-owned). + - Rows = work categories: Functional Requirements, User Acceptance + Testing, NFRs, Infrastructure, QA, Production Deploy, Release + Attestation. + - Cells = R/A/C/I per role per category. The assignment per REQ-215: + - **Citizen Developer:** Responsible for all Functional Requirements + + User Acceptance Testing (via their AI coding agent / upstream + agentic SDLC / upstream development platform — the source does not + matter as all are subject to the same compliance standards). + - **Platform:** Responsible for all NFRs + Infrastructure + QA + + Production deployments to cloud. + - **Release Management:** co-owned — QA + SRE attestations required + by the actual release, performed agentically but overseen & + triggered by the Citizen Developer. + - Render as a markdown table. + - Include the compliance-standard-equivalence note: regardless of the + source (AI agent, agentic SDLC, dev platform), the citizen + developer's output is subject to the same compliance standards. +3. **Create `docs/scope.md`** — citizen-developer-facing copy of the + PDLC-upstream scope statement. Cross-references PROJECT.md §Scope as + the source of truth. Plain-language prose (no CIAgent metadata + references — REQ-52 precedent). +4. **Create `docs/raci.md`** — citizen-developer-facing copy of the RACI + matrix. Renders the same table as PROJECT.md §RACI Matrix. Explains + the three roles in plain language. Cross-references PROJECT.md §RACI + Matrix as the source of truth. Includes the compliance-standard + equivalence note. +5. **Edit `docs/presentations/nova-no-humans-platform-marp.md`** — add 2 + new slides after the existing Slide 16 (Recap + Ask), before the + appendix slides: + - **Slide 19 — Scope: Downstream of PDLC.** States the PDLC is + upstream; Nova governs infra + delivery only; integration is + through the contract boundary. Benefit callout: "you now know + exactly where Nova's boundary is — infrastructure and delivery, not + product development." + - **Slide 20 — RACI: Who Owns What.** Renders the 3-role × 7-category + RACI table. Benefit callout: "you now know who is responsible for + what — citizen developer owns FRs + UAT, platform owns NFRs + infra + + deploy, release management is co-owned attestation." + - The 5-act arc (D-130) is preserved — these are append-only context + slides, not a new act (per D-134: "no act restructure"). + - Update the **Slide 1 — Arc Preview** text to reflect the 20-slide + count (change "18 slides" / "5-act arc" references if they cite a + count; the slide count is now 20 main + appendix). Update the footer + `Act %{page}/5 — v1.17` → `Act %{page}/5 — v1.18` (the deck now + reflects the v1.18 milestone content). +6. **Run `scripts/render_deck.sh + docs/presentations/nova-no-humans-platform-marp.md`** — regenerates + HTML + PPTX (S&P theme preserved — regression check vs P1). +7. **Commit** the updated PROJECT.md, `docs/scope.md`, `docs/raci.md`, + the updated deck markdown, the regenerated HTML, and the regenerated + PPTX binary. +8. **Attach** the PPTX to the `v1.17.2` Gitea release via + `scripts/attach_release_asset.py --tag v1.17.2 --file + docs/presentations/nova-no-humans-platform.pptx`. -**Primary persona:** backend-engineer. **Supporting:** data-engineer -(event schemas). +### Must-haves (verification gate) -**Tasks (vertical slices):** +- [ ] `PROJECT.md` has a `## Scope: Nova is Downstream of PDLC` section + under Domain Boundaries. +- [ ] `PROJECT.md` has a `## RACI Matrix` section with a 3-column + (Citizen Developer / Platform / Release Management) × 7-row table. +- [ ] `docs/scope.md` exists, is citizen-developer-facing (no `.ciagent/` + references), and cross-references PROJECT.md §Scope. +- [ ] `docs/raci.md` exists, is citizen-developer-facing, renders the + RACI table, and cross-references PROJECT.md §RACI Matrix. +- [ ] The deck has 20 main slides (Slide 19 = Scope, Slide 20 = RACI) + + the appendix slides. Slide 1 Arc Preview reflects 20 slides. +- [ ] `scripts/render_deck.sh` re-renders HTML + PPTX successfully; the + S&P theme is preserved (grep `#D6002A` in the deck markdown still + returns ≥4 hits — P1 regression check). +- [ ] `docs/presentations/nova-no-humans-platform.pptx` is committed + (binary) and attached to the `v1.17.2` Gitea release. +- [ ] CAP-024 deck structure regression passes (20 slides, x3 arc, + per-slide benefits on the 2 new slides). -1. **CloudEvents envelope + schemas** — `core/metrics/event_envelope.py` - defines the CloudEvents 1.0 envelope + `platform.*` semantic conventions - (specversion, id, source, type, time, subject, datacontenttype, platform - block, data). `schemas/metrics_event.schema.json` validates the envelope. - `schemas/metrics_run_manifest.schema.json` validates per-run manifests. - - *Acceptance:* `python -m jsonschema` validates a sample event against - the schema; `tests/test_metrics_emitters.py::test_envelope` passes. +### Ship tag -2. **Per-run manifest writer** — `core/metrics/run_manifest.py` emits - `nova.run.started`, `nova.run.completed`, `nova.run.failed` events with - (run_id, contractId, env, stages×durations, exit, confidence, HITL block - count). Writes `metrics/runs/.json`. `scripts/run_platform.sh` - invokes the writer at run start + run end. - - *Acceptance:* a `--check-only` run produces `metrics/runs/.json` - with a valid manifest; `test_run_manifest` passes. - -3. **Persist ephemeral `$WORK/*.json`** — `run_platform.sh` copies - `$WORK/pcr.json`, `signal.json`, `event.json`, `outbox_item.json`, - `stack.json` to `metrics/runs//` as durable artifacts (the - ephemeral `$WORK` copies remain for the running pipeline; the persisted - copies are the metrics source of truth). - - *Acceptance:* after a run, `metrics/runs//pcr.json` exists and - matches `$WORK/pcr.json`; a test asserts the copy. - -4. **pytest addopts** — `pyproject.toml` `addopts` gains - `--junitxml=metrics/test-results.xml --json-report --cov=core --cov=adapters - --cov-report=json:metrics/coverage.json`. CAP-009 (offline pytest suite - passes) must remain Verified (assumption A5 — additive flags). - - *Acceptance:* `bash scripts/run_ci.sh` exits 0; `metrics/test-results.xml` - + `metrics/coverage.json` exist; regression gate 22/22 (run at P6, but - P1 must not break any cap locally). - -5. **Infracost post-processor** — `core/metrics/infracost_adapter.py` runs - Infracost on `terraform show -json plan.tfplan` (offline, reads plan JSON, - no live AWS). Emits `nova.cost.estimated{delta_usd}`. Degrades gracefully - (omits the event, logs a warning) when Infracost CLI is absent (A6). - `run_platform.sh` invokes it after the plan stage. - - *Acceptance:* when Infracost is available, `metrics/runs//` - contains a `cost_estimate.json`; when absent, the run still exits 0; - `test_infracost_adapter` passes (mock the CLI). - -6. **Decision Ledger (SQLite hash-chain)** — `core/metrics/decision_ledger.py` - extends `outbox_writer.py` to emit to a SQLite append-only table - (`metrics/decision_ledger.db`) with a hash chain (`prev_hash` + own - `hash`, SHA-256). Emits `ai.decision.made` events (decision_id=run_id, - chosen_action=band outcome, confidence=score, alternatives=perInput - breakdown, human_override=HITL block) with outcome backfill from - `apply.completed`. Honors D-083 (no S3 Object Lock/JWS — local SQLite - hash-chain only). - - *Acceptance:* `metrics/decision_ledger.db` exists after a run; the - hash chain verifies (`verify-chain` returns 0 broken); `test_decision_ledger` - passes. - -7. **Attestation event emission** — `core/hitl_gates.py` emits - `attestation.recorded` events to the Decision Ledger on qa/prod/dr gates - (approver, env, concerns, result). D-132. (Dev skips — autonomous.) - - *Acceptance:* a mocked qa gate produces an `attestation.recorded` row - in the Decision Ledger; `test_attestation_event` passes. - -8. **Confidence decision event emission** — `core/confidence_signal.py` - emits `nova.confidence.computed` + `nova.ai.decision.made` events (D-122: - the "AI decision" is the confidence-gated policy engine, not an LLM). - - *Acceptance:* a confidence computation produces both events in - `metrics/events.jsonl`; `test_confidence_event` passes. - -9. **Policy event emission** — `adapters/terraform/policy/checkov_adapter.py` - emits `nova.policy.evaluated` events (rule count, pass/fail/skipped, - severity breakdown). - - *Acceptance:* a Checkov run produces a `nova.policy.evaluated` event; - `test_policy_event` passes. - -10. **Lifecycle success-rate emitter** — each lifecycle run writes - `metrics/lifecycle/-.json` (module, env, phase - apply/modify/destroy, result, duration_ms). REQ-205 emitter half. - - *Acceptance:* a mocked lifecycle run produces the JSON; the emitter - test passes. - -11. **Capability event emission** — `core/regression_verify.py` emits - `nova.capability.verified` events (capability ID, status, tier, duration). - - *Acceptance:* a regression run produces `nova.capability.verified` - events; `test_capability_event` passes. - -**Must-haves (phase ships only if ALL true):** -- `core/metrics/event_envelope.py`, `run_manifest.py`, - `infracost_adapter.py`, `decision_ledger.py` exist and are tested. -- `metrics/events.jsonl` is appended to on every run (CloudEvents 1.0 - envelope, valid against `schemas/metrics_event.schema.json`). -- `metrics/runs/.json` manifest exists after every run. -- `metrics/decision_ledger.db` exists with a verified hash chain. -- `outbox_writer.py` extended to write to the SQLite Decision Ledger. -- `hitl_gates.py` emits `attestation.recorded` (D-132). -- `confidence_signal.py` emits `nova.confidence.computed` + - `nova.ai.decision.made` (D-122). -- `checkov_adapter.py` emits `nova.policy.evaluated`. -- `pyproject.toml` addopts include `--junitxml` + `--json-report` + `--cov`. -- `bash scripts/run_ci.sh` exits 0. -- No existing capability regresses (22/22 locally). - -**Risks + mitigations:** -- *Risk:* `--junitxml`/`--cov` addopts break the existing test suite. - *Mitigation:* A5 (additive flags); verify CAP-009 stays Verified locally - before merging. -- *Risk:* Infracost CLI not available in CI. *Mitigation:* A6 — degraded - mode (omit event, log warning, don't fail the run). -- *Risk:* SQLite hash-chain corruption on concurrent writes. *Mitigation:* - single-writer model (the run manifest writer is the only writer per run); - WAL mode + `BEGIN IMMEDIATE`. -- *Risk:* Event schema drift between emitters and collector. *Mitigation:* - schemas authored first (task 1); all emitters validate against the schema - before writing. +`v1.17.2` --- -### Phase P2 — metrics-collector (Wave 2, feat) +## Phase P3 — submission-readiness (feat) -**Goal:** Read all grounded signals (files + events) into a normalized -SQLite cold store at `metrics/nova_metrics.db` with idempotent re-runs. -After P2, the metrics layer has a queryable store — P3 exports it, P4 -catalogs it. +- **Wave:** 3 +- **Requirements covered:** REQ-217, REQ-218, REQ-219, REQ-220 +- **Persona assignment:** data-engineer (schema: `schemas/submission-readiness.schema.json` + + the ingestor dispatch wiring co-owned with backend-engineer) + + backend-engineer (validator `core/submission_readiness.py` + CLI mode + in `contract_ingestor.py` + `tests/test_submission_readiness.py` + + reason-code catalog in `docs/submission-readiness.md`) +- **Description:** Define what is "acceptable to start" as a machine- + checkable contract — a superset gate above `contract.schema.json` + validity. The schema adds required Nova tags, per-env mandatory + metadata (W3.E), declared policy preconditions, the + `developer`/`agentic` profile (with agentic markers per REQ-22/W3.E), + and an `appSource` pointer. The validator runs as + `contract_ingestor.py --check-readiness` (D-133), returns a structured + `ReadinessResult` with reason codes, and on fail emits a + citizen-developer-facing error (not a stack trace). -**Requirements covered:** REQ-189, REQ-200, REQ-201, REQ-205 (collector -half), REQ-206 (collector half), REQ-207. +### Tasks -**Primary persona:** data-engineer. **Supporting:** backend-engineer -(event formats). +1. **Create `schemas/submission-readiness.schema.json`** (JSON Schema + draft 2020-12) — per REQ-217 + RESEARCH §3.3. This is a **superset + gate ABOVE `contract.schema.json`**, NOT a duplicate (PROJECT.md hard + constraint). It references but does not redefine contract fields. + Schema fields: + - `contractId`: string, non-empty, required (promoted from the Lambda + envelope to a contract-level required field). + - `environment`: enum `["dev", "qa", "prod", "dr"]`, required + (references `contract.schema.json`'s environment — does not + redefine; uses it to select the per-env mandatory set). + - `tags`: object, required. Required keys: `nova:owner`, + `nova:contract`, `nova:environment`, `nova:cost-center` (`nova:ref` + optional). References `schemas/tagging-standard.json`'s + `required_tags` shape (D-054). + - `policyPreconditions`: object (map of string→boolean/string), + required. Declared policy expectations the platform will enforce + (e.g. `{"public-ingress": false}`). + - `profile`: enum `["developer", "agentic"]`, required (REQ-217 / + W3.E). + - `appSource`: object `{repo: string, ref: string}`, required + (REQ-217 — repo + ref pointer for runtime fetch). + - **Per-env mandatory (W3.E) — conditional `allOf` / `if-then`:** + - `dev` requires `stack` + `environment` (base contract fields). + - `qa` adds `validation.e2eSuite` + `validation.loadTest`. + - `prod` adds `runbook` + `dashboard` + `oncall`. + - `dr` adds `drDrillRef`. + - `inputs` map: optional everywhere (W3.E). + - `profile: agentic` → conditionally requires + `naturalLanguageIntent` (string), `confidenceAtSubmission` (number + 0–1), `agentTrace` (object/string) per REQ-22 / W3.E. + - `additionalProperties: false` at the top level (the gate is strict — + no undocumented fields, per the v1.14 REQ-145 precedent). + - `$id`: `https://nova.cloudinit.dev/schemas/submission-readiness.schema.json` + (D-110 brand consistency). + - `$schema`: `https://json-schema.org/draft/2020-12/schema`. +2. **Create `core/submission_readiness.py`** — the validator (REQ-218, + D-133). Invoked as `contract_ingestor.py --check-readiness`. Returns a + structured `ReadinessResult`. Implementation per RESEARCH §3.2 + §3.4: + - `ReadinessResult` dataclass/Pydantic model: `{passed: bool, checks: + list[{name, passed, reason_code}], contract_id: str}`. + - `validate_readiness(contract: dict) -> ReadinessResult` — the main + entry point. + - **Validation order (two-layer gate, RESEARCH §3.2):** + 1. Call `contract_ingestor._validate_contract_schema(contract)` first + (the shape gate — reuses the existing function in + `core/lambda/contract_ingestor.py` line 57; if shape fails, return + early with a `CONTRACT_SHAPE_INVALID` reason code). + 2. Validate against `schemas/submission-readiness.schema.json` via + `jsonschema` (the gate — loads the schema from disk; if + jsonschema unavailable, fail loud with `SCHEMA_UNAVAILABLE`). + 3. Run the readiness checks that produce the citizen-developer-facing + reason codes (REQ-218): + - `MISSING_TAGS` — the 5 required Nova tags are not all present. + - `ENV_MISSING_MANDATORY::` — the per-env mandatory + field is absent (e.g. `ENV_MISSING_MANDATORY:qa:validation.e2eSuite`). + - `AGENTIC_MISSING_INTENT` — profile is `agentic` but + `naturalLanguageIntent` / `confidenceAtSubmission` / + `agentTrace` is missing. + - `MISSING_APP_SOURCE` — `appSource` is missing or incomplete. + - `POLICY_PRECONDITION_MISSING` — `policyPreconditions` is empty + or missing. + 4. Return all reason codes at once (not one-at-a-time — C2 Clarity: + the citizen developer sees the full scope of fixes needed). + - On fail → the caller (CLI or Lambda) emits a citizen-developer-facing + error (not a stack trace — REQ-218). On pass → proceeds to existing + ingestion. +3. **Edit `core/lambda/contract_ingestor.py`** — add the + `--check-readiness` CLI mode (D-133, RESEARCH §3.4 A-7). The ingestor + is currently Lambda-only (no `__main__` block); P3 adds one: + - Add `if __name__ == "__main__":` block at the bottom that parses + `sys.argv` (argparse). Subcommand: `--check-readiness ` + (reads a YAML/JSON contract file path; also supports `--stdin` to + read from stdin). + - The `--check-readiness` subcommand calls + `core.submission_readiness.validate_readiness(contract)` and prints + the `ReadinessResult` as JSON to stdout. + - On fail → exit non-zero with the citizen-developer-facing error + (the reason codes, not a stack trace). On pass → exit 0 with + `READY: `. + - The Lambda path is NOT changed by this task (the readiness gate is a + pre-flight CLI surface; whether the Lambda also gates on readiness + is a separate decision — REQ-218 says "On pass → proceeds to + existing contract ingestion," which the CLI path satisfies). + - Co-ownership: backend-engineer owns the dispatch wiring; + data-engineer owns the schema it validates against (PERSONAS.md + territory-overlap table). +4. **Create `docs/submission-readiness.md`** — citizen-developer-facing + doc (REQ-219). Explains what is acceptable to start. Sections: + - **What this checks** — the 5 readiness dimensions (tags, per-env + mandatory, policy preconditions, profile, appSource). + - **Good example** — a complete, passing contract (annotated with + which checks it satisfies). + - **Rejected examples** — one per reason code (a contract missing + tags → `MISSING_TAGS`; a qa contract missing `validation.e2eSuite` + → `ENV_MISSING_MANDATORY:qa:validation.e2eSuite`; an agentic + contract missing intent → `AGENTIC_MISSING_INTENT`; a contract + missing `appSource` → `MISSING_APP_SOURCE`; a contract with empty + `policyPreconditions` → `POLICY_PRECONDITION_MISSING`). + - **Reason-code catalog** — the 5 reason codes with their meaning + + how to fix (co-owned: lead-developer writes the narrative, + backend-engineer writes the reason-code catalog that mirrors the + validator's return codes — PERSONAS.md territory-overlap table). + - References `schemas/submission-readiness.schema.json` as the source + of truth. +5. **Create `tests/test_submission_readiness.py`** (REQ-220) — covers: + - Good contract passes (all checks green, `ReadinessResult.passed == True`). + - Missing tags fail with `MISSING_TAGS`. + - Missing env mandatory fails with + `ENV_MISSING_MANDATORY::` (test at least qa + prod + dr + cases). + - Agentic profile missing intent fails with `AGENTIC_MISSING_INTENT`. + - Missing appSource fails with `MISSING_APP_SOURCE`. + - Missing policyPreconditions fails with + `POLICY_PRECONDITION_MISSING`. + - The CLI mode (`contract_ingestor.py --check-readiness`) works + end-to-end: a good contract file → exit 0 + `READY:`; a bad + contract file → exit non-zero + the reason codes in stdout. +6. **Run the test suite** — `pytest tests/test_submission_readiness.py` + passes; the existing suite (`pytest`) still passes (no regressions). -**Tasks (vertical slices):** +### Must-haves (verification gate) -1. **Fact/dimension schemas** — `schemas/metrics_fact_run.schema.json`, - `schemas/metrics_fact_capability.schema.json`, - `schemas/metrics_fact_policy_check.schema.json`, - `schemas/metrics_fact_confidence.schema.json`, - `schemas/metrics_fact_test.schema.json`, - `schemas/metrics_fact_decision.schema.json`, - `schemas/metrics_fact_cost_estimate.schema.json`, - `schemas/metrics_fact_lifecycle.schema.json`, - `schemas/metrics_dim_capability.schema.json`, - `schemas/metrics_dim_milestone.schema.json`. Schema-first (data-engineer - constraint): all schemas exist before any collector code. - - *Acceptance:* all schemas validate sample rows; `python -m jsonschema` - passes for each. +- [ ] `schemas/submission-readiness.schema.json` exists, is valid JSON + Schema draft 2020-12, and `python3 -c "import jsonschema; + jsonschema.Draft202012Validator.check_schema(json.load(open('schemas/submission-readiness.schema.json')))"` succeeds. +- [ ] The schema references `contract.schema.json` (via `$ref` or by + delegating the shape check to the validator) — it does NOT + redefine `id`/`name`/`environment`/`infrastructure` (superset gate, + not duplicate — PROJECT.md hard constraint). +- [ ] `core/submission_readiness.py` exists, `python3 -m py_compile + core/submission_readiness.py` succeeds, and + `validate_readiness(good_contract)` returns + `ReadinessResult(passed=True)`. +- [ ] `core/lambda/contract_ingestor.py` has a `__main__` block; + `python3 core/lambda/contract_ingestor.py --check-readiness + ` exits 0; `python3 core/lambda/contract_ingestor.py + --check-readiness ` exits non-zero with a + citizen-developer-facing reason code (not a stack trace). +- [ ] `docs/submission-readiness.md` exists, has a good example + 5 + rejected examples (one per reason code), and references the schema + as source of truth. +- [ ] `tests/test_submission_readiness.py` passes (all 5+ reason-code + cases + the CLI end-to-end case). +- [ ] The full test suite passes (`pytest` — no regressions from the + ingestor edit). -2. **Collector core** — `core/metrics/collector.py` reads: - - `REGRESSION_REPORT.json` → `fact_capability` + `dim_capability`. - - `metrics/runs/*.json` → `fact_run`. - - `metrics/test-results.xml` (junit) → `fact_test`. - - `metrics/coverage.json` → `fact_test.coverage` column. - - `metrics/runs//pcr.json` → `fact_policy_check`. - - `metrics/runs//signal.json` → `fact_confidence`. - - `metrics/decision_ledger.db` → `fact_decision`. - - `metrics/runs//cost_estimate.json` → `fact_cost_estimate`. - - `metrics/lifecycle/*.json` → `fact_lifecycle`. - - `CHECKPOINT.json` → `dim_milestone`. - Writes to `metrics/nova_metrics.db` (SQLite cold store, D-126). - - *Acceptance:* after a run + collector invocation, - `metrics/nova_metrics.db` has all fact/dim tables populated; - `test_metrics_collector` passes. +### Ship tag -3. **Idempotent re-runs** — the collector is idempotent: re-running it - produces identical row counts + a verified chain. REQ-200. - - *Acceptance:* `test_metrics_collector_idempotent` passes (two runs → - identical row counts + chain verified). - -4. **Decision Ledger CLI** — `core/metrics/decision_ledger_cli.py` supports - `query`, `verify-chain`, `stats`, `export`, `replay`. `verify-chain` - detects broken hashes; `replay` prints ordered events. REQ-207. - - *Acceptance:* `decision_ledger_cli.py verify-chain` exits 0 on a clean - chain, exits 1 on a tampered chain; `test_decision_ledger_cli` passes. - -5. **Metrics README** — `metrics/README.md` documents regenerable vs - append-only artifacts + the restore procedure (the cold store is - regenerable from the raw signals; the Decision Ledger is append-only). - REQ-201. - - *Acceptance:* `metrics/README.md` exists with the two categories + a - restore procedure section. - -**Must-haves:** -- `core/metrics/collector.py` exists and is tested. -- `metrics/nova_metrics.db` is produced with all fact/dim tables. -- Idempotent re-runs (REQ-200) verified by test. -- `core/metrics/decision_ledger_cli.py` exists with all 5 subcommands. -- `metrics/README.md` documents regenerable vs append-only + restore. -- `bash scripts/run_ci.sh` exits 0. - -**Risks + mitigations:** -- *Risk:* Schema drift between P1's event formats and P2's fact schemas. - *Mitigation:* data-engineer authors both; backend-engineer reviews the - event-format alignment. -- *Risk:* Junit XML parsing edge cases (test names with special chars). - *Mitigation:* use `xml.etree.ElementTree` with XPath; test with a fixture - containing edge-case names. +`v1.17.3` --- -### Phase P3 — powerbi-export (Wave 2, feat) +## Phase P4 — atelier-skills (docs) -**Goal:** Emit CSV/JSON views from the SQLite cold store to -`metrics/powerbi/` — fact + dimension views + 8 empty placeholder views -for deferred metrics. After P3, a PowerBI folder-connector dashboard can -be built. +- **Wave:** 3 (parallelizable with P3 in a parallelization-enabled run) +- **Requirements covered:** REQ-221, REQ-222 +- **Persona assignment:** lead-developer (9 skill files + `docs/skills.md` + index + PROJECT.md BA.A extension) +- **Description:** Create 9 Atelier-derived skill files under `skills/` + keyed to Atelier domain paths, extending the BA.A 5-skill citizen- + developer catalog. Each skill names the Atelier source path, distills + the first-principles to the citizen-developer-relevant subset, links to + agent-checklist triggers, and maps to the BA.A catalog. Create a + `docs/skills.md` index page. The research (RESEARCH §1.3) confirmed the + exact 9-skill list — no adjustment needed. -**Requirements covered:** REQ-190, REQ-199, REQ-208, REQ-209 (P3 half), -REQ-205 (view half). +### Tasks -**Primary persona:** data-engineer. +1. **Create `skills/` directory** with 9 Atelier-derived skill files + (REQ-221, D-138). Each file is markdown, structured as: + - **Atelier source path** (e.g. `domains/security/`). + - **P-rules distilled** (the citizen-developer-relevant subset — see + RESEARCH §1.3 table for the exact P-rules per skill). + - **First-principles distillation** (plain language; no Atelier-internal + jargon; the citizen-developer-relevant subset, not the full domain). + - **Agent-checklist triggers** (links to + `review/agent-checklist.md` sections the citizen developer's AI + agent runs before finishing a task). + - **BA.A catalog mapping** (which of the 5 BA.A skills this extends: + web API, worker, scheduled job, static asset, basic observability + bootstrap — per RESEARCH §1.3). + The 9 files (per REQ-221 + RESEARCH §1.3): + - `skills/api.md` — Atelier `domains/api/`. P-rules: P1 Contract + Fidelity, P2 Clarity, P5 Versioning, P6 Idempotency, P8 Security, P9 + Error Transparency. Extends: web API. + - `skills/security.md` — Atelier `domains/security/`. P-rules: P1 Zero + Trust, P2 Least Privilege, P4 Input Validation, P6 Crypto + Correctness, P8 Fail Securely, P9 Secret Hygiene. Extends: all 5 + (cross-cutting). + - `skills/data.md` — Atelier `domains/data/`. P-rules: P1 Truth, P3 + Invariants in Schema, P4 Migration Safety, P7 Type Fidelity, P9 + Referential Integrity. Extends: web API, worker, scheduled job. + - `skills/testing.md` — Atelier `domains/testing/`. P-rules: P1 Tests + as Specification, P3 Determinism, P5 Coverage of Behavior, P9 Edge + Case Coverage, P10 No Test Theater. Extends: all 5 (UAT is a citizen- + developer RACI responsibility). + - `skills/observability.md` — Atelier `domains/observability/`. + P-rules: P1 Structured by Default, P2 Correlation, P6 No Secrets in + Obs, P7 Actionable Alerts. Extends: basic observability bootstrap. + - `skills/errors.md` — Atelier `domains/errors/`. P-rules: P1 Errors + are Data, P2 Fail Loudly, P3 Fail Specifically, P4 Preserve Context, + P5 Recoverable When Possible. Extends: web API, worker, scheduled + job. + - `skills/devops.md` — Atelier `domains/devops/`. P-rules: P1 + Reproducibility, P4 Rollback First, P5 Progressive Delivery, P6 + Config as Code, P8 Security at Every Layer. Extends: scheduled job, + worker (deploy/release is co-owned Release Mgmt). + - `skills/infrastructure-as-code.md` — Atelier + `domains/infrastructure-as-code/`. P-rules: P1 Declarative Intent, P2 + Idempotence, P4 Plan Before Apply, P5 Version Everything, P10 + Secrets Never in Code. Extends: static asset (the contract→Terraform + path). + - `skills/compliance.md` — Atelier `domains/compliance/`. P-rules: P1 + Audit Logs Append-Only, P2 Every Significant Action Logged, P4 + Policy is Code, P5 Policy is Evaluated as a Gate, P9 Secrets + Redacted in Audit. Extends: all 5 (cross-cutting; Nova's compliance + posture). +2. **Create `docs/skills.md`** (REQ-222) — the index page. Sections: + - **Skill catalog** — a table listing the 9 skills with their Atelier + source path + BA.A catalog mapping. + - **Atelier provenance** — explains the skills are derived from + `coreci/atelier` (the first-principles docs-as-code engineering + framework — 8 core principles, 19 domains, 190 P-rules); the 9 + skills are the citizen-developer-relevant subset of the 13 relevant + domains (RESEARCH §1.2 — 6 domains excluded: UI/UX, Kubernetes, + GitOps, i18n, Edge, Messaging). + - **How the citizen developer's AI agent consumes them** — read the + relevant skill before completing a task; run the Atelier + `review/agent-checklist.md` before finishing. The agent-checklist + will be exposed as an MCP tool in P5 (`atelier.validate_against_principles`). + - **The 4 "reference-only" domains** (Performance, Documentation, + Concurrency, AI/ML) — their principles are cited inside the 9 skills + + this index but do NOT get their own skill file (RESEARCH §1.2 — a + citizen developer's first production-grade service does not need a + standalone Concurrency or AI/ML skill). + - No `.ciagent/` references (consumer-facing — REQ-52 precedent). +3. **Edit `PROJECT.md`** — extend the BA.A decision (W3.E resolution + table, line ~886) with a reference to the Atelier-derived skill + catalog. Add a note that the BA.A 5-skill catalog (web API, worker, + scheduled job, static asset, basic observability bootstrap) is + extended by the 9 Atelier-derived skills under `skills/`, indexed at + `docs/skills.md`. -**Tasks (vertical slices):** +### Must-haves (verification gate) -1. **PowerBI export core** — `core/metrics/powerbi_export.py` reads - `metrics/nova_metrics.db` and emits CSV/JSON views to `metrics/powerbi/`: - `fact_run.csv`, `fact_capability.csv`, `fact_policy_check.csv`, - `fact_confidence.csv`, `fact_test.csv`, `fact_decision.csv`, - `fact_cost_estimate.csv`, `fact_lifecycle.csv`, `dim_capability.csv`, - `dim_milestone.csv`. D-129 (CSV/JSON folder connector). - - *Acceptance:* after `powerbi_export.py` runs, all 10 CSV files exist - in `metrics/powerbi/` with non-empty content (given a populated cold - store); `test_powerbi_export` passes. +- [ ] `skills/` directory exists with exactly 9 markdown files: `api.md`, + `security.md`, `data.md`, `testing.md`, `observability.md`, + `errors.md`, `devops.md`, `infrastructure-as-code.md`, `compliance.md`. +- [ ] Each skill file names its Atelier source path (e.g. + `domains/security/`), distills ≥4 P-rules, links to agent-checklist + triggers, and maps to a BA.A catalog skill. +- [ ] `docs/skills.md` exists, has a skill-catalog table (9 rows), an + Atelier-provenance section, a "how the AI agent consumes them" + section, and the 4 reference-only domains note. +- [ ] `docs/skills.md` has no `.ciagent/` references (consumer-facing). +- [ ] `PROJECT.md` BA.A decision is extended with the Atelier-derived + skill catalog reference. +- [ ] The full test suite still passes (`pytest` — no code changes, docs + only, but verify no regressions). -2. **8 deferred placeholder views** — empty CSV files with documented - schemas (headers only, no data rows) for the 8 deferred metrics: - (1) Live Infrastructure Health, (2) Live Outbox Write Rate, - (3) Tamper-Evident Ledger Checkpoints, (4) Onboarding Funnel - (requested→granted), (5) Drift Auto-Reversal Rate, (6) Live CUR - Reconciliation, (7) SLA / Unplanned Downtime, (8) Predictive vs Reactive - Ratio. D-123. Each has a header row documenting the columns + a comment - row citing the blocking decision ID. - - *Acceptance:* all 8 placeholder CSVs exist with header rows + a - decision-ID comment; `test_placeholder_views` passes. +### Ship tag -3. **METRICS_VIEWS.md data dictionary** — `docs/METRICS_VIEWS.md` has a - per-column data-dictionary table (column, type, source/formula, unit, - grounded/derived/deferred status) for every view. REQ-209 (P3 half). - - *Acceptance:* `docs/METRICS_VIEWS.md` exists with a complete - per-column table covering all 18 views (10 fact/dim + 8 placeholder). - -4. **NOVA_DASHBOARD_README.md** — `metrics/powerbi/NOVA_DASHBOARD_README.md` - documents the folder-connector import path + a starter visual model + - a reference screenshot placeholder. REQ-208. - - *Acceptance:* the README exists with import steps + visual model - description. - -5. **Schema validation in CI** — `run_ci.sh` validates - `metrics/powerbi/*.json` + a sample `metrics/events.jsonl` against their - schemas; exits 0. REQ-199. - - *Acceptance:* `bash scripts/run_ci.sh` validates the PowerBI JSON - exports + a sample events file; exits 0. - -**Must-haves:** -- `core/metrics/powerbi_export.py` exists and is tested. -- `metrics/powerbi/` contains all 10 fact/dim CSVs + 8 placeholder CSVs. -- `docs/METRICS_VIEWS.md` has the per-column data dictionary. -- `metrics/powerbi/NOVA_DASHBOARD_README.md` exists. -- `run_ci.sh` schema validation (REQ-199) passes. -- `bash scripts/run_ci.sh` exits 0. - -**Risks + mitigations:** -- *Risk:* Placeholder view schemas diverge from what the future emitter - will produce. *Mitigation:* the schema is documented in the header row - + METRICS_VIEWS.md; the future emitter must conform to the documented - schema. -- *Risk:* PowerBI folder connector quirks (CSV encoding, delimiters). - *Mitigation:* UTF-8 + comma-delimited; documented in the README. +`v1.17.4` --- -### Phase P4 — metrics-catalog + north-star-integration (Wave 3, docs) +## Phase P5 — atelier-mcp (feat) -**Goal:** Catalog every executive KPI in `docs/METRICS.md` with -grounded/derived/deferred status + per-KPI definition-of-success docs. -Wire `NORTH_STAR.md` into CIAgent context-loading so every future -`/ci-run` reads it. Produce the trust-snapshot report, the deferred-metrics -roadmap, the confidence-gate halt rate metric, and the no-humans thesis -brief. After P4, the metrics layer is fully documented and the strategic -direction is durable. +- **Wave:** 4 +- **Requirements covered:** REQ-223, REQ-224, REQ-225 +- **Persona assignment:** backend-engineer (MCP server + plugin-registry + + vendored Atelier + tests) +- **Description:** Build the Atelier MCP server (`mcp/atelier/server.py`) + with a plugin-registry architecture (D-140): `plugins/.py` + modules each expose `register(mcp) -> None` and call `@mcp.tool()` for + their tools. The server scans `plugins/` and calls `register` on each. + Initial plugins: `principles.py` (`atelier.lookup_principle`, + `atelier.list_domains`, `atelier.matrix_lookup`) and `validation.py` + (`atelier.validate_against_principles` — agentic validation against the + Atelier agent-checklist). Uses the MCP Python SDK v2 (D-137). stdio + transport (D-135). Vendor the Atelier snapshot at pinned tag `v0.3.6` + (D-136) for audit reproducibility. -**Requirements covered:** REQ-186, REQ-191, REQ-192, REQ-193, REQ-194, -REQ-195, REQ-204, REQ-209 (P4 half), REQ-210, REQ-211, REQ-212, REQ-213 -(P4 half). +### Tasks -**Primary persona:** lead-developer. **Supporting:** data-engineer -(metric definitions). +1. **Create `mcp/atelier/vendor/`** — vendored Atelier snapshot at tag + `v0.3.6` (REQ-224, D-136, RESEARCH §1.6). The vendored content is a + clean copy of the Atelier repo at tag `v0.3.6` (the `core/`, + `domains/`, `matrix/`, `review/` directories — the docs the MCP tools + read; `examples/` and `languages/` are optional but included for + completeness). Mechanics per RESEARCH §1.6: + - Fetch `https://git.cloudinit.dev/coreci/atelier/archive/v0.3.6.tar.gz`. + - Extract the doc directories into `mcp/atelier/vendor/`. + - Verify the matrix is at the complete state: 19 domains, 190 P-rules + (the Coverage Summary in `matrix/principles-matrix.md` confirms this). +2. **Create `mcp/atelier/vendor/VERSION.md`** — records the pinned tag + + provenance (REQ-224, RESEARCH §1.6): + - Tag: `v0.3.6` + - Commit: `66b4767d25` + - Date: 2026-08-05 + - Milestone: "v0.4 Edge + Messaging + Language-Derived Docs" + - P-rule count: 190 + - Domain count: 19 + - Source URL: `https://git.cloudinit.dev/coreci/atelier` +3. **Create `scripts/update_atelier_vendor.sh`** (executable, + `set -euo pipefail`) — helper for intentional upgrades (REQ-224). + Takes a tag arg, fetches the tarball from + `https://git.cloudinit.dev/coreci/atelier/archive/.tar.gz`, + extracts the doc directories into `mcp/atelier/vendor/`, and updates + `VERSION.md`. Intentional upgrades only (re-run + re-audit). +4. **Create `mcp/atelier/server.py`** (REQ-223, D-135, D-137, D-140, + RESEARCH §2.2) — the MCP server. Implementation per the RESEARCH §2.2 + skeleton: + - `from mcp.server import MCPServer` (v2 high-level server — NOT + `FastMCP`, which was v1; RESEARCH §2.1 A-2). + - `mcp = MCPServer("atelier")` — one arg = server name. + - **Plugin-registry (D-140):** scan `plugins/`, import each module via + `importlib.import_module(f".plugins.{p.stem}", __package__)`, call + `register(mcp)` on each. `sorted(pathlib.Path(__file__).parent.glob("plugins/*.py"))` + makes load order deterministic (audit reproducibility — RESEARCH + §2.2 notes). + - `@mcp.tool()` for the server-level tool `atelier_list_domains` (or + delegate to a plugin — the skeleton shows it inline; the + implementation may move it to `plugins/principles.py` for consistency + with the plugin-registry pattern). + - `if __name__ == "__main__": mcp.run()` — stdio transport is the + default (D-135; RESEARCH §2.1 A-3). HTTP-ready on the same object + (future milestone — Out of Scope for v1.18). +5. **Create `mcp/atelier/plugins/__init__.py`** — empty init (makes + `plugins/` a package). +6. **Create `mcp/atelier/plugins/principles.py`** (REQ-223, + RESEARCH §1.5) — the principles plugin. `register(mcp: MCPServer) -> + None` containing `@mcp.tool()` calls for: + - `atelier_lookup_principle(domain: str, principle_id: str) -> + PrincipleLookup` — resolves a principle reference to its full text + + core derivation + checklist items. Resolution path per RESEARCH §1.5: + load `vendor/core/first-principles.md` (if domain=="core") or + `vendor/domains//first-principles.md`, parse the principle + section; cross-reference `vendor/matrix/principles-matrix.md` for the + core derivation; cross-reference + `vendor/review/agent-checklist.md` for checklist items; check + non-tradeable status in `vendor/domains//first-principles.md` + §3. Return the `PrincipleLookup` Pydantic model (RESEARCH §1.5). + - `atelier_list_domains() -> list[DomainInfo]` — returns the 19 + domain names + P-rule counts + Nova-relevance flag (the plugin + hardcodes the Nova-relevance table from RESEARCH §1.2 so the + citizen developer's agent can filter to the 13 relevant / 9 + skill-bearing domains). + - `atelier_matrix_lookup(domain: str) -> DomainMatrix` — returns the + full domain→core mapping for one domain (all 10 P-rules → their + core C-rule(s)), used by `validate_against_principles` to set + `severity` and by conflict resolution when two findings collide. + - Lazily load + cache the vendored markdown in module-level dicts (C8 + Economy — don't re-parse the matrix on every lookup; RESEARCH §2.2 + notes). +7. **Create `mcp/atelier/plugins/validation.py`** (REQ-223, + RESEARCH §1.4) — the validation plugin. `register(mcp: MCPServer) -> + None` containing: + - `atelier_validate_against_principles(snippet: str, language: str, + domains: list[str], run_core: bool = True) -> ValidateResult` — + agentic validation against the Atelier agent-checklist, beyond + Wiz/Checkmarx/Mend. Input/output models per RESEARCH §1.4 + (`ValidateInput`, `Violation`, `ValidateResult` Pydantic models). + The plugin reads the vendored `review/agent-checklist.md` (frozen at + the pinned tag — RESEARCH §1.4) and maps each checklist line to a + predicate function keyed by `(language, principle)`. The validation + catches C1 (correctness) + C7 (observability) violations in a + known-bad snippet and passes a known-good snippet (REQ-225 test + case). +8. **Create `mcp/atelier/README.md`** (REQ-224) — documents the server: + - How to run (`python3 mcp/atelier/server.py` — stdio transport; the + citizen developer's AI agent spawns the server as a subprocess). + - Transport: stdio now (D-135); HTTP-ready on the same object (future + milestone — Out of Scope). + - Tool catalog: the 4 tools (`atelier.lookup_principle`, + `atelier.list_domains`, `atelier.matrix_lookup`, + `atelier.validate_against_principles`) with their input/output + schemas. + - Plugin-authoring guide: how to add a new plugin (`plugins/.py` + with `register(mcp)` — D-140; no `server.py` edits). + - Vendoring policy: pinned tag `v0.3.6` for audit reproducibility + (D-136); `scripts/update_atelier_vendor.sh` for intentional + upgrades; live-fetch is NOT implemented (Out of Scope). +9. **Create `tests/test_atelier_mcp.py`** (REQ-225) — covers: + - **Tool registration** — all 4 tools discoverable via `tools/list` + (the MCP protocol's tool-discovery call; the test spawns the server + in-process or uses the SDK's test harness). + - `atelier.lookup_principle("security", "P4")` returns the principle + text ("Input Validation") + core C-rule (`C1`) + checklist items + (RESEARCH §1.5 example). + - `atelier.validate_against_principles` catches a planted C1 + (correctness) + C7 (observability) violation in a known-bad + snippet and passes a known-good snippet (REQ-225 explicit case). + - `atelier.matrix_lookup("security")` returns the domain→core mapping + (all 10 P-rules → their core C-rule(s)). + - **Plugin discovery** — the server loads all plugins in `plugins/` + (the test verifies `plugins/principles.py` + + `plugins/validation.py` are both loaded; the `register` function + was called on each). +10. **Add the MCP Python SDK v2 dependency** to `requirements-test.txt` + (or `pyproject.toml` test dependencies): `mcp>=2.0` (the + `modelcontextprotocol/python-sdk` package; D-137). Pin per the + project's dependency convention. +11. **Run the test suite** — `pytest tests/test_atelier_mcp.py` passes; + the existing suite still passes. -**Tasks (vertical slices):** +### Must-haves (verification gate) -1. **METRICS.md catalog** — `docs/METRICS.md` catalogs every executive KPI - with: name, NORTH_STAR target, `grounded`/`derived`/`deferred` status, - source file or decision ID, and a link to the per-KPI definition doc. - REQ-195. Covers all metrics from the scorecard (RESEARCH.md §3): - Touchless Resolution Rate, Human Escalation Frequency, MTTR (platform-run), - AI Decision Accuracy, Decision Ledger Coverage, Attestation Coverage, - Capability Health, Confidence Distribution, Policy Pass Rate, Test - Count/Pass Rate, Provisioning Lead Time, Deployment Frequency, - Cost Estimates (Infracost), FTE Hours Saved, Platform ROI, - Confidence-Gate Halt Rate, + the 8 deferred metrics. - - *Acceptance:* `docs/METRICS.md` exists; every KPI has a status badge - + a source link; a grep confirms no KPI is missing a status. +- [ ] `mcp/atelier/server.py` exists, `python3 -m py_compile + mcp/atelier/server.py` succeeds, and imports + `from mcp.server import MCPServer` (v2 high-level server — NOT + `FastMCP`). +- [ ] `mcp/atelier/plugins/principles.py` + + `mcp/atelier/plugins/validation.py` exist; each has a + `register(mcp)` function containing `@mcp.tool()` calls. +- [ ] `mcp/atelier/vendor/` exists with `core/`, `domains/`, `matrix/`, + `review/` directories vendored from Atelier tag `v0.3.6`. +- [ ] `mcp/atelier/vendor/VERSION.md` records tag `v0.3.6`, commit + `66b4767d25`, 190 P-rules, 19 domains. +- [ ] `scripts/update_atelier_vendor.sh` exists, is executable, and takes + a tag arg. +- [ ] `mcp/atelier/README.md` documents how to run, transport, tool + catalog, plugin-authoring guide, vendoring policy. +- [ ] `tests/test_atelier_mcp.py` passes: 4 tools discoverable, + `lookup_principle` returns the principle + core rule, + `validate_against_principles` catches C1+C7 violations in a + known-bad snippet + passes a known-good snippet, + `matrix_lookup` returns the domain→core mapping, plugin discovery + loads all plugins. +- [ ] The full test suite passes (`pytest` — no regressions from the new + dependency). -2. **Per-KPI definition-of-success docs** — `docs/metrics/.md` for - every KPI (D-127). Each doc defines: the metric, the formula, the - grounding status, the source file, the definition of success (what - number = "won"), and the deferred dependency (if applicable). - - *Acceptance:* `docs/metrics/` contains one `.md` per KPI; each doc - has all 5 sections. +### Ship tag -3. **Zero-touch efficiency metrics docs** — REQ-191: Autonomous Resolution - Rate, Human Escalation Frequency, AI Decision Accuracy, MTTD/MTTR - (platform-run, D-131). Documented in METRICS.md + per-KPI docs with - the attestation exclusion clarification (attestation gates are designed - controls, not escalations). - - *Acceptance:* the 4 metrics have per-KPI docs with the correct - formulas + attestation exclusion language. - -4. **Velocity metrics docs** — REQ-192: Provisioning Lead Time - (apply.completed.time − intent.received.time), Deployment Frequency - (count(apply.completed) per day). Self-Healing Velocity deferred. - - *Acceptance:* the 2 metrics have per-KPI docs; the deferral is - documented. - -5. **Financial & cost-ROI metrics docs** — REQ-193: FTE Hours Saved - (derived), Cost Savings via Infracost (grounded), Cost Efficiency Ratio - (derived), Platform ROI (derived formula). Live CUR deferred (D-096). - - *Acceptance:* the 4 metrics have per-KPI docs with formulas; the CUR - deferral cites D-096. - -6. **Reliability, security & compliance metrics docs** — REQ-194: - Zero-Trust Policy Compliance Rate (from pcr.json), Attestation Coverage - (prod/dr promotions attested by a human ÷ total prod/dr promotions; - grounded in `hitl_gates.py` + outbox `approver_*` attributes). Uptime, - Patch Remediation, SLA/downtime deferred (D-096). **Attestation Coverage - is canonically owned here (REQ-194), not in REQ-191.** - - *Acceptance:* the 2 grounded metrics have per-KPI docs; the 3 deferred - metrics have deferral docs citing D-096. - -7. **NORTH_STAR integration** — REQ-186: `NORTH_STAR.md` is referenced from - `PROJECT.md` (a "Strategic Direction" section pointing to it) + - `ARCHITECTURE.md` (the v1.17 addendum already references it). `config.json` - gains `strategic_direction_file: ".ciagent/NORTH_STAR.md"` so the run - workflow reads it at SPECIFY. - - *Acceptance:* `PROJECT.md` has a Strategic Direction section; - `config.json` has the `strategic_direction_file` key; a test confirms - the file is readable. - -8. **NORTH_STAR diff-check in CI** — REQ-204: `run_ci.sh` includes - `check_north_star_diff` that fails when Vision/Objectives/Anti-Goals/ - Targets sections change without a `NORTH_STAR-CHANGE:` commit trailer. - - *Acceptance:* a test commit changing a Target without the trailer - fails the check; a commit with the trailer passes. - -9. **Deferred-metrics activation roadmap** — `docs/METRICS_DEFERRED_ROADMAP.md` - lists 8 deferred metrics + onboarding-grant half with {blocking decision, - unblock requirement, candidate milestone} + a "Hot-Path Activation - (post-D-096)" section (Nova-native only, D-120) + "Re-evaluation - Triggers" section. REQ-210. - - *Acceptance:* the roadmap exists with all 8 + the onboarding-grant - half + the 2 sections. - -10. **Trust-snapshot report** — `core/metrics/trust_snapshot.py` emits - `metrics/TRUST_SNAPSHOT.md` with 5 trust metrics (Decision Ledger - Coverage, Attestation Coverage, Capability Health, AI Decision - Accuracy, Confidence-Gate Halt Rate) + chain-integrity verdict + - snapshot hash. Runs offline. REQ-211. - - *Acceptance:* `metrics/TRUST_SNAPSHOT.md` exists after running - `trust_snapshot.py`; the 5 metrics + verdict + hash are present; - `test_trust_snapshot` passes. - -11. **Confidence-Gate Halt Rate metric** — REQ-212: `docs/METRICS.md` + - trust snapshot include "Confidence-Gate Halt Rate" (signal.json - band=halt ÷ total runs). PowerBI view includes it (added to - `fact_confidence` projection in P3's export — coordinate with P3). - - *Acceptance:* METRICS.md has the metric; the trust snapshot includes - it; the PowerBI export includes a column for it. - -12. **No-humans thesis brief** — `docs/NO_HUMANS_THESIS.md` defines the - thesis, grounded proof metrics, deferred proof metrics, and explicit - anti-claims (incl. D-122 honesty: the "AI" is the confidence-gated - policy engine, not an LLM). REQ-213 (P4 half). The unified deck's - Vision act cites it (P5). - - *Acceptance:* `docs/NO_HUMANS_THESIS.md` exists with all 4 sections; - the anti-claims section explicitly addresses D-122. - -**Must-haves:** -- `docs/METRICS.md` catalogs every KPI with status + source. -- `docs/metrics/*.md` per-KPI docs exist for every KPI. -- `NORTH_STAR.md` referenced from PROJECT.md + ARCHITECTURE.md + config.json. -- `run_ci.sh` includes `check_north_star_diff` (REQ-204). -- `docs/METRICS_DEFERRED_ROADMAP.md` exists (REQ-210). -- `core/metrics/trust_snapshot.py` + `metrics/TRUST_SNAPSHOT.md` (REQ-211). -- Confidence-Gate Halt Rate in METRICS.md + trust snapshot + PowerBI (REQ-212). -- `docs/NO_HUMANS_THESIS.md` exists (REQ-213 P4 half). -- `bash scripts/run_ci.sh` exits 0. - -**Risks + mitigations:** -- *Risk:* KPI definitions drift from NORTH_STAR targets. *Mitigation:* - the catalog cross-references NORTH_STAR target rows; the diff-check - (REQ-204) catches NORTH_STAR changes. -- *Risk:* The no-humans thesis overclaims. *Mitigation:* D-122 honesty - constraint — the anti-claims section explicitly states the "AI" is the - confidence-gated policy engine; A3. +`v1.17.5` --- -### Phase P5 — deck-rebuild (Wave 3, docs+test) +## Phase P6 — deck-slides-atelier (docs) -**Goal:** Merge the two existing decks into one unified narrative deck -"Nova — The No-Humans Infrastructure Platform" with the 5-act arc -(Problem → Vision → How → Proof → Roadmap), x3 structure at deck + slide -level, per-slide benefit callouts, fluid transitions, a metrics glossary -appendix slide, a "what's deferred" slide, and the no-humans thesis cited -in the Vision act. Retire both old decks. Re-run the 4-step deck process -(source `.md` → Marp → HTML → talking-points). +- **Wave:** 5 +- **Requirements covered:** REQ-226, REQ-227, REQ-228 +- **Persona assignment:** lead-developer (3 new deck slides + README + update + talking-points sync + HTML/PPTX re-render) +- **Description:** Add the 21st deck slide to the unified deck → 21 slides + total. P2 added slides 19 (Scope) + 20 (RACI); P6 adds slide 21 + (Atelier). Update the Arc Preview slide to reflect 21 slides. Sync the + talking-points file for the 3 new slides (Scope, RACI, Atelier). + Re-render HTML + PPTX (S&P theme preserved — regression check vs P1). + Update the README slide count + deck table. -**Requirements covered:** REQ-196, REQ-197, REQ-202, REQ-203, REQ-213 -(P5 half). +### Tasks -**Primary persona:** lead-developer. +1. **Edit `docs/presentations/nova-no-humans-platform-marp.md`** — add + the 21st slide (REQ-226, D-134): + - **Slide 21 — Production-Grade Guidance via Atelier.** Content: + - The 9 Atelier-derived skills (under `skills/`, indexed at + `docs/skills.md`) extend the BA.A 5-skill catalog. + - The Atelier MCP server (`mcp/atelier/server.py`, stdio transport) + exposes 4 tools: `atelier.lookup_principle`, + `atelier.list_domains`, `atelier.matrix_lookup`, + `atelier.validate_against_principles`. + - Agentic validation goes beyond deterministic scanners + (Wiz/Checkmarx/Mend) by catching correctness/clarity/simplicity/ + observability gaps (C1/C2/C3/C7) against the Atelier + agent-checklist. + - Vendored Atelier (pinned tag `v0.3.6`) for audit reproducibility + (D-136) — an agentic validation result is replayable against the + exact principles that produced it. + - Benefit callout: "you now know the citizen developer is not + unguided — production-grade engineering principles are + machine-checkable, and the validation goes beyond SAST to + correctness, clarity, simplicity, and observability." + - Slides 19 (Scope) + 20 (RACI) were added in P2; P6 confirms they + are still present and renumbers if needed so the slide order is + Scope → RACI → Atelier (19 → 20 → 21). + - Update **Slide 1 — Arc Preview** to reflect 21 slides (change the + slide-count reference; the 5-act arc is preserved — D-134: the 3 + new slides are append-only context, not a new act). +2. **Edit `docs/presentations/nova-no-humans-platform-talking-points.md`** + (REQ-226) — sync the talking points for the 3 new slides (Scope, + RACI, Atelier). Each new slide gets a talking-points section with 3–6 + punchy, actionable cues + a key takeaway per slide (per the v1.9.7 + talking-points format). +3. **Edit `docs/presentations/README.md`** (REQ-227) — update: + - The slide count (21 slides + appendix). + - The deck table (add the 3 new slide titles: "Scope: Downstream of + PDLC", "RACI: Who Owns What", "Production-Grade Guidance via + Atelier"). +4. **Run `scripts/render_deck.sh + docs/presentations/nova-no-humans-platform-marp.md`** (REQ-228) — + regenerates HTML + PPTX. The S&P theme is preserved (regression check + vs P1 — grep `#D6002A` in the deck markdown still returns ≥4 hits). +5. **Commit** the updated deck markdown, talking-points, README, the + regenerated HTML, and the regenerated PPTX binary. +6. **Attach** the PPTX to the `v1.17.6` Gitea release via + `scripts/attach_release_asset.py --tag v1.17.6 --file + docs/presentations/nova-no-humans-platform.pptx`. -**Tasks (vertical slices):** +### Must-haves (verification gate) -1. **Unified deck source markdown** — `docs/presentations/nova-no-humans-platform.md` - is the single source of truth (the full slide-by-slide plan is in the - "Deck Rebuild Plan" section below). The 5-act arc with x3 at deck level - (opening = arc preview, body = tell them, closing = recap + ask) + x3 - per slide (opens with what it covers, delivers, closes with benefit - callout). Fluid transitions written into each slide's opening line. - REQ-196, REQ-197. - - *Acceptance:* the source `.md` exists with all slides from the deck - plan below; each slide has the 3-part structure; transitions are - written. +- [ ] The deck has 21 main slides: Slide 19 = Scope, Slide 20 = RACI, + Slide 21 = Atelier (+ appendix slides). +- [ ] Slide 1 Arc Preview reflects 21 slides. +- [ ] Slide 21 (Atelier) mentions the 9 skills, the 4 MCP tools, agentic + validation beyond SAST, and the vendored pinned tag `v0.3.6`. +- [ ] `docs/presentations/nova-no-humans-platform-talking-points.md` has + talking-points sections for all 3 new slides (Scope, RACI, + Atelier). +- [ ] `docs/presentations/README.md` reflects 21 slides + the 3 new + titles in the deck table. +- [ ] `scripts/render_deck.sh` re-renders HTML + PPTX successfully; the + S&P theme is preserved (grep `#D6002A` — P1 regression check). +- [ ] `docs/presentations/nova-no-humans-platform.pptx` is committed + (binary) and attached to the `v1.17.6` Gitea release. +- [ ] CAP-024 deck structure regression passes (21 slides, x3 arc, + per-slide benefits on all 3 new slides). -2. **Marp deck** — `docs/presentations/nova-no-humans-platform-marp.md` - (Marp-formatted with the S&P visual theme, `sp-theme.json` unchanged). - - *Acceptance:* the Marp deck renders to HTML with the correct slide - count + theme. +### Ship tag -3. **HTML render** — `docs/presentations/nova-no-humans-platform.html` - (re-rendered from the Marp deck). - - *Acceptance:* the HTML exists and opens with the correct title slide. - -4. **Talking points** — `docs/presentations/nova-no-humans-platform-talking-points.md` - (distilled from the Marp deck, one section per slide with speaker notes). - - *Acceptance:* the talking-points file exists with one section per - slide. - -5. **Metrics glossary appendix slide** — REQ-202: the deck has a - "Metrics Glossary" appendix slide with one-line KPI definitions + - grounding badges (grounded/derived/deferred). - - *Acceptance:* the glossary slide exists with all KPIs + badges. - -6. **"What's Deferred — and Why" slide** — REQ-203: the deck has a slide - pairing each of 8 deferred metrics with its blocking decision ID. - - *Acceptance:* the deferred slide exists with all 8 + decision IDs. - -7. **No-humans thesis cited in Vision act** — REQ-213 (P5 half): the - Vision act cites `docs/NO_HUMANS_THESIS.md` (the thesis, grounded proof, - deferred proof, anti-claims). - - *Acceptance:* the Vision act slides reference the thesis brief. - -8. **Retire both old decks** — delete `how-the-platform-works.md` + - `-marp.md` + `.html` + `-talking-points.md` + `the-developer-experience.md` - + `-marp.md` + `.html` + `-talking-points.md`. D-130. - - *Acceptance:* a grep confirms the old deck files are deleted; no - references to them remain in the repo. - -**Must-haves:** -- `docs/presentations/nova-no-humans-platform.md` (+ marp + html + - talking-points) exists with the full slide plan. -- x3 structure at deck + slide level (REQ-197). -- Per-slide benefit callouts (REQ-197). -- Fluid transitions written into each slide (REQ-197). -- Metrics glossary appendix slide (REQ-202). -- "What's Deferred" slide (REQ-203). -- No-humans thesis cited in Vision act (REQ-213 P5 half). -- Both old decks deleted (D-130). -- `bash scripts/run_ci.sh` exits 0. - -**Risks + mitigations:** -- *Risk:* The deck claims a metric that isn't grounded yet. *Mitigation:* - P5 Proof act depends on P4's METRICS.md; every cited metric has a - grounded source file verified by the catalog. -- *Risk:* The old decks are referenced by other docs. *Mitigation:* grep - for references before deletion; update or remove them. +`v1.17.6` --- -### Phase P6 — regression-capability (Wave 4, test) +## Phase P7 — final-review-ship (final) -**Goal:** Add CAP-023 (metrics collector runs, emits expected schema) + -CAP-024 (deck structure: slide count, x3 present, per-slide benefit -present) to `core/regression_verify.py`. After P6, the regression gate -protects the metrics layer + the deck structure. +- **Wave:** 6 +- **Requirements covered:** all (REQ-214..228) — verification that every + requirement is complete; milestone ship. +- **Persona assignment:** lead-developer (review coordination + audit + + milestone ship) + backend-engineer (regression gate + technical + verification) + data-engineer (schema audit) +- **Description:** Multi-persona review of all v1.18 phases, audit of the + requirement coverage, regression gate run (CAP-023 metrics collector + + CAP-024 deck structure + the existing 22 capabilities), and milestone + ship: merge to main, tag `v1.17.7`, delete phase branches. -**Requirements covered:** REQ-198. +### Tasks -**Primary persona:** backend-engineer. **Supporting:** data-engineer -(CAP-023 schema). +1. **Review** — multi-persona review of P1–P6. Lead-developer verifies the + deck (21 slides, S&P theme, x3 arc, talking-points sync), RACI + + scope docs, and skills index. Backend-engineer verifies the MCP + server (4 tools, plugin-registry, vendored Atelier), the + submission-readiness validator (reason codes, CLI mode), and the + render/attach scripts. Data-engineer verifies the submission-readiness + schema (superset gate, per-env mandatory, no duplication of contract + fields). Findings recorded in `.ciagent/REVIEW.md`. +2. **Audit** — requirement coverage audit. Every REQ-214..228 is checked + against the shipped artifacts. The traceability table in + `REQUIREMENTS.md` §v1.18 is updated: all 15 requirements move from + `pending` → `complete (v1.17.x)`. Gaps are fixed before ship (no + partial shipments). +3. **Regression gate** — `bash scripts/run_regression.sh` (D-091) runs + all auto-verifiable capabilities. CAP-023 (metrics collector) + + CAP-024 (deck structure: 21 slides, x3 present, per-slide benefit + present) must pass. The existing 22 capabilities must stay Verified + (no regressions from v1.18's schema/code additions). +4. **Milestone ship:** + - Merge the milestone branch `milestone/v1.18-citizen-developer-guidance` + to `main`. + - Tag `v1.17.7` (the milestone release tag — final patch on the v1.17.x + line = the v1.18 milestone release per the tag-line decision). + - Force-move the floating `v1.17` + `v1` tags to `v1.17.7` (D-057 + precedent — consumers on `@v1.17` or `@v1` receive the update). + - Create the Gitea release for `v1.17.7` with an auto-generated body + (the v1.18 milestone summary). + - Attach the final PPTX to the `v1.17.7` release via + `scripts/attach_release_asset.py`. + - Delete the phase branches (`phase/01-sp-theme-restoration` through + `phase/06-deck-slides-atelier`) after merge. +5. **Update `.ciagent/` metadata** — ROADMAP.md §v1.18 marked complete; + PROJECT.md §v1.18 objective marked complete with the ship tag; + CAPABILITY_INVENTORY.md gains CAP-025 (submission-readiness gate) + + CAP-026 (Atelier MCP server) if the regression gate certifies them; + REVIEW.md updated with the v1.18 review content. -**Tasks (vertical slices):** +### Must-haves (verification gate) -1. **CAP-023 — metrics collector** — `core/regression_verify.py` gains a - `CAP-023` check: runs `core/metrics/collector.py` against a fixture - metrics dir, asserts the SQLite cold store has all fact/dim tables with - the expected schema, asserts idempotent re-run. Tags Verified/Decayed/Broken. - - *Acceptance:* `CAP-023` returns Verified when the collector produces - the correct schema; `test_regression_cap023` passes. +- [ ] All 15 requirements (REQ-214..228) are `complete` in the + `REQUIREMENTS.md` §v1.18 traceability table. +- [ ] `bash scripts/run_regression.sh` passes (all capabilities Verified; + CAP-024 deck structure regression passes at 21 slides). +- [ ] The milestone branch is merged to `main`. +- [ ] Tag `v1.17.7` exists; floating tags `v1.17` + `v1` point at it. +- [ ] The `v1.17.7` Gitea release exists with the PPTX attached. +- [ ] Phase branches are deleted. +- [ ] `.ciagent/ROADMAP.md` §v1.18 marked complete. +- [ ] `.ciagent/REVIEW.md` updated with v1.18 review content. -2. **CAP-024 — deck structure** — `core/regression_verify.py` gains a - `CAP-024` check: parses `docs/presentations/nova-no-humans-platform.md`, - asserts (a) slide count is in the expected range (12–20), (b) the x3 - structure is present (opening arc preview + closing recap), (c) each - slide has a benefit callout. Tags Verified/Decayed/Broken. - - *Acceptance:* `CAP-024` returns Verified when the deck meets all 3 - criteria; `test_regression_cap024` passes. +### Ship tag -3. **Regression gate run** — `bash scripts/run_regression.sh` runs the - full gate (22 prior capabilities + CAP-023 + CAP-024 = 24 total). All - must pass (Verified or Skipped per D-118). - - *Acceptance:* the regression report shows 24 capabilities, all - Verified or Skipped, 0 Decayed/Broken. - -**Must-haves:** -- `CAP-023` + `CAP-024` in `core/regression_verify.py`. -- `bash scripts/run_regression.sh` passes (24 capabilities, 0 Broken). -- `bash scripts/run_ci.sh` exits 0. - -**Risks + mitigations:** -- *Risk:* CAP-024's slide-count range is too tight and breaks on minor - deck edits. *Mitigation:* the range is 12–20 (generous); the check - focuses on structure (x3 + benefit callouts), not exact count. +`v1.17.7` (milestone release) --- -### Phase P7 — final-review-ship (Wave 4, review+audit+ship) - -**Goal:** Multi-persona review (incl. deck story quality), audit, and -milestone ship. After P7, v1.17 is complete and ready for the final merge. - -**Requirements covered:** all (review gate). - -**Primary persona:** lead-developer. **Supporting:** all active personas -(review participation). - -**Tasks (vertical slices):** - -1. **Multi-persona review** — each active persona reviews their territory: - - backend-engineer: event emitters, Decision Ledger, Infracost adapter, - regression CAP-023/024 code. - - data-engineer: collector, PowerBI export, schemas, data dictionary. - - lead-developer: NORTH_STAR integration, METRICS.md catalog, deck - narrative, no-humans thesis. - - Deck story quality review: the lead-developer reviews the deck for - narrative coherence, fluidity, and benefit-callout quality. - - *Acceptance:* review findings recorded; P0/P1 findings fixed before - ship; P2 findings logged for future milestones. - -2. **Audit** — verify: - - All 29 requirements (REQ-185..213) have a status of `complete` in - the traceability table. - - No stale claims in the deck (every metric citation has a grounded - source). - - `NORTH_STAR.md` is readable + referenced. - - The regression gate passes (24 capabilities). - - `bash scripts/run_ci.sh` exits 0. - - *Acceptance:* audit PASS recorded in `---ci---` block. - -3. **Milestone completion** — update `PROJECT.md`, `ROADMAP.md`, - `REQUIREMENTS.md` traceability to mark v1.17 complete. Tag `v1.16.7` - (P7 patch on the v1.16.x line). - - *Acceptance:* `PROJECT.md` reflects v1.17 complete; tag `v1.16.7` - exists. - -**Must-haves:** -- All 29 requirements marked complete. -- Multi-persona review complete (incl. deck story quality). -- Audit PASS. -- Regression gate 24/24 (Verified or Skipped). -- `bash scripts/run_ci.sh` exits 0. -- Tag `v1.16.7` exists. - -**Risks + mitigations:** -- *Risk:* Review surfaces a P0 finding late. *Mitigation:* the review is - scoped to each persona's territory; findings are fixed before the audit - step. - ---- - -### Phase P8 — milestone-ship (Final) - -**Goal:** Merge the milestone branch to main, tag `v1.16.8` (the milestone -release), publish the Gitea release, and delete the milestone branches. - -**Requirements covered:** all (ship gate). - -**Primary persona:** lead-developer. - -**Tasks (vertical slices):** - -1. **Merge to main** — merge `milestone/v1.17-strategic-metrics-deck` → - `main`. - - *Acceptance:* `main` contains all v1.17 commits; `git log main` shows - the milestone merge. - -2. **Tag + release** — tag `v1.16.8` on main; publish the Gitea release - (`Nova v1.16.8 — Strategic Direction, Leadership Metrics & Unified Story`) - with the release notes summarizing the three pillars. - - *Acceptance:* tag `v1.16.8` exists; Gitea release published (release - ID recorded). - -3. **Delete milestone branches** — delete `milestone/v1.17-strategic-metrics-deck` - + all `phase/NN-*` branches. - - *Acceptance:* `git branch -r` shows no v1.17 milestone/phase branches. - -**Must-haves:** -- `main` has the v1.17 merge. -- Tag `v1.16.8` exists. -- Gitea release published. -- Milestone + phase branches deleted. - -**Risks + mitigations:** -- *Risk:* Merge conflicts on main. *Mitigation:* the milestone branch is - off the v1.16 complete merge; rebase before merge if needed. - ---- - -## Deck Rebuild Plan - -> The unified deck: **"Nova — The No-Humans Infrastructure Platform."** -> 5-act arc: Problem → Vision → How → Proof → Roadmap. x3 at deck level -> (opening = arc preview, body = tell them, closing = recap + ask) + x3 -> per slide (opens with what it covers, delivers, closes with benefit -> callout). Fluid transitions written into each slide's opening line. -> Act indicator in the Marp footer (`Act N/5: `). - -### Deck-level x3 structure - -| Level | "What I'm going to tell you" | "Tell them" | "What I told you" | -|-------|------------------------------|-------------|-------------------| -| **Deck** | Slide 1 (arc preview: Problem→Vision→How→Proof→Roadmap; with 18V+0-consumer stake line) | Slides 2–15 (the 5 acts, 14 slides) | Slide 16 (recap of 5 acts + the business-decision ask) | -| **Per slide** | Opening line: "This slide shows X" | Body: bullets/diagram/table | Closing line: "Benefit: you now know Y" | - -### Act 1 — Problem (2 slides) - -> **Transition into Act 1:** (none — this is the opening; the arc preview -> slide sets up all 5 acts). - -**Slide 1 — Arc Preview (the "what I'm going to tell you" deck-level opening)** -- *Opens:* "This deck proves Nova is the no-humans infrastructure platform — - and shows you the metrics that make the claim defensible." -- *Stake line (G-Q8 binding):* "Today: 18 capabilities verified, 0 consumer - estates in production. This deck shows what's proven, what's pipeline-ready, - and what's honestly deferred." -- *Delivers:* The 5-act arc as a visual roadmap: Problem → Vision → How → - Proof → Roadmap. One-line summary per act. -- *Closes:* "Benefit: you leave this deck knowing which claims are proven - today, which are pipeline-ready, and which are deferred with a documented - unblock path — no marketing, just grounded evidence." -- *Grounded metrics cited:* 18 Verified + 4 Skipped (source: - `REGRESSION_REPORT.json`); 0 consumers (source: `PROJECT.md:495`). -- *Deferred metrics:* none. - -**Slide 2 — The No-Humans Imperative** -- *Opens:* "This slide shows why the operator is the bottleneck — and why - removing them from operations (not accountability) is the imperative." -- *Delivers:* The cost of humans-in-the-loop: L1/L2 ops hours, escalation - latency, the trust gap (autonomous claims without proof). Cites the - no-humans thesis (`docs/NO_HUMANS_THESIS.md`). -- *Closes:* "Benefit: you now know the problem framing — autonomy in - operations, human at stage gates, is the path forward." -- *Grounded metrics cited:* none (problem framing). -- *Deferred metrics:* none. -- *Transition into Act 2:* "Having defined the problem, here is Nova's - strategic direction toward solving it." - -### Act 2 — Vision/Direction (3 slides) - -> **Transition into Act 2:** "Having defined the problem, here is Nova's -> strategic direction toward solving it." - -**Slide 3 — Nova's Vision** -- *Opens:* "This slide states Nova's vision — infrastructure operations - become invisible, with provable trust." -- *Delivers:* The NORTH_STAR vision statement verbatim. The attestation - model: human attestation required at stage gates (QA for production, SRE - for operational readiness); autonomy in operations, not in - accountability. Cites `docs/NO_HUMANS_THESIS.md` (the thesis, grounded - proof, deferred proof, anti-claims incl. D-122 honesty). -- *Closes:* "Benefit: you now know the destination — invisible operations - with provable trust, not promised trust." -- *Grounded metrics cited:* none (vision). -- *Deferred metrics:* none. -- *Transition:* "The vision is ambitious — here are the 4 strategic - objectives that make it concrete." - -**Slide 4 — Strategic Objectives + Anti-Goals** -- *Opens:* "This slide pairs what Nova is building toward (4 objectives) - with what Nova refuses to build (5 anti-goals)." -- *Delivers:* The 4 strategic objectives (zero-touch ops, provable trust, - compounding ROI, default substrate for agentic consumption) + the 5 - anti-goals (not a hyperscaler competitor, not a general AI platform, not - removing humans from accountability, not for legacy infra, not sold to - operators). From `NORTH_STAR.md`. -- *Closes:* "Benefit: you now know the scope boundaries — Nova is - purpose-built for infrastructure operations, sold to leadership on - outcomes, and explicitly not a general-purpose AI platform or a - hyperscaler competitor." -- *Grounded metrics cited:* none (direction). -- *Deferred metrics:* none. -- *Transition:* "The objectives are committed to measurable targets — - here is the 12–18 month scorecard, with honest grounding status." - -**Slide 5 — 12–18 Month Targets (the scorecard)** -- *Opens:* "This slide shows the committed targets — numbers a board - member can repeat back — with their grounding status." -- *Delivers:* The NORTH_STAR targets table with the grounding column: - Touchless Resolution Rate ≥99% (grounded), Human Escalation <0.1% - (grounded), MTTR <60s (grounded, platform-run), AI Decision Accuracy - ≥99.5% (grounded), Decision Ledger Coverage 100% (grounded), - Attestation Coverage 100% (grounded), Cloud Spend Reduction ≥25% - (partial — Infracost grounded, CUR deferred), Platform ROI ≥250% - (derived), + deferred targets (Predictive vs Reactive, Drift Auto-Reversal, - AI-Agent Intent Share) marked **Planned**. -- *Closes:* "Benefit: you now know the destination numbers — and which - ones are measurable today vs deferred honestly." -- *Grounded metrics cited:* Touchless Resolution Rate, Human Escalation - Frequency, MTTR, AI Decision Accuracy, Decision Ledger Coverage, - Attestation Coverage — all `grounded` with source files. -- *Deferred metrics marked Planned:* Predictive vs Reactive, Drift - Auto-Reversal, AI-Agent Intent Share. -- *Transition into Act 3:* "The targets are committed — here is how Nova - works to achieve them." - -### Act 3 — How it works (4 slides) - -> **Transition into Act 3:** "The targets are committed — here is how -> Nova works to achieve them." - -**Slide 6 — The Platform Pipeline** -- *Opens:* "This slide shows the contract-to-evidence pipeline — how - intent becomes verified infrastructure without an operator." -- *Delivers:* The pipeline flow: contract → resolver → adapter → terraform - plan → Checkov (policy) → confidence signal → HITL gate (dev autonomous; - qa/prod/dr attested) → apply → evidence. Mermaid diagram. Grounded in - `scripts/run_platform.sh` + `core/contract_resolver.py` + - `adapters/terraform/adapter.py` + `core/confidence_signal.py`. -- *Closes:* "Benefit: you now know the path from intent to evidence — - and where the human appears (stage gates only)." -- *Grounded metrics cited:* none (architecture). -- *Deferred metrics:* none. -- *Transition:* "The pipeline produces decisions — here is how every - decision is captured and made accountable." - -**Slide 7 — The Decision Ledger** -- *Opens:* "This slide shows the Decision Ledger — every AI decision - captured with confidence, alternatives, and outcome." -- *Delivers:* The Decision Ledger architecture: `outbox_writer.py` - extended → SQLite append-only hash-chain table. `ai.decision.made` - events (decision_id=run_id, chosen_action=band, confidence=score, - alternatives=perInput, human_override=HITL block) with outcome backfill - from `apply.completed`. `attestation.recorded` events for qa/prod/dr. - D-121, D-122, D-132. Honors D-083 (no S3 Object Lock/JWS — local - hash-chain this milestone). -- **D-122 honesty sentence (G-Q4 binding):** "Nova's 'AI' is the - confidence-gated policy engine (confidence_signal + HITL gate), not - an LLM planner. The Decision Ledger captures this real decision path — - not a fabricated 'AI agent' that doesn't exist yet." -- *Closes:* "Benefit: you now know why 'autonomous' is defensible — every - decision is immutable, queryable, and accountable. And you know exactly - what 'AI' means here: a confidence-gated policy engine, not a black-box - LLM." -- *Grounded metrics cited:* Decision Ledger Coverage 100% (source: - `core/metrics/decision_ledger.py` + `metrics/decision_ledger.db`). -- *Deferred metrics marked Planned:* Tamper-Evident Ledger Checkpoints - (D-083). -- *Transition:* "Decisions are captured — here is how stage-gate - attestation keeps humans in accountability." - -**Slide 8 — The 8-Concern Attestation Matrix** -- *Opens:* "This slide shows the 8-concern attestation matrix — the - designed controls that keep humans at stage gates." -- *Delivers:* The 8 concerns (functional, performance, security posture, - contract NFRs, operational readiness, incident response, capacity/cost, - resilience). Offline-testable concerns run for real; operator-supplied - concerns accept signed evidence artifacts. Separation-of-duties on prod. - Grounded in `core/attestation_matrix.py` + `core/hitl_gates.py`. -- *Closes:* "Benefit: you now know the gate model — autonomy in - operations, human in accountability, by design." -- *Grounded metrics cited:* Attestation Coverage 100% (source: - `core/hitl_gates.py` + outbox `approver_*` attributes). -- *Deferred metrics:* none. -- *Transition into Act 4 (G-Q13 binding — rewritten):* "You've now seen - how Nova works — the pipeline, the Decision Ledger, the attestation - gates. But 'how it works' is not 'proof it works.' The next four slides - show the measured evidence: capability health, trust metrics, efficiency, - and cost — every number grounded in a real file, not a marketing claim." - -**Slide 9 — Telemetry Architecture (G-Q14 binding — benefit reframed from data plumbing to trust)** -- *Opens:* "This slide shows how Nova instruments itself — the - CloudEvents envelope, the cold store, and the PowerBI export." -- *Delivers:* The telemetry architecture diagram (from ARCHITECTURE.md - v1.17 addendum): platform components → CloudEvents 1.0 envelope → - `metrics/events.jsonl` + `metrics/runs/` + `metrics/decision_ledger.db` - → collector → `metrics/nova_metrics.db` (SQLite cold store) → - `metrics/powerbi/` (CSV/JSON views) → PowerBI. D-120 (Nova-native), - D-125 (hybrid events/files), D-126 (cold-only). -- *Closes:* "Benefit: you now know that every metric in this deck is - traceable to a real emitted event — the architecture IS the trust - substrate. When a CFO asks 'where does this number come from?', the - answer is a file path, not a Slack thread." -- *Grounded metrics cited:* none (architecture). -- *Deferred metrics marked Planned:* Hot-path (live ops dashboard) — D-126. -- *Transition into Act 4:* "The architecture is sound — here is the - measured proof." - -### Act 4 — Proof (4 slides) - -> **Transition into Act 4:** "The architecture is sound — here is the -> measured proof." - -**Slide 10 — Capability Health + Confidence Distribution** -- *Opens:* "This slide shows the grounded proof: capability health and - confidence distribution from real runs." -- *Delivers:* Capability health: 18 Verified + 4 Skipped (post-D-096 - teardown) from `.ciagent/REGRESSION_REPORT.json`. Confidence - distribution: from `metrics/nova_metrics.db` `fact_confidence` — score - histogram, band breakdown (pass/halt). The honesty model: Skipped is - honest (resources torn down per D-096), not a failure. -- *Closes:* "Benefit: you now know the platform is verified — 18 - capabilities pass, 4 are honestly skipped, 0 broken." -- *Grounded metrics cited:* Capability Health (source: - `REGRESSION_REPORT.json`), Confidence Distribution (source: - `metrics/nova_metrics.db` `fact_confidence`). -- *Deferred metrics:* none. -- *Transition:* "Capability health is necessary — here is the trust - substrate that makes autonomy defensible." - -**Slide 11 — Decision Ledger + Attestation Coverage** -- *Opens:* "This slide shows the trust metrics — Decision Ledger coverage - and attestation coverage, both 100%." -- *Delivers:* Decision Ledger Coverage: 100% of platform runs emit - `ai.decision.made` with outcome backfill (source: - `metrics/decision_ledger.db`). Attestation Coverage: 100% of prod/dr - promotions attested by a human (source: `hitl_gates.py` + outbox - `approver_*` attributes). AI Decision Accuracy: decisions not followed - by apply.failed/incident within 5min. The trust-snapshot report - (`metrics/TRUST_SNAPSHOT.md`) with chain-integrity verdict. -- *Closes:* "Benefit: you now know the trust is provable — not a marketing - claim, a queryable record." -- *Grounded metrics cited:* Decision Ledger Coverage, Attestation - Coverage, AI Decision Accuracy (source: `metrics/decision_ledger.db` + - `metrics/TRUST_SNAPSHOT.md`). -- *Deferred metrics:* Tamper-Evident Ledger Checkpoints (D-083) — Planned. -- *Transition:* "Trust is provable — here is the operational efficiency - that makes the ROI real." - -**Slide 12 — Zero-Touch Efficiency (G-Q10 binding — split from old slide 12)** -- *Opens:* "This slide shows the zero-touch efficiency metrics — - touchless resolution, human escalation, and MTTR." -- *Delivers:* Touchless Resolution Rate (runs without operational HITL - block ÷ total; attestation gates excluded). Human Escalation Frequency - (operational HITL blocks only). MTTR (platform-run: apply.failed → - successful retry, D-131). **Post-Pilot caveat (G-Q5 binding):** these - three metrics are computed on N internal runs today; the - production-denominator activates when a pilot estate runs (see - NORTH_STAR Post-Pilot Targets section). -- *Closes:* "Benefit: you now know the zero-touch efficiency is - measurable — the pipeline works today on internal runs, and the - denominator expands to production estates when a pilot activates." -- *Grounded metrics cited:* Touchless Resolution Rate, Human Escalation - Frequency, MTTR (source: `metrics/nova_metrics.db` `fact_run`). -- *Derived metrics:* none on this slide. -- *Deferred metrics marked Planned:* Self-Healing Velocity (no - auto-remediator). -- *Transition:* "Efficiency is half the ROI story — here is the cost - side." - -**Slide 13 — Cost & ROI (G-Q10 binding — split from old slide 12; G-Q15 binding — formula inline + N=0 caveat)** -- *Opens:* "This slide shows the cost estimates and the ROI formula — - with honest caveats about the current denominator." -- *Delivers:* Cost Estimates via Infracost (pre-apply, grounded). - **ROI formula shown inline (G-Q15 binding):** `Platform ROI = (FTE - hours saved × blended rate + cloud savings + avoided downtime) ÷ - platform op cost`. **N=0 caveat (G-Q5/G-Q15 binding):** "These - derived metrics are computed on N internal runs today; the - production-denominator activates post-pilot. The formula is grounded; - the production numbers are not yet." FTE Hours Saved (derived). Platform - ROI (derived formula). The grounded/derived/deferred honesty model. -- *Closes:* "Benefit: you now know the ROI formula — and you know it's - computed on internal runs today, not fabricated production numbers. - The formula is ready; the production denominator activates with a - pilot." -- *Grounded metrics cited:* Cost Estimates (source: - `metrics/nova_metrics.db` `fact_cost_estimate`). -- *Derived metrics:* FTE Hours Saved, Platform ROI (formula shown inline). -- *Deferred metrics marked Planned:* Live CUR Reconciliation (D-096), - Drift Auto-Reversal (D-096). -- *Transition:* "The proof is grounded — here is what is honestly - deferred." - -**Slide 14 — What's Deferred — and Why (G-Q11 binding — preempt: deferrals are measurement infra, not whether the platform runs without humans)** -- *Opens:* "This slide pairs each deferred metric with its blocking - decision — honesty about what isn't measured yet." -- **Preempt (G-Q11 binding):** "To be clear: these deferrals are - *measurement infrastructure*, not whether the platform runs without - humans. The platform IS autonomous in operations. What's deferred is - the *evidence pipeline* for certain metrics (live infra health, drift - detection, predictive remediation) — not the autonomy itself." -- *Delivers:* The 8 deferred metrics + onboarding-grant half, each paired - with its blocking decision ID: (1) Live Infrastructure Health — D-096, - (2) Live Outbox Write Rate — D-096, (3) Tamper-Evident Ledger - Checkpoints — D-083, (4) Onboarding Funnel (granted) — D-113/D-114/D-119, - (5) Drift Auto-Reversal — D-096 + no scheduler, (6) Live CUR - Reconciliation — D-096, (7) SLA / Unplanned Downtime — D-096, - (8) Predictive vs Reactive — future emitter. From - `docs/METRICS_DEFERRED_ROADMAP.md`. -- *Closes:* "Benefit: you now know the boundaries — what Nova measures - today, and exactly what blocks the rest. The autonomy is real; the - measurement gaps are documented." -- *Grounded metrics cited:* none (deferral honesty). -- *Deferred metrics:* all 8 + onboarding-grant half, each with decision ID. -- *Transition into Act 5:* "The proof is honest — here is the roadmap - from here to the 12–18 month targets." - -### Act 5 — Roadmap/Ask (2 slides) - -> **Transition into Act 5:** "The proof is honest — here is the roadmap -> from here to the 12–18 month targets." - -**Slide 15 — Roadmap to the North Star** -- *Opens:* "This slide shows the path from v1.17's grounded metrics to - the 12–18 month targets — the unblock path for each deferred metric." -- *Delivers:* The deferred-metrics activation roadmap (from - `docs/METRICS_DEFERRED_ROADMAP.md`): each deferred metric → blocking - decision → unblock requirement → candidate milestone. The hot-path - activation section (post-D-096, Nova-native only, D-120). Re-evaluation - triggers. -- *Closes:* "Benefit: you now know the path — every deferred metric has - an unblock requirement and a candidate milestone." -- *Grounded metrics cited:* none (roadmap). -- *Deferred metrics:* all 8 referenced with unblock paths. -- *Transition:* "The roadmap is clear — here is the recap and the ask." - -**Slide 16 — Recap + Ask (the "what I told you" deck-level closing; G-Q16 binding — ask reframed as a business decision)** -- *Opens:* "This slide recaps the 5 acts and states the ask." -- *Delivers:* Recap: Problem (operator bottleneck) → Vision (invisible - ops, provable trust) → How (pipeline + Decision Ledger + attestation) → - Proof (18V+4S, 100% ledger coverage, 100% attestation, grounded ROI - formula) → Roadmap (deferred metrics have unblock paths). **The ask - (G-Q16 binding — reframed as a business decision, not insider - language):** "The ask is a business decision: approve a pilot estate - to activate the production-denominator metrics (Touchless Resolution, - Human Escalation, AI Decision Accuracy), and approve the tamper- - evident ledger build-out (D-083 lift) to move from local hash-chain - to S3 Object Lock + JWS. These two decisions move Nova from - 'pipeline-ready' to 'production-proven.'" -- *Closes:* "Benefit: you leave with a clear business decision to make - — approve a pilot + the ledger build-out — and the confidence that - every claim in this deck is grounded, derived, or honestly deferred." -- *Grounded metrics cited:* Capability Health, Decision Ledger Coverage, - Attestation Coverage (recap). -- *Deferred metrics:* referenced as the ask. - -### Appendix slides (2 slides) - -**Slide A1 — Metrics Glossary** -- *Opens:* "This appendix defines every KPI in one line with its grounding - badge." -- *Delivers:* One-line definitions for all KPIs with grounded/derived/ - deferred badges. REQ-202. -- *Closes:* "Benefit: you now have a reference for every metric mentioned - in the deck." -- *Grounded metrics cited:* all (glossary). -- *Deferred metrics:* all (badged). - -**Slide A2 — Operating Model & Cost** -- *Opens:* "This appendix shows the real cost figures + the zero-cost - steady state." -- *Delivers:* `COST.md` figures ($0.001883 / 8 days, ~$0.007/mo, - S3-dominated, zero BAU compute) + the zero-cost-steady-state / D-096 - teardown claim. References the pre-mortem (`PRE_MORTEM.md`: v1.10 decay - root cause + four forward failure modes + structural mitigations). -- *Closes:* "Benefit: you now know the operating cost is negligible — and - the structural mitigation that prevents decay." -- *Grounded metrics cited:* Cost figures (source: `COST.md`). -- *Deferred metrics:* none. - -### Fluidity strategy - -1. **Every slide's opening line references the previous slide's close.** - Each slide above has an explicit transition sentence. No disjointed - jumps. The Act 3→4 boundary (slide 9→10) was rewritten per G-Q13 - binding: "But 'how it works' is not 'proof it works.'" -2. **Act indicator in the Marp footer.** `Act N/5: ` keeps the - audience oriented. Configured in the Marp theme. -3. **The arc is visible.** Slide 1 (arc preview + stake line) + slide 16 - (recap + business-decision ask) bookend the deck. The audience always - knows where they are in the 5-act structure. -4. **Per-slide benefit callout is the last line.** Every slide closes with - "Benefit: ..." — the audience leaves each slide with a takeaway, not a - cliffhanger. Benefit callouts rewritten per G-Q9 binding (slides 1, 4, - 13, 16 now give specific value, not generic restatements). -5. **The Proof act is the centerpiece.** It is 5 slides (the longest act, - expanded from 4 per G-Q10 binding: slide 12 split into Zero-Touch - Efficiency + Cost & ROI) because the PO's direction is "prove it, don't - promise it." The grounded/derived/deferred honesty model is the - narrative spine of the Proof act. -6. **Deferred metrics are shown, not hidden.** Slide 14 ("What's Deferred - — and Why") pairs each deferred metric with its blocking decision, - with a preempt (G-Q11 binding) clarifying that deferrals are - measurement infrastructure, not whether the platform runs without - humans. -7. **The D-122 honesty sentence on slide 7.** The deck explicitly states - that Nova's "AI" is the confidence-gated policy engine, not an LLM - planner — per G-Q4 binding. This prevents the "no fabrication" - constraint from being violated by implication. -8. **Derived metrics carry the N=0 caveat.** Slides 12 and 13 annotate - derived metrics (FTE, ROI) with "computed on N internal runs; - production-denominator activates post-pilot" — per G-Q5/G-Q15 binding. - The ROI formula is shown inline (G-Q15). - -### Deck file inventory (after P5) - -| File | Status | -|------|--------| -| `docs/presentations/nova-no-humans-platform.md` | NEW (source of truth, 16 main + 2 appendix slides per G-Q10 split) | -| `docs/presentations/nova-no-humans-platform-marp.md` | NEW (Marp) | -| `docs/presentations/nova-no-humans-platform.html` | NEW (rendered) | -| `docs/presentations/nova-no-humans-platform-talking-points.md` | NEW (talking points) | -| `docs/presentations/how-the-platform-works.md` | DELETED (retired, D-130) | -| `docs/presentations/how-the-platform-works-marp.md` | DELETED | -| `docs/presentations/how-the-platform-works.html` | DELETED | -| `docs/presentations/how-the-platform-works-talking-points.md` | DELETED | -| `docs/presentations/the-developer-experience.md` | DELETED (retired, D-130) | -| `docs/presentations/the-developer-experience-marp.md` | DELETED | -| `docs/presentations/the-developer-experience.html` | DELETED | -| `docs/presentations/the-developer-experience-talking-points.md` | DELETED | - ---- - -## Wave Dependency Graph - -``` -Wave 1 Wave 2 Wave 3 Wave 4 Final - ┌──────────────────┐ ┌──────────────────┐ ┌──────────────┐ -P1 (event emitters)──┤P2 (collector) │ │P4 (catalog + │ │P6 (regression│ P8 - │ P3 (powerbi │──▶│ NORTH_STAR │──▶│ capability) │──▶(ship) - │ export) │ │ integration) │ │P7 (review + │ - └──────────────────┘ │P5 (deck rebuild) │ │ audit + ship)│ - └──────────────────┘ └──────────────┘ - -Critical path: -P1 ──▶ P2 ──▶ P3 ──▶ P4 ──▶ P5(Proof) ──▶ P6 ──▶ P7 ──▶ P8 - -Parallelization: - Wave 2: P2 schemas + P3 view schemas can be authored concurrently. - Wave 3: P4 docs/metrics/*.md + P5 Problem/Vision/How acts can be authored - concurrently; P5 Proof act waits for P4 METRICS.md. - Wave 4: P6 CAP-023 test can be drafted while P5 finishes. -``` - -**Dependency details:** - -| Phase | Depends on | Blocks | -|-------|------------|--------| -| P1 | (none — foundation) | P2, P3, P4, P5, P6 | -| P2 | P1 (event formats) | P3 (SQLite store), P4 (catalog sources), P6 (CAP-023) | -| P3 | P2 (SQLite store) | P4 (PowerBI view references), P6 (CAP-023 schema) | -| P4 | P2 + P3 (grounded metrics) | P5 (Proof act citations), P6 (CAP-024 deck structure) | -| P5 | P4 (METRICS.md for Proof act) | P6 (CAP-024 deck structure) | -| P6 | P2 + P3 (CAP-023) + P5 (CAP-024) | P7 (regression gate must pass) | -| P7 | P1–P6 (all prior phases) | P8 (audit must pass) | -| P8 | P7 (milestone complete) | (none — terminal) | - ---- - -## Execution approach - -- **Per-phase ship:** each execution phase merges `phase/NN-*` → - `milestone/v1.17-strategic-metrics-deck` and tags a patch on the v1.16.x - line (`v1.16.1` = P1 ... `v1.16.7` = P7, `v1.16.8` = P8 final). -- **Verification:** 4-layer verify (structural/behavioral/security/quality) - per phase; the regression gate (D-091, 22 prior + CAP-023 + CAP-024 = 24 - capabilities) runs at P6 and P7. -- **No live AWS:** `NOVA_LIFECYCLE_MODE=plan` default; all metrics that - require live AWS ship as placeholder views (D-096). Infracost runs - offline (reads plan JSON, A6). -- **Test discipline:** each phase that changes runtime code adds/updates - tests; `bash scripts/run_ci.sh` exits 0 at every phase boundary. -- **No fabrication:** every metric carries a grounded/derived/deferred - status with a source file or decision ID. No fabricated numbers in any - deck slide or METRICS.md entry. -- **Decision discipline:** D-120..D-132 are locked. This plan does not - re-open any locked decision. If a decision needs revisiting, it goes - through the GRILL, not the plan. \ No newline at end of file +## Plan-Level Risks + Notes + +1. **Atelier tag drift (A-1, conf 0.92).** The vendored tag is `v0.3.6` + (fetched 2026-08-05). If a v0.5 milestone lands before P5 ships, the + pin is stale — but the VERSION.md + `update_atelier_vendor.sh` model + makes a future upgrade a deliberate, audited action, not silent drift. + P5 should re-verify the latest Atelier tag at execution time and + document any divergence in VERSION.md. +2. **MCP Python SDK v2 import name (A-2, conf 0.88).** The high-level + server class is `MCPServer` (NOT `FastMCP`, which was v1). If a + future SDK patch restores a `FastMCP` alias, both imports would work, + but the v2 canonical name is `MCPServer`. P5 should verify the import + against the installed SDK version at execution time. +3. **`mcp.run()` stdio entry point (A-3, conf 0.85).** The exact `run()` + signature for stdio vs HTTP is not fully spelled out on the SDK + landing page. P5 should verify the exact run call from the "Running + your server" docs page before finalizing `server.py`. If stdio + requires an explicit transport argument, the fix is a one-line change + in `server.py` (D-135 — the server object is transport-agnostic). +4. **Submission-readiness validator wiring (A-7, conf 0.80).** D-133 + places the readiness gate as `contract_ingestor.py --check-readiness` + (a CLI pre-flight). REQ-218 says "On pass → proceeds to existing + contract ingestion" — this is satisfied by the CLI path (the citizen + developer runs `--check-readiness` before submitting). Whether the + Lambda path ALSO gates on readiness (a pre-write gate in + `_submit_contract`) is a P3 implementation decision. The plan + defaults to CLI-only (the Lambda path is unchanged) to avoid changing + the Lambda's behavior mid-milestone; the Lambda gate can be added in + a future milestone if desired. +5. **PPTX binary in git (D-141).** Committing the PPTX binary directly + (no LFS) is the decision. Decks are small (~1–5 MiB); git handles + binary blobs. Binary diffs are not delta-friendly, but deck changes + are infrequent (3 times this milestone). If the repo grows + significantly, a future milestone may reconsider LFS — but only if + git.cloudinit.dev confirms LFS server-side support. +6. **Wave 3 parallelism (P3‖P4) is theoretical.** This run executes + sequentially (P3 then P4). The parallelism is noted for future + parallelization-enabled runs. The two phases have zero file overlap + (P3: `schemas/`, `core/`, `tests/`, `docs/submission-readiness.md`; + P4: `skills/`, `docs/skills.md`, `PROJECT.md` BA.A) so they COULD run + concurrently without conflict. +7. **Deck slide numbering.** P2 adds slides 19 + 20 (scope + RACI) → 20 + slides. P6 adds slide 21 (Atelier) → 21 slides. The Arc Preview slide + is updated in both P2 (to 20) and P6 (to 21). The 5-act arc (D-130) + is preserved throughout — the new slides are append-only context, not + a new act (D-134). +8. **No new frontend (frontend-engineer deactivated).** v1.18 has no + frontend; decks are markdown (lead-developer territory); the MCP + server exposes tools to an AI agent, not a web UI. The + frontend-engineer persona stays deactivated (PERSONAS.md v1.18 + roster). No reactivation trigger in this milestone. \ No newline at end of file diff --git a/.ciagent/PROJECT.md b/.ciagent/PROJECT.md index 2ffa95a..07c5df4 100644 --- a/.ciagent/PROJECT.md +++ b/.ciagent/PROJECT.md @@ -598,6 +598,90 @@ utility, unrelated to presentations). No code changes; 494 tests pass; `run_ci.sh` + `run_platform.sh --check-only` green. PPTX files uploaded to Gitea release. +## Objective for Milestone v1.18 (active — Citizen Developer & Production-Grade Guidance) + +v1.18 advances Nova from a platform that governs infrastructure delivery +to one that **instructs the citizen developer on production-grade +engineering** and defines a **clear, machine-checkable contract for what +is acceptable to start**. Five user-directed inputs drive the milestone: + +1. **S&P Global theme restoration.** The v1.17 P5 deck rebuild consolidated + two decks into one unified narrative deck but lost the S&P Global Energy + brand visual identity (introduced v1.9.2 / P45, commit `ae0cb58`). The + Marp `style:` block (red-core `#D6002A`, grey-90 `#1B1B1B`, Akkurat Pro + font, 8px top accent bar) is restored to the unified deck. The mermaid + `sp-theme.json` survived; only the Marp CSS theme was lost. + +2. **PDLC-upstream scope made explicit.** Core Tenet #2 already states the + platform "does not penetrate upstream product/SDLC" and Anti-Goal #1 says + "Not an upstream development platform." v1.18 promotes this from a + buried tenet to a dedicated, unmissable scope statement in PROJECT.md + + `docs/scope.md` + a deck slide: **the PDLC (Product Development + Lifecycle — product backlog, code authorship, IDE) is upstream of Nova; + Nova governs infra + delivery only; integration is through the validated + contract boundary.** + +3. **RACI matrix.** A three-role responsibility matrix clarifies who owns + what: **Citizen Developer** (Responsible for all Functional Requirements + + User Acceptance Testing, via their AI coding agent / upstream agentic + SDLC / upstream development platform — the source does not matter as all + are subject to the same compliance standards), **Platform** (Responsible + for all NFRs + Infrastructure + QA + Production deployments to cloud), + **Release Management** (co-owned: QA + SRE attestations required by the + actual release, performed agentically but overseen & triggered by the + Citizen Developer). Source of truth in PROJECT.md + `docs/raci.md` + a + deck slide. + +4. **Nova input contract — "what is acceptable to start."** A JSON Schema + (`schemas/submission-readiness.schema.json`) defines the + acceptable-to-start gate as a superset *above* contract-schema validity: + schema-valid contract + required Nova tags + per-env mandatory metadata + (per W3.E) + declared policy preconditions + (for L3B) `profile:agentic` + markers + `appSource` pointer. A validator (`core/submission_readiness.py`, + invoked as `contract_ingestor.py --check-readiness`) returns a structured + `ReadinessResult` with reason codes. On fail → citizen-developer-facing + error (not a stack trace); on pass → proceeds to existing ingestion. + +5. **Atelier integration — production-grade guidance + agentic validation.** + Nova consumes `coreci/atelier` (a first-principles docs-as-code + engineering framework — 8 core principles, 19 domains, 190 P-rules) via + two surfaces: **skills** (markdown files under `skills/` keyed to Atelier + domain paths, surfaced to the citizen developer's AI agent, extending the + BA.A 5-skill catalog) and an **MCP server** (`mcp/atelier/server.py`, + plugin-registry architecture, stdio transport, vendored Atelier snapshot + for audit reproducibility) exposing tools for principle-lookup, + domain-listing, matrix-lookup, and agentic validation against the + Atelier agent-checklist — validation that goes beyond deterministic + scanners (Wiz/Checkmarx/Mend) by catching correctness/clarity/simplicity/ + observability gaps. + +**Deck automation (cross-cutting):** any phase modifying +`docs/presentations/*-marp.md` or `docs/presentations/assets/` MUST +re-render HTML + PPTX, **commit the PPTX to git** (binary, no LFS), and +attach it to the phase's Gitea release. New scripts: +`scripts/render_deck.sh` (HTML + PPTX render) and +`scripts/attach_release_asset.py` (Gitea release asset upload). + +**Milestone type:** Feature (P1 S&P theme restoration + P3 readiness +schema/validator + P5 MCP server are new code/features). Tags run on the +**v1.17.x** patch line (previous minor per branch-strategy): `v1.17.0` (P0) +→ `v1.17.1..v1.17.6` (P1–P6) → `v1.17.7` (P7 final = milestone release). + +**Phase count:** 8 (P0 pre-execution + 6 execution + 1 final). + +**Hard constraints:** +- DO NOT make anything up (NORTH_STAR.md honesty model). +- The submission-readiness schema is a superset gate above + `contract.schema.json`, NOT a duplicate — it references but does not + redefine contract fields. +- The MCP server is plugin-registry extensible (future capabilities drop + in as new plugin files, no `server.py` edits). +- Atelier is vendored (pinned tag) for audit reproducibility — an agentic + validation result must be replayable against the exact principles that + produced it. +- PPTX is a first-class artifact: committed (history) + attached (download) + — both always, not optional. + ## Requirements ### v1.0 (Prior milestone — the demo) @@ -1133,4 +1217,22 @@ P7 review+audit+ship). Tags on the v1.16.x line: `v1.16.0` (P0) → | D-129 | PowerBI delivery = CSV/JSON files, folder connector. | Nova is offline-first; no live connector to a running service. PowerBI ingests via the folder connector. | P3 emits CSV/JSON to metrics/powerbi/. | | D-130 | Deck arc = Problem → Vision → How → Proof → Roadmap. | The unified narrative deck's 5-act structure. x3 arc at deck + slide level. Per-slide benefit callouts. Fluid transitions. Both old decks retired. | P5 builds the unified deck; old decks deleted. | | D-131 | MTTR scope = platform-run MTTR. | The <60s MTTR target refers to platform-run failures (apply.failed → successful retry), not infra-incident MTTR (no incident detection system). Infra-incident MTTR deferred. | P4 grounds platform-run MTTR. | -| D-132 | Attestation instrumentation = emit attestation.recorded events. | The attestation system (hitl_gates.py + attestation_matrix.py + separation_of_duties.py) already exists. Instrument it: emit attestation.recorded events into the Decision Ledger + PowerBI. Attestation Coverage = 100% target grounded from outbox approver_* attributes. | P1 emits attestation events; P4 grounds Attestation Coverage. | \ No newline at end of file +| D-132 | Attestation instrumentation = emit attestation.recorded events. | The attestation system (hitl_gates.py + attestation_matrix.py + separation_of_duties.py) already exists. Instrument it: emit attestation.recorded events into the Decision Ledger + PowerBI. Attestation Coverage = 100% target grounded from outbox approver_* attributes. | P1 emits attestation events; P4 grounds Attestation Coverage. | + +## Key Decisions (v1.18) + +Resolved at the CLARIFY stage (full autonomy — all within locked +constraints or user-directed scope). New v1.18 decisions: + +| ID | Decision | Rationale | Outcome | +|----|----------|-----------|---------| +| D-133 | Submission-readiness validator location = extend `contract_ingestor.py --check-readiness`. | Adding a new CLI binary is unnecessary; the ingestor is the existing entry point for contract submission. The validator is a subcommand that runs before ingestion proceeds. No new binary, no new entry point to maintain. | P3 implements the subcommand; no new CLI binary. | +| D-134 | Deck slide budget = 18 → 21 slides (no act restructure). | The 3 new slides (scope/RACI/atelier) are leadership-relevant and append after the existing 18. The 5-act arc (D-130) is preserved; the new slides are append-only context, not a new act. | P6 appends 3 slides → 21 total. | +| D-135 | Atelier MCP transport = stdio now; HTTP-ready (same server object). | stdio is the local-agent transport (the citizen developer's AI agent spawns the server as a subprocess). The MCP Python SDK v2 supports Streamable HTTP on the same `MCPServer` object, so adding HTTP later is a transport-only change in `server.py`, not a rewrite. | P5 ships stdio; HTTP deferred (documented in README). | +| D-136 | Atelier source = vendor pinned tag under `mcp/atelier/vendor/`. | An agentic validation result is only reproducible if the principles that produced it are pinned. Live-fetch breaks replayability (Atelier `main` drifts). Vendoring matches the v1.16 P15 offline-first precedent and the Nova thesis (provable trust). `mcp/atelier/vendor/VERSION.md` records the pinned tag; `scripts/update_atelier_vendor.sh` is the intentional upgrade path. | P5 vendors Atelier; live-fetch not implemented. | +| D-137 | MCP server language = Python (MCP Python SDK v2, `modelcontextprotocol/python-sdk`). | Nova's `core/` is Python. The MCP Python SDK v2 (23.9k stars, MIT, stable) matches the codebase; type hints become JSON Schema automatically (`@mcp.tool()` decorator). | P5 uses Python SDK v2. | +| D-138 | Skill catalog format = markdown files under `skills/` keyed to Atelier domain paths. | Markdown is the established Nova docs format (Jekyll Pages, 4-step deck process). Each skill file names the Atelier source path, distills the first-principles, links to agent-checklist triggers, and maps to the BA.A catalog. | P4 authors 9 markdown skill files. | +| D-139 | RACI role names = Citizen Developer / Platform / Release Management (co-owned). | User-specified. The 3 roles are the columns of the RACI table. Release Management is co-owned: QA + SRE attestations are required by the actual release (performed agentically, overseen & triggered by the Citizen Developer). | P2 authors the RACI with these 3 roles. | +| D-140 | MCP server extensibility = plugin-registry (`plugins/.py` implementing `register(mcp)`). | Future capabilities (new scanners, policy evaluators, cost tools) drop in as new plugin files — no `server.py` edits. `server.py` scans `plugins/` and calls `register` on each. This is the extensibility insurance: plugins are decoupled from the server entrypoint. | P5 implements the plugin-registry; initial plugins are `principles.py` + `validation.py`. | +| D-141 | PPTX storage = commit binary directly to `docs/presentations/` (no LFS). | Decks are small (~1-5 MiB); git handles binary blobs. LFS requires server-side support (unverified for git.cloudinit.dev) + client config. Committing directly is simplest and works without any repo/server config. Binary diffs are not delta-friendly, but deck changes are infrequent. | P1/P2/P6 commit .pptx directly. | +| D-142 | Deck render trigger = any phase modifying `docs/presentations/*-marp.md` or `docs/presentations/assets/` must re-render HTML + PPTX, commit PPTX, and attach to the Gitea release. | PPTX was previously manual + release-only (not committed). v1.18 makes it a first-class artifact: committed (history) + attached (download), both always, not optional. Automated via `scripts/render_deck.sh` + `scripts/attach_release_asset.py`. | P1/P2/P6 run the render+commit+attach pipeline. | \ No newline at end of file diff --git a/.ciagent/REQUIREMENTS.md b/.ciagent/REQUIREMENTS.md index 41052c9..a1bc882 100644 --- a/.ciagent/REQUIREMENTS.md +++ b/.ciagent/REQUIREMENTS.md @@ -1180,3 +1180,177 @@ with documented schemas. - A third deck — the two existing decks merge into one; no new standalone metrics deck. - A Nova web UI — dashboards are PowerBI, not a Nova-built frontend. + +--- + +## v1.18 — Citizen Developer & Production-Grade Guidance + +> **Milestone type:** Feature. Tags run on the v1.17.x patch line (previous +> minor per branch-strategy). `v1.17.0` (P0) → `v1.17.1..v1.17.6` (P1–P6) → +> `v1.17.7` (P7 final = milestone release). +> **Active milestone:** v1.18. **Branch:** +> `milestone/v1.18-citizen-developer-guidance`. + +### Requirements + +- **REQ-214** — S&P Global Energy Marp theme restored in the unified deck + (`docs/presentations/nova-no-humans-platform-marp.md`). The `style:` block + from commit `ae0cb58` (v1.9.2 / P45) is ported: H1/H2 `#D6002A` + (S&P red-core), title-slide bg `#1B1B1B` (grey-90) with 8px `#D6002A` top + accent bar, body text `#1B1B1B`, blockquote border `#D6002A`, + table headers `#F0F0F0`, font `'Akkurat Pro'` with web-safe fallbacks. The + current Nova header/footer text is preserved (rebrand is not touched — + only the visual theme is restored). HTML re-rendered with the S&P theme. + +- **REQ-215** — RACI matrix authored in `PROJECT.md` (new `## RACI Matrix` + section) and `docs/raci.md` (citizen-developer-facing copy). Three roles: + **Citizen Developer** (Responsible for all Functional Requirements + User + Acceptance Testing — via their AI coding agent / upstream agentic SDLC / + upstream development platform; the source does not matter as all are + subject to the same compliance standards), **Platform** (Responsible for + all NFRs + Infrastructure + QA + Production deployments to cloud), + **Release Management** (co-owned: QA + SRE attestations required by the + actual release, performed agentically but overseen & triggered by the + Citizen Developer). Rendered as a table: rows = work categories (FRs, UAT, + NFRs, Infra, QA, Prod deploy, Release attestation), columns = R/A/C/I per + role. Includes the compliance-standard-equivalence note. + +- **REQ-216** — PDLC-upstream scope statement made explicit in `PROJECT.md` + (new `## Scope: Nova is Downstream of PDLC` subsection under Domain + Boundaries) and `docs/scope.md`. States that the PDLC (Product Development + Lifecycle — product backlog, code authorship, IDE) is upstream of Nova; + Nova governs infra + delivery only; integration is through the validated + contract boundary. Promotes Core Tenet #2 + Anti-Goal #1 from buried + tenets to a dedicated, unmissable scope statement. + +- **REQ-217** — `schemas/submission-readiness.schema.json` (JSON Schema + draft 2020-12) defines what is acceptable to start — a superset gate + *above* `contract.schema.json` validity. Required fields: `contractId` + (non-empty), `environment` (dev/qa/prod/dr) with the W3.E per-env mandatory + table enforced (dev: stack+environment; qa: +validation.e2eSuite + +validation.loadTest; prod: +runbook+dashboard+oncall; dr: +drDrillRef), + `tags` (the 5 required Nova tags per D-054: `nova:owner`, `nova:contract`, + `nova:environment`, `nova:cost-center`, `nova:ref`), `policyPreconditions` + (declared policy expectations the platform will enforce, e.g., + `public-ingress: false`), `profile` (`developer` or `agentic`; if + `agentic`, requires `naturalLanguageIntent`, `confidenceAtSubmission`, + `agentTrace` per REQ-22 / W3.E), `appSource` (repo + ref pointer for + runtime fetch). + +- **REQ-218** — `core/submission_readiness.py` validator, invoked as + `contract_ingestor.py --check-readiness` subcommand (decision D-133). Returns + a structured `ReadinessResult` (pass/fail per check, with reason codes). + On fail → the ingestor rejects with a citizen-developer-facing error + (not a stack trace). On pass → proceeds to existing contract ingestion. + Calls `contract.schema.json` validation first, then the readiness checks. + Reason codes: `MISSING_TAGS`, `ENV_MISSING_MANDATORY::`, + `AGENTIC_MISSING_INTENT`, `MISSING_APP_SOURCE`, `POLICY_PRECONDITION_MISSING`. + +- **REQ-219** — `docs/submission-readiness.md` citizen-developer-facing doc + explaining what is acceptable to start, with good + rejected examples and + the reason-code catalog. References `schemas/submission-readiness.schema.json` + as the source of truth. + +- **REQ-220** — `tests/test_submission_readiness.py` covers: good contract + passes; missing tags fail with `MISSING_TAGS`; missing env mandatory fails + with `ENV_MISSING_MANDATORY::`; agentic profile missing intent + fails with `AGENTIC_MISSING_INTENT`; missing appSource fails with + `MISSING_APP_SOURCE`. + +- **REQ-221** — `skills/` directory with 9 Atelier-derived skill files mapped + to the BA.A citizen-developer catalog: `skills/api.md` (domains/api/), + `skills/security.md` (domains/security/), `skills/data.md` (domains/data/), + `skills/testing.md` (domains/testing/), `skills/observability.md` + (domains/observability/), `skills/errors.md` (domains/errors/), + `skills/devops.md` (domains/devops/), `skills/infrastructure-as-code.md` + (domains/infrastructure-as-code/), `skills/compliance.md` + (domains/compliance/). Each names the Atelier source path, distills the + first-principles to the citizen-developer-relevant subset, links to + agent-checklist triggers, and maps to the BA.A 5-skill catalog (web API, + worker, scheduled job, static asset, basic observability bootstrap). + +- **REQ-222** — `docs/skills.md` index page listing the skill catalog, the + Atelier provenance, and how the citizen developer's AI agent consumes them + (read before completing a task; run `review/agent-checklist.md` before + finishing). `PROJECT.md` BA.A decision extended with the Atelier-derived + skill catalog reference. + +- **REQ-223** — `mcp/atelier/server.py` MCP server (stdio transport, + decision D-135) with a **plugin-registry architecture** (decision D-140): + `plugins/.py` modules each expose `register(mcp: MCPServer) -> None` + and call `@mcp.tool()` for their tools; `server.py` scans `plugins/` and + calls `register` on each. Initial plugins: `principles.py` + (`atelier.lookup_principle`, `atelier.list_domains`, `atelier.matrix_lookup`) + and `validation.py` (`atelier.validate_against_principles` — agentic + validation against the Atelier agent-checklist, beyond Wiz/Checkmarx/Mend). + Uses the MCP Python SDK v2 (`modelcontextprotocol/python-sdk`). + +- **REQ-224** — `mcp/atelier/vendor/` vendored Atelier snapshot (pinned tag, + decision D-136) for audit reproducibility. `mcp/atelier/vendor/VERSION.md` + records the pinned tag + a `scripts/update_atelier_vendor.sh` helper for + intentional upgrades. `mcp/atelier/README.md` documents the server: how to + run, transport, tool catalog, plugin-authoring guide, vendoring policy. + +- **REQ-225** — `tests/test_atelier_mcp.py` covers: tool registration (all 4 + tools discoverable via `tools/list`), `atelier.lookup_principle` returns + the principle text + core C-rule, `atelier.validate_against_principles` + catches a planted C1 (correctness) + C7 (observability) violation in a + known-bad snippet and passes a known-good snippet, `atelier.matrix_lookup` + returns the domain→core mapping, plugin discovery loads all plugins in + `plugins/`. + +- **REQ-226** — 3 new deck slides added to the unified deck + (`docs/presentations/nova-no-humans-platform-marp.md`) → 21 slides total: + Slide 19 "Scope: Downstream of PDLC", Slide 20 "RACI: Who Owns What", + Slide 21 "Production-Grade Guidance via Atelier". Arc Preview slide + updated to reflect 21-slide count. Talking points + (`nova-no-humans-platform-talking-points.md`) synced for the 3 new slides. + S&P theme preserved (regression check vs P1). CAP-024 deck structure + regression passes. + +- **REQ-227** — `docs/presentations/README.md` slide count + deck table + updated to reflect 21 slides + the 3 new slide titles. + +- **REQ-228** — `scripts/render_deck.sh` (renders HTML + PPTX from a Marp + deck, commits both to git) and `scripts/attach_release_asset.py` (uploads + a file to a Gitea release via the API). Any phase modifying + `docs/presentations/*-marp.md` or `docs/presentations/assets/` MUST + re-render HTML + PPTX, commit the PPTX binary to `docs/presentations/`, + and attach it to the phase's Gitea release. PPTX is stored as a committed + binary (no LFS, decision D-141). + +### Out of Scope (v1.18) + +- **Streamable HTTP transport for the MCP server** — stdio ships now; HTTP + is a future milestone (the SDK supports it on the same server object, so + adding it later is a transport-only change, not a rewrite). +- **A Nova-built frontend / dashboard** — observability stays PowerBI / + external; no Nova web UI. +- **Replacing the existing BA.A 5-skill catalog** — the Atelier-derived + skills extend it, not replace it. +- **Live AWS re-provisioning** (D-096, still deferred) — submission-readiness + validates the contract shape, not a live AWS deployment. +- **A second forge adapter** (GitLab) — BA.F cross-platform evolution is + future work. +- **Atelier live-fetch mode** — vendoring is the only mode this milestone; + live-fetch (with its reproducibility trade-offs) is not implemented. + +### v1.18 Traceability + +| REQ | Phase | Status | +|-----|-------|--------| +| REQ-214 | P1 | pending | +| REQ-215 | P2 | pending | +| REQ-216 | P2 | pending | +| REQ-217 | P3 | pending | +| REQ-218 | P3 | pending | +| REQ-219 | P3 | pending | +| REQ-220 | P3 | pending | +| REQ-221 | P4 | pending | +| REQ-222 | P4 | pending | +| REQ-223 | P5 | pending | +| REQ-224 | P5 | pending | +| REQ-225 | P5 | pending | +| REQ-226 | P6 | pending | +| REQ-227 | P6 | pending | +| REQ-228 | P1/P2/P6 | pending | diff --git a/.ciagent/RESEARCH.md b/.ciagent/RESEARCH.md index 755aed5..8dba006 100644 --- a/.ciagent/RESEARCH.md +++ b/.ciagent/RESEARCH.md @@ -1493,3 +1493,856 @@ Total: ~12–16 slides. Opening = arc preview; closing = recap + ask. cost estimate. No live AWS access required. If Infracost is not available, the `cost.estimated` event is omitted (degraded mode, not a failure). + +--- + +## v1.18 Research — Citizen Developer & Production-Grade Guidance + +> Phase 0 RESEARCH. Autonomy = full. Findings are evidence-grounded +> (fetched from live sources, not assumed). The Atelier repo, the MCP +> Python SDK v2 docs, the existing Nova schemas/ingestor, and the Marp +> CLI README were all fetched directly. Decisions are logged with +> confidence scores; low-confidence items are flagged. + +### 1. Atelier Integration Reference + +#### 1.1 The 8 core principles (C1–C8) + +Source: `core/first-principles.md` (fetched 2026-08-06 from +`https://git.cloudinit.dev/coreci/atelier/raw/branch/main/core/first-principles.md`). +Precedence is a **total order** — a lower-numbered principle is never +sacrificed for a higher-numbered one (C1 never sacrificed; C2 only for +C1; C3 only for C1/C2; C4–C8 tradeable among themselves but always below +C1–C3). + +| ID | Principle | One-line description | +|----|-----------|----------------------| +| **C1** | Correctness | The system does what it is supposed to do, and nothing else. Highest principle; never overridden. Security is a subset (exploitable code is incorrect). Includes temporal correctness (a late answer is wrong when the deadline mattered). | +| **C2** | Clarity | The intent of the code is obvious to its reader. Optimize for the reader; names reveal intent; comments explain *why* not *what*. Unclear code is where bugs hide. | +| **C3** | Simplicity | The solution is as simple as possible, and no simpler. Complexity is the enemy of correctness; every line is a liability. Not laziness — the result of removing everything unnecessary. | +| **C4** | Locality | Decisions and their consequences live near each other. State, logic, side effects that depend on each other live near each other. A change needing many distant files is a locality violation. | +| **C5** | Reversibility | Every decision can be undone, and the cost of undoing is known. Migrations/deploys/schema/API changes reversible by default. Versioning, feature flags, rollback paths are the mechanisms. | +| **C6** | Composability | Parts combine into wholes, and the parts are reusable in new wholes. A part that does one thing well composes; the boundary is its contract. Composable parts are understandable in isolation. | +| **C7** | Observability | The system's behavior is visible to the people who must understand it. Logs/metrics/traces are first-class, designed in. An observable system answers "what/why/what next" without reading source. | +| **C8** | Economy | The system uses no more resources than the task requires (time, memory, attention, money, complexity). Most tradeable principle; unbounded growth in any resource is a defect. | + +The precedence string (from `core/first-principles.md` §3): +`C1 Correctness > C2 Clarity > C3 Simplicity > C4 Locality > C5 Reversibility > C6 Composability > C7 Observability > C8 Economy`. + +Conflict resolution (`core/conflict-resolution.md`, fetched): a +deterministic 6-step procedure. The **hierarchy** is +`core/first-principles.md` > `domains//first-principles.md` > +`domains//.md` > `languages/.md` > `examples/.md`. +Same-level conflicts resolve by core derivation (via the matrix), then +by specificity, then by filing an issue (a tie is a defect). A domain's +"non-tradeable" declaration (e.g. Security: 8 of 10) promotes those +rules to **C1-equivalent** — a binding escalation recorded in the +matrix's derivation. + +#### 1.2 The 19 domains and Nova-citizen-dev relevance + +Source: `matrix/principles-matrix.md` (fetched) + the releases page +(v0.4 milestone = 19 domains, 190 P-rules, confirmed in the v0.3.6 +release notes and the matrix Coverage Summary). + +| # | Domain | Atelier path | P-rules | Nova-citizen-dev relevant? | Reason | +|---|--------|--------------|---------|------------------------------|--------| +| 1 | UI/UX | `domains/uiux/` | 10 | **NO** — excluded | v1.18 has no frontend (Out of Scope: "A Nova-built frontend / dashboard"). Decks are markdown, not a UI. | +| 2 | API Design | `domains/api/` | 10 | **YES** | A citizen developer building a web API / worker / scheduled job touches API contracts. Maps to `skills/api.md`. | +| 3 | Security | `domains/security/` | 10 | **YES** | Zero-trust, input validation, secret hygiene, fail-securely — universal for any production-grade service. Maps to `skills/security.md`. | +| 4 | Data | `domains/data/` | 10 | **YES** | Schema-as-truth, migration safety, referential integrity — applies to any stateful service. Maps to `skills/data.md`. | +| 5 | Testing | `domains/testing/` | 10 | **YES** | Tests-as-specification, determinism, edge-case coverage — required for a citizen developer's UAT. Maps to `skills/testing.md`. | +| 6 | Performance | `domains/performance/` | 10 | **YES (reference, not a skill)** | Measure-first, bounded operations, no N+1, timeouts. NOT one of the 9 REQ-221 skills; Performance principles are cited inside the 9 skills + the index. | +| 7 | Observability | `domains/observability/` | 10 | **YES** | Structured logs, correlation IDs, no secrets in logs — the "basic observability bootstrap" BA.A skill. Maps to `skills/observability.md`. | +| 8 | Errors | `domains/errors/` | 10 | **YES** | Errors are data, fail loudly + specifically, preserve context — production-grade error handling. Maps to `skills/errors.md`. | +| 9 | Documentation | `domains/documentation/` | 10 | **YES (reference, not a skill)** | Docs-as-code, audience awareness, examples mandatory. REQ-221 does NOT list `skills/documentation.md`; a self-referential "documentation skill" is redundant. Principles cited inside `docs/skills.md` index. | +| 10 | Concurrency | `domains/concurrency/` | 10 | **YES (reference, not a skill)** | Immutability, bounded queues, timeouts — advanced for a citizen developer's first 5 skills. REQ-221 does NOT list `skills/concurrency.md`. Top rules cross-referenced inside `skills/api.md` + `skills/errors.md`. | +| 11 | DevOps | `domains/devops/` | 10 | **YES** | Reproducibility, rollback-first, config-as-code — the citizen developer co-owns Release Management (RACI). Maps to `skills/devops.md`. | +| 12 | Infrastructure as Code | `domains/infrastructure-as-code/` | 10 | **YES** | Declarative intent, idempotence, plan-before-apply, no secrets in HCL — directly relevant to the Nova contract→Terraform path. Maps to `skills/infrastructure-as-code.md`. | +| 13 | Kubernetes | `domains/kubernetes/` | 10 | **NO** — excluded | Nova emits Terraform (ECS/Fargate per the architecture), not K8s manifests. Kyverno adapter is "ready but inactive" (D-053). Not citizen-dev-relevant. | +| 14 | GitOps + Operators | `domains/gitops-operators/` | 10 | **NO** — excluded | Nova uses a push pipeline (contract → resolve → plan → apply), not a pull-based reconciler. Not citizen-dev-relevant. | +| 15 | AI/ML | `domains/ai-ml/` | 10 | **YES (reference, not a skill)** | Reproducibility, data versioning, drift detection — relevant *to Nova itself* (Nova is an agentic platform), but a citizen developer on Nova is NOT building ML models; they consume Nova's agentic capability. REQ-221 does NOT list `skills/ai-ml.md`; the Atelier AI/ML domain is platform-team guidance, not citizen-dev guidance. | +| 16 | i18n | `domains/i18n/` | 10 | **NO** — excluded | Not relevant to a citizen developer's first production-grade service on Nova. | +| 17 | Compliance | `domains/compliance/` | 10 | **YES** | Audit logs append-only, policy-as-code, evidence-by-operation — directly relevant (Nova's compliance posture is a selling point). Maps to `skills/compliance.md`. | +| 18 | Edge | `domains/edge/` | 10 | **NO** — excluded | Nova does not deploy edge/CDN for the citizen developer's first 5 skills; Route53/ACM/CloudFront are consumer-supplied extension points (D-049). | +| 19 | Messaging | `domains/messaging/` | 10 | **NO** — excluded | The citizen developer's first 5 skills (web API / worker / scheduled job / static asset / observability bootstrap) do not require a broker; messaging is a future capability. | + +**Relevant count:** 13 of 19 are relevant to *some* Nova audience +(YES or YES-reference). Of those, **9 become skills** (per REQ-221, the +planned count). The other 4 relevant domains (Performance, Documentation, +Concurrency, AI/ML) are **reference-only** — their principles are cited +inside skills or the `docs/skills.md` index, but they do NOT get their +own skill file. This matches REQ-221's exact 9-skill list. + +**Excluded count:** 6 of 19 (UI/UX, Kubernetes, GitOps, i18n, Edge, +Messaging) are not relevant to a Nova citizen developer building a +production-grade application — confirmed. + +#### 1.3 Atelier domain → Nova skill mapping (final 9-skill list) + +REQ-221 names exactly 9 skills. The research **confirms the planned 9** +— no adjustment needed. The mapping (each skill cites its Atelier source +path + distills the citizen-developer-relevant subset + links to +agent-checklist triggers + maps to the BA.A 5-skill catalog): + +| Nova skill file | Atelier domain path | P-rules distilled | BA.A catalog skill it extends | +|-----------------|----------------------|-------------------|--------------------------------| +| `skills/api.md` | `domains/api/` | P1 Contract Fidelity, P2 Clarity, P5 Versioning, P6 Idempotency, P8 Security, P9 Error Transparency | web API | +| `skills/security.md` | `domains/security/` | P1 Zero Trust, P2 Least Privilege, P4 Input Validation, P6 Crypto Correctness, P8 Fail Securely, P9 Secret Hygiene | all 5 (cross-cutting) | +| `skills/data.md` | `domains/data/` | P1 Truth, P3 Invariants in Schema, P4 Migration Safety, P7 Type Fidelity, P9 Referential Integrity | web API, worker, scheduled job | +| `skills/testing.md` | `domains/testing/` | P1 Tests as Specification, P3 Determinism, P5 Coverage of Behavior, P9 Edge Case Coverage, P10 No Test Theater | all 5 (UAT is a citizen-developer RACI responsibility) | +| `skills/observability.md` | `domains/observability/` | P1 Structured by Default, P2 Correlation, P6 No Secrets in Obs, P7 Actionable Alerts | basic observability bootstrap | +| `skills/errors.md` | `domains/errors/` | P1 Errors are Data, P2 Fail Loudly, P3 Fail Specifically, P4 Preserve Context, P5 Recoverable When Possible | web API, worker, scheduled job | +| `skills/devops.md` | `domains/devops/` | P1 Reproducibility, P4 Rollback First, P5 Progressive Delivery, P6 Config as Code, P8 Security at Every Layer | scheduled job, worker (deploy/release is co-owned Release Mgmt) | +| `skills/infrastructure-as-code.md` | `domains/infrastructure-as-code/` | P1 Declarative Intent, P2 Idempotence, P4 Plan Before Apply, P5 Version Everything, P10 Secrets Never in Code | static asset (the contract→Terraform path) | +| `skills/compliance.md` | `domains/compliance/` | P1 Audit Logs Append-Only, P2 Every Significant Action Logged, P4 Policy is Code, P5 Policy is Evaluated as a Gate, P9 Secrets Redacted in Audit | all 5 (cross-cutting; Nova's compliance posture) | + +**Final recommendation: 9 skills, exactly as REQ-221 planned.** +Confidence 0.95 — the planned list maps cleanly to the relevant Atelier +domains and to the BA.A 5-skill catalog; the 4 "reference-only" domains +(Performance, Documentation, Concurrency, AI/ML) are correctly *not* +elevated to skills (a citizen developer's first production-grade service +does not need a standalone Concurrency or AI/ML skill; Performance and +Documentation principles are cited inside the 9 skills + the index). + +#### 1.4 Agent-checklist → MCP `atelier.validate_against_principles` checks + +Source: `review/agent-checklist.md` (fetched). The checklist has a +**Core (C1–C8)** section (8 subsections, ~30 boolean items) plus +**domain-specific trigger sections** (one per domain; Nova-relevant +ones: API, Security, Data, Testing, Performance, Observability, Errors, +Concurrency, DevOps, IaC, Compliance). + +The MCP `atelier.validate_against_principles` tool (REQ-223, in +`plugins/validation.py`) runs the relevant checklist items against a +code/diff snippet. The tool input model: + +```python +class ValidateInput(BaseModel): + snippet: str # the code/diff to validate + language: str # e.g. "python", "terraform", "yaml" + domains: list[str] # e.g. ["security", "api"] — which domain triggers to run + run_core: bool = True # always run C1–C8 unless explicitly skipped +``` + +The structured output model (Pydantic, returned as `structured_content`): + +```python +class Violation(BaseModel): + principle: str # e.g. "C1", "security/P9" + checklist_item: str # the verbatim checklist question + severity: str # "C1" (blocking) | "non-tradeable" | "tradeable" + evidence: str # the snippet substring + why it fails + fix_hint: str # the principle's remediation guidance + +class ValidateResult(BaseModel): + snippet_id: str # hash of the snippet for replay + passed: bool + violations: list[Violation] + domains_checked: list[str] + core_checked: bool +``` + +**Checklist → check mapping** (the validation plugin encodes each +checklist item as a boolean predicate over the snippet + language): + +| Checklist section | MCP check behavior | Nova-relevant? | +|-------------------|--------------------|-----------------| +| **C1 Correctness** (4 items) | Run all 4; any fail → `severity: "C1"` (blocking). | YES — always run (core) | +| **C2 Clarity** (4 items) | Heuristic checks: name smell (`data/temp/x/doStuff`), comment-why ratio. | YES — always run | +| **C3 Simplicity** (4 items) | Dead-code heuristic, function-length, premature-abstraction. | YES — always run | +| **C4 Locality** (3 items) | Cross-file-change heuristic (for diffs); within-file coupling. | YES — always run | +| **C5 Reversibility** (3 items) | Migration-has-down, deploy-has-rollback presence checks. | YES — always run | +| **C6 Composability** (3 items) | Single-responsibility heuristic, boundary-typed check. | YES — always run | +| **C7 Observability** (4 items) | Log-presence, error-context, metric, **no-secrets-in-logs** (hard check). | YES — always run | +| **C8 Economy** (3 items) | Unbounded-growth, no-timeout, resource-leak heuristics. | YES — always run | +| If API | 5 items: nouns-plural-lowercase, status codes, structured errors, schema validation, auth-required. | YES — when `domains` includes "api" | +| If Security | 5 items: no-secrets-in-code/logs/URLs, input-validation, output-encoding, vetted-crypto, authz-checked. **All 5 are non-tradeable** (Security domain §3). | YES — when "security" | +| If Data | 5 items: schema-reflects-domain, constraints-in-schema, migration-up-down, domain-types, no-SELECT-star. | YES — when "data" | +| If Testing | 4 items: independence, determinism, edge-cases, failure-specificity. | YES — when "testing" | +| If Performance | 4 items: no-unbounded, no-N+1, timeouts, cache-invalidation. | YES — when "performance" | +| If Observability | 4 items: structured-logs, correlation-id, no-high-cardinality, alerts-have-runbooks. | YES — when "observability" | +| If Errors | 4 items: not-swallowed, specific, context-preserved, recovery-attempted. | YES — when "errors" | +| If Concurrency | 5 items: shared-state-minimized, minimal-locks, bounded-queues, timeouts, cancellation. | YES — when "concurrency" | +| If DevOps | 4 items: pipeline-is-process, rollback-known, config-in-code, env-parity. | YES — when "devops" | +| If IaC | 8 items: declarative, pinned-providers, remote-locked-state, plan-before-apply, no-secrets-in-HCL, versioned-modules, drift-is-incident, least-priv-providers. | YES — when "infrastructure-as-code" | +| If Compliance | 10 items: append-only-audit, a-priori-action-set, retention-as-policy, policy-as-code, policy-as-gate, continuous-evidence, attributable-identity, subject-access, redacted-secrets, observable-posture. | YES — when "compliance" | + +The validation plugin reads the vendored `review/agent-checklist.md` +(frozen at the pinned tag — §1.6) so the checks are replayable against +the exact checklist version that produced a result. The plugin maps each +checklist line to a predicate function keyed by `(language, principle)` +so a "no secrets in code" check runs differently for Python (ast scan for +string-constant assignment) vs Terraform (HCL scan for hardcoded +provider keys) vs YAML (scan for `api_key:` literals). + +#### 1.5 Principle-lookup query model + +`atelier.lookup_principle(domain: str, principle_id: str)` (REQ-223, in +`plugins/principles.py`) resolves a principle reference to its full +text + core derivation + checklist items. Resolution model: + +**Input:** +```python +class LookupInput(BaseModel): + domain: str # "security" | "api" | "data" | ... | "core" + principle_id: str # "P4" | "C1" (core) | "P9" +``` + +**Resolution path (the lookup algorithm):** +1. If `domain == "core"`: load `vendor/core/first-principles.md`, parse + the `### C. ` section for `principle_id` (e.g. `C1` → + the "C1. Correctness" section). Return the full principle text. +2. Else: load `vendor/domains//first-principles.md`, parse the + `### P. ` section for `principle_id` (e.g. `security/P4` → + the "P4. Input Validation" section). +3. **Cross-reference the matrix:** load + `vendor/matrix/principles-matrix.md`, find the row for + ` P`, extract the `Core` column (e.g. Security P4 → `C1`). + This is the core derivation. +4. **Cross-reference the checklist:** load + `vendor/review/agent-checklist.md`, find the `If ` section, + extract the checklist items tagged with `P` (the IaC section + tags items with `(P1)`, `(P10)` etc.; the Security section items map + to P9, P4, P5, P6, P1/P10 by content). +5. **Check non-tradeable status:** load + `vendor/domains//first-principles.md` §3 (Conflict + Resolution); if the principle is listed as "never sacrificed", mark + `non_tradeable: true` (escalates it to C1-equivalent per + `core/conflict-resolution.md` §6). + +**Return (structured output):** +```python +class PrincipleLookup(BaseModel): + domain: str # "security" + principle_id: str # "P4" + name: str # "Input Validation" + text: str # full principle body + core_derivation: list[str] # ["C1"] (from the matrix) + non_tradeable: bool # True for security P1-P8, P9; False for P10 + checklist_items: list[str] # the verbatim checklist questions for this P-rule + source_path: str # "domains/security/first-principles.md" (relative to vendor/) +``` + +**Example resolution — `atelier.lookup_principle("security", "P4")`:** +- `name`: "Input Validation" +- `text`: "All input is untrusted until proven otherwise. Validation + happens at the boundary, against a schema, with explicit failure + modes." +- `core_derivation`: `["C1"]` (matrix row: Security P4 → C1) +- `non_tradeable`: `true` (Security §3 lists P4 as "never sacrificed") +- `checklist_items`: `["Input is validated at the boundary", "Output is + encoded for its context"]` (from `review/agent-checklist.md` If Security) +- `source_path`: `"domains/security/first-principles.md"` + +The two companion tools: +- `atelier.list_domains()` → returns the 19 domain names + their + P-rule counts + relevance flag (the plugin hardcodes the + Nova-relevance table from §1.2 so the citizen developer's agent can + filter to the 13 relevant / 9 skill-bearing domains). +- `atelier.matrix_lookup(domain: str)` → returns the full domain→core + mapping for one domain (all 10 P-rules → their core C-rule(s)), used + by `validate_against_principles` to set `severity` and by conflict + resolution when two findings collide. + +#### 1.6 Recommended Atelier pinned tag to vendor + +**Recommendation: vendor tag `v0.3.6`** (the v0.4 milestone release). + +Evidence (from `https://git.cloudinit.dev/coreci/atelier/releases`, +fetched 2026-08-06): +- The latest release is **v0.3.6**, dated 2026-08-05 16:22:58 +00:00, + tagged `v0.3.6` (commit `66b4767d25`), marked **Stable**, with the + title "v0.3.6 — v0.4 milestone: Edge + Messaging + Language-Derived + Docs". +- It is the **v0.4 milestone release** (the release notes state: + "v0.4 — Edge + Messaging + Language-Derived Docs (Milestone + Release). Tag: v0.3.6 (NFR milestone — final patch IS the deliverable; + no separate minor tag per branch-strategy.md)"). +- The matrix is at its complete state: **19 domains, 190 P-rules** + (the Coverage Summary in `matrix/principles-matrix.md` confirms this + exactly; the v0.3.6 release notes confirm "170 → 190 P-rules across + 19 domains"). All 190 P-rules trace to ≥1 core C-rule (no orphans — + verified in the release audit). +- `-11 commits to main since this release` — there is post-release + activity on `main`, which is exactly why pinning matters: vendoring + `main` HEAD would be a moving target. `v0.3.6` is the frozen, + audited, reproducible snapshot. This satisfies D-136 (vendor for audit + reproducibility) — an agentic validation result must be replayable + against the exact principles that produced it. + +**Vendoring mechanics (for REQ-224):** +- `mcp/atelier/vendor/` = a clean copy of the Atelier repo at tag + `v0.3.6` (the `core/`, `domains/`, `matrix/`, `review/` directories — + the docs the MCP tools read; `examples/` and `languages/` are optional + but cheap to include for completeness). +- `mcp/atelier/vendor/VERSION.md` records: tag `v0.3.6`, commit + `66b4767d25`, date 2026-08-05, milestone "v0.4 Edge + Messaging + + Language-Derived Docs", P-rule count 190, domain count 19. +- `scripts/update_atelier_vendor.sh` = a helper that takes a tag arg, + fetches the tarball from + `https://git.cloudinit.dev/coreci/atelier/archive/.tar.gz`, + extracts the doc directories into `mcp/atelier/vendor/`, and updates + `VERSION.md`. Intentional upgrades only (re-run + re-audit). + +Confidence: 0.95. The only risk is that a v0.5 milestone lands before +P5 ships — but the pinning model (VERSION.md + update script) makes a +future upgrade a deliberate, audited action, not a silent drift. + +--- + +### 2. MCP Python SDK v2 Reference + +Source: `https://py.sdk.modelcontextprotocol.io/` (the official Python +SDK docs, fetched 2026-08-06) + the Tools page +(`.../servers/tools/`) + the Structured Output page +(`.../servers/structured-output/`). The docs document **v2, the current +stable release line** (Python 3.10+). + +#### 2.1 Confirmed API patterns + +1. **Server creation + import path.** The v2 high-level server class is + `MCPServer` (NOT `FastMCP` — that was v1; v2 renamed/restructured): + ```python + from mcp.server import MCPServer + mcp = MCPServer("atelier") # one arg = server name + ``` + This is the exact pattern shown in the docs' landing-page example and + the Tools-page example. There is no `FastMCP` import in v2. + +2. **`@mcp.tool()` decorator — inputSchema from type hints.** Confirmed + verbatim from the docs: "No JSON Schema. `a: int, b: int` *is* the + schema." The SDK reads three things from the function: + - **name** = the function name (`search_books`) + - **description** = the docstring (the model sees this) + - **arguments** = the type hints (`query: str`, `limit: int`) + The SDK generates the JSON Schema and sends it during `tools/list`. + Type hints are **the contract** — if a client sends `"limit": "ten"`, + the SDK rejects it *before the function runs*. Optional args = + default values (`limit: int = 10` → leaves `required`, gains + `default: 10`). Richer constraints via + `Annotated[int, Field(ge=1, le=50, description="...")]`. Enums via + `Literal["a", "b"]`. Pydantic `BaseModel` parameter = structured + "body" (nested as `$defs`). + +3. **Multiple tools / dynamic registration (plugin-registry).** The + `@mcp.tool()` decorator is called on the `mcp` object. A plugin + receives `mcp` and calls `@mcp.tool()` on it — this is plain Python + decorator application, no registration magic. The plugin-registry + pattern (D-140): + ```python + # plugins/principles.py + from mcp.server import MCPServer + def register(mcp: MCPServer) -> None: + @mcp.tool() + def atelier_lookup_principle(domain: str, principle_id: str) -> PrincipleLookup: + """Look up an Atelier principle by domain + ID.""" + ... + ``` + `server.py` scans `plugins/`, imports each module, calls + `register(mcp)`. Each plugin's `@mcp.tool()` calls register the tool + on the shared `mcp` object. **This is the confirmed dynamic- + registration pattern** — no `add_tool()` API is needed; the decorator + does it. + +4. **stdio transport.** The landing-page example shows `uv run mcp dev + server.py` (Inspector). For stdio transport (D-135: stdio now), the + server runs over stdio via the SDK's run entry point. The v2 server + object supports stdio as the default transport. The exact run call is + `mcp.run()` (the SDK handles the transport based on how the process + is launched — stdio when invoked by an MCP host over stdio). The + README's "no protocol handling" promise means `mcp.run()` is the only + call needed. (HTTP transport is on the same server object — Out of + Scope for v1.18, future milestone; the server object is + transport-agnostic so adding HTTP later is a transport-only change, + confirming D-135.) + +5. **outputSchema / structured output.** Confirmed: **the return type + annotation IS the output schema.** From the Structured Output page: + "the return type annotation is the output schema. It's published in + `tools/list` as `output_schema`." A Pydantic `BaseModel` return type + produces an unwrapped object schema (no `result` wrapper); a + `TypedDict` or `dataclass` works identically. The result carries + both `content` (text, for the model) and `structured_content` (data, + for the application). **Validation is enforced**: whatever the + function returns is validated against the schema before it leaves the + server — a mismatch is a tool error (not a corrupt result). This is + exactly what `atelier.validate_against_principles` needs: a + `ValidateResult(BaseModel)` return type gives the host a structured + `violations` list while giving the model a JSON-text rendering of the + same object. `structured_output=False` opts out (text-only); we do + NOT opt out for the validation tool. + +6. **`listChanged` capability / dynamic tool registration.** The v2 + docs (Tools page + landing page) describe tool registration as + declarative (`@mcp.tool()` at import time). The docs do NOT document + a runtime `listChanged` notification API on the high-level + `MCPServer`. For Nova's use case (plugins loaded once at server + startup, not added/removed at runtime), this is fine — all 4 tools + are registered before `mcp.run()`. A future milestone that adds + tools at runtime would need the low-level Server + (`advanced/low-level-server/`) for explicit notification control. + **Conclusion: no `listChanged` needed for v1.18; the plugin-registry + loads at startup, before the stdio loop.** Confidence 0.85 (the docs + are silent on a high-level `listChanged`; the low-level server has + it, but we use the high-level server). + +#### 2.2 Skeleton for `mcp/atelier/server.py` (P5 basis) + +This is the 15-line pattern Nova's server should follow (the basis for +P5 implementation): + +```python +import importlib, pathlib +from mcp.server import MCPServer + +mcp = MCPServer("atelier") # server name; stdio transport is the default + +# Plugin-registry: scan plugins/, import each, call register(mcp). +for p in sorted(pathlib.Path(__file__).parent.glob("plugins/*.py")): + if p.stem != "__init__": importlib.import_module(f".plugins.{p.stem}", __package__).register(mcp) + +@mcp.tool() +def atelier_list_domains() -> list[dict]: + """List the 19 Atelier domains with P-rule counts + Nova-relevance.""" + return [{"domain": "security", "p_rules": 10, "nova_relevant": True}, ...] + +if __name__ == "__main__": + mcp.run() # stdio transport (D-135); HTTP-ready on the same object (future) +``` + +**Notes on the skeleton:** +- `MCPServer("atelier")` — one import, one constructor arg (the name). +- The plugin loop uses `importlib` + a `register(mcp)` convention (D-140). + Each plugin's `register` body contains `@mcp.tool()` calls that + register that plugin's tools on the shared `mcp` object. `sorted()` + makes plugin load order deterministic (audit reproducibility — a + plugin load order that changes between runs would break replay). +- The sample tool shows the pattern: `@mcp.tool()`, type hints ARE the + input schema, docstring IS the description, return type IS the + output schema. The real `atelier_list_domains` returns a + `list[DomainInfo]` (a `list[BaseModel]` → wrapped in `{"result": [...]}`, + per the Structured Output docs). +- `mcp.run()` — the single entry point; stdio is the default. No + transport boilerplate. Adding HTTP later = a transport argument or a + different run call on the same object (D-135, Out of Scope for v1.18). +- The vendored Atelier snapshot (`mcp/atelier/vendor/`) is read by the + plugin tool functions (not shown in the skeleton); the plugins load + the markdown files lazily on first tool call and cache the parsed + structure in module-level dicts (C8 Economy — don't re-parse the + matrix on every lookup). + +--- + +### 3. Submission-Readiness Gap Analysis + +#### 3.1 `contract.schema.json` defines SHAPE, not the readiness gate + +Confirmed by reading `/root/acdl/schemas/contract.schema.json` (51 +lines). The schema defines the **contract shape** only: +- `required`: `["id", "name", "environment", "infrastructure"]` +- `id`: pattern `^[a-z][a-z0-9-]{2,5}$` (3–6 char acronym) +- `name`: minLength 3 +- `environment`: enum `["dev", "qa", "prod", "dr"]` +- `infrastructure`: map keyed by module name, each entry has `version` + (optional semver) + `inputs` (required, additionalProperties allowed) +- `additionalProperties: false` (top-level + per-module) + +**What it does NOT define (the gap):** +- ❌ No `tags` field (the 5 required Nova tags per D-054) +- ❌ No per-env mandatory metadata (the W3.E table: dev=stack+environment; + qa+=e2eSuite+loadTest; prod+=runbook+dashboard+oncall; dr+=drDrillRef) +- ❌ No `policyPreconditions` field (declared policy expectations) +- ❌ No `profile` field (`developer` | `agentic`; agentic requires + `naturalLanguageIntent`, `confidenceAtSubmission`, `agentTrace`) +- ❌ No `appSource` field (repo + ref pointer for runtime fetch) +- ❌ No `contractId` field at the top level (the ingestor payload has + `contractId` in the Lambda envelope, but the contract *blob* itself + does not — the readiness schema promotes it to a required field per + REQ-217) + +The schema's own description confirms this is the shape: "A consumer +contract declares intent: which infrastructure to deploy, in which +environment, with which inputs." It is the *intent shape*, not the +*ready-to-start gate*. + +#### 3.2 The readiness schema is a SUPERSET gate ABOVE contract-schema validity + +Confirmed by PROJECT.md (lines 635–643, the v1.18 scope statement) and +REQ-217. The relationship: + +``` +contract.schema.json (SHAPE — id/name/environment/infrastructure) + ▲ + │ references but does NOT redefine contract fields + │ +submission-readiness.schema.json (GATE — superset above shape validity) + = contract-shape-valid (delegate to contract.schema.json) + + tags (5 required Nova tags, D-054) + + per-env mandatory (W3.E table) + + policyPreconditions (declared policy expectations) + + profile (developer | agentic + agentic markers) + + appSource (repo + ref pointer) + + contractId (non-empty, promoted to required) +``` + +PROJECT.md hard constraint (line 674–676): "The submission-readiness +schema is a superset gate above `contract.schema.json`, NOT a +duplicate — it references but does not redefine contract fields." + +This means `submission-readiness.schema.json` uses +`$ref` to `contract.schema.json` for the contract shape (or validates +the contract blob against it as a first step), then adds the gate +fields *alongside* it. The validator (REQ-218) calls +`contract.schema.json` validation **first** (the existing +`_validate_contract_schema` in the ingestor), then the readiness +checks. This is a two-layer gate, not a merged schema. + +#### 3.3 Fields the new `schemas/submission-readiness.schema.json` must add + +Per REQ-217 + W3.E (PROJECT.md line 888) + D-054 (tagging standard): + +| Field | Type | Required | Source / rule | +|-------|------|----------|---------------| +| `contractId` | string (non-empty) | **YES** | REQ-217. Promoted from the Lambda envelope to a contract-level required field. | +| `environment` | enum `dev/qa/prod/dr` | **YES** | Already in `contract.schema.json`; the readiness schema references it (does not redefine) and uses it to select the per-env mandatory set. | +| `tags` | object | **YES** | D-054 / `schemas/tagging-standard.json`. Required keys: `nova:owner`, `nova:contract`, `nova:environment`, `nova:cost-center` (`nova:ref` optional). The readiness schema references `tagging-standard.json`'s `required_tags` shape. | +| `policyPreconditions` | object (map of string→boolean/string) | **YES** | REQ-217. Declared policy expectations the platform will enforce (e.g. `{"public-ingress": false}`). | +| `profile` | enum `developer` \| `agentic` | **YES** | REQ-217 / W3.E. | +| `profile` == `agentic` → requires: `naturalLanguageIntent` (string), `confidenceAtSubmission` (number 0–1), `agentTrace` (object/string) | per W3.E | **conditional** | REQ-22 / W3.E. These are "optional everywhere" per W3.E (a `developer` profile omits them) but **required when profile is `agentic`**. | +| `appSource` | object `{repo: string, ref: string}` | **YES** | REQ-217. Repo + ref pointer for runtime fetch. | +| **Per-env mandatory (W3.E):** | | | | +| `dev` | `stack` + `environment` | **YES** | W3.E. (These are the base contract fields; the readiness schema enforces their presence for dev.) | +| `qa` adds | `validation.e2eSuite` + `validation.loadTest` | **YES for qa** | W3.E. | +| `prod` adds | `runbook` + `dashboard` + `oncall` | **YES for prod** | W3.E. | +| `dr` adds | `drDrillRef` | **YES for dr** | W3.E. | +| `inputs` map | object | optional everywhere | W3.E ("inputs map is always optional"). | + +The per-env mandatory table is a **conditional `allOf`** in JSON Schema +draft 2020-12: an `if`/`then` keyed on `environment` that requires the +env-specific fields. The reason code +`ENV_MISSING_MANDATORY::` (REQ-218) maps directly to this +conditional check. + +#### 3.4 How `contract_ingestor.py` currently works (P3 wiring point) + +Read `/root/acdl/core/lambda/contract_ingestor.py` (502 lines). The +current entry point + dispatch: + +- **Entry point:** `lambda_handler(event, context)` (line 460). Parses + `event["body"]` (JSON string) → `payload`. Reads `action` (default + `"submit_contract"`). +- **Identity validation:** `_validate_caller_identity(event, payload)` + (line 293) — checks IAM caller ARN, `consumerRepo` format, + `contractId` format (regex `^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$`), + `environment` enum (from `core/environments/*.json`, P10/REQ-174), + error-length cap. Fails closed if no IAM identity (P10). +- **Action dispatch (line 475):** + - `submit_contract` → `_submit_contract(payload)` (line 135): + validates required fields (`consumerRepo`, `contractId`, `contract`, + `environment`), size-caps the contract blob (256 KB, P11/REQ-175), + calls `_validate_contract_schema(contract)` (line 57 — validates + against `schemas/contract.schema.json` via `jsonschema`; no-op if + schema/jsonschema unavailable; bypassed by `NOVA_LAMBDA_LOCAL_BYPASS`), + writes to DynamoDB `nova-contracts` (PK `consumerRepo`, SK + `contractId#submittedAt`). + - `report_error` → `_report_error` (D-055, GitHub/Gitea issue). + - `validate_change_request` → `_validate_change_request` (REQ-93). + - `onboard_consumer` → `_onboard_consumer` (P18/REQ-182, validates + against `schemas/onboarding.schema.json`). +- **Error mapping:** ValueError → 400 (or 401 for identity failures); + other Exception → 500 (defensive top-level guard, `pragma: no cover`). + +**Where P3 adds `--check-readiness` (D-133):** + +The ingestor is a **Lambda handler**, not a CLI. D-133 says the +validator is "invoked as `contract_ingestor.py --check-readiness` +subcommand" — this is a **local CLI mode** for citizen-developer +pre-flight validation, NOT a new Lambda action. The implementation +pattern (confirmed by the existing code structure): + +1. Add a `if __name__ == "__main__":` block at the bottom of + `contract_ingestor.py` that parses `sys.argv` (argparse or manual). + The existing file has NO `__main__` block (it's Lambda-only); P3 + adds one. +2. The `--check-readiness` subcommand loads a contract file (or reads + stdin), validates it against + `schemas/submission-readiness.schema.json` (REQ-217) via the new + `core/submission_readiness.py` validator (REQ-218), and prints a + structured `ReadinessResult` (pass/fail per check + reason codes). +3. The validator (`core/submission_readiness.py`) calls + `_validate_contract_schema(contract)` first (reusing the existing + function — the shape gate), then runs the readiness checks (tags, + per-env mandatory, policyPreconditions, profile:agentic markers, + appSource). +4. On fail → the CLI exits non-zero with a **citizen-developer-facing + error** (not a stack trace) — REQ-218. On pass → proceeds to + existing ingestion (in the Lambda path, the readiness check would + be a pre-write gate; in the CLI path, it's a pre-flight check that + returns 0). + +**Reason codes (REQ-218, the validator's return vocabulary):** +`MISSING_TAGS`, `ENV_MISSING_MANDATORY::`, +`AGENTIC_MISSING_INTENT`, `MISSING_APP_SOURCE`, +`POLICY_PRECONDITION_MISSING`. Each maps to a failed check in the +schema's conditional `allOf`. The validator returns a list of these +(not a single error) so a citizen developer sees *all* gaps at once, +not one-at-a-time (C2 Clarity — the reader understands the full scope +of fixes needed). + +#### 3.5 Gitea release-asset API endpoint (for `scripts/attach_release_asset.py`) + +Confirmed from the existing `scripts/ship_phase.sh` (line 38) which +already uses the Gitea releases API, and from the Gitea API swagger +(`https://gitea.com/api/swagger`, fetched — the OpenAPI/Swagger JSON is +published there; the endpoint is standard Gitea). + +**Release creation (existing pattern, `ship_phase.sh` line 38):** +``` +POST https://git.cloudinit.dev/api/v1/repos/continuous-intelligence/acdl/releases +Authorization: token +Content-Type: application/json +Body: {"tag_name": "...", "name": "...", "body": "..."} +Response: {"id": , ...} +``` + +**Release asset attachment (the new endpoint, for +`attach_release_asset.py`):** +``` +POST https://git.cloudinit.dev/api/v1/repos/continuous-intelligence/acdl/releases/{release_id}/assets +Authorization: token +Content-Type: multipart/form-data +Form fields: + name = + attachment = +Response: {"id": , "name": "...", "size": ..., "download_count": 0, ...} +``` + +The Gitea API endpoint is `POST +/api/v1/repos/{owner}/{repo}/releases/{id}/assets` with a **multipart +form** containing `name` (the display filename) and `attachment` (the +file binary). The `{id}` is the numeric release ID returned by the +release-creation call (the `d.get('id')` in `ship_phase.sh` line 40). +`attach_release_asset.py` (REQ-228) takes a release tag (or ID) + a +file path, resolves the tag → release ID (GET +`/api/v1/repos/.../releases/tags/{tag}` if only the tag is known), then +POSTs the multipart form. The token comes from `.env.secrets` +(`NOVA_GITEA_TOKEN`, same as `ship_phase.sh` line 35). + +**Implementation note:** `urllib` (used throughout `contract_ingestor.py` +and `ship_phase.sh`) does not natively produce multipart form bodies — +`attach_release_asset.py` must either (a) construct the multipart +boundary + body manually (the standard `urllib` pattern), or (b) use +`requests` if available. The repo's convention is stdlib-only +(`urllib`, no `requests` dependency in the ingestor), so the script +should construct the multipart body manually (C3 Simplicity — no new +dependency for one script; C8 Economy — stdlib is sufficient). A +~30-line `multipart_encode(fields, files)` helper is the standard +stdlib pattern. + +--- + +### 4. Marp PPTX Theme Fidelity + +#### 4.1 The PPTX export path and inline-CSS survival + +Source: the Marp CLI README (`https://github.com/marp-team/marp-cli`, +fetched) + the existing `docs/presentations/README.md` (lines 93–105) ++ the v1.9.2 theme commit `ae0cb58` (verified via `git show`). + +**Confirmed export command (from `docs/presentations/README.md` line +96–99):** +```bash +CHROME_PATH=/root/.cache/ms-playwright/chromium-1217/chrome-linux64/chrome \ + npx --yes @marp-team/marp-cli@latest --allow-local-files \ + docs/presentations/nova-no-humans-platform-marp.md \ + -o .pptx +``` + +**How PPTX export works (from the Marp CLI README, `--pptx` section):** +The default (non-editable) PPTX "consists of **pre-rendered background +images**." Marp renders each slide in a headless browser (Chrome/Chromium +via the `--browser-path` / `CHROME_PATH` env), captures the rendered +slide as a high-resolution image (default scale factor 2x — the README +states: "By default, Marp CLI will use 2 as the default scale factor in +PPTX"), and embeds those images as full-slide background pictures in the +PPTX. Presenter notes are supported; the PPTX opens in PowerPoint, +Keynote, Google Slides, LibreOffice Impress. + +**Inline `style:` CSS survival — CONFIRMED YES.** Because the slides +are **rasterized in a headless browser**, the browser's rendering engine +applies the inline `style:` CSS block (H1/H2 `#D6002A`, title-slide bg +`#1B1B1B` with 8px `#D6002A` accent, body text `#1B1B1B`, blockquote +border `#D6002A`, table headers `#F0F0F0`, font `'Akkurat Pro'` + +fallbacks) exactly as it does for HTML export. The CSS is *baked into +the pixels* of each slide image. The PPTX is a sequence of images, not +editable PPTX shapes — so there is no "CSS stripping" step. The S&P +Global Energy theme **survives PPTX export** in the standard +(non-editable) path. + +The current unified deck (`docs/presentations/nova-no-humans-platform-marp.md`) +already has the `style: |` block in its frontmatter (verified: line 8 +`style: |`, line 2 `marp: true`, line 3 `theme: default`). So the S&P +theme is already inline; PPTX export will honor it. + +**Caveat — `--pptx-editable` (NOT used):** The experimental +`--pptx-editable` flag generates editable PPTX (texts/shapes, not +images), and the README warns: "If the theme and inline styles are +providing complex styles into the slide, `--pptx-editable` may throw an +error or output the incomplete result." Nova does NOT use +`--pptx-editable` (the S&P theme is complex inline CSS); the standard +image-based PPTX is the path. REQ-228 specifies `--pptx +--allow-local-files`, not `--pptx-editable`. + +#### 4.2 Fallback (NOT needed, documented for completeness) + +If PPTX export ever strips inline CSS (it does NOT in the standard +path, per §4.1), the fallback is a **Marp custom theme CSS file** +referenced via `--theme `: + +```bash +CHROME_PATH=... npx @marp-team/marp-cli@latest --allow-local-files \ + --theme docs/presentations/assets/sp-theme.css \ + docs/presentations/nova-no-humans-platform-marp.md \ + -o output.pptx +``` + +Marp CLI supports custom theme CSS files via `--theme ` (the +README's "Use custom theme" section: "A custom theme created by user +also can use easily by passing the path of CSS file"). The CSS file +would be `docs/presentations/assets/sp-theme.css` containing the same +rules currently in the inline `style:` block, prefixed with the +`@theme` meta comment (Marpit convention: `/* @theme sp-energy */`). +The deck's frontmatter `theme:` directive would then be set to the +custom theme name instead of `default`. + +**Recommendation: do NOT use the fallback.** The inline `style:` block +survives the standard PPTX path (rasterized images). The fallback adds +a file to maintain in sync with the inline block (a DRY violation — +two sources of truth for the S&P colors). REQ-214 restores the S&P +theme *in the unified deck's inline `style:` block* (the v1.9.2 +pattern); the PPTX export uses the same deck file. **The S&P colors +survive PPTX export via the inline `style:` block. No `--theme` flag, +no separate CSS file needed.** Confidence 0.90 (the only residual risk +is a Marp CLI version regression that changes the rasterization path — +mitigated by `@marp-team/marp-cli@latest` pinning in the render script +and the PPTX slide-count/media verification step already in +`docs/presentations/README.md` lines 332–340). + +#### 4.3 `ship_phase.sh` release pattern + `attach_release_asset.py` extension + +Confirmed from `scripts/ship_phase.sh` (read in full, 46 lines): + +- **Line 38:** `POST + https://git.cloudinit.dev/api/v1/repos/continuous-intelligence/acdl/releases` + with `Authorization: token ` (read from + `.env.secrets`, line 35) + JSON body `{"tag_name", "name", "body"}` + (line 37). The response's `id` is the release ID (line 40: + `d.get('id')`). +- The script creates the tag, pushes, creates the release, prints + `release_id: tag: `. + +**How `attach_release_asset.py` extends it (REQ-228):** +`attach_release_asset.py` is a **separate script** (not a modification +to `ship_phase.sh`) that runs *after* the release exists. It takes a +release tag (or ID) + a file path, then: +1. **Resolve tag → release ID** (if only the tag is known): `GET + /api/v1/repos/continuous-intelligence/acdl/releases/tags/{tag}` → + the release object's `id`. +2. **Upload the asset:** `POST + /api/v1/repos/continuous-intelligence/acdl/releases/{id}/assets` + with multipart form (`name` = filename, `attachment` = file binary) + + `Authorization: token ` (same `.env.secrets` + source). +3. **Print** `asset_id: release: file: ` for the + ship log. + +The render+attach flow (REQ-228, triggered by any +`docs/presentations/*-marp.md` or `docs/presentations/assets/` change, +D-142): +``` +render_deck.sh → HTML (committed) + PPTX (committed, D-141) + ↓ +attach_release_asset.py → PPTX uploaded to the phase's Gitea release +``` + +PPTX is a **first-class artifact** (PROJECT.md line 682–683): committed +to git (history) + attached to the release (download) — both always, +not optional. This is the D-141 decision (no LFS — the binary is +committed directly). + +--- + +### 5. Assumptions logged (v1.18) + +- **A1 (0.92):** The Atelier `v0.3.6` tag is the correct pin. It is the + latest release (2026-08-05), the v0.4 milestone release, and the + complete matrix state (19 domains, 190 P-rules). `-11 commits to main + since this release` confirms `main` is a moving target — pinning is + required for audit reproducibility (D-136). Risk: a v0.5 lands before + P5 ships — mitigated by VERSION.md + update script (deliberate + upgrade, not silent drift). +- **A2 (0.88):** The MCP Python SDK v2 high-level server class is + `MCPServer` (import `from mcp.server import MCPServer`), NOT + `FastMCP`. The docs (landing page + Tools page) use `MCPServer` + consistently; `FastMCP` was the v1 name. D-137 (MCP Python SDK v2) + resolves to this import. Risk: the v1→v2 rename — if a future SDK + patch restores a `FastMCP` alias, both imports would work, but the v2 + canonical name is `MCPServer`. +- **A3 (0.85):** `mcp.run()` starts the stdio transport by default (no + explicit transport argument needed for the stdio path). The docs + show `uv run mcp dev server.py` (Inspector) and the "no protocol + handling" promise implies `mcp.run()` is the single entry point. The + exact `run()` signature for stdio vs HTTP is not spelled out on the + landing page (it's in the "Running your server" section, not fetched + in full); the D-135 decision (stdio now, HTTP-ready on the same + object) is consistent with a single `run()` entry point. P5 + implementation should verify the exact run call from the + "Running your server" docs page. +- **A4 (0.90):** The standard (non-editable) PPTX export bakes inline + `style:` CSS into the rasterized slide images. The Marp README + states PPTX "consists of pre-rendered background images" — the + browser rendering applies the CSS before rasterization. The S&P + theme survives PPTX export. The `--pptx-editable` path (NOT used) is + the only path that could strip CSS, and Nova does not use it. +- **A5 (0.88):** The Gitea release-asset endpoint is `POST + /api/v1/repos/{owner}/{repo}/releases/{id}/assets` with multipart + `name` + `attachment`. This is the standard Gitea API (the swagger at + `gitea.com/api/swagger` publishes the OpenAPI spec); the existing + `ship_phase.sh` uses the sibling `.../releases` endpoint, confirming + the API root + auth pattern. The `{id}` is the numeric release ID + (resolvable from the tag via `GET .../releases/tags/{tag}`). +- **A6 (0.85):** The submission-readiness schema uses JSON Schema draft + 2020-12 conditional `allOf` / `if-then` for the per-env mandatory + table (W3.E). This is the standard pattern for "if environment=qa + then require validation.e2eSuite + validation.loadTest." The + `jsonschema` library (already a dependency, used in + `contract_ingestor.py`) supports draft 2020-12 conditionals. The + validator (`core/submission_readiness.py`) may implement the per-env + check in Python (clearer reason codes) rather than relying solely on + schema conditionals — the schema is the *shape*, the validator is + the *gate* with the citizen-developer-facing reason codes (REQ-218). +- **A7 (0.80):** The `--check-readiness` CLI mode is added as a + `if __name__ == "__main__":` block in `contract_ingestor.py` (which + currently has none — it's Lambda-only). D-133 says "invoked as + `contract_ingestor.py --check-readiness`" — this is a local + pre-flight CLI, not a new Lambda action. The validator lives in + `core/submission_readiness.py` (REQ-218); the ingestor dispatches to + it. This keeps the Lambda path unchanged (the readiness gate is a + pre-write step in `_submit_contract` only if desired; the CLI path + is the citizen-developer pre-flight). Risk: the exact wiring (does + the Lambda also gate on readiness, or only the CLI?) is a P3 + implementation decision — REQ-218 says "On pass → proceeds to + existing contract ingestion," implying the gate is in the + submission path, but the CLI mode is the pre-flight surface. +- **A8 (0.90):** The 9-skill list in REQ-221 is final (no adjustment). + The research confirms the 9 Atelier domains map cleanly to the BA.A + 5-skill catalog; the 4 "reference-only" domains (Performance, + Documentation, Concurrency, AI/ML) are correctly NOT elevated to + skills. Adding a 10th skill would break REQ-221's exact list and the + BA.A mapping. +- **A9 (0.88):** The `mcp-engineer` persona is NOT needed — it folds + into backend-engineer. The MCP plugin-registry (D-140) is a Python + backend pattern (decorators, type hints, stdio, urllib). The SDK v2 + API surface is small and FastAPI/Pydantic-style (already in + backend-engineer's range). D-143 logged in PERSONAS.md records this. diff --git a/.ciagent/ROADMAP.md b/.ciagent/ROADMAP.md index 3e0e5fe..0cc3d2b 100644 --- a/.ciagent/ROADMAP.md +++ b/.ciagent/ROADMAP.md @@ -1683,3 +1683,62 @@ deferred (D-113/D-114). Ship tag at milestone COMPLETE: `v1.15.26` (NFR milestone; final patch IS the release). **DONE.** + +## v1.18 (active — Citizen Developer & Production-Grade Guidance, tag line `v1.17.x`) + +Nova advances from a platform that governs infrastructure delivery to one +that **instructs the citizen developer on production-grade engineering** +and defines a **clear, machine-checkable contract for what is acceptable +to start**. Five user-directed inputs drive the milestone: + +1. **S&P Global theme restoration** (P1) — the v1.17 P5 deck rebuild lost + the S&P Global Energy brand visual identity (introduced v1.9.2 / P45). + The Marp `style:` block (`#D6002A` red, `#1B1B1B` grey-90, Akkurat Pro, + 8px accent bar) is restored to the unified deck. +2. **PDLC-upstream scope** (P2) — promotes Core Tenet #2 + Anti-Goal #1 + from buried tenets to a dedicated, unmissable scope statement: the PDLC + is upstream of Nova; Nova governs infra + delivery only. +3. **RACI matrix** (P2) — three-role responsibility matrix (Citizen + Developer / Platform / Release Management co-owned) clarifies who owns + what, with the compliance-standard-equivalence note. +4. **Nova input contract** (P3) — `schemas/submission-readiness.schema.json` + + `core/submission_readiness.py` validator define "what is acceptable to + start" as a superset gate above contract-schema validity. +5. **Atelier integration** (P4+P5) — skills (markdown, extending BA.A) + an + MCP server (plugin-registry, vendored Atelier, agentic validation + beyond Wiz/Checkmarx/Mend). + +**Milestone type:** Feature (P1 theme restoration + P3 schema/validator + +P5 MCP server are new code). Tags run on the v1.17.x patch line: +`v1.17.0` (P0) → `v1.17.1..v1.17.6` (P1–P6) → `v1.17.7` (P7 final = +milestone release). + +**Deck automation (cross-cutting, REQ-228):** any phase modifying +`docs/presentations/*-marp.md` or `docs/presentations/assets/` re-renders +HTML + PPTX, commits the PPTX binary to git, and attaches it to the +phase's Gitea release. + +**Phase count:** 8 (P0 pre-execution + 6 execution + 1 final). + +**Phases:** +- **P1 — sp-theme-restoration** (feat): restore S&P Global Marp theme to + unified deck + HTML re-render + PPTX commit + release attach. REQ-214,228. +- **P2 — pdlc-scope-raci** (docs): PDLC-upstream scope + RACI matrix + + 2 deck slides + HTML/PPTX re-render. REQ-215,216,228. +- **P3 — submission-readiness** (feat): JSON Schema + validator + docs + + tests. REQ-217,218,219,220. +- **P4 — atelier-skills** (docs): 9 Atelier-derived skill files + index + + BA.A extension. REQ-221,222. +- **P5 — atelier-mcp** (feat): plugin-registry MCP server + vendored + Atelier + 4 tools + tests. REQ-223,224,225. +- **P6 — deck-slides-atelier** (docs): 3 new deck slides (scope/RACI/atelier) + → 21 slides + talking points + HTML/PPTX re-render + README. REQ-226,227,228. +- **P7 — final-review-ship** (final): review + audit + milestone ship. + +**Requirements:** REQ-214..228 (15 requirements). See +`.ciagent/REQUIREMENTS.md` §v1.18. + +**Open decisions to lock (CLARIFY/GRILL):** D-133 (validator location), +D-134 (deck slide budget), D-135 (MCP transport), D-136 (Atelier vendoring), +D-137 (MCP server language), D-138 (skill format), D-139 (RACI roles), +D-140 (MCP plugin-registry), D-141 (PPTX storage), D-142 (deck render trigger). diff --git a/.ciagent/config.json b/.ciagent/config.json index ed5f34e..91282dc 100644 --- a/.ciagent/config.json +++ b/.ciagent/config.json @@ -8,7 +8,7 @@ ], "active_project": "acdl", "active_projects": ["acdl"], - "active_milestone": "v1.17", + "active_milestone": "v1.18", "autonomy": { "level": "full", "escalation_hooks": ["deploy", "delete_data", "merge_to_main"],