Skip to content

Add a handoff brief for the Leaf decomposition investigation - #1268

Draft
JimWallace wants to merge 3 commits into
mainfrom
claude/side-by-side-notebook-edit-iaw9z5
Draft

JimWallace wants to merge 3 commits into
mainfrom
claude/side-by-side-notebook-edit-iaw9z5

Conversation

@JimWallace

Copy link
Copy Markdown
Owner

Docs only. Context for a fresh agent picking up what the "multi-extend parser bug" was blocking, now that #1266 established the rule was a misdiagnosis.

What's in it

The finding as a mechanism, not a rule. Leaf's lexer has no notion of an HTML comment, so tag syntax written in prose is lexed as if it stood in the markup. The verified table covers all five behaviours, including the two that are counterintuitive: #(field) silently interpolates a real context value into the served HTML, and a commented-out include still resolves.

Method before findings. The section on how to verify comes second on purpose. The investigation that produced the correction first produced a wrong answer: a probe loop filtered on a test name that doesn't exist, so swift test reported 0 tests passed, the grep matched nothing, and every row was recorded as "BREAKS" — a clean, dramatic, entirely fictional result that was about to be written into CLAUDE.md. Control first, assert on a marker you've seen appear, falsify everything. Six assertions in the workbench feature were green while testing nothing; an agent walking in cold should budget for that.

The blocked work, measured. Four templates still over 700 lines, and the concrete duplication between assignment-new.leaf and _assignment-edit-body.leafsuite-sections 9× vs 6×, check-schema 3× vs 3×, 16 vs 22 script tags. Flagged explicitly as marker counts: a signal of shared structure, not proof, to be diffed before anyone proposes a shared partial.

What was not verified, so the next reader doesn't inherit unearned confidence: LeafKit 1.14.3 only, nesting depth beyond three levels untested, no direct disproof of a size effect, and render tests don't exercise page JS. Plus the innerHTML-destroys-element-identity hazard that cost a real debugging cycle in #1267.

What it asks for

A recommendation, not a refactor — and it says explicitly that "the rule was wrong and the work it blocked isn't worth doing anyway" is an acceptable outcome. These are the two highest-traffic authoring surfaces in the product, and a shared partial that gets the create-vs-edit differences subtly wrong is worse than two honest copies.

Linked from CLAUDE.md's reference list so it's findable without the path. No changelog fragment — nothing user-facing changes.

Checked that the brief contains no live Leaf tag syntax, so pasting it into a template or a Leaf-rendered page can't trip the bug it documents.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AqxwrNsbhyWt6hFvf8rMpj


Generated by Claude Code

claude added 3 commits August 5, 2026 01:39
Self-contained context for picking up what the "multi-extend parser bug"
was blocking, now that the rule has been corrected (#1266): the real
cause is that Leaf's lexer has no notion of an HTML comment, so tag
syntax written in prose is lexed as if it stood in the markup.

Covers the verified behaviour table, the concrete duplication between
assignment-new.leaf and _assignment-edit-body.leaf that decomposition
would address, and what was NOT verified -- version coverage, nesting
depth, whether template size ever mattered -- so the next reader does not
inherit confidence that was not earned.

Leads with method rather than findings, because the investigation that
produced the correction first produced a WRONG answer: a probe loop
filtered on a test name that does not exist, so every row came back
"BREAKS" while measuring nothing, and that was nearly written into
CLAUDE.md. Control first, assert on a marker you have seen appear,
falsify everything.

Asks for a recommendation rather than a refactor, and says explicitly
that "the rule was wrong and the work it blocked is not worth doing
anyway" is an acceptable answer -- these are the two highest-traffic
authoring surfaces in the product, and a shared partial that gets the
create-vs-edit differences subtly wrong is worse than two honest copies.

Linked from CLAUDE.md's reference list so it is findable without the path.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AqxwrNsbhyWt6hFvf8rMpj
An assignment is closed for the entire time it is being authored --
creation, cloning, and every save return it to closed -- so for course
staff this banner was permanently on screen and carried nothing they
could act on. The open/closed state is still surfaced where it can be
changed. The `isReadOnly` branch is untouched: students still get the
view-only notice, which does tell them something.

The test that pinned the banner asserted "staff must see the
staff-editable notice instead". Inverted rather than deleted, so it now
guards against the banner coming back, and the assertions either side of
it -- staff keep an editable notebook, staff do not get the student
notice, submit stays gated -- are unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AqxwrNsbhyWt6hFvf8rMpj
It was omitted entirely for a notebook with no `{{placeholders}}`, on the
reasoning that the two views would be byte-identical there so the control
was noise. The cost of that is worse than the noise: a missing control is
indistinguishable from one that failed to render, and the question it
raises ("why does the solution have this and the assignment not?") is
exactly the question the control could have answered.

Now rendered unavailable, with the reason in the tooltip. The disabled
state comes from the server (`openFileHasTemplateView`) rather than being
applied by JS, so it does not flash enabled on load; workbench.js keeps it
in sync after an in-place switch.

Note this does not change WHEN a notebook has a template view -- that is
still per-file, driven by whether that file's stored bytes contain
placeholders. An assignment showing the control disabled while its
solution shows it enabled is now legible rather than mysterious: the
starter has no placeholders and the solution does.

The new test needed tightening before it was worth having. It first
asserted `html.contains("disabled")`, which passed with the attribute
deleted -- "disabled" appears elsewhere on a page this size. Scoped to the
button's own markup via a small `htmlElement(in:containing:)` helper, and
re-falsified.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AqxwrNsbhyWt6hFvf8rMpj
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants