Summary
deno.lock on main is out of date: packages/fresh/deno.json declares a direct dependency on @fresh/plugin-vite@^1.1.2, but the lock contains only the workspace-member dependency line and none of that declaration's resolution closure. deno ci --prod therefore fails frozen, which blocks the release path.
This is a release blocker. It failed v0.0.6-canary.3 before any tag or publish.
Evidence
release-canary.yml run 31600415045, step 6 "Cut ephemeral canary branch and tag":
error: The lockfile is out of date. Run `deno install --frozen=false`, or rerun with `--frozen=false` to update it.
error: Uncaught (in promise) Error: deno ci --prod failed with exit 1.
Steps 7–19 were skipped, so no canary version was minted, nothing was published, and no JSR publish attempt was consumed. Step 4 (JSR budget) had already passed. Only v0.0.6-canary.1 and .2 exist, and no ephemeral release/canary-* branch remains.
Root cause
main@5705aeb19 carries exactly one lock line for the new dependency:
"jsr:@fresh/plugin-vite@^1.1.2", # under the packages/fresh workspace member
but no top-level specifier resolution. Regenerating with the repo-pinned Deno 2.9.5 produces the deterministic closure — 386 insertions, 9 deletions — including the direct specifiers jsr:@fresh/plugin-vite@^1.1.2, npm:@babel/core, npm:@prefresh/vite, npm:@remix-run/node-fetch-server, npm:@types/babel__core, npm:rollup, npm:vite, plus jsr:@fresh/core@2, jsr:@deno/loader@0.4, @std/dotenv, @std/fmt, @std/media-types, and the derived Babel/Vite transitive graph. With that closure, deno ci --prod passes.
How it happened — recorded so the rule is right next time
During #1459 the same closure appeared as uncommitted churn (+385/-9) written by a new client-bundle test fixture's real vite build. It was diagnosed as incidental harness churn because its composition (Babel/Vite/Rollup/Preact resolver entries) looks exactly like build-toolchain noise, and it was reduced to the single workspace-member line as the "exact minimal delta".
That diagnosis was wrong in substance. The churn was not a side effect of running a build — it was the required closure of the newly declared packages/fresh dependency, which the build happened to trigger. Adding --no-lock to the fixture then stopped the regeneration, so the incomplete lock reached main and looked settled.
The generalisable lesson: when a manifest gains a direct dependency, the lock delta is whatever deno install deterministically produces for it — "minimal" is not a target to hand-tune toward, and a one-line delta under a workspace member is a symptom of an incomplete lock, not evidence of a clean one.
Acceptance criteria
Provenance
0.0.6 runtime lane, 2026-08-12. Canary.3 run 31600415045; source main@5705aeb19 (#1558).
Refs #1459.
Summary
deno.lockonmainis out of date:packages/fresh/deno.jsondeclares a direct dependency on@fresh/plugin-vite@^1.1.2, but the lock contains only the workspace-member dependency line and none of that declaration's resolution closure.deno ci --prodtherefore fails frozen, which blocks the release path.This is a release blocker. It failed
v0.0.6-canary.3before any tag or publish.Evidence
release-canary.ymlrun31600415045, step 6 "Cut ephemeral canary branch and tag":Steps 7–19 were skipped, so no canary version was minted, nothing was published, and no JSR publish attempt was consumed. Step 4 (JSR budget) had already passed. Only
v0.0.6-canary.1and.2exist, and no ephemeralrelease/canary-*branch remains.Root cause
main@5705aeb19carries exactly one lock line for the new dependency:but no top-level specifier resolution. Regenerating with the repo-pinned Deno 2.9.5 produces the deterministic closure —
386 insertions, 9 deletions— including the direct specifiersjsr:@fresh/plugin-vite@^1.1.2,npm:@babel/core,npm:@prefresh/vite,npm:@remix-run/node-fetch-server,npm:@types/babel__core,npm:rollup,npm:vite, plusjsr:@fresh/core@2,jsr:@deno/loader@0.4,@std/dotenv,@std/fmt,@std/media-types, and the derived Babel/Vite transitive graph. With that closure,deno ci --prodpasses.How it happened — recorded so the rule is right next time
During #1459 the same closure appeared as uncommitted churn (
+385/-9) written by a new client-bundle test fixture's realvite build. It was diagnosed as incidental harness churn because its composition (Babel/Vite/Rollup/Preact resolver entries) looks exactly like build-toolchain noise, and it was reduced to the single workspace-member line as the "exact minimal delta".That diagnosis was wrong in substance. The churn was not a side effect of running a build — it was the required closure of the newly declared
packages/freshdependency, which the build happened to trigger. Adding--no-lockto the fixture then stopped the regeneration, so the incomplete lock reachedmainand looked settled.The generalisable lesson: when a manifest gains a direct dependency, the lock delta is whatever
deno installdeterministically produces for it — "minimal" is not a target to hand-tune toward, and a one-line delta under a workspace member is a symptom of an incomplete lock, not evidence of a clean one.Acceptance criteria
deno.lockonmaincontains the complete deterministic closure ofpackages/fresh's declared@fresh/plugin-vite@^1.1.2dependency, generated with the repo-pinned Deno 2.9.5deno ci --prodpasses frozenv0.0.6-canary.3is re-dispatched from the correctedmainSHA and reaches terminal greenProvenance
0.0.6 runtime lane, 2026-08-12. Canary.3 run
31600415045; sourcemain@5705aeb19(#1558).Refs #1459.