Files
deepseek-harness/docs
Yichen Jiang cf09012892 feat(worktrees): reclaim safe UI checkouts when archiving sessions (#7403)
* feat(worktrees): clean up safe UI checkouts when sessions are archived

* refactor(workspace): share archive notice registration

* refactor(session-query): return observation sessions directly

* docs(worktrees): align archive guide and client catalog after merge

* refactor(worktrees): move archive cleanup into the worktree service

The worktree service now records each checkout it creates as a
`plugin:worktree/created` record, folds them in its own `worktree`
projection with fork-aware ownership, and reclaims a clean, unreferenced
checkout when the Session that created it is archived. The Forge panel
reads the service's record and forwards its cleanup state; it no longer
writes a `created` record, owns a retention projection, or gates every
Session's directory access.

Admission registers the attempt inside the Workspace write queue and
returns; inspection runs afterwards, reading cold Sessions through the
projection cache when mounted and from their log otherwise, with subagent
children of an archived ancestor counted as archived. Only a path being
removed holds `working-directory/access`, whose request now carries the
access's `signal`, and listeners withdraw before the drain. Ignored files
no longer retain a checkout, matching Git's non-force removal; processes
and terminals are not consulted.

The Forge bundle mounts one `worktree` service: the `forge-worktree` row
and the `optional-forge-panel` group that isolated a second service are
gone, and `forge-panel` is a top-level row. `canRemove`, `remove`, the
`forgeWorktreeRetention` projection, and `ForgeWorktreeCleanup` are
removed; `WorktreeService.cleanupOf`, `WorktreeCleanup`, and the
`worktree/cleanup` Host event replace them. The upgrade guide moves to
the current version directory and covers the id removals.

* docs(worktrees): move the archive upgrade guide to v0.2.2-rc.1 and wrap a test line

* test(worktrees): satisfy the static and consumer gates

Move the removal step into `removal.ts` as `removeCheckout`, so the specs
drive the real function and intercept it through a module mock instead of
reaching a private method through an assertion to unknown. Classify
`CREATED_RECORD` as a peer-required Host export for the Forge panel, ship
the compiled `lib/types/*.js` that the `./types` subpath names, refresh the
worktree recorded session with the creation record the service now writes,
and regenerate the module graph.

* refactor(worktrees): share the creation record schema with the Forge panel

The worktree package owns `createdWorktreeSchema`, the validator of its
`plugin:worktree/created` payload; the Forge projection imports it instead
of redeclaring the same object.

* test(web): refresh the Forge plugin card golden for the single worktree row

The card lists six components: the isolated `forge-worktree` row is gone.

* build(worktrees): pin zod to the unified 4.6.6

master unified every zod declaration on 4.6.6, so the worktree package's new
dependency follows it and the lockfile resolves again under --frozen-lockfile.

* test(worktrees): cover every reclamation path for the per-file gate

Drop the dead branches CI's coverage lane found: the placeholder trailing
slash in `within`, the aborted-lifetime check in `schedule`, the rejection
arm of a task that never rejects, and the undefined arms of the cold reads.
`cleanupOf` re-reads the attempt after waiting, so a cold Session without
creations settles to null instead of a stale placeholder. Removals of one
path never overlap, so `remove` keeps one entry per path without chaining.

New cases: a cold Session without creations, a borrower that appears
between inspection and the locked recheck, a subagent child with an unknown
parent, a creation record whose payload fails validation, a live fork that
moved out of the checkout, a cached cold Session without a directory, the
Forge projection ignoring a creation without an open request, the Remote
with and without the service, and the client's removed follow-up.

* feat(worktrees): add the retain-on-archive switch

`retainOnArchive`, a volatile field of the worktree service's Config, skips
cleanup admission while it is on; it is read at each archive, so a change
applies to later archives only. The service keeps its instance off the
generated Settings pages, and the Forge client draws the switch as the
`plugins.row.config` page of the bundle's `worktree` row, staged through
the shared Plugins form until one explicit save.

Docs: the worktree, Forge, and bundle READMEs, the archive-worktrees
upgrade guide, the config and client catalogs, and the
explicit-worktree-creation note.

* docs(module-graph): record the worktree service's settings dependency

`gen-module-graph --check` failed on CI after the retain-on-archive switch
declared `@deepseek-ai/dsh-settings`; regenerate the graph.

* test(snapshots): refresh terminal-panel-tools for master's runtime-context reminder

Master's #7321 wrapped the runtime-context snapshot in a `<system-reminder>`
after this fixture was last refreshed, so `test:snapshot` fails on master's
own tree; refresh the one user message so the replay matches.
2026-11-05 18:10:06 +08:00
..
…