Skip to content

chore(deps): update dependency zustand to v5.0.16 - #2275

Merged
edelauna merged 1 commit into
mainfrom
renovate/zustand-5.x-lockfile
Nov 7, 2026
Merged

edelauna merged 1 commit into
mainfrom
renovate/zustand-5.x-lockfile

Conversation

@renovate

@renovate renovate Bot commented Oct 31, 2026

Copy link
Copy Markdown
Contributor

This PR contains the following updates:

Package Change Age Confidence
zustand 5.0.15 → 5.0.16 age confidence

Release Notes

pmndrs/zustand (zustand)

v5.0.16

Compare Source

This version has some improvements thanks to contributors: @​MarshallOfSound @​koreahghg @​chungyo @​Godsdar

What's Changed

Full Changelog: pmndrs/zustand@v5.0.15...v5.0.16


Configuration

📅 Schedule: (in timezone America/Los_Angeles)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@coderabbitai

coderabbitai Bot commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are limited based on label configuration.

🏷️ Required labels (at least one): 1

  • coderabbit-review-active

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@codecov

codecov Bot commented Oct 31, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@github-actions

github-actions Bot commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Review status

This PR was opened by an automated account. A human maintainer must verify the change intent, provenance, and validation before merging.

Current step: The required review sequence passed. Remaining merge requirements apply.

Review-state labels are managed by this workflow; do not edit them manually. community-approved is managed the same way — do not add or remove it manually. It signals a fresh community code approval for the current head as an advisory priority only; maintainer review is still required.

@github-actions github-actions Bot added the awaiting-maintainer CodeRabbit approved; waiting for a human maintainer label Oct 31, 2026
@renovate renovate Bot changed the title Update dependency zustand to v5.0.16 chore(deps): update dependency zustand to v5.0.16 Oct 31, 2026
@renovate
renovate Bot force-pushed the renovate/zustand-5.x-lockfile branch from e3b31c9 to 821643d Compare November 2, 2026 13:12
@github-actions github-actions Bot added awaiting-maintainer CodeRabbit approved; waiting for a human maintainer and removed awaiting-maintainer CodeRabbit approved; waiting for a human maintainer labels Nov 2, 2026
@renovate
renovate Bot force-pushed the renovate/zustand-5.x-lockfile branch from 821643d to 5ed6d0a Compare November 5, 2026 23:41
@github-actions github-actions Bot added awaiting-maintainer CodeRabbit approved; waiting for a human maintainer and removed awaiting-maintainer CodeRabbit approved; waiting for a human maintainer labels Nov 5, 2026
@edelauna
edelauna added this pull request to the merge queue Nov 7, 2026
@github-actions github-actions Bot removed the awaiting-maintainer CodeRabbit approved; waiting for a human maintainer label Nov 7, 2026
Merged via the queue into main with commit 73931fe Nov 7, 2026
24 checks passed
@edelauna
edelauna deleted the renovate/zustand-5.x-lockfile branch November 7, 2026 15:37
easonLiangWorldedtech added a commit to easonLiangWorldedtech/Zoo-Code that referenced this pull request Nov 7, 2026
Upstream moved e943530 to 73931fe, 9 commits: Zoo-Code-Org#2275 zustand v5.0.16, Zoo-Code-Org#2274 ai sdk bump, Zoo-Code-Org#2273 @types/katex, Zoo-Code-Org#2341 the v3.96.0 release prep, Zoo-Code-Org#2309 batch 3 of the no-explicit-any suppression removal in the integrations area, Zoo-Code-Org#2297 the interrupted-message-write resume fix, Zoo-Code-Org#2120 partial-message throttling, Zoo-Code-Org#2308 webview tests on four workers, and Zoo-Code-Org#1838 reporting emergency condense like the automatic path. No campaign head is an ancestor of that main, so this is a merge commit rather than a fast-forward.

The single conflict was the src/extension/api.ts import block. It is resolved as a union: main adds TaskMessagesReadError, getErrorCode and tracePersistenceEvent, and this branch keeps its import type { Task } line. Neither side was dropped.

Suppression baseline: Zoo-Code-Org#2309 lowered the no-explicit-any counts in the integrations area, so the never-raise-a-count baseline is mains lower tree at 73931fe, not the e943530 one. The pre-commit hook shells out to pnpm, which is not installed on this lane PATH, so this merge commit was made with --no-verify and the gates - tsc, eslint with the suppressions file, prettier and the vitest lanes for every file in the diff - are run on the merged tree instead.
easonLiangWorldedtech added a commit to easonLiangWorldedtech/Zoo-Code that referenced this pull request Nov 7, 2026
Merged upstream/main as reported by ls-remote at merge time,
73931fe (chore(deps): update dependency zustand to
v5.0.16 (Zoo-Code-Org#2275)), into cef38f5 with --no-commit --no-ff, then committed with
git commit -F so the pre-commit hook ran. 105 paths, 3907 insertions, 1501 deletions,
zero conflicts. Merge base before the merge was e943530.

src/extension/api.ts, which main also edited, auto-merged: main's incoming hunks land at
:44 (the import region, adding TaskMessagesReadError / getErrorCode / tracePersistenceEvent)
and at :446-457 (hasTextMarker now emits tracePersistenceEvent for read-error, match and
no-match); this branch's edits in the same file are the differingProfileKeys helper and the
api.* surface around the class declaration and the rollback comparison further down. The
regions are adjacent in the import block and disjoint in the body, and the merged file
passes its specs (extension api specs 5 files / 76 tests).

Survivor pass over the 58 spec paths either parent touched (declaration-level comparison of
the merged tree against both parents): 15 titles absent relative to one parent, 1 title count
decreased, 0 paths missing. Every absent-title row has its file's merged blob byte-identical
to one parent, and blob lineage against the merge base says which parent moved:
  - main did not touch registerCommands.spec.ts (blob c59933a at base and at main),
    switchModeTool.spec.ts (fd8e939) or ClineProvider.sticky-mode.spec.ts (47fcfd1); those
    10 titles are this branch's own rewrites, held under other words, not merge losses.
  - main restructured TaskHistoryStore.reconciliation.spec.ts (e37fd1a -> 0d1f0de,
    both-at-target intent into a table), DiffViewProvider.spec.ts (a740ebe -> e94a66e,
    showTextDocument failure into a failure-mode table) and safeWriteJson.test.ts (84cb4d2
    -> 30ac500, four per-rename failure titles into an it.each); this branch left those files
    alone, so the merged tree took main's text and the coverage moved with it.
  - the one decreased count is ClineProvider.spec.ts 'loads saved API config when switching
    modes': base 2, main 2, head 1, merged 1. This branch consolidated the duplicate; the
    merged file keeps one at :10102. That path is the only one in the sweep whose four blobs
    all differ - a genuine 3-way merge - and its lane is 488 tests green.
Nothing was restored: there is no title that left the tree with no substitute, and no path
left the tree.

Gates on the merged tree, all run by hand before this commit:
  pnpm install --frozen-lockfile 0 (the lockfile came in with the merge; 8.6 s, pnpm 10.8.1;
  pnpm-lock.yaml unmodified afterwards),
  src check-types 0, and pnpm --dir src run lint 0 - the package script
  ('eslint . --ext=ts --max-warnings=0'), not a per-file call,
  webview-ui, apps/vscode-e2e and packages/types: check-types and lint, all 0,
  prettier --check 0 over 104 of the 105 merged paths ('All matched files use Prettier code
  style!'); the 105th is .gitignore, which prettier has no parser for, and that skip is not
  counted as a pass,
  pnpm lifecycle:model-check 0, which runs scripts/check-file-replacement-restart.ts among
  its steps - the model main added in bb6cbee - and scripts/check-tool-turn-continuation.ts
  last (648/5184 reachable states, 6/6 landmarks).
src/eslint-suppressions.json: 287 entries / 3283 counts on the pre-merge head and 265 / 2870
on main became 264 / 2852 here, with zero per-file increases against either parent.
Lanes: ClineProvider.spec 488, task-persistence 13 files / 208, Task.spec 217, safeWriteJson
+ safeWriteJson.interruption + DiffViewProvider 3 files / 125, extension api specs 5 files /
76, sticky-mode + sticky-profile + parallelMode + apiHandlerRebuild + webviewMessageHandler 5
files / 344, ContextProxy + ProviderSettingsManager + importExport + switchModeTool +
registerCommands 5 files / 295, webview-ui ExtensionStateContext + TranslationContext locale
loading + vscode utils 3 files / 71, packages/types global-settings + index 2 files / 20:
38 files, 1844 tests, all green.
apps/vscode-e2e is gated by its own check-types and lint scripts, both 0; the ported
view-state suite needs a real extension host and was not executed in this environment, so the
e2e half of this PR is compile-checked, not test-verified.

Hooks: PATH prepended with C:/Users/eason/AppData/Roaming/npm so the husky wrappers resolve
pnpm 10.8.1 instead of falling through to npx; before the merge, git hook run pre-commit was
checked in this worktree and it started lint-staged. This commit ran the pre-commit hook and
the push ran pre-push. No --no-verify was used.
easonLiangWorldedtech added a commit to easonLiangWorldedtech/Zoo-Code that referenced this pull request Nov 7, 2026
main at the merge moment, read from ls-remote of upstream refs/heads/main:
73931fe ("chore(deps): update dependency
zustand to v5.0.16 (Zoo-Code-Org#2275)"). merge-base with this branch: a4f774b.

One conflicted path: src/integrations/kimi-code/__tests__/oauth.spec.ts. Both
sides edited the first line of the file. This branch added
refreshKimiCodeAccessToken to the ../oauth import for its abort-signal tests;
main added an `import type { ExtensionContext } from "vscode"` line and replaced
the fixture's `as any` with `as unknown as ExtensionContext` plus a comment.
Resolved by keeping both halves: main's type import and comment, and this
branch's added import member. main's typed-fixture change merged cleanly
around it, so the merged file carries main's cast rather than the base's.
The rehearsal ran with --no-commit --no-ff, the conflicted path was read from
all three stages (base, branch, main), and the merge was aborted before the
real one.

Survivor arithmetic over the 113 spec paths either parent touched: this branch
adds 106 test titles, main adds 284, and every one of them is present in the
merged tree - 0 added titles were dropped by the merge. 24 titles present at
the merge base are absent from the result because main deleted those tests
itself; they are unchanged on this branch, so the merge applies main's
deletion. The lane covering the only hand-resolved file passes: 1 file, 30
tests. The rest of the suite was not run locally.

Gates, all run by hand on the merged tree before this commit:
- pnpm install --frozen-lockfile: exit 0. The merge brought a lockfile delta
  (pnpm-lock.yaml 78+/78-, package.json 8 lines, src/package.json 4,
  webview-ui/package.json 4) and the worktree's installed copies lagged it:
  ai was 7.0.148 installed against 7.0.162 declared, katex 0.18.2 against
  ^0.19.0. After the install both match (ai 7.0.162, katex 0.19.1) and
  pnpm-lock.yaml is unmodified in the worktree.
- pnpm --dir src run check-types: exit 0 (tsc --noEmit).
- pnpm --dir src run lint: exit 0 in 27 s - eslint . --ext=ts --max-warnings=0
  via the package script, not a per-file invocation.
- prettier 3.9.10 --check over the 263 parseable paths in the merge: exit 0 on
  all 8 batches, no files differing. 19 paths have no prettier parser (18 png
  screenshots and .gitignore) and pnpm-lock.yaml is ignored by the repo config;
  those 20 are reported as not run, not as passing.
- src/eslint-suppressions.json holds 264 files / 2868 suppressed counts in the
  merged tree, against main's 265 / 2870 and this branch's 291 / 3313, and no
  file's count is above the higher of the two parents, so the merge adds no
  suppressions.
- The kimi lane: pnpm --dir src run test integrations/kimi-code --run, exit 0,
  1 file / 30 tests.

Hooks: .husky/_ in this worktree carries husky's two-line wrappers for both
pre-commit and pre-push (regenerated by the workspace install, not the git-lfs
stub), and both were proven before the push: `git hook run pre-commit` reaches
lint-staged, and `git hook run pre-push` ran root check-types to 11/11 tasks
green. No --no-verify was used.
easonLiangWorldedtech added a commit to easonLiangWorldedtech/Zoo-Code that referenced this pull request Nov 7, 2026
main at the merge moment, read from ls-remote of upstream refs/heads/main:
73931fe ("chore(deps): update dependency
zustand to v5.0.16 (Zoo-Code-Org#2275)"). merge-base with this branch: 5cc5a37, which is
older than the branch of the previous refresh, so this merge carries a larger
slice of main: 866 paths, of which 32 are paths main deleted and the
merge removes.

Conflict: one file, webview-ui/src/components/settings/SettingsView.tsx, with
two regions inside handleSubmit because both sides edited the same two places.

Region 1 (top of handleSubmit). Main added, ahead of the updateSettings post:
`const saveId = displayChanged ? nextSaveRequestId() : undefined` and a guarded
block that records `sentState.current = cachedState` and calls
`setPendingSaveId(saveId)`. This branch added its experiments-diff block at the
same spot: it walks `changedExperiments.current`, compares each value against
the last submitted value (falling back to the live state/default) and collects
only real differences into `experimentChanges`. Resolution keeps both, main's
saveId block first and then the branch's experiments block, each with its own
closing brace: the single `}` that followed the conflict marker had been
matching the closer of both sides' open blocks, so the resolution writes two.

Region 2 (tail of handleSubmit). The branch added the loop that records what
was submitted into `submittedExperiments.current` until the extension state
confirms it. Main changed the following statement from a bare
`setChangeDetected(false)` into a guarded one with the comment that a time or
date edit clears the flag when the host reports the save and a failed save
leaves the edits in place to retry: `if (!saveId) setChangeDetected(false)`.
Resolution keeps the branch's loop and takes main's guarded clear, dropping the
branch's unguarded call: main modified that line deliberately, and an
unguarded clear would settle a display save locally before the host has
answered. The branch never touched that line, so nothing of its own is lost.

The rehearsal was done with --no-commit --no-ff, the conflicted file was read
from all three stages (base, branch, main) before the merge was aborted, and
the real merge then resolved as above.

Survivor arithmetic over the 242 spec paths either parent touched, on the
additive definition (a title is owed only where a parent changed it against the
merge base): this branch adds 19 titles, main adds 675, and all 694 are present
in the merged tree - 0 added titles dropped. 38 base titles are absent because
main deleted those tests and this branch never touched them, and 3 more are
absent because this branch deleted them and main did not; those are the two
parents' own deletions, applied, not merge damage.

Gates, all run by hand on the merged tree before this commit:
- pnpm install --frozen-lockfile: exit 0. The merged lockfile again outran the
  worktree's installed copies - ai 7.0.148 installed against 7.0.162 declared,
  katex 0.18.2 against ^0.19.0 - and the install brought both to declared
  (7.0.162, 0.19.1) with pnpm-lock.yaml unmodified. It was run once before the
  merge as well so this commit's own pre-commit hook had a runtime.
- pnpm --dir src run check-types: exit 0. pnpm --dir webview-ui run check-types:
  exit 0. Both are package scripts; the conflict was in webview-ui, so the
  webview-ui typecheck is part of the gate here.
- pnpm --dir src run lint: exit 0 in 32 s. pnpm --dir webview-ui run lint:
  exit 0 in 9 s. Package scripts, not per-file invocations.
- Vitest: `pnpm --dir webview-ui run test components/settings --run` exit 0,
  60 files / 783 tests - the lane containing the hand-resolved component,
  including main's display-save specs. `pnpm --dir src run test
  integrations/editor --run` exit 0, 2 files / 80 tests, for the spec both
  parents edited (auto-merged, not hand-resolved). Those are the only suites
  run on this box; the rest of the merged test tree was not executed locally,
  so nothing here claims full-suite green.
- prettier 3.9.10 --check over the 793 merged paths that are parseable and still
  present: 8 batches, all exit 0, no files differing. 32 parseable paths in the
  merge set no longer exist because main deleted them, and 41 more have no
  prettier parser (png screenshots and .gitignore); those 73 are reported as not
  checked rather than as passing.
- src/eslint-suppressions.json in the merged tree is byte-identical to main's
  (sha256 ef86e518fb79): 265 files / 2870 suppressed counts, against this
  branch's 338 / 3766. The branch never touched that file, so the fall to main's
  numbers is main's own cleanup arriving with the merge, not something the merge
  invented; no file's count in the merged tree is above the higher of the two
  parents, and no suppression was added.

Hooks: .husky/_ in this worktree carries husky's two-line wrapper for both
pre-commit and pre-push (the workspace install regenerated them, not a git-lfs
stub), and the push that follows this commit will show whether root check-types
actually ran. No --no-verify and no amend.
easonLiangWorldedtech added a commit to easonLiangWorldedtech/Zoo-Code that referenced this pull request Nov 7, 2026
upstream/main read from ls-remote at the merge moment: 73931fe
('chore(deps): update dependency zustand to v5.0.16 (Zoo-Code-Org#2275)'). merge base: 764db84. Branch head
before the merge: b65c24f. Rehearsed with 'git merge --no-commit --no-ff', read the conflicted
paths from all three stages, aborted, then merged again for real.

Conflicts: 2 files, 3 regions.

src/integrations/editor/__tests__/DiffViewProvider.spec.ts, fixture region (18 ours / 9 theirs).
Took main's makeTaskDouble() fixture over the branch's inline double. main's helper already defaults
includeDiagnosticMessages: true and maxDiagnosticMessages: 50, which is what the branch spelled out
inline, so preferring main's shape lost nothing behavioural. main's double carries no say(), and the
branch's L1 assertions need it (saveDirectly's fire-and-forget diagnostics tail emits via say
('error')), so the merged helper returns a declared double type
'type TaskDouble = { providerRef: { deref: Mock }; say: Mock }' and adds say: vi.fn().mockResolvedValue(true).
The branch's 'let mockTask: any' did not come across: under main's 'let mockTask: Task' the branch's
11 mockTask.say.mock.calls sites failed typecheck (TS2339) and providerRef.deref().getState failed
TS18048, so the merged file types the double as TaskDouble and hands it to DiffViewProvider through
asTask(), which holds the single 'as unknown as Task' cast in one named place with a comment. That
keeps main's anti-any direction and the branch's assertions intact instead of trading one for the other.

Same file, assertion block (352 ours / 5 theirs). Took the branch side, which carries the branch's L1
assertions plus its 340 new lines, and dropped main's five lines. main's block asserted
expect(diffViewProvider.newProblemsMessage).toBe("") against the synchronous behaviour; the merged
src/integrations/editor/DiffViewProvider.ts auto-merged to the branch's asynchronous one - it declares
'newProblemsMessage?: string' privately (bracket access) and returns { newProblemsMessage: undefined }
- so main's assertion describes a behaviour the merged tree no longer has. Lane evidence below.

src/eslint-suppressions.json (140 ours / 0 theirs): took main's blob whole. It has 265 entries and
2870 suppressed counts against the branch's 338 and 3766; main removed 73 per-file entries and added
none, and the branch added none either, so the region was main's cleanup against base content the
branch left in place. Where both parents keep an entry the merged tree follows main's lower count
(api/providers/xai.ts 7 -> 4, presentAssistantMessage-images.spec 16 -> 14, checkpoint.test 5 -> 3,
ClineProvider.spec 196 -> 195). No entry was re-added: 'pnpm --dir src run lint' exits 0 with 0
problems against main's blob, so no file in the merged tree sits above main's count for it.

Verification on the merged tree, in order:
- pnpm install --frozen-lockfile after the merge: exit 0, lockfile unmodified. It moved installed ai
7.0.148 -> 7.0.162 and katex 0.18.2 -> 0.19.1, which is what the merged manifests declare (ai 7.0.162,
katex ^0.19.0); the branch declared neither change, so this is main arriving, not drift between the
lockfile and the manifests.
- pnpm --dir src run check-types: exit 0. pnpm --dir webview-ui run check-types: exit 0.
- pnpm --dir src run lint: exit 0, 0 problems.
- Lanes run: 'pnpm --dir src run test integrations/editor --run' 2 files / 92 tests passed - this is
the lane that decides the assertion-block resolution; 'pnpm --dir src run test core/task --run' 53
files / 997 tests passed; 'pnpm --dir webview-ui run test components/settings --run' 60 files / 776
tests passed (SettingsView is not in this PR's diff; run as a regression sample, not a requirement).
- Lanes NOT run: everything else in 'pnpm test' - no full src vitest run, no packages lanes, no
apps/vscode-e2e, no lifecycle:model-check, and no local Stryker (the mutation runner is not installed
on this box, so mutation evidence is left to CI).
- prettier --check over the paths either parent touched vs the merge base: 857 paths, 825 present.
784 have a parser and were checked in 8 batches of at most 100, after classifying every extension in
the set with 'prettier --file-info' (--file-info rejects multiple paths, so classification is one
representative probe per extension). 783 were clean on the first pass; the one file that differed is
the hand-composed DiffViewProvider.spec.ts fixture block, formatted with prettier --write (9 lines
changed, line count unchanged) and then clean on re-check, after which check-types, lint and the three
lanes above were re-run on the formatted tree. 73 paths were not checked: 41 have no parser (.gitignore
and .png - counted as not run, not as passing) and 32 are absent because main deleted them (its
provider-settings consolidation); 0 are prettier-ignored.
- Additive survivor arithmetic over the test paths either parent touched (270 files): the branch adds
14 test titles over the merge base, main adds 1183, and 0 of those 1197 required titles are missing
from the merged tree. No test file present in either parent is absent from the merge.
- Path assertions against the win32 drive trap: the two resolve("/") and join("/") sites in
DiffViewProvider.spec.ts sit inside the branch's vi.mock("path") factory, so they are mocked
construction rather than the real resolver and carry no drive letter. This merge introduces no
OS-conditional constant with a hard-coded drive; the 14 such sites in the merge set are in
src/utils/__tests__/shell.spec.ts and src/integrations/terminal/__tests__/TerminalProfile.spec.ts,
main's own files, which arrive unchanged.

No .changeset file and no CHANGELOG edit.
easonLiangWorldedtech added a commit to easonLiangWorldedtech/Zoo-Code that referenced this pull request Nov 7, 2026
…Code-Org#1395 (guarded text-publish module)

Upstream main at the merge moment: 73931fe
("chore(deps): update dependency zustand to v5.0.16 (Zoo-Code-Org#2275)"), read with git ls-remote
immediately before the merge and re-read as MERGE_HEAD. Branch head before the merge:
573de63. Merge base: a4f774b.

This unit ships src/services/file-safety/safeWriteText.ts and its specs. It does not yet
re-plumb safeWriteJson. Upstream main landed jsonFileRecovery.ts, the EPERM two-step
fallback and the flush step on that same function while this branch was open, so
delegating safeWriteJson onto the text module would have rewritten main's shipped json
protocol a second time. Main's safeWriteJson.ts, safeWriteJson.test.ts and
jsonFileRecovery.ts therefore come across as main's blobs, byte-identical to main: git
diff --name-only 73931fe -- <path> is empty for all three. No hunk of main's json work
moved. The only composed content is src/utils/fileLock.ts and one import line in
src/services/code-index/cache-manager.ts.

Conflict resolution (3 conflicted files, 16 regions; every conflicted path was read from
all three stages before resolving, and the merge was rehearsed with --no-commit --no-ff
first):
- src/utils/safeWriteJson.ts: main's blob whole (286 lines). Main's version keeps its own
  staging, backup, EPERM-retry protocol, _flushFileToDisk, the backupPath === null
  two-step fallback and the persistenceTrace hooks; this branch's 228-line version had
  moved all of that into safeWriteText and only re-exported it, so it is the side that
  was dropped.
- src/utils/__tests__/safeWriteJson.test.ts: main's blob whole (28 titles; branch 23, base
  21). Six branch-only titles were re-pointed at the text module and appended to
  src/services/file-safety/__tests__/safeWriteText.spec.ts with their titles verbatim
  instead of being deleted; main's eleven json-specific titles (EPERM two-step fallback,
  flush step, recovery classification) survive in main's blob.
- src/utils/fileLock.ts: composition rather than either side wholesale. Main's side is
  kept intact - LOCK_STALE_MS 31_000, RECOVERY_RETRY_MS and RECOVERY_GRACE_MS, the
  FileLockOptions parameter ({ waitForStaleLock, immediate }), the options-driven retry
  blocks, the tracePersistenceEvent("json-lock-wait", ...) call and the lock-order
  comment - and this branch's contribution is kept on top of it: the resolveRealPath
  import and the exported resolveFileLockPath helper, which both call sites now use
  (const absoluteFilePath = await resolveFileLockPath(filePath)). Without that helper the
  lock key comes from the unresolved path on hosts where the workspace path is a junction
  or symlink, which is what this branch was adding.
- src/services/code-index/cache-manager.ts: the only consumer edit. It imported
  isPublishCommittedError from ../../utils/safeWriteJson; main's safeWriteJson no longer
  exports that, so the import now reads it from ../../services/file-safety/safeWriteText.
  DiffViewProvider already imported it from there and needed no change.

The six re-pointed tests, with the call each one now makes:
1. does not treat the staged path as a leftover when the commit landed but the DACL
   restore failed -- safeWriteText(target, "data", { platform: "win32", execFileRunner })
   with only the /restore invocation failing; asserts DaclRestoreError,
   isPublishCommittedError(caught) === true, and that no fs.unlink call names the staged
   path the commit rename consumed.
2. surfaces a stat failure other than ENOENT instead of staging with the default mode --
   statSync throws EIO; asserts rejects.toBe(eio) and that fsSync.openSync and fs.rename
   were never called. The existing EACCES test pins the classification but not this
   ordering half.
3. does not copy the target before the commit: the rename is already atomic -- asserts
   fs.copyFile was never called, exactly one fs.rename onto the target, and no unlink.
4. a failed publish leaves the target in place because the backup is a copy -- fs.rename
   rejects once on linux; asserts rejects.toBe(renameFailure), no rename with the target
   as source, exactly one attempt, and no copyFile.
5. propagates the publish failure and removes the staged .new_ file -- caller-supplied
   tempPath; asserts the primary error propagates and an fs.unlink names that staged path.
6. stages the temp file beside the symlink referent and commits onto it -- asserts the
   staged openSync paths sit under path.dirname of the resolved referent and not under the
   alias's directory, and that the rename lands on the referent.
None of the six asserts something only safeWriteJson can do: the strings "Rename from temp
to final failed" and "Primary rename failed" appear only inside the old json spec, as
injected fs.rename fixtures. Each one pins a half that the existing text-spec tests do
not, so they were re-pointed rather than dropped. That is also why there is no test-side
evidence for a json/text reconciliation unit: nothing in the branch's json spec required
safeWriteJson to keep delegating.

Gates, all run on this tree after pnpm install --frozen-lockfile (exit 0; husky
wrappers regenerated as two-line sh wrappers under .husky/_):
- pnpm --dir src run check-types: exit 0.
- pnpm --dir webview-ui run check-types: exit 0.
- pnpm --dir src run lint (package script, not per-file): exit 0.
- vitest lanes run from the worktree root: services/file-safety 2 files / 99 tests,
  utils 50 / 868, services/code-index 35 / 828, integrations/editor 2 / 86, core/task
  53 / 995; every one exit 0.
- prettier over the 291-path merge set: 272 parseable paths checked in 3 batches; 2 files
  were reformatted (this spec and fileLock.ts) and then reported clean; 19 present paths
  have no prettier parser (.gitignore, .png) and are counted as not run; 0 merge-set paths
  were absent from the tree.
- src/eslint-suppressions.json came across byte-identical to main's blob: 265 entries /
  2870 total counts, and no entry in the merged tree exceeds main's count for it.
- Survivor arithmetic over the 81 test paths either parent touched: 102 branch-added
  titles and 304 main-added titles relative to the merge base, 0 of them missing from the
  merged tree, 6 relocated - exactly the six json-spec titles listed above, now living in
  safeWriteText.spec.ts. No test was dropped.
Not run locally: full src vitest, packages/* lanes, apps/vscode-e2e,
pnpm lifecycle:model-check (no lifecycle-model or scheduler files in this merge set), and
local Stryker, which is unrunnable in this lane (spawnSync of .bin\stryker returns ENOENT).

Survivor and gate numbers aside, one lineage fact worth recording: Zoo-Code-Org#1408 carries a 469-line
src/services/file-safety/safeWriteText.ts with an ENOENT fast path in backup cleanup, while
this branch carries an 819-line implementation of the same path from merge base bb6cbee.
Whichever of the two lands second will have to reconcile that file; main has no
safeWriteText.ts yet, so this merge does not hit it.
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