Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions scripts/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,11 @@ imports it, except `mcp-app`, which no widget imports and which lands in
`skills/leaf/mcp-app/` for an MCP host to read from the install.

A bundle reproduces its tracked bytes exactly when every input it fetches is pinned,
which holds for `marked`, `sortable`, `beautiful-mermaid`, `highlight`, and `jsdiff`,
so a clean `git status` after a run is the check that the bundle still matches the
script. `plot` and `pierre` reach npm's resolver for transitive dependencies and inherit
its ranges, so a diff from either can be an upstream patch rather than drift.
which holds for `marked`, `sortable`, `beautiful-mermaid`, `floating-ui`, `highlight`,
and `jsdiff`, so a clean `git status` after a run is the check that the bundle still
matches the script. `plot`, `pierre`, and `mcp-app` reach npm's resolver for transitive
dependencies and inherit its ranges, so a diff from one of those can be an upstream
patch rather than drift.

Rerun a bundle after changing its pin or the registry input it reads; do not patch a
generated bundle or `examples/corpus.html` directly.
46 changes: 46 additions & 0 deletions tests/test_interact_layer.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""CLI, plugin payload, layer, and customization tests."""

import ast
import contextlib
import json
import os
Expand Down Expand Up @@ -299,6 +300,51 @@ def names(scope):
assert not unnamed, f"unnamed in scripts/CLAUDE.md: {unnamed}"


def test_the_tooling_instructions_place_every_vendored_bundle():
"""Whether a rebuild reproduces its bytes must be named where sessions read.

`scripts/CLAUDE.md` says a clean `git status` after `vendor.py <bundle>` is the
check that the bundle still matches the script, and that the check holds only for
the bundles whose every fetched input is pinned. That sentence is what a session
consults before reading a rebuild's diff as drift or as an upstream patch, so a
bundle it never places has no answer either way — which is how `floating-ui`, whose
pins cover its whole closure, and `mcp-app`, whose do not, both went unplaced. The
names come from `vendor.py` rather than a list here, for the reason the routing
above states: a list is the second copy, and the bundle added without the sentence
would stay green.
"""
tree = ast.parse((ROOT / "scripts" / "vendor.py").read_text(encoding="utf-8"))
bundles = {
key.value
for node in ast.walk(tree)
for target in (
node.targets
if isinstance(node, ast.Assign)
else [node.target]
if isinstance(node, ast.AnnAssign)
else []
)
if isinstance(target, ast.Name) and target.id in {"BUILDS", "COPIES"}
for key in node.value.keys
if isinstance(key, ast.Constant)
}
paragraphs = [
paragraph
for paragraph in (ROOT / "scripts" / "CLAUDE.md")
.read_text(encoding="utf-8")
.split("\n\n")
if paragraph.startswith("A bundle reproduces its tracked bytes exactly")
]

assert bundles, "no bundles read — an empty set places itself"
assert len(paragraphs) == 1, (
"scripts/CLAUDE.md no longer opens one paragraph with "
f"'A bundle reproduces its tracked bytes exactly': {len(paragraphs)} found"
)
unplaced = sorted(name for name in bundles if f"`{name}`" not in paragraphs[0])
assert not unplaced, f"unplaced in scripts/CLAUDE.md: {unplaced}"


def test_the_root_instructions_name_every_directory_ci_gates_on_its_own():
"""A gate `uv run pytest tests` does not reach must be named where sessions read.

Expand Down
Loading