Skip to content

feat(editor): route the diff-view save through the guard (U8, #1375) - #1916

Open
easonLiangWorldedtech wants to merge 22 commits into
Zoo-Code-Org:mainfrom
easonLiangWorldedtech:fws/u8-diffview-guarded-save
Open

easonLiangWorldedtech wants to merge 22 commits into
Zoo-Code-Org:mainfrom
easonLiangWorldedtech:fws/u8-diffview-guarded-save

Conversation

@easonLiangWorldedtech

@easonLiangWorldedtech easonLiangWorldedtech commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Split unit U8 of #1833, under the plan on this issue (5993969784 / 5994039786 / 5994053776). Base is U8 (#1918) per the merge order.

Scope (one gate scope): the interactive save path — saveChanges() publishes through the guard, a rejected save cleans up only its own placeholder and tab, and one teardown path owns a cancelled save.

Content source of record: kind: commit, base 7c291bb08 → head 6768ccfaf, replayed on the current main tip 9af61f87e so this branch carries nothing that main already has.

Budget (own delta, not the stacked view): 2542 a+d / 486 changed executable lines. 2542 a+d is above the 1000 hard cap — documented deviation: the file's 2056-line spec is a single file whose tests are interleaved across the behaviours, and splitting it would move tests away from the behaviour they prove.

Verification at this head: 130 passed; ESLint --max-warnings=0 clean on every file in the unit; Prettier clean; src/eslint-suppressions.json never increased.

The GitHub view also carries the unmerged base, so the numbers above are this unit's own delta.

@coderabbitai

coderabbitai Bot commented Oct 5, 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
  • Configuration used: Repository: Zoo-Code-Org/Zoo-Code/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 2580cff2-4daa-4378-9287-dd12a371114f

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
  • Autopilot · 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

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the has-conflicts PR has merge conflicts with the base branch label Oct 5, 2026
@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Review status

Thanks for contributing. This comment tracks the review sequence and the next action.

Current step: Fix the failing required CI checks; awaiting-maintainer requires CI and automated review completion.

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.

@easonLiangWorldedtech
easonLiangWorldedtech force-pushed the fws/u8-diffview-guarded-save branch from ed27ffe to a7df0c2 Compare October 5, 2026 12:35
…ve (U1, issue 1375)

Split unit U1 of PR 1833. Three changes, each with a test that fails without it:
- a caller-supplied staging path is checked for location and file type before anything is written, so an arbitrary path or a symlink cannot be published onto the target;
- a failed parent-directory fsync on POSIX is reported as PostCommitDurabilityError instead of being swallowed, so a successful return never claims durability the filesystem did not grant;
- the staged file and this write's own staging directory are released before RollbackFailureError is thrown.

Focused coverage for resolveLockKey added: canonical parent directory, a dangling-link chain, and termination at the bounded depth on a two-link cycle.
@easonLiangWorldedtech
easonLiangWorldedtech force-pushed the fws/u8-diffview-guarded-save branch from a7df0c2 to a6a3ce3 Compare October 5, 2026 12:55
…ishTarget (U1, issue 1375)

The resolver may fall back to the given path only when lstat also reports the path as absent. An EACCES or EIO failure says nothing about whether the path is a link, so falling back would publish through a link we were not allowed to inspect. Focused tests added for both branches.
@easonLiangWorldedtech
easonLiangWorldedtech force-pushed the fws/u8-diffview-guarded-save branch from a6a3ce3 to 2d6d158 Compare October 5, 2026 13:16
easonLiangWorldedtech added 2 commits October 5, 2026 22:30
… type-sound

compile failed at the unit head on three points:
- RollbackFailureError needs a string backupPath, but the throw now happens after cleanup, so the
  `string | null` narrowing was lost. The failure is now held as { error, backupPath }.
- The async lstat stand-in is built on the Stats prototype so it satisfies fsSync.Stats.
- The realpath/readlink mocks are typed to the real signatures; the readlink mock answers once
  because only the link path is read.

tsc clean, 50 tests pass, ESLint --max-warnings=0 clean, no suppression change.
@easonLiangWorldedtech
easonLiangWorldedtech force-pushed the fws/u8-diffview-guarded-save branch from 2d6d158 to d749d72 Compare October 5, 2026 14:39
easonLiangWorldedtech added 6 commits October 5, 2026 22:47
The any usage this entry covered is gone in the rewritten file, so the count drops 4 -> 3.
eslint --prune-suppressions --max-warnings=0 confirms it.
The read tools record the observed on-disk version through task.observationRegistry, but the field
was only declared in a later unit, so at this head the call dereferences undefined and the mocked
e2e run fails on the read_file smoke tests. The registry is introduced by this unit, so the field
belongs here.

tsc clean on this unit, 11 observationRegistry tests pass, ESLint --max-warnings=0 clean.
The two any usages this entry covered are gone in the rewritten spec, so the count drops 98 -> 96.
eslint --prune-suppressions --max-warnings=0 confirms it.
@easonLiangWorldedtech
easonLiangWorldedtech force-pushed the fws/u8-diffview-guarded-save branch from d749d72 to 5e72ea6 Compare October 5, 2026 14:52
@github-actions github-actions Bot removed the has-conflicts PR has merge conflicts with the base branch label Oct 5, 2026
U6's ApplyPatchTool calls saveChanges with the writeKind argument, so the parameter must exist
before U6 can build. U8 owns that signature, so U8 now lands before U6.
@easonLiangWorldedtech
easonLiangWorldedtech force-pushed the fws/u8-diffview-guarded-save branch from 5e72ea6 to 45b7912 Compare October 5, 2026 15:13
@codecov

codecov Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Same four apply_diff tests 404 on the mock server here while the identical code passes e2e at U7 and U9.
easonLiangWorldedtech added 2 commits October 6, 2026 02:49
This unit was rebuilt from the pre-fix content source, so its copy of safeWriteText.ts
still restored the backup over a write whose commit rename had already succeeded when
the parent-directory fsync failed.

Unit 1 (fws/u1-atomic-publish) already fixes this. Taking the file here keeps the
shared code byte-identical across the units, so merging the chain in order does not
overwrite unit 1's fix.

Tests: 52 passed in safeWriteText.spec.ts.
@easonLiangWorldedtech

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor
⚠️ Action not completed

Review rate limited.

easonLiangWorldedtech added 7 commits October 6, 2026 03:44
safeWriteJson rethrows RollbackFailureError and the telemetry callers record only
error.message, so the generic wrapper message lost the filesystem errno text of the
publish failure. Include the publish error message while keeping the rollback context
(publishError, rollbackError, backupPath) unchanged.

Tests: 52 passed in safeWriteText.spec.ts, ESLint clean with --max-warnings=0.
… rollback failure

The assertion accepted any rmdir argument, so a regression that removed a different
directory still passed. Read this write's own staging directory from fsSync.mkdirSync
and assert that exact path.

Tests: 52 passed in safeWriteText.spec.ts, ESLint clean with --max-warnings=0.
The dump path was the fixed sibling <target>.acl.tmp. A pre-existing user file at that
path is unlinked by the failed-save branch and by both cleanup paths, and two concurrent
writes to the same target share one dump, so one write can restore or delete the other's.
Use the per-write unique name like the staging file.

Tests: 52 passed in safeWriteText.spec.ts, ESLint clean with --max-warnings=0.
…he other eight units of the same chain with the same guard behaviour

This branch has not been deployed

No deployments
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