Merge phase/00-pre-execution — v1.17.0 (v1.18 P0 pre-execution complete: specify+clarify+research+plan+grill)
This commit is contained in:
@@ -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."
|
||||
}
|
||||
+102
-351
@@ -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/<name>.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. |
|
||||
+875
-1109
File diff suppressed because it is too large
Load Diff
+103
-1
@@ -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. |
|
||||
| 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/<name>.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. |
|
||||
@@ -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:<env>:<field>`,
|
||||
`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:<env>:<field>`; 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/<name>.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 |
|
||||
|
||||
@@ -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/<x>/first-principles.md` >
|
||||
`domains/<x>/<topic>.md` > `languages/<lang>.md` > `examples/<x>.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<n>. <Name>` section for `principle_id` (e.g. `C1` →
|
||||
the "C1. Correctness" section). Return the full principle text.
|
||||
2. Else: load `vendor/domains/<domain>/first-principles.md`, parse the
|
||||
`### P<n>. <Name>` 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
|
||||
`<Domain> P<n>`, 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 <Domain>` section,
|
||||
extract the checklist items tagged with `P<n>` (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/<domain>/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/<tag>.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:<env>:<field>` (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:<env>:<field>`,
|
||||
`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 <NOVA_GITEA_TOKEN>
|
||||
Content-Type: application/json
|
||||
Body: {"tag_name": "...", "name": "...", "body": "..."}
|
||||
Response: {"id": <release_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 <NOVA_GITEA_TOKEN>
|
||||
Content-Type: multipart/form-data
|
||||
Form fields:
|
||||
name = <filename, e.g. "nova-no-humans-platform.pptx">
|
||||
attachment = <the file, multipart>
|
||||
Response: {"id": <asset_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 <output-path>.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 <path>`:
|
||||
|
||||
```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 <path>` (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 <NOVA_GITEA_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: <id> tag: <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 <NOVA_GITEA_TOKEN>` (same `.env.secrets`
|
||||
source).
|
||||
3. **Print** `asset_id: <id> release: <tag> file: <name>` 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.
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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"],
|
||||
|
||||
Reference in New Issue
Block a user