feat: multi-instance session lease, write fencing, and fs/watch reliability#1920
Open
7Sageer wants to merge 5 commits into
Open
feat: multi-instance session lease, write fencing, and fs/watch reliability#19207Sageer wants to merge 5 commits into
7Sageer wants to merge 5 commits into
Conversation
🦋 Changeset detectedLatest commit: d1ff815 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
commit: |
7Sageer
force-pushed
the
refactor-fs-watch
branch
from
July 19, 2026 14:01
a030953 to
3d7ffc7
Compare
…bility Single-instance reliability: - Journal: preserve content on write failure with sticky JournalStorageError, per-batch fsync, last-header open, and zero-write cold reads - Broadcaster: writeFailure gate, deterministic dispose drain, replay failure now triggers resync_required; graceful close ordering in start.ts - fswatch: per-connection monotonic seq, pinned truncated semantics, and gitignore double-cache invalidation; __global__ session made volatile Cross-process lock unification: - agent-core-v2 CrossProcessLockService: parameterized lock modes (heartbeat-TTL implemented), token-guarded release/update, rename-isolated stale takeover, creation window, PID-reuse detection (conservative on macOS) - config.toml and workspace registry locked read-modify-write; mcp.json watch - kap-server lock protocol aligned (lock_id, process_started_at, three-layer stale detection); minidb release ownership fixed, legacy cleanup removed Multi-instance session ownership (gated by multi_server flag): - Session leases with write fencing; 40921 SESSION_HELD_BY_PEER with typed details (routable/creating/holder-unresponsive/held-by-local-instance) and unregistered-writer detection; write-authority registry hard gate in AppendLogStore, session metadata, and flush paths - kimi-web redirect to the holder with pending approvals/questions replay; klient transparent redirect with loop guard - session.list_changed cross-instance discovery via two-layer fs watch; ownership field on GET /sessions Stale-write fencing and skill hot reload: - Session file ledger + agent file fencing: hard gate with the flag on, advisory note with it off; dirty-tick signals from fs watch - Skill root watcher hot reload: catalog reload, turn-boundary listing reminder, and skill_catalog.changed volatile event to web clients
7Sageer
force-pushed
the
refactor-fs-watch
branch
from
July 19, 2026 14:28
3d7ffc7 to
56f1a5a
Compare
…lock Per-session flock is now held for the entire time a server hosts a session, making the kernel the single arbiter of ownership: process death releases the lock, so heartbeats, TTL-based stale takeover, and pid liveness probing are no longer needed. owner.json is reduced to a redirect hint (instance address), written atomically after acquire. - add @moonshot-ai/kernel-file-lock (fs-ext-extra-prebuilt; flock on unix, LockFileEx emulation on windows) - crossProcessLockService shrinks to try-acquire/checkHeld/release - minidb lockfile adopts the same flock-held semantics - delete processProbe
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Related Issue
No linked issue — the problem is explained in the next section.
Problem
With
kimi websharing one home across servers (#1826), several kap-server instances can now run against the sameKIMI_CODE_HOME— but session journals, config files, workspace registry, and minidb stores had no cross-process coordination: journal appends could interleave, config writes could clobber each other, a second writer could delete a live lock, and clients had no way to discover or reach the instance actually holding a session.Single-instance operation also had correctness gaps of its own: a failed journal write could silently lose session events, the fs/watch layer went stale on
.gitignorechanges and issued per-server (not per-connection) sequence numbers, replay failures surfaced as silent gaps, and server shutdown ordering was nondeterministic.What changed
Single-instance reliability
JournalStorageError) instead of being silently dropped; per-batch fsync; open reads the last valid header; cold reads perform zero writes.readSincethrows), deterministic dispose drain, replay failure now triggersresync_required; deterministic, idempotent server close ordering instart.ts.truncatedsemantics (clients rebuild baseline via REST),.gitignoredouble-cache invalidation; the__global__session is now fully volatile; the host fs watcher filters special files (sockets/fifos/devices) so one unwatcherdable entry cannot poison a whole directory watch.Cross-process lock unification
agent-core-v2gainsCrossProcessLockService: heartbeat-TTL (fd keepalive) and TTL modes, token-guarded release/update, rename-isolated stale takeover, creation window, PID-reuse detection via process start-time identity (conservative on macOS where the identity is unavailable).config.tomland the workspace registry now do locked read-modify-write with on-disk format preserved;mcp.jsongains a watch.renew().Multi-instance session ownership (behind
KIMI_CODE_EXPERIMENTAL_MULTI_SERVER)40921 SESSION_HELD_BY_PEERwith typeddetails(routable/creating/holder-unresponsive/held-by-local-instance) plus unregistered-writer detection; a write-authority hard gate rechecks the lease inside AppendLogStore, session metadata, and flush paths.SessionRedirectChannel+KlientConnection).session.list_changedvolatile hint via two-layer fs watch, and anownershipfield onGET /sessions.klient/test/e2efollowing feat(klient): contract-driven facade with http/ipc/memory transports #1768) covering double-open refusal with journal integrity, SIGSTOP/SIGCONT non-takeover, andkill -9dead takeover with rename isolation.Stale-write fencing and skill hot reload
skill_catalog.changedvolatile event pushed to web clients.Verification
tsctypecheck across agent-core-v2, kap-server, klient, protocol, minidb, kimi-web, node-sdk; full package test suites for all of the above, including the relocated dual-instance e2e.Known limitations and follow-ups
session.list_changedrelies on fs event delivery. On macOS (chokidar 4 without native fsevents), directory notifications can be coalesced and held under multi-instance fs load (a >45s stall was observed in an in-process dual-instance test; the e2e pins determinism with a test-side tree kicker). The hint is volatile and self-healing — clients re-pull on focus/reconnect, and theownershipjoin onGET /sessionsis the authoritative path — so this is a freshness degradation, not a correctness hole. Follow-up: a slow readdir reconciliation loop inSessionListWatchService; Linux (inotify) behavior is unverified.sysctlOID used on Linux).session.journal_write_failed,file.stale_conflict) are defined but not yet wired to an appender.skill_catalog.changed(node-sdk is in-process; there is no WS event surface to forward) — web clients get it.server.close()steps can hit their 5s/10s timeouts when the disk is saturated by a preceding heavy suite). Every affected file passes in isolation (68/68 in the exact failing files); the sensitivity comes from the new fsync-heavy durability paths and is worth a dedicated hardening pass.Checklist
gen-changesetsskill, or this PR needs no changeset.gen-docsskill, or this PR needs no doc update (the multi-instance behavior is behind an experimental flag; no user-facing docs to update yet).