install.sh --refresh omits packages/core/hooks/package.json ({"type":"module"}) → refreshed pre-push hook crashes on Node ≥22
Summary
The full install ships a hooks-scoped package.json with {"type":"module"} so the shipped packages/core/hooks/pre-push.ts loads as ESM (the #532 fix). The --refresh path (do_refresh) refreshes the hook .ts files but never copies that package.json, so an existing consumer upgraded via install.sh --refresh ends up with the new multi-file pre-push.ts without the type:module marker. On Node ≥22 the hook then dies with the exact require-cycle the marker exists to prevent.
Same class as #531 ("refresh fixed X but left Y") — a do_refresh completeness gap, surfaced while verifying the #551 delivery path (#615) on a real already-installed consumer (timeliner).
Evidence
Full install copies the marker:
install.sh:915 copy_safe "$PKG_ROOT/packages/core/templates/shared/hooks-package.json" \
"$PROJECT_ROOT/packages/core/hooks/package.json"
…with the rationale spelled out right above it (install.sh:908–913): without type:module, the nearest package.json governs; a consumer root with no "type" ⇒ CJS ⇒ tsx's require(esm) bridge hits the Node ≥22 cycle and the hook dies with a stack trace.
But do_refresh only refreshes the .ts + fallback, not the marker:
install.sh:608 echo "▶ Core hooks (TS) → packages/core/hooks/"
install.sh:615 refresh_safe "$PKG_ROOT/packages/core/hooks/$_ts" "$PROJECT_ROOT/packages/core/hooks/$_ts"
install.sh:617-618 refresh_safe ... pre-push.fallback.sh
# no refresh_safe for hooks-package.json → packages/core/hooks/package.json
Observed on timeliner after install.sh --refresh:
packages/core/hooks/pre-push.ts present (refreshed, imports ./checks/*.ts, ./utils/*.ts).
packages/core/hooks/package.json absent.
- Consumer root
package.json has no "type" field.
- Manually writing
packages/core/hooks/package.json = {"type":"module"} (i.e. what install.sh:915 would have shipped) cleared the module-type error.
Suggested fix
Add the marker to do_refresh, mirroring install.sh:915:
refresh_safe "$PKG_ROOT/packages/core/templates/shared/hooks-package.json" \
"$PROJECT_ROOT/packages/core/hooks/package.json"
And/or add a --refresh-completeness test asserting every artefact the full install ships under packages/core/hooks/ is also delivered by do_refresh (would also have caught #531-class gaps).
Environment
- Consumer:
timeliner (Hono+Expo+Drizzle pnpm monorepo), upgraded via install.sh --refresh, framework staging 5d9b330.
- macOS, Node v24.3.0.
install.sh --refreshomitspackages/core/hooks/package.json({"type":"module"}) → refreshed pre-push hook crashes on Node ≥22Summary
The full install ships a hooks-scoped
package.jsonwith{"type":"module"}so the shippedpackages/core/hooks/pre-push.tsloads as ESM (the #532 fix). The--refreshpath (do_refresh) refreshes the hook.tsfiles but never copies thatpackage.json, so an existing consumer upgraded viainstall.sh --refreshends up with the new multi-filepre-push.tswithout thetype:modulemarker. On Node ≥22 the hook then dies with the exact require-cycle the marker exists to prevent.Same class as #531 ("refresh fixed X but left Y") — a
do_refreshcompleteness gap, surfaced while verifying the #551 delivery path (#615) on a real already-installed consumer (timeliner).Evidence
Full install copies the marker:
…with the rationale spelled out right above it (install.sh:908–913): without
type:module, the nearestpackage.jsongoverns; a consumer root with no"type"⇒ CJS ⇒ tsx'srequire(esm)bridge hits the Node ≥22 cycle and the hook dies with a stack trace.But
do_refreshonly refreshes the.ts+ fallback, not the marker:Observed on
timelinerafterinstall.sh --refresh:packages/core/hooks/pre-push.tspresent (refreshed, imports./checks/*.ts,./utils/*.ts).packages/core/hooks/package.jsonabsent.package.jsonhas no"type"field.packages/core/hooks/package.json={"type":"module"}(i.e. whatinstall.sh:915would have shipped) cleared the module-type error.Suggested fix
Add the marker to
do_refresh, mirroring install.sh:915:And/or add a
--refresh-completeness test asserting every artefact the full install ships underpackages/core/hooks/is also delivered bydo_refresh(would also have caught #531-class gaps).Environment
timeliner(Hono+Expo+Drizzle pnpm monorepo), upgraded viainstall.sh --refresh, framework staging5d9b330.