Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2ea9fb4e51 | |||
| 52b16bbef1 | |||
| 68908d7f6a | |||
| 85cc962fda | |||
| ba28017f5b | |||
| 17903973aa | |||
| 6dfde4b785 | |||
| 13ee34b5a7 | |||
| ac791c7d23 | |||
| bc31c54940 | |||
| eda7e827b9 | |||
| 4c547780e5 | |||
| 0c4f5582f3 | |||
| b85da0471b | |||
| b51dfb1c03 | |||
| 246c0e93b3 | |||
| 50a8089e27 |
@@ -1,37 +1,28 @@
|
|||||||
{
|
{
|
||||||
"phase": 2,
|
"phase": 0,
|
||||||
"stage": "complete",
|
"stage": "plan",
|
||||||
"milestone": "v1.30",
|
"milestone": "v1.31",
|
||||||
"phase_role": "final",
|
"phase_role": "pre_execution",
|
||||||
"attempts": 0,
|
"attempts": 0,
|
||||||
"updated_at": "2026-08-20T14:40:00Z",
|
"updated_at": "2026-08-20T16:18:00Z",
|
||||||
"project": "acdl",
|
"project": "acdl",
|
||||||
"projects": ["acdl", "nova-blockchain-exchange"],
|
"projects": ["acdl", "nova-blockchain-exchange"],
|
||||||
"active_milestone": "v1.30",
|
"active_milestone": "v1.31",
|
||||||
"milestone_branch": null,
|
"milestone_branch": "milestone/v1.31-leadership-deck-polish",
|
||||||
"phase_branch": null,
|
"phase_branch": "acdl/phase/00-pre-execution",
|
||||||
"tag_line": "v1.29.x",
|
"tag_line": "v1.30.x",
|
||||||
"phase_name": "final-review-ship",
|
"phase_name": "pre-execution",
|
||||||
"milestone_type": "feature",
|
"milestone_type": "nfr",
|
||||||
"reqs_covered": ["REQ-372.1","REQ-372.2","REQ-372.3","REQ-372.4","REQ-372.5","REQ-372.6","REQ-372.7","REQ-372.8","REQ-372.9","REQ-372.10","REQ-372.11","REQ-372.12"],
|
"reqs_covered": [],
|
||||||
"reqs_partial": [],
|
"reqs_partial": [],
|
||||||
"previous_milestone": {
|
"previous_milestone": {
|
||||||
"milestone": "v1.30",
|
"milestone": "v1.30",
|
||||||
"tag": "v1.29.3",
|
"tag": "v1.29.5",
|
||||||
"complete": true,
|
"complete": true,
|
||||||
"merged_to_main": "96765fe",
|
"merged_to_main": "13ee34b",
|
||||||
"branches_deleted": true,
|
"branches_deleted": true,
|
||||||
"releases_created": true,
|
"releases_created": true,
|
||||||
"release_ids": [811, 812, 813]
|
"release_ids": [811,812,813,814,818]
|
||||||
},
|
},
|
||||||
"ship": {
|
"notes": "v1.31 P0 complete (specify+clarify+research+plan). D-247 locked: refinement-only, theme-preserving invariants. Plan = single vertical slice P1: rewrite visible prose + improve layout in nova-leadership-deck-marp.md, re-render PPTX, smoke test must pass."
|
||||||
"tag": "v1.29.3",
|
|
||||||
"release_id": 813,
|
|
||||||
"release_url": "https://git.cloudinit.dev/continuous-intelligence/acdl/releases/tag/v1.29.3",
|
|
||||||
"merged_to_main": true,
|
|
||||||
"merge_commit": "96765fe",
|
|
||||||
"branches_deleted": ["phase/02-final-review-ship", "milestone/v1.30-leadership-deck"],
|
|
||||||
"local_only": false
|
|
||||||
},
|
|
||||||
"notes": "v1.30 MILESTONE COMPLETE. Tag v1.29.3 (milestone release), Gitea release id=813. Merged to main 96765fe. All milestone branches deleted (local + remote). REQ-372.1..12 all complete. CAP-042 + D-241..D-243 recorded. 3 Gitea releases: 811 (P0 v1.29.1), 812 (P1 v1.29.2), 813 (P2 v1.29.3). Checkpoint cleared — next run starts a new milestone."
|
|
||||||
}
|
}
|
||||||
@@ -689,8 +689,8 @@ New requirements REQ-354..REQ-369 + REQ-371 + REQ-363b — full text in
|
|||||||
|
|
||||||
### v1.30 ID allocations (no collisions with shipped history)
|
### v1.30 ID allocations (no collisions with shipped history)
|
||||||
|
|
||||||
- **Decisions:** `D-241..D-243` (3 decisions, authored in CLARIFY).
|
- **Decisions:** `D-241..D-246` (6 decisions, authored in CLARIFY
|
||||||
Max existing D = D-240 (v1.29). Next free: D-244.
|
across P0 + P3). Max existing D = D-240 (v1.29). Next free: D-247.
|
||||||
- **D-241** — Leadership deck is a single-shot, discrete, hand-
|
- **D-241** — Leadership deck is a single-shot, discrete, hand-
|
||||||
authored artifact (NOT a compression of the existing citizen-
|
authored artifact (NOT a compression of the existing citizen-
|
||||||
developer pitch `nova-autonomous-cloud-delivery-marp.md`).
|
developer pitch `nova-autonomous-cloud-delivery-marp.md`).
|
||||||
@@ -707,6 +707,18 @@ New requirements REQ-354..REQ-369 + REQ-371 + REQ-363b — full text in
|
|||||||
- **D-243** — Date anchor discipline: August 2026 is a month-only
|
- **D-243** — Date anchor discipline: August 2026 is a month-only
|
||||||
presentation anchor (no specific day); November 2026 is the
|
presentation anchor (no specific day); November 2026 is the
|
||||||
runway anchor (~90 days).
|
runway anchor (~90 days).
|
||||||
|
- **D-244** — Slide 1 becomes a black-background cover (overrides
|
||||||
|
grill G-1). Visual treatment only; on-slide text unchanged.
|
||||||
|
- **D-245** — Slide 7 "What works now" content addition. New
|
||||||
|
on-slide block before the ask. Records: 13 L1 + 2 L2 live
|
||||||
|
(confidence 0.800), next-steps arc (greenfield pilots → promote
|
||||||
|
to prod → SPGE constitutional library → infra layer). "sandbox"
|
||||||
|
is colloquial for the dev AWS account `581513795199`; "SPGE
|
||||||
|
constitutional library" is external/unverified-in-repo.
|
||||||
|
- **D-246** — 7 S&P-themed mermaid diagrams, one per slide,
|
||||||
|
rendered via local mmdc with vendored Chromium libs (24 Debian
|
||||||
|
bookworm .deb packages fetched, `.so` files extracted). `.mmd`
|
||||||
|
sources + PNGs committed for reproducibility.
|
||||||
- **Capabilities:** `CAP-042` (1 capability, appended at ship).
|
- **Capabilities:** `CAP-042` (1 capability, appended at ship).
|
||||||
Max existing CAP = CAP-041 (v1.29). Next free: CAP-043.
|
Max existing CAP = CAP-041 (v1.29). Next free: CAP-043.
|
||||||
|
|
||||||
@@ -1032,4 +1044,98 @@ Infrastructure & Operations leadership in August 2026." Asks for
|
|||||||
architecture endorsement and runway to next milestone by November
|
architecture endorsement and runway to next milestone by November
|
||||||
2026. Velocity framing with **60% goal as internal directional
|
2026. Velocity framing with **60% goal as internal directional
|
||||||
target, not sourced claim**. Closes with "Use the runway to land the
|
target, not sourced claim**. Closes with "Use the runway to land the
|
||||||
architecture endorsement."
|
architecture endorsement."
|
||||||
|
|
||||||
|
## v1.31 — Leadership Deck Polish II (active milestone)
|
||||||
|
|
||||||
|
> **NFR/refinement milestone — polish pass on the v1.30 leadership
|
||||||
|
> deck.** A single refinement phase that enriches the visible on-slide
|
||||||
|
> prose, improves the slide layout, and re-renders the PPTX — without
|
||||||
|
> altering the S&P visual theme, the 7-slide structure, the speaker-note
|
||||||
|
> word-count bands, the vision `[1]` grounding, or the diagram PNGs.
|
||||||
|
> The v1.30 deck shipped with sparse visible wording (slides 2–6
|
||||||
|
> averaged 43–67 visible words, leaning on diagrams); v1.31 makes each
|
||||||
|
> slide stand on its own as a readable artifact while a presenter
|
||||||
|
> speaks, so the deck reads cleanly both live and as a leave-behind.
|
||||||
|
>
|
||||||
|
> This is a **refinement-only** milestone (no new features, no new
|
||||||
|
> slides, no theme change, no schema change). Tags run on the
|
||||||
|
> **v1.30.x** line (previous minor): `v1.30.0` (P0) → `v1.30.1` (P1
|
||||||
|
> execution = milestone release). Milestone branch:
|
||||||
|
> `milestone/v1.31-leadership-deck-polish`. Authoritative resume
|
||||||
|
> state: `.ciagent/CHECKPOINT.json`.
|
||||||
|
>
|
||||||
|
> **Source spec:** REQ-373 v1.0 (locked 2026-08-20). Full requirement
|
||||||
|
> text in `.ciagent/REQUIREMENTS.md` §v1.31.
|
||||||
|
|
||||||
|
### v1.31 ID allocations (no collisions with shipped history)
|
||||||
|
|
||||||
|
- **Decisions:** `D-247` (1 decision, authored in CLARIFY).
|
||||||
|
- **D-247** — Polish is **refinement-only and theme-preserving**.
|
||||||
|
The S&P theme tokens (`#D6002A`, `#1B1B1B`, `#FFFFFF`, `#F0F0F0`),
|
||||||
|
the 7-slide count, the per-slide speaker-note word-count bands
|
||||||
|
(1/2/4/6: 150–300; 3/5: 250–400; 7: 200–300), the vision `[1]`
|
||||||
|
citations on slides 3/5/7, the 7 mermaid diagram PNGs, and the
|
||||||
|
footer string are all **invariants** of this milestone — they must
|
||||||
|
not change. Polish is confined to: (a) denser, better-structured
|
||||||
|
visible body prose on each slide, (b) layout improvement within
|
||||||
|
the existing `render_pptx.py` block vocabulary (lead/quote/plain/
|
||||||
|
bullet/ordered/image/table/benefit), and (c) re-rendering the
|
||||||
|
PPTX. No new slides, no new diagrams, no theme tokens, no new
|
||||||
|
speaker-note bands. The citizen-developer deck
|
||||||
|
(`nova-autonomous-cloud-delivery-marp.md`) remains untouched
|
||||||
|
(D-241 still holds).
|
||||||
|
- **Capabilities:** none new (CAP-042 is refined in place; no new CAP
|
||||||
|
allocated). Next free CAP remains CAP-043.
|
||||||
|
|
||||||
|
### v1.31 Scope (CLARIFY-grounded, full autonomy)
|
||||||
|
|
||||||
|
Refinement of `docs/presentations/nova-leadership-deck-marp.md`:
|
||||||
|
|
||||||
|
- Enrich the **visible on-slide prose** on every slide so the deck
|
||||||
|
reads as a standalone artifact (current slides 2–6 average 43–67
|
||||||
|
visible words; target a denser, well-structured body that does not
|
||||||
|
crowd the diagram or overflow the slide).
|
||||||
|
- Improve **slide layout** using the existing renderer's block
|
||||||
|
vocabulary — re-balance the order of lead/quote/plain/benefit
|
||||||
|
blocks so each slide has a clear title, a framing line, the body,
|
||||||
|
the diagram, and a closing italic benefit line where present.
|
||||||
|
- Preserve all invariants (D-247): theme tokens, slide count = 7,
|
||||||
|
speaker-note bands, `[1]` citations on 3/5/7, the 7 diagram PNGs,
|
||||||
|
the footer string.
|
||||||
|
- Re-render `docs/presentations/nova-leadership-deck.pptx` via
|
||||||
|
`scripts/render_pptx.py`; the smoke test
|
||||||
|
`scripts/check_leadership_deck.sh` must still exit 0.
|
||||||
|
|
||||||
|
### v1.31 Hard constraints (invariants — D-247)
|
||||||
|
|
||||||
|
- Slide count stays exactly 7.
|
||||||
|
- S&P theme tokens are the only colors.
|
||||||
|
- Speaker-note word counts stay in band per REQ-372.4 bands.
|
||||||
|
- `[1]` citations remain present in slides 3, 5, 7 speaker notes.
|
||||||
|
- The 7 diagram PNGs (`assets/png/leadership-slide-N.png`) are reused
|
||||||
|
unchanged; `.mmd` sources are not modified.
|
||||||
|
- Footer string `Nova Platform - Infrastructure & Operations` unchanged.
|
||||||
|
- `scripts/render_pptx.py` is not modified (no new renderer features
|
||||||
|
needed — polish uses the existing block vocabulary).
|
||||||
|
- The citizen-developer deck is not touched.
|
||||||
|
|
||||||
|
### v1.31 Requirements
|
||||||
|
|
||||||
|
Full text in `.ciagent/REQUIREMENTS.md` §v1.31. Summary:
|
||||||
|
|
||||||
|
- **REQ-373.1** — Visible prose density: every slide's on-slide body
|
||||||
|
(excluding speaker notes + images) is enriched to a richer, well-
|
||||||
|
structured wording that reads as a standalone artifact.
|
||||||
|
- **REQ-373.2** — Layout improvement: each slide uses the renderer's
|
||||||
|
block vocabulary to balance title → frame → body → diagram → benefit.
|
||||||
|
- **REQ-373.3** — Invariants preserved (D-247): theme, 7 slides,
|
||||||
|
note bands, `[1]` citations, diagram PNGs, footer.
|
||||||
|
- **REQ-373.4** — PPTX re-rendered; smoke test exits 0.
|
||||||
|
|
||||||
|
### v1.31 phase status (live — tag `v1.30.1` = the milestone release)
|
||||||
|
|
||||||
|
| Phase | Status | Tag |
|
||||||
|
|-------|--------|-----|
|
||||||
|
| P0 pre-execution | in flight | v1.30.0 |
|
||||||
|
| P1 polish | pending | v1.30.1 (milestone release) |
|
||||||
@@ -1025,15 +1025,96 @@ principles, anti-goals, and integration-boundary claims to
|
|||||||
|
|
||||||
| REQ | Phase | Status |
|
| REQ | Phase | Status |
|
||||||
|-----|-------|--------|
|
|-----|-------|--------|
|
||||||
| REQ-372.1 | P1 | complete (v1.29.2) |
|
| REQ-372.1 | P1/P3 | complete (v1.29.5, polished) |
|
||||||
| REQ-372.2 | P1 | complete (v1.29.2) |
|
| REQ-372.2 | P1/P3 | complete (v1.29.5, polished) |
|
||||||
| REQ-372.3 | P1 | complete (v1.29.2) |
|
| REQ-372.3 | P1/P3 | complete (v1.29.5, polished) |
|
||||||
| REQ-372.4 | P1 | complete (v1.29.2) |
|
| REQ-372.4 | P1/P3 | complete (v1.29.5, polished) |
|
||||||
| REQ-372.5 | P1 | complete (v1.29.2) |
|
| REQ-372.5 | P1/P3 | complete (v1.29.5, polished) |
|
||||||
| REQ-372.6 | P1 | complete (v1.29.2) |
|
| REQ-372.6 | P1/P3 | complete (v1.29.5, polished) |
|
||||||
| REQ-372.7 | P1 | complete (v1.29.2, visual review pass) |
|
| REQ-372.7 | P1/P3 | complete (v1.29.5, polished + diagrams) |
|
||||||
| REQ-372.8 | P1 | complete (v1.29.2) |
|
| REQ-372.8 | P1/P3 | complete (v1.29.5, polished) |
|
||||||
| REQ-372.9 | P1 | complete (v1.29.2) |
|
| REQ-372.9 | P1/P3 | complete (v1.29.5, polished) |
|
||||||
| REQ-372.10 | P1 | complete (v1.29.2) |
|
| REQ-372.10 | P1/P3 | complete (v1.29.5, polished) |
|
||||||
| REQ-372.11 | P1 | complete (v1.29.2) |
|
| REQ-372.11 | P1/P3 | complete (v1.29.5, polished) |
|
||||||
| REQ-372.12 | P1 | complete (v1.29.2) |
|
| REQ-372.12 | P1/P3 | complete (v1.29.5, polished) |
|
||||||
|
|
||||||
|
## v1.31 — Leadership Deck Polish II (active milestone)
|
||||||
|
|
||||||
|
> **Refinement-only NFR milestone — polish pass on the v1.30 leadership
|
||||||
|
> deck.** Enriches visible on-slide prose + improves layout, then
|
||||||
|
> re-renders the PPTX. No new features, no new slides, no theme change,
|
||||||
|
> no diagram change (D-247). Tags run on the **v1.30.x** line (previous
|
||||||
|
> minor): `v1.30.0` (P0) → `v1.30.1` (P1 = milestone release). The
|
||||||
|
> v1.30 requirements (REQ-372.1..12) remain complete and are NOT
|
||||||
|
> re-opened; v1.31 adds REQ-373.1..4 as a refinement layer over the
|
||||||
|
> same artifact.
|
||||||
|
|
||||||
|
### Decisions (locked in CLARIFY, full autonomy — load-bearing for v1.31)
|
||||||
|
|
||||||
|
- **D-247 (refinement-only, theme-preserving):** The polish is
|
||||||
|
confined to visible prose density + layout. The following are
|
||||||
|
**invariants** and must not change: the S&P theme tokens
|
||||||
|
(`#D6002A`, `#1B1B1B`, `#FFFFFF`, `#F0F0F0`); the 7-slide count; the
|
||||||
|
per-slide speaker-note word-count bands (1/2/4/6: 150–300; 3/5:
|
||||||
|
250–400; 7: 200–300, per REQ-372.4); the `[1]` citations on slides
|
||||||
|
3/5/7 (per REQ-372.12); the 7 mermaid diagram PNGs and their `.mmd`
|
||||||
|
sources; the footer string `Nova Platform - Infrastructure &
|
||||||
|
Operations`. No new slides, no new diagrams, no renderer changes.
|
||||||
|
The citizen-developer deck is untouched (D-241 still holds).
|
||||||
|
|
||||||
|
### Requirements
|
||||||
|
|
||||||
|
#### REQ-373.1 — Visible prose density enriched per slide
|
||||||
|
|
||||||
|
**Priority:** High · **Journey:** J1
|
||||||
|
|
||||||
|
**Given** the v1.30 deck shipped with sparse visible wording (slides
|
||||||
|
2–6 averaged 43–67 visible words, leaning on diagrams), **when** the
|
||||||
|
polished source markdown is inspected, **then** every slide's on-slide
|
||||||
|
body (excluding speaker-note HTML comments and image references)
|
||||||
|
carries richer, well-structured wording that lets the slide read as a
|
||||||
|
standalone artifact — a title, a framing line, a body, and (where
|
||||||
|
present) a closing italic benefit — without crowding the diagram or
|
||||||
|
overflowing the 16:9 slide. Verified by visual review against the
|
||||||
|
Slide Content Map and by the smoke test still passing.
|
||||||
|
|
||||||
|
#### REQ-373.2 — Layout improved within the renderer block vocabulary
|
||||||
|
|
||||||
|
**Priority:** High · **Journey:** J1
|
||||||
|
|
||||||
|
**Given** the existing `scripts/render_pptx.py` block vocabulary
|
||||||
|
(lead/quote/plain/bullet/ordered/image/table/benefit) is not modified,
|
||||||
|
**when** the polished PPTX is rendered, **then** each slide balances
|
||||||
|
its blocks so the reading order is clear (title → frame → body →
|
||||||
|
diagram → benefit) and the diagram remains the visual anchor. No new
|
||||||
|
renderer features are added.
|
||||||
|
|
||||||
|
#### REQ-373.3 — v1.30 invariants preserved (D-247)
|
||||||
|
|
||||||
|
**Priority:** High · **Journey:** J1
|
||||||
|
|
||||||
|
**Given** the D-247 invariants, **when** the polished source + PPTX
|
||||||
|
are validated, **then**: slide count = 7; the only hex colors are the
|
||||||
|
four S&P tokens; per-slide speaker-note word counts remain in band per
|
||||||
|
REQ-372.4; `[1]` citations remain in slides 3, 5, 7 speaker notes; the
|
||||||
|
7 diagram PNGs are reused unchanged; the footer string is unchanged.
|
||||||
|
The smoke test enforces (a)–(f) and must exit 0.
|
||||||
|
|
||||||
|
#### REQ-373.4 — PPTX re-rendered; smoke test exits 0
|
||||||
|
|
||||||
|
**Priority:** High · **Journey:** J1
|
||||||
|
|
||||||
|
**Given** the polished source markdown, **when**
|
||||||
|
`scripts/render_pptx.py docs/presentations/nova-leadership-deck-marp.md
|
||||||
|
--output docs/presentations/nova-leadership-deck.pptx` is invoked,
|
||||||
|
**then** the PPTX is written with 7 slides and python-pptx raises no
|
||||||
|
exceptions, **and** `bash scripts/check_leadership_deck.sh` exits 0.
|
||||||
|
|
||||||
|
### v1.31 Traceability (live — see CHECKPOINT.json for authoritative state)
|
||||||
|
|
||||||
|
| REQ | Phase | Status |
|
||||||
|
|-----|-------|--------|
|
||||||
|
| REQ-373.1 | P1 | pending |
|
||||||
|
| REQ-373.2 | P1 | pending |
|
||||||
|
| REQ-373.3 | P1 | pending |
|
||||||
|
| REQ-373.4 | P1 | pending |
|
||||||
@@ -146,22 +146,40 @@
|
|||||||
10 NFR constraints. Tags: `v1.28.0` (P0) → `v1.28.1..v1.28.5` (P1..P5)
|
10 NFR constraints. Tags: `v1.28.0` (P0) → `v1.28.1..v1.28.5` (P1..P5)
|
||||||
→ `v1.28.6` (P6 final = milestone release).
|
→ `v1.28.6` (P6 final = milestone release).
|
||||||
|
|
||||||
- **v1.30 (complete, tag `v1.29.3` = the v1.30 release, merged to main
|
- **v1.30 (complete, tag `v1.29.5` = the v1.30 release, merged to main
|
||||||
2026-08-20):** Single-shot Leadership Deck. Feature milestone. A
|
2026-08-20):** Single-shot Leadership Deck (polished). Feature
|
||||||
hand-authored 7-slide PPTX deck for Infrastructure & Operations
|
milestone. A hand-authored 7-slide PPTX deck for Infrastructure &
|
||||||
leadership (CTO + VP Technology + Product Management), presented
|
Operations leadership (CTO + VP Technology + Product Management),
|
||||||
August 2026, securing architecture endorsement and a November 2026
|
presented August 2026, securing architecture endorsement and a
|
||||||
runway. The deck is a **discrete artifact** (D-241: NOT a
|
November 2026 runway. The deck is a **discrete artifact** (D-241:
|
||||||
compression of the existing citizen-developer pitch
|
NOT a compression of the existing citizen-developer pitch
|
||||||
`nova-autonomous-cloud-delivery-marp.md`, which remains unmodified).
|
`nova-autonomous-cloud-delivery-marp.md`, which remains unmodified).
|
||||||
Authored as Marp markdown, rendered via the existing
|
Authored as Marp markdown, rendered via the existing
|
||||||
`scripts/render_pptx.py` (narrowly extended per D-242: path arg +
|
`scripts/render_pptx.py` (narrowly extended per D-242: path arg +
|
||||||
`--output` + per-slide footer textbox + leading-comment skip).
|
`--output` + per-slide footer textbox + leading-comment skip +
|
||||||
Smoke test `scripts/check_leadership_deck.sh` (on-demand, NOT a CI
|
auto-fit + vertical balance + bullet-marker fix). **Polished in P3**
|
||||||
gate). Vision `[1]` grounding in slides 3/5/7 speaker notes
|
(D-244: slide 1 → black cover; D-245: slide 7 "What works now" block
|
||||||
(resolve to `docs/vision.md`). 12 requirements (REQ-372.1..12), 1
|
— L1/L2 stacks live at confidence 0.800, next steps: greenfield
|
||||||
capability (CAP-042), 3 decisions (D-241..D-243). Tags: `v1.29.1`
|
pilots → promote to prod → SPGE constitutional library → infra
|
||||||
(P0) → `v1.29.2` (P1 execution) → `v1.29.3` (P2 final = milestone
|
layer; D-246: 7 S&P-themed mermaid diagrams, one per slide, rendered
|
||||||
|
via local mmdc with vendored Chromium libs). Smoke test
|
||||||
|
`scripts/check_leadership_deck.sh` (on-demand, NOT a CI gate). Vision
|
||||||
|
`[1]` grounding in slides 3/5/7 speaker notes (resolve to
|
||||||
|
`docs/vision.md`). 12 requirements (REQ-372.1..12), 1 capability
|
||||||
|
(CAP-042), 6 decisions (D-241..D-246). Tags: `v1.29.1` (P0) →
|
||||||
|
`v1.29.2` (P1 first draft) → `v1.29.3` (P2 first-draft final) →
|
||||||
|
`v1.29.4` (P3 polish) → `v1.29.5` (P4 polished final = milestone
|
||||||
|
release).
|
||||||
|
|
||||||
|
- **v1.31 (active):** Leadership Deck Polish II — refinement-only NFR
|
||||||
|
milestone. Enriches the v1.30 deck's visible on-slide prose and
|
||||||
|
improves slide layout, then re-renders the PPTX. Preserves all
|
||||||
|
v1.30 invariants (D-247): S&P theme tokens, 7-slide count, speaker-
|
||||||
|
note word-count bands, `[1]` citations on slides 3/5/7, the 7
|
||||||
|
mermaid diagram PNGs, and the footer string. No new slides, no new
|
||||||
|
diagrams, no renderer changes; the citizen-developer deck is
|
||||||
|
untouched. 4 requirements (REQ-373.1..4), 1 decision (D-247). Tags
|
||||||
|
run on the v1.30.x line: `v1.30.0` (P0) → `v1.30.1` (P1 = milestone
|
||||||
release).
|
release).
|
||||||
|
|
||||||
> **Full v1.0–v1.24 phase detail, wave ordering, success criteria, and
|
> **Full v1.0–v1.24 phase detail, wave ordering, success criteria, and
|
||||||
|
|||||||
@@ -357,7 +357,7 @@
|
|||||||
| CAP-039 | Platform ops reposplit | v1.29 / `v1.28.6` | `nova-platform-ops` (out-of-band), `docs/operator-guide-platform-ops.md`, `docs/archive/nova-idp-cfn-v1.28.md` | REQ-369, REQ-OPS-GUIDE, D-232, D-235 | covered-reference | engineering (`acdl/acdl`, GitHub) ends at the artifact; operations (`nova-platform-ops`, Gitea-private, OPER-PRIV) begins at the live platform; tag-pin handoff; CFN archived; covered-reference REQs tracked via cutover gates |
|
| CAP-039 | Platform ops reposplit | v1.29 / `v1.28.6` | `nova-platform-ops` (out-of-band), `docs/operator-guide-platform-ops.md`, `docs/archive/nova-idp-cfn-v1.28.md` | REQ-369, REQ-OPS-GUIDE, D-232, D-235 | covered-reference | engineering (`acdl/acdl`, GitHub) ends at the artifact; operations (`nova-platform-ops`, Gitea-private, OPER-PRIV) begins at the live platform; tag-pin handoff; CFN archived; covered-reference REQs tracked via cutover gates |
|
||||||
| CAP-040 | KJ substrate lockstep | v1.29 / `v1.28.6` | `nova-platform-ops` (out-of-band), `platform/abac/kj-version.txt`, `.github/workflows/publish.yml` | REQ-371, REQ-363, REQ-363b, D-238, D-239 | covered-reference | one ECR image digest shared by Lambda `image_uri` + Fargate task `image`; `lifecycle.precondition` on both resources at `terraform plan`; KJ-STATIC (`CGO_ENABLED=0`, `file(1)` asserts `statically linked`); no second pipeline, no second SHA pin |
|
| CAP-040 | KJ substrate lockstep | v1.29 / `v1.28.6` | `nova-platform-ops` (out-of-band), `platform/abac/kj-version.txt`, `.github/workflows/publish.yml` | REQ-371, REQ-363, REQ-363b, D-238, D-239 | covered-reference | one ECR image digest shared by Lambda `image_uri` + Fargate task `image`; `lifecycle.precondition` on both resources at `terraform plan`; KJ-STATIC (`CGO_ENABLED=0`, `file(1)` asserts `statically linked`); no second pipeline, no second SHA pin |
|
||||||
| CAP-041 | JWKS edge-only | v1.29 / `v1.28.6` | `nova-platform-ops` (out-of-band), `docs/operator-guide-platform-ops.md` | REQ-364, REQ-365, REQ-366, INV-18, D-233 | covered-reference | JWKS is the only public read surface; CloudFront + OAC (`AuthType: AWS_IAM`, NOT `NONE`, `OriginAccessControlOriginType: lambda`, `SigningBehavior: always`); direct Function URL → 403, via-CloudFront → 200; WAF rate-limit 3000/5min + AWSManagedRulesCommonRuleSet; ACM DNS-validated in us-east-1; Route53 A-alias |
|
| CAP-041 | JWKS edge-only | v1.29 / `v1.28.6` | `nova-platform-ops` (out-of-band), `docs/operator-guide-platform-ops.md` | REQ-364, REQ-365, REQ-366, INV-18, D-233 | covered-reference | JWKS is the only public read surface; CloudFront + OAC (`AuthType: AWS_IAM`, NOT `NONE`, `OriginAccessControlOriginType: lambda`, `SigningBehavior: always`); direct Function URL → 403, via-CloudFront → 200; WAF rate-limit 3000/5min + AWSManagedRulesCommonRuleSet; ACM DNS-validated in us-east-1; Route53 A-alias |
|
||||||
| CAP-042 | Leadership presentation deck (single-shot) | v1.30 / `v1.29.3` | `docs/presentations/nova-leadership-deck-marp.md`, `docs/presentations/nova-leadership-deck.pptx`, `scripts/check_leadership_deck.sh` | REQ-372.1..REQ-372.12, D-241, D-242, D-243 | local | Single-shot 7-slide PPTX deck for Infrastructure & Operations leadership (CTO + VP Technology + Product Management); presented August 2026; November 2026 runway anchor; discrete hand-authored artifact (NOT a compression of the citizen-developer pitch per D-241); rendered via existing `scripts/render_pptx.py` (narrowly extended per D-242); smoke test on-demand (NOT a CI gate); vision `[1]` grounding in slides 3/5/7 |
|
| CAP-042 | Leadership presentation deck (single-shot, polished) | v1.30 / `v1.29.5` | `docs/presentations/nova-leadership-deck-marp.md`, `docs/presentations/nova-leadership-deck.pptx`, `scripts/check_leadership_deck.sh`, `scripts/render_leadership_diagrams.sh`, `docs/presentations/assets/mmd/leadership-slide-{1..7}.mmd`, `docs/presentations/assets/png/leadership-slide-{1..7}.png` | REQ-372.1..REQ-372.12, D-241..D-246 | local | Single-shot 7-slide PPTX deck for Infrastructure & Operations leadership (CTO + VP Technology + Product Management); presented August 2026; November 2026 runway anchor; discrete hand-authored artifact (NOT a compression of the citizen-developer pitch per D-241); rendered via existing `scripts/render_pptx.py` (narrowly extended per D-242); polished in P3 (D-244 cover slide, D-245 slide 7 "What works now" block, D-246 7 S&P-themed mermaid diagrams); smoke test on-demand (NOT a CI gate); vision `[1]` grounding in slides 3/5/7 |
|
||||||
|
|
||||||
## Archive pointers
|
## Archive pointers
|
||||||
|
|
||||||
|
|||||||
@@ -206,8 +206,118 @@ at the v1.30 ship wave (CAP-042 row + intake assumption correction).
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Polish-phase decisions (D-244, D-245, D-246 — full autonomy)
|
||||||
|
|
||||||
|
The first draft (v1.29.3) passed all 12 REQs but the rendered PPTX
|
||||||
|
has 7 polish issues (vertical imbalance, text clipping, double bullet
|
||||||
|
markers, no visual variety, near-invisible footer, slide-6 red wall,
|
||||||
|
blockquote grey). The user requested: (1) polish all 7 issues, (2)
|
||||||
|
add a "What works now" emphasis to slide 7, (3) generate mermaid
|
||||||
|
diagrams for every slide. These decisions record the deviations from
|
||||||
|
prior binding decisions.
|
||||||
|
|
||||||
|
### D-244 — Slide 1 becomes a black-background cover (overrides grill G-1)
|
||||||
|
|
||||||
|
**Polish issue #4.** Grill G-1 locked "all 7 slides as white content
|
||||||
|
slides." The user approved making slide 1 a black-background cover
|
||||||
|
(strong opener for a live leadership presentation) while keeping
|
||||||
|
slides 2-7 as white content slides. The on-slide body text from the
|
||||||
|
Slide Content Map is preserved verbatim — only the visual treatment
|
||||||
|
(background + text color) changes. REQ-372.7's "deviation requires
|
||||||
|
CLARIFY" clause applies to *content* deviations; this is a
|
||||||
|
presentation polish, not a content change. The source change: slide
|
||||||
|
1's `## The friction...` → `# The friction...` (H1) + `<!-- _class:
|
||||||
|
title -->` directive, which triggers `render_title_slide` (black bg,
|
||||||
|
red top bar, white text).
|
||||||
|
**Confidence:** 1.0 (user-confirmed).
|
||||||
|
|
||||||
|
### D-245 — Slide 7 "What works now" content addition (deviation from Slide Content Map)
|
||||||
|
|
||||||
|
**User request.** A new "What works now" block is added to slide 7's
|
||||||
|
on-slide body, before the existing "What we ask" block. This is a
|
||||||
|
*content* deviation — the Slide Content Map specifies slide 7 as:
|
||||||
|
What we ask / Why now / What comes back + closer. The new block
|
||||||
|
emphasizes what's proven today (L1/L2 stack deployment works, live
|
||||||
|
apply to the sandbox/dev AWS account, confidence 0.800) and the
|
||||||
|
next-steps arc (ingest greenfield pilot projects → promote from
|
||||||
|
sandbox to production → integrate with the SPGE constitutional
|
||||||
|
library → serve as the infrastructure layer).
|
||||||
|
|
||||||
|
**Factual grounding (verified in RESEARCH):**
|
||||||
|
- 13 L1 primitives + 2 L2 modules in `modules/registry.json` (all at
|
||||||
|
`1.0.0`): alb, cloudfront, dynamodb, ecr, ecs-cluster, ecs-service,
|
||||||
|
iam-role, kms-key, rds, s3, uptime, vpc, waf + microservice, static-
|
||||||
|
assets.
|
||||||
|
- CAP-031: live `terraform apply` against AWS account `581513795199`
|
||||||
|
(the dev environment, `mode: full`, dev-only per D-209), producing
|
||||||
|
real ARNs (ALB, ECS, DynamoDB, S3, KMS) at confidence 0.800. This is
|
||||||
|
a **live AWS apply**, NOT "tested locally" and NOT a "sandbox"
|
||||||
|
account (the codebase has no sandbox account; the pilot-readiness
|
||||||
|
policy D-208 blocks placeholder accounts).
|
||||||
|
|
||||||
|
**"sandbox" colloquial term note:** The user explicitly chose to keep
|
||||||
|
"sandbox" as a colloquial term for the dev AWS account after I flagged
|
||||||
|
that the codebase fact is "dev account `581513795199`, live apply."
|
||||||
|
The slide uses "sandbox" (colloquial); the speaker notes carry the
|
||||||
|
precise facts (dev account, live apply, confidence 0.800).
|
||||||
|
|
||||||
|
**"SPGE constitutional library" unverified-in-repo note:** "SPGE"
|
||||||
|
and "constitutional library" appear nowhere in the codebase (0
|
||||||
|
matches across all `.md`/`.py`/`.json`/`.yml`). The user confirmed it
|
||||||
|
is an external system the audience recognizes. The slide includes it
|
||||||
|
as a named next-step integration target, not as a current capability.
|
||||||
|
The speaker notes do not assert it exists in the codebase.
|
||||||
|
|
||||||
|
The Slide Content Map in PROJECT.md is updated to reflect the new
|
||||||
|
slide 7 structure.
|
||||||
|
**Confidence:** 0.90.
|
||||||
|
|
||||||
|
### D-246 — Mermaid diagrams on all 7 slides
|
||||||
|
|
||||||
|
**User request.** Each of the 7 slides gets a leader-friendly,
|
||||||
|
non-technical mermaid diagram covering its core concept. Different
|
||||||
|
mermaid shapes per slide for visual variety.
|
||||||
|
|
||||||
|
**Render path (verified):** The local `mmdc` (mermaid-cli) is blocked
|
||||||
|
by missing Chromium shared libraries (10+ system libs absent, no
|
||||||
|
root). Resolution: 24 Debian bookworm `.deb` packages fetched from the
|
||||||
|
Debian mirror, `.so` files extracted to `/home/opencode/tmp/so2/`,
|
||||||
|
`LD_LIBRARY_PATH` set to include them. Chromium (puppeteer cache at
|
||||||
|
`/home/opencode/.cache/puppeteer/chrome/.../chrome`) launches with
|
||||||
|
the vendored libs; `mmdc` renders with the S&P theme (`sp-theme.json`)
|
||||||
|
+ 2x scale + transparent background. Verified: test diagram renders
|
||||||
|
to a valid PNG with all 4 S&P colors present. The `.mmd` source files
|
||||||
|
+ rendered PNGs are committed for reproducibility; a future
|
||||||
|
environment with system Chromium can re-render via the existing
|
||||||
|
`scripts/render_slides.sh` mermaid step.
|
||||||
|
|
||||||
|
**Theme:** Inline `%%{init: {...}}%%` directive in each `.mmd` with
|
||||||
|
S&P theme variables (`primaryColor:#1B1B1B`, `primaryBorderColor:
|
||||||
|
#D6002A`, `primaryTextColor:#fff`, `secondaryColor:#fff`,
|
||||||
|
`tertiaryColor:#F0F0F0`, `lineColor:#1B1B1B`) — only the 4 S&P tokens.
|
||||||
|
Transparent background. No component names, no technical jargon —
|
||||||
|
concepts only (leader-friendly).
|
||||||
|
|
||||||
|
**Diagram-type-per-slide mapping:**
|
||||||
|
1. flowchart LR — 3 frictions → Nova absorbs them
|
||||||
|
2. flowchart TB — Central IT golden image → Nova one layer up
|
||||||
|
3. flowchart LR with subgraphs — two principles → everything inherits
|
||||||
|
4. flowchart LR (3 columns) — Live · Attested · Stays human
|
||||||
|
5. flowchart LR (two halves) — In Nova's lane / Outside Nova's lane
|
||||||
|
6. timeline — the 18-month shape (α→β→γ→δ)
|
||||||
|
7. flowchart LR — what works now → next steps arc
|
||||||
|
|
||||||
|
The Slide Content Map in PROJECT.md is updated to include a "Diagram"
|
||||||
|
field per slide.
|
||||||
|
**Confidence:** 0.88.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Requirements impact
|
## Requirements impact
|
||||||
|
|
||||||
No requirements are added, removed, or re-scoped by these decisions.
|
No requirements are added, removed, or re-scoped by D-241–D-243.
|
||||||
D-241–D-243 are load-bearing context for executing REQ-372.1–.12 as
|
D-244–D-246 are polish-phase decisions that record deviations from
|
||||||
written. The spec is locked (v1.0, 2026-08-20); no spec text changes.
|
prior binding decisions (G-1) and the Slide Content Map (slide 7).
|
||||||
|
The spec is locked (v1.0, 2026-08-20); no spec text changes. The
|
||||||
|
Slide Content Map in PROJECT.md is updated to reflect D-245 (slide 7
|
||||||
|
structure) and D-246 (diagram field per slide).
|
||||||
@@ -8,8 +8,8 @@ state for offline agent loading.
|
|||||||
|
|
||||||
## Why archive
|
## Why archive
|
||||||
|
|
||||||
The active milestone is v1.27 (PO State Catalog & Ciagent Compression).
|
The active milestone is v1.30 (Single-shot Leadership Deck, complete).
|
||||||
The `.ciagent/` root was compressed twice:
|
The `.ciagent/` root was compressed three times:
|
||||||
|
|
||||||
1. **v1.26 P2 compression** (~11,164 lines → ~5,232): the
|
1. **v1.26 P2 compression** (~11,164 lines → ~5,232): the
|
||||||
completed-milestone narratives (v1.0–v1.24) were relocated. Per the
|
completed-milestone narratives (v1.0–v1.24) were relocated. Per the
|
||||||
@@ -22,6 +22,14 @@ The `.ciagent/` root was compressed twice:
|
|||||||
+ COST (predates v1.26 pilot) were relocated. The 4 pre-execution
|
+ COST (predates v1.26 pilot) were relocated. The 4 pre-execution
|
||||||
files (CLARIFY/GRILL/IDEATE/RESEARCH) were rewritten by v1.27 P0
|
files (CLARIFY/GRILL/IDEATE/RESEARCH) were rewritten by v1.27 P0
|
||||||
and stay active through v1.27.
|
and stay active through v1.27.
|
||||||
|
3. **v1.30 post-milestone compression** (17 → 8 files): the v1.30
|
||||||
|
phase-specific pre-execution files (CLARIFY/RESEARCH/GRILL/PLAN/
|
||||||
|
PERSONAS) were snapshotted to the archive and removed from the
|
||||||
|
active root — they are regenerated fresh each milestone. The stale
|
||||||
|
IDEATE (v1.27), IAM_POLICY (v1.28), and REGRESSION_REPORT (v1.26)
|
||||||
|
were also archived. The persistent files (PROJECT, REQUIREMENTS,
|
||||||
|
ROADMAP, STATE, ARCHITECTURE, NORTH_STAR, config, CHECKPOINT)
|
||||||
|
remain in the active root.
|
||||||
|
|
||||||
## Contents
|
## Contents
|
||||||
|
|
||||||
|
|||||||
@@ -2,21 +2,28 @@
|
|||||||
"projects": [
|
"projects": [
|
||||||
{
|
{
|
||||||
"slug": "acdl",
|
"slug": "acdl",
|
||||||
"name": "Nova — The New Dawn of DevSecOps",
|
"name": "Nova \u2014 The New Dawn of DevSecOps",
|
||||||
"default": true
|
"default": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "nova-blockchain-exchange",
|
"slug": "nova-blockchain-exchange",
|
||||||
"name": "Nova Pilot Consumer — Blockchain Stock Exchange",
|
"name": "Nova Pilot Consumer \u2014 Blockchain Stock Exchange",
|
||||||
"default": false
|
"default": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"active_project": "acdl",
|
"active_project": "acdl",
|
||||||
"active_projects": ["acdl", "nova-blockchain-exchange"],
|
"active_projects": [
|
||||||
"active_milestone": "v1.30",
|
"acdl",
|
||||||
|
"nova-blockchain-exchange"
|
||||||
|
],
|
||||||
|
"active_milestone": "v1.31",
|
||||||
"autonomy": {
|
"autonomy": {
|
||||||
"level": "full",
|
"level": "full",
|
||||||
"escalation_hooks": ["deploy", "delete_data", "merge_to_main"],
|
"escalation_hooks": [
|
||||||
|
"deploy",
|
||||||
|
"delete_data",
|
||||||
|
"merge_to_main"
|
||||||
|
],
|
||||||
"clarify_budget": 10,
|
"clarify_budget": 10,
|
||||||
"decision_confidence_threshold": 0.6,
|
"decision_confidence_threshold": 0.6,
|
||||||
"max_revision_iterations": 3,
|
"max_revision_iterations": 3,
|
||||||
@@ -42,35 +49,72 @@
|
|||||||
"escalate_high_severity": true,
|
"escalate_high_severity": true,
|
||||||
"bash_allowlist": {
|
"bash_allowlist": {
|
||||||
"allowed_commands": [
|
"allowed_commands": [
|
||||||
"git", "ls", "cat", "head", "tail", "wc",
|
"git",
|
||||||
"echo", "mkdir", "cp", "mv", "rm", "touch",
|
"ls",
|
||||||
"pwd", "which", "env", "printenv",
|
"cat",
|
||||||
"python3", "pytest", "pip",
|
"head",
|
||||||
"terraform", "checkov",
|
"tail",
|
||||||
"curl", "wget",
|
"wc",
|
||||||
"docker", "docker-compose"
|
"echo",
|
||||||
|
"mkdir",
|
||||||
|
"cp",
|
||||||
|
"mv",
|
||||||
|
"rm",
|
||||||
|
"touch",
|
||||||
|
"pwd",
|
||||||
|
"which",
|
||||||
|
"env",
|
||||||
|
"printenv",
|
||||||
|
"python3",
|
||||||
|
"pytest",
|
||||||
|
"pip",
|
||||||
|
"terraform",
|
||||||
|
"checkov",
|
||||||
|
"curl",
|
||||||
|
"wget",
|
||||||
|
"docker",
|
||||||
|
"docker-compose"
|
||||||
],
|
],
|
||||||
"max_output_bytes": 1048576,
|
"max_output_bytes": 1048576,
|
||||||
"timeout_ms": 30000,
|
"timeout_ms": 30000,
|
||||||
"blocked_env_vars": [
|
"blocked_env_vars": [
|
||||||
"HOME", "PATH", "USER", "SHELL",
|
"HOME",
|
||||||
"AWS_*", "*_TOKEN", "*_KEY", "*_SECRET",
|
"PATH",
|
||||||
"*_PASSWORD", "*_CREDENTIAL",
|
"USER",
|
||||||
"GITHUB_TOKEN", "GITHUB_API_KEY",
|
"SHELL",
|
||||||
"OPENAI_API_KEY", "ANTHROPIC_API_KEY",
|
"AWS_*",
|
||||||
|
"*_TOKEN",
|
||||||
|
"*_KEY",
|
||||||
|
"*_SECRET",
|
||||||
|
"*_PASSWORD",
|
||||||
|
"*_CREDENTIAL",
|
||||||
|
"GITHUB_TOKEN",
|
||||||
|
"GITHUB_API_KEY",
|
||||||
|
"OPENAI_API_KEY",
|
||||||
|
"ANTHROPIC_API_KEY",
|
||||||
"OLLAMA_CLOUD_API_KEY"
|
"OLLAMA_CLOUD_API_KEY"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"git": {
|
"git": {
|
||||||
"branching_strategy": "flat",
|
"branching_strategy": "flat",
|
||||||
"_branching_strategy_note": "Nova uses flat workflow (committed directly to main per established convention since v1.0; renamed ACDL→Nova in v1.15). The 'phase' strategy is advisory; CIAgent uses milestone/phase branches for v1.14 but the project convention is flat.",
|
"_branching_strategy_note": "Nova uses flat workflow (committed directly to main per established convention since v1.0; renamed ACDL\u2192Nova in v1.15). The 'phase' strategy is advisory; CIAgent uses milestone/phase branches for v1.14 but the project convention is flat.",
|
||||||
"auto_commit": true,
|
"auto_commit": true,
|
||||||
"auto_push": true
|
"auto_push": true
|
||||||
},
|
},
|
||||||
"secrets": {
|
"secrets": {
|
||||||
"sources": [".env", ".env.secrets", ".env.*"],
|
"sources": [
|
||||||
"disallow": ["shell_env", "netrc", "keychain", "rc_files", "global_config"],
|
".env",
|
||||||
|
".env.secrets",
|
||||||
|
".env.*"
|
||||||
|
],
|
||||||
|
"disallow": [
|
||||||
|
"shell_env",
|
||||||
|
"netrc",
|
||||||
|
"keychain",
|
||||||
|
"rc_files",
|
||||||
|
"global_config"
|
||||||
|
],
|
||||||
"scopes": {
|
"scopes": {
|
||||||
"forge": "NOVA_FORGE_TOKEN",
|
"forge": "NOVA_FORGE_TOKEN",
|
||||||
"gitea": "NOVA_FORGE_TOKEN",
|
"gitea": "NOVA_FORGE_TOKEN",
|
||||||
@@ -112,10 +156,18 @@
|
|||||||
"backend": {
|
"backend": {
|
||||||
"provider": "auto",
|
"provider": "auto",
|
||||||
"agent_backends": {
|
"agent_backends": {
|
||||||
"opencode": { "enabled": true },
|
"opencode": {
|
||||||
"codex": { "enabled": true },
|
"enabled": true
|
||||||
"claude-code": { "enabled": true },
|
},
|
||||||
"hermes": { "enabled": true }
|
"codex": {
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"claude-code": {
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"hermes": {
|
||||||
|
"enabled": true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"llm_backends": {
|
"llm_backends": {
|
||||||
"openai": {
|
"openai": {
|
||||||
@@ -148,7 +200,13 @@
|
|||||||
},
|
},
|
||||||
"ideation": {
|
"ideation": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"categories": ["security", "quality", "architecture", "coverage", "improvement"],
|
"categories": [
|
||||||
|
"security",
|
||||||
|
"quality",
|
||||||
|
"architecture",
|
||||||
|
"coverage",
|
||||||
|
"improvement"
|
||||||
|
],
|
||||||
"confidence_threshold": 0.6,
|
"confidence_threshold": 0.6,
|
||||||
"max_ideas": 20,
|
"max_ideas": 20,
|
||||||
"external_signals": {
|
"external_signals": {
|
||||||
@@ -162,7 +220,11 @@
|
|||||||
},
|
},
|
||||||
"chaos": {
|
"chaos": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"scenarios": ["backend_unavailable", "requirement_change", "test_coverage_drop"]
|
"scenarios": [
|
||||||
|
"backend_unavailable",
|
||||||
|
"requirement_change",
|
||||||
|
"test_coverage_drop"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sessions": {
|
"sessions": {
|
||||||
@@ -178,30 +240,77 @@
|
|||||||
"name": "lead-developer",
|
"name": "lead-developer",
|
||||||
"domain": "coordination",
|
"domain": "coordination",
|
||||||
"frameworks": [],
|
"frameworks": [],
|
||||||
"constraints": ["pragmatic", "battle-tested defaults"],
|
"constraints": [
|
||||||
|
"pragmatic",
|
||||||
|
"battle-tested defaults"
|
||||||
|
],
|
||||||
"territory": []
|
"territory": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "data-engineer",
|
"name": "data-engineer",
|
||||||
"domain": "data",
|
"domain": "data",
|
||||||
"frameworks": ["drizzle", "postgresql"],
|
"frameworks": [
|
||||||
"constraints": ["schema-first", "type-safe ORM", "migration-driven"],
|
"drizzle",
|
||||||
"territory": ["**/migrations/**", "**/schema/**", "**/models/**", "**/db/**", "prisma/schema.prisma", "drizzle/**", "**/*.sql"]
|
"postgresql"
|
||||||
|
],
|
||||||
|
"constraints": [
|
||||||
|
"schema-first",
|
||||||
|
"type-safe ORM",
|
||||||
|
"migration-driven"
|
||||||
|
],
|
||||||
|
"territory": [
|
||||||
|
"**/migrations/**",
|
||||||
|
"**/schema/**",
|
||||||
|
"**/models/**",
|
||||||
|
"**/db/**",
|
||||||
|
"prisma/schema.prisma",
|
||||||
|
"drizzle/**",
|
||||||
|
"**/*.sql"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "backend-engineer",
|
"name": "backend-engineer",
|
||||||
"domain": "backend",
|
"domain": "backend",
|
||||||
"frameworks": ["fastify", "hono"],
|
"frameworks": [
|
||||||
"constraints": ["api-first", "strict-typing", "dependency-injection"],
|
"fastify",
|
||||||
"territory": ["**/api/**", "**/routes/**", "**/services/**", "**/middleware/**", "**/controllers/**", "**/auth/**"]
|
"hono"
|
||||||
|
],
|
||||||
|
"constraints": [
|
||||||
|
"api-first",
|
||||||
|
"strict-typing",
|
||||||
|
"dependency-injection"
|
||||||
|
],
|
||||||
|
"territory": [
|
||||||
|
"**/api/**",
|
||||||
|
"**/routes/**",
|
||||||
|
"**/services/**",
|
||||||
|
"**/middleware/**",
|
||||||
|
"**/controllers/**",
|
||||||
|
"**/auth/**"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "frontend-engineer",
|
"name": "frontend-engineer",
|
||||||
"domain": "frontend",
|
"domain": "frontend",
|
||||||
"active": false,
|
"active": false,
|
||||||
"frameworks": ["react", "next.js"],
|
"frameworks": [
|
||||||
"constraints": ["component-first", "server-components", "minimal-client-js"],
|
"react",
|
||||||
"territory": ["**/components/**", "**/pages/**", "**/hooks/**", "**/styles/**", "**/*.tsx", "**/*.css", "**/*.vue"],
|
"next.js"
|
||||||
|
],
|
||||||
|
"constraints": [
|
||||||
|
"component-first",
|
||||||
|
"server-components",
|
||||||
|
"minimal-client-js"
|
||||||
|
],
|
||||||
|
"territory": [
|
||||||
|
"**/components/**",
|
||||||
|
"**/pages/**",
|
||||||
|
"**/hooks/**",
|
||||||
|
"**/styles/**",
|
||||||
|
"**/*.tsx",
|
||||||
|
"**/*.css",
|
||||||
|
"**/*.vue"
|
||||||
|
],
|
||||||
"reason": "ACDL has no frontend (no package.json); decks are markdown (lead-developer territory). Deactivated per PERSONAS.md:80."
|
"reason": "ACDL has no frontend (no package.json); decks are markdown (lead-developer territory). Deactivated per PERSONAS.md:80."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -220,4 +329,4 @@
|
|||||||
"engine": "kyverno-json",
|
"engine": "kyverno-json",
|
||||||
"policy_root": "adapters/kyverno-json/policies"
|
"policy_root": "adapters/kyverno-json/policies"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
%%{init: {'theme':'base', 'themeVariables': {'primaryColor':'#1B1B1B','primaryBorderColor':'#D6002A','primaryTextColor':'#fff','secondaryColor':'#fff','secondaryBorderColor':'#D6002A','secondaryTextColor':'#1B1B1B','tertiaryColor':'#F0F0F0','lineColor':'#1B1B1B','fontFamily':'"Helvetica Neue","Arial",sans-serif'}}}%%
|
||||||
|
flowchart LR
|
||||||
|
subgraph TODAY["Today — the gap is widening"]
|
||||||
|
direction TB
|
||||||
|
V["Delivery velocity<br/>↑ rising fast"]
|
||||||
|
C["Coordination surface<br/>↑↑ rising faster"]
|
||||||
|
V -.-|"gap"| C
|
||||||
|
end
|
||||||
|
subgraph COST["The cost of the gap"]
|
||||||
|
direction TB
|
||||||
|
R1["Remediation<br/>cycles"]
|
||||||
|
R2["Gate fatigue<br/>& morale loss"]
|
||||||
|
R3["Compliance<br/>found late"]
|
||||||
|
end
|
||||||
|
TODAY -->|"absorbs"| NOVA
|
||||||
|
subgraph NOVA["Nova closes the gap"]
|
||||||
|
direction TB
|
||||||
|
N1["Owned primitives<br/>= no per-team infra authoring"]
|
||||||
|
N2["Attested up front<br/>= no late compliance"]
|
||||||
|
N3["Policy-bounded<br/>= no manual gating"]
|
||||||
|
end
|
||||||
|
COST -->|"absorbs"| NOVA
|
||||||
|
style TODAY fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style COST fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style NOVA fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style V fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style C fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style R1 fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style R2 fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style R3 fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style N1 fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style N2 fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style N3 fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
%%{init: {'theme':'base', 'themeVariables': {'primaryColor':'#1B1B1B','primaryBorderColor':'#D6002A','primaryTextColor':'#fff','secondaryColor':'#fff','secondaryBorderColor':'#D6002A','secondaryTextColor':'#1B1B1B','tertiaryColor':'#F0F0F0','lineColor':'#1B1B1B','fontFamily':'"Helvetica Neue","Arial",sans-serif'}}}%%
|
||||||
|
flowchart LR
|
||||||
|
SDLC["SDLC<br/>code authored,<br/>built, tested"]
|
||||||
|
PDLC["PDLC<br/>product backlog,<br/>release planning"]
|
||||||
|
CONTRACT["The<br/>contract"]
|
||||||
|
INGEST["Contract<br/>ingestor"]
|
||||||
|
RESOLVE["Resolve<br/>→ L1/L2 stack"]
|
||||||
|
POLICY["Policy +<br/>confidence<br/>enforcement"]
|
||||||
|
APPLY["Reconcile<br/>→ live cloud"]
|
||||||
|
PROD["Running,<br/>observable,<br/>attested infra"]
|
||||||
|
SDLC --> CONTRACT
|
||||||
|
PDLC --> CONTRACT
|
||||||
|
CONTRACT -->|"validated<br/>boundary"| INGEST
|
||||||
|
INGEST --> RESOLVE
|
||||||
|
RESOLVE --> POLICY
|
||||||
|
POLICY --> APPLY
|
||||||
|
APPLY -->|"production-grade<br/>by construction"| PROD
|
||||||
|
style SDLC fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style PDLC fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style CONTRACT fill:#fff,color:#D6002A,stroke:#D6002A
|
||||||
|
style INGEST fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style RESOLVE fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style POLICY fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style APPLY fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style PROD fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
%%{init: {'theme':'base', 'themeVariables': {'primaryColor':'#1B1B1B','primaryBorderColor':'#D6002A','primaryTextColor':'#fff','secondaryColor':'#fff','secondaryBorderColor':'#D6002A','secondaryTextColor':'#1B1B1B','tertiaryColor':'#F0F0F0','lineColor':'#1B1B1B','fontFamily':'"Helvetica Neue","Arial",sans-serif'}}}%%
|
||||||
|
flowchart TB
|
||||||
|
ROOT["Two tenets<br/>discipline everything"]
|
||||||
|
SB["Sovereign boundary<br/>govern the delivery lifecycle<br/>do not reach upstream"]
|
||||||
|
LA["Lower autonomous<br/>higher attested<br/>compute: platform<br/>choice: human"]
|
||||||
|
ROOT --> SB
|
||||||
|
ROOT --> LA
|
||||||
|
SB -->|"shapes"| FM["4-layer model<br/>artifact → contract →<br/>infra → runtime"]
|
||||||
|
SB -->|"shapes"| CS["Contract schema<br/>the only integration<br/>surface to SDLC/PDLC"]
|
||||||
|
SB -->|"shapes"| PE["Policy envelope<br/>confidence, NFRs,<br/>boundaries enforced"]
|
||||||
|
LA -->|"shapes"| HITL["HITL gates<br/>named approver ≠ PR author<br/>at qa, prod, dr"]
|
||||||
|
LA -->|"shapes"| CONF["Confidence signal<br/>0.50 → 0.75 → 0.90 → 0.95<br/>escalation below threshold"]
|
||||||
|
LA -->|"shapes"| AUDIT["Audit lineage<br/>every action → one owner<br/>→ one evidence entry"]
|
||||||
|
style ROOT fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style SB fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style LA fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style FM fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style CS fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style PE fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style HITL fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style CONF fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style AUDIT fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
%%{init: {'theme':'base', 'themeVariables': {'primaryColor':'#1B1B1B','primaryBorderColor':'#D6002A','primaryTextColor':'#fff','secondaryColor':'#fff','secondaryBorderColor':'#D6002A','secondaryTextColor':'#1B1B1B','tertiaryColor':'#F0F0F0','lineColor':'#1B1B1B','fontFamily':'"Helvetica Neue","Arial",sans-serif'}}}%%
|
||||||
|
flowchart LR
|
||||||
|
DEV["dev<br/>autonomous<br/>conf ≥ 0.50<br/>zero-touch"]
|
||||||
|
QA["qa<br/>HITL gate<br/>conf ≥ 0.75<br/>named approver<br/>≠ PR author"]
|
||||||
|
PROD["prod<br/>HITL gate<br/>conf ≥ 0.90<br/>named approver<br/>≠ PR author"]
|
||||||
|
DRENV["dr<br/>HITL gate<br/>conf ≥ 0.95<br/>named approver<br/>≠ PR author"]
|
||||||
|
DEV -->|"promotion"| QA
|
||||||
|
QA -->|"promotion"| PROD
|
||||||
|
PROD -->|"promotion"| DRENV
|
||||||
|
ESC["Escalation:<br/>below threshold<br/>→ human judgment"] -.->|"triggers"| QA
|
||||||
|
ESC -.->|"triggers"| PROD
|
||||||
|
ESC -.->|"triggers"| DRENV
|
||||||
|
style DEV fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style QA fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style PROD fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style DRENV fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style ESC fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
%%{init: {'theme':'base', 'themeVariables': {'primaryColor':'#1B1B1B','primaryBorderColor':'#D6002A','primaryTextColor':'#fff','secondaryColor':'#fff','secondaryBorderColor':'#D6002A','secondaryTextColor':'#1B1B1B','tertiaryColor':'#F0F0F0','lineColor':'#1B1B1B','fontFamily':'"Helvetica Neue","Arial",sans-serif'}}}%%
|
||||||
|
flowchart LR
|
||||||
|
subgraph ABOVE["Above the contract — upstream, not Nova"]
|
||||||
|
APP["Application<br/>business logic"]
|
||||||
|
IDE["IDE · sprint ·<br/>author workflows"]
|
||||||
|
APPSEC["AppSec · dependency<br/>review · runtime security"]
|
||||||
|
VM["VM · bare-metal ·<br/>OS lifecycles<br/>consumed, not maintained"]
|
||||||
|
end
|
||||||
|
CONTRACT["the contract<br/>━━━━━━━━━<br/>declared intent<br/>validated, published"]
|
||||||
|
subgraph BELOW["Below the contract — Nova's lane"]
|
||||||
|
L1["L1 primitives<br/>S3 · RDS · Lambda<br/>ECS · KMS · DynamoDB"]
|
||||||
|
L2["L2 compositions<br/>microservice ·<br/>static-assets"]
|
||||||
|
GUARD["Guardrails<br/>confidence · policy<br/>attestation · audit"]
|
||||||
|
end
|
||||||
|
RT["Production<br/>runtime"]
|
||||||
|
ABOVE -.->|"declares via"| CONTRACT
|
||||||
|
CONTRACT -->|"validated boundary"| BELOW
|
||||||
|
BELOW -->|"reconciles to"| RT
|
||||||
|
style ABOVE fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style BELOW fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style APP fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style IDE fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style APPSEC fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style VM fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style CONTRACT fill:#fff,color:#D6002A,stroke:#D6002A
|
||||||
|
style L1 fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style L2 fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style GUARD fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style RT fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
%%{init: {'theme':'base', 'themeVariables': {'primaryColor':'#1B1B1B','primaryBorderColor':'#D6002A','primaryTextColor':'#fff','secondaryColor':'#fff','secondaryBorderColor':'#D6002A','secondaryTextColor':'#1B1B1B','tertiaryColor':'#F0F0F0','lineColor':'#1B1B1B','fontFamily':'"Helvetica Neue","Arial",sans-serif'}}}%%
|
||||||
|
flowchart LR
|
||||||
|
subgraph NOW["Now"]
|
||||||
|
A["α — operating model<br/>named platform-ops body<br/>SLAs on every L2"]
|
||||||
|
end
|
||||||
|
subgraph Q1["Q1 2027"]
|
||||||
|
B["β — infra observability<br/>auto-published on apply<br/>no per-team dashboards"]
|
||||||
|
end
|
||||||
|
subgraph Q2["Q2 2027"]
|
||||||
|
G["γ — runbook generation<br/>from observed patterns<br/>SREs start, not blank"]
|
||||||
|
end
|
||||||
|
subgraph Q4["Q3-Q4 2027"]
|
||||||
|
D["δ — audit ledger<br/>S3 Object Lock + JWS<br/>externally verifiable"]
|
||||||
|
end
|
||||||
|
A -->|"unlocks"| B
|
||||||
|
B -->|"builds on"| G
|
||||||
|
G -->|"matures to"| D
|
||||||
|
NOW -.->|"governance<br/>is the unlock"| B
|
||||||
|
subgraph UNCHANGED["Stays constant across the arc"]
|
||||||
|
C["The contract surface<br/>remains the only<br/>SDLC/PDLC integration"]
|
||||||
|
end
|
||||||
|
D -.->|"exits to"| UNCHANGED
|
||||||
|
style NOW fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style Q1 fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style Q2 fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style Q4 fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style UNCHANGED fill:#fff,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style A fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style B fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style G fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style D fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style C fill:#fff,color:#1B1B1B,stroke:#D6002A
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
%%{init: {'theme':'base', 'themeVariables': {'primaryColor':'#1B1B1B','primaryBorderColor':'#D6002A','primaryTextColor':'#fff','secondaryColor':'#fff','secondaryBorderColor':'#D6002A','secondaryTextColor':'#1B1B1B','tertiaryColor':'#F0F0F0','lineColor':'#1B1B1B','fontFamily':'"Helvetica Neue","Arial",sans-serif'}}}%%
|
||||||
|
flowchart TB
|
||||||
|
subgraph PROVEN["Proven today — the foundation"]
|
||||||
|
direction LR
|
||||||
|
L1L2["13 L1 + 2 L2<br/>live in registry"]
|
||||||
|
PILOT["Pilot live-apply<br/>confidence 0.800<br/>dev AWS account"]
|
||||||
|
L1L2 --- PILOT
|
||||||
|
end
|
||||||
|
subgraph ARC["The runway arc — next steps"]
|
||||||
|
direction LR
|
||||||
|
N1["Ingest greenfield<br/>pilot projects"]
|
||||||
|
N2["Promote<br/>dev → prod<br/>activate qa, prod, dr"]
|
||||||
|
N3["Integrate SPGE<br/>constitutional library<br/>at the contract surface"]
|
||||||
|
N4["Serve as the<br/>infrastructure layer<br/>beneath every app"]
|
||||||
|
N1 --> N2 --> N3 --> N4
|
||||||
|
end
|
||||||
|
subgraph ASK["The ask"]
|
||||||
|
ENDORSE["Architecture<br/>endorsement"]
|
||||||
|
RUNWAY["Runway to next<br/>milestone by Nov 2026"]
|
||||||
|
ENDORSE --- RUNWAY
|
||||||
|
end
|
||||||
|
subgraph RISK["If we don't — the structural risk"]
|
||||||
|
GAP["Delivery acceleration<br/>vs operational absorption<br/>gap widens through 2027"]
|
||||||
|
end
|
||||||
|
PROVEN -->|"foundation enables"| ARC
|
||||||
|
ARC -->|"lands at"| ASK
|
||||||
|
ASK -.->|"without it"| RISK
|
||||||
|
style PROVEN fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style ARC fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style ASK fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style RISK fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style L1L2 fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style PILOT fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style N1 fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style N2 fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style N3 fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style N4 fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
style ENDORSE fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style RUNWAY fill:#1B1B1B,color:#fff,stroke:#D6002A
|
||||||
|
style GAP fill:#F0F0F0,color:#1B1B1B,stroke:#D6002A
|
||||||
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 91 KiB |
@@ -14,6 +14,11 @@
|
|||||||
Vision grounding: [1] citations in slides 3, 5, 7 speaker notes
|
Vision grounding: [1] citations in slides 3, 5, 7 speaker notes
|
||||||
resolve to docs/vision.md (the spec's acdl-vision.md reference).
|
resolve to docs/vision.md (the spec's acdl-vision.md reference).
|
||||||
|
|
||||||
|
Diagrams: 7 S&P-themed mermaid diagrams (D-246), one per slide,
|
||||||
|
rendered via scripts/render_leadership_diagrams.sh (mmdc + vendored
|
||||||
|
Chromium libs). Sources: assets/mmd/leadership-slide-N.mmd.
|
||||||
|
PNGs: assets/png/leadership-slide-N.png.
|
||||||
|
|
||||||
Render: python3 scripts/render_pptx.py docs/presentations/nova-leadership-deck-marp.md \
|
Render: python3 scripts/render_pptx.py docs/presentations/nova-leadership-deck-marp.md \
|
||||||
--output docs/presentations/nova-leadership-deck.pptx
|
--output docs/presentations/nova-leadership-deck.pptx
|
||||||
Smoke test: bash scripts/check_leadership_deck.sh
|
Smoke test: bash scripts/check_leadership_deck.sh
|
||||||
@@ -42,7 +47,10 @@ style: |
|
|||||||
@media print { section { overflow: hidden; } }
|
@media print { section { overflow: hidden; } }
|
||||||
---
|
---
|
||||||
|
|
||||||
## The friction every delivery team lives today
|
<!-- _class: title -->
|
||||||
|
<!-- _paginate: false -->
|
||||||
|
|
||||||
|
# The friction every delivery team lives today
|
||||||
|
|
||||||
> *Velocity is up; the coordination surface around each change is up faster.*
|
> *Velocity is up; the coordination surface around each change is up faster.*
|
||||||
|
|
||||||
@@ -52,6 +60,8 @@ style: |
|
|||||||
|
|
||||||
> *Nova absorbs all three — owned building blocks, separation of concerns, attested compliance up front.*
|
> *Nova absorbs all three — owned building blocks, separation of concerns, attested compliance up front.*
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Three patterns drive the friction every delivery team lives today, and all three trace back to one binding constraint: software delivery scales with the coordination surface around it, not the engineering inside it [1]. That is the claim the vision document opens with, and it is the lens for everything Nova does.
|
Three patterns drive the friction every delivery team lives today, and all three trace back to one binding constraint: software delivery scales with the coordination surface around it, not the engineering inside it [1]. That is the claim the vision document opens with, and it is the lens for everything Nova does.
|
||||||
|
|
||||||
@@ -70,13 +80,11 @@ Nova absorbs all three. Owned building blocks, separation of concerns, attested
|
|||||||
|
|
||||||
> *You already recognize this pattern.*
|
> *You already recognize this pattern.*
|
||||||
|
|
||||||
Every Central IT team curates a golden image for Windows, for Linux, for macOS. They own it. They patch it. They ship it. Consumers consume it without thinking about what's inside.
|

|
||||||
|
|
||||||
Nova plays the same role one layer up — for everything that runs your cloud. S3 buckets with SSE-KMS posture. RDS instances with deletion protection and PITR. Lambda containers with static ABAC binaries. ALBs, ECS services, KMS keys, DynamoDB tables. Each one is owned by the platform team, patched by the platform team, attested by the platform team, and consumed by anyone who declares a contract.
|
Central IT curates the golden image; Nova curates the cloud infrastructure. Owned, patched, attested, consumed by contract.
|
||||||
|
|
||||||
The difference: every primitive is versioned, tested across its entire lifecycle, and bounded by policy before any consumer ever touches it.
|
> *Nova's lane is the infrastructure beneath the application. AppSec stays with the application team.*
|
||||||
|
|
||||||
> *Nova's lane is the infrastructure beneath the application. AppSec, dependency review, and runtime application security stay where they have always been — with the application team.*
|
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
The Central IT golden-image pattern is one every leadership team already recognizes. Central IT curates the Windows image, the Linux image, the macOS image. They own it, they patch it, they ship it, and consumers consume it without thinking about what is inside. That trade — per-application control for uniform operability — is a trade every enterprise has already made at the OS layer.
|
The Central IT golden-image pattern is one every leadership team already recognizes. Central IT curates the Windows image, the Linux image, the macOS image. They own it, they patch it, they ship it, and consumers consume it without thinking about what is inside. That trade — per-application control for uniform operability — is a trade every enterprise has already made at the OS layer.
|
||||||
@@ -92,13 +100,13 @@ And the lane stays narrow. Nova's lane is the infrastructure beneath the applica
|
|||||||
|
|
||||||
## Two principles that organize everything else
|
## Two principles that organize everything else
|
||||||
|
|
||||||
> *The architecture is principled, not improvised. Two tenets discipline every other decision.*
|
> *Two tenets discipline every other decision.*
|
||||||
|
|
||||||
**Sovereign boundary.** Nova governs the delivery lifecycle; it does not reach upstream into product or software development [1]. Integration with SDLC and PDLC partners happens exclusively through the validated, published contract surface. What lives outside the contract is not Nova's domain.
|

|
||||||
|
|
||||||
**Lower autonomous · higher attested.** Lower environments proceed through agentic automation. Promotion to higher environments requires deliberate human attestation — not as a rubber stamp, but as policy-mandated accountability [1]. The compute the platform makes; the choice the human keeps.
|
**Sovereign boundary** — Nova governs the delivery lifecycle; it does not reach upstream [1]. Integration with SDLC and PDLC happens exclusively through the contract surface.
|
||||||
|
|
||||||
> *Everything else in the architecture inherits from these two.*
|
**Lower autonomous · higher attested** — lower environments proceed through agentic automation; promotion requires deliberate human attestation [1]. The compute the platform makes; the choice the human keeps.
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
The architecture is principled, not improvised. Two tenets discipline every other decision the platform makes, and both come straight from the vision document [1].
|
The architecture is principled, not improvised. Two tenets discipline every other decision the platform makes, and both come straight from the vision document [1].
|
||||||
@@ -114,14 +122,13 @@ And the point for this room: these two tenets are not aspirational. They are loa
|
|||||||
|
|
||||||
## Live · Attested · Stays human
|
## Live · Attested · Stays human
|
||||||
|
|
||||||
**Live today**
|

|
||||||
41 capabilities across 12 domains. Contract ingestor, audit outbox, state buckets, and the live pilot run have been operating in our AWS estate since v1.7; pilot evidence at v1.26 returned confidence 0.800. DORA + adoption + policy-conformance metrics flow to PowerBI from the same audit stream as the lineage. Every finding carries one owner, one patch state, one audit entry — one pane, no second source of truth. A POC is production-grade by construction: there is no "POC that became prod" surprise.
|
|
||||||
|
|
||||||
**Attested on promotion**
|
**Live today** — 41 capabilities across 12 domains; pilot confidence 0.800. One pane, no second source of truth.
|
||||||
qa, prod, and dr require a named human approver distinct from the PR author. Rubber stamps cannot be silently issued.
|
|
||||||
|
|
||||||
**Stays human — by design**
|
**Attested on promotion** — qa, prod, dr require a named human approver distinct from the PR author.
|
||||||
Confidence below the autonomy threshold at qa, prod, or dr triggers human escalation [1]. Some categories of decision are preserved for human judgment, and the platform says so out loud.
|
|
||||||
|
**Stays human — by design** — confidence below the autonomy threshold triggers human escalation [1].
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Three columns, three claims, one disambiguation. The claims are real, observable, and disciplined — and the distinction matters for this room.
|
Three columns, three claims, one disambiguation. The claims are real, observable, and disciplined — and the distinction matters for this room.
|
||||||
@@ -137,20 +144,13 @@ Disciplined: attested on promotion, stays human by design. qa, prod, and dr requ
|
|||||||
|
|
||||||
## The boundary keeps us honest
|
## The boundary keeps us honest
|
||||||
|
|
||||||
> *Nova stays where it belongs.*
|

|
||||||
|
|
||||||
**In Nova's lane**
|
**In Nova's lane** — infrastructure primitives, operational guardrails, CVE response at the infra layer.
|
||||||
- → Infrastructure primitives: S3, RDS, Lambda, ECS, DynamoDB, KMS, CloudFront.
|
|
||||||
- → Operational guardrails: confidence, policy, attestation, audit lineage.
|
|
||||||
- → CVE response at the infrastructure layer.
|
|
||||||
|
|
||||||
**Outside Nova's lane**
|
**Outside Nova's lane** — application business logic, IDE & sprint workflows [1], AppSec, VM/bare-metal/OS lifecycles [1].
|
||||||
- → Application business logic.
|
|
||||||
- → IDE, sprint, author workflows [1].
|
|
||||||
- → Application-layer security: AppSec, dependency review, runtime threat modeling.
|
|
||||||
- → VM, bare-metal, OS lifecycles [1].
|
|
||||||
|
|
||||||
> *The line is the contract. Everything below the contract is Nova. Everything above it stays where it has always been.*
|
> *The line is the contract. Everything below it is Nova. Everything above it stays where it has always been.*
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
The boundary is not a defensive posture. It is an operating principle — and it is the principle that keeps the architecture honest [1].
|
The boundary is not a defensive posture. It is an operating principle — and it is the principle that keeps the architecture honest [1].
|
||||||
@@ -168,13 +168,12 @@ The line is the contract. Everything below the contract is Nova. Everything abov
|
|||||||
|
|
||||||
> *Where CDLC meets SDLC + PDLC — through the contract surface, not above it.*
|
> *Where CDLC meets SDLC + PDLC — through the contract surface, not above it.*
|
||||||
|
|
||||||
**α (now → Q4'26) — Operating model + federated governance.** A named platform-ops body owns the platform; SLAs on every L2 are ratifiable by platform + consumer. The operating model is published; integration surfaces for SDLC and PDLC harnesses are documented at the contract boundary.
|

|
||||||
|
|
||||||
**β (Q1'27) — Auto-published infra observability.** Every consumer stack ships with CloudWatch dashboards, uptime-kuma monitors, and alert routing on apply — infrastructure primitives publish observability as a property, no per-team authoring required.
|
**α (now → Q4'26)** Operating model + federated governance.
|
||||||
|
**β (Q1'27)** Auto-published infra observability.
|
||||||
**γ (Q2'27) — Runbook generation from telemetry.** Every L1 primitive ships with an auto-generated incident runbook derived from observed patterns. SREs get a starting runbook, not a blank page.
|
**γ (Q2'27)** Runbook generation from telemetry.
|
||||||
|
**δ (Q3'27 → Q4'27)** Audit ledger, tamper-resistant.
|
||||||
**δ (Q3'27 → Q4'27) — Audit ledger, tamper-resistant + externally addressable.** The SQLite hash-evidence stream migrates to S3 Object Lock + JWS signatures. External counsel verifies any production change back to a named human attestation.
|
|
||||||
|
|
||||||
> *Nova absorbs no IDE, no editor, no sprint tool, no agent harness.*
|
> *Nova absorbs no IDE, no editor, no sprint tool, no agent harness.*
|
||||||
|
|
||||||
@@ -196,23 +195,22 @@ Nova absorbs no IDE, no editor, no sprint tool, no agent harness. The contract s
|
|||||||
|
|
||||||
## What we ask · What comes back
|
## What we ask · What comes back
|
||||||
|
|
||||||
**What we ask.**
|

|
||||||
Architecture endorsement. Runway to the next milestone.
|
|
||||||
|
|
||||||
**Why now.**
|
**What works now.** Deploying L1 & L2 stacks works today in the sandbox AWS account — 13 L1 primitives and 2 L2 modules, live-applied at confidence 0.800. Next steps: ingest greenfield pilot projects, promote from sandbox to production, integrate with the SPGE constitutional library, and serve as the infrastructure layer.
|
||||||
Agentic SDLC is reshaping the delivery curve. What is barely keepable today — incident response, compliance reconciliation, security remediation — does not compress at the same rate as the velocity it has to keep pace with. By the end of 2027, the gap between delivery acceleration and operational absorption is the structural risk.
|
|
||||||
|
|
||||||
**What comes back.**
|
**What we ask.** Architecture endorsement. Runway to the next milestone.
|
||||||
The infrastructure foundation that absorbs the velocity. Metrics that tell us where to push next. Audit lineage that closes the regulatory question. The next milestone, **by November 2026**.
|
|
||||||
|
**Why now.** Agentic SDLC is reshaping the delivery curve. What is barely keepable today — incident response, compliance reconciliation, security remediation — does not compress at the same rate as the velocity it has to keep pace with. By the end of 2027, the gap between delivery acceleration and operational absorption is the structural risk.
|
||||||
|
|
||||||
|
**What comes back.** The infrastructure foundation that absorbs the velocity. Metrics that tell us where to push next. Audit lineage that closes the regulatory question. The next milestone, **by November 2026**.
|
||||||
|
|
||||||
> *What we do not ask for: an IDE, a sprint tool, an author workflow, an upstream pipeline. Nova stays in its lane [1].*
|
> *What we do not ask for: an IDE, a sprint tool, an author workflow, an upstream pipeline. Nova stays in its lane [1].*
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
This is presented to Infrastructure and Operations leadership in August 2026. The ask is two things: architecture endorsement, and runway to the next milestone by November 2026.
|
This is presented to Infrastructure and Operations leadership in August 2026. What works now: deploying L1 and L2 stacks works today. 13 L1 primitives and 2 L2 modules are live in the registry; the pilot ran a live terraform apply against the dev AWS account at v1.26 and returned confidence 0.800 — a measured number, not a forecast. We refer to the dev account colloquially as the sandbox. Next steps: ingest greenfield pilot projects (greenfield consumers with no legacy to reconcile), promote from sandbox to production (the promotion path with HITL gates exists; the pilot was dev-only, so activating qa, prod, dr is the next step), integrate with the SPGE constitutional library (an external governance system the audience recognizes; the platform meets it at the contract surface), and serve as the infrastructure layer.
|
||||||
|
|
||||||
Why now. Agentic SDLC is reshaping the delivery curve. The velocity is up, and it is going to keep going up. What is barely keepable today — incident response, compliance reconciliation, security remediation — does not compress at the same rate as the velocity it has to keep pace with. The operational absorption side of the curve is steeper than the delivery acceleration side, and the gap between them is the structural risk. By the end of 2027, that gap is the thing that breaks cadence. Internal directional target: a 60% reduction in the operational absorption gap is the goal we are holding ourselves to — not a sourced claim, a directional target, and the metrics the platform already produces will tell us whether we are closing it.
|
The ask is architecture endorsement and runway to the next milestone by November 2026. Why now: agentic SDLC is reshaping the delivery curve. What is barely keepable today — incident response, compliance reconciliation, security remediation — does not compress at the same rate as the velocity. By end of 2027, the gap between delivery acceleration and operational absorption is the structural risk. Internal directional target: a 60% reduction in that gap — not a sourced claim, a directional target the platform's metrics will track.
|
||||||
|
|
||||||
What comes back. The infrastructure foundation that absorbs the velocity. Metrics that tell us where to push next. Audit lineage that closes the regulatory question. And the next milestone, by November 2026. That is the runway ask: not a budget, not a headcount, not a re-org. Runway to land the architecture endorsement and demonstrate the next milestone.
|
What comes back: the infrastructure foundation that absorbs the velocity, metrics that tell us where to push next, audit lineage that closes the regulatory question, and the next milestone by November 2026. Not a budget, not a headcount — runway to land the architecture endorsement. What we do not ask for: an IDE, a sprint tool, an author workflow, an upstream pipeline. Nova stays in its lane [1]. The sovereign boundary makes the ask small and the return large.
|
||||||
|
|
||||||
What we do not ask for: an IDE, a sprint tool, an author workflow, an upstream pipeline. Nova stays in its lane [1]. The sovereign boundary is the discipline that makes the ask small and the return large. Use the runway to land the architecture endorsement.
|
|
||||||
-->
|
-->
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# render_leadership_diagrams.sh — render the 7 leadership-deck mermaid
|
||||||
|
# diagrams to PNG via mmdc. Single-shot helper (NOT a CI gate, per
|
||||||
|
# D-241/D-246). Uses vendored Chromium shared libraries (D-246).
|
||||||
|
#
|
||||||
|
# Usage: bash scripts/render_leadership_diagrams.sh
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(git rev-parse --show-toplevel)"
|
||||||
|
|
||||||
|
MMD_DIR="docs/presentations/assets/mmd"
|
||||||
|
PNG_DIR="docs/presentations/assets/png"
|
||||||
|
THEME_JSON="$MMD_DIR/sp-theme.json"
|
||||||
|
PUPPETEER_CFG="docs/presentations/assets/puppeteer-config.json"
|
||||||
|
|
||||||
|
# Vendored Chromium shared libraries (D-246) — extracted from Debian
|
||||||
|
# bookworm .deb packages to /home/opencode/tmp/so2/
|
||||||
|
VENDORED_SO="/home/opencode/tmp/so2"
|
||||||
|
export LD_LIBRARY_PATH="${VENDORED_SO}:${LD_LIBRARY_PATH:-}"
|
||||||
|
|
||||||
|
export CHROME_PATH="/home/opencode/.cache/puppeteer/chrome/linux-152.0.7977.42/chrome-linux64/chrome"
|
||||||
|
|
||||||
|
echo "=== Rendering leadership deck mermaid diagrams (S&P theme, 2x, transparent) ==="
|
||||||
|
for mmd in "$MMD_DIR"/leadership-slide-*.mmd; do
|
||||||
|
name="$(basename "$mmd" .mmd)"
|
||||||
|
png="$PNG_DIR/$name.png"
|
||||||
|
echo " $name.mmd → $name.png"
|
||||||
|
npx --yes @mermaid-js/mermaid-cli@11.16.0 \
|
||||||
|
--configFile "$THEME_JSON" \
|
||||||
|
--puppeteerConfigFile "$PUPPETEER_CFG" \
|
||||||
|
-s 2 -b transparent \
|
||||||
|
--input "$mmd" \
|
||||||
|
--output "$png" 2>&1 | grep -v "^$" || true
|
||||||
|
done
|
||||||
|
echo " Rendered $(ls "$PNG_DIR"/leadership-slide-*.png 2>/dev/null | wc -l) leadership PNGs."
|
||||||
@@ -31,7 +31,7 @@ try:
|
|||||||
from pptx.util import Inches, Pt, Emu
|
from pptx.util import Inches, Pt, Emu
|
||||||
from pptx.dml.color import RGBColor
|
from pptx.dml.color import RGBColor
|
||||||
from pptx.enum.shapes import MSO_SHAPE
|
from pptx.enum.shapes import MSO_SHAPE
|
||||||
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
|
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR, MSO_AUTO_SIZE
|
||||||
from pptx.oxml.ns import qn
|
from pptx.oxml.ns import qn
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print("ERROR: python-pptx not installed.", file=sys.stderr)
|
print("ERROR: python-pptx not installed.", file=sys.stderr)
|
||||||
@@ -206,11 +206,13 @@ def _add_title_bar(slide):
|
|||||||
return bar
|
return bar
|
||||||
|
|
||||||
|
|
||||||
def _add_footer(slide, text: str):
|
def _add_footer(slide, text: str, dark_bg: bool = False):
|
||||||
"""Right-aligned footer textbox at the bottom of every slide.
|
"""Right-aligned footer textbox at the bottom of every slide.
|
||||||
|
|
||||||
REQ-372.5 / D-242: the python-pptx path does not read the Marp
|
REQ-372.5 / D-242: the python-pptx path does not read the Marp
|
||||||
`footer:` directive, so the footer is rendered as a textbox.
|
`footer:` directive, so the footer is rendered as a textbox.
|
||||||
|
F4 polish: dark text on white content slides, light text on the
|
||||||
|
black cover slide.
|
||||||
"""
|
"""
|
||||||
if not text:
|
if not text:
|
||||||
return None
|
return None
|
||||||
@@ -225,7 +227,7 @@ def _add_footer(slide, text: str):
|
|||||||
r.text = text
|
r.text = text
|
||||||
r.font.name = FONT_NAME
|
r.font.name = FONT_NAME
|
||||||
r.font.size = Pt(10)
|
r.font.size = Pt(10)
|
||||||
r.font.color.rgb = GREY_HEADER
|
r.font.color.rgb = GREY_HEADER if dark_bg else BODY_TEXT
|
||||||
return tb
|
return tb
|
||||||
|
|
||||||
|
|
||||||
@@ -308,9 +310,15 @@ def _strip_inline_emphasis(text: str) -> str:
|
|||||||
return text
|
return text
|
||||||
|
|
||||||
|
|
||||||
def _inline_runs(p, text: str, *, size: int = 18, base_color: RGBColor = BODY_TEXT):
|
def _inline_runs(p, text: str, *, size: int = 18, base_color: RGBColor = BODY_TEXT,
|
||||||
"""Add inline runs to paragraph `p`, rendering **bold** as red strong,
|
bold_color: RGBColor = None):
|
||||||
`code` as monospace, *italic* as italic. Other text is plain."""
|
"""Add inline runs to paragraph `p`, rendering **bold** as strong,
|
||||||
|
`code` as monospace, *italic* as italic. Other text is plain.
|
||||||
|
F5(b): bold_color defaults to RED (legacy behavior) but can be
|
||||||
|
overridden to base_color to de-emphasize bold on slides with many
|
||||||
|
bold sections (avoids a red wall)."""
|
||||||
|
if bold_color is None:
|
||||||
|
bold_color = RED
|
||||||
# Tokenize on `**...**`, `*...*`, `` `...` ``
|
# Tokenize on `**...**`, `*...*`, `` `...` ``
|
||||||
tokens = re.split(r"(\*\*[^*]+\*\*|`[^`]+`|\*[^*]+\*)", text)
|
tokens = re.split(r"(\*\*[^*]+\*\*|`[^`]+`|\*[^*]+\*)", text)
|
||||||
for tok in tokens:
|
for tok in tokens:
|
||||||
@@ -322,7 +330,7 @@ def _inline_runs(p, text: str, *, size: int = 18, base_color: RGBColor = BODY_TE
|
|||||||
r.font.name = FONT_NAME
|
r.font.name = FONT_NAME
|
||||||
r.font.size = Pt(size)
|
r.font.size = Pt(size)
|
||||||
r.font.bold = True
|
r.font.bold = True
|
||||||
r.font.color.rgb = RED
|
r.font.color.rgb = bold_color
|
||||||
elif tok.startswith("`") and tok.endswith("`"):
|
elif tok.startswith("`") and tok.endswith("`"):
|
||||||
r = p.add_run()
|
r = p.add_run()
|
||||||
r.text = tok[1:-1]
|
r.text = tok[1:-1]
|
||||||
@@ -586,7 +594,7 @@ def parse_slide(slide_src: str):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def render_title_slide(prs, slide_data, footer_text: str = ""):
|
def render_title_slide(prs, slide_data, deck_dir: Path, footer_text: str = ""):
|
||||||
slide = prs.slides.add_slide(prs.slide_layouts[6]) # blank
|
slide = prs.slides.add_slide(prs.slide_layouts[6]) # blank
|
||||||
_set_bg(slide, BLACK)
|
_set_bg(slide, BLACK)
|
||||||
# red top bar
|
# red top bar
|
||||||
@@ -635,7 +643,12 @@ def render_title_slide(prs, slide_data, footer_text: str = ""):
|
|||||||
r_b.font.italic = True
|
r_b.font.italic = True
|
||||||
r_b.font.color.rgb = WHITE
|
r_b.font.color.rgb = WHITE
|
||||||
cur_top += Inches(0.85)
|
cur_top += Inches(0.85)
|
||||||
_add_footer(slide, footer_text)
|
elif kind == "image":
|
||||||
|
# image on title slide (D-246 diagrams on cover)
|
||||||
|
img_path = deck_dir / item[1]
|
||||||
|
_add_picture(slide, img_path, top=cur_top)
|
||||||
|
cur_top += Inches(3.6)
|
||||||
|
_add_footer(slide, footer_text, dark_bg=True)
|
||||||
|
|
||||||
|
|
||||||
def render_content_slide(prs, slide_data, deck_dir: Path, footer_text: str = ""):
|
def render_content_slide(prs, slide_data, deck_dir: Path, footer_text: str = ""):
|
||||||
@@ -644,63 +657,102 @@ def render_content_slide(prs, slide_data, deck_dir: Path, footer_text: str = "")
|
|||||||
_add_title_bar(slide)
|
_add_title_bar(slide)
|
||||||
_add_title_text(slide, slide_data["title"], color=RED, size=28, top=0.25,
|
_add_title_text(slide, slide_data["title"], color=RED, size=28, top=0.25,
|
||||||
bold=True, height=0.7)
|
bold=True, height=0.7)
|
||||||
cur_top = Inches(1.05)
|
# F5(b): if a slide has >=4 lead/bold-prefixed blocks, de-emphasize
|
||||||
|
# them to black+bold (section labels) instead of red+bold (avoids a
|
||||||
|
# red wall on milestone-timeline slides like slide 6). Count both
|
||||||
|
# explicit lead blocks (**...** on own line) and plain blocks that
|
||||||
|
# start with **bold** inline.
|
||||||
|
def _is_bold_block(item):
|
||||||
|
if item[0] == "lead":
|
||||||
|
return True
|
||||||
|
if item[0] == "plain" and item[1].lstrip().startswith("**"):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
bold_count = sum(1 for item in slide_data["body"] if _is_bold_block(item))
|
||||||
|
lead_color = BODY_TEXT if bold_count >= 4 else RED
|
||||||
|
# F1: vertical balance — pre-compute the content height to center
|
||||||
|
# the block between the title (bottom ~0.95") and the footer
|
||||||
|
# (top ~7.12"). Content starts at 1.05" by default; if the total
|
||||||
|
# content height is short, push it down to vertically center.
|
||||||
|
INC = {"lead": 0.50, "plain": 0.45, "quote": 0.55, "bullet": 0.40,
|
||||||
|
"ordered": 0.40, "image": 4.10, "table": 0.42, "code": 0.50,
|
||||||
|
"benefit": 0.75}
|
||||||
|
total_h = sum(INC.get(item[0], 0.40) for item in slide_data["body"])
|
||||||
|
content_start = 1.05
|
||||||
|
available = 7.12 - content_start # footer at 7.12
|
||||||
|
if total_h < available - 0.5 and total_h > 0:
|
||||||
|
offset = (available - total_h) / 2.0
|
||||||
|
offset = min(max(offset, 0), 1.2) # cap at +1.2"
|
||||||
|
content_start = round(content_start + offset, 2)
|
||||||
|
cur_top = Inches(content_start)
|
||||||
for item in slide_data["body"]:
|
for item in slide_data["body"]:
|
||||||
kind = item[0]
|
kind = item[0]
|
||||||
if kind == "lead":
|
if kind == "lead":
|
||||||
tb = slide.shapes.add_textbox(MARGIN_X, cur_top, CONTENT_W, Inches(0.5))
|
tb = slide.shapes.add_textbox(MARGIN_X, cur_top, CONTENT_W, Inches(0.5))
|
||||||
tf = tb.text_frame
|
tf = tb.text_frame
|
||||||
tf.word_wrap = True
|
tf.word_wrap = True
|
||||||
|
tf.auto_size = MSO_AUTO_SIZE.SHAPE_TO_FIT_TEXT
|
||||||
p = tf.paragraphs[0]
|
p = tf.paragraphs[0]
|
||||||
p.alignment = PP_ALIGN.LEFT
|
p.alignment = PP_ALIGN.LEFT
|
||||||
_inline_runs(p, item[1], size=18, base_color=RED)
|
_inline_runs(p, item[1], size=18, base_color=lead_color,
|
||||||
# make the whole lead bold-strong-red
|
bold_color=lead_color)
|
||||||
|
# make the whole lead bold
|
||||||
for r in p.runs:
|
for r in p.runs:
|
||||||
r.font.bold = True
|
r.font.bold = True
|
||||||
r.font.color.rgb = RED
|
r.font.color.rgb = lead_color
|
||||||
cur_top += Inches(0.5)
|
cur_top += Inches(0.50)
|
||||||
elif kind == "plain":
|
elif kind == "plain":
|
||||||
tb = slide.shapes.add_textbox(MARGIN_X, cur_top, CONTENT_W, Inches(0.4))
|
tb = slide.shapes.add_textbox(MARGIN_X, cur_top, CONTENT_W, Inches(0.4))
|
||||||
tf = tb.text_frame
|
tf = tb.text_frame
|
||||||
tf.word_wrap = True
|
tf.word_wrap = True
|
||||||
|
tf.auto_size = MSO_AUTO_SIZE.SHAPE_TO_FIT_TEXT
|
||||||
p = tf.paragraphs[0]
|
p = tf.paragraphs[0]
|
||||||
p.alignment = PP_ALIGN.LEFT
|
p.alignment = PP_ALIGN.LEFT
|
||||||
_inline_runs(p, item[1], size=18, base_color=BODY_TEXT)
|
_inline_runs(p, item[1], size=18, base_color=BODY_TEXT,
|
||||||
cur_top += Inches(0.4)
|
bold_color=lead_color)
|
||||||
|
cur_top += Inches(0.45)
|
||||||
elif kind == "quote":
|
elif kind == "quote":
|
||||||
tb = slide.shapes.add_textbox(
|
tb = slide.shapes.add_textbox(
|
||||||
MARGIN_X + Inches(0.3), cur_top, CONTENT_W - Inches(0.3), Inches(0.6)
|
MARGIN_X + Inches(0.3), cur_top, CONTENT_W - Inches(0.3), Inches(0.6)
|
||||||
)
|
)
|
||||||
tf = tb.text_frame
|
tf = tb.text_frame
|
||||||
tf.word_wrap = True
|
tf.word_wrap = True
|
||||||
|
tf.auto_size = MSO_AUTO_SIZE.SHAPE_TO_FIT_TEXT
|
||||||
p = tf.paragraphs[0]
|
p = tf.paragraphs[0]
|
||||||
p.alignment = PP_ALIGN.LEFT
|
p.alignment = PP_ALIGN.LEFT
|
||||||
_inline_runs(p, item[1], size=18, base_color=GREY_TEXT)
|
_inline_runs(p, item[1], size=18, base_color=BODY_TEXT)
|
||||||
# italicize the whole blockquote
|
# italicize the whole blockquote
|
||||||
for r in p.runs:
|
for r in p.runs:
|
||||||
r.font.italic = True
|
r.font.italic = True
|
||||||
r.font.color.rgb = GREY_TEXT
|
r.font.color.rgb = BODY_TEXT
|
||||||
cur_top += Inches(0.6)
|
cur_top += Inches(0.55)
|
||||||
elif kind == "bullet":
|
elif kind == "bullet":
|
||||||
# accumulate consecutive bullets into one text frame
|
# accumulate consecutive bullets into one text frame
|
||||||
# (handled below in a second pass; we render single here as fallback)
|
# (handled below in a second pass; we render single here as fallback)
|
||||||
tb = slide.shapes.add_textbox(MARGIN_X, cur_top, CONTENT_W, Inches(0.35))
|
tb = slide.shapes.add_textbox(MARGIN_X, cur_top, CONTENT_W, Inches(0.35))
|
||||||
tf = tb.text_frame
|
tf = tb.text_frame
|
||||||
tf.word_wrap = True
|
tf.word_wrap = True
|
||||||
|
tf.auto_size = MSO_AUTO_SIZE.SHAPE_TO_FIT_TEXT
|
||||||
p = tf.paragraphs[0]
|
p = tf.paragraphs[0]
|
||||||
p.alignment = PP_ALIGN.LEFT
|
p.alignment = PP_ALIGN.LEFT
|
||||||
p.level = item[1]
|
p.level = item[1]
|
||||||
r = p.add_run()
|
r = p.add_run()
|
||||||
prefix = "• " if item[1] == 0 else ("– " if item[1] == 1 else "· ")
|
# F3: if the bullet text starts with →, omit the bullet glyph
|
||||||
r.text = prefix + _strip_inline_emphasis(item[2])
|
stripped_text = _strip_inline_emphasis(item[2])
|
||||||
|
if item[1] == 0:
|
||||||
|
prefix = "" if stripped_text.lstrip().startswith("→") else "• "
|
||||||
|
else:
|
||||||
|
prefix = "– " if item[1] == 1 else "· "
|
||||||
|
r.text = prefix + stripped_text
|
||||||
r.font.name = FONT_NAME
|
r.font.name = FONT_NAME
|
||||||
r.font.size = Pt(18 if item[1] == 0 else 16)
|
r.font.size = Pt(18 if item[1] == 0 else 16)
|
||||||
r.font.color.rgb = BODY_TEXT
|
r.font.color.rgb = BODY_TEXT
|
||||||
cur_top += Inches(0.35)
|
cur_top += Inches(0.40)
|
||||||
elif kind == "ordered":
|
elif kind == "ordered":
|
||||||
tb = slide.shapes.add_textbox(MARGIN_X, cur_top, CONTENT_W, Inches(0.35))
|
tb = slide.shapes.add_textbox(MARGIN_X, cur_top, CONTENT_W, Inches(0.35))
|
||||||
tf = tb.text_frame
|
tf = tb.text_frame
|
||||||
tf.word_wrap = True
|
tf.word_wrap = True
|
||||||
|
tf.auto_size = MSO_AUTO_SIZE.SHAPE_TO_FIT_TEXT
|
||||||
p = tf.paragraphs[0]
|
p = tf.paragraphs[0]
|
||||||
p.alignment = PP_ALIGN.LEFT
|
p.alignment = PP_ALIGN.LEFT
|
||||||
r = p.add_run()
|
r = p.add_run()
|
||||||
@@ -708,7 +760,7 @@ def render_content_slide(prs, slide_data, deck_dir: Path, footer_text: str = "")
|
|||||||
r.font.name = FONT_NAME
|
r.font.name = FONT_NAME
|
||||||
r.font.size = Pt(18)
|
r.font.size = Pt(18)
|
||||||
r.font.color.rgb = BODY_TEXT
|
r.font.color.rgb = BODY_TEXT
|
||||||
cur_top += Inches(0.35)
|
cur_top += Inches(0.40)
|
||||||
elif kind == "image":
|
elif kind == "image":
|
||||||
img_path = deck_dir / item[1]
|
img_path = deck_dir / item[1]
|
||||||
_add_picture(slide, img_path, top=cur_top)
|
_add_picture(slide, img_path, top=cur_top)
|
||||||
@@ -721,6 +773,7 @@ def render_content_slide(prs, slide_data, deck_dir: Path, footer_text: str = "")
|
|||||||
tb = slide.shapes.add_textbox(MARGIN_X, cur_top, CONTENT_W, Inches(0.6))
|
tb = slide.shapes.add_textbox(MARGIN_X, cur_top, CONTENT_W, Inches(0.6))
|
||||||
tf = tb.text_frame
|
tf = tb.text_frame
|
||||||
tf.word_wrap = True
|
tf.word_wrap = True
|
||||||
|
tf.auto_size = MSO_AUTO_SIZE.SHAPE_TO_FIT_TEXT
|
||||||
p = tf.paragraphs[0]
|
p = tf.paragraphs[0]
|
||||||
p.alignment = PP_ALIGN.LEFT
|
p.alignment = PP_ALIGN.LEFT
|
||||||
r = p.add_run()
|
r = p.add_run()
|
||||||
@@ -751,7 +804,7 @@ def render_deck(md_path: Path, pptx_path: Path):
|
|||||||
is_title = (idx == 0) or data["is_title_class"] or data["title_is_h1"]
|
is_title = (idx == 0) or data["is_title_class"] or data["title_is_h1"]
|
||||||
# The appendix is a content slide (rendered normally)
|
# The appendix is a content slide (rendered normally)
|
||||||
if idx == 0 and (data["title_is_h1"] or data["is_title_class"]):
|
if idx == 0 and (data["title_is_h1"] or data["is_title_class"]):
|
||||||
render_title_slide(prs, data, footer_text=footer_text)
|
render_title_slide(prs, data, deck_dir, footer_text=footer_text)
|
||||||
elif data["is_title_class"] and not data["title_is_h1"] and idx != 0:
|
elif data["is_title_class"] and not data["title_is_h1"] and idx != 0:
|
||||||
# Marp _class: title on a non-H1 slide (e.g., appendix) — render as
|
# Marp _class: title on a non-H1 slide (e.g., appendix) — render as
|
||||||
# content but with a title-style bar. Keep it simple: content slide.
|
# content but with a title-style bar. Keep it simple: content slide.
|
||||||
|
|||||||