Skip to content

docs(plan): standing artifact-provenance audit for M2–M5 upstream bumps - #298

Merged
adnaan merged 3 commits into
mainfrom
docs/m2-provenance-audit
Jul 19, 2026
Merged

docs(plan): standing artifact-provenance audit for M2–M5 upstream bumps#298
adnaan merged 3 commits into
mainfrom
docs/m2-provenance-audit

Conversation

@adnaan

@adnaan adnaan commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #296, and the plan-side half of #297.

M0 Phase 0 closed #295's mechanismmake build now runs npm ci, so the committed client bundle can no longer be built from stale node_modules. It did not close the class: a bundle can be correct-by-construction yet behaviorally regressive (an upstream client regression, or a server↔client wire mismatch — livetemplate exports ClientVersion precisely because there is no runtime handshake). No install-time check sees that, and CI does not run the live UI, excluding the e2e suite twice over (-tags=ci and -skip='E2E|e2e').

Every M2–M5 milestone pins a new upstream release per convention 11 and therefore regenerates this artifact — M5 certainly, since it ships a client-side feature. M1 does not, which is what makes deferring the CI work reasonable rather than negligent.

What this adds

A standing pre-bump checklist in the M2–M5 section, placed where convention 10 guarantees the executing session reads it — M2 will be a different session without this context, and a risk-section entry alone is too easy to skim past:

Also cross-links #297 from the § Risks entry.

Why #297 was deferred rather than done now

The natural CI smoke subset is the checkbox suite that #292/#293 had to stabilize. Putting headless Chrome into CI to guard a risk that doesn't bite until M2 risks trading a quiet problem for a flaky one, on the critical path of the demo milestone. Better made with M1's test-stability learnings in hand — so this records the decision point rather than pre-empting it.

Docs-only; no code changes.

🤖 Generated with Claude Code

https://claude.ai/code/session_018M9pJSPmG6i1D8s6rpEV4h

M0 Phase 0 closed #295's mechanism (make build now runs npm ci) but not
the class: a bundle can be correct-by-construction yet behaviorally
regressive -- an upstream client regression, or a server<->client wire
mismatch. No install-time check sees that, and CI does not run the live
UI, since it excludes the e2e suite twice over.

Each of M2-M5 pins a new upstream release per convention 11 and so
regenerates the artifact -- M5 certainly, as it ships a client-side
feature. M1 does not, which is what makes deferring this reasonable
rather than negligent.

Adds a pre-bump checklist where the executing session will actually read
it, since M2 will be a different session without this context: verify
direction rather than mere difference, match livetemplate's declared
ClientVersion rather than npm latest, run the local suite under
GOWORK=off, and treat a checkbox-toggle failure as a bundle problem until
proven otherwise -- it mimics the flakiness #292/#293 fixed and the tell
is 100% reproducibility.

Also records the explicit decision point for #297 (browser e2e smoke
subset in CI), deferred out of M0 on purpose: the natural smoke subset is
the checkbox suite that #292/#293 had to stabilize, so that call is
better made with M1's stability learnings in hand.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018M9pJSPmG6i1D8s6rpEV4h
@claude

claude Bot commented Jul 19, 2026

Copy link
Copy Markdown

Review

Docs-only change (docs/plans/2026-07-09-ephemeral-ui-reframe.md), no code touched, so the usual bug/perf/security/test-coverage lenses mostly don't apply. Focused on internal consistency instead. Cross-checked the following and they all hold up:

  • internal/assets/client/README.md exists and already documents the directional-verification / ClientVersion-matching guidance this checklist points back to.
  • The ctrlKey 1→5 marker and "M0 Phase 0's Learn" reference match what's actually in that Learn section (line 293/302).
  • #297 and #295 are real, correctly-linked issues (open / closed respectively), and "convention 11" / "convention 9" match the session-guide definitions elsewhere in the doc.

One accuracy concern worth a look before this lands:

The "M2–M5 regenerates this artifact" claim overstates M4. The new section says "each of M2–M5 pins a new upstream release (convention 11) and therefore regenerates this artifact" — but per the Roadmap outline just above it, M4 bumps lvt/components, and that's a Go-only server-side dependency (github.com/livetemplate/lvt/components in go.mod, consumed in internal/runtime/state.go / internal/server/websocket.go). It's unrelated to client/package.json's @livetemplate/client dependency that actually produces tinkerdown-client.browser.js. M2/M3 bump the Go livetemplate module too, and there's a real argument they should trigger a client-bundle check (since ClientVersion is the wire contract the checklist itself cites) — but M4's components bump doesn't touch the client bundle at all. As written, a future session executing M4 could be sent down the whole JS-bundle-verification checklist (npm ci, ctrlKey-style marker check, checkbox e2e focus) for a change that never touches that artifact. Worth either scoping the checklist to "M2/M3/M5" explicitly, or adding a line clarifying that M4 only applies if @livetemplate/client itself is also bumped alongside components.

Minor/non-blocking:

  • The standing checklist is placed correctly per convention 10 (top-to-bottom scan will hit it before M2 implementation), so the stated placement rationale checks out.
  • Markdown renders fine (checkbox list, nested parenthetical, issue link) — no formatting nits.

Nothing else stood out; the cross-link into § Risks and the M0 Phase 0 Learn tie-back are accurate and well-scoped.

Review-bot catch on #298, verified: the checklist said "each of M2-M5
pins a new upstream release and therefore regenerates this artifact",
which is wrong for M4. github.com/livetemplate/lvt/components is a
server-side Go module consumed by internal/server/websocket.go and
internal/runtime/state.go; it appears nowhere in client/src or
client/package.json, so bumping it does not touch the browser bundle.

As written, a session executing M4 would have been sent through npm ci,
a marker check and checkbox-focused e2e for an artifact its change never
regenerates -- wasted work that also teaches the wrong mental model.

The real trigger is a bump to @livetemplate/client specifically. Replaces
the blanket claim with a per-milestone table: M1 no; M2/M3 yes but
transitively, since ClientVersion is a wire contract with no runtime
handshake so a server bump obliges matching the client; M4 no; M5
certainly, as it ships a client-side feature.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018M9pJSPmG6i1D8s6rpEV4h
@adnaan

adnaan commented Jul 19, 2026

Copy link
Copy Markdown
Contributor Author

Good catch — verified and fixed in the follow-up commit.

You're right that lvt/components is server-side Go (internal/server/websocket.go, internal/runtime/state.go) and appears nowhere in client/src or client/package.json. My sentence conflated 'pins an upstream release' with 'regenerates the browser bundle' — as written it would have sent an M4 session through npm ci, a marker check and checkbox-focused e2e for an artifact that change never touches. Wasted work, and it teaches the wrong mental model besides.

Replaced the blanket claim with a per-milestone table naming the real trigger (a bump to @livetemplate/client specifically): M1 no; M2/M3 yes but transitively — since ClientVersion is a wire contract with no runtime handshake, a server bump obliges matching the client, which is exactly what M0 Phase 0 did; M4 no, with the reason stated so it isn't re-litigated; M5 certainly.

I took the table over your 'scope to M2/M3/M5' option because the M2/M3 case is indirect — the bundle isn't what's being bumped, the wire contract is what drags it along — and a bare milestone list would have lost that reasoning.

@claude

claude Bot commented Jul 19, 2026

Copy link
Copy Markdown

Review

Docs-only change to docs/plans/2026-07-09-ephemeral-ui-reframe.md, adding a standing pre-bump checklist for M2–M5 plus a one-line cross-link from § Risks. Verified the substantive claims against the actual repo state rather than just reading the prose:

  • client/package.json pins @livetemplate/client@^0.18.2 and go.mod pins livetemplate v0.19.1 — matches the "server v0.19.1 → client 0.18.2" example given for M0 Phase 0. ✓
  • github.com/livetemplate/lvt/components is imported only in internal/runtime/state.go and internal/server/websocket.go (both server-side Go), and nowhere under client/src — confirms the M4 "No" row is correct after the second commit's fix. ✓
  • CI (.github/workflows/ci.yml) does run go test -tags=ci -skip='E2E|e2e' ./... — the "excludes the e2e suite twice over" claim is accurate. ✓
  • internal/assets/client/README.md already documents the regeneration/verification procedure the new checklist points to (make build-client, direction-not-difference verification, ClientVersion wire-contract note) — the new section correctly defers to it instead of duplicating it. ✓

This is a good example of self-correcting process: the second commit (b7ffd3d) fixed a real error the first commit introduced (claiming M4 regenerates the client bundle, which is false since lvt/components is server-only) — that catch is accurate and the resulting per-milestone table is now correct.

Nits (non-blocking)

  1. PR description says "convention 10"; the plan itself calls this "convention 9." The doc defines convention 9 as "Outline expansion is a milestone's first task... expands its design... before implementation" (line 190/523/525), which is indeed what guarantees a milestone-kickoff session reads the new checklist. Convention 10 in the doc is the separate "auto-position on the progress tracker" rule. Doesn't affect the merged file, but worth fixing in the PR body / commit message for anyone cross-referencing later, since this doc treats convention numbers as load-bearing citations elsewhere.

  2. Table row wording for M2/M3 ("Yes, transitively") is correct but relies on the reader already accepting "no runtime handshake ⇒ server bump obliges client bump" as a hard rule rather than a should. Given how load-bearing this distinction is (it's the entire reason the checklist exists), it might be worth one clause noting the rare counter-case — a livetemplate release that touches only server-side APIs (e.g., Validate() is arguably server-only) and doesn't change ClientVersion at all, in which case M2 could also legitimately land a "No." As written the table reads as an unconditional rule for M2/M3 rather than "check ClientVersion, which so far has always changed." Not wrong today, just slightly overclaimed for a plan doc that otherwise is careful to hedge ("Yes, transitively").

Overall: accurate, well-scoped, and appropriately deferential to #297 rather than scope-creeping browser e2e into this PR. No code changes to review for bugs/security/perf, and no tests are applicable to a docs-only change.

Second review-bot catch on #298, and the same class of error as the
first: "Yes, transitively" for M2/M3 read as an unconditional rule, when
what actually governs is whether the release moves ClientVersion. A
livetemplate release touching only server-side APIs may leave it
unchanged -- Validate() is arguably one -- making M2 legitimately a No.

Reworded both rows to "Check ClientVersion" with the counter-case
spelled out. The distinction is the reason the checklist exists, so
stating it as a rule to look up rather than a conclusion to inherit is
the difference between a session verifying and a session assuming.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018M9pJSPmG6i1D8s6rpEV4h
@adnaan

adnaan commented Jul 19, 2026

Copy link
Copy Markdown
Contributor Author

Taken — same class of error as your first catch, so worth fixing rather than landing.

Reworded both M2/M3 rows from "Yes, transitively" to "Check ClientVersion", with your counter-case stated explicitly: a release touching only server-side APIs may leave the constant unchanged (Validate() is arguably one), making M2 legitimately a No.

That's the right framing anyway — the distinction is the whole reason the checklist exists, and stating it as a constant to look up rather than a conclusion to inherit is the difference between a future session verifying and assuming. Landing after this goes green.

@claude

claude Bot commented Jul 19, 2026

Copy link
Copy Markdown

Review

Docs-only change (plan file), and unusually well fact-checked for a PR like this — I verified the claims against the actual repo rather than just reading the prose, and everything checks out:

Nice to see the commit history shows this already went through two rounds of self-correction from review-bot catches (the M4 blanket-claim bug, then the M2/M3 hard-yes-vs-check distinction) — both fixes are reflected correctly in the final diff.

Minor nits (non-blocking)

  • Heading capitalization is a little inconsistent: #### Standing Audit item for milestones... capitalizes "Audit" but not "item," which doesn't match the sentence-case-with-key-nouns-capitalized pattern used by sibling headings like #### Phase 0 (M0) — Upstream version bump.... Cosmetic only.
  • The new section's checklist items are fairly detailed for something living under "M2–M5 phases — outline only (expanded at milestone kickoff per convention 9)." Worth double-checking that convention 9's "expand design at kickoff" step won't feel like it's re-litigating a checklist that's already fairly prescriptive here — though as a standing cross-milestone audit item (vs. per-milestone design) that's probably the right home for it and this is a judgment call, not a defect.

No code changes, so no functional bugs, performance, or security concerns to flag, and test coverage is N/A for a docs-only PR. Good change — the "why" section in the description (why #297 was deferred rather than pre-empted) is also a useful bit of context to have preserved in the plan itself rather than only in the PR body.

@adnaan
adnaan merged commit 1b63ffd into main Jul 19, 2026
1 check passed
@adnaan
adnaan deleted the docs/m2-provenance-audit branch July 19, 2026 20:22
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.

make build regenerates the committed client bundle from stale node_modules, breaking checkbox e2e tests

1 participant