Skip to content

Commit bf2f2bb

Browse files
committed
Track quality gates and graph outcomes
1 parent a8d73c3 commit bf2f2bb

38 files changed

Lines changed: 1153 additions & 9 deletions

.github/workflows/preview-viz.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ jobs:
5555
for path in \
5656
"/" \
5757
"/examples/values" \
58+
"/examples/async-await" \
59+
"/examples/networking" \
60+
"/examples/subprocesses" \
61+
"/journeys/workers" \
5862
"/prototyping/journey-figures-gestalt"; do
5963
url="${base}${path}"
6064
echo "Checking ${url}"

Makefile

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: test embed-examples build check-generated fingerprint browser-layout-test seo-cache-lint verify-examples check-registry-integrity check-confusable-pairs check-broad-surface-tours check-footgun-coverage check-notes-supported quality-checks format-examples verify-python-version verify dev deploy lint
1+
.PHONY: test embed-examples build check-generated fingerprint browser-layout-test seo-cache-lint verify-examples check-registry-integrity check-confusable-pairs check-broad-surface-tours check-footgun-coverage check-notes-supported check-quality-scores check-no-figure-rationales check-journey-outcomes quality-checks format-examples verify-python-version verify smoke-deployment dev deploy lint
22

33
test:
44
python3 -m unittest discover -s tests -v
@@ -38,7 +38,16 @@ check-footgun-coverage:
3838
check-notes-supported:
3939
scripts/check_notes_supported.py
4040

41-
quality-checks: check-registry-integrity check-confusable-pairs check-broad-surface-tours check-footgun-coverage check-notes-supported
41+
check-quality-scores:
42+
scripts/check_quality_scores.py
43+
44+
check-no-figure-rationales:
45+
scripts/check_no_figure_rationales.py
46+
47+
check-journey-outcomes:
48+
scripts/check_journey_outcomes.py
49+
50+
quality-checks: check-registry-integrity check-confusable-pairs check-broad-surface-tours check-footgun-coverage check-notes-supported check-quality-scores check-no-figure-rationales check-journey-outcomes
4251

4352
format-examples:
4453
scripts/format_examples.py
@@ -54,5 +63,8 @@ verify: build test seo-cache-lint verify-examples quality-checks browser-layout-
5463
dev:
5564
uv run pywrangler dev --port 9696
5665

66+
smoke-deployment:
67+
scripts/smoke_deployment.py $(URL)
68+
5769
deploy: build
5870
uv run pywrangler deploy

docs/example-quality-rubric.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ Score each example on a 10 point scale:
99
3. **Alternatives and boundaries (0-0.75)** — the page names nearby choices and shows when to prefer this feature instead: `while` vs `for`, tuple vs list, `None` vs exception, property vs method, eager collection vs lazy stream, and similar alternatives.
1010
4. **Executable determinism (0-1.0)** — the sample runs as-is, has stable output, avoids network/time/randomness unless that is the lesson, and demonstrates cause and effect.
1111
5. **Python idiom and accuracy (0-1.0)** — code uses current Python 3.13 idioms, names reflect the concept, and prose is technically precise without distracting caveats.
12-
6. **Literate programming fit (0-1.0)** — prose and source read as one continuous article; each paragraph explains the adjacent fragment; comments are used only when they clarify the program itself.
13-
7. **Source/result pairing (0-1.0)** — each important source fragment has nearby output that proves the semantic point, not merely that the code ran.
14-
8. **Concept decomposition (0-1.0)** — the example breaks the concept into meaningful parts instead of presenting one compressed trick.
12+
6. **Literate programming fit (0-0.75)** — prose and source read as one continuous article; each paragraph explains the adjacent fragment; comments are used only when they clarify the program itself.
13+
7. **Source/result pairing (0-0.75)** — each important source fragment has nearby output that proves the semantic point, not merely that the code ran.
14+
8. **Concept decomposition (0-0.75)** — the example breaks the concept into meaningful parts instead of presenting one compressed trick.
1515
9. **Progressive walkthrough (0-0.75)** — each cell introduces one new idea, and the sequence builds toward the complete concept. Single-cell examples are acceptable only for intentionally atomic concepts.
1616
10. **Representative coverage (0-0.75)** — the code covers the forms promised by the title, summary, and prose, and the catalog has an explicit home for every common Python syntax form. Do not claim lists, dictionaries, and sets while showing only two of them; do not let syntax such as `break`, `continue`, `assert`, `nonlocal`, `yield from`, `async for`, or `:=` exist only as untested assumptions.
17-
11. **Practical usefulness (0-1.0)** — names, data, and outputs resemble simplified real code rather than toy placeholders; the example gives the feature a reason to exist.
17+
11. **Practical usefulness (0-0.75)** — names, data, and outputs resemble simplified real code rather than toy placeholders; the example gives the feature a reason to exist.
1818
12. **Editorial progression (0-1.0)** — broad examples move through a deliberate sequence: motivation, smallest concrete form, model/protocol, common operations, boundary or edge case, and neighboring concepts. The page should feel like a guided exposition rather than a sample tray.
1919

2020
Topic-specific gates:

docs/lessons-learned.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,7 @@ git diff --check
112112
- **Lines must terminate AT elements, not in their gaps or interiors.** A 1.5px gap between a tree edge and a leaf dot reads as "the tree is disconnected" (the `exception-group-peel` bug). A line endpoint 2px inside a circle reads as "the arrow pierces the node" (the `context-bowtie` bug). When connecting to a dot, end the line at the dot's centre and let the dot draw on top — the visual termination is the circumference, with zero gap or overshoot.
113113
- **Journey pages render section figures inline.** `SECTION_FIGURES` lives in `src/marginalia.py` (single source of truth, keyed by section title) and `render_for_section(title)` is invoked from `render_journey_page` between each section's meta and its example list. The same paint code that produces the `/prototyping/journey-figures-gestalt` review page renders on production journey pages; drift between the two is structurally impossible. Contract 10 asserts every section in `JOURNEYS` has a figure and every figure name resolves.
114114
- **An explicit comparison loop should iterate over the topic's whole spectrum.** When a cell teaches by doing `for label, value in [(...), (...)]: print(...)`, the bracketed list IS the lesson. Two items is a binary contrast; three items reads as a progression. The strings example presented English (pure ASCII, 1 byte/char) against Thai (3 bytes/char) but skipped the Latin-extended middle (French `café`: 4 code points, 5 bytes — `é` is 2 UTF-8 bytes). Adding the middle row turned the cell from "ASCII vs non-Latin" into "1-byte / 2-byte / 3-byte progression." The rule is narrow — most examples spread categories across cells, which is also a valid pattern — but when a comparison loop exists, fill it with the topic's actual spectrum, not just the endpoints.
115+
- **Quality debt must be tracked, not normalized away.** `docs/example-quality-rubric.md` sets a 9.0 target and `scripts/check_quality_scores.py` enforces the score registry: pages below the hard minimum need a concrete improvement backlog entry, and Hello World is the only standing waiver because first examples are traditionally tiny. A score below target is allowed only when the remaining work is named.
116+
- **No-figure decisions need a registry.** Some examples should not have figures, but that cannot be an invisible omission. `scripts/check_no_figure_rationales.py` validates `no_figure_rationales` so future constraint-shaped pages can opt out explicitly instead of shipping weak diagrams.
117+
- **Journey sections need outcome contracts.** `scripts/check_journey_outcomes.py` ties each journey section to learner outcomes and support examples so journey pages stay mental maps rather than catalog slices.
118+
- **Deployment smoke belongs beside CI.** `scripts/smoke_deployment.py` checks rendered Worker pages, runtime-boundary pages, journey pages, and prototype review pages for HTTP failures and exception markers. Build success is not enough; the deployed Worker must render.

0 commit comments

Comments
 (0)