Skip to content

0.4.0: build-output seeding, pub/sub tag propagation, cluster e2e, init/doctor CLI, MCP server - #7

Merged
leejpsd merged 13 commits into
mainfrom
next/0.4
Aug 2, 2026
Merged

0.4.0: build-output seeding, pub/sub tag propagation, cluster e2e, init/doctor CLI, MCP server#7
leejpsd merged 13 commits into
mainfrom
next/0.4

Conversation

@leejpsd

@leejpsd leejpsd commented Jul 31, 2026

Copy link
Copy Markdown
Owner

Summary

The 0.4.0 core roadmap plus agent-optimization Phases 2–3, held as a draft for final approval per the release plan (docs/release-checklist-0.4.0.md).

  • Build-output cache seeding (/seed + `nextjs-cache-handler seed`): NX-protected inserts of prerendered routes (incl. PPR segment maps), Pages routes, and fetch-cache. Verified on the real demo app: cold server's first request = `x-nextjs-cache: HIT`.
  • `tagPubSub` (opt-in): push-based cross-instance tag propagation — 3ms measured over real Redis (both clients), scan polling retained as the consistency net.
  • Redis Cluster e2e: real 3-master cluster suite (Lua/CROSSSLOT, per-master SCAN, ISR, pubsub fallback) + new CI job — removes the "unit-tested only" caveat.
  • `init`/`doctor` CLI (zero-dep): version-aware wiring, idempotent rules injection, Redis diagnostics.
  • MCP server package (`mcp/`, unpublished): 7 tools, dry-run-first invalidation, stdio smoke + live-Redis verified.

Test evidence

Unit 153 · integration 25 (real Redis) · cluster 5 (real 3-master) · real-app seeding e2e · MCP stdio/live smokes. Core stays zero-dependency.

Release plan on approval

See docs/release-checklist-0.4.0.md — merge → two-phase release workflow → npm 0.4.0 via trusted publishing; MCP 0.1.0 first publish needs one manual `npm publish` (new package can't pre-configure trusted publishing).

🤖 Generated with Claude Code

leejpsd and others added 13 commits August 1, 2026 02:57
Zero-dependency bin (node builtins; Redis via the package's own adapters).
init: Next-version detection (15 → ISR only, 16.1+ → both handlers), shim
generation with the detected client type, next.config guidance (guidance
only — the file is never auto-edited), .env.example append, idempotent
marker-based rules injection into CLAUDE.md/AGENTS.md, optional local skill
install. doctor: ping/latency, next-* key bucket counts, write/read
round-trip; stable [ok]/[warn]/[action]/[error] prefixes for agent parsing.
Phase 2 of the agent-optimization plan.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
seedBuildOutput() reads prerender-manifest.json and seeds App Router routes
(html/rsc/meta plus complete PPR segment maps — partial segment sets are
skipped as unsafe), Pages Router routes, and fetch-cache entries into Redis
as the exact records the incremental handler serves (revalidateSec included
so soft-SWR works on seeded entries; tags carried via meta headers so
invalidation applies). Writes use SET NX so live instances' newer entries
always win. Exposed as /seed and a CLI 'seed' command (redis→ioredis
fallback). Validated end to end: demo app's real build seeded 15 routes +
1 fetch entry; a cold server's FIRST request returned x-nextjs-cache: HIT.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
updateTags publishes {tags, ts} on <keyPrefix>inval:<ns>; each instance
lazily subscribes on a dedicated duplicate connection (redis@5 duplicate +
subscribe, ioredis duplicate + message events) and merges timestamps into
its local mirror monotonically. Subscription failures retry with a 5s
cooldown and never surface to callers — the refreshTags scan remains the
consistency safety net, so pub/sub only ever buys latency. Cluster clients
(no duplicate-based subscribe wired) disable it with a single warning.
Measured cross-instance propagation over real Redis: 3ms on both client
types, vs ~2.1s end-to-end with scan-only propagation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
scripts/cluster-test-env.sh spins up a local 3-master cluster (no docker);
tests/cluster covers set-with-tags and revalidate-hard Lua under CROSSSLOT
constraints with hashTag slotting, refreshTags via the per-master
scanIterator, cross-handler soft propagation, tagPubSub's graceful cluster
fallback, and the ISR handler round-trip. Wired as npm run test:cluster and
a dedicated CI job (apt redis-server, no containers). README cluster claims
upgraded from 'unit-tested only' to e2e-tested.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…hed)

Standalone MCP server (stdio, runs locally against the user's Redis — no
hosting) giving agents structured cache operations: cache_health,
cache_search, cache_inspect (record decode incl. compression markers),
tag_state (both layers), explain_key, simulate_swr, and invalidate_tag
(dry-run unless confirm: true; publishes on the tagPubSub channel when
executing). Verified via a real stdio JSON-RPC smoke (7 tools listed) and
live tool calls against real Redis (health ping, ISR tag state read,
dry-run plan). Separate package so the core keeps zero runtime deps.
NOT published yet — first publish requires user action (see release
checklist).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… document 0.4 features in skill/api docs

Two overlapping gated ops could both pass the active check and open two
duplicate subscriber connections, leaking one. An attempting flag makes the
subscription attempt single-flight. SKILL.md and docs/api.md gain the 0.4
surface (seed command/entry point, tagPubSub, doctor/init, MCP pointer) so
the 0.4.0 tarball ships accurate agent guidance.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
BLOCKER fixes: seeding now skips PPR routes carrying postponed resume state
(a seeded copy would freeze the unresolved shell as final HTML); both
adapters tear down the duplicate connection when SUBSCRIBE fails (an ACL
without channel permissions previously leaked one connected duplicate per
5s retry — ~17k/day toward maxclients) and report connection death via a
new onDown callback so pubsub.active un-latches and the retry path
re-establishes. Also: seedBuildOutput closes redis@5 clients (dispose on
adaptRedisV5 — programmatic callers no longer hang); getImpl folds
memTagExp into tag freshness (publisher-clock skew could get a pushed
timestamp dropped by the scan rebuild's carry-over); pub/sub message
handler prunes the mirrors; CLI seed gains --namespace/--key-prefix/
--hash-tag/--compression plus key-shape output (config mismatches were
silently seeding unreadable keys) and error-parity on the ioredis path; ISR
readTagStates uses per-key GETs instead of a cross-slot MGET that CROSSSLOT-
failed multi-tag entries on Cluster; route-handler outputs get their own
seed counter; init writes .mcp.json (registers the MCP server, never
clobbers an existing file). release.yml gains a publish_mcp dispatch input
using the same trusted-publisher workflow identity. 4 blocker regression
tests added (158 unit total).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tion

HASH_TAG env mirrors the handler option: marker reads/writes, namespace
discovery (braces preserved), and the pubsub channel now match {ns}-braced
key shapes — previously every 'use cache' operation silently missed for
Cluster deployments while reporting success. cache_inspect guards with
STRLEN (>2MB → sizes/TTL only) and bounds zlib output (16MB) against
decompression bombs. Agent-supplied tags are glob-escaped in SCAN patterns;
explain_key parses un-namespaced ISR tags containing colons; invalidate_tag
reports warnings when no use-cache namespace was found and documents its
non-atomic hard mode. Verified with a live braced-marker probe.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@leejpsd
leejpsd marked this pull request as ready for review August 2, 2026 05:26
@leejpsd
leejpsd merged commit 30d385f into main Aug 2, 2026
6 checks passed
@github-actions github-actions Bot mentioned this pull request Aug 2, 2026
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.

1 participant