docs: update workshop README for notebook-first content model

Rewrite the CX Discovery Workshop README to reflect the architecture
shift where content lives in the notebook's `topic-bank` cell rather
than in `discoverylib/topics.py`. The library now holds code only, the
notebook is the deliverable (no longer generated via build_notebook.py),
and tests pin content read directly from the notebook. Update layout,
run, and extending sections accordingly.
This commit is contained in:
2026-07-31 10:24:42 +00:00
parent 71b913d7fe
commit 53c069fddb
11 changed files with 3613 additions and 3906 deletions

View File

@@ -30,37 +30,40 @@ prompts, grouped by topic → sub-topic) and the **captured-session appendix**
Mercury stage. The 8 topics / 26 sub-topics / ~110-minute agenda are the
structured form of the source survey.
## Where the content lives: in the notebook
The topic bank — every topic, sub-topic, and facilitator prompt — lives in
the **`topic-bank` cell** of
[`notebooks/cx_discovery.ipynb`](notebooks/cx_discovery.ipynb) (the code cell
tagged `topic-bank`, right under the title). **Content is edited there, in
Jupyter — never in a `.py` file.** It is the study's verbatim anchor: wording
tracks the source survey
[`docs/cx_discovery_survey.md`](docs/cx_discovery_survey.md) (the original
`cxxm.md`), and the `key` slugs are stable identities the sidebar widgets,
captured notes, and JSON export all key off — never renumber or rename them
casually. The cell's own comment block carries the full editing rules.
`discoverylib/` holds **code only**: the `Topic`/`SubTopic` schema, the
status vocabulary, and the session engine — every engine function takes the
bank as its first argument. The ~42 sidebar widgets are built by a runtime
loop over `TOPICS`, so board, checklist, script, gate, and export all pick up
a content edit automatically. The test suite reads the tagged cell straight
out of the notebook (no kernel) and pins the content, so `pytest` guards the
bank exactly as shipped.
## Layout
```
discoverylib/ # the engine — all content & logic
topics.py # the topic bank (verbatim anchor from the survey)
session.py # status vocabulary, progress, checklist, export payload
notebooks/cx_discovery.ipynb # THE deliverable — content (topic-bank cell) + presentation
discoverylib/ # the engine — code only, no content
session.py # Topic/SubTopic schema, status vocabulary, progress, export payload
staging.py # stage/backstage detection (copied verbatim)
notebooks/cx_discovery.ipynb # the deliverable (generated — see below)
scripts/
build_notebook.py # regenerates the notebook from cell sources
export_report.py # nbconvert → exports/*.html + *.md
tests/ # engine pins + stage/backstage test
scripts/export_report.py # nbconvert → exports/*.html + *.md
tests/ # content pins (read from the notebook) + engine pins + staging test
docs/cx_discovery_survey.md # source survey (the original cxxm.md)
exports/ # generated report sources
```
## The notebook is generated
The notebook wires ~42 Mercury widgets (a status selector + notes box per
topic, a checkbox per sub-topic), all derived from the topic bank so they can't
drift from `discoverylib`. Rather than hand-maintain that JSON, the notebook is
built from readable cell sources in
[`scripts/build_notebook.py`](scripts/build_notebook.py):
```bash
python scripts/build_notebook.py # regenerate after editing a cell
```
Edit facilitation *content* (topics, sub-topics, prompts, scope, minutes) in
[`discoverylib/topics.py`](discoverylib/topics.py) — not in the notebook.
## Run
```bash
@@ -69,15 +72,23 @@ pip install -e ".[dev]"
mercury --working-dir . # serve the stage (share this screen)
jupyter lab # analyst / facilitator view
pytest # engine pins + stage/backstage
pytest # content pins + engine pins + stage/backstage
jupyter nbconvert --to notebook --execute --inplace notebooks/cx_discovery.ipynb # gate
python scripts/export_report.py # exports/*.html + *.md for the LLM handoff
```
## Extending
New or reshaped discovery content is a `discoverylib/topics.py` edit, a test
pin (`tests/test_topics.py` recounts, `tests/test_session.py` for new logic),
then `python scripts/build_notebook.py`. Add a topic and the sidebar controls,
board, checklist, script, gate, and export all pick it up — because they're all
generated from the bank.
New or reshaped discovery content is an edit to the notebook's `topic-bank`
cell in JupyterLab, then:
1. Re-run the notebook — the in-notebook **gate** recounts the bank
(topics / sub-topics / prompts / key order / agenda minutes); update its
pins if the change is deliberate.
2. `pytest``tests/test_topics.py` pins the same shape from outside the
kernel; re-pin the counts there too.
Add a topic and the sidebar controls, board, checklist, script, gate, and
export all pick it up — they're all derived from `TOPICS` at runtime. New
*logic* (not content) goes in `discoverylib/session.py` with pins in
`tests/test_session.py`.