Commit Graph
26126 Commits
Author SHA1 Message Date
sjw1231 ffde355ab7 refactor(jobs,terminal): import HarnessError from dsh-error
JobError and TerminalError only need the error base, so dsh-jobs and
dsh-terminal depend on dsh-error instead of the LLM runtime. The Python
SDK runtime closure includes the new package.

Refs #7869
2026-11-05 21:40:22 +08:00
sjw1231 71cb6c739a refactor(error): move HarnessError to the dependency-free dsh-error package
dsh-llm depends on dsh-attachment and dsh-typert-protocol, so classes in
those packages could not extend a base defined in dsh-llm without a
project-reference cycle. HarnessError now lives in @deepseek-ai/dsh-error,
which has no dependencies; dsh-llm declares it as a peer and re-exports
the same class, so existing imports and instanceof checks keep working.
The Agent Note records why the original leaf-package placement no longer
holds.

Refs #7869
2026-11-05 21:26:38 +08:00
sjw1231 09604ac04d refactor(tools): tighten cancellation, approval, and job error contracts
Type the approval denial helper with a closed ApprovalErrorCode, state
that a cancellation is recognized by the signal reason or an Error named
AbortError, note that ApprovalError names a denial rather than a thrown
class, and separate JOB_CONTROLLER_UNAVAILABLE from a missing jobs
service. The jobs README describes JobError as the seam's export rather
than as current caller behavior, and the terminal test asserts one
concurrent send failure.

Refs #7869
2026-11-05 20:21:45 +08:00
sjw1231 ecae589b38 fix(repeat-tool-reminder): keep a downstream block's error info
The reminder rebuilt a downstream post-execute block from its feedback
and contexts, which would drop the block's new optional info. It now
spreads the downstream decision, so a blocked call keeps its structured
error identity when the reminder fires.

Refs #7869
2026-11-05 20:16:44 +08:00
sjw1231 3368b86e2c refactor(tools): keep approval and context codes off the plugin entry
The plugin entry may export only Loader fields and Service or Error
classes, so the ApprovalError and ToolContextUnavailableError code
constants move to an internal module; the recorded strings are
unchanged.

Refs #7869
2026-11-05 20:12:48 +08:00
sjw1231 a964c739d2 Merge remote-tracking branch 'origin/master' into refactor/tool-errors-foundation 2026-11-05 20:00:51 +08:00
Ruilin Geng dd06371929 feat(gates): 禁止插件入口新增值导出 (#7860)
* feat(gates): reject value exports on function plugin entries

A function plugin entry may export only the Loader fields (name, inject,
Config, apply), types, and classes whose instances extend Cordis Service or
Error, as docs/defensive-patterns/package-surface.md requires. The new
verify-plugin-entry-exports gate reads every packages/*/*/src/index.ts that
exports a value apply through the Host and then the Client compiler face,
and rejects any other value export, including a default export beside
apply, values that arrive through export *, and exports that do not resolve.

Exports that predate the gate are listed per package in
scripts/plugin-entry-existing-exports.ts. A listed export passes; a line
fails when its package has no function plugin entry, its list is empty or
repeats a name, or it names an export the entry no longer reports.

* docs(gates): mark new existing-export lines as rule exceptions

A line added to scripts/plugin-entry-existing-exports.ts after the gate's
introduction is an exception under the plugin entry rule in
docs/defensive-patterns/package-surface.md, which requires the domain
owner's confirmation.

* fix(gates): report a default export beside apply even when it is a class

The class allowance also covered the default export, so a function plugin
entry that default-exported a class extending Cordis Service or Error beside
apply passed the gate. The Loader then loads that default export instead of
the module namespace, which is the mixed plugin form the rule forbids. A
default export beside apply is now reported whatever it holds.

* fix(gates): judge plugin entry exports by their run-time export paths

The gate read TypeScript's export table, which differs from what the entry
exports at run time in two forms. An `export type { x }` hid a value that
`export *` brings in under the same name, although the type-only export is
erased and the value stays. A name that a nested `export type *` reaches was
reported as a value, although nothing reaches the entry at run time.

The gate now walks the emitted export forms: type-only exports and declare
declarations emit nothing, a re-export emits only a run-time export of its
target, and `export *` brings in every run-time name of its target except
default and the names the module exports itself. An `export *` whose module
does not resolve is reported as `*`.

* feat(gates): check service plugin entries for value exports

The plugin entry rule in docs/defensive-patterns/package-surface.md covers
both entry forms: a function plugin exports the Loader fields, a service
plugin default-exports its plugin class, and beyond those a Host entry may
export only Service Definition classes and error types. The gate checked
only function plugins, so a value on a service plugin entry, which another
package imports past the Loader row just the same, went unreported, and an
entry could escape the gate by default-exporting a class.

An entry without apply whose default export is a class the Loader can
construct is now a service plugin. Its default class passes under any name,
as do types and classes extending Cordis Service or Error; name, inject,
Config, and every other value are reported. Libraries, a default export
that is not a class, and an abstract default class, which defines a
capability seam, stay unchecked. The corpus guard now requires both forms.

The existing-export list is regenerated to cover the service plugin
entries' current value exports.

* fix(gates): admit the plugin entry export list as a plugin record name

The plugin entry export list now records the session service entry's
existing value exports, appendPluginRecord among them. Like the published
dependency policy, the list names the function without calling it, so the
plugin record caller gate admits it.

* chore(gates): list the plugin entry exports that landed on master

Master gained value exports on the plugin-manager, llm, and subagent
service entries and renamed office-to-pdf to office-kit before the gate
lands. They predate the gate, so the existing-export list records them.
2026-11-05 11:11:05 +00:00
winewill 46bf9a9d44 Merge pull request #7887 from deepseek-harness/fix/windows-workspace-first-paint
Fix white flash on Windows dark workspace startup
2026-11-05 19:05:23 +08:00
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
brickmaker be1c087a77 Merge pull request #7969 from deepseek-harness/docs/desktop-uninstall-cache-cleanup
docs(desktop): 完善桌面端卸载清理脚本
2026-11-05 18:09:29 +08:00
winewill 0d6212f0f6 test(snapshots): align terminal panel runtime context reminder 2026-11-05 18:09:21 +08:00
brickmaker 001f153172 docs(desktop): refine uninstall cleanup paths 2026-11-05 17:54:51 +08:00
Yichen Jiang 5e602b4116 Merge remote-tracking branch 'origin/master' into worktree/archive-session-worktrees 2026-11-05 17:54:42 +08:00
Yichen Jiang bf1c5aa0c7 fix(snapshots): refresh terminal-panel-tools for runtime context reminders (#7968)
#6699 recorded terminal-panel-tools with the old runtime context text, and #7321 then wrapped runtime context in <system-reminder>. The keyless refresh changes only that user-message text in session.v4.jsonl.
2026-11-05 17:53:43 +08:00
Turtle 03e70034e6 refactor(agent-preset): consolidate creator skills into dsh-doc (#6633)
* feat(release): publish package source, declaration maps, and documentation

Every release member publishes its TypeScript source and the declaration
maps that resolve into it, and @deepseek-ai/dsh publishes the repository
Markdown documentation staged from docs/ at prepack time.

The ./src/* export most members already declared now resolves for an
installed consumer, and a consumer editor follows a declaration to the
implementation. Bundled JavaScript maps stay unpublished; the vendored
family and the Desktop runtime file policy are unchanged.

Rationale: .agents/notes/implemented/process/2026-10-08-published-source-and-docs.md

* feat(release): publish JavaScript maps and compress bundles

Every emitted JavaScript map ships beside the bundle it describes, and the
workspace build and the client preset compress bundles without mangling
identifiers.

The documentation payload now mirrors the website publication manifest and
is removed again by `postpack`; Desktop and the Python executable exclude
the published source, documentation, and maps; `clean` removes a staged
copy. Typert's publication contract gains the Remote declaration map.

* fix(release): keep node bundles readable for the worker image

The browser worker image lowers `yield*` only as a whole statement and
rewrites `for await` loops by their source layout, so compressed node-side
entries either fail that lowering or lower to unparseable code. Only the
browser bundles keep compression, which removes about a third of their text.

The bundle-purity assertion now matches the module-loader call regardless of
the quote style compression picks, and the release-pack fixture exercises
the installed package's new documentation requirement.

* feat(release): publish the whole documentation tree

`@deepseek-ai/dsh` copies `docs/` in full instead of the website's page
set: the maintainer documents, the generated migration records, the
translation guidelines, and the `*.i18n.yaml` consistency records ship
with the installed package, so the documentation's own links resolve
without a checkout.

* feat(release): publish the upgrade guides with the documentation

The staged documentation keeps the website's page set and adds every
`docs/upgrade-guide/` document, which is what an installed reader consults
when a released change breaks something. The rest of the maintainer tree
stays out.

* feat(agent-preset): ship plugin artwork skill with creator mode

* docs(skills): clarify artwork icon lookup and official review steps

* refactor(agent-preset): fold plugin artwork into cordis plugin development

* feat(agent-preset): require detail documents for creator bundles

* test(release): expect source and maps in master's new payload cases

* refactor(agent-preset): consolidate creator skills into dsh-doc

* feat(release): keep installed docs and source readable in Desktop

Desktop keeps the published src/ and docs/ trees inside app.asar, and
every model shell call receives DSH_INSTALL_DIR and DSH_NODE_EXECUTABLE
so an agent can read them through Electron's Node mode. Staging also
generates docs/upgrade-guide/README.md, an index of the upgrade guides
grouped by the release they upgrade from.

Minified client bundles print string literals with backticks: the
worker image packer now recognizes those chunk requests, client license
banners are prepended after minification so their text survives, and
the affected artifact tests accept either quote.

* docs(agent-preset): add dsh-doc install, upgrade, and fallback guidance

* docs(agent-preset): align dsh-doc archive reads and upgrade start versions

* docs(agent-preset): bound dsh-doc upgrade index reads and test documented commands

* test(desktop): read archived docs through the Windows PowerShell form

Regenerate the config catalog for the shifted shell-env source line.

* docs(upgrade-guide): correct dsh-doc session verification step

* test(agent-preset): use a block body for dsh-doc fixture cleanup

* test(desktop): wait for the GUI-subsystem Electron process from PowerShell

* docs(agent-preset): read the running DSH version from the installation

* build(release): publish source and maps from the message-quotes package

* docs(agent-preset): document the verified PowerShell runtime invocation

* docs(agent-preset): keep PowerShell runtime output streams and exit code

* docs(tool-cordis): describe the shipped dsh-doc skill

* docs(skills): load configuration guidance separately

* fix(skills): declare shared template details in every locale

* fix(skills): verify dsh-doc guidance through recorded sessions

* test(skills): retain current runtime reminder in dsh-doc replay

* test(snapshot): refresh terminal panel runtime context
2026-11-05 17:53:22 +08:00
sjw1231 43408f9d1a docs(module-graph): record jobs and terminal dependencies on dsh-llm
JobError and TerminalError extend HarnessError, so dsh-jobs and
dsh-terminal now depend on dsh-llm.

Refs #7869
2026-11-05 17:52:28 +08:00
Yichen Jiang 54be750f26 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 17:28:24 +08:00
Yichen Jiang f880228060 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.
2026-11-05 17:28:23 +08:00
sjw1231 1b2cac01e4 feat(jobs): add JobError with closed job failure codes
The jobs Service Definition now exports JobError, a HarnessError whose
code is one of JOB_ERROR_CODES, so job registries and job-backed tools
can report background, ownership, and limit failures with routable
codes. The stacked per-area refactors adopt it.

Refs #7869
2026-11-05 17:07:42 +08:00
sjw1231 3f3e9caeae feat(tools): add ToolContextUnavailableError for missing call context
Tool bodies that lack a calling Agent, an injected service, or an open
turn get one shared HarnessError with the TOOL_CONTEXT_UNAVAILABLE
code, instead of each tool throwing a plain Error. The stacked
per-area refactors adopt it at their call sites.

Refs #7869
2026-11-05 17:07:42 +08:00
sjw1231 3b9f88dd2e refactor(terminal): make TerminalError a HarnessError
TerminalError already carried a stable code but extended Error, so
terminal tool failures persisted without error.name and error.code.
It now extends HarnessError with the same name, codes, and constructor.

Refs #7869
2026-11-05 17:07:42 +08:00
sjw1231 3d8d0ba95c feat(tools): let guard denials and post-execute blocks carry error info
A ToolGuard may return a ToolGuardDenial with optional ToolErrorInfo,
and a post-execute block may supply info; the registry records it on
the failed result. checkGuards now returns the normalized denial.
String guards and blocks without info keep their existing results.

Refs #7869
2026-11-05 17:07:42 +08:00
sjw1231 7e180cfd70 feat(tools): attach ApprovalError codes to approval denials
An ask that approval does not grant now denies with ApprovalError and
APPROVAL_REJECTED, APPROVAL_CANCELLED, or APPROVAL_UNAVAILABLE, so a
user rejection is routable on tool/result like other structured
failures. Model-facing reasons are unchanged.

Refs #7869
2026-11-05 16:56:27 +08:00
Yichen Jiang 200e6a8f4a Merge remote-tracking branch 'origin/master' into worktree/archive-session-worktrees
# Conflicts:
#	snapshots/session/worktree/session.v4.jsonl
2026-11-05 16:52:49 +08:00
sjw1231 fc6afa97fe fix(tools): classify cancellation thrown by a started tool body
A started tool body that throws the signal's reason or an AbortError
without HarnessError identity now keeps its message and carries
AbortError / ABORTED, so the cancellation is routable like the
registry's own cancellation results. HarnessErrors and distinct
failures that settle during cancellation stay unchanged.

Refs #7869
2026-11-05 16:51:42 +08:00
Yichen Jiang 481641b1b9 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.
2026-11-05 16:51:29 +08:00
winewill 5e17999f78 docs(desktop): describe current startup theme behavior 2026-11-05 16:51:25 +08:00
winewill d456f6c58b fix(theme): preserve boot preference during client initialization 2026-11-05 16:51:25 +08:00
winewill ac60dc5188 Read startup appearance from Host settings instead of a theme cache 2026-11-05 16:51:25 +08:00
winewill 327aeefca1 Update welcome startup theme mock for native appearance events 2026-11-05 16:51:25 +08:00
winewill 21ebc61074 Restore desktop theme before startup and track Windows background changes 2026-11-05 16:51:25 +08:00
winewill c174e33a1b Paint the Windows workspace with its startup theme before the first frame 2026-11-05 16:51:25 +08:00
流光 1c63ff48be Merge pull request #7642 from deepseek-harness/fix/macos-scrolled-content-window-drag
fix(client): 修复 macOS 滚动内容遮挡标题栏拖动
2026-11-05 16:38:10 +08:00
_Kerman a773ebb233 Merge pull request #7321 from deepseek-harness/xtr/runtime-context-reminders
fix(context): frame runtime reminders and track prior snapshots
2026-11-05 16:35:17 +08:00
imccyu a98f470d75 Merge pull request #7928 from deepseek-harness/feat/markdown-fence-slots
feat(ui-chat): dispatch Markdown fences by language through a keyed hoc slot
2026-11-05 16:29:15 +08:00
Yichen Jiang bde500ecc2 Merge pull request #6699 from deepseek-harness/feat/agent-terminal-panel-tools
feat(terminal): run Agent terminal tools in visible Web sidebar terminals
2026-11-05 08:28:44 +00:00
brickmaker 5991a206e4 docs(desktop): add unified uninstall cleanup guide (#7878)
* docs(desktop): add unified uninstall cleanup guide

* docs(desktop): address uninstall guide review fixes

* docs(desktop): restore original cleanup commands and desktop labels

* docs(desktop): clarify optional cleanup and simplify guide

* docs: remove desktop uninstall link from development guide
2026-11-05 08:19:27 +00:00
Xinyu Yang 873e36e18f refactor(client): unify window drag exclusion attribute 2026-11-05 16:15:59 +08:00
Yichen Jiang f2b7de9ac9 test(snapshots): refresh creation-recommendations for the terminal bundle's new description
The personalized-pages skill lists official plugins with their localized
descriptions; only the persistent terminal bundle's description changes.
2026-11-05 16:15:08 +08:00
Yichen Jiang e43486ff63 test(terminal-panel): cover the backend's current-policy lookup without a real shell
Windows CI skips the real-shell integration test, which was the only
caller of the spawned session's current-policy closure, so backend.ts
fell below the per-file coverage gate there. A backend test now sends on
a spawned session after the Session policy changes.
2026-11-05 16:15:08 +08:00
Xinyu Yang 596bd317d6 docs: move window drag upgrade guide to current version 2026-11-05 16:09:52 +08:00
_Kerman 03cd147c2c Merge origin/master into xtr/runtime-context-reminders 2026-11-05 15:55:01 +08:00
Turtle 74f74c927e Merge pull request #6702 from deepseek-harness/feat/plugin-index-metrics
feat(plugin-market): clarify index order and add popularity metrics
2026-11-05 15:50:41 +08:00
Xinyu Yang 630cd17b86 fix(client): simplify window drag exclusions and coverage 2026-11-05 15:40:38 +08:00
Xinyu Yang 30eeaeca28 fix(client): handle macOS window drag review findings 2026-11-05 15:40:38 +08:00
Xinyu Yang 5d47fb39c2 fix(client): isolate macOS window regions from scrolled content 2026-11-05 15:39:27 +08:00
turtle1999 20d38e784b chore: integrate current master for pre-merge validation 2026-11-05 15:35:26 +08:00
_Kerman 1807de9bc9 test(python): recognize runtime reminders in permission assertions 2026-11-05 15:34:48 +08:00
_Kerman e4544c5854 Merge origin/master into xtr/runtime-context-reminders 2026-11-05 15:24:14 +08:00
_Kerman beb5186e36 Merge origin/master into xtr/runtime-context-reminders 2026-11-05 15:23:36 +08:00