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:
@@ -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`.
|
||||
|
||||
Reference in New Issue
Block a user