Vertical-slice plan for v1.18 Citizen Developer & Production-Grade Guidance. Wave order: W1=P1, W2=P2, W3=P3+P4 (parallelizable), W4=P5, W5=P6, W6=P7. Sequential execution this run. 8 plan-level risks documented (conf 0.80-0.92). ---ci--- project: acdl phase: 0 milestone: v1.18 status: plan ---/ci---
53 KiB
Nova — Phase Plan v1.18 (Citizen Developer & Production-Grade Guidance)
Milestone: v1.18 — Citizen Developer & Production-Grade Guidance Branch:
milestone/v1.18-citizen-developer-guidanceTag line:v1.17.xpatch line —v1.17.0(P0) →v1.17.1..v1.17.6(P1–P6) →v1.17.7(P7 final = milestone release). Previous minor per branch-strategy (v1.17 shipped on the v1.16.x line; v1.18 is a Feature milestone → tags run on the previous minor's patch line = v1.17.x). Phase count: 8 (P0 pre-execution [DONE] + 6 execution + 1 final). Source of truth for requirements:.ciagent/REQUIREMENTS.md§v1.18 (REQ-214..228, 15 requirements). Source of truth for decisions:.ciagent/PROJECT.md§"Key Decisions (v1.18)" (D-133..D-142). Source of truth for research:.ciagent/RESEARCH.md§v1.18 (Atelier skill mapping, MCP SDK skeleton, submission-readiness gap analysis, Marp PPTX fidelity).
Wave Ordering
All 6 execution phases are sequenced for this run (the repo uses a flat
/ci-run workflow — one phase at a time). The theoretical parallelism is
documented for future parallelization-enabled runs.
| Wave | Phases | Rationale |
|---|---|---|
| Wave 1 | P1 | Theme restoration + render/attach scripts. P2/P6 depend on the render scripts existing. P6 depends on the S&P theme. Foundation — nothing else can ship a re-rendered deck without this. |
| Wave 2 | P2 | RACI + PDLC-scope docs + 2 deck slides → 20 slides. Depends on P1's render_deck.sh + attach_release_asset.py + restored S&P theme. Re-renders HTML+PPTX. |
| Wave 3 | P3, P4 (parallelizable) | P3 (submission-readiness schema+validator+doc+tests) and P4 (Atelier skills + index) have NO dependency on each other. P3 touches schemas/, core/, tests/, docs/submission-readiness.md. P4 touches skills/, docs/skills.md, PROJECT.md BA.A. Zero file overlap. In a parallelization-enabled run these two could execute concurrently. |
| Wave 4 | P5 | Atelier MCP server (plugin-registry, vendored Atelier, tests). Depends on P4's skill catalog being present (the MCP atelier.list_domains tool returns the Nova-relevance table that P4 codifies in docs/skills.md; the server reads the vendored Atelier snapshot that P5 itself vendors — but the skill provenance in docs/skills.md is the cross-reference). Strictly P5 vendors Atelier independently of P4; the dependency is narrative consistency (the MCP server's domain list should match the skills index). |
| Wave 5 | P6 | 3 new deck slides (scope/RACI/atelier) → 21 slides + README update + talking-points sync + HTML+PPTX re-render. Depends on P1 (theme + scripts), P2 (scope + RACI content + 2-slide precedent), P4 (atelier skills content for the Atelier slide), P5 (MCP server content for the Atelier slide). The deck slide that introduces Atelier must reflect what P4 + P5 actually shipped. |
| Wave 6 | P7 | Final review + audit + milestone ship (merge to main, tag v1.17.7, delete branches). |
Execution order for this run: P1 → P2 → P3 → P4 → P5 → P6 → P7 (sequential). The Wave 3 parallelism (P3‖P4) is noted for future runs but NOT exercised here.
Phase P1 — sp-theme-restoration (feat)
- Wave: 1
- Requirements covered: REQ-214, REQ-228
- Persona assignment: lead-developer (deck
style:block restoration + HTML re-render verification) + backend-engineer (scripts/render_deck.shscripts/attach_release_asset.py)
- Description: Restore the S&P Global Energy Marp
style:block (from commitae0cb58, v1.9.2 / P45) to the unified deck. The v1.17 P5 deck rebuild lost the S&P visual identity when it consolidated the two decks into one; the mermaidsp-theme.jsonsurvived but the Marp CSS theme was replaced with a generic dark-navy theme. Create the deck-automation scripts (render_deck.sh+attach_release_asset.py) that become the reusable render+commit+attach pipeline for P2 and P6. Re-render HTML. Commit the PPTX binary. Attach to the phase's Gitea release.
Tasks
- Edit
docs/presentations/nova-no-humans-platform-marp.md— replace the currentstyle: |block (lines 8–15, the generic dark-navy theme:#1a1a2e/#16213e) with the S&P Global Energystyle:block from commitae0cb58(docs/presentations/how-the-platform-works-marp.mdfrontmatter). The restored block must contain:section { font-family: "Akkurat Pro", "Helvetica Neue", "Arial", sans-serif; font-size: 22px; color: #1B1B1B; }h1 { color: #D6002A; font-size: 34px; margin-bottom: 0.3em; }h2 { color: #D6002A; font-size: 26px; margin-bottom: 0.2em; }section.title { background: #1B1B1B; color: #fff; border-top: 8px solid #D6002A; }section.title h1 { color: #fff; }table { font-size: 18px; width: 100%; }th { background: #F0F0F0; }blockquote { border-left: 4px solid #D6002A; color: #2E2E2E; font-size: 20px; }img { display: block; margin: 0 auto; max-height: 320px; }.badge { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 14px; font-weight: 600; }.today { background: #c6f6d5; color: #22543d; }.planned { background: #fef3c7; color: #78350f; }- Preserve the current Nova header text (
Nova — The No-Humans Infrastructure Platform) and thefooter: 'Act %{page}/5 — v1.17'line — the rebrand is NOT touched (REQ-214: "the current Nova header/footer text is preserved"). Only the visual theme (colors + font + accent bar) is restored.
- Create
scripts/render_deck.sh(executable,set -euo pipefail) — renders HTML + PPTX from a Marp deck markdown file. Usage:render_deck.sh <deck-marp.md>. Implementation per RESEARCH §4.1:- Reads the deck path from
$1(required; fails with usage message if absent). - Derives the output basename (strip
-marp.mdsuffix → bare name; e.g.nova-no-humans-platform-marp.md→nova-no-humans-platform). - Output paths:
<basename>.htmland<basename>.pptxin the same directory as the input deck. - HTML render:
npx --yes @marp-team/marp-cli@latest --allow-local-files <deck> -o <basename>.html(self-contained HTML, base64-embedded images). - PPTX render:
CHROME_PATH=<chromium-path> npx --yes @marp-team/marp-cli@latest --allow-local-files <deck> -o <basename>.pptx(standard image-based PPTX, NOT--pptx-editable— per RESEARCH §4.1 the inlinestyle:CSS survives the rasterization path). TheCHROME_PATHis resolved from~/.cache/ms-playwright/chromium-*/chrome-linux64/chrome(the existing path documented indocs/presentations/README.mdline 96). - Exit 0 on success; non-zero on render failure (the
set -epropagates). - Prints
rendered: <html-path>andrendered: <pptx-path>.
- Reads the deck path from
- Create
scripts/attach_release_asset.py(executable Python, stdlib-only per RESEARCH §3.5) — uploads a file to a Gitea release via the API. Usage:attach_release_asset.py --tag <release-tag> --file <path> [--name <display-name>]. Implementation per RESEARCH §3.5:- Reads
NOVA_GITEA_TOKENfrom.env.secrets(same source asscripts/ship_phase.shline 35) — load via a small helper that reads.env.secretskey=value lines. - Resolves tag → release ID:
GET https://git.cloudinit.dev/api/v1/repos/continuous-intelligence/acdl/releases/tags/{tag}withAuthorization: token <NOVA_GITEA_TOKEN>→ response JSONid. - Uploads the asset:
POST https://git.cloudinit.dev/api/v1/repos/continuous-intelligence/acdl/releases/{id}/assetswithmultipart/form-data(name= display filename,attachment= file binary) +Authorization: token <NOVA_GITEA_TOKEN>. - Constructs the multipart body manually via
urllib(stdlib-only, per RESEARCH §3.5 — a ~30-linemultipart_encode(fields, files)helper with a generated boundary; norequestsdependency). - Prints
asset_id: <id> release: <tag> file: <name>on success. - Exits non-zero on API error (HTTP non-2xx) with a clear message (not a stack trace — C2 Clarity).
- Reads
- Run
scripts/render_deck.sh docs/presentations/nova-no-humans-platform-marp.md— regeneratesnova-no-humans-platform.html(committed) + createsnova-no-humans-platform.pptx(committed, D-141 — no LFS). - Commit the updated deck markdown, the regenerated HTML, and the new PPTX binary to the phase branch.
- Attach the PPTX to the phase's Gitea release (after
ship_phase.shcreates thev1.17.1tag + release):python3 scripts/attach_release_asset.py --tag v1.17.1 --file docs/presentations/nova-no-humans-platform.pptx. - Update
docs/presentations/README.md— document the newrender_deck.sh+attach_release_asset.pyscripts in the deck-build process section; note that PPTX is now a committed binary (D-141) + attached to every phase's release (D-142).
Must-haves (verification gate)
docs/presentations/nova-no-humans-platform-marp.mdfrontmatterstyle:block contains#D6002A(S&P red-core),#1B1B1B(grey-90),8px solid #D6002A(top accent bar),'Akkurat Pro'(font). A grep for#D6002Ain the deck markdown returns ≥4 hits (h1, h2, title-bg border, blockquote border).- The Nova header (
Nova — The No-Humans Infrastructure Platform) and footer (Act %{page}/5 — v1.17) text are UNCHANGED (rebrand preserved — REQ-214). scripts/render_deck.shexists, is executable, and exits 0 when run against the unified deck.scripts/attach_release_asset.pyexists, is executable, andpython3 -m py_compile scripts/attach_release_asset.pysucceeds.docs/presentations/nova-no-humans-platform.htmlis regenerated (mtime newer than the deck markdown) and opens in a browser showing the S&P red accent bar + dark title-slide background.docs/presentations/nova-no-humans-platform.pptxexists (binary, committed, no LFS) and is attached to thev1.17.1Gitea release.docs/presentations/README.mddocuments the two new scripts.- CAP-024 deck structure regression passes (the S&P theme restoration must not break the 18-slide structure — slide count, x3 arc, per-slide benefit callouts all preserved).
Ship tag
v1.17.1
Phase P2 — pdlc-scope-raci (docs)
- Wave: 2
- Requirements covered: REQ-215, REQ-216, REQ-228
- Persona assignment: lead-developer (RACI matrix + PDLC-scope
statement in PROJECT.md +
docs/raci.md+docs/scope.md+ 2 deck slides + HTML/PPTX re-render) - Description: Promote Core Tenet #2 + Anti-Goal #1 from buried tenets to a dedicated, unmissable scope statement: the PDLC is upstream of Nova; Nova governs infra + delivery only; integration is through the validated contract boundary. Author a three-role RACI matrix clarifying who owns what across the citizen-developer → platform → release-management boundary. Add 2 deck slides (scope + RACI) → 20 slides. Re-render HTML + PPTX using P1's scripts; commit PPTX; attach to release.
Tasks
- Edit
PROJECT.md— add a new## Scope: Nova is Downstream of PDLCsubsection under## Domain Boundaries(after the existing "Interface:" bullet). Content (per REQ-216):- State that the PDLC (Product Development Lifecycle — product backlog, code authorship, IDE) is upstream of Nova.
- State that Nova governs infra + delivery only.
- State that integration is through the validated contract boundary (the contract is the only ingress; Nova does not penetrate upstream product/SDLC).
- Promote Core Tenet #2 ("The Delivery Lifecycle is a Sovereign Boundary") + Anti-Goal #1 ("Not an upstream development platform") from buried tenets to this dedicated, unmissable statement.
- Edit
PROJECT.md— add a new## RACI Matrixsection (after the## Scope: Nova is Downstream of PDLCsubsection, before## Core Tenetsor at the end of the Domain Boundaries cluster). Content (per REQ-215, D-139):- Three roles (columns): Citizen Developer, Platform, Release Management (co-owned).
- Rows = work categories: Functional Requirements, User Acceptance Testing, NFRs, Infrastructure, QA, Production Deploy, Release Attestation.
- Cells = R/A/C/I per role per category. The assignment per REQ-215:
- Citizen Developer: Responsible for all Functional Requirements
- User Acceptance Testing (via their AI coding agent / upstream agentic SDLC / upstream development platform — the source does not matter as all are subject to the same compliance standards).
- Platform: Responsible for all NFRs + Infrastructure + QA + Production deployments to cloud.
- Release Management: co-owned — QA + SRE attestations required by the actual release, performed agentically but overseen & triggered by the Citizen Developer.
- Citizen Developer: Responsible for all Functional Requirements
- Render as a markdown table.
- Include the compliance-standard-equivalence note: regardless of the source (AI agent, agentic SDLC, dev platform), the citizen developer's output is subject to the same compliance standards.
- Create
docs/scope.md— citizen-developer-facing copy of the PDLC-upstream scope statement. Cross-references PROJECT.md §Scope as the source of truth. Plain-language prose (no CIAgent metadata references — REQ-52 precedent). - Create
docs/raci.md— citizen-developer-facing copy of the RACI matrix. Renders the same table as PROJECT.md §RACI Matrix. Explains the three roles in plain language. Cross-references PROJECT.md §RACI Matrix as the source of truth. Includes the compliance-standard equivalence note. - Edit
docs/presentations/nova-no-humans-platform-marp.md— add 2 new slides after the existing Slide 16 (Recap + Ask), before the appendix slides:- Slide 19 — Scope: Downstream of PDLC. States the PDLC is upstream; Nova governs infra + delivery only; integration is through the contract boundary. Benefit callout: "you now know exactly where Nova's boundary is — infrastructure and delivery, not product development."
- Slide 20 — RACI: Who Owns What. Renders the 3-role × 7-category RACI table. Benefit callout: "you now know who is responsible for what — citizen developer owns FRs + UAT, platform owns NFRs + infra + deploy, release management is co-owned attestation."
- The 5-act arc (D-130) is preserved — these are append-only context slides, not a new act (per D-134: "no act restructure").
- Update the Slide 1 — Arc Preview text to reflect the 20-slide
count (change "18 slides" / "5-act arc" references if they cite a
count; the slide count is now 20 main + appendix). Update the footer
Act %{page}/5 — v1.17→Act %{page}/5 — v1.18(the deck now reflects the v1.18 milestone content).
- Run
scripts/render_deck.sh docs/presentations/nova-no-humans-platform-marp.md— regenerates HTML + PPTX (S&P theme preserved — regression check vs P1). - Commit the updated PROJECT.md,
docs/scope.md,docs/raci.md, the updated deck markdown, the regenerated HTML, and the regenerated PPTX binary. - Attach the PPTX to the
v1.17.2Gitea release viascripts/attach_release_asset.py --tag v1.17.2 --file docs/presentations/nova-no-humans-platform.pptx.
Must-haves (verification gate)
PROJECT.mdhas a## Scope: Nova is Downstream of PDLCsection under Domain Boundaries.PROJECT.mdhas a## RACI Matrixsection with a 3-column (Citizen Developer / Platform / Release Management) × 7-row table.docs/scope.mdexists, is citizen-developer-facing (no.ciagent/references), and cross-references PROJECT.md §Scope.docs/raci.mdexists, is citizen-developer-facing, renders the RACI table, and cross-references PROJECT.md §RACI Matrix.- The deck has 20 main slides (Slide 19 = Scope, Slide 20 = RACI) + the appendix slides. Slide 1 Arc Preview reflects 20 slides.
scripts/render_deck.shre-renders HTML + PPTX successfully; the S&P theme is preserved (grep#D6002Ain the deck markdown still returns ≥4 hits — P1 regression check).docs/presentations/nova-no-humans-platform.pptxis committed (binary) and attached to thev1.17.2Gitea release.- CAP-024 deck structure regression passes (20 slides, x3 arc, per-slide benefits on the 2 new slides).
Ship tag
v1.17.2
Phase P3 — submission-readiness (feat)
- Wave: 3
- Requirements covered: REQ-217, REQ-218, REQ-219, REQ-220
- Persona assignment: data-engineer (schema:
schemas/submission-readiness.schema.json- the ingestor dispatch wiring co-owned with backend-engineer) +
backend-engineer (validator
core/submission_readiness.py+ CLI mode incontract_ingestor.py+tests/test_submission_readiness.py+ reason-code catalog indocs/submission-readiness.md)
- the ingestor dispatch wiring co-owned with backend-engineer) +
backend-engineer (validator
- Description: Define what is "acceptable to start" as a machine-
checkable contract — a superset gate above
contract.schema.jsonvalidity. The schema adds required Nova tags, per-env mandatory metadata (W3.E), declared policy preconditions, thedeveloper/agenticprofile (with agentic markers per REQ-22/W3.E), and anappSourcepointer. The validator runs ascontract_ingestor.py --check-readiness(D-133), returns a structuredReadinessResultwith reason codes, and on fail emits a citizen-developer-facing error (not a stack trace).
Tasks
- Create
schemas/submission-readiness.schema.json(JSON Schema draft 2020-12) — per REQ-217 + RESEARCH §3.3. This is a superset gate ABOVEcontract.schema.json, NOT a duplicate (PROJECT.md hard constraint). It references but does not redefine contract fields. Schema fields:contractId: string, non-empty, required (promoted from the Lambda envelope to a contract-level required field).environment: enum["dev", "qa", "prod", "dr"], required (referencescontract.schema.json's environment — does not redefine; uses it to select the per-env mandatory set).tags: object, required. Required keys:nova:owner,nova:contract,nova:environment,nova:cost-center(nova:refoptional). Referencesschemas/tagging-standard.json'srequired_tagsshape (D-054).policyPreconditions: object (map of string→boolean/string), required. Declared policy expectations the platform will enforce (e.g.{"public-ingress": false}).profile: enum["developer", "agentic"], required (REQ-217 / W3.E).appSource: object{repo: string, ref: string}, required (REQ-217 — repo + ref pointer for runtime fetch).- Per-env mandatory (W3.E) — conditional
allOf/if-then:devrequiresstack+environment(base contract fields).qaaddsvalidation.e2eSuite+validation.loadTest.prodaddsrunbook+dashboard+oncall.draddsdrDrillRef.
inputsmap: optional everywhere (W3.E).profile: agentic→ conditionally requiresnaturalLanguageIntent(string),confidenceAtSubmission(number 0–1),agentTrace(object/string) per REQ-22 / W3.E.additionalProperties: falseat the top level (the gate is strict — no undocumented fields, per the v1.14 REQ-145 precedent).$id:https://nova.cloudinit.dev/schemas/submission-readiness.schema.json(D-110 brand consistency).$schema:https://json-schema.org/draft/2020-12/schema.
- Create
core/submission_readiness.py— the validator (REQ-218, D-133). Invoked ascontract_ingestor.py --check-readiness. Returns a structuredReadinessResult. Implementation per RESEARCH §3.2 + §3.4:ReadinessResultdataclass/Pydantic model:{passed: bool, checks: list[{name, passed, reason_code}], contract_id: str}.validate_readiness(contract: dict) -> ReadinessResult— the main entry point.- Validation order (two-layer gate, RESEARCH §3.2):
- Call
contract_ingestor._validate_contract_schema(contract)first (the shape gate — reuses the existing function incore/lambda/contract_ingestor.pyline 57; if shape fails, return early with aCONTRACT_SHAPE_INVALIDreason code). - Validate against
schemas/submission-readiness.schema.jsonviajsonschema(the gate — loads the schema from disk; if jsonschema unavailable, fail loud withSCHEMA_UNAVAILABLE). - Run the readiness checks that produce the citizen-developer-facing
reason codes (REQ-218):
MISSING_TAGS— the 5 required Nova tags are not all present.ENV_MISSING_MANDATORY:<env>:<field>— the per-env mandatory field is absent (e.g.ENV_MISSING_MANDATORY:qa:validation.e2eSuite).AGENTIC_MISSING_INTENT— profile isagenticbutnaturalLanguageIntent/confidenceAtSubmission/agentTraceis missing.MISSING_APP_SOURCE—appSourceis missing or incomplete.POLICY_PRECONDITION_MISSING—policyPreconditionsis empty or missing.
- Return all reason codes at once (not one-at-a-time — C2 Clarity: the citizen developer sees the full scope of fixes needed).
- Call
- On fail → the caller (CLI or Lambda) emits a citizen-developer-facing error (not a stack trace — REQ-218). On pass → proceeds to existing ingestion.
- Edit
core/lambda/contract_ingestor.py— add the--check-readinessCLI mode (D-133, RESEARCH §3.4 A-7). The ingestor is currently Lambda-only (no__main__block); P3 adds one:- Add
if __name__ == "__main__":block at the bottom that parsessys.argv(argparse). Subcommand:--check-readiness <contract-file>(reads a YAML/JSON contract file path; also supports--stdinto read from stdin). - The
--check-readinesssubcommand callscore.submission_readiness.validate_readiness(contract)and prints theReadinessResultas JSON to stdout. - On fail → exit non-zero with the citizen-developer-facing error
(the reason codes, not a stack trace). On pass → exit 0 with
READY: <contractId>. - The Lambda path is NOT changed by this task (the readiness gate is a pre-flight CLI surface; whether the Lambda also gates on readiness is a separate decision — REQ-218 says "On pass → proceeds to existing contract ingestion," which the CLI path satisfies).
- Co-ownership: backend-engineer owns the dispatch wiring; data-engineer owns the schema it validates against (PERSONAS.md territory-overlap table).
- Add
- Create
docs/submission-readiness.md— citizen-developer-facing doc (REQ-219). Explains what is acceptable to start. Sections:- What this checks — the 5 readiness dimensions (tags, per-env mandatory, policy preconditions, profile, appSource).
- Good example — a complete, passing contract (annotated with which checks it satisfies).
- Rejected examples — one per reason code (a contract missing
tags →
MISSING_TAGS; a qa contract missingvalidation.e2eSuite→ENV_MISSING_MANDATORY:qa:validation.e2eSuite; an agentic contract missing intent →AGENTIC_MISSING_INTENT; a contract missingappSource→MISSING_APP_SOURCE; a contract with emptypolicyPreconditions→POLICY_PRECONDITION_MISSING). - Reason-code catalog — the 5 reason codes with their meaning + how to fix (co-owned: lead-developer writes the narrative, backend-engineer writes the reason-code catalog that mirrors the validator's return codes — PERSONAS.md territory-overlap table).
- References
schemas/submission-readiness.schema.jsonas the source of truth.
- Create
tests/test_submission_readiness.py(REQ-220) — covers:- Good contract passes (all checks green,
ReadinessResult.passed == True). - Missing tags fail with
MISSING_TAGS. - Missing env mandatory fails with
ENV_MISSING_MANDATORY:<env>:<field>(test at least qa + prod + dr cases). - Agentic profile missing intent fails with
AGENTIC_MISSING_INTENT. - Missing appSource fails with
MISSING_APP_SOURCE. - Missing policyPreconditions fails with
POLICY_PRECONDITION_MISSING. - The CLI mode (
contract_ingestor.py --check-readiness) works end-to-end: a good contract file → exit 0 +READY:; a bad contract file → exit non-zero + the reason codes in stdout.
- Good contract passes (all checks green,
- Run the test suite —
pytest tests/test_submission_readiness.pypasses; the existing suite (pytest) still passes (no regressions).
Must-haves (verification gate)
schemas/submission-readiness.schema.jsonexists, is valid JSON Schema draft 2020-12, andpython3 -c "import jsonschema; jsonschema.Draft202012Validator.check_schema(json.load(open('schemas/submission-readiness.schema.json')))"succeeds.- The schema references
contract.schema.json(via$refor by delegating the shape check to the validator) — it does NOT redefineid/name/environment/infrastructure(superset gate, not duplicate — PROJECT.md hard constraint). core/submission_readiness.pyexists,python3 -m py_compile core/submission_readiness.pysucceeds, andvalidate_readiness(good_contract)returnsReadinessResult(passed=True).core/lambda/contract_ingestor.pyhas a__main__block;python3 core/lambda/contract_ingestor.py --check-readiness <good-contract.yaml>exits 0;python3 core/lambda/contract_ingestor.py --check-readiness <bad-contract.yaml>exits non-zero with a citizen-developer-facing reason code (not a stack trace).docs/submission-readiness.mdexists, has a good example + 5 rejected examples (one per reason code), and references the schema as source of truth.tests/test_submission_readiness.pypasses (all 5+ reason-code cases + the CLI end-to-end case).- The full test suite passes (
pytest— no regressions from the ingestor edit).
Ship tag
v1.17.3
Phase P4 — atelier-skills (docs)
- Wave: 3 (parallelizable with P3 in a parallelization-enabled run)
- Requirements covered: REQ-221, REQ-222
- Persona assignment: lead-developer (9 skill files +
docs/skills.mdindex + PROJECT.md BA.A extension) - Description: Create 9 Atelier-derived skill files under
skills/keyed to Atelier domain paths, extending the BA.A 5-skill citizen- developer catalog. Each skill names the Atelier source path, distills the first-principles to the citizen-developer-relevant subset, links to agent-checklist triggers, and maps to the BA.A catalog. Create adocs/skills.mdindex page. The research (RESEARCH §1.3) confirmed the exact 9-skill list — no adjustment needed.
Tasks
- Create
skills/directory with 9 Atelier-derived skill files (REQ-221, D-138). Each file is markdown, structured as:- Atelier source path (e.g.
domains/security/). - P-rules distilled (the citizen-developer-relevant subset — see RESEARCH §1.3 table for the exact P-rules per skill).
- First-principles distillation (plain language; no Atelier-internal jargon; the citizen-developer-relevant subset, not the full domain).
- Agent-checklist triggers (links to
review/agent-checklist.mdsections the citizen developer's AI agent runs before finishing a task). - BA.A catalog mapping (which of the 5 BA.A skills this extends: web API, worker, scheduled job, static asset, basic observability bootstrap — per RESEARCH §1.3). The 9 files (per REQ-221 + RESEARCH §1.3):
skills/api.md— Atelierdomains/api/. P-rules: P1 Contract Fidelity, P2 Clarity, P5 Versioning, P6 Idempotency, P8 Security, P9 Error Transparency. Extends: web API.skills/security.md— Atelierdomains/security/. P-rules: P1 Zero Trust, P2 Least Privilege, P4 Input Validation, P6 Crypto Correctness, P8 Fail Securely, P9 Secret Hygiene. Extends: all 5 (cross-cutting).skills/data.md— Atelierdomains/data/. P-rules: P1 Truth, P3 Invariants in Schema, P4 Migration Safety, P7 Type Fidelity, P9 Referential Integrity. Extends: web API, worker, scheduled job.skills/testing.md— Atelierdomains/testing/. P-rules: P1 Tests as Specification, P3 Determinism, P5 Coverage of Behavior, P9 Edge Case Coverage, P10 No Test Theater. Extends: all 5 (UAT is a citizen- developer RACI responsibility).skills/observability.md— Atelierdomains/observability/. P-rules: P1 Structured by Default, P2 Correlation, P6 No Secrets in Obs, P7 Actionable Alerts. Extends: basic observability bootstrap.skills/errors.md— Atelierdomains/errors/. P-rules: P1 Errors are Data, P2 Fail Loudly, P3 Fail Specifically, P4 Preserve Context, P5 Recoverable When Possible. Extends: web API, worker, scheduled job.skills/devops.md— Atelierdomains/devops/. P-rules: P1 Reproducibility, P4 Rollback First, P5 Progressive Delivery, P6 Config as Code, P8 Security at Every Layer. Extends: scheduled job, worker (deploy/release is co-owned Release Mgmt).skills/infrastructure-as-code.md— Atelierdomains/infrastructure-as-code/. P-rules: P1 Declarative Intent, P2 Idempotence, P4 Plan Before Apply, P5 Version Everything, P10 Secrets Never in Code. Extends: static asset (the contract→Terraform path).skills/compliance.md— Atelierdomains/compliance/. P-rules: P1 Audit Logs Append-Only, P2 Every Significant Action Logged, P4 Policy is Code, P5 Policy is Evaluated as a Gate, P9 Secrets Redacted in Audit. Extends: all 5 (cross-cutting; Nova's compliance posture).
- Atelier source path (e.g.
- Create
docs/skills.md(REQ-222) — the index page. Sections:- Skill catalog — a table listing the 9 skills with their Atelier source path + BA.A catalog mapping.
- Atelier provenance — explains the skills are derived from
coreci/atelier(the first-principles docs-as-code engineering framework — 8 core principles, 19 domains, 190 P-rules); the 9 skills are the citizen-developer-relevant subset of the 13 relevant domains (RESEARCH §1.2 — 6 domains excluded: UI/UX, Kubernetes, GitOps, i18n, Edge, Messaging). - How the citizen developer's AI agent consumes them — read the
relevant skill before completing a task; run the Atelier
review/agent-checklist.mdbefore finishing. The agent-checklist will be exposed as an MCP tool in P5 (atelier.validate_against_principles). - The 4 "reference-only" domains (Performance, Documentation,
Concurrency, AI/ML) — their principles are cited inside the 9 skills
- this index but do NOT get their own skill file (RESEARCH §1.2 — a citizen developer's first production-grade service does not need a standalone Concurrency or AI/ML skill).
- No
.ciagent/references (consumer-facing — REQ-52 precedent).
- Edit
PROJECT.md— extend the BA.A decision (W3.E resolution table, line ~886) with a reference to the Atelier-derived skill catalog. Add a note that the BA.A 5-skill catalog (web API, worker, scheduled job, static asset, basic observability bootstrap) is extended by the 9 Atelier-derived skills underskills/, indexed atdocs/skills.md.
Must-haves (verification gate)
skills/directory exists with exactly 9 markdown files:api.md,security.md,data.md,testing.md,observability.md,errors.md,devops.md,infrastructure-as-code.md,compliance.md.- Each skill file names its Atelier source path (e.g.
domains/security/), distills ≥4 P-rules, links to agent-checklist triggers, and maps to a BA.A catalog skill. docs/skills.mdexists, has a skill-catalog table (9 rows), an Atelier-provenance section, a "how the AI agent consumes them" section, and the 4 reference-only domains note.docs/skills.mdhas no.ciagent/references (consumer-facing).PROJECT.mdBA.A decision is extended with the Atelier-derived skill catalog reference.- The full test suite still passes (
pytest— no code changes, docs only, but verify no regressions).
Ship tag
v1.17.4
Phase P5 — atelier-mcp (feat)
- Wave: 4
- Requirements covered: REQ-223, REQ-224, REQ-225
- Persona assignment: backend-engineer (MCP server + plugin-registry + vendored Atelier + tests)
- Description: Build the Atelier MCP server (
mcp/atelier/server.py) with a plugin-registry architecture (D-140):plugins/<name>.pymodules each exposeregister(mcp) -> Noneand call@mcp.tool()for their tools. The server scansplugins/and callsregisteron each. Initial plugins:principles.py(atelier.lookup_principle,atelier.list_domains,atelier.matrix_lookup) andvalidation.py(atelier.validate_against_principles— agentic validation against the Atelier agent-checklist). Uses the MCP Python SDK v2 (D-137). stdio transport (D-135). Vendor the Atelier snapshot at pinned tagv0.3.6(D-136) for audit reproducibility.
Tasks
- Create
mcp/atelier/vendor/— vendored Atelier snapshot at tagv0.3.6(REQ-224, D-136, RESEARCH §1.6). The vendored content is a clean copy of the Atelier repo at tagv0.3.6(thecore/,domains/,matrix/,review/directories — the docs the MCP tools read;examples/andlanguages/are optional but included for completeness). Mechanics per RESEARCH §1.6:- Fetch
https://git.cloudinit.dev/coreci/atelier/archive/v0.3.6.tar.gz. - Extract the doc directories into
mcp/atelier/vendor/. - Verify the matrix is at the complete state: 19 domains, 190 P-rules
(the Coverage Summary in
matrix/principles-matrix.mdconfirms this).
- Fetch
- Create
mcp/atelier/vendor/VERSION.md— records the pinned tag + provenance (REQ-224, RESEARCH §1.6):- Tag:
v0.3.6 - Commit:
66b4767d25 - Date: 2026-08-05
- Milestone: "v0.4 Edge + Messaging + Language-Derived Docs"
- P-rule count: 190
- Domain count: 19
- Source URL:
https://git.cloudinit.dev/coreci/atelier
- Tag:
- Create
scripts/update_atelier_vendor.sh(executable,set -euo pipefail) — helper for intentional upgrades (REQ-224). Takes a tag arg, fetches the tarball fromhttps://git.cloudinit.dev/coreci/atelier/archive/<tag>.tar.gz, extracts the doc directories intomcp/atelier/vendor/, and updatesVERSION.md. Intentional upgrades only (re-run + re-audit). - Create
mcp/atelier/server.py(REQ-223, D-135, D-137, D-140, RESEARCH §2.2) — the MCP server. Implementation per the RESEARCH §2.2 skeleton:from mcp.server import MCPServer(v2 high-level server — NOTFastMCP, which was v1; RESEARCH §2.1 A-2).mcp = MCPServer("atelier")— one arg = server name.- Plugin-registry (D-140): scan
plugins/, import each module viaimportlib.import_module(f".plugins.{p.stem}", __package__), callregister(mcp)on each.sorted(pathlib.Path(__file__).parent.glob("plugins/*.py"))makes load order deterministic (audit reproducibility — RESEARCH §2.2 notes). @mcp.tool()for the server-level toolatelier_list_domains(or delegate to a plugin — the skeleton shows it inline; the implementation may move it toplugins/principles.pyfor consistency with the plugin-registry pattern).if __name__ == "__main__": mcp.run()— stdio transport is the default (D-135; RESEARCH §2.1 A-3). HTTP-ready on the same object (future milestone — Out of Scope for v1.18).
- Create
mcp/atelier/plugins/__init__.py— empty init (makesplugins/a package). - Create
mcp/atelier/plugins/principles.py(REQ-223, RESEARCH §1.5) — the principles plugin.register(mcp: MCPServer) -> Nonecontaining@mcp.tool()calls for:atelier_lookup_principle(domain: str, principle_id: str) -> PrincipleLookup— resolves a principle reference to its full text + core derivation + checklist items. Resolution path per RESEARCH §1.5: loadvendor/core/first-principles.md(if domain=="core") orvendor/domains/<domain>/first-principles.md, parse the principle section; cross-referencevendor/matrix/principles-matrix.mdfor the core derivation; cross-referencevendor/review/agent-checklist.mdfor checklist items; check non-tradeable status invendor/domains/<domain>/first-principles.md§3. Return thePrincipleLookupPydantic model (RESEARCH §1.5).atelier_list_domains() -> list[DomainInfo]— returns the 19 domain names + P-rule counts + Nova-relevance flag (the plugin hardcodes the Nova-relevance table from RESEARCH §1.2 so the citizen developer's agent can filter to the 13 relevant / 9 skill-bearing domains).atelier_matrix_lookup(domain: str) -> DomainMatrix— returns the full domain→core mapping for one domain (all 10 P-rules → their core C-rule(s)), used byvalidate_against_principlesto setseverityand by conflict resolution when two findings collide.- Lazily load + cache the vendored markdown in module-level dicts (C8 Economy — don't re-parse the matrix on every lookup; RESEARCH §2.2 notes).
- Create
mcp/atelier/plugins/validation.py(REQ-223, RESEARCH §1.4) — the validation plugin.register(mcp: MCPServer) -> Nonecontaining:atelier_validate_against_principles(snippet: str, language: str, domains: list[str], run_core: bool = True) -> ValidateResult— agentic validation against the Atelier agent-checklist, beyond Wiz/Checkmarx/Mend. Input/output models per RESEARCH §1.4 (ValidateInput,Violation,ValidateResultPydantic models). The plugin reads the vendoredreview/agent-checklist.md(frozen at the pinned tag — RESEARCH §1.4) and maps each checklist line to a predicate function keyed by(language, principle). The validation catches C1 (correctness) + C7 (observability) violations in a known-bad snippet and passes a known-good snippet (REQ-225 test case).
- Create
mcp/atelier/README.md(REQ-224) — documents the server:- How to run (
python3 mcp/atelier/server.py— stdio transport; the citizen developer's AI agent spawns the server as a subprocess). - Transport: stdio now (D-135); HTTP-ready on the same object (future milestone — Out of Scope).
- Tool catalog: the 4 tools (
atelier.lookup_principle,atelier.list_domains,atelier.matrix_lookup,atelier.validate_against_principles) with their input/output schemas. - Plugin-authoring guide: how to add a new plugin (
plugins/<name>.pywithregister(mcp)— D-140; noserver.pyedits). - Vendoring policy: pinned tag
v0.3.6for audit reproducibility (D-136);scripts/update_atelier_vendor.shfor intentional upgrades; live-fetch is NOT implemented (Out of Scope).
- How to run (
- Create
tests/test_atelier_mcp.py(REQ-225) — covers:- Tool registration — all 4 tools discoverable via
tools/list(the MCP protocol's tool-discovery call; the test spawns the server in-process or uses the SDK's test harness). atelier.lookup_principle("security", "P4")returns the principle text ("Input Validation") + core C-rule (C1) + checklist items (RESEARCH §1.5 example).atelier.validate_against_principlescatches a planted C1 (correctness) + C7 (observability) violation in a known-bad snippet and passes a known-good snippet (REQ-225 explicit case).atelier.matrix_lookup("security")returns the domain→core mapping (all 10 P-rules → their core C-rule(s)).- Plugin discovery — the server loads all plugins in
plugins/(the test verifiesplugins/principles.py+plugins/validation.pyare both loaded; theregisterfunction was called on each).
- Tool registration — all 4 tools discoverable via
- Add the MCP Python SDK v2 dependency to
requirements-test.txt(orpyproject.tomltest dependencies):mcp>=2.0(themodelcontextprotocol/python-sdkpackage; D-137). Pin per the project's dependency convention. - Run the test suite —
pytest tests/test_atelier_mcp.pypasses; the existing suite still passes.
Must-haves (verification gate)
mcp/atelier/server.pyexists,python3 -m py_compile mcp/atelier/server.pysucceeds, and importsfrom mcp.server import MCPServer(v2 high-level server — NOTFastMCP).mcp/atelier/plugins/principles.py+mcp/atelier/plugins/validation.pyexist; each has aregister(mcp)function containing@mcp.tool()calls.mcp/atelier/vendor/exists withcore/,domains/,matrix/,review/directories vendored from Atelier tagv0.3.6.mcp/atelier/vendor/VERSION.mdrecords tagv0.3.6, commit66b4767d25, 190 P-rules, 19 domains.scripts/update_atelier_vendor.shexists, is executable, and takes a tag arg.mcp/atelier/README.mddocuments how to run, transport, tool catalog, plugin-authoring guide, vendoring policy.tests/test_atelier_mcp.pypasses: 4 tools discoverable,lookup_principlereturns the principle + core rule,validate_against_principlescatches C1+C7 violations in a known-bad snippet + passes a known-good snippet,matrix_lookupreturns the domain→core mapping, plugin discovery loads all plugins.- The full test suite passes (
pytest— no regressions from the new dependency).
Ship tag
v1.17.5
Phase P6 — deck-slides-atelier (docs)
- Wave: 5
- Requirements covered: REQ-226, REQ-227, REQ-228
- Persona assignment: lead-developer (3 new deck slides + README update + talking-points sync + HTML/PPTX re-render)
- Description: Add the 21st deck slide to the unified deck → 21 slides total. P2 added slides 19 (Scope) + 20 (RACI); P6 adds slide 21 (Atelier). Update the Arc Preview slide to reflect 21 slides. Sync the talking-points file for the 3 new slides (Scope, RACI, Atelier). Re-render HTML + PPTX (S&P theme preserved — regression check vs P1). Update the README slide count + deck table.
Tasks
- Edit
docs/presentations/nova-no-humans-platform-marp.md— add the 21st slide (REQ-226, D-134):- Slide 21 — Production-Grade Guidance via Atelier. Content:
- The 9 Atelier-derived skills (under
skills/, indexed atdocs/skills.md) extend the BA.A 5-skill catalog. - The Atelier MCP server (
mcp/atelier/server.py, stdio transport) exposes 4 tools:atelier.lookup_principle,atelier.list_domains,atelier.matrix_lookup,atelier.validate_against_principles. - Agentic validation goes beyond deterministic scanners (Wiz/Checkmarx/Mend) by catching correctness/clarity/simplicity/ observability gaps (C1/C2/C3/C7) against the Atelier agent-checklist.
- Vendored Atelier (pinned tag
v0.3.6) for audit reproducibility (D-136) — an agentic validation result is replayable against the exact principles that produced it. - Benefit callout: "you now know the citizen developer is not unguided — production-grade engineering principles are machine-checkable, and the validation goes beyond SAST to correctness, clarity, simplicity, and observability."
- The 9 Atelier-derived skills (under
- Slides 19 (Scope) + 20 (RACI) were added in P2; P6 confirms they are still present and renumbers if needed so the slide order is Scope → RACI → Atelier (19 → 20 → 21).
- Update Slide 1 — Arc Preview to reflect 21 slides (change the slide-count reference; the 5-act arc is preserved — D-134: the 3 new slides are append-only context, not a new act).
- Slide 21 — Production-Grade Guidance via Atelier. Content:
- Edit
docs/presentations/nova-no-humans-platform-talking-points.md(REQ-226) — sync the talking points for the 3 new slides (Scope, RACI, Atelier). Each new slide gets a talking-points section with 3–6 punchy, actionable cues + a key takeaway per slide (per the v1.9.7 talking-points format). - Edit
docs/presentations/README.md(REQ-227) — update:- The slide count (21 slides + appendix).
- The deck table (add the 3 new slide titles: "Scope: Downstream of PDLC", "RACI: Who Owns What", "Production-Grade Guidance via Atelier").
- Run
scripts/render_deck.sh docs/presentations/nova-no-humans-platform-marp.md(REQ-228) — regenerates HTML + PPTX. The S&P theme is preserved (regression check vs P1 — grep#D6002Ain the deck markdown still returns ≥4 hits). - Commit the updated deck markdown, talking-points, README, the regenerated HTML, and the regenerated PPTX binary.
- Attach the PPTX to the
v1.17.6Gitea release viascripts/attach_release_asset.py --tag v1.17.6 --file docs/presentations/nova-no-humans-platform.pptx.
Must-haves (verification gate)
- The deck has 21 main slides: Slide 19 = Scope, Slide 20 = RACI, Slide 21 = Atelier (+ appendix slides).
- Slide 1 Arc Preview reflects 21 slides.
- Slide 21 (Atelier) mentions the 9 skills, the 4 MCP tools, agentic
validation beyond SAST, and the vendored pinned tag
v0.3.6. docs/presentations/nova-no-humans-platform-talking-points.mdhas talking-points sections for all 3 new slides (Scope, RACI, Atelier).docs/presentations/README.mdreflects 21 slides + the 3 new titles in the deck table.scripts/render_deck.shre-renders HTML + PPTX successfully; the S&P theme is preserved (grep#D6002A— P1 regression check).docs/presentations/nova-no-humans-platform.pptxis committed (binary) and attached to thev1.17.6Gitea release.- CAP-024 deck structure regression passes (21 slides, x3 arc, per-slide benefits on all 3 new slides).
Ship tag
v1.17.6
Phase P7 — final-review-ship (final)
- Wave: 6
- Requirements covered: all (REQ-214..228) — verification that every requirement is complete; milestone ship.
- Persona assignment: lead-developer (review coordination + audit + milestone ship) + backend-engineer (regression gate + technical verification) + data-engineer (schema audit)
- Description: Multi-persona review of all v1.18 phases, audit of the
requirement coverage, regression gate run (CAP-023 metrics collector +
CAP-024 deck structure + the existing 22 capabilities), and milestone
ship: merge to main, tag
v1.17.7, delete phase branches.
Tasks
- Review — multi-persona review of P1–P6. Lead-developer verifies the
deck (21 slides, S&P theme, x3 arc, talking-points sync), RACI +
scope docs, and skills index. Backend-engineer verifies the MCP
server (4 tools, plugin-registry, vendored Atelier), the
submission-readiness validator (reason codes, CLI mode), and the
render/attach scripts. Data-engineer verifies the submission-readiness
schema (superset gate, per-env mandatory, no duplication of contract
fields). Findings recorded in
.ciagent/REVIEW.md. - Audit — requirement coverage audit. Every REQ-214..228 is checked
against the shipped artifacts. The traceability table in
REQUIREMENTS.md§v1.18 is updated: all 15 requirements move frompending→complete (v1.17.x). Gaps are fixed before ship (no partial shipments). - Regression gate —
bash scripts/run_regression.sh(D-091) runs all auto-verifiable capabilities. CAP-023 (metrics collector) + CAP-024 (deck structure: 21 slides, x3 present, per-slide benefit present) must pass. The existing 22 capabilities must stay Verified (no regressions from v1.18's schema/code additions). - Milestone ship:
- Merge the milestone branch
milestone/v1.18-citizen-developer-guidancetomain. - Tag
v1.17.7(the milestone release tag — final patch on the v1.17.x line = the v1.18 milestone release per the tag-line decision). - Force-move the floating
v1.17+v1tags tov1.17.7(D-057 precedent — consumers on@v1.17or@v1receive the update). - Create the Gitea release for
v1.17.7with an auto-generated body (the v1.18 milestone summary). - Attach the final PPTX to the
v1.17.7release viascripts/attach_release_asset.py. - Delete the phase branches (
phase/01-sp-theme-restorationthroughphase/06-deck-slides-atelier) after merge.
- Merge the milestone branch
- Update
.ciagent/metadata — ROADMAP.md §v1.18 marked complete; PROJECT.md §v1.18 objective marked complete with the ship tag; CAPABILITY_INVENTORY.md gains CAP-025 (submission-readiness gate) + CAP-026 (Atelier MCP server) if the regression gate certifies them; REVIEW.md updated with the v1.18 review content.
Must-haves (verification gate)
- All 15 requirements (REQ-214..228) are
completein theREQUIREMENTS.md§v1.18 traceability table. bash scripts/run_regression.shpasses (all capabilities Verified; CAP-024 deck structure regression passes at 21 slides).- The milestone branch is merged to
main. - Tag
v1.17.7exists; floating tagsv1.17+v1point at it. - The
v1.17.7Gitea release exists with the PPTX attached. - Phase branches are deleted.
.ciagent/ROADMAP.md§v1.18 marked complete..ciagent/REVIEW.mdupdated with v1.18 review content.
Ship tag
v1.17.7 (milestone release)
Plan-Level Risks + Notes
- Atelier tag drift (A-1, conf 0.92). The vendored tag is
v0.3.6(fetched 2026-08-05). If a v0.5 milestone lands before P5 ships, the pin is stale — but the VERSION.md +update_atelier_vendor.shmodel makes a future upgrade a deliberate, audited action, not silent drift. P5 should re-verify the latest Atelier tag at execution time and document any divergence in VERSION.md. - MCP Python SDK v2 import name (A-2, conf 0.88). The high-level
server class is
MCPServer(NOTFastMCP, which was v1). If a future SDK patch restores aFastMCPalias, both imports would work, but the v2 canonical name isMCPServer. P5 should verify the import against the installed SDK version at execution time. mcp.run()stdio entry point (A-3, conf 0.85). The exactrun()signature for stdio vs HTTP is not fully spelled out on the SDK landing page. P5 should verify the exact run call from the "Running your server" docs page before finalizingserver.py. If stdio requires an explicit transport argument, the fix is a one-line change inserver.py(D-135 — the server object is transport-agnostic).- Submission-readiness validator wiring (A-7, conf 0.80). D-133
places the readiness gate as
contract_ingestor.py --check-readiness(a CLI pre-flight). REQ-218 says "On pass → proceeds to existing contract ingestion" — this is satisfied by the CLI path (the citizen developer runs--check-readinessbefore submitting). Whether the Lambda path ALSO gates on readiness (a pre-write gate in_submit_contract) is a P3 implementation decision. The plan defaults to CLI-only (the Lambda path is unchanged) to avoid changing the Lambda's behavior mid-milestone; the Lambda gate can be added in a future milestone if desired. - PPTX binary in git (D-141). Committing the PPTX binary directly (no LFS) is the decision. Decks are small (~1–5 MiB); git handles binary blobs. Binary diffs are not delta-friendly, but deck changes are infrequent (3 times this milestone). If the repo grows significantly, a future milestone may reconsider LFS — but only if git.cloudinit.dev confirms LFS server-side support.
- Wave 3 parallelism (P3‖P4) is theoretical. This run executes
sequentially (P3 then P4). The parallelism is noted for future
parallelization-enabled runs. The two phases have zero file overlap
(P3:
schemas/,core/,tests/,docs/submission-readiness.md; P4:skills/,docs/skills.md,PROJECT.mdBA.A) so they COULD run concurrently without conflict. - Deck slide numbering. P2 adds slides 19 + 20 (scope + RACI) → 20 slides. P6 adds slide 21 (Atelier) → 21 slides. The Arc Preview slide is updated in both P2 (to 20) and P6 (to 21). The 5-act arc (D-130) is preserved throughout — the new slides are append-only context, not a new act (D-134).
- No new frontend (frontend-engineer deactivated). v1.18 has no frontend; decks are markdown (lead-developer territory); the MCP server exposes tools to an AI agent, not a web UI. The frontend-engineer persona stays deactivated (PERSONAS.md v1.18 roster). No reactivation trigger in this milestone.