Cutting v0.3.0 surfaced a real gap: the GitHub Release asset (sql.html, built by release.yml's fresh npm install) is not byte-identical to the artifact built locally and deployed to the three demo clusters, despite both being built from the exact same commit (3cab9fd) and carrying the same build stamp (v0.3.0 (3cab9fd)).
Root cause: package-lock.json is gitignored by project convention, so every npm install re-resolves the full dependency tree fresh. The four bundled runtime deps (CodeMirror 6, Chart.js, dagre, signals-core) were identical in both builds (checked via npm ls), but a transitive dependency — @kurkle/color (a Chart.js dependency) — resolved to 0.3.4 in the local install and 0.4.0 in the CI install (registry latest as of the release), because Chart.js's own declared range apparently allows both and nothing pins it. Confirmed via npm view @kurkle/color version.
Impact: low for this specific case (isolated to Chart.js's internal color-parsing helper — diff was 4 tiny hunks inside one minified <script> block, nothing in the app's own logic or the other three deps). But the general problem stands: the "GitHub Release asset == what's deployed == what a local build reproduces" invariant that's been relied on for release verification since v0.1.5 (see the deploy-sql-browser-demo-clusters memory notes) can silently break whenever any transitive dependency ships a new version between two npm install runs, with no warning.
Options to consider (not resolved in this pass — deployed clusters and local build are internally consistent with each other, just diverged from the newly cut GitHub Release asset for v0.3.0):
- Commit
package-lock.json (reverses the current no-lockfile convention — trades drift risk for the usual lockfile-staleness tradeoffs).
- Accept the drift as a known limitation of intentionally always picking up the latest transitive-dep patches, and drop/soften the "byte-identical" release-verification claim in docs/memory.
- Pin
@kurkle/color (and audit other transitive deps of the four approved runtime deps) explicitly in package.json overrides.
Filed as inbox — deferred rather than fixed now since it doesn't block v0.3.0 (the three clusters are correctly in sync with each other and with main), and the fix is a deliberate call on the no-lockfile convention that's out of scope for a routine release cut.
Cutting v0.3.0 surfaced a real gap: the GitHub Release asset (
sql.html, built byrelease.yml's freshnpm install) is not byte-identical to the artifact built locally and deployed to the three demo clusters, despite both being built from the exact same commit (3cab9fd) and carrying the same build stamp (v0.3.0 (3cab9fd)).Root cause:
package-lock.jsonis gitignored by project convention, so everynpm installre-resolves the full dependency tree fresh. The four bundled runtime deps (CodeMirror 6, Chart.js, dagre, signals-core) were identical in both builds (checked vianpm ls), but a transitive dependency —@kurkle/color(a Chart.js dependency) — resolved to0.3.4in the local install and0.4.0in the CI install (registry latest as of the release), because Chart.js's own declared range apparently allows both and nothing pins it. Confirmed vianpm view @kurkle/color version.Impact: low for this specific case (isolated to Chart.js's internal color-parsing helper — diff was 4 tiny hunks inside one minified
<script>block, nothing in the app's own logic or the other three deps). But the general problem stands: the "GitHub Release asset == what's deployed == what a local build reproduces" invariant that's been relied on for release verification since v0.1.5 (see the deploy-sql-browser-demo-clusters memory notes) can silently break whenever any transitive dependency ships a new version between twonpm installruns, with no warning.Options to consider (not resolved in this pass — deployed clusters and local build are internally consistent with each other, just diverged from the newly cut GitHub Release asset for v0.3.0):
package-lock.json(reverses the current no-lockfile convention — trades drift risk for the usual lockfile-staleness tradeoffs).@kurkle/color(and audit other transitive deps of the four approved runtime deps) explicitly inpackage.jsonoverrides.Filed as
inbox— deferred rather than fixed now since it doesn't block v0.3.0 (the three clusters are correctly in sync with each other and withmain), and the fix is a deliberate call on the no-lockfile convention that's out of scope for a routine release cut.