feat: add master notebook library scaffolding and review tooling

Add CLAUDE.md defining the Palladium master notebook conventions and
Red Panda Approval criteria, plus a review-notebook slash command for
LLM-driven notebook review.

Expand .gitignore to block client/engagement documents and generated
exports, keeping masters client-clean while allowing text/image sources.

Normalize slider widget numeric values from floats to integers in
notebook JSON.
This commit is contained in:
2026-07-31 16:16:07 +00:00
parent 53c069fddb
commit a967f73d09
61 changed files with 4881 additions and 4257 deletions

View File

@@ -1,21 +1,32 @@
# Mercury Notebook Deliverable Pattern v1.0.0
# Mercury Notebook Deliverable Pattern v1.1.0
Standardizes how Palladium studies ship business-case deliverables: a Mercury-served
Jupyter notebook **is** the artifact — math in a self-contained study package,
Standardizes how Palladium masters — **Studies and Assessments** — ship notebook
deliverables: a Mercury-served Jupyter notebook **is** the artifact — logic in a
self-contained study package, content and client data in tagged notebook cells,
presentation in reactive notebooks, verification gates pinning every number, and
LLM-readable exports. All new studies follow this pattern; the Streamlit app path is
LLM-readable exports. All masters follow this pattern; the Streamlit app path is
retired by it.
## 🐾 Red Panda Approval™
This pattern follows Red Panda Approval standards.
This pattern follows Red Panda Approval standards (see `CLAUDE.md` for the rubric).
**Audience note:** this document is written to be loaded whole as context by an LLM
agent building or modifying a study. Rules are imperative (MUST/SHOULD/NEVER), each
agent building or modifying a master. Rules are imperative (MUST/SHOULD/NEVER), each
with a one-line *why*. Long code lives in the runnable template
[`template/MercuryNotebook/`](../template/MercuryNotebook/) — copy it to start a study;
snippets here are excerpts from it. The full-scale reference implementation is the CTM
Genesys study, [`studies/202607_CTM_GenesysCX/`](../studies/202607_CTM_GenesysCX/).
snippets here are excerpts from it (note: the template still encodes the py-engine
model only). The reference implementation of the **notebook-first content model** is
[`assessments/CX_Discovery_Workshop/`](../assessments/CX_Discovery_Workshop/); the
largest worked multi-notebook example remains the CTM Genesys study,
[`studies/202607_CTM_GenesysCX/`](../studies/202607_CTM_GenesysCX/).
**Docs map:** this file holds the **shared mechanics** every master obeys.
[`Assessment_Pattern_V1-00.md`](Assessment_Pattern_V1-00.md) and
[`Study_Pattern_V1-00.md`](Study_Pattern_V1-00.md) specialize it per master type —
read the one for your master type first. `CLAUDE.md` at the repo root is the
always-on contract (rubric, three-layer contract, taxonomy, risk tiers,
confidentiality) and takes precedence where documents disagree.
---
@@ -53,9 +64,11 @@ Instead, this pattern defines:
```
palladium/
├── docs/ # repo-wide docs (this pattern, brand.md)
├── docs/ # repo-wide docs (the patterns, brand.md)
├── template/
│ └── MercuryNotebook/ # copy-me starting point (runnable)
├── assessments/
│ └── Instrument_Name/ # reusable workshop master (UNDATED), e.g. CX_Discovery_Workshop
└── studies/
├── YYYYMM_TEI_Vendor_Product/ # vendor TEI study, e.g. 202602_TEI_Amazon_Connect
└── YYYYMM_Client_EngagementName/ # client study, e.g. 202607_CTM_GenesysCX
@@ -63,6 +76,10 @@ palladium/
- Names MUST use **underscores, never dashes** — dashed directories can't be Python
packages, and everything in a study is importable code.
- **Studies are dated** (`YYYYMM_` — they reproduce a dated publication or engagement);
**Assessments are undated** (living instruments). An **engagement copy** of a master
is stamped `YYYYMM_Client_Instrument` at copy-time and lives OUTSIDE this repo — see
the copy-out checklist in the Assessment Pattern and `CLAUDE.md` § Confidentiality.
- Every study is self-contained with this layout (from the template):
```
@@ -93,11 +110,11 @@ JupyterLab by analysts, executed headless by nbconvert for exports. NEVER build
parallel UI (Streamlit, Dash, a second "app" rendering the same model) — two surfaces
over one model always diverge, and the notebook already *is* the interactive surface.
### 2 · Engine/presentation split
### 2 · Engine/presentation split — and where content lives
Notebooks hold **no math**. Every number a stakeholder sees is computed in the study
package and imported. *Why:* the package is testable and diffable; notebook cells are
neither. The test suite pins the engine; the notebook only arranges its outputs.
package and imported. *Why:* the package is testable and diffable for *logic*; the
test suite pins the engine; the notebook only arranges its outputs.
```python
# notebook cell — arrange and render, never compute
@@ -106,6 +123,15 @@ inc, net_by = case_flows(total_by_year, ben_by_year)
kpi = case_kpis(inc, net_by, DISCOUNT_RATE)
```
The split cuts the other way for **content and client data**: notebooks hold no math,
but they DO hold the human-authored content (topic banks, survey text, facilitation
prompts) and the client facts (spend, headcount, engagement identity) — in **tagged
cells** (`topic-bank`, `engagement-data`), edited in Jupyter. Content NEVER lives in a
`.py` file. *Why:* the notebook is the document the consultant reads and edits;
content hidden in importable modules defeats the point of a notebook. Tests pin
content by reading the tagged cells with nbformat and exec'ing them — no kernel
needed. Full contract: the [Assessment Pattern](Assessment_Pattern_V1-00.md).
### 3 · The Mercury reactivity contract
Mercury re-executes only the cells **below** a changed widget's cell — never the
@@ -416,8 +442,15 @@ Each of these cost a debugging session or a client-facing embarrassment. Don't.
## Testing
Layers, from inner to outer — every study ships all four:
Layers, from inner to outer — every master ships layers 14; layer 0 covers the whole
library from the repo root:
0. **Repo-level structural suite** (`tests/test_notebooks.py`, run from the ROOT venv:
`make check-notebooks`) — kernel-free nbformat checks on every committed notebook:
parses, python3 kernel, no error outputs, cleanly executed top-to-bottom, and (for
notebook-first masters) the tagged-cell taxonomy. Every notebook must be classified
in `tests/nbcheck.py`; grandfathered ones skip the notebook-first tier with a
recorded reason.
1. **Engine pins** (`tests/`) — hand-checked acceptance numbers for every model
function; the contracted overlay AND the verbatim record both pinned, so neither can
drift. Compute by hand first, then pin (see