Compare commits

...
Author SHA1 Message Date
Turtle 477b4f4205 Merge pull request #5180 from deepseek-harness/rel/dsh-0.1.7-rc.2
release(dsh): 0.1.7-rc.2
2026-09-24 21:39:59 +08:00
turtle1999 787b746b80 release(dsh): 0.1.7-rc.2 2026-09-24 21:24:26 +08:00
Turtle f9564a0d48 Merge pull request #5175 from deepseek-harness/turtle/disable-shipped-schedule
feat(web): disable shipped schedule and time context plugins
2026-09-24 20:55:39 +08:00
Turtle f84891eaff Merge pull request #5150 from deepseek-harness/fix/auto-review-user-approval
fix(auto-review): ask the user after a denial and report reviewer failures
2026-09-24 20:48:39 +08:00
turtle1999 374b9cc1fb test(web): align shipped composition fixtures with disabled scheduling 2026-09-24 20:41:51 +08:00
Yichen Jiang 24f28dfdb6 Merge pull request #5173 from deepseek-harness/worktree/model-selection-background-save
fix(session): save default model settings in the background
2026-09-24 20:31:25 +08:00
turtle1999 cad6fef2fd feat(web): disable shipped schedule and time context plugins 2026-09-24 20:27:14 +08:00
Xu Hanxiang 4ef97b92a9 Merge pull request #4827 from deepseek-harness/fix/truncate-without-splitting-surrogates
fix(tools): keep surrogate pairs intact when capping tool output
2026-09-24 20:16:49 +08:00
Turtle c92c72eb46 Merge pull request #5165 from deepseek-harness/turtle/atomic-write-exited-lock-takeover
fix: take over a writer lock whose holder exited, and wait for its pnpm run
2026-09-24 20:11:31 +08:00
Yichen Jiang e786c3f74a test(web): await background model preference saves 2026-09-24 20:08:56 +08:00
Turtle 1afcc03ff9 Merge pull request #5174 from deepseek-harness/revert-4868-reconciled-pr4839-ux-evidence
Revert "feat: reconcile timed questions with legacy default"
2026-09-24 20:06:41 +08:00
Turtle 32905d5ab5 Revert "feat: reconcile timed questions with legacy default" 2026-09-24 20:06:09 +08:00
mektpoy ea3667175d Merge remote-tracking branch 'origin/master' into fix/truncate-without-splitting-surrogates 2026-09-24 20:03:02 +08:00
Turtle 6e45fd5bea Merge pull request #4500 from deepseek-harness/fix/windows-directory-junction
fix(workspace-files): list directory links through their resolved target
2026-09-24 19:58:39 +08:00
imccyu a64eaf0b5e Merge pull request #4868 from deepseek-harness/reconciled-pr4839-ux-evidence
feat: reconcile timed questions with legacy default
2026-09-24 19:56:56 +08:00
Turtle 1bd3df926d fix(plugin-manager): wait for a pnpm run its exited operation left behind
Review found three ways the takeover could let two writers overlap.

- A claimant that read an exited PID could remove the lock of a new
  holder that reused that PID before the claim. The claimant now probes
  the PID again under the claim, after re-reading the record.
- The browser Worker's process shim reports its own PID as absent, so a
  second writer in the Worker took over the first one's live lock. A
  record naming the contender's own process is never taken over.
- Takeover proves only that the holder exited, while a pnpm run it
  started can still be writing the profile. Each profile operation now
  records its pnpm run in .plugin-manager/run.json and removes the record
  when the run ends; an operation that finds a record waits for the run
  within the existing tree bound and otherwise refuses, naming the
  process and the record, without running pnpm.

A failed removal of the exited holder's lock now waits instead of
failing the acquisition, the probe range is stated as int32, and the
tests inject exited PIDs instead of reusing real ones, which Windows
reissues at once.
2026-09-24 19:55:41 +08:00
turtle1999 0a134ef94e fix(auto-review): localize the approval prompt and sync docs with the ask fallback
The tools pipeline's ask decision now carries an optional displayReason
that ToolRuntime forwards to the approval service, so the Auto review
prompt is localized while the audited reason stays English.

Adds the auto-review-approval Web snapshot for a user rejection after a
reviewer denial and for a reviewer failure, and updates the permission
preset pages, READMEs, Agent Notes, and child-agent JSDoc that still
described the shared never bundle.
2026-09-24 19:54:37 +08:00
Yichen Jiang 86331673d9 fix(session): save default model settings in the background 2026-09-24 19:48:49 +08:00
Magolorandimccyu a56d2bf2ff fix(user-questions): reset projection version and use brand utility
Co-authored-by: imccyu <[email protected]>
2026-09-24 19:43:16 +08:00
Magolorandimccyu 652bc9d396 fix(user-questions): align styles and cover wait cleanup
Co-authored-by: imccyu <[email protected]>
2026-09-24 19:43:16 +08:00
Magolorandimccyu bb19061473 feat(user-questions): support timed waits and late replies
Co-authored-by: imccyu <[email protected]>
2026-09-24 19:43:16 +08:00
turtle1999 74f85e177e Merge remote-tracking branch 'origin/master' into fix/windows-directory-junction
# Conflicts:
#	.agents/notes/implemented/architecture/2026-09-05-workspace-files-service.i18n.yaml
#	.agents/notes/implemented/architecture/2026-09-05-workspace-files-service.md
#	.agents/notes/implemented/architecture/2026-09-05-workspace-files-service.zh.md
#	packages/api/workspace-files/README.i18n.yaml
2026-09-24 19:41:46 +08:00
Turtle fb018e3e7a Merge pull request #5159 from deepseek-harness/fix/profile-bundle-skip-once
fix(boot): report skipped profile bundles once per start
2026-09-24 19:41:11 +08:00
imccyu b16b1eaea8 Merge pull request #5117 from deepseek-harness/ihsiang/shortcut-sidebar-polish
feat(web): refine shortcut editing and sidebar hints
2026-09-24 19:38:09 +08:00
Turtle c8631b2064 Merge pull request #5109 from deepseek-harness/refactor/trim-tool-constraint-descriptions
refactor(tools): trim constraint prose from tool descriptions
2026-09-24 19:34:54 +08:00
Turtle 6d5b3e8c23 Merge pull request #5156 from deepseek-harness/turtle/model-select-pending-spinner
feat(ui-model-selection): show a spinner while a model selection is pending
2026-09-24 19:34:15 +08:00
Turtle 7bd17809e3 Merge pull request #5163 from deepseek-harness/turtle/fix-issue-3390-dfb901b523d2
feat(ui-tool): link the collapsed web fetch URL
2026-09-24 19:25:41 +08:00
Turtle 6dbf4ab6c9 docs(notes): name the kernel lock the Session lease already holds on Windows
The takeover note said no Windows binding exists for a kernel-released lock; the Session write lease already holds a named semaphore there through koffi.
2026-09-24 19:25:36 +08:00
Yudong Han 8e816b7ea4 Merge pull request #5167 from deepseek-harness/deps/libreoffice-kit-0.1.1
chore(deps): upgrade LibreOffice Kit to 0.1.1
2026-09-24 19:22:18 +08:00
turtle1999 0a6de62671 refactor(boot): derive skipped bundles only from Profile.skippedBundles
skippedProfileBundles recomputed the selected-minus-loaded bundle set from
the manifest, a second home for what loadProfileDirectory already records.
Runtime resolution and generateConfigSchema now read
profile.skippedBundles, so generateConfigSchema no longer reads the profile
manifest and drops its binName parameter.
2026-09-24 19:19:52 +08:00
Yichen Jiang a5309122f4 Merge pull request #5011 from deepseek-harness/worktree/voice-setup-navigation
feat(voice-input): guide unready microphones to plugin setup
2026-09-24 19:16:33 +08:00
Yichen Jiang 193f9ce413 fix(llm): keep oversized request extensions from blocking model requests (#5168)
Optional request extension fields had no size bound. A very large field
could exceed the runtime's string limit while the request was serialized,
which failed every attempt, including retries.

- Bound the extension payload carried by one request (8 MiB by default,
  configurable) and send the remainder with later requests.
- If the combined request still cannot be serialized, send the base
  request without extension fields and log which fields were omitted.
- Add regression tests and update the related references and decision note.
2026-09-24 11:15:37 +00:00
turtle1999 d55f434cdf fix(ui-model-selection): own the pending selection in ModelDirectory
The seat kept the pending row in local state, so a stale settlement after
connection/reset could clear a newer selection's spinner, a remount lost
it, and /model popup selections never marked a row. ModelDirectory now
publishes the submitted selection as pending under its generation guard.
The trigger spins whenever a selection is pending, so leaving the row's
pane keeps the feedback visible.
2026-09-24 19:09:14 +08:00
Turtle 910711e6c1 fix(atomic-write): keep the PID-only lock record
The hostname guarded only writers on several hosts sharing one file,
which no supported deployment does, and macOS changes its hostname when
networks change, so locks from before the change could not be taken
over. The nonce closed a race that needs the PID space to wrap between
two reads. Keeping the `<pid>\n` record lets processes of both releases
interoperate.
2026-09-24 19:06:07 +08:00
turtle1999 473f381420 test(cli): export reportSkippedBundles from the desktop-host app-boot stub 2026-09-24 19:04:53 +08:00
Turtle b8e30bf599 fix(ui-tool): address review on web fetch summary link 2026-09-24 19:02:19 +08:00
yixiangihsiang f1b65c78f1 Merge latest origin/master and refresh translation pairing 2026-09-24 18:59:19 +08:00
yudshj 03bd8258c3 chore(deps): upgrade LibreOffice Kit to 0.1.1 2026-09-24 18:56:22 +08:00
Turtle 7e7ba139fd fix(atomic-write): take over a writer lock whose holder exited
A process that ends without running withFileLock's finally left
<file>.lock behind, and every later writer timed out until an operator
deleted it. `dsh plugin` interrupted with Ctrl-C, `dsh web` exiting
right after disposal while a cancelled install still restores files,
and any crash all left the profile package lock this way.

The lock now records its holder's PID, hostname, and a nonce. A
contender that finds a record from this host whose PID a signal probe
reports absent claims that record through a wx-created claim file,
re-reads the lock, removes it only while it still holds the record, and
retries at once. A PID-only record from an earlier release counts as
written on this host, so locks left before this change are taken over
too. Empty, incomplete, foreign-host, and live-holder records are still
waited for.
2026-09-24 18:46:42 +08:00
turtle1999 0a1d102ef0 Merge remote-tracking branch 'origin/master' into fix/profile-bundle-skip-once
# Conflicts:
#	packages/boot/app-boot/README.i18n.yaml
2026-09-24 18:44:35 +08:00
Turtle 61a0ed487e feat(ui-tool): link the collapsed web fetch URL
Closes #3390
2026-09-24 18:41:58 +08:00
yixiangihsiang 4d4bb4c907 fix(client): reveal new-session keys on hover and align settings radius 2026-09-24 18:40:55 +08:00
turtle1999 c8b10a16be fix(boot): report skipped profile bundles once per start
loadProfileDirectory printed each skipped bundle on every call, and startup,
runtime resolution, the config editor, the plugin manager, and HMR all load
the profile, so one incompatible bundle printed the same warning six times at
startup and again on each Web page load. Loading now returns the skips in
Profile.skippedBundles, and the CLI and Desktop launchers print them once per
start with reportSkippedBundles.
2026-09-24 18:32:48 +08:00
turtle1999 20b0730310 Merge remote-tracking branch 'origin/master' into fix/auto-review-user-approval 2026-09-24 18:19:32 +08:00
Chinesezjc 0ca5865a5c Merge pull request #5153 from deepseek-harness/fix/preset-legacy-tool-expectation
test: expect the Host Schedule tools in the legacy preset patch case
2026-09-24 18:19:09 +08:00
turtle1999 c87959bc44 feat(ui-model-selection): show a spinner while a model selection is pending
session.selectModel can take seconds while the Host persists the default
model. The composer seat disabled its rows with no other feedback; the
chosen row now spins in its check slot, and the trigger spins in place of
its chevron while the menu is closed.
2026-09-24 18:18:34 +08:00
lsdsjyandlsdsjy 1103c1a7dd fix(web): 将开发者工具开关更名为代码工作工具 (#5149)
* fix(web): 将开发者工具开关更名为代码工作工具

* test(web): 补齐旧预设配置的定时任务工具断言

* docs(web): 同步代码工作工具开关名称

---------

Co-authored-by: lsdsjy <[email protected]>
2026-09-24 10:15:55 +00:00
mektpoy 223ad4c373 docs(output-retention): address review feedback on the surrogate cap
- State the contract precisely: the cut never introduces a lone high
  surrogate, and an unpaired surrogate the input already carries is not
  repaired.
- Document the new export in the package README: a character-budget preview
  section naming the persistent bash and pwsh shells and str_replace_editor,
  plus a Known Limitations bullet that no longer contradicts it.
- Drop the assertion restatement from the two shell test comments.
- Let the str-replace test helper reuse a root so the clipped context reads
  its file inside its own working directory.
2026-09-24 18:15:52 +08:00
Turtle 488409e306 Merge pull request #5141 from deepseek-harness/turtle/settings-subagent-label-ffe748ff3c38
fix(client): use 子智能体 on the Chinese Subagent settings page
2026-09-24 18:12:29 +08:00
Ziya 77f8d83363 Merge pull request #5143 from deepseek-harness/fix/schedule-record-prompt-clamp
fix(ui-schedule): clamp saved prompts in task run records to two lines
2026-09-24 03:07:56 -07:00
yixiangihsiang eccfda04d6 Merge origin/master into ihsiang/shortcut-sidebar-polish 2026-09-24 18:05:36 +08:00
Xu Hanxiang 8267edfa62 Merge pull request #5148 from deepseek-harness/fix/agent-preset-legacy-schedule-tools
test(cli): expect the shipped Schedule tools in the legacy preset
2026-09-24 18:03:17 +08:00
Turtle 217fb65ac7 Merge pull request #5133 from deepseek-harness/turtle/time-context-ten-minutes
feat(time-context): default injections to ten-minute intervals
2026-09-24 18:01:18 +08:00
imccyu 13de94764b Merge pull request #4839 from deepseek-harness/timed-user-questions-two-settlements
feat: continue timed user questions as two settlements
2026-09-24 18:00:47 +08:00
Chinesezjc 1fa5ea3faa test: expect the Host Schedule tools in the legacy preset patch case
The shipped Web bundle gives every live root Agent the Host Schedule
tools, and every other scenario in this file that boots the shipped
base/web bundle with the minimal preset expects ['bash',
...SCHEDULE_TOOLS]. This case uses the same bootWeb composition and adds
only a settings patch, which does not change tool composition, so its
['bash'] expectation failed on every PR.
2026-09-24 18:00:23 +08:00
turtle1999 307a1920a5 test(cli): expect Schedule tools in the legacy-patch minimal preset
The minimal preset carries the Schedule tools since #5123; the
legacy-patch case added by #5108 still expected bash alone.
2026-09-24 17:58:58 +08:00
Ziya 90e8dfd17f Merge branch 'master' into fix/schedule-record-prompt-clamp 2026-09-24 02:58:29 -07:00
yixiangihsiang 08daf789d5 fix(client): keep new-session shortcuts visible and address review 2026-09-24 17:53:53 +08:00
turtle1999 409fb145af fix(auto-review): ask the user after a denial and report reviewer failures
A reviewer denial now returns the tools pipeline's ask decision when the
Session's approval policy is ask, so the user can approve, reject, or
cancel the call. Selecting Auto writes the ask policy; a recorded Auto
selection still matches never, which delegated children pin, so their
denials stay final.

A reviewer failure now fails the call with its specific error instead of
presenting it as an Auto review denial.
2026-09-24 17:53:25 +08:00
turtle1999 341023a9e7 refactor(schedule): trim constraint prose from Schedule tool descriptions
Keep the timing rules that apply to every selector in the create
description once, move the cron day-field and fixed-rate alignment rules
onto their parameters, and drop parameter formats, result fields, and
Host compare-and-set details from the tool descriptions.
2026-09-24 17:52:58 +08:00
turtle1999 8f86c22a9a refactor(tools): apply send_message, job_kill, and read_image review wording
Drop the extension-less path hint from read_image and the
returns-before-stopped note from job_kill, and describe send_message
delivery without "resumes a turn". image-compaction lowers its context
window by the 30-token tool-schema estimate reduction.
2026-09-24 17:52:58 +08:00
turtle1999 ab2f5d3009 refactor(tools): drop system-prompt repeats of tool definitions
Tool guidance sections keep only what the tool definitions do not say.
Apply review: reword interrupt_agent and list_agents, carry "a rejected
escalation stays denied" in the rejection error, pin
sandboxPermissionsDescription, and fix stale README and Agent Note
statements. Record the tool-definition rules in agent-experience.

Compaction threshold snapshots shift their context windows by the
370-token system-prompt estimate reduction; escalation-rejected moves to
a v4 fixture for the new rejection text.
2026-09-24 17:52:58 +08:00
turtle1999 321a6fa740 refactor(tools): trim constraint prose from tool descriptions
Delete constraints the model learns from the call result, shorten
implementation detail, and move per-parameter rules into the owning
parameter descriptions. Bash, pwsh, and fs share one
sandbox_permissions description in dsh-sandbox.

The standard preset's first-turn prompt drops from 7985 to 6551 tokens.
Compaction threshold snapshots lower their context windows by the
1548-token tool-schema estimate reduction so each trigger keeps its
position; their fixtures move to v4 generations.
2026-09-24 17:52:58 +08:00
Turtle 3c9c18c9fe fix(preset): route profile feature enabling through cordis-plugin-development (#5138)
Broaden the skill description to cover enabling a shipped plugin that a
bundle leaves disabled, add the workspace-bundle recipe for it, forbid
hand-editing profile files that install_bundle owns, and verify installs
through the install result and cordis_inspect_query instead of logs,
process lists, or paged list_plugins calls.
2026-09-24 17:51:15 +08:00
12c9dd599e feat(approval): localize approval explanations (#4793)
* feat(approval): localize prompts and allow consent for one turn

* test(approval): update cast baseline and Web PTC prompt pin

* fix(approval): cover PTC language and clarify turn consent

* fix(approval): group turn consent under allow menu

* fix(approval): keep turn consent in memory only

* test(snapshot): refresh owners for merged justification guidance

* fix(approval): drop duplicate allow-once from the allow menu

* refactor(approval): derive turn consent expiry from one check

Replace the turn approval bookkeeping (revocation state, incremental log
cursor, and turn-signal listeners) with one side-effect-free expiry check
over the log and lifetime flags. Events now only withdraw open
presentations early; the expiry check decides whether an answer or turn
consent still applies, including for Sessions without event publication.

* refactor(approval): drop one-turn consent and keep localization only

Remove the allowed-turn answer, the live turn-consent state, the allow
menu, and their tests, notes, and recorded Web scenario. The approval
service returns to the master request path; the request keeps the
localized displayReason for presentation, and the card resolves it in
the active UI language.

* test(snapshots): record the localized justification schema text in new scenarios

---------

Co-authored-by: Turtle <[email protected]>
Co-authored-by: Kaige-Gao <[email protected]>
2026-09-24 17:47:42 +08:00
ZiyaZhang d8e3efa860 test(cli): expect Schedule tools in the legacy preset-patch session
#5108 added this case against a master where the shipped Web bundle had no
Schedule rows; #5123 then made Schedule part of the default Web composition.
Every other minimal-preset session in this file already expects bash plus
the four Schedule tools, so this one does too.
2026-09-24 02:47:26 -07:00
mektpoy a09402b41c test(cli): expect the shipped Schedule tools in the legacy preset
The shipped Web composition gained the four Host Schedule tools, and the
other four minimal-agent assertions in this file already expect them. The
legacy profile-patch scenario still expected bash alone, so master's E2E
lane failed on it. Align it with its siblings.
2026-09-24 17:46:21 +08:00
lsdsjy 62db4c88c9 Merge pull request #5127 from deepseek-harness/fix/account-model-settings
fix(web): 修复账号模型设置的 namespace 识别
2026-09-24 17:43:32 +08:00
Turtle 259534c2c7 docs: call the Chinese settings page 子智能体 in zh READMEs 2026-09-24 17:40:47 +08:00
ZiyaZhang 27a0a4606c Merge remote-tracking branch 'upstream/master' into fix/schedule-record-prompt-clamp
# Conflicts:
#	packages/client/ui-schedule/README.i18n.yaml
2026-09-24 02:31:11 -07:00
Turtle bfd7e859f5 docs(client): re-record ui-settings-subagent README pairing 2026-09-24 17:26:11 +08:00
lsdsjy c0f0bcf587 Merge pull request #5108 from deepseek-harness/feat/developer-mode-preset-selection
feat(web): 由开发者模式统一控制新任务模式选择
2026-09-24 17:24:51 +08:00
mektpoy 9c64dee509 Merge origin/master into fix/truncate-without-splitting-surrogates
Conflict resolution:
- docs/config-catalog and docs/module-graph: regenerate with the current
  generators, which write the bilingual pages together.
- The conflict came from master's new short-fingerprint pairing records: our
  branch still carried the previous full-hash records. Take master's record
  format, then re-record the output-retention README pair after regenerating
  its two sides.
2026-09-24 17:23:43 +08:00
turtle1999 e1f65ea640 fix(preset): route profile feature enabling through cordis-plugin-development
Broaden the skill description to cover enabling a shipped plugin that a
bundle leaves disabled, add the workspace-bundle recipe for it, forbid
hand-editing profile files that install_bundle owns, and verify installs
through the install result and cordis_inspect_query instead of logs,
process lists, or paged list_plugins calls.
2026-09-24 17:20:17 +08:00
imccyu fa6d9fd75b docs(user-questions): propose timed waits and late replies 2026-09-24 17:20:01 +08:00
Turtle cf8fe108d5 fix(client): call Subagent 子智能体 in the Chinese settings page 2026-09-24 17:18:42 +08:00
Chinesezjc 4611e32e64 Merge pull request #5123 from deepseek-harness/feat/automation-phase1
feat(schedule): ship Schedule in the default Web composition
2026-09-24 17:10:53 +08:00
ZiyaZhang 955a706d33 fix(ui-schedule): clamp saved prompts in task run records to two lines
Each record rendered its whole saved prompt, so a long instruction on a
recurring task filled the records tab with the same text once per run.
A prompt longer than two lines now shows two lines and an Expand toggle;
the toggle appears only while the clamp hides text, and a collapsed prompt
re-measures when the panel width changes.

Also drop the stale comment about the removed message-id anchor.
2026-09-24 01:59:56 -07:00
lsdsjy d183c8a8c0 fix(web): 按账号 provider 识别模型编辑器 2026-09-24 16:57:08 +08:00
lsdsjy 5577becafe fix(web): clear staged preset when developer tools turn off 2026-09-24 16:49:42 +08:00
Chinesezjc f31e51124b test(cli): pin the shipped Schedule rows by name, not loader id 2026-09-24 16:49:34 +08:00
Kexin Liu 89756afa72 Merge pull request #4691 from deepseek-harness/fix/focus-ring-brand-primary
fix(client): unify blue focus rings and keep silent focus silent
2026-09-24 16:48:12 +08:00
Dudu-0223 974c149446 Merge pull request #5114 from deepseek-harness/refactor/catalog-descendant-listing
refactor(subagent): discover descendants through parent catalogs
2026-09-24 16:46:03 +08:00
Chinesezjc 015c187e67 test(cli): read the inspect answer through the spill policy
The shipped Web composition now puts four Schedule tools on every live root
Agent, which pushes a full-preset `cordis_inspect_query` answer past the
12,500-token inline budget, so the spill policy retains its head and tail with
a spill path instead of the complete JSON.
2026-09-24 16:41:20 +08:00
Turtleandturtle1999 950910bdf9 fix(ci): preserve Wine build metadata and isolate test fixtures (#5088)
* fix(ci): preserve Wine build metadata and isolate test fixtures

* test(web): reopen shortcut fixture sidebar with its binding

---------

Co-authored-by: turtle1999 <[email protected]>
2026-09-24 16:37:37 +08:00
lsdsjy 7b86b84c2f fix(web): 修复账号模型设置的 namespace 识别 2026-09-24 16:37:07 +08:00
Chinesezjc 5c768e3c8a fix(schedule): point shared session references at the selected generation
Refreshed owners publish a v4 generation, so every scenario that names
another owner's Session fixture must name that owner's highest generation.
The shipped Web composition also puts the Host Schedule tools on every live
root Agent, so the minimal-preset tool-table assertions include them.
2026-09-24 16:37:05 +08:00
Turtle a3480857dd feat(plugins): offer Auto review and keep Inspector explicitly installed (#4867)
* feat(experimental): ship every experimental capability as an optional bundle

dsh-base mounts the registration-only browser-use and computer-use
services; the Playwright MCP, Chrome DevTools MCP, native and MCP Cua
Driver providers, Auto review, and the Inspector become one-row bundles
listed in OPTIONAL_BUNDLES with an icon and locale display metadata.
verify-default-product-isolation requires both for every optional
bundle. Python PTC and Stagehand stay explicit compositions.

* feat(experimental): keep optional bundles inside the install closure

Drop the Playwright MCP, Chrome DevTools MCP, and native Cua Driver
bundles: each is a runtime dependency of every install and would add
about 85 MB of provider runtimes whether or not enabled. dsh-browser-use
leaves dsh-base with them. The three packages keep their locale display
metadata for component rows.

* feat(experimental): drop the Cua Driver MCP bundle and leave dsh-base untouched

* test(web): refresh Official-group goldens for the four optional bundles

* fix(plugins): use an uninstalled bundle as the install example and pin optional-bundle metadata

The install guide's example is now @deepseek-ai/dsh-subagent-codex,
a published bundle no shipped profile carries, since Auto review is an
installed optional bundle. The optional-bundle spec guards its corpus and
pins each bundle's title, description, and icon in both languages; the
Inspector's Loader test mounts its real bundle patch, its Client names
the reload a hot-enabled page needs, and its description states the
loopback DevTools endpoint's reach.

* test(web): refresh GitHub install recovery placeholder snapshot
2026-09-24 16:33:50 +08:00
Dudu-0223 af371e21c0 revert(subagent): preserve list_agents tool descriptions 2026-09-24 16:32:57 +08:00
Dudu-0223 88500a0f3a fix(subagent): align catalog discovery docs and regression coverage 2026-09-24 16:30:58 +08:00
Chinesezjc fe6ce46248 docs(context): keep the group summary within its word budget 2026-09-24 16:28:51 +08:00
imccyu 3eadc9b56c Merge pull request #5107 from deepseek-harness/fix/desktop-local-markdown-images
fix(desktop): 修复本地 Markdown 图片预览
2026-09-24 16:27:11 +08:00
turtle1999 da05b8d9c5 test(web): reopen shortcut fixture sidebar with its binding 2026-09-24 16:27:07 +08:00
Dudu-0223 4e6a1c1073 fix(session-query): classify live projection failures as corrupt 2026-09-24 16:13:37 +08:00
Chinesezjc e896737840 feat(schedule): ship Schedule in the default Web composition
The Web bundle now mounts `time-context` and `schedule` and leaves the
`ui-schedule` client row enabled, so the Automation tasks page, the Session
reminder catalog, and the `schedule_*` tools work without an overlay. Both
packages join the bundle's declared dependencies, and the example overlay is
deleted: re-inserting its rows would mount both Host plugins twice.

The fixed-rate floor drops from 300 to 60 seconds across the Host decoder,
the create and update validation, the model-visible tool schema, and the
client's per-unit floors.

Web recorded sessions and header sidecars are refreshed for the readings
`time-context` now appends; `normalizeWebSessionVolatiles` tokenizes their
sampled instant, browser zone, and elapsed duration so replay stays stable.
2026-09-24 16:11:52 +08:00
mektpoy 8e42deafa1 fix(client): keep the sidebar toggle's focus ring unclipped
The sidebar toggle is flush with `.logoRow`, which clips its own overflow, so
the standard outward ring lost every pixel that left the row: the reviewer saw
the ring cut on the toggle in both the expanded header and the settled rail.

The 36px rail toggle is also 1px wider than its 35px row, so the control's own
right edge was clipped there. Draw this control's ring inside its own box and
stop clipping the row once the rail has settled; the ring keeps the standard
`--dsw-focus-ring-width` colour and width, and pointer modality still resolves
`--dsw-focus-ring-color` to transparent.

`focus-rings.e2e.ts` asserts the whole ring against every clipping ancestor in
both layouts, in both themes.
2026-09-24 16:02:45 +08:00
turtle1999 6720a1206f fix(ci): reconcile workspace fixture with current master 2026-09-24 16:02:31 +08:00
Ziya 60e69cb931 Merge pull request #5113 from deepseek-harness/fix/github-recovery-on-mirror
fix(plugin-manager): offer another way when a GitHub failure already asked the mirror
2026-09-24 01:01:22 -07:00
yixiangihsiang ed3dcf54c5 feat(web): refine shortcut editing and sidebar hints 2026-09-24 15:55:33 +08:00
Dudu-0223 311cac1c17 docs: refresh subagent dependency graph 2026-09-24 15:54:47 +08:00
Dudu-0223 a4ddc28ed5 refactor(subagent): traverse descendant catalogs recursively 2026-09-24 15:49:55 +08:00
ZiyaZhang d7db3a2f06 test(plugin-manager): name the on-mirror recovery case by what it asserts 2026-09-24 00:46:50 -07:00
liukx0205 9827bcfb37 Merge master into fix/focus-ring-brand-primary 2026-09-24 15:38:51 +08:00
lsdsjy 53e000810d Merge origin/master into feat/developer-mode-preset-selection 2026-09-24 15:33:43 +08:00
ZiyaZhang ef516f98cf fix(plugin-manager): offer another way when a GitHub failure already asked the mirror 2026-09-24 00:29:39 -07:00
imccyu 55fadaa601 Merge pull request #5030 from deepseek-harness/ihsiang/ui-visual-consistency
feat(web): 统一界面圆角与菜单材质,优化文件改动展示
2026-09-24 15:10:55 +08:00
imccyu d3314da7c2 test(web): expect unblurred desktop onboarding confirmations 2026-09-24 14:58:55 +08:00
imccyu 59d2e01575 revert(desktop): remove branch-local development launchers 2026-09-24 14:58:55 +08:00
imccyu 6000dcdda5 fix(web): reconcile visual consistency after master rebase 2026-09-24 14:58:55 +08:00
yixiangihsiang 63c7e370ce test(desktop): isolate packaging Git observations from concurrent fixtures 2026-09-24 14:58:55 +08:00
yixiangihsiang df2372fefe fix(web): preserve macOS overlay opacity and desktop launch settings 2026-09-24 14:58:55 +08:00
yixiangihsiang 8b60939220 fix(desktop): confine launcher proxies to runtime preparation 2026-09-24 14:58:54 +08:00
yixiangihsiang fdd14a0989 feat(web): unify UI materials and streamline file review 2026-09-24 14:58:54 +08:00
lsdsjy 7e97c458ba Merge pull request #5106 from deepseek-harness/fix/account-balance-timeout
fix(account): extend balance request timeout to 30 seconds
2026-09-24 14:50:25 +08:00
mektpoy 74a0c834f9 Merge remote-tracking branch 'origin/master' into fix/focus-ring-brand-primary
Only the ui-theme README pairing record conflicted; re-recorded. The stylesheet
corpus spec passes over master's new client sheets, so no ring needed realigning.
2026-09-24 14:49:16 +08:00
mektpoy 006244a3ad refactor(client): unify the trajectory cell's selected ring on the brand blue
`.selected` still named `--dsw-alias-brand-primary-new-colorprimary-new-color`, the
corrupted token left by a botched rename; its dark value is `deepseek-450` while
every focus ring now uses `deepseek-400`. The selection ring reads the clean
brand-blue alias instead, so one blue covers selection and focus.
2026-09-24 14:47:50 +08:00
winewill 3511c45426 Merge pull request #5015 from deepseek-harness/feat/close-window-quit-behavior
feat(desktop): 关闭窗口隐藏到后台,退出前按任务状态确认
2026-09-24 14:45:04 +08:00
lsdsjy 4c4108ef1b test(web): 修复模式选择测试类型断言与分支覆盖 2026-09-24 14:42:13 +08:00
winewill fbb3fb770f fix(desktop): cancel pending quit decisions during installer exit 2026-09-24 14:36:02 +08:00
lsdsjy a44534e274 feat(web): 由开发者模式统一控制新任务模式选择 2026-09-24 14:29:18 +08:00
winewill 5637311d5a fix(desktop): confirm the first close with the shared shell dialog 2026-09-24 14:25:02 +08:00
winewill 20dae9b6fa test(desktop): align close behavior fixtures after master rebase 2026-09-24 14:24:39 +08:00
winewill eec2b5fa6e fix(desktop): enlarge whale artwork in Windows tray icon 2026-09-24 14:24:39 +08:00
winewill e6f135f15c fix(desktop): harden quit bypass and background-notice bookkeeping after review
- Only the definitive Windows session-end message bypasses the quit
  confirmation; the macOS power-off flag clears on the next focus or show
  because another application can cancel that shutdown.
- A bypassing quit disposes the pending confirmation so a late inspection
  result opens no box and an answered box cannot approve.
- Cancelling a quit that closing the welcome window started shows the
  welcome window again.
- The first-hide notice records its marker only after delivery and
  withdraws it on failure; the Windows quit dialog uses the multi-size ICO.
- windowShown settles when the awaited window is destroyed.
- Cross-link the partially superseded window-menus note; tidy docs.
2026-09-24 14:24:39 +08:00
winewill 4745934683 feat(desktop): hide the window on close and confirm interruptible quits
Closing the main window hides it on macOS and Windows; the page and the
Host keep running and the next show resumes the same document. Windows
gets a permanent tray icon (open / quit) and a one-time notification the
first time the window is hidden after installation.

Every ordinary quit entry asks the Host over a new quit-inspection IPC
request for active tasks (same rule as the update restart check) and
armed scheduled reminders (schedule family of workspace/session-activity
for loaded sessions). Nothing to interrupt quits silently; otherwise a
native message box explains what stops, with Quit as the default and
Cancel on Esc. Inspection failure or a missed two-second deadline counts
as running tasks. The installer restart, fatal recovery, the development
restart command, and OS session end skip the confirmation.

Also: defer the downloaded-update confirmation while the window is hidden,
render the tray ICO from the vector icon, and point the installer's
running-application message at the tray.

Closes #4013
2026-09-24 14:24:39 +08:00
lsdsjy c846fd48a3 fix(account): extend balance request timeout to 30 seconds 2026-09-24 14:11:23 +08:00
Kaige-Gao 7f0a53dfb3 fix(desktop): render local Markdown images
Resolve local image paths through the authenticated dsh-app file route and allow that route in rewritten Markdown images. Cover desktop rendering, previews, encoded filenames, and unsupported origins.

Fixes #5105.
2026-09-24 14:10:13 +08:00
Yudong Han 31da6718a9 Merge pull request #5091 from deepseek-harness/fix/document-preview-white-placeholder
fix(web): 统一文档加载提示、分页留白和主题背景
2026-09-24 14:07:10 +08:00
yudshj ed4445b028 fix(web): unify document loading and spaced theme-aware pages 2026-09-24 13:57:42 +08:00
Yichen Jiang 55b06e6f81 Merge pull request #5098 from deepseek-harness/worktree/model-api-key-autofill
fix(web): suppress saved-password autofill in API key inputs
2026-09-24 13:55:56 +08:00
Yichen Jiang 9a816ec171 Merge pull request #5065 from deepseek-harness/worktree/issue-5003-review-a73e0a
fix(app-boot): preserve routed resolution errors under async module hooks
2026-09-24 13:50:38 +08:00
Yichen Jiang 1197478415 Revert "fix(session): isolate source migration verifiers in processes"
This reverts commit f1cc349a4290fbf34e1f68e51ea787524e761d7c.
2026-09-24 13:46:52 +08:00
winewill 1bc594d701 Merge pull request #5076 from deepseek-harness/feat/windows-update-restart
fix(desktop): clarify Windows updates and raise the restarted window
2026-09-24 13:41:12 +08:00
Yichen Jiang fa04034a9c fix(session): isolate source migration verifiers in processes 2026-09-24 13:31:16 +08:00
Yichen Jiang 11c0511271 fix(web): align remaining API key inputs with autofill policy 2026-09-24 12:32:10 +08:00
Yichen Jiang 4cc76d04e9 fix(web): suppress saved-password autofill in API key inputs 2026-09-24 12:31:56 +08:00
liukx0205 4f1a1289f5 fix(client): use blue focus rings in light and dark themes 2026-09-24 12:24:47 +08:00
Kexin Liu 450f155955 Merge pull request #4826 from deepseek-harness/feat/unify-code-highlight-languages
统一并扩展代码高亮语言表(read 卡片与侧栏 Code 预览)
2026-09-24 12:10:50 +08:00
liukx0205 e71fa92030 Merge master into fix/focus-ring-brand-primary 2026-09-24 12:05:19 +08:00
liukx0205 bf4d264368 Merge master into feat/unify-code-highlight-languages 2026-09-24 11:58:08 +08:00
Yichen Jiang 9a9a331963 fix(voice-input): preserve draft focus during setup guidance 2026-09-24 11:55:27 +08:00
2fd748edad feat(desktop): 按请求凭据区分欠费提示及充值入口 (#4858)
* feat(desktop): distinguish account quota alerts from API key notices

* docs: condense architecture introduction within existing budget

(cherry picked from commit 01aacaee4d48fd7f4d00acb5e23758084d3f224e)

* test(desktop): cover quota notice lifecycle and remove unknown casts

(cherry picked from commit 7fd09407c482d1f0e30f24ba0ebf23cd844ac9a1)

* chore(account-quota): align tests, catalogs, and bilingual pairs with the account plugin

* fix(ui-settings-account): pass the Platform retry label to the account top-up overlay

* fix(chat): preserve quota failures and global notices

* fix(account): keep active top-up pages across quota notices

* fix(account): share platform page ownership and release quota holds

* fix(account): defer notices behind the shared Platform page

The single native Platform view covers the document, so a quota failure that arrives while a Settings-opened page shows is deferred rather than retained: the newest failure still replaces an older notice and its Modal appears after the viewer returns if still current. Top up remains the retained case, releasing its hold and page request with the entry.

* test(account): align quota fixture with bonus actions

* fix(account): preserve quota notice and Platform return focus

* fix(account): preserve onboarding return reads and failed notices

* docs(account): clarify page opener return ownership

* test(account): drive bonus acknowledgement retry deterministically

---------

Co-authored-by: liyao <[email protected]>
Co-authored-by: lsdsjy <[email protected]>
2026-09-24 11:50:11 +08:00
winewill 037bed1f41 fix(desktop): reject running app before installer extraction 2026-09-24 11:49:01 +08:00
Yichen Jiang 1648bb6587 Merge origin/master into worktree/voice-setup-navigation 2026-09-24 11:45:52 +08:00
lsdsjy 5be03410cd Merge pull request #4990 from deepseek-harness/fix/platform-webview-persistence
fix(desktop): persist account-scoped Platform page preferences
2026-09-24 11:21:21 +08:00
Yichen Jiang 730446172e test(voice-input): address setup guidance review feedback 2026-09-24 11:11:21 +08:00
lsdsjy dd0578fadd Merge origin/master into fix/platform-webview-persistence 2026-09-24 11:05:40 +08:00
Turtle 2099andTurtle 16af6fddc7 fix(plugins): name the default install source by the registry it names (#5084)
* fix(plugins): name the default install source by the registry it names

The add-plugin dialog showed "默认安装源" for pnpm's own registry, which
told the reader nothing about where the install would download from. Name
npm's own registry as the official npm registry, and any other registry
pnpm's own configuration names by that registry's name or host, so the
folded control reads by the registry the install actually asks.

* test(plugins): cover comparing an unparseable registry address

---------

Co-authored-by: Turtle <[email protected]>
2026-09-24 10:55:35 +08:00
07akioni 655534d009 Merge pull request #5046 from deepseek-harness/fix/language-neutral-default-workspace-naming
fix(workspace): keep the default Workspace path language-neutral
2026-09-24 10:41:07 +08:00
_Kerman 26dcd5a247 Merge remote-tracking branch 'origin/master' into fix/language-neutral-default-workspace-naming
# Conflicts:
#	.agents/notes/implemented/feature/2026-09-20-default-workspace.i18n.yaml
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/config-catalog.zh.md
#	docs/subsystems/workspace.i18n.yaml
#	packages/api/workspace-controller/README.i18n.yaml
#	packages/client/ui-workspace/README.i18n.yaml
#	packages/client/ui-workspace/tests/workspaces-service.client.spec.ts
#	packages/workspace/workspace/README.i18n.yaml
2026-09-24 10:30:24 +08:00
turtle1999 687aa02578 fix(ci): preserve Wine build metadata and isolate test fixtures 2026-09-24 02:32:24 +08:00
winewill a67119845d fix(desktop): align update fixtures and clear deferred startup focus 2026-09-24 01:18:52 +08:00
winewill a7e745de66 Merge master into feat/windows-update-restart 2026-09-24 01:11:36 +08:00
winewill 3bcf1bfc7c Merge pull request #4967 from deepseek-harness/fix/desktop-main-bundle-order
build(desktop): bundle the main process after the workspace tsdown pass
2026-09-24 00:44:55 +08:00
std4453 3055bad0d1 Merge pull request #5078 from deepseek-harness/fix/onboarding-recharge-artwork
feat(desktop): add onboarding with current artwork and work-detail defaults
2026-09-24 00:36:30 +08:00
Yifffan f032bd2d04 Merge pull request #5002 from deepseek-harness/session-archieve-refine
feat(client): explicit three-way archived filter with empty-state refinements
2026-09-24 00:18:51 +08:00
zhc 7cadefb991 fix(onboarding): use shared modal focus ownership 2026-09-23 23:58:21 +08:00
Yif 5688962ee9 test(ui-primitives): count the 94 merged public glyphs 2026-09-23 23:48:05 +08:00
Yif 6ddece2439 refactor(ui-workspace): share the viewing store with the row toast as a declared store
The archived filter reaches the row toast through the registration's declared
store instead of a registrant-owned view hook, per the cross-entry view-state
rule. The README names the toast action by its actual label, and the
unarchive e2e switches back to Hide archived so it again proves the restored
row is an ordinary row in the default view.
2026-09-23 23:48:04 +08:00
Yif d6e5dc7748 test(client): cover the unset archived filter and follow the three-way menu in web goldens 2026-09-23 23:48:00 +08:00
Yif aaf733c175 fix(client): let a snippetless search result use the full row for its workspace name 2026-09-23 23:48:00 +08:00
Yif 64352df324 style(client): tune empty-state tokens and glyph spacing 2026-09-23 23:47:59 +08:00
Yif e28434bbc8 chore(client): re-record slot catalog source lines after the slots import 2026-09-23 23:47:59 +08:00
Yif 2129486048 feat(client): give the session list an iconed empty state with an archived-only way back 2026-09-23 23:47:30 +08:00
Yif 62bd4363e6 feat(client): omit the toast filter action while archived rows are visible 2026-09-23 23:46:21 +08:00
Yif 9775a95315 feat(client): make archived filtering an explicit three-way menu choice
The view-options filter is now hide/all/only radio items, the
archived-only view drops Workspaces without an archived Session, and
tree children of a dropped Workspace nest under the nearest shown
ancestor (#4854).
2026-09-23 23:46:21 +08:00
Yif 82b8c476e6 feat(client): add archive-off glyph and reuse chat-lines for session references 2026-09-23 23:46:21 +08:00
zhc 0e18138427 test(web): start bonus notice scenario after onboarding 2026-09-23 23:44:51 +08:00
zhc 6233f998a2 merge: integrate current account bonus notices with onboarding 2026-09-23 23:43:53 +08:00
winewill 1e5af11d8c build(desktop): emit shortcuts protocol before the main bundle 2026-09-23 23:42:19 +08:00
winewill 917613c776 Merge master and preserve Desktop bundle validation 2026-09-23 23:40:02 +08:00
zhc e44a4d4dd3 test(desktop): separate fixture state from native window members 2026-09-23 23:35:58 +08:00
lsdsjy a523d8ec58 Merge pull request #5040 from deepseek-harness/feat/account-bonus-notices
feat(account): show bonus notices and send Platform client metadata
2026-09-23 23:35:54 +08:00
zhc ac586cefca test(desktop): type overlay visibility fixture explicitly 2026-09-23 23:35:13 +08:00
涂轶翔 f6a2c700af Merge pull request #4844 from deepseek-harness/feat/dynamic-tool-update-message
Support dynamic tool updates during active conversations
2026-09-23 23:35:08 +08:00
zhc 4fdcaf16b5 merge: integrate desktop shortcuts and refresh onboarding decisions 2026-09-23 23:34:17 +08:00
Chinesezjc 7a362b263b Merge pull request #4335 from deepseek-harness/feat/schedule-storage-phase1
feat(schedule): persist tasks and resume due sessions
2026-09-23 23:33:33 +08:00
lsdsjy 6171ed6f5d Merge origin/master into feat/account-bonus-notices 2026-09-23 23:25:21 +08:00
lsdsjy 3ff8fe093a fix(account): satisfy bonus notice style and coverage checks 2026-09-23 23:12:19 +08:00
流光 6638afae5e Merge pull request #4938 from deepseek-harness/feat/shortcuts-rework
feat(shortcuts): restore configurable shortcuts with regression fixes
2026-09-23 23:08:15 +08:00
zhc f55c8d5215 test(desktop): await the selected onboarding preference write 2026-09-23 22:57:42 +08:00
lsdsjy b9fb1cceea fix(web): synchronize read-only spreadsheet scroll state 2026-09-23 22:53:08 +08:00
zhc c4b13d154f merge: refresh master translation pairing format 2026-09-23 22:47:06 +08:00
Xinyu Yang bfb624cd3b Merge master translation record migration into feat/shortcuts-rework 2026-09-23 22:46:08 +08:00
mektpoy c3cd67a2e8 Merge remote-tracking branch 'origin/master' into fix/focus-ring-brand-primary
Only the bilingual pairing records conflicted. Master moved Agent Note records to
per-heading hashes, so this branch's note record was re-recorded in that format;
the ui-primitives and ui-theme README records were re-recorded unchanged. The
stylesheet corpus spec still passes over master's new client sheets, so no ring
needed realigning this time.
2026-09-23 22:43:43 +08:00
lsdsjy 99032c6b10 Merge origin/master into feat/account-bonus-notices 2026-09-23 22:42:37 +08:00
Tianyi Cui ba66011fdb test(sdk): use generated sample data for cache probes
The probe needs a value that cannot be inferred from the prompt, not protected information. Describing that generated UUID as a private secret made the API test depend on an unrelated disclosure decision. Use an explicitly synthetic sample label and a benign formatting update while preserving execution audits, first-continuation cache assertions, and disabled retries.
2026-09-23 22:40:40 +08:00
Tianyi Cui 5827477658 test(web): account for tool update process rows
Open the running Think disclosure explicitly when a process group also contains tool updates, and keep the fork process summary expandable in its ARIA expectation. Record the Goal request-series marker in a V4 fixture successor while preserving the historical V3 recording. Production behavior and the scroll assertions stay unchanged.
2026-09-23 22:40:40 +08:00
Tianyi Cui 611c2bc2e9 test(headless): refresh dynamic tool request expectations
Record explicit request-series starts and the tool additions admitted when resuming a seeded parent with no tool declarations. Keep tool names and the shifted source-event reference alongside that activation history. Refresh only the affected owner-local outputs to the current writer format; retain historical replay fixtures and the unchanged child expectation.
2026-09-23 22:40:40 +08:00
Tianyi Cui f6848ee921 fix(agent-loop): preserve prompt history during supported tool updates
Tool changes previously forced prompt consolidation even when the prepared
route could activate new tools through history. Rewriting the first system
message, or clearing an earlier appended prompt, reset the declaration
series and turned additions into immediate declarations.

Only routes without toolUpdate need that tool-triggered consolidation.
Capable routes append the full changed prompt and keep existing messages.
Explicit series starts, surface replacements, and unsupported prompt
routes still consolidate; retained-name definition changes still rebuild
tool declarations in Session.

Cover both update modes and reset paths, and pin the combined prompt/tool
transition through the shipped headless profile with shared schema goldens.
2026-09-23 22:40:40 +08:00
Tianyi Cui f765a21dc7 test(sdk): verify cache reuse across native tool additions
Run a real DeepSeek conversation through the built SDK profile and change the scoped tool registry through a model-invoked controller. Compare the first post-addition cache usage with the preceding request after unique user history has been cached; verify deferred declarations, chronological activation, and actual tool execution. Removal remains covered without requiring its cache prefix to survive. Disable test and provider retries so a warmed transition cannot hide a cache regression.
2026-09-23 22:40:39 +08:00
Tianyi Cui e221615112 test(sdk): cover native dynamic tool lifecycle 2026-09-23 22:40:39 +08:00
Yixiang Tu 43048098f6 test(llm): cover dynamic tool updates and clarify documented limits 2026-09-23 22:40:38 +08:00
Yixiang Tu 1b0c2e5760 fix(session): retain baseline-bound tool activations 2026-09-23 22:40:36 +08:00
Yixiang Tu 1321345c84 docs: keep architecture within its word budget 2026-09-23 22:40:36 +08:00
Yixiang Tu 8862ed8266 docs: mirror regenerated event table rows into the Chinese counterpart 2026-09-23 22:40:36 +08:00
Yixiang Tu 59318c1204 fix(llm): clarify tool update projection and preserve deferred activation 2026-09-23 22:40:19 +08:00
Xinyu Yang e8daeb4969 test(web): align window drag fixture with desktop shortcuts 2026-09-23 22:39:48 +08:00
Yixiang Tu 7e5f906945 feat(client): present compact developer tool update notices 2026-09-23 22:39:34 +08:00
Yixiang Tu bc8c0dbf40 feat(llm): emit dynamic tool updates and project them per route
Log tool changes as developer messages independently of model capability,
fold committed headers and updates into Session.toolHistory(), and let the
LLM runtime construct deferred and retained declarations for routes that
declare a toolUpdate mode. DeepSeek serializes updates as system-role
tool_addition/tool_removal blocks with defer_loading and the tool-changes
beta header. An unchanged restored tool continues the series and is
re-offered through its recorded blocks instead of rewriting declarations.

Replace the obsolete rejection tests with wire assertions and add coverage
for the session fold, loop emission, route projection, config validation,
and the beta header. Chat and Trajectory changes land separately.
2026-09-23 22:39:26 +08:00
mektpoy c3a8318377 test(web): type the ring sample as a colour triple 2026-09-23 22:38:29 +08:00
lsdsjy 651f419bf8 Merge remote-tracking branch 'origin/master' into fix/platform-webview-persistence 2026-09-23 22:37:17 +08:00
lsdsjy 1efb58f47e Merge origin/master into feat/account-bonus-notices 2026-09-23 22:33:20 +08:00
Turtle e7def469e1 feat(i18n): key translation pairing records by heading section (#5036)
* feat(i18n): key translation pairing records by heading section

Replace the whole-file blob hashes in *.i18n.yaml with one entry per
heading section that still holds language-specific content, keyed by the
English heading-slug path. Blocks identical across the pair (generated
table rows, code blocks, shared regions) stay out of the hash, so edits to
different sections and identical regenerations merge with Git's default
text merge, including on GitHub.

Remove the dsh-translation-pairing merge driver, its resolver command and
installer wiring; gen-translation-brief recovers last-confirmed text from
commit history. Migrate all active records, archive the superseded Agent
Note, and record the replayed conflict reduction in the new one.

* test(i18n): refresh translation prompt snapshot for the terminology note

* feat(i18n): exclude only code blocks and generated regions from pairing records

Replace byte-equality masking with an explicit rule: a record hash skips
fenced code blocks and BEGIN/END GENERATED regions, the two kinds of
content the pairing gate already requires to be identical on both sides.

Move generated data into regions written into both pages:
gen-config-catalog renders both languages and the record with per-package
regions labelled by code identifiers; gen-module-graph keeps its table in a
region; gen-doc-graphs splices the event matrix regions into the Chinese
page. Add a generic region splice beside the region grammar.
2026-09-23 22:32:06 +08:00
Xinyu Yang 64d401c820 fix(shortcuts): align package versions with release 2026-09-23 22:26:26 +08:00
zhc 7b4541e21c fix(desktop): use public work detail types and precise persistence checks 2026-09-23 22:26:19 +08:00
lsdsjy 311ab0524f Merge remote-tracking branch 'origin/master' into fix/platform-webview-persistence 2026-09-23 22:25:54 +08:00
zhc 82fe79a7b1 fix(desktop): integrate onboarding with current master 2026-09-23 22:24:21 +08:00
lsdsjy 235b13ab12 Merge origin/master into feat/account-bonus-notices 2026-09-23 22:23:57 +08:00
mektpoy 6921e37b99 chore(code-language): match the root release version
master released 0.1.7-rc.1 while the package added by this branch still declared 0.1.7-alpha.2, which failed Dependency layout (verify-npm-install-layout), Pack npm tarballs (release members must share one version) and node 24 / static (constraints) from one cause. Merge origin/master and bump the new package to the root version.
2026-09-23 22:23:51 +08:00
zhc ad86306feb fix(desktop): align onboarding with current work detail modes 2026-09-23 22:21:19 +08:00
zhc 372c311511 fix(desktop): refresh recharge onboarding artwork 2026-09-23 22:21:18 +08:00
07akioni 93b832f1b0 Merge pull request #4459 from deepseek-harness/feat/desktop-onboarding
feat(desktop): add device-local account onboarding
2026-09-23 22:21:18 +08:00
mektpoy 120612ddc8 Merge remote-tracking branch 'origin/master' into feat/unify-code-highlight-languages 2026-09-23 22:17:39 +08:00
Xinyu Yang 851686d144 Merge latest origin/master into feat/shortcuts-rework 2026-09-23 22:12:48 +08:00
Xinyu Yang 4b03fefec1 Merge origin/master into feat/shortcuts-rework 2026-09-23 22:10:54 +08:00
07akioni d9ff18ec2a Merge pull request #4622 from deepseek-harness/feat/window-drag-coverage
refactor(client): 让每个 chrome 行自持窗口拖拽(单一声明 + 覆盖契约 + 统一重收集)
2026-09-23 22:08:13 +08:00
winewill 174d385bf5 Merge master into fix/desktop-main-bundle-order 2026-09-23 22:07:37 +08:00
lsdsjy 7d56ff04aa fix(account): address bonus notice review and balance labels 2026-09-23 22:06:29 +08:00
lsdsjy 50293e4dd4 Merge origin/master into feat/account-bonus-notices 2026-09-23 22:05:41 +08:00
lsdsjy bf5eb8a39a Merge pull request #4650 from deepseek-harness/feat/account-provider-signout
feat(account,models): separate account routing and confirm sign-out impact
2026-09-23 21:48:20 +08:00
lsdsjy 9a9948bc83 test(web): align unavailable model and cold session expectations 2026-09-23 21:33:16 +08:00
Xu Hanxiang f717f413da Merge pull request #4813 from deepseek-harness/fix/windows-file-open-and-preview
fix(web): 修复 Windows 文件预览、应用图标与默认打开操作
2026-09-23 21:29:24 +08:00
winewill d2a5490fa0 fix(desktop): clarify Windows updates and raise the restarted window 2026-09-23 21:25:54 +08:00
lsdsjy 71f0713b86 fix(llm): align provider packages with release version 2026-09-23 21:18:17 +08:00
lsdsjy b1cb0d6718 Merge remote-tracking branch 'origin/master' into feat/account-provider-signout 2026-09-23 21:17:27 +08:00
mektpoy 4a409edf8b fix(client): keep the plugin manager's whole top strip draggable
The page carried a 28px top inset above its head row, so the window's topmost 28px on that page belonged to no drag region — the frame's former band covered it, and the per-row mark did not. The inset moves into the head rows themselves (.pageHead and .detailTop), which now start at the window's top edge while the content keeps its position. The browser lane pins each row's top edge at zero and the negative control confirms both assertions fail on the pre-fix sheet.
2026-09-23 21:10:27 +08:00
liukx0205 caa4b8feca fix: highlight CSV without changing the default spreadsheet preview 2026-09-23 21:09:42 +08:00
lsdsjy eff44a957c test(headless): isolate API-key credential snapshots 2026-09-23 21:08:21 +08:00
Turtle 46a7f68b09 Merge pull request #5073 from deepseek-harness/rel/dsh-0.1.7-rc.1
release(dsh): 0.1.7-rc.1
2026-09-23 21:03:33 +08:00
lsdsjy 3cf49f26ab fix(account): cover live notices and satisfy CI checks 2026-09-23 20:53:30 +08:00
turtle1999 a60af51e80 release(dsh): 0.1.7-rc.1 2026-09-23 20:47:45 +08:00
lsdsjy 4e0283c89b Merge remote-tracking branch 'origin/master' into feat/account-provider-signout 2026-09-23 20:45:29 +08:00
Turtle 07ad70817f fix(plugins): deny incompatible bundles and clarify compatibility refusals (#5061)
* fix(plugins): deny incompatible bundles and clarify compatibility refusals

A bundle package is not a plugin row, so startup admission never read its
own DSH peers: a bundle installed outside DSH or before a DSH upgrade still
applied its patch layer. loadProfileDirectory now skips such a bundle like an
unreadable one unless the profile exempts that exact pair.

A post-install refusal in a profile without a lockfile reinstalls from the
restored manifest instead of failing a frozen install and leaving the
rejected packages in node_modules.

Compatibility warnings now name the `dsh plugin allow-version` command for
CLI-managed profiles, startup denials name the row id instead of a resolved
module URL, and the CLI no longer reports "pnpm failed" when pnpm never ran.

* feat(plugins): report incompatible versions as typed refusals

Compatibility checks now yield the refused packages as data instead of a
profile-specific sentence. runProfilePnpm returns them as
PackageResult.incompatible, and the plugin manager refuses with the
incompatible-version code carrying the same records. Each surface renders
them: the CLI prints the exact allow-version command for its profile, the
Web plugin manager words them through its locale dictionary, and app-boot
keeps one neutral English diagnostic for logs and startup stderr.

* fix(plugin-manager): drop the agent exemption hint from the incompatibility reason
2026-09-23 20:44:06 +08:00
_Kerman ce5ef7a17b fix(workspace): let confirming the seeded label pin a default title
Review caught two real gaps in the previous commit.

The rename dialog's no-op check compared the localized display title, so
on an automatically titled Workspace the seeded prefill equalled it and
Rename stayed disabled — the user had no direct way to pin the visible
name. The dialog now seeds the draft with the label on screen while the
stored title decides whether confirming saves, and the duplicate check
excludes the target by Workspace identity instead of by title, since the
seeded label equals the row's own displayed title.

The registry took the automatic title from the canonical path, so a
symlink at the first-use path titled the Workspace after its target and
the default lost its localized label. The title now comes from the
requested directory's final segment; the path stays canonical.

Also: drop a rotting file count and the stale localized-path wording from
the Agent Notes, record the two cwd-derived Session label fallbacks as
known consequences, trim the WorkspaceBrowser memo comment to the
non-obvious part, and remove the deleted request type from the
hand-maintained catalog LINK_MAP.
2026-09-23 20:32:57 +08:00
imccyu c76217a356 Merge pull request #5053 from deepseek-harness/feat/tool-preparing-progress
feat(chat): add work detail modes and file preparation progress
2026-09-23 20:28:16 +08:00
imccyu 490f569044 Merge pull request #5067 from deepseek-harness/revert-5062-ihsiang/chat-flow-visual-polish
Revert "fix(web): 恢复蓝色深度求索动画并优化过程折叠展示"
2026-09-23 20:22:22 +08:00
imccyu 7c8a44ac31 Revert "feat(web): restore the process-row polish on the grouped work details"
This reverts commit 036d53fb612c785a17d9e6068f58b155d87120c1.
2026-09-23 20:21:46 +08:00
ihsiang b09dd94827 feat(web): restore the process-row polish on the grouped work details
* feat(web): restore the process-row polish on the grouped work details

The sweep highlight, shared row colors, expanded-row spacing, and the
12–24px font-size range were developed against the pre-revert work-details
implementation. Re-apply them to the grouped implementation that replaced it.

- TextShimmer keeps its active-driven span and now paints a masked sweep
  overlay in the theme's `--dsw-alias-label-shimmer` color, so the base text
  inherits the caller's color and hover changes.
- DisclosureRow owns the row color: tertiary at rest, secondary on hover,
  with glyphs, titles, and summaries inheriting it; tool, skill, command,
  reasoning, and workflow rows drop their own hover darkening.
- ChatView spaces process rows 8px apart and keeps 16px beside Assistant
  responses; the grouped header sits 8px above its first member.
- The Settings font-size stepper accepts 12–24px, and the grouped header's
  leading box and glyph scale with the content font-size delta.

* fix(web): restore blue running status and refine process disclosures

* fix(web): finalize running snapshots and whale animation

* fix(web): preserve disclosure layout and repair CI fixtures
2026-09-23 20:10:50 +08:00
turtle1999 f64c57dbb2 fix(plugin-manager): drop the agent exemption hint from the incompatibility reason 2026-09-23 20:04:31 +08:00
lsdsjy 1098fa52ea fix(account): use configured Platform origin for account link 2026-09-23 20:00:34 +08:00
lsdsjy 9759ea2719 Merge origin/master into feat/account-provider-signout 2026-09-23 20:00:03 +08:00
mektpoy f35db51bee fix(native-command): transport the Windows adapter as a script file
Resolving packaged-app icons grew the embedded C# until the generated
-EncodedCommand line reached 32,883 characters for a 222-character path,
past the 32767-character CreateProcess limit, so association queries stopped
starting for long multibyte paths. Write the adapter to a private temporary
script and pass it with -File instead; the command line no longer grows with
the path. The temporary directory is removed once the call settles.

The icon fallback also reads the handler name the caller already fetched
instead of calling GetName again, and the README records that icon
visibility depends on resolving the Shell's indirect reference.
2026-09-23 19:58:58 +08:00
mektpoy 64795b4879 fix(ui-open-in-app): open the application the control names
With no OS-marked default the split button labelled the first registered
application and marked it "(default)" in the menu, but the primary action
still asked the OS to resolve the association again; on Windows that can
prompt or open a different application than the button promises. Send that
application's id explicitly and keep the association path for the case the
Host actually marked a default.

The snapshot scenario now clears the platform's own default marker and
re-enters the file, so the association is read again instead of reusing the
answer already held, and it asserts the launched target rather than only the
labels.
2026-09-23 19:58:53 +08:00
mektpoy 2a0531e9c3 fix(code-language): address review on the persisted hint and aliases
Review threads: shrink READ_LANG_BY_EXTENSION to the suffixes whose own name is the better label (tsx/jsx/tf/tfvars/gradle) since the other 41 values already equal the language short name; label .hcl as hcl and .tfvars as tfvars instead of tf; accept .groovy alongside .gradle with its own short name; document that LANG_ALIASES also carries the persisted short ids; route the three inline alias lookups through grammarForHint; state that a short name may equal the grammar id; fix the util README wording.

Tests: cover .groovy, the four self-naming suffixes, and every id each suffix reaches through the shipped surfaces (the hand-synced LAZY_ALIASES list could not catch an alias whose target is neither boot nor lazy).
2026-09-23 19:57:19 +08:00
turtle1999 51d70c5f5c feat(plugins): report incompatible versions as typed refusals
Compatibility checks now yield the refused packages as data instead of a
profile-specific sentence. runProfilePnpm returns them as
PackageResult.incompatible, and the plugin manager refuses with the
incompatible-version code carrying the same records. Each surface renders
them: the CLI prints the exact allow-version command for its profile, the
Web plugin manager words them through its locale dictionary, and app-boot
keeps one neutral English diagnostic for logs and startup stderr.
2026-09-23 19:51:29 +08:00
mektpoy c5c09c9afa Merge remote-tracking branch 'origin/master' into feat/unify-code-highlight-languages 2026-09-23 19:49:34 +08:00
imccyu 96a4607ba2 test(chat): refresh work detail snapshots and preparation progress 2026-09-23 19:48:45 +08:00
imccyu 6943f9fee6 fix(chat): satisfy hook documentation and lint contracts 2026-09-23 19:48:45 +08:00
imccyu 5a32aae571 docs(chat): align preparing hooks and work detail modes 2026-09-23 19:48:45 +08:00
imccyu 1b55f5bea3 fix(chat): retain preparing tools and ordering until step completion 2026-09-23 19:48:45 +08:00
imccyu 4987e90b32 fix: static 2026-09-23 19:48:45 +08:00
imccyu ac77cefba7 test(chat): cover work detail modes and preparation subscriptions 2026-09-23 19:48:45 +08:00
imccyu d6fb1351b3 fix(chat): refine verbose headers and file preparation rows 2026-09-23 19:48:45 +08:00
imccyu 015a9b202c feat(chat): add four work detail modes and legacy mappings 2026-09-23 19:48:45 +08:00
imccyu b660f72d4e feat(tool): show content preparation progress for file mutations 2026-09-23 19:48:45 +08:00
mektpoy 63797c0208 docs(client): retire the sidebar note's window-drag pulse claim
The retained-tab-layout note still stated that existing window-drag region pulses remain; this layer's pulse is gone and the shell watcher replaces it. Rewrite both sides and re-record the pair.
2026-09-23 19:48:22 +08:00
mektpoy 7dfad90748 fix(client): keep the drag watcher alive through a slide and stop a float being dragged
The recall watcher now tolerates a short quiet window so a report that arrives before a CSS transition moves anything cannot end the loop on its first unchanged sample, re-arms on a transition or animation that touches a marked row, and re-arms on a child list change in a container holding one. A dock picture withdraws its strip's drag claim while a pane floats, because a float sorted before that row would otherwise sit earlier in the document and lose its own subtraction. The settings panel closes when an onboarding step appears, since the step's overlay marks only #root inert. Prose and the two Agent Notes record the Windows narrowing of the Platform overlay return bar, the collection rule, and the rows' one home in the ui-theme manifest.
2026-09-23 19:45:14 +08:00
Yudong Han fb8bb16345 Merge pull request #5052 from deepseek-harness/fix/zoom-rerender
fix(preview): redraw PDF and Office pages after pinch zoom
2026-09-23 19:42:44 +08:00
Yichen Jiang 2152881fcf fix(app-boot): preserve routed resolution errors under async module hooks
Node's module-hooks thread serializes resolver errors and returns the stack
accessor as a read-only configurable data property. Rewriting the routed
importer then assigned error.stack, threw a TypeError, and replaced the
original ERR_PACKAGE_PATH_NOT_EXPORTED or ERR_MODULE_NOT_FOUND error, so
plugin metadata reported a failure instead of falling back to package fields.

The importer rewrite now redefines a rejected stack value in place and
rethrows the original error with its code.
2026-09-23 19:42:34 +08:00
mektpoy f1869391d1 Merge remote-tracking branch 'origin/master' into fix/truncate-without-splitting-surrogates 2026-09-23 19:37:43 +08:00
yudshj 312341970c Merge master into fix/zoom-rerender 2026-09-23 19:31:59 +08:00
mektpoy e39b0c307c fix(client): align the image lightbox and image button rings
Master's newest commits add `.close` in ImageLightbox and `.imageButton` in
MarkdownText, each declaring the brand token directly. Both now read
`--dsw-focus-ring-color` through `--dsw-focus-ring-width`, as the stylesheet
corpus spec requires of every client focus rule.
2026-09-23 19:31:07 +08:00
mektpoy fefead85e9 Merge remote-tracking branch 'origin/master' into fix/focus-ring-brand-primary 2026-09-23 19:29:43 +08:00
imccyu 9b510d89a5 Merge pull request #5029 from deepseek-harness/feat/chat-image-preview-4941
feat(chat): 图片链接悬停预览与内联图片放大
2026-09-23 19:27:02 +08:00
Yudong Han 896c81d796 Merge pull request #5047 from deepseek-harness/fix/excel-trackpad-dark-mode
fix(web): support free spreadsheet trackpad panning and readable controls
2026-09-23 19:26:26 +08:00
lsdsjy 57a98bff5f fix(account): use medium weight for bonus notice title 2026-09-23 19:17:00 +08:00
turtle1999 747c98b0db fix(plugins): deny incompatible bundles and clarify compatibility refusals
A bundle package is not a plugin row, so startup admission never read its
own DSH peers: a bundle installed outside DSH or before a DSH upgrade still
applied its patch layer. loadProfileDirectory now skips such a bundle like an
unreadable one unless the profile exempts that exact pair.

A post-install refusal in a profile without a lockfile reinstalls from the
restored manifest instead of failing a frozen install and leaving the
rejected packages in node_modules.

Compatibility warnings now name the `dsh plugin allow-version` command for
CLI-managed profiles, startup denials name the row id instead of a resolved
module URL, and the CLI no longer reports "pnpm failed" when pnpm never ran.
2026-09-23 19:14:19 +08:00
Turtle 5ea77078d6 feat(plugins): enforce DSH peer compatibility with exact exemptions (#4980) 2026-09-23 18:56:56 +08:00
turtle1999 2c67633990 feat(plugins): enforce DSH peer compatibility with exact exemptions 2026-09-23 18:46:08 +08:00
mektpoy 58c70c2cca test(web): key the no-default marker to the platform that owns it
The new no-default scenario cleared the macOS application catalog, which
does nothing on Linux: `gio mime` owns the OS default there, and the
Linux stub never wrote the launch log, so CI timed out waiting for the
application gesture. Clear the marker each platform actually reads, log
launches from both stubs, and compare the launched id against the
platform's own registration id.
2026-09-23 18:41:50 +08:00
mektpoy 4ba758f47f Merge origin/master into fix/truncate-without-splitting-surrogates
Conflict resolution:
- docs/config-catalog: regenerate the English page; the Chinese page follows the
  three shifted Config sources and the bilingual pair record is re-recorded.
- docs/module-graph: the generator rewrites all three artifacts together.
- packages/shell/tool-pwsh-persistent/src/index.ts: keep master's rewrite of the
  prompt handling and re-apply the surrogate cap and its import.
- The three package.json dependency entries follow master's workspace:* range
  convention, and the lockfile importer specifiers match them.
2026-09-23 18:28:28 +08:00
mektpoy 5b4be3cfe8 fix(client): align the icon button's ring with the shared ring colour
Master's newest agent-preset sheet carries both the new `.helpButton` and the
retained `.iconButton`, whose focus ring still declared the brand token
directly. The stylesheet corpus spec rejects that form, so it now reads
`--dsw-focus-ring-color` with the brand-token fallback.
2026-09-23 18:21:14 +08:00
mektpoy ef7f44662d Merge remote-tracking branch 'origin/master' into fix/focus-ring-brand-primary
ui-theme/README.md, README.zh.md and README.i18n.yaml conflicted again: master
extended the `design-platform.css` sentence with the `--dsw-alias-file-diff-*`
palette. Kept that sentence together with this branch's `focus.css` paragraphs
and the seven-sheet entry list, then re-recorded the pairing hashes.
2026-09-23 18:20:56 +08:00
mektpoy fd5c4043fa Merge remote-tracking branch 'origin/master' into feat/window-drag-coverage
# Conflicts:
#	packages/client/ui-settings-general/package.json
2026-09-23 18:14:37 +08:00
mektpoy 20315dd321 Merge remote-tracking branch 'origin/master' into fix/windows-file-open-and-preview 2026-09-23 18:13:37 +08:00
yudshj 19d6df2b2f fix(web): pan read-only spreadsheets on both trackpad axes 2026-09-23 18:13:19 +08:00
yudshj e0e8327992 fix(preview): redraw PDF pages after settled zoom 2026-09-23 18:12:21 +08:00
imccyu 7eb9629e0a Merge pull request #5041 from deepseek-harness/fix-gateway-mem
fix(gateway): bound stream cancellation retention
2026-09-23 18:10:58 +08:00
Turtle 4aa207c5fe feat(preset): add plugin practices reference to creator skill (#5025)
* feat(preset): add creator-mode plugin practices skill

Creator mode mounts packages/preset/agent-preset/skills. The new
cordis-plugin-practices skill states Harness-specific principles and
concrete rules for plugins that survive upgrades and avoid polling or
rescanning session logs: waterfall delegation, restrict/guard over
assemble, agent.ctx ownership, no new session event types from profile
plugins, session projections, and slot-based UI.

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

A separate skill competed with cordis-plugin-development for the same
trigger. The practices now live in references/practices.md, read from
procedure step 2 before choosing an extension point.

* feat(preset): require Harness components and tokens for plugin pages

A creator-built management page served as an iframe with its own
stylesheet could not match the Harness design. The practices reference
now requires slot-rendered React pages built from ui-primitives, theme
tokens from Theme inspection, and light/dark checks in the real slot.

* feat(preset): make host UI consistency a principle and a verification step

Adds principle 6: the rendering surface decides whether a plugin can
match the Harness UI, so it is chosen before any view. Step 4 of
cordis-plugin-development now verifies primitives, token-only styles,
and light/dark rendering beside a comparable host page.

* feat(preset): prefer theme tokens over pre-stable ui-primitives

ui-primitives is a pre-stable platform module; creator plugins are plain
JS without type checks, and a throwing component blanks the slot entry.
The practices reference now treats tokens as the default way to match
the host, limits primitives to behavior that is costly to reproduce, and
tells the agent how to detect a slot entry crash after an upgrade.

* feat(preset): forbid runtime imports of Harness Client packages in plugins

Creator plugins must assume ui-primitives and other Client packages break
without notice. The practices reference now has plugins copy markup, CSS,
and behavior from primitives, or inspect the rendered host control, and
keep --dsw-alias-* tokens as the only shared styling dependency.

* fix(preset): correct plugin practices against runtime behavior

- agent.ctx registrations need a plugin-owned disposer too; plugin
  unload does not remove them.
- Timers start work with followup(); inject() does not wake the agent.
- inject() logs agent/inbox/spliced at call time; agent/request cannot
  change messages.
- Guards are synchronous; awaited decisions return ask from
  tools/pre-execute.
- Chat node renderers are keyed by kind; slot inject reinstalls on
  declaration return.

skills.spec now keeps whole-file cordis-plugin-development references
below the pruner threshold as the read tool renders them.
2026-09-23 18:06:52 +08:00
mektpoy c5e0a407ca test(web): cover the file menu when no application is the OS default
The reported defect is the branch where the Shell lists associated
applications but marks none as the default: the split button promoted
"Show file location" to the primary action and hid the applications
behind the menu.

Record that state in the keyless document-preview scenario. The new
golden pins the primary action to the opening control, and the gesture
log asserts the main button opens the file while the menu's marked
default launches the first registered application.
2026-09-23 18:05:08 +08:00
mektpoy 9fd52295fc fix(client): finish the ring-colour sweep and name the tooltip/ring split
Two focus treatments still named a colour of their own: the TurnNavigator
mark's tick filled with `state-business-primary` under a comment that already
claimed the brand colour, and the plugin inventory search input drew its focus
border in `state-business-primary` while the shadow beside it read
`--dsw-focus-ring-color`. Both now read the same ring colour as the rest.

`Tooltip` states why it takes `pointerModality()`'s wide answer while focus
rings read the narrower `data-input-modality` attribute the module publishes.
2026-09-23 17:58:06 +08:00
mektpoy 27ba49aa13 Merge remote-tracking branch 'origin/master' into feat/unify-code-highlight-languages 2026-09-23 17:57:38 +08:00
mektpoy 68e826a42f docs(client): record the window drag modules and the settings overlay placement
The ui-web source map gains the two window-drag modules and its boot row names the watcher install; ui-settings-general states that the settings panel portals beside #root. Both pairs are re-recorded. The ui-settings-general manifest keeps master's dependency order so only the two new dev entries appear in its diff.
2026-09-23 17:54:28 +08:00
yudshj e4234651ee fix(web): support spreadsheet tab gestures and readable name box 2026-09-23 17:52:13 +08:00
_Kerman ff1c7d415f fix(workspace): keep the default Workspace path language-neutral
The first-use directory name and its stored title came from the Client's
startup language, so one product decision carried two incompatible
requirements: a path addressed by shell commands, tool arguments, @path
references, and session logs, and a label a reader reads.

The controller now owns the fixed `default-workspace` directory name and
the registry titles the Workspace after that same segment, so
`workspace.initializeDefault` takes no request at all —
WorkspaceInitializeDefaultRequest and its name validation are gone, and
the registry resolver returns a path instead of a path and title. No
language reaches the Host.

Browser consumers label a Workspace through the new
`workspaceDisplayTitle`: a title still equal to the automatic one reads
as the localized default name from the `common` namespace, every other
title reads verbatim. The Workspace browser resolves it once at the store
read, so rows, hover card, search meta, and the rename and delete dialogs
inherit it; the hero picker and the Conversation chip resolve it too.
Confirming a rename stores the text on screen, which is what stops a row
following the language.
2026-09-23 17:46:32 +08:00
Xu Hanxiang c5dc0853d6 Merge pull request #4686 from deepseek-harness/fix/desktop-dev-runtime-target
fix(desktop): resolve the development runtime directory from the build target
2026-09-23 17:43:43 +08:00
lsdsjy 850d78b798 fix(account): refresh after top-up and accept exponent balances 2026-09-23 17:42:15 +08:00
lsdsjy 9987cae3ea fix(desktop): apply shared toast theme in welcome 2026-09-23 17:29:24 +08:00
lsdsjy e310916e59 refactor(llm): let providers resolve request authentication 2026-09-23 17:29:24 +08:00
lsdsjy 8f180cf45f fix(account): deliver credential expiry notices without replay 2026-09-23 17:26:01 +08:00
lsdsjy 8e5866e7b0 fix(models): retain API-key provider catalogs without credentials 2026-09-23 17:23:39 +08:00
Kaige-Gao bd2a49a2ca fix(chat): use elevated scrollbar colors for image previews 2026-09-23 17:22:55 +08:00
lsdsjy 5590fbee7c fix(account): update sign-in dialog copy 2026-09-23 17:22:45 +08:00
Xinyu Yang cec4e70f8d fix(settings): let modal restore preset guide focus 2026-09-23 17:21:45 +08:00
imccyu 45f5cd34b0 fix(gateway): pass explicit undefined in retention test 2026-09-23 17:20:38 +08:00
Xu Hanxiang 62aef4c583 Merge branch 'master' into fix/desktop-dev-runtime-target 2026-09-23 17:19:03 +08:00
lsdsjy 51be61db98 Merge origin/master into feat/account-bonus-notices 2026-09-23 17:15:22 +08:00
Kaige-Gao 4839239954 fix(chat): address image preview review and coverage gaps 2026-09-23 17:12:03 +08:00
Ziya e68fb0bc8d Merge pull request #5022 from deepseek-harness/fix/subagent-zh-terminology
fix(i18n): 将 UI「子代理」改为「子智能体」
2026-09-23 17:08:26 +08:00
imccyu 4cfd292a7b fix(gateway): bound stream cancellation retention 2026-09-23 17:07:09 +08:00
Xinyu Yang 1aebb43147 fix(web): wait for sidebar collapse in delivery test 2026-09-23 17:02:19 +08:00
ZiyaZhang dc0ae81905 Merge remote-tracking branch 'upstream/master' into fix/subagent-zh-terminology 2026-09-23 01:54:16 -07:00
Xinyu Yang afbd10991a chore: update temporary CI merge to latest master 2026-09-23 16:44:04 +08:00
mektpoy a8776afa87 Merge remote-tracking branch 'origin/master' into fix/desktop-dev-runtime-target 2026-09-23 16:43:00 +08:00
Xinyu Yang 31688747ad chore: temporarily merge master for CI validation 2026-09-23 16:41:44 +08:00
Yudong Han 219db5454a Merge pull request #5027 from deepseek-harness/fix/excel-preview-sheet-navigation
fix(web): separate spreadsheet tab navigation from zoom controls
2026-09-23 16:38:47 +08:00
ZiyaZhang 3675e91cf9 fix(i18n): update subagent labels added on master 2026-09-23 01:34:17 -07:00
Yudong Han 5e25475857 fix(office): use bundled LibreOffice Kit 0.1.0 CLI across deployments (#4902)
* chore(office): upgrade libreoffice kit to 0.0.1-2

* fix(office): guide bounded CLI rendering and preview reuse

* chore(office): consume published LibreOffice Kit 0.0.3

* test(office): mock the complete LibreOffice converter interface

* chore(office): upgrade LibreOffice Kit to 0.0.4

* fix(office): expose bundled LibreOffice Kit 0.1.0 CLI across deployments

* fix(office): inspect Excel visuals only for layout tasks

* fix(office): allow compatible LibreOffice Kit 0.1 updates

* fix(office): stop Excel QA on blank previews and run regressions in CI

* fix(office): end workbook visual QA after an empty preview
2026-09-23 08:32:15 +00:00
ZiyaZhang f4c6b012aa Merge remote-tracking branch 'upstream/master' into fix/subagent-zh-terminology 2026-09-23 01:32:15 -07:00
mektpoy fe4d18fda3 test(desktop): provide the required primary runtime directory in the welcome startup spec
`welcome-startup.spec.ts` imports the unpackaged main entry, which now
requires `DSH_DESKTOP_PRIMARY_RUNTIME_DIR`. Stub it beside the neighbouring
`DSH_DESKTOP_*` values so the suite reaches the welcome startup it covers.
2026-09-23 16:29:28 +08:00
Kaige-Gao 907a241b61 Merge remote-tracking branch 'origin/master' into feat/chat-image-preview-4941 2026-09-23 16:28:26 +08:00
imccyu e5e9b5b982 Merge pull request #4985 from deepseek-harness/feat/tool-call-preparing
feat(chat): show preparing tools during live generation
2026-09-23 16:24:46 +08:00
Kaige-Gao 7fe9c06fa6 feat(chat): preview image links on hover and expand inline images 2026-09-23 16:18:09 +08:00
yudshj c920174964 fix(web): separate spreadsheet tab navigation from zoom controls 2026-09-23 16:13:21 +08:00
imccyu 3776169373 test(client): align wait agent row title expectation 2026-09-23 16:11:44 +08:00
imccyu 19675fd061 fix(client): align subagent coordination and wait labels 2026-09-23 16:11:44 +08:00
imccyu 536764c8b4 test(web): align snapshots with write activity labels 2026-09-23 16:11:44 +08:00
imccyu b66b602c72 fix(chat): address preparing lifecycle review feedback 2026-09-23 16:11:44 +08:00
imccyu 913aa2289b fix(chat): unify tool lifecycle titles and activity labels 2026-09-23 16:11:44 +08:00
imccyu 701026b5bf test(chat): bind the preparation start spy 2026-09-23 16:11:44 +08:00
imccyu 5840898e07 perf(tool): retain unchanged subcall branches 2026-09-23 16:11:44 +08:00
imccyu b2817d77fb perf(chat): batch preparing tool updates 2026-09-23 16:11:44 +08:00
imccyu a60d4df027 test(desktop): await ASAR fixture output completion 2026-09-23 16:11:44 +08:00
imccyu 833835d95c test(chat): retire unknown casts from tool row fixtures 2026-09-23 16:11:44 +08:00
imccyu 74511b3dcb test(chat): cover live preparation and durable history replay 2026-09-23 16:11:43 +08:00
imccyu d3086e6571 feat(chat): present tools in preparing, start, and result stages 2026-09-23 16:11:43 +08:00
imccyu d550f1c4af feat(conversation): initialize contexts from transient start matches 2026-09-23 16:11:43 +08:00
Turtle ccaa0dc11c fix(plugin-manager): bound pnpm runs so a silent child cannot hold the profile lock (#4982)
* fix(plugin-manager): bound pnpm runs so a silent child cannot hold the profile lock

A pnpm child that prints its completion line and then never exits holds the
profile write lock until the host is restarted, so every other session and host
on that profile fails after its own lock timeout (issue #4981). execa resolves
its promise only once the piped stdio has ended, so a run now completes on the
process's own exit and drains the pipes under a bound instead of awaiting their
end.

A service run whose captured output stays silent for idleTimeoutMs is
terminated, reports timedOut alongside its exit status, and is not retried on
the next registry; a run with inherited descriptors captures nothing and is
left unbounded for its operator.

* test(plugin-manager): type the mocked child and await the drain descendants

The inherited-descriptor fixture no longer needs its legacy `as unknown` cast,
because the mocked child is typed for the fields the operations read; the
retired baseline entry is pruned (verify-no-unknown-casts).

The drain specs wait for the killed descendant to exit before removing its
directory: Windows refuses to delete a directory a live process still holds.

* test(plugin-manager): stop the drain descendant deterministically

The descendant that holds the pipes now ends on a stop file the teardown
writes, and on its own after a minute, so the fixture leaves no process behind
when a kill cannot be delivered. Windows stops it through taskkill, and the
spec waits for the exit before removing the directory it ran in.

* test(plugin-manager): run the drain descendant from its own script file

Windows cannot carry a nested `-e` script through another spawn argument: the
descendant failed to start there, so the fixture asserted on a process that was
already gone. The descendant now runs from a script file the fixture writes.

* test(plugin-manager): cover the bounded drain everywhere and stage the real descendant on POSIX

Windows does not stage a descendant that keeps the inherited pipes open past
the direct child's exit, so the real-process cases run on POSIX only. The
mocked child now models execa's own completion rule — its promise settles only
once both pipes end — which covers the bounded drain on every platform and
still fails without the raw-exit race.

* test(plugin-manager): cover the drain failure path without a child process

An output consumer failure that the bounded drain cuts short is staged with the
mocked child as well, so the per-file coverage gate also holds where the
real-process cases are skipped.

* fix(plugin-manager): terminate the whole tree of a stalled run

A lifecycle script is a child of pnpm, so signalling pnpm alone left an
approved postinstall writing into the profile after the operation reported a
timeout and released the lock. A stalled run now stops its process group (or
Windows process tree) and waits for it to disappear before the caller restores
the files. The cut tail's close is told apart from a reading failure by where it
happened, so a failure from before the cut still surfaces.

* docs(plugin-manager): regenerate the config catalog after the rebase

The English catalog gains `idleTimeoutMs` from the regenerator, and the Chinese
counterpart carries the same interface line so the pair stays consistent.

* fix(plugin-manager): terminate a run's tree through execa, keeping exit cleanup

Spawning a service run with `detached` made execa skip the handler that kills
the child when the manager exits, so a crashed manager left the pnpm tree
running in the profile. `killDescendants` spawns the run as its own process
group while keeping that cleanup, and it addresses the tree on every kill path,
including cancellation. The module now only decides the probe target and waits
for quiescence.
2026-09-23 16:11:30 +08:00
Jiawei Song 19844ea9ad Merge pull request #5001 from deepseek-harness/fix/diff-review-colors
fix(web): 优化文件 diff Review 的浅色和深色配色
2026-09-23 16:09:33 +08:00
ZiyaZhang a2278b460c fix(i18n): limit subagent terminology changes to requested UI copy 2026-09-23 01:09:27 -07:00
Xinyu Yang d0861be2cd fix(shortcuts): restore PRD reference order 2026-09-23 16:04:22 +08:00
mektpoy 80e4da0e3d fix(desktop): take the development project target as an explicit input
`prepareDevelopmentProject()` resolved the build target from the host
platform and architecture, so a Linux host threw `unsupported target
linux-x64` while writing the runtime descriptor. Pass the target in
instead: the launcher supplies the target it prepared, and isolated tests
supply a fixed supported target.

Extract `desktopTargetPlatform()` into desktop-build-paths.mjs so the
target-to-payload mapping has one home, and use it for the qualification
runner, which previously derived both its target directory and its
descriptor from the host architecture.

Correct the README limitation to name the module that now performs the
architecture check.
2026-09-23 16:03:17 +08:00
ZiyaZhang f132684c81 fix(i18n): scope subagent terminology to UI and refresh snapshots 2026-09-23 00:57:07 -07:00
lsdsjy e9a438d9e9 chore: merge master into account provider branch 2026-09-23 15:52:07 +08:00
Turtle 3d6d46b8a6 Merge pull request #4896 from deepseek-harness/fix/preset-ui-20260921
fix(ui-agent-preset): restore the read-only configuration viewer
2026-09-23 15:50:34 +08:00
Yudong Han dd004b4221 fix(web): simplify read-only spreadsheet preview controls (#5006)
* fix(web): simplify read-only spreadsheet preview controls

* fix(web): soften read-only spreadsheet freeze dividers

* fix(web): hide read-only spreadsheet freeze dividers

* fix(web): keep spreadsheet formula bar on one line
2026-09-23 07:46:13 +00:00
Xu Hanxiang 38596d5c70 Merge pull request #4876 from deepseek-harness/fix/windows-open-through-explorer
fix(native-command): open Windows paths through explorer.exe
2026-09-23 15:46:04 +08:00
mektpoy b1eebbd045 fix(lockfile): drop re-resolution churn from the merge-forwards
pnpm install --lockfile-only, run to align the new workspace edge's specifiers, also re-resolved unrelated entries: it pinned registry.npmjs.org tarball URLs on the two libreoffice-kit optional platform packages and downgraded glob 7.2.3 to 7.2.0. The tarball URLs fail verify-lockfile-policy against the mirror's published metadata.

Rebuild the file as the base lockfile plus only the three intended importer additions (the new package's block and its two consumers), so the resolution entries stay byte-identical to master.
2026-09-23 15:41:12 +08:00
mektpoy 8b75ec9903 Merge remote-tracking branch 'origin/master' into feat/unify-code-highlight-languages 2026-09-23 15:39:36 +08:00
ZiyaZhang 8833ef9f63 Merge upstream/master into fix/subagent-zh-terminology 2026-09-23 00:38:59 -07:00
ZiyaZhang 995caa05ed fix(i18n): translate subagent as 子智能体 in Chinese UI 2026-09-23 00:33:41 -07:00
lsdsjy b8df537f07 fix(desktop): return to initial welcome page after sign-out 2026-09-23 15:28:12 +08:00
Yifffan 10292baeff Merge pull request #4818 from deepseek-harness/ui/agent-team-header-panel-refine
feat(web): refine the Team header panel interactions and adaptive header
2026-09-23 15:26:24 +08:00
Turtle bbeef5f250 Merge pull request #5020 from deepseek-harness/copy/plugin-experimental-labels
fix(web): label beta features as experimental
2026-09-23 15:24:43 +08:00
turtle1999 d52424042c Merge remote-tracking branch 'origin/master' into fix/preset-ui-20260921 2026-09-23 15:21:17 +08:00
Dudu-0223 2ea753960c fix(web): align Team card elevation and preset header expectations 2026-09-23 15:14:29 +08:00
Dudu-0223 2b44a4b657 fix(web): preserve Team hover pinning and responsive task expansion 2026-09-23 15:14:29 +08:00
Dudu-0223 4face54ea7 test(web): align adjacent navigation snapshots with header UI 2026-09-23 15:14:29 +08:00
Dudu-0223 0b62921f37 test(web): align Team panel snapshot with pinned projection UI 2026-09-23 15:14:29 +08:00
Yif 86e3e0e448 feat(web): refine the Team header panel interactions and adaptive header
The Team panel opens on hover with the subagent-catalog grace timings, pins
on click, polls the one-shot view RPC every 20s while open (replacing the
toolbar refresh/close controls), and eagerly loads on mount so the trigger
keeps a stable two-person icon. The lead card navigates from teammate
conversations, the current conversation carries a Current chat tag (selected
ring only among multiple members), task descriptions clamp to two lines
behind an expand toggle, an empty board shows a one-line description, and a
lone member narrows the panel to one column.

The header title row becomes an inline-size container: the preset label
hides first, then the Team trigger collapses to its icon and switches to
click-only opening. The subagent catalog moves to the front of the actions
band so lineage stays beside the title crumbs, and its pinned-menu behavior
matches the Team panel. Tooltip gains a gap prop for tight anchors.
2026-09-23 15:14:29 +08:00
Dudu-0223 61936aa113 Merge pull request #4810 from deepseek-harness/feat/agent-team-projection-panel
feat(agent-team): drive the Web Team panel from the agentTeam projection
2026-09-23 15:14:25 +08:00
Turtle 3b8be2928f Merge pull request #5017 from deepseek-harness/turtle/fix-tooltip-layering-e1cc527c20d0
fix(web): keep composer-stack tooltips above the input card
2026-09-23 15:14:07 +08:00
lsdsjy 150303ff22 fix(account): refine bonus notice lifecycle and diagnostics 2026-09-23 15:13:29 +08:00
ZiyaZhang 3c20f401d2 fix(web): label beta features as experimental 2026-09-23 00:07:13 -07:00
lsdsjy 9e19ca3e45 fix(account): limit automatic model selection to account login 2026-09-23 15:06:00 +08:00
turtle1999 a56e82e5dd fix(ui-agent-preset): share reader keyboard focus handling 2026-09-23 15:02:27 +08:00
Turtle a96d45af40 test(web): name the covering element in the tooltip hit test
Review follow-up on the tooltip layering fix. The helper probes
`bubble.contains(hit)` instead of identity, so a bubble that grows child
elements still passes, and each probe returns the hit element's tag and
class, so a regression reports what covered the bubble instead of a bare
`expected false to be true` — the pre-fix run now names `DIV.u82K-q_input`
for both probes.

The `portal` JSDoc says the ancestor stacking context confines the
bubble's z-index to that context rather than resolving it against
siblings.
2026-09-23 15:00:52 +08:00
Dudu-0223 63cc821e7e Merge master into feat/agent-team-projection-panel 2026-09-23 14:57:32 +08:00
Dudu-0223 df7fa8945c refactor(agent-team): narrow projection fields and task views 2026-09-23 14:54:21 +08:00
mektpoy ef0eaa3167 docs(code-language): restate the read-hint contract in the summary
The Summary narrated the change ("the suffixes the old read table recognized keep their historical value") rather than the contract, and at 109 words it exceeded the 100-word package Summary limit.

State the rule a reader at HEAD can act on: a suffix a recorded session already holds keeps its persisted value, every other suffix takes its language's short name. The dropped path-separator and leading-dot detail stays documented under Language selection. Both languages updated and the pairing record re-recorded.
2026-09-23 14:53:58 +08:00
mektpoy 192ab1155d fix(code-language): match the root release version
The package joined the workspace as version 0.1.6-alpha.2 while the root release moved on, which failed three CI jobs from one cause: constraints (version must match root), Dependency layout (verify-npm-install-layout finds no workspace version), and Pack npm tarballs (dsh release members must share one version).
2026-09-23 14:53:52 +08:00
mektpoy edd0a438bf docs(native-command): state that the Explorer handoff acknowledgement proves no open
The open paragraph accepted Explorer's exit code 1 as a delegated handoff but
did not repeat the reveal paragraph's warning that the acknowledgement proves no
application opened the file, which the Agent Note records for the Remote answer
`{ opened: true }`.
2026-09-23 14:49:30 +08:00
turtle1999 02383832df Merge remote-tracking branch 'origin/master' into fix/preset-ui-20260921 2026-09-23 14:45:13 +08:00
lsdsjy 40da69ff75 refactor(account): isolate provider authentication and preserve model selections 2026-09-23 14:43:47 +08:00
Turtle 5082e05f71 fix(web): keep composer-stack tooltips above the input card
The goal strip and the queue dock ride directly above the input card, and
both create a stacking context (`isolation: isolate`) so their frosted
panel stays behind their own content. A tooltip bubble left inside that
context resolves its z-index there, where the card — painted later in the
same context — wins: the goal strip's bubble showed a two-pixel sliver
and the queue dock's stayed entirely hidden.

Portal those dock tooltips to the body, where the bubble's z-index
resolves above the whole card. The ui-primitives `portal` contract now
names the capping stacking context beside clipped containers, because
neither container clips its bubble.

The queue-actions aria goldens lose the tooltip line: the captured center
column no longer contains the portaled bubble. The scenario still covers
it by role and adds a hit test at the bubble's center and bottom edge, as
does goal-bar.
2026-09-23 14:43:23 +08:00
sjw1231 c4955b1900 test(web): strengthen diff review color assertions 2026-09-23 14:42:08 +08:00
Ziya 354da32a38 Merge pull request #4979 from deepseek-harness/fix/github-install-connectivity
fix(plugin-manager): fail fast on stalled GitHub connections
2026-09-23 14:38:25 +08:00
Xinyu Yang f6006c5547 fix(shortcuts): finish modal toggles and automatic focus handling 2026-09-23 14:34:20 +08:00
Dudu-0223 f546068553 fix(agent-team): align package metadata with merged release 2026-09-23 14:27:58 +08:00
mektpoy 88b1ea3c0b docs: state the code-language comments as current contracts
The new JSDoc and test prose narrated the change instead of the shipped
behavior: "pre-unification", "the old read table", "used to persist ... it
now persists". A reader at HEAD cannot resolve those stages, and the
persisted-value rule they describe is a durability contract that stands on
its own.

Restate each as the present contract: a suffix whose value a recorded
session already holds keeps it byte-identical; every other suffix takes its
language's short name. Rename the test's transcribed expectation away from
the branch vantage and re-wrap the module comment the earlier edit left
over-long.
2026-09-23 14:23:07 +08:00
mektpoy 5774f385f4 Merge remote-tracking branch 'origin/master' into feat/unify-code-highlight-languages
# Conflicts:
#	packages/client/ui-primitives/package.json
#	packages/fs/tool-fs/package.json
2026-09-23 14:19:53 +08:00
Dudu-0223 3bf6d738f1 fix(agent-team): keep late activation on normal reconnect path 2026-09-23 14:16:57 +08:00
Yichen Jiang 26b4980364 feat(voice-input): guide unready microphones to plugin setup 2026-09-23 14:15:26 +08:00
Yudong Han 5124a2a310 fix(web): show model IDs in monospace and names on hover (#5004)
* fix(web): show original model IDs on hover

* fix(web): display model IDs with names on hover
2026-09-23 06:10:30 +00:00
Dudu-0223 2aa3a469db fix(agent-team): consume shared projections without panel loads 2026-09-23 14:08:25 +08:00
winewill 0126d5be20 fix(desktop): load the flock entry lazily and build native/system on demand
`package-target.ts` imported `macos-notarization-proxy.ts`, whose top-level
import of `@deepseek-ai/node-addon-system/flock` resolves through the package
`exports` to the unbuilt `lib/flock.js` on a clean checkout. The step that
emits that file runs inside the same packaging script, so `check:package`,
`package:*`, and the `restore:mac-proxy` recovery command all failed with
`ERR_MODULE_NOT_FOUND` before reaching it; running `pnpm run typecheck` first
left the host addon binary missing instead, which failed at lock time.

The proxy lock now loads the entry at first use through `flock-entry.ts`. When
the import is unresolvable or the host platform package lacks a binary listed
in its `prebuilds.json`, the loader runs `pnpm run build:native-system` and
`pnpm --dir native/system run build:ts` before importing again; other errors
and build failures propagate, and a failed load is retried by the next call.
`check:package` no longer touches the entry at all.

Tests cover the loader steps and load the proxy module from a directory where
the addon package cannot be resolved. The Desktop README records the
behavior in both languages.

(cherry picked from commit 2d74cf50310d4efbbccbbe79a105fcc3a468b19d)
2026-09-23 14:03:10 +08:00
Dudu-0223 3f07e34b5e Merge remote-tracking branch 'origin/master' into codex/pr-4810-review-fixes
# Conflicts:
#	packages/experimental/agent-team/package.json
#	packages/experimental/client-ui-agent-team/package.json
#	pnpm-lock.yaml
2026-09-23 13:58:31 +08:00
ZiyaZhang d7b45fb415 Merge remote-tracking branch 'origin/master' into fix/github-install-connectivity 2026-09-22 22:18:07 -07:00
ZiyaZhang 75d74a055e fix(plugin-manager): preserve authentication fallback during GitHub checks 2026-09-22 22:15:09 -07:00
turtle1999 f68d4b5aba Merge remote-tracking branch 'origin/master' into fix/preset-ui-20260921
# Conflicts:
#	packages/preset/agent-preset-registry/package.json
2026-09-23 13:08:30 +08:00
Yichen Jiang 752953d2b6 Merge pull request #4966 from deepseek-harness/worktree/voice-model-download-mirrors
feat(voice-input): support automatic and manual model download sources
2026-09-23 13:01:51 +08:00
mektpoy 2b9923fede fix(native-command): escape both Explorer field separators and keep non-ASCII literal
On Windows 11 ARM64 build 26200 Explorer splits its own command line at
commas and equals signs and rejects percent-encoded non-ASCII in a file
URI, falling back to the Documents folder in both cases without reporting
it. `explorerTarget()` now escapes `=` next to `,` and decodes Node's
non-ASCII escapes back to the literal characters the shell resolves, so
the two rules stay in one place. The Agent Note and the target-encoding
table record the measured behavior.
2026-09-23 12:33:31 +08:00
winewill 4e41ccadcc build(desktop): check every import record and mirror the bundle step in the wine gate
The packaged-imports plugin moves from generateBundle to moduleParsed so
external dynamic import() and require() targets, which chunk metadata
omits, fail the bundle too. Each bundle now carries an import policy:
the main process allows Node builtins, sandboxed preloads only the
modules Electron's require polyfill resolves, and the failure names the
importing module and the allowed set. The wine Windows gate bundles
apps/desktop after the Host tsdown pass like build:lib:host, the
ts-build-config note lists that step, and the tsdown docs name the
workspace match exactly.

Fixes #4993
2026-09-23 12:03:48 +08:00
Ziya c3afd488aa Merge pull request #4962 from deepseek-harness/ux/plugin-install-20260922
feat(plugin-manager): offer mirror recovery for GitHub install failures
2026-09-23 12:03:47 +08:00
Yichen Jiang 3f0022a8fa Merge remote-tracking branch 'origin/master' into worktree/voice-model-download-mirrors 2026-09-23 12:03:11 +08:00
Turtle 040f47a822 Merge pull request #4987 from deepseek-harness/turtle/fix-title-overlap-b5d8f732773e
fix(ui-settings-account): clear the Windows caption for the Platform return bar
2026-09-23 12:02:28 +08:00
Ruilin Geng c68c6db9ca Merge pull request #4717 from deepseek-harness/fix/webkit-model-picker
fix(web): 修复 Safari 模型菜单鼠标选择失效
2026-09-23 11:59:53 +08:00
Yichen Jiang 0067efc8ae Merge pull request #4992 from deepseek-harness/worktree/pin-official-deepseek-first
fix(web): keep official DeepSeek first in model settings
2026-09-23 11:59:00 +08:00
Yichen Jiang d40dbef91b feat(voice-input): expose preparation download source selection 2026-09-23 11:58:54 +08:00
Yifffan 5bc57902d5 Merge pull request #4970 from deepseek-harness/docs/client-ui-ux-skill
docs(skills): add the dsh-client-ui-ux skill
2026-09-23 11:53:56 +08:00
lsdsjy fff88f7375 fix(desktop): harden Platform storage cleanup and identity publication 2026-09-23 11:30:37 +08:00
lsdsjy 2fc9262f3e chore: merge master into account provider branch 2026-09-23 11:19:22 +08:00
Yichen Jiang dc374b8879 fix(web): keep official DeepSeek first in model settings 2026-09-23 11:18:01 +08:00
lsdsjy c062c615dc feat(account): align signed-out sidebar menu with design 2026-09-23 11:13:27 +08:00
lsdsjy 4283f62d01 fix(desktop): leave sign-in activation to the completion page 2026-09-23 11:11:44 +08:00
lsdsjy 10b6ffec3f fix(desktop): use regular weight for welcome API key heading 2026-09-23 11:00:13 +08:00
lsdsjy be3ecb4977 fix(desktop): persist account-scoped Platform page preferences 2026-09-23 10:55:33 +08:00
Turtle 14a062acb7 docs(ui-settings-account): record the Platform view caption limitation
Review follow-up: the caption menu is inert while the Platform view is open,
which the previous geometry hid; state it under Known Limitations, and drop
the duplicated 40px figure the Desktop owns. The style spec's rule lookup
anchors on the rule boundary and asserts with toContain.
2026-09-23 10:47:17 +08:00
Turtle ceb997cdef fix(ui-settings-account): clear the Windows caption for the Platform return bar
The embedded Platform view renders its 48px return bar at the top of the
window. On Windows the Desktop-owned caption menu occupies that strip (fixed
at top 0, 40px high, z-index 1100), so the "Back to DeepSeek Harness" label
and the Application/Edit menu text were painted over each other.

Offset the overlay by --dsh-windows-titlebar-height where the Desktop preload
publishes its caption marker, the same clearance AppFrame and the sidebar
caption controls use. The return bar and the native view bounds, which come
from the viewport element's rectangle, both move below the strip.
2026-09-23 10:33:17 +08:00
gengruilin 60b5800816 Merge origin/master into fix/webkit-model-picker 2026-09-23 10:26:50 +08:00
ZiyaZhang 0edfe83573 fix(plugin-manager): bound GitHub connection checks before installation 2026-09-22 08:33:49 -07:00
imccyu 00102833df Merge pull request #4978 from deepseek-harness/worktree/release-dsh-0.1.7-alpha.2
release: [email protected]
2026-09-22 23:25:38 +08:00
imccyu 10ea83bcc3 release(dsh): 0.1.7-alpha.2 2026-09-22 23:12:55 +08:00
imccyu 178ee3a9eb Merge pull request #4975 from deepseek-harness/worktree/release-vendor-4.0.4
release(vendor): cordis 4.0.4, cosmokit 1.8.5, group 1.0.4, hmr 1.0.1…
2026-09-22 23:12:01 +08:00
ZiyaZhang 4bf9d2e0c0 Merge master into plugin installation recovery 2026-09-22 08:03:27 -07:00
imccyu d0dca04e22 release(vendor): cordis 4.0.4, cosmokit 1.8.5, group 1.0.4, hmr 1.0.19, include 1.0.9, loader 1.0.5, logger-console 1.0.4, schemastery 3.18.4, timer 1.1.6 2026-09-22 23:02:28 +08:00
imccyu 3950647caa Merge pull request #4954 from deepseek-harness/fix/dsh-exact-workspace-dependencies
build: 锁定 DSH 版本并将 vendor/native 依赖限制为补丁升级
2026-09-22 22:59:56 +08:00
imccyu 3889e97de0 Merge pull request #4947 from deepseek-harness/fix/chat-groups-followup
fix(chat): 稳定滚动控件与嵌套自动跟随
2026-09-22 22:59:36 +08:00
lsdsjy 081526aa3e feat(account): show bonus notices after visible display 2026-09-22 22:51:09 +08:00
imccyu 08c0e8e71b fix(chat): deduplicate admitted local steering 2026-09-22 22:47:12 +08:00
lsdsjy 3970cc974f feat(account): send client metadata with Platform requests 2026-09-22 22:42:11 +08:00
imccyu 43a8a22824 fix(chat): restore turn rail width threshold and clarify scroll gestures 2026-09-22 22:25:32 +08:00
lsdsjy 318c83fa84 chore: merge master and restore PR validation 2026-09-22 22:25:13 +08:00
Dudu-0223 9095678c8c fix(agent-team): address remaining projection review comments 2026-09-22 22:21:10 +08:00
Dudu-0223 9fcb76d9bc Merge remote-tracking branch 'origin/master' into codex/pr-4810-review-fixes 2026-09-22 22:17:37 +08:00
imccyu f6966f8fab test(client): align resize fixtures and restore branch coverage 2026-09-22 22:08:50 +08:00
imccyu fad9e27706 test(web): stabilize resize and scroll fixtures 2026-09-22 21:44:39 +08:00
imccyu 838eff14eb fix(chat): preserve reading intent around group scrolling 2026-09-22 21:44:00 +08:00
imccyu 4e6028a604 build: use tilde ranges for vendor and native workspaces 2026-09-22 21:14:06 +08:00
imccyu b9b5f7c58e fix: complete exact DSH ranges in application and runtime manifests 2026-09-22 21:12:57 +08:00
imccyu 7021420f29 fix: validate dependency ranges across every workspace 2026-09-22 21:12:57 +08:00
imccyu 37372101b5 build: pin internal DSH workspace dependencies 2026-09-22 21:12:56 +08:00
imccyu c92d5ebe18 perf(ui): fit tooltips from observed sizes 2026-09-22 21:07:56 +08:00
imccyu 820824edd7 fix(chat): stabilize input echo admission and ordering 2026-09-22 21:07:55 +08:00
imccyu 50ba2c8bb2 fix(session): align history pagination with turn boundaries 2026-09-22 21:07:55 +08:00
imccyu 2251b6189b fix(chat): preserve sticky headers with overflow clipping 2026-09-22 21:07:55 +08:00
imccyu 13dfae20c3 fix(chat): settle native scroll following before retargeting 2026-09-22 21:07:55 +08:00
imccyu fb02779a26 fix(chat): restore turn rail container queries 2026-09-22 21:07:55 +08:00
imccyu 1f029fc442 docs(chat): record scroll ownership and control geometry 2026-09-22 21:07:55 +08:00
imccyu 633cf7394e fix(chat): share independent scroll following with native group animation 2026-09-22 21:07:55 +08:00
imccyu 6b4055bf32 fix(chat): keep floating controls outside transcript clipping 2026-09-22 21:07:55 +08:00
Yif e8d5278c46 docs(skills): fix review findings in dsh-client-ui-ux and add scrollbar rule
Point selectable hover content at HoverCard (Tooltip has no interactive
prop), require a persistently mounted toast host, scope the font-weight
cap to new feature CSS, prefer theme typography tokens, link the styling
owners, date the design-reviewer roster, add the scrollbar containment
rule, and make the skill discoverable from packages/client/AGENTS.md.
2026-09-22 21:03:30 +08:00
Xinyu Yang 120cac4ea7 refactor(conversation): keep stop shortcut turn tracking internal 2026-09-22 21:02:32 +08:00
Xinyu Yang 6a82709a2b fix(shortcuts): preserve focus and tab layout, block overlay input 2026-09-22 21:02:32 +08:00
Xinyu Yang 91423ea1b4 revert: restore configurable Web and desktop shortcuts
Restore the feature removed by #4886 on current master. Preserve the current settings entry point, moving-menu behavior, and desktop update UI.
2026-09-22 21:02:32 +08:00
imccyu 3dcfbf2094 Merge pull request #4964 from deepseek-harness/fix-reconnect
fix(web): gate reconnects on application readiness
2026-09-22 21:00:21 +08:00
Yif 6a07033145 docs(skills): require designer review for new icons and user-perceivable UI changes 2026-09-22 20:39:38 +08:00
mektpoy b66e51e7ab fix(client): align master's new focus rings with the shared ring colour
Four focus rings added on master after this branch's base still declared their
own colour: PresetGuideDialog's panel, CodeCard's action (state-business-primary),
SegmentedControl's tab, and AccountSection's link button (button-primary-fill).
The stylesheet corpus spec now rejects each of them, so they read
`--dsw-focus-ring-color` with the brand-token fallback like every other ring.
CodeCard keeps its 1px dense width; the other three take
`--dsw-focus-ring-width`.
2026-09-22 20:37:46 +08:00
mektpoy fae37cd705 Merge remote-tracking branch 'origin/master' into fix/focus-ring-brand-primary
Conflicts and how they were resolved:

- ui-agent-preset/AgentPresetSection.module.css: master replaced the icon-only
  tooltip actions (`.iconButton`, `.iconDanger`, `.revealedPath`) with
  `.cardHelp` + `.helpButton`, which deleted the one declaration this branch
  edited. Took master's structure and re-applied the branch's change to the two
  `.cardMain:focus-visible` rings, which master kept unchanged.
- ui-theme/README.md and README.zh.md: master documented the separately exported
  `brand-font.css`; this branch documented `focus.css`. Kept both, with the
  dynamic entry's sheet list at seven sheets including `focus.css`.
  `README.i18n.yaml` re-recorded with `verify-translation-pairing --write`.
2026-09-22 20:37:05 +08:00
mektpoy 5925925d20 Merge remote-tracking branch 'origin/master' into fix/desktop-dev-runtime-target
# Conflicts:
#	apps/desktop/src/main.ts
2026-09-22 20:30:25 +08:00
mektpoy a6b909c767 docs(native-command): correct the non-interactive Explorer claim
The recorded exit code 0 after about 30 seconds was not reproduced: an SSH
session 0 on Windows 11 ARM64 build 26200 measured exit code 1 after about a
second with no association invoked, the same exit code a delegated open
returns. The README, both Agent Note languages, and the `explorerTarget` JSDoc
now record that measurement, and the `Invoke-Item` contrast keeps its
qualitative part without the timing.
2026-09-22 20:29:24 +08:00
mektpoy 2063f667ea Merge remote-tracking branch 'origin/master' into fix/windows-file-open-and-preview
# Conflicts:
#	packages/util/native-command/README.i18n.yaml
#	packages/util/native-command/README.md
#	packages/util/native-command/README.zh.md
2026-09-22 20:28:17 +08:00
mektpoy bca9cecc7d fix(client): keep pointer focus silent through descendant and editable rings
Pointer suppression previously cleared `outline-color` on the focused element
alone, so a ring painted by a descendant, a pseudo-element, or a `box-shadow`
stayed visible, and editable text controls lost the focus feedback they need on
click.

Ring colour now flows through `--dsw-focus-ring-color`, which component outlines
and focus-ring shadows read alongside the brand token. Every ring that inherits
the variable is suppressed together, and `body :focus-visible:not(:read-write)`
limits the suppression to rings while editable controls keep their own feedback.

Keyboard modality returns on Tab, Home, End, PageUp, or PageDown, and on focus
reaching a different control after a non-composing key. IME composition keys,
refocusing the same control, and window blur leave rings silent. The desktop
preload menubar suppresses its own ring inside its shadow root, where the
document-level attribute does not reach.
2026-09-22 20:28:10 +08:00
mektpoy b73031be9b test(native-command): pin the Explorer target for verbatim and device paths
A verbatim `\\?\` prefix and a `\\.\` device namespace take Node's UNC
resolution, and the comma encoding has to survive them. The drive-root case is
pinned separately because Node restores a trailing separator against the host's
`path.sep`, which differs on the Windows host this opener runs on.
2026-09-22 20:27:45 +08:00
mektpoy 3063767eef Merge remote-tracking branch 'origin/master' into feat/unify-code-highlight-languages 2026-09-22 20:27:08 +08:00
mektpoy 9cdfcd5f04 Merge remote-tracking branch 'origin/master' into feat/window-drag-coverage 2026-09-22 20:26:59 +08:00
sjw1231 fd784e4429 fix(web): refine file diff review colors 2026-09-22 20:23:45 +08:00
winewill 06717aebbb build(desktop): bundle the main process after the workspace tsdown pass
The root tsdown workspace pass builds every member concurrently, so the
Desktop main bundle could resolve its inlined workspace devDependencies
(dsh-home-paths, dsh-app-boot, dsh-deepseek-account) before their lib/
output existed. rolldown then kept them as external imports, which the
asar does not ship, and the packaged application failed at launch with
ERR_MODULE_NOT_FOUND on a clean checkout; stale lib/ output on long-lived
checkouts hid the defect.

apps/desktop leaves the root workspace list and build:lib:host bundles it
after the Host pass. Every Desktop bundle now runs a rolldown plugin that
fails the build when a chunk imports a bare specifier the packaged
application cannot resolve: electron and the manifest dependencies for
the main bundle, electron alone for sandboxed preloads.
2026-09-22 20:11:51 +08:00
gengruilin 969c3df8c1 Merge origin/master into fix/webkit-model-picker 2026-09-22 20:10:46 +08:00
Yichen Jiang 1498b01923 feat(voice-input): select responsive model download mirrors 2026-09-22 20:06:00 +08:00
mektpoy bf3de68213 Merge remote-tracking branch 'origin/master' into tmp4876 2026-09-22 20:04:19 +08:00
Yichen Jiang 37e4dc2dee Merge pull request #4961 from deepseek-harness/worktree/model-discovery-display-name
fix(web): show discovered model names in picker
2026-09-22 19:56:28 +08:00
imccyu a44ced5b96 fix(web): gate Remote WebSockets on application readiness 2026-09-22 19:54:21 +08:00
Yichen Jiang d4b109f439 Merge pull request #4907 from deepseek-harness/worktree/plugin-install-country-registry
feat(plugin-manager): select the first responsive public registry
2026-09-22 19:51:49 +08:00
Yichen Jiang bef0869d14 test(web): select discovered models by display name 2026-09-22 19:44:57 +08:00
lsdsjy 5a3c316401 fix(desktop): deliver welcome expiry notice once across windows 2026-09-22 19:21:12 +08:00
ZiyaZhang 82a7dd9c3f test(plugin-manager): strengthen GitHub recovery assertions 2026-09-22 04:04:33 -07:00
winewill 84394b818c Merge pull request #4919 from deepseek-harness/fix/fatal-diagnostics-and-crash-reports
fix: contain spill failures, recover failed client batches, and write Desktop crash reports
2026-09-22 19:01:39 +08:00
Yif 5b600047d2 docs(agents): add dsh-client-ui-ux skill for client UI/UX design and review
Collects the standing judgment rules for product-user-visible GUI work:
token and shared-treatment reuse, light/dark readability, font weight and
size scale, feedback-surface choice (toast vs in-place notice vs empty
state), loading treatments, overlay dismiss/fit/clip checks, macOS/Windows
window adaptation, and spacing review. dsh-code-review links it from its
sources of truth so UI PR reviews load it.
2026-09-22 18:52:15 +08:00
winewill ec852793b5 Merge remote-tracking branch 'origin/master' into fix/fatal-diagnostics-and-crash-reports 2026-09-22 18:51:57 +08:00
Yichen Jiang bdbf1fe339 Merge origin/master into registry response selection 2026-09-22 18:39:34 +08:00
Yichen Jiang 3c50bf6b6c feat(plugin-manager): choose the first responsive public registry 2026-09-22 18:38:43 +08:00
Ziya 20e7407ff1 Merge branch 'master' into ux/plugin-install-20260922 2026-09-22 18:36:24 +08:00
ZiyaZhang d6e5b7e41a feat(plugin-manager): offer mirror recovery for GitHub install failures 2026-09-22 03:24:45 -07:00
winewill c22b226b18 fix: address review threads on the fatal-diagnostics PR
- Agent Notes: cross-link the new decision with the native fatal recovery
  and fail-loud release notes both ways, rewrite the older note's
  console-retention and dialog-detail facts in place, and state the report's
  actual bounds.
- crash-report: cut the rendered error section at 256 KiB and prune only
  files matching the generated crash-<time>-<source>.log syntax.
- main: backendReady follows the backend state except during shutdown, so a
  failure while tearing down a ready backend still reads as running.
- subprocess-local: the temporary-file-cleaner hint is appended only for
  ENOENT; other codes rely on the appended error.
- client-modules: describeError is module-private; BootModuleRow.url's
  JSDoc names its fallback role.
2026-09-22 18:20:12 +08:00
winewill af28c551f3 Merge pull request #4913 from deepseek-harness/fix/windows-installer-extract-diagnostics
fix(desktop): report Windows extraction failures with 7-Zip evidence
2026-09-22 18:15:40 +08:00
Yichen Jiang b34b5d33a1 fix(web): show discovered model names in picker 2026-09-22 18:01:37 +08:00
winewill 603a8fc7d3 Merge remote-tracking branch 'origin/master' into fix/fatal-diagnostics-and-crash-reports 2026-09-22 17:58:58 +08:00
Turtle 505559b03b Merge pull request #4955 from deepseek-harness/turtle/settings-link-copy-064fa5feb8cd
fix(client): clarify chat link-opening settings copy
2026-09-22 17:42:50 +08:00
winewill 30a7f8f787 Merge branch 'master' into fix/windows-installer-extract-diagnostics 2026-09-22 17:37:28 +08:00
Dudu-0223 7c296b3f08 Merge pull request #4951 from deepseek-harness/fix/teammate-lead-guidance
fix(agent-team): explain teammate discovery and messaging
2026-09-22 17:36:31 +08:00
mektpoy fac0d8d877 docs(native-command): record the interactive-session requirement for Explorer opens 2026-09-22 17:35:54 +08:00
Turtle b2ec54159f docs(client): name the Sidebar Browser in the link-opening row prose
The ui-chat README described the visibility rule as "while the built-in browser
is available", a phrase that now reads like an option label. Both languages name
the Sidebar Browser, matching the sentence that follows.
2026-09-22 17:33:49 +08:00
Yichen Jiang 108f767a89 Merge pull request #4949 from deepseek-harness/worktree/fix-voice-language-settings
fix(voice-input): persist recognition language settings
2026-09-22 17:31:21 +08:00
winewill 7b2094d04d fix(desktop): keep the Host's original diagnostic in startup crash reports
A Host startup failure reached the crash report as a fresh Error built from
a message string three hops away from the original: the Host sent only
error.message over the fatal IPC event, DesktopHostProcess wrapped it in a
new Error, desktopErrorState flattened it to text, and main.ts wrapped that
text again. Stack, cause, code, and path were gone, and the Host's stderr
tail arriving with the later exit was blocked by the first-failure latch.

The Host now sends its complete inspected error alongside the message
(bounded to 64 KiB; carried over IPC rather than stderr because the two
race and the shell reports the first failure it sees). DesktopHostProcess
keeps it on DesktopHostFatalError.diagnostic, the backend error state
carries the original failure object, main.ts reports that object, and the
crash report prints the Host diagnostic verbatim in its own section.
2026-09-22 17:31:17 +08:00
mektpoy 03294cb653 test(native-command): pin every Explorer open target through one table 2026-09-22 17:31:12 +08:00
winewill d8924486ad fix(desktop): declare the cordis peer the packaged application needs
apps/desktop imports @deepseek-ai/dsh-api-gateway/stream-protocol, whose
import chain reaches @deepseek-ai/dsh-typert-protocol and then
@deepseek-ai/cordis. Both intermediate packages declare cordis as a
peerDependency and nothing satisfied it for the application closure, so
electron-builder omitted cordis from app.asar and the packaged main process
died before opening a window with ERR_MODULE_NOT_FOUND. A workspace checkout
resolves the peer through pnpm's own links, so development runs and the unit
lanes stayed green while every packaged build since efbc8e26b6 (2026-09-20)
failed to launch.

The lockfile additionally drops a stale duplicate [email protected] in favour of the
7.2.3 it already carries; any real pnpm install removes it.

Verified with a signed win-x64 installer built from this tree: app.asar now
ships cordis and @standard-schema/spec, and the installed application opens
its main window.
2026-09-22 17:21:06 +08:00
Dudu-0223 a79e3a2a5f fix(agent-team): explain teammate discovery and messaging 2026-09-22 17:18:08 +08:00
Turtle c81adc2569 Merge pull request #4948 from deepseek-harness/turtle/agent-experience-skill
docs(skills): add the agent-experience skill
2026-09-22 17:16:36 +08:00
Turtle a294fc55d0 Merge pull request #4930 from deepseek-harness/fix/641-unbounded-completion-wakes
fix(tool-jobs): wake an idle owner for every completion by default
2026-09-22 17:14:13 +08:00
Turtle aba3472b1d fix(client): clarify chat link-opening settings copy
The Settings → General row for Chat link destinations now reads
网页链接默认打开方式 with the description 对话中网页链接的打开位置 and the option
labels 应用内侧边栏 and 默认浏览器. English keeps the title "Open chat links in" and
now reads "Choose where to open web links", "In-App Sidebar", and "Default
Browser".

The `ui-chat.linkOpening` setting, its values, persistence, visibility rule, and
open behavior are unchanged. The row spec, the clickable-link gallery scenario,
and the two package READMEs name the new copy; the bilingual pairing records were
re-confirmed for the README pairs.
2026-09-22 17:12:43 +08:00
Dudu-0223 d257fa4af7 fix(agent-team): limit the reminder to the lead identity 2026-09-22 17:08:45 +08:00
imccyu b980fdf5df Merge pull request #4950 from deepseek-harness/worktree/release-dsh-0.1.5-rc.3-history-to-master
chore(release): record dsh 0.1.5-rc.3 history on master
2026-09-22 17:07:52 +08:00
ihsiang e420c44d60 Merge pull request #4857 from deepseek-harness/ihsiang/unify-code-block-ui
feat(web): 统一代码块样式与复制、换行控件
2026-09-22 17:06:07 +08:00
turtle1999 bada62b50b docs(skills): add the agent-experience skill
Carry the user-scoped agent-experience guidance into the repository unchanged so
project sessions discover it beside the other repository skills. The file,
including its frontmatter, is byte-identical to the personal copy.
2026-09-22 17:03:36 +08:00
Dudu-0223 6ec97fa124 fix(agent-team): tell teammates how to message the lead 2026-09-22 17:02:25 +08:00
lsdsjy f0f4bb73fc fix(desktop): keep welcome back action on one line 2026-09-22 16:58:55 +08:00
yixiangihsiang 9c6c407da2 Merge master into ihsiang/unify-code-block-ui 2026-09-22 16:57:18 +08:00
Yichen Jiang 7c84d9d790 fix(voice-input): persist recognition language settings 2026-09-22 16:55:33 +08:00
imccyu 3ae2f687f1 merge: record dsh 0.1.5-rc.3 history on master
Keep the master tree unchanged while recording the dsh-v0.1.5-rc.3 release ancestry.
2026-09-22 16:50:58 +08:00
Yudong Han d3c5f959aa Merge pull request #4921 from deepseek-harness/fix/4918-excel-preview-resize
fix(web): resize Excel previews with their pane
2026-09-22 16:46:26 +08:00
lsdsjy 26af73ff50 chore: merge master account theme updates 2026-09-22 16:34:42 +08:00
HYD@OVERTON 58651b8359 fix(web): resize Excel previews with their pane 2026-09-22 16:33:30 +08:00
turtle1999 2d653be7b0 fix(tool-jobs): address review on the unbounded wake default
Skip the per-owner wake ledger entirely when no cap is configured.
Rewrite the 2026-08-11 Agent Note in place for the opt-in cap and add
a note recording why the default was removed. Keep `subagent`
untranslated in Chinese prose and drop change narration from the test.

Refs #4944
2026-09-22 16:33:24 +08:00
yixiangihsiang 5929af046c Merge master into ihsiang/unify-code-block-ui 2026-09-22 16:32:42 +08:00
yixiangihsiang 780e07b8ed test(web): align built boot assertions with diff layout 2026-09-22 16:28:46 +08:00
lsdsjy 32ca127565 Merge pull request #4898 from deepseek-harness/fix/contact-form-url
fix(client): update Feedback form and omit account UID
2026-09-22 16:27:23 +08:00
turtle1999 536b444f36 Merge remote-tracking branch 'origin/master' into fix/641-unbounded-completion-wakes 2026-09-22 16:26:50 +08:00
Huanqi Cao f5d7de2a01 Merge pull request #4807 from deepseek-harness/fix/pwsh-prompt-readiness
fix(pty): keep the controlled prompt so persistent pwsh settles fast
2026-09-22 16:25:59 +08:00
lsdsjy 4777947b6c fix(client): keep account UID fields out of questionnaire URLs
The Contact us action already stopped prefilling the signed-in UID, but a
configured contact form URL could still carry its own prefill_uid or hide_uid.
contactUrl now drops both query parameters unconditionally, with regression
coverage that starts from a form URL containing them.

The contact URL test also pins the shipped default form path, and the injected
contactUs documentation and the AccountProfile summary no longer describe a
support UID that is no longer sent.
2026-09-22 16:16:34 +08:00
lsdsjy 930d187e04 Merge remote-tracking branch 'origin/master' into fix/contact-form-url
# Conflicts:
#	packages/client/ui-settings-account/README.i18n.yaml
#	packages/client/ui-settings-account/README.md
#	packages/client/ui-settings-account/README.zh.md
2026-09-22 16:13:19 +08:00
Dudu-0223 ee0048558d test(web): capture terminal recovery readiness with its snapshot 2026-09-22 16:13:15 +08:00
lsdsjy 3e4119ebdb fix(account): expire account credentials on inference HTTP 401 2026-09-22 16:12:01 +08:00
Yudong Han 34a0a8e81d fix(web): preserve Excel previews across OPC paths and XML encodings (#4872)
* fix(web): resolve XLSX part relationships and namespace aliases

* fix(web): keep Excel browser scenario in the host test program

* fix(excel): preserve XML encodings and relocated workbook parts

* fix(excel): exclude installed launchers from dependency patch

* fix(excel): restore Strict and case-equivalent workbook previews
2026-09-22 08:04:13 +00:00
Dudu-0223 700b636508 fix(agent-team): limit baseline loading fix to the panel 2026-09-22 16:00:57 +08:00
lsdsjy e76a5eba21 Merge pull request #4903 from deepseek-harness/fix/platform-login-theme
fix(desktop): match Platform login theme
2026-09-22 16:00:44 +08:00
lsdsjy 8e92f17e9c chore: merge master into account provider branch 2026-09-22 15:50:45 +08:00
lsdsjy 64154d2f68 test(models): declare available fixture models and update selection flows 2026-09-22 15:49:54 +08:00
lsdsjy 785a92ab03 fix(client): rename the contact menu entry to Feedback
The account menu entry that opens the questionnaire is now labeled Feedback in
English and 意见反馈 in Chinese. The menu action, contact form URL and its
configuration options keep their existing names.

Expected menu snapshots and the bilingual README record the new copy.
2026-09-22 15:49:30 +08:00
lsdsjy 3b6a5399e8 docs(desktop): clarify login theme ownership 2026-09-22 15:49:20 +08:00
yixiangihsiang fd8bed1ad0 Merge master into ihsiang/unify-code-block-ui 2026-09-22 15:45:41 +08:00
yixiangihsiang 62f816f3a5 feat(web): refine code card spacing and thinking blocks 2026-09-22 15:44:57 +08:00
lsdsjy 37d3a31e29 fix(account): sign out on rejected inference tokens 2026-09-22 15:44:26 +08:00
Dudu-0223 bfc772bb47 Merge remote-tracking branch 'origin/master' into codex/pr-4810-review-fixes 2026-09-22 15:40:58 +08:00
Dudu-0223 749f05e9fa fix(agent-team): refresh projections when opening the panel 2026-09-22 15:38:32 +08:00
Yichen Jiang ab7cdbee75 Merge remote-tracking branch 'origin/master' into worktree/plugin-install-country-registry 2026-09-22 15:38:14 +08:00
Huanqi Cao 41fd0baf91 Merge remote-tracking branch 'origin/master' into fix/pwsh-prompt-readiness
# Conflicts:
#	docs/config-catalog.i18n.yaml
2026-09-22 15:36:21 +08:00
lsdsjy f50059e425 fix(desktop): theme workspace sign-in links 2026-09-22 15:34:58 +08:00
Turtle 5ca6d34ac6 Merge pull request #4924 from deepseek-harness/turtle/fix-queued-edit-newline-54bfaf4e59d7
fix(web): keep line breaks when re-editing a queued message
2026-09-22 15:33:31 +08:00
Yichen Jiang 8cf07ea76c fix(plugin-manager): preserve remembered registries during initial lookup 2026-09-22 15:32:16 +08:00
turtle1999 b6775f6d4f fix(tool-jobs): wake an idle owner for every completion by default
`maxConsecutiveWakes` no longer defaults to 3. Unset, every background
job completion wakes its idle owner; the cap is opt-in.

With the default cap, a session chaining background commands and
one-shot subagents exhausted the budget after three wakes. The fourth
notice was injected into the next-step inbox without waking the owner,
the client showed nothing, and the session stalled until the user
typed something (dsh-external/issues#641).

Closes dsh-external/issues#641
2026-09-22 15:29:23 +08:00
lsdsjy 43f107d164 fix(account): expire grants rejected by Platform response code 2026-09-22 15:27:38 +08:00
lsdsjy 2c098434b9 Merge remote-tracking branch 'origin/master' into fix/platform-login-theme 2026-09-22 15:27:06 +08:00
lsdsjy 13fe312e15 test(desktop): fix login theme CI fixtures 2026-09-22 15:26:39 +08:00
lsdsjy bc8e8005fc docs: refresh module graph for account provider dependencies 2026-09-22 15:19:29 +08:00
lsdsjy 4dae756ced Merge remote-tracking branch 'origin/master' into feat/account-provider-signout 2026-09-22 15:13:22 +08:00
Turtle 753df93b85 test(web): pin the multiline queued edit in the browser lane
The recorded-session scenario edited with a single-line value, so the ARIA
golden could not catch a return to a newline-stripping editor. Edit with a
two-line value and assert the model-bound user message keeps the line break;
with the previous input element the scenario fails on that assertion. Also
refresh the stale input cast and pin that Shift+Enter is not consumed.
2026-09-22 15:12:35 +08:00
lsdsjy 06a3daef9f Merge remote-tracking branch 'origin/master' into feat/account-provider-signout 2026-09-22 15:08:47 +08:00
Yichen Jiang 8ae7631861 Merge pull request #4916 from deepseek-harness/worktree/settings-provider-docs
docs(settings): correct provider configuration paths and examples
2026-09-22 15:08:34 +08:00
lsdsjy 6ef32577a3 fix(account,models): reconcile provider lifecycle with master 2026-09-22 15:06:16 +08:00
lsdsjy b1c084e769 Merge pull request #4904 from deepseek-harness/fix/web-account-client-platform
fix(credentials): send web client platform header for account requests
2026-09-22 15:02:35 +08:00
Yichen Jiang 13d9606675 test(voice-input): synchronize idle cleanup failure observation 2026-09-22 14:59:47 +08:00
Turtle c74e36acfc fix(web): keep line breaks when re-editing a queued message
The inline queue editor was a single-line input, and HTML strips newlines
from such a value: opening and saving a multi-line queued message silently
collapsed it into one line before delivery. Edit in a textarea that grows
with its content, capped at six lines; Enter saves, Shift+Enter breaks the
line, and Escape still cancels.
2026-09-22 14:55:34 +08:00
Jiawei Song e950c8bea4 Merge pull request #4838 from deepseek-harness/fix/4823-message-overflow-review-menu
fix(web): 修复消息长文件名溢出和 Review 浮窗菜单错位
2026-09-22 14:47:21 +08:00
winewill a19a48edea Merge pull request #4837 from deepseek-harness/feat/desktop-update-ui-2
fix(desktop): polish the Windows update copy, app icon and About dialog
2026-09-22 14:42:44 +08:00
lsdsjy f21098e9d3 fix(account): expire rejected credentials and hide signed-out provider 2026-09-22 14:41:33 +08:00
winewill cafb9b93b4 fix: address adversarial review of the fatal-diagnostics branch
client-modules: a batch that already executed is never requested again,
even when its first importer was a row it did register — every executed
batch URL is remembered and a still-missing row goes straight to its
one-resource URL. The in-process module system test in test-support is
updated to the aggregated arrival message. describeError replaces three
inline non-Error ternaries and is covered.

subprocess-local: the spill path is published only after the exclusive
open succeeds, so a failed open (EEXIST on a planted entry included) can no
longer unlink a path this process did not create; a reporter that throws is
contained and written to stderr; logSpillFailure builds the owner reporter
for both the runtime and the SSH helper so the logging path is exercised
once instead of duplicated. Tests cover the runtime logger, the bare-caller
stderr default, EEXIST, and a throwing reporter.

desktop: a fatal failure during shutdown still writes its report; the
report phase follows the backend state so a failure during a restart is
'startup' again; writeReport is a required recovery operation and the
dialog tests await the write; the shell pid is labelled; the withheld
response-header list states why set-cookie is dropped.

app-boot, READMEs, Agent Note: "never resumes" is restated as control never
returning to the failed operation while the loop runs until release
settles; inspect output is bounded; incident inferences (who removed the
spill directory, which batch failure occurred) are written as inferences.
2026-09-22 14:41:10 +08:00
lsdsjy 5f1a524f61 docs(credentials): clarify private platform request headers 2026-09-22 14:39:19 +08:00
Dudu-0223 db4bfb4c96 docs(agent-team): refresh generated module dependencies 2026-09-22 14:37:05 +08:00
lsdsjy 6a133a02b8 Merge origin/master into fix/web-account-client-platform 2026-09-22 14:36:24 +08:00
Yichen Jiang 43bd7010d0 test(llm): isolate idle timeout from HTTP setup timing 2026-09-22 14:36:17 +08:00
mektpoy 1a21e958df Merge remote-tracking branch 'origin/master' into tmp4876 2026-09-22 14:34:28 +08:00
Dudu-0223 7befda1147 test(agent-team): release fixtures and respect snapshot types 2026-09-22 14:32:01 +08:00
winewill bed4a2b565 fix(desktop): address review of the extraction failure report
- Headline skips the archive path 7-Zip echoes before an open failure
  (also when the path contains spaces) and prefers the operation line.
- Raw process statuses such as 0xC0000005 are kept and printed in hex
  instead of being clamped to INT_MAX.
- The expanded panel excerpts the result and 7-Zip's own lines rather
  than the report header.
- The saved report keeps up to 16 MiB of output, records any cut, and
  trims a partial UTF-8 sequence before decoding.
- The details view no longer reads the UTF-8 log as ANSI; the test seam
  define and the zero-padded GetTime order are documented; the smoke
  asserts a year-first report name and normalizes -FrameLibrary.
- README names the real updater cache directory.
2026-09-22 14:30:56 +08:00
Huanqi Cao dbd34bcc0d Merge remote-tracking branch 'origin/master' into fix/pwsh-prompt-readiness
# Conflicts:
#	docs/config-catalog.i18n.yaml
2026-09-22 14:30:34 +08:00
Yichen Jiang c9591d9445 Merge remote-tracking branch 'origin/master' into worktree/plugin-install-country-registry 2026-09-22 14:29:40 +08:00
Yichen Jiang d459183f32 docs(settings): correct provider configuration paths and examples 2026-09-22 14:28:46 +08:00
Dudu-0223 b7d9c0f6a4 Merge remote-tracking branch 'origin/master' into feat/agent-team-projection-panel 2026-09-22 14:27:15 +08:00
Dudu-0223 843e1b97af fix(agent-team): scope projection reads and address review feedback 2026-09-22 14:27:00 +08:00
yixiangihsiang ce2ba9b216 Merge master into ihsiang/unify-code-block-ui 2026-09-22 14:23:25 +08:00
CreatixChu ee4458f6d0 Merge pull request #4802 from deepseek-harness/fix/4775-multimodal-tool-retention
fix: 按统一 token 预算保留工具结果中的图文内容
2026-09-22 14:22:45 +08:00
Yichen Jiang d407a6ce90 test(credentials): allow either concurrent account request order 2026-09-22 14:22:13 +08:00
mektpoy ab77b55663 Merge origin/master into feat/window-drag-coverage
master grew a fourth drag owner after this branch: the Platform overlay's return
bar (ui-settings-account) declared `app-region: drag` on its own header. The
branch absorbs it into the contract — the header marks itself `data-window-drag`,
its own app-region drag/no-drag rules are deleted, the ui-theme manifest pins the
row and its 48px height, and the Agent Note's row list names it — so the tree
declares the drag surface in exactly two places again (the shell's mark rule and
the Windows caption row).

Earlier resolutions from the first merge stand: the dockkit strip keeps its mark,
the sidebar-right pulse stays deleted, ui-settings-general keeps upstream's
dsh-settings and this branch's react-dom, and tsconfig.host.json takes upstream's
`files: []`.

Checks: build, build:web, typecheck, test:gui, the ui-theme/base-styles gates, the
window-drag-coverage lane, doc-sync and translation pairing.
2026-09-22 13:49:49 +08:00
winewill 4544874d62 Merge branch 'master' into fix/windows-installer-extract-diagnostics 2026-09-22 13:46:04 +08:00
mektpoy 67eb749ef7 Merge origin/master into feat/window-drag-coverage
Conflict resolutions:
- ui-dockkit TabPanel: keep upstream's reworked tab strip and re-add the row's
  `data-window-drag` mark on `css.tabStrip`.
- ui-sidebar-right SidebarRight.tsx/.module.css: keep upstream's retention
  rewrite and re-delete its hand-written one-frame app-region pulse; the shell's
  window-drag watcher owns recollection.
- ui-settings-general/package.json: keep upstream's `@deepseek-ai/dsh-settings`
  dev dependency and this branch's `react-dom`.
- tsconfig.host.json: take upstream's `files: []`; client sources belong to the
  client aggregate.
- pnpm-lock.yaml: master's lock plus only the react-dom importer entries.
2026-09-22 13:41:21 +08:00
imccyu a4c74a91e0 Merge pull request #4909 from deepseek-harness/worktree/release-dsh-0.1.5-rc.3
release: [email protected]
2026-09-22 13:26:23 +08:00
winewill 6530130ffa docs(agent-notes): record fatal diagnostics and crash report decisions 2026-09-22 13:25:38 +08:00
winewill e38cca76fd feat(desktop): write a crash report before the fatal recovery dialog
The fatal recovery dialog showed the last eight lines of the error and
promised that the full diagnostic was in the Electron console, which a
packaged installation never surfaces. Two field failures were diagnosed
from screenshots of those eight lines: a Host killed by an uncaught
exception whose path happened to be in the tail, and a renderer boot
failure whose real import error lived only in the renderer console.

Every reportFatal caller now names its source (host, web-boot, renderer,
main). Before the first dialog opens, the shell writes
crash-<time>-<source>.log under app.getPath('logs') with the source, the
startup or running phase, application and runtime versions, the complete
inspected error with its properties and cause chain, and the primary
window's recent error-level console output (a 64 KiB tail captured from
webContents 'console-message'). The dialog names the file on its own line,
independent of whether the error was shortened and in the listener-conflict
variant too; the wait is bounded to one second and a failed write shows the
dialog without a path. Startup keeps the ten newest reports. Buttons and
recovery actions are unchanged.
2026-09-22 13:22:27 +08:00
imccyu 8e7cca22ca release(dsh): 0.1.5-rc.3 2026-09-22 13:08:07 +08:00
imccyu 943af81a18 fix(release): pin vendor dependencies for dsh 0.1.5 2026-09-22 13:07:34 +08:00
winewill 5864a6f6f1 fix(desktop): drop connection-level headers and bundle cache headers when forwarding to the Host
forwardWebRequest relayed transfer-encoding, connection, keep-alive, and
the other hop-by-hop headers from the Host's response into the dsh-app://
response, describing a Node fetch connection that Chromium never saw. It
also relayed the Host's `cache-control: public, max-age=31536000,
immutable` on plugin bundles whose revision changes on every launch, so
each start wrote another unreusable copy into the renderer's disk cache.

The forwarder now strips the connection-level header set alongside the
encoding headers it already removed and marks /plugins/ responses
no-store. Whether either header contributed to the observed batch load
failure is unverified; both are corrections in their own right.
2026-09-22 13:03:13 +08:00
winewill afde35880f feat(client-modules): recover from a failed batch script and record import errors
One application batch is a single classic script that registers every
package in sequence, requested exactly once during boot. A transient
failure of that one <script> request failed every row in the batch and,
through arriveGraphRow's dependency wait, every row that injects or
requests them; the boot audit then listed each as "import failed (see
console for the import error)" with the real error only in the renderer
console.

Arrival now distinguishes the two failure kinds. A transport failure
(script error event, nothing executed) is retried once on the same URL and
the retry is shared by every row waiting on that batch. A script that
loaded without registering a row is never re-executed, because register()
rejects duplicates and a replay would stop at the first package the
original run did register. Either way each still-missing row then loads its
own one-resource combo URL, which the Host serves for every package. A batch
URL that failed is remembered so later rows skip straight to their
fallback; a one-resource URL is not, so it stays retryable on the next
import as before. Dependency failures are wrapped with the consumer and
dependency names so a cascade reads as a chain.

The module system records the last import() or prefetch() failure per
graph row at the outer operation, so factory execution errors are captured
as well as arrival errors, and clears it on success or invalidation.
assertEntriesActive takes the module system and reports that text per
fiberless entry.
2026-09-22 13:00:13 +08:00
Yichen Jiang 9f52c6401e docs(ip-geolocation): refresh the module dependency graph 2026-09-22 12:57:05 +08:00
Yichen Jiang 22be805026 fix(ip-geolocation): align the package with the current release 2026-09-22 12:50:28 +08:00
winewill 9f9a50e553 feat(app-boot): treat uncaught exceptions as fatal through installFailLoud
The Desktop Host and every other profile launcher installed a fail-loud
handler for unhandled rejections only. A synchronous throw from a stream
'data' listener fell through to Node's default uncaught-exception path: it
printed and exited without the surface's release hook, and the label and
format differed from every other fatal diagnostic.

installFailLoud now registers the same report for 'uncaughtException' with
the label `fatal uncaught exception`, shares the exit latch and release
timeout with rejections, and never resumes the process. The diagnostic is
util.inspect(err, { depth: 4 }) instead of err.stack so enumerable
properties (a node:fs error's code, syscall, and path) and the cause chain
reach stderr; the `fatal load failure` label for rejections is unchanged
because the Web profile expected-output e2e tests match it.
2026-09-22 12:46:37 +08:00
winewill cfa84ed4e3 fix(subprocess-local): contain spill file failures instead of killing the host
OutputCollector.spillAll ran openSync/writeSync inside the stream 'data'
listener with no containment. When the private per-process spill directory
had been removed by a temporary-file cleaner, the first overflowing chunk
threw ENOENT from Pipe.onStreamRead, became an uncaught exception in the
Desktop Host, and the Electron shell reported it as a fatal failure.

Spilling is best-effort by contract (spillPath is optional; a failed final
close already withholds it). Every filesystem failure while opening or
appending the spill file now discards the spill, reports once through the
owner's logger, and leaves in-memory collection untouched. Spill inputs move
into one SpillOptions object with the reporter, so tail-only collectors no
longer pass an empty directory; prepareManagedProcessBinding is the explicit
resolve step for the directory and reporter defaults, and the runtime and
SSH helper supply their plugin loggers.

Tests cover ENOENT on open (removed directory), ENOTDIR on open, and ENOSPC
on append after the file exists, asserting the tail stays byte-exact, the
spill file is withdrawn, and the reporter fires once.
2026-09-22 12:40:07 +08:00
winewill ab62f09c22 fix(desktop): report Windows extraction failures with 7-Zip evidence
The installer showed "Failed to decompress files" and discarded 7-Zip's
error output, so a failure such as security software quarantining an
extracted file could not be told apart from a full disk or a broken
download.

- InstallerExtract returns negated Win32 errors for launch failures so
  they no longer collide with 7-Zip exit codes; 7-Zip writes UTF-8 errors.
- window-frame.dll composes a report (result, archive, destination,
  Windows version, full 7-Zip output), saves it under the updater cache
  directory, and presents a task dialog with the first error line, a
  collapsible bounded excerpt, and a Copy error details button. Silent
  installs keep only the report; a missing task dialog falls back to a
  message box.
- Unsigned Windows builds name their installer *-unsigned.exe so a
  shared file cannot pass for a release artifact; version discovery
  still counts them.
- The directory smoke asserts the saved report on a broken archive and
  smoke-windows.ps1 accepts the prepared DLL.

Refs #4893
2026-09-22 12:38:05 +08:00
Yichen Jiang dccf989cd8 feat(plugin-manager): prefer the mainland mirror for CN network exits 2026-09-22 12:37:32 +08:00
creatixchu c5ca36387b Merge remote-tracking branch 'origin/master' into fix/4775-multimodal-tool-retention
# Conflicts:
#	packages/spill/spill-policy/package.json
2026-09-22 12:35:56 +08:00
mektpoy 95611fbc63 fix(native-command): encode the Explorer target so a comma stays in the path 2026-09-22 12:24:53 +08:00
mektpoy d6a693796d Merge remote-tracking branch 'origin/master' into feat/unify-code-highlight-languages 2026-09-22 12:21:30 +08:00
mektpoy 19b7de31a6 refactor(tool-fs): persist the read language hint as a short id 2026-09-22 12:21:19 +08:00
Turtle c36a83ff6b Merge pull request #4901 from deepseek-harness/rel/dsh-0.1.7-alpha.1
release(dsh): 0.1.7-alpha.1
2026-09-22 12:12:33 +08:00
lsdsjy f5c96b6340 fix(credentials): identify web account requests with client platform header 2026-09-22 12:09:40 +08:00
creatixchu 670a903237 test: clarify parallel recovery fixture cleanup 2026-09-22 12:08:55 +08:00
creatixchu b74bef5d40 test: exercise image recovery and real PTC retention 2026-09-22 12:03:54 +08:00
lsdsjy 817623750a fix(desktop): match Platform login theme
Opened and copied authorization links carried no palette, so the Platform
login page rendered its own stored preference. Append the effective Desktop
palette as theme=light or theme=dark, resolving system through the theme
source the preload publishes.

The theme source now reaches nativeTheme on Windows as well: the preload
drops its macOS-only guard, since shouldUseDarkColors is read for every
platform, and gates the DOMContentLoaded listener with once.
2026-09-22 12:02:54 +08:00
turtle1999 112ce776ac release(dsh): 0.1.7-alpha.1 2026-09-22 11:59:16 +08:00
Huanqi Cao 8aff71863b Merge remote-tracking branch 'origin/master' into fix/pwsh-prompt-readiness
# Conflicts:
#	docs/config-catalog.i18n.yaml
2026-09-22 11:52:42 +08:00
Turtle 6942625430 Merge pull request #4897 from deepseek-harness/fix/web-ui-hide-account-sign-in
fix(web): hide DeepSeek account sign-in outside desktop
2026-09-22 11:50:02 +08:00
winewill 9d91bb01c9 fix(desktop): read the About copy from the live locale
master replaced the startup-bound messages constant with a locale that
follows the settings preference; the About dialog now reads the same
locale as the update prompts so the two never mix languages.
2026-09-22 11:48:33 +08:00
winewill 3305bb1938 Merge remote-tracking branch 'origin/master' into feat/desktop-update-ui-2 2026-09-22 11:44:41 +08:00
sjw1231 5ac920e50c chore: merge latest master into message and review fixes 2026-09-22 11:39:33 +08:00
lsdsjy adbb0e0dc4 fix(client): update the contact form URL and drop its account UID prefill
The Contact us entry now opens the current Feishu questionnaire, and the URL
no longer carries the signed-in account UID: contactUs stops reading the
account profile, contactUrl stops writing prefill_uid and hide_uid, and the
remaining build and browser context fields keep their existing behavior.

The url, package tests and the bilingual README and account-login note state
the same current facts.
2026-09-22 11:39:14 +08:00
lsdsjy 75546dc8e9 fix(web): hide DeepSeek account sign-in outside desktop 2026-09-22 11:38:43 +08:00
ZiyaZhang 2426d398b5 fix(ui-agent-preset): restore the read-only configuration viewer
The declarative-preset refactor (#4569) removed the registry's read Remote
together with the YAML editor, and with it the 查看配置 card action that
opened a preset's composition read-only. #4850 brought the Creator entry
back and had to leave 查看配置 out because `agentPresets/read` was gone.

Give the registry a read-only `read` Remote that renders a declaration's
child plugin list from the in-memory definition in the Loader's own
entry-list dialect, so `!!js` conditions read as declared, and put the card
action back at the right end of each card footer: an icon that opens the
YAML in a read-only dialog titled after the preset. Nothing accepts YAML
back, and a broken preset stays readable because its diagnostic points into
that YAML.

Fixes #4895
2026-09-21 20:38:30 -07:00
Turtle 1c96299173 Merge pull request #4831 from deepseek-harness/worktree/voice-input-icon
fix(voice-input): improve plugin icon and setup diagnostics
2026-09-22 11:35:32 +08:00
creatixchu de45804084 test: refresh tool projection API snapshot 2026-09-22 11:32:07 +08:00
imccyu 1e9c7b410a Merge pull request #4891 from deepseek-harness/worktree/release-vendor-4.0.2
release(vendor): cordis 4.0.3, cosmokit 1.8.4, group 1.0.3, hmr 1.0.1…
2026-09-22 11:31:17 +08:00
Huanqi Cao 091db6c8c3 Merge remote-tracking branch 'origin/master' into fix/pwsh-prompt-readiness
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.zh.md
2026-09-22 11:30:34 +08:00
creatixchu 94728ebd23 fix: repair multimodal retention CI resolution and coverage 2026-09-22 11:28:51 +08:00
creatixchu 06923b8868 Merge remote-tracking branch 'origin/master' into fix/4775-multimodal-tool-retention 2026-09-22 11:25:47 +08:00
imccyu efa63a7fc4 release(vendor): cordis 4.0.3, cosmokit 1.8.4, group 1.0.3, hmr 1.0.18, include 1.0.8, loader 1.0.4, logger-console 1.0.3, schemastery 3.18.3, timer 1.1.5 2026-09-22 11:21:12 +08:00
Yichen Jiang d20c90a091 Merge remote-tracking branch 'origin/master' into worktree/voice-input-icon 2026-09-22 11:19:32 +08:00
Turtle 1d1b033f77 Revert "feat(shortcuts): add configurable Web and desktop shortcuts" (#4886) 2026-09-22 11:17:24 +08:00
_Kerman ad83cce36a fix(session): repair missing turn ends during V3 migration (#4689)
* fix(session): repair interrupted turns during V3 migration

* docs(session-format-v3-to-v4): state reference remapping in the summary and code

The frontmatter summary still promised preserved references after the edge
began remapping audited same-artifact references around an inserted
interrupted turn/end. Two local comments record why the opaque branch moves
only `seq` and why the open-step flag needs no reset at a turn boundary.

* docs(session-format-catalog): describe the V3-to-V4 edge as a converting link

The catalog listed the edge as an identity conversion, which stopped being
true once it inserted an evidenced interrupted turn/end and remapped the
audited local references that follow.
2026-09-22 11:13:54 +08:00
Yichen Jiang 2fb7c881db Merge remote-tracking branch 'origin/master' into worktree/voice-input-icon 2026-09-22 11:13:49 +08:00
Turtle 2c95550e87 Revert "feat(shortcuts): add configurable Web and desktop shortcuts" 2026-09-22 11:04:01 +08:00
Yichen Jiang 577ccabb96 fix(voice-input): match microphone support and capsule stroke widths 2026-09-22 11:03:25 +08:00
creatixchu 6b227a81a7 docs: sync plugin inventory after master merge 2026-09-22 11:00:31 +08:00
Yichen Jiang 9799132631 fix(voice-input): outline the capsule without changing microphone proportions 2026-09-22 10:59:08 +08:00
Yichen Jiang dc1e6e967b fix(voice-input): use the outline microphone icon 2026-09-22 10:53:06 +08:00
creatixchu 4137d1d628 Merge remote-tracking branch 'origin/master' into fix/4775-multimodal-tool-retention
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.zh.md
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
2026-09-22 10:52:21 +08:00
Dudu-0223 d08aac9db2 fix(agent-team): read current projections through standard hooks 2026-09-22 10:46:06 +08:00
Dudu-0223 5ca4fea9b5 Merge master into feat/agent-team-projection-panel 2026-09-22 10:45:10 +08:00
Yichen Jiang 8c022b8013 fix(voice-input): use waveform artwork and filled microphone 2026-09-22 10:42:59 +08:00
流光 08b73684d0 feat(shortcuts): add configurable Web and desktop shortcuts (#4847)
- Add shortcut discovery, search, recording, and customization.
- Persist device-local bindings with conflict detection and reset support.
- Integrate shortcuts with desktop menus, workspace actions, and sidebar focus.
- Add unit coverage and browser regression snapshots.
2026-09-22 03:46:10 +08:00
Xinyu Yang a0d453d3c6 fix(shortcuts): complete CI coverage and browser regressions 2026-09-22 03:27:55 +08:00
imccyu a68c1f6539 Merge pull request #4852 from deepseek-harness/feat/chat-process-groups-product
feat(chat): grouped work details and scoped rendering optimizations
2026-09-22 02:57:17 +08:00
imccyu c7b9c91497 fix(chat): preserve steering order and limit expanded mode to live turns 2026-09-22 02:34:16 +08:00
Huanqi Cao 44900be005 docs(native-command): name explorer.exe in the Windows open note
The Agent Note title said 'the shell's own application resolution', which names a layer instead of the command the opener runs.
2026-09-22 02:07:32 +08:00
Huanqi Cao 68e43b173e fix(native-command): open Windows paths through the shell's resolution
The settings sheet's Open configuration file action opened nothing on Windows when the user's default lived only in the Explorer per-user record (FileExts\\<ext>\\UserChoiceLatest), which Explorer honors and the association resolver inside the host process does not. Invoke-Item also exits 0 when it finds no application, so the Remote answered { opened: true } and the sheet rendered no error.

Windows opens now hand the path to explorer.exe as one argv element - the resolution a double-click performs - and revealNativePath shares that invocation rule. The shared helper accepts Explorer's delegate exit 1 for an open and a reveal alike; every other failure and every cancellation still rejects. The PowerShell command string and powershellLiteral are gone: the path crosses the process boundary as argv, with no escaping step.

Fixes #4428
2026-09-22 01:57:21 +08:00
imccyu 504013def1 refactor(chat): simplify process titles and clarify grouping notes 2026-09-22 01:32:38 +08:00
imccyu 5d62f82bc0 fix(chat): preserve cross-client pending input order 2026-09-22 01:08:15 +08:00
imccyu 809e0942b9 fix(session): retire confirmed steering echoes on resync 2026-09-22 01:08:15 +08:00
imccyu 12d9dd6aa4 test(web): refresh chat process group snapshots 2026-09-22 00:45:46 +08:00
imccyu 3bf26d0954 docs(chat): consolidate grouping rationale and review status 2026-09-22 00:45:46 +08:00
imccyu 9ad25a6ab6 fix(chat): cover turn triggers and preserve reading anchors 2026-09-22 00:45:46 +08:00
imccyu 3b4ecc9d20 fix(chat): retain assistant nodes and steering echoes 2026-09-22 00:45:46 +08:00
imccyu 92046a8abc fix: snapshots 2026-09-22 00:45:46 +08:00
imccyu 275008d324 fix: static 2026-09-22 00:45:46 +08:00
imccyu b12a72867a fix(chat): keep early turn controls after opening input 2026-09-22 00:45:46 +08:00
imccyu 4d4af31d16 fix(chat): retain typed source receivers and paging results 2026-09-22 00:45:46 +08:00
imccyu 22cd2cd387 test(chat): align turn presentation and deterministic clock fixtures 2026-09-22 00:45:46 +08:00
imccyu 99c0e8dcf6 test(plan): cover scoped card binding and availability failures 2026-09-22 00:45:46 +08:00
imccyu ee3526059e docs(chat): complete grouping and viewport API comments 2026-09-22 00:45:46 +08:00
imccyu a0bf09f629 docs(chat): remove the obsolete work-details migration tracker 2026-09-22 00:45:46 +08:00
imccyu 19e5af7ded perf(chat): locate visible turns with outer-row binary search 2026-09-22 00:45:46 +08:00
imccyu 97daa6a799 perf(conversation): ignore idle width-handle pointer movement 2026-09-22 00:45:46 +08:00
imccyu 5ff9ab8757 perf(plan): subscribe cards to turn-local plan data 2026-09-22 00:45:45 +08:00
imccyu a7fc7d4f56 perf(chat): restore preference focus before publishing updates 2026-09-22 00:45:45 +08:00
imccyu 3a046413de perf(locale): avoid unchanged document language writes 2026-09-22 00:45:45 +08:00
imccyu 376f68199e perf(chat): narrow group title updates and defer edge measurements 2026-09-22 00:45:45 +08:00
imccyu 1bcb633c3f feat(chat): add grouped work details and stable history paging 2026-09-22 00:45:45 +08:00
imccyu e17e1ac801 feat(client): present turn triggers and completed-turn footers 2026-09-22 00:45:45 +08:00
imccyu 4b78b6577c feat(client): inject reset-aware disclosure hooks 2026-09-22 00:45:45 +08:00
imccyu b47cef687e Merge pull request #4863 from deepseek-harness/fix-excel
fix(web): 修复含绘图的 XLSX 文件预览
2026-09-22 00:41:02 +08:00
Xinyu Yang 76ab2a32d1 fix(shortcuts): align settings launcher and browser regressions with master 2026-09-22 00:20:29 +08:00
imccyu d49f2b1bf8 test(client): make rebuild generations independent of clock precision 2026-09-22 00:18:59 +08:00
imccyu 5270b7ffa1 test(hmr): wait for filesystem ctime before polling assertions 2026-09-22 00:01:10 +08:00
Xinyu Yang 7b564f61e7 fix(shortcuts): integrate current desktop guests and client APIs 2026-09-21 23:57:50 +08:00
Xinyu Yang 069c370987 fix(shortcuts): address review findings and modal focus 2026-09-21 23:57:49 +08:00
Xinyu Yang 49fc4f0e5b refactor(shortcuts): remove unused state and tighten command context 2026-09-21 23:57:49 +08:00
Xinyu Yang f815d6c733 fix(shortcuts): stabilize recording, focus, and desktop dispatch 2026-09-21 23:57:49 +08:00
Xinyu Yang 365ef73c7c feat(client): prioritize action tooltips over workspace previews
Hide an enclosing hover preview while an action tooltip is visible, and restore the preview when the tooltip closes.
2026-09-21 23:57:49 +08:00
Xinyu Yangand神河一号 - 烈焰流光 b7ac0ade10 feat(shortcuts): add fixed stop and approval actions
Add scoped double-Escape cancellation and fixed approval actions. Reserve their input combinations and preserve composition, modal, and input-owner arbitration.

Co-authored-by: 神河一号 - 烈焰流光 <[email protected]>
2026-09-21 23:57:49 +08:00
Xinyu Yangand神河一号 - 烈焰流光 f54744e35b feat(shortcuts): add focused panel and page commands
Route file, terminal, browser, split, fullscreen, close, and refresh commands to the focused panel. Connect native Desktop page and window actions to the same command owners.

Co-authored-by: 神河一号 - 烈焰流光 <[email protected]>
2026-09-21 23:57:49 +08:00
Xinyu Yangand神河一号 - 烈焰流光 a532a687a6 feat(shortcuts): add workspace and session commands
Connect saved bindings to workspace search, creation, session naming, forking, archiving, and external opening. Publish the loaded conversation history needed to select fork targets.

Co-authored-by: 神河一号 - 烈焰流光 <[email protected]>
2026-09-21 23:57:49 +08:00
Xinyu Yangand神河一号 - 烈焰流光 efdf8e5b6d feat(shortcuts): add configurable Web and desktop shortcuts
Add the keyboard registry, device-local preferences, and searchable shortcut editor. Support Web routing and native Desktop single-key and two-key bindings.

Co-authored-by: 神河一号 - 烈焰流光 <[email protected]>
2026-09-21 23:57:28 +08:00
imccyu 2d236df56f test(client): wait for filesystem ctime before revision checks 2026-09-21 23:49:42 +08:00
imccyu 6ba92b3f05 fix(web): preview XLSX workbooks with unsupported drawings 2026-09-21 23:26:50 +08:00
imccyu d7c238a98d Merge pull request #4855 from deepseek-harness/fix/client-revisions-server-restart
fix(web): preserve sessions across server restarts
2026-09-21 23:24:51 +08:00
lsdsjy 099eacf108 Merge pull request #4475 from deepseek-harness/feat/desktop-welcome-and-window-controls
feat(desktop,credentials): add Welcome and DeepSeek account sign-in
2026-09-21 23:04:14 +08:00
lsdsjy 5b9a33fa61 test(account): align browser flows and diagnose stalled transport 2026-09-21 22:48:12 +08:00
imccyu d1fb051e0f test(web): stamp bootstrap artifacts before rebuild checks 2026-09-21 22:41:17 +08:00
yixiangihsiang f114233545 fix(web): cover code-card overflow and refresh browser expectations 2026-09-21 22:40:55 +08:00
lsdsjy 2a1eb24285 fix(account): cover lifecycle failures and restore CI compatibility 2026-09-21 22:32:30 +08:00
Turtle d1255ab1a4 docs(agent-preset): enumerate and verify skill files with Host file tools only (#4856)
* docs(agent-preset): enumerate and verify skill files with Host file tools only

* docs(agent-preset): list template files instead of enumerating the skill directory

The glob and search tools spawn a native ripgrep process, which cannot read
inside app.asar any more than a shell can; the skill now carries the complete
template file list and forbids enumeration.
2026-09-21 22:30:57 +08:00
lsdsjy 0d985d55a2 merge: sync master into desktop welcome branch 2026-09-21 22:11:39 +08:00
lsdsjy 43ff526d1e fix(ui-settings-account): retry failed embedded Platform pages 2026-09-21 22:06:05 +08:00
lsdsjy f8175d5989 fix(desktop): synchronize embedded Platform locale 2026-09-21 21:59:10 +08:00
yixiangihsiang 8d2cd0cf72 feat(web): unify code block styling and icon controls 2026-09-21 21:57:35 +08:00
lsdsjy 9d0b8da486 fix(desktop): use medium weight for welcome brand 2026-09-21 21:53:05 +08:00
imccyu 092ae937b7 test(web): cover session recovery across server restarts 2026-09-21 21:47:52 +08:00
imccyu b1921cf56d fix(client): keep artifact revisions stable across server restarts 2026-09-21 21:47:52 +08:00
Turtle b13bbc027c feat(agent-preset): progressive creator skills and profile shell facts (#4836)
* feat(tool-cordis): inspect live plugin Config schemas

Replace the Host `Builtin` inspect provider, which described a dynamic Host
half the model can no longer define, with a `Config` provider that lists every
live Loader entry with its Config status and projects one entry's native
Schemastery Config into a self-contained JSON Schema document. app-boot exports
its projector, native-schema check, and the shared `loaderExpression`
definition for the live walk; the CLI dump keeps its profile-composition path.

* fix(tool-cordis): refresh config catalog pointer and presets e2e provider list

* feat(agent-preset): progressive creator skills and profile shell facts

Split `cordis-plugin-development` into a short procedure with `references/`
read on demand and copyable `templates/`, replace the source-reading ban in
both creator skills with an ordered list of knowledge sources, and add the
`cordis-composition-reference` skill with the Loader patch dialect and a
generated, doc-sync-gated list of loadable plugin packages. `shell-env`
exposes `DSH_PROFILE` and `DSH_PROFILE_DIR` so skills can address the installed
profile.

* chore(agent-preset): regenerate plugin package list after merging master

* fix(tool-cordis): resolve the Loader at Config query time

A Host composed programmatically without a Loader keeps registering the
inspect providers; `Config.listConfigs` reports the missing Loader when
queried. Refresh the advanced-toolchain recordings whose provider list now
carries `Config` in place of `Builtin`.

* chore(agent-preset): regenerate plugin package list after merging master

* docs: regenerate module graph for the tool-cordis app-boot dependency

* docs: regenerate module graph for the shell-env app-boot dependency

* docs: regenerate event graph pointer for app-boot exports

* fix(agent-preset): address review on creator skills

`Config.listConfigs` reports each entry's resolved `packageDir` through the
profile package lookup, and the skills read READMEs and built declarations
there instead of guessing `$DSH_PROFILE_DIR/node_modules`, which holds only
profile-installed packages. Skills name the PowerShell variable syntax and the
no-profile omission; the composition reference no longer attributes
`overridden` to `list_plugins`; references point at the templates instead of
pasting them. The skills spec renders every skill and bounds it by the pruner
threshold in code points, checks referenced files and the source-reading ban
across all skill files.

* fix(tool-cordis): address review on the Config inspect provider

Report the Loader entry id (unique across include trees) beside the tree-local
patch id, classify group and include carriers as `tree`, treat disabled and
disposed fibers as `inactive`, and drop the unreachable boolean-schema branch
by narrowing the projector's root type. The presets e2e now queries
`Config.listConfigs` over the booted Web profile and projects the shipped
`tools` row; the advanced-toolchain recordings carry the updated manifest.

* fix(tool-cordis): page the Config directory and filter it by plugin name

A full directory of a shipped Web profile exceeds the 50000-byte spill cap
once rows carry more fields, and the spilled preview is no longer JSON.
`Config.listConfigs` now returns pages (`offset`, `limit` up to 100, default
25) with `total` and `nextOffset`, and an exact plugin `name` filter; the
presets e2e reads the shipped rows through the filter.

* chore(agent-preset): refresh skill recordings after the paged Config query

* docs(agent-preset): teach the composition skill to migrate legacy presets

A preset authored before declaration rows lived in
`$DSH_HOME/.agent-presets/<id>/` as `preset.yml` plus `agent.cordis.yml`;
the skill now maps those files onto a declaration bundle and re-checks plugin
names against the package list.

* docs(agent-preset): read skill files through the file-read tool only

Desktop ships the skill directory inside app.asar, which the Host process can
open but shell commands, node, and pnpm cannot. The skills now say to read
references and templates with the file-read tool and copy templates into the
workspace before installing or checking them; the spec rejects shell reads of
skill files.

* docs(agent-preset): document bundle display metadata and package.json icon in the host-plugin reference
2026-09-21 21:28:35 +08:00
mektpoy 6f056da42f chore(deps): keep only the lockfile delta the settings portal needs
The consolidated commit refreshed unrelated transitive resolutions while it
resolved the settings portal's new react-dom dependency. Restore those entries to
their previous versions and keep only the two importer entries the portal needs;
the lockfile already carries both snapshots.
2026-09-21 21:17:55 +08:00
07akioni 8b993f43e0 Merge pull request #4845 from deepseek-harness/dev/desktop-devtools
feat(desktop): enable hidden native DevTools shortcuts
2026-09-21 21:07:26 +08:00
Turtle 1b87a2a889 fix(ui-agent-preset): restore the Creator entry on the preset settings page (#4850)
The declarative-preset refactor replaced the settings section's visible
"让 Agent 帮我创建预设模式" entry with a question-mark icon beside the title
that opened an explanatory modal, and rewrote the section's markup and CSS
along with it.

Restore the section as Ziya's commit 1ed59986f7 had it, minus the copy
(复制预设) and view (查看配置) card actions the refactor removed for good:
the roster keeps its cards, mode help and picker row, the custom group stays
on screen with the Creator entry as its tail, and the question-mark modal is
gone. The creator button stages the cordis preset and starts a task in it,
disabled with the picker's own reason while mode selection is off.

Delete and open-location stay out: the registry exposes only `list` and
`select`, and the roster row no longer carries a trust or a document.

The section spec covers the entry's four paths, and the Web scenario
replaces its help-dialog step with one that drives the entry to a host
session composed from cordis.
2026-09-21 21:05:20 +08:00
07akioni e47e85cce6 test(desktop): remove obsolete overlay DevTools assertion 2026-09-21 20:58:15 +08:00
07akioni fc7c9c2e2f fix(desktop): retain update overlay DevTools availability 2026-09-21 20:57:01 +08:00
07akioni 54f6433357 test(desktop): avoid untyped nested overlay matcher 2026-09-21 20:47:26 +08:00
07akioni 355e43c1f3 refactor(desktop): use hidden native DevTools menu shortcuts 2026-09-21 20:43:38 +08:00
mektpoy 613157c5db Merge remote-tracking branch 'origin/master' into feat/unify-code-highlight-languages 2026-09-21 20:42:39 +08:00
Turtle 8c146d978f feat(tool-cordis): inspect live plugin Config schemas (#4834)
* feat(tool-cordis): inspect live plugin Config schemas

Replace the Host `Builtin` inspect provider, which described a dynamic Host
half the model can no longer define, with a `Config` provider that lists every
live Loader entry with its Config status and projects one entry's native
Schemastery Config into a self-contained JSON Schema document. app-boot exports
its projector, native-schema check, and the shared `loaderExpression`
definition for the live walk; the CLI dump keeps its profile-composition path.

* fix(tool-cordis): refresh config catalog pointer and presets e2e provider list

* fix(tool-cordis): resolve the Loader at Config query time

A Host composed programmatically without a Loader keeps registering the
inspect providers; `Config.listConfigs` reports the missing Loader when
queried. Refresh the advanced-toolchain recordings whose provider list now
carries `Config` in place of `Builtin`.

* docs: regenerate module graph for the tool-cordis app-boot dependency

* docs: regenerate event graph pointer for app-boot exports

* fix(tool-cordis): address review on the Config inspect provider

Report the Loader entry id (unique across include trees) beside the tree-local
patch id, classify group and include carriers as `tree`, treat disabled and
disposed fibers as `inactive`, and drop the unreachable boolean-schema branch
by narrowing the projector's root type. The presets e2e now queries
`Config.listConfigs` over the booted Web profile and projects the shipped
`tools` row; the advanced-toolchain recordings carry the updated manifest.

* fix(tool-cordis): page the Config directory and filter it by plugin name

A full directory of a shipped Web profile exceeds the 50000-byte spill cap
once rows carry more fields, and the spilled preview is no longer JSON.
`Config.listConfigs` now returns pages (`offset`, `limit` up to 100, default
25) with `total` and `nextOffset`, and an exact plugin `name` filter; the
presets e2e reads the shipped rows through the filter.
2026-09-21 20:39:29 +08:00
mektpoy ba88134117 Merge remote-tracking branch 'origin/master' into feat/unify-code-highlight-languages 2026-09-21 20:37:43 +08:00
turtle1999 d52227c135 fix(ui-agent-preset): restore the Creator entry on the preset settings page
The declarative-preset refactor replaced the settings section's visible
"让 Agent 帮我创建预设模式" entry with a question-mark icon beside the title
that opened an explanatory modal, and rewrote the section's markup and CSS
along with it.

Restore the section as Ziya's commit 1ed59986f7 had it, minus the copy
(复制预设) and view (查看配置) card actions the refactor removed for good:
the roster keeps its cards, mode help and picker row, the custom group stays
on screen with the Creator entry as its tail, and the question-mark modal is
gone. The creator button stages the cordis preset and starts a task in it,
disabled with the picker's own reason while mode selection is off.

Delete and open-location stay out: the registry exposes only `list` and
`select`, and the roster row no longer carries a trust or a document.

The section spec covers the entry's four paths, and the Web scenario
replaces its help-dialog step with one that drives the entry to a host
session composed from cordis.
2026-09-21 20:19:06 +08:00
07akioni ff16cf535a fix(desktop): suppress DevTools shortcuts behind update overlays 2026-09-21 20:18:40 +08:00
winewill 53abf11bdd fix(desktop): keep the Windows About dialog on the startup locale
Review pointed out that About read its copy from the renderer-reported
Windows language while the shared update dialog stamps its lang and
close label from the startup locale, so an in-app language switch mixed
languages inside one dialog. About now uses the same startup messages
as Check for Updates. The menu click also logs a dialog that fails to
open instead of leaving an unhandled rejection, and the return type no
longer hides the message-box result behind unknown.
2026-09-21 20:11:05 +08:00
07akioni edae410733 feat(desktop): support Command Option I for macOS DevTools 2026-09-21 20:06:43 +08:00
lsdsjy e8778d413d Merge commit 'e3c84634b4' into HEAD 2026-09-21 20:02:27 +08:00
lsdsjy 3306fac787 merge: include latest master in desktop welcome branch 2026-09-21 20:01:07 +08:00
lsdsjy e682ad3e5b fix(ui-settings-account): keep sign-in errors in the login dialog 2026-09-21 19:56:34 +08:00
lsdsjy a2bc1e412c test(account): type browser popup proxy values 2026-09-21 19:54:43 +08:00
lsdsjy d5db0ff0c4 merge: sync master into desktop welcome branch 2026-09-21 19:53:28 +08:00
Yichen Jiang fcd89f691a fix(voice-input): explain model preparation download failures 2026-09-21 19:50:20 +08:00
07akioni 982fb17754 feat(desktop): open renderer DevTools with F12 in packaged builds 2026-09-21 19:49:04 +08:00
Jiawei Song f384ee7418 Merge branch 'master' into fix/4823-message-overflow-review-menu 2026-09-21 19:48:47 +08:00
Yichen Jiang cbae324bfa feat(workspace): stop a Session's running work before archiving it (#4765)
* feat(workspace): stop a Session's running work before archiving it

Archiving was a pure visibility write, so a Session archived mid-turn kept
running out of sight. The Workspace registry now owns archive admission
through two Host events: `workspace/session-activity` reports what still
runs and refuses the plain archive as `workspace/session-active`;
`workspace/session-stop`, requested with `stopActivity`, stops that work the
way the user's own stop actions do before the archive write. The API Session
Controller reports and stops turns, subagent descendants, and owned jobs and
rejects any model step for an archived Session; the Schedule plugin reports
and deletes active reminders. The sidebar turns the refusal into a
stop-and-archive confirmation listing the Host's answer.

* test(workspace): pin the widened archive signature and prove child liveness by heartbeat

The Client inspect catalog spec pins archiveSession's new options
parameter, and the archive e2e reads the Bash child's liveness from a
heartbeat file instead of a pid: the Linux sandbox runs the tool in its own
PID namespace, so the pid it reports is not comparable from the test.

* test(workspace): cover the archive-admission providers and dialog to the per-file gate

Drop the provider's unused disposer and the dialog's unreachable confirm
guard, read reminders without a catch that no composition can reach, and
add the cases the coverage lane found missing: a stop without a jobs
registry, a looping lineage, a descendant whose projections reject, the
dialog's Escape guard and non-Error reason, and a family merged by another
provider.

* fix(workspace): write the archive before stopping, gate subagent lineage, and delete reminders under the schedule barriers

Review round on #4765. The registry now writes the archive set before it
dispatches `workspace/session-stop`, so the durable set already gates
every wake the stops induce; the controller's `agent/pre-step` gate also
blocks subagent descendants of an archived Session and contains each
cancel or kill on its own. The Schedule plugin's stop listener runs as a
management delete in the agent's transaction queue between the same two
persistence barriers the `schedule_delete` tool uses. The confirm dialog
selects singular or plural English lines and keys list rows by index.
Docs: archive-admission section with type-equiv blocks on the workspace
subsystem page, write-first order and residual windows in the READMEs
and the Agent Note, and the missing zh reminders sentence.

* test(web): scope the question composer's New Session wait to the Sessions tree

The wide sidebar's New Session button carries the same visible label as
a fresh session row, so the unscoped `getByText` either settled on the
button before the row existed or hit a strict-mode violation once the
row rendered first, which is how the snapshots lane failed on
ece68c2ab5. Waiting inside the Sessions tree names the row alone.

* fix(schedule): answer archive admission from the owned runtime's fold, not the projection registry

The `sessionProjections.snapshot` API is the Client projection view and
is not a Host read path (review on #4765). `ScheduleRuntime.activeRecords()`
folds the live log the way every drive does, and the archive-admission
listeners ask the owned runtime for that fold: a session without a live
agent or without an owned runtime has nothing armed to fire, so it reports
nothing and has nothing to stop. Covers the runtime-less agent, a fold that
turns unreadable at the persistence barrier, and the stopping/faulted
runtime answering nothing.

* refactor(subagent): report and stop subagent descendants from the Subagent runtime

The `subagent` family of archive admission moves out of the API Session
Controller into `dsh-subagent`, which records the lineage at delegation
and owns the descriptor (review on #4765): `SubagentRuntime` answers
`workspace/session-activity` with the running descendants, labelled from
each child's descriptor through a live Session observation, and
`workspace/session-stop` by cancelling each of them with the parent
cause. The controller keeps turns, owned jobs, and the lineage step gate,
and composes its provider through `ctx.plugin(SessionActivityProvider)`
with declared injections instead of a bare installer call. `dsh-workspace`
becomes an optional type-only peer of `dsh-subagent`.

* refactor(jobs): answer archive admission for owned jobs from the job registry seam

The `job` family moves out of the API Session Controller into `dsh-jobs`
(review on #4765): the seam's constructor installs the
`workspace/session-activity` and `workspace/session-stop` listeners for
every implementation through the abstract `list` and `kill` alone, so the
controller no longer knows the jobs vocabulary and keeps only the turn
family and the archived-lineage step gate. `dsh-workspace` becomes an
optional type-only peer of `dsh-jobs`.

* refactor(workspace): leave SessionActivityKindMap empty and let each provider merge its family

The workspace package no longer names any activity family (review on
#4765): `SessionActivityKindMap` is empty, and each provider merges its own
key from a module both its faces import — `turn` in the API Session
Controller's types, `job` in the job registry seam's view, `subagent` in
the Subagent runtime's control types, `schedule` in the Schedule plugin's
types. The confirm dialog imports those modules for its cases and keeps
the generic line for any other key; the registry and controller suites
merge test-owned families instead of borrowing the providers'.

* refactor(agent): report and stop the running turn from the Agent registry

The `turn` family moves out of the API Session Controller into `dsh-agent`
(review on #4765): the registry's constructor installs the
`workspace/session-activity` and `workspace/session-stop` listeners for
every Agent it publishes, answering with its own lookup and cancelling the
turn with the user cause, and merges the `turn` key from its client-safe
types. The controller keeps only the archived-lineage step gate, renamed
`ArchivedSessionGate`. `dsh-workspace` becomes an optional type-only peer
of `dsh-agent`; the workspace package depends on none of the providers,
so the edge stays acyclic.

Since #3127 a foreground Bash command is a registered job from its start,
so the archive dialog lists it beside the turn; the e2e and its ARIA golden
expect that row, and the capture keeps the running job by design.
2026-09-21 11:46:13 +00:00
lsdsjy 44b15a3377 fix(desktop,credentials): address sign-in review regressions 2026-09-21 19:39:42 +08:00
winewill 89251dde83 Merge remote-tracking branch 'origin/master' into feat/desktop-update-ui-2 2026-09-21 19:39:37 +08:00
sjw1231 7ebbd370cd test(web): preserve quoted file reference coverage 2026-09-21 19:34:51 +08:00
sjw1231 719cc56276 Merge branch 'master' into fix/4823-message-overflow-review-menu 2026-09-21 19:25:06 +08:00
mektpoy fe09f495a5 Merge remote-tracking branch 'origin/master' into feat/unify-code-highlight-languages
# Conflicts:
#	packages/client/ui-primitives/tsconfig.json
#	pnpm-lock.yaml
2026-09-21 19:19:36 +08:00
lsdsjy 1137e86aef fix(desktop,ui-theme): align bundled Montserrat fonts with onboarding 2026-09-21 19:19:00 +08:00
mektpoy b0ad792e6b fix(web): keep dedicated previews and the read-card lang domain
The shared code-language table must not claim a suffix a dedicated viewer
declares, and the Host read card must keep the `lang` values it already
persisted.

- Drop `csv` from the shared table: Code registers before Spreadsheet, so
  the earlier body would take `.csv` and the browser snapshot gate fails.
- Add `readLangHintForPath`, the read card's legacy projection over the
  shared table: the 43 pre-unification suffixes keep their old short ids
  byte for byte, new suffixes use the canonical id.
- Add an ownership regression test over the full preview registry that
  turns red when `csv` returns, plus byte-level and alias-normalized tests
  for the read projection.
2026-09-21 19:14:08 +08:00
winewill 894f25b91e fix(desktop): source the About product name from the locale
The client UI i18n gate rejects literal message text in main.ts; the
Windows About dialog now reads the product name from the dictionaries
like every other shell string.
2026-09-21 19:03:39 +08:00
mektpoy dc07e5a50d fix(tools): keep surrogate pairs intact when capping tool output
Three tools capped the preview text they return with String.prototype.slice
at a UTF-16 code-unit budget. A cut that lands inside a surrogate pair
leaves a lone high surrogate, which is not well-formed text: a strict JSON
reader rejects the durable Session log carrying it, and the preview shows a
broken glyph. A lone surrogate retained in history has already blocked every
later Messages request for one session.

Centralize the cap in output-retention as
truncateWithoutSplittingSurrogatePair, and use it from the persistent bash
and pwsh shells and the string-replace editor. The cut drops the unpaired
half instead of keeping it, so the retained text stays a prefix and is at
most one code unit shorter than before.

The new dependency edges and the shifted Config sources regenerate
docs/module-graph and docs/config-catalog, including the committed
translation pair.

Refs #4817
2026-09-21 18:51:19 +08:00
Yudong Han f65c15a5cf feat(preview): unify document zoom controls (#4785) 2026-09-21 10:49:45 +00:00
Yudong Han d0ddf939f0 refactor(office): transfer PDFs as multipart bytes (#4830)
* refactor(office): transfer PDFs as multipart bytes

* fix(document-preview): address Office review feedback
2026-09-21 10:30:10 +00:00
Turtle 601d6761e4 feat(settings): project volatile Config through profile-backed forms (#4587) 2026-09-21 18:26:03 +08:00
Yichen Jiang da7ca4265a fix(voice-input): explain model download network requirements 2026-09-21 18:09:31 +08:00
Jiawei Song c63e174b7b Merge pull request #4798 from deepseek-harness/fix/4670-review-tab-scroll-and-filename
fix(ui-deliverables): prevent edge rebound and preserve filename endings
2026-09-21 18:08:50 +08:00
Jiawei Song 08653de38a Merge branch 'master' into fix/4670-review-tab-scroll-and-filename 2026-09-21 17:59:51 +08:00
07akioni c82e40d498 Merge pull request #4809 from deepseek-harness/otel/product-telemetry
feat(telemetry): add explicit product event OTLP exporter
2026-09-21 17:59:21 +08:00
winewill bc4e8bafe6 Merge remote-tracking branch 'origin/master' into feat/desktop-update-ui 2026-09-21 17:58:40 +08:00
sjw1231 5847ff8721 chore: merge master into review tab fixes 2026-09-21 17:58:14 +08:00
Yichen Jiang 645e4faab2 fix(voice-input): add a dedicated plugin icon 2026-09-21 17:54:37 +08:00
07akioni 6d13819fbc docs(telemetry): regenerate module graph after package rename 2026-09-21 17:50:32 +08:00
07akioni 3a3aaaf796 Merge pull request #4804 from deepseek-harness/fix/desktop-ripgrep-unpack
fix(desktop): unpack platform ripgrep executables
2026-09-21 17:50:05 +08:00
sjw1231 5aa21749b9 fix(web): wrap long file references and track floating menus
Fixes #4823
2026-09-21 17:48:27 +08:00
winewill c1edda8a37 fix(desktop): show the Windows About command in the update dialog
Electron's About role on Windows falls back to a bare system message
box, which looks nothing like the shell's dimmed update prompts. Design
asked for the version check to match Check for Updates, so the Windows
menu item now opens the shared update dialog with the application name,
localized version line and a single OK button; macOS keeps the native
panel. The About command follows the renderer's chosen language like
the rest of the Windows caption menu.
2026-09-21 17:46:26 +08:00
07akioni 535cb4aae3 fix(telemetry): isolate collector transport and address review 2026-09-21 17:45:19 +08:00
mektpoy 6945da14cb feat(web): unify the code-highlight language table and extend it
The document Code preview and the Host read card each owned an
extension-to-language table that had drifted: the preview table had 13
extensions the read card lacked, and the two returned different language
ids for the same suffix. Both now resolve through the new zero-dependency
@deepseek-ai/dsh-util-code-language, which also adds common Windows,
config, markup, and language extensions. Every added grammar stays in the
lazy set; the boot grammars are unchanged.

Fixes #4822
2026-09-21 17:42:11 +08:00
winewill 1566f3f5ad fix(desktop): round the Windows app icon corners further
The Windows badge used a 44px radius on its 1024px plate, which reads as
nearly square on the desktop next to other Windows 11 icons. Raise the
radius to 192px (3/16 of the plate, matching Tencent Meeting's corner)
and re-export the transparent 1024×1024 PNG from the SVG; the ICO for
the app, installer and uninstaller and the About panel image all derive
from that PNG.
2026-09-21 17:40:49 +08:00
winewill 481b6b57e5 fix(desktop): simplify the update-available restart notice
The manual check dialog explained that the release bundles its matching
dsh runtime before mentioning the restart. Users only need to know the
app restarts to finish updating; the bundling detail belongs in the
README, not the confirmation. Both locales carry the shorter sentence.
2026-09-21 17:39:50 +08:00
07akioni b2ad3bf020 Merge remote-tracking branch 'origin/master' into fix/desktop-ripgrep-unpack 2026-09-21 17:37:59 +08:00
creatixchu 754733d5d1 test: update shell spill snapshot for the shared token budget 2026-09-21 17:34:29 +08:00
07akioni 8b89200324 Merge remote-tracking branch 'origin/master' into otel/product-telemetry 2026-09-21 17:33:03 +08:00
winewill dcac4c6eac Merge pull request #4792 from deepseek-harness/build/windows-release-scripts
fix(desktop): 修复 Windows 发布脚本阻断缺陷并建立构建版本权威来源
2026-09-21 17:31:45 +08:00
Yichen Jiang b2db503913 Merge pull request #4458 from deepseek-harness/feat/plugin-detail-slots
feat(web): open plugin detail-page slots and move official settings pages to companions
2026-09-21 17:30:26 +08:00
creatixchu f3c6d0c0df test: refresh multimodal tool catalog after master update 2026-09-21 17:28:00 +08:00
Huanqi Cao 68b44d78ba Merge remote-tracking branch 'origin/master' into fix/pwsh-prompt-readiness
# Conflicts:
#	docs/config-catalog.i18n.yaml
2026-09-21 17:21:55 +08:00
winewill 5fdad8d838 Merge branch 'master' into build/windows-release-scripts 2026-09-21 17:21:48 +08:00
creatixchu 575dc9add0 Merge remote-tracking branch 'origin/master' into fix/4775-multimodal-tool-retention 2026-09-21 17:21:38 +08:00
Turtle 4eb26f0e71 feat(cli): export JSON Schema for Cordis configuration (#4705)
* feat(cli): dump native Cordis config schemas

* test(cli): include schema dump in launcher help snapshot

* feat(cli): export JSON Schema for Cordis configuration

* fix(cli): preserve config schema discovery and annotations

* fix(cli): conservatively project effectful config validation

* refactor(boot): encapsulate profile config schema generation

* fix(cli): follow Loader disabling and native writeback in config schema

- Dormant group/include rows (disabled without group: true) may omit
  config and are recorded as childless trees; the entry schema skips
  their child declarations, matching the Loader, which never creates them.
- Lazy builders run once per document, and a wrapped null-only projection
  keeps a deduplicated type list so the document stays compilable.
- Union widening applies only when an earlier branch can write adapted
  values back through a container; +Infinity max and -Infinity min
  without a step are treated as the native no-ops they are.
- Projection limitations repeat at every entry sharing a Config, and the
  entry schema documents the boolean/expression domain of disabled.
- Record the schema-dump validation policy as an Agent Note.
2026-09-21 09:19:24 +00:00
creatixchu b0be6e79c2 fix: preserve failed PTC image result forwarding semantics 2026-09-21 17:17:03 +08:00
Yichen Jiang aba8b3a29f Merge remote-tracking branch 'origin/master' into feat/plugin-detail-slots 2026-09-21 17:15:10 +08:00
Yichen Jiang 5882efd7ce test(web): re-record the bundle golden for plugin-owned identity
The bundle page now titles the fixture by its package name, prints the
row id as code under the row's title, and drops the missing-description
line, as master's row and official goldens already record.
2026-09-21 17:13:41 +08:00
Yichen Jiang 4b54e59a52 Merge pull request #3127 from deepseek-harness/worktree/job-kill-delivery
feat(jobs): human job kill, timeout promotion, and workflow run_in_background
2026-09-21 17:13:28 +08:00
Yichen Jiang 873140cff3 test(web): follow master's slot fixture and cast rules after the merge
The Plugins page spec's configuration bodies take the view positionally
as master's fixture does, the companion and section specs read a slot
entry's injected face through a Pick of the members they assert instead
of a double assertion, and the no-unknown-casts baseline drops the
entries retired with the moved settings tests.
2026-09-21 17:13:17 +08:00
winewill 735700c4b5 Merge pull request #4789 from deepseek-harness/feat/windows-clean-uninstall
feat(desktop): Windows 卸载随应用清除 Electron 本机数据,保留 .dsh
2026-09-21 17:12:00 +08:00
creatixchu 14c1fec958 test: record mixed-content retention through the headless profile 2026-09-21 17:11:56 +08:00
creatixchu 79468e26dd test: stabilize multimodal spill recovery locators 2026-09-21 17:08:01 +08:00
winewill d54b000bdb fix(desktop): keep the new specs off the built tree and off unknown casts
The afterPack spec mocked the built runtime tree through a path relative
to the spec, which only resolves once `lib/` exists; on a clean checkout
the hook imported the real module and every case failed. It now mocks
the path the hook actually resolves, as the asar-unpack spec does, and
passes with `lib/` absent.

The toolchain probe assertion reached its matcher through an assertion
to unknown, which `verify-no-unknown-casts` forbids. It compares the
reported tools and detail directly instead.
2026-09-21 17:05:33 +08:00
Yifffan f33b604ca2 Merge pull request #4786 from deepseek-harness/fix/4781-dedupe-open-with-apps
fix(native-command): macOS「从应用打开」菜单去重
2026-09-21 17:05:06 +08:00
winewill 0981cd5924 fix(desktop): harden the Windows uninstall data removal after review
Pinned directories are now opened with listing access so the handle takes
part in share checks and a rename or replacement of the directory under the
helper fails; a metadata-only handle did not participate. A DSH_HOME published
as an environment variable protects overlapping targets, and /KEEP_APP_DATA
retains data alongside --updated, matching the flags electron-builder passes
to an older uninstaller. The remover clears read-only attributes, keeps
deleting siblings after a locked file, and removes only ordinary empty scope
parents below %APPDATA% instead of an NSIS RMDir that would also unlink a
junction. The redundant un.DataInit extraction is gone.

The native regression now runs from the installer test driver and covers the
protected root, rename blocking, read-only and locked files and parent
removal; the uninstaller smoke uses a per-run scope, polls for the temp-copy
handoff, asserts InstallLocation after each silent install, and adds
/KEEP_APP_DATA and DSH_HOME-inside cases. The Agent Note keeps the topic's
2026-09-08 filename, states the amendment in the decision, and defers macOS.
2026-09-21 17:01:54 +08:00
Yudong Han 5b4ca4a29e Merge pull request #4808 from deepseek-harness/fix/pr4346-spreadsheet-review
fix(preview): harden spreadsheet conversion
2026-09-21 17:01:28 +08:00
Yichen Jiang 36a29b424d test(web): settle the transient running-job control before conversation goldens
A foreground shell command is a job while it runs, and its removal reaches
the browser one coalesced roster frame after the tool result, so a
conversation golden captured right after the turn could catch the header's
running-job control; the replay round-trip golden did on CI. captureStableAria
now waits for that control to leave unless a scenario keeps it, which the
two job scenarios that capture a running row do.
2026-09-21 17:01:17 +08:00
creatixchu 4694540e2a Merge remote-tracking branch 'origin/master' into fix/4775-multimodal-tool-retention
# Conflicts:
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
2026-09-21 16:59:45 +08:00
Yichen Jiang ecb66a3497 Merge remote-tracking branch 'origin/master' into feat/plugin-detail-slots
# Conflicts:
#	.agents/notes/implemented/architecture/2026-09-16-plugin-configuration-on-the-plugins-page.i18n.yaml
#	.agents/notes/implemented/architecture/2026-09-16-plugin-configuration-on-the-plugins-page.md
#	.agents/notes/implemented/architecture/2026-09-16-plugin-configuration-on-the-plugins-page.zh.md
#	apps/web/tests/expected/plugin-config/row.expected.md
#	apps/web/tests/fixtures/plugins/fixture-live-client/client.js
#	apps/web/tests/plugin-config.e2e.ts
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/config-catalog.zh.md
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	packages/bundle/web-app/package.json
#	packages/client/ui-plugin-manager/README.i18n.yaml
#	packages/client/ui-plugin-manager/README.md
#	packages/client/ui-plugin-manager/README.zh.md
#	packages/client/ui-plugin-manager/src/client/PluginManagerPage.tsx
#	packages/client/ui-plugin-manager/src/client/index.ts
#	packages/client/ui-plugin-manager/src/client/slot-contract.ts
#	packages/client/ui-plugin-manager/tests/components.client.spec.tsx
#	packages/client/ui-settings-plugins/README.i18n.yaml
#	packages/client/ui-settings-plugins/README.md
#	packages/client/ui-settings-plugins/README.zh.md
#	packages/extensions/cordis-client-runner/src/client/slot-catalog.ts
#	pnpm-lock.yaml
2026-09-21 16:59:17 +08:00
creatixchu e52209da40 test: share multimodal snapshot composition 2026-09-21 16:57:59 +08:00
creatixchu 5c1d966c3f test: cover image recovery failures and snapshot registration 2026-09-21 16:55:13 +08:00
Huanqi Cao 74f4c438de test(pty): pin the pwsh fast path by settle reason
The composition suite's idleSilenceMs: 30000 was below the suite's own send
bound (dsh-terminal-bash timeoutMs: 300000), so the comment claiming silence
could settle nothing was wrong: a regressed send still settled as inferred_idle
after ~30 s and only the accumulated case timeout caught it.

The case now records every send's waitReason and requires at least six
stdin_read settlements with no inferred_idle. Reinstating the removed prompt
override fails it in 30 s with 'expected 0 to be greater than or equal to 6'
while the output assertions still pass. The silence tier returns to its product
default.

Also renames the two stale test titles ('private shell prompt', and the
cancellation phase that no longer covers an initialization send), pins the
stdin_read fallback's session retention, and records the interactive-child
consequence of that retention in the package README pair and the Agent Note.
2026-09-21 16:53:15 +08:00
Dudu-0223 552235aab6 docs: align the Chinese config catalog with the regenerated source line 2026-09-21 16:52:05 +08:00
creatixchu c4c18ef0d4 test: align retention checks and catalogs with token budgets 2026-09-21 16:50:35 +08:00
dsh-agent 2545414c02 test(preview): lock ini admission to the code renderer
The issue reported .ini files with no preview. On master the ini grammar is
already in CODE_HIGHLIGHT_EXTENSIONS, so the code renderer claims the
suffix and .ini previews. No production change is required; this test
records the admission behavior so a future allowlist change cannot silently
drop the reported suffix.
2026-09-21 16:46:45 +08:00
Dudu-0223 38dbb56237 test(agent-team): type Team panel fixtures without unknown casts and regenerate catalogs
The static CI gate rejected four new assertions to unknown in the
rewritten Team panel specs. Build the Session list, Session snapshot,
and injected-callback fixtures as typed values, prune the retired
baseline fingerprints, and regenerate the module graph, config, and
persistence catalogs for the removed Remote dependency edges and the
shifted source lines.
2026-09-21 16:45:40 +08:00
creatixchu ab102138c8 fix: retain ordered tool text and images within a token budget 2026-09-21 16:45:21 +08:00
lsdsjy 4ae923fe6f fix(desktop): refine welcome typography and copy feedback 2026-09-21 16:44:47 +08:00
dsh-agent 6fa5151d8a fix(ui-open-in-app): keep an application as the default file action
The Host's default marker is best effort: on Windows it comes from the
Shell's ASSOCSTR_EXECUTABLE/APPID answer, which does not always name an
enumerated handler. When no application carried that marker the split
button promoted 显示文件位置 to the primary action even though the menu
listed applications that can open the file.

Select the OS-marked default when present, otherwise the first registered
handler in Shell preference order, and mark it as the menu default.
Reveal is promoted only when no application is registered at all.
2026-09-21 16:39:38 +08:00
dsh-agent d685383ee6 fix(native-command): resolve packaged Windows app icons
Windows 11 ships some applications (Notepad, other Store apps) as MSIX
packages whose Shell handler reports an indirect icon reference such as
@{Microsoft.WindowsNotepad_...?ms-resource://.../NotepadAppList.png}
instead of a file path. SHDefExtractIcon cannot read that reference, so
the menu showed the generic fallback glyph.

Resolve an indirect reference with SHLoadIndirectString before extracting,
and fall back to the handler's executable when the resolved source still
yields no image.
2026-09-21 16:39:34 +08:00
lsdsjy 4e5e1f9c7a fix(ui-settings-account): allow retry after active sign-in errors 2026-09-21 16:39:31 +08:00
Yichen Jiang 131fb841f2 Merge remote-tracking branch 'origin/master' into worktree/job-kill-delivery
# Conflicts:
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
2026-09-21 16:39:19 +08:00
winewill b8050f0251 fix(desktop): finish the review items the first pass missed
Three comments in the same review round went unread and still applied.

A failed tag push left the local tag in place, so the printed recovery
`git tag … && git push …` short-circuited on "already exists" and never
pushed. The result now carries the commands still outstanding, and the
tests cover a failed push and a failed tag separately.

Automatic numbering caught every error from resolving the upload
destination, which turned a misconfigured destination into silent local
numbering that can reuse a published index. It now checks whether a
destination is configured at all and lets an invalid one fail, and the
remaining catch names the error it reports.

`pnpmCommand` fell back to a bare `pnpm`, which on Windows is the batch
shim spawnSync cannot start — the failure this branch exists to fix. It
says so instead, and keeps the fallback where a shim is executable.

The afterPack regression this branch introduced earlier reached review
because nothing exercised that hook: one spec calls it directly for an
ordinary build, a prepared qualification runtime, and a build version,
and it fails when the expected version collapses back to one value.
2026-09-21 16:37:50 +08:00
Dudu-0223 1dc518f217 feat(agent-team): drive the Web Team panel from the agentTeam projection
The Team panel read a Remote snapshot on open and behind an explicit
refresh button, while the subagent catalog panel updates from Host
projection frames. The Team projection was Host-only and its `apply`
mutated state in place, so the projection registry could never publish
a client view for it.

Publish a durable-only `agentTeam` wire view: roster rows with their
durable phase, non-deleted task views through the same readiness,
owner-name, and write-overlap derivation the task board returns to
agents, and `failure` beside the last valid state when a persisted Team
record is rejected. `apply` now returns a new state per applied Team
event and replaces only the touched collection, so mailbox-only events
reuse the previous view reference and publish nothing.

The Web panel derives every row from the shared Session store: the Lead
from the current Session's subagent address, running/inactive from
Session status, and the model from the member Session's durable
`modelSelection` projection. Opening requests the Lead's projection
baseline when the store has none, a failed read shows a retry control,
and the refresh button and Remote mount are gone. The `agentTeams/view`
Remote method remains for callers that need live availability and the
configured model.

The Team panel web e2e now asserts that Host-side task creation and
claiming reach the open panel without any user action.
2026-09-21 16:37:10 +08:00
07akioni 3a3422f517 Merge remote-tracking branch 'origin/master' into otel/product-telemetry 2026-09-21 16:34:37 +08:00
Yichen Jiang 0659ded55b refactor(job-controller): drop the subagent ownership fence from job.kill
The registry's owner fence is the only access rule for a human kill: a job
is killable by the session whose list carries it, and a child session's own
jobs are no exception. The fence had pulled two implementation helpers out
of the Session Controller's package entry (plus a safe-host-export exception
for them) so the job controller could import them; both go, and the job
controller no longer depends on the agent registry or the Session Controller.
2026-09-21 16:34:15 +08:00
Turtle 949e875f7c Merge pull request #4732 from deepseek-harness/turtle/favicon-dark-fix-c387d950b8d9
fix(web): select static favicons with media-qualified links
2026-09-21 16:28:26 +08:00
07akioni 910d52f717 feat(telemetry): add explicit product event OTLP exporter 2026-09-21 16:28:18 +08:00
Jiawei Song 9e87907849 Merge branch 'master' into fix/4670-review-tab-scroll-and-filename 2026-09-21 16:27:08 +08:00
Huanqi Cao b900840784 Merge remote-tracking branch 'origin/master' into fix/pwsh-prompt-readiness
# Conflicts:
#	docs/config-catalog.i18n.yaml
2026-09-21 16:26:08 +08:00
Yif b631804d2b Merge remote-tracking branch 'origin/master' into fix/4781-dedupe-open-with-apps 2026-09-21 16:25:47 +08:00
07akioni c1ad3bb493 test(desktop): align ripgrep packaging checks and fixtures 2026-09-21 16:25:03 +08:00
Huanqi Cao 4f74f956ec Merge remote-tracking branch 'origin/master' into fix/pwsh-prompt-readiness
# Conflicts:
#	docs/config-catalog.i18n.yaml
2026-09-21 16:24:49 +08:00
Turtle d1e22a7e24 feat(preset): declare Agent compositions in profile YAML (#4569)
* feat(preset): declare Agent compositions in profile YAML

* fix(preset): share scope binding cleanup and refresh module graph

* fix(preset): use host syntax colors in the YAML editor

* fix(preset): write new profile declarations as block YAML

* fix(preset): align eager activation with browser and worker surfaces

* fix(ui-agent-preset): retain the existing preset card layout

* fix(preset): keep rows waiting for a Host service mounted and re-audit after settlement

A preset row whose Host provider was still activating at declaration time
was reported as waiting for a missing service, and the registry recorded the
definition as broken for the rest of the process. Split the mount audit into
failed and pending rows: failures and root-realm leaks still reject the
mount, while pending rows stay mounted and every read and binding re-audits
them after the Host Loader tree settles.

Remove the accidental self-dependency of @deepseek-ai/dsh-web-app and its
lockfile self-link. Archive the copy-only preset authoring note, which the
declarative-preset note fully supersedes, and update the ralph note's
restore recipe to the profile-patch mechanism.

* chore(lint): re-key and prune the unknown-cast baseline after the master merge

* refactor(web-app): ship each Agent preset as its own bundle patch file

`dsh.bundle.patch` accepts an ordered file list, so the four shipped preset
declarations move out of the 1000-line web patch into
`presets/<id>.patch.yml`, one insert per file, applied after the host patch.
The host patch keeps the preset registry row. Gates and test scaffolds that
read the web layer resolve every patch file through `bundlePatchPaths`
instead of one hardcoded path.

* refactor(preset): drop the save notice injected into live Agents

The notice duplicated the save result the Web editor already shows, and
after the producer-owned message sources it would have needed its own
persisted source kind. Saving now only persists and reports the activation
diagnostic; the persistence catalog is unchanged from master.

* docs: regenerate the module graph after dropping the registry's llm dependency

* test(ui-agent-preset): cover the guide dialog's keyboard handling on the declarative section

* fix(preset): address the remaining review comments

Apply the lowercase id rule only when creating a declaration, so presets
declared with other ids stay editable. Export `isBuiltInPreset` from the
display fold and key the client card groups on it. Remove the dead `error`
and `retry` locale keys, the JSDoc orphaned by the `trust` removal, the
`trust` fields in the plugin-inventory test fixtures, and the stale
`dsh-agent-presets` package name in comments and READMEs.

* refactor(preset): make the Web preset page view-and-select only

Remove the child-plugin YAML editor, the `agent_preset` tool and the
registry's read/save Remote methods. Presets are declared and changed only by
bundle patches; the settings page keeps the roster, the new-task default and
the mode help, and its question icon explains that and offers to start a
Creator-mode task. The `editing-cordis-compositions` skill and the Creator
persona describe the bundle-based path, and the authored skill-load Session
and Web snapshots are refreshed for it.

* docs(skill): make the composition skill self-sufficient for preset authoring

State where the shipped declarations live, list every declaration field,
inline a complete minimal bundle and an override example, and name the
verification calls, so Creator mode no longer reads DSH package sources to
infer the format. Refresh the authored skill-load Session for the new text.

* test(tools): drop the removed agent_preset tool from the catalog expectation
2026-09-21 08:24:18 +00:00
winewill 685ed95f17 Merge remote-tracking branch 'origin/master' into feat/windows-clean-uninstall 2026-09-21 16:20:49 +08:00
Turtle 933d3bf39e Merge pull request #4784 from deepseek-harness/turtle/chip-model-truncate-4889eecc8358
fix(web): collapse model text when composer controls cannot fit
2026-09-21 16:20:18 +08:00
sjw1231 6340df605d refactor(client): share file tree path labels and improve review tests 2026-09-21 16:19:56 +08:00
winewill 0b91ce2126 refactor(desktop): drop the uninstall data-removal log line
Nobody reads the uninstaller details list and NSIS keeps no log file, so the
failure message added no diagnostic value while costing a bilingual string.
Removal failures now leave residue silently; the uninstaller carries no custom
copy.
2026-09-21 16:15:57 +08:00
07akioni b20a383a7a fix(desktop): unpack platform ripgrep executables 2026-09-21 16:15:47 +08:00
winewill 0181baae5b Merge branch 'master' into build/windows-release-scripts
Adopt the `unsignedArtifacts` build path master introduced, in place of
the directory this branch was joining by hand for automatic numbering.
2026-09-21 16:14:26 +08:00
Yichen Jiang 2bba702a6e Merge remote-tracking branch 'origin/master' into worktree/job-kill-delivery 2026-09-21 16:14:21 +08:00
Turtle a9840f055f fix(web): select static favicons with media-qualified links 2026-09-21 16:13:38 +08:00
Yichen Jiang 7a29f57199 chore(session-controller): drop the leftover dsh-jobs type import
The import came with the session.killJob Remote that later moved to the
job controller; nothing in this package reads ctx.jobs any more, and the
package declares no dependency on the seam.
2026-09-21 16:12:14 +08:00
Yif 3cab7723e4 fix(native-command): validate macOS grouping fields without an unsafe any 2026-09-21 16:12:09 +08:00
Turtle 4a2b8486da Merge master to resolve PR #4784 conflicts 2026-09-21 16:11:41 +08:00
Yudong Han 22da693201 Merge pull request #4346 from deepseek-harness/web/excel-frontend-preview
feat(preview): open spreadsheets in the browser
2026-09-21 16:06:37 +08:00
winewill 1b6451a647 fix(desktop): follow the documented release version rules
Review found that `apps/desktop/README.md#release-versions` and the
2026-09-16 version-derivation note already specify this convention, and
that three of their requirements were reversed without saying so. The
rules themselves are right; what was wrong was leaving them undocumented
and rejecting one of the forms they prescribe.

A stable base takes `-test.YYYYMMDD.index`, which validation refused
because such a version ranks below its base. That ordering is the point:
the form belongs to a test feed that never serves the production
release. Both READMEs, the older note, and a new note now record which
requirements this change reverses and why.

Three defects the review found, each reproducible:

- `afterPack` compared the bundled runtime against the product version,
  which broke installed-update qualification: that flow passes a runtime
  whose version was deliberately rewritten. The expected version is now
  a parameter the preparer supplies, and `verifyDesktopRuntime` says
  "bundled X is not the expected Y" rather than naming Electron.
- Upload could only learn the published version from a shell variable,
  conflicting with "release fields come only from the target file". It
  reads the completion record packaging wrote, and a mismatch now prints
  the version that record holds.
- Automatic numbering read one listing page and one fixed directory. It
  now follows every page, discards a listing it could not finish rather
  than reusing an index that would overwrite a published installer,
  bounds the request through the client's own timeout, and reads the
  directory an unsigned build actually writes.

Also: `npm run` and `yarn run` set `npm_execpath` too, so the pnpm
resolution checks the path names pnpm; the argument separator can arrive
after a run script's preset arguments, not only first; and the toolchain
probe, parser, build commit, and tarball readers now have specs.
2026-09-21 16:04:08 +08:00
creatixchu 4e47ba6c1d chore: start multimodal tool result retention work 2026-09-21 16:03:43 +08:00
sjw1231 02a0c70662 fix(ui-deliverables): preserve review fixes in shared file diff 2026-09-21 16:01:02 +08:00
Huanqi Cao 97545d9c8f fix(pty): keep the controlled prompt so persistent pwsh settles fast
tool-pwsh-persistent installs its own `prompt` function after spawn, so
terminal-bash prompt readiness never matched and every send degraded to the
silence tier (idleSilenceMs + handoffGraceMs) under production defaults. This
is the defect the persistent bash tool fixed for the bash stack.

The tool now initializes without a prompt send and detects the no-end-marker
fallback through the seam's stdin_read wait reason instead of matching its own
prompt text. The private prompt constant and its stripping are deleted, so
partial output can carry the backend's own trailing prompt.

Tool calls drop from 8493/3722/3832/3759 ms to 1340/255/251/241 ms (spawn and
initialization plus the first command, then three warm commands; Windows,
production defaults, real Loader composition). The loader composition suite
pushes idleSilenceMs beyond the send bound, so every case fails if prompt
readiness regresses.
2026-09-21 15:57:08 +08:00
yudshj 57bcfac402 Merge remote-tracking branch 'origin/master' into web/excel-frontend-preview 2026-09-21 15:54:49 +08:00
Yichen Jiang 2cbf8df484 Merge pull request #4412 from deepseek-harness/worktree/experimental-voice-input
feat(voice-input): add optional local SenseVoice dictation
2026-09-21 15:53:42 +08:00
winewill ec52049610 docs(desktop): drop the Start menu claim for InstallLocation
On Windows 11 the Start menu context-menu Uninstall opens the installed-apps
list for every Win32 application regardless of the uninstall entry; only MSIX
packages uninstall from there. Keep InstallLocation as standard uninstall-entry
metadata and stop attributing Start menu behavior to it.
2026-09-21 15:48:14 +08:00
yudshj e7287e499e Merge remote-tracking branch 'origin/master' into web/excel-frontend-preview 2026-09-21 15:47:19 +08:00
Yif 1a14166d2b fix(native-command): validate the full handler list and dedupe only for display 2026-09-21 15:46:03 +08:00
Dudu-0223 5e0934ebbb Merge pull request #4698 from deepseek-harness/fix/team-task-board-read-only
fix(web): make Team tasks read-only and contain the panel
2026-09-21 15:45:52 +08:00
Yichen Jiang 080bea0b85 Merge remote-tracking branch 'origin/master' into worktree/experimental-voice-input
# Conflicts:
#	scripts/gen-cordis-catalog.ts
2026-09-21 15:39:45 +08:00
Dudu-0223 a93aa38876 Merge branch 'master' into fix/team-task-board-read-only 2026-09-21 15:38:03 +08:00
yudshj cbe0d84fc1 Merge remote-tracking branch 'origin/master' into web/excel-frontend-preview 2026-09-21 15:37:28 +08:00
CreatixChu 683625b793 Merge pull request #4780 from deepseek-harness/ihsiang/changed-files-hover-preview
feat(web): preview changed-file diffs on hover
2026-09-21 15:36:12 +08:00
yudshj 61a0acc4da fix(preview): satisfy strict spreadsheet lint 2026-09-21 15:35:57 +08:00
Dudu-0223 3324157b7f fix(web): address Team panel review feedback 2026-09-21 15:30:18 +08:00
imccyu 85f16860f5 Merge pull request #4758 from deepseek-harness/feat/chat-step-groups
feat(web): add definition-owned conversation groups
2026-09-21 15:29:30 +08:00
creatixchu e17f505504 Merge master into ihsiang/changed-files-hover-preview 2026-09-21 15:27:19 +08:00
winewill 4ab8fbfacc fix(desktop): name the commit a build records instead of its provenance
The concrete-terms gate forbids "provenance": the repository asks for the
exact source, field, or identity a value holds. The module records one
commit and whether its tree was dirty, so it and its callers say that.

The toolchain step also has to stay out of the way of the packaging
entry's error-recording test, which fakes the host platform and would
otherwise report the absent Windows compilers rather than the failure it
exercises. The test mocks the probe, as it already does for the release
environment and the signing keychain, and expects the new stage.
2026-09-21 15:26:29 +08:00
Yichen Jiang 4c7c7a552f Merge remote-tracking branch 'origin/master' into worktree/job-kill-delivery 2026-09-21 15:26:10 +08:00
Yichen Jiang bb20149360 refactor(shell): register foreground commands as jobs at start and drop the promotion protocol
With a job registry composed, tool-bash and tool-pwsh now register every
command with ctx.jobs as it starts and wait on the job with the registry's
own bounded wait: a command that finishes in time returns the ordinary
foreground result and its record is removed, one that outlives the timeout
returns the same job id it already had, and a kill from outside the call is
reported as `[stopped: <reason>]`. Nothing changes hands at the deadline, so
the shell seam loses `onExpiry: 'offer'`, `ShellExecution.promotion`, and
`ShellPromotionOffer`, and both local executors drop their offer arm.

The registry stays optional: the tools register a foreground-only definition
while no registry is composed and swap to the job-backed one inside a
`ctx.inject(['jobs'])` fork, so a composition without jobs keeps a plain bash
with no job tools in the model's schema. A refused registration at the start
(admission, no controller) runs under the executor's deadline kill, and a wait
that expires before the process spawned ends as the preparation timeout.

JobRegistry gains `remove(id, caller?)` and the `settled` event reports
`awaited`, so dsh-tool-jobs no longer keeps its own wait ledger; it withholds
notices for awaited settlements and for kills the model requested. The tool
catalog harvest composes the registry so the shipped schema stays documented,
and the two compaction fixtures move their context window from 10000 to 10300
tokens because the branch's larger tool schemas pushed their condensed history
over the old trigger, which requested a fourth scripted model call.
2026-09-21 15:23:08 +08:00
Yichen Jiang 262ee1bc23 fix(voice-input): address lifecycle and provider review feedback 2026-09-21 15:21:16 +08:00
sjw1231 c6e38b364f fix(client): resolve review tab conflicts and path label coverage 2026-09-21 15:19:38 +08:00
Huanqi Cao eb7d3af91c Merge pull request #4582 from deepseek-harness/fix/windows-acl-delete-escape
fix(sandbox): confine Windows deletes to the granted root
2026-09-21 15:18:36 +08:00
winewill 93a65a9a94 feat(desktop): remove Electron data on Windows uninstall without a custom page
Product dropped Harness-home cleanup from the uninstaller, so the opt-in page,
its bilingual dialog, the uninstall.ini home record and the overlap check go
away. The uninstaller now always removes the Electron user-data directory,
the %APPDATA% product directory and the updater cache through the native
helper; the Harness home is never touched. Silent uninstalls remove the same
data, upgrades retain it, and a locked file is logged instead of stopping the
uninstall.

Electron derives user data from the scoped package name, so the removal
targets %APPDATA%\@deepseek-ai\dsh-desktop and removes the empty scope
directory afterwards. The previous fixture used an unscoped name and never
reached that directory; the fixture now uses a scoped package name.

The native uninstall smoke runs end to end on the development host after two
test fixes: the interactive uninstaller was launched hidden, which made every
control invisible to the text search, and the Chinese finish text matched
"已经从" instead of MUI's "已从你". The native remover regression is renamed
data-cleanup-test.exe because UAC installer detection demanded elevation from
the unmanifested uninstall-data-test.exe.
2026-09-21 15:14:44 +08:00
Dudu-0223 35489c0f5c fix(web): manage Team panel keyboard focus 2026-09-21 15:09:08 +08:00
Dudu-0223 59b5a4ac0f chore: prune removed Team test assertion baselines 2026-09-21 15:09:07 +08:00
Dudu-0223 253fb5e66d fix(web): make Team tasks read-only and contain the panel 2026-09-21 15:09:07 +08:00
07akioni 7717eb39c0 Merge pull request #4553 from deepseek-harness/07akioni/fix-desktop-office-asar
fix(desktop): unpack native Office engine and verify packaged conversion
2026-09-21 15:08:18 +08:00
sjw1231 795e5024bc fix(ui-deliverables): fill diff row backgrounds across scroll width 2026-09-21 15:05:43 +08:00
Yichen Jiang d44d899c71 Merge pull request #4783 from deepseek-harness/feat/docs-image-viewer
为文档截图复用 Mermaid 弹层与缩放逻辑
2026-09-21 15:04:42 +08:00
Turtle cf323fdaac docs(web): clarify model collapse contract and geometry ownership 2026-09-21 15:01:04 +08:00
imccyu a67ad91237 feat(client): expose indexed positions to group definitions 2026-09-21 14:56:14 +08:00
Yif 64094e8991 test(web): match the 36px unpreviewable open control height 2026-09-21 14:56:01 +08:00
lsdsjy 0d2fbaad67 fix(session-controller,ui-model-selection,ui-settings): handle catalog and account setup failures 2026-09-21 14:55:08 +08:00
lsdsjy 9cf12959f2 fix(ui-model-selection): retain effort and open unselected models directly 2026-09-21 14:54:51 +08:00
lsdsjy 7dc86578d8 fix(ui-settings-account,ui-model-selection): align with updated primitives and catalog checks 2026-09-21 14:54:51 +08:00
lsdsjy 325e28bfa0 fix(ui-model-selection,llm-deepseek): prioritize account models and simplify provider label 2026-09-21 14:54:51 +08:00
lsdsjy cc478ac70a feat(client,session-controller,llm): track available models and expose account settings 2026-09-21 14:54:51 +08:00
lsdsjy 17825ee8c0 feat(agent,llm-deepseek,ui-settings-account): separate account routing and confirm sign-out 2026-09-21 14:54:50 +08:00
lsdsjy 7079376f28 fix(ui-settings): restore settings panel dimensions and radius 2026-09-21 14:53:25 +08:00
Huanqi Cao 11d36dd102 Merge remote-tracking branch 'origin/master' into fix/windows-acl-delete-escape
# Conflicts:
#	docs/config-catalog.i18n.yaml
2026-09-21 14:51:40 +08:00
winewill ee0fc82267 fix(desktop): check the bundled runtime against the product version
Injecting a build version renamed the Electron shell but not the dsh
runtime packed into it, and afterPack required the two to be equal, so
every build carrying a build version failed after packaging finished.
The bundled runtime is the dsh package at the product version, which is
what the check now compares against; the app already reports the shell
version and the bundled runtime version separately to the update policy.

Rename the flag to --build-version. The repository already has
DOWNLOAD_TEST_RELEASE_ID for the opaque test feed directory, so calling
a version a release id invited a reader to confuse the two. Accept a
forwarded `--` as well, because `pnpm run <script> -- --build-version x`
passes the separator through as an argument and every following option
would otherwise parse as a second target.
2026-09-21 14:45:35 +08:00
sjw1231 60cdd547ae fix(ui-deliverables): preserve filename endings in review headers 2026-09-21 14:45:18 +08:00
imccyu 7f382a1e2c Merge pull request #4757 from deepseek-harness/worktree-npmlink
feat(boot): resolve linked plugin peers from the running installation
2026-09-21 14:38:32 +08:00
gengruilin b1d878b33d fix(website): address shared viewer review feedback 2026-09-21 14:31:37 +08:00
yudshj ad9f77db04 fix(preview): compact spreadsheet formula warning 2026-09-21 14:28:15 +08:00
winewill 950ed3f6df feat(desktop): publish a build version without rewriting the manifests
Packaging a build for a test feed or a colleague required bumping the
version in 295 manifests plus the lockfile first, because the version a
build publishes was only ever read from the checkout. Those edits cannot
be committed, so every such build left the working tree dirty, and the
`<version>.<date>.<sequence>` convention behind them lived only in the
operator's memory.

The version a build publishes is now an input. `--release-id` names it,
`--release-id auto` numbers it after the builds already published to the
destination bucket (falling back to local artifacts, since a fresh CI
checkout has none), and it reaches electron-builder through
extraMetadata, the update feed, and the upload validation as one value.
The manifests keep the product version, aligned with the dsh npm
package, and a release still publishes exactly that.

Validation goes through `semver` itself, because `electron-updater`
compares feed versions with `semver.gt` against the installed
`app.getVersion()`: a build version must outrank the product version it
extends, which holds for `0.1.6-alpha.2.20260921.1` over
`0.1.6-alpha.2` and cannot hold on a stable version, where a fourth
release number is not a version at all.

Two things a build could not previously answer for itself:

- Artifacts now carry the commit they were packaged from and whether
  that checkout was dirty, so a build handed to a colleague is traceable
  without a tag.
- A production upload tags that commit as `desktop-v<version>` once the
  artifacts are public, and reports what to run by hand rather than
  failing an upload that already completed. Test and local builds are
  deliberately left untagged.

A toolchain step now probes tar and the Windows installer compiler
before the first build step, so a host that cannot finish the sequence
says so in seconds rather than minutes.
2026-09-21 14:23:48 +08:00
winewill dbbecd2461 feat(desktop): opt-in Windows uninstall data removal
The Windows uninstaller keeps every user file by default and adds a custom
page with unchecked options for desktop browser data and update caches, the
desktop plugin profile, and the complete Harness home. Selecting the whole
home requires a native warning that names the actual folder and the CLI
impact, defaults to Cancel, and forces the desktop child selection. Silent
and upgrade uninstalls never remove data, including through the legacy
--delete-app-data flag, which the adapted upstream template no longer honors.

Packaged Desktop records its resolved home in uninstall.ini under the
Electron user-data directory so a custom DSH_HOME is offered instead of the
default; a length field detects truncated NSIS reads and an invalid record
disables whole-home removal. The native remover in window-frame.dll rejects
protected roots and overlap with retained data, holds directory handles
during traversal, and unlinks reparse points without entering their targets.

Installation now also writes InstallLocation on the Windows uninstall entry,
which Explorer needs to associate the Start menu shortcut with this entry so
that the context-menu Uninstall launches the uninstaller directly instead of
opening the installed-apps list. The upstream template only records the
value under its private key.

Closes #3993
2026-09-21 14:22:39 +08:00
Ziya d7d099c7eb Merge pull request #4772 from deepseek-harness/copy/ptc-description-20260920
fix(web): describe PTC mode by the tasks it suits
2026-09-21 14:19:44 +08:00
Turtle 69fb366034 test(web): provide font events in built-bundle jsdom fixtures 2026-09-21 14:19:02 +08:00
Yifffan f91f461dc6 Merge branch 'master' into fix/4781-dedupe-open-with-apps 2026-09-21 14:16:43 +08:00
Yif 9a485724f6 fix(open-in-app): scale the empty-state opener chevron up and trim its height to 36px 2026-09-21 14:15:11 +08:00
Ziya a95dfea48d Merge branch 'master' into copy/ptc-description-20260920 2026-09-21 14:11:33 +08:00
Yichen Jiang b3d54fcef7 Merge pull request #4605 from deepseek-harness/worktree/model-provider-entry-ux-dde717
feat(models-ui): one add-provider entry with a segmented mode switch
2026-09-21 14:10:47 +08:00
imccyu 7252e5823b fix(boot): keep linked-root removal independent of relinking 2026-09-21 14:00:52 +08:00
imccyu 73e9efbbdf docs(boot): define linked-root removal across generations 2026-09-21 14:00:52 +08:00
imccyu cf41c158ba fix(boot): keep host lookups native and fix source smoke fixtures 2026-09-21 14:00:52 +08:00
imccyu c9d4b7561d fix(boot): apply linked peers at each native lookup position 2026-09-21 14:00:52 +08:00
imccyu 3e7af9cfbb feat(boot): resolve linked plugin peers from the running installation 2026-09-21 14:00:51 +08:00
imccyu a946008275 docs(boot): document linked plugin peer resolution 2026-09-21 14:00:51 +08:00
Yif 6cb1cd921f fix(native-command): collapse duplicate macOS handler copies to one menu entry 2026-09-21 13:58:18 +08:00
Yichen Jiang ed0700ffb5 Merge remote-tracking branch 'origin/master' into worktree/model-provider-entry-ux-dde717 2026-09-21 13:57:38 +08:00
07akioni 818c51f969 Merge remote-tracking branch 'origin/master' into 07akioni/fix-desktop-office-asar 2026-09-21 13:57:30 +08:00
Turtle c136d821dd fix(web): collapse model text when composer controls cannot fit 2026-09-21 13:56:47 +08:00
Turtle 4aba48ec03 fix(cordis): register Host inspect providers once per process (#4742)
`tool-cordis` registered the four first-party Host inspect providers from
every preset row that mounted it. The Host registry rejects a duplicate
provider id, so a second preset carrying `tool-cordis` — or a user preset
copied from a shipped one — failed to mount in the same process.

- Add `@deepseek-ai/dsh-tool-cordis/host` (`cordis-inspect-providers`),
  the host-plane row that registers the providers; the Web host
  composition mounts it beside `cordis-host-runner`. The per-session
  `tool-cordis` row now only registers the tools and its prompt section.
- Gate the `cordis` preset's `tool-plugin-manager` row on `profileContext`,
  the same condition `dsh-base` applies to the host `plugin-manager`
  service, so a profile-less embedding still mounts the preset.
2026-09-21 05:55:09 +00:00
yixiangihsiang 440070e4f8 fix(web): address diff preview review findings 2026-09-21 13:51:53 +08:00
07akioni 4e5aec6a74 Merge remote-tracking branch 'origin/master' into codex/office-package-master 2026-09-21 13:46:31 +08:00
Yifffan b6cb6be3da Merge pull request #4767 from deepseek-harness/fix/desktop-minimize-vibrancy
fix(desktop): 修复 macOS 最小化恢复后侧边栏毛玻璃短暂透明,同时修改 session 跑马灯效果
2026-09-21 13:42:11 +08:00
gengruilin cb718ce9da feat(website): enlarge screenshots with the shared media viewer 2026-09-21 13:40:37 +08:00
07akioni e0b5ab5ebd Merge master into PR #4553 and resolve runtime helper import 2026-09-21 13:39:09 +08:00
imccyu 7dd6d1fc31 docs(client): mark the grouping foundation implemented 2026-09-21 13:30:25 +08:00
imccyu b9252673e9 fix(client): report only changed turn locations 2026-09-21 13:30:25 +08:00
imccyu b3549ee455 fix(client): preserve grouped chat navigation and view lifecycle 2026-09-21 13:30:25 +08:00
imccyu c1c3410cf0 fix(benchmarks): declare grouping runtime dependency 2026-09-21 13:30:25 +08:00
imccyu 0076de86fc test(client): cover group injection and conversation fixtures 2026-09-21 13:30:25 +08:00
imccyu a7d457349f docs(client): record the conversation grouping foundation 2026-09-21 13:30:25 +08:00
imccyu 1b3b56c8f1 feat(client): render stable conversation group references 2026-09-21 13:30:25 +08:00
imccyu c890269a19 feat(client): add definition-owned conversation groups 2026-09-21 13:30:25 +08:00
winewill 766eee63eb fix(release): run pnpm and tar portably on Windows
spawnSync cannot start the pnpm .cmd shim without a shell, so the bump
step's lockfile refresh failed with ENOENT on Windows after rewriting
every manifest. Resolve pnpm to a JavaScript entry executed by the
current Node: the run-script's npm_execpath when present, otherwise the
workspace's own pnpm dependency (located on disk because pnpm's manifest
does not export its bin entry).

GNU tar parses the colon in an absolute Windows path as a remote-host
separator and aborts, so the tarball readers now run tar in the
tarball's directory and pass only its file name.
2026-09-21 13:30:12 +08:00
yudshj 767cb38567 fix(locales): update titles for Office document in Chinese and English 2026-09-21 13:20:45 +08:00
yudshj 15415600d1 fix(preview): render spreadsheet values as literal text 2026-09-21 13:20:45 +08:00
yudshj 9f6434d24b refactor(web): move Office loading into its injected face 2026-09-21 13:20:45 +08:00
yudshj f51092015f refactor(preview): align spreadsheets with shared file preview structure 2026-09-21 13:20:45 +08:00
yudshj e70fa89400 feat(preview): support xls csv and tsv 2026-09-21 13:20:45 +08:00
yudshj 30b6abad5c fix(preview): retain Excel worksheet selections 2026-09-21 13:20:44 +08:00
yudshj 087dc65e89 feat(preview): render Excel workbooks in the browser 2026-09-21 13:20:44 +08:00
yixiangihsiang 90a1b23e4a feat(web): preview changed-file diffs on hover 2026-09-21 13:19:52 +08:00
Yudong Han eaf0f68bb2 Merge pull request #4401 from deepseek-harness/perf/workspace-file-binary-transfer
feat(api): support binary fields in Remote results
2026-09-21 05:18:16 +00:00
Yifffan d7318cb7b5 Merge branch 'master' into fix/desktop-minimize-vibrancy 2026-09-21 13:17:27 +08:00
_Kerman e4fbb92570 Merge pull request #4770 from deepseek-harness/xtr/normalize-agent-cancel-cause
fix(agent-loop): copy the cancel cause before logging turn/end
2026-09-21 13:13:36 +08:00
Yif 8dafa0829b Merge remote-tracking branch 'origin/fix/desktop-minimize-vibrancy' into fix/desktop-minimize-vibrancy 2026-09-21 13:04:29 +08:00
Yif b4886c7e5b feat(workspace): marquee hovered session titles with fades on both cut edges 2026-09-21 13:02:48 +08:00
Yif 44fe86eaf8 test(desktop): cover the minimize backdrop swap and extract the chrome fallback fill 2026-09-21 13:02:45 +08:00
Ziya 63b7a0f7c1 Merge branch 'master' into copy/ptc-description-20260920 2026-09-21 12:53:07 +08:00
Yudong Han e98b5703c7 refactor(api): move Remote result projection to gateway 2026-09-21 12:50:42 +08:00
Yudong 2aac7c8ef5 fix(connection): keep narrowed attachment path type 2026-09-21 12:50:41 +08:00
Yudong 285f0a7005 fix(connection): narrow binary transport values 2026-09-21 12:50:41 +08:00
Yudong 983b89f9a5 refactor(fs): default unsupported file watching 2026-09-21 12:50:41 +08:00
Yudong ecf6acfb15 feat(api): support binary fields in Remote results 2026-09-21 12:50:40 +08:00
_Kerman 2e99e6021d Merge remote-tracking branch 'origin/master' into xtr/normalize-agent-cancel-cause 2026-09-21 12:45:05 +08:00
CreatixChu 6fba9d3bfb Merge pull request #4544 from deepseek-harness/worktree/issue-3881-folder-drop
feat(web): 桌面端支持将文件夹拖入输入框
2026-09-21 12:44:44 +08:00
Turtle 7520fe94e1 refactor(preset): 精简创造模式的 system prompt (#4745)
* refactor(preset): trim the creation-mode system prompt

The `cordis` preset persona repeated what the plugin_manager and
cordis_inspect_* tool descriptions and the two shipped skills already
carry. Keep only identity, the shipped-preset constraint, the visual
request routing rule, and which skill to load for what.

Drop the tool-cordis prompt section, which restated its own tool
descriptions, and the cordis_inspect_query navigation hints that the
provider manifests returned by cordis_inspect_list already state.
Shorten both skill descriptions so the first-turn catalog stays small.

First-turn request for the cordis preset, measured through the DeepSeek
API with deepseek-v4-flash: 9572 -> 8975 prompt tokens.

* docs: regenerate config catalog after section order removal

* docs: regenerate module graph after tool-cordis dependency removal

* refactor(preset): give the cordis preset the standard persona

Creation mode's system prompt now equals standard mode's; the skill
catalog and the shipped skills carry every routing and off-limits rule.
The plugin skill description states the visual-request destination.

First-turn request for the cordis preset: 9572 -> 8815 prompt tokens.

* fix(review): document current tool-cordis state and pin the shared persona

The tool-cordis README pair now states that only the two tool schemas
enter requests, that disposal removes tools and providers, and that
the first-turn skill catalog carries the routing. The Web skill row
test resolves the owner's selected fixture generation instead of a
fixed v3 path. The preset e2e asserts the cordis persona sections
equal standard's.
2026-09-21 04:43:38 +00:00
_Kerman 3773c4f85b docs(agent-loop): correct the owning cancellation note
The 2026-07-16 explicit-turn-cancellation note still described a frozen,
detached signal reason and a two-variant cause union. The README paragraph
added here points readers at that note as the owner of the signal
lifecycle, so the stale mechanism was load-bearing.

It now records why freezing the caller's cause is not an alternative:
undici assigns `stack` from strict-mode code, so a frozen reason makes
fetch reject with `TypeError: Cannot add property stack` in place of the
abort reason.

Also names `turn/end`'s declared `TurnEndCancelCause` in the README and
takes the reviewer's helper-doc wording.
2026-09-21 12:42:36 +08:00
lsdsjy a43da8740d fix(desktop,ui-settings-account): resolve branch hygiene violations 2026-09-21 12:42:03 +08:00
Yichen Jiang b42a93d62f Merge remote-tracking branch 'origin/master' into worktree/job-kill-delivery
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/event-producer-consumer.i18n.yaml
#	docs/module-graph.i18n.yaml
#	docs/tool-catalog.i18n.yaml
#	packages/api/session-controller/README.i18n.yaml
#	packages/api/session-controller/src/commands.ts
#	packages/client/ui-jobs/tests/browser-plugin.client.spec.ts
#	packages/client/ui-jobs/tests/job-list-action.client.spec.tsx
#	packages/shell/tool-bash/README.i18n.yaml
#	packages/shell/tool-bash/src/background.ts
#	packages/shell/tool-pwsh/src/background.ts
2026-09-21 12:40:44 +08:00
Ziya f206efb628 Merge branch 'master' into copy/ptc-description-20260920 2026-09-21 12:38:17 +08:00
creatixchu 6ac2d741a6 test(llm): retain pending mock listeners through teardown 2026-09-21 12:36:54 +08:00
creatixchu 6f07deab31 test(llm): preserve coverage timeout budget and drain stalled fixtures 2026-09-21 12:33:59 +08:00
creatixchu 49ff1f815d Merge origin/master into worktree/issue-3881-folder-drop 2026-09-21 12:33:50 +08:00
Yichen Jiang 35a02e1658 Merge pull request #3052 from deepseek-harness/worktree/process-plugin-streaming-72f9b3
feat(jobs): consolidate the job seam around one output ring and stream it to the session-header job list
2026-09-21 12:27:29 +08:00
Yichen Jiang dc1f87e890 Merge branch 'master' of github.com:deepseek-harness/deepseek-harness into worktree/process-plugin-streaming-72f9b3 2026-09-21 12:03:46 +08:00
Yichen Jiang 21d2c8b948 Merge pull request #4768 from deepseek-harness/worktree/input-plugin-extension-hooks
feat(web): expose input plugin extension hooks
2026-09-21 12:03:10 +08:00
winewill 4df3de2075 fix(desktop): sharpen installer brand art and progress-page scaling
Re-render the four installer brand banners from the vector sources:
the badge follows the Figma spec (three-stop gradients, layered drop
shadows) and the whale no longer inherits shape-rendering=crispEdges,
which disabled anti-aliasing and left jagged edges. The wordmark now
reaches its design color instead of a soft #353638.

Draw the progress-page brand with high-quality bicubic interpolation
and half-pixel offset so the always-2x bitmap stays crisp when scaled
down at 96 DPI.
2026-09-21 12:02:49 +08:00
lsdsjy f0b896aac8 refactor(desktop): render welcome with React and shared assets 2026-09-21 11:58:18 +08:00
creatixchu e30f0c7774 test(terminal): check descendant quiescence instead of PID removal 2026-09-21 11:58:04 +08:00
Turtle a0f59aac40 fix(llm-pi-ai): stop re-parsing streamed tool-call arguments on every delta (#4740)
pi-ai 0.85.1 runs parseStreamingJson over the whole accumulated argument
JSON on every tool-call delta, so one large tool call costs O(n²) CPU on
the event loop and a multi-megabyte argument stream stalls every session
in the process. Patch the six stream adapters to parse once at
toolcall_end, document the patch, and cover both OpenAI protocols.

Fixes #4739
2026-09-21 03:53:37 +00:00
mektpoy a2487e34b7 fix(desktop): lock the development runtime target and complete the resolution
- main-startup: assert primaryRuntime for the unpackaged Host and cover a
  missing DSH_DESKTOP_PRIMARY_RUNTIME_DIR as a fatal startup dialog with no
  Host started.
- test-workspace-updates: pass the prepared primary-runtime directory instead
  of an application/runtime path the runner never creates.
- development-project: derive the descriptor platform/arch from
  resolveDesktopBuildTarget so it matches the prepared payload.
- main: resolve the unpackaged primary runtime once at startup instead of
  inside the Host factory.
- dev: keep the environment override symmetric with its neighbours.
- README: document the variable as required for unpackaged launches and record
  the remaining win32-arm64 payload architecture limitation.
2026-09-21 11:53:32 +08:00
Yichen Jiang bb7e92c999 Merge remote-tracking branch 'origin/master' into worktree/process-plugin-streaming-72f9b3
# Conflicts:
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/persistence-catalog.i18n.yaml
#	docs/persistence-catalog.md
#	docs/persistence-catalog.zh.md
#	docs/persistence-schema.json
2026-09-21 11:51:54 +08:00
ZiyaZhang e649981497 fix(web): describe PTC mode by the tasks it suits
The PTC card in Settings explained the mechanism (the agent chains tools
through code) rather than which tasks to pick it for, so readers could
not tell it apart from Standard mode the way the Minimal and Creator
cards allow. Reword the Chinese and English card and new-task menu copy
to name the tasks: batch tool calls whose results are then filtered,
organized, deduplicated, counted, or summarized. Update the four ARIA
snapshots that embed this text.
2026-09-20 20:49:56 -07:00
Yichen Jiang 3f17ab99d4 refactor(chat): restore ui-chat import paths to master
Six ui-chat modules carried import-path and line-wrap differences unrelated
to the jobs seam; they now match master byte for byte.
2026-09-21 11:46:55 +08:00
_Kerman 35f3abf1fa fix(agent-loop): copy the cancel cause before logging turn/end
Node's fetch assigns an enumerable `stack` string onto the abort reason
object it receives, and the loop logged that same object into `turn/end`.
The undici trace became durable session data under a field no reader
declares. A transport adding a property JSON discards instead made
`Session.append` reject the ending, leaving a turn with no close.

`abortedCancelCause()` narrows the untyped `AbortSignal.reason` once and
copies the declared fields, replacing the three `as AgentCancelCause`
assertions at the two read sites and the log write.
2026-09-21 11:45:03 +08:00
creatixchu 20be0ff297 Merge origin/master into worktree/issue-3881-folder-drop 2026-09-21 11:41:36 +08:00
Yichen Jiang 4625cd376f Merge branch 'worktree/input-plugin-extension-hooks' into worktree/experimental-voice-input 2026-09-21 11:40:10 +08:00
Yichen Jiang 2ab948a11b Merge remote-tracking branch 'origin/master' into worktree/input-plugin-extension-hooks 2026-09-21 11:39:00 +08:00
creatixchu d0ac0afbe2 fix(composer): recognize pasted directories through entry metadata 2026-09-21 11:38:44 +08:00
CreatixChu c240582109 Merge pull request #4646 from deepseek-harness/feat/4562-file-open-apps
feat: 统一文件和目录的跨平台打开控件
2026-09-21 11:38:41 +08:00
Yichen Jiang 9746e97260 Merge branch 'worktree/input-plugin-extension-hooks' into worktree/experimental-voice-input 2026-09-21 11:36:00 +08:00
Yichen Jiang 9df1b6033a fix(web): keep the empty composer dock collapsed 2026-09-21 11:35:35 +08:00
Yichen Jiang 61719629fc Merge remote-tracking branch 'origin/master' into worktree/process-plugin-streaming-72f9b3
# Conflicts:
#	apps/web/tests/expected/agent-preset-selection/header.expected.md
#	docs/architecture.i18n.yaml
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	docs/persistence-catalog.i18n.yaml
#	docs/persistence-catalog.md
#	docs/persistence-catalog.zh.md
#	docs/persistence-schema.json
#	docs/subsystems/web-client.i18n.yaml
#	packages/api/README.i18n.yaml
#	packages/api/README.md
#	packages/api/README.zh.md
#	packages/api/session-controller/README.i18n.yaml
#	packages/api/session-controller/README.md
#	packages/api/session-controller/README.zh.md
#	packages/api/session-controller/src/client/sessions/manager.ts
#	packages/api/session-controller/src/client/sessions/service.ts
#	packages/api/session-controller/tests/manager.client.spec.ts
#	packages/client/locale/tests/language-row.client.spec.tsx
#	packages/client/ui-chat/tests/chat-view.client.spec.tsx
#	packages/client/ui-chat/tests/transcript-view-row.client.spec.tsx
#	packages/client/ui-conversation/tests/conversation-registry.client.spec.ts
#	packages/client/ui-conversation/tests/enter-behavior-row.client.spec.tsx
#	packages/client/ui-conversation/tests/input-bar.client.spec.tsx
#	packages/client/ui-conversation/tests/input-matrix.client.spec.tsx
#	packages/client/ui-conversation/tests/input-scenarios.client.spec.tsx
#	packages/client/ui-conversation/tests/skeleton.client.spec.tsx
#	packages/client/ui-deliverables/tests/deliverables.client.spec.tsx
#	packages/client/ui-jobs/tests/job-list-action.client.spec.tsx
#	packages/client/ui-layout/tests/app-frame.client.spec.tsx
#	packages/client/ui-layout/tests/document-title.client.spec.tsx
#	packages/client/ui-open-in-app/tests/open-in-app-action.client.spec.tsx
#	packages/client/ui-primitives/README.i18n.yaml
#	packages/client/ui-session/tests/ui-session.client.spec.ts
#	packages/client/ui-settings-general/tests/settings-root.client.spec.tsx
#	packages/client/ui-settings-unarchive-sessions/tests/components.client.spec.tsx
#	packages/client/ui-subagent/README.i18n.yaml
#	packages/client/ui-subagent/README.md
#	packages/client/ui-subagent/README.zh.md
#	packages/client/ui-subagent/src/client/SubagentHeaderLineage.tsx
#	packages/client/ui-subagent/tests/conversation-ui.client.spec.tsx
#	packages/client/ui-theme/tests/appearance-row.client.spec.tsx
#	packages/client/ui-theme/tests/font-size-row.client.spec.tsx
#	packages/client/ui-tool/tests/coverage-tails.client.spec.tsx
#	packages/client/ui-tool/tests/diff-card.client.spec.tsx
#	packages/client/ui-tool/tests/image-card.client.spec.tsx
#	packages/client/ui-tool/tests/read-card.client.spec.tsx
#	packages/client/ui-tool/tests/terminal-card.client.spec.tsx
#	packages/client/ui-trajectory/tests/views.client.spec.tsx
#	packages/client/ui-user-questions/tests/plan-review-panel.client.spec.tsx
#	packages/client/ui-user-questions/tests/user-questions-composer.client.spec.tsx
#	packages/client/ui-workflow-run/tests/workflow-run.client.spec.tsx
#	packages/client/ui-workspace/tests/apply.client.spec.ts
#	packages/client/ui-workspace/tests/tree.client.spec.ts
#	packages/client/ui-workspace/tests/workspace-browser.client.spec.tsx
#	packages/client/ui-workspace/tests/workspace-picker.client.spec.tsx
#	packages/client/ui-workspace/tests/workspaces-service.client.spec.ts
#	packages/extensions/cordis-client-runner/src/client/slot-catalog.ts
#	packages/jobs/tool-jobs/src/index.ts
#	packages/shell/tool-bash/README.i18n.yaml
#	packages/test-support/client-runtime/src/sessions.ts
2026-09-21 11:34:20 +08:00
lsdsjy b6594005f7 fix(ui-settings-account): report clipboard failures without failing sign in 2026-09-21 11:32:33 +08:00
sjw1231 c84c908656 fix(ui-deliverables): prevent split diff edge rebound 2026-09-21 11:29:02 +08:00
imccyu 3834da8602 Merge pull request #4754 from deepseek-harness/desktop-browser
feat(desktop): retain sidebar webviews and restore saved pages
2026-09-21 11:24:48 +08:00
Yichen Jiang 103aee7396 Merge branch 'worktree/input-plugin-extension-hooks' into worktree/experimental-voice-input
# Conflicts:
#	apps/desktop/README.i18n.yaml
#	apps/desktop/README.md
#	apps/desktop/README.zh.md
#	packages/client/ui-plugin-manager/src/client/presentation.ts
#	packages/client/ui-plugin-manager/tests/components.client.spec.tsx
#	packages/extensions/cordis-client-runner/src/client/slot-catalog.ts
2026-09-21 11:15:10 +08:00
creatixchu 62891ca4fc Merge origin/master into worktree/issue-3881-folder-drop 2026-09-21 11:11:36 +08:00
Yichen Jiang 0aa6f94749 feat(web): expose input plugin extension hooks 2026-09-21 11:11:21 +08:00
imccyu 640e26806b docs(sidebar): describe the final retained browser architecture 2026-09-21 11:10:31 +08:00
sjw1231 2c5d49645b docs(ui-deliverables): plan review tab fixes for #4670 2026-09-21 11:09:13 +08:00
lsdsjy 31cce49fff fix(desktop): unify welcome material and action placement 2026-09-21 11:06:59 +08:00
Yichen Jiang 511476782b test(web): complete input action fixture after master merge 2026-09-21 11:02:05 +08:00
Yichen Jiang b3ff0f5dc7 Merge remote-tracking branch 'origin/master' into worktree/experimental-voice-input
# Conflicts:
#	packages/client/ui-plugin-manager/tests/components.client.spec.tsx
#	packages/client/ui-primitives/README.i18n.yaml
#	packages/client/ui-primitives/README.md
#	packages/client/ui-primitives/README.zh.md
#	packages/client/ui-primitives/tests/icons.client.spec.tsx
#	packages/client/ui-primitives/tests/state-dot.client.spec.tsx
2026-09-21 10:56:23 +08:00
Yifffan 2ced4d130b Merge branch 'master' into fix/desktop-minimize-vibrancy 2026-09-21 10:54:01 +08:00
creatixchu 82692090c8 Merge remote-tracking branch 'origin/master' into feat/4562-file-open-apps 2026-09-21 09:56:00 +08:00
imccyu 8e441f7da2 test(browser): complete sidebar retention and navigation coverage 2026-09-21 04:12:54 +08:00
imccyu 599f556deb test(sidebar): follow retained DOM layout in browser checks 2026-09-21 04:12:54 +08:00
imccyu 7be9188d20 fix(browser): complete preload fixtures and scrollbar bindings 2026-09-21 04:12:54 +08:00
imccyu 346b27b037 fix(webworker-packer): skip declaration-only export roots 2026-09-21 03:36:52 +08:00
imccyu d8438ecf06 refactor(browser): isolate Electron code and defer native coverage 2026-09-21 03:25:30 +08:00
imccyu 94bc5b25b8 test(desktop): cover webview and sidebar retention lifetimes 2026-09-21 03:13:15 +08:00
imccyu 0e652514ea fix(browser): declare workspace client injection 2026-09-21 02:33:35 +08:00
imccyu 60ef7b1261 fix(ci): refresh sidebar catalog and complete API docs 2026-09-21 02:29:00 +08:00
imccyu e9a0d5ac77 fix(desktop): address sidebar retention and webview review findings 2026-09-21 02:17:37 +08:00
imccyu 5614184902 chore(browser): prune retired unknown-cast baseline 2026-09-21 01:50:16 +08:00
imccyu 1489526281 fix(desktop): import updater declarations through package types 2026-09-21 01:47:28 +08:00
imccyu 37df1ea375 fix(browser): separate desktop types from client compilation 2026-09-21 01:47:20 +08:00
imccyu c402892c1a feat(browser): add manual page recovery and cwd storage grouping 2026-09-21 00:58:23 +08:00
imccyu ab4bd4c630 feat(desktop): enable lease-scoped sidebar webview guests 2026-09-21 00:58:23 +08:00
imccyu cbd866fa72 refactor(browser): separate navigation and presentation providers 2026-09-21 00:58:23 +08:00
imccyu 96b2aca346 feat(sidebar): retain session views across tab presentation changes 2026-09-21 00:58:23 +08:00
imccyu bf712e1404 feat(dockkit): add stable retained tab layout 2026-09-21 00:58:22 +08:00
imccyu 37535cf44a Merge pull request #4753 from deepseek-harness/fix/pr-4749-review
fix(chat): address presentation review findings
2026-09-21 00:46:02 +08:00
imccyu 4533be9531 fix(chat): address presentation review findings 2026-09-21 00:32:43 +08:00
imccyu b173fe1c19 Merge pull request #4749 from deepseek-harness/feat/chat-presentation-channel
feat(ui-chat): restore independent work-detail presentation from #4565
2026-09-21 00:10:18 +08:00
Turtle 3f7016a422 feat(config): add volatile schemas and watcher-driven updates (#4579)
* feat(cordis): add volatile config references without remounting

* refactor(cordis): use internal prefix for volatile updates

* fix(schemastery): preserve metadata-free serialized schemas

* refactor(config): move volatile updates into an opt-in Loader plugin

* refactor(config): reuse Loader context patch for volatile updates

* refactor(config): let the volatile watcher commit equal candidates

* refactor(config): separate comparison from volatile reconciliation

* refactor(loader): extract pure entry option diff

* refactor(loader): compare volatile config through schema metadata

* refactor(loader): make volatile comparison policy explicit

* refactor: name config reload and volatile HMR events

* refactor(loader): compare volatile config in one schema walk; declare hmr/volatile-update in volatile-hmr

Replace the mask/project pair in vendor/loader/src/config/diff.ts with one recursive schema-guided comparison. Absent objects now compare as their declared schema default at every object node, not only under volatile ancestors; both inputs resolve to the same validated config, so the one changed assertion (undefined vs {} under a non-volatile object schema) becomes unchanged. The isJsExpr special case is dropped: expression keys fall through to raw comparison.

Move the hmr/volatile-update Events declaration from vendored Cordis core to its producer, packages/boot/volatile-hmr, matching how dsh-hmr declares hmr/change and hmr/reload. Vendored cordis events.ts returns to upstream content; the inherited Cordis API catalog and the event matrix are regenerated, and the tutorial example imports the package types.

* fix(cosmokit): compare sparse array slots in deepEqual; extend volatile diff coverage

Array.prototype.every skipped holes, so deepEqual(Array(1), ['new']) was true in one direction. Compare every index with holes read as undefined.

config/diff.ts treats expression objects as opaque values even when a schema field shares the marker name, and looks up field schemas with Object.hasOwn so unknown keys named after Object prototype members compare raw. Tests cover absent-object defaults, sparse arrays in both directions, prototype-named keys, metadata-free serialized schema nodes, and a runtime remount check in volatile-hmr. READMEs and the architecture note describe the object-default rule.

* test(schemastery): build serialized schema fixtures without unknown casts

verify-no-unknown-casts rejects the two as-unknown assertions in scripts/volatile-config.spec.ts. Parse the serialized nodes from JSON text instead, matching scripts/loader-config-diff.spec.ts.

* docs(volatile-hmr): drop the scope-scan tag from hmr/volatile-update

verify-scoped-events rejects @dshScopeScan on an event that carries no scoped keys. Catalogs and the event matrix are regenerated.

* docs: regenerate module graph for the volatile-hmr dependency edge

verify-module-graph reports the merged docs stale: volatile-hmr now lists its app-boot dependency.

* test(volatile-hmr): watch the real YAML through an exact config watch

The Windows coverage lane lost the whole spec: its vitest worker exited without a report once this test started a chokidar directory watch (root: ['.']), the only real directory watch in the test suite. Register the include file through hmr.watchConfig instead, the pattern the HMR package's own real-file tests run on Windows, and emit loader/config-reload from the refresh callback as the root-watch path does. packages/boot/hmr/tests/coordination.spec.ts already covers that root-watch emission with a mocked watcher; volatile-hmr and hmr sources stay at 100% coverage.

* test(volatile-hmr): pass the Include path as a file URL

On Windows the plain absolute path made the include subtree fail to load, so the profile-patch test found no consumer entry. Other Include fixtures in this spec already pass file URLs.

* refactor(loader): commit volatile config in Entry.update and remove volatile-hmr

loader/config-reload was emitted from two places (app-boot profile reconciliation and the HMR root watch) and by hand in tests, because a separate plugin needed a "configuration applied" signal to run its own pass. Every update path already funnels through Entry.update, which is where the Loader decides to skip a remount for a volatile-only change. Entry._commitVolatile now parses the candidate through the fiber's internal/config hook and schema, commits the new values into the running references when the ordinary effective values still match, and emits loader/volatile-update to the owning fiber. A changed ordinary effective value falls back to the ordinary remount instead of leaving the instance stale; an invalid candidate is logged and keeps the running references, with the raw config retained for the next activation. Forced group updates take the same path.

Remove packages/boot/volatile-hmr, its event, the app-boot loader/config-reload declaration and emit, and the HMR emission. Loader runtime and real-file tests move to scripts/loader-volatile-update.spec.ts. Docs, catalogs, the event matrix, module graph and the architecture note follow.

* test: share the volatile schema fixture between the schema and Loader specs

The duplication gate flagged the identical Config fixture in scripts/volatile-config.spec.ts and scripts/loader-volatile-update.spec.ts.

* refactor(loader): reduce config/diff.ts to equalExceptVolatile

Entry.update now computes the strict raw option changes itself and only asks diff.ts whether two raw configs differ at most in volatile fields. The ignoreVolatile flag, the options object and the "config is the sole change" rule leave diff.ts; they were the Loader's decision and now sit next to the commit they gate. The raw-config deepEqual in the volatile branch is gone because the strict change list already answers it.

* refactor(loader): type the volatile comparison against Schemastery's Schema

config/diff.ts narrows the plugin's Standard Schema to Schemastery's own Schema type instead of a hand-written structural interface, which makes vendor/loader a type-only dependent of @deepseek-ai/schemastery. The rescope codemod treats the vendor identifier comparison like schemastery's own source and renames the import through an exact edit.

* fix(loader): address review findings on the volatile commit path

Entry.update only replaces the fiber's pending raw config for a volatile-only change, so a noSave direct update survives a no-op entry update. _commitVolatile logs at debug level when ordinary effective values changed and the ordinary update applies, dispatches loader/volatile-update with a Context receiver like Cordis' own filtered emits, and isolates a throwing listener. Schemastery reports unsupported volatile values as ValidationError with their path and validates a lazy inner once when it is built. The inherited-event catalog gains internal/config and corrected source lines; the Loader spec imports dsh-hmr by package name and covers the new behaviors. Docs record that class-instance ordinary fields always take the remount path and that .default() accepts the raw input type.
2026-09-21 00:04:06 +08:00
gengruilin cbd6562506 docs(web): clarify browser dependency installation 2026-09-20 23:45:19 +08:00
gengruilin b79b64f788 Merge origin/master into fix/webkit-model-picker 2026-09-20 23:42:15 +08:00
imccyu c3c3d95608 test(web): align preview and fence checks with chat folding 2026-09-20 23:36:20 +08:00
Yichen Jiang b73a71e89c Merge pull request #4751 from deepseek-harness/worktree/preset-error-session-creation-1b1161
fix(web): report a refused new session through the Workspace notice
2026-09-20 23:30:38 +08:00
Yichen Jiang c7e6e36dd1 fix(web): keep a superseded creation notice silent and add its e2e
Review follow-ups on the refused-creation notice:

- `openWorkspace` raises `createFailed` only while its navigation is
  current, so a refusal that lands after a later navigation or owner
  disposal stays silent — the gate `initializeDefaultWorkspace` already
  uses and what the README states; two service cases pin it.
- `RowActionToast` switches on the closed notice union and ends in
  `assertNever`, so an unhandled kind fails to compile instead of
  rendering another notice's copy.
- `apps/web/tests/new-session-refused.e2e.ts` drives the composed Web
  server with a user preset whose row cannot resolve and compares the
  notice's ARIA golden, beside the default-Workspace failure scenario.
- `@throws` on `openWorkspace` covers every failure (catalog
  regenerated); `RowToast.createFailed` records why the Host code stays
  in the copy; the README states that other failures show their own
  message.
2026-09-20 23:22:13 +08:00
imccyu f1c035b1e9 test(chat): align presentation coverage and snapshots 2026-09-20 23:20:07 +08:00
imccyu 89ee08b781 docs: record completed chat migration and deferred turn-step work 2026-09-20 22:45:29 +08:00
imccyu bcd14d776c perf(ui-chat): memoize tool and command rows 2026-09-20 22:45:29 +08:00
imccyu b6f99fad55 feat(ui-chat): filter system prompts and permission commands 2026-09-20 22:45:29 +08:00
imccyu 007241d2a8 feat(ui-chat): add text shimmer to running rows 2026-09-20 22:45:29 +08:00
imccyu e24805a536 feat(ui-chat): refine reasoning previews and disclosure cues 2026-09-20 22:45:28 +08:00
imccyu 508329fe57 feat(ui-chat): add presentation policy channel 2026-09-20 22:45:28 +08:00
dcc c2be3d9a0b test(web): pin the desktop update chrome's shared palette
Numeric download progress renders without an ellipsis, and a failure keeps the update chip's palette instead of a separate error color. Pin the progress label and the shared badge background, and let the retry label carry the failure distinction.
2026-09-20 22:41:53 +08:00
Yichen Jiang 93ad804bf1 fix(web): report a refused new session through the Workspace notice
An explicit New Session (sidebar and header buttons, the workspace row
button, and the hero workspace pick) whose `session.create` the Host
refuses — for example a default preset whose composition names a
plugin that no longer resolves (`agent-preset/invalid`) — was only
logged with `console.warn`, so the click looked like it did nothing.

`openWorkspace` now shows the failure through the shared Workspace
notice as a `createFailed` toast quoting the Host's stable code and
message on the long hold, then rethrows as before. Startup restoration
does not go through `openWorkspace` and stays console-only.
2026-09-20 22:40:00 +08:00
dcc 5015426866 fix(ui): unify desktop update badge colors 2026-09-20 22:33:00 +08:00
dcc 422ded6f7a fix(ui): align desktop update tag styling 2026-09-20 22:33:00 +08:00
winewill 6446944fa6 Merge pull request #4669 from deepseek-harness/build/test-release-path-id
build(desktop): isolate test downloads by release ID
2026-09-20 22:06:58 +08:00
winewill 338eea071e Merge remote-tracking branch 'origin/master' into build/test-release-path-id 2026-09-20 21:59:07 +08:00
07akioni 287f879d67 Merge pull request #4738 from deepseek-harness/fix/4728-macos-localizations
fix(desktop): 修复 macOS 中文系统首次启动默认英文
2026-09-20 21:50:03 +08:00
winewill b793dd2df6 Merge remote-tracking branch 'origin/master' into build/test-release-path-id
# Conflicts:
#	apps/desktop/scripts/desktop-package-environment.mjs
#	apps/desktop/tests/package-target-stages.spec.ts
2026-09-20 21:46:58 +08:00
creatixchu db10002cdd test(web): include file items in image drop fixture 2026-09-20 21:34:31 +08:00
creatixchu 5953ab2913 test(composer): use explicit void paste handler 2026-09-20 21:24:49 +08:00
creatixchu 444ce0444b fix(composer): type paste regression and refresh slot catalog 2026-09-20 21:14:44 +08:00
creatixchu 52a4a5bdb3 fix(composer): preserve batches and quoted directory references 2026-09-20 21:12:06 +08:00
07akioni 27fa7ed9ff Merge pull request #4681 from deepseek-harness/xtr/default-workspace-first-send
feat(workspace): prepare a default workspace on startup
2026-09-20 21:04:06 +08:00
Christina Lee ea05e57b60 Merge branch 'master' into fix/4728-macos-localizations 2026-09-20 20:56:39 +08:00
gengruilin 06ef26a80f fix(web): preserve focus when toggling the model picker 2026-09-20 20:56:34 +08:00
liyao 942e496ce7 fix(desktop): declare macOS bundle localizations 2026-09-20 20:45:29 +08:00
Turtle 31e6b3f150 fix(client): rotate every ongoing StateDot loader in phase (#4737)
CSS animations start when their element is inserted, so loaders mounted
at different moments rotated out of step in the sidebar session list.
The ongoing loader now pins its spin and dash animations to document
time zero on mount so every visible loader shares one phase.
2026-09-20 20:45:23 +08:00
_Kerman a4fdaebf52 Merge remote-tracking branch 'origin/master' into xtr/default-workspace-first-send 2026-09-20 20:44:25 +08:00
_Kerman 5ec3353af2 refactor(workspace): reuse toast for default initialization failures 2026-09-20 20:42:50 +08:00
Yif d72f85a0ad fix(desktop): paint an opaque base while minimized to cover the vibrancy reattach gap 2026-09-20 20:41:48 +08:00
creatixchu 1790a09f77 Merge remote-tracking branch 'origin/master' into feat/4562-file-open-apps 2026-09-20 20:33:24 +08:00
Turtle f2a22a3108 test(web): provide favicon environment in desktop boot fixture 2026-09-20 20:05:17 +08:00
Turtle 6b9c01996f fix(web): refresh favicon colors with the system scheme 2026-09-20 19:54:54 +08:00
imccyu 2411452433 Merge pull request #4707 from deepseek-harness/subagent-catalog
perf(session): avoid duplicate cold reads on conversation open
2026-09-20 19:27:13 +08:00
winewill 2c233c64f0 Merge pull request #4716 from deepseek-harness/feat/current-version-display
feat(client): 在通用设置展示当前版本号
2026-09-20 19:19:04 +08:00
mektpoy 31a83ebc4b refactor(client): let chrome rows own the macOS window drag
The macOS window's draggable area was a hand-written band: a 52px strip, deepened
to 76px by a marker the Conversation header had to keep in step with its own
height. It drifted from the layout — blank runs inside a chrome row did not drag,
and a control a few pixels away dragged the window instead.

Chrome rows now mark their own element (`data-window-drag`) and the shell declares
the surface once (`html[data-platform='darwin'] [data-window-drag]`), so a row's own
box is its draggable geometry and no fixed band has to match any row's height. The
frame band, its 52/76 figures, the marker, and the per-sheet drag rules are gone;
interactive controls and overlays portal beside `#root` where one rule subtracts
them.

Recollection becomes one shell watcher (`window-drag/recall.ts`): Electron rebuilds
the window's drag rects only when a computed app-region value changes
(electron#32341), so the watcher measures every marked row each frame while the
surface moves, sets `data-window-drag-recall` for the frames whose geometry changed,
and clears it on the frame that finds the geometry settled. The right panel's
hand-written pulse is deleted with it.

Coverage is a contract with executable parts. `window-drag/regions.ts` publishes the
composition rule and the interactive selector that both the sheet and its spec
compare against; the ui-theme gate asserts the package tree declares drag in exactly
two places and pairs every row's mark with its sheet, selector, and authored height;
and the browser lane boots the shipped composition in Chromium with the darwin
marker to assert per-row geometry, a content body under a marked head row, a
covering overlay, and the watcher's pulse. The plugin manager's detail views mark
the head row they share rather than the pane they render in, so their text and form
labels stay content.

Both real machines agree: the macOS matrix ran on a real `hiddenInset` window with
HID-level pointer input and window-frame readback, and the Windows matrix on a
Windows 11 ARM64 VM — chrome rows drag, content and the covering overlay do not,
and the controls keep their clicks.

Refs #4619
2026-09-20 19:01:15 +08:00
imccyu 42f9a76b77 test(client): align remaining navigation refresh expectations 2026-09-20 18:58:22 +08:00
mektpoy 65ba30ab4f refactor(client): name the standard focus-ring width
Every ring that used 2px now reads --dsw-focus-ring-width. The dense tables and
toolbars keep their 1px ring on purpose: at 2px they visibly outweigh the rows
they sit between, so the standard value and the dense exception stay distinct
rather than converging on a number nobody measured.
2026-09-20 18:47:45 +08:00
Yudong Han a25780c63b Merge pull request #4725 from deepseek-harness/fix/sidebar-excel-default-app 2026-09-20 18:45:17 +08:00
mektpoy 5a7b2e6f33 fix(client): ring the workspace header controls inside their clipping boxes
The action cluster animates its width with overflow hidden, and the search pill
clips to its rounded shape, so an outer ring on the add, search and clear
controls was cut to a sliver. This package declared no focus style at all — every
control fell back to the browser default inside those boxes.

Ring the three controls inside the element, the direction issue #4655 allows.
2026-09-20 18:44:58 +08:00
imccyu 045e2f9360 test(client): omit absent optional Session fixture fields 2026-09-20 18:41:30 +08:00
imccyu ad2dad1186 test(client): cover auxiliary reads with retained Session fixtures 2026-09-20 18:41:30 +08:00
imccyu d25490d8b4 test(subagent): replace legacy unknown cast with typed fixture 2026-09-20 18:41:30 +08:00
imccyu 280048d868 fix(client): align navigation callbacks and projection tests 2026-09-20 18:41:30 +08:00
imccyu d088572e11 fix(session): declare persistence identity for Typert analysis 2026-09-20 18:41:30 +08:00
imccyu be0d63661c perf(client): remove redundant projection reads from navigation 2026-09-20 18:41:29 +08:00
imccyu dfff5056f4 perf(client): defer auxiliary reads until history is ready 2026-09-20 18:41:29 +08:00
imccyu 6fef0f0af9 fix(session-query): stabilize persistence cache identity 2026-09-20 18:41:29 +08:00
Turtle 2099andTurtle e8f3d02da8 fix(web): batch session expansion and keep running sessions visible (#4715)
* fix(web): expand workspace sessions in bounded batches

* fix(web): keep running sessions outside overflow quota

---------

Co-authored-by: Turtle <[email protected]>
2026-09-20 10:38:56 +00:00
imccyu 068cf03441 Merge pull request #4648 from deepseek-harness/worktree/remote-duplex-stream
feat(gateway): let every Remote stream carry a client uplink
2026-09-20 18:32:58 +08:00
mektpoy ae59505baf Merge remote-tracking branch 'origin/master' into tmp4500-sync 2026-09-20 18:24:54 +08:00
Turtle 654caa4bbd feat(bundle): accept an ordered patch file list in dsh.bundle.patch (#4722)
* feat(bundle): accept an ordered patch file list in dsh.bundle.patch

`dsh.bundle.patch` now accepts `string | string[]`. A list names patch
files applied in order as one bundle layer; each file's relative plugin
paths still resolve beside that file. `bundlePatchPaths` in dsh-app-boot
is the one resolver from a declaration to absolute paths, and every
reader uses it: profile loading, plugin-manager reconcile and bundle
rows, the client-runtime roster, and the workspace, cordis-config, and
product-isolation gates. `ProfileLayer.patchPath` becomes `patchPaths`.

* fix(bundle): keep declared patch files package-relative in the workspace gate

path.join produced backslash entries on Windows, so the expected files
list did not match package.json files. bundlePatchFiles returns the
validated declaration as written; bundlePatchPaths joins it.
2026-09-20 18:20:24 +08:00
Ziya d495b2e5f2 Merge pull request #4718 from deepseek-harness/copy/preset-language-20260920
feat(web): clarify agent presets and add mode guides
2026-09-20 18:19:26 +08:00
winewill 21e315a7dd docs(client): record the shell's Current version row in ui-settings-general
The shell registers two General rows after #4716, but README.md and
README.zh.md still described only Developer tools in three places each.
Align both sides and re-record the bilingual pairing hashes.

Also close the review nits: assert the settings.general.item rows dispose
on unload, give the localized-label cases distinct titles (%s printed the
dictionary object, so both read "[object Object]"), complete the
CurrentVersionRow @param, and note why current-version orders last.
2026-09-20 18:18:13 +08:00
ZiyaZhang d620c1e4b7 fix(web): soften segmented tab focus styling 2026-09-20 03:08:34 -07:00
ZiyaZhang 5aa0e3f806 test(web): align developer tools check with preset copy 2026-09-20 03:00:57 -07:00
creatixchu 112c9e5749 feat(web): cite dropped folders and files as @ references on Desktop
The Desktop preload reports a picked file's real path through
__DSH_HOST_PATHS__. Where that bridge exists, the composer inserts a dropped,
picked, or pasted folder or non-image file as the same @path reference chip
the user could have typed, so nothing uploads and the model reads the target
with its file tools; images keep uploading. The drop handler names dropped
directories through the entry API, and a browser without the bridge refuses
a dropped folder with product copy instead of failing it as an upload.
2026-09-20 18:00:26 +08:00
imccyu ffea3c8818 fix(gateway): close the remaining uplink lifecycle gaps 2026-09-20 17:53:18 +08:00
imccyu 5a8d3b7498 docs(agents): state the uplink note in English on both sides and cross-link its neighbours 2026-09-20 17:53:18 +08:00
imccyu 6872651527 docs: regenerate the module graph 2026-09-20 17:53:18 +08:00
imccyu 520c225b87 test(gateway): cover the uplink edge paths 2026-09-20 17:53:17 +08:00
imccyu 755f022ef0 docs: regenerate catalogs and document the mock uplink handle 2026-09-20 17:53:17 +08:00
imccyu 5fbae69d18 docs(agents): pair the Remote uplink stream note in English 2026-09-20 17:53:17 +08:00
imccyu d07182d3d8 docs(agents): record the Remote uplink stream as implemented 2026-09-20 17:53:17 +08:00
imccyu 355df025d4 fix(gateway): harden the Remote uplink lifecycle 2026-09-20 17:53:17 +08:00
imccyu 8ce7c27671 refactor(connection): admit every request as the single operator Peer 2026-09-20 17:53:17 +08:00
imccyu e427600e32 test: pin the scope export roster and map dsh-brand for the proxy type program 2026-09-20 17:53:17 +08:00
imccyu 35602063d7 refactor(typert): name the client stream handle RemoteStreamHandle everywhere 2026-09-20 17:53:17 +08:00
imccyu 77f1a493aa refactor(typert): keep the Remote marker mode as the 'stream' literal 2026-09-20 17:53:17 +08:00
imccyu ebdc1609c6 docs(agents): mark the duplex note's pseudo-code fences as text 2026-09-20 17:53:17 +08:00
imccyu 089004c418 test(gateway): cover the Remote uplink and document it
Tests bring the changed sources to full per-file coverage, the READMEs and
docs describe the uplink, the invocation context, and the Peer registry in
both languages, and the generated catalogs are refreshed.
2026-09-20 17:53:17 +08:00
imccyu 021bd03b70 feat(gateway): let every Remote stream carry a client uplink
Every Typert Remote stream accepts client-to-Host items on the same
logical stream. A method declares the uplink item type in its return
type, RemoteStream<Out, In>, and reads the items through
this.ctx.invocation.uplink(); the invocation also carries the calling
Peer. Client generated methods return a handle that iterates the
downlink and exposes send/end/dispose for the uplink.
2026-09-20 17:53:16 +08:00
fz a1e0ce557d Merge pull request #4460 from deepseek-harness/feat/workspace-dependencies-package
feat(sdk): bundle shared Office Python runtime and configurable skills
2026-09-20 17:50:17 +08:00
winewill 5ff352b0be test(web): include current version without built-in browser 2026-09-20 17:50:05 +08:00
Yichen Jiang a165e82bfc feat(ui-plan): lead the plan chip with the plan glyph and a hover close (#4710)
The composer's plan-mode chip rendered its label followed by a 12px
one-pixel cross, out of step with the sibling access-mode trigger's
glyph-then-label layout. The chip now leads with the 14px plan glyph
(the /plan command's own icon) and swaps it for a new circled close —
IconCloseCircleFill, a filled disc with the cross knocked out — while
the enabled chip is hovered or keyboard-focused, so the pending click
reads as turning plan mode off.

The pill's corners move from a 999px circular capsule to the compact
Button geometry (14px on the 28px row) under the theme's superellipse
curvature, matching every neighbouring control; the lifecycle-chrome
probe now pins that radius and the shared corner-shape.
2026-09-20 17:49:06 +08:00
_Kerman 5294b15b31 docs(workspace): separate constructor parameter tags 2026-09-20 17:48:58 +08:00
_Kerman 78d6f7bc1f test(client): mock default workspace initialization during boot 2026-09-20 17:48:46 +08:00
winewill 9d7e5e30ac Merge remote-tracking branch 'origin/master' into feat/current-version-display 2026-09-20 17:46:50 +08:00
ZiyaZhang 05a229ccc9 feat(web): clarify agent presets and add mode guides 2026-09-20 02:45:48 -07:00
Yudong c1f37fef9d fix(sidebar): open spreadsheets in default app 2026-09-20 17:39:28 +08:00
gengruilin 6613660223 fix(web): keep model picker focus during mouse selection 2026-09-20 17:37:44 +08:00
Yichen Jiang ab9689b2ca fix(web): bind the right Sidebar before same-commit mount effects (#4693)
* fix(web): bind the right Sidebar before same-commit mount effects

A plan review arriving while a global panel was active crashed its opener when the user returned: the frame mounts the Conversation column ahead of the right Sidebar seat, so PlanReviewOpen's mount effect called ctx.sidebarRight.openResource before the seat's passive bindService effect had published the binding. The slot runtime retired the crashed entry for the rest of the page, removing the View full plan link and every later automatic open.

Publish the seat binding from a layout effect, which runs before any passive effect of the same commit regardless of tree order. The seat spec mounts a Conversation-column opener ahead of the seat and returns from a global panel; the plan-review Web scenario delivers a review while the Plugins panel is open and expects the preview and the link after the return. Both fail before the fix.

* fix(web): open the plan review once the Sidebar seat is mounted

Replace the layout-effect binding with an observable: ctx.sidebarRight.mounted publishes the session whose seat is on screen, undefined while a global panel replaces the Conversation. The seat keeps binding from its passive effect. PlanReviewOpen reads the source through a bound hook and opens once a seat is defined, so a review mounting ahead of the seat in the same commit no longer assumes a bound seat and never crashes its entry.

The seat spec's opener stand-in now reads `mounted` the way a slot component does; the service spec pins that only real transitions publish, and the PlanReviewOpen spec covers a review that mounts before any seat and opens once the seat binds.

* test(web): align the plan-review console tripwires and the seat term

The off-screen review case now asserts the reconnect warnings like its siblings and filters crash logs by error level as the other e2e files do. The zh README keeps 席位 for the seat throughout.

* test(plan): keep the review props cast at its baseline fingerprint

verify-no-unknown-casts counts a modified assertion as new. The two PlanReviewOpen specs now share the unchanged baseline cast through one helper and supply the seat hook as a typed value beside it.
2026-09-20 09:35:00 +00:00
fz fa1065b6b2 Merge remote-tracking branch 'origin/master' into feat/workspace-dependencies-package 2026-09-20 17:33:02 +08:00
_Kerman b21fc2c8d1 Merge origin/master into xtr/default-workspace-first-send 2026-09-20 17:26:38 +08:00
mektpoy 9a74ba5d08 fix(client): give tooltips and focus rings the modality rule each needs
A tooltip asks what the last input was: after any key the user is working from
the keyboard, so a programmatic focus may raise a bubble. A focus ring asks
something narrower — Chromium reveals an already-focused control as soon as any
key arrives, including a modifier or Escape that never navigated anywhere, which
is the ring users report as unexplained.

Record both answers and publish the ring's narrower one, so tooltips keep their
existing behaviour and rings stay silent for a pointer's focus.
2026-09-20 17:26:14 +08:00
winewill 1628c1d030 feat(client): display current version in general settings 2026-09-20 17:23:08 +08:00
_Kerman 2cd03c9758 refactor(workspace): omit unchanged registry state fields 2026-09-20 17:20:54 +08:00
_Kerman 3a7f8f9657 test(web): restore ordinary workspace picker readiness 2026-09-20 17:20:44 +08:00
_Kerman 4d2e420ef8 refactor(workspace): initialize the default workspace on startup 2026-09-20 17:19:54 +08:00
creatixchu 7d002f7eff test: compare Windows file identity and refresh delivery controls 2026-09-20 17:17:40 +08:00
creatixchu e0187ecdf8 Merge remote-tracking branch 'origin/master' into feat/4562-file-open-apps 2026-09-20 17:16:21 +08:00
Yichen Jiang 8d6245bcc8 Merge pull request #4701 from deepseek-harness/fix/settings-navigation-scroll
fix(web): 设置导航支持溢出滚动
2026-09-20 17:14:32 +08:00
winewill 6848f1e118 Merge pull request #4567 from deepseek-harness/fix/windows-mandatory-update-overlay
fix(desktop): Windows 强更使用主窗口内蒙层并修复退出清理
2026-09-20 17:12:17 +08:00
Tianyi Cui 3f33c06f40 Merge pull request #4629 from deepseek-harness/worktree/dynamic-conversation/messages-only
Make the official DeepSeek adapter Messages-only
2026-09-20 17:10:58 +08:00
mektpoy db92970146 fix(client): keep focus rings inside the containers that clip them
The breadcrumb trail and the Miller column scroll, and the column's left edge
carries no padding, so an outer ring on their buttons was clipped to a sliver.
The TurnNavigator marker sits at the scroller's right edge, which clipped three
of its four sides. Ring those inside the element instead — the direction issue
#4655 allows — and change no layout value.
2026-09-20 17:08:43 +08:00
mektpoy 9e7350bb8c fix(client): keep a pointer's focus silent until focus navigation
Clicking a control leaves it focused with :focus-visible false, so nothing is
drawn. Chromium then reveals the ring the moment any key arrives — a modifier,
Escape, a typed character — which is the unexplained focus ring users report:
they never navigated there, yet a ring appears under the pointer's last target.

Record the input modality on the document element, publish the keyboard modality
only for focus navigation (Tab, arrow keys), and let the global focus sheet keep
a pointer's focus transparent. Tooltip's pointer modality moves into the same
module so tooltips and rings follow one rule.
2026-09-20 17:05:51 +08:00
winewill 032394fc48 Merge remote-tracking branch 'origin/master' into fix/windows-mandatory-update-overlay 2026-09-20 17:01:23 +08:00
Turtle 8f0dd55c2c feat(plugins): render icons from package manifests (#4697)
* feat(plugins): render icons from package manifests

* fix(plugins): include declared icons in canonical package payloads
2026-09-20 17:00:17 +08:00
Turtle 2099andTurtle 3eab1714bc feat(web): add chat link opening preference (#4671)
* feat(web): add chat link opening preference

* docs(web): clarify preference-controlled link routing

* fix(web): hide link preference without a browser

* fix(web): make the built-in browser opt-in

* test(web): honor profile-aware browser availability

---------

Co-authored-by: Turtle <[email protected]>
2026-09-20 17:00:03 +08:00
creatixchu 086b64103f test: verify transient feedback and single-action file controls 2026-09-20 16:51:58 +08:00
creatixchu c7a4fae8e5 fix: complete shared menu types and remove obsolete button styles 2026-09-20 16:48:25 +08:00
creatixchu a4148d687f fix: refine file action menus feedback and shared queries 2026-09-20 16:46:58 +08:00
Dudu-0223 05b056f18c Merge pull request #4635 from deepseek-harness/fix/lazy-subagent-migration
fix(session): preserve unreadable children in migrated subagent catalogs
2026-09-20 16:45:25 +08:00
Yichen Jiang 393f72e32e Merge pull request #4690 from deepseek-harness/worktree/web-desktop-startup-commands-a97723
feat(infra): unify Web and Desktop launch commands
2026-09-20 16:35:26 +08:00
gengruilin 47ee608079 fix(web): allow overflowing settings navigation to scroll 2026-09-20 16:34:49 +08:00
07akioni 76427b4c5f Merge remote-tracking branch 'origin/master' into codex/pr-4553 2026-09-20 16:30:59 +08:00
fz 6b1c9c169d Merge remote-tracking branch 'origin/master' into feat/workspace-dependencies-package 2026-09-20 16:30:31 +08:00
lsdsjy 82ae763772 fix(deepseek-account): rename login source parameter 2026-09-20 16:28:21 +08:00
Xu Hanxiang dff5506934 Merge pull request #4499 from deepseek-harness/fix/windows-plugin-list-type-size
fix(client): raise the package identity contrast in the plugin views
2026-09-20 16:27:26 +08:00
Yichen Jiang 7d56ca5cee Merge remote-tracking branch 'origin/master' into worktree/web-desktop-startup-commands-a97723 2026-09-20 16:27:07 +08:00
Yichen Jiang 44cf9b703d docs(readme): point developers at dev:web and the Make targets 2026-09-20 16:25:03 +08:00
mektpoy 230d975a04 docs(client): explain the identity tiers and the detailName scope
The shared rule now states why the collapsed identity and the expanded value keep two label tiers, and the detailName comment names the row identity it also renders.
2026-09-20 16:18:56 +08:00
mektpoy 40edba6a8d Merge remote-tracking branch 'origin/master' into fix/desktop-dev-runtime-target 2026-09-20 16:13:36 +08:00
Xu Hanxiang 5dc6767d7b Merge pull request #4491 from deepseek-harness/fix/windows-menu-tooltip-overlap
fix(desktop): place Windows caption tooltips below the titlebar
2026-09-20 16:02:54 +08:00
_Kerman 43372b28ce Merge origin/master into xtr/default-workspace-first-send 2026-09-20 16:00:37 +08:00
fz 686986fdea Merge remote-tracking branch 'origin/master' into feat/workspace-dependencies-package 2026-09-20 16:00:35 +08:00
winewill 1e20aecef5 Merge remote-tracking branch 'origin/master' into fix/windows-mandatory-update-overlay 2026-09-20 15:59:42 +08:00
mektpoy 08b310b5a8 fix(client): paint every keyboard focus ring with the brand colour
Focus rings named eight different colours across 54 client stylesheets, and a
control that declared no ring fell back to the browser default, whose colour
follows the operating-system accent — so the same build showed orange on one
machine and blue on another.

Every keyboard focus ring now uses --dsw-alias-brand-primary. A global ui-theme
focus.css sheet reaches the controls that declare no ring of their own, and 49
declarations name the same token. Only the colour changed: each declaration
keeps its width, style and offset.
2026-09-20 15:59:12 +08:00
_Kerman d4d03b7c41 docs(workspace): clarify default directory lookup and cancellation 2026-09-20 15:58:53 +08:00
_Kerman 8e313eaa30 test(workspace): cover first-use configuration and preset failures 2026-09-20 15:58:33 +08:00
_Kerman cfec29eb69 fix(web): show first-use preparation and update browser readiness 2026-09-20 15:58:10 +08:00
_Kerman 6fa56a0cf7 fix(conversation): preserve first drafts across Session retirement 2026-09-20 15:57:45 +08:00
mektpoy 91fcd9180a docs(client): name the caption bubble owner and record the badge gap
The occupying badge chooses its own side, and the update badge keeps a right-opening bubble that the Windows caption menu can cover; ui-settings-general records that as a known limitation.
2026-09-20 15:55:29 +08:00
winewill dc81ed348c Merge pull request #4684 from deepseek-harness/build/windows-cache-concurrency
build(desktop): parallelize Windows signature cache hits
2026-09-20 15:55:23 +08:00
Yichen Jiang 453e8c09ac Merge remote-tracking branch 'origin/master' into worktree/web-desktop-startup-commands-a97723 2026-09-20 15:51:01 +08:00
mektpoy 6f1de05d54 Merge remote-tracking branch 'origin/master' into fix/windows-directory-junction 2026-09-20 15:51:00 +08:00
Yichen Jiang 78dcbc8587 feat(infra): unify Web and Desktop launch commands
Web and Desktop now share one command pair: start:* launches the artifacts
of a prior complete build and dev:* builds first, then launches. start:web
is new and spells out the same source launch vector as `pnpm dsh web`;
dev:web runs `pnpm run build`, the three rebuild watchers, and `dsh web` in
one terminal, with --skip-build and --no-serve for the previous two-terminal
flow. The launcher gate pins both scripts to the dsh CLI, and a root
Makefile names the same commands as make web|dev-web|desktop|dev-desktop|build.

The dev-web stage supervisor waits for stages the terminal already
interrupted, escalates only survivors, forwards SIGTERM once, and reports a
stage that exits on its own. Signal listeners are persistent because the
tsdown watchers bundle signal-exit, which re-raises a signal when it finds
no other listener.
2026-09-20 15:50:41 +08:00
winewill f3e8021eaa Merge remote-tracking branch 'origin/master' into fix/windows-mandatory-update-overlay 2026-09-20 15:48:35 +08:00
fz 9e49d7dbcf Merge remote-tracking branch 'origin/master' into feat/workspace-dependencies-package 2026-09-20 15:46:05 +08:00
Dudu-0223 e848b6226f Merge remote-tracking branch 'origin/master' into codex/fix-migration 2026-09-20 15:45:12 +08:00
Dudu-0223 e44efedeb0 fix(session): isolate corrupt compressed headers during discovery 2026-09-20 15:44:52 +08:00
mektpoy 8b8f10a8c6 docs(ui-sidebar): scope the Windows caption bubble claim
The previous sentence claimed every caption icon bubble opens below the caption, but only the sidebar toggle and New Session derive side=bottom; an occupying sidebar.toggle.badge keeps the default side.
2026-09-20 15:39:48 +08:00
winewill 466aa2232b Merge remote-tracking branch 'origin/master' into build/windows-cache-concurrency 2026-09-20 15:37:42 +08:00
mektpoy 3515c48a37 fix(desktop): resolve the development runtime directory from the build target
The unpackaged shell derived the primary-runtime directory from process.arch, while preparePrimaryRuntime() resolves the target through resolveDesktopBuildTarget(), which fixes Windows to x64. On a Windows ARM64 host the shell looked under targets/win-arm64 while the payload was under targets/win-x64, and the missing office-skills/scripts/check_office.py became a fatal startup dialog.

The launcher now resolves that directory through the same resolver and passes it to the shell as DSH_DESKTOP_PRIMARY_RUNTIME_DIR.
2026-09-20 15:37:38 +08:00
winewill d4c5a1723f test(desktop): isolate update UI in directory-picker preload integration 2026-09-20 15:36:49 +08:00
winewill ecb00a6cd0 Merge remote-tracking branch 'origin/master' into build/windows-cache-concurrency 2026-09-20 15:36:17 +08:00
lsdsjy 1b83e0ff13 Merge pull request #4665 from deepseek-harness/fix/developer-tools-preferences
fix(web): preserve plugin tabs and enable developer tools by default
2026-09-20 15:34:51 +08:00
winewill c193e0dfee Merge pull request #4683 from deepseek-harness/fix/macos-menu-product-name
fix(desktop): localize macOS application menu names
2026-09-20 15:34:32 +08:00
winewill db7ee5f487 build(desktop): parallelize Windows signature cache hits 2026-09-20 15:32:37 +08:00
winewill bea5bde6cc docs(desktop): clarify localized native menu behavior 2026-09-20 15:27:06 +08:00
winewill 015e60ff40 test(desktop): satisfy strict lint in mandatory update regressions 2026-09-20 15:23:36 +08:00
lsdsjy 04debcbd65 feat(ui-settings-account): link to Platform account information 2026-09-20 15:23:26 +08:00
winewill 69ac149090 fix(desktop): isolate mandatory update actions and handle main-window lifecycle 2026-09-20 15:20:04 +08:00
fz 35fe8e0966 Merge pull request #4677 from deepseek-harness/fix/4664-atomic-native-addon-extraction
fix(pkg): make SEA native addon extraction atomic
2026-09-20 15:18:26 +08:00
Kexin Liu 883311e556 Merge pull request #4349 from deepseek-harness/refactor/client-session-presentation
fix(web): prevent session blank rollback after acceptance
2026-09-20 15:16:49 +08:00
Dudu-0223 21ec132c0e test(preview): expect versioned unknown child catalog entries 2026-09-20 15:15:43 +08:00
Huanqi Cao d0f9a5c410 Merge remote-tracking branch 'origin/master' into fix/windows-acl-delete-escape
# Conflicts:
#	docs/config-catalog.i18n.yaml
2026-09-20 15:12:34 +08:00
Dudu-0223 a978ad1994 fix(subagent): version unknown catalog payloads locally 2026-09-20 15:09:37 +08:00
winewill fd75c47ae9 fix(desktop): localize macOS application menu names 2026-09-20 15:08:57 +08:00
winewill 12f0608cad Merge master into fix/windows-mandatory-update-overlay 2026-09-20 15:07:10 +08:00
_Kerman b93f55f7ff Merge remote-tracking branch 'origin/master' into xtr/default-workspace-first-send 2026-09-20 15:03:03 +08:00
fz 3085139699 test(runtime): align fixtures with current type-safety gates 2026-09-20 15:02:02 +08:00
_Kerman e71df56b1a feat(workspace): create the default workspace on first send 2026-09-20 14:59:15 +08:00
liukx0205 5e13010b90 test(web): document suite-level browser setup and bound the reconnect polls 2026-09-20 14:54:27 +08:00
liukx0205 b882e7fc20 docs(session): record the client-local engagement memory limits 2026-09-20 14:54:27 +08:00
liukx0205 d8480db9f0 refactor(web): read engagement retention from one identity set
Address review: retention now has a single definition (retainedIds) shared by
the list-refresh sweep and the single-id prune, an already-engaged identity
skips the redundant row mutation, and the ledger documents why Host-asserted
running is recorded before any holder exists while the client-local acceptance
callback requires one.
2026-09-20 14:54:20 +08:00
fz f25957d442 Merge remote-tracking branch 'origin/master' into feat/workspace-dependencies-package 2026-09-20 14:50:54 +08:00
fz 065def9d41 docs: use compliant issue references in native extraction note 2026-09-20 14:50:48 +08:00
Dudu-0223 f984683956 fix(subagent): store unknown mode in the existing catalog event 2026-09-20 14:46:54 +08:00
Tianyi Cui 5a53758b03 test: preserve plugin-manager integration after stack rebase 2026-09-20 14:45:26 +08:00
lsdsjy 4f0ee6b105 fix(settings): defer developer features until host preference resolves 2026-09-20 14:45:24 +08:00
winewill 8e5073ee61 docs(desktop): clarify test release ID reuse and qualification 2026-09-20 14:44:36 +08:00
liukx0205 4bff618b17 docs(web): note the metadata hint applied over the engagement rule 2026-09-20 14:44:25 +08:00
liukx0205 ae58d210eb docs(web): scope the second projection store to a discarded store 2026-09-20 14:44:01 +08:00
liukx0205 7aa2d4b5cc docs(web): note the retained subagent catalog on session removal 2026-09-20 14:44:01 +08:00
liukx0205 e3f0d3fb6e fix(web): preserve session engagement across blank list refreshes 2026-09-20 14:43:46 +08:00
Tianyi Cui ddf11a4f0e fix: name Anthropic Messages in DeepSeek endpoint guidance 2026-09-20 14:37:58 +08:00
Tianyi Cui 0959c5be45 Align provider guides with Messages-only configuration 2026-09-20 14:37:58 +08:00
Tianyi Cui 9ab5c8e672 Fix Messages real-API package resolution and usage assertions 2026-09-20 14:37:58 +08:00
Tianyi Cui 385a540d7e Fix Messages-only consumer validation and document recovery 2026-09-20 14:37:58 +08:00
Tianyi Cui 2b29f31dc6 test(llm): assert native Messages file metadata 2026-09-20 14:37:19 +08:00
Tianyi Cui 99e22ebbeb refactor(llm): make the official DeepSeek adapter Messages-only 2026-09-20 14:37:19 +08:00
Dudu-0223 6f3140d7cf Merge origin/master into fix/lazy-subagent-migration 2026-09-20 14:37:01 +08:00
fz 5992977f2e fix(pkg): make SEA native addon extraction atomic
@yao-pkg/pkg's SEA bootstrap extracts native addons from the VFS into a
per-user cache ($PKG_NATIVE_CACHE_PATH/pkg/<sha256>/) with plain
writeFileSync, so concurrent first starts of the same executable truncate
files another process has already mapped: SIGBUS on Linux, "Library not
loaded" for sharp's libvips on macOS. Extend the existing pnpm patch so the
three write sites go through a same-directory temporary file and
renameSync; a cache path is then either absent or complete, every process
finishes its own copy pass before it loads, and identical content makes
concurrent renames harmless without a lock. Cache location, hash keying,
and per-file comparison are unchanged. The single-exe Agent Note records
the decision and the measured before/after runs.

Closes #4664
2026-09-20 14:36:27 +08:00
07akioni 90f0dc8f7d Check terminal descendant quiescence without requiring PID reaping 2026-09-20 14:31:11 +08:00
Dudu-0223 17a52a8fe3 fix(subagent): retain unreadable children in migrated catalogs 2026-09-20 14:30:02 +08:00
Turtle 8cf9c0eded fix(bash): allow blank justification without escalation (#4662)
* fix(bash): allow blank justification without escalation

* fix(bash): permit empty reasons when repeating the current mode
2026-09-20 14:28:57 +08:00
creatixchu c1ee42cd9c fix: portal file action tooltips outside clipped cards 2026-09-20 14:28:15 +08:00
winewill c05771d828 build(desktop): isolate test downloads by release ID 2026-09-20 14:17:51 +08:00
07akioni 2f4b354253 Fix Office packaging tests for static checks and Windows paths 2026-09-20 14:17:36 +08:00
lsdsjy c7c900a912 fix(settings): enable developer tools by default 2026-09-20 14:15:59 +08:00
lsdsjy a026ab1397 fix(onboarding): scope developer tools to trajectory tab visibility 2026-09-20 14:11:17 +08:00
creatixchu a4cd2f57a0 fix: keep file action feedback visible while hovering delivery cards 2026-09-20 14:07:32 +08:00
creatixchu a6daee84ca test: enable the shared opener in the delivery replay 2026-09-20 14:06:00 +08:00
creatixchu 6f1857ae1b test: refresh delivery snapshots for shared file controls 2026-09-20 14:04:54 +08:00
creatixchu 03fde971e2 build: allow browser-safe file association metadata validation 2026-09-20 14:02:18 +08:00
creatixchu 1f7e491526 docs: describe shared delivery and review file actions 2026-09-20 14:00:41 +08:00
07akioni 552bf8a869 Merge master into desktop Office ASAR fix 2026-09-20 14:00:04 +08:00
creatixchu 28089001a2 fix: complete file action slot contracts and branch coverage 2026-09-20 13:59:00 +08:00
imccyu bc2c9bd11a Merge pull request #4427 from deepseek-harness/session-actions-slot
feat(client): add extensible session menu actions
2026-09-20 13:56:15 +08:00
creatixchu 59fdc2604d test: provide the file action slot runtime in delivery fixtures 2026-09-20 13:56:09 +08:00
creatixchu b80722812b fix: scope shared file actions to their owning views 2026-09-20 13:55:27 +08:00
creatixchu 56d0534c30 refactor: share native file actions across delivery and review views 2026-09-20 13:53:16 +08:00
Huanqi Cao e553344063 test(sandbox): drop new unknown casts after the merge-forward
The no-unknown-casts ratchet landed on master after this branch, so the new stub tables in the ACL failure paths can no longer assert through unknown. Route them through a typed partial stub, type the bigint handles as NativePtr, and prune the three retired baseline entries.
2026-09-20 13:42:58 +08:00
creatixchu 33782150cd fix: name the default application in opening tooltips 2026-09-20 13:42:31 +08:00
creatixchu 6e260998c9 fix: refine shared file controls and native query errors 2026-09-20 13:39:11 +08:00
imccyu ee61acfe7e docs(client): describe session row entries as plain menuitem buttons
The Client Slot catalog serves `cordis-client-runner` closures, which cannot
`require` anything, so the `sidebar.workspaces.session.menu.item` example
now renders a `role="menuitem"` `<button>` and the doc names
`MenuItemButton` as what the shipped rows use rather than what an entry must
render; the README separates the Module Loader lane, which does reach the
primitive through `require`, from the runner lane. The Agent Note and the
contract module doc say the entries read the pin and archive sets through
hooks their own faces inject, that the owner draws no separator, and that
the strip keeps clicks from opening the row. `RowActionToast` gets its
contract sentence and the rename-assembly spec points at the e2e that
exists.
2026-09-20 13:33:58 +08:00
imccyu c4949c4d0c fix(client): isolate row action clicks and collapse submenus from the menu list
The Session row's action strip stops click propagation itself, so a
`sidebar.workspaces.session.row.action` entry that renders a plain button no
longer opens the row as a side effect; the shipped buttons drop their own
handling. `Menu` decides submenu exclusivity on the list's own bubbles, by
DOM: reaching a top-level row that is not a submenu parent, by pointer or by
focus, closes the open card for data rows and component rows alike, which
the per-row handlers only did for data rows. A group start on the list's
first row draws no hairline.

The first live-fixture e2e case registers the scaffold's cleanup right after
launch, as the file's other cases do. The three pin scenarios the browser
spec lost when the order write moved into `UiWorkspace.pinSession` — newer
saved orders during a pending pin, a Workspace disappearing during one, and
members whose summaries are temporarily missing — return as service cases.
2026-09-20 13:33:55 +08:00
creatixchu 27b7fd0e2f fix: preserve Shell reference storage during failed handoff cleanup 2026-09-20 13:26:18 +08:00
creatixchu 7943fb3917 Merge master into file application controls 2026-09-20 13:25:10 +08:00
_Kerman dfcef60d06 Merge pull request #4513 from deepseek-harness/xtr/fix-snapshot-source-ranges
fix(session-snapshot): expand source references before writing fixtures
2026-09-20 13:24:41 +08:00
Yichen Jiang c6bc1a2fab Merge remote-tracking branch 'origin/master' into worktree/experimental-voice-input
# Conflicts:
#	apps/desktop/electron-builder.config.mjs
#	apps/desktop/tests/macos-signature.spec.ts
#	apps/desktop/tests/main-startup.spec.ts
#	apps/web/tests/expected/plugin-config/official.expected.md
#	apps/web/tests/expected/plugin-manager/live-enabled.expected.md
#	apps/web/tests/expected/plugin-manager/manager.expected.md
#	apps/web/tests/plugin-config.e2e.ts
#	apps/web/tests/plugin-manager.e2e.ts
#	apps/web/tsconfig.json
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	packages/client/ui-conversation/src/client/skeleton/InputBar.tsx
#	packages/client/ui-plugin-manager/src/client/locales.ts
#	packages/client/ui-plugin-manager/src/client/presentation.ts
#	packages/client/ui-plugin-manager/tests/components.client.spec.tsx
#	packages/client/ui-primitives/README.i18n.yaml
#	packages/client/ui-primitives/README.md
#	packages/client/ui-primitives/README.zh.md
#	packages/client/ui-primitives/src/StateDot.tsx
#	packages/client/ui-primitives/src/icons/index.tsx
#	packages/client/ui-primitives/tests/icons.client.spec.tsx
#	packages/experimental/README.i18n.yaml
#	packages/experimental/README.md
#	packages/experimental/README.zh.md
#	packages/extensions/cordis-client-runner/src/client/slot-catalog.ts
#	pnpm-lock.yaml
#	scripts/gen-cordis-catalog.ts
#	tsconfig.host.json
2026-09-20 13:22:11 +08:00
creatixchu 6493cdac9c fix: retain the Windows Shell host until asynchronous handoff settles 2026-09-20 13:14:49 +08:00
_Kerman 1491975dba Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-4513
Re-record the session-snapshot README bilingual pairing sidecar, and admit
the source-reference regression fixture with the v4 producer-owned `user`
message source kind.
2026-09-20 13:09:14 +08:00
imccyu 3821dc58e3 Merge pull request #4639 from deepseek-harness/fix-migration-v4
fix(session): serve cold forked sessions from the projection cache
2026-09-20 13:04:11 +08:00
creatixchu 39af517961 test: evaluate the Windows fixture output path as a PowerShell expression 2026-09-20 12:58:58 +08:00
creatixchu cbc51b5446 test: isolate native application identity and cold-history associations 2026-09-20 12:51:18 +08:00
imccyu 7d1afeccb0 test(web): register the live fixture rows in the session menu list
The fixture plugin's rows join `sidebar.workspaces.session.menu.item` after
the shipped rows, the first one opening the plugin group with
`separatorBefore`, and dismiss the menu through `useMenuOpenState`.
2026-09-20 12:40:35 +08:00
imccyu 4517603c28 fix(client): rename the row rename request type off the Host name
The typert Cordis catalog drops any exported name that two declarations
share, so ui-workspace's `SessionRenameRequest` made the generator remove
Session Controller's request type from the model-facing API catalog. The
row-side pending rename is `SessionRenameTarget`: the Session and the title
the dialog seeds from.
2026-09-20 12:40:11 +08:00
creatixchu 5218958366 test: keep native association expectations strictly typed 2026-09-20 12:35:53 +08:00
creatixchu 4fb9d34275 fix: use the native test task timeout for fixture readiness 2026-09-20 12:32:05 +08:00
creatixchu b689c724d1 docs: describe cross-platform file opening and pin desktop browser fixtures 2026-09-20 12:28:41 +08:00
creatixchu b4b0c4e4c8 test: exercise native Linux file handoff and document shared adapters 2026-09-20 12:24:09 +08:00
imccyu 21586fe28c feat(client): compose session row actions from slot lists
A Session row's "..." menu and its hover buttons become two list slots the
WorkspaceBrowser entry declares, `sidebar.workspaces.session.menu.item` and
`sidebar.workspaces.session.row.action`. The shipped actions register from
apply the way a client plugin does: pin (menu 100, button 200), rename (200),
fork (300), archive (menu 400, button 100). An entry receives only the row
identity, reads the pin and archive sets through Set hooks its own face
injects, decides its own visibility, renders `MenuItemButton` or one icon
button, and dismisses the menu through the slot-level `useMenuOpenState`
hook bound from the row's render occurrence.

Each action's behavior lives in its injected callbacks. `UiWorkspace` gains
`pinSession` and `unpinSession`; the pin write into the saved orders happens
there, through the viewing-store instance the apply creates and hands the
browser's registration as its handle (the ui-layout pattern), reading the
memberships current at completion. The rename dialog and the row-action
notice are `shell.overlay` entries fed by apply-closure observables through
the faces' `hooks`; the archived notice switches the archived filter
directly. WorkspaceBrowser threads no action callbacks, renders no toast,
and hosts no rename dialog; its title double-click raises the same rename
request.

In ui-primitives, `MenuItemButton` is the plain `role="menuitem"` row for
menus whose rows are components: it shares a data row's markup and styling
and needs no shared state, because `Menu` decides the keyboard walk from the
DOM and now runs the post-selection focus return once on the list's click
bubble for every row kind. `Menu` accepts such rows as `children` beside
`items`, which becomes optional together with `onSelect`; `separatorBefore`
lets a row start a group with the same hairline a separator entry draws. The
context-based `MenuAction` goes away with its extension group.
2026-09-20 12:20:24 +08:00
creatixchu aac990d2d4 test: cover desktop lookup fallbacks and cancel native fixture work 2026-09-20 12:20:04 +08:00
mektpoy 63190fc870 fix(client): unify the plugin identity colour on label-tertiary
Review feedback on this PR: keep one identity colour rather than raising the
card subtitle to label-secondary. The detail-page package name moves from
label-caption to label-tertiary; the settings card subtitle keeps its own
colour and shares only the 12px size with the row it expands into.
2026-09-20 12:19:13 +08:00
imccyu 5ca9b77c44 test(client): expect the pin row ahead of the session menu actions
master's session row menu now leads with Pin session and SessionNode
carries pinned/archived, so the slot-action specs and the Web golden take
the row as it is after the rebase.
2026-09-20 12:17:48 +08:00
Magolor d849d656a5 fix(client): use baseline menu primitive 2026-09-20 12:17:48 +08:00
Magolor 4db234b408 fix(client): align session action slot contract 2026-09-20 12:17:47 +08:00
Magolor fec5c888c4 fix(client): preserve session action slot contract 2026-09-20 12:17:47 +08:00
Magolor cfcd3f3b0e test(client): cover session action focus handoff 2026-09-20 12:17:47 +08:00
Magolor e5a72d73df feat(client): add extensible session menu actions 2026-09-20 12:17:47 +08:00
creatixchu a8c5ca85a1 test: cover Linux associations and native Windows Shell handoff 2026-09-20 12:15:15 +08:00
creatixchu a1545a9bf5 feat: share file associations across macOS Windows and Linux 2026-09-20 12:10:54 +08:00
Dudu-0223 f44b78a622 fix(session): complete parent catalogs while isolating child failures 2026-09-20 12:09:57 +08:00
creatixchu 219bbe47c7 feat: reuse the opening menu in a larger preview action 2026-09-20 12:00:03 +08:00
Dudu-0223 c08ead6900 Merge remote-tracking branch 'origin/master' into fix/lazy-subagent-migration
# Conflicts:
#	packages/client/ui-plugin-manager/tests/components.client.spec.tsx
#	packages/client/ui-workspace/README.i18n.yaml
#	packages/client/ui-workspace/README.md
#	packages/client/ui-workspace/README.zh.md
2026-09-20 11:58:21 +08:00
creatixchu 71b7bbeb88 fix: wait for file associations before enabling the default action 2026-09-20 11:55:48 +08:00
creatixchu 6111f879fd test: verify shared opener menu toggling and SSH visibility 2026-09-20 11:50:40 +08:00
creatixchu 5c409c39bc fix: type shared opening fixtures and document default actions 2026-09-20 11:48:58 +08:00
creatixchu e969aaff58 refactor: share compact opening controls for files and directories 2026-09-20 11:46:50 +08:00
lsdsjy c74c8bc471 Merge origin/master into feat/desktop-welcome-and-window-controls 2026-09-20 11:37:38 +08:00
lsdsjy f20c3e6a87 fix(desktop): align welcome typography and action sizing 2026-09-20 11:31:41 +08:00
lsdsjy f0a35eba0d feat(credentials,ui-settings-account): display bonus wallets separately 2026-09-20 11:31:41 +08:00
lsdsjy 0c0789e4df fix(deepseek-account-platform): identify embedded desktop requests 2026-09-20 11:31:41 +08:00
lsdsjy 9b53f0abbb fix(ui-settings-account): center collapsed account avatar 2026-09-20 11:31:41 +08:00
lsdsjy fb829bfc5c fix(desktop): refine welcome sign-in and workspace entry focus 2026-09-20 11:31:41 +08:00
lsdsjy 2d0f431181 feat(deepseek-account,ui-settings-account): display profile avatars with icon fallback 2026-09-20 11:31:41 +08:00
lsdsjy adcd85c08a fix(deepseek-account-platform): preserve client type in login completion redirects 2026-09-20 11:31:41 +08:00
lsdsjy 4232634dd7 fix(desktop): keep workspace hidden during startup activation 2026-09-20 11:31:41 +08:00
lsdsjy 575de9ccbd fix(ui-settings-account,deepseek-account): reset copy feedback and retain successful profiles 2026-09-20 11:31:41 +08:00
lsdsjy 52d5ecd7c6 fix(desktop): update welcome copy and remove forced preview 2026-09-20 11:31:41 +08:00
lsdsjy d952001c8c fix(ui-settings-account,desktop): adopt shared menu styling after master rebase 2026-09-20 11:31:41 +08:00
lsdsjy 68f8d32d83 fix(desktop,deepseek-account): share platform headers for Host API requests 2026-09-20 11:31:40 +08:00
lsdsjy 8cadbe8655 fix(desktop): clean up embedded views and complete packaged startup 2026-09-20 11:31:40 +08:00
lsdsjy d9456b9464 fix(ui-settings-account): fall back to masked contact in sidebar 2026-09-20 11:31:40 +08:00
07akioni 31b9b5cb77 fix(account-controller): declare generated schema dependency 2026-09-20 11:31:40 +08:00
lsdsjy d58c8cfcde fix(desktop): reconcile welcome startup with current update lifecycle 2026-09-20 11:31:40 +08:00
lsdsjy fe6702cb20 feat(credentials): configure inference origin and discard mismatched account grants 2026-09-20 11:31:40 +08:00
lsdsjy b73a2c8d2d fix(desktop,credentials,ui-settings-account): configure embedded deployment and disable label selection 2026-09-20 11:31:40 +08:00
lsdsjy 3402c95291 fix(ui-settings-account): hide account tab while signed out 2026-09-20 11:31:40 +08:00
lsdsjy 5b7195e032 feat(desktop,credentials,client): update sign-in protocol and Platform experience 2026-09-20 11:31:40 +08:00
lsdsjy 048297321a feat(desktop,credentials,client): integrate DeepSeek account sign-in and Platform pages 2026-09-20 11:31:40 +08:00
lsdsjy 753eff67b1 feat(desktop,client): add the native welcome window 2026-09-20 11:31:27 +08:00
Huanqi Cao 94a2d4af28 Merge remote-tracking branch 'origin/master' into fix/windows-acl-delete-escape
# Conflicts:
#	docs/config-catalog.i18n.yaml
2026-09-20 11:17:22 +08:00
creatixchu c6c9da3eba chore: retire the removed path-action unknown-cast baseline 2026-09-20 11:03:54 +08:00
creatixchu dd39d56af5 test: remove legacy unknown assertion from path-action fixture 2026-09-20 11:02:45 +08:00
creatixchu 79798d8c5a fix: satisfy package publication and file-action coverage gates 2026-09-20 11:00:05 +08:00
imccyu 4b02d03ed5 test(session): compare the forked cold row's recency with the list formula
The cold row's updatedAt is the later of the header's creation time and the cached last prompt; the fork's creation time is wall-clock and can trail the inherited prompt by a millisecond, so the restart test asserts the same maximum instead of the prompt time alone.
2026-09-20 10:54:20 +08:00
creatixchu 0c3045d488 fix: validate native metadata and refresh generated source references 2026-09-20 10:45:21 +08:00
creatixchu 5325babc7b test: cover default native command adapter selection 2026-09-20 10:43:06 +08:00
creatixchu e435340eff test: exercise application selection through the recorded Web session 2026-09-20 10:41:48 +08:00
creatixchu 0ae1b2f91c docs: describe native file application selection and platform scope 2026-09-20 10:39:42 +08:00
creatixchu 0839011204 fix: include native association types in client compilation 2026-09-20 10:37:11 +08:00
creatixchu 03d44191b3 fix: expose browser-safe file association metadata to Remote generation 2026-09-20 10:35:56 +08:00
creatixchu 97877bd8b4 test: cover file handler selection and shared path authorization 2026-09-20 10:34:24 +08:00
creatixchu d6d9d47c49 fix: constrain application icon pixels before transport 2026-09-20 10:32:57 +08:00
creatixchu 39bde1a5c9 feat: query file applications for sidebar opening (#4562) 2026-09-20 10:31:32 +08:00
imccyu de055efa9a test(session): list a forked Session's cached title after a Host restart
A real fork made through sessions.fork is checkpointed into the projection cache, the Context is disposed, and a Host booted over the same storage root serves the fork's title and list metadata from the header alone, as a kind: 'cached' block, without inspecting or opening the log.
2026-09-20 02:04:37 +08:00
imccyu fd76c9534f docs(session): sync the client merge-rule prose with cached and sequenced rows
The session-controller README, the per-session store JSDoc, and the projcache predecessor-recovery and durable-web-queue-recovery notes described one higher-seq-wins rule and the asOfSeq -1 title hint. They now state that higher-seq-wins applies among Host-sequenced values, that cached list blocks yield to the connected Session's baseline, and that the predecessor title carries its stored row's watermark under kind: 'cached'.
2026-09-20 01:48:34 +08:00
imccyu 6ab579b643 fix(web): label the assembled-remote fixture's list projection blocks
The built-client fixture served newly created Sessions with a control-baseline block as their list projections. Since SessionProjectionHints requires `kind`, the real client's applyListBlock would have hit assertNever on it; the created Session is live on the fixture Host, so its block is sequenced.
2026-09-20 01:48:33 +08:00
imccyu f3310dc746 docs(session): record the list block kind decision and cross-link the client merge rules
The listing identity note describes the `kind` field, rejects routing on the -1 sentinel, and links the projcache predecessor-recovery and projection-owned client state notes; the latter's client merge rules now distinguish Host-sequenced rows from cached list hints.
2026-09-20 01:31:52 +08:00
imccyu c4d40864fd fix(client): route list projection blocks by kind
A `sequenced` list block merges key by key under higher-seq-wins like any Host-computed value, so a delayed control baseline at a lower cut can neither overwrite nor clear a newer live-session list value. Only a `cached` block goes through applyCached and yields to every sequenced write. The projection store's module docs describe the two row kinds.
2026-09-20 01:31:52 +08:00
imccyu 1b51a1ad2d fix(session): label list projection blocks with their sequence space
SessionProjectionHints gains a required `kind`: `sequenced` when the Host's live registry computed the block for an attached Session, `cached` when a header-only listing viewed it from the persisted projection cache. `asOfSeq` stays the producer's own watermark in that space, so the cache read faces report the lowest served row seq again instead of the -1 sentinel. The two fields are independent: `kind` names the sequence space, `asOfSeq` the position in it.
2026-09-20 01:31:52 +08:00
imccyu 2ef33c7f28 docs(session): record the projection cache listing identity decision
Agent Note for the lifecycle identity read-only face and the client store's cached/sequenced row kinds: mechanism, rejected alternatives, and what stays untouched.
2026-09-20 01:31:52 +08:00
imccyu 9ff8f26450 fix(client): keep list-cached projection rows below sequenced writes
ProjectionValueStore rows are either cached (viewed from the persisted checkpoint by the session list, no comparable seq) or sequenced (computed by the connected Host, seq comparable within the connection). Cached values fill empty keys only; every baseline discards cached rows before seeding, and every frame replaces them regardless of seq, so a connected Session's values always supersede list hints. The list response and api-session/added blocks write cached rows.
2026-09-20 01:31:52 +08:00
imccyu 86ca9de07e fix(session): read cold seeded rows from the projection cache by header
The projection cache read-only face (cachedSnapshot, cachedPredecessorTitle) now matches the lifecycle identity a header witnesses (formatVersion, createdAt, cwd, isSeeded) and serves its rows as a cached block with asOfSeq -1. The fold face (hydratePrepared, write, coldSnapshot) keeps the full identity including the inherited cut. The session list and @ completion drop their isSeeded guards, so forked sessions keep their cached title and list metadata across a Host restart; list-children keeps its body fallback.
2026-09-20 01:31:52 +08:00
Tianyi Cui bfcfc9ed2f Merge pull request #4603 from deepseek-harness/worktree/session-attachment-carriers-20260919
fix(session): restrict attachment discovery to declared event content
2026-09-20 00:38:00 +08:00
Tianyi Cui 85c6e80e0c Merge remote-tracking branch 'origin/master' into worktree/session-attachment-carriers-20260919 2026-09-20 00:27:54 +08:00
Tianyi Cui 4b49137aa6 Merge pull request #4357 from deepseek-harness/worktree/fix-deepseek-files-json-errors
fix(llm): classify malformed Files JSON responses
2026-09-20 00:16:58 +08:00
Tianyi Cui 2319cbe476 Merge pull request #4623 from deepseek-harness/worktree/simplification-skill-survey-20260919
docs: refine simplification discovery and add nine proposals
2026-09-20 00:12:35 +08:00
Tianyi Cui 3f9567a4c9 Merge pull request #4604 from deepseek-harness/worktree/team-opaque-json-20260919
fix(agent-team): preserve opaque JSON in mailbox projections
2026-09-20 00:11:59 +08:00
imccyu 00dac23ba0 Merge pull request #4621 from deepseek-harness/worktree-fix0919
fix: 修复侧边栏 Fork、终端提示与持久 Shell 取消行为
2026-09-19 23:49:59 +08:00
imccyu d8c993a622 docs(shell): clarify queued cancellation regression coverage 2026-09-19 23:31:31 +08:00
imccyu 54b0aae8e6 docs(web): clarify retained subagent status sources 2026-09-19 23:31:31 +08:00
imccyu cdd082c4ae test(web): preserve terminal liveness evidence after layout loss 2026-09-19 23:31:31 +08:00
imccyu a05f2244cf fix(plugins): remove unknown casts from metadata loading and fixtures 2026-09-19 23:05:40 +08:00
imccyu d67545f367 docs: sync catalogs and contracts for session fixes 2026-09-19 23:05:40 +08:00
imccyu 8771607f8b test: cover sidebar fork and persistent shell cancellation regressions 2026-09-19 23:05:40 +08:00
imccyu 9d4fa54c2d fix(shell): settle persistent shell cancellation without throwing its reason 2026-09-19 23:05:40 +08:00
imccyu b7b587692d fix(web): disable terminal recovery and cleanup slots 2026-09-19 23:05:39 +08:00
imccyu a7ce695461 fix(web): position new forks before their source 2026-09-19 23:05:39 +08:00
imccyu 1e48dae2aa fix(web): keep sidebar forks from switching sessions 2026-09-19 23:05:39 +08:00
Dudu-0223 e6e5d95b29 test(session): align migration corpus and CLI expectations with lazy reads 2026-09-19 23:03:38 +08:00
Dudu-0223 6362113ef8 Merge master into fix/lazy-subagent-migration 2026-09-19 22:53:29 +08:00
Dudu-0223 1c16bc9a0e test(subagent): use branded descriptor sequence in restored identity 2026-09-19 22:47:59 +08:00
Dudu-0223 a9985b49ae fix(session): migrate historical subagents only when opened 2026-09-19 22:47:01 +08:00
mektpoy 88ee6039c6 Merge remote-tracking branch 'origin/master' into fix/windows-plugin-list-type-size 2026-09-19 22:33:52 +08:00
mektpoy bb2326f044 fix(client): raise the plugin package name contrast on the detail page
The package name under a plugin's title is the exact spec that installs it, yet
it was the palest alias in the palette: label-caption, 2.13:1 against white,
lighter than the free-text description below it. Use label-secondary, the same
alias the description uses, for 5.80:1.
2026-09-19 22:24:35 +08:00
imccyu 3863992e67 Merge pull request #4571 from deepseek-harness/worktree-pluginlocale
feat: 插件元信息支持按 export 多语言展示
2026-09-19 22:15:53 +08:00
Xu Hanxiang 128d7d81d0 Merge pull request #4574 from deepseek-harness/fix/4573-browser-use-shared-instances
fix(browser-use): share the installation scope and MCP client instances
2026-09-19 22:04:23 +08:00
Tianyi Cui 4ffc8c7bef docs: clarify survey evidence and proposal cleanup steps 2026-09-19 21:58:03 +08:00
mektpoy faa6986b2b docs(browser-use): use the runtime resolution vocabulary in the instance note
The profile resolution lookup order note, merged today, owns the mechanism this
note describes and names it runtime resolution with an interception layer at
$DSH_HOME/profiles/node_modules. This note adopts that vocabulary and links the
owning record instead of restating the resolution order.

It also records the boundary the sibling experimental providers leave open: a
profile that installs one of them beside this package hoists their
dsh-mcp-client dependency into the profile's own node_modules, so this package's
peer resolves there and the two copies keep separate serverName reservations.
The scope split does not return, because none of them declares dsh-scope.
Issue #4628 tracks moving those declarations to peers.

Refs #4628
2026-09-19 21:53:43 +08:00
mektpoy 3014457c60 fix(client): share one size for the plugin inventory entry identity
Keep the Loader entry id at one size in both places it appears - the card
subtitle and the row the card expands into - by moving the shared code-font
typography into a single rule. The subtitle keeps its own secondary label
colour against the expanded row's primary one.
2026-09-19 21:46:43 +08:00
Tianyi Cui cf75d1d099 docs: refine simplification discovery and add nine proposals 2026-09-19 21:31:31 +08:00
Tianyi Cui 3a0d640214 test(llm): show malformed Files payloads in case names
Interpolating an empty body directly produces empty parentheses in the failure title, making the empty-response case harder to distinguish from the truncated JSON case in CI logs.

Use JSON formatting for the existing case object so the operation and body are visible, including an explicit empty string. Keep the same inputs, error classification, original-cause assertions, and single-request checks.
2026-09-19 21:19:46 +08:00
Tianyi Cui 914bd34ea7 test(session-log-export): type attachment fixtures without unknown bridges
The attachment-policy fixtures introduced three assertions to unknown and
changed two previously recorded assertions. The new repository gate rejects
those escape hatches even though the earlier branch CI passed.

Give the user, tool-result, and inbox fixtures their required V4 message
metadata and declared identifier types. Declare the fixture's plugin content
tag through ContentBlockMap, and check the flat tool-result fixture directly
as its concrete SessionEvent type. Keep intentional malformed inbox entries
and opaque extension fields in the existing negative cases.

Remove all five unknown bridges without adding allowances. Delete the two
baseline entries retired by the rewritten existing fixtures; the other
three assertions were never part of the accepted baseline. Attachment
runtime code and the tests' access-denial and complete-log assertions remain
unchanged.

Validation: the Host TypeScript aggregate and all 52 archive tests pass.
verify-no-unknown-casts reports no new or stale entries, with 1575 existing
assertions remaining; the baseline adds zero allowances and retires two.
2026-09-19 21:19:32 +08:00
Tianyi Cui d4ff95c8e2 docs(llm): distinguish Files JSON decoding from metadata validation
The operation, HTTP status, and parser cause added by responseJson belong to JSON decoding failures. Existing metadata validation also uses INVALID_RESPONSE but does not provide those fields, so the broader phrase parsing failures promises too much.

Limit the README guarantee to JSON decoding and keep metadata-validation behavior unchanged. Keep the Agent Note focused on why the existing INVALID_RESPONSE code is used without inferring a transport retry, and link to the README for the error-field details. Update both languages and their pairing records.
2026-09-19 21:19:07 +08:00
Tianyi Cui 0c44e5461d fix(session): restrict attachment discovery to declared event content
Attachment reads and ZIP export previously inferred ownership from common
field names on arbitrary events. Opaque ignorable plugin payloads could
therefore cause storage reads, while declared compaction content was missed.

Select attachment-bearing fields by current built-in event type in both
readers. Read direct image and file blocks, including flat V4 tool results
and developer messages, without interpreting extra block fields. Leave
unknown payloads and malformed inbox entries opaque. The archive preserves
the complete logical log even when its payload does not authorize a read.

V4 validates title requests as one text block, so do not treat them as an
attachment carrier. Compaction keeps its declared ContentBlock fields for
valid custom producers; the basic producer's text-only output is documented.
Historical wrappers remain the adjacent converters' responsibility rather
than a second compatibility path in attachment readers.

Adapt the original policy change to master after V4 landed, retaining its
author credit and scope. Cover tool-result export explicitly, keep Team
fixtures free of invented message roles, and verify that denied carriers
never read storage. The 889 owning tests pass with 100% statement, branch,
function, and line coverage for both changed runtime files.

Co-authored-by: Tianyi Cui <[email protected]>
2026-09-19 21:08:29 +08:00
mektpoy 4167b60997 Merge remote-tracking branch 'origin/master' into fix/4573-browser-use-shared-instances 2026-09-19 21:03:19 +08:00
Tianyi Cui df3f4477ea test(agent-team): type opaque JSON fixtures without unknown assertions
The new no-unknown-casts check rejects two assertions introduced by these projection regressions. Both fixtures intentionally represent unknown content: malformed input sent to the admission checks, and a cached plugin block whose opaque field was already lost.

Declare those inputs as unknown variables instead of asserting their expressions to unknown. Keep the same malformed values, content assertions, checkpoint replay, and production validation. Do not expand the recorded cast allowances or change any runtime behavior.
2026-09-19 20:59:52 +08:00
Tianyi Cui f56aecb314 test(agent-team): remove an unused store from checkpoint restoration
The cold checkpoint regression calls only the projection registry register and restore methods. Neither needs SessionStore, so mounting and disposing that extra service obscured the fixture dependency. Keep the registry lifecycle and the recovered-content assertion unchanged.
2026-09-19 20:59:52 +08:00
Tianyi Cui 50d38688be docs(agent-team): state the local content validation scope precisely
The Team projector declares only a subset of current content validators; the existing file and image validator gaps are not fixed by opaque JSON preservation. Limit the new prose to those local validators instead of promising full ContentBlockMap validation.

Keep cache behavior in the README and invalidation rationale in the existing decision note. Document why unknown JSON objects pass through by reference without changing any parser branch or expanding this repair into unrelated validation policy.
2026-09-19 20:59:52 +08:00
Tianyi Cui 1e6630a856 fix(agent-team): preserve opaque JSON through mailbox projections
A valid unknown content block can own a __proto__ JSON field. Zod object reconstruction silently drops that key when Team events are projected and when checkpoints are admitted, even though the original Session log still contains it.

Validate the unknown block tag without reconstructing its decoded JSON fields. Keep the current V4 local validators and the rejection of retired tool-result content. Bump only the Team projection cache stateVersion from 3 to 4 so old lossy checkpoints are rebuilt from the unchanged log; this is not a Session format or schema change.

Cover direct and nested opaque JSON fields inside accepted native V4 content, plus public registry restoration from an older lossy checkpoint. Historical tool-result conversion remains owned by the Session migration and is not restored in the Team parser. Update the README and existing Team decision rationale together.

Adapted from the Team JSON preservation work in b8f1da92599123e5d5bae6c174f73b5b778f3554 by Tianyi Cui.

Co-authored-by: Tianyi Cui <[email protected]>
2026-09-19 20:59:52 +08:00
Tianyi Cui d6a0e3323e fix(llm): classify malformed Files JSON responses
Empty or truncated successful Files API bodies currently escape as bare SyntaxError values. They omit which Files operation failed and the successful HTTP status, obscuring the diagnostic while the caller still needs to reject the response.

Route upload, list, retrieve, and delete JSON parsing through one helper that converts only SyntaxError to LlmError INVALID_RESPONSE. Preserve the operation, HTTP status, and original parser cause; transport and cancellation failures retain their original identity. Do not introduce retries or reinterpret malformed JSON as a successful response.

Keep regressions for both Messages and Chat Completions, all four operations, empty/truncated bodies, single request execution, and non-parser error identity. This improves classification and diagnostics without claiming to repair the remote cause of intermittent empty responses.

Co-authored-by: Tianyi Cui <[email protected]>
2026-09-19 20:59:51 +08:00
Tianyi Cui b1dbe92356 Merge pull request #4618 from deepseek-harness/worktree/fix-migration-json-typing-20260919
fix(test): type migrated JSON without an unknown cast
2026-09-19 20:57:47 +08:00
Tianyi Cui 77bcc35adb fix(test): type migrated JSON without an unknown cast
The merged concurrent migration test used an as-unknown widening assertion after JSON.parse. Master now rejects newly introduced unknown casts, so that test blocks the repository gate and unrelated PR validation. Give the map callback an explicit unknown return type instead. Keep the gate baseline unchanged; parsing and assertions have the same runtime behavior.
2026-09-19 20:52:09 +08:00
mektpoy 76f0422653 Merge remote-tracking branch 'origin/master' into fix/4573-browser-use-shared-instances 2026-09-19 20:32:48 +08:00
Tianyi Cui a22ac3284d Merge pull request #4611 from deepseek-harness/worktree/parallel-v4-corpus-migration-20260919
perf(session): parallelize V4 migration with JSON reports
2026-09-19 20:27:44 +08:00
Tianyi Cui fafa154a14 Merge pull request #4610 from deepseek-harness/worktree/prohibit-as-unknown
feat(infra): prohibit new unknown casts and clean up existing uses
2026-09-19 20:27:11 +08:00
Tianyi Cui 84659abe3d docs(session): clarify bulk migration cache ownership
Name the JSONL backend and explain that its cache reuses recently decoded logs. This makes the bounded-batch rationale concrete without duplicating private implementation constant names in the operational description.
2026-09-19 20:19:43 +08:00
imccyu a9f205c584 refactor(plugins): rename PackageMeta to PluginLocalizedMeta 2026-09-19 20:19:08 +08:00
imccyu acec2ba713 docs(plugins): document PluginLocalizedMeta type name 2026-09-19 20:19:08 +08:00
imccyu 8ceaa725e0 build(plugins): validate locale resources and refresh catalogs 2026-09-19 20:19:07 +08:00
imccyu 0d611ea151 feat(web): display plugin-owned locale metadata 2026-09-19 20:19:04 +08:00
imccyu 0b7cb4102b feat(plugins): resolve installed metadata through runtime resource exports 2026-09-19 20:19:04 +08:00
imccyu f8240240fa docs(plugins): define localized display metadata and fallback rules 2026-09-19 20:19:03 +08:00
Tianyi Cui 0e46c4ed26 docs(session): specify fatal migration job behavior
An unexpected visitor rejection represents a batch-level programming or reporting failure, rather than a normal per-Session refusal. The scheduler already drains its active workers before surfacing it and does not start deferred retries. State that behavior explicitly so callers do not assume the retry pass runs after a fatal batch failure.
2026-09-19 20:18:58 +08:00
Tianyi Cui 0ab7976461 test(session): exercise the source-change retry through the CLI
The parent-child integration case can succeed without observing a race, while scheduler-only tests do not exercise the actual error classification or CLI output. Inject one genuine source-change error at the persistence open boundary in an isolated child process, then delegate to the real backend. Assert DEFERRED, completion of the other input, one RETRY, preserved source bytes and the resulting parent catalog. This adds no production test hook or timing-based race.
2026-09-19 20:18:41 +08:00
Tianyi Cui 33d93ab155 fix(session): accept safe numeric job-count overrides
The command promises any positive safe integer, but its additional decimal-spelling regex rejected valid expert overrides such as 1e2 and +1. Let Number parse the supplied value and retain the positive safe-integer check. This preserves the CPU-based default cap while allowing equivalent numeric spellings and larger explicit values.
2026-09-19 20:16:30 +08:00
Tianyi Cui 0dd9a282b8 test(session): clean migration fixtures without traversing junctions
The source-entry regression creates a Windows junction to the real checkout. Its local unlink normally removes it, but fallback teardown must remain safe if that unlink fails. Use the repository fixture cleanup helper to unlink reparse points before recursive deletion and retain its bounded Windows handle-release retries. This changes only test resource cleanup.
2026-09-19 20:14:54 +08:00
Tianyi Cui e65d349de3 fix(infra): reconcile cast baseline with Session V4 master 2026-09-19 20:13:58 +08:00
Tianyi Cui fd0654e96b fix(infra): stabilize cast fingerprints and reject unknown unions 2026-09-19 20:13:58 +08:00
Tianyi Cui 580bdc7258 refactor: remove redundant unknown casts 2026-09-19 20:13:58 +08:00
Tianyi Cui c5d775d437 feat(infra): prohibit new assertions to unknown 2026-09-19 20:13:58 +08:00
Dudu-0223 bc45bd821a Merge pull request #4530 from deepseek-harness/fix/compaction-threshold-reserves-completion
fix(compaction): reserve output tokens and 64K pressure headroom
2026-09-19 20:10:38 +08:00
Tianyi Cui f476a25de3 feat(session): emit structured corpus migration summaries
A text error list does not show how failures are distributed across historical source versions or let developers aggregate repeated rejection reasons. Emit and save the same JSON report with per-version outcomes, stable failure groups and per-input diagnostics, plus runtime, checkout and report locations. Keep source versions from physical discovery rather than migrated handle headers.

Classify only known diagnostic fields such as unexpected members, unknown events, child prerequisites and sequence gaps. Preserve original messages and use an explicit fallback for other failures; the report makes no inference about historical producer bugs and cannot influence admission or retry decisions. Regression checks cover printed/file/log equality, private report files, grouped distinct sequence coordinates and source-file preservation.
2026-09-19 20:00:11 +08:00
Dudu-0223 ec7030afd3 fix(compaction): default summary output cap to headroom 2026-09-19 19:56:54 +08:00
Dudu-0223 9b016b6425 refactor(compaction): require an explicit output reservation 2026-09-19 19:56:53 +08:00
Dudu-0223 555b664b08 fix(compaction): reserve configurable 64K pressure headroom 2026-09-19 19:56:53 +08:00
Dudu-0223 b02b20d713 fix(compaction): pin output caps and cover proactive reserve replay 2026-09-19 19:56:51 +08:00
Dudu-0223 a1cebebd40 refactor(compaction): drop the spec's reservedCompletionTokens field
Review follow-up: nothing consumed the field. The reserve stays an input to
`resolveCompactSpec`, whose returned budgets already express its effect, so
`ResolvedCompactSpec` keeps its exported shape.

Note the name collision a consumer would have hit: `ResolvedTargetPolicy.maxTokens`
is the compaction *summarization* output cap (default 8192), not the routed
request's cap reserved from the same window.
2026-09-19 19:56:51 +08:00
Dudu-0223 0fadb08fbd fix(compaction): gate pressure on the message budget, not the whole window
Proactive pressure scaled `thresholdRatio` by the routed model's entire
context window, but a request also reserves output tokens the provider
charges to that same window — the LLM service deliberately never clamps
them (`packages/llm/llm/src/index.ts`).

With a 1,000,000-token window and the default 256,000-token request cap the
gate therefore sat at 800,000 while the provider refused any prompt above
792,576. Observed in a real session: three requests died at 792,850 /
797,639 / 793,352 message tokens ("maximum context length is 1048576 ...
you requested 1048850 tokens"), no pressure compaction ever fired, and the
overflow recovery that did run could not condense an ~800k-token history
into the 8192-token summary cap.

Scale both ratios by the message budget left after the reserve, sourced from
the effective request envelope's `maxTokens` and falling back to the
adapter's per-request output default. A reserve that leaves no message
budget reports a target-specific pressure configuration error, matching the
existing per-route warning policy rather than silently disabling proactive
compaction. The headless compaction e2e advertises a coherent capacity/cap
pair so its 8000-token message budget and 4000-token threshold are unchanged.

Related #1841
2026-09-19 19:56:51 +08:00
Tianyi Cui e105557046 perf(session): parallelize V4 corpus migration
Sequential corpus migration waits for each Session to finish I/O and publication verification before starting the next. Use a bounded queue with one shared persistence Context, defaulting to available CPU count capped at 16. Expert --jobs overrides accept any positive safe integer. Stable input indices and separate completion counts keep interleaved progress useful for large corpora without opening every log simultaneously.

A concurrently upgraded child can invalidate its parent evidence. Preserve the backend revision checks and defer only the explicit source-change error for one serial retry after initial work drains. Corruption, unsupported formats and writer locks remain failures; historical files and existing V4 data remain unchanged. Deterministic scheduler tests cover 10,000 inputs, bounded overlap and retry ordering, while real raw/zstd corpora verify parent catalogs and serial-equivalent output. Performance timing was stopped at user request because the host has competing workloads.
2026-09-19 19:49:30 +08:00
Tianyi Cui 0fa88d4875 Merge pull request #4320 from deepseek-harness/release/session-log-v4
feat(session): introduce Session format V4
2026-09-19 19:44:48 +08:00
mektpoy 31925760ca Merge remote-tracking branch 'origin/master' into fix/4573-browser-use-shared-instances 2026-09-19 19:31:56 +08:00
mektpoy 73bf301227 Merge remote-tracking branch 'origin/master' into fix/windows-menu-tooltip-overlap 2026-09-19 19:30:41 +08:00
mektpoy 656066e0a1 Merge remote-tracking branch 'origin/master' into fix/windows-directory-junction
# Conflicts:
#	packages/api/workspace-files/README.i18n.yaml
#	packages/api/workspace-files/README.md
#	packages/api/workspace-files/README.zh.md
2026-09-19 19:28:00 +08:00
Tianyi Cui 8dc1d0e3ed feat(session): add one-time V4 corpus migration command
Give developers one pnpm command to exercise the release migration against their own Session roots. Inventory physical generations so malformed entries remain visible, then reuse JSONL write-open locking, validation, and exclusive successor publication with the full root available for child-catalog evidence. Open existing V4 files read-only and preserve every historical generation.

Report each selected source and outcome, continue after individual failures, repeat all errors at the end, and retain a private temporary report with checkout/runtime details and full causes. A failed run exits nonzero. Explicitly close handles because source-launch await-using lowering inside a loop can retain a previous iteration error. Real-entry regressions cover raw/zstd tool-result conversion, repeated runs, unchanged originals, failure continuation, and unsupported layouts. Document the command in the migration cookbook.
2026-09-19 18:51:42 +08:00
Tianyi Cui b28fca7e87 docs(session): correct incomplete child evidence migration policy
The V4 acknowledgement still said missing child descriptors reject migration. The converter already skips backfill when a child has no single supported own descriptor, while explicit identity, timestamp, and mode conflicts still reject publication. Align both language versions with that behavior so release reviewers and corpus testers do not expect an obsolete refusal. Preserve every machine acknowledgement and schema fingerprint.
2026-09-19 18:51:32 +08:00
Tianyi Cui 370e1efcdb test(session-reference): use declared plugin sources in V4 fixtures
The conversation fixture used an undeclared goal source and forced it
through MessageSource with a double assertion. That bypassed the V4
producer-owned source types instead of exercising an input accepted by
createUserMessage.

Use the fixture's existing declared test source for both injected plugin
messages and remove the unused MessageSource import. The resolver excludes
all non-user, non-checkpoint sources, so these cases do not depend on goal
identity or need a goal-package dependency. Message content, event order,
captured sequence numbers, and every projection assertion stay unchanged.

Validation: all 49 session-reference tests pass, the Host TypeScript
aggregate passes, and the diff passes whitespace checks.
2026-09-19 18:22:32 +08:00
Tianyi Cui fdff56c293 fix(cli): drop retired link-mode override after master integration
The release branch still passed resolutionMode: link from the source CLI
and documented a separate link/runtime selector. The integrated master
has removed that selector and its materializer in favor of one runtime
resolver that also supports source launches. The spread kept compiling
because excess-property checking did not reject it, but the property was
ignored by runProfile and the retained prose contradicted the runtime.

Remove the dead option/comment and its obsolete bilingual paragraph.
The CLI entry and the architecture note now match the integrated master;
keep source-module identity verified through its real source-launch and
tool-execution tests. This retires an old integration workaround, without
changing Session V4 or restoring a second profile resolution backend.
2026-09-19 18:03:33 +08:00
Tianyi Cui 5da1515286 test(cli): inspect flat V4 results in source launch smoke
The new master source-tool smoke reads isError and content from a V3
nested tool-result block. After integration with the V4 release, that
block no longer exists: the durable message itself has role tool,
toolCallId, isError and result content. The old assertions fail to
compile and cannot verify the current writer's output.

Read the existing V4 fields while retaining the real source-profile
launch, single Tools instance, call identity, sandbox error and shell
output checks. Do not impose the old single-wrapper cardinality on the
flat content array. This adapts the incoming regression test without
changing the V4 format, migration implementation or stored recordings.
2026-09-19 18:01:49 +08:00
Tianyi Cui 8b0b2dc1d8 Merge master b86916de into release/session-log-v4
Integrate the master tip observed for the final V4 landing preparation on
top of the already merged migration stack. Preserve the V4 writer, flat
message migration, extension policy, catalog validation and historical
recordings while bringing in upstream profile resolution and desktop/UI
changes.

Resolve four generated translation-pairing records from the combined
English/Chinese text. Keep this master checkpoint separate from any
integration fixes and retain all reviewed parent history. Follow-up
validation covers the affected launch/UI paths and migration replay.
2026-09-19 18:00:36 +08:00
Tianyi Cui 2e061ec93f Merge pull request #4583 from deepseek-harness/worktree/v4-lossless-tool-results-20260919
fix(session): preserve extensions while flattening V3 tool results
2026-09-19 17:51:02 +08:00
Tianyi Cui 56f8c7f51b docs(session): keep migration mappings specific to each edge
The cookbook previously promoted plugin prefixes and owner separation into a general requirement. That overstates the migration policy: direct source kinds and ordinary metadata need no new namespace solely because they are extensible.

Require each edge to document only the mappings its target needs and why, preserve nested opaque data, and permit alpha refusal of unexpected source fields that would otherwise acquire new target meaning. Exact V3 source and ToolSchema choices remain in the V3-to-V4 README; no runtime, schema, or provider behavior changes.
2026-09-19 17:27:14 +08:00
imccyu b3961e06a0 Merge pull request #4608 from deepseek-harness/worktree-removelink-rename
refactor(boot): rename the profile resolution generation to the runtime resolution
2026-09-19 17:25:04 +08:00
Tianyi Cui bb81d312ae docs(session): scope extension prefixes to declared mappings
The convention identifies how an edge preserves the identifiers and extension fields that it explicitly maps; it does not require every extension-owned field in every source slot to be renamed.

Keep the cookbook general enough for preserved stream-start extras while retaining the exact field-owner mappings documented by each migration edge. This changes policy wording only, not the current V4 schema or conversion implementation.
2026-09-19 17:20:53 +08:00
Tianyi Cui 7528528007 test(session): name the wrapper pass-through assertion precisely
This case calls only liftToolResult; the native validator has separate coverage. Name the behavior actually asserted so the test title does not claim both paths are covered by one assertion. Assertions and production behavior are unchanged.
2026-09-19 17:20:53 +08:00
Tianyi Cui 3e31760bc7 docs(session): explain historical result field ownership
The flat result conversion prefixes every extension-owned field, not just names currently colliding with core fields. Correct the cookbook wording to match that complete mapping.

Record why retaining opaque message and wrapper owners does not invent a shared owner or a new core metadata field. The deliberate costs are retaining duplicate opaque values and requiring plugin consumers to use V4 names; the first-class tool-message decision and runtime implementation stay unchanged.
2026-09-19 17:20:53 +08:00
Tianyi Cui 4ab9101271 docs(session): state the flat result converter failure contract
The exported converter rejects malformed wrappers with SessionFormatError in addition to refusing unsupported nesting. Document both failure categories so callers can distinguish corruption from a converter support limit.

Remove the obsolete claim that recorded replay compares serialized field order: the native-writer parity assertion compares parsed objects. The emitted fields and their order remain unchanged.
2026-09-19 17:20:53 +08:00
Tianyi Cui 45ce6ef21d docs(session): clarify converter fixes leave existing successors intact
An incoming converter runs only when a historical generation is selected. Fixing a mapping after the target ships does not revisit already-produced target files, so allowing compatible converter fixes must not imply repairing those files automatically.

Keep the user-approved ability to extend or correct historical conversion without a target version bump. Require documentation of changed accepted mappings and continued support for existing outputs, and distinguish that work from changing target representation or interpretation incompatibly. Keep operational alpha guidance in the cookbook and the owning decision note focused on the runtime facts.
2026-09-19 17:20:53 +08:00
Tianyi Cui c7923096c7 test(session): bind tool-result parity to retained V3 replay
The parity assertion previously compared a fixed V3 log with whichever generation the ordinary scenario selected. A legitimate V4 re-recording could change call ids and make the assertion compare different model inputs.

Run an additional replay-only variant through the existing headless runner with both its replay file and migration expectation bound to the retained V3 recording. Keep the ordinary scenario on its highest generation, retain call ids in the comparison, and preserve every committed recording.

Validation: the ordinary replay, retained-V3 replay, and old-wrapper negative control pass. Changing only the latest V4 call ids makes the former assertion fail but leaves the corrected retained-V3 replay passing; both fixture and source bytes are restored after this control.
2026-09-19 17:20:53 +08:00
Tianyi Cui e90c55e0ab docs(session): distinguish converter support from target compatibility
The compatibility obligation belongs to the released target format.
An incoming converter can be fixed or support more historical inputs after
the target ships, as long as its output preserves that target's meaning.
Alpha releases may reject valid historical cases without an implemented,
evidenced mapping instead of expanding the format for speculative inputs.

Record the native-writer oracle, pre-normalization comparison, supported
flat V4 tool-result representation, uniform plugin naming, owner collision
rules, retained source files and read-only private corpus handling in the
migration cookbook. Align the existing architecture note with this rule;
keep native target changes and source conversion fixes distinct.

This updates contributor guidance only. It does not change finalization
checkpoint machinery, existing V4 schemas, or any released codec.
2026-09-19 17:20:53 +08:00
Tianyi Cui 1e7686b2c9 test(session): compare migration with raw native writer output
The ordinary snapshot comparator prepares both inputs through the current
format catalog. That can hide a writer still emitting an old tool-result
wrapper: both sides become the same normalized representation.

For the existing stock tool-call-turn replay, explicitly migrate its
retained V3 recording and compare result message fields with the freshly
harvested native log before format normalization. Check both generation
headers and remove only the generated message ID from this comparison.
Do not use the scenario's selected V4 successor as the migration input.

Add a negative control whose header claims the current writer while its
body keeps the V3 wrapper; the raw comparison must reject it. The same
shipped headless profile and stock bash tool provide the positive case.
Keep all recordings and their selected generations unchanged.
2026-09-19 17:20:53 +08:00
Tianyi Cui 0c8180c9b6 fix(session): preserve V3 result extensions in flat tool messages
The ordinary V3 writer records a user-role message containing one result
wrapper. V4 writes the same tool output directly in a tool-role message.
Keep that native V4 representation instead of introducing a nested message
content type for hypothetical historical shapes.

Preserve extra historical fields when removing the wrapper. Prefix outer
message fields with plugin:message: and result fields with plugin:result:
so equal names retain their original ownership and cannot overwrite the
interpreted call ID or error flag. Include the complete old name, even
when it is already prefixed, and preserve every JSON value and own key.
Only the validated wrapper supplies the interpreted result fields.

Leave unimplemented nested-result conversion as an explicit refusal that
preserves its source. Describe this as the converter's current limit, not
an impossibility or a reason to extend the established V4 format.

Cover owner/name collisions, opaque special keys, absent error flags,
unchanged sources and strict native reopening through plain and compressed
read/write persistence. No current message type or schema is added.
2026-09-19 17:20:53 +08:00
Tianyi Cui 869367d5d0 test(session): continue catalog backfill after unavailable evidence
Isolated complete/incomplete-child tests did not distinguish skipping one child
from prematurely stopping the entire candidate loop. A stop could therefore
silently omit a later child's fully supported catalog fact.

Pair a complete child with an older unavailable child so deterministic ordering
processes the unavailable evidence first. Cover missing, unsupported-version,
and multiple-descriptor evidence, requiring exactly the complete child's fact
with the correct sequence and timestamp.

A temporary continue-to-break mutation failed all three new cases. Restoring
the implementation passed the focused 19 cases and the complete selected owner
run: 428 passed, one compression-specific skip, with 100% coverage on facts.ts
and migration.ts. This commit changes tests only.
2026-09-19 17:17:29 +08:00
Tianyi Cui e838401a9b docs(session): state incomplete catalog evidence limits
The child-catalog README did not record the lasting missing-entry consequence
under Known Limitations, and its validation wording implied that duplicate or
unsupported descriptors had their discovery fields checked. The converter only
checks those fields when exactly one supported own descriptor is available.

Specify that distinction, retain creation-time checks for existing entries, and
state that current V4 reads do not rescan children to repair an omitted entry.
Document the first-descriptor composition reader and last-descriptor identity
projection accurately: multiple own records violate the establishing provider's
exactly-once rule, so the backfill policy does not choose between those consumer
policies. This corrects the rationale without changing migration admission.

Update the paired English/Chinese package docs and decision note together.
Validation: doc-sync 41/41, full lint, and owner tests passed; production source,
frozen generations, persistence schema, and recorded fixtures are unchanged.
2026-09-19 17:17:29 +08:00
Tianyi CuiandDudu-0223 ade7035fd8 fix(session): preserve parents with incomplete child catalog evidence
A readable V3 child may have no own descriptor, an unknown descriptor version,
or multiple descriptors. Those states do not provide a unique discovery fact,
but they do not make the parent or the retained child history unreadable.
Rejecting the entire parent prevented otherwise valid V3 Sessions from opening.

Append a missing parent catalog row only for exactly one supported own child
descriptor. Keep existing parent entries and every child record when no fact is
available. Retain rejection of mismatched creation times, unambiguous mode/label
conflicts, malformed known fields, unreadable membership and revision drift.

Cover raw and compressed read/write publication, preserved source bytes, late
descriptor availability, inherited descriptors and Preview packing. Document
that unavailable discovery evidence can leave a child absent from its parent
catalog and does not trigger automatic backfill after the V4 successor exists.

Extracts the child-evidence behavior from 7ba7e174dd1 and the Preview regression
from 9c85eb60bd25, preserving the original migration authors' work while keeping
message representation and extension interpretation outside this commit.

Co-authored-by: Dudu-0223 <[email protected]>
2026-09-19 17:17:29 +08:00
Tianyi Cui c6f6aa3293 fix(session): preserve V3 tool-schema metadata keys
The V3 writer on master declares and emits only name, description and
parameters. deferLoading is a first-class V4 persistence addition whose
provider behavior is not implemented yet. Prefixing every historical extra
ToolSchema key changes ordinary plugin metadata without a format need.

Preserve all ordinary tool-definition keys and JSON values unchanged,
including vendor metadata, own __proto__ properties, already-prefixed keys
and nested parameters. Remove the general key-renaming mapper. Reject only
an own top-level deferLoading field in V3 input: there is no established V3
meaning to translate, and the alpha converter may refuse unsupported source
forms rather than invent compatibility semantics. Leave native V4's
optional-true declaration, admission and provider refusal behavior intact.

The regression tests fail on the old mapper for metadata preservation and
unsupported-field refusal. Physical plain/zstd read/write tests verify source
bytes and identity remain unchanged and no V4 successor appears on refusal;
controls preserve nested parameters.deferLoading and native V4 true values.
No Session format/schema change, frozen codec edit, or historical recording
version bump is needed.
2026-09-19 17:15:38 +08:00
Tianyi Cui d5a109c60f fix(session): preserve direct V3 source kinds during wrapper conversion
Convert an unknown legacy plugin wrapper such as
{kind: 'plugin', plugin: 'acme'} into {kind: 'plugin:acme'}, retaining the
complete plugin name after one prefix. Keep the existing explicit
first-party producer renames and preserve all non-identity metadata.

A direct source already records its producer in kind. Reclassifying
unknown direct kinds into plugin:source:<name> needlessly changes that
attribution and forces plugin consumers to adopt new identifiers even
though V4 accepts their existing representation. Return every valid
direct source unchanged, including already-prefixed names. Remove the
obsolete direct-kind table and two-category identity helper rather than
adding collision classification or another mapping layer.

Update the source conversion examples, codec/restore regressions, and
native fixture producers together. Refresh only the owning Python
advanced scenario's unshipped V4 outputs; preserve historical V0-V3
recordings and their generation selection. Event names, content tags,
and ToolSchema migration remain separate concerns.

Refs #2692
2026-09-19 17:11:45 +08:00
imccyu cf3505b88e docs: call the package table the runtime resolution everywhere it is named
The generation note keeps generation for succession only and names the table, the interception, and the routes with the code's words; the CLI reference, Desktop, plugin-package-inventory, and loader-smoke READMEs, the bundled-runtime, agent-teams, plugin-bundles, and source-launch notes, and the client AGENTS guide follow. Pairing records re-recorded.
2026-09-19 17:06:35 +08:00
imccyu f7f22a6b48 refactor(boot): finish the interception vocabulary in code comments and the app-boot README
The Consumer-owned strictness bullet names the Loader subtree that agent presets own instead of the runtime resolution; the service field, its file comment, the dispose JSDoc, and the route JSDoc use interception; the native-after-interception route documents both anchors it can carry; stale module-fallback comments name the runtime resolution; importFromResolution matches its parameter.
2026-09-19 17:06:35 +08:00
imccyu b605d114bd docs(boot): finish the runtime resolution terminology in the generation and desktop notes 2026-09-19 17:06:35 +08:00
imccyu c0f34b4bcd docs(boot): name both installation anchor sources
The CLI derives the installation anchor from import.meta.url and the Desktop Host builds it from its runtime directory; neither is a symlink, so the installation root is kept as given. The note and the traversal comment say so instead of attributing every launcher to import.meta.url.
2026-09-19 17:06:35 +08:00
imccyu 06b0ff9560 docs(boot): describe the installation closure size without point-in-time counts 2026-09-19 17:06:35 +08:00
imccyu 058d1d779b docs(boot): keep the ancestor chain code block language neutral
The numbered chain lists directories only; the legend for ①-⑤ moves into prose so both language sides can read it while the code block stays byte-identical for the pairing gate.
2026-09-19 17:06:35 +08:00
imccyu 9848ac75f2 test(cli): explain the sandbox-unavailable acceptance in the source tool smoke 2026-09-19 17:06:35 +08:00
imccyu 048fc3e580 docs(boot): state that the installation anchor is already a real path
The lookup-order note records that the launcher derives the installation anchor from import.meta.url, so bundle discovery and dependency traversal start from the same real directory.
2026-09-19 17:06:35 +08:00
imccyu 15e07d2721 refactor(boot): rename the profile resolution generation to the runtime resolution
RuntimeResolution, RuntimeResolutionEntry, RuntimeResolutionOptions, and createRuntimeResolution replace the generation-named table types; installRuntimeInterception returns a RuntimeInterception; PluginPackages takes { resolution }; Worker environment data carries { resolution }; routes are native, interception, and native-after-interception. replace() keeps its successor-generation wording.
2026-09-19 17:06:34 +08:00
imccyu 5f48b2fff6 docs(boot): call the package table the runtime resolution
Notes and the app-boot README name the startup package table the runtime resolution and the installed hook the interception; generation remains the word for the additive successor semantics of replace().
2026-09-19 17:06:34 +08:00
imccyu bffd317c8c Merge pull request #4570 from deepseek-harness/worktree-removelink
fix(boot): keep runtime-only profile resolution and real package anchors
2026-09-19 17:04:22 +08:00
Yifffan a30f3a68c8 Merge pull request #4509 from deepseek-harness/feat/macos-sidebar-ui-and-drag-refine
feat(client): frame-owned macOS window chrome with single drag owner
2026-09-19 16:58:41 +08:00
imccyu 109efc7942 test(boot): cover the projection removal edge cases
A profile with the legacy directory but no node_modules, and a symlink whose target parent is gone, exercise the remaining branches of removeLinkProjections; the non-ENOENT realpath failure is a host filesystem fault and is excluded from coverage like its siblings.
2026-09-19 16:49:21 +08:00
Yif 9c48e74409 test(web): capture sidebar snapshots after the track-easing gate settles
The columnTransition probe raced data-animating's transitionend/600ms
settle: checkpoints recorded whichever side of the window the capture
landed on. Waiting for the attribute to drop pins the steady state —
no declared transition (computed 'all') — deterministically.
2026-09-19 16:39:47 +08:00
Yif 45d77b0e8e fix(ui-theme): match the scrollbar sheet exclusion against /-separated scan paths 2026-09-19 16:39:46 +08:00
imccyu 02fec3209e fix(boot): remove link-backend profile projections on profile load
removeLinkProjections unlinks the symlinks under a profile's node_modules whose target lies inside <profile>/.dsh-module-fallback/node_modules and then removes that directory; pnpm-installed packages and every other symlink stay. loadProfile and the Desktop applyRelease call it once per launch. Regression: with bundle A installed but deselected and bundle B selected, B's same-named plugin resolves instead of A's projected copy.
2026-09-19 16:34:07 +08:00
imccyu 0c342a81c4 docs(boot): record the one-time removal of link-backend profile projections
The lookup-order note, the cleanup-removal note, and the app-boot and Desktop READMEs state that profile load removes the .dsh-module-fallback projections the dsh 0.1.5 releases wrote into a profile, so a deselected bundle's projected plugin no longer shadows the same-named plugin the generation selects from another bundle.
2026-09-19 16:34:07 +08:00
Yif 9e95a7b183 fix(client): keep fullscreen sidebar strips draggable via fine-grained dockkit subtraction
Drop the fullscreen panel's whole-box no-drag: it swallowed the strips'
blank-run window drag and made no-drag the steady state, turning the
open/close app-region nudge into a computed-value no-op (electron#32341)
exactly when a hidden panel opens straight into fullscreen. The panel now
declares no steady-state app-region in either presentation, and ui-dockkit
subtracts the one box base.css never matches — the plain-div split divider —
alongside tabs, strip-end chrome, and pane bodies. New specs pin both
contracts against the stylesheets on disk.
2026-09-19 16:19:44 +08:00
Yif c6c1df6869 fix(ui-theme): normalize stylesheet-scan paths to forward slashes for Windows 2026-09-19 16:19:34 +08:00
Yichen Jiang 72d5194ce4 test(settings-models): drop an unnecessary JsonValue assertion in the add-card spec 2026-09-19 16:10:26 +08:00
Yichen Jiang f7fe7a1060 test(docs): re-record the translation prompt after the model-provider terminology rows 2026-09-19 16:08:17 +08:00
Yichen Jiang 7d06fcdc05 fix(settings-models): derive the add panels, lock the switch in flight, pair tabs with panels
The add card's panels are now derived from the shown mode and the modes
visited since it opened, and each renders only while its mode is still
offered, so a refresh that changes which modes are offered — every
configurable row gone, the pi-ai namespace unmounted, a route freed
after the catalog was exhausted — can neither leave the card without a
panel nor keep a form whose write the Host would refuse. The catalog
draft resolves to the chosen row while its namespace can take the
write, else to the first addable row; closing either panel forgets it,
so a later refresh cannot open a row editor unasked.

Both cards report a write or an endpoint interrogation in flight, and
the switch and the catalog select lock while one is, since a switch
underneath it would orphan the answer or the picker it opens. The
SegmentedControl takes the owner's id and pairs each tab with its panel
through `aria-controls` and `aria-labelledby`; a card offering one mode
carries that mode as its title instead of an orphan tabpanel, and a
locked segment names its reason as hover text. `fullWidth` goes: no
consumer asked for it.
2026-09-19 16:04:34 +08:00
Yichen Jiang 536a94b188 fix(settings-models): exact Models nav locators, scoped vendor term, review nits
The new "添加模型提供商" button shares a prefix with the Models nav entry,
so every e2e that clicked the nav through a non-exact locator resolved
two buttons once the page rendered; the nav locators are exact now.

The vendor sense of "provider" is registered in the terminology table
as 模型提供商 with its scope — the Models settings copy, the providers
user guide, and this package's README — while the generic provider rows
keep 提供方, and the package's Chinese README uses the vendor term
throughout. The custom card's header comment no longer claims a mode
switch that a custom-only card does not render, and the SegmentedControl
suite gains a positive Home/End case whose first enabled option is not
the first option.
2026-09-19 15:48:10 +08:00
Tianyi Cui ec2c4f2a42 test(session): isolate vocabulary fixture Git commands from caller paths
The new vocabulary fixture helper set cwd to a private repository but still
inherited GIT_DIR, GIT_WORK_TREE and GIT_INDEX_FILE. A negative control with
two disposable repositories demonstrated that git add/commit changed the
foreign repository's HEAD instead of the intended fixture repository.

Remove only those three location variables from the child environment.
Leave the caller's environment untouched and retain the existing identity,
hook and signing overrides. The regression checks the foreign HEAD and work
tree remain unchanged while the intended target commits its private file.
This is confined to the test helper; it adds no production Git abstraction
or Session-format behavior.
2026-09-19 15:43:10 +08:00
Tianyi Cui 696aa5f97c docs(session): describe retained source kinds by historical admission
The preserved direct-source set is the predecessor migration's accepted set
without the plugin wrapper. It includes older coordinator and subagent-report
identities even though those names have no current producer declaration.
Describe that historical admission fact instead of implying every retained
identity has a live V4 owner. No mapping or runtime behavior changes.
2026-09-19 15:43:10 +08:00
Tianyi Cui 4d9c4e7a12 fix(session): reject retired tool results in V4 Team checkpoints
Central V4 event admission already rejects tool-result content in Team
queue records, but projection checkpoints use the Team state schema directly.
After restoring the baseline Team parser during extraction, the production
SessionProjectionRegistry.restore() path accepted a decoded native V4
checkpoint containing the retired wrapper without reading an event.

Remove only that V4-incompatible schema arm. Keep the existing unknown-JSON
parser unchanged; its independent own-key preservation fix remains in the
standalone master PR, where recursive V3 tool results are still valid.

Exercise the real checkpoint restoration recipe with a valid text state and
an invalid retired-result state, plus queued-event projection. The new
checkpoint rejection failed before this change; central event admission and
the complete Team owner suite pass afterward with 100% projection coverage.
No Session schema, format version or projection state version is changed:
the rejected value is already outside the native V4 content vocabulary.
2026-09-19 15:43:10 +08:00
Tianyi Cui 88897a16c6 refactor(session): separate Team opaque JSON preservation from migration
Retaining own keys in the Team projection/checkpoint parser fixes a generic
JSON reconstruction defect. It is independent of V3-to-V4 identifier
conversion and can be reviewed directly against master, where recursive V3
tool-result content is still valid.

Restore the Team implementation, tests and paired README to this layer's
parent after the standalone owner captured the exact delta from 85737364be9.
The standalone port retains V3 validators and applies only the non-cloning
unknown-JSON repair. Migration content handling for team/message/queued and
all approved namespace, delivery and source-admission rules remain intact.

This removes an independent runtime/parser policy from the format stack;
it does not change any Session schema, codec, version or stored source file.
2026-09-19 15:43:10 +08:00
Tianyi Cui d5302e33f8 refactor(session): separate attachment carrier policy from V4 migration
The event-type allowlist and opaque-payload attachment policy change live
Session authorization/export behavior independently of a format upgrade.
They belong in a focused PR against master, where supported native V3 nested
tool-result content must also be handled deliberately.

Restore the session-controller and archive implementation, tests and README
pairs to this layer's parent. Remove the test-only session-format-catalog
dependency and its lock entry with the migration-specific attachment tests.
The original changes are captured from immutable commit 85737364be9 for the
standalone work; migration identifier conversion and reader checks are intact.

This extraction keeps the integration stack's existing attachment behavior
until the separate policy change is reviewed. It makes no Session-format,
schema or version change.
2026-09-19 15:43:10 +08:00
Tianyi Cui 11ef33b336 fix(session): reject unknown required V3 events before target interpretation
The physical V3 codec admits an unclassified event envelope without deciding
whether its type is required. The V3-to-V4 stage then used shared message
walkers and target vocabulary, so an invalid required developer/message could
acquire the V4 developer role although historical V3 restoration rejects it.
Generic required unknown events were also left to the wrong version's reader.

After preserving explicitly ignorable extensions, require every remaining
source type to belong to the fixed V3 vocabulary before interpreting payloads.
This is a fail-loud check for invalid or nonconforming source data, not new
compatibility handling for third-party events, which carry ignorable:true.
The approved plugin identifier conversion and native V4 readers are unchanged.

Exercise a complete developer-event sequence through direct migration,
historical/current catalogs, ignorable conversion and native V4 restoration;
add a generic unknown type. Both negative controls accepted the invalid source
before this guard. Plain/zstd read/write regressions verify refusal preserves
the source generation and never publishes a partial V4 successor.
2026-09-19 15:43:10 +08:00
Tianyi Cui fc74dbf4ea fix(session): limit delivery migration checks to the V4 target
A V3 delivery marker claiming generation 4 would become active when its
header advances to V4. The integration baseline already refused that case.
Renaming every higher-generation marker instead introduced a general
conversion policy for future formats that this V3-to-V4 edge does not own.

Restore the targeted generation 4 refusal. Keep other delivery event names,
payloads and coordinates unchanged, including generations 5 and 99, which
remain inactive in V4. Their future activation checks belong to a concrete
later format edge. Preserve the separate plugin-event identifier policy.

Cover read/write opens for both plain and zstd storage: target-generation
refusal preserves source bytes and publishes no successor, while later
markers survive V4 publication and native reopening unchanged. Update the
snapshot-normalizer cases and document the alpha converter coverage limit:
unsupported histories may fail without source mutation, and later converter
fixes may expand support without a new version when V4 output stays compatible.
2026-09-19 15:43:10 +08:00
Tianyi Cui 28b209867f fix(session): preserve historical stream-start extension field names
V3 and V4 declare the same block-start fields: type, index and blockType.
The migration's identifier policy can qualify an extension blockType, but
prefixing every additional field has no current V4 field collision to solve.
That rewrite changed captured keys to anticipate hypothetical future fields.

Retain every non-blockType field and value exactly, including already
prefixed names and own JSON keys. Keep the approved blockType identifier
prefix and the separate ToolSchema field policy unchanged. Update the local
conversion tests to verify both known and extension starts retain metadata
and to use the actual raw-record time field. Later field-specific conversion
belongs to a concrete source/target change instead of this edge.
2026-09-19 15:43:09 +08:00
Tianyi Cui 2833ff566e test(session): expect prefixed V3 opaque event identities on JSONL open
The JSONL retired-content admission matrix covers both historical V3 input
and native V4 input across read/write and plain/zstd storage. V3 migration
now prefixes unknown ignorable event identities with plugin:, while native
V4 reads retain their stored identity. The shared expectation still required
the unchanged V3 event tag and caused four deterministic CI failures.

Select the expected event type by input generation while retaining the full
payload, envelope, and immutable source-byte assertions. This corrects the
test for the intended migration without weakening native admission or
changing runtime behavior. The focused 20-case matrix now passes; restoring
the old expectation reproduces the same four failures locally.
2026-09-19 15:43:09 +08:00
Tianyi Cui bf29247fad fix(session): namespace historical V3 extensions with plugin prefixes
V3 permits external event, source and content identities and additional
request-tool fields. Copying those values into V4 can give an old plugin
named tool a core source identity, turn old tool-addition content into a
registry instruction, or activate formerly ignored deferLoading and delivery
metadata. Rejecting such collisions would instead refuse valid source logs.

Keep historical extensions in the existing extensible JSON representation.
Prefix unknown content and ignorable event tags with plugin:, preserving
all other content fields and opaque event payloads. Prefix external source
identities with plugin:plugin: or plugin:source: so wrapper and direct kinds
cannot collide even when original names already contain a category prefix.
Known first-party mappings remain explicit and unchanged.

Prefix extra request-tool field names and block-start field names with
plugin:, retaining exact values and existing-prefix doubling. Core schema
parameters, arguments, replay state and nested plugin data are not traversed.
Keep future-generation delivery records inactive after header promotion.
Pin the V3 event vocabulary independently of the current writer and provide
an offline verifier against an explicitly selected historical source commit.

Attachment authorization and export inspect declared event content only.
Team checkpoints preserve all own keys of unknown JSON blocks while still
rejecting malformed known content and retired core tool-result blocks.
Exercise physical read/write/reopen, prefix injectivity, own __proto__ keys,
provider opacity and retained source-identity snapshots.

No generic extension block, metadata wrapper or new schema-tooling type is
introduced. V4 type declarations, persistence schema, checkpoint and frozen
V0-V3 codecs remain unchanged. Canonical tool-result lifting and incomplete
child-catalog policy remain separate concerns.

Adapted from the extension-preservation work in 7ba7e174dd1 by Tianyi Cui.
Co-authored-by: Tianyi Cui <[email protected]>
2026-09-19 15:43:09 +08:00
Tianyi Cui cc970738d8 docs(session): scope checkpoint JSON preservation to domain reads
The cache reader preserves opaque JSON keys, but each projection still
parses the returned checkpoint through its own stateSchema before hydration.
State that ownership explicitly so documentation does not imply this reader
fix also changes projection-defined transformations or cloning behavior.

Distinguish the synthetic V7 StorageDomain regression fixture from released
cache archives. Describe its read, put and reopen path directly, and group
its JSON validation checks separately from archived-version recovery.
Translate the Chinese Agent Note headings and keep the paired docs aligned.
The note retains the borrowed-value tradeoff and links the independent
predecessor-format and lifecycle-identity decision.

Production expressions and all test assertions remain unchanged; only
contracts, fixture descriptions, test labels and grouping are clarified.
The fix does not add another persistence format or broaden migration scope.
2026-09-19 15:43:09 +08:00
Tianyi Cui df0145271d fix(session): preserve opaque checkpoint keys on domain reopen
The projection-cache writer preserves lossless JSON, including own keys named
__proto__. The z.json reader rebuilds objects and drops those keys, so opening
the same stored checkpoint can produce state different from Session replay.
This affects embedded result metadata and opaque extension payloads as well
as other projection state.

Validate with the existing isJsonValue predicate used by the writer's
snapshotJsonValue rules. It rejects non-JSON and lossy values without
rebuilding valid borrowed records. Keep the stored representation and domain
version unchanged: this is a reader correction, not a new cache format.

Exercise a fixture captured through the actual pre-fix writer with a real
StorageDomain open, rewrite, close and reopen. Preserve nested prototype-named
keys and retain negative coverage for invalid JSON values. Document why this
validation matches the storage-domain immutable borrowed-value contract.

Use neutral arbitrary JSON in the new opaque-state fixture so this reader
regression stays independent of Session message representation. Its own
prototype-named keys and nested arrays are unchanged in purpose. Confirm
the fixture matches the pre-fix StorageDomain writer output and that the
old z.json reader fails its key-preservation assertion. No released Session
recordings or historical cache fixtures are edited.
2026-09-19 15:43:09 +08:00
Tianyi Cui d7e523b8b8 perf(session): traverse stored JSON arrays by index
Cold current-generation reopen freezes the complete decoded event graph
before publishing shared-frozen history. Compact assistant streams carry
125,000 text values and 124,600 time deltas in the required benchmark;
for-in traversal enumerates their array indexes as string property keys.
An open-only profile attributes about 4.2 ms to complete event freezing.

Use numeric indexing for arrays produced by JSON decoding and the fixed
migration catalog. Those arrays contain indexed JSON values only. Keep
every Object.freeze call and every nested-object visit, preserve the
object-key path including own __proto__ and constructor data, and never
infer deep immutability from a shallow Object.isFrozen result. No decoding,
admission, relationship validation, or freezing moves past open().

The unchanged five-sample V4 reopen median falls from 22.6 to 17.7 ms on
M4 Pro / Node 24.19. Restoring and rebuilding the exact old traversal gives
21.7 ms. First-history and resume also improve; Agent retained heap stays
4.5 MB and every 128 MB case completes. Keep the existing 63 ms gate,
fixture dimensions, cold-process setup, and all other budgets unchanged.
Local measurements establish removed work; hosted CI remains the required
runner verdict.

Cover nested opaque arrays and objects, special JSON keys, rejected
mutations, and shared event identity through historical V3 and native V4
reads. Record the before/candidate/restored samples and the local-versus-CI
limit in the existing performance note.
2026-09-19 15:43:09 +08:00
Tianyi Cui 1613a10c03 merge: integrate pinned master into session-log-v4
Merge master 7e2b049d8e2523127a3b4fba38cab4748ef0c72f, observed on
2026-09-19 at 07:38:37 UTC, into release/session-log-v4 at
c4663e8671e33bc2cfdbc868b0b18d979508d39b. Keep this base integration
separate from the five persistence repair PRs so their review diffs
remain focused and can be rebased without moving their fixes here.

Combine master's pin ordering and archived-session filter with V4's
parent-owned direct child catalog. Both grouped and flat sidebar rows
must pass the Session list to the V4 activity calculation; restoring
master's summary-lineage traversal would reintroduce the removed
subagent ownership and count unrelated descendants.

Keep master's removal of the archived-session settings page. Its only
release-side test change renamed a Session list fixture field, so no
runtime behavior is lost by deleting that obsolete test. Adapt the
release-side direct-child-status regression to the new row/filter
arguments and preserve its assertions.

Retain master's workspace ordering and row-motion documentation while
keeping the V4 child-catalog wording. Reconcile the generated bilingual
records against the merged documents. Frozen V0-V3 codecs, recorded
Session JSONL inputs, and the current V4 persistence schema are unchanged.

Refs #2692, #3273
2026-09-19 15:42:11 +08:00
Yif 699d06a7eb feat(client): widen overlay top margins to the frame's top clearance
Publish --dsh-frame-top-clearance on html[data-platform='darwin'] so
body-portalled overlays inherit it; useAnchoredMaxHeight and the portalled
Menu widen their 12px viewport margin to it, Modal centralizes the vertical
padding its cards previously each computed, and the trigger menu keeps an
84px margin on every platform so it stops below the conversation header.
Reduce Transparency replaces the sidebar tint with a 90%-opaque fill.
2026-09-19 15:37:47 +08:00
imccyu 45417197c6 refactor(boot): name routes and collectors after the interception layer
Resolution routes are native, generation, and native-after-generation: Node keeps the importer's lookup, answers from the generation entry at the interception layer, or resumes its chain at that layer. The profile module collects installation-scope and profile-scope packages and reads package manifests under those names; the generation types describe the interception layer instead of a fallback table.
2026-09-19 15:34:09 +08:00
imccyu f34f8ef04d docs(boot): name the native lookup after the generation in the generation note 2026-09-19 15:34:09 +08:00
imccyu 82337a2e71 test(boot): canonicalize temporary roots with the native realpath
Windows tmpdir spells the user directory with an 8.3 short name. Generation anchors and Node's own resolution report the long name, so the resolver, generation, and real-launch fixtures now create their roots through realpathSync.native and compute expected paths the same way.
2026-09-19 15:19:32 +08:00
Yichen Jiang 8a320a276b feat(settings-models): one add entry with third-party and custom-API modes
The Models page offered two side-by-side buttons, "Add provider" and
"Add a custom provider", which asked a new user to classify their
provider by an implementation fact — whether it is in the installed
pi-ai catalog — before seeing anything. One "Add model provider" button
now opens one card whose segmented mode switch chooses between a
third-party model provider (the catalog select over the provider
editor) and a custom model API (the create form for a relay, a
self-hosted server, or any other OpenAI- or Anthropic-compatible
endpoint), with a one-line purpose beneath the switch. A panel mounts
the first time its mode is shown and stays mounted, hidden, while the
card is open, so switching modes discards neither draft.

A mode is offered only while its namespace is mounted and disabled
while it has nothing to offer, which keeps the old per-button
availability; with one mode the card shows that form alone. The
protocol pickers name each protocol by its product name while the
stored value stays the schema identifier, and an unnamed protocol shows
that identifier. The Chinese copy of this page calls a provider 提供商
throughout.

The e2e scenarios drive the single entry and its custom-API mode, and
the ARIA goldens that carry the page copy are re-recorded. The user
guide describes the one entry with fresh screenshots in both languages.
2026-09-19 15:14:52 +08:00
Yichen Jiang 6840878bf2 feat(ui-primitives): add SegmentedControl
A tablist of two or more equal-width segments with one sliding
indicator, for switching a card or panel between a few mutually
exclusive modes. The owner holds the selection; `label` names the list
and every segment label is owner-localized. Arrow keys, Home, and End
walk the enabled segments with a roving tabindex, and the keyboard
follows the selection once the owner adopts it.

Segments are equal grid tracks sized to the widest label when the
control hugs its content, which is what lets the indicator be placed
arithmetically from the segment count and selected index rather than by
measuring the DOM. The indicator draws its stroke inside the soft
elevation shadow, as every elevated surface does.
2026-09-19 15:14:37 +08:00
imccyu 03e3a3bca0 refactor(desktop): note the runtime descriptor validation in applyRelease
applyRelease keeps readDesktopRuntime for its fail-loud validation after the cleanup consumer was removed.
2026-09-19 15:06:26 +08:00
imccyu 1c806e5a16 docs(desktop): record the profile cleanup removal
A simplification note records why production Desktop no longer cleans core-package copies out of the profile, keeps the 2026-09-15 motivation and rejected alternatives, and names the capability given up and the reintroduction conditions; the superseded 2026-09-15 note is consolidated into it. The bundled-runtime note drops its cleanup qualification paragraph, and the Desktop README describes launch preparation without the cleanup step.
2026-09-19 15:06:26 +08:00
Tianyi Cui fe46abc02f Merge pull request #4594 from deepseek-harness/worktree/guard-ci-bubblewrap-pin-20260919
test(ci): reject prunable Ubuntu bubblewrap URLs
2026-09-19 15:03:37 +08:00
imccyu 71c7f6cc09 refactor(boot): name the interception layer parent and note intentional anchors
routeScoped names the profile parent whose node_modules is the interception layer. The installation traversal records why the installation root keeps its caller-supplied directory and why generation construction keeps its Promise return type.
2026-09-19 14:39:45 +08:00
imccyu 0e2097ac18 docs(boot): describe the interception layer in the generation note and README
The generation note and the app-boot README no longer claim that runtime lookup hides the shared position or recognizes profile projections: generation entries occupy their package names at $DSH_HOME/profiles/node_modules and every other name sees that directory as an ordinary ancestor. Pairing records re-recorded.
2026-09-19 14:39:44 +08:00
Huanqi Cao 08217140b8 Merge remote-tracking branch 'origin/master' into fix/windows-acl-delete-escape 2026-09-19 14:31:47 +08:00
imccyu 81b6934804 docs(boot): add the English lookup-order note and refresh the wrapper note
Translate the profile lookup-order Agent Note section for section and record its pairing. The desktop-web-wrapper note names the runtime resolution generation instead of module fallbacks and drops the one-time desktop-runtime-state cleanup that no longer exists.
2026-09-19 14:28:07 +08:00
Huanqi Cao 7201569aef docs(config-catalog): carry the source-line refresh to the zh pair
The generated catalog is a bilingual pair, so the regenerated English side
must be brought over with its Chinese counterpart before the pairing record
is re-written.
2026-09-19 14:17:59 +08:00
imccyu d71b8a2f1c refactor(boot): narrow legacy-links exports and refresh resolution JSDoc
isPackagedExecutable has one caller in its own module; the installation traversal comment names the runtime resolver instead of the removed fallback directory.
2026-09-19 14:12:02 +08:00
Yif a80f5186a6 Merge remote-tracking branch 'origin/master' into feat/macos-sidebar-ui-and-drag-refine 2026-09-19 14:05:21 +08:00
Huanqi Cao 85724fb5b0 docs(config-catalog): refresh the sandbox-local Config source line
The comment edit in sandbox-local/src/index.ts moved the Config block from
line 44 to 45, and the generated catalog records that line.
2026-09-19 14:05:18 +08:00
Huanqi Cao 4753e45f95 test(sandbox): probe cmd's own > NUL redirection
The CI Windows runner reports an empty \0 for a PowerShell-level
'>nul' redirection around the cmd call, and PowerShell's '>nul' opens a file
named nul rather than exercising cmd's redirection. Pass the whole command
to cmd so it parses '>NUL' itself and prove it with cmd's own output.
2026-09-19 13:54:48 +08:00
Yif de74a45f60 feat(desktop): raise the main window minimum width to 520 2026-09-19 13:42:52 +08:00
Yif 3f7a209835 revert(ui-primitives): drop the tooltip pointer-focus suppression 2026-09-19 13:42:50 +08:00
Huanqi Cao 3d5ba3b83f fix(sandbox): scope the delete deny to containers, clearing the review round
The inheritable `Deny Everyone FILE_DELETE_CHILD` also reached FILES, and
0x40 is a member of FILE_ALL_ACCESS: measured against a real runner, a
Medium caller's CreateFileW(GENERIC_ALL) on every file, directory, and temp
root inside a granted root returned ACCESS_DENIED. The deny now carries
CONTAINER_INHERIT_ACE, so files keep working; a FullControl open of a
DIRECTORY inside a granted root stays denied and is pinned as the residual
cost of denying a right the full-access mask contains.

Also from the review:

- Leaks on fail-closed paths: the label ACL on both early SetEntriesInAclW
  exits, the read descriptor when the label build fails, and the parsed
  capability SID when either well-known-SID creation fails.
- `revokeWrite` keeps the shared Low label while another capability grant
  remains on the directory, so two grants on one path stay independently
  revocable; `hasExactLabel` delegates to hasExactEntry.
- The delete probe uses process.execPath, restrictTokenIntegrity guards a
  zero-length SID, and verify/abi-probe.cpp covers the new constants
  (compiled; static_asserts pass).
- Consumers updated in the same change: sandbox-local source comments and
  README pair, pwsh-sandbox README pair, docs/subsystems/sandbox pair, and
  the 2026-07-06 sandbox note pair no longer cite the Everyone-write
  boundary as a current partial reason.
- New Agent Note records the mandatory-integrity decision, the deny scoping,
  the standing label with its externality (other Low-integrity processes
  running as the user, surviving the session), and the rejected
  alternatives; the 2026-08-08 note cross-links it.
- New runner pins: NUL stays writable under the Low token, the FullControl
  file/directory split, and the shared-label revoke. Per-file coverage back
  to 100%.
2026-09-19 13:42:47 +08:00
Yichen Jiang ff3d162401 Merge pull request #4600 from deepseek-harness/worktree/fix-markdown-preview-images
fix(web): render local images in Markdown previews
2026-09-19 13:31:42 +08:00
Yif c8e3cb2b87 test(web): track breadcrumb text crumb and shell.leading seat in e2e and goldens 2026-09-19 13:31:41 +08:00
imccyu 938b62c0aa refactor(desktop): drop link-era profile cleanup
Remove cleanProfileCorePackages and migrateDesktopProfileLinks with their specs; applyRelease keeps runtime validation, settings migration, and profile creation. A regression pins that installed packages, declarations, legacy state, and the lockfile survive a launch.
2026-09-19 13:29:13 +08:00
imccyu a311386983 test(cli): cover shared-layer packages in real profile launches
The src/lib x installed/npm-link fixture adds a stale @deepseek-ai/dsh-tools link in profiles/node_modules, a plugin dependency absent from the generation with nested external leaves, and byte-for-byte preservation of profile files and link targets.
2026-09-19 13:29:13 +08:00
imccyu 6f57030958 fix(boot): occupy the interception layer instead of hiding it
The generation stands in for $DSH_HOME/profiles/node_modules/<name> only for names it carries; other names see that directory as an ordinary ancestor. The interception layer is the first ancestor node_modules above the importer's profile directory, so application-owned profiles follow the same rule. Stale .dsh-module-fallback projections are ordinary symlinks: their shape recognition leaves the resolver, the local package names, and the bundle dependency traversal.

The resolver spec gains a table-driven matrix over importer, package kind, ancestor layers, and directory or symlink form, with readable fixture names.
2026-09-19 13:29:13 +08:00
imccyu db831733da docs(boot): record the profile lookup order and interception layer
Add the Chinese Agent Note describing profile resolution as Node's ancestor node_modules chain with the generation occupying the package directories at $DSH_HOME/profiles/node_modules, the ESM/CommonJS, web/desktop, and npm-link scenarios, and the developer onboarding guide.
2026-09-19 13:29:13 +08:00
imccyu 518c7a604b fix(boot): preserve runtime fallback precedence 2026-09-19 13:29:13 +08:00
imccyu fcc6cc8c12 docs(boot): align runtime-only resolution contracts 2026-09-19 13:29:13 +08:00
imccyu 0bac274273 test(cli): run source tool smoke after build 2026-09-19 13:29:13 +08:00
imccyu 4b79c744ab docs(cli): clarify source smoke build prerequisites 2026-09-19 13:29:13 +08:00
imccyu 6d8aac066d fix(boot): resolve profile dependencies from real package directories 2026-09-19 13:29:13 +08:00
imccyu 4b9141a89e docs(boot): document runtime-only profile resolution 2026-09-19 13:29:13 +08:00
imccyu 9fd0a5ad52 refactor(boot): keep runtime-only profile resolution 2026-09-19 13:29:13 +08:00
Yif 8f2f13bc48 Merge remote-tracking branch 'origin/master' into feat/macos-sidebar-ui-and-drag-refine 2026-09-19 13:26:16 +08:00
imccyu bd2247c510 Merge pull request #4505 from deepseek-harness/feat/session-pin-archive
feat(workspace): 会话置顶与侧边栏归档筛选
2026-09-19 13:25:57 +08:00
Yichen Jiang 7951cee0d5 fix(web): render local images in Markdown previews 2026-09-19 13:21:37 +08:00
Huanqi Cao 688d7b694b test(sandbox): drop the host-dependent whoami integrity assertion
whoami /groups reports the mandatory label on this workstation but produces
no matching line on the CI Windows runner, so the assertion pinned the host
rather than the product. The lowered integrity level stays covered by the
unit pin on restrictTokenIntegrity and by the behavior that only holds with
it: the Everyone-Modify denial, the outside-delete denial, and the
cross-root delete denial. README records the cmdlet as host-dependent
diagnostic noise again.
2026-09-19 13:05:01 +08:00
imccyu 7e4045c4c0 test(client): align sidebar interactions and browser snapshots 2026-09-19 12:54:14 +08:00
imccyu 7baccf5d85 fix(workspace): unify pin IDs and preserve complete session order 2026-09-19 12:54:13 +08:00
imccyu f1e06a69ef fix(ui-primitives): preserve toast lifetime across rerenders 2026-09-19 12:54:13 +08:00
imccyu 842bf71350 perf(workspace): replace auto-animate with scoped row motion 2026-09-19 12:53:24 +08:00
Yichen Jiang 320e961122 test(jobs): refresh background tool snapshot headers 2026-09-19 12:22:46 +08:00
Tianyi CuiandLegGasai 766e6f9176 test(ci): reject prunable Ubuntu bubblewrap URLs
The merged dependency repair in #4589 uses a recorded Launchpad build,
but #4591 also requires a regression guard against restoring the live
Ubuntu package pool. Those pool URLs disappear when versions are
superseded, even when the content digest is pinned.

Adapt LegGasai's URL guard from closed PR #4590 to the build-specific
endpoint that landed in #4589. Check the endpoint structure without
copying the current build number, version, or checksum into the test,
and reject Ubuntu pool downloads anywhere in the script so adding a
pool fallback cannot bypass the guard.

Negative controls restore the original archive URL and inject security
and ports pool fallback URLs; each fails the new guard. The original
script is restored byte-for-byte before all 44 workflow tests pass.
This adds only a static regression test, with no network calls or
changes to the download script or CI execution behavior.

Co-authored-by: LegGasai <[email protected]>
2026-09-19 12:08:11 +08:00
Yif 34d78d843d feat(workspace): restore the hover title reveal with an 8px jitter floor
Hovering a session row again scrolls a clipped title to its far edge
(the #4423 reveal), but overflow of at most 8px stays put so barely
clipped titles do not jitter. The hover mask fade yields back to plain
clipping — at the scrolled extent the fade would cover the revealed
tail. Row action buttons tighten from gap 12 to 10.
2026-09-19 12:04:07 +08:00
Yif 1d221f9723 fix(workspace): end-aligned action tooltips, slower hover cards, archived-row alignment 2026-09-19 12:04:07 +08:00
Yif 9ca19474ab fix(workspace): tooltip the row hover actions and open the sliders glyph 2026-09-19 12:04:07 +08:00
Yif 94c62ea564 fix(client): draw the sidebar new-chat glyph at the regular weight 2026-09-19 12:04:07 +08:00
Yif 5474efe890 fix(client): lighten the ellipsis glyph and adopt the Toast success tone 2026-09-19 12:04:07 +08:00
Yif bd0461c894 fix(workspace): give the compact-label row spec the pin/archive props 2026-09-19 12:04:07 +08:00
Yif 3e96ed79a7 fix(workspace): steady hovered session titles and polish the sidebar controls
Hovering a session row no longer scrolls its clipped title (the mask fade
stays), the one-time archived-filter callout and the content-search
unavailable notice are gone, the group-row new-session button shares the
new-chat glyph, and the view-options trigger uses the two-slider icon with
a 200px menu floor and a visible separator hairline.
2026-09-19 12:04:07 +08:00
Yif 33d496951c feat(workspace): session pinning and the sidebar archived filter
Pin sessions to the top of the sidebar and reach archived sessions
through the view-options filter instead of a settings page; archiving
gains an undo/filter toast, and row motion stays reserved for pin jumps
and archive fades.
2026-09-19 12:04:07 +08:00
Tianyi Cui df65ea84ee Merge pinned master 386ed6b6 into session-log-v4
Include the user's merge of #4589 so Linux CI uses the available, verified
Ubuntu bubblewrap 0.12.0 build instead of the pruned 0.9.0 archive URL.
The user explicitly authorized this CI-prerequisite refresh without waiting
for the ordinary hourly master-following interval.

Preserve the reviewed upstream commit and exact one-file patch. The recorded
Launchpad build URL, checksum, extraction and namespace probe match #4589,
whose supported Ubuntu 24.04 preparation and execution checks passed. Bash
syntax and merge whitespace checks pass; no product runtime, Session format
or snapshot generation changes are introduced by this merge.
2026-09-19 12:01:04 +08:00
Yichen Jiang 37b31ba0d4 Merge branch 'worktree/jobs-api-review-3052' into worktree/jobs-api-review-3127 2026-09-19 11:58:57 +08:00
Yichen Jiang 8eb96113c7 Merge remote-tracking branch 'origin/master' into worktree/jobs-api-review-3052 2026-09-19 11:58:01 +08:00
Tianyi Cui c167f6d3e0 Merge pull request #4589 from deepseek-harness/worktree/fix-ci-bubblewrap-012-20260919
fix(ci): pin a compatible bubblewrap 0.12.0 build
2026-09-19 11:55:07 +08:00
Tianyi Cui 32ec78c79e fix(ci): pin a compatible bubblewrap 0.12.0 build
Ubuntu removed the superseded 0.9.0-1ubuntu0.1 payload from its live
archive pool, so the shared Linux CI preparation step fails with HTTP
404 before tests start. Address Ubuntu's recorded Launchpad build so
future pool pruning does not invalidate the pinned download location.

Select upstream's 0.12.0 security release for CVE-2026-87766 instead of
Ubuntu's isolated 0.9.0 backport, whose regressions and support limits
are documented by upstream in Launchpad bug 2166359. Keep checksum
verification, direct extraction, and the existing namespace probe.

Verify build 33546835 against its published SHA256 and archive SHA512.
Its amd64 ELF requires at most GLIBC_2.38 and x86-64 baseline; its
packaging requires Linux 5.10. Ubuntu 24.04 provides glibc 2.39, Linux
6.8, and the required libcap2/libselinux1 versions. This changes only
the CI helper's pinned payload, not product sandbox configuration.
2026-09-19 11:39:05 +08:00
Tianyi Cui 91212afc00 Merge pinned master e83fbddc into session-log-v4
Include the user's merge of #4586 so the V4 integration and its child PR
exercise the corrected spill-policy synchronization tests. Preserve the
upstream commit and authorship and keep this master checkpoint separate from
migration changes and the remaining benchmark investigation.

The merge changes only the spill-policy test file. Its added and removed
lines match the reviewed upstream fix exactly, while the release branch's
existing V4 fixture adaptations remain intact. No runtime source, persisted
format, or snapshot generation changes.

Validation: all 31 spill-policy owner tests pass with 100% package coverage.
2026-09-19 11:30:48 +08:00
Tianyi Cui f863b47a48 Merge pull request #4586 from deepseek-harness/worktree/fix-spill-policy-gates-20260919
test(spill-policy): synchronize slow-backend regressions on events
2026-09-19 11:23:10 +08:00
Yichen Jiang 3bcac0b878 test(web): expect three startup plugin batches in the keyless smoke
The application phase's map-form combo URL passes the 3 KiB limit once
the four settings companions join the composition, so the module system
partitions that phase into two combos beside the bootstrap one, as the
loading model allows. The smoke pins the three immutable batches and
still checks every combo's script, map, and cache header.
2026-09-19 10:46:51 +08:00
Yichen Jiang 08c3189c3c Merge branch 'worktree/jobs-api-review-3052' into worktree/jobs-api-review-3127
# Conflicts:
#	apps/web/tests/snapshots/live-job-stream/settled.expected.md
#	apps/web/tests/snapshots/live-job-stream/streaming.expected.md
#	snapshots/web/background-job-list/running.expected.md
2026-09-19 10:43:19 +08:00
Yichen Jiang 9f3ddc1a19 test(web): re-record the bundle golden after the detail-page chrome change
The crumb, uninstall, and configure controls no longer render an icon child in the accessibility tree; the bundle page golden this branch added follows the row and official goldens master re-recorded.
2026-09-19 10:41:31 +08:00
Yichen Jiang c4bc8b847a Merge branch 'worktree/jobs-api-review-3052' into worktree/jobs-api-review-3127
# Conflicts:
#	packages/client/ui-jobs/src/client/JobListAction.tsx
#	packages/shell/bash-local/tests/executor.spec.ts
2026-09-19 10:40:27 +08:00
Yichen Jiang 629c53d5a0 test(jobs): refresh snapshots for decorative icon accessibility 2026-09-19 10:40:25 +08:00
Yichen Jiang 30b882a1b2 fix(jobs): keep client detail tests on the pure renderer 2026-09-19 10:37:48 +08:00
Yichen Jiang 3135e4d612 Merge remote-tracking branch 'origin/master' into feat/plugin-detail-slots
# Conflicts:
#	apps/web/tests/expected/plugin-config/row.expected.md
#	packages/client/ui-plugin-manager/src/client/PluginManagerPage.tsx
#	packages/client/ui-primitives/src/index.ts
#	packages/client/ui-primitives/src/settings-form/fields.tsx
#	packages/client/ui-settings-plugins/package.json
#	packages/client/ui-settings-plugins/src/client/locales.ts
2026-09-19 10:36:07 +08:00
Yichen Jiang 70cacfdcaa test(shell): cover cancellation before reading failed launch results 2026-09-19 10:35:48 +08:00
Yichen Jiang 5c10701df2 Merge remote-tracking branch 'origin/master' into worktree/jobs-api-review-3052
# Conflicts:
#	apps/web/tests/expected/agent-preset-selection/header.expected.md
#	packages/client/ui-chat/src/client/chat/ContextInjectionRow.tsx
#	packages/client/ui-jobs/package.json
#	packages/client/ui-jobs/src/client/JobListAction.module.css
#	packages/client/ui-jobs/src/client/JobListAction.tsx
#	packages/client/ui-jobs/tests/job-list-action.client.spec.tsx
#	packages/client/ui-subagent/README.i18n.yaml
#	packages/client/ui-subagent/README.md
#	packages/client/ui-subagent/README.zh.md
#	packages/client/ui-subagent/src/client/SubagentHeaderLineage.tsx
2026-09-19 10:35:09 +08:00
Tianyi Cui 9f34db2373 test(spill-policy): await observed spill and dispatch stages
The slow-backend regressions start real NodeRuntime subprocesses, but
vi.waitFor silently imposed a one-second deadline on normal scheduling and
tool execution. Under concurrent Linux and Windows coverage this rejected
valid runs before the tested spill or dispatch stage was reached.

Resolve promises at the actual save-entry and dispatch-start observations,
and fail immediately if the run completes before those observations. Queue
all three requests up front in the bounded-backlog case so a missing third
start tests backpressure rather than child request timing. Cleanup releases
both queued and future spill gates and awaits execution completion.

Keep the existing outer test deadlines, product limits, result assertions,
and ordering checks. A temporary 1.2-second tool delay reproduces both old
failures and passes with these tests; temporarily removing the actual
backpressure wait still fails the third-dispatch assertion. No experiment
or product-code change is included.

Fixes #4585
2026-09-19 03:21:10 +08:00
Tianyi Cui 87f0df0550 Merge pinned master 5ec3ffe337 into session-log-v4
Keep the master refresh separate from the V3-to-V4 lossless-conversion and
checkpoint JSON fixes so the release baseline and each feature change remain
independently reviewable. This checkpoint extends the already-published
4435f6f519 merge before the #4583 child is rebased.

Integrate exactly master 5ec3ffe337062ab5bb4955933008afe8d0a0b915. Its #4156
changes add watched file/document refresh, filesystem watch readiness,
directory expansion restoration, and chat bottom-follow fixes. They update
shared filesystem and Client consumers without changing Session format or
snapshot generation.

The merge has no conflicts. Its 114-file scope and line counts match upstream;
code and prose additions/removals are unchanged. Only the two translation
pairing records incorporate the release branch's retained V4 documentation.

Validation: 762 owner tests passed (1 platform skip), 11 focused Web tests
passed, full build passed, and all 41 doc-sync checks passed. Runtime closure
and Client package checks passed; fs-local publint completed with the existing
source-wildcard export warning.
2026-09-19 02:39:04 +08:00
imccyu 29598c7ce9 Merge pull request #4156 from deepseek-harness/feat/issue-3930-preview-refresh
feat(web): refresh previews after turns and native file changes
2026-09-19 02:26:26 +08:00
Huanqi Cao 7450e1eb24 docs(sandbox): tighten the comments added by the delete-confinement fix
One home per fact: the parent-FILE_DELETE_CHILD rationale now lives in the
acl module doc and the package README instead of being retold in
restrictTokenIntegrity, init(), and grantWrite. Drops the duplicated
inline narration; behavior unchanged.
2026-09-19 02:25:01 +08:00
Huanqi Cao 36e632751e fix(sandbox): deny the ambient parent-delete right inside granted roots
The Low integrity label confines writes and deletes to the labeled roots,
but every granted root is labeled Low, so the integrity check alone still
let one confined child delete inside ANOTHER granted root (another
workspace, a live sibling temp directory): Windows authorizes a delete from
the parent directory's FILE_DELETE_CHILD right, which the write-restricted
intersection never reaches.

Each grant now also denies FILE_DELETE_CHILD to the world SID in the same
SetNamedSecurityInfoW call, so the capability ACE's DELETE bit is the only
delete authority inside a granted root. The idempotent skip additionally
requires the exact deny, so a root granted by an earlier build receives it
on its next provision. Delete paths inside the roots keep working; a file
whose own DACL grants no DELETE is no longer deletable through its parent's
rights, for the confined child and for the user's own processes alike.
2026-09-19 02:06:30 +08:00
Huanqi Cao d5ad3baeb5 fix(sandbox): confine Windows deletes with a Low integrity label
The write-restricted token's capability-SID intersection only covers the
write bits of the object's own access check. Windows also authorizes a
write or a delete from the parent directory's FILE_DELETE_CHILD right, and
no restricting SID has to co-sign that authority: the confined child could
therefore delete any file its ambient user SIDs control. `cmd /c del`
outside the workspace succeeded under BOTH modes, and .NET
File.Delete/DeleteFileW did too wherever the ambient DACL held Modify.

Lower the restricted token to Low integrity and apply a Low no-write-up
mandatory label to every granted directory in the same SetNamedSecurityInfoW
call that adds its capability ACE. The kernel evaluates the integrity policy
inside the access check whichever right supplied the authority, so the
granted roots stay writable while everything else becomes delete-proof as
well as write-proof. The label inherits to new children and follows the
existing standing/revocable grant lifecycle.

Also closes the Everyone-Modify ambient write boundary, and pins the delete
paths (cmd, .NET, Remove-Item, libuv) in runner.spec.ts.
2026-09-19 01:38:29 +08:00
imccyu 5c0b43f16e test(web): include connection diagnostics in SVG failures 2026-09-19 01:16:12 +08:00
imccyu 072ea695b9 fix(chat): retain bottom follow during stream updates 2026-09-19 01:16:12 +08:00
Tianyi Cui a7a8fa3c16 Merge pinned master into session log v4
Bring the Browser guide subtitle simplification from master
b605980eb049ce2cc578cdb608f7f8dee66f7b56 onto release checkpoint
2958f0f5cf67f81b18ad690a82c68c606f246d0c.

Keep this upstream synchronization in its own merge commit so the release
refresh can be reviewed independently from the lossless tool-content
conversion. The conflict-free merge contains the exact two-file upstream
patch: shorter English and Chinese guide subtitles and matching assertions.

Validation: all three ui-sidebar-browser apply tests pass, scoped type-aware
lint passes, the Client UI locale gate passes, and the first-parent patch
matches the pinned master delta from 0e9385ad8b in both full-diff and stable
patch-id comparisons.
2026-09-19 00:54:54 +08:00
Turtle 2099andTurtle 29d96fa538 fix(web): simplify Browser guide subtitle (#4561)
Co-authored-by: Turtle <[email protected]>
2026-09-19 00:39:22 +08:00
imccyu 7e09291f15 fix(sidebar): preserve expansion during directory restoration 2026-09-19 00:10:11 +08:00
Tianyi Cui bd5b1cd44f test(session): keep persistence fixture inventory keys portable
The accepted-baseline tests inventory temporary files with keys produced by
the host path.join. On Windows those keys contain backslashes, but the status
lookup and acknowledgement-preservation filters use repository-style slash
paths. Windows coverage therefore reads undefined for the status assertion;
the filtered preservation loops also select no files on that platform.

Use posix.join for logical inventory keys while keeping native path.join for
filesystem access. All platforms now exercise the same status lookup and
preservation assertions. This is confined to the test helper and changes no
production admission rule, compatibility policy, schema, or recorded fixture.
2026-09-19 00:07:18 +08:00
Tianyi Cui e134ba8765 fix(session): format unvalidated row fields explicitly in diagnostics
The retired-content guard runs on parsed physical JSON before normal event
admission so recovery cannot suppress a retired wrapper after another invalid
row. At that point type and sequence fields are still JSON values rather than
validated event fields. Implicit interpolation therefore violates the typed
lint rule on the final combined branch.

Use explicit String conversions only for the error subject. Keep the guard's
ordering and refusal checks unchanged; requiring an already-valid envelope
here would weaken the pre-recovery check. This does not change the stored
representation or add a migration rule.
2026-09-18 23:51:53 +08:00
Tianyi Cui 5152c097bb docs(session): catalog every V3-to-V4 transformation and refusal
The V3-to-V4 README described the main representation changes but did not
enumerate the complete admission and preservation rules. That left reviewers
without a package-owned reference for supported histories, child evidence,
native validation, or cases that must fail without publishing a successor.

Document historical conversion separately from native V4 admission, including
source renames and collisions, first-class tool results, child catalogs,
delivery metadata, retained identities and references, lifecycle checks,
developer-message constraints, fork behavior and recovery entry points.
Explicitly identify the retired-wrapper refusal and the limited scope of
general content validation rather than implying a complete payload validator.

Require this transformation/admission catalog in the version-addition
cookbook so future adjacent migrations document each supported mapping,
unchanged representation, refusal and preservation obligation. Preserve the
accepted-baseline policy: compatible V4 additions use new acknowledgements;
only breaking changes require a new writer version.
2026-09-18 23:49:21 +08:00
Tianyi Cui cbb4df8750 fix(session): refuse retired tool-result content during V4 admission
Released V3 accepts tool-result wrappers in ordinary user content. Leaving
those wrappers in a V4 artifact violates its declared content types and
reaches provider serializers that cannot represent them. Converting such
rows would require a new event, role, or source ownership decision.

Reject retired result tags only in known interpreted content slots and
raw Assistant stream block starts/ends. Reuse the native retired-syntax
admission path before recoverable suffix suppression and target artifact
restoration before successor publication. Preserve the existing system
and tool-result validators and the canonical V3 tool/result wrapper lift.

Known ignorable developer rows receive the same check during encoding;
unaware physical readers still defer their opaque developer payloads.
Tool arguments, replay state, schema parameters, nested metadata, and
unknown ignorable event payloads are not recursively scanned.

Real JSONL regressions cover V3 migration and native V4 read/write in
plain and Zstandard storage, including a corrupt native prefix. Refusals
preserve source bytes and the sole generation; opaque payloads survive.
No declared schema, frozen V0-V3 codec, or snapshot generation changes.
2026-09-18 23:49:20 +08:00
imccyu a77250603c fix(fs): watch parent before acknowledging missing files 2026-09-18 23:45:02 +08:00
Tianyi Cui 0112eaf3a8 feat(session): finalize the accepted V4 compatibility baseline
The integrated V3-to-V4 records contain the header increase that authorizes
their breaking changes. Leaving those terminal records editable would let a
later change reuse that already accepted 3-to-4 increase, so version 4 would
not establish a stable compatibility baseline for persisted user data.

Capture the accepted root classifications and semantic record digests in a
separate finalization checkpoint. Validate that checkpoint before rendering
or writing acknowledgement artifacts, and preserve its accepted records even
after the current writer advances. Keep publication evidence independent:
the verified released version remains 3 until a release establishes otherwise.

Compare future writer-4 schemas with the accepted baseline using the existing
compatibility classifier. Compatible additions remain permitted through new
same-version acknowledgement records. Breaking changes require a higher
writer and their own header transition; comments, aliases and source-location
changes do not alter the accepted semantics. Later unaccepted compatible
records retain the existing update workflow.

Document the distinction between finalization, publication and compatible
evolution, with regression coverage for locked records, incomplete or
inconsistent checkpoints, additive changes and future-version transitions.
2026-09-18 23:40:56 +08:00
imccyu 5b13cba35c test(workspace-files): cover initially missing watch targets 2026-09-18 23:27:30 +08:00
imccyu 4f55590aea fix(sidebar): correct automatic refresh and watch lifecycles 2026-09-18 23:27:30 +08:00
imccyu 9493ed6f61 test(sidebar): cover automatic refresh and watch lifecycle 2026-09-18 23:27:29 +08:00
imccyu 19d1f87492 fix(sidebar): satisfy lint and documentation checks 2026-09-18 23:27:29 +08:00
imccyu cf9213ca5f fix(sidebar): finalize resource auto-refresh behavior and tests 2026-09-18 23:27:28 +08:00
imccyu c71e907490 feat(web): add watched sidebar resource refresh 2026-09-18 23:27:28 +08:00
Yif b46af4d288 Merge remote-tracking branch 'origin/master' into feat/macos-sidebar-ui-and-drag-refine 2026-09-18 23:05:35 +08:00
Yif 1cfb776604 fix(ci): re-record slots pairing, refresh breadcrumb golden, cover null-panel nudge branch
The master merge invalidated docs/subsystems/slots.md's recorded pairing hashes; the minimal-preset UI golden still expected the breadcrumb as a disabled button, which darwin drag-band avoidance intentionally turned into plain text; and the app-region nudge effect's unattached-ref return had no darwin first-render test.
2026-09-18 23:05:24 +08:00
Tianyi Cui 498d0e8ecd merge: refresh session-log-v4 from pinned master
Merge master 0e9385ad8b9e75146f4baec2e731dd961f11c87c, observed when
this final integration step started, into the merged V4 release branch.
Keep the complete upstream history and do not advance to later master
commits during finalization.

Bring the Web trust-domain and relative-route handling, plugin install
cancellation, and npm registry mirror configuration into the common
release baseline. Retain the V4 codecs, producer-source policy,
parent-owned catalogs, and fork/migration behavior from the merged stack.

The merge needs no manual conflict resolution and changes no Session
JSONL inputs, snapshot generations, format packages, or persistence
schema/history files. This checkpoint precedes the separate V4 freeze
and audit fixes so each change keeps its own rationale and validation.
2026-09-18 22:35:14 +08:00
mektpoy 135104fb10 docs(browser-use): record the profile plugin instance-sharing decision
Adds the implemented Agent Note for the rule issue #4573 exposed: an
out-of-tree plugin declares every host runtime whose cross-instance identity
matters as a peer (plus dev), never as a dependency.

Records the mechanism (dsh-scope mints its tag per module instance), what the
duplicate does to a per-Agent registration, the alternatives that lost
(mounting on agent.ctx, a shared Symbol.for tag, version alignment), and the
open coverage gap: verify-package-dependencies selects no packages/experimental
package, so tests/shared-host-runtimes.spec.ts is the only pin.
2026-09-18 22:22:07 +08:00
fz 87cd0d8eb9 fix(skill): validate workspace dependency entry types 2026-09-18 22:19:37 +08:00
Yif d1e7bd0901 fix(client): keep the drag-gate fixture path outside packages/ so verify-package-paths resolves 2026-09-18 22:18:52 +08:00
imccyu 94607e48d6 Merge pull request #4578 from deepseek-harness/revert-4565-ihsiang/work-details-toggle
Revert "feat(web): add work details presentation modes"
2026-09-18 22:12:19 +08:00
imccyu 50460879db Revert "feat(web): add work details presentation modes" 2026-09-18 22:11:53 +08:00
涂轶翔 60f2b1a2c9 Merge pull request #4429 from deepseek-harness/feat/developer-session-changes
feat(session): add developer changes using historical tool schemas
2026-09-18 22:11:29 +08:00
ihsiang 68a684d9c0 Merge pull request #4565 from deepseek-harness/ihsiang/work-details-toggle
feat(web): add work details presentation modes
2026-09-18 22:04:42 +08:00
Yif 6f77b92121 docs(notes): reconcile shell.leading note with the sessionless conversation.header.leading seat
Master's sessionless-sidebar work renamed the conversation leading seat to
root-scoped conversation.header.leading instead of deleting it; the note now
states both seats' current roles rather than claiming outright removal.
2026-09-18 22:01:05 +08:00
Yif 64556a1285 fix(client): restore fullscreen panel drag subtraction, correct seat mount-condition docs
The fixed fullscreen right panel sits over the frame's leading band and the
sidebar logo row's drag rects, so without a whole-box no-drag its
non-interactive content dragged the window; restore the subtraction (darwin).
The shell.leading note and AppFrame comment now state the real mount
condition (darwin && sidebarCollapsed) instead of the platform-agnostic
collapsedWidth === 0 claim, which Windows' caption collapse also satisfies.
2026-09-18 21:51:01 +08:00
yixiangihsiang daa2387546 fix(ui-chat): derive trigger titles from durable sources 2026-09-18 21:47:37 +08:00
fz bffd23d3bc Merge remote-tracking branch 'origin/master' into feat/workspace-dependencies-package 2026-09-18 21:45:56 +08:00
fz 44e4750673 test(sdk): match Office startup wait to conversion deadline 2026-09-18 21:45:15 +08:00
Yif d94aef5214 Merge remote-tracking branch 'origin/master' into feat/macos-sidebar-ui-and-drag-refine 2026-09-18 21:42:09 +08:00
Yif 50f7bc0bc6 fix(client): declare pointerup/pointercancel on Tooltip AnchorProps 2026-09-18 21:41:57 +08:00
Yichen Yan 2708df4a9c Merge pull request #4203 from deepseek-harness/yyc/web-relative-routes-reviewed
fix(web): resolve feature routes from the document directory and gate browser routes
2026-09-18 21:28:35 +08:00
Yif 5467209f8e fix(client): settle tooltip pointer flag, harden drag gate, scope shared-curve doc
Clear pointerFocus on pointerup/pointercancel so a press that never moves
focus cannot swallow the next keyboard focus; match prefixed/unprefixed
app-region with !important tolerance and prove the allowlist path rejects
an offender; scope the ui-layout shared-curve limitation to data-animating.
2026-09-18 21:23:11 +08:00
mektpoy de8b10f8ab fix(browser-use): share the installation's scope and MCP client instances
A profile installs @deepseek-ai/dsh-experimental-browser-use-runtime from npm
beside the dsh installation, and that package declared @deepseek-ai/dsh-scope
and @deepseek-ai/dsh-mcp-client as dependencies, so the install carried its own
copy of both.

dsh-scope mints its scope-tag symbol per module instance, so the copy's
createScope tags a context the host's scopeOf cannot read. Every Agent's MCP
tools then registered in the global tool layer: the first Agent succeeded and
each later Agent's tool synchronization hit a name conflict, which
failOnStartupError turned into a failed creation.

Both are now peer dependencies (plus dev), which is how every other consumer of
ctx.tools and dsh-scope declares them and how a profile install reaches the
installation's single instance through the profiles module fallback.
schemastery stays a dependency: it carries no instance-local state.

Fixes #4573
2026-09-18 21:21:10 +08:00
Yichen Jiang 82c7889b0e Merge pull request #4539 from deepseek-harness/worktree/npm-registry-mirror-config-029a47
feat(plugin-manager): pick a registry and fall back through mirrors when one is unreachable
2026-09-18 20:58:06 +08:00
Yif 8837c532d1 Merge remote-tracking branch 'origin/master' into feat/macos-sidebar-ui-and-drag-refine 2026-09-18 20:54:38 +08:00
Yichen Jiang 61b099b77c fix(client): draw the registry popover's hairline as its elevation stroke
master's elevation contract (elevation-styles.client.spec.ts) rejects a
neutral border beside an lv/elevation shadow: the stroke belongs to the
shadow. The registry options keep their l3 hairline through
--dsw-elevation-stroke-color, as Menu does, with border: 0.
2026-09-18 20:50:04 +08:00
mektpoy 931505a9cc fix(workspace-files): list directory links through their resolved target
Windows directory junctions are reparse points that lstat reports as symlinks, so list refused My Music, My Pictures and My Videos with workspace-file/not-directory while its own listing reported them as directories. list now follows a final link, requires the resolved target to be a directory inside the workspace root, and keeps read's no-follow gate.
2026-09-18 20:45:00 +08:00
Yichen Jiang 5fe06ee64b Merge remote-tracking branch 'origin/master' into worktree/npm-registry-mirror-config-029a47
# Conflicts:
#	packages/client/ui-plugin-manager/src/client/PluginManagerPage.tsx
#	packages/client/ui-plugin-manager/src/client/manager-store.ts
2026-09-18 20:37:39 +08:00
Yichen Jiang 27207bfedb test(plugin-manager): stop an install before its first run deterministically
The cancelled-between-attempts case raced a zero-delay timer against the
file restore between two registries; under parallel load the restore won,
the second attempt started, and the once-only mock let it reach the real
pnpm. The stop now lands while the registries are read, before any run,
which is the same guard and cannot race.
2026-09-18 20:28:15 +08:00
Yichen Jiang 4d75946def Merge pull request #4552 from deepseek-harness/worktree/plugin-install-close
fix(web): allow closing pending plugin installations
2026-09-18 20:25:17 +08:00
lsdsjy 6ad7c991bf test(ui-chat,web): align browser coverage with work details folding 2026-09-18 20:23:46 +08:00
Yichen Jiang 1dfd026b84 Merge remote-tracking branch 'origin/master' into worktree/npm-registry-mirror-config-029a47
# Conflicts:
#	apps/web/tests/expected/plugin-install-cancel/cancelled.expected.md
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	packages/boot/plugin-manager/README.i18n.yaml
#	packages/boot/plugin-manager/README.md
#	packages/boot/plugin-manager/README.zh.md
#	packages/client/ui-plugin-manager/README.i18n.yaml
#	packages/client/ui-plugin-manager/README.md
#	packages/client/ui-plugin-manager/README.zh.md
#	packages/client/ui-plugin-manager/src/client/PluginManagerPage.tsx
2026-09-18 20:21:59 +08:00
Yichen Jiang 75b20ea98c fix(web): remove unreachable fallback and pin snapshot scroll 2026-09-18 20:17:28 +08:00
mektpoy 771ebf4ace fix(web): scan plain src for a dual-face browser package without src/client 2026-09-18 20:06:44 +08:00
Yichen Jiang e7094c81e2 Merge origin/master into worktree/plugin-install-close 2026-09-18 20:03:08 +08:00
lsdsjy 50b7dd21a2 fix(ui-chat,web): isolate process updates and restore lifecycle details 2026-09-18 20:02:15 +08:00
Yichen Jiang f938ebad64 fix(web): recover lost plugin installation responses 2026-09-18 19:58:04 +08:00
Yichen Yan de2e799b0e Merge pull request #4202 from deepseek-harness/yyc/web-trust-domain-reviewed
feat(web): serve the shell, API and plugin resources from the document directory
2026-09-18 19:46:36 +08:00
lsdsjy afc62255a5 test(ui-chat): include performance settings in migration fixtures 2026-09-18 19:36:48 +08:00
lsdsjy 93caf245b4 fix(ui-settings): enable developer tools by default 2026-09-18 19:34:33 +08:00
lsdsjy f7daba8ca7 fix(ui-chat): map legacy normal work details to detailed 2026-09-18 19:34:33 +08:00
lsdsjy cb561cbe4e fix(ui-chat,web): align work detail labels and Bash snapshot 2026-09-18 19:22:24 +08:00
lsdsjy 6a9febf6fe Merge remote-tracking branch 'origin/master' into fix/pr4565-ci 2026-09-18 19:18:11 +08:00
Tianyi Cui 8913d033dc refactor(chat): match user messages before developer refusal
The input-message definition classifies ordinary user, steering, and injected
context messages. Put that supported path first so readers can follow its
matching rules directly, then handle deferred developer history afterward.

Keep the append/checkpoint predicates, matched identity, null result for
other events, and explicit developer error unchanged. This is a local
readability change with no presentation or persistence behavior change.

Validation: all 61 conversation-node definition tests pass, including user
classification and developer refusal. Scoped lint and whitespace checks pass.
2026-09-18 19:08:11 +08:00
Yixiang TuandTianyi Cui e0bd7e1960 feat(session): add developer changes using historical tool schemas
Session V4 reserves developer-role messages for incremental model-visible
session changes. The role, tool addition/removal blocks, and deferred-loading
marker need a durable representation before independent provider and UI
integrations can emit or consume them. Known developer events must match an
open turn and step; unsupported providers and UI consumers fail explicitly.

Request headers already capture full tool definitions. Persisting another
ToolSchema in each addition would duplicate Session information and create
two definitions that could drift. Additions therefore store toolName, and
the containing developer event uses headerSeq to select one earlier known
request/header for all its additions. A same-name replacement keeps its
historical definition identity through restart, fork and surface changes.
Removals require no definition copy, and ordinary developer messages omit
headerSeq. Generic sourceEventSeqs remains independent derivation metadata.

The rejected inline tool field is optional never with @persistenceReserved.
The schema extractor retains that uninhabited slot, so permitting a future
value requires a format bump instead of being mistaken for compatible
optional metadata. Unrelated optional fields remain additive and readable.

Native and Session admission reject missing, forward, non-header, unknown,
ambiguous and incomplete referenced definitions, and reject the retired
inline tool field. Validate complete schema fields only for referenced
definitions, preserving unrelated header behavior and extra JSON metadata.
Unknown ignorable records remain opaque. Empty developer nodes retain their
surface position without producing a message or shadowing the system head.
No automatic emitter, provider activation, UI implementation, or speculative
public resolver is added.

Keep the core-owned developer source binding beside the introduced role,
including the request-only type rejection and attribution round trips. Update
consumer guards, SDK/snapshot handling, bilingual owner documentation, and
the same unreleased V4 acknowledgement. Keep earlier tool/source migration
work and its documentation in the parent. Preserve the existing recorded
Cordis inspection generation from the original developer change.

Integration keeps the final source layer as the sole parent and preserves
master's Messages input filtering, empty-user omission, empty tool results,
and system-update placement. Developer/deferred guards still run before
conversion. Native V4 admission, header references, reservation declarations,
and generic tooling match the validated marker candidate. Parent-owned
fixture and generator fixes remain in the parent.

Earlier feature validation passed full build, full lint, 41 doc-sync gates,
and 16 hygiene gates. The unchanged native implementation retains that evidence.
The focused Session/V4/request-input run passes 884 tests across 38 files with
100% statement, branch, function and line coverage for the V3-to-V4 package
and Session surface. Consumer tests pass 482 with one existing skip; tool,
message and optional-field tests pass 146. Cordis inspection and compaction
replays pass in both source and built modes (two cases per mode). Ten invalid
referenced-definition/unknown-header controls failed before their scoped
guards and pass after them.

Reservation validation: the actual generated developer root records tool as
optional primitive never. Widening it requires a bump, while traceId remains
additive and preserved; all 85 focused reader/classifier tests pass.

Final-parent validation: 205 tests across eight provider, type, catalog,
Session and native-format files pass. The preserved parent fixture verifies
Messages input-history replay; runtime/declaration and parent-owned-file
comparisons show no loss during the final rebase.

Co-authored-by: Tianyi Cui <[email protected]>
2026-09-18 19:08:11 +08:00
Tianyi Cui b88afa8a72 fix(ptc): name persisted producer attribution ptc-mode
The producer-source refactor introduced the unreleased V4 discriminator
code-mode even though this source identifies images deferred from successful
PTC subcalls. Name it ptc-mode before V4 ships so persisted attribution
matches the producer and does not freeze obsolete terminology into new logs.

Keep the live writer, V3-to-V4 migration output, collision guard, and reserved
producer policy aligned. Both released tools-code-mode and tools-ptc plugin
lookup keys map to ptc-mode. Preserve those historical keys, opaque message
text and IDs, all frozen V0-to-V3 generations, and recorded Session inputs.

Update the owning tests, producer documentation, current catalog, and V4
acknowledgement. The canonical schema audit identifies exactly three changed
roots; reversing only the source literal restores each prior digest. The
large generated JSON diff comes from graph ordering, with 61 roots and 572
types retained.

Validation: the seven-file focused run passed 298 tests and exposed four
stale current-output expectations in two migration files. After correcting
those expectations, both files passed all 23 tests. All 41 documentation
gates and full lint passed; frozen generations and recorded inputs are
unchanged.
2026-09-18 19:07:12 +08:00
_KermanandTianyi Cui fb79a944f5 refactor(llm): separate durable producer sources from request inputs
Give durable user context its producer-owned source kind instead of a generic plugin wrapper. The V3-to-V4 conversion preserves the frozen rename and collision rules, all own JSON metadata, event coordinates, and historical request-only kinds. Native catalog and JSONL admission retain source validation so unknown attribution can survive without its producer while malformed owned sources are refused.

Use an explicit user-only RequestUserInput for auxiliary LLM prompts that do not own durable message identity. Auto Review and compaction remove their request-only source registrations while retaining prompt content and freezing; provider serializers and projections keep the same wire data, assistant replay isolation, image ordering, and tool correlation. Session writes, Agent delivery, and recorded title requests continue to require identified durable messages.

Bind the saved compatibility policy only to user sources and qualify tmux location attribution without weakening fixed system, model, or tool semantics. Rebuild the current inventory and unpublished V4 acknowledgement on the actual tool-role parent, preserving its rationale and all accepted historical records. The catalog format version records tooling metadata; Session remains V4. Developer-role policy and activation belong to their own feature.

The latest-master Messages adapter, serialization, request-input typing, EpochHeader reservation, and attribution checks pass 103 tests across five files. The retained V3 Messages input-history snapshot passes through the source profile; Host/Client typechecks and all 41 documentation gates pass. The generated comparison records four changed roots and 447 unchanged type fingerprints. Latest-master ARIA changes are retained, with producer source labels applied independently; new Messages fixtures retain their producer names as declared source kinds and use the fixed system-message helper; recorded Session generations are unchanged by this regrouping.

Co-authored-by: Tianyi Cui <[email protected]>
2026-09-18 19:07:12 +08:00
Tianyi Cui 29f7e7bdf5 fix(session): reserve retired system text in request-header schemas
Native V4 admission and Session adoption reject every request/header.header.system field because system prompts belong to system/message events. EpochHeader omitted that key, so the generated schema classified adding optional system text as a same-version optional-property addition even though released readers would reject it.

Declare system?: never with the shared persistenceReserved marker so the schema records the existing prohibition. Widening the field to string now changes a forbidden value set and requires a version bump. Keep both runtime guards and all unknown-metadata handling unchanged, and document the reservation alongside the current header type and V4 acknowledgement.

The regression extracts the actual event:request/header schema, checks the optional-never field, widens only that property, and verifies the version-bump diagnostic and native refusal. It fails without marker extraction and passes with the shared tooling support. The focused reservation, retired-syntax, and Session surface suites pass 65 tests; all 436 type-equiv blocks match their source. Generic marker extraction belongs to the foundational tooling change.
2026-09-18 19:05:33 +08:00
_KermanandTianyi Cui f4a32dbd0a refactor(llm): flatten tool results and validate native V4 sessions
Represent tool results as tool-role messages and migrate released wrappers
without losing outer own JSON fields, call identity, error state, or writer
field order. Refuse nested or wrapper-only information that has no lossless
current representation before successor publication.

Validate current event relationships directly instead of projecting V4 data
back into V3. Keep lifecycle, PTC, title/command, compaction, system-field and
retired-syntax checks on catalog restoration and ordinary JSONL opens. The
Worker JSON equality helper must inspect own keys so it cannot admit PTC
arguments that Node rejects.

Keep the source role change, required native admission and consumer fixture
updates in one complete review layer. Explain shared-type changes in the
persistence record and the native reader rationale in its existing note.
Use checked branded fixture identities and discriminant narrowing instead
of unknown double casts; fixture values and assertions remain intact.

This recomposes the original tool-role work by _Kerman with the independently
validated migration and admission repairs by Tianyi Cui. Frozen generations
and snapshot input version selection are retained.

Co-authored-by: Tianyi Cui <[email protected]>
2026-09-18 19:05:32 +08:00
Tianyi Cui c6e62ff971 fix(persistence): retain explicitly forbidden JSON fields
A reader can reject a property name while its type declares that property
as optional never. Dropping it from the extracted schema makes a future
optional JSON value look additive, although the existing reader refuses it.
The type history must retain that explicit prohibition.

Support the argument-free @persistenceReserved marker only on optional
properties whose values are never or undefined. Keep those properties as
optional primitive-never nodes, so later JSON values change an existing
field and require a version bump. Reject invalid placement, arguments,
repeated tags, required or JSON-valued declarations, and mapped uses that
violate the reservation. Keep every unmarked omission rule unchanged.

The classification regression failed before this change with an additive
optional-property result and now requires a type-change bump. All fifteen
focused reservation cases and all 210 tooling tests pass, including inherited
fields, misuse, and unmarked preservation. Host typecheck, scoped lint, and
pairing pass. Regeneration leaves the unannotated baseline catalog and
inventory byte-identical; all 61 roots still match their existing history.
No runtime property is activated in this tooling commit.
2026-09-18 19:05:32 +08:00
Tianyi Cui a6981c56f6 feat(persistence): add stable catalogs and policy-aware schema review
Traversal ordinals and first-owner paths gave shared persistence types
unstable display names. Keep authored names and source locations as metadata,
use structural digests for identity, and render complete kind/form groups
with bounded array labels. Preserve historical rendering and stored graphs.

Record supported source compatibility promises with their property binding,
policy version, discriminator, preservation rule, and qualified kind set.
The extractor and classifier require explicit opt-ins in both compared
schemas; ordinary or unsupported changes retain strict classification.
Policy-bearing graphs use the format-2 fingerprint domain while unannotated
graphs keep their format-1 fingerprints. Runtime owners activate bindings
only with the corresponding reader behavior; this tooling layer activates
none and changes no package source or Session generation.

Provide a read-only before/after review command that groups shared structural
evidence without replacing authoritative compatibility diagnostics. Match
changed alternatives only through unique literal discriminators and retain
ambiguous additions and removals as independent facts.

At the X baseline, all 61 roots and 472 schemas, digests, and source fields
are unchanged. The inventory remains format 1 and removes only 296 synthetic
names. Existing acknowledgement history still matches every root. All 195
focused tooling tests, Host build/full lint, and bilingual pairing pass.
2026-09-18 19:05:32 +08:00
Tianyi Cui bc710ac726 test(web): await the settled branch action in fork snapshots
The merged performance/usage preference hides elapsed-time controls by
default. The release-only mid-turn fork scenario still waited for
"Ran for", so its ARIA check timed out despite a completed child turn.

Wait for the visible, enabled branch action belonging to live turn 2.
That action requires the settled turn tail and directly exercises the
fork affordance this scenario owns. Preserve the existing exact-cut,
synthetic closer, resume-header, completed-turn, and streaming checks.
Keep the default preference rather than enabling unrelated timing UI.

Refresh only the obsolete elapsed-time button in the ARIA expected
output. Session JSONL inputs, historical generations, snapshot versions,
and production code remain unchanged. The former wait failed locally;
the four-case scenario passes in ordinary comparison mode after this fix.
2026-09-18 19:02:10 +08:00
winewill 925f609092 Merge remote-tracking branch 'origin/master' into fix/windows-mandatory-update-overlay 2026-09-18 18:47:20 +08:00
Yif 761f53223a feat(desktop): align main window default and minimum size with Codex (1280x820, min 480x600) 2026-09-18 18:44:24 +08:00
winewill d7fd452e96 test(desktop): exercise embedded mandatory update recovery on Windows 2026-09-18 18:40:31 +08:00
mektpoy 0e23ee6789 Merge branch 'yyc/web-trust-domain-reviewed' into yyc/web-relative-routes-reviewed
# Conflicts:
#	packages/client/ui-chat/tests/assistant-markdown-path-images.client.spec.tsx
#	packages/client/ui-open-in-app/README.i18n.yaml
#	packages/client/ui-open-in-app/README.md
#	packages/client/ui-open-in-app/README.zh.md
#	packages/client/ui-open-in-app/src/client/index.ts
#	packages/session-query/session-log-export/README.i18n.yaml
2026-09-18 18:35:31 +08:00
Yif e9b928d993 Merge remote-tracking branch 'origin/master' into feat/macos-sidebar-ui-and-drag-refine
# Conflicts:
#	.agents/notes/implemented/feature/2026-09-13-macos-hidden-titlebar-vibrancy.i18n.yaml
#	.agents/notes/implemented/feature/2026-09-13-macos-hidden-titlebar-vibrancy.md
#	.agents/notes/implemented/feature/2026-09-13-macos-hidden-titlebar-vibrancy.zh.md
#	docs/subsystems/slots.i18n.yaml
#	docs/subsystems/slots.md
#	docs/subsystems/slots.zh.md
#	packages/client/ui-conversation/src/client/contract/slots.ts
#	packages/client/ui-conversation/src/client/skeleton/ConversationRoot.module.css
#	packages/client/ui-conversation/tests/skeleton.client.spec.tsx
#	packages/client/ui-sidebar/README.i18n.yaml
#	packages/client/ui-sidebar/README.md
#	packages/client/ui-sidebar/README.zh.md
#	packages/client/ui-sidebar/src/client/HeaderLeadingControls.tsx
#	packages/client/ui-sidebar/src/client/index.ts
#	packages/client/ui-sidebar/tests/apply.client.spec.tsx
#	packages/extensions/cordis-client-runner/src/client/slot-catalog.ts
2026-09-18 18:34:12 +08:00
Yichen Jiang 998d2ce8c9 fix(client): narrow the registry options to their content 2026-09-18 18:33:17 +08:00
mektpoy 2c6f634771 Merge branch 'master' into yyc/web-trust-domain-reviewed
# Conflicts:
#	tsconfig.host.json
2026-09-18 18:31:17 +08:00
Yichen Jiang 78522443f7 fix(client): keep the registry's host to its option
The control beside the guide, the attempt line, the run badges, and
the failure lists name a registry by its name alone; only the option
in the list carries the host it names.
2026-09-18 18:30:37 +08:00
winewill fdc4887c38 fix(desktop): embed Windows mandatory updates in the main window 2026-09-18 18:26:40 +08:00
Yichen Jiang c34e33cbd9 fix(client): title the registries by their hosts and drop the fallback note
The default registry reads as such with the host pnpm names, the
mirror carries its host too, and no line under them repeats it or
describes the order the Host would ask; the order shows only as the
Host asks it.
2026-09-18 18:25:57 +08:00
Tianyi Cui c95d045fdc docs(session): correct fork seed marker ownership
Arbitrary-sequence forks place the inherited end-seed marker before their
synthetic tool, step and turn closers. The Session constructor receives that
whole prepared seed, so firstLiveSeq can follow the inherited marker and the
constructor is no longer its sole producer. The retained documentation still
claimed both facts and could lead a consumer to use the wrong ownership cut.

Name buildForkSeed and the constructor as the two core producers, distinguish
the inherited cut from ordinary restore markers, and retain the warning about
plugins appending their own markers. Correct the subsystem reference's claim
that interrupted is the only synthetic turn ending: forked is also never
emitted by a live loop. Keep the bilingual reference and type-equivalent
excerpts aligned with the source JSDoc.

Refresh the required persistence catalog after the JSDoc change. Its schema
inventory changes only three source-line locations; all 61 roots, 472 types
and fingerprints remain identical. Parsed TypeScript declarations printed
without comments are also identical, so this changes neither runtime behavior
nor persisted fields, historical generations or recorded Session fixtures.
2026-09-18 18:25:39 +08:00
Tianyi Cui 044cd4fb49 merge: integrate pinned master into session-log-v4 base
Merge master 01d96c168a84227374e3aa741e94ddfbb498e27e, observed when
this integration started, after the published 6de3db41 checkpoint. Keep
master's author history and preserve the release writer, adjacent
migrations, historical Session generations, and parent-owned catalogs.

Combine blank Session writer acquisition and superseded-startup
cancellation with the release branch's projection refresh and panel
preservation. A startup acquisition may finish after a later navigation,
but must not retain a stale main Session or reveal its Conversation.
Update the existing regression's retention expectation while preserving
its panel and active-navigation assertions.

Keep the release catalog loading, known-leaf, and parent availability
behavior alongside master's completed-turn status and aligned sidebar
icons. Regenerate the config locations and pair the combined README
contracts. Preserve upstream's Linux process-state assertion repair.
2026-09-18 18:21:47 +08:00
Yifffan afc27869f7 Merge pull request #4532 from deepseek-harness/feat/plugin-refine
refine(plugin-manager): polish install dialog, wizard states, and plugin artwork
2026-09-18 18:05:11 +08:00
Kaige-Gao 0ed5151d0b Merge pull request #4448 from deepseek-harness/feat/session-header-feedback
feat(web): add feedback to session header menu
2026-09-18 18:01:38 +08:00
Kaige-Gao 1b622ae54c Merge master into feat/session-header-feedback 2026-09-18 17:47:22 +08:00
yixiangihsiang ae1cf3106b fix(web): polish work detail interactions 2026-09-18 17:46:32 +08:00
fz 5c263aaaf6 Merge remote-tracking branch 'origin/master' into feat/workspace-dependencies-package 2026-09-18 17:45:01 +08:00
fz defb9c3736 fix(sdk): shorten bundled Python resource paths on Windows 2026-09-18 17:44:15 +08:00
Yif c3226f93e9 Merge remote-tracking branch 'origin/master' into feat/plugin-refine
# Conflicts:
#	packages/client/ui-primitives/README.i18n.yaml
#	packages/client/ui-primitives/README.md
#	packages/client/ui-primitives/README.zh.md
#	packages/client/ui-primitives/tests/icons.client.spec.tsx
2026-09-18 17:43:20 +08:00
CreatixChu e651d00a9f Merge pull request #4354 from deepseek-harness/worktree/present-changes-dedup
通过提示词减少重复展示
2026-09-18 17:33:28 +08:00
Yif 978e39e94e fix(plugin-manager): align plugin-config e2e and README quotes with revised copy
The plugin-config e2e pinned the old terminal one-liner and its golden still
carried the three pre-revision summaries; the ui-plugin-manager READMEs still
quoted the renamed install-guide button. Refresh the golden, update the
assertion and both READMEs, and re-record the translation pairing.
2026-09-18 17:30:31 +08:00
Kaige-Gao de3f4c24ea fix: address feedback menu review and Linux process assertion 2026-09-18 17:30:19 +08:00
yixiangihsiang 5f90ac119e fix(web): refine live work disclosure presentation 2026-09-18 17:28:59 +08:00
lsdsjy 776efdf321 fix(ui-chat): hide infrastructure rows and retain turn triggers 2026-09-18 17:26:32 +08:00
lsdsjy f2cf7272ef fix(ui-tool,ui-skill): localize Chinese tool step titles 2026-09-18 17:26:31 +08:00
lsdsjy 687ee6e2c7 fix(ui-chat): align work detail modes and disclosure titles 2026-09-18 17:26:31 +08:00
lsdsjy ad1ddfd0b1 fix(ui-chat): hide settled reasoning previews when collapsed 2026-09-18 17:25:57 +08:00
lsdsjy 4216e778f5 fix(ui-chat): place response actions at the turn bottom 2026-09-18 17:25:57 +08:00
creatixchu 6453db05ca Merge remote-tracking branch 'origin/master' into worktree/present-changes-dedup
# Conflicts:
#	packages/client/ui-deliverables/README.i18n.yaml
#	packages/client/ui-deliverables/README.md
#	packages/client/ui-deliverables/README.zh.md
2026-09-18 17:25:53 +08:00
mektpoy c85e1d7b72 fix(client): raise the plugin inventory package identity to 12px
The Plugins settings inventory drew the Loader entry identity (cardIdentity)
at 11px in the code font, one step below the 12px the same identifier gets in
the expanded card's entry row. On Windows the code stack resolves to Consolas,
where 11px reads thin. Raise it to 12px/18px so it matches the sibling
identifier row and the page's other small text.

Fixes #4496
2026-09-18 17:25:40 +08:00
lsdsjy e132da911a fix(ui-chat): hide disclosure arrows for empty turn processes 2026-09-18 17:25:38 +08:00
lsdsjy 0859dca83f fix(ui-chat): show at least one second for completed turns 2026-09-18 17:25:37 +08:00
lsdsjy 55c564f31c feat(ui-chat): show independent notices for non-human turn triggers 2026-09-18 17:25:37 +08:00
lsdsjy fac2a46c02 fix(ui-chat): reset nested disclosures when collapsing a turn 2026-09-18 17:25:36 +08:00
lsdsjy a0c71e9f00 feat(ui-chat): add work details modes and keep retry rows separate 2026-09-18 17:25:36 +08:00
mektpoy 0301a0a062 fix(desktop): place Windows caption tooltips below the titlebar
The Windows caption menu host sits at z-index 1100 in the strip that --dsh-windows-menu-start reserves to the right of the sidebar toggle and New Session, so the sidebar's right-side hover bubbles rendered underneath the Application/Edit text. Render those two bubbles below the 40px caption instead; ordinary Web and macOS keep the default right side.
2026-09-18 17:25:14 +08:00
lsdsjy 0ce6ab6775 feat(ui-chat): reflect turn outcomes in process disclosure titles 2026-09-18 17:24:20 +08:00
lsdsjy b2296f5916 feat(ui-chat): show expanded turn timer from turn start 2026-09-18 17:23:52 +08:00
lsdsjy 97514daa23 feat(ui-chat): refine process titles and expose retry activity 2026-09-18 17:23:51 +08:00
lsdsjy fab6622abb feat(ui-chat): fold consecutive process steps and complete paginated turns 2026-09-18 17:23:51 +08:00
Yichen Jiang 2b168ce1ae fix(client): float the registry options over the install dialog and let its content scroll
With the guide open, unfolding the registry options pushed the dialog
past the viewport, and the card did not scroll. The options now float
from their toggle in a portal, right-aligned to it, folded by Escape
(claimed before the dialog's own Escape) or a pointer outside them,
and by the store when a run starts; useAnchoredPosition gains end
alignment for this. The dialog's content region scrolls under its
footer. The mirror reads as the mainland China mirror without a tag.
2026-09-18 17:20:10 +08:00
ihsiang 669bc2036f Merge pull request #4545 from deepseek-harness/ihsiang/refine-web-review-subagent-status
feat(web): refine review and subagent status UI
2026-09-18 17:19:52 +08:00
Turtle 5c8933fbe3 fix(session): acquire blank Session writers before reuse (#4392)
* fix(session): keep blank session discovery local to each host

* fix(session): acquire blank writers before reusing sessions

* refactor(workspace): separate saved selection restoration from blank lookup

* fix(workspace): create after the selected blank writer is held

* test(web): align blank reload snapshot with current icons
2026-09-18 17:19:40 +08:00
fz 9d66716e50 Merge remote-tracking branch 'origin/master' into feat/workspace-dependencies-package 2026-09-18 17:19:26 +08:00
fz 37983d9298 feat(sdk): bundle shared Office authoring resources 2026-09-18 17:17:46 +08:00
creatixchu ac0a042f08 Merge remote-tracking branch 'origin/master' into worktree/present-changes-dedup 2026-09-18 17:16:34 +08:00
creatixchu ba98bcbf08 test: refresh presentation guidance after review 2026-09-18 17:12:03 +08:00
creatixchu 223385954d fix: recommend at most four files per presentation 2026-09-18 17:10:38 +08:00
creatixchu 63c1e04b93 fix: keep file access available across presentation clients 2026-09-18 17:09:02 +08:00
Yichen Jiang cb2750019a fix(plugin-manager): read pnpm's own registry, its stdout refusals, and lay failures where they belong
Review of #4539. A refusal pnpm view prints as JSON on stdout was read
as unknown, so no registry was ever asked after a dead one; stderr and
stdout are now read alike, and a lookup killed at its bound is a
network refusal. pnpm's own registry joins the fallback plan only once
pnpm config get registry names npm's own or a configured fallback, so
a company registry in .npmrc is never followed by a public one, and a
registry pnpm already names is asked once. The Host lays each failure
at the registry or the spec's own host, reading the host off error
lines only, and reports it as ChangeResult.failedAt; a stop that lands
between attempts is cancelled, not failed. The package publishes its
registry rule through ./registry so the dialog plans with the Host's
own function, starts from the registry the Host asks first until one
is remembered, tags that one as the default, labels pnpm's own by the
host it names, and words and offers a change of registry from the
Host's attribution. ERR_PNPM_NO_OFFLINE_META is no longer a network
failure.
2026-09-18 17:03:04 +08:00
07akioni 6d7a5f9cc3 fix(desktop): verify archived descriptors and harden Office resolution 2026-09-18 17:01:17 +08:00
yixiangihsiang a0c7299f8b feat(web): refine review and subagent status UI 2026-09-18 17:01:04 +08:00
fz 1e3afc63ad Merge remote-tracking branch 'origin/master' into feat/workspace-dependencies-package 2026-09-18 16:58:33 +08:00
winewill f5b0f56ce6 Merge pull request #4528 from deepseek-harness/perf/macos-packaging
perf(desktop): speed up macOS packaging with verified signature caching
2026-09-18 16:56:48 +08:00
Yichen Jiang 6e456264a9 test(web): wait for sidebar collapse before reopening 2026-09-18 16:47:24 +08:00
Tianyi Cui d40f3fb658 test(hooks): synchronize inspection of an unpublished install lock
The Windows coverage job can schedule the test after the old 200 ms
publication delay has elapsed. File existence then no longer proves an
empty lock, so the setup assertion fails even though the installer is
correct. The original implementation reproduces that failure when parent
inspection is held until the record has been published.

Replace the delay-only test hook with two opt-in fixture barriers. Hold the
publisher after exclusive creation, and acknowledge the contender only
after it has observed an incomplete record. The test checks the empty bytes
before releasing both processes and always releases and awaits them during
cleanup. Existing normal-path lock and initialization budgets are unchanged;
no test barrier is entered without its explicit environment setting.

The focused barrier case and all 38 installer tests pass, as do scoped lint
and whitespace checks. This changes test synchronization rather than
loosening lock ownership or increasing production timeouts.
2026-09-18 16:40:25 +08:00
winewill 870b0099c6 fix(desktop): retain packaging errors and restore unconfigured proxies 2026-09-18 16:36:33 +08:00
creatixchu 13692e9179 test: refresh selective presentation prompt snapshots 2026-09-18 16:35:51 +08:00
Turtle de662ee010 fix(boot): skip failed profile bundles and retain recovery controls (#4516) 2026-09-18 16:35:50 +08:00
creatixchu 2e55564e02 fix: specify absolute paths for inline image rendering 2026-09-18 16:32:56 +08:00
creatixchu 28fbe7433d fix: guide selective file presentation through prompts 2026-09-18 16:31:13 +08:00
Yif a6267c8d90 fix(plugin-manager): per-instance artwork ids, detail error feedback, coverage
Give every plugin artwork per-instance SVG def ids via useId so repeats on
one page keep their gradients and clips; drop the dead agent-team-web-profile
artwork row; keep the read-failure alert and retry visible on detail pages;
cover the new artwork components and the default-artwork branch; document the
artwork exports in the ui-primitives READMEs; refresh the plugin-manager and
plugin-install-cancel web expected outputs for the revised copy.
2026-09-18 16:30:25 +08:00
creatixchu c19d1f12fb Merge remote-tracking branch 'origin/master' into worktree/present-changes-dedup 2026-09-18 16:26:45 +08:00
07akioni 54d46ad4d4 fix(desktop): unpack and verify native Office conversion 2026-09-18 16:25:29 +08:00
Tianyi Cui 959164f157 test(headless): align catalog diagnostic status with inactive state
Master's agent-target update reports non-running children as inactive. The
release-only descriptorless-child regression still expected ready, so CI
failed before comparing the persisted result. Update only that status in
the assertion and its expected output; direct catalog discovery and the
absence of corrupt-child diagnostics remain asserted.

The expected log retains version 3 and every other byte. A built assembled
headless run passes in normal comparison mode, preserving the older input
format and its upgrade/reconstruction coverage rather than refreshing the
snapshot generation.
2026-09-18 16:21:57 +08:00
winewill 6ed957ec33 Merge origin/master into perf/macos-packaging 2026-09-18 16:08:38 +08:00
Yichen Jiang 736730c3fd fix(web): allow closing pending plugin installations 2026-09-18 16:00:47 +08:00
Yif 92101e1a5b fix(ui-conversation): render the current crumb as text so the title joins the drag band
The current session's breadcrumb was a disabled button: the global darwin
no-drag rule subtracted it from the window drag band while its disabled state
and button user-select kept it from doing anything else, leaving the title a
dead zone that neither dragged the window nor selected. Plain text keeps the
native titlebar behavior — the title drags the window; ancestor crumbs stay
buttons.
2026-09-18 15:59:27 +08:00
CreatixChu bedcb7b58c Merge pull request #4373 from deepseek-harness/worktree/sidebar-open-in-default-app
为不支持预览的侧边栏文件提供本地打开操作
2026-09-18 15:59:19 +08:00
winewill fa6941971a Merge origin/master into perf/macos-packaging 2026-09-18 15:58:57 +08:00
Tianyi Cui c3cfe83d2e merge: update the session-log-v4 integration base from master
Merge a2acc7d3eb620bb52f09f7ea3b5a3a1c23353e18 after preserving the earlier
master checkpoint and its successful CI. Carry current provider input-history
handling, UI controls, agent targeting, and runner-concurrency changes into
the integration base without changing the Session migration feature layers.

Keep durable direct-child catalog semantics alongside the upstream running /
inactive vocabulary. Resolve the snapshot description conflicts by retaining
that upstream status text and the existing descendants-only diagnostic rule;
the source and all 53 JSON tool descriptions agree. Preserve parent-session
availability handling with the upstream stale-blank and batched-history fixes.

The merged application builds, all 41 documentation gates pass, and focused
provider, tool-control, and Session Controller tests pass (98, 29, and 125).
Recorded input changes come from master: one refreshed v3 list-agents sample
and three new v3 scenarios; no migration bumps an existing snapshot generation.
2026-09-18 15:52:56 +08:00
creatixchu e22005ae10 Sync session controller configuration catalog translation 2026-09-18 15:51:49 +08:00
creatixchu 1902842b6c Merge remote-tracking branch 'origin/master' into worktree/sidebar-open-in-default-app 2026-09-18 15:50:51 +08:00
winewill bba78f0534 Merge pull request #4514 from deepseek-harness/perf/windows-signature-cache
feat(desktop): share Windows runtime signature cache across worktrees
2026-09-18 15:48:55 +08:00
CreatixChu 4960abd402 Merge pull request #4371 from deepseek-harness/worktree/issue-4370-code-diff-sidebar
fix(web): 左右滚动同步
2026-09-18 15:40:22 +08:00
Yichen Jiang 66c1c5fadd fix(client): drop the sync-lag clause from the npmmirror registry line 2026-09-18 15:39:23 +08:00
winewill 545ccdb6f9 test(desktop): load proxy lock fixture from source 2026-09-18 15:37:33 +08:00
winewill 750bf4988e fix(desktop): initialize Windows cache under stage ownership 2026-09-18 15:37:05 +08:00
winewill 1a7308fbaa test(shell): synchronize background process completion 2026-09-18 15:37:05 +08:00
winewill 7754a6fd49 test(desktop): isolate Windows cache path from host platform 2026-09-18 15:37:05 +08:00
winewill d4ed1d93d8 feat(desktop): share Windows runtime signature cache across worktrees 2026-09-18 15:37:05 +08:00
creatixchu 363343fb83 Refresh config locations and satisfy typed fixture lint 2026-09-18 15:36:56 +08:00
Yichen Jiang e303efe017 fix(client): align an offered registry's line under its title
The indent meant for the typed address's field and line also reached
the line under each offered registry, pushing it past the title.
2026-09-18 15:36:41 +08:00
lsdsjyandlsdsjy 3e216c3d64 feat(ui-chat): add performance and usage display preference (#4478)
* feat(ui-chat): add performance and usage display preference

* fix(ui-chat): address performance preference review findings

* test(ui-chat): refresh Chinese turn footer snapshots

* docs(ui-chat): clarify completed-turn timing visibility

* test(ui-chat): capture preference failure screenshots

* fix(ui-chat): align performance preference with current icons

---------

Co-authored-by: lsdsjy <[email protected]>
2026-09-18 15:35:50 +08:00
creatixchu dd8c4b817b Keep fixture slot adapters explicitly typed 2026-09-18 15:33:47 +08:00
creatixchu ed4d95482b Assert the retained file action path in toolbar coverage 2026-09-18 15:32:55 +08:00
creatixchu 04d0235673 Verify local file opening and address sidebar review findings 2026-09-18 15:31:50 +08:00
Yifffan 54b76da126 Merge branch 'master' into feat/plugin-refine 2026-09-18 15:30:26 +08:00
fz 32524892a3 Merge origin/master into feat/workspace-dependencies-package 2026-09-18 15:27:45 +08:00
winewill 8dca1b7713 Merge master to synchronize desktop update dialogs 2026-09-18 15:27:03 +08:00
creatixchu 8f2a183514 fix(web): document paired column ref lifetime 2026-09-18 15:26:22 +08:00
creatixchu 12c0cbb56d Use document preview client config and shorten README summary 2026-09-18 15:24:51 +08:00
Yichen Jiang e06c7852ff Merge remote-tracking branch 'origin/master' into worktree/npm-registry-mirror-config-029a47 2026-09-18 15:24:42 +08:00
creatixchu 2cea45edc6 Remove duplicate guard from custom renderer fixture 2026-09-18 15:24:00 +08:00
creatixchu c538c4ec8f Adapt Office renderer fixture to file action slots 2026-09-18 15:23:13 +08:00
creatixchu 419d7c57c7 fix(web): make scroll frame callback return explicit 2026-09-18 15:23:00 +08:00
winewill 3bd8cfdf20 Merge pull request #4523 from deepseek-harness/fix/modal-backdrop-transition
fix(desktop): keep update dialog backdrop stationary across prompts
2026-09-18 15:22:22 +08:00
creatixchu 9e1635b6b6 Merge master and refresh sidebar file-opening integrations 2026-09-18 15:21:47 +08:00
Yichen Jiang 398a4247ae feat(client): pick and remember the registry a plugin install asks first
The install dialog folds a registry control beside the guide: the
official registry, the mirrors the Host configured, and a typed
address, remembered in this browser and passed to the check and the
run. The installing screen names the registry the Host moved on to,
each pnpm run carries its registry, and a failed run names every
registry asked, or the host a git or tarball spec could not reach,
with a shortcut back to the registry options. The Host answers the
spec's own host and the registries it asked so the dialog can say so.

Also documents the registry plan in the package READMEs, the boot
subsystem page, the catalogs, and an Agent Note; pins the flow through
a real Host/browser e2e and refreshes the tool-schema snapshots.
2026-09-18 15:21:44 +08:00
Yichen Jiang 716e2e2683 feat(plugin-manager): ask configured registries in turn while one is unreachable
Add registry and fallbackRegistries to the manager Config, ask them in
order from inspect and installBundle with --registry, and move on only
for failures another registry can change: unreachable, timed out, or a
copy the registry lacks. A git or tarball spec's own host is never
retried through a registry, and a registry outside the configured set
is asked alone. The lookup runs without pnpm's retries so a dead
registry is reported within inspectTimeoutMs; the install keeps pnpm's
defaults. Results carry the registries asked, the install-state event
names each attempt, and the plugin_manager tool takes a registry.
2026-09-18 15:21:44 +08:00
Yifffan a363f7b5af Merge branch 'master' into feat/plugin-refine 2026-09-18 15:21:20 +08:00
creatixchu cc9caed57b fix(web): type browser regression style cleanup as Node 2026-09-18 15:19:50 +08:00
winewill a051fed540 Merge latest master into perf/macos-packaging 2026-09-18 15:18:13 +08:00
creatixchu b5cbcad854 fix(web): preserve split diff scroll offsets across clamped peers 2026-09-18 15:17:13 +08:00
Yichen Jiang 3e206546fd Merge pull request #4351 from deepseek-harness/worktree/fix-new-session-stale-blank
fix(web): reconcile stale blank session hints from projections
2026-09-18 15:17:11 +08:00
winewill 7313e8dcc7 Merge master and fix desktop packaging proxy locking and checks 2026-09-18 15:17:03 +08:00
Yifffan 0c4f554d6e Merge branch 'master' into feat/plugin-refine 2026-09-18 15:16:13 +08:00
winewill 0c38f6fe43 Merge branch 'master' into fix/modal-backdrop-transition 2026-09-18 15:15:51 +08:00
creatixchu 79677e4824 Merge remote-tracking branch 'origin/master' into worktree/issue-4370-code-diff-sidebar 2026-09-18 15:15:11 +08:00
Yif e67aca993e docs(notes): align window-chrome notes and sidebar README with shipped drag ownership
The seat note claimed a plugin-manager inline clearance formula that never
shipped (entry pages pad by the unconditional --dsh-frame-top-clearance) and
omitted the 84px fullscreen clearance tier. The vibrancy note still called the
sidebar top strip a drag region after that declaration moved to the frame's
.leadingBand, said drag lives in "exactly two places" while the Windows caption
::before is a third, and lacked the dsh-desktop:window-fullscreen relay that
drives html[data-fullscreen]. The ui-sidebar README carried the same stale
top-strip drag claim. Chinese sides follow; pairings re-recorded.
2026-09-18 15:14:59 +08:00
Yichen Jiang ce4810cacb Merge pull request #4533 from deepseek-harness/worktree/custom-provider-url-placeholders
fix(web): match custom provider URL placeholders to protocol
2026-09-18 15:14:28 +08:00
Yif b42bb09420 Merge remote-tracking branch 'origin/master' into feat/plugin-refine 2026-09-18 15:10:18 +08:00
Kaige-Gao fa009c79e4 Merge master into feat/session-header-feedback 2026-09-18 15:10:02 +08:00
winewill 021a3c6065 Merge branch 'master' into fix/modal-backdrop-transition 2026-09-18 15:08:00 +08:00
fz ce09d8a293 Merge origin/master into feat/workspace-dependencies-package 2026-09-18 15:06:49 +08:00
Yichen Jiang 27eec0a247 Merge remote-tracking branch 'origin/master' into worktree/fix-new-session-stale-blank
# Conflicts:
#	packages/api/session-controller/README.i18n.yaml
#	packages/api/session-controller/README.md
#	packages/api/session-controller/README.zh.md
#	packages/api/session-controller/src/client/sessions/manager.ts
#	packages/api/session-controller/tests/manager.client.spec.ts
2026-09-18 15:05:52 +08:00
Turtle 2099andTurtle f83800530c fix(web): recolor the plan chip and align it with the control row (#4399)
* fix(web): make the plan chip a business-accent control at row height

The chip borrowed the warn-state pair for a plain mode flag, so it read as
a warning, and its 2px vertical padding left it 4px shorter than the + and
select controls beside it. It now uses the business accent pair, takes the
row's 28px height, and carries Chinese copy; the unused chip.off.*
dictionary entries had no surface and are dropped.

* docs(web): re-record the plan chip README pair

* docs(web): state the plan chip's close glyph and drop stale copy claims

The READMEs described the chip without the × the component renders, and the
zh side still quoted the English accessibility string after this branch gave
the namespace its own Chinese one.

* test(web): pin the plan chip's accent tokens, height, and Chinese copy

The lifecycle-chrome lane asserted the chip's warn pair; it now asserts the
business pair plus the 28px row height, and a zh plan-active golden records
the 「计划」 label the chip shows under the Chinese locale.

* fix(web): color claimed command tokens with the business accent

The draft's claimed token still used the warn label color while the plan chip
moved to the business pair, so a claimed /计划 read orange above a blue chip.
The claim decoration and the tests asserting its inline style now use
state-business-primary.

* fix(web): keep the composer control row on one line at narrow widths

The fixed-width mode chips and send circle left the row's 12px gaps deciding
between a slack first line and a wrapped trailing group: beside the plan chip,
a long model name moved the model trigger and send circle to a second line
while the first line still had room. Narrow rows now use 8px gaps, which holds
the row together down to the icon-only model trigger.

* fix(web): drop the context ring in the narrow composer row

With plan mode on and a long model name, the 28px occupancy ring plus its gap
was what pushed the trailing group onto a second line. The ring yields at the
same row width that already hides the access-mode label, so the fixed controls
keep one line; the reading stays reachable from a wider window.

---------

Co-authored-by: Turtle <[email protected]>
2026-09-18 15:04:54 +08:00
Yif c52400ad72 test(ui-primitives): count the new check-circle glyph in the icon set 2026-09-18 15:01:43 +08:00
Yichen Jiang 98c083bb31 fix(web): match custom provider URL placeholders to protocol 2026-09-18 15:01:24 +08:00
winewill 0c3eb28276 test(desktop): await mandatory overlay fade after policy clearance 2026-09-18 14:59:30 +08:00
winewill 72d93cbcc2 fix(desktop): reset scroll when replacing update prompts 2026-09-18 14:59:30 +08:00
winewill a666209a59 fix(desktop): fade mandatory update overlays in place 2026-09-18 14:59:30 +08:00
winewill 299101077a fix(desktop): keep update dialog backdrop stationary across prompts 2026-09-18 14:59:30 +08:00
fz b51e64d70e refactor(skill): flatten primary runtime version metadata 2026-09-18 14:57:12 +08:00
07akioni 3f5b1e283b Merge pull request #4464 from deepseek-harness/07akioni/fix-sessionless-sidebar-controls
fix(client): keep sidebar navigation available without a session
2026-09-18 14:55:25 +08:00
Yif 76fa3860c6 fix(plugin-manager): drop guide item background that surfaced in dark mode 2026-09-18 14:54:12 +08:00
Yif 3065e75d08 Merge remote-tracking branch 'origin/master' into feat/plugin-refine
# Conflicts:
#	packages/client/ui-plugin-manager/src/client/locales.ts
#	packages/client/ui-primitives/src/icons/index.tsx
2026-09-18 14:45:13 +08:00
Yichen Jiang b1cf410e0c Merge pull request #4520 from deepseek-harness/worktree/windows-observational-reuse
refactor(ci): reuse Windows builds for observational checks
2026-09-18 14:42:43 +08:00
_Kerman 8fe06cfb24 Merge pull request #3956 from deepseek-harness/xtr/tool-card-details
feat(web): render compact details for recorded tool results
2026-09-18 14:42:13 +08:00
fz b16b116408 Merge origin/master into feat/workspace-dependencies-package 2026-09-18 14:41:15 +08:00
Dudu-0223 eb570e306a Merge pull request #4251 from deepseek-harness/fix/4246-agent-targets
fix: expose Team targets and simplify model agent statuses
2026-09-18 14:39:52 +08:00
07akioni d6002c1018 Merge master and preserve compact conversation header layout 2026-09-18 14:39:32 +08:00
_Kerman 7bd832675a Merge latest master into xtr/tool-card-details 2026-09-18 14:34:46 +08:00
_Kerman 91679f8351 Merge remote-tracking branch 'origin/master' into xtr/fix-snapshot-source-ranges 2026-09-18 14:33:25 +08:00
Dudu-0223 66846bf8c0 test: refresh agent guidance in sidecars added on master
subagent-activation-limit and plugin-manager-mcp landed after this branch
diverged and still pinned the idle/ready descriptions; regenerate both
through their owners so every pinned header carries the shipped text.
2026-09-18 14:29:35 +08:00
Dudu-0223 cda99db4c0 docs: align remaining agent availability prose with the shipped vocabulary
Sync the pinned schedule-catalog tool-schema sidecar with the refreshed
list_agents, send_message, subagent, and subagent_fork descriptions; the
catalog e2e does not compare it, so the refresh missed it. Rewrite the
Agent Teams note's Steer sentence and the ownership-release limitation so
`idle` no longer appears where the roster vocabulary is running/inactive,
and fix the two-clause comma splice and a zh full-width spacing slip.
2026-09-18 14:29:35 +08:00
Dudu-0223 563d040d23 test: refresh subagent guidance in plugin manager snapshot 2026-09-18 14:29:35 +08:00
Dudu-0223 b9e59cbaee refactor: unify Team availability in the service 2026-09-18 14:29:35 +08:00
Dudu-0223 8b6831daa0 test: refresh agent guidance embedded in PTC prompts 2026-09-18 14:29:35 +08:00
Dudu-0223 507e0e6dfe fix: expose Team targets and simplify model agent statuses 2026-09-18 14:29:35 +08:00
Yif e509dd9341 fix(client): pulse an app-region nudge at the right panel's open/close edges
Electron recollects window drag rects only when a style or layout pass
dirties an app-region value, and Blink skips hidden boxes when collecting
them, so the first open of the slid-off panel left the strip swallowed by
the drag band until an unrelated layout ran.
2026-09-18 14:28:12 +08:00
Yif 9ae6f0defa fix(client): mount the shell.leading seat on macOS only and cover the fullscreen relay 2026-09-18 14:28:07 +08:00
Yichen Jiang ed50586256 refactor(ci): remove unused Windows observational entry 2026-09-18 14:27:45 +08:00
imccyu 21e31ac05e Merge pull request #4494 from deepseek-harness/perf/chat-navigation-history
perf(chat): 虚拟化轮次导航并聚合历史跳转
2026-09-18 14:21:32 +08:00
winewill 5ef7023b6c perf(desktop): cache verified macOS runtime signatures 2026-09-18 14:15:47 +08:00
imccyu 462c354792 test(web): await both subagent settings saves 2026-09-18 14:13:48 +08:00
imccyu 6f66437de4 fix(ui-chat): prioritize submissions over pending scroll samples 2026-09-18 14:13:48 +08:00
imccyu d53c305224 fix(ui-chat): preserve turn rail follow and preview behavior 2026-09-18 14:13:48 +08:00
imccyu 8f62fc8ebd test(web): separate rail wheel input from keyboard preview assertions 2026-09-18 14:13:48 +08:00
imccyu 0a8702b216 docs: record chat navigation performance and ownership decisions 2026-09-18 14:13:47 +08:00
imccyu 3d360e7fdb perf(session-controller): publish historical jump pages as one batch 2026-09-18 14:13:47 +08:00
imccyu e22b0d75e8 refactor(ui-chat): separate viewport and scroll navigation policies 2026-09-18 14:13:47 +08:00
imccyu f89cd786aa perf(ui-chat): virtualize fixed-pitch turn navigation 2026-09-18 14:13:47 +08:00
Yichen Jiang 235db2a031 Merge remote-tracking branch 'origin/master' into worktree/windows-observational-reuse
# Conflicts:
#	.github/workflows/ci.yml
2026-09-18 14:13:26 +08:00
Tianyi Cui 1dd0ec6ac5 test(web): retain fork snapshot coverage with decorative icons
The release-only mid-turn fork scenario retained the old accessibility
children after master switched common icons to decorative presentation.
Refresh its expected tree from the built scenario: the same top-level
button names, failure text, parent/child prompts, and response remain.
Only redundant icon and label children disappear.

CI reproduced the mismatch. All four fork cases pass after refresh and
again in normal comparison mode. A mechanical comparison confirms that
removing nested children and their now-unused parent colons is the entire
expected-output change. The recorded Session generations and production
code are untouched.
2026-09-18 14:13:20 +08:00
Yichen Jiang 965e2c2995 Merge pull request #4512 from deepseek-harness/worktree/messages-input-history-compat
fix(llm): tolerate assistant blocks in Messages input history
2026-09-18 14:10:47 +08:00
Turtle 5459be6656 ci: halve core-seconds in static and Windows observational lanes (#4521)
* ci: trial smaller Blacksmith static and observational runners

* ci: measure the 16-vCPU control for runner sizing

* ci: use 4-vCPU static and 8-vCPU observational runners

* ci: retain 8-vCPU static runner for completion time
2026-09-18 14:01:46 +08:00
Yif bd6447479d refine(plugin-manager): polish install dialog guide, input, and wizard states 2026-09-18 14:00:50 +08:00
Yichen Jiang a116bf73c6 Merge master and name combined Windows checks 2026-09-18 13:41:06 +08:00
_Kerman b53fda5961 Merge latest master into xtr/tool-card-details 2026-09-18 13:33:54 +08:00
Yif 02bb08ecd9 fix(client): compensate menu fills for the blur the transparent window disables 2026-09-18 13:33:00 +08:00
Yif 8072511aad fix(client): subtract dockkit strip runs and pane bodies from the macOS drag band 2026-09-18 13:32:55 +08:00
Yif e44345c044 test(desktop): stub syncWindowFullscreen in preload-platform mocks 2026-09-18 13:32:53 +08:00
Yichen Jiang 51d8c45413 Merge pull request #4477 from deepseek-harness/worktree/unify-agent-team-bundle
fix(agent-team): enable tools and Web UI with one bundle
2026-09-18 13:21:45 +08:00
Tianyi Cui 4375f6cd83 test(web): align catalog button snapshot with decorative icons
The latest master hides the catalog chevron from the accessibility tree.
The release-only catalog-push snapshot still expected that image child,
although the button retains its complete "2 subagents" accessible name.
Refresh that expected output after the actual built Web scenario; its
recorded Session input and all interaction assertions remain unchanged.

The old expectation failed against the merged application. The refresh
changed only this three-line snapshot, and the normal read-only rerun
passed all 11 subagent conversation cases with every replay call consumed.
2026-09-18 13:21:30 +08:00
Turtle 9d5fc30632 ci: adapt concurrency to available runner CPUs (#4518)
* ci: adapt worker pools to available runner CPUs

* ci: preserve local snapshot worker defaults

* test: isolate CI worker overrides in gate fixtures

* docs: clarify shared Windows worker limits
2026-09-18 13:17:34 +08:00
Yichen Jiang 46f7ab097f refactor(ci): reuse Windows builds for observational checks 2026-09-18 13:14:35 +08:00
Tianyi Cui 8306ddaa14 merge: refresh session-log-v4 base from master
Merge master 0fdadce5189dcf13a00c2ed8293be95b9bb29c2c into the reviewed
Session V4 integration base. Preserve its V4 persistence and direct-catalog
subagent navigation while carrying forward current UI controls, decorative
icons, Desktop signing/runtime changes, and upstream tests.

Resolve lineage conflicts by retaining interaction-time catalog authority,
known-leaf handling and row order together with the shared status icons.
Keep both Desktop shell-routing regressions and one production route; master
now includes the route repair previously carried by this integration branch.

The full build, 41 documentation gates, two Desktop shell tests and 34 focused
Client lineage tests pass. Further built Web and packaging checks precede
publication. Preserve this pinned merge checkpoint before taking a newer
master tip, and propagate it through the reorganized feature stack.
2026-09-18 13:11:25 +08:00
Yichen Jiang 19e6e7b81b test(agent-team): verify browser activation and document bundle composition 2026-09-18 12:53:31 +08:00
Turtle de742f7f45 Prune active Agent Notes and preserve historical archive formatting (#4431) 2026-09-18 04:50:47 +00:00
_Kerman 9ee0d1257b test(session-snapshot): cover source-reference projection directly 2026-09-18 12:44:35 +08:00
Yichen Jiang 5daaaea3c0 Merge pull request #4457 from deepseek-harness/worktree/plan-tab-text-icon
fix(web): align plan sidebar with file previews
2026-09-18 12:41:32 +08:00
Yichen Jiang ae180d1d24 test(llm): document Messages input compatibility limits 2026-09-18 12:40:44 +08:00
Yudong Han fee816628f Merge pull request #4506 from deepseek-harness/fix/office-font-warning
fix(web): move Office font warnings into the document toolbar
2026-09-18 12:34:15 +08:00
Yichen Jiang 231798102a Merge remote-tracking branch 'origin/master' into worktree/unify-agent-team-bundle 2026-09-18 12:32:38 +08:00
Yichen Jiang 732f198cf4 Merge remote-tracking branch 'origin/master' into worktree/plan-tab-text-icon
# Conflicts:
#	apps/web/tests/expected/plan-review/temporary.expected.md
#	packages/client/ui-plan/src/client/PlanPreview.tsx
#	snapshots/web/plan-review/preview.expected.md
2026-09-18 12:31:05 +08:00
Turtle 3164e3c616 ci: right-size Blacksmith runners by workload (#4489)
* ci: right-size Blacksmith runners by workload

* ci: retain static runner capacity supported by utilization

* ci: retain observational runner for peak CPU and memory demand

* ci: restore Windows build to 16 vCPU after runtime regression

* ci: trial 4-vCPU runtime packaging to reduce CPU time allocation

* ci: trial 2-vCPU Linux packaging and serial Windows tests

* ci: include Windows packaging in 2-vCPU trial
2026-09-18 12:28:51 +08:00
Yif fd04c0c4be feat(client): make the macOS sidebar wordmark a window-drag surface
On darwin the expanded brand renders as a plain span instead of the New
Session shortcut button, so it stops matching the global interactive
no-drag rule and inherits the logo row's drag region; the dedicated New
Session button keeps the action.
2026-09-18 12:25:05 +08:00
winewill 1e390797e8 Merge branch 'refactor/desktop-update-domain-config' into perf/mac-packaging-timing 2026-09-18 12:08:57 +08:00
yudshj da37b69fb9 Merge master into fix/office-font-warning 2026-09-18 12:07:58 +08:00
yudshj 19736552c0 fix(web): align Office font warning with shared toolbar styles 2026-09-18 12:03:54 +08:00
Yif b9bc99b675 Merge origin/master (#4451 developer tools setting)
The view tab strip keeps the data-conversation-tabs marker on upstream's
showTabs condition, so the deepened drag band follows the compact header.
2026-09-18 12:01:55 +08:00
std4453 215226753d Merge pull request #4451 from deepseek-harness/feat/developer-tools-preference
feat(client): add shared developer tools setting
2026-09-18 12:00:10 +08:00
Yif 994e998b7d feat(client): deepen the conversation drag band to the header block
While the Conversation is selected and its header shows the view tab strip,
the macOS window drag band grows from 52px to the 76px header block (title
row plus tab strip), so blank header space drags. The band matches the
strip's data-conversation-tabs marker via :has, so a compact header (single
view, per #4451's developer-tools setting) falls back to the 52px strip.
2026-09-18 11:59:45 +08:00
winewill 76a592e3ab refactor(desktop): configure test policy login origins 2026-09-18 11:57:56 +08:00
winewill e0264148b0 perf(desktop): configure macOS packaging concurrency and retain phase logs 2026-09-18 11:54:54 +08:00
fz 4d34cd87dd fix(skill): address shared runtime review findings 2026-09-18 11:52:04 +08:00
_Kerman 449c679892 fix(session-snapshot): expand source references before writing fixtures 2026-09-18 11:47:09 +08:00
Yichen Jiang 82c6a5e4f4 fix(llm): tolerate assistant blocks in Messages input history 2026-09-18 11:44:40 +08:00
fz 3ebd70020c Merge origin/master into feat/workspace-dependencies-package 2026-09-18 11:42:26 +08:00
Yif c8b17dd4d0 refine(plugin-manager): per-plugin artwork, trailing load-failure notice, friendlier copy 2026-09-18 11:38:45 +08:00
Yif d66b9c81b1 fix(desktop): drop superseded preload.ts after merge
Upstream removed the standalone plugin manager and replaced this bridge
with preload-app.ts; the fullscreen sync it carried already lives there.
2026-09-18 11:36:21 +08:00
Yichen Jiang dd8d39c843 Merge remote-tracking branch 'origin/master' into worktree/unify-agent-team-bundle
# Conflicts:
#	packages/experimental/agent-team-profile/package.json
#	packages/experimental/agent-team-web-profile/package.json
2026-09-18 11:34:21 +08:00
07akioni 21c347913d fix(client): preserve sessionless header geometry across platforms 2026-09-18 11:30:37 +08:00
Yif e9def243e2 Merge origin/master into feat/macos-sidebar-ui-and-drag-refine
Keeps both window-chrome features: this branch's macOS shell.leading seat,
single drag owner, and fullscreen sync alongside upstream's Windows desktop
titlebar (#4407). ipc.ts and preload-app.ts merge both platforms' channels
and preload wiring; Tooltip merges upstream's suppression context with this
branch's pointer-focus suppression; slot-catalog regenerated.
2026-09-18 11:27:06 +08:00
07akioni e0c8b1dfca Merge remote-tracking branch 'origin/master' into 07akioni/fix-sessionless-sidebar-controls
# Conflicts:
#	packages/client/ui-conversation/README.i18n.yaml
#	packages/client/ui-conversation/README.md
#	packages/client/ui-conversation/README.zh.md
2026-09-18 11:23:23 +08:00
Yif 8019d37d3f feat(client): frame-owned macOS window chrome with single drag owner
One 52px leadingBand in the AppFrame (frame's first child) plus the sidebar
logoRow are the only -webkit-app-region drag surfaces; everything interactive
subtracts itself through two global base.css rules (interactive elements and
body > :not(#root) overlay portals), so header controls, breadcrumb chips, and
strip tabs stay clickable under the band. A ui-theme stylesheet gate pins the
two-file drag allowlist. The frame publishes --dsh-frame-top-clearance (48px)
for entry pages (plugin manager list and detail) beside the existing
--dsh-frame-leading-clearance, replacing per-page hardcoded insets. The
shell.leading window-chrome seat moves the collapsed-sidebar reopen controls
from the conversation header to the frame. Sidebar vibrancy tint drops the
blue cast in dark mode and halves its fill opacity, light mode softens the
blue mix, and the logo row tightens 4px above New Session.
2026-09-18 11:08:13 +08:00
yudshj 9b27cc0587 fix(web): move Office font warnings into the document toolbar 2026-09-18 11:06:09 +08:00
zhc fb2be52104 fix(client): compact conversation headers without view tabs 2026-09-18 11:03:07 +08:00
zhc 4429a672b7 refactor(client): keep developer preference in settings scope 2026-09-18 11:03:06 +08:00
zhc caaaf89b1e fix(client): separate developer tool policy and harden static previews 2026-09-18 11:03:06 +08:00
zhc 54e6aabf0c test(client): cover developer tools row settings injection 2026-09-18 11:03:06 +08:00
zhc 07e3619ec3 test(web): enable developer tools in trajectory image fixture 2026-09-18 11:03:06 +08:00
zhc 012f993ed4 fix: address developer tools preference review 2026-09-18 11:03:06 +08:00
zhc cdaafbc456 feat(client): add shared developer tools setting 2026-09-18 11:03:05 +08:00
winewill 831ea36f2c Merge pull request #4461 from deepseek-harness/ihsiang/unify-web-ui-visual-language
Unify the Web UI visual language
2026-09-18 11:00:11 +08:00
winewill bf34d10e23 Merge pull request #4455 from deepseek-harness/fix/windows-native-dependency-signing
fix(desktop): sign native dependencies, cache signatures and restore startup dialogs
2026-09-18 09:26:22 +08:00
Tianyi Cui 863ffe83a6 test(desktop): type the application path mock as string
The shell asset regression substitutes a real package path through getAppPath, but the shared test harness inferred only the literal desktop-test-app. Vitest executed the test successfully while the repository TypeScript build rejected the path override.

Declare the mock return type as string to match Electron getAppPath and permit both fixture and real package paths. This changes only test typing; it adds no casts or production behavior. The focused production-routing regression passes after the correction.
2026-09-18 02:00:08 +08:00
Tianyi Cui 64c669fc79 fix(plan): open embedded plan previews in the visible sidebar
A child conversation rendered in a parent Sidebar keeps the child Session identity for reading its plan. Routing navigation through openResourceIn(child) confused that document identity with the layout owner: a child with no adopted Sidebar store silently opened nothing, and an existing child store was invisible.

Use the mounted Sidebar navigation service for both logged and temporary plan previews. Keep the complete child Session resource address, so reads and reload still target the correct document. A real-controller regression adopts only the visible parent store and proves both child entry points populate it without creating child layout state; it fails before the fix.

All 47 ui-plan owner tests and all four built Web plan-review cases pass, along with the full build, scoped typed lint, and bilingual pairing. No Session event, stored document, fixture generation, or resource-address format changed.
2026-09-18 01:56:04 +08:00
Tianyi Cui 13cbe34fc0 docs(subagent): use the registered sidebar chat address
The imported conversation note names a chat resource host that the current parser rejects. The provider is registered under subagentchat and its existing helpers and reference documentation use that host. Correct both language examples without changing addresses, parsing, or persisted layouts.
2026-09-18 01:53:37 +08:00
Tianyi Cui 12e3d45cdc fix(desktop): stop copying the retired management preload
The workspace-update qualification runner still copied lib/preload.cjs after the standalone management preload and its build entry were removed. A clean Desktop build emits only the application, mandatory-update, and update-dialog preloads, so qualification failed with ENOENT before Electron could start; stale outputs could conceal that failure.

Remove only the obsolete copy-list entry. Keep all three current preloads required and retain ordinary copy failures. Executing the actual copy loop against artifacts from a fresh isolated Desktop build now copies exactly those three files byte-for-byte while lib/preload.cjs is absent; the same loop failed at that missing file before this change.
2026-09-18 01:53:37 +08:00
Tianyi Cui 8ae136f402 fix(desktop): serve shell-owned update assets
Ordinary and mandatory update windows still load dsh-app://shell documents after the standalone plugin manager was removed. The production protocol handler handled only the app hostname, so their existing HTML, scripts, and styles returned 404; mandatory-load failure deliberately retains the modal block.

Route the shell hostname to the packaged renderer directory through the existing static-asset helper. Retain its GET/HEAD, path-containment, MIME, and missing-file rules; keep isolated preloads and owned-window IPC authorization unchanged.

The regression imports the real main entry, captures its registered protocol callback, and reads all seven actual update assets through the real static helper. It fails with 404 before the fix and passes afterward, including HEAD, rejected methods, malformed paths, traversal, and unknown resources. Sixteen adjacent static/dialog/overlay tests pass, and the Desktop package builds from a fresh worktree.
2026-09-18 01:53:37 +08:00
Tianyi Cui 371c804336 test(cli): run the headless profile through source and built launchers
The expected-output CI lane sets DSH_EXAMPLE_MODE=lib. Selecting tsx/esm
alone did not exercise the source bin there, and the compatibility test
only checked --help, so removing source profile link resolution could
silently restore duplicate source/lib Tools instances in a green CI run.

Run the existing real headless-profile tool round trip explicitly in both
src and lib modes. The explicit mode overrides the CI environment default;
the source case uses the supported tsx/esm entry. Both cases retain the
real profile, shell tool, persisted Session assertions, stdout, and stderr
expectations, with isolated temporary directories. No recorded generation
or output normalization changes are needed.

After a full build, both cases pass with DSH_EXAMPLE_MODE=lib. Negative
control: removing only the source bin link-resolution selection makes the
source case fail at scheduler.prepare while the built case still passes.
Restoring the implementation makes both cases pass again. Scoped lint
passes. This puts the regression in the existing post-build expected-output
CI lane without adding artifact requirements to compatibility-only jobs.
2026-09-18 01:53:37 +08:00
Tianyi Cui 8b5a78e9ac test(loader-smoke): observe the forwarded source hook in the child
The success fixture can run under either tsx hook, so its previous output
assertions stayed green when runLoaderSmoke stopped forwarding sourceImport.
Line coverage therefore did not protect the supported ESM-only launcher.

Include the actual child process execArgv in the fixture output and assert
the resolved tsx/esm hook requested by the caller. The regression observes
Node launch arguments rather than reproducing the helper implementation.
Align the optional sourceImport spread with the adjacent mode spread;
this keeps the same behavior for defined and absent values.

Negative control: removing forwarding passed the old test but failed the
new assertion because the child loaded tsx/dist/loader.mjs instead of
esm/index.mjs. With forwarding restored, all 25 loader-smoke tests pass
and src/index.ts retains 100% statement, branch, function, and line coverage.
Scoped lint passes.
2026-09-18 01:53:37 +08:00
Tianyi Cui 6205c2be70 test(web): wait for both Subagent settings saves
The shared Subagent card submits the model-selection and limits namespaces
independently. The model-selection write can finish first, so its presence
in settings.yaml does not establish that maxDepth has reached disk. CI
observed subagent: {} with the completed model allowlist at that point.

Move the existing exact-label disabled Save wait before the persistence
assertions. The form uses a distinct Saving label until every namespace
save finishes, so this observes the shared operation's completion before
checking both results. Retain every assertion, timeout, and expected file.

A diagnostic barrier on the real subagent settings mutation reproduced the
original missing-maxDepth failure with both correct requests recorded and
the form still saving. With the relocated wait, releasing that same write
persisted maxDepth without another user action. The barrier run passed all
10 cases, and the unchanged whole plugin-config Web suite also passed 10/10.
2026-09-18 01:41:08 +08:00
winewill 6088ac7a85 perf(desktop): cache verified Windows signatures and isolate timestamps 2026-09-18 01:15:59 +08:00
Tianyi Cui 335c5cbe26 fix(cli): keep source profile imports in one module graph
The runtime profile default is correct for installed applications, but the
supported TypeScript CLI also runs tsx workspace aliases. In that launch,
profile resolution loaded both packages/core/tools/src/index.ts and
packages/core/tools/lib/index.js. The ToolRuntime instance and agent-loop
consumer therefore held different private TOOL_RUNTIME_SCHEDULER symbols;
the first tool call failed while reading scheduler.prepare.

The source bin now explicitly selects linked profile resolution using its
own .ts module identity. Built and packaged launches keep runtime resolution,
and explicit runProfile overrides remain unchanged. No service or symbol
identity is widened to conceal duplicate module instances.

Forward the existing sourceImport option through runLoaderSmoke and select
tsx/esm for headless source snapshots. This exercises the actual supported
source-launch vector while retaining the same recorded Session and expected
outputs. The loader-smoke subprocess test covers forwarding that hook.

Evidence: the official tsx/esm compaction replay failed before the fix while
loading both Tools module URLs. After the fix it loads only src/index.ts and
prints COMPACTION RECOVERED. The same focused replay passes under both
DSH_EXAMPLE_MODE=src and lib after rebuilding Host artifacts. The 43 CLI and
loader tests passed, including runtime defaults and explicit link/dual/runtime
overrides. Loader-smoke coverage passed 25 tests with 100% statements,
branches, functions, and lines. Host build, full lint, and all 41 doc-sync
gates passed. Recorded JSONL generations and snapshot normalization are
unchanged; temporary diagnostics were removed from built artifacts.
2026-09-18 00:06:26 +08:00
Tianyi Cui 7e42e8aa65 fix(release): align V4 migration package with master version
The pinned master merge updates the DSH package family to 0.1.6-alpha.2, but the release-only V3-to-V4 migration package has no master counterpart to carry that manifest change. Match the family package version so installed artifacts and hygiene describe one release identity. Session format remains V4; migration schemas, committed generations, and snapshot input versions do not change.

The combined source passes the full build, 93 Client tests, 631 persistence tests with one skip, all 41 documentation gates, all 16 hygiene gates, and full lint. The original pinned-master merge checkpoint remains in history.
2026-09-17 23:28:32 +08:00
Tianyi Cui d66b21894c merge: integrate latest master into session-log-v4
Merge master 62b700bba7bb71e66d2d5a3b850ba8f4dd0fd6b4 into release/session-log-v4 at 4825bc01a999f564e79172a6af28e34fc757c540. Preserve this pinned integration checkpoint before any later upstream movement so the dependent session-format repairs have an immutable rebase base.

Keep release projection-backed child catalogs, independent Session references, exact fork behavior, V4 writer, and existing migration data. Adapt the incoming subagent sidebar chat to refreshProjections rather than the removed dedicated catalog API, preserve title projections in complete projection fixtures, and retain both sidebar actions and release lineage/status behavior. Remove the duplicate SessionProjectionMap import introduced by automatic merging.

Preserve both disjoint archive seals without changing any existing hash. Regenerate current Cordis and documentation catalogs from the combined source, retaining release session methods plus master slot factories. The frozen V0-V3 runtime paths are unchanged. Initial validation passed the full build, 93 focused Client tests, and all 1905 archived artifact seals; remaining integration and snapshot checks follow on this checkpoint.
2026-09-17 23:23:48 +08:00
Tianyi Cui b6156b90fe Merge pull request #4389 from deepseek-harness/worktree/merge-master-session-v4-20260917-2
merge: sync master into session-log-v4
2026-09-17 23:03:02 +08:00
yixiangihsiang 0f7a507fbd test(web): assert stopped summary tone 2026-09-17 21:41:12 +08:00
winewill aa181c66e5 fix(desktop): preserve unpacked PE files and target runtime descriptors 2026-09-17 21:31:34 +08:00
winewill 702f9e4ff1 Restore desktop shell dialogs and guard destroyed windows on exit 2026-09-17 21:31:33 +08:00
winewill 3d2876f046 Run packaged smoke with production profile resolution 2026-09-17 21:31:32 +08:00
winewill 4d46bff152 Normalize dependency metadata before sealing desktop runtime 2026-09-17 21:31:32 +08:00
winewill 5a409fc771 fix(desktop): sign all Windows native dependencies before packaging 2026-09-17 21:31:31 +08:00
yixiangihsiang 938436e7bc fix(web): preserve tool-specific stopped summaries 2026-09-17 21:28:44 +08:00
CreatixChu ddefc45fbc Merge pull request #4469 from deepseek-harness/worktree/release-dsh-0.1.6-alpha.2
release(dsh): 0.1.6-alpha.2
2026-09-17 21:19:19 +08:00
yixiangihsiang 870388e2c0 test(web): refresh file link snapshot 2026-09-17 21:17:02 +08:00
fz be8040d042 test(sdk): align Office checks with runtime profile resolution 2026-09-17 21:15:55 +08:00
fz ef4a7efa91 Merge origin/master into feat/workspace-dependencies-package 2026-09-17 21:11:58 +08:00
creatixchu 6b1808f432 release(dsh): 0.1.6-alpha.2 2026-09-17 21:11:19 +08:00
imccyu 8dfc6fe1ec Merge pull request #4471 from deepseek-harness/worktree-resolutionmode
feat(cli): use runtime resolution for plain Node launches
2026-09-17 21:11:11 +08:00
fz 8fad9ccd8c feat(skill): complete shared Office runtime builds for SDK carriers 2026-09-17 21:10:12 +08:00
yixiangihsiang 488e438277 fix(web): address review feedback 2026-09-17 21:04:42 +08:00
imccyu e68f5d5aba fix: test 2026-09-17 20:59:38 +08:00
Yichen Yan e699b482fe Merge branch 'yyc/web-trust-domain-reviewed' into yyc/web-relative-routes-reviewed 2026-09-17 20:56:41 +08:00
Yichen Yan 8256c84630 chore(docs): regenerate the Cordis catalog after merging master 2026-09-17 20:48:53 +08:00
imccyu d9a55c7c0d fix: revert desktop 2026-09-17 20:47:27 +08:00
imccyu 1bfe2c4559 fix: test 2026-09-17 20:46:35 +08:00
Yichen Jiang 9f21d7842a fix(agent-team): enable tools and Web UI with one bundle 2026-09-17 20:41:39 +08:00
imccyu 896f0b7ec5 fix: budget doc 2026-09-17 20:26:04 +08:00
Yichen Yan 8e93da68f3 test(web): pin route-gate violations by line and match feature routes exactly
The gate spec asserts line and rule per violation instead of counts; the
open-in-app fake carriers match the relative route exactly so a re-absolutized
route cannot pass; the root and mount cases of the markdown file route share
one table; a fixture echo of its own icon URL is dropped.
2026-09-17 20:24:49 +08:00
imccyu 0ea890044f test(cli): cover runtime profile defaults and sync docs 2026-09-17 20:23:14 +08:00
Yichen Yan d607e185ad Merge branch 'yyc/web-trust-domain-reviewed' into yyc/web-relative-routes-reviewed 2026-09-17 20:21:54 +08:00
Yichen Jiang 02dbcc3ef3 Merge remote-tracking branch 'origin/master' into feat/plugin-detail-slots 2026-09-17 20:17:19 +08:00
Yichen Yan 9ed3d642e1 test(web): tighten the public-mount fence and drop unused fixture branches
Any request outside the mount is an escape, not only same-origin ones; the
socket presence check is superseded by the frame polls; the redirect landing
is asserted by pathname. The scaffold's unused mount host option, hostFetch
mount routing, and the proxy's bare-mount redirect had no caller.
2026-09-17 20:16:58 +08:00
Yichen Jiang caa0c99be1 docs(web): follow up the review on the companion move and detail slots
The maintained docs now name the four companion packages where they
still credited `ui-settings-plugins`: the web-app row comment, the
Plugins page README, the ui-settings README, and the client group
README, which gains a row per companion. The ui-settings README states
the `whileServed` lifetime and disposer ownership beside `bind`, and the
JSDoc says the caller owns the disposer. The settings-page cookbook
keeps the one home of the lazy-CJS build limitation for packages outside
this repository, its JSX example is a tsx fence, and the architecture
index and website label follow the page's title. The Agent Note records
the shell page's `plugins.item` id, the two companions that use
`ctx.remote` list api-remotes in `dsh.client.inject`, and the moved form
model test speaks of the form.
2026-09-17 20:13:26 +08:00
Yichen Jiang fd01a407b2 test(web): update plan preview snapshots after removing copy button 2026-09-17 20:12:42 +08:00
Yichen Yan b62a9f5c27 Merge branch 'master' into yyc/web-trust-domain-reviewed 2026-09-17 20:09:23 +08:00
imccyu 9ddef327a4 feat: resolution mode link to runtime 2026-09-17 20:08:51 +08:00
Yichen Jiang 29126c0a32 fix(web): align plan preview copy controls with Markdown files 2026-09-17 19:57:18 +08:00
07akioni 1628e911c8 fix(client): keep sidebar navigation available without a session 2026-09-17 19:38:57 +08:00
yixiangihsiang 4937343a5e feat(web): unify the client visual language 2026-09-17 19:14:41 +08:00
imccyu 9e3a30f85a Merge pull request #4417 from deepseek-harness/feat/subagent-sidebar-chat
feat(client): open subagent chats in sidebar
2026-09-17 18:17:10 +08:00
fz 6e49ccad18 feat(skill): extract the workspace-dependencies tool into a package
Move `load_workspace_dependencies` and the primary-runtime payload logic out
of `apps/desktop-host` into `@deepseek-ai/dsh-tool-workspace-dependencies`
so profiles other than Desktop can mount the same tool. Desktop keeps its
behavior through the package.

Two additions for carriers that are not Electron applications:

- `root` is optional: without it the payload is validated and used in place
  (no copy under the Harness home), which suits read-only container layers.
- `runtime.json` accepts `linux`, and the `node` / `pnpm` components are
  optional; the returned paths and the tool output omit what the payload
  does not ship.

The `sdk` profile mounts the tool and `@deepseek-ai/dsh-skill-office` when
`DSH_PRIMARY_RUNTIME` names a payload directory (its sibling `office-skills/`
carries the skill resources); both rows stay disabled otherwise. Both
packages join the Python runtime closure.
2026-09-17 18:16:47 +08:00
imccyu d05b42980b refactor(client): move sidebar chat to subagent 2026-09-17 18:04:02 +08:00
imccyu 49b9ccbfcd fix(client): preserve round sidebar action 2026-09-17 18:04:02 +08:00
imccyu 34a43129a6 fix(session-reference): preserve title fallback 2026-09-17 18:04:02 +08:00
imccyu 871f332971 fix(client): keep sidebar integration optional 2026-09-17 18:04:02 +08:00
imccyu c6c3ad935d test(client): cover sidebar chat edge paths 2026-09-17 18:04:02 +08:00
imccyu 4f38c60797 fix(client): satisfy sidebar chat gates 2026-09-17 18:04:02 +08:00
imccyu 3e136c2f30 docs: refresh module graph 2026-09-17 18:04:02 +08:00
imccyu da7dc34f7d fix(client): align subagent sidebar references 2026-09-17 18:04:01 +08:00
imccyu e62587c163 feat(client): open subagent chats in sidebar 2026-09-17 18:03:57 +08:00
Yichen Jiang 93e67201dd refactor(web): move the official settings pages into companion packages
Each official settings page now lives in a client package of its own:
`ui-settings-shell`, `ui-settings-agent-loop`, `ui-settings-subagent`
and `ui-settings-web-search` register into `plugins.item` while the Host
serves their namespaces, through the new `settingsScope.whileServed`
watch, each with its own dictionary and styles. The form model, the
fields and the form move to `ui-primitives` as the shared settings kit,
so a community package's browser half builds a page the same way.
`ui-settings-plugins` keeps only the Built-in plugins section shell
around the inventory tab.

The companions hold Loader rows in `web-app` behind the section; the
client catalog, config catalog and module graph regenerate; the
settings-card cookbook walks through a companion package.
2026-09-17 17:59:12 +08:00
Yichen Jiang a815a7f2a9 feat(web): open action, badge and section slots on plugin detail pages
The Plugins page declares three list slots as children of its main
entry: `plugins.detail.actions` renders at the head of a detail page
before its switch and uninstall controls, `plugins.detail.badge` after
the tags beside the title, and `plugins.detail.section` below the page's
own content. Every entry receives a `subject` owner prop naming what the
open page is about — a bundle, one row of a bundle, or an official item —
so one entry serves any page and renders nothing elsewhere. A row's page
still opens only for rows with a `plugins.row.config` entry.

The `plugin-config` web lane drives the three slots through the live
fixture on its bundle page and its row page, records a new bundle
golden, and shows the fixture contributing nothing to an official page.
2026-09-17 17:58:29 +08:00
Jiawei Song 04bab1cbd2 Merge pull request #4408 from deepseek-harness/fix/trajectory-attachments
fix(web): unify trajectory attachment presentation
2026-09-17 17:55:02 +08:00
Yichen Jiang 0495ad9846 fix(web): use the plain text file icon for plan tabs 2026-09-17 17:52:08 +08:00
Yichen Jiang 3958f801e3 Merge pull request #4414 from deepseek-harness/worktree/plan-sidebar-cards
feat(web): keep plan artifacts and automatically open sidebar previews
2026-09-17 17:49:08 +08:00
Yichen Jiang 3fb29e0803 fix(web): identify plan preview tabs with a plan icon 2026-09-17 17:31:34 +08:00
sjw1231 4f3f737996 merge(web): sync master for trajectory attachments 2026-09-17 17:31:00 +08:00
Yichen Jiang 5b1a2d8613 Merge pull request #4250 from deepseek-harness/feat/docs-platform-command-tabs
feat(docs): 增加 Python SDK 平台命令标签
2026-09-17 17:23:50 +08:00
Yichen Jiang 38bfc29876 fix(web): restore the plain plan review status dot 2026-09-17 17:22:28 +08:00
Turtle 2099 65648082a3 feat(web): reveal a clipped sidebar session title on hover (#4423)
* feat(web): reveal a clipped sidebar session title on hover

A session title wider than its sidebar row is clipped with an ellipsis, so a
long parent title hides the `(1)` that distinguishes its fork. Hovering the row
now scrolls the title to its far edge and returns it to the start when the
pointer leaves. The title stays an `overflow: hidden` scrollport, so nothing
reflows and no scrollbar appears; `scroll-behavior: smooth` supplies the motion
(reduced motion keeps the jump), and the hovered row clips instead of
ellipsizing because a scrolled box still paints the ellipsis over the revealed
characters.

Covered by the row component spec, the stylesheet contract spec, and a new
keyless Chromium scenario that hovers a seeded clipped row in the assembled
application and asserts the reached scroll extent.

* fix(web): return the revealed session title in one step

Review follow-up on the hover reveal:

- Return the title to its start with `scrollTo({ behavior: 'instant' })` instead
  of a smooth scroll. A smooth return carried the resting ellipsis and the
  narrowing cell over the travelling text for its whole duration.
- Scope `scroll-behavior: smooth` to `.sessionRow .title` so Workspace rows are
  untouched, and fold the reduced-motion reset into the file's existing block.
- Guard the hover-only `text-overflow: clip` with `@media (hover: hover)`: a
  touch tap latches `:hover` after the title has already returned, which would
  otherwise strand that row without its ellipsis.
- Pin the contract in the browser scenario: computed `scroll-behavior` is
  `smooth` by default and `auto` under reduced motion, and the return lands
  inside one step. Add the unit case for the explicit instant return.
2026-09-17 17:19:29 +08:00
Yichen Jiang 9d93fbd7ad Merge remote-tracking branch 'origin/master' into worktree/plan-sidebar-cards
# Conflicts:
#	packages/client/ui-deliverables/README.i18n.yaml
#	packages/client/ui-deliverables/README.md
#	packages/client/ui-deliverables/README.zh.md
2026-09-17 17:18:51 +08:00
Dudu-0223 f28c654799 Merge pull request #4255 from deepseek-harness/issue-3997-markdown-file-links
feat(web): open file references with concise location labels
2026-09-17 17:15:13 +08:00
gengruilin 4ab1fc3bfe Merge master into feat/docs-platform-command-tabs 2026-09-17 17:11:07 +08:00
Dudu-0223 4bdacc5f2a Merge branch 'master' into issue-3997-markdown-file-links 2026-09-17 17:06:33 +08:00
Dudu-0223 953bdc9854 Merge master after code block preview rollback 2026-09-17 17:01:22 +08:00
Turtle 2d36ac3369 Merge pull request #4380 from deepseek-harness/turtle/master-ci-git-config
fix(workspace-changes): ignore scrubbed ambient Git config
2026-09-17 16:57:11 +08:00
sjw1231 70ba425ba2 docs(web): remove raw disclosure reset guarantees
Refs #4356
2026-09-17 16:53:50 +08:00
Turtle ad9a4c37a2 Merge pull request #4436 from deepseek-harness/turtle/agent-note-creation-threshold
docs: require lasting rationale before creating agent notes
2026-09-17 16:53:01 +08:00
Yichen Jiang 3d345d27bc Merge branch 'worktree/jobs-api-review-3052' into worktree/jobs-api-review-3127 2026-09-17 16:52:55 +08:00
sjw1231 03f93dc2a5 revert(web): remove raw disclosure reset on record selection
Refs #4356
2026-09-17 16:52:41 +08:00
Turtle 7d383f1fb9 Merge pull request #4426 from deepseek-harness/turtle/remove-enabled-dot-5feeef8fab26
refactor(web): drop the duplicate plugin-list status dot
2026-09-17 16:52:39 +08:00
Yichen Jiang 0d734a8fe7 fix(jobs): adapt desktop update checks to session callers 2026-09-17 16:52:09 +08:00
Yichen Jiang de617e2d0b Merge branch 'worktree/jobs-api-review-3052' into worktree/jobs-api-review-3127 2026-09-17 16:50:14 +08:00
Yichen Jiang 4b299845e0 Merge remote-tracking branch 'origin/master' into worktree/jobs-api-review-3052 2026-09-17 16:49:48 +08:00
Yichen Jiang eae08a9745 Merge origin/master into worktree/plan-sidebar-cards 2026-09-17 16:49:40 +08:00
Yichen Jiang c2fb2bd4e8 Merge branch 'worktree/jobs-api-review-3052' into worktree/jobs-api-review-3127
# Conflicts:
#	.agents/notes/implemented/feature/2026-08-08-web-background-job-display.i18n.yaml
#	docs/config-catalog.i18n.yaml
#	docs/event-producer-consumer.i18n.yaml
#	docs/module-graph.i18n.yaml
#	docs/subsystems/jobs.i18n.yaml
#	docs/subsystems/shell.i18n.yaml
#	docs/subsystems/shell.md
#	docs/subsystems/shell.zh.md
#	docs/tool-catalog.i18n.yaml
#	packages/api/session-controller/README.i18n.yaml
#	packages/context/tmux-context/tests/tmux-context.spec.ts
#	packages/e2b/e2b/tests/fixtures/composition/bin.ts
#	packages/extensions/tool-cordis/src/api-catalog.ts
#	packages/shell/bash-local/README.i18n.yaml
#	packages/shell/bash-local/README.md
#	packages/shell/bash-local/README.zh.md
#	packages/shell/bash-local/src/index.ts
#	packages/shell/bash-local/tests/executor.spec.ts
#	packages/shell/bash-sandbox/README.i18n.yaml
#	packages/shell/bash-sandbox/README.md
#	packages/shell/bash-sandbox/README.zh.md
#	packages/shell/bash-sandbox/src/index.ts
#	packages/shell/bash-sandbox/tests/bwrap.e2e.ts
#	packages/shell/bash-sandbox/tests/landlock.e2e.ts
#	packages/shell/bash-sandbox/tests/partial-landlock.spec.ts
#	packages/shell/bash-sandbox/tests/sandbox.spec.ts
#	packages/shell/bash-sandbox/tests/seatbelt.e2e.ts
#	packages/shell/pwsh-local/README.i18n.yaml
#	packages/shell/pwsh-local/README.md
#	packages/shell/pwsh-local/README.zh.md
#	packages/shell/pwsh-local/src/index.ts
#	packages/shell/pwsh-local/tests/executor.spec.ts
#	packages/shell/pwsh-sandbox/README.i18n.yaml
#	packages/shell/pwsh-sandbox/README.md
#	packages/shell/pwsh-sandbox/README.zh.md
#	packages/shell/pwsh-sandbox/src/index.ts
#	packages/shell/pwsh-sandbox/tests/sandbox.spec.ts
#	packages/shell/shell/README.i18n.yaml
#	packages/shell/shell/README.md
#	packages/shell/shell/README.zh.md
#	packages/shell/shell/src/index.ts
#	packages/shell/shell/tests/service.spec.ts
#	packages/shell/tool-bash/README.i18n.yaml
#	packages/shell/tool-bash/src/index.ts
#	packages/shell/tool-bash/tests/tools.spec.ts
#	packages/shell/tool-pwsh/README.i18n.yaml
#	packages/shell/tool-pwsh/src/index.ts
#	packages/shell/tool-pwsh/tests/background.spec.ts
#	packages/shell/tool-pwsh/tests/tools.spec.ts
#	packages/workflow/tool-workflow/README.i18n.yaml
#	packages/workflow/tool-workflow/package.json
#	packages/workflow/tool-workflow/tests/tool-workflow.spec.ts
#	snapshots/session/ptc-python-turn/system-prompt.expected.md
2026-09-17 16:48:06 +08:00
Yichen Jiang 46b4f94802 fix(web): preview unlogged plans and preserve subagent history addresses 2026-09-17 16:44:34 +08:00
imccyu a4452b2ed2 Merge pull request #4442 from deepseek-harness/revert-3906-perf/code-block-preview-renders
Revert "feat(client): optimize code block previews and source highlighting"
2026-09-17 16:41:25 +08:00
Kaige-Gao 9ce43f925c feat(web): add feedback to session header menu 2026-09-17 16:40:13 +08:00
Dudu-0223 4c546124b9 refactor(web): route Markdown file navigation through delegate provider 2026-09-17 16:39:53 +08:00
imccyu e0427f38e9 Restore sealed diagram preview note 2026-09-17 16:39:23 +08:00
Turtle 93e8139e23 Merge pull request #4439 from deepseek-harness/turtle/trim-delegate-ci-message
chore(ci): trim delegate review dismissal message
2026-09-17 16:34:52 +08:00
imccyu 81e05abaab Revert "feat(client): optimize code block previews and source highlighting" 2026-09-17 16:31:47 +08:00
Yichen Jiang 5ad77a9532 Merge remote-tracking branch 'origin/master' into worktree/jobs-api-review-3052
# Conflicts:
#	packages/api/remotes/src/client/index.ts
2026-09-17 16:30:09 +08:00
winewill 45b5b53c23 Merge pull request #4033 from deepseek-harness/feat/desktop-update
feat(desktop): 普通更新、强制升级与 Windows 安装体验
2026-09-17 16:29:18 +08:00
Dudu-0223 5bb7d45e66 Merge master and preserve Markdown file links with previews 2026-09-17 16:25:25 +08:00
Yichen Jiang d2b277286f refactor(jobs): drop unrelated client refactors 2026-09-17 16:24:12 +08:00
Turtle adce1b4b5c docs: preserve mechanical and local edit exemptions 2026-09-17 16:23:18 +08:00
winewill 3cbb9442fa Fix Desktop async window-state lint 2026-09-17 16:19:02 +08:00
Turtle 926534c44b docs: keep agent note criteria edits minimal 2026-09-17 16:18:11 +08:00
Turtle f2c5c2a6a2 chore(ci): trim delegate review dismissal message 2026-09-17 16:17:28 +08:00
Turtle 730bcc7c85 docs: require lasting rationale before creating agent notes 2026-09-17 16:11:04 +08:00
winewill 064d8f8670 Merge origin/master into feat/desktop-update 2026-09-17 16:11:00 +08:00
sjw1231 5530e1b821 merge(web): sync master for trajectory attachments
Refs #4356
2026-09-17 16:09:29 +08:00
Yichen Jiang 5d173b170d test(web): strengthen plan dismissal checks and clarify review contracts 2026-09-17 16:09:29 +08:00
winewill 954184934a Remove obsolete Desktop lint suppressions 2026-09-17 16:08:05 +08:00
winewill 721e2e13c7 Merge origin/master into feat/desktop-update 2026-09-17 16:07:27 +08:00
Yichen Jiang 8c3ec757df Merge remote-tracking branch 'origin/master' into worktree/plan-sidebar-cards
# Conflicts:
#	packages/client/ui-user-questions/src/client/PlanReviewPanel.tsx
#	packages/extensions/cordis-client-runner/src/client/slot-catalog.ts
2026-09-17 16:05:19 +08:00
Yichen Jiang 80c0a5c1e8 test(voice-input): complete waking state fixture 2026-09-17 16:05:13 +08:00
Yichen Jiang 9644155c4e fix(voice-input): handle capture failures and queued wakeups 2026-09-17 16:03:02 +08:00
Yichen Yan 29182514ed fix(web): resolve feature routes from the document directory and gate browser routes 2026-09-17 16:00:36 +08:00
Yichen Yan eeb9b03465 feat(web): serve the shell, API and plugin resources from the document directory 2026-09-17 16:00:15 +08:00
Yudong Han 9ec34c00fe Merge pull request #3906 from deepseek-harness/perf/code-block-preview-renders
feat(client): optimize code block previews and source highlighting
2026-09-17 15:56:41 +08:00
07akioni 67a04b4768 Merge pull request #4425 from deepseek-harness/feat/remove-desktop-plugin-debug
refactor(desktop): remove standalone plugin manager
2026-09-17 15:52:59 +08:00
winewill e03f58c6e9 fix(desktop): close update review copy and documentation gaps 2026-09-17 15:52:57 +08:00
sjw1231 9836c4daaf docs(web): describe trajectory thumbnail status feedback
Refs #4356
2026-09-17 15:45:33 +08:00
sjw1231 70b4237c00 fix(web): keep trajectory thumbnail status readable
Refs #4356
2026-09-17 15:44:43 +08:00
Yichen Jiang 2394816cc1 test(web): snapshot the plan review summary and two actions 2026-09-17 15:44:00 +08:00
Turtle f91d5e310d refactor(web): drop the plugin-list dot for an active fiber
A collapsed plugin card carried both an enablement tag and a green root-fiber
status dot; for the common `active` phase the two stated the same settled
state. The dot now renders only for `pending`, `loading` and `unloading`,
the phases the enablement tag cannot state, and the expanded card keeps the
phase fact.

Related to #4424
2026-09-17 15:41:58 +08:00
winewill 72f5fcc905 Merge remote-tracking branch 'origin/master' into feat/desktop-update 2026-09-17 15:38:13 +08:00
Yichen Jiang 7de3757bad feat(web): show a concise plan summary in the review card 2026-09-17 15:37:13 +08:00
Yichen Jiang f3644dcdf3 fix(voice-input): keep waveform below recording controls 2026-09-17 15:37:07 +08:00
yudshj 34bc53eff8 perf(client): defer offscreen diagram previews 2026-09-17 15:34:33 +08:00
yudshj bd1904da0e test(web): refresh Thinking code block controls snapshot 2026-09-17 15:34:32 +08:00
yudshj aaa62b09dc fix(web): reject Mermaid image nodes before layout 2026-09-17 15:34:32 +08:00
yudshj 63b5403a43 fix(web): keep preview failures readable and trim unrelated scope 2026-09-17 15:34:31 +08:00
yudshj 078e11389a test(web): update shared code action accessibility snapshots 2026-09-17 15:33:58 +08:00
yudshj 9b9a60f439 fix(client): size chat previews from diagrams and defer source rendering 2026-09-17 15:33:58 +08:00
winewill 21887adc00 Merge origin/master into feat/desktop-update 2026-09-17 15:33:25 +08:00
imccyu 5100350d9b Merge pull request #4379 from deepseek-harness/worktree-sidebrowser
feat(web): add Sidebar Browser tabs
2026-09-17 15:28:39 +08:00
07akioni 8c81181bce fix(desktop): align plugin cleanup notes and cover profile locks 2026-09-17 15:28:16 +08:00
Yichen Jiang 0055d993fc docs(voice-input): clarify setup and cover microphone permissions 2026-09-17 15:24:49 +08:00
Yichen Jiang 11637ac48e test(web): place plan cards after the completed reply 2026-09-17 15:24:11 +08:00
Yichen Jiang 30b951f929 Merge remote-tracking branch 'origin/master' into worktree/plan-sidebar-cards
# Conflicts:
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
2026-09-17 15:21:35 +08:00
07akioni 3caff6dba4 Merge master and preserve desktop plugin manager removal 2026-09-17 15:20:49 +08:00
Yichen Jiang 577e4a036d fix(web): collect submitted plans in the final turn artifacts 2026-09-17 15:18:35 +08:00
winewill 25b6f868ca fix(desktop): classify update failures and refresh recovered Host 2026-09-17 15:18:02 +08:00
imccyu 80f90e61d3 fix(client): handle Sidebar Browser navigation fallbacks 2026-09-17 15:14:12 +08:00
imccyu 9637a4d051 test(web): open inline-code links in Sidebar Browser 2026-09-17 15:14:12 +08:00
imccyu 3dff3813d8 fix(client): align Sidebar Browser security docs 2026-09-17 15:14:12 +08:00
imccyu 45958f12df docs(client): update Sidebar Browser behavior 2026-09-17 15:14:11 +08:00
imccyu ef1218ac24 feat(client): refine Sidebar Browser controls 2026-09-17 15:14:11 +08:00
imccyu 8968fedec2 feat(client): open message links in Sidebar Browser 2026-09-17 15:14:11 +08:00
imccyu 66edeb85af docs(client): document Sidebar Browser 2026-09-17 15:14:10 +08:00
imccyu 1e42aec10e feat(web): ship Sidebar Browser 2026-09-17 15:14:10 +08:00
imccyu 9fed351d3d feat(client): add Sidebar Browser 2026-09-17 15:14:10 +08:00
07akioni c0489984ff Merge pull request #4407 from deepseek-harness/07akioni/windows-desktop-titlebar
feat(desktop): integrate Windows caption navigation and localized menus
2026-09-17 15:12:34 +08:00
Yichen Jiang 0c374357dd Merge pull request #4419 from deepseek-harness/worktree/web-context-meter-footer
feat(web): move context usage into composer stats
2026-09-17 15:11:49 +08:00
Dudu-0223 cf06315851 Merge pull request #4317 from deepseek-harness/feat/subagent-limit-settings
feat(subagent): configure delegation limits in the GUI
2026-09-17 15:10:44 +08:00
07akioni f14efb220d Merge remote-tracking branch 'origin/master' into feat/remove-desktop-plugin-debug
# Conflicts:
#	.agents/notes/archived/manifest.json
2026-09-17 15:06:31 +08:00
07akioni 4b6474133a refactor(desktop): remove standalone plugin manager 2026-09-17 15:02:59 +08:00
Dudu-0223 646aadc52c fix(client): clarify Subagent capacity help text 2026-09-17 14:59:43 +08:00
Yichen Jiang d34628703a Merge remote-tracking branch 'origin/master' into worktree/web-context-meter-footer 2026-09-17 14:57:42 +08:00
Yudong Han 0e5ec6defa Merge pull request #4041 from deepseek-harness/office-sidebar-preview
feat(preview): consume shared Office conversion in sidebar
2026-09-17 14:57:23 +08:00
imccyu 1d6ef883db Merge pull request #4359 from deepseek-harness/worktree-slotfactory
feat(client): add reusable component factories
2026-09-17 14:52:11 +08:00
Yichen Jiang ae4fc751eb fix(web): keep composer context details within the viewport 2026-09-17 14:49:30 +08:00
Yichen Jiang 0d5ef60789 Merge pull request #4420 from deepseek-harness/worktree/hide-builtin-profile-bundles
fix(web): hide built-in profile bundles from plugin cards
2026-09-17 14:48:40 +08:00
yudshj afe85c1cfd fix(preview): preserve PDF text layer rotation 2026-09-17 14:43:30 +08:00
Yichen Jiang 05e675863b fix(web): hide built-in profile bundles from plugin cards 2026-09-17 14:40:29 +08:00
winewill bd49c6e58b Merge branch 'master' into feat/desktop-update 2026-09-17 14:40:23 +08:00
Yichen Jiang a096637d01 test(web): cover automatic plan previews on narrow screens 2026-09-17 14:40:08 +08:00
Dudu-0223 0dbe49a893 test(web): settle complete folder queries before drilling 2026-09-17 14:38:24 +08:00
Yichen Jiang e68bc539b8 test(web): snapshot artifact-style plans and automatic previews 2026-09-17 14:35:19 +08:00
Yichen Jiang 1e1dd43fee feat(web): open submitted plans automatically with artifact cards 2026-09-17 14:31:22 +08:00
winewill e8a3bc701a fix(desktop): verify installed update ASAR runtime layout 2026-09-17 14:28:23 +08:00
Yichen Jiang 5ccf1c57d2 fix(voice-input): align CI fixtures and source-only coverage 2026-09-17 14:23:25 +08:00
Dudu-0223 5c507b12c6 test(web): refresh Subagent summary in plugin manager snapshots 2026-09-17 14:23:12 +08:00
Dudu-0223 fae11e6dc1 Merge master into PR 4317 and adapt Subagent configuration page 2026-09-17 14:23:12 +08:00
yudshj 10dc97ca04 test(preview): cover retries while resource is unavailable 2026-09-17 14:18:49 +08:00
Yichen Jiang 472ddfa7ae fix(web): align plan card borders and cover review identity 2026-09-17 14:15:51 +08:00
Yichen Jiang 7e12403d84 fix(voice-input): reduce recording action icon sizes 2026-09-17 14:11:11 +08:00
07akioni 3f41c6c02f fix(desktop): defer caption menus until the application mounts 2026-09-17 14:06:14 +08:00
imccyu 7852631012 fix(client): regenerate slot catalog 2026-09-17 14:06:14 +08:00
imccyu c094b663fb feat(client): add reusable component factories 2026-09-17 14:06:14 +08:00
winewill d1585abdd9 fix(desktop): release mandatory modal on install quit and bind DPAPI upload target 2026-09-17 14:04:15 +08:00
Yichen Jiang b6726fe79d feat(web): move context usage into composer stats 2026-09-17 13:59:25 +08:00
07akioni e36bdaa914 fix(desktop): preserve caption editing and navigation across overlays 2026-09-17 13:58:51 +08:00
Turtle 7e392f7616 Merge pull request #4400 from deepseek-harness/turtle/web-picker-agent-instructions
docs: pin browse picker for agent Web automation
2026-09-17 13:58:43 +08:00
Yichen Jiang 913fca0187 Merge remote-tracking branch 'origin/master' into worktree/plan-sidebar-cards 2026-09-17 13:58:33 +08:00
Yichen Jiang 018c0e5156 fix(voice-input): align dictation toolbar controls 2026-09-17 13:57:51 +08:00
yudshj 4de7612f39 refactor(preview): keep renderer loading format independent 2026-09-17 13:53:18 +08:00
Yichen Jiang ab834ac667 test(web): cover plan resource cancellation and sidebar bindings 2026-09-17 13:46:41 +08:00
Yichen Jiang 8d37a43316 Merge remote-tracking branch 'origin/master' into worktree/experimental-voice-input 2026-09-17 13:45:00 +08:00
winewill 12c9c86547 Merge branch 'master' into feat/desktop-update 2026-09-17 13:42:21 +08:00
Yichen Jiang f6428a164e feat(web): keep submitted plans in chat and open them in sidebar 2026-09-17 13:39:31 +08:00
Dudu-0223 6dad87b417 Merge master and preserve file links with compact Markdown 2026-09-17 13:37:06 +08:00
Dudu-0223 7c55730a97 chore: move file-reference evaluation to personal repository 2026-09-17 13:36:02 +08:00
Yichen Jiang 9d0f475a47 fix(voice-input): keep preparation status in plugin details 2026-09-17 13:33:38 +08:00
Dudu-0223 c2190c4588 Merge pull request #4372 from deepseek-harness/feat/subagent-settings-ui
feat(web): unify Subagent settings UI
2026-09-17 13:31:09 +08:00
Yichen Jiang 23d21e2fde fix(voice-input): restore cached readiness and preserve composer controls 2026-09-17 13:28:26 +08:00
07akioni e62a0e3e5d fix(desktop): explain listener conflicts with exit and restart recovery 2026-09-17 13:27:19 +08:00
sjw1231 641253e730 merge(web): sync latest trajectory markdown changes
Refs #4356
2026-09-17 13:25:05 +08:00
yudshj bbd5fa2cf4 refactor(preview): align Office content discriminant 2026-09-17 13:12:02 +08:00
sjw1231 f27e9bf37b merge(web): sync master for trajectory attachments
Refs #4356
2026-09-17 13:06:04 +08:00
Tianyi Cui a6d7195e53 Merge pull request #4390 from deepseek-harness/worktree/fix-4187-thinking-markdown
fix(web): render Thinking with compact Markdown
2026-09-17 13:03:04 +08:00
yudshj ab0f04cbac refactor(preview): name Office loading mode explicitly 2026-09-17 13:02:15 +08:00
winewill eb10557199 test(desktop): pin supported platform in startup tests 2026-09-17 13:01:32 +08:00
yudshj 2e779cafca refactor(preview): let Office own document loading 2026-09-17 12:52:13 +08:00
07akioni 502c67d3bf Merge remote-tracking branch 'origin/master' into 07akioni/windows-desktop-titlebar
# Conflicts:
#	apps/desktop/src/main.ts
#	apps/desktop/tests/main-startup.spec.ts
2026-09-17 12:40:55 +08:00
Yichen Jiang 8d62caf7fa Merge remote-tracking branch 'origin/master' into worktree/experimental-voice-input 2026-09-17 12:40:38 +08:00
Yichen Jiang 47ae64ee68 feat(voice-input): add optional local SenseVoice dictation 2026-09-17 12:39:53 +08:00
sjw1231 f176327afc docs(web): record implemented trajectory attachment presentation
Refs #4356
2026-09-17 12:35:14 +08:00
sjw1231 9119f14522 fix(web): reset raw attachment disclosures on record selection
Refs #4356
2026-09-17 12:34:49 +08:00
Tianyi Cui 85022b5c46 merge: sync Office conversion from latest master 2026-09-17 12:33:52 +08:00
winewill 38d375070f test(desktop): use native file URL for login placeholder 2026-09-17 12:32:06 +08:00
winewill fed28b6245 test(desktop): keep publisher test source-plane only 2026-09-17 12:19:48 +08:00
07akioni 5c2cc19efd feat(desktop): integrate Windows caption navigation and localized menus 2026-09-17 12:11:09 +08:00
yudshj 1c9f2e3a1f Merge master into office-sidebar-preview 2026-09-17 12:05:47 +08:00
winewill ddc1e28e17 test(desktop): cover update indicator fallback states 2026-09-17 12:05:43 +08:00
_Kerman 83b2ff7aa1 fix(client): preserve tool detail navigation and layout 2026-09-17 12:04:19 +08:00
_Kerman f32c0cc3d9 refactor(client): simplify recorded tool detail models 2026-09-17 12:03:41 +08:00
Tianyi Cui 490a79c693 fix(client): release replaced sidebar store adoptions 2026-09-17 11:57:25 +08:00
Turtle c885d9f862 docs: pin browse picker for agent web automation 2026-09-17 11:55:54 +08:00
yudshj 880c186146 refactor(document): consolidate Office preview remotes 2026-09-17 11:52:46 +08:00
winewill 6f79f40892 Merge remote-tracking branch 'origin/master' into feat/desktop-update 2026-09-17 11:36:18 +08:00
winewill 593db4e0b7 test(desktop): stub update listeners in host disconnect fixture 2026-09-17 11:36:05 +08:00
_Kerman 566be5ae1b Merge latest origin/master into xtr/tool-card-details 2026-09-17 11:35:39 +08:00
sjw1231 212f5f9ccc test(web): cover trajectory attachment presentation
Refs #4356
2026-09-17 11:33:29 +08:00
_Kerman 68825ecc57 Merge origin/master into xtr/tool-card-details 2026-09-17 11:32:23 +08:00
Tianyi Cui 2fb2a5cc65 merge: sync desktop menus and startup diagnostics from master 2026-09-17 11:31:06 +08:00
ZiyaZhang 6affc44992 fix(web): update Subagent parallelism copy 2026-09-16 20:31:03 -07:00
Yudong Han 6130eac6b7 Merge pull request #4282 from deepseek-harness/office/render-cache
feat(document): shared office-to-pdf conversion with bounded queues and caching
2026-09-17 11:29:41 +08:00
winewill 371054b072 chore(release): restore merge-target prerelease version 2026-09-17 11:27:24 +08:00
_Kerman b91c96c5ee fix(client): avoid duplicate expanded tool receipt statuses 2026-09-17 11:21:33 +08:00
_Kerman cba87e84d5 fix(client): distinguish recorded tool status colors 2026-09-17 11:21:11 +08:00
Tianyi Cui 27389e0899 fix(client): preserve unmounted settings and composer ownership 2026-09-17 11:19:07 +08:00
winewill a5528b02a3 Merge remote-tracking branch 'origin/master' into feat/desktop-update
# Conflicts:
#	apps/desktop/src/main.ts
#	apps/desktop/tests/main-startup.spec.ts
2026-09-17 11:16:45 +08:00
yudshj 12302ac6c3 refactor(workspace-files): keep bounded reads within readAll 2026-09-17 11:15:52 +08:00
yudshj b911efef39 refactor(workspace-files): reuse bounded reads and return raw Host bytes 2026-09-17 11:15:51 +08:00
yudshj e30a391326 docs(office-to-pdf): link the bounded conversion decision 2026-09-17 11:15:51 +08:00
yudshj 773d743bce docs(office-to-pdf): clarify conversion and engine package ownership 2026-09-17 11:15:51 +08:00
yudshj 11669006e6 refactor(document): consolidate Office conversion into office-to-pdf 2026-09-17 11:15:51 +08:00
yudshj 43839d1209 docs(document): refresh shared conversion module graph 2026-09-17 11:15:36 +08:00
yudshj a69639a200 fix(document): select Office engines from declared native targets 2026-09-17 11:15:36 +08:00
yudshj a193b51c96 refactor(document): name Office PDF conversion explicitly 2026-09-17 11:15:36 +08:00
yudshj 9d2a3bf2b7 feat(document): decouple shared Office conversion from preview 2026-09-17 11:15:21 +08:00
Yichen Jiang 321bce2627 Merge remote-tracking branch 'origin/master' into worktree/jobs-api-review-3052
# Conflicts:
#	packages/api/session-controller/src/client/sessions/manager.ts
#	packages/api/session-controller/src/client/sessions/service.ts
#	packages/api/session-controller/tests/manager.client.spec.ts
#	packages/api/session-controller/tests/sessions-service.client.spec.ts
#	packages/client/locale/tests/language-row.client.spec.tsx
#	packages/client/ui-chat/tests/chat-view.client.spec.tsx
#	packages/client/ui-chat/tests/transcript-view-row.client.spec.tsx
#	packages/client/ui-conversation/tests/conversation-registry.client.spec.ts
#	packages/client/ui-conversation/tests/enter-behavior-row.client.spec.tsx
#	packages/client/ui-conversation/tests/input-bar.client.spec.tsx
#	packages/client/ui-conversation/tests/skeleton.client.spec.tsx
#	packages/client/ui-deliverables/tests/deliverables.client.spec.tsx
#	packages/client/ui-jobs/tests/job-list-action.client.spec.tsx
#	packages/client/ui-layout/tests/app-frame.client.spec.tsx
#	packages/client/ui-layout/tests/document-title.client.spec.tsx
#	packages/client/ui-session/tests/ui-session.client.spec.ts
#	packages/client/ui-settings-unarchive-sessions/tests/components.client.spec.tsx
#	packages/client/ui-subagent/tests/conversation-ui.client.spec.tsx
#	packages/client/ui-theme/tests/appearance-row.client.spec.tsx
#	packages/client/ui-theme/tests/font-size-row.client.spec.tsx
#	packages/client/ui-tool/tests/coverage-tails.client.spec.tsx
#	packages/client/ui-tool/tests/diff-card.client.spec.tsx
#	packages/client/ui-tool/tests/read-card.client.spec.tsx
#	packages/client/ui-tool/tests/terminal-card.client.spec.tsx
#	packages/client/ui-trajectory/tests/views.client.spec.tsx
#	packages/client/ui-user-questions/tests/plan-review-panel.client.spec.tsx
#	packages/client/ui-user-questions/tests/user-questions-composer.client.spec.tsx
#	packages/client/ui-workflow-run/tests/workflow-run.client.spec.tsx
#	packages/client/ui-workspace/tests/tree.client.spec.ts
#	packages/client/ui-workspace/tests/workspace-browser.client.spec.tsx
#	packages/client/ui-workspace/tests/workspace-picker.client.spec.tsx
#	packages/client/ui-workspace/tests/workspaces-service.client.spec.ts
#	packages/test-support/client-runtime/src/sessions.ts
2026-09-17 11:11:25 +08:00
Turtle e7a4621aa9 Merge pull request #4362 from deepseek-harness/turtle/startup-diagnostics
fix(cli): group startup failures and pending services
2026-09-17 11:09:21 +08:00
winewill a11b0a218c Merge branch 'codex/desktop-test-package-20260916' into feat/desktop-update
# Conflicts:
#	packages/client/ui-deliverables/package.json
#	packages/client/ui-directory-picker-native/package.json
#	packages/extensions/tool-cordis/package.json
2026-09-17 11:05:11 +08:00
sjw1231 1da97f30f8 fix(web): unify trajectory attachment presentation
Refs #4356
2026-09-17 11:03:04 +08:00
turtle1999 a9b7491cf8 fix(boot): keep startup metadata out of ordinary error output 2026-09-17 10:55:23 +08:00
Turtle b4a60c8471 Merge pull request #4375 from deepseek-harness/turtle/orchestrator-3576650b674f
fix(desktop): declare the standard macOS window menus
2026-09-17 10:54:45 +08:00
winewill c06d2719d0 merge: sync latest master into desktop updates 2026-09-17 10:48:32 +08:00
Tianyi Cui c840ac431d fix(client): settle preset selections and isolate generation stores 2026-09-17 10:43:21 +08:00
Dudu-0223 51e9e1599d fix(web): address file-reference review feedback 2026-09-17 10:38:09 +08:00
Dudu-0223 453348fcef Merge remote-tracking branch 'origin/master' into codex/issue-3997-citations
# Conflicts:
#	packages/client/ui-deliverables/README.i18n.yaml
#	packages/client/ui-deliverables/README.md
#	packages/client/ui-deliverables/README.zh.md
2026-09-17 10:33:22 +08:00
Tianyi Cui 039415d5a4 fix(web): preserve compact math and inspector typography 2026-09-17 10:18:42 +08:00
Tianyi Cui fa3e5cbaf6 fix(client): preserve state across Session reference updates 2026-09-17 09:38:24 +08:00
Tianyi Cui 7d9166ea40 fix(web): keep Thinking tables below the collapse header 2026-09-17 09:37:14 +08:00
Tianyi Cui e5038fcf9e fix(web): render Thinking with compact Markdown 2026-09-17 09:17:34 +08:00
Tianyi Cui 5c25efba91 merge: integrate Client Session references into session-log-v4 2026-09-17 08:59:42 +08:00
yudshj f9aa94a161 refactor(preview): pass raw Office bytes and share source checks 2026-09-17 08:47:51 +08:00
yudshj e39a6a48ea Merge branch 'codex/office-decouple-conversion' into codex/office-decouple-preview 2026-09-17 08:45:22 +08:00
yudshj fdd8197674 refactor(workspace-files): reuse bounded reads and return raw Host bytes 2026-09-17 08:44:54 +08:00
imccyu f0aebe0d8b Merge pull request #4368 from deepseek-harness/refactor/client-session-references
refactor(client): own Session generations with explicit references
2026-09-17 05:52:30 +08:00
imccyu 2438bdd4d6 docs(client): document explicit Session ownership 2026-09-17 05:28:58 +08:00
imccyu 6d3b5d4526 test(client): migrate Session reference coverage 2026-09-17 05:28:19 +08:00
imccyu b9b14dc05e refactor(client): bind Session UI through providers 2026-09-17 05:28:06 +08:00
imccyu 1bf048eb71 refactor(gateway): retain Session contexts through dispatch 2026-09-17 05:27:36 +08:00
imccyu 6830e1460d refactor(session-controller): own Client Session generations 2026-09-17 05:27:26 +08:00
imccyu c52ef9fada feat(client): add ownership lifecycle primitives 2026-09-17 05:27:15 +08:00
Tianyi Cui a23331ba17 Merge pull request #4382 from deepseek-harness/worktree/session-log-v4-master-4304-20260917
merge: integrate subagent capacity settings into session-log-v4
2026-09-17 01:23:33 +08:00
Tianyi Cui 2d94201ef1 merge: integrate subagent capacity settings into session-log-v4 2026-09-17 01:14:07 +08:00
Tianyi Cui 5872c51d2b Merge pull request #4381 from deepseek-harness/worktree/merge-master-into-session-log-v4-20260916
merge: sync master into session-log-v4
2026-09-17 00:50:45 +08:00
Dudu-0223 98ebcccf9e Merge pull request #4304 from deepseek-harness/feat/continuable-activation-limit
feat(subagent): enforce live capacity and persist delegation limits
2026-09-17 00:50:15 +08:00
Tianyi Cui 038c36b138 merge: update master integration with released fork support 2026-09-17 00:40:09 +08:00
Dudu-0223 04a3c30a04 fix(subagent): default delegation depth to one 2026-09-17 00:38:16 +08:00
Dudu-0223 9fcf9f7b11 merge: sync master into continuable activation limits 2026-09-17 00:35:36 +08:00
Dudu-0223 22b942bb19 Merge pull request #2687 from deepseek-harness/feat/session-fork-arbitrary-seq
feat(session): fork exact event prefixes with synthetic tail results
2026-09-17 00:31:22 +08:00
Tianyi Cui d97a2e858e test(snapshot): align imported MCP fixture with release tool prose 2026-09-17 00:26:47 +08:00
turtle1999 4233590de6 fix(workspace-changes): ignore scrubbed ambient Git config 2026-09-17 00:16:33 +08:00
Tianyi Cui 0a1e2691ab merge: integrate master into session-log-v4 2026-09-17 00:12:27 +08:00
Tianyi Cui 8696ec6cef feat(session): fork exact event prefixes with synthetic tail results 2026-09-17 00:00:44 +08:00
ZiyaZhang 78f4c5ae32 style(web): remove Subagent section divider 2026-09-16 09:00:22 -07:00
Tianyi Cui 88229fac33 Merge pull request #4378 from deepseek-harness/worktree/fix-release-windows-coverage-20260916
test(windows): avoid taskkill after descendant exit
2026-09-16 23:56:09 +08:00
ZiyaZhang a8de4c334e style(web): soften Subagent help icons 2026-09-16 08:48:14 -07:00
Tianyi Cui 1ccef293fa fix(tests): keep Windows Job fixture cleanup with its owner 2026-09-16 23:29:08 +08:00
Dudu-0223 e2107a0394 Merge pull request #4311 from deepseek-harness/feat/parent-catalog-consumers-rebuilt
feat(subagent): migrate direct catalog consumers to parent projections
2026-09-16 23:12:01 +08:00
Yichen Jiang ce113eb86a Merge pull request #4376 from deepseek-harness/feat/plugin-page-config-items
feat(web): host plugin configuration on the Plugins page
2026-09-16 22:35:24 +08:00
Turtle 403c9b74f4 docs(desktop): trim the macOS menu prose
The README enumerated every menu item, accelerator, and label behavior;
state only the capability and its platform condition. The Agent Note now
records the verified Electron mechanism instead of a bare claim: role
labels are English literals in Electron, re-applied to the native items
before the menu opens.
2026-09-16 22:07:58 +08:00
Yichen Jiang 3c394440ab Merge remote-tracking branch 'origin/master' into worktree/jobs-api-review-3052
# Conflicts:
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	docs/persistence-catalog.i18n.yaml
#	docs/persistence-catalog.md
#	docs/persistence-catalog.zh.md
#	docs/persistence-schema.json
2026-09-16 22:05:51 +08:00
Yichen Jiang 57a705fa7e feat(web): let the install dialog's close control stop a running install
While the Host runs an install, the dialog's close control was disabled. It now asks the Host to stop the run, the same request as Cancel install, and closes the dialog once the Host confirms the stop; when the Host answers too late or cannot confirm, the dialog stays with that word. Escape and the mask keep waiting while the Host owns the operation. The control is labelled 取消安装并关闭 / Cancel install and close while it does this.
2026-09-16 22:05:20 +08:00
Dudu-0223 e55093b47d feat(subagent): migrate direct catalog consumers to parent projections 2026-09-16 22:05:17 +08:00
Yichen Jiang a63dd809a2 refactor(web): share the card head and page top on the Plugins page
The cards and the pages of the Plugins page repeated their head (icon, opening title, tags, one-liner) and their top (crumb, icon, actions); CardHead and DetailTop carry them once, which is what the duplication gate asked for. DOM and behavior are unchanged.
2026-09-16 22:01:40 +08:00
Dudu-0223 1d1ae1a5af fix(session): migrate historical subagent catalogs to V4 2026-09-16 22:00:38 +08:00
Yichen Jiang 62c66dad02 feat(web): open a row's configuration from its name and label the guide examples
- A bundle row with a configuration page is opened from its name, which carries an inline chevron like the plugin cards; the separate configure button and its `configure` label are gone. Status and switch stay at the right.
- The three install-guide examples carry an "示例:" / "Example: " label before the code.
- README and Agent Note record that a bundle's pages live with the row that carries its browser half: `dsh-client-modules` attaches that half to the row named by the bare package name, so a page keyed to a subpath row disappears with the root row.
2026-09-16 21:46:29 +08:00
turtle1999 59e446b757 Merge origin/master into startup diagnostics 2026-09-16 21:45:21 +08:00
Turtle 965de16f56 Merge remote-tracking branch 'origin/master' into turtle/orchestrator-3576650b674f 2026-09-16 21:45:01 +08:00
Turtle b9fde8d063 fix(desktop): complete the macOS menu defaults
Add the standard application hide commands (Cmd+H, Option+Cmd+H, Show All) and
pin them with the window commands in the startup test, drop the redundant mock
cast that failed the lint gate, move the Agent Note to bug-fix, and state the
English role labels and the Dock-activation condition in both READMEs.
2026-09-16 21:42:42 +08:00
turtle1999 053cad9442 fix(cli): complete startup diagnostics before exiting 2026-09-16 21:40:54 +08:00
Turtle 22c96420fe Merge pull request #4367 from deepseek-harness/turtle/orchestrator-2d656b6cb16e
feat(client): lead known-site links with the site's own mark
2026-09-16 21:31:27 +08:00
Turtle 024a7f8107 Merge pull request #4355 from deepseek-harness/turtle/sanitize-profile
fix(desktop): sanitize profile before recovery restart
2026-09-16 21:29:43 +08:00
Turtle 380994942d fix(desktop): declare the standard macOS window menus
The custom application menu replaces Electron's default one, so macOS lost
File > Close Window (Cmd+W) and Window > Minimize (Cmd+M) while the traffic
light and the Dock activation path still closed and reopened the window.
Declare the fileMenu and windowMenu roles on macOS, keep Windows and Linux on
the application and Edit menus, and pin the per-platform template.
2026-09-16 21:25:17 +08:00
turtle1999 5e942d39eb test(bench): set trajectory navigation budget to 650 ms 2026-09-16 21:21:55 +08:00
Yichen Jiang 90af3110b7 feat(web): host plugin configuration on the Plugins page
The Plugins page declares three slots as children of its main entry:
`plugins.item` lists an official plugin's page in the Official group,
`plugins.bundle.config` renders a bundle's own form on its page, and
`plugins.row.config` gives a row a configure control opening the row's
page. Every entry renders in the `summary` and `page` views the page
passes as owner props; the page draws the title, icon, and crumb and
projects the ledgers beside its store, naming no configurable plugin.

`ui-settings-plugins` registers its four host-plane pages into
`plugins.item` while the Host serves their namespaces and withdraws them
when it stops; the forms keep edits until a save and drop them on leaving
the page, so the discard control and the unsaved marker are gone. The
Settings section becomes the Built-in plugins shell around the inventory
tab, and `settings.plugin.item` is retired.

The Official group opens with the optional bundles the installation
ships, tagged Beta where the feature is one and without an official tag,
followed by the configuration pages. Auto review leaves the optional
bundles and the CLI's dependencies; the install guide names it as its
example spec. The version tag is a capsule like the other tags.

The `plugin-config` web lane drives the pages through the real wire and
opens a community fixture's row page after switching its bundle on; the
settings lanes re-record the renamed navigation entry.
2026-09-16 21:05:34 +08:00
creatixchu dcf2b67896 feat(web): open Sidebar-previewed files in the default application
The document preview declares two child slots handing the previewed file
and its Host path to other plugins: the header actions after its own
controls, and the empty state of a file it cannot render, where Retry stood.
Empty-state read failures now name their recourse: not-text and too-large
offer the handoff, not-found and non-regular paths offer nothing, and the
rest keep Retry. The unsupported-suffix empty state offers the same seat.

ui-open-in-app fills both seats with an "Open" split button (default
application, or the file manager reveal from its menu) and an empty-state
"Open in default app" button. Both call the Session Remote the Host already
publishes: canOpenWorkspacePath once per page decides whether they render,
openWorkspacePath runs each gesture. Only the pressed control disables while
its gesture settles; a failure announces once through a transient toast.

The delivery cards keep their own opener this iteration. The design, slot
pair, failure classification, and toast rule come from Yifffan's PR #4120.
2026-09-16 21:00:57 +08:00
ZiyaZhang ea2651b86b feat(web): unify Subagent settings UI 2026-09-16 05:51:03 -07:00
Turtle 7eede143bd docs(client): state the known-site suffix count correctly
The mapping holds forty host suffixes, not thirty-eight: WeChat and QQ
each keep their own suffix, and Telegram and WhatsApp each add a second
short-link host.
2026-09-16 20:37:14 +08:00
07akioni 004526ab0a Merge pull request #4339 from deepseek-harness/fix/session-used-toast
fix: 会话被占用时提示退出其他 DSH 实例后重试
2026-09-16 20:29:20 +08:00
winewill b3795cb99f fix(desktop): make Windows mandatory update window movable 2026-09-16 20:25:24 +08:00
turtle1999 ac2f890291 fix(cordis): dispose only the registered logger exporter 2026-09-16 20:23:44 +08:00
Turtle 214ab45932 feat(client): cover mainstream sites in known-site link marks
Review asked for the sites a general audience visits. The vocabulary
grows from fourteen developer sites to thirty-four marks across search
(Google, Baidu, DuckDuckGo), video and audio (TikTok, Netflix, Spotify),
social and messaging (Facebook, Instagram, Reddit, Telegram, WhatsApp,
WeChat, QQ, Weibo), shopping (Taobao, AliExpress, eBay), reference and
community (Quora, V2EX), and Apple.

Matching now takes the longest host suffix, so weixin.qq.com keeps the
WeChat mark while qq.com keeps QQ. The spec covers one URL per site,
still requires distinct marks, and pins the Telegram and WhatsApp
aliases as well; the README and Agent Note record the categories, the
bounded per-site cost, and the licensing and trademark position.
2026-09-16 20:23:26 +08:00
Yichen Jiang 55d57d33b6 fix(session): initialize blankness from retained metadata 2026-09-16 20:22:14 +08:00
yudshj b307cbffab docs(preview): follow renamed conversion decision 2026-09-16 20:18:07 +08:00
07akioni 3766f4af95 merge: resolve event catalog conflicts with master 2026-09-16 20:18:01 +08:00
yudshj 7bc0db4470 Merge remote-tracking branch 'origin/office/render-cache' into codex/office-decouple-preview 2026-09-16 20:17:24 +08:00
creatixchu a4493ceb39 fix(deliverables): scroll the split review columns together on both axes
Each unwrapped split column is its own scroll container, and only the
horizontal offset was mirrored onto the other side, so wheel-scrolling one
column left the other behind and the paired rows drifted apart. Mirror the
vertical offset the same way.
2026-09-16 20:15:40 +08:00
yudshj 2f98700396 Merge remote-tracking branch 'origin/master' into codex/office-decouple-conversion
# Conflicts:
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	pnpm-lock.yaml
2026-09-16 20:14:36 +08:00
turtle1999 18260e3b0c fix(cli): save full startup diagnostics under DSH_HOME logs 2026-09-16 20:11:15 +08:00
Yichen Jiang f65799a236 docs(session): clarify blank-state projection guarantees 2026-09-16 20:05:48 +08:00
Turtle f018fe8f10 refactor(client): take known-site link marks from simple-icons
Review asked for a maintained artwork source instead of the fourteen
copied Simple Icons paths. SiteGlyph now imports siGithub and its
thirteen peers from the simple-icons package (CC0-1.0), added as a
ui-primitives devDependency and pinned by the lockfile, so a mark is one
host-map entry and updates arrive with the package. Each mark draws in a
28-unit viewBox inset by two units, which keeps the ~8% margin the
20-unit ic_ds_* glyphs carry, and the gallery fixture uses a synthetic
GitHub URL because verify-repository-references rejects the
organization URL.

Also from that review: the spec covers github.io and x.com, keeps its
comment truthful about which aliases collapse, and names the
single-label-host fallback case; the older clickable-link note states
the url glyph and per-site marks in the present tense; the package
README records that the known-site list is fixed and everything else
keeps the globe.
2026-09-16 20:05:47 +08:00
yudshj bab800bf74 docs(office-to-pdf): link the bounded conversion decision 2026-09-16 19:57:41 +08:00
creatixchu f92f984d3d docs(notes): propose one card per delivered changed file 2026-09-16 19:48:48 +08:00
CreatixChu 8225e18d70 Merge pull request #4279 from deepseek-harness/worktree/changes-diff-preview
轮次 Review tab:逐文件对比改动
2026-09-16 19:43:40 +08:00
sjw1231 17dd9f0e29 docs(web): propose consistent trajectory attachment presentation
Refs #4356
2026-09-16 19:42:54 +08:00
winewill 6d05e76b89 feat(desktop): open Feishu login DevTools with F12 2026-09-16 19:38:47 +08:00
winewill c624c2eff0 fix(desktop): present installer welcome and package 0.1.6-alpha.1.20260916.2 2026-09-16 19:37:48 +08:00
creatixchu c1f9d19658 test(web): refresh the present-svg golden for the review-opening card 2026-09-16 19:34:27 +08:00
creatixchu 974d0271c0 fix(deliverables): satisfy the static gates and Windows tests
Regenerate the client and persistence catalogs, document the review address builder with a plain parameter, share the changed-file coordinate parsing between the comparison and native-open routes, and fold the summary and comparison stores onto one Host read store. A path with no existing ancestor but the filesystem root keeps its spelling on every platform, and the temp-root test redirects TMP and TEMP as well as TMPDIR while counting only the recorder's own directories.
2026-09-16 19:32:25 +08:00
CreatixChu b784e586ef Merge pull request #3986 from deepseek-harness/worktree/code-diff-card
代码 diff 卡片
2026-09-16 19:31:07 +08:00
creatixchu 2875e28a0e Merge remote-tracking branch 'origin/worktree/code-diff-card' into worktree/changes-diff-preview 2026-09-16 19:26:39 +08:00
07akioni 8960d2cf11 Merge pull request #4361 from deepseek-harness/07akioni/fix-windows-shell-console
fix(subprocess): hide Windows PTC and shell console windows
2026-09-16 19:25:13 +08:00
Turtle 59456dbb5b feat(client): lead known-site links with the site's own mark
Clickable external links now lead with the destination site's own mark
instead of the globe when the host belongs to a known site: GitHub,
GitLab, npm, PyPI, Stack Overflow, MDN, Wikipedia, Hacker News, YouTube,
X, Bilibili, Zhihu, Juejin, and CSDN. LinkIcon takes an optional href and
resolves the mark through a private SiteGlyph module; markdown anchors,
reference links, URL-promoted inline code, and web-card source and fetch
links pass their sanitized destination. Unmapped hosts, non-http schemes,
and the file categories keep today's glyph.

The marks are the single-path form of Simple Icons (CC0-1.0) on its
24x24 viewBox, filled with currentColor like every other link glyph, so
they follow the link alias in both themes and on hover.

Coverage: the LinkIcon spec pins one host per mapped site plus the alias
and fallback branches, the markdown and web-card specs pin their consumer
wiring, and the clickable-links gallery e2e pins the assembled mark
against the globe in a real browser.
2026-09-16 19:23:03 +08:00
creatixchu 5991ea36ae Merge remote-tracking branch 'origin/master' into worktree/code-diff-card 2026-09-16 19:22:17 +08:00
creatixchu c63da07322 Merge remote-tracking branch 'origin/master' into worktree/code-diff-card 2026-09-16 19:19:58 +08:00
Yichen Jiang e9f2ad41a1 Merge pull request #4353 from deepseek-harness/worktree/blank-session-sidebar
fix(web): allow opening the sidebar before the first message
2026-09-16 19:19:57 +08:00
07akioni bbbd93ad32 Merge remote-tracking branch 'origin/master' into fix/session-used-toast 2026-09-16 19:12:13 +08:00
turtle1999 38fb1a11f9 fix(cli): group startup failures and pending services 2026-09-16 19:04:12 +08:00
07akioni f8b1309fe5 fix(subprocess): hide Windows shell console windows at creation 2026-09-16 18:56:39 +08:00
yudshj 8ed7d7fde5 Merge remote-tracking branch 'origin/office/render-cache' into codex/office-decouple-preview 2026-09-16 18:54:47 +08:00
yudshj 07e398cc15 Merge remote-tracking branch 'origin/master' into codex/office-decouple-conversion 2026-09-16 18:51:09 +08:00
Turtle 5c0ca8e420 Merge master into turtle/sanitize-profile 2026-09-16 18:47:01 +08:00
yudshj 24828084ca Merge remote-tracking branch 'origin/office/render-cache' into codex/office-decouple-preview 2026-09-16 18:41:54 +08:00
Turtle 04794bd90e fix(desktop): clarify profile recovery scope and diagnostics 2026-09-16 18:41:47 +08:00
yudshj 682011adfa docs(office-to-pdf): clarify conversion and engine package ownership 2026-09-16 18:39:38 +08:00
winewill a609246a35 docs(desktop): confirm release version before packaging 2026-09-16 18:05:05 +08:00
winewill 69bf9f9054 release(dsh): 0.1.6-alpha.1.20260916.1 2026-09-16 18:04:50 +08:00
Yichen Jiang d1e93e5482 test(web): match the terminal close response without unsafe JSON access 2026-09-16 18:03:03 +08:00
Turtle f756097108 Merge pull request #4324 from deepseek-harness/turtle/creator-plugin-manager
feat(creator): use Plugin Manager for persistent plugins
2026-09-16 17:58:53 +08:00
Yichen Jiang 51a9382b61 test(web): await terminal close acknowledgement before cleanup assertions 2026-09-16 17:57:09 +08:00
Yichen Jiang b0542ec0e2 test(web): update blank session header snapshots 2026-09-16 17:48:48 +08:00
Turtle 3cd6782114 refactor(boot): name the profile pnpm invocation explicitly 2026-09-16 17:40:40 +08:00
Turtle 2fc6e38d2b test(web): refresh Creator skill instructions card 2026-09-16 17:29:54 +08:00
Turtle 60058f118b fix(boot): timestamp profile patch backups 2026-09-16 17:26:25 +08:00
turtle1999 8c5ae870c2 fix(creator): address plugin workflow review findings 2026-09-16 17:22:38 +08:00
Turtle 8d5c7e4e2a fix(desktop): back up profile patches during recovery 2026-09-16 17:10:21 +08:00
Yichen Jiang 7f2d7b1791 fix(web): allow opening the sidebar before the first message 2026-09-16 17:10:10 +08:00
yudshj 54d268c409 feat(preview): consume shared Office conversion independently 2026-09-16 17:06:55 +08:00
winewill c13cc074fd merge: preserve Desktop test release base versions 2026-09-16 16:59:44 +08:00
winewill a2215799b8 fix(desktop): preserve the dsh base in dated test versions 2026-09-16 16:59:07 +08:00
turtle1999 d86da2e31c test(plugin-manager): keep approval assertions type-safe 2026-09-16 16:55:46 +08:00
winewill 1be847f736 feat(desktop): add native About menu and panel 2026-09-16 16:55:32 +08:00
creatixchu 26e2196a86 fix(deliverables): scroll the split review columns sideways together 2026-09-16 16:53:44 +08:00
turtle1999 9a83772560 fix(plugin-manager): request approval for single-call full access 2026-09-16 16:53:34 +08:00
07akioni 73c2300ce4 merge: align session toast fix with latest master 2026-09-16 16:51:49 +08:00
yudshj d3ed04defa refactor(document): consolidate Office conversion into office-to-pdf 2026-09-16 16:50:04 +08:00
creatixchu 142ca8b956 Merge remote-tracking branch 'origin/worktree/code-diff-card' into worktree/changes-diff-preview 2026-09-16 16:49:48 +08:00
creatixchu 91d9346aa1 fix(deliverables): open the review from the card header and scroll unwrapped split columns separately
The card header opens the turn's review on its first file instead of the common folder, so the folder route and its Host lookup go away and the native open lives only in the review tab. The split view without wrapping draws each side as its own column that scrolls sideways, so a long line no longer runs under the other side; with wrapping both sides still share one row per pair.
2026-09-16 16:44:52 +08:00
Yichen Jiang fa2abdd6f1 fix(web): reconcile stale blank session hints from projections 2026-09-16 16:39:53 +08:00
creatixchu 9a74f173d3 Merge remote-tracking branch 'origin/master' into worktree/code-diff-card 2026-09-16 16:31:23 +08:00
turtle1999 470d4aae11 fix(plugin-manager): require full access for agent tool calls 2026-09-16 16:27:48 +08:00
Yichen Jiang 257df553b6 Merge pull request #4334 from deepseek-harness/worktree/model-input-checkboxes
feat(web): unify model input controls and catalog inheritance
2026-09-16 16:10:50 +08:00
turtle1999 040be00cb4 test(creator): align Web fixtures with persistent plugin management 2026-09-16 16:10:40 +08:00
yudshj 68183a5de3 docs(document): refresh shared conversion module graph 2026-09-16 16:07:38 +08:00
Yichen Jiang 6e41857b2e Merge remote-tracking branch 'origin/master' into worktree/jobs-api-review-3052
# Conflicts:
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	packages/api/remotes/src/client/index.ts
#	packages/api/session-controller/README.i18n.yaml
#	packages/api/session-controller/README.md
#	packages/api/session-controller/README.zh.md
#	packages/api/session-controller/src/client/sessions/manager.ts
#	packages/api/session-controller/src/control.ts
#	packages/api/session-controller/src/types.ts
#	packages/api/session-controller/tests/client-apply.client.spec.ts
#	packages/api/session-controller/tests/manager.client.spec.ts
#	packages/api/session-controller/tests/projection-store.client.spec.ts
#	packages/api/session-controller/tests/queue-store.client.spec.ts
#	packages/api/session-controller/tests/sessions-service.client.spec.ts
#	packages/api/session-controller/tests/transport.client.spec.ts
#	packages/client/ui-jobs/package.json
#	packages/client/ui-primitives/src/TerminalBlock.module.css
#	packages/client/ui-primitives/src/TerminalBlock.tsx
#	packages/client/ui-primitives/tests/terminal-block.client.spec.tsx
#	packages/extensions/tool-cordis/src/api-catalog.ts
#	packages/test-support/client-runtime/src/assembly/remote-default-responses.ts
2026-09-16 16:05:59 +08:00
Yichen Jiang cb731e26e9 Merge master into worktree/model-input-checkboxes 2026-09-16 16:03:24 +08:00
Turtle 15b5ba0d44 Merge pull request #4273 from deepseek-harness/turtle/sidebar-parent-folders
feat(web): add opt-in Workspace tree grouping
2026-09-16 16:00:36 +08:00
yudshj 14f375168d Merge master with released Office skills into shared conversion 2026-09-16 15:59:07 +08:00
Turtle bd241e28fa Merge pull request #4337 from deepseek-harness/turtle/author-approval-credit-1-1
Raise author approval credit to 1.1 at 100 merged PRs
2026-09-16 15:53:14 +08:00
Yichen Jiang 1596097147 Merge remote-tracking branch 'origin/master' into worktree/jobs-api-review-3052
# Conflicts:
#	apps/web/tsconfig.json
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	packages/api/remotes/package.json
#	packages/api/remotes/src/client/index.ts
#	packages/api/session-controller/tests/client-apply.client.spec.ts
#	packages/api/session-controller/tests/control-jobs.host.spec.ts
#	packages/api/session-controller/tests/fake-api.client.ts
#	packages/api/session-controller/tests/manager.client.spec.ts
#	packages/client/ui-jobs/package.json
#	packages/extensions/cordis-client-runner/src/client/slot-catalog.ts
#	packages/jobs/jobs-local/README.i18n.yaml
#	packages/jobs/jobs-local/README.md
#	packages/jobs/jobs-local/README.zh.md
#	packages/jobs/jobs-local/src/index.ts
#	packages/jobs/jobs-local/tests/jobs.spec.ts
#	packages/jobs/tool-jobs/tests/tool-jobs.spec.ts
#	packages/shell/shell/README.i18n.yaml
#	packages/shell/shell/README.md
#	packages/shell/shell/README.zh.md
#	packages/shell/tool-bash/README.i18n.yaml
#	packages/shell/tool-bash/README.md
#	packages/shell/tool-bash/README.zh.md
#	packages/shell/tool-bash/src/background.ts
#	packages/shell/tool-bash/src/index.ts
#	packages/shell/tool-pwsh/src/background.ts
#	packages/shell/tool-pwsh/src/index.ts
2026-09-16 15:53:02 +08:00
Turtle 5ec3368285 fix(web): address Workspace tree review feedback 2026-09-16 15:51:26 +08:00
Yichen Jiang 5d51ba5a9c refactor(web): clarify model input docs and strengthen tests 2026-09-16 15:49:16 +08:00
07akioni e297b75a5d merge: align session toast fix with latest master 2026-09-16 15:47:57 +08:00
turtle1999 74e5694e6b test(creator): refresh Python restart tool inventory 2026-09-16 15:47:27 +08:00
turtle1999 92da029f6d test(creator): replace retired Cordis tool scenarios 2026-09-16 15:39:17 +08:00
turtle1999 7342687170 fix(creator): bound visual verification and refresh module graph 2026-09-16 15:39:17 +08:00
turtle1999 ed32f57f88 feat(creator): use Plugin Manager for persistent plugins 2026-09-16 15:39:16 +08:00
07akioni 5c369a0a1f fix: carry session writer failures by typed remote code 2026-09-16 15:38:34 +08:00
Yudong Han c81dec55de Merge pull request #4286 from deepseek-harness/office/bundled-skills
feat(desktop): enable standalone Office skills
2026-09-16 15:34:50 +08:00
Yichen Jiang f5683559a5 fix(web): isolate model settings tests and update input guide 2026-09-16 15:33:50 +08:00
Yichen Jiang 2a5c227199 test(web): cover model draft and provider input defaults 2026-09-16 15:22:05 +08:00
yudshj 82ab876331 fix(office): validate strict and corrupt OOXML 2026-09-16 15:21:18 +08:00
yudshj fa518ecd89 feat(desktop): enable standalone Office skills 2026-09-16 15:21:18 +08:00
07akioni eb57fdb9c6 fix: load optional persistence errors only with its service 2026-09-16 15:19:09 +08:00
Yichen Jiang 941cf78b5d Merge pull request #4336 from deepseek-harness/worktree/messages-tool-history-json
fix(llm): tolerate malformed historical Messages tool input
2026-09-16 15:18:59 +08:00
winewill 08b75ade40 fix(desktop): show a local document while the policy login page loads
The login window navigated straight to the policy origin, so a slow or redirecting remote page left the window blank. The packaged placeholder is now the window's first document and the login request starts only after it settles; the first committed remote document replaces it, so nothing overlays the third-party page and a pending subresource cannot extend it.
2026-09-16 15:18:30 +08:00
winewill a3d2cb400b fix(desktop): tighten the update entry label and downloaded detail
The available state now reads "新版本" / "Update" instead of a sentence, and the downloaded confirmation keeps only "The update has downloaded." The entry also takes back the row's 2px bleed plus the foot rows' 2px inset so it ends on the same trailing edge as the other sidebar rows. The desktop dictionary additionally carries the login loading string used by the following commit.
2026-09-16 15:18:23 +08:00
Turtle b432223364 feat(web): make Workspace tree an explicit grouping option 2026-09-16 15:18:05 +08:00
winewill daf185fd24 fix(client): yield the enclosing tooltip to a nested one
The collapsed rail's update badge renders inside the expand button, so hovering it showed both the version notice and "Open sidebar". Tooltip now publishes a suppression setter that a nested tooltip claims while its own bubble is visible; the enclosing tooltip keeps its hover state and measured position, so its bubble returns as soon as the nested one is gone.
2026-09-16 15:18:03 +08:00
creatixchu fc10bc18e0 feat(deliverables): review one turn's changed files in a single tab
The per-file comparison tab becomes a `changes-review` tab per turn: a file selector in the header lists every recorded file, a card row opens the tab on its file through a navigation parameter, and the header's tools switch between the unified and a side-by-side view, switch line wrapping, open the whole file in the Sidebar, and open it in the default application when a desktop exists. View and wrap choices are kept per tab in an exclusive store.
2026-09-16 15:07:34 +08:00
Yichen Jiang 99402378b7 Merge pull request #4333 from deepseek-harness/worktree/user-terminal-permissions
feat(web): give user terminals system-user permissions
2026-09-16 15:04:33 +08:00
yudshj fcf9f4cfa2 fix(document): select Office engines from declared native targets 2026-09-16 14:55:38 +08:00
07akioni e0f170b8d0 fix: explain session writer contention in toasts 2026-09-16 14:50:38 +08:00
creatixchu a1ac8371de test(acp): refresh the fs-same-mode fixture for the write operation metadata 2026-09-16 14:47:52 +08:00
Dudu-0223 f25f3527ef test(ui-deliverables): preserve file-reference prompt evaluations 2026-09-16 14:44:16 +08:00
winewill 60c39996b9 Merge remote-tracking branch 'origin/feat/desktop-update' into feat/desktop-update
# Conflicts:
#	.agents/notes/implemented/architecture/2026-08-25-electron-desktop-packaging-and-updates.i18n.yaml
#	.agents/notes/implemented/architecture/2026-08-25-electron-desktop-packaging-and-updates.md
#	.agents/notes/implemented/architecture/2026-08-25-electron-desktop-packaging-and-updates.zh.md
2026-09-16 14:37:32 +08:00
creatixchu 7b93d1bd83 Merge remote-tracking branch 'origin/master' into worktree/code-diff-card 2026-09-16 14:37:28 +08:00
Turtle e879c7456a Merge pull request #4321 from deepseek-harness/turtle/builtin-plugin-i18n
fix(web): localize built-in plugin names and descriptions
2026-09-16 14:37:15 +08:00
07akioni bc49038b82 Merge pull request #4323 from deepseek-harness/fix/desktop-mac
fix(ptc): preserve Electron Node mode when launching programs
2026-09-16 14:36:40 +08:00
Turtle c7e7e8bc18 Raise author approval credit to 1.1 at 100 merged PRs 2026-09-16 14:35:17 +08:00
winewill e6c507d65f fix(desktop): upload releases with Tencent COS SDK 2026-09-16 14:34:05 +08:00
Yichen Jiang 1f030b3c1c fix(llm): tolerate malformed historical Messages tool input 2026-09-16 14:28:20 +08:00
07akioni 46bac5f7db Merge master and retain desktop execution PATH isolation 2026-09-16 14:20:57 +08:00
lsdsjy 44c65b70ad Merge pull request #4257 from deepseek-harness/fix/desktop-directory-picker
fix(desktop,client): attach workspace folder dialogs to the application window
2026-09-16 14:11:15 +08:00
07akioni 3e6d93171d Keep desktop package launchers out of the Host execution PATH 2026-09-16 14:03:41 +08:00
lsdsjy 285da0fa64 style(desktop): wrap dialog mock after rebase 2026-09-16 14:03:25 +08:00
yudshj fd3cdf539b refactor(document): name Office PDF conversion explicitly 2026-09-16 13:59:49 +08:00
Yichen Jiang ab695ef4cf feat(web): give user terminals system-user permissions 2026-09-16 13:52:23 +08:00
lsdsjy 21c7828678 docs(desktop,client): align native directory picker summaries 2026-09-16 13:50:38 +08:00
lsdsjy 48dd4b3bea test(desktop,client): keep picker composition coverage with its feature 2026-09-16 13:50:37 +08:00
lsdsjy ea5f1dce4a fix(desktop,client): preserve folder creation and verify picker wiring 2026-09-16 13:50:21 +08:00
lsdsjy 73dcae2915 fix(desktop,client): attach workspace folder dialogs to the application window 2026-09-16 13:50:07 +08:00
Turtle 8e5f4caec2 Merge pull request #4326 from deepseek-harness/turtle/sandbox-same-mode
fix(sandbox): accept repeated effective permission modes
2026-09-16 13:49:42 +08:00
Yichen Jiang cc394230bf feat(web): unify model input controls and catalog inheritance 2026-09-16 13:48:07 +08:00
Tianyi Cui 3bde1a56e3 fix(test): prepare preview generations and preserve embedded stream timing 2026-09-16 13:46:05 +08:00
Dudu-0223 ed0ae7786d test(web): align shipped file-reference guidance expectation 2026-09-16 13:43:20 +08:00
yudshj 96e68ded13 feat(document): decouple shared Office conversion from preview 2026-09-16 13:43:02 +08:00
creatixchu fac80a84fb Merge remote-tracking branch 'origin/worktree/code-diff-card' into worktree/changes-diff-preview 2026-09-16 13:39:21 +08:00
creatixchu 2440937459 fix(workspace-changes): list oversized pairs, bound capture reads, and resolve paths through symlinked ancestors
Two oversized captures are no longer treated as unchanged, so the file is listed as oversized instead of vanishing; an oversized side outranks a binary one in the card and the tab alike. Captures read at most maxFileBytes + 1 bytes through a file handle, a missing file resolves through its nearest existing ancestor so a path created through a directory symlink keeps one canonical spelling, and ls-tree matches paths literally. The comparison tab draws at most 5,000 lines. Docs record that comparisons serve whole file text beyond the workspace root, the newline normalization, and the coarse payload bound; the card note's row behavior is current again.
2026-09-16 13:37:22 +08:00
Dudu-0223 fbc6abcfd4 feat(web): guide file references with concise colon labels 2026-09-16 13:36:39 +08:00
turtle1999 aea150a17e test(pwsh): align repeated sandbox mode expectations 2026-09-16 13:35:31 +08:00
Dudu-0223 8040a599ac Merge origin/master into issue-3997-markdown-file-links 2026-09-16 13:29:27 +08:00
Tianyi Cui 8a46149577 fix(test): validate retained V3 layouts and current reference captures 2026-09-16 13:21:19 +08:00
turtle1999 61c548e200 fix(sandbox): accept repeated effective permission modes 2026-09-16 13:16:33 +08:00
Yichen Jiang 43e1e241ee Merge pull request #4254 from deepseek-harness/feat/docs-page-markdown-actions
feat(docs): add page Markdown copy and view actions
2026-09-16 13:15:34 +08:00
Yudong Han c19983150c Merge pull request #4276 from deepseek-harness/office/python-runtime
feat(desktop): bundle standalone Python Office runtime
2026-09-16 13:14:26 +08:00
Dudu-0223 0eed02d447 fix(subagent): map capacity refusal and clarify one-shot scope 2026-09-16 13:11:47 +08:00
07akioni a66d81e33f fix(ptc): limit Electron selector to startup and budget native tests 2026-09-16 13:11:08 +08:00
Tianyi Cui 9c10de50a6 fix(test): compare native Python delivery generations without rewriting goldens 2026-09-16 13:02:13 +08:00
yudshj 869a3f6d27 feat(desktop): ship standalone Python Office runtime 2026-09-16 13:00:13 +08:00
Tianyi Cui d3dbcfe710 Merge master into release/session-log-v4 2026-09-16 12:58:34 +08:00
Dudu-0223 25650d3d35 Merge backend delegation settings from #4304 2026-09-16 12:52:55 +08:00
07akioni a139e6e9e1 fix(ptc): preserve Electron Node mode when launching programs 2026-09-16 12:52:50 +08:00
Dudu-0223 ab8bc05695 Merge remote-tracking branch 'origin/master' into feat/continuable-activation-limit 2026-09-16 12:52:09 +08:00
Dudu-0223 a69bcf3636 feat(subagent): own editable delegation limits in the backend 2026-09-16 12:51:50 +08:00
Tianyi Cui 669b724a78 feat(session): add the V4 integration format and retain V3 replay inputs 2026-09-16 12:50:34 +08:00
creatixchu 664190c6f9 Merge remote-tracking branch 'origin/master' into worktree/code-diff-card
# Conflicts:
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
2026-09-16 12:42:02 +08:00
Tianyi Cui c4f1cae6c6 Merge pull request #4313 from deepseek-harness/fix/llm-remove-v4-flash-models
feat(llm): drop the V4 Flash and V4 Flash Vision Exp default models
2026-09-16 12:36:35 +08:00
winewill bfe6beb517 fix(desktop): preflight Windows signing before builds 2026-09-16 12:32:11 +08:00
Dudu-0223 6b63916d9c docs(subagent): regenerate settings dependency graph 2026-09-16 12:30:16 +08:00
Turtle 6bc7938a15 fix(web): localize built-in plugin names and descriptions 2026-09-16 12:26:54 +08:00
Tianyi Cui 5e4cfe670f chore(session): initialize V4 release integration PR 2026-09-16 12:16:01 +08:00
Dudu-0223 845115d0f8 feat(subagent): edit delegation limits in plugin settings 2026-09-16 12:05:50 +08:00
winewill 011dbc9fb8 Merge remote-tracking branch 'origin/feat/desktop-update' into feat/desktop-update 2026-09-16 11:51:15 +08:00
Dudu-0223 d7f9d3a773 fix(subagent): default to eight live continuable children 2026-09-16 11:50:17 +08:00
winewill c781e85e92 fix(desktop): isolate Windows signature inspection modules 2026-09-16 11:49:36 +08:00
Kexin Liu ac0acf55a6 Merge pull request #4231 from deepseek-harness/feat/composer-selection-keyboard
feat(client): give the composer's selections and its menus one keyboard model
2026-09-16 11:49:20 +08:00
Dudu-0223 6bdbe4dff2 Merge remote-tracking branch 'origin/master' into feat/continuable-activation-limit 2026-09-16 11:47:10 +08:00
winewill 9fefcd7c06 fix(desktop): prepare unattended macOS signing from required p12 2026-09-16 11:46:48 +08:00
winewill b06ea72226 fix(desktop): preserve verified runtime signatures during packaging 2026-09-16 11:43:04 +08:00
Tianyi Cui a55b08233f test(llm): point the keyless onboarding case at a listed model
The case verifies first-boot catalog browsing and an actionable
MISSING_CREDENTIAL, so it follows the default catalog instead of an
unlisted id whose route only proves pass-through.
2026-09-16 11:39:32 +08:00
winewill b37687c141 fix(desktop): sign bundled Windows runtime before validation 2026-09-16 11:31:41 +08:00
Tianyi Cui f2beb99c3b feat(llm): remove the V4 Flash and V4 Flash Vision Exp defaults
The shipped DeepSeek catalog keeps V41 Flash and V4 Pro only; the removed
ids still pass through as text-only routes when configured explicitly.

Updates the adapter tests, the Web settings goldens that render the default
catalog, and the regenerated config catalog.
2026-09-16 11:26:21 +08:00
winewill 63dd8fb80d feat(desktop): add ordinary and mandatory update flows 2026-09-16 10:48:23 +08:00
Yichen Jiang 2bc7697265 Merge pull request #3596 from deepseek-harness/feat/plugin-mgmt-4-web
feat(web): manage global plugins from the sidebar
2026-09-15 23:40:55 +08:00
Dudu-0223 2d24d80d5f docs: synchronize translated subagent event references 2026-09-15 23:33:26 +08:00
Yichen Jiang a9fe93fc0b refactor(plugins): name bundles by their package name only
`dsh.title` was a manifest field this branch introduced: the manager read
it for `listBundles` and `inspect`, and the Web page showed it over the
package name. A bundle is named by its package name now, so `DshManifest`
keeps only its shipped fields, the page derives every heading from the
name, and the install dialog's subject line reads the name the Host
answered. The two e2e fixtures drop their titles and the manager lane's
goldens follow.
2026-09-15 23:31:54 +08:00
Dudu-0223 16620a3a70 feat(subagent): cap live continuable activations per root at 16 2026-09-15 23:29:22 +08:00
Turtle 9ec915433e Merge pull request #4294 from deepseek-harness/turtle/weighted-approval-delegate
feat: support weighted approval delegation
2026-09-15 23:00:46 +08:00
Yichen Jiang b017b2861c fix(experimental): declare react as a build input of the agent team client
@deepseek-ai/dsh-experimental-client-ui-agent-team listed react under
dependencies, which the shipped client packages never do: react reaches the
browser through the web build. Now that the agent team web profile is an
optional bundle of @deepseek-ai/dsh, that dependency pulled react into the
npm install layout, where verify-npm-install-layout rejects it.
2026-09-15 22:56:08 +08:00
Yichen Jiang e22c63185a test(web): resolve the built app-boot when a scaffold launches
scaffold.ts required the launcher's built module at import time, so the
unit lane, which runs without a build, failed to load
scaffold-generation.spec.ts for its fixture-name helpers. The built copy
is now resolved on the first launch, which needs the build anyway; the
mounted copy is unchanged.
2026-09-15 22:56:07 +08:00
Yichen Jiang 15eb952733 test(client): count the plugin page's two glyphs in the icon set
The info ring and the plugin pinwheel joined the hand-authored product
glyphs without the icon-set inventory following: master's count of 79
stayed after the merge while the barrel exports 81.
2026-09-15 22:56:04 +08:00
Yichen Jiang 430f88d1c5 refactor(web): keep the plugin manager's store state types package-private
The Client entry re-exported ConfirmState, InstallState, ManagerNotice and
PluginManagerState from the controller store although no other package names
them; the page, its tests and the presentation module import them from the
store directly. Only the face, the page props and the locale key stay public.
2026-09-15 22:38:48 +08:00
Yichen Jiang 79729c3422 refactor(plugins): read a bundle's one-liner from the package description only
The dsh manifest gains no description field: a bundle's card shows the
package.json description, and the shipped optional bundles carry no
display title or description of their own until localized metadata is
designed. The plugin author tutorial shows the bundle declaration alone.
2026-09-15 22:26:58 +08:00
Yichen Jiang fa320209ab refactor(plugins): name the optional bundles in the launcher, not the installation manifest
OPTIONAL_BUNDLES in app-boot lists the bundles the installation ships
switched off; the plugin manager, the default-product isolation gate,
the workspace constraints, and the packed-install check read that one
list instead of a dsh.optionalBundles field in apps/cli/package.json.
2026-09-15 22:22:22 +08:00
Yichen Jiang f04c265725 refactor(plugins): stop announcing patch generations applied outside the manager
app-boot no longer emits profile/reconciled after a reload, and the plugin
manager no longer turns such a generation into a plugin-manager/changed
notice: the Web page learns of a CLI or hand edit on its next read. The
change event keeps only the reasons a manager operation produces.
2026-09-15 22:21:06 +08:00
Turtle 3e9b6ad94e fix: authenticate and reconcile approval delegations 2026-09-15 22:12:41 +08:00
Turtle 60d26ac4ab fix: dismiss prior reviews when delegating approval 2026-09-15 21:41:04 +08:00
Yichen Jiang 5e5f0a2393 fix(web): start the approval retry with a fresh log and keep the install dialog in view
The retry that allows blocked install scripts drops the failed run from
the dialog instead of stacking the new run under it. The dialog no longer
grows past the viewport: the card is capped and everything under the
head scrolls, so the close and edit controls stay reachable however long
pnpm's output is.
2026-09-15 21:40:54 +08:00
Yichen Jiang c3c7a4f412 refactor(app-boot): drop the root Include lookup by id
reconcileProfilePatches finds the root Include only through the registry
the module that mounted it keeps, as it did before the Web page: a tree
mounted by another copy of app-boot was a test-harness situation, not a
product one. The web e2e scaffold now mounts and resolves the profile
through the built app-boot, loaded with Node's own require so it shares
the module map with the Host plugins the profile loads, instead of the
source copy a bare import resolves to.
2026-09-15 21:39:42 +08:00
Yichen Jiang c13d21fb95 feat(web): approve blocked install scripts from the install dialog
When pnpm leaves a dependency's install scripts undecided, the failed
screen lists the pending packages and offers to allow them and retry in
place of plain retry; the Host saves the permission in the profile before
running pnpm again, and the installed screen names what was allowed. A
failure the Host could not name falls back to the manual instruction, and
a stale approval is worded like the other refusals. A new web lane drives
the whole flow through a fake pnpm that blocks, then installs.
2026-09-15 21:23:01 +08:00
Yichen Jiang 075aab54a7 Merge remote-tracking branch 'origin/master' into feat/plugin-mgmt-4-web
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/config-catalog.zh.md
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	docs/subsystems/boot.i18n.yaml
#	docs/subsystems/boot.md
#	docs/subsystems/boot.zh.md
#	packages/api/remotes/src/client/index.ts
#	packages/boot/plugin-manager/README.i18n.yaml
#	packages/boot/plugin-manager/README.md
#	packages/boot/plugin-manager/README.zh.md
#	packages/boot/plugin-manager/src/index.ts
#	packages/boot/plugin-manager/src/types.ts
#	packages/boot/plugin-manager/tests/manager.spec.ts
#	packages/client/ui-settings-plugin-inventory/src/client/locales.ts
#	packages/client/ui-settings-plugin-inventory/src/client/management.tsx
#	packages/client/ui-settings-plugin-inventory/tests/components.client.spec.tsx
#	packages/extensions/tool-cordis/src/api-catalog.ts
#	pnpm-lock.yaml
#	scripts/verify-default-product-isolation.spec.ts
2026-09-15 21:15:15 +08:00
07akioni 6f893f270a Merge pull request #4263 from deepseek-harness/desktop/native-fatal-recovery
feat(desktop): use native dialogs for fatal recovery
2026-09-15 21:06:04 +08:00
Turtle faf8da83f0 Merge pull request #4277 from deepseek-harness/turtle/plugin-build-approval
fix(plugin-manager): approve blocked dependency builds before retrying
2026-09-15 20:59:02 +08:00
Yichen Jiang 8059d76ea3 feat(plugins): ship Auto review as an optional bundle
The installation lists @deepseek-ai/dsh-experimental-auto-review beside
the two Agent Teams layers under dsh.optionalBundles, so a blank Web
profile offers it in the built-in group switched off. The bundle gets a
display title and one-liner, and its README says where it is switched on.
2026-09-15 20:58:37 +08:00
07akioni 8c28d87de8 Merge remote-tracking branch 'origin/master' into desktop/native-fatal-recovery
# Conflicts:
#	apps/web/tests/composer-draft-scroll.e2e.ts
2026-09-15 20:55:28 +08:00
imccyu 8129f8f6bd Merge pull request #4238 from deepseek-harness/worktree-bootfast3
Optimize Web startup dependency loading
2026-09-15 20:52:53 +08:00
Turtle e2ae9411cb feat: support weighted approval delegation 2026-09-15 20:51:47 +08:00
Yichen Jiang bc0ecae21f feat(plugins): ship optional bundles switched off and guide the install dialog
The dsh installation lists under `dsh.optionalBundles` the bundles it
ships for a person to switch on. The plugin manager reports them as
`optional`, and the Web plugin page shows them first, in a built-in
group with an official tag, off until selected and never removable.
Agent Teams ships this way, so a blank profile offers both of its
layers. Default-product isolation, the workspace constraints, and the
packed-install check accept that one dependency edge and nothing else
experimental.

A bundle's title and one-liner come from `dsh.title` and the new
`dsh.description`, else from the package name and `description`. A
dependency without a bundle patch is no longer listed unless the
profile selects it. The install dialog asks for a package name or
address; a guide under the field shows the three accepted forms with
an example each and ends in a security warning, and the copy no longer
speaks of a plugin ID.
2026-09-15 20:51:12 +08:00
imccyu 7fb4cb4c8e fix(client): version lazy chunks by build generation 2026-09-15 20:45:49 +08:00
imccyu 45c74c5483 fix(client): satisfy chunk loader test lint 2026-09-15 20:45:49 +08:00
imccyu b98d5c8003 test(client): cover lazy chunk loader branches 2026-09-15 20:45:49 +08:00
imccyu 72aaad53fd docs(config): refresh generated catalog pairing 2026-09-15 20:45:49 +08:00
imccyu b1471fd73c perf(client): load split bundles on demand 2026-09-15 20:45:49 +08:00
imccyu 7f5385bf01 revert(client): remove eager chunk scanning 2026-09-15 20:45:49 +08:00
imccyu d28807e05c fix(client): preserve lazy chunk runtime semantics 2026-09-15 20:45:49 +08:00
imccyu 7c74636892 perf(api-gateway): avoid duplicate client input parsing 2026-09-15 20:45:49 +08:00
imccyu 75a56be10c perf(llm): avoid aggregate pi-ai runtime import 2026-09-15 20:45:49 +08:00
imccyu ee9f43bc5d fix(client): align lazy chunk metadata 2026-09-15 20:45:49 +08:00
imccyu a5c224f9b1 feat(client): lazy-load PDF and terminal runtimes 2026-09-15 20:45:49 +08:00
Turtle ef4985792d docs: refresh plugin manager dependency graph 2026-09-15 20:45:09 +08:00
imccyu 49c341a449 Merge pull request #4292 from deepseek-harness/revert-4285-fix/composer-draft-scroll-jump
Revert "fix(web): insert pasted composer text as line-break nodes"
2026-09-15 20:44:54 +08:00
imccyu f0367432d4 Revert "fix(web): insert pasted composer text as line-break nodes" 2026-09-15 20:44:32 +08:00
07akioni 89a89408c6 refactor(desktop): remove unused recovery IPC paths 2026-09-15 20:38:37 +08:00
Turtle a5dea502a6 fix(plugin-manager): address approval review and remove agent notices 2026-09-15 20:37:36 +08:00
07akioni 6db9466c4e test(web): synchronize composer selection before deletion 2026-09-15 20:30:04 +08:00
07akioni 7b36291967 Merge remote-tracking branch 'origin/master' into desktop/native-fatal-recovery 2026-09-15 20:27:09 +08:00
07akioni 09be5f750a fix(desktop): clean profile core packages before production startup 2026-09-15 20:23:08 +08:00
Chinesezjc 0810a4403a Merge pull request #4285 from deepseek-harness/fix/composer-draft-scroll-jump
fix(web): insert pasted composer text as line-break nodes
2026-09-15 20:03:25 +08:00
07akioni 791f731c08 fix(desktop): bound fatal diagnostics and restore failed package operations 2026-09-15 20:00:05 +08:00
07akioni f4b7a5948c fix(desktop): support Node 26 runtime archive extraction 2026-09-15 19:44:59 +08:00
liukx0205 cccfdb6040 Merge origin/master into feat/composer-selection-keyboard 2026-09-15 19:42:37 +08:00
gengruilin 7aca916679 fix(docs): keep platform commands readable in MPA builds 2026-09-15 19:30:58 +08:00
Chinesezjc 96da25c8f5 fix(web): insert pasted composer text as line-break nodes
The composer's paste path used RangeSelection.insertText, which keeps every
pasted newline inside one text node. In that document the browser reports the
collapsed caret's geometry as the whole block's, so deleting the draft's last
line moved the capped scrollport to the draft's head while the caret stayed at
its end.

RangeSelection.insertRawText splits the input into text and line-break nodes,
the document a typed draft already has.
2026-09-15 19:29:53 +08:00
Yichen Jiang 96136c0282 Merge remote-tracking branch 'origin/master' into feat/plugin-mgmt-4-web 2026-09-15 19:17:09 +08:00
Yichen Jiang d50f062c64 fix(web): reword the plugin install dialog and name failed actions
Drop the "built-in components it changes" section from a bundle's page:
the rows a patch overrides are a composition detail nobody acts on from
the page. A failed enable, disable, uninstall, or row switch now says
which it was, and the Chinese toasts lose their trailing period. The
install dialog is worded around the plugin ID, which is the package
name, with a hint on what an ID looks like and no real plugin as the
example; the spec forms it names are the ones the Host's inspect takes.
2026-09-15 19:06:52 +08:00
Yichen Jiang 5c8b4e5834 fix(web): show the full package name on a bundle's page
A bundle's title is its `dsh.title` or a shortened name, so the page
never said which package a bundle is, and nothing on it could be typed
into an install elsewhere. The name now sits under the title as the exact
package spec.
2026-09-15 18:41:56 +08:00
creatixchu a79b97ecca feat(deliverables): compare each changed file from the card
Rows of the changed-files card open a `changes-diff` right-Sidebar tab that compares the file at turn start and turn end. The workspace-changes recorder copies every file a file tool edits into the Session's temporary directory before the first edit and again at turn end, so files git does not cover are compared without git and counted first-to-last; `maxFileBytes` caps copies and snapshot reads, and `diffTimeoutMs` degrades a slow line comparison to whole-file replacement.
2026-09-15 18:38:33 +08:00
Turtle f9756edac0 test(plugin-manager): canonicalize pnpm fixture workspace paths 2026-09-15 18:33:00 +08:00
Turtle db2e03b89d refactor(web): derive workspace hierarchy automatically from paths 2026-09-15 18:31:22 +08:00
Turtle 8848e1e94f test(plugin-manager): install packed addon for build approval coverage 2026-09-15 18:22:31 +08:00
Yif c6b81a75fd fix(web): polish the plugin page, detail page, and rail per design
Ported from fix/plugin-manager-ui-polish (cce193cff3, 4ed0f1c9cb) onto
the page as it stands after the #4182 re-port: a 32px rhythm on the page
and the detail sections; a four-arc pinwheel icon on the cards, the
detail head, and the sidebar entry; the version as a tag beside the
detail title and the crumb leading back only; a red-tinted uninstall pill
with its trash icon and a plus icon on Add plugin; a round refresh action
and caption-toned counts; 12px hover rounding across the rail controls;
and the group copy renamed to Installed. The non-bundle group and its
info tooltip are not carried, since the page lists bundles only.
2026-09-15 18:11:11 +08:00
Turtle ffffac3cba fix(plugin-manager): approve blocked dependency builds before retrying 2026-09-15 18:09:28 +08:00
Turtle e706da7424 refactor(web): unify workspace grouping controls and row highlights 2026-09-15 18:03:18 +08:00
Turtle d492b2cd36 feat(web): group sidebar workspaces by parent folder 2026-09-15 17:56:33 +08:00
Yichen Jiang 0d4b32f077 fix(web): keep plugin cards in title order across switches
The Host lists selected bundles before the rest of the profile's
dependencies, so switching a bundle moved its card to the front or the
back of the sidebar page. The store now orders the views by the title a
person reads, and a card stays where it is whatever the Host answers.
2026-09-15 17:55:57 +08:00
_Kerman 31209ea9d7 Merge pull request #2746 from deepseek-harness/xtr/durable-inbox-web-recovery
fix(web): restore pending Inbox after restart
2026-09-15 17:42:57 +08:00
creatixchu 9f219e48a9 Merge remote-tracking branch 'origin/master' into worktree/code-diff-card
# Conflicts:
#	scripts/gen-cordis-catalog.ts
2026-09-15 17:35:04 +08:00
Turtle 775d5f5369 Merge pull request #4262 from deepseek-harness/turtle/author-approval-weight
feat(ci): add author approval credit from merged PR history
2026-09-15 17:31:24 +08:00
gengruilin 423e86ff7d fix(docs): preserve menu activation across pointer focus changes 2026-09-15 17:28:14 +08:00
creatixchu c8bc10440b fix(workspace-changes): review round on the served summaries
A repository whose baseline snapshot failed records nothing instead of
degrading to a file-tool summary; the write tool persists whether it
created or updated, so an unchanged overwrite outside snapshot coverage
no longer counts its content as added; hunks inside nested repositories
are dropped before check-ignore, which refused them with exit 128 and
lost the whole turn; a temporary root inside the work tree keeps the
recorder's own directory out of the snapshots; numstat keeps tabs in
file names; the summary carries line totals over the uncapped list and
the snapshot tree ids; the client's summary store abandons reads that
began before a connection reset. Docs and fixtures follow.
2026-09-15 17:28:14 +08:00
Yichen Jiang dc9256536b Merge remote-tracking branch 'origin/master' into feat/plugin-mgmt-4-web
Master now carries the final #4182 plugin manager and the live client
module graph of #4189, so the web management layer is re-ported onto
them:

- The manager keeps master's `ManagementError` codes, `ChangeResult`
  stages, `configure()` under `hmr.runExclusive`, `reload()` warnings
  and `writePluginEnabled` name matching, and adds back `inspect`,
  request-id installs with `plugin-manager/install-log` and
  `plugin-manager/install-state`, `cancelInstall`, `listBundles` titles,
  rows and overrides, `packageResult.kind`, `pnpmCommand` and
  `inspectTimeoutMs`, and `plugin-manager/changed` after each change and
  each `profile/reconciled`. A failed or cancelled installation restores
  the snapshotted manifest and lockfile instead of master's one-shot
  `pnpm remove` cleanup, so `cleanup` and `remainingDependencies` leave
  the result.
- App boot keeps master's reconciliation diagnostics and emits
  `profile/reconciled`; `watchUserPatches` goes with the launcher's
  watcher now that HMR owns profile reloads.
- The settings Plugin list tab stays read-only with #4189's page-local
  sync failures and retry; master's bundle form and row checkboxes are
  dropped again. The sidebar page words the Host's codes through its
  dictionary, and a client bundle change follows the live module graph
  without a page reload.
- The web e2e scaffold no longer chooses a reload policy: the base
  bundle's `hmr` row turns on with the profile context and application
  readiness, and `profile.hmr: false` disables it through an overlay for
  the startup-only scenario.
2026-09-15 17:28:08 +08:00
_Kerman 4d306deb0a Merge remote-tracking branch 'origin/master' into xtr/durable-inbox-web-recovery 2026-09-15 17:22:59 +08:00
gengruilin 38b2bf2f6c fix(docs): address Markdown actions review feedback 2026-09-15 17:22:50 +08:00
_Kerman f3c0ae620b test(web): disambiguate workspace rows during reconnect 2026-09-15 17:22:49 +08:00
Wenlu Wang 011bbf8eec Merge pull request #4230 from deepseek-harness/feature/model-image-input-setting
feat(web): add model image input settings
2026-09-15 17:14:29 +08:00
Turtle b5a6905832 feat(ci): add author approval credit from merged PRs 2026-09-15 17:14:23 +08:00
Turtle 47c94a1d5e Merge pull request #4252 from deepseek-harness/turtle/profile-command-shorthand
feat(cli): support dsh <profile> shorthand
2026-09-15 17:08:24 +08:00
07akioni 57af1f0013 docs(desktop): remove stale runtime and reload descriptions 2026-09-15 16:57:55 +08:00
gengruilin eb59250ce9 feat(docs): present Markdown actions in a split-button menu 2026-09-15 16:52:46 +08:00
_Kerman 992a932a16 Merge remote-tracking branch 'origin/master' into xtr/durable-inbox-web-recovery
# Conflicts:
#	packages/api/session-controller/README.i18n.yaml
#	packages/api/session-controller/README.md
#	packages/api/session-controller/README.zh.md
#	packages/client/ui-conversation/README.i18n.yaml
#	packages/client/ui-conversation/README.md
#	packages/client/ui-conversation/README.zh.md
#	packages/client/ui-conversation/src/client/contract/input.ts
#	packages/client/ui-conversation/src/client/input/facade.ts
2026-09-15 16:52:24 +08:00
Magolor bd421cce7b fix(llm): resolve Messages endpoint suffix (#4241)
* fix(llm): resolve Messages endpoint suffix

* test(subagent): update Messages endpoint expectation

* fix(llm): preserve official Messages routes

* fix(llm): harden Messages endpoint resolution

* refactor(llm): clarify Messages API ownership

* fix(llm): recognize only exact Messages v1 roots
2026-09-15 16:51:56 +08:00
07akioni d50d3cb745 Merge remote-tracking branch 'origin/master' into desktop/native-fatal-recovery 2026-09-15 16:50:40 +08:00
Turtle 7d4188b450 fix(cli): address profile shorthand review feedback 2026-09-15 16:49:03 +08:00
Turtle 1d6534a810 feat(cli): support profile command shorthand 2026-09-15 16:49:02 +08:00
07akioni dfb07a038c feat(desktop): replace failure pages with native recovery dialog 2026-09-15 16:48:27 +08:00
Turtle 511216983e Merge pull request #4182 from deepseek-harness/turtle/plugin-manager
feat: manage profile plugins with unified dsh-hmr
2026-09-15 16:41:28 +08:00
Dudu-0223 cc872a39b9 test(subprocess): verify owned exit listeners on disposal 2026-09-15 16:39:42 +08:00
Yichen Jiang 4d1adb8541 feat(web): manage plugins over the #4182 manager from the sidebar page
The sidebar Plugins page now drives `ctx.pluginManager` from #4182 and the
settings Plugin list tab goes back to read-only: its bundle form and row
checkboxes are removed, and the page joins `listBundles` with
`listPlugins` into one view per bundle, decides availability from the
inventory's `managementAvailable`, switches bundles and rows through
`setBundleEnabled` and `setPluginEnabled`, and confirms uninstalls.

The manager gains what the guided install dialog needs: `inspect(spec)`
reads a spec through the registry or a directory before anything installs
and refuses specs without a bundle; `installBundle` takes a request id,
streams each pnpm run as `plugin-manager/install-log`, reports its phases
as `plugin-manager/install-state`, classifies a failed run into
`packageResult.kind`, names the bundle it added, and restores
`package.json` and `pnpm-lock.yaml` when the run fails, is cancelled, or
adds a package without a bundle patch; `cancelInstall(requestId)` answers
only after pnpm exited and the files are back; `listBundles` carries
titles, one-liners, declared rows with their live entries, and the
built-in rows a bundle overrides; every completed operation and every
patch generation applied outside the manager emits
`plugin-manager/changed`. The config gains `pnpmCommand` and
`inspectTimeoutMs`. App boot emits `profile/reconciled` after each applied
patch generation and finds a root Include mounted under its pinned id by
another copy of the module.

Row diagnostics, dependency checks, and the non-bundle dependency group
are not carried over; the web e2e scaffold mounts a launcher-style
managed profile instead of the removed profile runtime.
2026-09-15 16:36:31 +08:00
Yichen Jiang b3e964c340 Merge PR #4182 (turtle/plugin-manager) into feat/plugin-mgmt-4-web
The web plugin management layer now sits on the current-profile plugin
manager from #4182 instead of the boot and manager layers of #3593 and
#3594. This merge takes #4182's host side whole — `packages/boot/hmr`,
its `packages/boot/plugin-manager`, `profileContext` in app-boot, the
vendored loader change — and drops the replaced host packages and their
app-boot, inventory, Remote, CLI, and catalog edits. The web files of
#3596 are carried over unchanged: the sidebar page package, the
ui-primitives terminal changes, the settings-section tweaks, the e2e
scenarios and fixtures, and the two web Agent Notes. They do not build
against the new host until the following commit adapts them.
2026-09-15 16:36:31 +08:00
creatixchu da6e3f9edf fix(workspace-changes): count an appended line as one addition
The file tools persist both sides of a hunk without a trailing newline,
so re-diffing an append read the previous last line as rewritten and
reported +2 -1 for +1 -0. Both sides are line-terminated before the
diff, the rule the per-call diff card already applies.
2026-09-15 16:31:24 +08:00
Turtle cc190b07d5 Merge pull request #4002 from deepseek-harness/turtle/blame-weighted-approval
feat(ci): scale approval weights with production blame
2026-09-15 16:30:25 +08:00
Dudu-0223 25525dc495 test(web): register file-link scenario in host compilation 2026-09-15 16:25:49 +08:00
Dudu-0223 9e611c90a3 test(web): finish sidebar transitions before preview capture 2026-09-15 16:22:40 +08:00
Dudu-0223 7bc0154bfc test(web): verify keyboard file navigation and capture preview 2026-09-15 16:22:03 +08:00
Turtle 311156b1c2 Merge master and preserve profile-managed HMR 2026-09-15 16:20:47 +08:00
Dudu-0223 1ec62afbdb feat(web): open Markdown file links in sidebar previews 2026-09-15 16:17:53 +08:00
gengruilin cb464f1894 fix(docs): preserve UTF-8 in raw Markdown navigation 2026-09-15 16:15:11 +08:00
Turtle 794b658401 fix(ci): address production blame approval review 2026-09-15 16:14:37 +08:00
Turtle 08021a16d8 fix(plugin-manager): keep package operations outside HMR 2026-09-15 16:08:22 +08:00
creatixchu 8f0cdc9a98 Merge remote-tracking branch 'origin/master' into worktree/code-diff-card 2026-09-15 16:05:29 +08:00
Yichen Jiang b03d5c68ea Merge pull request #4189 from deepseek-harness/worktree/client-modules-live
feat(web): apply client plugin changes without reloading
2026-09-15 15:57:45 +08:00
gengruilin 23135e62dc feat(docs): add page Markdown copy and view actions 2026-09-15 15:55:52 +08:00
gengruilin bcb49ade82 feat(docs): add independent platform command tabs 2026-09-15 15:51:26 +08:00
imccyu b51eb87125 Merge pull request #4209 from deepseek-harness/fix/issue-3479-linear-cache
fix(session-controller): reconcile list cache in linear time
2026-09-15 15:51:08 +08:00
creatixchu c48f4203d9 feat(workspace-changes): summarize file-tool edits outside a git repository
A working directory outside any repository, or a Host without git, no
longer loses the card: the recorder skips the snapshots and builds the
summary from the hunks the file tools persisted, with the working
directory as the workspace, so shell edits are the only gap. The
sidebar e2e scopes its chip clicks to the prose mention now that the
card offers the same open, and the present-svg and permission-policy
scenarios gain the card their write calls earn.
2026-09-15 15:44:11 +08:00
Yichen Jiang 3e24e501cd Merge remote-tracking branch 'origin/master' into worktree/client-modules-live 2026-09-15 15:43:42 +08:00
07akioni 05fb7b90e8 Merge pull request #3981 from deepseek-harness/07akioni/thin-electron-webui
refactor(desktop): run shared Web UI in a thin Electron shell
2026-09-15 15:39:43 +08:00
Yichen Jiang c28fcc6cdb Merge remote-tracking branch 'origin/master' into worktree/client-modules-live
# Conflicts:
#	docs/subsystems/client-modules.i18n.yaml
#	docs/subsystems/client-modules.md
#	docs/subsystems/client-modules.zh.md
#	packages/client/hmr/package.json
#	packages/client/modules/README.i18n.yaml
#	packages/client/modules/README.md
#	packages/client/modules/README.zh.md
2026-09-15 15:31:14 +08:00
Turtle 61665c3454 fix(plugin-manager): clean failed installs and address critical review findings 2026-09-15 15:15:49 +08:00
creatixchu 2a77c59a49 test(web): refresh the changed-files golden for master's edit-card counts and desktop copy 2026-09-15 15:14:35 +08:00
kingwl 41e591b3e4 fix(web): address model image settings review 2026-09-15 15:13:56 +08:00
creatixchu 1ea80b7b69 Merge remote-tracking branch 'origin/master' into worktree/code-diff-card
# Conflicts:
#	packages/client/ui-deliverables/package.json
#	snapshots/web/present-svg/ui.expected.md
2026-09-15 15:11:02 +08:00
07akioni 830c82687b revert: restore original CLI profile boot exports 2026-09-15 14:56:19 +08:00
ihsiang 9441552679 Merge pull request #4163 from deepseek-harness/ihsiang/fix-conversation-width-handle-layering
fix(ui): keep transcript resize handles unobtrusive
2026-09-15 14:53:40 +08:00
yixiangihsiang 1bec11e366 fix(ui): keep transcript resize handles unobtrusive 2026-09-15 14:39:38 +08:00
liukx0205 21a785902b fix(client): keep a launcher-opened menu open through its own focus track
Opening the trigger menu from the launcher button has to put the keyboard in
the editor for the arrows to drive it, and Lexical's focus restores its
selection a tick later — a track the controller read as an empty draft and
answered by closing the menu the gesture had just opened. A launcher-opened
menu now survives that single follow-up track; typing, picking, Escape or a
pointer press still takes over.

The access-confirmation golden follows the panel's new highlight: it parks on
the row the options mark as the current value rather than the top row.
2026-09-15 14:39:21 +08:00
07akioni 9ce6d98e11 fix(ci): validate Web injection payload and cover macOS sidebar controls 2026-09-15 14:32:29 +08:00
Turtle 07c6a65f4f Merge pull request #4232 from deepseek-harness/turtle/orchestrator-0d396914f8c0
fix(web): clarify external-app limits for delivered files
2026-09-15 14:25:00 +08:00
Yichen Jiang 6d05c9557f fix(web): forward client graphs without Host lifecycle waits 2026-09-15 14:23:47 +08:00
liukx0205 afbe3a4b1d refactor(client): compute the menu's keyboard region once per key 2026-09-15 14:22:03 +08:00
liukx0205 b263581e92 fix(client): answer the review bot's findings on the keyboard hand-offs
- The model seat decides before consuming: a focused control that is not a row
  (a retry button) keeps the browser's traversal, and Tab enters the list only
  from the trigger.
- A launcher-opened menu is a fresh intent, so the dismissal that closed the
  same token earlier no longer silences it.
- Comments and JSDoc now match the implementation: the near-end entry resumes
  from the walk's last index, Shift+Tab leaves whenever the menu is open, and
  the anchor hand-back names the control that opened the menu.
- The e2e focus assertions all go through `expect.poll`.
- Regression coverage for a rowless pane (the trigger keeps the keyboard) and
  for a focused retry keeping its Tab, in the seat and the popup shell.
- The PR records the two public-surface changes (`SessionInput.focus()` in,
  `bindComposerFocus` out) and the row-fill focus decision.
2026-09-15 14:21:00 +08:00
07akioni 255374afa1 fix(cli): expose only the shared profile runner API 2026-09-15 14:16:48 +08:00
liukx0205 5c3081eeaa fix(client): tighten the keyboard hand-offs, and drop the dialog Escape layering
Review follow-ups on the hand-offs this branch added:

- Menu gives the keyboard back to the control that opened it (an anchor may
  wrap several, as a split button does), falls back to a disabled-free anchor
  button, leaves a Tab it cannot use to the browser, and no longer moves focus
  while the owner keeps the list open.
- The model seat settles only real rows with Tab and keeps the keyboard on its
  trigger when a pane's rows are disabled or absent.
- The popup shell leaves Tab to the browser when nothing can be settled (the
  error strip's retry button stays reachable), and a dismissal caused by a
  stale catalog returns the keyboard like the other paths.
- A frozen-tier track is the submit gesture's own bookkeeping and no longer
  re-arms a menu the user dismissed.
- The launcher reuses the shared caret-preserving focus helper; the option
  contract records that `active` is the row an accept gesture confirms; the
  conversation README documents the composer's key and focus behavior.

The dialog/menu Escape layering this branch also carried is out of scope here
and has been removed again.
2026-09-15 14:16:14 +08:00
Turtle 59fb655d66 Merge remote-tracking branch 'origin/master' into turtle/plugin-manager 2026-09-15 14:16:09 +08:00
Yichen Jiang 2c9375e509 fix(web): reconcile pending plugin revisions and preserve bootstrap 2026-09-15 14:15:23 +08:00
Turtle b77c19c376 fix(hmr): retain consecutive profile configuration changes 2026-09-15 14:13:57 +08:00
Turtle 9cee793b90 Merge branch 'master' into turtle/blame-weighted-approval 2026-09-15 14:08:57 +08:00
liukx0205 3065f9cc27 docs(client): drop a reverted implementation from the note's evidence list 2026-09-15 13:59:38 +08:00
07akioni b43e85129c Merge macOS hidden titlebar while preserving local Web startup 2026-09-15 13:58:23 +08:00
liukx0205 4fc515cb68 fix(client): keep the ring on the triggers and off the menu rows
The two split the other way around: the composer's triggers keep the focus
ring their design gives them (a 2px `--dsw-alias-border-l3` ring), while a
walked menu row shows the hover fill alone, without the browser's default
outline doubling it.
2026-09-15 13:55:50 +08:00
liukx0205 449a4610d7 fix(client): keep the browser ring on the focused menu row
The menu family was the only place that suppressed the browser's default focus
ring. It keeps that ring now, like the app's other controls, on top of the
hover fill a walked row already carried.
2026-09-15 13:52:49 +08:00
07akioni 4feb87da34 feat(desktop): load bundled Web UI before backend readiness 2026-09-15 13:43:27 +08:00
Turtle 0976569d16 fix(web): clarify external app availability for delivered files 2026-09-15 13:42:42 +08:00
Turtle b5bbf210d1 Merge pull request #4198 from deepseek-harness/turtle/master-ci-packed-inventory
test(ci): repair packed inventory context fixture
2026-09-15 13:40:44 +08:00
liukx0205 4b8a47a198 docs(client): record the SessionInput focus addition in the note 2026-09-15 13:38:56 +08:00
liukx0205 f46b025fd5 feat(client): give the shared menu family its keyboard model
Arrow navigation was bound to `autoFocus`, so the dropdowns that open with the
keyboard on their trigger — the composer's permission seat, the settings
pickers, the workspace and preset chips — had no walk at all, and a walk that
read its position from `document.activeElement` alternated between the first
and last row as soon as a row refused focus. The walk now works either way and
resumes from the index it last focused.

The keyboard returns to the anchor on Escape and on a selection — unless the
owner moved it itself, as a presented file card does for its preview button —
and the focused row wears the hover fill instead of the browser's ring. An open
menu takes the first Escape from the dialog it sits in.

The composer's trigger menu keeps its own Tab, which settles or drills the
highlighted candidate; Escape and Shift+Tab leave it without settling, and a
dismissed menu stays dismissed until its query changes. Opening it from the
launcher button returns the keyboard to the editor first, since the menu is a
combobox over that editor.
2026-09-15 13:35:27 +08:00
liukx0205 c47a469aec feat(client): accept and leave with Enter, Tab, and Escape in the composer
The popup select panel and the model seat hold focus while open, and their Tab
fell through to the browser's traversal, leaving an open surface that only a
pointer press clears. Both now settle on Enter or Tab, leave on Escape or
Shift+Tab, walk with the arrows, and park on the value in use: the panel's
highlight on the row its options mark current, the seat's drilled pane on its
checked row, with the keyboard handed back to the cell that drilled in when the
pane is left.

Dismissal rides the conversation's own focus(), so the caret returns where the
draft left it instead of at the start.
2026-09-15 13:35:04 +08:00
Yichen Jiang 1fec9adb61 docs(web): clarify client plugin reload failures 2026-09-15 13:29:58 +08:00
kingwl 3df6f92d03 feat(web): configure model image input in settings 2026-09-15 13:26:25 +08:00
Yichen Jiang 358384f045 Merge pull request #4206 from deepseek-harness/worktree/sidebar-session-recovery
feat(web): restore sidebar layouts and reclaim unattended terminals
2026-09-15 13:25:27 +08:00
Turtle 86497c479c Merge remote-tracking branch 'origin/master' into turtle/plugin-manager
# Conflicts:
#	packages/client/ui-settings-plugin-inventory/package.json
2026-09-15 13:09:38 +08:00
Yichen Jiang 149ed69912 test(subprocess-local): cover configured ZDOTDIR without zsh 2026-09-15 13:08:03 +08:00
Turtle abd765a600 refactor(hmr): own profile reload lifecycle through YAML 2026-09-15 13:01:06 +08:00
Yichen Jiang ac2bed35e2 feat(web): guide plugin installation with a pre-install check and classified failures
The install dialog asks the Host to read a spec before installing it:
`plugins/inspect` sorts the spec (registry name, absolute path, git address,
tarball), asks the registry through `pnpm view` in the profile directory, or
reads a directory's package.json, and refuses what would fail with
`plugins/inspect-rejected` and a problem the dialog words under the field.
A failed pnpm run carries a `kind` classified from how it ended and what pnpm
printed, shown as one line with the output folded behind the details.
Enabling happens after the fact from the installed screen, which scrolls the
list to the first new bundle. Refusals of the moment and the confirmed
cancellation are toasts; the run is stopped through the manager's
`cancelInstall` and the dialog offers the spec again once the Host confirms.
The non-pack dependency group folds by default under its own name.

The host config gains `inspectTimeoutMs`; the CLI passes it explicitly.
2026-09-15 12:43:44 +08:00
Yichen Jiang ad8a00c291 Merge remote-tracking branch 'origin/master' into worktree/sidebar-session-recovery
# Conflicts:
#	packages/subprocess/subprocess-local/src/index.ts
2026-09-15 12:15:20 +08:00
Yichen Jiang 281723bed8 fix(web): isolate terminal bindings and validate saved layouts 2026-09-15 12:07:01 +08:00
Dudu-0223 53046b21b4 fix(session-controller): reconcile list cache in linear time 2026-09-15 11:36:52 +08:00
07akioni aa083ebfa4 Merge latest master into thin Electron Web UI 2026-09-15 11:25:07 +08:00
imccyu 0d1f50007f Merge pull request #4192 from deepseek-harness/worktree-bootfast2
perf(web): bootstrap client fast
2026-09-15 11:16:06 +08:00
imccyu e459e32637 perf(typert): materialize generated schemas on first use 2026-09-15 11:06:43 +08:00
imccyu 232ab768a9 perf(runtime): defer optional native dependencies 2026-09-15 11:06:43 +08:00
imccyu eb8cc594b3 feat(util): add caller-relative lazy require 2026-09-15 11:06:42 +08:00
imccyu 42286726c8 perf(web): defer client combo assembly 2026-09-15 11:00:34 +08:00
Yichen Jiang a2112c07e4 test(subprocess): refresh terminal activity API snapshot 2026-09-15 10:47:47 +08:00
CreatixChu 0a15e36e7f Merge pull request #4171 from deepseek-harness/worktree/release-dsh-0.1.6-alpha.1
release(dsh): 0.1.6-alpha.1
2026-09-15 10:42:33 +08:00
Yichen Jiang ccd6121c99 Merge remote-tracking branch 'origin/master' into worktree/sidebar-session-recovery
# Conflicts:
#	apps/web/tests/sidebar-terminal.e2e.ts
#	packages/client/ui-sidebar-terminal/src/client/TerminalBody.module.css
2026-09-15 10:29:08 +08:00
Yichen Jiang b25c5ad82e feat(web): restore sidebar layouts and reclaim unattended terminals 2026-09-15 10:27:44 +08:00
creatixchu ea53423b60 release(dsh): 0.1.6-alpha.1 2026-09-15 09:35:57 +08:00
Yif f2db686404 feat(desktop): macOS hidden titlebar with vibrancy sidebar
hiddenInset titlebar with traffic lights over a vibrancy sidebar, darwin-only
via data-platform set by the desktop preload: transparent chain to the window
material, native-theme sync from the app theme source, sidebar top strip +
full hide when collapsed with reopen controls in the new
conversation.session.header.leading slot, title-row drag regions, and
fullscreen right-sidebar traffic-light clearance via the dockkit strip inset.
2026-09-15 02:26:57 +08:00
turtle1999 dcf1d274d9 test(ci): repair packed inventory context fixture 2026-09-15 01:34:35 +08:00
07akioni bafe2b7d55 Merge master into thin Electron Web UI and reconcile runtime resolution 2026-09-15 01:17:42 +08:00
Chinesezjc 64a8ba929d Merge pull request #4195 from deepseek-harness/fix/compaction-banner-offset
fix(web): hold a compaction summary's code banner below the pinned header
2026-09-15 00:13:26 +08:00
Chinesezjc b416ac99e4 fix(web): hold a compaction summary's code banner below the pinned header
A summary's fenced code block pins its banner at the scrollport top, where the
pinned compaction header already sits, so the header covers the banner's Copy
control and a click there collapses the summary. Stop the banner below the
header's band and square the pinned header's corners so its opaque fill masks
the scrolling prose at the edges.
2026-09-15 00:03:33 +08:00
Turtle ca4db9c755 fix(hmr): match Node module paths and contain startup reload failures 2026-09-15 00:00:53 +08:00
Chinesezjc c75e3d4e81 Merge pull request #1170 from deepseek-harness/sticky-collapsible-headers
feat(web): pin Think and compaction headers sticky while scrolling
2026-09-14 23:34:53 +08:00
imccyu 57364a8475 Merge pull request #4104 from deepseek-harness/feat/electron-asar-runtime-resolution
feat(desktop): use runtime profile resolution in packaged carriers
2026-09-14 23:30:37 +08:00
Turtle 4d13d8ad9d Merge remote-tracking branch 'origin/master' into turtle/plugin-manager 2026-09-14 23:30:17 +08:00
Turtle 5a9c159c27 fix: preserve manager failures and support worker preview imports 2026-09-14 23:26:43 +08:00
Turtle 8e327513ba fix: remove inactive bundles after incomplete installation 2026-09-14 23:17:24 +08:00
imccyu 344a3c9257 test(desktop): avoid unsafe asymmetric matchers 2026-09-14 23:13:01 +08:00
imccyu 01f2f01a2f Merge pull request #3651 from deepseek-harness/fix/profile-module-resolution
feat(boot): add profile resolution modes
2026-09-14 23:12:15 +08:00
imccyu 1b56c865fa fix(pkg): restore VFS Dirent reads 2026-09-14 23:10:47 +08:00
Turtle 438c862fea refactor: keep profile launch context data-only and HMR backend-scoped 2026-09-14 23:09:06 +08:00
Turtle d06e6b5519 feat: coordinate profile management through dsh-hmr 2026-09-14 23:09:06 +08:00
Turtle 98b92b683c feat: add current-profile plugin manager service and Web controls 2026-09-14 23:09:05 +08:00
Yichen Jiang e350e76496 Merge commit '8448a6a48511508f6f6e19273c13ab994897dcb0' into worktree/pr3596-global-only
# Conflicts:
#	packages/boot/plugin-manager/tests/plugin-manager.spec.ts
2026-09-14 22:55:22 +08:00
Yichen Jiang 70f6f30817 fix(plugins): join package removal when the manager is disposed 2026-09-14 22:53:10 +08:00
imccyu fa7d5519f5 feat(desktop): run runtime host from asar 2026-09-14 22:52:44 +08:00
imccyu c917a4e0bd feat(cli): force runtime resolution in pkg builds 2026-09-14 22:52:44 +08:00
imccyu 0bade5a010 chore(runtime): upgrade builtin loader to 0.1.6 2026-09-14 22:52:44 +08:00
imccyu c3a66d9cd2 refactor(boot): use addon-managed native cache 2026-09-14 22:50:11 +08:00
imccyu d4350442e8 docs(boot): remove private native cache lifecycle 2026-09-14 22:50:00 +08:00
imccyu 0de61878b3 fix(boot): treat null exports as legacy resolution 2026-09-14 22:30:51 +08:00
imccyu 32e6e872f6 fix(boot): bind internal ESM default resolver 2026-09-14 22:30:51 +08:00
imccyu 0d4b097375 fix(app-boot): align remaining runtime resolution edges 2026-09-14 22:30:51 +08:00
imccyu 69ab6575d1 fix(boot): preserve selected explicit path errors 2026-09-14 22:30:50 +08:00
imccyu 3cacc0e69a fix(boot): preserve selected package failures 2026-09-14 22:30:50 +08:00
imccyu c75f667822 fix(boot): cover profile resolution edge cases 2026-09-14 22:30:50 +08:00
imccyu db098c8a24 fix(presets): isolate package lookup failures 2026-09-14 22:30:50 +08:00
imccyu 013aead5c9 fix(boot): align runtime profile resolution with links 2026-09-14 22:30:50 +08:00
imccyu 2fc699255f test(boot): use native path canonicalization 2026-09-14 22:30:49 +08:00
imccyu a663bbf4b8 test(boot): canonicalize Windows resolver paths 2026-09-14 22:30:49 +08:00
imccyu 9c914dfea9 test(boot): cover explicit fallback failures 2026-09-14 22:30:49 +08:00
imccyu 6823f8a00c fix(boot): align runtime and link resolution 2026-09-14 22:30:49 +08:00
imccyu aa4c46edeb fix(boot): drop stale workflow worker dependency 2026-09-14 22:30:49 +08:00
imccyu 123272b05e chore(cli): restore profile resolver lockfile entry 2026-09-14 22:30:49 +08:00
imccyu 662bdf3833 docs(profile-resolution): clarify review assumptions 2026-09-14 22:30:48 +08:00
imccyu 6aa2e4633c feat(boot): add profile resolution modes 2026-09-14 22:30:48 +08:00
imccyu 22fed0f1eb Merge pull request #4191 from deepseek-harness/worktree-draft-editor-isolation
refactor(web): isolate draft editor runtime and view bindings
2026-09-14 22:24:45 +08:00
Yichen Jiang bdc496cc06 feat(web): cancel plugin installation with Host confirmation 2026-09-14 22:20:01 +08:00
Yichen Jiang 27ec094db3 Merge commit 'd4993fc780f98c06304c47a09c018b2f48f70926' into worktree/pr3596-global-only 2026-09-14 22:11:30 +08:00
imccyu b5abe6cf29 refactor(web): isolate draft editor implementation without behavior changes 2026-09-14 22:10:52 +08:00
imccyu 218db70b75 docs(web): define two-stage draft editor isolation 2026-09-14 22:10:52 +08:00
Yichen Jiang cf992b52f9 fix(plugins): preserve observed exit codes on cancellation 2026-09-14 22:09:02 +08:00
Yichen Jiang 9c80145109 Merge commit '0f88503eb30b0c9e06d297f4863e5b42746e291c' into worktree/pr3596-global-only 2026-09-14 22:05:18 +08:00
Yichen Jiang f511455e14 test(plugins): verify CLI interruption and document recovery 2026-09-14 22:03:57 +08:00
_Kerman 11c4c52d1a Merge pull request #4186 from deepseek-harness/xtr/revert-3880-chat-behavior
fix(chat): revert Chat behavior changes from #3880
2026-09-14 22:03:27 +08:00
Yichen Jiang eca54e94a7 fix(plugins): publish shared subprocess installation chunks 2026-09-14 21:59:59 +08:00
Yichen Jiang b49f57ca12 fix(web): share pending loads across matching graph notifications 2026-09-14 21:59:58 +08:00
_Kerman d7a83ca5d6 docs(trajectory): clarify timing and thinking ownership 2026-09-14 21:55:14 +08:00
_Kerman 24a4c88859 test(chat): pin restored timing through settlement and reload 2026-09-14 21:55:05 +08:00
Yichen Jiang 9d58c54f49 Merge commit '1438b3ade6248047b74cc05f461845e9eb8bdedf' into worktree/pr3596-global-only
# Conflicts:
#	packages/boot/plugin-manager/tests/plugin-manager.spec.ts
2026-09-14 21:54:50 +08:00
Yichen Jiang 3302b38df1 Merge remote-tracking branch 'origin/master' into worktree/client-modules-live 2026-09-14 21:51:29 +08:00
Yichen Jiang ff1f3f72a1 feat(plugins): cancel installations after process and file cleanup 2026-09-14 21:50:33 +08:00
CreatixChu db942b3530 Merge pull request #4183 from deepseek-harness/worktree/session-log-upload-default-test-aware
feat(session): enable log upload by default with explicit test configuration
2026-09-14 21:49:42 +08:00
Yichen Jiang fb0fb48033 feat(web): apply client plugin changes without reloading 2026-09-14 21:47:38 +08:00
creatixchu 0eb87a4590 test: fix upload expectations and exited process cleanup 2026-09-14 21:34:38 +08:00
Tianyi Cui 7da882dbeb fix(session): pin the disabled upload branch in the real-API extension test
With the plugin defaulting to on, the messages e2e case that asserts an
absent `dsh_session_log` must disable it explicitly; otherwise the stub
rejects the field it did not expect and the model call finishes as an
error. Also align the wire reference and feedback subsystem docs with the
default-on field.
2026-09-14 21:27:27 +08:00
creatixchu 9532ed3b28 test(sdk): declare upload policy for existing replay compositions 2026-09-14 21:19:03 +08:00
creatixchu 31ec6bc7e3 fix(session): keep upload defaults independent of test runners 2026-09-14 21:15:42 +08:00
07akioni 6d835dfe47 docs: align historical timer reference with master 2026-09-14 21:10:25 +08:00
creatixchu ac917f4df3 docs: align Chinese session-log source reference 2026-09-14 21:04:13 +08:00
creatixchu 4885f90769 docs: refresh session-log config source reference 2026-09-14 21:02:31 +08:00
07akioni 5141675053 docs: mark removed workflow timer reference as historical 2026-09-14 21:01:35 +08:00
_Kerman 251ef01acf fix(chat): revert historical timing recovery from #3880 2026-09-14 21:00:40 +08:00
creatixchu 32b9c99560 Merge remote-tracking branch 'origin/worktree/session-log-upload-default-test-aware' into codex/pr-4183-ci 2026-09-14 21:00:20 +08:00
_Kerman 3db1085da2 fix(chat): restore collapsed thinking by default 2026-09-14 20:59:55 +08:00
creatixchu b35d728d42 test(session): cover environment-aware upload defaults 2026-09-14 20:59:55 +08:00
creatixchu ebf89a8455 Merge remote-tracking branch 'origin/master' into codex/pr-4183-ci 2026-09-14 20:59:46 +08:00
Tianyi Cui 6ce915d3fc fix(session): keep the recorded-session marker check branch-free
The per-file coverage gate measures `packages/*/*/src` at 100% branches;
a short-circuiting `||` over the two lane markers leaves the second
operand unexecuted under Vitest. Testing the marker list instead keeps
the same default without an uncovered branch.
2026-09-14 20:58:49 +08:00
07akioni 9413105c31 fix(desktop): prepare and sign usable bundled runtimes 2026-09-14 20:57:26 +08:00
Tianyi Cui 2389b65246 feat(session): default session-log upload on outside recorded-session lanes
`@deepseek-ai/dsh-session-log-deepseek` now contributes `dsh_session_log`
unless a composition sets `enabled: false`. A recorded-Session lane
(`$VITEST` or `$DSH_SNAPSHOT`) keeps the default off, because its
committed fixtures are both replay input and expected output for the
persisted log; no fixture regeneration is needed.
2026-09-14 20:49:44 +08:00
Yichen Jiang 4f7336c831 Merge pull request #4178 from deepseek-harness/worktree/terminal-color-contrast
fix(web): preserve terminal colors and cursor contrast
2026-09-14 20:38:25 +08:00
Yichen Jiang 578e1e428f test(web): cover terminal cursor theme binding 2026-09-14 20:30:19 +08:00
Yichen Jiang 80043785c4 fix(web): preserve terminal colors and cursor contrast 2026-09-14 20:17:19 +08:00
Yichen Jiang ab6bb7b86f refactor(web): keep Gateway argument handling unchanged 2026-09-14 20:16:49 +08:00
Yichen Jiang 850d2882f6 Merge commit '03af7e39c641a58fd77f5b3f7b3eb089f200e519' into worktree/pr3596-global-only 2026-09-14 19:57:15 +08:00
Yichen Jiang fd2c0df8cb Merge commit '6eab1e46616edf64daf1350a88526277ce915a10' into worktree/pr3594-manifest-mergeup 2026-09-14 19:56:41 +08:00
Yichen Jiang bf749078fb docs(architecture): condense launch overview after integration 2026-09-14 19:56:21 +08:00
Yichen Jiang 9dc51c4666 Merge commit '7d96a1bcda353371db935725ef3a8d228312f42e' into worktree/pr3594-manifest-mergeup
# Conflicts:
#	packages/api/remotes/src/client/index.ts
#	pnpm-lock.yaml
2026-09-14 19:55:22 +08:00
Yichen Jiang 3cbc19d1d0 Merge pull request #4173 from deepseek-harness/worktree/sidebar-guide-terminal-menu
feat(web): launch terminals from provider guide menus
2026-09-14 19:52:22 +08:00
Chinesezjc 67271a921b feat(web): pin Think and compaction headers sticky while scrolling
Both blocks render their expanded body uncapped, so a long reasoning chain or
compaction summary carried the disclosure header off the viewport and buried
the toggle. Pin each header to the conversation scroll container while the
block is open, keeping the rule scoped to these two blocks so the capped tool
rows do not stack headers at the top of the viewport.

The compaction header also overrides its stacking rank above the summary's
code-block banner and keeps an opaque hover fill.
2026-09-14 19:52:04 +08:00
Yichen Jiang 534d05a924 Merge remote-tracking branch 'origin/master' into worktree/pr3593-manifest-3899
# Conflicts:
#	.agents/notes/rejected/simplification/2026-07-26-builtin-timer-promises-for-hand-rolled-sleeps.i18n.yaml
#	.agents/notes/rejected/simplification/2026-07-26-builtin-timer-promises-for-hand-rolled-sleeps.md
#	.agents/notes/rejected/simplification/2026-07-26-builtin-timer-promises-for-hand-rolled-sleeps.zh.md
#	scripts/gen-cordis-catalog.ts
2026-09-14 19:51:13 +08:00
Yichen Jiang 4012092d24 feat(web): launch terminals from provider guide menus 2026-09-14 19:22:22 +08:00
07akioni 5105c77706 test(desktop): fix runtime CI fixtures across platforms 2026-09-14 19:20:12 +08:00
Yichen Jiang e936a5245f Merge commit '2b1fbef125279026d8df67db7143b54e87279f9a' into worktree/pr3596-global-only 2026-09-14 19:15:56 +08:00
Yichen Jiang f7170bd899 Merge commit 'beeaa1d083570c93fcb1500749454a5b9ea4b698' into worktree/pr3594-manifest-mergeup 2026-09-14 19:15:36 +08:00
Yichen Jiang 379fc28126 docs(cli): describe preserved bundle activation choices 2026-09-14 19:15:17 +08:00
Yichen Jiang d6be592b8f Merge bundle activation selection into plugin manager 2026-09-14 19:14:53 +08:00
Yichen Jiang 90dddfbf08 refactor(boot): derive bundle enablement from selected layers 2026-09-14 19:14:06 +08:00
Turtle ad9fd17faf Merge pull request #4164 from deepseek-harness/turtle/orchestrator-3d7fcb93e79d
fix(client): show local changes in edit diff cards
2026-09-14 19:11:08 +08:00
Turtle f50309b5d9 fix(client): bound contextual diff comparison work 2026-09-14 19:02:59 +08:00
Yifffan 7c4067c24e Merge pull request #4044 from deepseek-harness/fix/sidebar-document-preview-polish
Sidebar refine: 侧边栏 PDF/图片预览/格式空态/loading 等整体优化
2026-09-14 18:37:30 +08:00
creatixchu 620c52ca66 test(web): give the clickable-links gallery its own native-open overlay 2026-09-14 18:32:48 +08:00
Turtle 53786d6415 test(client): guard contextual diff replay against page errors 2026-09-14 18:23:58 +08:00
creatixchu dde4dccbd2 feat(workspace-changes): keep change summaries on the Host for the Session's lifetime
The workspace/changes event now carries only the turn number. The
recorder keeps each announced summary in memory under the event's
sequence and serves it through the new workspaceChanges service; the
Web deliverables plugin reads it once per announcement through an
authenticated summary route and renders the card only while the Host
still serves it, so a conversation reopened after a Host restart has no
card for its earlier turns. Snapshot objects move from a shared,
size-bounded store under the Harness home to a temporary directory per
Session that disposal removes, which retires the dshHome and
objectStoreMaxBytes fields. The cold-seeded fold scenario goes with the
logged file list; the client spec covers the fold and the recorded
scenario covers the served summary.
2026-09-14 18:21:12 +08:00
07akioni 0c88492646 feat(desktop): bundle release-bound workspace runtimes 2026-09-14 18:09:22 +08:00
Yif f51addaa0d fix(web-sidebar): resolve review feedback on document preview polish
- files tree records its scroll offset in a ref and commits it once on
  unmount, only while the owner's signal is live, so a scroll neither
  re-renders the tree nor writes to a forgotten bucket
- LoadingIndicator drops iconOnly and always renders icon-only
- registry and the unviewable list share one suffix-matching module, and
  register() rejects binaryExtensions entries outside extensions
- drop the ambiguous key suffix from the unviewable office group
- extract the text preview's header path block shared by the unsupported
  and content branches; clsx for static class joins; CSS trailing newline
- sync the preview-operations and polish Agent Notes with shipped facts
2026-09-14 18:06:23 +08:00
Ruilin Geng bb2b325486 Merge pull request #4137 from deepseek-harness/feat/docs-site-mermaid-viewer
feat(docs): 支持 Mermaid 图表全屏缩放和平移
2026-09-14 17:57:00 +08:00
Turtle 242410cf4b fix(client): render actual changes in contextual diff cards 2026-09-14 17:52:28 +08:00
creatixchu e5ac976e4b Merge remote-tracking branch 'origin/master' into worktree/code-diff-card
# Conflicts:
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	pnpm-lock.yaml
2026-09-14 17:49:25 +08:00
winewill 64df6d25cc Merge updated thin Electron Web UI into installer design
Propagate the master conflict fix and current Desktop changes while retaining
the installer interface and platform-local packaging configuration.
2026-09-14 17:10:26 +08:00
winewill 361c20cb41 Merge master into thin Electron Web UI
Retain the Desktop profile-boot alias alongside the new browser-use and
terminal aliases when resolving tsconfig.base.json.
2026-09-14 17:06:17 +08:00
Turtle e32f88dff2 Merge pull request #4024 from deepseek-harness/turtle/orchestrator-837dec7391c5
perf(terminal-bash): make scrollback retention incremental
2026-09-14 17:05:02 +08:00
Yichen Jiang f14032abd3 Merge pull request #4155 from deepseek-harness/worktree/web-terminal-theme
feat(web): follow application theme in sidebar terminals
2026-09-14 17:01:40 +08:00
Turtle b42913c8f1 Merge master and adapt terminal retention fixtures 2026-09-14 16:52:55 +08:00
Yichen Jiang 2d660bf078 fix(web): list only installed packages on the sidebar Plugins page
The sidebar page no longer shows the profile template's own bundles
(dsh-base, dsh-web-app). The Settings Plugins section gets its read-only
Plugin list tab back for them, with both of its groups collapsed by
default. Restores @deepseek-ai/dsh-client-ui-settings-plugin-inventory
with its web bundle row, tsconfig entries, catalogs, and goldens, and
drops the built-in tag, locked switch, and source fact the page no
longer needs.
2026-09-14 16:45:13 +08:00
_Kerman cbf9fbc29e refactor(agent-loop): remove duplicate Inbox projection registration 2026-09-14 16:35:40 +08:00
Yifffan 44cee2e1f5 Merge branch 'master' into fix/sidebar-document-preview-polish 2026-09-14 16:35:23 +08:00
Tianyi Cui 0e9e89e63f Merge pull request #4149 from deepseek-harness/worktree/projection-cache-drain-20260914
test: wait for cache writes and workflow child starts
2026-09-14 16:35:01 +08:00
Tianyi Cui b730c2cb83 Merge pull request #4092 from deepseek-harness/worktree/browser-use-backends
feat(browser-use): add experimental per-Session backends
2026-09-14 16:33:14 +08:00
Yichen Jiang 1daed09185 feat(web): follow application theme in sidebar terminals 2026-09-14 16:18:50 +08:00
Tianyi Cui 7e8d42d122 test(workflow): await host child starts before cancellation 2026-09-14 16:17:59 +08:00
Tianyi Cui 88e0a5acd1 test(session): await every successful cache replacement 2026-09-14 16:17:41 +08:00
Tianyi Cui 3ba25cd4cb test(session): exclude interval fallback from mandatory checkpoint 2026-09-14 16:09:15 +08:00
Tianyi Cui a90d8df582 test(session): await durable turn-end cache checkpoints 2026-09-14 16:00:09 +08:00
Tianyi Cui a3fb17c703 Merge pull request #4141 from deepseek-harness/worktree/subagent-settlement-text
fix(subagent): keep settlement notices text-only
2026-09-14 15:50:22 +08:00
Tianyi Cui 16f97e2dfb refactor(browser-use): defer DSH inference integration 2026-09-14 15:43:14 +08:00
Yichen Jiang 0ef4ff9bd0 Merge pull request #4139 from deepseek-harness/worktree/terminal-common-shells
feat(web): show common shells by default
2026-09-14 15:36:15 +08:00
Tianyi Cui b86b89da94 docs(subagent): align settlement notice descriptions 2026-09-14 15:27:38 +08:00
Yichen Jiang d5155007e0 refactor(web): manage bundles without module composition actions 2026-09-14 15:24:55 +08:00
Yichen Jiang 95e2da7416 refactor(plugins): retain bundle management and existing row toggles 2026-09-14 15:20:59 +08:00
Yichen Jiang d31c59b3b2 refactor(boot): limit package metadata to bundle management 2026-09-14 15:15:28 +08:00
Tianyi Cui 1d26330415 test(subagent): reuse Messages fixtures and clarify notice contracts 2026-09-14 15:13:13 +08:00
_Kerman cf4ba60b47 Merge remote-tracking branch 'origin/master' into xtr/durable-inbox-web-recovery
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/config-catalog.zh.md
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
2026-09-14 15:01:03 +08:00
Tianyi Cui 6caeb505c5 fix(browser-use): await existing Agent creation lifecycle 2026-09-14 14:50:23 +08:00
gengruilin 91f6733096 fix(docs): align Mermaid viewer accessible titles 2026-09-14 14:49:48 +08:00
Tianyi Cui e543cc9a6e Merge awaited Agent creation from master 2026-09-14 14:46:15 +08:00
Tianyi Cui 29debb8b24 fix(subagent): keep settlement notices text-only 2026-09-14 14:44:11 +08:00
_Kerman 15e9861e8a docs: trim repeated Inbox recovery rationale 2026-09-14 14:38:29 +08:00
Yichen Jiang c89e0cbdbd fix(web): remove preset UI injection from global plugin manager 2026-09-14 14:37:49 +08:00
_Kerman 9ca343b316 docs: revert unrelated timer-note path repair 2026-09-14 14:37:33 +08:00
_Kerman f6e145c1ea chore: remove duplicate cold-session test include 2026-09-14 14:37:19 +08:00
Yichen Jiang 0122acf731 Merge global plugin manager scope into Web management
# Conflicts:
#	packages/client/ui-settings-plugin-inventory/tests/components.client.spec.tsx
2026-09-14 14:35:30 +08:00
Yichen Jiang 6a6796f48d refactor(web): separate preset management from global plugins 2026-09-14 14:34:42 +08:00
Tianyi Cui ebe3ee4d4c docs(browser-use): refresh auxiliary event type acknowledgement 2026-09-14 14:33:23 +08:00
Tianyi Cui 52a8f7a759 docs(browser-use): clarify conditional tool ordering 2026-09-14 14:31:53 +08:00
Yichen Jiang 1ddd7e08c3 fix(web): keep Windows PowerShell in terminal choices 2026-09-14 14:31:41 +08:00
Tianyi Cui ee031f9cf9 Merge master into browser-use backends 2026-09-14 14:30:58 +08:00
_Kerman 28a4241e9f Merge pull request #3583 from deepseek-harness/xtr/agent-setup-hook
feat(agent)!: replace agent/session-start with awaited agent/created
2026-09-14 14:25:09 +08:00
Tianyi Cui 9845c543c0 docs(browser-use): refresh provider dependency graph 2026-09-14 14:23:52 +08:00
Yichen Jiang 249c8d1565 feat(web): show common shells by default 2026-09-14 14:20:25 +08:00
creatixchu 722008aeeb docs(deliverables): add the subsystem page the package-group gate requires
The deliverables group README links a subsystems page that carries the
PresentedFile, WorkspaceChangedFile, and WorkspaceChangesData
declarations and names the two log-only events; the persistence catalog
links the payload types to it.
2026-09-14 14:16:59 +08:00
Yichen Jiang 07f9daa55a refactor(plugins): limit manager operations to the global profile 2026-09-14 14:16:18 +08:00
creatixchu dce58eaf4e Merge remote-tracking branch 'origin/master' into worktree/code-diff-card
# Conflicts:
#	apps/web/package.json
2026-09-14 14:15:04 +08:00
_Kerman 49f601e902 Merge remote-tracking branch 'origin/master' into xtr/durable-inbox-web-recovery
# Conflicts:
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	packages/api/session-controller/README.i18n.yaml
#	packages/api/session-controller/README.md
#	packages/api/session-controller/README.zh.md
#	packages/api/session-controller/tests/client-apply.client.spec.ts
#	packages/api/session-controller/tests/fake-api.client.ts
#	packages/api/session-controller/tests/manager.client.spec.ts
#	packages/api/session-controller/tests/projection-store.client.spec.ts
#	packages/api/session-controller/tests/queue-store.client.spec.ts
#	packages/api/session-controller/tests/session-pending-submissions.client.spec.ts
#	packages/client/connection/src/client/fixture.ts
#	packages/client/connection/tests/fixture.client.spec.ts
#	packages/core/agent-loop/README.i18n.yaml
#	packages/core/agent-loop/README.md
#	packages/core/agent-loop/README.zh.md
#	packages/extensions/tool-cordis/src/api-catalog.ts
2026-09-14 14:12:25 +08:00
07akioni 6711bb9e24 fix(desktop): hide context menu shortcut labels 2026-09-14 14:10:06 +08:00
07akioni 49fcf87cb2 Merge pull request #4133 from deepseek-harness/07akioni/fix-table-hover-height
fix(web): prevent short markdown tables from shifting on hover
2026-09-14 14:03:49 +08:00
_Kerman d3856902b6 Merge pull request #3880 from deepseek-harness/xtr/trajectory-json-string-wrapping
feat(client): improve trajectory JSON and PTC inspection
2026-09-14 14:01:59 +08:00
_Kerman 0a382becb3 Merge latest origin/master into xtr/agent-setup-hook 2026-09-14 13:57:18 +08:00
07akioni f0463cf80d fix(test): use block bodies for void browser callbacks 2026-09-14 13:53:09 +08:00
gengruilin ece25ff8e6 refactor(docs): simplify Mermaid fullscreen viewer controls 2026-09-14 13:52:42 +08:00
_Kerman 1119fa2544 test(web): refresh the Auto-review trajectory golden for PTC summaries
The trajectory ledger now summarizes a recorded run_code call with the
program description instead of its raw JSON arguments, and marks it with
the code-inspection icon. Refresh the Auto-review denial golden so the
replayed ARIA expectation matches the shipped rendering.
2026-09-14 13:50:23 +08:00
creatixchu fa8938d202 refactor(deliverables): simplify path helpers, hunk classification, and card status
Path helpers reuse isInside instead of re-deriving containment from
relative(); the recorder classifies uncovered file-tool hunks in one
pass over the canonical map; the card renders line counts through one
component and derives header and row gesture copy from the same phase
reader.
2026-09-14 13:47:52 +08:00
Yichen Jiang 444c801718 Merge pull request #3864 from deepseek-harness/worktree/web-sidebar-terminal
feat(web): add interactive sidebar terminals
2026-09-14 13:47:12 +08:00
07akioni 3ceb5af4d7 fix(desktop): add native text context menus 2026-09-14 13:42:50 +08:00
Yichen Jiang 743df72db2 Merge PR #3595 API simplification 2026-09-14 13:41:18 +08:00
Yichen Jiang 27896dd532 Merge PR #3594 API simplification 2026-09-14 13:40:01 +08:00
Yichen Jiang ef71137220 Merge PR #3593 API simplification
# Conflicts:
#	docs/architecture.i18n.yaml
#	docs/architecture.md
#	docs/architecture.zh.md
2026-09-14 13:39:32 +08:00
Yichen Jiang 8fc785de3a refactor(boot): keep bundle analysis internal 2026-09-14 13:36:26 +08:00
07akioni 8ab3579e06 test(web): guard fitting table geometry across interaction 2026-09-14 13:34:00 +08:00
creatixchu f800ea46e5 refactor(deliverables): group tool-present and workspace-changes under packages/deliverables
Both Host packages hand the turn's deliverables to the user and neither
is a filesystem capability, so they leave packages/fs for a new
packages/deliverables group. The Client package stays at
packages/client/ui-deliverables. Paths in tsconfig references and
aliases, gates, generated catalogs, READMEs, and the implemented notes
follow the move; archived notes and released schema records stay as
written.
2026-09-14 13:33:54 +08:00
creatixchu 88d40e28ab docs(config): refresh the workspace-changes catalog entry after the source moved 2026-09-14 13:04:26 +08:00
winewill c47a2c16b4 feat(desktop): load platform packaging settings from local dotenv files
Load target-owned Windows and macOS release settings, validate them before
preparation, and provide a configuration-only check command. Share the local
settings with upload, installer tests, and manual macOS signature checks.

Exercise English and Chinese installer fixtures using visible UI labels and
cover registered installation paths with trailing separators.
2026-09-14 12:47:08 +08:00
Turtle 6a4a825a88 Merge pull request #4079 from deepseek-harness/turtle/master-ci-platform-tests
test(ci): repair platform fixtures, gallery clock and cache teardown
2026-09-14 12:39:59 +08:00
creatixchu 904e589573 test(web): keep the sentence the right-Sidebar scenario waits for 2026-09-14 12:39:59 +08:00
creatixchu 86a1bf1e80 fix(workspace-changes): resolve canonical paths lazily and make the tests portable
The packed worker deployment offers no realpathSync.native at plugin load, so
the home and temporary roots are now canonicalized asynchronously when a
Session first locates its repository. Windows-neutral tests replace chmod
and POSIX-only path expectations, and the right-Sidebar scenario enters
through the closing prose's file mention.
2026-09-14 12:37:22 +08:00
gengruilin cd0cc91382 fix(docs): keep Mermaid wheel zoom anchored to the pointer 2026-09-14 12:36:32 +08:00
gengruilin b0ec8cef32 feat(docs): add fullscreen Mermaid diagram viewer 2026-09-14 12:25:23 +08:00
07akioni 9187c3662e Merge master and fix desktop editing and Windows lock contention 2026-09-14 12:16:33 +08:00
Yichen Jiang 0a0563cc9b test(web): mock retained terminals in assembled fixtures 2026-09-14 12:13:26 +08:00
Yichen Jiang 0a7f47e3f2 Merge remote-tracking branch 'origin/master' into worktree/web-sidebar-terminal 2026-09-14 12:03:02 +08:00
Yichen Jiang 11b2114786 fix(web): align terminal launcher controls and guide appearance 2026-09-14 12:00:29 +08:00
creatixchu 7f5f4e778a fix(web): keep line counts visible after a changed-files row opens
A completed native open no longer replaces the row's counts with a lasting
acknowledgement; only pending and failed opens do, for rows and the folder
header alike.
2026-09-14 11:53:19 +08:00
07akioni 6d81d0fdbd test(web): update table hover scrollbar expectation 2026-09-14 11:47:13 +08:00
07akioni 55a17d2e57 fix(ui): keep markdown table height stable on hover 2026-09-14 11:46:02 +08:00
creatixchu 8ea92ce9b5 fix(workspace-changes): count argument-derived hunks, isolate per-turn state, and harden git handling
Review round fixes: a write that creates a file persists no hunks and
str_replace_editor persists none at all, so mutation calls now contribute
hunks from their arguments when the result carries none; each turn owns a
state object so a record still running for an interrupted turn cannot be
reset by the next turn; git add accepts exit code 1 from --ignore-errors;
rev-parse failures other than a missing repository fail loud; only a missing
index or store is tolerated; the temporary-root exclusion uses the repository
root; a row without a verified Host path previews in the Sidebar. The
recorded scenario now creates an ignored file.
2026-09-14 11:33:59 +08:00
creatixchu 8a52d27a93 Merge remote-tracking branch 'origin/master' into worktree/code-diff-card
# Conflicts:
#	docs/persistence-changes/historical-formats/README.i18n.yaml
#	docs/persistence-changes/historical-formats/README.md
#	docs/persistence-changes/historical-formats/README.zh.md
#	docs/persistence-schema.json
2026-09-14 11:26:05 +08:00
creatixchu 3010cb3dba fix(workspace-changes): resolve the types subpath to source and complete exported JSDoc
Map @deepseek-ai/dsh-workspace-changes/types to src so the persistence catalog
links source instead of built output, and document every exported function
and recorder method.
2026-09-14 11:18:52 +08:00
CreatixChu 48de2d1ba0 Merge pull request #3440 from deepseek-harness/worktree/3041-image-offload-log-design
feat(session, llm): durable image offload watermark
2026-09-14 11:17:06 +08:00
Yichen Jiang c257c79872 Merge branch 'worktree/pr3595-sep14-sync' into feat/plugin-mgmt-4-web 2026-09-14 11:16:19 +08:00
_Kerman a85778448a Merge origin/master into xtr/trajectory-json-string-wrapping 2026-09-14 11:15:34 +08:00
Yichen Jiang 4373a42552 docs(settings): refresh the generated module graph 2026-09-14 11:15:21 +08:00
Yichen Jiang 4ca7c816d4 Merge branch 'worktree/pr3594-manifest-mergeup' into worktree/pr3595-sep14-sync 2026-09-14 11:14:17 +08:00
Yichen Jiang b0a2aa7ec0 test(plugins): cover portable read failures and refresh the module graph 2026-09-14 11:13:34 +08:00
Yichen Jiang 3219a2d8e1 docs(api): refresh terminal dependency graph 2026-09-14 11:10:18 +08:00
creatixchu 0d2fcf22dc docs(persistence): refresh format facts after acknowledging the workspace/changes event 2026-09-14 11:08:18 +08:00
Yichen Jiang 673fce91e2 Merge branch 'worktree/pr3595-sep14-sync' into feat/plugin-mgmt-4-web
# Conflicts:
#	packages/client/ui-plugin-manager/README.i18n.yaml
#	packages/client/ui-settings-plugin-inventory/README.md
#	packages/client/ui-settings-plugin-inventory/tests/components.client.spec.tsx
#	scripts/verify-package-readme-model-experience.ts
#	tsconfig.base.json
#	tsconfig.client.json
2026-09-14 11:07:31 +08:00
creatixchu a27cfb9bd3 Merge remote-tracking branch 'origin/master' into worktree/code-diff-card
# Conflicts:
#	apps/web/package.json
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	docs/persistence-catalog.i18n.yaml
#	docs/persistence-catalog.md
#	docs/persistence-catalog.zh.md
#	pnpm-lock.yaml
2026-09-14 11:07:18 +08:00
Yichen Jiang 37e5d8c4aa fix(web): remember shell choices before terminal startup 2026-09-14 11:02:53 +08:00
winewill 64451b0e04 Merge latest thin Electron Web UI base into installer design 2026-09-14 10:59:48 +08:00
Yichen Jiang 33d89aee77 feat(web): choose and remember terminal shells 2026-09-14 10:59:46 +08:00
creatixchu cdfd8ab5b0 test(web): refresh the changed-files golden for the decorative header glyph 2026-09-14 10:59:38 +08:00
Yichen Jiang 0f14d6703b Merge branch 'worktree/pr3594-manifest-mergeup' into worktree/pr3595-sep14-sync
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/event-producer-consumer.i18n.yaml
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	packages/client/connection/src/client/fixture.ts
2026-09-14 10:56:36 +08:00
creatixchu d6634272d5 feat(workspace-changes): keep snapshot objects in a private store under the Harness home
Write every snapshot blob and tree into a per-repository object directory
under DSH_HOME/workspace-changes with the repository's objects attached as a
read-only alternate, so the user's repository gains no objects and the Harness
owns retention through objectStoreMaxBytes. The placement follows the
workspace change journal POC and costs nothing measurable.
2026-09-14 10:55:15 +08:00
Yichen Jiang 83747b255f refactor(preset): name overlay row fields explicitly 2026-09-14 10:50:13 +08:00
Yichen Jiang 8dc899641a Merge branch 'worktree/pr3593-manifest-3899' into worktree/pr3594-manifest-mergeup
# Conflicts:
#	.agents/notes/implemented/architecture/2026-09-11-native-entry-diagnostics-and-static-plugin-declarations.i18n.yaml
#	.agents/notes/implemented/architecture/2026-09-11-native-entry-diagnostics-and-static-plugin-declarations.md
#	.agents/notes/implemented/architecture/2026-09-11-native-entry-diagnostics-and-static-plugin-declarations.zh.md
#	docs/capability-seams.i18n.yaml
#	docs/capability-seams.md
#	docs/capability-seams.zh.md
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.zh.md
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	packages/api/remotes/src/client/index.ts
#	packages/api/remotes/src/remote-events.ts
#	packages/extensions/tool-cordis/src/api-catalog.ts
#	scripts/check-workspace-constraints.ts
#	scripts/gen-cordis-catalog.ts
2026-09-14 10:49:21 +08:00
Yichen Jiang 94419d809b Merge remote-tracking branch 'origin/master' into worktree/pr3593-manifest-3899
# Conflicts:
#	docs/capability-seams.i18n.yaml
#	docs/capability-seams.md
#	docs/capability-seams.zh.md
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	packages/extensions/tool-cordis/src/api-catalog.ts
#	packages/host/plugin-inventory/README.i18n.yaml
#	packages/host/plugin-inventory/README.md
#	vitest.config.ts
2026-09-14 10:44:12 +08:00
Yichen Jiang 1b7b50bbe1 Merge remote-tracking branch 'origin/master' into worktree/web-sidebar-terminal
# Conflicts:
#	apps/web/package.json
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	packages/api/remotes/src/client/index.ts
#	packages/e2b/subprocess-e2b/README.md
#	packages/e2b/subprocess-e2b/README.zh.md
#	packages/e2b/subprocess-e2b/src/index.ts
#	packages/e2b/subprocess-e2b/src/terminal.ts
#	packages/e2b/subprocess-e2b/tests/subprocess.spec.ts
#	packages/e2b/subprocess-e2b/tests/terminal.spec.ts
#	packages/mcp/mcp-resources/README.i18n.yaml
#	pnpm-lock.yaml
#	scripts/verify-package-readme-model-experience.ts
#	snapshots/session/cordis-inspect-jsdoc/session.v3.jsonl
#	tsconfig.base.json
#	tsconfig.client.json
#	tsconfig.host.json
2026-09-14 10:36:31 +08:00
creatixchu 2b1dabec86 Refresh merged SDK recordings and persistence documentation 2026-09-14 10:25:54 +08:00
creatixchu 27d52a4edb Update image tests for split adapters and durable offload failures 2026-09-14 10:21:54 +08:00
creatixchu a7070008e7 Merge master and integrate image offload with both DeepSeek protocols 2026-09-14 10:19:11 +08:00
imccyu 9ccd9b0634 Merge pull request #3960 from deepseek-harness/worktree-feqatest
test(client): replace legacy fixtures with RemoteMock
2026-09-13 23:09:09 +08:00
imccyu f258024b4d docs(testing): correct fixture migration guidance 2026-09-13 22:51:53 +08:00
imccyu e179c4ae14 test(client): preserve migrated fixture semantics 2026-09-13 22:51:53 +08:00
imccyu c0e8252afe refactor(client): remove fixture-only API residue 2026-09-13 22:51:53 +08:00
Tianyi Cui b84a8226bd fix(browser-use): initialize MCP clients without new core APIs 2026-09-13 22:39:18 +08:00
Tianyi Cui e41511d844 fix(browser-use): integrate current MCP resources and snapshots 2026-09-13 22:39:17 +08:00
Tianyi Cui d1e32e481a fix(browser-use): close lifecycle gaps and isolate replay fixtures 2026-09-13 22:39:16 +08:00
Tianyi Cui 0752a09ae6 docs(browser-use): explain the Stagehand action timer limit 2026-09-13 22:39:16 +08:00
Tianyi Cui e1612c2fdc feat(browser-use): add per-Session experimental browser backends 2026-09-13 22:39:16 +08:00
imccyu 7e331d72ed test(file-upload): cover unnamed byte uploads 2026-09-13 21:54:31 +08:00
imccyu 566db0b6cb docs(testing): retire browser fixture references 2026-09-13 21:30:03 +08:00
imccyu 5541ae0d2d refactor(client): replace browser fixture with RemoteMock 2026-09-13 21:30:03 +08:00
imccyu eb2cb668a5 test(web): run fixture browser cases through Host 2026-09-13 21:30:02 +08:00
imccyu 9b091919e2 test(session-controller): migrate remaining Remote fixtures 2026-09-13 21:30:02 +08:00
imccyu c1504a2aa6 fix(client-modules): resolve the owning Loader instance 2026-09-13 21:27:54 +08:00
imccyu 77db56687b test(ui-message-feedback): use RemoteMock 2026-09-13 21:27:53 +08:00
imccyu a475a65bed fix(client-test-runtime): isolate client instances 2026-09-13 21:27:53 +08:00
Tianyi Cui 5ca77db865 Merge pull request #4089 from deepseek-harness/worktree/deepseek-messages-parity
feat(llm): default DeepSeek to Messages with Files parity
2026-09-13 21:19:03 +08:00
Tianyi Cui accafa5fb2 refactor(llm): inherit Messages defaults and verify live parity 2026-09-13 20:36:50 +08:00
Tianyi Cui aef56a3108 test(ci): align external-agent and workflow endpoint fixtures 2026-09-13 20:36:50 +08:00
Tianyi Cui ece35a1a38 test(ci): exercise Messages defaults in runtime smokes 2026-09-13 20:36:50 +08:00
Tianyi Cui 7d3dab66a2 fix(llm): harden Messages transport and Files parity 2026-09-13 20:36:50 +08:00
Tianyi Cui b0641b83fc feat(llm): default DeepSeek to Messages with Files parity 2026-09-13 20:36:50 +08:00
Tianyi Cui 9531265ff3 Merge pull request #4098 from deepseek-harness/worktree/unarchive-sessions
feat(workspace): restore archived sessions from a settings page
2026-09-13 17:36:52 +08:00
Tianyi Cui 76941d0085 fix(workspace): keep the newest archive set from stale replies
Both archive verbs answer with the complete set, so a reply that lands
after a newer request or after a pushed increment overwrote it. The
Client model now installs an answer only while it is still the latest
archive-set request, and the follow increment and baseline supersede it.

Also narrow the page's public surface and its states: the locale
namespace stays internal, row derivation is a memo over the framework
hooks, the search input carries one accessible name, the empty-archive
message no longer covers a set whose entries cannot be restored, and the
new package declares no client dependency edge it does not import.
2026-09-13 16:45:45 +08:00
Tianyi Cui e1ee806226 chore(cordis): regenerate the client slot catalog
The new Settings section registers one more settings.section contribution,
which the generated client slot catalog lists.
2026-09-13 16:45:45 +08:00
Tianyi Cui ae34320a5b test(web): expect the unarchive verb and the archived-sessions nav row
The Client Cordis catalog now publishes unarchiveSession on both the
Workspace service and the UI navigation capability, and the new Settings
section adds one nav row that every settings-dialog aria snapshot carries.
Refresh those expectations; the goldens gain only that row.
2026-09-13 16:45:45 +08:00
Tianyi Cui 5f773a0ded feat(workspace): restore archived sessions from a settings page
Sessions could be archived from the sidebar row menu but never restored:
the registry-global archive set was a one-way display filter with no
inverse RPC and no surface listing its members.

WorkspaceRegistry.unarchiveSession drops one id from archivedSessionIds in
one durable write on the same operation chain as archive, with no
session-existence probe because a removal cannot introduce an unknown
referent. The Workspace controller exposes it as workspace.unarchiveSession
returning the complete archive set, which the existing archived follow
increment already propagates, so no frame type and no persisted field
changes.

The new client package dsh-client-ui-settings-unarchive-sessions owns the
restore surface: one localized settings.section page listing the archive
set joined with loaded session summaries, newest archive first, searchable
by title or workspace, with one Unarchive action per row.
2026-09-13 16:45:45 +08:00
Tianyi Cui 9e87d16f3a Merge pull request #4116 from deepseek-harness/worktree/coverage-attribution
fix(coverage): canonicalize partition locations before the blob merge
2026-09-13 16:45:02 +08:00
Tianyi Cui 8ba386ec69 Merge branch 'master' into worktree/coverage-attribution 2026-09-13 16:37:55 +08:00
Tianyi Cui 2214891606 Merge pull request #4119 from deepseek-harness/worktree/workflow-sandbox-ptc
fix(workflow): execute orchestration through sandboxed PTC
2026-09-13 16:33:51 +08:00
Tianyi Cui 10930a0205 fix(coverage): fail loud when the canonicalizer gets no coverage data
Vitest types `Reporter.onCoverage` as `unknown`, so a payload that carries no
istanbul `data` record now fails the partition instead of silently leaving
every location uncanonicalized; a spec case pins that rejection. The module
docs keep the contract and link the Agent Note for the mechanism, the
partition spec names what it asserts (the reporter argument, not Vitest hook
ordering), and the notes correct the `Infinity` origin to ast-v8-to-istanbul,
record the reporter-ordering dependency, and name the reporter each partition
child carries.
2026-09-13 15:17:06 +08:00
Tianyi Cui c171a7a9a2 fix(coverage): canonicalize partition locations before the blob merge
A source file carries one istanbul statement map per Vite environment, so a
node suite and a jsdom suite that load the same module enter the merged
report through two maps that spell one statement differently. istanbul
reconciles those overlapping ranges by attributing the hits of the narrowest
containing range, but only while a location carries numeric line and column
values. ast-v8-to-istanbul ends a whole-line statement at column Infinity, and
the partition blob serializes Infinity as null, so the merge command kept the
client-only spelling as an extra, unhit statement: a file whose every statement
ran reported 96.96% and failed the per-file 100% gate.

The coordinator now passes each partition a reporter whose onCoverage hook
rewrites every non-finite end column to a finite line-end column before the
blob is written, which restores that reconciliation without weakening the
gate. The uncovered-locations reporter reads the same column as a line end.
2026-09-13 15:13:59 +08:00
Tianyi Cui 9b6457bc12 Merge pull request #4106 from deepseek-harness/worktree/mcp/optional-surface
feat(mcp): expose profile resources only when servers are configured
2026-09-13 14:59:10 +08:00
Tianyi Cui e9a300f192 Merge pull request #4100 from deepseek-harness/worktree/persistence-format-history
docs(session): backfill and require every persistence format reference
2026-09-13 14:58:05 +08:00
Tianyi Cui e636da11fb Merge branch 'master' into worktree/mcp/optional-surface 2026-09-13 14:52:01 +08:00
Tianyi Cui 6811c59efb Merge branch 'master' into worktree/persistence-format-history 2026-09-13 14:49:15 +08:00
Tianyi Cui 34f80b8e6e fix(workflow): close lifecycle and CI integration gaps 2026-09-13 14:47:56 +08:00
Tianyi Cui 35af8698c2 fix(workflow): execute orchestration in the sandboxed PTC runtime 2026-09-13 14:47:56 +08:00
Tianyi Cui 4f071d6762 Merge pull request #4117 from deepseek-harness/worktree/fix-mcp-snapshot-ralph-defaults
test(mcp): align snapshots with Ralph disabled by default
2026-09-13 14:47:53 +08:00
Yif f7e010a70a docs(agent-notes): cite issue 3974 as plain text to satisfy the repository-references gate 2026-09-13 13:37:02 +08:00
Yif 25e6e976b7 test(sidebar-documentpreview): cover the visible-label loading branch and drop the stale single-viewer control from the seeded-history golden 2026-09-13 13:28:16 +08:00
Yifffan 20d78f0e77 Merge branch 'master' into fix/sidebar-document-preview-polish 2026-09-13 07:26:09 +02:00
Tianyi Cui 004ef35010 test(mcp): align snapshots with Ralph disabled by default 2026-09-13 12:39:33 +08:00
Tianyi Cui 38070996c1 docs(session): nest historical formats under persistence changes 2026-09-13 12:19:46 +08:00
Tianyi Cui 765c87fb87 fix(docs): address persistence format history review 2026-09-13 12:08:08 +08:00
Tianyi Cui b08f6c421b docs(session): backfill and gate persistence format references 2026-09-13 12:08:07 +08:00
Tianyi Cui b5376e3d02 test(mcp): align resource snapshots with shipped defaults 2026-09-13 11:55:25 +08:00
Tianyi Cui 4c6b2c02af docs(mcp): clarify resource discovery and profile verification 2026-09-13 11:52:42 +08:00
Tianyi Cui 815a5eb01e test(mcp): include resources in minimal profile expectations 2026-09-13 11:52:42 +08:00
Tianyi Cui e08468954a feat(mcp): activate profile resource tools for configured servers 2026-09-13 11:52:42 +08:00
Tianyi Cui 99a73ca1d4 Merge pull request #4101 from deepseek-harness/worktree/demote-ralph
feat(presets): disable ralph in the default compositions
2026-09-13 11:42:40 +08:00
Tianyi Cui 351645a6c9 Merge pull request #4112 from deepseek-harness/worktree/file-search-root-fixture-20260913
test(file-reference): publish restored workspace fixtures atomically
2026-09-13 11:34:01 +08:00
Tianyi Cui a9bba3bac5 Merge pull request #4082 from deepseek-harness/worktree/mcp/resources
feat(mcp): add scoped resources and server instructions
2026-09-13 11:27:47 +08:00
Tianyi Cui deb0d7e1b5 test(file-reference): publish restored workspace fixtures atomically 2026-09-13 04:56:35 +08:00
Tianyi Cui c7d2e99b8e docs(presets): state the web-app disable in the present tense 2026-09-13 01:14:06 +08:00
turtle1999 c8370240a8 test(ci): pin gallery time and dispose projection cache fixtures 2026-09-13 00:42:12 +08:00
Tianyi Cui d49192b6ac docs(presets): name the new id in the ralph restore recipe 2026-09-13 00:41:44 +08:00
turtle1999 d9ec28ed3b Merge branch 'master' of https://github.com/deepseek-harness/deepseek-harness into turtle/master-ci-platform-tests 2026-09-13 00:37:52 +08:00
Tianyi Cui 73985344cd feat(presets): disable ralph in the default compositions 2026-09-13 00:15:39 +08:00
Tianyi Cui 7efd4ab20c Merge pull request #4087 from deepseek-harness/worktree/ci/dependency-catalog-rescope
fix(ci): preserve recorded npm resolution during vendor rescoping
2026-09-12 23:25:44 +08:00
Tianyi Cui 834bd55a59 fix(mcp): expose scoped resource server names to the model 2026-09-12 22:40:51 +08:00
Tianyi Cui aec2d5e5f0 docs(mcp): explain resource providers and server instructions 2026-09-12 22:40:51 +08:00
Tianyi Cui 3ba5b6eb04 feat(mcp): add scoped resources and server instructions 2026-09-12 22:40:50 +08:00
Tianyi Cui f6e7166762 docs(mcp): align bridge note with SDK-owned discovery 2026-09-12 22:38:00 +08:00
Tianyi Cui 3785b68ecf fix(mcp): own transports through protocol negotiation 2026-09-12 22:31:42 +08:00
Tianyi Cui 395f79b772 docs(mcp): describe subsystem roles and configuration 2026-09-12 22:31:42 +08:00
Tianyi Cui 489c3ac715 feat(mcp): negotiate modern protocols with the official SDK
Preserve the verified SDK layer tree from c8b248b480 before rebasing its complete net change.
2026-09-12 22:31:42 +08:00
Tianyi Cui 55fc8b91e4 fix(ci): preserve recorded npm resolution during vendor rescoping 2026-09-12 22:25:10 +08:00
Tianyi Cui c2a68638b2 Merge pull request #4059 from deepseek-harness/worktree/publish-all-experimental
feat(release): publish all experimental packages
2026-09-12 22:19:29 +08:00
Tianyi Cui 60a413034a Merge branch 'worktree/default-product-no-experimental' into worktree/publish-all-experimental 2026-09-12 22:04:27 +08:00
Tianyi Cui a280cf34f5 test: canonicalize browser notices fixture paths 2026-09-12 22:04:16 +08:00
Tianyi Cui 7a4dca21c7 Merge branch 'worktree/default-product-no-experimental' into worktree/publish-all-experimental 2026-09-12 21:32:08 +08:00
Tianyi Cui 0e060aa675 fix(ci): canonicalize browser notice roots with native realpath 2026-09-12 21:30:51 +08:00
Tianyi Cui 00b2470eb6 test: canonicalize Windows Vite fixture roots 2026-09-12 21:26:53 +08:00
Tianyi Cui 5b491e8cc6 fix(ci): skip product graph capture during dependency analysis 2026-09-12 21:20:43 +08:00
Tianyi Cui b5d463ca5c test(release): cover packed experimental worker consumers 2026-09-12 20:56:26 +08:00
Tianyi Cui 22c5ae6abc fix: cover supported experimental isolation inputs 2026-09-12 20:56:26 +08:00
Tianyi Cui 42c5b65643 feat(release): publish all experimental packages 2026-09-12 20:56:26 +08:00
Tianyi Cui 8f14f98a1a ci(web): verify composed profiles, live registries, and bundle inputs 2026-09-12 20:56:26 +08:00
Tianyi Cui f34dd86285 ci(release): keep experimental packages out of the default product 2026-09-12 20:56:26 +08:00
Tianyi Cui 251210d517 test(release): cover baseline package discovery 2026-09-12 20:56:26 +08:00
Tianyi Cui 6e30e1a300 feat(release): use a private denylist for experimental packages 2026-09-12 20:56:26 +08:00
Tianyi Cui 5bb449f716 Merge pull request #3717 from deepseek-harness/worktree/pr2437-recovery/metadata
fix: include package-index links and align residual metadata
2026-09-12 20:52:51 +08:00
Tianyi Cui 3b27563290 fix: include package-index links and align residual metadata 2026-09-12 20:20:02 +08:00
Tianyi Cui 6c3c3064c3 refactor: align instruction and job helper symbols 2026-09-12 20:20:02 +08:00
Tianyi Cui 739285c813 docs: correct surviving package and service references 2026-09-12 20:20:02 +08:00
Tianyi Cui be682f7a59 Merge pull request #4086 from deepseek-harness/worktree/linux-signal-outcome-preservation
fix(subprocess): preserve exit outcomes when signaling fails
2026-09-12 20:12:20 +08:00
Tianyi Cui dd55f38614 docs(subprocess): record signal error isolation and fixture safety 2026-09-12 19:44:51 +08:00
Tianyi Cui 083d192007 Merge current master into direct outcome fix 2026-09-12 19:25:51 +08:00
Tianyi Cui 020b84c301 Merge pull request #4060 from deepseek-harness/worktree/persistence-prerelease-backfill
docs(session): backfill persistence history for all alpha and RC tags
2026-09-12 19:16:42 +08:00
Tianyi Cui 71334b9c78 fix(subprocess): preserve direct outcomes on signal failure 2026-09-12 19:14:34 +08:00
pku-xht 771dd49a06 Merge pull request #3304 from deepseek-harness/auto-review-per-call
feat(permission): add Auto review mode
2026-09-12 18:58:41 +08:00
Tianyi Cui 3b264679ea Merge pull request #4085 from deepseek-harness/worktree/linux-direct-signal-ack
fix(subprocess): confirm direct SIGKILL after group delivery
2026-09-12 18:57:14 +08:00
Tianyi Cui 4adfe00207 fix(session): validate generated release facts 2026-09-12 18:52:17 +08:00
Tianyi Cui 0b7f0b072b chore: enforce maintained repository reference policy 2026-09-12 18:52:17 +08:00
Tianyi Cui 2d5391eede docs(session): use tags throughout historical release records 2026-09-12 18:52:17 +08:00
Tianyi Cui aea077ac75 docs(session): backfill alpha and RC persistence history 2026-09-12 18:52:17 +08:00
Tianyi Cui 35dbd84ac4 test: isolate Git config without a Windows device path 2026-09-12 18:52:02 +08:00
Tianyi Cui c07df5aa65 fix(subprocess): confirm direct SIGKILL after group delivery 2026-09-12 18:49:15 +08:00
Tianyi Cui 2b367a9aeb Merge updated Computer Use parent with master CI fix 2026-09-12 18:40:48 +08:00
Tianyi Cui 7a841fa908 Merge master with subprocess CI fix from #4080 2026-09-12 18:39:39 +08:00
Tianyi Cui b905d399df Fix offline reference checks and preserve native pack inputs 2026-09-12 18:37:56 +08:00
Tianyi Cui 1b4e1ac076 test: separate independent policy gate registration cases 2026-09-12 18:37:56 +08:00
Tianyi Cui 6b651380a7 feat: enforce maintained repository reference policy 2026-09-12 18:37:56 +08:00
Tianyi Cui 631c52fd4f Merge master into computer-use provider branch 2026-09-12 18:37:00 +08:00
Tianyi Cui 76a4153330 Merge pull request #4080 from deepseek-harness/worktree/acp-scope-settlement-fix
fix(subprocess): wait for fallback exit before scope failure
2026-09-12 18:33:55 +08:00
Tianyi Cui a43fd7d8a7 Merge pull request #4071 from deepseek-harness/worktree/dependency-catalog
docs: generate deduplicated npm dependency JSON
2026-09-12 18:31:14 +08:00
Magolor a630265a02 docs(session): define the LogicalSession refactor plan (#3654)
* docs(session): define the runtime and storage refactor plan

Document the staged SessionRuntime, SessionService, and SessionStorage design, developer transition rules, capability protocols, data compatibility, and FAQ in English and Chinese.

* docs(session): describe the switchable runtime-access gate in the plan

The plan said the access gate rejects concrete-class bindings. The
shipped gate is switchable: its checked-in default is `warn`, which
prints every finding, annotates it in GitHub Actions, and exits 0, so
branches that still bind `Session` merge while their consumers migrate.
`DSH_SESSION_RUNTIME_ACCESS=enforce` fails the gate for one run, and the
checked-in default flips to `enforce` once no in-flight branch binds
the class. Record that in the stage table and the enforcement section.

* docs(session): rename SessionRuntime to LogicalSession in the rebuild plan

The logical session interface is named `LogicalSession`; the plan, the
capability protocols, the developer transition rules, and the FAQ use
that name for the type, the detached factories (`createLogicalSession`,
`restoreLogicalSession`), the access gate (`verify-logical-session-access`,
`DSH_LOGICAL_SESSION_ACCESS`), and the prose that called the object a
runtime. The overview note moves to
`2026-09-06-logical-session-storage-rebuild.*` with a new pairing record.

The FAQ records why `SessionRuntime` was rejected: the package naming
table reserves `Runtime` for a component that runs live work, and the
interface holds one session's identity and log without running anything.
2026-09-12 18:11:15 +08:00
Tianyi Cui c6721f992e docs: retain hosted run identities without organization URLs 2026-09-12 18:05:41 +08:00
Tianyi Cui 4b99ace8fb fix(subprocess): await direct fallback settlement before scope failure 2026-09-12 17:55:53 +08:00
turtle1999 fabbcf8c76 test(ci): cover control requests and fix cross-volume fixtures 2026-09-12 17:38:12 +08:00
Tianyi Cui 66734e344a Merge Computer Use parent into Auto review for PR stack 2026-09-12 17:06:46 +08:00
Tianyi Cui 7900404541 fix: deduplicate dependency JSON and isolate npm configuration 2026-09-12 17:06:38 +08:00
Tianyi Cui cd97419e81 fix(computer-use): cancel image admission and fix source snapshots 2026-09-12 16:43:52 +08:00
Tianyi Cui af4ad05845 feat: add computer use with Cua Driver providers 2026-09-12 16:41:12 +08:00
Tianyi Cui 313768f520 docs: generate published npm dependency catalog 2026-09-12 16:36:36 +08:00
Tianyi Cui 03888a1619 Merge pull request #4066 from deepseek-harness/turtle/master-ci-persistence-budget
test(ci): stabilize master persistence integration budgets
2026-09-12 16:09:09 +08:00
Tianyi Cui a92ac9e949 Merge pull request #4057 from deepseek-harness/worktree/ptc-sandbox/ptc-naming
refactor(ptc): align runtime packages and services with PTC naming
2026-09-12 16:05:11 +08:00
Tianyi Cui 83d121c8c0 docs(ptc): align runtime terminology and naming decision links 2026-09-12 15:03:04 +08:00
Tianyi Cui 7c9bb5914c refactor(ptc): align runtime packages and services with PTC naming 2026-09-12 15:03:04 +08:00
Tianyi Cui e892c1abf5 test(ssh): preserve stream reads across supported Node versions 2026-09-12 15:03:04 +08:00
Tianyi Cui 305847127a fix(deps): retain locked PDF canvas optional dependencies 2026-09-12 15:03:03 +08:00
Tianyi Cui 28c4daa66c fix(ssh): keep completion cleanup under release ownership 2026-09-12 15:03:03 +08:00
Tianyi Cui ac43c2656f fix(ssh): propagate output closure and bound exit observations 2026-09-12 15:03:03 +08:00
Tianyi Cui d3fa7030ef fix(ssh): retain failed results and join all process cleanup 2026-09-12 15:03:03 +08:00
Tianyi Cui d951a49038 fix(ssh): preserve remote filenames in file URLs 2026-09-12 15:03:03 +08:00
Tianyi Cui 119d44fc4c docs(ssh): generate the shared-instance dependency graph 2026-09-12 15:03:03 +08:00
Tianyi Cui c886f26b91 docs(ssh): record the administrative timer range 2026-09-12 15:03:03 +08:00
Tianyi Cui 1c5a201af8 fix(ssh): reject timeouts above the native timer range 2026-09-12 15:03:03 +08:00
Tianyi Cui 7673f90d18 docs(ssh): define trusted runtime installation prerequisites 2026-09-12 15:03:03 +08:00
Tianyi Cui 969e968e0e fix(ssh): disable signal-triggered helper inspection 2026-09-12 15:03:03 +08:00
Tianyi Cui c6e531e45b refactor(ssh): retain TLS ownership of raw socket errors 2026-09-12 15:03:03 +08:00
Tianyi Cui b5fd914306 test(ssh): isolate backend availability from helper dispatch 2026-09-12 15:03:03 +08:00
Tianyi Cui 561bfc3bbb fix(ssh): join authenticated stream teardown and validate package closure 2026-09-12 15:03:03 +08:00
Tianyi Cui abb7c6a49d fix(ssh): join transport cleanup and preserve collected output 2026-09-12 15:03:03 +08:00
Tianyi Cui 32de4412dc refactor(sandbox): await cancellable process preparation 2026-09-12 15:03:03 +08:00
Tianyi Cui 72226bd061 feat(ssh): authenticate streams and join remote process cleanup 2026-09-12 15:03:03 +08:00
Tianyi Cui 4fb0fdac68 feat(ssh): checkpoint POSIX helper and remote providers 2026-09-12 15:03:03 +08:00
Tianyi Cui 73e38e1758 fix(shell): include confinement preparation in foreground deadlines 2026-09-12 15:03:03 +08:00
Tianyi Cui f72c2e019d fix(preview): provide the native realpath callback alias 2026-09-12 15:03:03 +08:00
Tianyi Cui fd9d333fbe test(runtime): cover async preparation in built and Windows paths 2026-09-12 15:03:03 +08:00
Tianyi Cui 58b67dcb5a fix(fs): preserve physical traversal in directory entry paths 2026-09-12 15:03:03 +08:00
Tianyi Cui 0a7a69ec54 test(fs): exercise byte reads with a live cancellation signal 2026-09-12 15:03:02 +08:00
Tianyi Cui 4c7b6902e3 fix(fs): share native path rooting between resolve and lstat 2026-09-12 15:03:02 +08:00
Tianyi Cui 573f525c33 fix(fs): preserve native Windows drive-relative path resolution 2026-09-12 15:03:02 +08:00
Tianyi Cui caa69608fb refactor(sandbox): await cancellable preparation in process consumers 2026-09-12 15:03:02 +08:00
Tianyi Cui fc7f7ddda6 test(ptc): refresh portable denial and shared runtime schema fixtures 2026-09-12 15:03:02 +08:00
Tianyi Cui 4d4e333676 test(ptc): make sandbox denial recording portable and cover execution descriptors 2026-09-12 15:03:02 +08:00
Tianyi Cui a29991144a test(ptc): include program approval scenario in host type checking 2026-09-12 15:03:02 +08:00
Tianyi Cui c05e0953ef test(ptc): pin provider usage guidance in recorded program schemas 2026-09-12 15:03:02 +08:00
Tianyi Cui 2a08bf6ab9 feat(ptc): present provider execution guidance in logged program schema 2026-09-12 15:03:02 +08:00
Tianyi Cui c6b959783a test(ptc): record approved program execution and document per-call controls 2026-09-12 15:03:02 +08:00
Tianyi Cui a248cc4e64 feat(ptc): expose per-program timeout and sandbox approval controls 2026-09-12 15:03:02 +08:00
Tianyi Cui c5de252f8c docs(ptc): refresh persistence source references after master rebase 2026-09-12 15:03:02 +08:00
Tianyi Cui e21060defe test(code-runtime): observe native temp through inherited Windows handles 2026-09-12 15:03:02 +08:00
Tianyi Cui 091cbcdbfb fix(code-runtime): preserve native temp setup and preview activation 2026-09-12 15:03:02 +08:00
Tianyi Cui 2344830cfd test(code-runtime): align UI binding fixture and shared diagnostic ownership 2026-09-12 15:03:02 +08:00
Tianyi Cui bef3c26175 test(code-runtime): gate native enforcement cases on backend availability 2026-09-12 15:03:01 +08:00
Tianyi Cui 7f5eb6db9a fix(code-runtime): support SEA startup and immediate control writes 2026-09-12 15:03:01 +08:00
Tianyi Cui 98d3af0683 fix(code-runtime): separate model environment from native startup paths 2026-09-12 15:03:01 +08:00
Tianyi Cui a6f7eeadc6 fix(code-runtime): preserve native startup paths and preview packaging 2026-09-12 15:03:01 +08:00
Tianyi Cui ca7f3a523d test(tools): cover PTC standing policy and sandbox outcomes 2026-09-12 15:03:01 +08:00
Tianyi Cui 09e334622d docs(code-runtime): refresh confined runtime dependency graph 2026-09-12 15:03:01 +08:00
Tianyi Cui fc5cb0f649 test(code-runtime): complete sandboxed process coverage and catalogs 2026-09-12 15:03:01 +08:00
Tianyi Cui 8e19ec4962 feat(code-runtime): complete sandboxed Node execution and Session fixtures 2026-09-12 15:03:01 +08:00
Tianyi Cui f6904f4615 fix(tools): omit an absent Session during runtime policy resolution 2026-09-12 15:03:01 +08:00
Tianyi Cui 75ed8da3e0 feat(code-runtime): execute Node programs through confined processes 2026-09-12 15:03:01 +08:00
Tianyi Cui f95f7ec8dc refactor(code-runtime): name the Node runtime provider 2026-09-12 15:03:01 +08:00
Tianyi Cui b35a3b29eb fix(sandbox): pin ACL source resolution and recognize Node denials 2026-09-12 15:03:01 +08:00
Tianyi Cui e53c526320 test(subprocess): cover retained control endpoint teardown 2026-09-12 15:03:01 +08:00
Tianyi Cui 5bebc7c504 fix(sandbox): resolve source preload independently of command cwd 2026-09-12 15:03:01 +08:00
Tianyi Cui f5ef951ec5 test(subprocess): type rejected lifecycle results as unknown 2026-09-12 15:03:01 +08:00
Tianyi Cui 562e7f364e fix(subprocess): await control endpoint closure during disposal 2026-09-12 15:03:01 +08:00
Tianyi Cui 838da1d07e fix(subprocess): separate process quiescence from caller control streams 2026-09-12 15:03:01 +08:00
Tianyi Cui 96e12ddaf4 test(subprocess): cover source-only control launches and refresh generated references 2026-09-12 15:03:01 +08:00
Tianyi Cui c45d722d7b docs(subprocess): record the Windows duplex pipe requirement 2026-09-12 15:03:00 +08:00
Tianyi Cui 83a45679df fix(subprocess): create control carriers for overlapped Windows I/O 2026-09-12 15:03:00 +08:00
Tianyi Cui 63d462f28b test(subprocess): cover control disposal and runner forwarding 2026-09-12 15:03:00 +08:00
Tianyi Cui 1e5259c463 test(subprocess): type binary reads and native test spies precisely 2026-09-12 15:03:00 +08:00
Tianyi Cui 3ccb898cd5 test(subprocess): close control endpoint after the write callback 2026-09-12 15:03:00 +08:00
Tianyi Cui b9dfb8da1c test(subprocess): verify control inheritance and document channel ownership 2026-09-12 15:03:00 +08:00
Tianyi Cui d8efd4f8cd feat(subprocess): carry a duplex control pipe through managed launches 2026-09-12 15:03:00 +08:00
Tianyi Cui ff03531b97 docs(testing): record compaction fixture calibration 2026-09-12 15:02:37 +08:00
Tianyi Cui 65236780d1 test(ci): await final colors and build compactable history 2026-09-12 14:37:24 +08:00
turtle1999 0b368dfe78 test(persistence): budget heavy integration cases for CI 2026-09-12 14:35:03 +08:00
Tianyi Cui ee9ae1d0e0 docs(session): acknowledge Auto review error metadata 2026-09-12 14:22:33 +08:00
Tianyi Cui 2d9e3a175f docs(auto-review): name delegation records explicitly 2026-09-12 14:21:58 +08:00
Tianyi Cui 647e2aefbf Merge master into Auto review and reconcile recorded API types 2026-09-12 14:17:13 +08:00
Tianyi Cui 663a534d1f Merge pull request #3688 from deepseek-harness/policy-ci/policy-modules
refactor(ci): 分离 Issue policy 规则、GitHub IO 与生命周期
2026-09-12 13:31:13 +08:00
Tianyi Cui 0e77868739 Merge pull request #4032 from deepseek-harness/worktree/persistence-type-history
feat(session): enforce persistence type compatibility
2026-09-12 13:15:52 +08:00
Tianyi Cui 70a3be6f20 test(session): protect persistence digests from harmless reordering 2026-09-12 12:52:25 +08:00
Yifffan 1f76250952 Merge branch 'master' into fix/sidebar-document-preview-polish 2026-09-11 18:37:35 +02:00
Tianyi Cui f85b328450 chore(session): refresh persistence references after master merge 2026-09-12 00:13:33 +08:00
Yif 004dceed5e feat(sidebar-files): restore the tree's scroll position across tab switches 2026-09-12 00:07:50 +08:00
Yif adbe7e6395 fix(documentpreview): draw pdf page placeholders on the skeleton token 2026-09-12 00:07:40 +08:00
Tianyi Cui 7bbd7ef85c Merge commit 'cf74fa6ed7f3aad12b4e17e27be873d6b9438952' into worktree/persistence-type-history 2026-09-11 23:56:42 +08:00
Tianyi Cui 6e294b1c27 fix(session): infer persistence change decisions for agents 2026-09-11 23:56:06 +08:00
Yif 351b399639 feat(ui-commands): swap the feedback command icon to a paper plane 2026-09-11 23:42:32 +08:00
Yif f210305689 fix(documentpreview): fit images to the pane and polish binary and loading states 2026-09-11 23:42:20 +08:00
Turtle a0e1e11a86 Merge pull request #3996 from deepseek-harness/turtle/blacksmith-runtime-llm-e2e
ci: enable Blacksmith failover for runtime and DeepSeek e2e
2026-09-11 23:37:51 +08:00
Tianyi Cui 09a6fbc388 Merge pull request #4036 from deepseek-harness/worktree/ptc-sandbox/remove-e2b
refactor(e2b): retire the provider experiment and preserve remote seams
2026-09-11 23:30:29 +08:00
Turtle b625ebe440 Merge pull request #3151 from deepseek-harness/turtle/ban-ambiguous-origin-label
Ban an ambiguous origin label
2026-09-11 23:18:52 +08:00
Tianyi Cui a0a7e2c11c fix(session): harden and automate persistence change review 2026-09-11 23:15:26 +08:00
Tianyi Cui 845acdb3b7 refactor(ci): separate issue policy rules transport and lifecycle owners 2026-09-11 22:49:03 +08:00
Tianyi Cui f6e0d429e7 docs(ci): preserve current Issue label repair semantics 2026-09-11 22:48:20 +08:00
Tianyi Cui 2eeab3e65f fix(ci): preserve trusted legacy policy during preflight rollout 2026-09-11 22:42:46 +08:00
Tianyi Cui 108c87008b fix(ci): avoid unnecessary issue policy Project reads and lifecycle runs 2026-09-11 22:42:46 +08:00
Tianyi Cui 63a16e254d docs: clarify retained proxy and execution-world requirements 2026-09-11 22:35:08 +08:00
Tianyi Cui c49db8bc8c refactor(e2b): retire remote execution providers 2026-09-11 22:12:55 +08:00
Tianyi Cui 1e9b05d356 feat(session): verify persistence type history 2026-09-11 22:06:58 +08:00
lsdsjy 315e30e9f2 Merge pull request #3849 from deepseek-harness/turtle/issue-3848-headless-machine-readable-run
feat(headless): 支持 stdin 任务、--session-id 与 --json 事件流
2026-09-11 20:03:00 +08:00
lsdsjy fa5de9ea27 Merge remote-tracking branch 'origin/master' into HEAD 2026-09-11 19:47:59 +08:00
Turtle 68f9708e02 fix(terminal-bash): bound retained storage and status reads 2026-09-11 19:12:10 +08:00
Turtle cea837e065 perf(terminal-bash): retain scrollback incrementally 2026-09-11 18:40:06 +08:00
Yichen Jiang 17ce0910c4 fix(web): use installation records for plugin management 2026-09-11 18:27:11 +08:00
Yichen Jiang 23324b2b94 merge: align plugin event reference pairs 2026-09-11 18:24:55 +08:00
Yichen Jiang eda5fabfbf merge: align plugin event documentation 2026-09-11 18:24:26 +08:00
Yichen Jiang 0443cd8ad3 docs(plugins): align event references after metadata cleanup 2026-09-11 18:23:58 +08:00
Yichen Jiang e812aa66b1 merge: restore startup requirements across plugin management UI 2026-09-11 18:22:31 +08:00
Yichen Jiang dac1950ac8 merge: propagate consumer-owned startup requirements 2026-09-11 18:22:15 +08:00
Yichen Jiang 2b40a9d819 merge: restore startup requirements from plugin stack base
# Conflicts:
#	.agents/notes/implemented/architecture/2026-09-11-native-entry-diagnostics-and-static-plugin-declarations.i18n.yaml
#	.agents/notes/implemented/architecture/2026-09-11-native-entry-diagnostics-and-static-plugin-declarations.md
#	.agents/notes/implemented/architecture/2026-09-11-native-entry-diagnostics-and-static-plugin-declarations.zh.md
#	docs/capability-seams.i18n.yaml
#	docs/capability-seams.md
#	docs/capability-seams.zh.md
#	packages/boot/app-boot/src/profile.ts
#	scripts/gen-doc-graphs.ts
2026-09-11 18:21:48 +08:00
Dudu-0223 eb56c23575 Merge pull request #3861 from deepseek-harness/fix/team-identity-context
fix(agent-team): preserve fork prefixes and use teammate-only direct delegation
2026-09-11 18:21:28 +08:00
Yichen Jiang f747ada426 fix(boot): restore consumer-owned startup requirements 2026-09-11 18:17:44 +08:00
Yichen Jiang ecf8bfcccb test(web): cover live bundle toggles through the plugin Remote 2026-09-11 18:00:28 +08:00
Dudu-0223 950bdd3c4d Merge remote-tracking branch 'origin/master' into HEAD 2026-09-11 17:56:21 +08:00
imccyu 9edf90d33e Merge pull request #3984 from deepseek-harness/refactor/conversation-component-decomposition
refactor(conversation): extract panel and content components
2026-09-11 17:55:13 +08:00
Yichen Jiang fc0e19c88d Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web 2026-09-11 17:54:44 +08:00
Yichen Jiang a840641d78 Merge branch 'worktree/pr3594-manifest-mergeup' into feat/plugin-mgmt-3-settings 2026-09-11 17:54:38 +08:00
Yichen Jiang 52c215ee55 fix(plugins): resolve root state from plugin callers and report live failures 2026-09-11 17:54:29 +08:00
Yichen Jiang a9403470f8 Merge branch 'worktree/pr3593-manifest-3899' into worktree/pr3594-manifest-mergeup 2026-09-11 17:51:21 +08:00
Yichen Jiang fa240e7372 fix(boot): inject loader for plugin-scoped recomposition 2026-09-11 17:51:05 +08:00
Turtle 2b05a43eca fix: address concrete terminology review findings 2026-09-11 17:45:28 +08:00
Turtle 71d50b4a84 refactor: ban ambiguous origin label 2026-09-11 17:45:28 +08:00
Chinesezjc 62dd508cb0 test(permission): pin the disposed guard on the invalidation tick
The late-listener case now carries a pending generation change, so its
assertions depend on the disposed guard, and the silent-generation cases assert
their tick counts.
2026-09-11 17:45:23 +08:00
Dudu-0223 bfa6cc01aa fix(agent-team): raise default teammate limit to 16 2026-09-11 17:41:55 +08:00
imccyu 41915703cc refactor(conversation): move default views to its own module 2026-09-11 17:34:27 +08:00
imccyu f4dbec93df refactor(conversation): extract default views component 2026-09-11 17:34:27 +08:00
imccyu 8f5b1d71e3 refactor(conversation): move main panel to its own module 2026-09-11 17:34:27 +08:00
imccyu 0db88bd58d refactor(conversation): move content component to its own module 2026-09-11 17:34:26 +08:00
imccyu 2477554471 refactor(conversation): extract content component 2026-09-11 17:34:26 +08:00
imccyu 0220ec4989 refactor(conversation): extract main panel component 2026-09-11 17:34:26 +08:00
Yichen Jiang 3f9c25eb1d merge: propagate plugin diagnostics cleanup to web 2026-09-11 17:33:22 +08:00
Yichen Jiang 89d1bc27c1 Merge branch 'worktree/pr3594-manifest-mergeup' into feat/plugin-mgmt-3-settings 2026-09-11 17:30:34 +08:00
Yichen Jiang 074b1cb15e Merge branch 'worktree/pr3593-manifest-3899' into worktree/pr3594-manifest-mergeup 2026-09-11 17:29:57 +08:00
Yichen Jiang eaecfd59bf fix(plugins): notify only changed diagnostics and remove stale probe cleanup 2026-09-11 17:29:56 +08:00
creatixchu 63f1f6eca4 chore(workspace-changes): align the package version with the root after the master merge 2026-09-11 17:29:37 +08:00
07akioni b916f455af fix(ci): use HTTPS Ubuntu sources for browser dependencies 2026-09-11 17:27:29 +08:00
Yichen Jiang 26706559b2 refactor(boot): remove unpublished probe remnants and notes 2026-09-11 17:26:43 +08:00
Dudu-0223 22b843ed2b Merge remote-tracking branch 'origin/master' into HEAD 2026-09-11 17:25:51 +08:00
creatixchu 51de5bbc4d fix(web): draw the changed-files header tile with the design's angle-bracket mark 2026-09-11 17:25:50 +08:00
Dudu-0223 f74d625e5a Merge pull request #4001 from deepseek-harness/fix/session-fork-boundary
fix(session): stop forks at the selected turn end
2026-09-11 17:25:35 +08:00
Dudu-0223 41de75a96d Merge pull request #3935 from deepseek-harness/fix/workspace-recency-order
fix(workspace): derive recency and pause the current order in Manual
2026-09-11 17:24:49 +08:00
creatixchu 0f8457a017 feat(workspace-changes): record only git repositories and add the recorded card scenario
Drop the shadow repository tier: a working directory outside any git
repository records nothing and the card stays absent, because a configured
exclude list cannot replace a missing .gitignore reliably. Seed a committed
repository in a new keyless Web scenario so the recorded turn exercises the
recorder, and retire the produced-files row from the affected goldens.
2026-09-11 17:22:15 +08:00
Chinesezjc eb6373d711 fix(permission): tick only on a real generation change
A notification repeating the published generation no longer withdraws displayed
options, so the invalidation observable and the README describe the same rule.
The composer seat hides on a cleared catalog while the slash picker keeps its
failure and retry, and the disposed guard that both callers already provide is
gone from the tick.
2026-09-11 17:20:22 +08:00
Dudu-0223 589cc7ae87 test(web): align Team fixture with shipped delegation tools 2026-09-11 17:18:58 +08:00
Dudu-0223 dafff8e51c fix(subprocess): settle consumed empty scopes before exit notification 2026-09-11 17:05:15 +08:00
Chinesezjc 38391bf6ba Merge remote-tracking branch 'origin/master' into auto-review-per-call 2026-09-11 17:03:09 +08:00
Chinesezjc 14bdce3644 docs(permission): describe dismissal as a catalog invalidation
The package README, its Chinese pair, and the catalog spec now state both
public observables and pin the generation-change tick that withdraws displayed
options.
2026-09-11 17:00:54 +08:00
Dudu-0223 ca53514562 fix(ci): use HTTPS Ubuntu archives on Blacksmith 2026-09-11 17:00:30 +08:00
Dudu-0223 a68d3131c8 Merge branch 'master' into fix/session-fork-boundary 2026-09-11 16:56:46 +08:00
Yichen Jiang 8d843f603c Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web 2026-09-11 16:56:15 +08:00
Yichen Jiang 43b10b9ee6 Merge branch 'worktree/pr3594-manifest-mergeup' into feat/plugin-mgmt-3-settings 2026-09-11 16:56:11 +08:00
Yichen Jiang fa03c7dd15 Merge branch 'worktree/pr3593-manifest-3899' into worktree/pr3594-manifest-mergeup 2026-09-11 16:56:06 +08:00
Yichen Jiang 8279761268 fix(plugin-inventory): require the runtime diagnostics dependency 2026-09-11 16:55:56 +08:00
07akioni 587c21d06b refactor(desktop): inherit shared Web profile defaults 2026-09-11 16:54:39 +08:00
Yichen Jiang 4264b1d9f2 Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web 2026-09-11 16:53:06 +08:00
Yichen Jiang dc513272bf Merge branch 'worktree/pr3594-manifest-mergeup' into feat/plugin-mgmt-3-settings 2026-09-11 16:53:02 +08:00
Yichen Jiang aa1c40965c Merge branch 'worktree/pr3593-manifest-3899' into worktree/pr3594-manifest-mergeup 2026-09-11 16:52:57 +08:00
Yichen Jiang 96ba84e15d test(boot): exercise startup policy through installed bundle provenance 2026-09-11 16:52:37 +08:00
Yichen Jiang 8c3ddf0971 merge: adapt plugin management UI to native entry outcomes 2026-09-11 16:52:37 +08:00
Dudu-0223 5731647698 test(agent-team): follow the DeepSeek protocol module move 2026-09-11 16:48:15 +08:00
creatixchu 3c632ebf66 Merge remote-tracking branch 'origin/master' into worktree/code-diff-card 2026-09-11 16:47:45 +08:00
creatixchu f937f4e23b feat(web): record turn file changes with git snapshots and render the changed-files card
Add the dsh-workspace-changes Host plugin that snapshots the working tree at
turn start and end through a private git index, diffs the two trees, folds in
file-tool hunks for ignored and out-of-tree files, and appends a log-only
workspace/changes event. The Web deliverables plugin renders that event as the
changed-files card in place of the mutation-call row, with default-app and
common-folder opening through a new authenticated route.
2026-09-11 16:47:40 +08:00
Dudu-0223 96a3a32fa2 fix(ci): use HTTPS Ubuntu archives on Blacksmith 2026-09-11 16:47:31 +08:00
Dudu-0223 8eafb70b04 fix(ci): use HTTPS Ubuntu archives on Blacksmith 2026-09-11 16:47:09 +08:00
Dudu-0223 10175e62cc Merge master into fix/team-identity-context 2026-09-11 16:46:22 +08:00
Dudu-0223 ad3be9711d Merge master into fix/workspace-recency-order 2026-09-11 16:46:21 +08:00
winewill 4fa238bb5f fix(desktop): track extraction in directory installer 2026-09-11 16:43:51 +08:00
lsdsjy c58ddc5fa3 Merge remote-tracking branch 'origin/master' into HEAD 2026-09-11 16:41:56 +08:00
Yichen Jiang 7485d75e38 Merge pull request #3682 from deepseek-harness/worktree/llm-deepseek-messages
feat(llm): add Messages protocol support to DeepSeek
2026-09-11 16:38:43 +08:00
lsdsjy 62c04f12cc Merge remote-tracking branch 'origin/master' into HEAD 2026-09-11 16:37:19 +08:00
Dudu-0223 4984befd2c Merge master into fix/team-identity-context 2026-09-11 16:32:32 +08:00
Dudu-0223 b6e9b013f9 Merge master into fix/workspace-recency-order 2026-09-11 16:32:31 +08:00
Chinesezjc 4a935ed8fd fix(permission): drop the picker only on a catalog invalidation
Publishing the result of a read the picker waits for no longer closes that
picker, so a failed read keeps its error and retry state; a catalog
notification or generation change still withdraws stale options. Correct the
action-history rationale in the Auto review note and cover both paths with the
real popup controller.
2026-09-11 16:29:31 +08:00
winewill 188f72cd58 fix(desktop): track installer work and complete progress smoothly 2026-09-11 16:23:10 +08:00
winewill e12fbbcbb3 feat(desktop): apply designer icons to apps and Windows setup 2026-09-11 16:23:09 +08:00
winewill 6cc34319e5 fix(desktop): align installer progress with worker stages 2026-09-11 16:23:08 +08:00
winewill 00ca76dd21 fix(desktop): keep installer progress and completion responsive 2026-09-11 16:22:47 +08:00
winewill 9255b08ed3 fix(desktop): preserve installer dependencies and validate keyboard navigation 2026-09-11 16:22:46 +08:00
winewill 52bc79284f feat(desktop): integrate native Windows installer design 2026-09-11 16:22:44 +08:00
Yichen Jiang 3829cca80b Merge native plugin loading and update scoped settings consumers 2026-09-11 16:19:00 +08:00
Yichen Jiang 3ace0d0cf7 Merge profile settlement and await it before runtime notifications 2026-09-11 16:13:21 +08:00
Yichen Jiang 8c33df5d8e fix(boot): expose profile recomposition settlement to observers 2026-09-11 16:11:46 +08:00
Yichen Jiang b351ca0578 refactor(plugins): manage static declarations and native row outcomes 2026-09-11 16:11:03 +08:00
07akioni 695720ea8d Merge latest master into thin Electron Web UI branch 2026-09-11 15:59:07 +08:00
Yichen Jiang 96be622603 Merge native entry loading into plugin manager 2026-09-11 15:56:37 +08:00
Yichen Jiang 1144cf1e8e refactor(boot): use native entry diagnostics and static plugin declarations 2026-09-11 15:54:14 +08:00
07akioni bebf88de4f Use Electron Node runtime and replace Windows installations by directory 2026-09-11 15:52:05 +08:00
Yichen Jiang acb448e0c7 docs: normalize plugin decision note headers 2026-09-11 15:48:53 +08:00
Chinesezjc e995d71a0e fix(permission): keep the picker retryable after a failed catalog read
Availability now follows the Session projection alone, so a failed catalog
read surfaces through the picker's own retry instead of hiding the command.
Type-guard the persisted denial reason before trimming it, and record in the
Auto review note why the reviewer reads the complete action history.
2026-09-11 15:46:19 +08:00
Yichen Jiang bc13dcf550 Merge remote-tracking branch 'origin/master' into worktree/llm-deepseek-messages 2026-09-11 15:42:51 +08:00
Chinesezjc 1de37ddc2b test(web): follow the settled-loader startup audit
Loader settlement no longer rejects on a failed optional entry, so the Auto
rollback scenario reads the conflict from the startup audit. Refresh the Auto
denial golden for the merged composer chrome.
2026-09-11 15:41:46 +08:00
creatixchu 93581008aa docs: refresh the paired Session API record 2026-09-11 15:40:44 +08:00
Dudu-0223 4f1663c143 Merge remote-tracking branch 'origin/master' into fix/session-fork-boundary 2026-09-11 15:39:29 +08:00
Dudu-0223 88c3d05fbf fix(session): align browser fixture forks and legal log regressions 2026-09-11 15:39:20 +08:00
creatixchu 653a4164b8 docs: sync the projection disposer signature 2026-09-11 15:38:19 +08:00
creatixchu 4e7193945d fix: expose the projection registration async disposer 2026-09-11 15:38:04 +08:00
creatixchu 325c8d880a build: admit pure message projection leaves in browser bundles 2026-09-11 15:35:55 +08:00
Turtle 4c4b7e6cb2 Merge pull request #4003 from deepseek-harness/turtle/systemd-scope-exit-race
fix(ci): stabilize teardown, process sampling, and reply queue coverage
2026-09-11 15:35:08 +08:00
Yichen Jiang f7519bab0a Merge master settings checkpoint into plugin management UI 2026-09-11 15:34:07 +08:00
Yichen Jiang 6bb4ce0e37 Merge master manager checkpoint into scoped settings 2026-09-11 15:32:19 +08:00
Yichen Jiang 90aa315f40 Merge master boot checkpoint into plugin manager 2026-09-11 15:31:04 +08:00
creatixchu 401c3ef977 test: type the stored projection fixture as format events 2026-09-11 15:29:33 +08:00
Yichen Jiang 7c34e7a328 Merge master before native plugin loading migration 2026-09-11 15:28:51 +08:00
Dudu-0223 b16687ffcb Merge branch 'master' into fix/team-identity-context 2026-09-11 15:27:52 +08:00
creatixchu 1d4d22c1ff test: complete projection fixtures and configuration catalog 2026-09-11 15:26:54 +08:00
Dudu-0223 75b89b353d Merge branch 'master' into fix/workspace-recency-order 2026-09-11 15:25:54 +08:00
creatixchu 413ac14b16 refactor: move image offload projection into its plugin 2026-09-11 15:24:45 +08:00
Dudu-0223 11248ea949 fix(workspace): retain blank manual positions during reconnect 2026-09-11 15:21:09 +08:00
Dudu-0223 973bea8204 fix(session): use the selected turn end as the fork cut 2026-09-11 15:09:47 +08:00
Chinesezjc 6b19923ad5 fix(auto-review): clear the master integration gates
Register the permission catalog default response so the web roster boot
matches every Remote call it makes, and carry the deprecation rule for the
session history read this reviewer needs with the deferred migration
recorded in the package README.
2026-09-11 15:08:48 +08:00
Turtle 16f80298df Merge pull request #4006 from deepseek-harness/turtle/boot-failure-e2e
test(boot): cover Web failure recovery and inject module routes
2026-09-11 15:04:29 +08:00
Dudu-0223 0f8552df7f fix(session): retain fork tail until the first inbox change 2026-09-11 14:58:46 +08:00
turtle1999 fd0dce2f20 ci: route runtime and LLM e2e through Blacksmith failover 2026-09-11 14:51:15 +08:00
Dudu-0223 41196ae591 fix(agent-team): disable direct subagent tools in Team profiles 2026-09-11 14:50:52 +08:00
turtle1999 18a1955b7e fix(ci): handle scope termination races and cyclic process snapshots 2026-09-11 14:50:46 +08:00
turtle1999 85c37d1950 docs(boot): document startup and reload failure behavior 2026-09-11 14:45:37 +08:00
Yichen Jiang a326698ee7 Merge remote-tracking branch 'origin/master' into worktree/llm-deepseek-messages
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/config-catalog.zh.md
#	packages/llm/llm-deepseek/src/adapter.ts
#	packages/llm/llm-deepseek/src/common/request-pricing.ts
#	packages/llm/llm-deepseek/src/index.ts
#	packages/llm/llm-deepseek/tests/adapter.spec.ts
#	packages/llm/llm-deepseek/tests/image-tokens.spec.ts
2026-09-11 14:44:30 +08:00
turtle1999 6e60940ded feat(ci): cap blame approval weight at quarter ownership 2026-09-11 14:38:16 +08:00
turtle1999 eb9da8930e test(boot): cover Web failure recovery and inject module routes 2026-09-11 14:34:17 +08:00
Dudu-0223 3a48b62344 refactor(workspace): derive flat rows only after ordering 2026-09-11 14:31:25 +08:00
Chinesezjc 3afad043c6 Merge remote-tracking branch 'origin/auto-review-per-call' into auto-review-per-call 2026-09-11 14:29:11 +08:00
Chinesezjc 358d0bc49c Merge remote-tracking branch 'origin/master' into auto-review-per-call 2026-09-11 14:27:30 +08:00
Chinesezjc d8c54899b7 fix(experimental): align the Auto review package version with the release 2026-09-11 14:27:27 +08:00
creatixchu bc49b2a15c Merge master 28a4010f7d into image offload branch 2026-09-11 14:22:36 +08:00
_Kerman 20106ecda8 Merge pull request #3869 from deepseek-harness/xtr/ptc-sdk-literal-prompt
fix(ptc): preserve literal braces in generated SDK prompts
2026-09-11 14:20:23 +08:00
turtle1999 4563910ff4 fix(ci): retain pending status during blame evaluation 2026-09-11 14:19:19 +08:00
Chinesezjc a605cf579d Merge branch 'master' into auto-review-per-call 2026-09-11 14:19:16 +08:00
Dudu-0223 896a6c3e47 fix(session): stop forks at the selected turn end 2026-09-11 14:17:53 +08:00
turtle1999 cef92ed40b feat(ci): weight approvals by production blame ownership 2026-09-11 14:16:24 +08:00
Chinesezjc fed65b7cad Merge master into the Auto review branch
Resolve 36 conflicts across source, bilingual READMEs, and generated
documentation: keep master's command-identity and popup APIs, RemoteMock
test infrastructure, and regenerated catalogs; keep the Auto review
catalog, slot, dismissal, and snapshot content.
2026-09-11 14:15:32 +08:00
Yifffan ef39ebd0bb Merge pull request #3969 from deepseek-harness/refine/connecting-ui
feat(sidebar): refine the connection indicator states and interaction
2026-09-11 08:06:56 +02:00
Dudu-0223 d19d23cf86 fix(workspace): make manual session order browser-local 2026-09-11 14:05:13 +08:00
_Kerman 1d20d46a08 Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-3869 2026-09-11 13:54:03 +08:00
Turtle ef0041b351 Merge pull request #3964 from deepseek-harness/turtle/master-ci-browser-realpath
fix(ci): repair browser roots and asynchronous test fixtures
2026-09-11 13:49:06 +08:00
07akioni 253873f340 Merge origin/master into thin Electron Web UI branch 2026-09-11 13:43:03 +08:00
creatixchu c59d285f99 chore(compaction): mark existing history read for deferred migration 2026-09-11 13:43:02 +08:00
creatixchu ec3560c42e Merge master 16bf879af2 into image offload branch 2026-09-11 13:40:19 +08:00
lsdsjy 05373a4897 Merge remote-tracking branch 'origin/master' into HEAD 2026-09-11 13:37:34 +08:00
07akioni 6b05ed53e9 test(desktop): remove obsolete fs-ext payload smoke 2026-09-11 13:36:50 +08:00
Yifffan c160884c19 Merge branch 'master' into refine/connecting-ui 2026-09-11 07:32:49 +02:00
CreatixChu ac34c5deac Merge pull request #3938 from deepseek-harness/worktree/issue-3929-v41-request-image
更新v41的图片大小限制
2026-09-11 13:32:15 +08:00
turtle1999 40e39f4673 test(ci): control Python stray UTF-8 fragment delivery 2026-09-11 13:31:22 +08:00
Turtle 239f695e1f Merge pull request #3830 from deepseek-harness/turtle/required-plugin-startup-policy
feat(boot): distinguish required startup failures
2026-09-11 13:28:59 +08:00
Yif ce1a55816f Merge remote-tracking branch 'origin/refine/connecting-ui' into refine/connecting-ui 2026-09-11 13:28:50 +08:00
turtle1999 96ee6e49f9 test(terminal): await PowerShell prompt delivery 2026-09-11 13:22:55 +08:00
Yichen Jiang e5e9037dfb test(llm): opt in Messages system-update e2e 2026-09-11 13:17:25 +08:00
creatixchu db6dff8f67 Merge remote-tracking branch 'origin/master' into worktree/issue-3929-v41-request-image 2026-09-11 13:16:24 +08:00
turtle1999 464334bc4c test(boot): keep headless running after optional MCP startup failure 2026-09-11 13:10:03 +08:00
Turtle b576419a4c Merge branch 'master' into turtle/master-ci-browser-realpath 2026-09-11 13:03:10 +08:00
Turtle f93cea5734 Merge pull request #3983 from deepseek-harness/turtle/master-ci-windows-store
fix(ci): derive Windows standby store from workspace volume
2026-09-11 13:01:36 +08:00
_Kerman 95690d6453 Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-3869 2026-09-11 12:55:09 +08:00
Yichen Jiang 6ad0ddb899 test(llm): pin Messages e2e to its official endpoint 2026-09-11 12:51:25 +08:00
turtle1999 6894e93a12 refactor(app-boot): keep required startup policy private 2026-09-11 12:47:48 +08:00
turtle1999 4cd20c1a1e fix(app-boot): bound cyclic startup error diagnostics 2026-09-11 12:47:48 +08:00
turtle1999 25d5efcd86 Classify disabled expression errors in startup audits 2026-09-11 12:47:48 +08:00
turtle1999 f5b5a9da51 Require Web modules and connection during startup 2026-09-11 12:47:47 +08:00
turtle1999 97d1f7c203 fix(web-app): gate readiness on required startup entries 2026-09-11 12:47:47 +08:00
turtle1999 7fd41b833b fix(boot): limit required IDs to application endpoints 2026-09-11 12:47:47 +08:00
turtle1999 f4a7dd6077 fix(boot): preserve failure policy on nontransactional Loader 2026-09-11 12:47:46 +08:00
Turtle f308742050 test(boot): cover startup diagnostic variants 2026-09-11 12:47:46 +08:00
Turtle 941267b197 test(boot): type fixture fiber state 2026-09-11 12:47:46 +08:00
Turtle fbcad258ad test(boot): keep required fixture failures fatal 2026-09-11 12:47:46 +08:00
Turtle bd4cfc7c46 feat(boot): distinguish required startup failures 2026-09-11 12:47:46 +08:00
Yif dd7ba51a13 Merge remote-tracking branch 'origin/master' into refine/connecting-ui
# Conflicts:
#	packages/client/ui-primitives/README.i18n.yaml
#	packages/client/ui-primitives/README.md
#	packages/client/ui-primitives/README.zh.md
2026-09-11 12:29:34 +08:00
Ziya 1f56a2c0e0 Merge pull request #3970 from deepseek-harness/copy/ask-user-skip-20260910
fix(web): 简化提问卡片的中英文跳过文案
2026-09-11 11:54:51 +08:00
07akioni 7fe6acdf8b test(desktop): canonicalize pnpm fixture paths on Windows 2026-09-11 11:39:14 +08:00
ZiyaZhang 91da8a4ecf Merge master and retain its Python coverage fix 2026-09-10 20:38:00 -07:00
_Kerman 2832077b2c test(web): refresh tool details golden 2026-09-11 11:32:52 +08:00
Yichen Jiang bc99474e87 Merge remote-tracking branch 'origin/master' into worktree/llm-deepseek-messages
# Conflicts:
#	packages/llm/llm-deepseek/package.json
2026-09-11 11:27:47 +08:00
07akioni ae84dd3381 fix(desktop): address shared runtime review and CI regressions 2026-09-11 11:24:17 +08:00
_Kerman 6744f21a43 test(client): cover invalid detail locales 2026-09-11 11:20:25 +08:00
_Kerman 27e4529d15 fix(client): guard detail date localization 2026-09-11 11:18:01 +08:00
creatixchu f0f1988a7a Clarify token counts after aspect-preserving image projection 2026-09-11 11:14:33 +08:00
_Kerman bd16c3c89e fix(client): complete compact tool details review 2026-09-11 11:14:32 +08:00
creatixchu d995331772 feat(web): start the turn-level code diff card for #3501 2026-09-11 11:07:25 +08:00
creatixchu 08dba5f5f6 test(compaction): record summary image recovery through ACP 2026-09-11 11:00:17 +08:00
creatixchu 73e10fb80c fix(compaction): preserve summary diagnostics on cancellation 2026-09-11 10:58:36 +08:00
creatixchu debb4b9a9c fix(compaction): recover durable image offload in summary requests 2026-09-11 10:56:48 +08:00
creatixchu 275af6a2e2 Merge remote-tracking branch 'origin/master' into worktree/issue-3929-v41-request-image 2026-09-11 10:42:03 +08:00
turtle1999 e46cb49103 fix(ci): derive Windows standby store from workspace volume 2026-09-10 23:02:21 +08:00
07akioni 8c2fa73ceb refactor(desktop): share profile initialization and plugin management 2026-09-10 22:44:52 +08:00
07akioni 8345ac129e fix(desktop): separate default port and replace plugin update prompt 2026-09-10 22:29:49 +08:00
Yichen Jiang c291e7961a Merge pull request #3977 from deepseek-harness/worktree/release-0.1.5-sync-master
feat(web): sync feedback and file refinements from release
2026-09-10 22:17:09 +08:00
07akioni b373c45648 merge: incorporate latest master into thin Electron branch 2026-09-10 22:12:49 +08:00
07akioni e84a4e857e refactor(desktop): run shared Web UI in a thin Electron shell 2026-09-10 22:08:33 +08:00
Turtle e570e74705 Merge pull request #3962 from deepseek-harness/turtle/ci-smoke-20260910-1820
test(python): make stray-output sealing coverage deterministic
2026-09-10 22:01:34 +08:00
Yichen Jiang 59f2e3be33 Merge release/dsh-0.1.5 version 0.1.5-rc.2 into master sync branch 2026-09-10 21:53:53 +08:00
Yichen Jiang fb2c4b9e69 Merge pull request #3978 from deepseek-harness/worktree/release-dsh-0.1.5-rc.2
release(dsh): 0.1.5-rc.2
2026-09-10 21:50:19 +08:00
Yichen Jiang a305303422 release(dsh): 0.1.5-rc.2 2026-09-10 21:38:20 +08:00
Dudu-0223 a17f0733b1 test(workspace): stabilize sidebar captures and update blank placement 2026-09-10 21:34:45 +08:00
Dudu-0223 4857614be0 fix(workspace): pause current ordering in manual mode 2026-09-10 21:25:09 +08:00
Yichen Jiang 3bfcebe15e Merge master into worktree/release-0.1.5-sync-master 2026-09-10 21:23:11 +08:00
Yichen Jiang 2107e4697e Merge pull request #3973 from deepseek-harness/worktree/release-0.1.5-backport-feedback-deliverables
feat(web): backport feedback and file refinements to 0.1.5
2026-09-10 21:09:45 +08:00
Yifffan 879949e1c9 Merge branch 'master' into refine/connecting-ui 2026-09-10 14:55:03 +02:00
yixiangihsiangandLegGasai 060323d8e2 feat(web): backport feedback and file refinements to 0.1.5
Backport the selected changes from PR #3928 and PR #3902 onto dsh-v0.1.5-rc.1, retaining baseline session recordings and excluding newer master commits.

Refs #3927
Refs #3903

Co-authored-by: LegGasai <[email protected]>
2026-09-10 20:51:46 +08:00
ZiyaZhang 884485e7e6 test(python): restore concat through its spy 2026-09-10 05:40:50 -07:00
ZiyaZhang 7bce0c26f5 test(python): make stray fragment coverage deterministic 2026-09-10 05:35:32 -07:00
Yif 11ca8020cd fix(sidebar): keep one reconnect label and confirm recovery from visibility
ConnectionController deduplicates repeated connecting states across backoff
attempts, so the shell cannot tell manual retries from automatic ones; a
shell-held flag either flipped the label mid-hold or stuck across later
attempts. Every attempt now reads the single connecting label, and the
two-second recovery confirmation starts when the recovered pill becomes
visible rather than at the state transition, so the 800ms hold never
shortens it.
2026-09-10 20:12:09 +08:00
ZiyaZhang 69db89f848 fix(web): shorten English question skip label 2026-09-10 05:06:14 -07:00
ZiyaZhang 2eed93628c fix(web): shorten Chinese question skip label 2026-09-10 05:00:38 -07:00
Yif b044e45438 test(web): pin the static connection pill in the lifecycle browser snapshot 2026-09-10 19:52:38 +08:00
lsdsjy 71b2cc80aa fix(headless): waive the deferred Session history read
Master's `deprecate-synchronous-session-event-reads` marks `Session.eventAt`
deprecated and rejects new production calls. `liveEvents` predates that decision
and still needs the ordered log to reconstruct the preset a session runs under,
so carry the repository's standard line-scoped waiver for deferred migration.
2026-09-10 19:32:54 +08:00
Yif 16e986548e test(sidebar): pin the refined connection indicator behavior and docs
Update the behavior tests for the static retry label, the 800ms minimum
connecting hold, manual-versus-automatic attempt naming, and the 150ms
fade-out unmount; restate the interaction in both packages' bilingual
READMEs and record the decision as an Agent Note.
2026-09-10 19:29:48 +08:00
lsdsjy 79bd986fa7 Merge remote-tracking branch 'origin/master' into HEAD 2026-09-10 19:16:53 +08:00
lsdsjy 145f20f712 Merge remote-tracking branch 'origin/master' into HEAD 2026-09-10 19:13:38 +08:00
lsdsjy 3be1ea10b9 refactor(headless): move the runner process hooks out of the package entry
Address the Code Entropy follow-up on d9c4f53758: the runner entry still
expanded its process-substitution object with a `readStdin` hook used only by
tests. Move that seam to `src/runner-internals.ts`, mirroring
`src/startup-internals.ts`, so neither entry grows package API for tests.
2026-09-10 19:13:05 +08:00
turtle1999 464e1cce49 fix(ci): canonicalize browser dependency scan roots 2026-09-10 19:01:00 +08:00
_Kerman b59d3605b7 fix(client): address compact tool details review 2026-09-10 18:29:12 +08:00
turtle1999 0963bdd7d3 test(python): control stray-output fragments for sealing coverage 2026-09-10 18:29:04 +08:00
turtle1999 39e6e6fb89 Retain awaited client cleanup after rebase 2026-09-10 18:21:19 +08:00
turtle1999 0e6505454e Align client boot import failure test with reverted Loader 2026-09-10 18:18:10 +08:00
turtle1999 ab4d22595b Merge master and await client plugin cleanup after removal 2026-09-10 18:18:10 +08:00
turtle1999 3b5daf10be test(ci): verify current master on PR runners 2026-09-10 18:16:47 +08:00
Turtle 060ae6f336 Merge pull request #3957 from deepseek-harness/fix/subprocess-linux-scope-empty-range
fix(ci): resolve Blacksmith scope teardown and hosted test failures
2026-09-10 18:11:48 +08:00
_Kerman 42b50bd377 Merge pull request #3828 from deepseek-harness/xtr/deprecate-session-event-readers
docs(session): deprecate synchronous event-history reads
2026-09-10 18:03:54 +08:00
Chinesezjc 1050091d82 Merge pull request #3926 from deepseek-harness/ci/blacksmith-hosted-image-fixes
test/ci: remove the host-paced assumptions the hosted coverage lanes hit
2026-09-10 18:01:54 +08:00
turtle1999 989b3d4390 Merge hosted-image test fixes for Blacksmith CI 2026-09-10 17:53:36 +08:00
07akioni 69005cb956 Merge pull request #3860 from deepseek-harness/fix/parallel-macos-notarization
perf(desktop): 并行 macOS 公证并记录上传加速说明
2026-09-10 17:52:40 +08:00
Chinesezjc 0377049465 ci: give the Linux coverage lane the hosted image's teardown budget
The managed-scope disposal cases in subprocess-local and bash-sandbox run past
the 5000ms default when this lane's four partitions, six workers per gate, and
sibling gates share one host. The same commit stays inside the budget on the
in-house pool: the hosted image exceeded it (run 34449848541) and the lane is
green with 90000 (run 34457655892). The Windows coverage lane already grants
the same budget for the same class of teardown.

(cherry picked from commit bf3468adf0947a51f09d4a1aaae2865f3e50a2f2)
2026-09-10 17:47:27 +08:00
Chinesezjc 114e8c9b09 test: drop two host-paced assumptions the hosted image exposes
The ACP plugin-config case drove a real dispose with 150ms graces. On the hosted
image the SIGKILL escalation landed while the managed scope could not take the
signal — systemctl failed the kill ("Failed to send signal SIGKILL to auxiliary
processes: Invalid argument") — so the run reported a teardown failure the
configuration never asked for. The case asserts that config graces reach the
real run, so the values only need to clear the host's scope handling. Its mock
refuses stdin EOF and SIGTERM by design, so the case waits out both graces and
carries its own budget for that fixed cost.

Both illegal-UTF-8 residual cases relied on a plain sched_yield leaving each
write as its own read chunk. A starved reader coalesces hundreds of bytes into
one chunk, which inflates the measured peak for correct accounting too: the
hosted image measured 2563 against the 2048 bound. Pace with a real sleep so
each byte is its own chunk everywhere, and keep each payload above the bound
(3200 bytes; 1100 CESU-8 sequences) so a raw-byte undercount still flushes past
it instead of only at EOF.

(cherry picked from commit 30e0c3ff0415befe3652a55611df8a18d82c18bb)
2026-09-10 17:47:27 +08:00
Chinesezjc c4c2d16308 test(subprocess): align the teardown race with the settlement contract
`disposal contains a spawn-failure rejection that races teardown` asserted one
winner of the race. A bootstrap that publishes its pre-exec failure rejects with
that failure, and a teardown that stops the bootstrap first settles as the
requested termination — the recorded failure only outranks the stop when it was
published before the stop landed. Assert the contract instead: a rejection
carries the failure, a stop carries SIGTERM, which only the Linux scope records
because the win32 job owner and the fallback launcher both reject the start.

The two terminal cases that drive a mocked PTY exit state why they pin
`internals.platform`: under the host's native scope the mocked exit races the
scope bootstrap and fails as `terminal scope exited before its bootstrap
consumed the launch request`.

(cherry picked from commit fee113eb9a5632555304858d2bf6355588a3aaf0)
2026-09-10 17:47:27 +08:00
Yif 626fa816a5 feat(sidebar): refine the connection indicator states and styling
The disconnected pill now names the retry action statically (refresh icon +
"连接异常,刷新重试") instead of swapping text on hover; connecting shows a
spinner, holds visible for at least 800ms, and distinguishes manual retry
(重新连接中) from automatic backoff (自动重连中); state changes fade over
150ms. Pill chrome tightened to 28px height with a 20%-alpha label border.
2026-09-10 17:45:56 +08:00
Turtle def3f88bf5 Merge pull request #3943 from deepseek-harness/fix/master-ci-corpus-css-pin
fix(ci): admit any `.css` refusal for the dockkit corpus exemption
2026-09-10 17:44:34 +08:00
creatixchu ffa536712a Merge remote-tracking branch 'origin/master' into worktree/issue-3929-v41-request-image
# Conflicts:
#	packages/attachment/attachment-local/README.i18n.yaml
#	packages/attachment/attachment-local/README.md
#	packages/attachment/attachment-local/README.zh.md
2026-09-10 17:41:17 +08:00
Turtle 3ece27847c Merge pull request #3925 from deepseek-harness/turtle/dsh-cache-path
feat(attachment-local): use shared cache for request images
2026-09-10 17:38:26 +08:00
Chinesezjc 87f32dc8ca docs(notes): record the hosted-image assumptions the coverage suite names
The failover leg runs this suite on pools this repository does not own, and the
coverage lanes failed there on host properties their cases never named: the
containment a mocked PTY exit raced, the grace a managed scope needs before it
can take a SIGKILL, reader coalescing in the illegal-UTF-8 residual cases, and
a Windows image that refuses the folder dialog class. Record what each case
pins now, what was rejected, and the runs that measured it, so the next pool
change starts from those host dependencies instead of re-diagnosing them.
2026-09-10 17:36:16 +08:00
Chinesezjc 45c10ed2ce ci: give the Linux coverage lane the hosted image's teardown budget
The managed-scope disposal cases in subprocess-local and bash-sandbox run past
the 5000ms default when this lane's four partitions, six workers per gate, and
sibling gates share one host. The same commit stays inside the budget on the
in-house pool: the hosted image exceeded it (run 34449848541) and the lane is
green with 90000 (run 34457655892). The Windows coverage lane already grants
the same budget for the same class of teardown.
2026-09-10 17:36:16 +08:00
Chinesezjc f45ca2d9ac test: drop two host-paced assumptions the hosted image exposes
The ACP plugin-config case drove a real dispose with 150ms graces. On the hosted
image the SIGKILL escalation landed while the managed scope could not take the
signal — systemctl failed the kill ("Failed to send signal SIGKILL to auxiliary
processes: Invalid argument") — so the run reported a teardown failure the
configuration never asked for. The case asserts that config graces reach the
real run, so the values only need to clear the host's scope handling. Its mock
refuses stdin EOF and SIGTERM by design, so the case waits out both graces and
carries its own budget for that fixed cost.

Both illegal-UTF-8 residual cases relied on a plain sched_yield leaving each
write as its own read chunk. A starved reader coalesces hundreds of bytes into
one chunk, which inflates the measured peak for correct accounting too: the
hosted image measured 2563 against the 2048 bound. Pace with a real sleep so
each byte is its own chunk everywhere, and keep each payload above the bound
(3200 bytes; 1100 CESU-8 sequences) so a raw-byte undercount still flushes past
it instead of only at EOF.
2026-09-10 17:36:15 +08:00
Chinesezjc df709f442c test(subprocess): align the teardown race with the settlement contract
`disposal contains a spawn-failure rejection that races teardown` asserted one
winner of the race. A bootstrap that publishes its pre-exec failure rejects with
that failure, and a teardown that stops the bootstrap first settles as the
requested termination — the recorded failure only outranks the stop when it was
published before the stop landed. Assert the contract instead: a rejection
carries the failure, a stop carries SIGTERM, which only the Linux scope records
because the win32 job owner and the fallback launcher both reject the start.

The two terminal cases that drive a mocked PTY exit state why they pin
`internals.platform`: under the host's native scope the mocked exit races the
scope bootstrap and fails as `terminal scope exited before its bootstrap
consumed the launch request`.
2026-09-10 17:36:14 +08:00
Chinesezjc ac5f851095 test(directory-picker): probe the folder dialog class instead of the platform
A Windows Server image can answer CoCreateInstance(CLSID_FileOpenDialog)
with CLASS_E_CLASSNOTAVAILABLE, so the win32 COM smoke has no dialog to
open and the POSIX rejection expectation is the only proof that image can
produce. Gate the pair on a PowerShell activation probe taken outside the
code under test, so a GUID or vtable regression in src still fails the
smoke instead of skipping it.
2026-09-10 17:36:13 +08:00
lsdsjy 40dc25fe1d Merge remote-tracking branch 'origin/master' into HEAD 2026-09-10 17:32:26 +08:00
lsdsjy 6d05765405 refactor(headless): keep the startup process seam out of the public entry
Address the Code Entropy finding on f67d722243: the `./startup` entry exported
`internals` only so tests could substitute process facts, which added avoidable
package API. Move the seam to `src/startup-internals.ts`, which no package
export names, and have the provider and its tests import it from there.
2026-09-10 17:29:15 +08:00
turtle1999 aaa02a3970 fix(subprocess): settle a Linux scope left active with no processes
Range observation waited for an active transient scope to leave `active`
before it would prove the managed range empty. systemd ends a scope only when
it observes the populated-to-empty transition, so a payload killed before the
manager placed it in the scope's cgroup leaves the unit active with an empty
cgroup forever. `waitForExit()` then polled a unit that could not change, and
`LocalSubprocessRuntime.disposeManagedProcesses()` awaited it without bound —
teardown hung for any command cancelled immediately after spawn.

Each state query now also reads the unit's process count. Once termination was
requested and the launcher has exited, a still-active unit reporting no
processes is the empty range: the launcher forked every process it will ever
fork, so nothing later joins that cgroup. The owner stops the leftover unit so
transient units cannot accumulate, and an unreported or `[not set]` count
stays unknown and keeps waiting.

The race needs a live user-systemd manager, so it stayed dormant wherever the
native scope path was unavailable and surfaced once CI routed lanes onto the
Blacksmith hosted image, whose runners accept that path. Ten repetitions of
`local.spec.ts > disposal kills still-running processes and awaits their exit`
in a Linux container with a user manager failed seven times before the change
and passed ten times after it.
2026-09-10 17:27:52 +08:00
Yichen Jiang 59c1ee7c82 test(web): retain historical Messages replay after provider consolidation 2026-09-10 17:27:32 +08:00
creatixchu 4b1408e1df Merge origin/master into worktree/3041-image-offload-log-design 2026-09-10 17:20:54 +08:00
Yichen Jiang 15dd4fa046 Merge remote-tracking branch 'origin/master' into worktree/llm-deepseek-messages 2026-09-10 17:20:22 +08:00
Yichen Jiang 6a137ea702 refactor(llm): unify DeepSeek protocol implementations 2026-09-10 17:19:51 +08:00
_Kerman 10029b995f feat(web): add compact details to recorded tool rows 2026-09-10 17:18:49 +08:00
_Kerman 0989a5cffc Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-3828 2026-09-10 17:17:09 +08:00
07akioni 42123ef019 fix(desktop): tighten parallel notarization checks 2026-09-10 17:12:45 +08:00
_Kerman 5a022a0db1 Merge latest origin/master into xtr/agent-setup-hook 2026-09-10 17:04:05 +08:00
_Kerman fd7ee32315 Merge origin/master into xtr/agent-setup-hook 2026-09-10 17:02:57 +08:00
07akioni ce94430e16 Merge master into fix/parallel-macos-notarization 2026-09-10 17:00:35 +08:00
imccyu 25d554d46e Merge pull request #3650 from deepseek-harness/worktree-feqatest
feat(test-support): whole-client test tier over an endpoint-named Remote mock
2026-09-10 16:58:13 +08:00
Yichen Jiang 218e7f815e Merge boot documentation correction into plugin management UI 2026-09-10 16:55:58 +08:00
Yichen Jiang 0746724e64 Merge boot documentation correction into scoped settings 2026-09-10 16:55:32 +08:00
Yichen Jiang 98338c8aa9 Merge boot documentation correction into plugin manager 2026-09-10 16:55:07 +08:00
_Kerman 8af1cb79f4 docs(core): update session start source event reference 2026-09-10 16:54:52 +08:00
07akioni 6fc0064b70 Merge pull request #3914 from deepseek-harness/fix/bundle-speed
perf(desktop): 优化运行时打包、启动及错误恢复
2026-09-10 16:54:32 +08:00
Yichen Jiang 8bdd47366f docs: refresh module graph after manifest merge 2026-09-10 16:54:16 +08:00
lsdsjy 9b330b653f docs(headless): correct the adopt-only wording and lockfile attribution
Address the ds-review-bot suggestions on 4099b84ee8:

- The post-resume comment scopes the write lease to other processes, so it no
  longer contradicts the post-idle re-check that defends against a same-process
  overlay writer.
- The Agent Note attributes `pnpm-lock.yaml` to the new
  `@deepseek-ai/dsh-session-query` workspace link instead of the shared chunk,
  which `scripts/check-workspace-constraints.ts` and the manifest publish.
- The package summary keeps "leaves nothing running behind", so it does not
  imply the runner leaves no persisted Session behind.
2026-09-10 16:52:43 +08:00
creatixchu 31f731cc6f Merge remote-tracking branch 'origin/master' into codex/pr-3440-resync-20260908
# Conflicts:
#	docs/subsystems/llm-streaming.i18n.yaml
#	docs/subsystems/llm-streaming.md
#	docs/subsystems/llm-streaming.zh.md
#	packages/llm/llm-deepseek/README.i18n.yaml
#	packages/llm/llm-deepseek/README.md
#	packages/llm/llm-deepseek/README.zh.md
#	packages/llm/llm-deepseek/src/request-pricing.ts
#	packages/llm/llm-deepseek/tests/request-pricing.spec.ts
2026-09-10 16:52:18 +08:00
turtle1999 5a88e5c4b9 docs(ci): state the full admitted failure class for the dockkit exemption
The package README and the Agent Note named an extension or error code but
omitted the unrelated-message case the classifier also rejects, and the note
loosened "Node's unknown-`.css`-extension refusal" to any non-`.css` failure.
2026-09-10 16:50:43 +08:00
Yichen Jiang 650d5f1478 Merge manifest-compatible scoped settings into plugin management UI 2026-09-10 16:50:07 +08:00
creatixchu b5e7fca4a5 feat(compaction): record image offload decisions without message replacement 2026-09-10 16:47:50 +08:00
creatixchu ba30b73f7b refactor(attachment): 求解器留在 llm-deepseek,存储层只接收目标尺寸
ImageRequestPolicy 改为 ImageRequestTarget,只含目标宽、高和字节目标;dsh-attachment 删除 token-grid 投影联合和 tokenGridProjection,只保留提供方无关的 requestImageDimensions 与 longEdgeDimensions。v41 求解器回到 llm-deepseek 的 image-tokens.ts,新增 deepSeekRequestImageDimensions,resolveRequestImageTarget 为每张图算出目标并加 4096 单边上限;pi-ai 路由按自身像素预算推导目标。

按 review 意见修正:v41 计价 Note 里已删除常量的过期句子就地改写;ProjectedDimensions 登记到 attachment 子系统页与 type-equiv 清单;Note 区分发送尺寸与提供方补齐后的网格;短边取整的措辞改为「按路由预测」。
2026-09-10 16:46:28 +08:00
_Kerman 632d42ee11 Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-3828 2026-09-10 16:42:45 +08:00
lsdsjy ef34e9d888 Merge remote-tracking branch 'origin/master' into turtle/issue-3848-headless-machine-readable-run 2026-09-10 16:42:31 +08:00
Yichen Jiang be8550c4c7 Merge manifest-compatible plugin manager into scoped settings 2026-09-10 16:40:27 +08:00
Yichen Jiang b12febec56 Merge manifest-compatible boot layer into plugin manager 2026-09-10 16:36:04 +08:00
imccyu f74ca1e266 fix(remote-mock): abort stream handle on consumer return 2026-09-10 16:34:32 +08:00
imccyu 4ffc774e5c test(settings): exercise settings through the whole-client fixture 2026-09-10 16:34:31 +08:00
imccyu d58c5455dd test(api): migrate Session and Workspace specs to assembled clients 2026-09-10 16:34:30 +08:00
imccyu 627c0f741e feat(test-support): assemble real clients with native test fixtures 2026-09-10 16:34:29 +08:00
imccyu 48d83eca66 refactor(client): share boot and transport integration points 2026-09-10 16:34:28 +08:00
imccyu 3d6fa12a6d feat(remote-mock): expose typed native mocks and controlled streams 2026-09-10 16:34:27 +08:00
imccyu 0718711886 docs(testing): define the native-mock client assembly tier 2026-09-10 16:34:27 +08:00
CreatixChu 8f85739d7b Merge pull request #3745 from deepseek-harness/worktree/composer-plus-menu
optimize: inputbar slash group and locale
2026-09-10 16:31:39 +08:00
turtle1999 529434e1df fix(ci): admit any .css refusal for the dockkit corpus exemption
The built-bundle import sweep pinned the Dockkit exemption to
`packages/client/ui-dockkit/lib/components/dockkit.module.css`, but the built
bundle imports `@deepseek-ai/dsh-client-ui-primitives` before its own
stylesheet, and the tsx launcher resolves that specifier through tsconfig
`paths` into the dependency's `src` tree. The sweep therefore reports
`packages/client/ui-primitives/src/StateDot.module.css`, so the pinned path can
never match where client build output exists; the Windows complete-gate
inventory reports the exempt bundle as an unexpected baseline failure.

Admit Node's unknown-`.css`-extension refusal for any stylesheet and keep every
other failure a finding. The classification controls cover an admitted Dockkit
stylesheet, the dependency's source stylesheet, another extension, an arbitrary
message, another error code, and a stale exemption.

Agent Note: .agents/notes/implemented/bug-fix/2026-09-10-built-bundle-css-exemption.md
2026-09-10 16:28:45 +08:00
lsdsjy 31be030ccc fix(headless): keep --json stderr free of commander's error print
Address the ds-review-bot findings on 8724223621:

- The JSON error override throws commander's control-flow error instead of
  delegating to `program.error`, whose own printer wrote an unprefixed
  `error: …` line to stderr and broke the documented `--json` contract.
- Cover the post-idle adoptability re-check with a focused case: an overlay that
  appends a preset while the runner awaits idle is still rejected, and the stale
  "live Session" comment now names that residual writer.
- Scope the Agent Note change sentence to the product change so it no longer
  claims the whole patch is confined to one package.
2026-09-10 16:25:19 +08:00
Yichen Jiang fcb3882e28 fix(boot): adapt plugin manifests to public package metadata 2026-09-10 16:24:00 +08:00
_Kerman 0600fa405b test(sdk): reuse serial creation header snapshots 2026-09-10 16:18:32 +08:00
_Kerman efa5294c00 test(agent-loop): drop duplicate creation disposal case 2026-09-10 16:18:25 +08:00
_Kerman 11656ca683 refactor(agent): keep registry registration startup-only 2026-09-10 16:18:04 +08:00
07akioni ae7462c526 test: clarify live SDK smoke completion acknowledgement 2026-09-10 16:13:54 +08:00
lsdsjy f63fdd89f4 Merge pull request #3889 from deepseek-harness/turn-duration-hours-unit
feat(web): add hours to turn duration labels
2026-09-10 16:12:36 +08:00
creatixchu e17a736cc3 docs: 同步请求图片投影文档与 Agent Note
更新 attachment、attachment-local、llm-deepseek 的 README,附件与 LLM 流式子系统文档,配置目录,type-equiv 清单,以及双语配对记录;新增请求图片投影的 Agent Note,并修正 v41 计价 Note 里关于 640,000 像素预算的说明。
2026-09-10 16:09:20 +08:00
creatixchu 06c491508f fix(llm-deepseek): 请求图片按 V4.1 token 网格投影
ImageRequestPolicy 改为投影规则加可选单边上限加字节目标,投影是 pixel-budget 或 token-grid 的封闭联合。token 网格求解器放在 dsh-attachment 的 request-projection 里,deepSeekImageTokens 复用同一个求解器计价。DeepSeek 路由默认按 14 px patch、3:1 降采样、1024 token 上限的网格投影,每张请求图片加 4096 像素单边上限,字节目标提高到 2 MiB;显式 imagePixelBudget 与 pi-ai 路由仍走总像素预算。缩放只按长边给定,短边由编码器四舍五入,与投影预测一致。变换版本升到 request-image-v6。

Closes #3929
2026-09-10 16:09:18 +08:00
Dudu-0223 b799912e48 Merge remote-tracking branch 'origin/master' into fix/team-identity-context 2026-09-10 16:04:04 +08:00
Dudu-0223 4491da1374 fix(agent-team): include identity only in the initial task 2026-09-10 16:03:49 +08:00
lsdsjy 9098a58f94 refactor(loader-smoke): model the smoke cwd as a discriminated input
Address the review suggestion that a caller-provided `cwd` left
`tempDirPrefix`/`tempDirParent` as dead but still-required inputs. The options
are now a union of "expand a prefix into a fresh temporary cwd" and "reuse this
existing directory", so the type system rejects passing both; the two callers
that reuse a directory drop their unused prefix.
2026-09-10 16:03:46 +08:00
lsdsjy 8d56babe15 Merge remote-tracking branch 'origin/master' into turtle/issue-3848-headless-machine-readable-run 2026-09-10 16:01:12 +08:00
lsdsjy 9bcb1e214c fix(headless): refuse a live Agent identity and finish the adopt-only docs
Address the ds-review-bot findings on 472554a29e:

- resolveAgent refuses an Agent already live under the requested id: its owner
  may still drive it, and `whenIdle` is not a single-message signal, so the
  one-shot runner cannot own an exclusive run interval over it. The adoptability
  rules still run first so the refusal stays specific.
- Refresh the README intro, identity section, and limitations, and the Agent
  Note live-identity rule and change scope, for adopt-only.
- Clarify the loader-smoke `cwd` JSDoc (the prefix/parent inputs are ignored)
  and pin the resumed wake's final text in the two-wake e2e.
2026-09-10 16:00:53 +08:00
creatixchu d0ba1a3c6c Merge remote-tracking branch 'origin/master' into worktree/composer-plus-menu 2026-09-10 16:00:13 +08:00
creatixchu 7910cd9e0b test(web): assert the shipped feedback command identity 2026-09-10 16:00:08 +08:00
Turtle ac495c0b5f Merge pull request #3934 from deepseek-harness/turtle/fix-weighted-approval-run-identity
fix(ci): refresh weighted approvals after numbered review runs
2026-09-10 15:58:39 +08:00
turtle1999 e7b8ebedaf fix(ci): identify approval review runs by workflow path 2026-09-10 15:55:00 +08:00
Dudu-0223 6e94ee4fb9 test(workspace): pin persisted mode ordering in Web replay 2026-09-10 15:54:57 +08:00
_Kerman c428e6ffb4 Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-3828 2026-09-10 15:54:56 +08:00
lsdsjy f0724ba7e8 Merge remote-tracking branch 'origin/master' into turtle/issue-3848-headless-machine-readable-run 2026-09-10 15:54:21 +08:00
lsdsjy 249d583892 feat(web): add hours to turn duration labels
Turns running at or past 3600s now read 1小时05分03秒 / 1h 05m 03s in the
running clock, the settled Ran-for footer, and the turn-time dialog, which
share formatRunDuration. Below an hour the second and minute branches are
unchanged, and the hour rolls at the unit boundary so 60分00秒 never appears.
2026-09-10 15:51:43 +08:00
Dudu-0223 8423b270e3 fix(workspace): derive recency independently of manual order 2026-09-10 15:51:42 +08:00
_Kerman c09574fc5f Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-3828 2026-09-10 15:51:42 +08:00
07akioni 9f27a45408 test: preserve immediate disposal and observe automatic terminal cleanup 2026-09-10 15:49:57 +08:00
creatixchu aed83d29ba Merge remote-tracking branch 'origin/master' into worktree/composer-plus-menu 2026-09-10 15:49:55 +08:00
creatixchu fff1ed7aa2 fix(plan): keep command identity independent of optional runtime 2026-09-10 15:48:25 +08:00
c31ac4fdfe feat(web): gate agent preset selection behind a setting (#3870)
* feat(web): gate agent preset selection behind a setting

* refactor(web): trim preset visibility diff

* refactor(web): simplify agent preset selection policy

* test(web): cover agent preset policy branches

* refactor(web): tighten agent preset policy flow

* fix(web): preserve preset default across picker toggle

* docs(web): align agent preset picker docs with the blank-task sync

Both picker transitions carry the effective default to the current blank task; started and historical sessions keep their labels, compositions, and recorded history. The Host README states the client rule and links the Web switch; the Agent Note English side matches the Chinese at line 64. Three i18n pairs re-recorded; doc-sync 34/34.

* refactor(web): simplify agent preset picker policy

* test(web): cover preset policy recovery

* docs(web): clarify disabled preset default copy

* fix(web): reconcile preset policy races

* fix(web): satisfy preset load lint

* fix(web): serialize preset roster refreshes

* fix(web): release preset refresh before notifying waiters

---------

Co-authored-by: ZiyaZhang <[email protected]>
Co-authored-by: Chinesezjc <[email protected]>
2026-09-10 07:48:06 +00:00
creatixchu 81d017bbaa docs: align generated catalog source links in both locales 2026-09-10 15:47:17 +08:00
creatixchu ca827aa2ad fix(commands): refresh catalogs and use type-only export identity 2026-09-10 15:44:30 +08:00
creatixchu 07413c2cc2 Merge remote-tracking branch 'origin/master' into worktree/composer-plus-menu 2026-09-10 15:38:30 +08:00
creatixchu 996278e6ce refactor: separate command identity and composer file action ownership 2026-09-10 15:38:13 +08:00
lsdsjy 349a84e81d Merge remote-tracking branch 'origin/master' into turtle/issue-3848-headless-machine-readable-run 2026-09-10 15:31:53 +08:00
turtle1999 d76704170b refactor(home-paths): simplify cache path dispatch 2026-09-10 15:24:27 +08:00
CreatixChu 646c4c2f33 Merge pull request #3924 from deepseek-harness/worktree/image-token-v41
fix(llm-deepseek): 图片 token 预估器改用官方计算器 v41 配置
2026-09-10 15:22:37 +08:00
lsdsjy 127d2c8eb5 fix(headless): align the adopt-only docs and prove resume end to end
Address the ds-review-bot findings on 9aea4b0804:

- Drop the stale "freshly created" wording from the resolveAgent `@returns`
  and rewrite its leading comment for the two remaining identity paths.
- Rewrite the README run-flow paragraph (EN and ZH), the intro sentence, and
  the cordis.patch.yml header comment for adopt-only.
- Add a real-composition two-wake e2e: capture the generated id from the first
  `--json` wake, resume it by `--session-id`, and assert one persisted log holds
  both tasks. `runLoaderSmoke` gains an optional caller-owned `cwd` so both
  wakes share one world; the harness leaves that directory in place.
2026-09-10 15:19:17 +08:00
turtle1999 3407d15bb3 Merge master into the Cordis revert branch 2026-09-10 15:18:28 +08:00
creatixchu ba2a931a23 Merge remote-tracking branch 'origin/master' into worktree/composer-plus-menu 2026-09-10 15:18:02 +08:00
turtle1999 7f005e2c0f test(attachment-local): isolate fallback cache home 2026-09-10 15:17:35 +08:00
07akioni 6becec9502 Merge master and retain its strict Linux startup cancellation handling 2026-09-10 15:13:38 +08:00
turtle1999 d911a7b422 feat(attachment-local): move request images into shared cache 2026-09-10 15:08:46 +08:00
07akioni 6d103f8f7c Revert Windows dialog smoke acceptance of unavailable COM classes 2026-09-10 15:08:38 +08:00
Yichen Jiang 61b02efa84 Merge pull request #3916 from deepseek-harness/worktree/fix-deliverable-sidebar-preview
fix(web): preview delivered file links in the sidebar
2026-09-10 15:06:09 +08:00
07akioni d570f32f32 Merge latest master into fix/bundle-speed 2026-09-10 15:03:23 +08:00
Yichen Jiang 8d1e8acdec Merge pull request #3917 from deepseek-harness/worktree/composer-reference-previews
feat(web): preview file and skill references in the sidebar
2026-09-10 15:00:37 +08:00
Yichen Jiang b79a227cec fix(subprocess): preserve Linux cancellation before bootstrap consumption 2026-09-10 14:45:45 +08:00
lsdsjy ea84ad31b6 feat(headless): require --session-id to name an existing Session
`--session-id` now adopts only: an id with no stored Session fails before the
task runs instead of creating an empty history the caller believes it is
resuming. A first round omits the flag, and the runtime reports the minted
`session-<uuid>` identity in the opening `session` event, so a supervisor
persists it and names it on every later wake.

Updates the help text, the README pair, the Agent Note pair, the generated
config catalog, the unit suite, and the product-profile e2e.
2026-09-10 14:44:44 +08:00
creatixchu f657a3e87a Merge remote-tracking branch 'origin/master' into worktree/image-token-v41 2026-09-10 14:42:07 +08:00
creatixchu f24bc3c832 fix(llm-deepseek): correct image pricing documentation and edge-case evidence 2026-09-10 14:40:50 +08:00
07akioni a62fab00b7 test: distinguish unavailable Windows dialog classes in native smoke 2026-09-10 14:33:20 +08:00
07akioni 4c024cf252 fix: preserve early process cancellation and sample stream markers promptly 2026-09-10 14:28:18 +08:00
turtle1999 85df0e7632 docs(home-paths): align cache helper example 2026-09-10 14:24:44 +08:00
lsdsjy 25f95302fd Merge remote-tracking branch 'origin/master' into turtle/issue-3848-headless-machine-readable-run
# Conflicts:
#	packages/bundle/headless/README.i18n.yaml
#	packages/bundle/headless/README.zh.md
2026-09-10 14:20:35 +08:00
Yichen Jiang 24e63e4555 fix(web): handle pending and linked skill previews 2026-09-10 14:19:01 +08:00
turtle1999 e4e0e78dd2 feat(home-paths): add dshCachePath 2026-09-10 14:16:35 +08:00
Yichen Jiang 72e6329267 Merge branch 'worktree/jobs-api-review-3052' into worktree/jobs-api-review-3127
# Conflicts:
#	packages/api/session-controller/README.i18n.yaml
#	packages/api/session-controller/README.zh.md
#	packages/shell/bash-sandbox/README.i18n.yaml
#	packages/shell/bash-sandbox/README.zh.md
#	packages/shell/pwsh-local/README.i18n.yaml
#	packages/shell/pwsh-local/README.zh.md
#	packages/shell/pwsh-sandbox/README.i18n.yaml
#	packages/shell/pwsh-sandbox/README.zh.md
#	packages/shell/shell/README.i18n.yaml
#	packages/shell/shell/README.zh.md
#	packages/shell/tool-bash/README.i18n.yaml
#	packages/shell/tool-bash/README.zh.md
#	packages/workflow/tool-workflow/README.i18n.yaml
#	packages/workflow/tool-workflow/README.zh.md
2026-09-10 14:09:55 +08:00
07akioni 82293ff45d refactor(desktop): remove unused plugin classification query 2026-09-10 14:07:51 +08:00
Yichen Jiang 1bd194ac17 Merge remote-tracking branch 'origin/master' into worktree/jobs-api-review-3052
# Conflicts:
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	packages/api/README.i18n.yaml
#	packages/api/README.zh.md
#	packages/api/remotes/src/client/index.ts
#	packages/api/session-controller/README.i18n.yaml
#	packages/api/session-controller/README.zh.md
#	packages/client/README.i18n.yaml
#	packages/client/README.zh.md
#	packages/client/ui-jobs/README.i18n.yaml
#	packages/client/ui-jobs/README.md
#	packages/client/ui-jobs/README.zh.md
#	packages/client/ui-jobs/package.json
#	packages/jobs/jobs-local/README.i18n.yaml
#	packages/jobs/jobs-local/README.md
#	packages/jobs/jobs-local/README.zh.md
#	packages/jobs/jobs/README.i18n.yaml
#	packages/jobs/jobs/README.md
#	packages/jobs/jobs/README.zh.md
#	packages/jobs/tool-jobs/README.i18n.yaml
#	packages/jobs/tool-jobs/README.zh.md
#	packages/shell/bash-local/README.i18n.yaml
#	packages/shell/bash-local/README.zh.md
#	packages/shell/pwsh-local/README.i18n.yaml
#	packages/shell/pwsh-local/README.zh.md
#	packages/shell/shell/README.i18n.yaml
#	packages/shell/shell/README.zh.md
#	packages/shell/tool-pwsh/README.i18n.yaml
#	packages/shell/tool-pwsh/README.zh.md
2026-09-10 14:06:59 +08:00
07akioni d55b2b3dad fix(desktop): make startup recovery and package rebuilds retryable 2026-09-10 14:05:44 +08:00
creatixchu a64dc3a690 fix(llm-deepseek): 图片 token 预估器改用官方计算器 v41 配置
DeepSeek 图像理解指南改为 544×544 放大下限、约 1300×1300 缩小目标、
单图 1024 token 上限;官方图片 Token 计算器以 v41 配置承载该规则。
重写 image-tokens.ts 为 v41 的逐句移植:取消对齐 pad、宽高比钳制和
奇偶校正网格布局,估算值从最坏情况上界变为精确值。测试向量按官方
计算器重新固定,request-pricing 期望值、README 与 Agent Note 同步更新。
2026-09-10 14:05:04 +08:00
Yichen Jiang 5445ad16eb test(web): update file link gallery preview label 2026-09-10 14:01:01 +08:00
Chinesezjc 40606d1558 Merge pull request #3873 from deepseek-harness/ci/failover-canary-leg
ci: opt-in canary runner leg for the CI pool failover switches
2026-09-10 13:59:53 +08:00
Yichen Jiang 6469b522c1 Merge pull request #3899 from deepseek-harness/worktree/manifest-plugin-metadata
feat(manifest): separate package metadata from DSH declarations
2026-09-10 13:55:51 +08:00
creatixchu 6fe445ea08 Merge origin/master into worktree/composer-plus-menu 2026-09-10 13:53:45 +08:00
07akioni 13fc0a60ec Merge remote-tracking branch 'origin/master' into fix/bundle-speed 2026-09-10 13:53:29 +08:00
creatixchu 1faab27329 Merge origin/master into PR #3440 2026-09-10 13:48:38 +08:00
Yichen Jiang 71046d8306 fix(web): unify inline file preview labels 2026-09-10 13:41:18 +08:00
Yichen Jiang ce7ceb6071 refactor(manifest): remove discovery categories 2026-09-10 13:38:36 +08:00
turtle1999 2376d210bd Preserve nested plugin errors after Cordis revert 2026-09-10 13:36:05 +08:00
Yichen Jiang 4115e8867b test(web): update SVG delivery sidebar snapshot 2026-09-10 13:31:36 +08:00
Yichen Jiang ff153dfb12 Merge remote-tracking branch 'origin/master' into worktree/fix-deliverable-sidebar-preview 2026-09-10 13:29:38 +08:00
turtle1999 a38c302e4a Merge master and resolve revert documentation conflicts 2026-09-10 13:09:19 +08:00
Dudu-0223 d769e2d157 docs(agent-team): regenerate the message dependency graph 2026-09-10 12:50:23 +08:00
Dudu-0223 271268a440 test(agent-team): avoid racing initial admission settlement 2026-09-10 12:46:05 +08:00
Dudu-0223 f0201f73a1 Merge master into fix/team-identity-context 2026-09-10 12:44:29 +08:00
Dudu-0223 b76fe343fe fix(agent-team): keep member identity in durable reminders 2026-09-10 12:42:44 +08:00
Tianyi Cui aa8262ec09 Merge pull request #3920 from deepseek-harness/feat/add-readme-citation
docs: add BibTeX citation to READMEs
2026-09-10 12:34:48 +08:00
07akioni dcec949f33 fix(python): allow workspace-only patches during runtime deploy 2026-09-10 11:50:46 +08:00
Yichen Jiang 597f0f8f1f fix(web): align composer reference heights and baselines 2026-09-10 11:50:41 +08:00
fz 81239767a7 docs: add BibTeX citation to READMEs 2026-09-10 11:49:17 +08:00
07akioni 710d7b5c33 Merge latest fix/bundle-speed and resolve desktop documentation conflicts 2026-09-10 11:37:57 +08:00
Yichen Jiang 081e054c54 Merge remote-tracking branch 'origin/master' into worktree/manifest-plugin-metadata
# Conflicts:
#	packages/boot/app-boot/README.i18n.yaml
#	packages/boot/app-boot/README.zh.md
2026-09-10 11:35:22 +08:00
Yichen Jiang 11d6bd05f3 feat(web): preview file and skill references in the sidebar 2026-09-10 11:31:27 +08:00
07akioni 8ce9b21ea9 Merge master into fix/bundle-speed and preserve desktop runtime changes 2026-09-10 11:25:04 +08:00
_Kerman f570a9d8c6 Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-3869
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	packages/core/system-prompt/README.i18n.yaml
#	packages/core/system-prompt/README.zh.md
#	packages/core/tools/README.i18n.yaml
2026-09-10 11:19:40 +08:00
_Kerman b511cd6c2d Merge origin/master into xtr/trajectory-json-string-wrapping
Resolve the markdown-preview revert and README proofreading against this
PR's trajectory inspection work:

- CodeBlock keeps `showHeader` (the PTC code inspector supplies its own
  toolbar) on top of master's `contentRef` scrollport wrapper.
- ui-primitives README records both `contentRef` and `showHeader`.
- ui-trajectory README keeps master's proofread wording alongside this
  PR's PTC inspection and timing paragraphs.
- Re-record the README.i18n.yaml pairing hashes for the three merged pairs.
2026-09-10 11:19:39 +08:00
_Kerman eb0a666415 Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-3828
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/subsystems/session.i18n.yaml
#	packages/core/session/README.i18n.yaml
2026-09-10 11:19:25 +08:00
Yichen Jiang ca2a9017ef fix(web): preview delivered file links in the sidebar 2026-09-10 11:13:43 +08:00
07akioni 20374de37d Merge remote-tracking branch 'origin/fix/bundle-speed' into fix/parallel-macos-notarization 2026-09-10 11:03:18 +08:00
07akioni 7814ccdfd9 Merge fix/bundle-speed into fix/parallel-macos-notarization 2026-09-10 11:02:53 +08:00
Yichen Jiang 66e4f809d7 Merge remote-tracking branch 'origin/master' into worktree/llm-deepseek-messages 2026-09-10 10:59:10 +08:00
Yichen Jiang 80badab556 Merge remote-tracking branch 'origin/master' into worktree/web-sidebar-terminal
# Conflicts:
#	packages/api/README.i18n.yaml
#	packages/api/README.zh.md
#	packages/e2b/subprocess-e2b/README.i18n.yaml
#	packages/e2b/subprocess-e2b/README.zh.md
2026-09-10 10:52:51 +08:00
Tianyi Cui 2377c272a8 Merge pull request #3908 from deepseek-harness/docs/readme-bilingual-proofread-20260909
docs(i18n): proofread bilingual README corpus
2026-09-10 10:50:25 +08:00
Yichen Jiang 12d3be3514 Merge remote-tracking branch 'origin/master' into worktree/web-sidebar-terminal
# Conflicts:
#	packages/client/ui-sidebar-right/README.i18n.yaml
#	packages/client/ui-sidebar-right/README.md
#	packages/client/ui-sidebar-right/README.zh.md
2026-09-10 10:48:47 +08:00
j-xiang 4ddf777ad8 Merge master into README proofreading branch 2026-09-10 10:42:13 +08:00
Yichen Jiang 4af56cf808 feat(llm): sync V41 Messages catalog and keep Web on Chat Completions 2026-09-10 10:32:04 +08:00
Yichen Jiang 5c82aa9371 refactor(manifest): separate package metadata from public DSH fields 2026-09-10 10:28:47 +08:00
Yichen Jiang 61176bf7c6 Merge remote-tracking branch 'origin/master' into worktree/llm-deepseek-messages
# Conflicts:
#	apps/web/tests/scaffold.ts
2026-09-10 10:25:39 +08:00
imccyu 183f08e9c6 Merge pull request #3912 from deepseek-harness/worktree/release/dsh-0.1.5-rc.1
release: [email protected]
2026-09-10 09:36:48 +08:00
imccyu 1ef9c1fa9a release(dsh): 0.1.5-rc.1 2026-09-10 09:13:14 +08:00
imccyu ecc6f11cf1 Merge pull request #3824 from deepseek-harness/worktree/deepseek-flash-catalog
feat(llm): add V41 Flash alongside V4 models
2026-09-10 09:13:00 +08:00
Yichen Jiang 0729dbec66 feat(llm): restore V4 Flash Vision Exp catalog entry 2026-09-10 03:39:57 +08:00
Yichen Jiang 441385fe38 feat(llm): retain V4 models alongside V41 Flash 2026-09-10 03:39:57 +08:00
Yichen Jiang c98fe6ecdd test(web): pin the recorded model before scenario overlays 2026-09-10 03:39:57 +08:00
Yichen Jiang 719331ecb7 test: keep webhook smoke on the shipped model route 2026-09-10 03:39:56 +08:00
Yichen Jiang 61c5954372 test: pin model routes in webhook and Cordis fixtures 2026-09-10 03:39:56 +08:00
Yichen Jiang bc5fd3b8dc feat(llm): default Chat Completions to DeepSeek V41 Flash 2026-09-10 03:39:56 +08:00
imccyu 4cbaeb8d69 Merge pull request #3909 from deepseek-harness/fix/sidebar-preview-layout-polish
fix(client): refine sidebar previews, guide, and stats
2026-09-10 03:38:01 +08:00
imccyu 3435dbd690 fix(web): address sidebar and stats review feedback 2026-09-10 03:20:55 +08:00
j-xiang e14b8795a9 docs(i18n): fix targeted README review findings 2026-09-10 03:04:19 +08:00
imccyu 57da0906f3 Merge remote-tracking branch 'refs/remotes/origin/pr-3910' into fix/sidebar-preview-layout-polish 2026-09-10 02:04:17 +08:00
j-xiang 267e8b933b docs(i18n): address README review feedback 2026-09-10 02:03:18 +08:00
imccyu ded26f225d chore(client): refresh slot catalog 2026-09-10 01:57:14 +08:00
imccyu 19b3c4c34b fix(client): keep preview scrollports current 2026-09-10 01:51:21 +08:00
j-xiang 89743f33b2 docs(i18n): polish reviewed README terminology 2026-09-10 01:42:58 +08:00
Yif 53d5c9386e fix(sidebar): pin the guide hero to the pure-gray ramp
The label-dimmed alias rides the bluish neutral ramp, whose cast shows
at the 56px compass; the hero now takes neutral-200 (light) and
neutral-700 (dark) from the pure-gray static ramp.
2026-09-10 01:32:45 +08:00
j-xiang b5578ae46a Merge master into README proofreading branch 2026-09-10 01:29:37 +08:00
Yif 1c044f5140 feat(sidebar): refine guide start page and quiet stat pill noise
The guide tab gains a compass hero, per-entry descriptions (shown while
at most four entries are listed), and a quieter cube placeholder for
entries that registered no glyph; the files entry registers its
description and folder glyph. Bundled stat fixes: the session usage
dialog drops the zero cache-write row, and the turn-time pill renders as
plain text when its dialog would only repeat the pill's own duration.
2026-09-10 01:23:24 +08:00
imccyu 284ab15519 fix(client): refine sidebar document previews 2026-09-10 01:04:55 +08:00
j-xiang 8e8fb2fc62 docs(i18n): proofread bilingual README corpus 2026-09-10 00:21:32 +08:00
imccyu b2e3b2a012 Merge pull request #3893 from deepseek-harness/worktree/release/dsh-0.1.5-alpha.2
release: [email protected]
2026-09-09 22:13:03 +08:00
imccyu dd393c1820 release(dsh): 0.1.5-alpha.2 2026-09-09 22:02:09 +08:00
Tianyi Cui 7588e1ea11 Merge pull request #3901 from deepseek-harness/revert-3710-feat/mermaid-preview
Revert "feat(web): preview Mermaid, Graphviz, SVG, and HTML code fences"
2026-09-09 22:01:43 +08:00
Tianyi Cui 58956c1a8a Revert "feat(web): preview Mermaid, Graphviz, SVG, and HTML code fences" 2026-09-09 22:01:10 +08:00
07akioni d09b4accd3 feat: 打包 + 错误处理优化 2026-09-09 21:10:02 +08:00
lsdsjy a69933d3e5 fix(headless): omit step usage when any attempt lacks a sample
Address the ds-review-bot v12 critical on PR #3849: `addUsage` published the
sum of the attempts that reported usage while silently dropping the ones that
did not, so `step_end.usage` looked exact but under-counted billed tokens.
Track completeness per step and omit usage entirely when any attempt in the
step reports no sample, matching `deriveTurnTokenUsage`'s fail-closed rule.
2026-09-09 21:05:19 +08:00
Yichen Jiang 220678e57d feat(manifest): declare plugin format, tags, and host compatibility 2026-09-09 21:03:44 +08:00
lsdsjy 980b4b77af fix(headless): close the v11 review gaps in the json run surface
Address the ds-review-bot v11 review on PR #3849:

- Accumulate every attempt's usage into `step_end.usage`, including a retried
  attempt whose only sample sits in its discarded `assistant/attempt` stream.
- Re-check the adopted Session after the idle wait, so a preset selected in
  that window is still rejected.
- Reject a whitespace-only `sessionId` supplied through a Cordis overlay, which
  bypasses the CLI trim check.
- Narrow the documented error contract: a profile whose own plugins fail to
  load exits before the runner mounts and keeps only stderr diagnostics.
2026-09-09 20:46:16 +08:00
_Kerman 192cc03dc4 Merge origin/master and preserve PTC code inspector controls 2026-09-09 20:35:12 +08:00
Yudong Han 83253e0d16 Merge pull request #3710 from deepseek-harness/feat/mermaid-preview
feat(web): preview Mermaid, Graphviz, SVG, and HTML code fences
2026-09-09 20:24:43 +08:00
_Kerman 9087b275bf Merge remote-tracking branch 'origin/master' into HEAD 2026-09-09 20:22:14 +08:00
imccyu 9d83e3e534 Merge pull request #3890 from deepseek-harness/feat/sidebar-image-preview
feat(sidebar): preview image files
2026-09-09 20:17:43 +08:00
lsdsjy b3f6c5e991 fix(headless): count the line terminator inside the 32 KiB event cap
Address the ds-review-bot v10 review on PR #3849: `boundJsonLine` bounded the
serialized JSON but not the newline the writer appends, so an event that
serialized to exactly 32 KiB produced a 32 KiB + 1 byte record. Reserve the
terminator byte inside the cap, document the cap as newline-inclusive, and
assert the written record length in the boundary tests.
2026-09-09 20:16:58 +08:00
Chinesezjc 360354e38b Merge remote-tracking branch 'origin/master' into ci/failover-canary-leg 2026-09-09 20:04:23 +08:00
_Kerman 5e0e5d00a6 Merge remote-tracking branch 'origin/master' into HEAD 2026-09-09 20:02:08 +08:00
imccyu 8870a13aa9 feat(sidebar): preview image files 2026-09-09 20:01:24 +08:00
Tianyi Cui f05e0fb6b9 Merge pull request #3878 from deepseek-harness/fix/ci-cancel-superseded
fix(ci): cancel superseded PR and master validation
2026-09-09 20:00:13 +08:00
Yudong 7aa73877e6 Merge origin/master into feat/mermaid-preview 2026-09-09 19:53:42 +08:00
Yichen Jiang cfdfd7ccb9 Merge remote-tracking branch 'origin/master' into worktree/web-sidebar-terminal 2026-09-09 19:53:05 +08:00
lsdsjy 755b44bbcd fix(headless): require the query service for every --session-id run
Address the ds-review-bot v9 review on PR #3849:

- Require `sessionQuery` before the live fast path too: a later process has no
  live Agent and must find the id through the query service, so a live identity
  no longer bypasses the check.
- Soften the live `stat` comment to what it proves: a stored record rules out an
  in-memory registration, while write-handle ownership is not queryable.
- Complete the `parseArguments` JSDoc and fix the broken English sentence in
  README.md and the Agent Note.
2026-09-09 19:53:03 +08:00
Yichen Jiang d28625c6d5 fix(web): restore terminal snapshots across host and sidebar lifecycles 2026-09-09 19:52:55 +08:00
_Kerman 29c09d320f refactor(client): remove unused JSON disclosure locale keys 2026-09-09 19:52:42 +08:00
_Kerman b6858789f0 fix(trajectory): identify PTC calls from recorded tool metadata 2026-09-09 19:52:42 +08:00
_Kerman 2bc1a7e347 test(trajectory): pin thinking defaults when switching records 2026-09-09 19:52:42 +08:00
_Kerman e7fc4e8fdc fix(client): isolate JSON copy feedback and guard string measurement 2026-09-09 19:52:42 +08:00
_Kerman 573b044320 refactor(client): share the line wrapping icon 2026-09-09 19:52:42 +08:00
Yudong 516bfd5f30 test(web): cover preview import recovery and color schemes 2026-09-09 19:49:56 +08:00
_Kerman 0ed47fe860 fix(agent-loop): preserve standalone inbox registration 2026-09-09 19:49:12 +08:00
creatixchu 5b8c445eeb fix(snapshots): preserve released inline image fixture 2026-09-09 19:46:13 +08:00
lsdsjy 7a4a55f30b fix(headless): fail closed on malformed preset records and unroundtrippable args
Address the ds-review-bot v6 review on PR #3849:

- A persisted `agent-preset/selected` record whose `data.agentPreset` is not a
  non-empty string used to read as "no preset", letting the run continue under
  this bundle's composition. It now fails closed.
- A live identity now has to be known to `sessionPersistence` (`stat`), since
  an Agent registered only in memory has no write handle and would flush
  nothing.
- Tool arguments that JSON cannot round-trip (an overflowing number such as
  `1e400`) keep their raw text instead of the `null` JSON.stringify reports.
2026-09-09 19:39:31 +08:00
creatixchu 2025036158 Merge origin/master into PR #3440 2026-09-09 19:36:15 +08:00
_Kerman b11c94716f Merge remote-tracking branch 'origin/master' into HEAD 2026-09-09 19:25:21 +08:00
imccyu 16953f2b8e Merge pull request #3884 from deepseek-harness/feat/public-experimental-agent-team
release: publish experimental Agent Teams packages
2026-09-09 19:21:51 +08:00
imccyu fbfc8123e3 Merge pull request #3871 from deepseek-harness/worktree-fixworkerflock
fix(webworker): restore session and workspace writes
2026-09-09 19:21:07 +08:00
Chinesezjc acc8535390 docs(ci): record the canary failover value and the glob fix across internal notes
The failover runbook, the node-compatibility note, the native-Windows note,
and the serial-reference note record the third variable value's scope and
exclusions (bilingual, pairing re-recorded); a new implemented process note
owns the value's participating set, the dormant-by-default canary posture,
and the walker-fix rationale. .github/AGENTS.md points at both notes.
2026-09-09 19:20:29 +08:00
Chinesezjc d79294f23a fix(scripts): enumerate repo files with a dirent walker instead of node fs.glob
Node's internal fs.glob, from some 24.x releases, lstat-probes
<matched>/<next segment> while expanding a ** pattern over a symlinked
file and throws ENOTDIR instead of skipping (observed on node 24.13.0
scanning snapshots/acp/image-compaction's symlinked
system-prompt.expected.md, which failed verify-md-wrap inside
check:ci:static). uniqueRepoFiles now walks with dirent types, never
probing a path under a file, and mirrors fs.glob's dot:false and
follow:false semantics: the four repo-files gate pattern sets enumerate
identically. Broken or cyclic symlinks fail loudly in the caller's
realpathSync, and pattern forms the walker does not model (metacharacters,
a trailing **, empty segments) are rejected up front. repo-files.spec.ts
pins the symlink, broken-link, and rejection behavior.
2026-09-09 19:20:29 +08:00
07akioni fc7abdcfb5 feat: 优化 windows 安装包打包 2026-09-09 19:18:34 +08:00
lsdsjy a5c21a69b8 fix(headless): require persistence for every --session-id path
Address the ds-review-bot v6 review on PR #3849: the guard sat before the
create branch only, so adopting an already-live identity could still run a
session whose history dies at exit. Move it to the top of resolveAgent, where
it covers both the live and the create path, and add a rejection test for the
live path alongside the existing create-path one.
2026-09-09 19:17:01 +08:00
Yichen Jiang f030b544a9 Merge remote-tracking branch 'origin/master' into worktree/web-sidebar-terminal
# Conflicts:
#	packages/client/ui-sidebar-right/README.i18n.yaml
#	packages/client/ui-sidebar-right/README.md
#	packages/client/ui-sidebar-right/README.zh.md
2026-09-09 19:15:51 +08:00
Chinesezjc 9bae613128 ci: add an opt-in canary value to the CI pool failover switches
The per-platform failover repository variables (DSH_CI_FAILOVER_LINUX and
DSH_CI_FAILOVER_WINDOWS) accept a third value alongside the existing
selfhosted routing. Set by a repository writer, the value retargets the
always-on pull-request and master lanes onto the matching hosted-runner
labels (16-core pools map to the 16-vCPU tier, standard legs to 4-vCPU);
unset or any other value keeps today's runners, so the leg is dormant until
a writer opts in - a canary path for capacity fallback, never the default.

Participating jobs: the three enterprise Linux workers, the node-compat
legs, the four Windows lanes, and the all-checks-passed verdict in ci.yml;
expected-filenames; the sandbox bwrap leg; and the two manual benchmark
matrices (4-32 vCPU tiers map to equivalents; 64/96-core rows keep the
fleet labels). Everything pinned to its own runner by spec, credential, or
host capability keeps it under every value, and the release-shaped chains
stay entirely hosted. request-review.yml was retired on master while this
work was in flight and the branch takes the deletion.

Specs pin the new branches: ci-workflow.spec.ts asserts the labels appear
in the extended selectors, and ci-compatible-selfhosted.spec.ts evaluates
the routing mode.
2026-09-09 19:02:10 +08:00
lsdsjy 97e4565a04 Merge remote-tracking branch 'origin/master' into turtle/issue-3848-headless-machine-readable-run 2026-09-09 19:01:51 +08:00
lsdsjy b3756a89d1 fix(headless): fail loud when --session-id would create a non-durable session
Address the ds-review-bot v6 review on PR #3849:

- Require the composed sessionPersistence service before creating an exact
  --session-id identity, so a profile that keeps sessionQuery but drops
  persistence exits 1 instead of printing an id whose history dies at exit.
- Stop exporting the now-internal boundJsonEvent and describe it in the
  present tense; its test now exercises boundJsonLine.
- Say "64 levels or deeper" in the README and Agent Note, matching the
  depth budget (an input keeps 63 nested containers, the 64th is cut).

Tests: 77 headless unit tests with per-file 100% coverage on src, 14 profile
e2e tests, constraints/typecheck/lint/doc/pairing gates.
2026-09-09 19:00:06 +08:00
_Kerman af20a0f004 Merge remote-tracking branch 'origin/master' into HEAD
# Conflicts:
#	packages/client/ui-primitives/src/markdown/CodeBlock.tsx
2026-09-09 18:57:48 +08:00
imccyu 63187de80f release: publish experimental Agent Teams packages 2026-09-09 18:54:14 +08:00
imccyu 9b308c9568 Merge pull request #3819 from deepseek-harness/feat/artifact-file-actions
feat(web): unify file icons, delivery actions, and sidebar interactions
2026-09-09 18:51:34 +08:00
_Kerman a9b5faef0b test(chat): collapse live thinking before checking its tail 2026-09-09 18:49:03 +08:00
_Kerman 4da3102130 Merge remote-tracking branch 'origin/master' into HEAD 2026-09-09 18:48:34 +08:00
Ruilin Geng 2b521b31f1 Merge pull request #3846 from deepseek-harness/fix/mcp-pagination-cycles
fix(mcp): reject repeated tool discovery cursors
2026-09-09 18:46:44 +08:00
_Kerman 508490b531 test(trajectory): omit absent optional fixture fields 2026-09-09 18:35:07 +08:00
lsdsjy a6fa383ba8 Merge remote-tracking branch 'origin/master' into turtle/issue-3848-headless-machine-readable-run 2026-09-09 18:34:16 +08:00
_Kerman 9c6b282535 test(client): cover raw JSON strings and wrapping preferences 2026-09-09 18:34:12 +08:00
turtle1999 d225dbba50 Remove nonessential remnants of Cordis PR 932 2026-09-09 18:34:11 +08:00
_Kerman 5230c60525 test(trajectory): expect ordinal step detail titles 2026-09-09 18:34:11 +08:00
_Kerman a73aca1978 test(client): cover assistant thinking disclosure defaults 2026-09-09 18:34:11 +08:00
lsdsjy d2dc505830 ci: re-trigger the pull-request run after the superseded run was dropped 2026-09-09 18:28:34 +08:00
_Kerman 056ca664c8 Merge remote-tracking branch 'origin/master' into HEAD 2026-09-09 18:24:55 +08:00
creatixchu 0b3248e67d test(web): stabilize delivered-file snapshots across CI hosts 2026-09-09 18:21:45 +08:00
Yichen Jiang 6e945def2f Merge origin/master into worktree/web-sidebar-terminal 2026-09-09 18:21:21 +08:00
imccyu d7ecdcf02c fix(lint): parenthesize file handle callback 2026-09-09 18:21:17 +08:00
imccyu 60a3d0fbc2 fix(webworker): support file handle chmod 2026-09-09 18:21:17 +08:00
imccyu 950474605f docs(webworker): record file handle compatibility 2026-09-09 18:21:16 +08:00
imccyu a7bd71e024 fix(webworker): preserve bigint file handle identity 2026-09-09 18:21:16 +08:00
imccyu 0a9c774617 docs(webworker): document bigint handle identity 2026-09-09 18:21:16 +08:00
_Kerman f36e1a3d1d fix(trajectory): show turn and ordinal step in detail titles 2026-09-09 18:20:13 +08:00
Tianyi Cui 3c4c6c3d7b fix(ci): cancel superseded PR and master validation 2026-09-09 18:20:01 +08:00
_Kerman f0810edd7f fix(trajectory): expand preview thinking by default 2026-09-09 18:19:51 +08:00
Yichen Jiang 0a525601a7 fix(web): harden sidebar terminal lifecycle and recovery 2026-09-09 18:17:47 +08:00
gengruilin 556857bcd2 Merge origin/master into fix/mcp-pagination-cycles 2026-09-09 18:15:36 +08:00
_Kerman 632b8e19b4 feat(trajectory): add a PTC code inspector 2026-09-09 18:15:09 +08:00
creatixchu b53fed39d7 Merge remote-tracking branch 'origin/master' into worktree/pr-3819-release-sync 2026-09-09 18:07:26 +08:00
creatixchu b9587ada12 fix(web): open delivered files using the viewed session scope 2026-09-09 18:07:16 +08:00
lsdsjy 3488db77bf fix(headless): cap the bounding recursion depth and route error events through the line cap
Address the ds-review-bot v6 review on PR #3849:

- Cut a projected payload nested deeper than 64 levels instead of recursing
  until the stack overflows; the isolated session listener would otherwise
  drop the `tool_call` silently.
- Write both `error` events (startup usage errors and runner failures) through
  `boundJsonLine`, so the documented 32 KiB line cap covers JSON-escaping
  expansion as well as the 8 KiB message cap.

Tests: 76 headless unit tests with per-file 100% coverage on src, 14 profile
e2e tests, constraints/typecheck/lint/doc/pairing gates.
2026-09-09 18:06:29 +08:00
Tianyi Cui 8803287f71 Merge pull request #3853 from deepseek-harness/fix/3835-tool-guidance-restrictions
fix: respect scoped tools in filesystem and web guidance
2026-09-09 18:04:11 +08:00
yudshj 4e0a405a9b fix(web): size diagram previews to image content 2026-09-09 18:01:36 +08:00
creatixchu 2ab73152ae Merge remote-tracking branch 'origin/master' into worktree/pr-3819-release-sync 2026-09-09 18:01:07 +08:00
creatixchu 7f69a3ec37 fix(web): complete shared file icon consumers and browser checks 2026-09-09 18:01:04 +08:00
creatixchu 43bf1d3f93 Merge remote-tracking branch 'origin/master' into worktree/pr-3819-release-sync 2026-09-09 17:56:14 +08:00
creatixchu 454caf0280 fix(web): reject empty sidebar splits and clarify page targeting 2026-09-09 17:56:11 +08:00
imccyu bd60582403 Merge pull request #3859 from deepseek-harness/worktree-sidebarsubagent
fix(workspace-files): support subagent session roots
2026-09-09 17:55:17 +08:00
_Kerman 28548ba1c7 Merge remote-tracking branch 'origin/master' into xtr/durable-inbox-web-recovery 2026-09-09 17:51:55 +08:00
creatixchu 9961eedec8 fix(web): preserve office file icons and lazy sidebar replay 2026-09-09 17:48:47 +08:00
Tianyi Cui cd95dda1bd Merge pull request #3866 from deepseek-harness/docs/session-format-authority
docs(session): centralize format status and timeless guidance
2026-09-09 17:46:17 +08:00
lsdsjy 0ca42f3b78 fix(headless): bound whole events, re-check adoption after resume, tighten --json scan
Address the ds-review-bot v5/v6 review on PR #3849:

- Register the shared `lib/json-stream-*.js` chunk in `packageFileExtras` and
  order `files` as the workspace-constraints gate requires, so
  `pnpm run constraints` passes.
- Re-validate the preset on the Session `agents.resume` actually attached,
  closing the TOCTOU window between `observeSession` and the write lease.
- Bound one serialized event line at 32 KiB: an over-long event keeps its
  scalar fields, drops structured ones, and at the extreme reduces to `type`.
- Normalize an empty tool-argument string to `{}`, matching the executor.
- Scan only real `--json` flags (stop at `--`, skip a `--session-id` value)
  before installing the JSON error override.

Tests: 74 headless unit tests with per-file 100% coverage on src, 14 profile
e2e tests, constraints/typecheck/lint/doc/pairing gates, tarball import smoke.
2026-09-09 17:40:47 +08:00
_Kerman 813ad965f9 fix(web): preserve newer projections across control baselines 2026-09-09 17:39:26 +08:00
HYD@OVERTON 9e050260e4 feat(web): adapt diagram previews to application theme 2026-09-09 17:39:04 +08:00
yudshj fb84576ea7 refactor(web): unify markdown preview components and notes 2026-09-09 17:39:04 +08:00
yudshj a8f9d81f3a feat(client): preview Graphviz, SVG, and HTML Markdown fences 2026-09-09 17:39:04 +08:00
fz 4fabbd39c5 test(web): scope Mermaid snapshots to diagram content 2026-09-09 17:39:04 +08:00
fz 0bfd594875 refactor(ui): use tagged Mermaid preview results 2026-09-09 17:39:04 +08:00
fz 220103670a fix(ui): retain Mermaid previews and support hybrid touch controls 2026-09-09 17:39:04 +08:00
fz fc0c885287 style(ui): simplify Mermaid preview controls 2026-09-09 17:39:04 +08:00
fz ee35e40bc8 feat(ui): preview Mermaid diagrams in Chat code blocks 2026-09-09 17:39:04 +08:00
_Kerman 3a32c617a3 feat(trajectory): remember JSON string wrapping preference 2026-09-09 17:38:02 +08:00
creatixchu 7c9b29563d Merge branch 'worktree/pr-3872-release-sync' into worktree/pr-3819-release-sync 2026-09-09 17:34:20 +08:00
creatixchu c6b3900d2a Merge remote-tracking branch 'origin/master' into worktree/pr-3872-release-sync 2026-09-09 17:33:47 +08:00
turtle1999 2abb542a22 Adapt current consumers to nontransactional Cordis Loader
Move exact user-patch watching into app boot and audit activation explicitly.
Wait for CLI fallback HMR and preset subtrees. Join the first fiber-disposal
result in the directory chooser and browser package runner. Keep async
update errors observable without restoring generic Loader rollback.

Restore the current workspace-link and Schemastery manifests and their gate.
Preserve unconditional patch-input cloning, awaited Include initialization,
and durable teardown writes. Update diagnostics, snapshots, bilingual docs,
and the exhaustive vendor divergence ledger.

Validation: focused Loader, watcher, preset, inventory, and cleanup tests;
100% watcher coverage; 32 Web preset cases; real CLI webhook model session;
SDK smokes; 13 headless expected cases; 3 recorded-session replays; build,
typecheck, lint contracts, and all 34 doc-sync gates.

A full Node 24/Python 3.12 Vitest run had 21806 passes and two failures:
a baseline-reproduced experimental CSS import failure and a Python probe
timeout that passed alone. The default Node 26/Python 3.9 run additionally
exposed unsupported Python and FileHandle-GC host failures.
2026-09-09 17:33:32 +08:00
turtle1999 e07f41d5fd Revert #932 transactional Cordis reload changes
Apply real git revert --no-commit operations in reverse order:

acb0797a1421eab128a4bd03355e930c1a221fb0
 af97714f2413a3e55f0f15ab1b283beb133b3f2d
2018b0b7e64b444bff82b62c9466f13adc4603bb
43170c027cfbf9155dad7a43c01ca39364d4aef2
a621e927d6b3763798c3929e28912d86c9576f2d

Resolve the app-boot package move, preserve deleted files and frozen archived
notes, retain the modern lockfile graph, and preserve independent later
lifecycle and lazy-config changes. Do not revert 6ac7d72d: that merge also
contains eight unrelated commits from the #936 dependency chain.

This is the mechanical intermediate result. Its focused check exposed
consumer and packaging incompatibilities. The following compatibility
commit supplies those adaptations and reconciles the vendor ledger.
2026-09-09 17:32:09 +08:00
_Kerman 2f7a02022a Merge origin/master into xtr/agent-setup-hook 2026-09-09 17:31:17 +08:00
imccyu d7dcc5f5af test(web): update sidebar preview expectations 2026-09-09 17:29:38 +08:00
imccyu 177eacbe8b docs(workspace-files): clarify session scope behavior 2026-09-09 17:29:38 +08:00
imccyu c5432b94f9 chore: satisfy workspace files CI gates 2026-09-09 17:29:38 +08:00
imccyu 7214a97723 fix(workspace-files): resolve subagent session roots 2026-09-09 17:29:38 +08:00
_Kerman e1f0911618 test(ptc): strengthen literal prompt assertions 2026-09-09 17:29:01 +08:00
Yichen Jiang 00b16cb63a fix(web): align terminal preview, styles, and snapshots 2026-09-09 17:29:00 +08:00
_Kerman 5a673b8a59 refactor(ptc): share the prompt section return type 2026-09-09 17:28:47 +08:00
Yif 3b4122ac16 feat(client): polish sidebar and file preview interactions
Seed sidebar default pages lazily on expansion, scope page-tab dedupe
to the target pane, let a sole tab split its own pane with a factory
backfill, close menus when focus enters a sandboxed iframe, and pin the
code preview copy banner while unifying its background with the pane.
2026-09-09 17:27:37 +08:00
creatixchu 1d55cab9e6 fix(web): use shared file type icons in delivery cards 2026-09-09 17:23:07 +08:00
creatixchu 644f6abd7c Merge branch 'worktree/pr-3858-release-sync' into worktree/pr-3819-release-sync
# Conflicts:
#	packages/client/ui-primitives/README.i18n.yaml
#	packages/client/ui-primitives/README.md
#	packages/client/ui-primitives/README.zh.md
2026-09-09 17:20:37 +08:00
creatixchu a7b5c8a043 Merge remote-tracking branch 'origin/master' into worktree/pr-3858-release-sync 2026-09-09 17:20:01 +08:00
_Kerman c6fb28a164 fix(client): use a collapse icon for expanded JSON strings 2026-09-09 17:19:18 +08:00
_Kerman 1549483397 feat(client): expand reasoning-only assistant output by default 2026-09-09 17:19:10 +08:00
_Kerman e4f0871b80 fix(trajectory): clarify overview overflow and tighten spacing 2026-09-09 17:19:03 +08:00
_Kerman ac09b7b519 fix(trajectory): narrow Chinese role column 2026-09-09 17:16:15 +08:00
lsdsjy 3797127eb2 fix(headless): publish the shared chunk and read the session's current preset
Address the ds-review-bot v6 review on PR #3849:

- Publish the `lib/json-stream-*.js` chunk that both entry points import.
  Without it the installed tarball failed to load with ERR_MODULE_NOT_FOUND,
  because `files` listed only `lib/index.js` and `lib/startup.js`.
- Resolve a Session's preset from its log (`agent-preset/selected`) instead of
  only the immutable creation header, so a Session that switched preset while
  blank is rejected too. Both the persisted and the live path scan the events.
- Write the `--json` error event for Commander grammar rejections (an unknown
  option, a missing option value) as well as the action's own usage errors, and
  drop Commander's `error: ` prefix from the event message so one event type
  carries one message shape.
- Reject a whitespace-only positional instead of falling back to stdin, so an
  accidental blank argument cannot consume a pipe.
- Document the stdin task as verbatim and the widened usage-error contract.

Tests: 68 headless unit tests with per-file 100% coverage on src, 14 profile
e2e tests, plus a packed-tarball import smoke check.
2026-09-09 17:16:09 +08:00
_Kerman aeb13413c7 test(agent): complete awaited creation migration 2026-09-09 17:14:53 +08:00
_Kerman 0fb509f544 fix(agent): preserve initialization failure during teardown 2026-09-09 17:14:16 +08:00
_Kerman e4be27d1d9 test(ptc): align workspace snapshot with shared SDK prompt 2026-09-09 17:13:08 +08:00
creatixchu f5804826a8 Merge remote-tracking branch 'origin/master' into codex/pr-3819 2026-09-09 17:13:08 +08:00
Tianyi Cui 8a41f7a8e1 docs(session): clarify release authority review findings 2026-09-09 17:12:06 +08:00
_Kerman e779831f40 fix(client): restore assistant timing from recorded streams 2026-09-09 17:10:44 +08:00
_Kerman 9cd0c703df fix(web): invalidate projections before opening control snapshots 2026-09-09 17:06:57 +08:00
Tianyi Cui 56c4c3e47c docs(session): centralize format status and timeless guidance 2026-09-09 17:06:03 +08:00
Tianyi Cui bafe887d6d Merge pull request #3851 from deepseek-harness/docs/released-v3-wording
docs(session): correct released V3 compatibility guidance
2026-09-09 17:05:14 +08:00
creatixchu dfda1d6aaf fix(web): ship protocol runtime dependency for delivered file actions 2026-09-09 17:02:24 +08:00
lsdsjy 45032ea1bd fix(headless): address re-review findings on the machine-readable run surface
- Reject adopting a Session recorded under an agent preset, and one that
  recorded no cwd; align the subagent/forked diagnostic wording.
- Write the bounded JSON `error` event for a --json usage error before exit,
  since the runner never mounts to write it.
- Keep the caller's exact --session-id instead of the trimmed value.
- Bound object keys and copy a literal `__proto__` key as data rather than
  through the inherited setter.
- Reject a lone `-` mixed with other task words.
- Document the in-turn failure contract and step-commit text/thinking timing.
2026-09-09 16:58:24 +08:00
gengruilin 86c61e24e9 Merge origin/master into fix/mcp-pagination-cycles 2026-09-09 16:57:25 +08:00
_Kerman 96a1749db6 fix(ptc): preserve literal braces in generated SDK prompts 2026-09-09 16:52:42 +08:00
creatixchu 99bffa7f9a fix(web): update delivery card snapshot and remove unused button segments 2026-09-09 16:52:04 +08:00
creatixchu b443c4d246 fix(present): resolve file services in live agent scope and refresh snapshots 2026-09-09 16:48:39 +08:00
_Kerman 819c2b2442 feat(client): show expanded JSON strings as raw text 2026-09-09 16:47:16 +08:00
creatixchu 7e4d9edc13 Merge remote-tracking branch 'origin/master' into codex/pr-3819 2026-09-09 16:45:05 +08:00
creatixchu 00bfdfbce6 fix(present): follow session filesystem access for deliverables 2026-09-09 16:44:51 +08:00
yixiangihsiang 1eee75b424 fix(client): satisfy icon validation gates 2026-09-09 16:41:15 +08:00
yixiangihsiang 4ee9e055d5 feat(client): add shared file type icons 2026-09-09 16:41:15 +08:00
Yichen Jiang e15a9b1bec feat(web): add interactive sidebar terminals 2026-09-09 16:40:58 +08:00
_Kerman 0e468a62f6 fix(trajectory): hide timing source in overview 2026-09-09 16:39:16 +08:00
_Kerman 24710859e5 Merge remote-tracking branch 'origin/master' into xtr/durable-inbox-web-recovery 2026-09-09 16:36:41 +08:00
Dudu-0223 291b890a1a fix(agent-team): append durable identity reminders after fork history 2026-09-09 16:32:32 +08:00
Turtle 6d99a8a53a Merge pull request #3794 from deepseek-harness/turtle/issue-3761-plugin-instance-label
fix(web): distinguish same-package plugin instances
2026-09-09 16:29:54 +08:00
_Kerman 18739de7c6 feat(client): improve trajectory JSON string display 2026-09-09 16:28:17 +08:00
_Kerman f3332af2a4 fix(web): discard projection state across host generations 2026-09-09 16:28:03 +08:00
_Kerman e101c448e5 fix(web): declare the conversation agent project reference 2026-09-09 16:27:48 +08:00
Tianyi Cui a5fc275a56 docs(session): address scoped review clarifications 2026-09-09 16:26:49 +08:00
Turtle d6a699be19 Merge pull request #3845 from deepseek-harness/turtle/keep-blocked-approval-pending
Keep blocked weighted approvals pending
2026-09-09 16:20:11 +08:00
_Kerman 9b7a8ccc9f feat(agent): await initialization through agent/created 2026-09-09 16:20:00 +08:00
creatixchu 74bf7aaa2f fix(web): preserve artifact actions across reconnects and keyboard use 2026-09-09 16:18:24 +08:00
fz aed212657a docs: clarify scoped guidance and file observation policy 2026-09-09 16:13:09 +08:00
creatixchu a43fa81f82 test: respect startup and teardown budgets in Windows fixtures 2026-09-09 16:08:19 +08:00
Turtle e9f1725b11 docs: record pending weighted approval blockers 2026-09-09 15:58:21 +08:00
turtle1999 0d44848ba6 Rename weighted approval publisher job 2026-09-09 15:58:21 +08:00
turtle1999 8eede0f60d Keep blocked approvals pending 2026-09-09 15:58:21 +08:00
lsdsjy 94d3273c19 Merge remote-tracking branch 'origin/master' into turtle/issue-3848-headless-machine-readable-run 2026-09-09 15:54:26 +08:00
yx.zhang 057b4879cf feat(web): align presented file cards with design 2026-09-09 15:53:44 +08:00
winewill 9c14f2785f perf(desktop): parallelize macOS notarization 2026-09-09 15:52:46 +08:00
lsdsjy ba6e19809d fix(headless): project committed content and scope live adoption 2026-09-09 15:51:23 +08:00
fz 4029451fa7 test: refresh guidance for the fetch-only composition 2026-09-09 15:50:06 +08:00
fz 9d6c964985 fix: respect scoped tools in filesystem and web guidance 2026-09-09 15:45:54 +08:00
Turtle 2e2489b888 fix(web): trim composition marker from plugin subtitles 2026-09-09 15:41:02 +08:00
Tianyi Cui 7b6b8a2baa docs(session): correct released V3 compatibility guidance 2026-09-09 15:32:55 +08:00
creatixchu a8faac2850 Merge origin/master feedback dialog changes into worktree/composer-plus-menu 2026-09-09 15:31:33 +08:00
lsdsjy 8662afb530 docs(headless): regenerate module graph for the run projection 2026-09-09 15:31:24 +08:00
Turtle 2b631c0646 test(web): update plugin settings golden order 2026-09-09 15:27:18 +08:00
yudshj c83f02ad81 fix(web): defer desktop metadata until delivery cards appear 2026-09-09 15:26:34 +08:00
yudshj 5b671d7df3 fix(web): show artifact paths relative to the workspace 2026-09-09 15:26:34 +08:00
yudshj b27d861741 docs: refresh native file action catalog references 2026-09-09 15:26:34 +08:00
yudshj 4158a96e14 feat(web): add native file actions to artifact cards 2026-09-09 15:26:28 +08:00
creatixchu 5a878f7c3e test(web): await restored theme before changing preference 2026-09-09 15:24:56 +08:00
imccyu da042b78ff Merge pull request #3765 from deepseek-harness/worktree/issue-3515-feedback-dialog
反馈弹窗:点踩与 /feedback 共用一个带分类的弹窗,提交后出 toast
2026-09-09 15:24:24 +08:00
lsdsjy 0e7361a489 test(headless): close per-file coverage on the run projection 2026-09-09 15:19:52 +08:00
_Kerman 1514635118 Merge master to unblock durable inbox recovery CI 2026-09-09 15:18:13 +08:00
lsdsjy d5fe1fb887 docs(headless): regenerate event producer graph and restore model-selection note 2026-09-09 15:17:01 +08:00
_Kerman 72f2e71070 fix(web): reconcile durable inbox recovery with master 2026-09-09 15:14:08 +08:00
lsdsjy ba6a90d2f2 feat(headless): add stdin task, --session-id, and --json run events 2026-09-09 15:12:32 +08:00
creatixchu 883e7f80fc Merge origin/master into worktree/composer-plus-menu 2026-09-09 15:02:42 +08:00
Turtle 1349af8e97 fix(web): give plugin identities a full row 2026-09-09 14:57:45 +08:00
creatixchu 0b5fca5c68 Merge remote-tracking branch 'origin/master' into worktree/issue-3515-feedback-dialog
# Conflicts:
#	apps/web/tests/message-feedback-layout.e2e.ts
2026-09-09 14:56:31 +08:00
Yudong Han ba5ce5700c Merge pull request #3832 from deepseek-harness/fix/file-delivery-present
fix(deliverables): distinguish file changes and require explicit delivery
2026-09-09 14:53:17 +08:00
Yichen Jiang 2e0106498e Merge branch 'worktree/jobs-api-review-3052' into worktree/jobs-api-review-3127 2026-09-09 14:53:12 +08:00
Yichen Jiang a8fc15ec85 test(jobs): align built codec smoke with remote method names 2026-09-09 14:52:55 +08:00
_Kerman 12ba944f54 test(lint): cover example history reader exemptions 2026-09-09 14:52:15 +08:00
_Kerman 14da43d9ff docs(session): link deprecated readers to the history policy 2026-09-09 14:51:50 +08:00
Yichen Jiang 4b1db738f5 test(bash): control promotion deadline after output readiness 2026-09-09 14:50:59 +08:00
Yichen Jiang dd7ea38578 fix(tests): adapt spill replay to unified shell execution 2026-09-09 14:46:41 +08:00
Yichen Jiang ab6dacc80e Merge branch 'worktree/jobs-api-review-3052' into worktree/jobs-api-review-3127
# Conflicts:
#	packages/shell/pwsh-local/tests/executor.spec.ts
#	packages/shell/shell/README.i18n.yaml
#	packages/shell/shell/README.md
#	packages/shell/shell/README.zh.md
#	packages/shell/tool-bash/README.i18n.yaml
#	packages/shell/tool-bash/README.md
#	packages/shell/tool-bash/README.zh.md
#	packages/workflow/tool-workflow/README.i18n.yaml
#	packages/workflow/tool-workflow/README.md
#	packages/workflow/tool-workflow/README.zh.md
2026-09-09 14:44:14 +08:00
Yichen Jiang b211c87150 Merge remote-tracking branch 'origin/master' into worktree/jobs-api-review-3052
# Conflicts:
#	apps/web/tests/agent-preset-selection.e2e.ts
#	apps/web/tests/expected/agent-preset-selection/header.expected.md
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	docs/persistence-catalog.i18n.yaml
#	docs/persistence-catalog.zh.md
#	packages/api/session-controller/README.i18n.yaml
#	packages/api/session-controller/README.md
#	packages/api/session-controller/README.zh.md
#	packages/api/session-controller/package.json
#	packages/client/ui-jobs/package.json
#	packages/jobs/jobs/README.i18n.yaml
#	packages/jobs/jobs/README.md
#	packages/jobs/jobs/README.zh.md
#	pnpm-lock.yaml
2026-09-09 14:42:11 +08:00
gengruilin 96ac11885e Merge origin/master into fix/mcp-pagination-cycles 2026-09-09 14:40:06 +08:00
Turtle f42fddad34 Merge pull request #3840 from deepseek-harness/turtle/remove-weighted-approval-cyborg-text
Remove cyborg wording from weighted approval
2026-09-09 14:35:50 +08:00
Tianyi Cui 456162410b Merge pull request #3780 from deepseek-harness/fix/master-ci-3661
test(ci): 固定异步完成观察并收紧导入豁免
2026-09-09 14:35:17 +08:00
CreatixChu 4f0adbc99a Merge pull request #3839 from deepseek-harness/fix/3838-composer-placeholder
fix(web): 输入空白字符后隐藏 Composer 占位提示
2026-09-09 14:34:43 +08:00
_Kerman cb999713d1 Merge latest master into xtr/durable-inbox-web-recovery 2026-09-09 14:31:52 +08:00
Huanqi Cao cc5a7697e7 Merge pull request #3698 from deepseek-harness/feat/picker-alt-foreground
fix(picker): foreground-activate the Windows native folder dialog via a synthesized Alt press
2026-09-09 14:28:23 +08:00
turtle1999 1eaba2809b Remove cyborg wording from weighted approval 2026-09-09 14:28:10 +08:00
creatixchu eff482c46b fix(web): stabilize composer command editing and scrolling 2026-09-09 14:27:51 +08:00
creatixchu 6c4a2fb294 Merge remote-tracking branch 'origin/master' into worktree/issue-3515-feedback-dialog
# Conflicts:
#	packages/client/ui-model-selection/tests/browser-plugin.client.spec.ts
2026-09-09 14:27:15 +08:00
creatixchu 224f75dc63 test(web): strengthen composer placeholder regression evidence 2026-09-09 14:15:25 +08:00
yx.zhang 30ea609363 Merge remote-tracking branch 'origin/pr-3765-head' into pr-3765 2026-09-09 14:06:27 +08:00
creatixchu a6ee97ebe1 Merge remote-tracking branch 'origin/master' into fix/3838-composer-placeholder 2026-09-09 14:04:23 +08:00
_Kerman 23f345e1dd Merge remote-tracking branch 'origin/master' into xtr/deprecate-session-event-readers 2026-09-09 14:03:26 +08:00
creatixchu 0f1164cdee fix(web): hide composer placeholder for whitespace drafts 2026-09-09 13:56:54 +08:00
yx.zhang 4b3cfcfaf3 style(feedback): refine feedback dialog disclosure and layout 2026-09-09 13:56:53 +08:00
Turtle cad50c2504 Merge pull request #3792 from deepseek-harness/turtle/issue-3762-provider-base-url-validation
fix(web): validate custom provider base URLs
2026-09-09 13:54:48 +08:00
yudshj 9708c4bb42 test(web): scope SVG delivery snapshot to the chat transcript 2026-09-09 13:41:56 +08:00
yudshj 152e0f42ca fix(web): await settled browser state and shorten file-change label 2026-09-09 13:41:56 +08:00
yudshj 7a0afea27f fix(deliverables): distinguish file changes and require explicit delivery 2026-09-09 13:41:56 +08:00
_Kerman ba1e73ddf5 Revert "test(credentials): await reload commit notifications"
This reverts commit 436ec72d4b744cbf3c1473680388d802940b6b9e.
2026-09-09 13:40:51 +08:00
_Kerman 5367541916 Revert "test(agent-team): await recovered mail acknowledgement"
This reverts commit 6e9b6abf38694f9e2ba4214e87356d90293f8dc8.
2026-09-09 13:40:51 +08:00
Turtle fac33d7ba7 Merge pull request #3791 from deepseek-harness/turtle/issue-3760-zh-display-model-copy
fix(web): localize Chinese display and model copy
2026-09-09 13:36:09 +08:00
pku-xht 6adc878785 Merge master sidebar UI polish 2026-09-09 13:27:07 +08:00
gengruilin 8053f3d450 Merge origin/master into fix/mcp-pagination-cycles 2026-09-09 13:19:42 +08:00
Tianyi Cui 6bc836c0c0 docs(ci): distinguish fixture controls from completion policy 2026-09-09 13:18:09 +08:00
Tianyi Cui 1b56cf6013 test(ci): retain useful regression controls after master rebase 2026-09-09 13:18:09 +08:00
Tianyi Cui da1df501b8 test(runtime): isolate busy-meter decisions from worker startup 2026-09-09 13:18:09 +08:00
Tianyi Cui 43d00069a9 test(web): await restoration before workspace actions 2026-09-09 13:18:09 +08:00
Tianyi Cui bc55f10a46 test(web): wait for admitted queue before steering shortcut 2026-09-09 13:18:09 +08:00
Tianyi Cui d85bdd80c1 test(ci): observe command readiness and transport settlement 2026-09-09 13:18:08 +08:00
Tianyi Cui c93bfee16e test(web): drain retained request handlers before teardown 2026-09-09 13:18:08 +08:00
Tianyi Cui e7feedab5e test(web): await durable UI and responsive layout publication 2026-09-09 13:18:08 +08:00
Tianyi Cui d38391d629 test(web): release timed-out barriers and await frame animations 2026-09-09 13:18:08 +08:00
Tianyi Cui 94a2b0a248 test(ci): await details transitions and report benchmark runtime 2026-09-09 13:18:08 +08:00
Tianyi Cui 5b0d65fd72 test(ci): observe asynchronous completion and settled layout 2026-09-09 13:18:08 +08:00
_Kerman 3744740b62 test(agent-team): await recovered mail acknowledgement 2026-09-09 13:17:21 +08:00
Huanqi Cao 2059bdf78e Merge remote-tracking branch 'origin/master' into feat/picker-alt-foreground 2026-09-09 13:17:20 +08:00
_Kerman c433ac7776 test(credentials): await reload commit notifications 2026-09-09 13:17:20 +08:00
_Kerman a61b0c5a56 test(lint): update the scoped deprecation fingerprint 2026-09-09 13:16:09 +08:00
Turtle ebd7e82075 Merge pull request #3834 from deepseek-harness/turtle/remove-automatic-review-requests
ci: remove automatic review requests
2026-09-09 13:13:25 +08:00
Turtle 939222a4ad fix(web): normalize custom provider base URLs 2026-09-09 13:12:43 +08:00
creatixchu a4954e1bd2 test(web): follow the renamed launcher and capitalized rows in CI gates
Registers slash/input-pick-files with the cordis catalog walk exemptions
beside its sibling slash-input events, and points the web e2e at the
'Add files or run commands' launcher and the capitalized row titles the
paperclip removal and the menu presentation introduced.
2026-09-09 12:58:11 +08:00
Turtle d6ed693f23 ci: remove automatic review requests 2026-09-09 12:56:06 +08:00
_Kerman 8f986c8da6 chore(session): scope history reader exemptions to tests 2026-09-09 12:55:32 +08:00
creatixchu ba066ab5f8 Merge remote-tracking branch 'origin/master' into worktree/composer-plus-menu 2026-09-09 12:53:09 +08:00
creatixchu 00c2c47e19 fix(web): key the claim hint on the command name, not the claim token
A localized claim token (/目标 ) made the composer look up hint.目标, miss the
dictionary, and fall back to the Host's usage string. CommandClaim now carries
the catalog name beside the display token, the state projection keeps it, and
the hint lookup reads it.
2026-09-09 12:52:41 +08:00
imccyu 88dfd72537 Merge pull request #3807 from deepseek-harness/sidebar-ui-polish-main
feat(web): right sidebar UI polish
2026-09-09 12:49:57 +08:00
pku-xht 01789bfa4d Merge master benchmark calibration fixes 2026-09-09 12:48:17 +08:00
creatixchu 0199633269 Merge remote-tracking branch 'origin/master' into worktree/issue-3515-feedback-dialog 2026-09-09 12:45:32 +08:00
creatixchu 700e8df91a test(feedback): cover the seed-failure and unmount paths of the Dislike control 2026-09-09 12:45:31 +08:00
_Kerman 37abcb74c5 chore(session): permit existing deprecated history reads 2026-09-09 12:33:53 +08:00
_Kerman aa491acc29 docs(session): record synchronous history read deprecation policy 2026-09-09 12:20:38 +08:00
imccyu 2f2831f033 test(web): align sidebar interaction expectations 2026-09-09 12:15:00 +08:00
imccyu ff3ccb4d7c test(web): use supported sidebar visibility assertion 2026-09-09 12:15:00 +08:00
imccyu 3481d4043e fix(client): align sidebar checks after rebase 2026-09-09 12:15:00 +08:00
Yif d0a1ab8723 chore(client): regenerate slot catalog after master merge 2026-09-09 12:15:00 +08:00
Yif c73dcecb96 fix(textpreview): say a stat-and-read failure once
A file whose stat and first page both fail — outside the workspace, gone —
showed the same line twice: the metadata bar above an identical centred body
failure. The bar now stands only over pages already loaded, and the centred
retry runs the full reload so one press clears both halves.
2026-09-09 12:15:00 +08:00
Yif 284758cbc3 test(web): refresh goldens for the sidebar aria renames
The expand/collapse and wrap toggles' accessible names diverged from their
tooltips, and the replay harness now normalizes clientTimeZone in recorded
sessions; every golden holding the old names or the literal zone refreshes.
2026-09-09 12:15:00 +08:00
Yif c76e371874 fix(sidebar): address review feedback on aria names, touch hits, and fullscreen close
- Split toggle aria-labels from their tooltips: the sidebar expand/collapse
  buttons announce "Open/Collapse right sidebar" so the two sidebars stay
  distinguishable, and the wrap toggle keeps an invariant "Line wrap" name
  beside aria-pressed while the tooltip keeps the action wording.
- A hidden tab close also takes no pointer events, so a touch press on the
  chip's trailing edge activates the tab instead of closing it; e2e closes
  hover the chip first, the way a reader would.
- Closing the last docked tab in fullscreen hands the mode back to push, so
  the next expand does not give the whole window to the start page.
- The drop scrim mixes from bg-base, not bg-layer-2, which dark mode binds
  to a lighter bluish step than the column beneath it.
- Document the menuitem probe in TabMenuExtras and the strip fade's known
  gap; match the open-in-app split-button comment to the 28px control row.
2026-09-09 12:14:59 +08:00
Yif 814f447b8f fix(dockkit): move ui-primitives to devDependencies and hoist zone glyph paths past the i18n gate 2026-09-09 12:14:59 +08:00
Yif 5e44fc79d3 test(web): refresh header and file-preview goldens for renamed controls 2026-09-09 12:14:59 +08:00
Yif 7a032b6366 test(web): disambiguate the left sidebar toggle from the right expand control 2026-09-09 12:14:58 +08:00
Yif 237618ca33 test(dockkit): cover the bottom drop-zone glyph 2026-09-09 12:14:58 +08:00
Yif e94241f601 feat(web): move the session-log control into the header more-actions menu 2026-09-09 12:14:58 +08:00
Yif 5ee343f735 feat(sidebar): live tab titles with file-type icons and disambiguated paths 2026-09-09 12:14:58 +08:00
Yif f4c1e31ba8 feat(sidebar): last-tab close rules and collapsed expand button
The lone guide tab withholds its close and menu, any other lone tab closes
together with the column, and the expand button renders only while collapsed
so the corner seat costs the header nothing.
2026-09-09 12:14:58 +08:00
Yif 838dbbe0d0 feat(dockkit): refine strip and chip presentation, close policy, and room reading
Chip capsules with scroll fades and live titles, drop-zone hint cards, the
canCloseTab control policy with the quiet lone chip and self-dismissing empty
menu, and a room reading that stays independent of hidden split controls.
2026-09-09 12:14:58 +08:00
Yif 69a13cef6d feat(primitives): add file-type icon set and shared link icon 2026-09-09 12:14:57 +08:00
_Kerman 5cfc765ff6 docs(session): deprecate direct event readers 2026-09-09 12:11:13 +08:00
Turtle bc4fde06ac fix(web): validate custom provider base URLs 2026-09-09 12:04:40 +08:00
gengruilin 189ca97ec9 Merge origin/master into fix/mcp-pagination-cycles 2026-09-09 12:04:24 +08:00
Tianyi Cui 08f646da36 Merge pull request #3812 from deepseek-harness/worktree/ci-reliability-master-followup-20260908
test(ci): stabilize asynchronous fixtures and benchmark budgets
2026-09-09 11:52:54 +08:00
gengruilin 454825ca38 Merge origin/master into fix/mcp-pagination-cycles 2026-09-09 11:49:04 +08:00
creatixchu 4b88085c2a style(feedback): refine dialog proportions 2026-09-09 11:41:24 +08:00
Tianyi Cui 2c0596c1ba docs(bench): clarify reviewed request-history limit 2026-09-09 11:29:05 +08:00
pku-xht e8a5e9dfd9 Merge master to restore required CI scheduling 2026-09-09 11:28:38 +08:00
Tianyi Cui ba4b8fddeb test(bench): calibrate hosted cold Agent resume limit 2026-09-09 11:26:48 +08:00
Tianyi Cui 2567d35cdf docs(bench): synchronize request-history limit 2026-09-09 11:26:48 +08:00
Tianyi Cui 843029448a test(code-runtime): allow measured worker initialization time 2026-09-09 11:26:48 +08:00
Tianyi Cui d1b1488ed3 test(session): await durable live writes with owned teardown 2026-09-09 11:26:48 +08:00
Tianyi Cui bd24f8a17f test(app-boot): control user-patch HMR event delivery 2026-09-09 11:26:48 +08:00
Tianyi Cui dc14f5e4f9 test(web): await resized details geometry through its transition 2026-09-09 11:26:48 +08:00
Tianyi Cui 48007d76f2 test(bench): allow measured request-history runner variation 2026-09-09 11:26:48 +08:00
Tianyi Cui fd5d68586f test(web): wait for model selection menu closure 2026-09-09 11:26:48 +08:00
Yichen Jiang 2044d2906b Merge remote-tracking branch 'origin/master' into worktree/llm-deepseek-messages
# Conflicts:
#	apps/web/tsconfig.json
#	tsconfig.host.json
2026-09-09 11:09:16 +08:00
Turtle 9606b69545 Merge origin/master into turtle/issue-3760-zh-display-model-copy 2026-09-09 11:02:57 +08:00
Turtle 43846e7032 Merge pull request #3783 from deepseek-harness/turtle/weighted-approval
feat: enforce weighted pull request approvals
2026-09-09 11:00:39 +08:00
Turtle 9da63ca94d Merge pull request #3789 from deepseek-harness/turtle/issue-3757-settings-accessible-name
fix(client): name collapsed Settings trigger
2026-09-09 10:56:30 +08:00
creatixchu 6207453d36 Merge remote-tracking branch 'origin/master' into worktree/issue-3515-feedback-dialog 2026-09-09 10:44:25 +08:00
pku-xht ad93e2f602 fix(auto-review): preserve nested trajectory errors and optional peer 2026-09-09 10:43:56 +08:00
creatixchu d692289533 style(feedback): compact the dialog to a 540px card with lighter chips and a grown detail box 2026-09-09 10:42:06 +08:00
imccyu c57fb6f7ef Merge pull request #3798 from deepseek-harness/worktree-sidebarfeat
feat(client): document previews — HTML, PDF, Markdown and code
2026-09-09 10:41:39 +08:00
creatixchu 1094431de9 docs(feedback): document the FeedbackSurface fields for the export-jsdoc gate 2026-09-09 10:33:09 +08:00
creatixchu a25e5fd8a9 test(sdk): refresh the feedback expectations on the V3 base and restore the frozen v2 generation 2026-09-09 10:27:15 +08:00
creatixchu 3e53a08f36 fix(feedback): keep the category tuple out of types.ts, retire the toast with its entry, and answer the review 2026-09-09 10:27:12 +08:00
creatixchu e6ff3290cf Merge remote-tracking branch 'origin/master' into worktree/composer-plus-menu
Takes the merged slash-command localization (#3557): its zh description
copy replaces this branch's, its contribution description() callback and
HOST_DESCRIPTION_KEYS are superseded by the label/description/icon
contribution face and presentation.ts, and its zh menu golden and
locale-switch test are refreshed for the sectioned menu.
2026-09-09 10:25:10 +08:00
creatixchu f2f9700de2 feat(feedback): open one feedback dialog from /feedback and Dislike, with categories and a toast
Dislike and a bare /feedback open the Session's feedback dialog, which
collects one of seven fixed categories and an optional description and
records through the messageFeedback put or the new sessionFeedback
Remote; Like records at once. A recorded rating shows the filled glyph
and every submission is acknowledged by a toast. feedback/record and
MessageFeedbackItem carry the optional category; the note popover, its
layout scenario, and the clearNote/clear verbs are removed. ui-commands
gains the action command kind the /feedback decoration runs as.

Closes #3515
2026-09-09 10:20:24 +08:00
imccyu 64560eaff1 fix(client): remove stale preview contracts 2026-09-09 10:12:46 +08:00
imccyu 93b30b9765 fix(client): narrow document preview contracts 2026-09-09 10:12:46 +08:00
imccyu be58ae0577 test(web): await sidebar collapse before snapshots 2026-09-09 10:12:46 +08:00
imccyu 4d07fbcb85 fix(client): address document preview review feedback 2026-09-09 10:12:46 +08:00
imccyu ce28b0672f fix(client): simplify PDF observer cleanup 2026-09-09 10:12:46 +08:00
imccyu 39872bafe6 docs(client): record sidebar guide translation 2026-09-09 10:12:45 +08:00
imccyu c78fdb583a fix(ci): refresh document preview metadata 2026-09-09 10:12:45 +08:00
imccyu 693621dcad fix(client): streamline continuous PDF previews 2026-09-09 10:12:41 +08:00
imccyu dcfd8c299d refactor(client): rename document preview package 2026-09-09 10:12:40 +08:00
imccyu 5c283d27e2 fix(client): allow outside previews and streamline document readers 2026-09-09 10:12:39 +08:00
imccyu 4321766ead feat(client): add extensible document previews and sidebar defaults 2026-09-09 10:12:38 +08:00
pku-xht c0348f7bfc Merge master to restore required CI scheduling 2026-09-09 08:35:58 +08:00
pku-xht 41fbde8034 fix(permission): revoke stale Auto choices and simplify review paths 2026-09-09 08:08:10 +08:00
Yichen Jiang 8249d54e47 style(web): open a package's page from its whole card and move its actions into the head
The card's title button stretches over the card, so a click anywhere opens
the page while the switch and the Add to… menu sit above the stretch and keep
their own clicks; descriptions are one ellipsised line again. On the page,
the description fills the column, and retry and uninstall sit in the head
beside the switch instead of at the bottom-right. The card surface binds the
elevated scrollbar pair the ui-theme rule asks of a sheet that scrolls.
2026-09-09 07:42:28 +08:00
Yichen Jiang 08974835d7 refactor(web): rename ui-settings-plugin-manager to ui-plugin-manager
The package hosts the sidebar's Plugins panel and a preset's capabilities
section, not a settings tab; the directory, the package name, and its
dictionary namespace (`pluginManager`) say so, and every reference, catalog,
and note follows.
2026-09-09 07:42:23 +08:00
Yichen Jiang c6e6023dee Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web 2026-09-09 07:20:46 +08:00
Yichen Jiang a98eacd664 Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-09 07:19:35 +08:00
Yichen Jiang 41d21f841c Merge branch 'feat/plugin-mgmt-1-boot' into feat/plugin-mgmt-2-manager 2026-09-09 07:18:29 +08:00
Yichen Jiang 34a279743d style(web): open a package's page from its title and clamp card descriptions
The card's chevron button goes: the title is the text button into the page,
underlined on hover, with the same accessible name. Descriptions wrap to two
lines instead of one ellipsised line.
2026-09-09 07:16:46 +08:00
Yichen Jiang c96854eec8 Merge remote-tracking branch 'origin/master' into feat/plugin-mgmt-1-boot 2026-09-09 07:16:26 +08:00
Yichen Jiang 541dee461b style(web): centre the plugin management column 2026-09-09 07:10:41 +08:00
Yichen Jiang 0aeebb017e feat(web): move plugin management to the sidebar's Plugins panel
Master's left sidebar grew global main panels, so the manager leaves the
Settings dialog: `ui-settings-plugin-manager` registers a `sidebar.panellist`
entry and the `main` panel it opens under one id, `plugins`, and the former
tab becomes `PluginManagerPage` with its own heading, intro, refresh, and
Add plugin, scrolling inside the main column. Plugin configuration stays in
the Settings Plugins section, which `ui-settings-plugins` now renders
without a tab strip when it holds one contribution.

Web e2e reaches the manager through the sidebar; the plugin-config,
plugin-manager, settings-chrome, and lifecycle-chrome scenarios and goldens
follow. The decision and why configuration does not move are in the new
Agent Note, cross-linked from the two notes it revises.
2026-09-09 07:00:55 +08:00
Yichen Jiang e9b3f80f0b Merge pull request #3724 from deepseek-harness/worktree/pi-ai-settings-recovery
fix(llm-pi-ai): keep catalog-invalid settings repairable
2026-09-09 06:37:54 +08:00
Yichen Jiang 5d90477cb1 test(web): refresh the preset-detail golden for master's tool-present row 2026-09-09 06:36:01 +08:00
Yichen Jiang dd3e690ef8 chore(client): regenerate the slot catalog after the master merge 2026-09-09 06:34:11 +08:00
Yichen Jiang 00a5aafdc3 Merge remote-tracking branch 'origin/master' into feat/plugin-mgmt-4-web
# Conflicts:
#	packages/client/ui-settings-plugins/package.json
2026-09-09 06:29:37 +08:00
Yichen Jiang d80891921b Merge remote-tracking branch 'origin/master' into worktree/pi-ai-settings-recovery
# Conflicts:
#	packages/llm/llm/README.i18n.yaml
#	packages/llm/llm/README.md
#	packages/llm/llm/README.zh.md
2026-09-09 06:18:13 +08:00
pku-xht 0eb0e8c770 Merge master to restore required CI for Auto review 2026-09-09 05:25:20 +08:00
pku-xht 9cfb120a63 merge: reconcile experimental Auto review implementation 2026-09-09 04:38:55 +08:00
pku-xht 55e53907ab feat(permission): add experimental Auto review 2026-09-09 04:36:19 +08:00
imccyu ab904f4b6b Merge pull request #3813 from deepseek-harness/worktree-nodeaddworkflow
ci(native): consolidate platform compatibility jobs
2026-09-09 02:45:46 +08:00
imccyu 063165a800 ci(native): consolidate platform compatibility jobs 2026-09-09 02:31:43 +08:00
fz 0ba6c25807 Merge pull request #3510 from deepseek-harness/feat/remove-str-replace-editor-from-minimal
feat(minimal): make editor opt-in and align bash output
2026-09-09 02:10:26 +08:00
fz 452fe6de55 Merge remote-tracking branch 'origin/master' into feat/remove-str-replace-editor-from-minimal 2026-09-09 01:49:09 +08:00
fz 887c1efd7a ci(npm): expose failed install HTTP diagnostics 2026-09-09 01:48:54 +08:00
fz 0f6e7442d7 perf(session): bundle migration verifier dependencies 2026-09-09 01:48:27 +08:00
Yudong Han 6635cddaa4 Merge pull request #3569 from deepseek-harness/fs/stream-bytes
feat(web): declare workspace deliveries and open source files
2026-09-09 01:33:20 +08:00
fz 40c9766a8d Merge origin/master into feat/remove-str-replace-editor-from-minimal 2026-09-09 01:22:09 +08:00
Yudong 228f3aef83 test(ci): stabilize completion waits and Session fixtures 2026-09-09 01:15:31 +08:00
yudshj 72549e91a0 test(present): pass the event to delivery matcher 2026-09-09 01:15:31 +08:00
yudshj cd2b9ca04a refactor(present): restore existing conversation coordinate handling 2026-09-09 01:15:31 +08:00
yudshj 207dce0bee docs(present): refresh module graph after removing attachments 2026-09-09 01:15:31 +08:00
yudshj c9038b4b31 refactor(present): declare and open workspace source files 2026-09-09 01:15:31 +08:00
yudshj 387e437af4 fix(web): use the preview-compatible stream promises entry 2026-09-09 01:15:31 +08:00
yudshj 6d8a400d79 fix(web): open delivered snapshots in the default application 2026-09-09 01:15:31 +08:00
yudshj 37d27fcdf9 feat(web): present immutable file deliveries with download cards 2026-09-09 01:15:31 +08:00
imccyu 4d831f2d14 Merge pull request #3771 from deepseek-harness/worktree-fixreactpeer
fix(web): move client dependencies to devDependencies
2026-09-09 01:15:27 +08:00
imccyu bfe82d4c2d Merge pull request #3784 from deepseek-harness/worktree-leftsideslot
feat(web): add panellist to left-sidebar
2026-09-09 00:59:11 +08:00
Dudu-0223 a4176ef851 Merge pull request #3674 from deepseek-harness/feat/parent-subagent-catalog-foundation
feat(subagent): record and observe parent-owned child catalogs
2026-09-09 00:37:47 +08:00
imccyu f39a37a523 fix(client): keep browser dependencies out of production installs 2026-09-09 00:30:37 +08:00
imccyu f3d7ef2b95 docs(client): define browser third-party build inputs 2026-09-09 00:30:36 +08:00
imccyu 58144ccf78 test(web): await command and settings readiness before assertions 2026-09-09 00:26:41 +08:00
imccyu e807447288 fix(client): re-read navigation cancellation after preparation 2026-09-09 00:26:41 +08:00
imccyu 713b1aacad docs(client): synchronize panel navigation APIs and contracts 2026-09-09 00:26:40 +08:00
imccyu 385f651c5f fix(test): release default slot runtime sources symmetrically 2026-09-09 00:26:36 +08:00
imccyu 8715fd2a87 fix(client): preserve the latest panel and session navigation 2026-09-09 00:26:36 +08:00
imccyu bc840b483e feat(client): simplify and exercise sidebar panel entries 2026-09-09 00:26:35 +08:00
imccyu 092d16d7ab style(client): satisfy panel lint rules 2026-09-09 00:26:35 +08:00
imccyu 9736136d95 fix(client): leave global panel entries empty by default 2026-09-09 00:26:34 +08:00
imccyu fbbcbf33fe docs(client): document global main-panel extension points 2026-09-09 00:26:34 +08:00
imccyu f95e781f3d test(client): migrate panel navigation fixtures and snapshots 2026-09-09 00:26:29 +08:00
imccyu fe460f7fd1 test(client): support panel selection in slot runtime 2026-09-09 00:26:29 +08:00
imccyu 581803bf57 feat(client): add global sidebar panels 2026-09-09 00:26:28 +08:00
Yichen Jiang 6d1a20b3cc Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web
# Conflicts:
#	docs/architecture.i18n.yaml
#	docs/architecture.md
#	docs/architecture.zh.md
#	packages/client/ui-settings-plugin-manager/package.json
2026-09-09 00:11:09 +08:00
Yichen Jiang 16cff3321c Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-09 00:08:21 +08:00
Yichen Jiang e755084dfb docs: mirror the regenerated event matrix rows in the zh copy 2026-09-09 00:07:52 +08:00
Yichen Jiang e070e1e074 docs: regenerate the event producer-consumer matrix after the master merge 2026-09-09 00:05:55 +08:00
Yichen Jiang e5feedd14f feat(llm-deepseek-messages): support in-history system prompt updates 2026-09-09 00:05:41 +08:00
Yichen Jiang 8d8a69f423 chore(plugin-manager): align the package versions with release 0.1.5-alpha.1 2026-09-09 00:05:12 +08:00
Yichen Jiang a75db2e521 Merge branch 'feat/plugin-mgmt-1-boot' into feat/plugin-mgmt-2-manager
# Conflicts:
#	docs/architecture.i18n.yaml
#	docs/architecture.md
#	docs/architecture.zh.md
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
2026-09-09 00:05:04 +08:00
Yichen Jiang 5528446814 docs(architecture): point the external-bundle paragraph at the app-boot README
The merged master text put docs/architecture.md over its 2400-word ceiling;
the details this paragraph repeated already live in packages/boot/app-boot.
2026-09-09 00:02:32 +08:00
fz b42b5b5e94 fix(ci): align minimal prompt-history expectations with shell-only turns 2026-09-08 23:57:15 +08:00
Yichen Jiang a8c97e33e5 Merge remote-tracking branch 'origin/master' into feat/plugin-mgmt-1-boot 2026-09-08 23:57:12 +08:00
Yichen Jiang e1c3ec00e2 fix(web): count the scoped mutate branch and draw the breadcrumb separator as a hairline
Awaiting inside each arm of the scope ternary left v8 with a negative else
count on the response check, which the coverage gate read as an uncovered
branch; the request is now chosen first and awaited once. The breadcrumb
separator was a 1px filled divider where every other neutral line is 0.5px.
2026-09-08 23:53:56 +08:00
Yichen Jiang 1f88b9cd8f chore(llm-deepseek-messages): align version with master 2026-09-08 23:44:14 +08:00
Yichen Jiang d21ee05ebb Merge remote-tracking branch 'origin/master' into worktree/llm-deepseek-messages 2026-09-08 23:38:48 +08:00
gengruilin 594305ce19 fix(mcp): reject repeated tool discovery cursors
Refs: https://github.com/deepseek-ai/deepseek-harness/discussions/3660
2026-09-08 23:33:23 +08:00
fz 25d675fcf3 Merge origin/master into feat/remove-str-replace-editor-from-minimal 2026-09-08 23:31:51 +08:00
Dudu-0223 4977ccc965 chore(chunked-list): follow master release version 2026-09-08 23:29:58 +08:00
fz 3c05dcb537 fix(ci): refresh persistent bash fixtures and synchronize LSP lifecycle test 2026-09-08 23:29:03 +08:00
Dudu-0223 5ab91467e2 test(cli): include catalog facts in profile expectations 2026-09-08 23:28:50 +08:00
Dudu-0223 79dda6cf45 test(subagent): align catalog snapshots with Session V3 2026-09-08 23:28:50 +08:00
Dudu-0223 e2fa69f5e2 test(snapshot): bind sibling roles to catalog publication order 2026-09-08 23:28:50 +08:00
Dudu-0223 9f69a7fb16 refactor(subagent): extract persistent chunked list utility 2026-09-08 23:28:50 +08:00
Dudu-0223 661135fe29 fix(subagent): reject invalid catalogs and preserve snapshot event order 2026-09-08 23:28:50 +08:00
Dudu-0223 ba731d1c9e fix(subagent): handle rejected runs after catalog failure 2026-09-08 23:28:50 +08:00
Dudu-0223 867c47c415 docs: drop unrelated projection README whitespace changes 2026-09-08 23:28:50 +08:00
Dudu-0223 59623c8ff4 docs(subagent): refresh event declaration references 2026-09-08 23:28:50 +08:00
Dudu-0223 0274a6dd75 fix(subagent): preserve catalog augmentation in declarations 2026-09-08 23:28:50 +08:00
Dudu-0223 924282cbcd fix(subagent): retain catalog event types in host exports 2026-09-08 23:28:50 +08:00
Dudu-0223 532e712c7b refactor(subagent): expose catalog through existing projection views 2026-09-08 23:28:50 +08:00
Dudu-0223 3dcabbba44 refactor(session-query): return all projection states by default 2026-09-08 23:28:50 +08:00
Dudu-0223 e3cb6dd352 refactor(session): limit hydration views to all or none 2026-09-08 23:28:50 +08:00
Dudu-0223 80e34ce709 perf(subagent): list parent catalog in event order 2026-09-08 23:28:50 +08:00
Dudu-0223 99462aef98 fix(subagent): preserve catalog citations and skip unrequested views 2026-09-08 23:28:50 +08:00
Dudu-0223 399d7313c4 test(session): cover historical catalog comparison failures 2026-09-08 23:28:50 +08:00
Dudu-0223 2db4bdd31d feat(subagent): record and observe parent-owned child catalogs 2026-09-08 23:28:50 +08:00
fz 94ff82f57b Merge origin/master into feat/remove-str-replace-editor-from-minimal 2026-09-08 23:22:25 +08:00
Turtle f830cfd66a Merge remote-tracking branch 'origin/master' into turtle/weighted-approval
# Conflicts:
#	.github/review-ownership/README.md
2026-09-08 21:06:57 +08:00
Turtle c2a5540ddb fix(web): distinguish plugin configuration instances 2026-09-08 21:05:37 +08:00
Turtle 555c04bdfc fix(web): localize Chinese model copy 2026-09-08 21:05:31 +08:00
Turtle 3c21d4c28c fix(client): name collapsed Settings trigger 2026-09-08 20:38:10 +08:00
Turtle c4855581c3 fix: preserve weighted approval review semantics 2026-09-08 20:19:29 +08:00
fz 1f1537914f feat(minimal): align persistent bash output with the one-shot shell contract
The minimal compositions serve the same models that trained against a
one-shot `bash` tool; three surface differences remained visible to them.

- Every settled command now appends `[Command finished with exit code N]`,
  including exit code 0, instead of `[exit code: N]` only on failure. A
  timeout appends `[Command timed out or OOM]` after the partial output.
- Trailing newlines are all dropped before the status trailer rather than
  only the last one.
- The `bash` description in the `minimal` preset and the `sdk-minimal`
  bundle replaces the two fixed network lines with a single environment-
  dependent line; the pwsh description is unchanged.

Tests, READMEs, the web minimal-preset schema snapshot, and the packaged
Python minimal model-visible snapshot follow the new wording. The
standalone `persistent-tools` SDK replay fixture keeps its own copy of the
old description since it is a per-launch customization, not the profile.
2026-09-08 19:48:21 +08:00
Turtle 4550bb6e69 feat: enforce weighted pull request approvals 2026-09-08 19:08:08 +08:00
Yichen Jiang 654ec0d8c1 Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web 2026-09-08 17:51:02 +08:00
Yichen Jiang bb91e042d2 Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-08 17:51:01 +08:00
Yichen Jiang 770f239fc6 Merge branch 'feat/plugin-mgmt-1-boot' into feat/plugin-mgmt-2-manager 2026-09-08 17:51:01 +08:00
Yichen Jiang ea624def34 refactor(web): share the enable switch, the notice line and the form observer plumbing
The duplication gate flagged three clones the plugin manager and the scoped
settings cards had grown: the bundle enable switch on a package's card and
page, the last-operation notice on the package list and a preset's section,
and the subscribe/bind/publish plumbing of CardForm and ScopedCardForms. Each
now has one owner: EnableSwitch, NoticeLine, and the ObservableForm base.
2026-09-08 17:50:31 +08:00
Yichen Jiang a8f2e84946 fix(app-boot): keep the probe's stderr tail across reads of any size
The tail dropped a whole kept chunk whenever a later chunk pushed the total
over the limit, so a flood that arrived as one read (Linux) left only the
bytes written after it. `StreamTail` trims the oldest kept chunk instead and
is unit-tested with both read patterns.
2026-09-08 17:50:29 +08:00
Yichen Jiang 2b01edcd5e Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web 2026-09-08 17:47:17 +08:00
Yichen Jiang e5196d85ed refactor(settings): keep each event's literal dispatch at its call site, share only the delivery loop 2026-09-08 17:46:35 +08:00
07akioni 8874a23b9e feat: 加速 mac sign 2026-09-08 17:44:05 +08:00
Yichen Jiang 5aaf978b19 Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web 2026-09-08 17:38:35 +08:00
Yichen Jiang ff94876574 refactor(settings): share the contained event fan-out between commit and document updates 2026-09-08 17:38:33 +08:00
Yichen Jiang 7a6b69ee25 Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web 2026-09-08 17:34:07 +08:00
Yichen Jiang c7385c588a Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-08 17:32:15 +08:00
Yichen Jiang aee2d84cc5 docs(plugin-manager): name the disabled-bundle record the installer keeps 2026-09-08 17:30:49 +08:00
Yichen Jiang 464264aede Merge branch 'feat/plugin-mgmt-1-boot' into feat/plugin-mgmt-2-manager 2026-09-08 17:30:21 +08:00
Yichen Jiang 07878ae1d3 fix(app-boot): record user-disabled bundles in the profile manifest
`disableBundle` now moves a package from `dsh.profile.bundles` to
`dsh.profile.disabledBundles`, and `reconcileInstalledBundles` enables only
a bundle named in neither list, so an unrelated pnpm run never re-enables a
bundle the user turned off while an update that gives a dependency
`dsh.bundle` still activates it (the built-bin e2e scenario the previous
"new dependencies only" rule broke). The record goes when its dependency
does.

Also: `visitIdentifiedRows` in patch-rows owns the per-patch restatement
tracking that compose-stack and external-bundles had cloned (duplication
gate), and the probe spec's flood fixture retries short and EAGAIN writes
because the child's stderr pipe is non-blocking once tsx touched
process.stderr (the test raced the parent's drain).
2026-09-08 17:29:35 +08:00
Yichen Jiang 9d9b39a41b chore(client): regenerate the slot catalog after the master merge 2026-09-08 17:09:51 +08:00
Yichen Jiang f3f1c7a87d Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web
# Conflicts:
#	packages/bundle/web-app/package.json
#	packages/client/ui-agent-preset/README.i18n.yaml
#	packages/client/ui-agent-preset/README.md
#	packages/client/ui-agent-preset/README.zh.md
#	packages/client/ui-settings-plugin-inventory/README.md
#	packages/client/ui-settings-plugin-inventory/README.zh.md
#	packages/client/ui-settings-plugin-manager/README.i18n.yaml
#	packages/client/ui-settings-plugin-manager/package.json
#	packages/client/ui-settings-plugins/README.i18n.yaml
#	packages/client/ui-settings-plugins/README.md
#	packages/client/ui-settings-plugins/README.zh.md
2026-09-08 17:02:09 +08:00
Yichen Jiang 6d67daf7df Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-08 16:56:55 +08:00
Yichen Jiang 7868fdcf3b chore(plugin-manager): follow the root version bump 2026-09-08 16:55:49 +08:00
Yichen Jiang ca291b0100 docs(plugin-manager): keep the package summaries within the summary budget
master now bounds a README Summary at 100 words; the boot group, the plugin
manager, and its host face say the same in fewer. The zh config catalog gains
the paragraph break the merge dropped.
2026-09-08 16:55:27 +08:00
Yichen Jiang bb408abe28 Merge branch 'feat/plugin-mgmt-1-boot' into feat/plugin-mgmt-2-manager
# Conflicts:
#	apps/cli/src/bin.ts
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/config-catalog.zh.md
#	packages/api/remotes/src/client/index.ts
#	packages/boot/app-boot/src/index.ts
#	packages/boot/app-boot/src/profile.ts
#	packages/host/README.i18n.yaml
#	packages/host/README.md
#	packages/host/README.zh.md
#	scripts/verify-package-readme-model-experience.ts
2026-09-08 16:52:09 +08:00
Yichen Jiang 5a9e1760fd Merge remote-tracking branch 'origin/master' into feat/plugin-mgmt-1-boot
# Conflicts:
#	apps/cli/src/dump-config.ts
#	apps/cli/src/profile-boot.ts
#	docs/capability-seams.i18n.yaml
#	docs/capability-seams.md
#	docs/capability-seams.zh.md
#	packages/boot/app-boot/src/profile.ts
#	packages/util/launch-environment/tests/launch-environment.spec.ts
#	scripts/check-workspace-constraints.ts
#	scripts/gen-cordis-catalog.ts
2026-09-08 16:42:34 +08:00
07akioni 8e4d3bab9f feat: 优化打包方式、启动速度 2026-09-08 16:39:17 +08:00
Yichen Jiang afa57ae093 refactor(boot): keep containment and composition internals off the package root
The root entry now exports only what the CLI, the plugin inventory, the
plugin manager, and tool-cordis use, plus the parameter and result types of
those operations. The contained group and its registry, the external-layer
composition, the row-ownership helpers, the probe format number, and the
runtime option type stay module exports the package's own tests import.
2026-09-08 16:37:16 +08:00
Yichen Jiang af2ebda892 test(web): compose the scaffold's stack with its user-disabled rows
The profile runtime reads user-disabled rows from the committed composition
now, so the e2e scaffold's stack carries the empty set and no longer hands the
runtime a patch reader.
2026-09-08 16:32:20 +08:00
Yichen Jiang 2f181a75ef fix(web): name the package-group title field as a key 2026-09-08 16:29:16 +08:00
Yichen Jiang 4c423bbb68 Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-08 16:28:49 +08:00
Yichen Jiang ec0504dc58 Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web 2026-09-08 16:28:49 +08:00
Yichen Jiang 22f92a8297 test(inventory): give the runtime its install anchor
The profile runtime takes installAnchor since the manager layer; the
user-disabled group test from the boot layer now supplies one.
2026-09-08 16:28:48 +08:00
Yichen Jiang da1bc2523a Merge branch 'master' into worktree/pi-ai-settings-recovery 2026-09-08 16:28:15 +08:00
Yichen Jiang 3787829d75 fix(web): name the confirmation copy map's fields as keys
verify-client-ui-i18n reads a title or description property holding a string
as hardcoded copy; the map holds dictionary keys, so its fields say so.
2026-09-08 16:26:09 +08:00
Yichen Jiang dcbac5ebf2 Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web
# Conflicts:
#	packages/boot/app-boot/src/probe.ts
#	packages/boot/app-boot/tests/probe.spec.ts
2026-09-08 16:25:29 +08:00
Yichen Jiang 16464f5147 Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-08 16:23:34 +08:00
Yichen Jiang 5694e50548 fix(plugin-manager): ask the runtime which rows the user disabled
The view attributes a disabled row through profileRuntime.userDisables, which
walks the groups holding the entry, and the manager spec stops passing the
runtime option the profile runtime no longer takes.
2026-09-08 16:23:33 +08:00
Yichen Jiang 731804affc Merge branch 'feat/plugin-mgmt-1-boot' into feat/plugin-mgmt-2-manager
# Conflicts:
#	packages/boot/app-boot/README.i18n.yaml
#	packages/boot/app-boot/README.md
#	packages/boot/app-boot/README.zh.md
2026-09-08 16:23:03 +08:00
Yichen Jiang c73d88e4e5 fix(boot): answer user-disabled entries from the profile runtime
The inventory keeps dsh-app-boot an optional, type-only peer, so the walk
over an entry's owning groups moves behind ProfileRuntime.userDisables(): a
consumer with the runtime asks it, one without reports composition as before.
The module graph and the cordis catalog follow.
2026-09-08 16:19:42 +08:00
Yichen Jiang d6f5160591 test(boot): type the id-less group row in the ownership spec 2026-09-08 16:16:12 +08:00
Yichen Jiang 792a68468f fix(boot): judge a package's cordis copy by package directory
The probe compared two resolved URLs, which differ for one package under a
source launch (src against lib), across a symlink, and behind the proxy a
packaged executable writes; it now walks each URL up to the cordis manifest,
follows a dsh module proxy to its target, and compares real package
directories, with a probe test for the linked and the proxied case. The README
records that the probe child itself cannot run from a packaged executable.
2026-09-08 16:14:21 +08:00
Yichen Jiang 20102bcd52 fix(boot): commit user-disabled rows with the composition and name a user row's trust
The runtime's user-disabled row ids now come from the committed composition —
composeProfileStack collects them from the user layers it composed — so a
rejected or half-written patch file no longer makes the list disagree with the
running tree or fail to parse. The inventory attributes a row disabled through
a group the user disabled to the user, through the shared userDisablesEntry
walk, and lists a user-layer row the composition left out under the new user
trust instead of builtin.
2026-09-08 16:13:03 +08:00
Yichen Jiang dd0fe585dd Merge remote-tracking branch 'origin/master' into worktree/pi-ai-settings-recovery 2026-09-08 16:07:59 +08:00
Yichen Jiang 6bc5e978ae fix(boot): harden the package probe's child
The probe child now runs with the harness's credential-shaped variables
scrubbed — the one rule every spawner uses, now defined in
dsh-launch-environment and re-exported by dsh-subprocess — and its report is
the one message echoing a per-run token the child removes from its environment,
together with process.send, before importing anything. The failure text keeps
the last 16 KiB of stderr instead of every byte, and the probe settles only on
the child's close, so no pipe or channel outlives the call.
2026-09-08 16:05:39 +08:00
Yichen Jiang 5f0ad7c4b1 fix(boot): keep disabled bundles disabled across runs and catch config-override duplicates
reconcileInstalledBundles now enables only the dependencies a run added, so
a bundle the user disabled keeps its state through an unrelated install or
removal. Row registration records the group each row is declared under: a
config override restates a row only under that group, while the same id twice
in one list or under another group is a duplicate — a contained bundle is left
out and a built-in layer fails loud, instead of the Loader rejecting the update
or moving the row at mount.
2026-09-08 16:01:05 +08:00
Yichen Jiang aa3a1c2b4a Merge remote-tracking branch 'origin/master' into worktree/llm-deepseek-messages
# Conflicts:
#	packages/llm/llm-deepseek/README.i18n.yaml
#	packages/llm/llm-deepseek/README.md
#	packages/llm/llm-deepseek/README.zh.md
2026-09-08 15:58:22 +08:00
Yichen Jiang 914dec6fea test(web): refresh Messages composer and timezone snapshots 2026-09-08 15:55:07 +08:00
Yichen Jiang e52ffcea87 Merge remote-tracking branch 'origin/master' into worktree/llm-deepseek-messages 2026-09-08 15:49:35 +08:00
Yichen Jiang 9addbf63e6 merge: adapt job controls to the parent registry API 2026-09-08 15:48:59 +08:00
Yichen Jiang 3df99217dc refactor(jobs): restore direct calls and align remote names 2026-09-08 15:44:48 +08:00
Yichen Jiang c9a702a267 Merge remote-tracking branch 'origin/master' into worktree/pi-ai-settings-recovery 2026-09-08 15:42:48 +08:00
Yichen Jiang dad135dd41 Merge remote-tracking branch 'origin/master' into worktree/pi-ai-settings-recovery 2026-09-08 15:42:25 +08:00
creatixchu 8ccf82cbf2 Merge remote-tracking branch 'origin/master' into worktree/3041-image-offload-log-design 2026-09-08 15:22:06 +08:00
creatixchu 4779f054b6 refactor(compaction): own image offload as a compaction executor
Move the IMAGE_OFFLOAD_REQUIRED recovery out of llm-retry into the new
@deepseek-ai/dsh-compaction-image-offload package, a sibling of the
tool-result pruner: image offload is compaction in another capacity
dimension. Each replaced node is priced through the seam's compaction/prune
shadow-price protocol before its marked copy lands. llm-retry returns to
master; the base bundle mounts the executor.
2026-09-08 15:10:16 +08:00
Yichen Jiang 29418faf62 fix(shell): settle a live handle's post-termination rejection as its outcome
The subprocess runtime rejects a handle's done with the cancellation reason
when it terminated the managed range before the target started, which the
Windows runner does whenever an abort or kill() races the launch. Both
executors filed that rejection as a provider failure, so result() re-threw
the caller's own AbortError instead of resolving the aborted or killed
classification. A live handle whose rejection follows this execution's own
kill() or spawn-signal abort now settles as that terminal outcome; a
synchronous spawn throw, which never produced a handle, stays a failure.
2026-09-08 14:45:41 +08:00
Yichen Jiang 9a8ea5eaf1 Merge branch 'worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery 2026-09-08 14:39:29 +08:00
Yichen Jiang f2f696c358 test(bash-sandbox): expect the merged provider-failure note for a synchronous ENOEXEC
The background branch of the synchronous ENOEXEC case still looked for the
pre-merge `spawn failed:` note; the merged providers render master's
stage-neutral `subprocess failed before reporting an outcome:` on that
path.
2026-09-08 14:38:35 +08:00
Yichen Jiang fe24dddea8 Merge remote-tracking branch 'origin/master' into worktree/process-plugin-streaming-72f9b3 2026-09-08 14:36:54 +08:00
creatixchu 6b673aedf5 docs(llm): drop the last watermark wording from llm-streaming and the retry test title 2026-09-08 14:08:47 +08:00
Yichen Jiang f3cf2efc97 Merge branch 'worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery 2026-09-08 13:53:00 +08:00
Yichen Jiang 80fa0bee05 Merge branch 'worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery
# Conflicts:
#	packages/shell/bash-local/README.i18n.yaml
#	packages/shell/bash-local/README.md
#	packages/shell/bash-local/README.zh.md
#	packages/shell/bash-local/src/index.ts
#	packages/shell/bash-local/tests/executor.spec.ts
#	packages/shell/pwsh-local/README.i18n.yaml
#	packages/shell/pwsh-local/README.md
#	packages/shell/pwsh-local/README.zh.md
#	packages/shell/pwsh-local/src/index.ts
#	packages/shell/shell/README.i18n.yaml
#	packages/shell/shell/README.md
#	packages/shell/shell/README.zh.md
#	snapshots/session/pwsh-tool-turn/tool-schemas.expected.json
2026-09-08 13:52:08 +08:00
fz 61cd1a3f91 Merge origin/master into feat/remove-str-replace-editor-from-minimal 2026-09-08 13:51:47 +08:00
Yichen Jiang 1f4d165aa2 test(snapshot): release the ACP diagnostic hold from the caller-bound wait
The scenario's barrier plugin patched ctx.jobs.wait, which the consolidated
seam no longer has: waits live on the operations forCaller hands out, so
the hold file was never removed and the mock ACP server never released the
prompt. The barrier now wraps forCaller and releases on that view's wait.
2026-09-08 13:51:16 +08:00
creatixchu c755e3e501 Merge remote-tracking branch 'origin/master' into worktree/3041-image-offload-log-design 2026-09-08 13:50:32 +08:00
Yichen Jiang da313e4fdc fix(llm-pi-ai): preserve actionable model diagnostics 2026-09-08 13:35:09 +08:00
Yichen Jiang 1242fdfdef Merge remote-tracking branch 'origin/master' into worktree/process-plugin-streaming-72f9b3
# Conflicts:
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	docs/subsystems/shell.i18n.yaml
#	docs/subsystems/shell.md
#	docs/subsystems/shell.zh.md
#	packages/api/remotes/package.json
#	packages/api/remotes/src/client/index.ts
#	packages/api/session-controller/src/control.ts
#	packages/api/session-controller/tests/control-jobs.host.spec.ts
#	packages/bundle/web-app/cordis.patch.yml
#	packages/bundle/web-app/package.json
#	packages/client/ui-chat/src/client/details/DetailsPanel.tsx
#	packages/client/ui-chat/src/client/details/tool-node-reader.ts
#	packages/client/ui-chat/tests/gate-branch-tails.client.spec.tsx
#	packages/client/ui-jobs/package.json
#	packages/client/ui-tool/tests/diff-card.client.spec.tsx
#	packages/client/ui-tool/tests/read-card.client.spec.tsx
#	packages/client/ui-tool/tests/search-card.client.spec.tsx
#	packages/client/ui-tool/tests/terminal-card.client.spec.tsx
#	packages/client/ui-tool/tests/web-card.client.spec.tsx
#	packages/shell/bash-local/README.i18n.yaml
#	packages/shell/bash-local/README.md
#	packages/shell/bash-local/README.zh.md
#	packages/shell/bash-local/src/index.ts
#	packages/shell/bash-local/tests/executor.spec.ts
#	packages/shell/pwsh-local/README.i18n.yaml
#	packages/shell/pwsh-local/README.md
#	packages/shell/pwsh-local/README.zh.md
#	packages/shell/pwsh-local/src/index.ts
#	packages/shell/shell/README.i18n.yaml
#	packages/shell/shell/README.md
#	packages/shell/shell/README.zh.md
#	packages/shell/shell/src/types.ts
#	packages/terminal/tool-terminal/tests/tools.spec.ts
#	tsconfig.client.json
2026-09-08 13:34:53 +08:00
Yichen Jiang e23030cb30 fix(web): show an install's removal runs in its dialog
The Host removes a rejected package under that package's name, so its
pnpm run streamed under a spec the dialog did not match and never showed.
The Host runs one mutation at a time: while the dialog's install is in
flight every chunk is its own, so the spec filter goes.
2026-09-08 13:27:27 +08:00
Yichen Jiang 07589e1c32 feat(web): render each pnpm run of an install as a terminal
The install dialog draws every pnpm run with the shared TerminalBlock: the
command line, pnpm's coloured output streaming in while it runs, the exit
code when it is not zero, and a line naming the profile directory it installs
into. A finished run leaves Done as the only action; editing the spec starts
over, and a failed run offers Retry.

TerminalBlock now shows the output printed so far while a command runs and
knows a settle without an exit code; cyan and bright cyan map onto two static
blues so pnpm's numbers stay legible on the light theme.
2026-09-08 13:19:09 +08:00
Yichen Jiang eb2ee55f83 Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web 2026-09-08 13:16:06 +08:00
Yichen Jiang cbd835f13e Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-08 13:16:04 +08:00
Yichen Jiang 6605c4de48 feat(plugin-manager): name the profile directory on install-log chunks
Every chunk now carries the directory pnpm ran in beside its argv, so a
renderer can say where the install lands. The generated event graph and the
cordis API catalog follow the chunk type.
2026-09-08 13:16:03 +08:00
Huanqi Cao a39d309187 fix(directory-picker-native): foreground-activate the Win32 folder dialog via a synthesized Alt press 2026-09-08 13:10:03 +08:00
Yichen Jiang 26abe2c82e Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web 2026-09-08 13:03:56 +08:00
Yichen Jiang d56ba7b995 Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-08 13:03:55 +08:00
Yichen Jiang 5953d2920c docs(plugin-manager): give the README installer example its colour option 2026-09-08 13:03:55 +08:00
Yichen Jiang fc20624b69 Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web 2026-09-08 12:55:08 +08:00
Yichen Jiang 0b2690004e Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-08 12:55:07 +08:00
Yichen Jiang 080e22ee03 feat(plugin-manager): keep pnpm's colours and name the command on install-log chunks
The installer now decides pnpm's colouring per consumer: the Web host keeps
colours on for the install dialog's terminal, the CLI turns them on only when
stdout is a terminal, and a plain log strips what a colour=always pnpm still
prints. Every chunk carries the argv it came from, so a renderer can label
each pnpm run.
2026-09-08 12:52:45 +08:00
creatixchu c75e100893 fix(client): share the shield contour and describe the menu glyphs by shape
The permission selector and IconShieldOutline16 now read one exported
SHIELD_OUTLINE_PATH; the icon-set header no longer claims every glyph is
filled; the three menu glyph docs name what they draw and where they are
used; the compact ring matches the set's extent; the icon pin asserts the
three names.
2026-09-08 12:47:21 +08:00
creatixchu 5b1bb021cf feat(web): group, localize, and re-present the composer command menu
The + button and a typed / open one menu with an Add section (File, Goal,
Plan, Feedback) and a Commands section (Compact, Permission, Model, Export)
in usage order; rows carry a glyph, a localized title and description, and
the command name as an alias where the localized title differs. Built-in
Host rows get their face from the ui-commands dictionaries when the catalog
description is the canonical English text. A menu pick fills the locale's
claim token (/计划 ) while the submission executes the catalog name, and a
typed localized token resolves on Space and Enter in every locale. The File
row is a new action contribution kind that opens the composer's file picker
through the scoped slash/input-pick-files event; the paperclip button is
removed and the + button reads "Add files or run commands".
2026-09-08 12:28:40 +08:00
creatixchu 2c9eda5b6f feat(client): add plan, compact, and shield glyphs for the composer menu 2026-09-08 12:05:06 +08:00
Yichen Jiang 8dc30d270c test(llm-pi-ai): cover recovery diagnostics and document repair limits 2026-09-08 12:04:18 +08:00
creatixchu 6329c53a37 refactor(llm-retry, session): offload images by surface replacement instead of a watermark event
Drop the image/offload event and every session change with it. An adapter's
IMAGE_OFFLOAD_REQUIRED failure now makes dsh-llm-retry replace the surface
nodes carrying the named oldest images with copies whose blocks are marked
offloaded, through the same surfaceOp: replace compaction uses, then retry the
step. ImageBlock.offloaded becomes a durable field the routes project and the
token meter prices; the session core, its event map, derivation, and
validation return to master.
2026-09-08 12:00:35 +08:00
Yichen Jiang e37f47fc53 fix(web): ask what depends on a row or a pack before any dialog opens
A disable — of a pack or of one row — used to open the confirmation at
once, showing "checking" until the Host answered, and close it again when
nothing depended on the target: a flash of a dialog for every switch-off
that needed none. The Host is now asked first, with the switch inert
meanwhile, and the dialog opens only for a target something depends on; an
uninstall keeps opening at once, since it is always confirmed. A check
that fails on the wire no longer stands between the person and the
action they asked for.
2026-09-08 11:54:07 +08:00
Yichen Jiang b327f58108 Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web 2026-09-08 11:43:11 +08:00
Yichen Jiang e5892dc40a Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-08 11:41:44 +08:00
Yichen Jiang 43ba51d585 docs(graphs): list app-boot among the consumers of internal/status
The contained group now listens for fiber activation, and the generated
event graph names it.
2026-09-08 11:41:17 +08:00
Yichen Jiang 24244f3a7e Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web 2026-09-08 11:38:01 +08:00
Yichen Jiang df41c01ab7 Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-08 11:37:24 +08:00
Yichen Jiang 4d83c2c71f fix(boot): drop a row's recorded wait once its service appears
A contained row left pending is recorded as waiting for a service, but a
live recomposition that brings the service back — a sibling row switched
on again — activates the fiber in place, with no create() to clear the
record, so the registry kept reporting a wait that was over. The group now
watches fiber states once it has recorded a wait and clears the record
when that row's fiber comes to life.
2026-09-08 11:36:33 +08:00
Yichen Jiang 107d07614a feat(web): ask before switching a row off that other rows depend on
Switching a row off first asks the Host what other rows inject of what the
row provides — the package-level dependents answer filtered to the services
this row provides — and waits for the same confirmation a pack's disable
uses, naming those rows; a row nothing depends on switches off at once, and
switching on never asks. A row whose fiber is active is running whatever
record the failure registry still holds for it, so a stale wait no longer
reads as waiting once the service it waited for is back.
2026-09-08 11:36:08 +08:00
Yichen Jiang fa48b101d2 test(web): align Messages snapshot with Sidebar 2026-09-08 11:33:58 +08:00
fz ad05ed6ad8 docs(minimal): describe current editor availability 2026-09-08 11:33:24 +08:00
Yichen Jiang db63b2be7f Merge remote-tracking branch 'origin/master' into worktree/llm-deepseek-messages 2026-09-08 11:30:28 +08:00
Yichen Jiang 6148b6ddba feat(web): read a row's wait for a service as one state
A row waiting for a service another row provides reads the same whether a
live recomposition left its fiber pending or a fresh composition recorded
the wait as an inject-pending failure: waiting for a dependency, on the
row, in the count line, and on the pack's tag in warning tone, with the
pack's reason line left to the row that explains it; the red problem is
kept for a real failure. A module's note about where it is composed now
wraps under its name, so a long list of presets no longer squeezes the
name into a column, and the module's own Add to… is all that sits at the
right.
2026-09-08 11:20:07 +08:00
Yichen Jiang 5bc792f629 refactor(llm): keep diagnostics in configurable provider metadata 2026-09-08 10:55:53 +08:00
Yichen Jiang acbb8e0a06 feat(web): group the plugin list by packs and plugins, and quiet the row states
The list splits into Plugin packs and Plugins, each with its count, in
place of one Installed group; a library counts among the plugins. Retry
and uninstall close a package's page at its bottom-right as outlined
buttons, uninstall in red. A row that is off says so in two words: Off
when the person switched it off, Off by default when the pack keeps it
off; the reason it cannot be switched on stays on the locked switch.
2026-09-08 10:54:31 +08:00
Yichen Jiang a12d30df2a refactor(llm-pi-ai): reuse settings validation for startup recovery 2026-09-08 10:47:05 +08:00
creatixchu 52386ec6fb test(llm-retry): follow agent loop testkit dependencies 2026-09-08 10:46:02 +08:00
Yichen Jiang ddb15a11a4 fix(web): drop the grid rules the row restyle left behind
The earlier row block stayed in the stylesheet beside the new one, so a
row still laid out as a three-column grid and squeezed its whole line into
the seven-pixel first column, one character per line.
2026-09-08 10:42:52 +08:00
creatixchu 73cee076fb Merge remote-tracking branch 'origin/master' into codex/pr-3440-resync-20260908 2026-09-08 10:37:36 +08:00
Yichen Jiang 2df9414138 feat(web): style a pack's rows as entries and drop the done notice
Each row on a package's page is an entry: a plugin icon, the row id over
the module it loads, its state with a dot at the right, then its switch;
rows sit on the page ground one hairline apart, so they read on a white
page too, where the filled bars vanished. A failure keeps its own line
under the entry. The modules a plugin declares addable read the same way.

A finished enable, disable, retry, uninstall, or added row no longer posts
a notice: the re-read list shows the new state, and only a restart the
change waits for, or a failure, has something to say.
2026-09-08 10:36:53 +08:00
Yichen Jiang 642b538fe0 Merge remote-tracking branch 'origin/master' into worktree/pi-ai-settings-recovery 2026-09-08 10:34:14 +08:00
Yichen Jiang fe03b0686d fix(llm-pi-ai): keep catalog-invalid settings repairable 2026-09-08 10:28:45 +08:00
Yichen Jiang 483e6b4920 feat(web): give every plugin package its own page
A card keeps the summary — name, one-liner, tags, its switch or Add to… —
and opens the package's page behind a crumb, as a preset card opens its
detail page: the version and source; a pack's rows as a list, every row on
one line with its state, its failure when one is recorded, and its switch
where the pack is switchable, with a filter past ten rows; the built-in
rows the pack changes; the modules the package declares addable, each
saying where it is composed, with an Add to… of its own; and retry and
uninstall. The expanded card and its component chips are gone with it.
2026-09-08 00:20:07 +08:00
Yichen Jiang 4032e87014 Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web 2026-09-07 23:53:44 +08:00
Yichen Jiang e023a43ddd Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-07 23:52:17 +08:00
Yichen Jiang 8a0aeccccc docs(plugin-manager): make the README examples self-contained
The two `ts` fences declare their inputs and import what they use, so the
doc-typecheck gate compiles them against the workspace API instead of
failing on the names the surrounding prose supplied.
2026-09-07 23:51:44 +08:00
Yichen Jiang f4f734964a feat(web): switch a plugin pack's components one by one
Each component chip of an external pack composed on a live-reload profile
carries a Switch that calls plugins.setRowDisabled against the profile's
global user layer: off writes `disabled: true` for the row id, on deletes
the key, and the tree recomposes at once while the rest of the pack keeps
running. A component the pack itself keeps off is locked with the reason,
since the user layer only denies; a failing component can be switched off;
a row another layer owns has nothing to switch. Built-in packs, packs that
are off, and profiles that apply patches at their next start keep the
read-only chips. Only the row with a write in flight goes inert.
2026-09-07 23:51:40 +08:00
fz 707d0e7e52 Merge origin/master into feat/remove-str-replace-editor-from-minimal 2026-09-07 23:25:03 +08:00
fz b92cc94122 test(minimal): cover documented editor opt-in 2026-09-07 22:56:48 +08:00
Yichen Jiang 74ef3f0510 fix(llm): degrade unusable Messages replay metadata 2026-09-07 21:32:06 +08:00
Yichen Jiang c258d3cf4e feat(web): use Messages for the default DeepSeek provider 2026-09-07 20:57:23 +08:00
creatixchu e44eb89065 test(llm-retry): cover the surface node that derives no message 2026-09-07 20:19:30 +08:00
creatixchu 523ae08a2d refactor(session, llm): cut the image offload surface to its callers
Drop Session.imageOffloadWatermark(), which no production code read once
recovery moved to llm-retry; shorten the append and seed validators; keep
offloadedImagePrefixCount and the represented-bytes arithmetic private to
requiredImageOffload, their only caller.
2026-09-07 20:18:56 +08:00
Yichen Jiang 57c6e7e9b2 fix(web): remove Messages endpoint helper text 2026-09-07 20:09:16 +08:00
Yichen Jiang 23fa53ecbc Merge master release and align Messages package version 2026-09-07 19:55:51 +08:00
fz 110db78707 Merge origin/master into feat/remove-str-replace-editor-from-minimal 2026-09-07 19:53:33 +08:00
fz 5c98a81a50 test(benchmarks): explicitly compose the SDK file editor 2026-09-07 19:43:49 +08:00
Yichen Jiang d28286938d feat(web): configure DeepSeek Messages beside Chat Completions 2026-09-07 19:39:37 +08:00
Yichen Jiang 9e9cf88ff7 Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web
# Conflicts:
#	packages/boot/plugin-manager/src/index.ts
2026-09-07 19:33:51 +08:00
fz d3281d0218 docs(minimal): explain editor opt-in configuration 2026-09-07 19:33:48 +08:00
Yichen Jiang 0b2d4886ab Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-07 19:31:50 +08:00
Yichen Jiang e0841bec01 refactor(plugin-manager): split the manager module by responsibility
`src/index.ts` held the installer, the manager, the view fold, and every
helper in one 1100-line file. It is now the package API alone, re-exporting
from `installer.ts` (pnpm runs, the probe cache, post-install checks),
`manager.ts` (every operation over the booted profile and the mutex),
`view.ts` (the package view fold and the row-ownership walk the dependents
query shares), `modules.ts` (declared-module row naming and views), and
`helpers.ts` (the diagnostic prefix, tooling bounds, spawn seam, and manifest
readers). The public surface, the tests, and the failure codes are unchanged.
2026-09-07 19:30:44 +08:00
fz 71a291cbc4 Merge origin/master into feat/remove-str-replace-editor-from-minimal 2026-09-07 19:28:12 +08:00
Yichen Jiang 34154b6861 feat(llm): add DeepSeek Anthropic Messages adapter 2026-09-07 19:20:29 +08:00
Yichen Jiang 0eff068ec4 Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web 2026-09-07 18:06:52 +08:00
Yichen Jiang bff6719fca Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/module-graph.i18n.yaml
2026-09-07 18:06:21 +08:00
Yichen Jiang 7af9c25737 refactor(app-boot): fold the patch-file parser and writer into app-boot
The `cordis.patch.yml` parser and the comment-preserving writer are the
Loader's format, not a mechanical primitive: they build on the include
plugin's dialect and the Loader's row types, which no other `util` package
does. They now live in `app-boot` as `src/patch-file.ts`, exported as
`@deepseek-ai/dsh-app-boot/patch-file` with its own bundle entry, so the
agent-preset roster and the plugin manager load them without the boot entry.
`dsh-patch-file` goes, with its README and catalog entries; `yaml` moves into
app-boot's dependencies.

A dozen plugin packages already depend on `dsh-app-boot`, so the roster
joining them costs nothing; the note records why the separate package was
tried and folded back.
2026-09-07 18:05:06 +08:00
Yichen Jiang 3af0c5f7fd Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web
# Conflicts:
#	.agents/notes/implemented/architecture/2026-09-04-plugin-manager-over-the-profile-runtime.i18n.yaml
#	.agents/notes/implemented/architecture/2026-09-04-plugin-manager-over-the-profile-runtime.md
#	.agents/notes/implemented/architecture/2026-09-04-plugin-manager-over-the-profile-runtime.zh.md
#	packages/host/plugin-manager/README.i18n.yaml
#	packages/host/plugin-manager/README.md
#	packages/host/plugin-manager/README.zh.md
#	packages/host/plugin-manager/src/index.ts
#	packages/host/plugin-manager/tests/plugin-manager.spec.ts
2026-09-07 17:53:20 +08:00
Yichen Jiang 2db66f10f4 Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/event-producer-consumer.i18n.yaml
#	docs/module-graph.i18n.yaml
2026-09-07 17:48:46 +08:00
Yichen Jiang 7b713ca83b refactor(plugin-manager): move plugin management out of the Web host
What plugin management does now lives in `dsh-plugin-manager`, a boot-group
package beside `app-boot`: `PluginInstaller` runs pnpm, probes, and judges new
packages over the profile on disk, and `PluginManager` adds every operation
over the booted tree, each refusal a `PluginOperationError` with a `plugins/*`
code and no Remote protocol attached. The manager reads the profile runtime,
the preset roster, and the running-agent count through per-call readers, and
the roster only as `PresetLayers`, so the package depends on neither the
roster nor the agent registry.

`dsh-host-plugin-manager` keeps `pluginManager` and the `plugins` Remote as a
relay: one Remote method per manager method, and one exhaustive switch
turning a failure into the Remote error of the same code (`plugins/bad-request`
into `gateway/bad-request`). Its `./types` re-exports the manager's types, so
`api-remotes` and the client import one vocabulary unchanged.

`dsh plugin add` and `remove` now run the installer instead of a bare pnpm
forwarder: every new package is probed, a package that declares neither a
bundle nor a plugin module is removed again with its reason, and newly
installed bundles are enabled as before. Other pnpm verbs still forward.
2026-09-07 17:47:08 +08:00
creatixchu ab93bfd90c refactor(session): fold the image offload helpers into surface.ts and index.ts
The watermark marking and position comparison sit next to deriveEventMessage
in surface.ts; the append/seed validation sits with the other event validators
in index.ts and the fold is inline. Only compareImagePositions stays exported.
2026-09-07 17:35:28 +08:00
creatixchu fcb976d3dc refactor(llm): recover IMAGE_OFFLOAD_REQUIRED in llm-retry instead of a new plugin package
Remove the llm-image-offload package and every registration it needed. The
recovery branch lives in dsh-llm-retry, which already sits on the
agent/request-error waterfall: an IMAGE_OFFLOAD_REQUIRED failure advances the
image/offload watermark by the count the adapter names and retries the step
outside the provider retry budget. Drop pre-dispatch planning with it: routes
no longer declare a request-image budget on their model info, and the byte
checks that stay in the DeepSeek and pi-ai adapters are provisional until the
provider reports uncacheable images itself.
2026-09-07 17:03:23 +08:00
Yichen Jiang 6a3582fe93 Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web 2026-09-07 16:32:08 +08:00
Yichen Jiang 89fb3ef083 Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/module-graph.i18n.yaml
2026-09-07 16:31:43 +08:00
Yichen Jiang 42764971ca refactor(agent-presets): remove the global-tool-mask package nothing composes
`dsh-global-tool-mask` wrapped `tools.restrict()` as a composition row so a
preset's user patch layer could hide a host tool. No shipped preset, the
plugin manager, and the settings UI compose such a row, so the package had a
README, a test, and no consumer. It goes, with its `apps/cli` dependency,
its `tsconfig.host.json` reference, the README example that named it, and the
generated catalogs. `tools.restrict()` stays: subagent tool filters call it.

Hiding a host tool from one preset is a per-preset setting for the
scope-resolved settings of the next layer, not a hand-written row; the Agent
Note records the removal under alternatives considered.
2026-09-07 16:29:41 +08:00
creatixchu cea09de58c Merge remote-tracking branch 'origin/master' into worktree/3041-image-offload-log-design 2026-09-07 15:58:23 +08:00
creatixchu 8c7b023d6c refactor(llm): move image offload planning into a plugin and trim the change surface
Keep the agent loop unchanged: the new @deepseek-ai/dsh-llm-image-offload
plugin plans the image/offload watermark on agent/pre-step from the routed
model's budget and advances it on agent/request-error when an adapter fails
with IMAGE_OFFLOAD_REQUIRED, returning the retry action the loop already
honours. Drop PreparedLlmCall.imageRequest and its validation, the planner
wrapper, the replay adapter's imageRequestMaxBytes option, and the duplicate
ACP snapshot scenario; share the exact-byte overflow count between the
DeepSeek and pi-ai adapters through requiredImageOffload(). The SDK image
snapshot replays an authored IMAGE_OFFLOAD_REQUIRED attempt instead of a
replay-only budget.
2026-09-07 15:58:20 +08:00
creatixchu 6b3681ae44 Merge remote-tracking branch 'origin/master' into worktree/3041-image-offload-log-design
# Conflicts:
#	docs/architecture.i18n.yaml
#	docs/architecture.md
#	docs/architecture.zh.md
2026-09-07 14:59:46 +08:00
creatixchu b6cb4609b6 Merge remote-tracking branch 'origin/master' into worktree/3041-image-offload-log-design 2026-09-07 14:40:05 +08:00
creatixchu 74f380806f test(snapshot): follow persona prefix config 2026-09-07 14:13:01 +08:00
creatixchu e147077526 Merge remote-tracking branch 'origin/master' into worktree/3041-image-offload-log-design 2026-09-07 14:08:26 +08:00
creatixchu fdbeeddc36 fix(session): tolerate contentless synthetic messages 2026-09-07 13:01:19 +08:00
creatixchu 5e277c2111 test(session): close image offload coverage gaps 2026-09-07 12:51:09 +08:00
creatixchu 57a3701a22 Merge remote-tracking branch 'origin/master' into worktree/3041-image-offload-log-design 2026-09-07 12:35:43 +08:00
creatixchu 60f9d9b936 Merge master and address image offload review 2026-09-07 12:27:48 +08:00
Yichen Jiang 9f8373df2b Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web
# Conflicts:
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.zh.md
2026-09-07 11:53:38 +08:00
Yichen Jiang 9037aeba88 Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings
# Conflicts:
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
2026-09-07 11:49:22 +08:00
Yichen Jiang c22d66ffd8 Merge branch 'feat/plugin-mgmt-1-boot' into feat/plugin-mgmt-2-manager 2026-09-07 11:46:01 +08:00
Yichen Jiang 84006d8d1f Merge remote-tracking branch 'origin/master' into feat/plugin-mgmt-1-boot 2026-09-07 11:44:35 +08:00
Yichen Jiang c58b23e44c Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web 2026-09-07 11:40:46 +08:00
Yichen Jiang 05187bdc6c Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-07 11:39:49 +08:00
Yichen Jiang 870aa6143f Merge branch 'feat/plugin-mgmt-1-boot' into feat/plugin-mgmt-2-manager 2026-09-07 11:39:22 +08:00
Yichen Jiang 66a9d0e7c3 test(inventory): compare listed entries in id order, as a digit-only assigned id reorders the store 2026-09-07 11:38:49 +08:00
Yichen Jiang 77846832de Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-07 11:35:27 +08:00
Yichen Jiang 4bf9dc3bcb Merge branch 'feat/plugin-mgmt-1-boot' into feat/plugin-mgmt-2-manager
# Conflicts:
#	packages/boot/app-boot/README.i18n.yaml
#	packages/boot/app-boot/README.md
#	packages/boot/app-boot/README.zh.md
#	packages/boot/app-boot/src/index.ts
2026-09-07 11:34:57 +08:00
Yichen Jiang aaf58eb5bf fix(boot): own the rows a config override sets, queue recompositions, and let records follow the configuration
Second review round on the contained-group composition:

- Ownership scanned only `insert` rows, so an external bundle could set a
  built-in row's id as a child through `{ id: own, config: [...] }` and the
  Loader re-parented that row under the bundle while `originOf` still named
  the built-in layer. The rows an id-targeted patch sets as a group's config
  now count as the layer's own: an external bundle that sets an id another
  layer owns is left out whole, a built-in layer that takes another layer's
  id fails loud, and a layer restating its own child is not a repeat.
- `recompose` read the committed profile before awaiting the update, so a
  watcher firing while a bundle was being enabled composed the tree before
  the enable and applied it after; the plugin vanished while `layers` kept
  listing it. Recompositions now queue, each reading what the previous one
  committed, and a rejection stays its own caller's outcome.
- A patch that replaced a built-in target's config removed the wrapper the
  bundle had put there, yet later inserts still targeted the detached
  wrapper and vanished. The composition forgets the wrapper on such an
  override and creates a new one under the same id.
- Generated wrapper ids bypassed the duplicate check, so a bundle declaring
  a row spelled like a wrapper produced two nodes with one id. Declared and
  generated ids now go through one registration.
- Failure records outlived their rows when a bundle update dropped a failed
  row without unmounting the group, or when a pending row sat in a plain
  nested group whose id the record named. A contained group now drops the
  records of rows its configuration no longer names after each update, and
  the audit records every row under the contained group that isolates it.
- `applyEntryPatches` assigned override values by reference, so applying a
  patch list carried a later insert's rows back into the patch object; the
  vendored include now clones object-valued overrides as it does inserts.
2026-09-07 11:28:19 +08:00
Yichen Jiang 6371bc4a41 Merge branch 'worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.zh.md
2026-09-07 10:44:53 +08:00
Yichen Jiang bf91cd855e Merge remote-tracking branch 'origin/master' into worktree/process-plugin-streaming-72f9b3
# Conflicts:
#	.agents/notes/archived/manifest.json
#	.agents/notes/implemented/architecture/2026-06-20-generic-long-running-tool-runtime.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-20-generic-long-running-tool-runtime.md
#	.agents/notes/implemented/architecture/2026-06-20-generic-long-running-tool-runtime.zh.md
#	.agents/notes/implemented/bug-fix/2026-09-05-nested-terminal-cards.i18n.yaml
#	.agents/notes/implemented/feature/2026-08-11-background-job-completion-wakes-an-idle-owner.i18n.yaml
#	.agents/notes/implemented/testing/2026-09-06-standard-hosted-benchmark-runner.i18n.yaml
#	docs/architecture.i18n.yaml
#	docs/capability-seams.i18n.yaml
#	docs/config-catalog.i18n.yaml
#	docs/cookbook/adding-a-tool.i18n.yaml
#	docs/event-producer-consumer.i18n.yaml
#	docs/module-graph.i18n.yaml
#	docs/persistence-catalog.i18n.yaml
#	docs/subsystems/shell.i18n.yaml
#	packages/client/ui-primitives/README.i18n.yaml
#	packages/jobs/jobs-local/README.i18n.yaml
#	packages/jobs/jobs/README.i18n.yaml
#	packages/jobs/jobs/README.md
#	packages/jobs/jobs/README.zh.md
#	packages/jobs/tool-jobs/README.i18n.yaml
#	packages/shell/tool-bash/README.i18n.yaml
#	packages/shell/tool-pwsh/README.i18n.yaml
2026-09-07 10:39:56 +08:00
pku-xht fdeeacef74 fix(web): revoke withdrawn permission choices 2026-09-06 09:32:09 +08:00
pku-xht 197161e660 fix(permission): simplify Auto identity and teardown 2026-09-06 07:14:09 +08:00
pku-xht 0861ee11f7 test(permission): cover Auto lifecycle and inheritance boundaries 2026-09-06 05:29:42 +08:00
pku-xht cdce3a9137 Merge master to restore required CI scheduling 2026-09-06 04:34:20 +08:00
pku-xht 2505fcaf97 fix(auto-review): align risk policy and core certification 2026-09-06 04:16:13 +08:00
fz 40539e9002 Merge origin/master into feat/remove-str-replace-editor-from-minimal 2026-09-06 00:58:49 +08:00
Yichen Jiang 54d5b2ff8b Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web
# Conflicts:
#	packages/boot/app-boot/src/probe.ts
2026-09-05 22:55:38 +08:00
Yichen Jiang 8c257a2c0c Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-05 22:49:37 +08:00
Yichen Jiang 59e2afc2e3 Merge branch 'feat/plugin-mgmt-1-boot' into feat/plugin-mgmt-2-manager 2026-09-05 22:46:57 +08:00
Yichen Jiang 6f524b6d8c Merge branch 'feat/plugin-mgmt-1-boot' into feat/plugin-mgmt-2-manager
# Conflicts:
#	apps/cli/src/profile-boot.ts
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/config-catalog.zh.md
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	docs/subsystems/core.i18n.yaml
#	packages/boot/app-boot/README.i18n.yaml
#	packages/boot/app-boot/README.md
#	packages/boot/app-boot/README.zh.md
#	packages/boot/app-boot/package.json
#	packages/boot/app-boot/src/contained-group.ts
#	packages/boot/app-boot/src/index.ts
#	packages/boot/app-boot/src/probe.ts
#	packages/boot/app-boot/src/profile-runtime.ts
#	packages/boot/app-boot/tests/profile-runtime.spec.ts
#	packages/host/plugin-inventory/tests/inventory.spec.ts
#	pnpm-lock.yaml
#	scripts/verify-package-readme-model-experience.ts
#	tsconfig.base.json
2026-09-05 22:46:55 +08:00
Yichen Jiang 8357838bc5 fix(include): detach inserted rows so re-applying a patch list mounts the same tree
`applyEntryPatches` pushed a patch's `insert` rows into the entry list by
reference, so a later patch that inserted into a group an earlier patch had
inserted mutated the patch's own object. With bundle rows now inserted into
their group by a separate patch, the Loader's rollback of a rejected update
re-applied the previous include config over those mutated objects and hit
`duplicate loader entry id`; the rollback failed and the rejection reason
named it instead of the row that broke. Inserted rows are now cloned before
they join the list, as the function's detachment contract already stated;
the vendored change is logged and pinned by an application-twice test.
2026-09-05 22:44:30 +08:00
Yichen Jiang 613adbb231 docs(boot): describe declared ids, author-facing manifest keys, and refresh the catalogs
The publish guide still told bundle authors that mounted row ids carry the
package prefix and that `!!js` gates should compare names, a scheme this
stack withdrew: ids stay as declared, and a shared id or a repeated one
leaves the bundle out with the reason. It now says so, and names
`dsh.title` and `dsh.plugins` with a pointer to the manifest package that
declares every key. The cordis catalog follows app-boot's changed exports.
2026-09-05 22:33:06 +08:00
Yichen Jiang d5613da2cb refactor(boot): read a row failure's stage from the Loader's typed error
`stageOf` parsed the stage out of the Loader's `failed to <stage> loader
entry` message. The vendored wrapper is now an exported `EntryUpdateError`
carrying its `stage`, logged as a local modification, and the contained
group reads the field. `isJsDisabled` wrapped `isJsExpr` behind a literal
`disabled === true` comparison that already excluded expression nodes, so
it goes. The post-boot rejection guard, its documentation, and the
external-bundle module doc now say what they do: the process keeps running
with nothing stopped or attributed to a plugin, and a contained group lets
a failing row's siblings mount rather than failing the bundle as a whole.
2026-09-05 22:19:36 +08:00
Yichen Jiang 0f95351405 fix(boot): report the package probe over IPC and validate what crosses the boundary
The probe's child was a script string that wrote its report to stdout, and
the parent parsed the whole stream as one JSON value: a plugin that merely
printed a line at import could not be probed, and a package that kept a
timer alive after import ran until the timeout. The parent asserted the
parsed value as the report, and the cache read checked only `format`, so a
file holding nothing but `{ "format": 2 }` came back as a complete record.

The child is now its own module, `probe-child.ts`, run through tsx under a
source launch and bundled as `lib/probe-child.js`, and it sends one report
over an IPC channel; stdout is not read at all, and the child is killed as
soon as the report arrived. `parseChildReport` and `parseProbeRecord`
validate the report and the cached record field by field, so an
unrecognized report is a rejection and an unrecognized record is probed
again. `PluginProbe.ok` now states what it is: the main export imported and
cordis is not a second copy; `kind` and `addable[].ok` decide what can be
enabled or added.
2026-09-05 22:19:36 +08:00
Yichen Jiang 0caceb2ced fix(boot): commit a recomposition only once the root include accepts it
`ProfileRuntime.recompose({ reloadBundles: true })` replaced its profile
before the Loader had accepted the update, so a rejected recomposition left
`current`, `layers`, and `originOf` describing a stack that never mounted.
The user patch watchers took a second path through the launcher's
`composeLive`, which wrote the new conflicts into the failure registry
before the update and kept composing from the runtime's stale profile.
Conflict records shared the registry with row failures under a fabricated
entry id and a group id that meant three different things, so the plugin
inventory attributed a conflict to the layer that won the id, and a bundle
disabled after failing kept its import and apply records forever.

The runtime now holds one committed composition — profile, stack ownership,
conflicts — and publishes a candidate only after `entry.update` resolves;
`originOf` reads the committed owners instead of recomputing them. The
watchers call `recompose` through a `reapply` callback, so every live change
goes through the one entry point. Conflicts live on the runtime with their
messages and never enter `pluginFailures`, whose records name rows that
reached the Loader; the inventory lists them under the layer that lost. A
contained group clears its rows' records when it unmounts.
2026-09-05 22:19:36 +08:00
Yichen Jiang 0914a152ff fix(boot): compose external bundles in written order with one wrapper per target
`composeExternalLayer` inserted every id-targeted patch after all inserts,
so a bundle that replaced a group's config and then appended to it lost the
appended row under the `runtime` stage; two inserts into the same built-in
group produced two wrapper groups with one id, which the Loader rejected as
a duplicate and the boot failed; and an id a bundle inserted twice was
indexed once, escaped the ownership check, and failed the boot the same way.

The composition now inserts the bundle's group empty and emits the bundle's
patches in the order written, re-targeting root inserts into the group and
gathering every insert into one built-in group in one wrapper. A repeated id
is a conflict of the bundle with itself: the bundle is left out whole and
recorded like any other conflict, and a built-in layer that repeats an id
fails loud. `composeProfileStack` renders each contained layer once and
returns the owner of every id with the patches and conflicts, and one walker
in `patch-rows.ts` replaces the five recursive scans of inserted rows.
2026-09-05 21:23:11 +08:00
Yichen Jiang 30062f6928 Merge remote-tracking branch 'origin/master' into feat/plugin-mgmt-1-boot
# Conflicts:
#	docs/module-graph.i18n.yaml
#	packages/boot/app-boot/README.i18n.yaml
#	packages/boot/app-boot/README.md
#	packages/boot/app-boot/README.zh.md
#	packages/boot/app-boot/src/index.ts
#	packages/boot/app-boot/src/profile.ts
2026-09-05 21:15:28 +08:00
Yichen Jiang 56bcd0dea7 Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web 2026-09-05 17:50:19 +08:00
Yichen Jiang e0c338cf37 Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-05 17:50:16 +08:00
Yichen Jiang eb818f9c92 chore(docs): regenerate the Cordis catalog for the manager's add verb 2026-09-05 17:49:38 +08:00
Yichen Jiang 864d659f01 Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web 2026-09-05 17:44:55 +08:00
Yichen Jiang 5801c63327 Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-05 17:44:39 +08:00
Yichen Jiang 67213084d6 chore(docs): regenerate the config catalog and make the patch-file README sketch compile 2026-09-05 17:39:15 +08:00
Yichen Jiang fe8c6a365b test(preset): cover the composition inventory's silent patch warning, anonymous inserts, and a layer gone before the read 2026-09-05 17:39:15 +08:00
Yichen Jiang 4cb2d7abb5 refactor(plugins): name the install verb add, as the CLI does
The client namespace service keeps install and remove for its own members
and refuses a Remote method of that name at mount, so the browser could
never reach plugins/install. A spec now reads the reserved names off the
gateway and checks every @Remote name against them.
2026-09-05 17:37:28 +08:00
Yichen Jiang 4d8e9c222b test(plugins): call the manager's add verb in the unresolvable-bundle case 2026-09-05 17:25:18 +08:00
Yichen Jiang 060668290c fix(web): drop the duplicated manager stylesheet copy and keep the theme gate's border rules 2026-09-05 17:23:30 +08:00
Yichen Jiang 148e94501a Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web
# Conflicts:
#	packages/boot/app-boot/src/probe.ts
2026-09-05 17:21:20 +08:00
Yichen Jiang 2e46014b32 Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-05 17:19:21 +08:00
Yichen Jiang cc04382160 test(plugins): a staged package may declare a stage the profile refuses 2026-09-05 17:18:40 +08:00
Yichen Jiang bc6f425d66 Merge branch 'feat/plugin-mgmt-1-boot' into feat/plugin-mgmt-2-manager
# Conflicts:
#	packages/host/plugin-inventory/tests/inventory.spec.ts
2026-09-05 17:16:20 +08:00
Yichen Jiang 26c4a324a1 test(plugins): cover the removal of a bundle the profile cannot resolve 2026-09-05 17:16:00 +08:00
Yichen Jiang f43259f9de refactor(plugins): share the child close settlement with the package probe 2026-09-05 17:14:42 +08:00
Yichen Jiang 1fd4743154 test(boot): cover the inventory's runtime attribution of rows and recorded failures 2026-09-05 17:13:07 +08:00
Yichen Jiang b09a1a311b Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web 2026-09-05 17:05:40 +08:00
Yichen Jiang 19c2bcb887 Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-05 17:04:29 +08:00
Yichen Jiang cd1de5867c test(plugins): let the bare Loader assign the inventory spec's row ids 2026-09-05 17:03:57 +08:00
Yichen Jiang 2ab225a108 fix(web): pass the component filter class in the form the Input primitive accepts 2026-09-05 16:56:07 +08:00
Yichen Jiang 1ea0868fba Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web 2026-09-05 16:13:18 +08:00
Yichen Jiang 05a04429bf Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-05 16:12:15 +08:00
Yichen Jiang a27cc229dc Merge branch 'feat/plugin-mgmt-1-boot' into feat/plugin-mgmt-2-manager
# Conflicts:
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	packages/api/remotes/src/client/index.ts
2026-09-05 16:11:43 +08:00
Yichen Jiang bd9b024509 Merge remote-tracking branch 'origin/master' into feat/plugin-mgmt-1-boot
# Conflicts:
#	docs/capability-seams.i18n.yaml
#	docs/module-graph.i18n.yaml
2026-09-05 16:10:07 +08:00
Yichen Jiang 0af7ca4c10 refactor(web): build the plugin manager on the shared ui-primitives controls
After master's consolidation, the Manage plugins tab and the preset
detail's Capabilities section use Switch, Tag, Button, Input, and StateDot
from ui-primitives instead of their own copies; only the icon buttons, the
red trash icon, and the component chips stay local, as the catalog has no
answer for them. The three packages the stack adds take the workspace
version master released.
2026-09-05 16:05:07 +08:00
Yichen Jiang d3dcaa1b37 Merge remote-tracking branch 'origin/master' into feat/plugin-mgmt-4-web
# Conflicts:
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	packages/api/remotes/src/client/index.ts
#	packages/client/ui-agent-preset/src/client/AgentPresetSection.tsx
#	packages/client/ui-settings-plugin-inventory/src/client/PluginInventorySettingsTab.module.css
#	packages/client/ui-settings-plugin-inventory/src/client/PluginInventorySettingsTab.tsx
#	packages/client/ui-settings-plugin-manager/package.json
2026-09-05 15:59:10 +08:00
Yichen Jiang ce9337db4e refactor(web): off components of a pack as chips grouped by reason
Only a failing component earns a line of its own; the ones a pack
switches off by design — base switches off dozens — sit as dashed chips
under why they are off, one group per reason.
2026-09-05 15:45:40 +08:00
Yichen Jiang e9c5a9d2f1 feat(web): count line and exceptions first for a pack's components
A plugin pack's expanded card no longer lists every component as a row:
a count line says how many and how many are running, off, or failing;
only the components that are off or failing get a line, each with why;
the rest sit as chips behind Show all with a filter. base carries close
to a hundred rows, of which three are off on macOS — those three are the
ones worth reading.
2026-09-05 15:38:41 +08:00
Yichen Jiang 0c40a810cb fix(web): trash icon for preset row deletion, drop the not-mounted line
The Delete on a row the person added to a preset is a red trash icon with
the same accessible name. The plugin card no longer says whether a running
session has the plugin loaded under the preset scope: the Host's registered
flag cannot tell "the preset does not compose it" from "no session runs",
so the line said nothing a person could act on. The unread shell field goes
with it; the README states when saved values apply instead.
2026-09-05 15:18:08 +08:00
Yichen Jiang d7d7b301d5 feat(web): move a preset's capabilities and settings onto its detail page
Agent presets: every card that composes carries a gear that opens the
preset's detail page (breadcrumb, name, marks, description) and declares a
`settings.agentPreset.detail` slot for the sections other plugins contribute.

Plugin manager: the session-plugins group leaves the tab for the detail
page's Capabilities section, with a red Delete on rows the person added and
an Add menu over the installed modules the preset lacks; the manage tab now
precedes the configuration tab.

Plugin configuration: the scope switch is gone. The tab edits the values
shared by all presets, and the same cards form the detail page's Settings
section, registered under a second keyed slot
(`settings.agentPreset.plugin.item`) and editing the preset's own scope while
the page is open. The roster dependency the switch needed leaves with it.

Web e2e goldens, both READMEs of each package, the Agent Note, the slot
catalog, and the inspect catalog follow.
2026-09-05 14:54:58 +08:00
Yichen Jiang 51d1df5c4d test(pwsh-local): expect the spawn-failure note on the observed stderr stream
The Windows-only synchronous spawn-throw case still expected empty observed
readers, the behavior before a rejected spawn started serving its note as the
whole observed stderr stream. It now mirrors the bash-local case: the note is
the stream at every offset, stdout stays empty, and the consuming read folds
the note in exactly once.
2026-09-05 14:53:50 +08:00
Yichen Jiang 57d51b3802 Merge branch 'worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery 2026-09-05 14:34:41 +08:00
Yichen Jiang f3b538cf8f Merge remote-tracking branch 'origin/master' into worktree/process-plugin-streaming-72f9b3 2026-09-05 14:32:14 +08:00
Yichen Jiang 3be4761178 Merge branch 'worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery
# Conflicts:
#	packages/api/job-controller/README.i18n.yaml
#	packages/api/job-controller/README.md
#	packages/api/job-controller/README.zh.md
2026-09-05 14:31:23 +08:00
Yichen Jiang 4baea3bb83 fix(jobs): spill paths as source metadata, live wait claims, narrower entries
Three review follow-ups on the consolidated jobs seam.

The spill file a pull source keeps is job metadata now: the pump reports it
to the registry on every read (present or withdrawn), the projection lists
it under output.spillPaths, and the model's dropped-output notice names it
from there. Attached to a gap chunk it was lost whenever the ring itself
evicted (a pump that kept up never produced a gap) or whenever the gap chunk
was evicted later, and it could not follow a source that withdrew its file.

A job_output wait's claim on the settlement now carries a live flag that
the caller's abort clears synchronously from the abort event. The registry
rejects an aborted wait on a later microtask, so a settlement announced in
between used to find the claim counted and skip the notice the tool result
was not going to carry either.

The job-controller client entry and the tool-jobs entry stop exporting
implementation classes and render helpers nothing outside the packages
consumes; the client entry keeps IJobs, which also carries the ctx.jobs
Context augmentation to consumers.
2026-09-05 14:28:28 +08:00
Yichen Jiang 206e5c6545 Merge branch 'worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery
# Conflicts:
#	apps/web/tests/background-job-list.e2e.ts
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.zh.md
#	packages/api/job-controller/README.i18n.yaml
#	packages/api/job-controller/README.md
#	packages/api/job-controller/README.zh.md
#	packages/api/session-controller/README.i18n.yaml
#	packages/api/session-controller/README.md
#	packages/api/session-controller/README.zh.md
2026-09-05 14:06:00 +08:00
Yichen Jiang 8bcd6f7519 refactor(jobs): rename visibleTo/VisibleJobs to forCaller/CallerJobs
The caller-bound operation set now says what it is: the jobs one caller
may operate on. The caller argument is required (SessionId | undefined),
so an anonymous view has to be requested explicitly instead of falling
out of a forgotten argument.
2026-09-05 14:00:47 +08:00
Yichen Jiang a53fb1497d feat(web): trim the plugin manager cards to name, one-liner, and switch
Every installed package, built-in packs included, is one card in one list:
a name, a one-liner, and its switch or Add to… menu, tagged only for a
pending restart, a problem, or being built-in; kind tags, running and off
tags, the two helper sentences, and the Installed subtitle are gone, and
the toolbar button reads Add. Uninstall and retry move into the expanded
card beside the version, the source, and a pack's components. The
session-plugin composition uses the same single-column cards, marks a
plugin the person installed as Local, and tags nothing else but a failed
row. Tags take the preset section's pill shape.
2026-09-05 12:16:57 +08:00
pku-xht 492c37494a test(web): align Auto denial goldens with composer 2026-09-05 06:22:11 +08:00
pku-xht c7fbe079f0 fix: align delegated preset snapshots 2026-09-05 05:57:39 +08:00
pku-xht 344432de76 Merge commit '746fc39c75c77eb7663f916002ae9e3fd9827a71' into auto-review-per-call
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/config-catalog.zh.md
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	packages/api/remotes/src/client/index.ts
#	packages/client/ui-conversation/src/client/locales.ts
#	packages/client/ui-conversation/src/client/skeleton/InputBar.tsx
#	packages/client/ui-conversation/tests/input-bar.client.spec.tsx
#	packages/extensions/cordis-client-runner/src/client/slot-catalog.ts
2026-09-05 03:46:30 +08:00
Yichen Jiang e001a9d2e4 Merge remote-tracking branch 'origin/master' into worktree/process-plugin-streaming-72f9b3
# Conflicts:
#	packages/client/ui-jobs/package.json
2026-09-04 17:33:19 +08:00
Yichen Jiang d3b1f2d1bc Merge remote-tracking branch 'origin/master' into worktree/process-plugin-streaming-72f9b3
# Conflicts:
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	packages/api/remotes/package.json
#	packages/api/remotes/src/client/index.ts
#	packages/api/session-controller/README.i18n.yaml
#	packages/api/session-controller/README.md
#	packages/api/session-controller/README.zh.md
#	packages/api/session-controller/tsconfig.host.json
#	packages/client/ui-approval/src/client/contract/slots.ts
#	packages/client/ui-chat/src/client/chat/MessageItem.tsx
#	packages/client/ui-chat/src/client/conversation-nodes/assistant.ts
#	packages/client/ui-chat/src/client/conversation-nodes/partial.ts
#	packages/client/ui-chat/src/client/conversation-nodes/tool.ts
#	packages/client/ui-chat/src/client/model/tool-call-tree.ts
2026-09-04 17:28:12 +08:00
Yichen Jiang a7302ee69e feat(web): simplify the plugin manager and drop the plugin list tab
The Manage plugins tab now speaks two nouns (plugin pack, plugin) and four
states (running, off, restart needed, problem). Cards carry a display name,
a one-liner, one kind tag, and their uninstall beside the switch; built-in
packs fold behind one line; the selected preset's composition renders as a
grid of cards named through the tab's own dictionary for harness modules
and through the manifest for third-party ones; entry ids, module names,
cordis copies, and probe times leave the page. The install dialog keeps
pnpm's output behind a fold that opens on failure and words each outcome;
confirmations name what still uses the package and no longer require an
acknowledgement. The client passes a preset row's declared id, not the
live tree's prefixed entry id, to the row actions.

The read-only Plugin list tab and its package, ui-settings-plugin-inventory,
are removed; the pluginInventory Remote stays as the manager's source of
preset compositions and host-tree module names.
2026-09-04 16:53:01 +08:00
pku-xht 3993d36c69 fix(auto-review): stabilize allow response protocol 2026-09-04 15:45:54 +08:00
pku-xht 5b6462f51c Merge commit 'c8e5c4c3a2315079b3ba0b26bc6e6c6b1edd204b' into auto-review-per-call 2026-09-04 15:03:41 +08:00
pku-xht 3879243d62 docs(auto-review): clarify teardown ordering 2026-09-04 14:57:21 +08:00
Yichen Jiang 8866b37604 Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web 2026-09-04 14:12:41 +08:00
Yichen Jiang 53e4d1c0f8 Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-04 14:12:40 +08:00
Yichen Jiang b876a499b2 Merge branch 'feat/plugin-mgmt-1-boot' into feat/plugin-mgmt-2-manager 2026-09-04 14:12:39 +08:00
Yichen Jiang e234dc75fd fix(boot): re-probe records an older probe format wrote 2026-09-04 14:12:38 +08:00
Yichen Jiang 8a96a7ea6a Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web 2026-09-04 14:11:27 +08:00
Yichen Jiang c75e8bce12 Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-04 14:11:01 +08:00
Yichen Jiang db2e34dd02 Merge branch 'feat/plugin-mgmt-1-boot' into feat/plugin-mgmt-2-manager 2026-09-04 14:10:59 +08:00
Yichen Jiang 1ef796fcf9 fix(boot): a plugin is a package that declares itself to dsh
The probe called any package whose main export is a function a `plugin`,
so `lodash` installed as an addable plugin module. A `plugin` now needs a
`dsh` section in its manifest or a dependency on `@deepseek-ai/cordis` as
well as a plugin-shaped export; a bare function export is a `library`.
2026-09-04 14:10:58 +08:00
Yichen Jiang a444460ad4 fix(shell): never offer cancelled work from the offer arm
The offer arm relayed the caller signal only through an abort listener, which a signal that was already aborted never fires, so a command cancelled before execute() spawned anyway, ran to its deadline, and was offered for promotion. The deadline callback also offered regardless of an earlier caller abort, so a process still in its termination grace could be promoted after the tool call was aborted. Both providers now relay an already-aborted signal immediately and settle the promotion undefined at the deadline once the caller aborted; the seam JSDoc states that an already-aborted signal counts as fired. Real-process and hanging-backend cases cover both providers.
2026-09-04 14:03:24 +08:00
Yichen Jiang b0cf8cc1d9 fix(tool-workflow): narrate background runs on the log channel
The record mirror appended phase, log, and member lines without a channel, and the model's job_output renders channel-less chunks as stdout, so a job_output before settlement returned observer narration the README promised it would not. The four appends now carry channel: 'log', which the registry keeps out of model reads while observers still stream it; the spec pins the channels and the status-only early read.
2026-09-04 14:03:23 +08:00
Yichen Jiang 59a64adde7 Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web 2026-09-04 13:52:44 +08:00
Yichen Jiang 1b3dee9c46 Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-04 13:52:42 +08:00
Yichen Jiang b1a1b1a7ab chore(docs): bring the Chinese event catalog along with the regenerated source links 2026-09-04 13:52:41 +08:00
Yichen Jiang 58d4050cb6 docs(tool-workflow): state why the background branch has no pre-abort check
ToolRuntime re-reads the caller signal immediately before execute(), and the workflow tool reaches jobs.start synchronously from there, so an in-tool check would be unreachable; bash and pwsh need theirs because they await a sandbox escalation approval before registering.
2026-09-04 13:52:24 +08:00
Yichen Jiang 600b780b97 chore(shell): align the pwsh mirror comments and the promotion read JSDoc
renderProcessRead and renderPwshProcessRead described themselves as the job_output renderer; their only caller is the timeout promotion embedding one consuming read, while job_output reads come from the registry ring. The pwsh presenter comment gains the promotions clause bash already has, and pwsh-sandbox drops a stray blank line.
2026-09-04 13:52:23 +08:00
Yichen Jiang 15cbcad1eb docs(notes): rewrite the three delivery notes to the shipped mechanisms
The timeout-promotion, workflow run_in_background, and human-job-kill notes kept their bodies in the present tense over ctx.activities, RunningJob/updateDetail, and the registry's reported bit, with Update headers doing the correcting. Their mechanism sentences now state the shipped facts (observed streams as pull sources, JobHandle/updateProgress, the tool-jobs delivery ledger), the Update headers shrink to cross-links, and the testing paragraph names the current specs.
2026-09-04 13:52:22 +08:00
Yichen Jiang 9fe106693c docs(shell): describe timeout promotion through the job ring, not ctx.activities
The tool-bash and tool-pwsh READMEs still said a promoted run is mirrored into ctx.activities, a seam the jobs consolidation deleted, and the shell README still called the observed readers optional and named the activity plane. The promoted run now feeds the registry's ring from the observed streams' current offsets and the Web list streams it through job.rows and job.observe; observed readers are required and carry the spawn-failure note.
2026-09-04 13:52:22 +08:00
Yichen Jiang 6b8ae2b721 Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web 2026-09-04 13:50:57 +08:00
Yichen Jiang 90d185b785 Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-04 13:50:55 +08:00
Yichen Jiang 3dd4a9a873 chore(docs): regenerate the module graph and event catalog for the plugin manager's agent dependency 2026-09-04 13:50:54 +08:00
Yichen Jiang ac517078ca feat(web): show what an install removed and why the Host refused a change
The install dialog lists the packages the Host removed again after
`pnpm add` with the Host's reason, and every action renders the two
refusals any mutation can meet — another change still running, a session
still running — in the Host's words instead of a generic failure line.
2026-09-04 13:49:04 +08:00
Yichen Jiang 368379e870 Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web
Carry the install verdict, manifest rollback, and the one-mutation and
running-session guards under the `add` verb this branch uses.
2026-09-04 13:44:09 +08:00
Yichen Jiang ca3d9af0a7 Merge remote-tracking branch 'origin/worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery
# Conflicts:
#	packages/shell/bash-sandbox/tests/sandbox.spec.ts
#	packages/shell/pwsh-local/tests/executor.spec.ts
2026-09-04 13:42:20 +08:00
Yichen Jiang 9862f16a40 Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-04 13:41:45 +08:00
Yichen Jiang e3386d1105 feat(plugins): judge an install after pnpm, restore the manifest on failure, run one mutation at a time
A successful `pnpm add` is no longer the end of `plugins/install`: a new
package that declares neither a bundle nor a plugin module, or a bundle
whose row id a composed layer already owns, is removed again and reported
under `removed` with its reason, while a package the probe refused stays
for the view to explain. The profile manifest is snapshotted before the run
and restored when pnpm fails. The manager refuses a second mutation while
one runs (`plugins/busy`) instead of racing on the manifest and user
layers, and `install`/`uninstall` refuse while a session is running
(`plugins/agents-running`), because pnpm rewrites the directory those
sessions import from.

`resolveProfileLayer` factors one bundle's layer out of `loadProfile` so the
manager can judge a candidate against the composed layers.
2026-09-04 13:41:20 +08:00
Yichen Jiang 7e5627f8e3 Merge remote-tracking branch 'origin/master' into worktree/process-plugin-streaming-72f9b3 2026-09-04 13:39:42 +08:00
Yichen Jiang 3d5431a862 Merge remote-tracking branch 'origin/worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery 2026-09-04 13:30:34 +08:00
Yichen Jiang 063ef188a6 chore(jobs): regenerate the catalogs after the review fixes
The settled-retention JSDoc, the required observed streams, and the session-controller type shifts changed what the config, persistence, Cordis, and event catalogs embed; CI's static and coverage lanes compared the stale copies. Regenerated, with the zh mirrors updated in step.
2026-09-04 13:29:54 +08:00
Yichen Jiang 42858723a6 Merge remote-tracking branch 'origin/worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery
# Conflicts:
#	packages/api/job-controller/README.i18n.yaml
#	packages/api/job-controller/README.md
#	packages/api/job-controller/README.zh.md
#	packages/api/session-controller/README.i18n.yaml
#	packages/api/session-controller/README.md
#	packages/api/session-controller/README.zh.md
#	packages/shell/bash-local/src/index.ts
#	packages/shell/pwsh-local/src/index.ts
#	packages/shell/tool-bash/src/background.ts
#	packages/shell/tool-bash/tests/tools.spec.ts
#	packages/shell/tool-pwsh/src/background.ts
#	packages/shell/tool-pwsh/tests/background.spec.ts
#	snapshots/web/approval-composer/session.v2.jsonl
#	snapshots/web/feedback-command/session.v2.jsonl
#	snapshots/web/fresh-round-trip/session.v2.jsonl
#	snapshots/web/goal-multi-turn-actions/session.jsonl
#	snapshots/web/lifecycle-chrome/session.v2.jsonl
#	snapshots/web/live-interactions/session.v2.jsonl
#	snapshots/web/minimal-preset/session.v2.jsonl
#	snapshots/web/permission-policy-context/session.v2.jsonl
#	snapshots/web/plan-review/session.jsonl
#	snapshots/web/ptc-round/session.v2.jsonl
#	snapshots/web/question-composer/session.v2.jsonl
#	snapshots/web/steering/session.v2.jsonl
#	snapshots/web/turn-tail-actions/session.v2.jsonl
#	snapshots/web/web-search-round/session.v2.jsonl
2026-09-04 13:27:34 +08:00
pku-xht 91b504e63e ci(e2e): isolate auto certification 2026-09-04 13:20:05 +08:00
pku-xht e6863256f7 ci(e2e): serialize shared-key real-model tests 2026-09-04 13:01:31 +08:00
Yichen Jiang 3a03d68891 fix(shell): serve a background spawn failure on the observed stderr stream
A rejected background spawn produces no process output, so the observed stderr reader the job registry pumps was empty and the model's job_output after such a failure showed only killed before exit, where master's consuming read rendered [stderr] followed by spawn failed: … with the cause. The local providers now serve the note as the whole observed stderr stream once the spawn rejected, and the consuming read still folds it in exactly once, so the model's first read after the failure is byte-identical to master's. ShellProcess.observed and both of its readers are required: every background process exposes offset readers, and the shell tools' pull sources no longer carry a no-readers branch.
2026-09-04 12:59:41 +08:00
Yichen Jiang 1c2d7771aa fix(job-controller): close an observation on the job's removal instead of a failed read
An owner's teardown settles and removes the record within one microtask chain, while the observation generation sleeps its flush window after the wake and then reads an id the registry no longer returns, failing the stream and flashing an error in the panel until the roster frame drops the row. The subscription now records a removed event for the observed id and the generation closes with that terminal projection.
2026-09-04 12:47:22 +08:00
Yichen Jiang 80bbdba617 fix(jobs): restore the dropped-output notice with its spill files for the model
The consuming shell read on master told the model where a truncated stream's complete text lived: [some output was dropped from memory; full output: <paths>]. The ring-backed read rendered a notice only for the ring's own eviction and ignored the gapBefore mark the pump puts on a chunk whose source lost bytes between two polls, so a fast producer's tail read as continuous output and no path survived. A lossy source read now carries the source's spillPath onto its gap chunk (JobSourceRead, JobAppendOptions, JobChunk), the pump forwards it, the ring retains it, and the model renderer emits master's notice for a producer-side gap or a ring eviction, listing the distinct spill files in offset order. The bash and pwsh sources already returned the subprocess reader's spillPath; the type now admits it.
2026-09-04 12:47:21 +08:00
pku-xht 8481e02b36 fix(auto-review): reinforce reviewer output contract 2026-09-04 12:46:25 +08:00
Yichen Jiang c673796496 docs(jobs): record the review follow-ups in the consolidation note 2026-09-04 12:27:17 +08:00
Yichen Jiang e680fbc3a0 refactor(jobs): check the announced event protocol in the invariant companion
The companion validated fields of single JobView projections, which the invariant rule rejects as a check without independent observations. It now tracks each job's announced protocol (registered first, one settlement, removal last, no progress after settlement), adopting a job first seen late, and compares every announced projection with the registry's own read of the same job: identity, output total, and the settled status and time. An output event announced before registration, which the registry emitted until the previous commit, is one of the cases it rejects.
2026-09-04 12:27:16 +08:00
Yichen Jiang 5f1d53640b fix(job-controller): show an observation failure that precedes the anchor
An observation stream that failed before its opened frame left no observed state, so the expanded row rendered nothing: no output, no notice. The client model now records such a failure as an errored, non-streaming view with no resume cursor, and the panel renders the interruption notice it promises.
2026-09-04 12:25:16 +08:00
Yichen Jiang 9f0600d11b fix(tool-jobs): count wait claims per call
Two concurrent job_output waits on one job shared a single ledger entry, so the first wait's timeout withdrew the claim the second wait still held and the settlement injected a completion notice the model had already received through that wait. Claims are counted per call now; a withdraw releases only its own.
2026-09-04 12:25:15 +08:00
Yichen Jiang 0712a4cc68 fix(jobs-local): keep unconsumed settled output for the model and announce registration first
Settlement trimmed the ring to settledRetainBytes before releasing waiters, so a job that finished before its first job_output handed the model only the last 16 KiB plus a dropped-output notice where master's consuming read kept the executor's whole tail. The ring now keeps every byte the model cursor has not consumed on top of the settled cap, and the first terminal model read trims to the cap.

The registered event was emitted after startPump, whose first drain runs synchronously and may announce output, so a source readable at once produced an output event for an id no subscriber had seen registered. The announcement now precedes the pump; the events JSDoc states that a job's first event is registered.
2026-09-04 12:25:14 +08:00
pku-xht 11c4fa1b0a fix(permissions): harden auto disposal migration 2026-09-04 12:21:56 +08:00
Yichen Jiang f0af64fb50 Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web 2026-09-04 12:18:20 +08:00
Yichen Jiang 4810cfa071 Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-04 12:18:19 +08:00
Yichen Jiang d926d39a1b chore(docs): regenerate the config catalog after the plugin manager import change 2026-09-04 12:18:18 +08:00
Yichen Jiang d4e69cd399 Merge branch 'feat/plugin-mgmt-3-settings' into feat/plugin-mgmt-4-web
Adopt owned row ids in the browser: the plugin manager tab shows `rowId`,
the web scaffold's profile runtime composes a stack, and the inventory spec
covers provenance and conflict attribution. Widen the install-result alias
the store spec had narrowed to `never[]`.
2026-09-04 12:15:20 +08:00
Yichen Jiang 2c0ca45f76 fix(jobs): carry the projection kind as an open string on the wire
JobView.kind was typed as the merge-extensible JobKind, so the job-controller program, which compiles only the merges it can see, generated a strict codec of bash | subagent for job.rows and job.observe. The first pwsh, pty-send, or workflow job failed frame validation on both ends and the browser dropped the whole roster. The projection now carries kind as a string; JobSpec.kind keeps the Host-side JobKind. A built-artifact smoke parses a pty-send row through the generated schemas, and the seam spec pins the open type.
2026-09-04 12:10:22 +08:00
Yichen Jiang 4903d1a6cb Merge branch 'feat/plugin-mgmt-2-manager' into feat/plugin-mgmt-3-settings 2026-09-04 12:10:11 +08:00
pku-xht dae5844f93 fix(auto-review): scope logged calls by step 2026-09-04 12:10:10 +08:00
Yichen Jiang 3b0a07e029 Merge branch 'feat/plugin-mgmt-1-boot' into feat/plugin-mgmt-2-manager
Adopt owned row ids in the plugin manager and inventory: a row view carries
`rowId` (the declared id a patch or row action targets) instead of the
withdrawn `originalId`, probe rows are listed under their declared ids, a
conflict record is attributed to the bundle it names, and the manager's
test boot records conflicts the way the launcher does.
2026-09-04 12:10:02 +08:00
Yichen Jiang b76bfbcc1f docs(notes): align the job runtime notes with the consolidated seam
The registry seam, runtime, admission, wake, and web display notes named JobStart, JobSnapshot, onJobDone, onJobsChanged, and the registry-owned reported bit as current facts. Rewrite those sentences to the shipped JobSpec/JobView contract, the events stream, and the tool-jobs delivery ledger; the wake note gains an Update header pointing at the consolidation note, and the display note's disposal paragraph now states the per-job removed event the registry emits.
2026-09-04 12:05:44 +08:00
Yichen Jiang 70a37b6cc1 chore(jobs): drop the formatting-only hunks left by the seam refactor
Revert the two brace-only rewrites in tool-workflow to master's one-line form and collapse the blank lines left where SessionJob was removed from the session-controller types.
2026-09-04 12:05:43 +08:00
Yichen Jiang 5d742503ea feat(boot): own row ids across the stack instead of prefixing external bundles
An external bundle keeps the ids its patch declares. composeProfileStack
decides ownership before anything mounts: built-in and boot-staged layers
claim first and a duplicate among them fails the boot, a contained bundle
that collides is left out whole, a user-layer insert of a taken id is
dropped, and every row left out is a `conflict` record in pluginFailures,
printed at boot and replaced on each recomposition. Boot, live reloads, and
--dump-config compose through the same function, so the dump shows the
contained groups the tree mounts.

The prefix made a user patch, a third-party manager's disabled rows, and a
bundle's own `!!js` id comparison miss silently; the note records both cases.
2026-09-04 12:02:11 +08:00
Yichen Jiang 424c8457d9 Merge remote-tracking branch 'origin/master' into worktree/process-plugin-streaming-72f9b3
# Conflicts:
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	packages/api/session-controller/tests/control-jobs.host.spec.ts
#	snapshots/web/fresh-round-trip/session.v2.jsonl
#	snapshots/web/ptc-round/session.v2.jsonl
2026-09-04 12:02:02 +08:00
pku-xht ca8d65e5c4 docs(auto-review): avoid deterministic output claim 2026-09-04 09:56:45 +08:00
pku-xht 5a99cd9a47 fix(auto-review): stabilize reviewer decisions 2026-09-04 09:27:16 +08:00
pku-xht 96c29c2e6a docs: refresh auto review event listeners 2026-09-04 08:47:30 +08:00
pku-xht 0df80cdf41 fix(auto-review): carry lifecycle cancellation to dispatch 2026-09-04 08:08:52 +08:00
pku-xht a3d00cebc0 Merge commit '0d361e6eede9e8a739e776949aa7d5e3de4472da' into auto-review-per-call
# Conflicts:
#	.agents/notes/implemented/feature/2026-07-25-subagent-policy-inheritance.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-25-subagent-policy-inheritance.md
#	.agents/notes/implemented/feature/2026-07-25-subagent-policy-inheritance.zh.md
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	docs/persistence-catalog.i18n.yaml
#	docs/persistence-catalog.md
#	docs/persistence-catalog.zh.md
#	packages/extensions/tool-cordis/src/api-catalog.ts
#	snapshots/session/cordis-inspect-jsdoc/session.v2.jsonl
#	snapshots/web/ptc-round/session.v2.jsonl
2026-09-04 07:10:24 +08:00
pku-xht d381a3c6f4 feat(auto-review): enforce risk-classified review 2026-09-04 06:46:20 +08:00
Yichen Jiang 84bed2e744 fix(web): keep an install or confirmation alive across the reads its own changes trigger
The Host announces plugins/changed while an install is still on the
wire — enabling recomposes before the call answers — and every such
event reads the packages again. The store used the read generation as
the install's liveness token, so the answer was dropped and the dialog
stayed at "installing"; the dependents answer of a confirmation was
dropped the same way. Liveness is now disposal, and for a confirmation
the confirmation still being the same one.
2026-09-04 04:54:05 +08:00
Yichen Jiang 6407ed8a44 fix(plugins): recognize the harness cordis copy by package directory
The probe compared the resolved cordis entry URLs of the child process
and the host. Under the source launcher tsx resolves the host's copy to
vendor/cordis/src/index.ts while the plain-Node child resolves
lib/index.js, so every third-party package was refused as carrying its
own copy. Compare the real package directories instead.

The install dialog now shows the Host's refusal reason after pnpm's
output when a run installs but cannot enable, and no longer forces a
width the modal cannot give it.
2026-09-04 04:48:58 +08:00
Yichen Jiang 1570eeeaee feat(web): manage plugins and per-preset settings from the browser
Add the Manage plugins tab (ui-settings-plugin-manager): package cards
with enable/disable switches, retry and uninstall, an install dialog
streaming pnpm output, and the selected preset's composition with per-row
switches and removal; the read-only list gains provenance facts.

Settings cards edit one scope at a time: ui-settings keeps one describe
mirror per settings scope (SettingsMirrorRegistry) and binds
{ namespace, scope }; ui-settings-plugins stages forms per scope, marks
inherited fields, and adds the skill-filesystem roots card.

Fixes surfaced by driving the browser end to end: the client gateway now
lets a call omit trailing parameters that accept undefined (PR3's
optional scope arguments failed the strict arity check), the plugins
install verb is `add` because the client namespace service reserves
`install`/`remove` (guarded by remote-method-names.host.spec), a plugin
module offers its main export as an addable `.`, and describing a settings
scope no owner registered resolves over the global instance's base and
never throws.

The web e2e scaffold can mount a profile runtime over fixture packages;
plugin-manager.e2e drives the tab and writes one field under a preset
scope; plugin-config and settings-chrome goldens are refreshed.
2026-09-04 04:32:31 +08:00
Yichen Jiang 80ea5fcdf5 feat(settings): resolve namespaces per named scope
A settings namespace is now a kind; each registration is an instance
filed under the caller's nearest named scope (dsh-scope gains
createScope(..., { id }) and scopeIdOf). Instances resolve defaults →
composition base → global user section → scopes.<id>.<ns>. Global writes
fan out to every instance gated on its own resolved value; scoped writes
commit one instance. Revisions are per section so a scope nothing has
registered yet can still be written when the kind exists. describe(),
the controller verbs, and both events take an optional trailing scope.
Presets name their standing scopes preset/<id>; skill-filesystem is the
first consumer, resolving customSkillDirs per scope with live updates.
2026-09-04 03:03:43 +08:00
Yichen Jiang dc969e2ee8 feat(plugins): plugin manager, preset user layers, and the patch-file writer
Add `dsh-host-plugin-manager`: the `pluginManager` service and the
`plugins` Remote that install, uninstall, enable, disable, and retry
bundles over the booted profile, add and remove rows in the profile's
or an agent preset's user layer, report what a package's services keep
alive, and fold the manifest, the probe record, and the live tree into
one view per package. pnpm runs the way the CLI runs it, streaming its
output as `plugins/install-log`; every change emits `plugins/changed`,
and api-remotes forwards both. Enabling is the Loader's own
transaction: a rejected recomposition restores the layer list, and a
runtime recomposition records contained rows through
`recordContainedStates` because the boot audit does not run again;
`ContainedGroup.create` now records a row that resolved pending rather
than clearing it.

Give every agent preset a user patch layer: `cordis.patch.yml` beside
a locally authored composition, or alone in `.agent-presets/<id>/`
for a shipped one. Discovery attaches and judges it, the mount applies
it as the include's runtime patches, standing generations follow the
layer's content and return to a retired generation when it comes back,
the composition inventory reports each row's `source` and
`disabledBy`, a copy carries the layer, and `removeOverlay` deletes it.
`dsh-global-tool-mask` is `tools.restrict()` as a scope-only row for
such a layer.

Add `dsh-patch-file` as the one home of the patch-list format: the
parser moved out of app-boot, plus a comment-preserving key-level
writer with lock, atomic replace, and readback. app-boot exports
`layerTrust`, `bundleLayerPatches`, and `recordContainedStates`, and
`ProfileRuntime` carries the install anchor.
2026-09-04 02:31:54 +08:00
Yichen Jiang d419e7e553 feat(boot): isolate external bundles and expose the booted profile
Mount every external bundle layer as a cordis:contained-group entry
`bundle/<package>` whose rows carry a `<package>/<id>` prefix, so one
community bundle that no longer loads records a failure in the root
`pluginFailures` registry instead of rejecting the whole Loader
transaction, and two bundles may declare the same row id. Classify
layers by origin (`builtin` for the template bundle and
`dsh.profile.firstParty`, `external` for profile dependencies) and let
`dsh.bundle.stage: boot` or `dsh.profile.stages` opt a bundle out of
isolation when it provides a service built-in rows inject; a built-in
row left pending beside an isolated bundle still fails boot and names
the bundle.

Keep `installFailLoud` for the boot transaction only and install
runtime guards afterwards: an unhandled rejection is reported and
contained, an uncaught exception is reported and exits. Report nested
fiber failures under built-in entries as advisory lines.

Provide `ctx.profileRuntime` from the launcher (layers with trust and
stage, row origin, user-disabled rows, recomposition through the root
include) and probe installed packages in a child process
(`probePackage`, cached under `profiles/<name>/.dsh-plugins/`). Split
installation from enablement in `reconcileInstalledBundles`; the CLI
keeps install-means-enable. The plugin inventory now reports `trust`,
`package`, `disabledBy`, and `failure` per row and lists rows only the
failure registry knows.
2026-09-04 02:26:01 +08:00
fz 8d06ebb5ac Revert "refactor: remove str_replace_editor"
This reverts commit d12b1146baa326e6facd3b10f81ae11db35ffd86.
2026-09-03 21:05:38 +08:00
Yichen Jiang b7632168cc test(tool-pwsh): pin the integration suite to the executor's timeout kill
With owners resolved by session id, the suite's id-less fake agent no
longer makes the timeout promotion fail admission, so a per-call timeout
promoted the run and the timed-out-marker assertion broke. Promotion over
a scripted executor stays covered by background.spec.
2026-09-03 18:20:33 +08:00
Yichen Jiang 59b16ed0e3 Merge remote-tracking branch 'origin/worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery 2026-09-03 18:01:12 +08:00
Yichen Jiang 14dc38b2fd test(session-controller): cover the cold-session baseline queue
The roster spec that exercised a session without a live agent left with
the roster; the queue baseline's empty arm needs its own case.
2026-09-03 18:00:42 +08:00
Yichen Jiang d81c5048db chore(jobs): regenerate the catalogs and re-record the job goldens after the seam merge
The merged tree carries promoteOnTimeout, the workflow run_in_background
config, and tool-jobs' pre-refactor requirement set; the settled job
goldens show the folded finished section, a static row for a job with no
retained output, and the human kill's reason in the detail.
2026-09-03 17:48:21 +08:00
Yichen Jiang ae28d2cc6d Merge remote-tracking branch 'origin/worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery 2026-09-03 17:46:07 +08:00
Yichen Jiang cd3a9ac881 Merge remote-tracking branch 'origin/worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery
# Conflicts:
#	apps/web/tests/background-job-list.e2e.ts
#	apps/web/tests/live-job-stream.e2e.ts
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/config-catalog.zh.md
#	docs/subsystems/jobs.i18n.yaml
#	docs/subsystems/jobs.md
#	docs/subsystems/jobs.zh.md
#	packages/api/job-controller/README.i18n.yaml
#	packages/api/job-controller/README.md
#	packages/api/job-controller/README.zh.md
#	packages/api/job-controller/src/client/index.ts
#	packages/api/job-controller/src/client/service.ts
#	packages/api/job-controller/src/index.ts
#	packages/api/job-controller/src/types.ts
#	packages/api/job-controller/tests/client-apply.client.spec.ts
#	packages/api/job-controller/tests/model.client.spec.ts
#	packages/api/job-controller/tsconfig.host.json
#	packages/api/session-controller/tests/control-jobs.host.spec.ts
#	packages/client/ui-jobs/README.i18n.yaml
#	packages/client/ui-jobs/README.md
#	packages/client/ui-jobs/README.zh.md
#	packages/client/ui-jobs/src/client/JobListAction.tsx
#	packages/client/ui-jobs/src/client/index.ts
#	packages/client/ui-jobs/tests/browser-plugin.client.spec.ts
#	packages/client/ui-jobs/tests/job-list-action.client.spec.tsx
#	packages/extensions/tool-cordis/src/api-catalog.ts
#	packages/jobs/jobs-local/src/index.ts
#	packages/jobs/jobs-local/tests/jobs.spec.ts
#	packages/jobs/jobs/README.i18n.yaml
#	packages/jobs/jobs/README.md
#	packages/jobs/jobs/README.zh.md
#	packages/jobs/jobs/src/index.ts
#	packages/jobs/jobs/src/types.ts
#	packages/jobs/tool-jobs/src/index.ts
#	packages/shell/tool-bash/src/index.ts
#	packages/shell/tool-bash/src/render.ts
#	packages/shell/tool-bash/tests/background.spec.ts
#	packages/shell/tool-bash/tests/tools.spec.ts
#	packages/shell/tool-pwsh/src/index.ts
#	packages/shell/tool-pwsh/src/render.ts
#	packages/subagent/tool-subagent/tests/tool-subagent.spec.ts
#	snapshots/web/background-job-list/settled.expected.md
2026-09-03 17:45:44 +08:00
Yichen Jiang 08a51f6d88 fix(tool-jobs): keep the agent registry optional
An owned job cannot start without the agent registry, so the plugin only
needs it to resolve a notice destination; requiring it left compositions
that run unowned jobs — the PTC harness, the pwsh loader and integration
suites — without an attached controller. The inject list, catalogs, and
README return to the pre-refactor requirement set.
2026-09-03 17:45:27 +08:00
Yichen Jiang fec81b7295 test(web): re-record the job goldens for the ring-backed rows
A settled job that retained no output is a static row, and a killed row
shows the kill reason in its detail. The live-stream scenario's idle
locator now matches the settled trigger exactly, so its settled capture
cannot race the roster refresh.
2026-09-03 17:20:06 +08:00
Yichen Jiang 9e8f3ce987 fix(tool-jobs): restore the background-job guidance text
The rewrite carried an older wording of the system-prompt section; the
recorded-session snapshots pin the current one. Model-visible text is
byte-identical to the pre-refactor plugin again.
2026-09-03 17:17:30 +08:00
Yichen Jiang 7b607ae6a2 fix(tool-jobs): build the notice status line from the public projection
The notice and its summary passed an optional detail as string | undefined,
which the build's exactOptionalPropertyTypes rejects while the test lane's
transform does not; publicJob() already carries the conditional.
2026-09-03 17:16:32 +08:00
Yichen Jiang cbb0ec0296 docs(jobs): describe the consolidated seam
- docs/subsystems/jobs.md (+zh) records JobSpec, JobHandle, JobHooks,
  JobOutcome, the pull-source types, JobChunk, JobOutputRead, JobView,
  JobRead, VisibleJobs, and the event types as type-equivalence blocks; the
  manifest and the cordis catalog link map follow
- the jobs, jobs-local, and tool-jobs READMEs (+zh) describe the ring, the
  caller-bound view, the event stream, and the notice ledger; the
  architecture table and the adding-a-tool cookbook drop record: true and
  readOutput
- Agent Note 2026-09-03-jobs-seam-consolidation owns the decision; the
  2026-09-01 record note and the 2026-08-08 web display note carry
  Superseded pointers and the display note links the rows spec
- regenerated catalogs (cordis, api, inspect, client, tool, config,
  persistence, doc graphs, module graph) with their Chinese mirrors; the
  cordis catalog drops the jobOutput exemption and the tool catalog mounts
  the agent registry for tool-jobs; the client model imports JobView from
  its leaf so the typert analyzer resolves it
2026-09-03 17:15:07 +08:00
fz 79b3d7a594 refactor: remove str_replace_editor 2026-09-03 17:02:37 +08:00
Yichen Jiang 84efac2c42 refactor(ui-jobs): read rows and observations from ctx.jobs
The header list watches its session's roster through ctx.jobs.watchRows
while mounted and reads rows and observed views from one jobs snapshot. A
row is expandable while the job is live or once it left retained output
behind; it shows the live progress line or the terminal detail. The web
e2e drivers kill through visibleTo(), and the client fixtures the roster
removal missed drop their jobs baselines.
2026-09-03 17:00:51 +08:00
Yichen Jiang b7ce934b29 refactor(job-controller): own the roster stream and the browser jobs service
- job.rows({ sessionId }) streams the jobs one session can see as whole-set
  frames: once on open, then after each coalesced burst of lifecycle
  commits; output appends never refresh it
- job.observe reads through visibleTo(sessionId) and carries JobView in its
  opened and status frames; the wire chunk is the registry's JobChunk
- the client installs ctx.jobs (ClientJobs over ClientJobsModel): watchRows
  and observe are reference-counted streams, rows drop with the last
  watcher or a terminal failure, observations keep their render tail
- the controller no longer needs the agent registry
2026-09-03 17:00:49 +08:00
Yichen Jiang 2132b7beeb refactor(session-controller): drop the job roster from the control stream
The control baseline and frames carry queues and projections only; the
SessionJob row type, the jobs frame, the registry subscription, and the
client jobsBySession mirror are gone, and every client fixture drops the
empty mirror. The roster moves to dsh-api-job-controller's job.rows
stream in the next change.
2026-09-03 16:43:15 +08:00
Yichen Jiang 10d76fbd03 refactor(producers): subagent and terminal jobs use session owners, results, and pull sources
- tool-subagent registers the parent session id as the owner and settleRun
  reports the child's final text as the job result, which the first read
  after settlement carries once
- tool-terminal hands the registry one pull source over the backend's
  consuming send reader (sendSource in background.ts) instead of a
  readOutput hook; the truncation marker stays in the delivered text
- the model's kill reason now shows in a killed job's status line, as the
  registry records it as the terminal detail
- test call sites move from jobs.list(owner) to visibleTo(owner).list()
2026-09-03 16:37:35 +08:00
Yichen Jiang 053d302210 refactor(shell tools): hand the job registry pull sources and terminal outcomes
tool-bash and tool-pwsh no longer render their own background reads.
processSources() wraps the process's observed offset readers as registry
pull sources, pumped at dsh-jobs-local's pumpPollMs, and processOutcome()
folds the settled sandbox facts into the terminal detail. observe.ts and
the recordPollMs config field are gone; READMEs and pairings follow.
2026-09-03 16:30:57 +08:00
Yichen Jiang 0e35952802 refactor(tool-jobs): render model reads from the ring and own the notice ledger
- job_output reads the per-job ring through visibleTo(): stdout, then one
  [stderr] section, log narration excluded, a dropped-output notice on a
  lossy read, and the result exactly once after settlement
- completion notices come from the registry event stream subscribed with
  { owners: 'scope' }; a wait claims its job when it starts and withdraws
  on timeout or abort, job_kill claims on 'requested', teardown settlements
  and unowned jobs are skipped, and a removal drops the ledger entry
- the notice destination is the agent registered for the owner session at
  settlement, so tool-jobs now injects the agent registry
- JobView exposes the producer's outputLimitBytes for the tool-result bound
- lint: hub disposer identity comment, unknown-typed matchers in seam tests
2026-09-03 16:30:57 +08:00
creatixchu 345b5cdc6f feat(session, llm): durable image offload watermark
Record the image offload point as the core image/offload session event so the
derived surface, every adapter, and the token meter share one offloaded set.
The agent loop plans the advance from the route's declared request-image
budget before dispatch; an adapter whose exact accounting still overflows
fails with IMAGE_OFFLOAD_REQUIRED and the loop advances by the named count.
2026-09-03 16:29:51 +08:00
Yichen Jiang 6626c74dbc refactor(jobs-local): contain a throwing pull source instead of freezing the job 2026-09-03 16:09:07 +08:00
fz e9f8641e76 Merge remote-tracking branch 'origin/master' into feat/remove-str-replace-editor-from-minimal
# Conflicts:
#	.agents/notes/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.i18n.yaml
#	.agents/notes/implemented/architecture/2026-08-23-python-sdk-dsh-profile-runtime.i18n.yaml
#	.agents/notes/implemented/architecture/2026-08-23-python-sdk-windows-x64-runtime.i18n.yaml
2026-09-03 16:05:56 +08:00
fz 63795eaa5c feat(minimal): remove str_replace_editor from minimal profiles 2026-09-03 16:03:59 +08:00
Yichen Jiang f55e9805c7 refactor(jobs-local): one ring, two cursors, and event routing
Every job owns an `OutputRing`; the model's `read` consumes from a
registry-kept cursor while `readAt` reads at absolute offsets. Pull
sources named by the spec are pumped by the registry and drained once
more before settlement. `visibleTo(caller)` binds the session fence
once; the three listener families become one event hub with explicit
filters; `reported` is gone and settlements announce their cause.
2026-09-03 16:03:16 +08:00
Yichen Jiang 1b97207150 refactor(jobs-local): extract the output ring and the registry-owned pump 2026-09-03 15:53:59 +08:00
Yichen Jiang 07941fe5e2 refactor(jobs): consolidate the seam into JobSpec, VisibleJobs, and one event stream
The registry seam keeps three members plus the controller handshake:
`start(spec)`, `visibleTo(caller)` (one authorization, then list / get /
read / readAt / kill / wait without a caller argument), and `events`
(one typed stream with an explicit filter instead of three listeners).
Every job owns an output ring: `JobSpec.output` names pull sources the
registry pumps, `JobHandle.append` pushes, and the model's consuming
`read` and observers' `readAt` read the same bytes through separate
cursors. `reported`, the `record` declaration, the producer `readOutput`
hook, and the `JobStart`/`RunningJob` split are gone; `JobView` is the
one projection, split into `progress` and terminal `detail`. The
client-safe `./view` leaf carries the projection vocabulary.
2026-09-03 15:51:39 +08:00
creatixchu abb2b31dbe Merge remote-tracking branch 'origin/master' into worktree/3041-image-offload-log-design 2026-09-03 14:40:29 +08:00
creatixchu c1b1cd2984 docs: propose a durable image offload watermark 2026-09-03 14:40:24 +08:00
Yichen Jiang 1307d66e70 Merge branch 'worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery 2026-09-03 13:45:24 +08:00
Yichen Jiang 09bd6bcf54 chore(http-proxy): align the package version with the 0.1.2-rc.1 bump 2026-09-03 13:45:09 +08:00
Yichen Jiang a2b9b8b03b Merge remote-tracking branch 'origin/master' into worktree/process-plugin-streaming-72f9b3 2026-09-03 13:42:07 +08:00
Yichen Jiang d0b9167dba Merge branch 'worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery
# Conflicts:
#	.agents/notes/implemented/feature/2026-08-25-unified-task-list.i18n.yaml
#	packages/jobs/jobs-local/src/index.ts
#	snapshots/web/cordis-tool-round/session.jsonl
2026-09-03 13:19:22 +08:00
Yichen Jiang b48c05d117 refactor(jobs): type the producer face by the record declaration, tidy review residue
- `JobStart` is a union discriminated by `record`: `RecordingJobStart.run`
  receives `RecordingJob` (with `append`), `PlainJobStart.run` receives the
  plain `RunningJob`, and the registry builds the plain face without the
  method, so the former warn-and-drop path is unrepresentable.
- Remove the duplicated JSDoc opener in the registry seam and correct the
  job-list slot comment (order 20 sits before the subagent catalog's 30).
- Restore the `cordis-tool-round` session fixture whose only change was a
  re-recorded `createdAt`.
- Update the 2026-08-08 job-display note's stale service-disposal and slot
  ordering facts; archive the superseded 2026-08-25 unified-task-list note
  and point its remaining inbound links at the archived snapshot.
2026-09-03 13:15:23 +08:00
Yichen Jiang 07d9d5b5cd Merge remote-tracking branch 'origin/worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery 2026-09-03 11:33:34 +08:00
Yichen Jiang 6a4d7ee242 chore(job-controller): align the package version with the 0.1.2-rc.1 bump 2026-09-03 11:33:05 +08:00
Yichen Jiang 6d65c12ef2 Merge remote-tracking branch 'origin/master' into worktree/process-plugin-streaming-72f9b3
# Conflicts:
#	packages/client/ui-jobs/package.json
2026-09-03 11:30:41 +08:00
Yichen Jiang dd3ac9f7bf test(web): re-record the job goldens for the barrier-held scenarios after the merge 2026-09-03 11:28:13 +08:00
Yichen Jiang 5295b25073 Merge remote-tracking branch 'origin/worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery
# Conflicts:
#	apps/web/tests/background-job-list.e2e.ts
#	apps/web/tests/live-job-stream.e2e.ts
#	apps/web/tests/snapshots/live-job-stream/settled.expected.md
#	apps/web/tests/snapshots/live-job-stream/streaming.expected.md
#	packages/api/job-controller/README.i18n.yaml
#	packages/api/job-controller/README.md
#	packages/api/job-controller/README.zh.md
#	snapshots/web/background-job-list/running.expected.md
#	snapshots/web/background-job-list/settled.expected.md
2026-09-03 11:25:17 +08:00
Yichen Jiang 761282724b fix(jobs): constant pump waits, quiescent client disposal, record flag on the roster
Review corrections on the observation record:

- `pumpJobOutput` subscribes to `done` once and keeps one pending timer;
  racing the same pending promise every poll round retained a reaction
  per round for the life of the job.
- The `ctx.jobOutput` effect disposer is async and awaits every open
  carrier's `dispose()`, so the fiber reports unloaded only once the old
  iterators are quiescent.
- `SessionJob.record: true` replaces `outputTotal`: `append` never commits
  a roster change, so the mirrored count was stale while output flowed;
  the live offsets ride the observation stream's `opened` anchor.
- The record is documented as a best-effort live preview whose
  cross-stream reordering is bounded by the poll interval.
- The web e2e scenarios hold their background job on a test-owned barrier
  file instead of a wall-clock sleep, and each is one test rather than a
  chain sharing a job id.
2026-09-03 11:23:41 +08:00
pku-xht 681b0b66a9 fix(auto-review): align review and teardown boundaries 2026-09-03 08:07:42 +08:00
pku-xht 92cb99e9e9 test(snapshot): canonicalize Auto review PTC fixture 2026-09-03 06:39:10 +08:00
pku-xht 1ec5f21e82 fix(permission): tighten Auto review validation 2026-09-03 05:33:34 +08:00
pku-xht 64b05dacdd Merge commit '7dd92d1c8c5a6b1cf47ac677026fb08296abb809' into auto-review-per-call
# Conflicts:
#	apps/web/tests/shipped-composition.e2e.ts
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	docs/persistence-catalog.i18n.yaml
#	docs/persistence-catalog.md
#	docs/persistence-catalog.zh.md
#	packages/client/ui-conversation/src/client/apply.ts
#	packages/client/ui-conversation/src/client/contract/slots.ts
#	packages/client/ui-conversation/src/client/skeleton/InputBar.tsx
#	packages/client/ui-conversation/tests/input-bar.client.spec.tsx
#	packages/client/ui-conversation/tsconfig.json
#	packages/client/ui-tool/README.i18n.yaml
#	packages/client/ui-tool/README.md
#	packages/client/ui-tool/README.zh.md
#	packages/client/ui-tool/src/client/tool/ToolCallTree.tsx
#	packages/client/ui-tool/src/client/tool/components/ToolRow.tsx
#	packages/extensions/tool-cordis/src/api-catalog.ts
2026-09-03 02:44:29 +08:00
pku-xht 535d7eab3a feat(auto-review): enforce per-call authorization 2026-09-03 02:17:30 +08:00
Yichen Jiang e8469d6f6c refactor(jobs): move the human kill to the job namespace
`session.killJob` becomes `job.kill` on `dsh-api-job-controller`, beside
`job.observe`, so the Session Controller carries only session control and
the roster while every per-job Remote lives on the job namespace. The
client `ctx.jobOutput` gains `kill(sessionId, jobId)`; `dsh-client-ui-jobs`
routes its stop control through it and no longer requires `sessions`.
Unknown or foreign jobs reject with `job/not-found`; the controller
requires `ctx.jobs` to load, so `jobs-unavailable` disappears. The two
subagent ownership-fence helpers are classified duplicate-install-safe
Host exports of the Session Controller for the cross-controller import.
2026-09-02 23:18:08 +08:00
Yichen Jiang 121db081a4 Merge remote-tracking branch 'origin/worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery 2026-09-02 22:59:43 +08:00
Yichen Jiang 294c11715e Merge remote-tracking branch 'origin/worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/config-catalog.zh.md
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	packages/extensions/tool-cordis/src/api-catalog.ts
#	scripts/gen-cordis-catalog.ts
#	snapshots/web/cordis-tool-round/session.jsonl
#	snapshots/web/fresh-round-trip/session.jsonl
#	snapshots/web/ptc-round/session.jsonl
2026-09-02 22:59:20 +08:00
Yichen Jiang e42eb13655 test(web): drop the stray slash after the sourceRoot token in three prompt pins 2026-09-02 22:58:24 +08:00
Yichen Jiang 7ec142a325 refactor(jobs): move job observation into api-job-controller
Review asked for the observation wire and its client service to leave
session-controller: a job should reach the Host only through its own
Remote namespace, and the session plugin's apply had to materialize
{ $stream, session } for a service that is not session state.

@deepseek-ai/dsh-api-job-controller now owns the Host JobController
(job.observe over ctx.jobs, requiring the agent and job registries) and
the client ClientJobOutput (ctx.jobOutput) over ClientJobOutputModel,
resolving both Remote faces in its own apply. The remotes assembly
mounts the job namespace; ui-jobs injects the new package; the wire
types drop their Session prefix and spell the status union out so the
client face pulls no Host declaration merges into browser programs.
session-controller keeps the jobsBySession roster and loses observe-job,
job-output, and the observe cadence config.

ui-chat's slots and snapshot-builder import CommandNode and friends from
the declaring package: the typert analyzer's cross-package rule trips on
the snapshot re-export as soon as another client face joins the root
Client program (the new controller does), which is why this branch
carried the change before. JobPumpSource documents why it is an offset
snapshot reader rather than a Node.js Readable.
2026-09-02 22:53:36 +08:00
Yichen Jiang 4db24c642d Merge remote-tracking branch 'origin/master' into worktree/process-plugin-streaming-72f9b3
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/config-catalog.zh.md
#	packages/client/ui-chat/src/client/contract/slots.ts
#	packages/client/ui-chat/src/client/conversation-nodes/chat-snapshot-builder.ts
#	packages/client/ui-jobs/package.json
#	packages/extensions/cordis-client-runner/src/client/slot-catalog.ts
2026-09-02 22:04:03 +08:00
Yichen Jiang d1ec8baaf5 Merge remote-tracking branch 'origin/master' into worktree/job-kill-delivery
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/config-catalog.zh.md
#	packages/client/ui-chat/src/client/contract/slots.ts
#	packages/client/ui-chat/src/client/conversation-nodes/chat-snapshot-builder.ts
#	packages/client/ui-jobs/package.json
#	packages/extensions/cordis-client-runner/src/client/slot-catalog.ts
#	snapshots/web/ptc-round/session.jsonl
#	snapshots/web/ptc-round/system-prompt.expected.md
2026-09-02 21:40:24 +08:00
creatixchu 1516c6018d docs: propose logging each request's image projection 2026-09-02 14:53:45 +08:00
Yichen Jiang 374baa2621 Merge branch 'worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery
Carries the session seq-brand master sync forward; unions the seq/offset
imports with this branch's jobs augmentation in commands.ts and
regenerates the catalogs and zh ports over the merged source.
2026-09-01 22:20:21 +08:00
Yichen Jiang c1e6d09305 Merge branch 'master' into worktree/process-plugin-streaming-72f9b3
Absorbs the session seq-brand refactor and the turn-rail preview layer;
regenerates the catalogs and graph docs from the merged source and
re-ports the zh config/event rows this branch owns.
2026-09-01 22:13:35 +08:00
Yichen Jiang a5af861041 fix(ci): finish the background-workflow snapshot fallout
Regenerates the module graph for tool-workflow's new dsh-jobs edge (the
doc-sync aggregate does not run that gate), refreshes the web lane's own
schema/prompt pins for the run_in_background tool text, re-packs every
session fixture the keyless refresh had left off the canonical packed
layout, covers pwsh-local's never-spawned empty observed readers, and
rewrites the pwsh-sandbox sync-rejection start() test to the seam's
actual containment contract — execute() never throws; the sync spawn
throw settles the handle killed and result() carries the attribution
split. That test sits behind the pwsh probe, so only the Windows lane
had ever executed it.
2026-09-01 22:03:37 +08:00
Yichen Jiang 12957a106e feat(workflow): run_in_background registers the run as an observed job
The workflow tool gains run_in_background (enableRunInBackground config,
default on): the run registers on ctx.jobs as an owned 'workflow' record
job and the call returns { kind: 'background', jobId, runId } immediately.
The run belongs to the job — job_kill, the list's stop control, and owner
teardown cancel it; no tool-step signal is bridged. Settlement maps the
stop reason onto the job outcome, with a completed run's rendered return
value riding output to the completion notice and job_output. A record
mirror streams workflow/phase, workflow/log, and member lifecycle lines
into the job record, replacing the removed activity mirror; the output
schema becomes a kind-discriminated union and 'workflow' joins JobKindMap.
Snapshot expected outputs are refreshed for the schema, prompt, and PTC
stub changes (the keyless refresh also migrates fixtures to the current
session write format: range sourceEventSeqs and reasoning-delta chunks).
2026-09-01 21:24:37 +08:00
Yichen Jiang d23fdf8ab7 test(ci): port the offer-expiry executor suite to pwsh-local
The promotion machinery was copied from bash-local without its tests;
runners without pwsh skip and exempt the file, so only the Windows
coverage lane surfaced the gap.
2026-09-01 21:06:34 +08:00
Yichen Jiang e578d07354 Merge remote-tracking branch 'origin/worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery 2026-09-01 20:53:38 +08:00
Yichen Jiang 592dfd8854 test(ci): cover the owned promotion paths
An agent-attributed timeout promotion fences the job to the calling
session in both shell tools, and the pwsh promoted job's cancel hook is
exercised through a registry kill.
2026-09-01 20:53:32 +08:00
Yichen Jiang 1cec452f09 test(ci): close the observe-job coverage gaps
Covers the woken-wait fast path (a wake landing while the generator is
suspended on a yield), the opened frame's live-detail arm, and the
sessionId-less caller resolution over an unowned job.
2026-09-01 20:51:18 +08:00
Yichen Jiang da48f65160 Merge branch 'worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery
Carries the hairline-elevation sweep forward; the settled-section heading,
chevron box, and stop control move to 0.5px borders while keeping this
branch's padding.
2026-09-01 20:36:55 +08:00
Yichen Jiang 2540fd8b78 Merge branch 'master' into worktree/process-plugin-streaming-72f9b3
Absorbs the superellipse-corner and hairline-elevation sweep; keeps the
data-with-body header divider on TerminalBlock at the new 0.5px width and
brings the job-list settled-section rule onto the hairline standard.
2026-09-01 20:34:59 +08:00
Yichen Jiang 4ee1e1af25 Merge branch 'worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery
Carries the master sync forward (invariant-companion cleanup, alpha.3 bump);
regenerates the client api catalog so ISession lists both killJob and the new
loadThrough, and refreshes the new ptc-python-turn scenario's system-prompt
pin for this branch's bash timeout-promotion schema text.
2026-09-01 20:30:36 +08:00
Yichen Jiang 891b45bf7f Merge branch 'master' into worktree/process-plugin-streaming-72f9b3
Absorbs the repo-wide no-op invariant companion removal (ui-jobs loses its
placeholder companion, export, and devDep), the 0.1.2-alpha.3 release bump,
and the tool-subagent-report package retirement; regenerates the client slot
catalog for the shifted contract line numbers.
2026-09-01 20:22:52 +08:00
Yichen Jiang b5c29ece22 fix(ci): regenerate catalogs and settle the merged job-list evidence
Catalog line references and the re-landed promoteOnTimeout blocks follow
the merge in both languages; the ordering test narrows getAttribute's null
before startsWith so the client face compiles.
2026-09-01 19:42:18 +08:00
Yichen Jiang a2fb67d06c Merge branch 'worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery
# Conflicts:
#	apps/web/tests/background-job-list.e2e.ts
#	apps/web/tests/live-job-stream.e2e.ts
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/config-catalog.zh.md
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	packages/client/ui-activity/README.md
#	packages/client/ui-activity/README.zh.md
#	packages/client/ui-activity/src/client/index.ts
#	packages/client/ui-jobs/README.i18n.yaml
#	packages/client/ui-jobs/src/client/JobListAction.tsx
#	packages/client/ui-jobs/tests/browser-plugin.client.spec.ts
#	packages/client/ui-jobs/tests/job-list-action.client.spec.tsx
#	packages/jobs/jobs-local/src/index.ts
#	packages/jobs/jobs/README.i18n.yaml
#	packages/jobs/jobs/README.md
#	packages/jobs/jobs/README.zh.md
#	packages/jobs/jobs/src/index.ts
#	packages/shell/tool-bash/src/index.ts
#	packages/shell/tool-bash/tests/observe.spec.ts
#	packages/shell/tool-pwsh/src/index.ts
#	packages/shell/tool-pwsh/tests/observe.spec.ts
#	packages/workflow/tool-workflow/tests/activity-mirror.spec.ts
#	pnpm-lock.yaml
2026-09-01 19:35:23 +08:00
Yichen Jiang 419a985fc9 fix(api): capture the session namespace for job observation at apply time
Observation (re)opens run on caller stacks — a React expand click, a
carrier retry — whose dynamic context has not declared remote.session, so
the ClientJobOutput wiring resolves the namespace to a concrete value while
the plugin's own context is current, exactly as the activity client did.
Caught by the live-job-stream web e2e, whose goldens (with the
background-job-list pair) now carry the ui-jobs list name; the client-apply
spec gains a jobOutput wiring smoke.
2026-09-01 19:04:25 +08:00
Yichen Jiang d2e9be4086 test(api): stub session.observeJob on the fake client namespace
The regenerated session namespace requires the new stream; the fake serves
a never-yielding generator, and job-output.client.spec exercises the real
consumer.
2026-09-01 18:36:29 +08:00
Yichen Jiang 3c79e71cdc docs(i18n): mirror the record refactor across the bilingual pairs
Chinese sides of the jobs, jobs-local, tool-bash, tool-pwsh, tool-workflow,
session-controller, and ui-jobs pages follow their English edits; the
generated en-only catalogs (config catalog, capability seams, event
producer/consumer) get the same section surgery by hand; the activity
subsystem page triplet is fully removed and the jobs page carries the
record contract in both languages with fresh type-equiv manifest entries.
The three prior activity notes point at the superseding note. Web e2e label
assertions follow the ui-jobs copy, and the three test call sites that
invoked run() bare pass the producer face.
2026-09-01 18:34:36 +08:00
Yichen Jiang 0dca00b425 refactor(api,client)!: delete the activity plane; one job roster with record observation
packages/activity/* and packages/api/activity-controller are removed. The
web roster is the session control stream's jobs frames alone; per-job output
observation rides session.observeJob and the client ctx.jobOutput service.
ui-activity returns to its upstream name ui-jobs and renders the single
roster — a row is expandable exactly when its job declared a record
(outputTotal present). Composition rows, dependency-policy exemptions,
tsconfig aliases and references, generated catalogs, and the docs pages
follow; the activity subsystem page is deleted and the jobs page gains the
record contract. The superseding Agent Note records the decision and points
the three prior notes at it.
2026-09-01 18:22:04 +08:00
Yichen Jiang 6e8a7a50ea feat(api): serve job-record observation from the session namespace
SessionJob rows carry outputTotal exactly for record-declaring jobs, and a
new session.observeJob stream serves one job's retained record from an
absolute offset (anchor, coalesced output frames, terminal status) with the
fenced read resolved from the request's session — the same authorization
shape as the jobs roster. The client half gains ctx.jobOutput: the
reference-counted per-job observation service and its accumulated view
model, ported from the activity controller this replaces.
2026-09-01 18:03:09 +08:00
Yichen Jiang 8537b8d5bb refactor(shell,workflow): produce into the job record instead of ctx.activities
bash and pwsh background runs declare record: true and pump their observed
streams straight into the job through observeProcessRecord — the open/end
pairing, outcome mapping, and registry-absent degradation branches are gone,
and the pump's final drain folds into hooks.done so the record holds its
last bytes before settlement closes it. activityPollMs becomes recordPollMs.

tool-workflow drops its foreground activity mirror deliberately: a
foreground run's live phase/log narration had the mirror as its only
carrier, and the transcript keeps the recorded run/member lifecycle events.
Live narration returns with backgrounded runs when workflow gains
run_in_background.
2026-09-01 17:52:42 +08:00
Yichen Jiang e580c0b333 feat(jobs): fold the streaming observation record into the job registry
A job can now declare record: true and stream raw output into a bounded
per-job ring through the RunningJob face its starter receives: readRecord
serves any number of observers at absolute byte offsets without touching
the consuming model cursor or notice state, onOutput signals advancement,
and updateDetail publishes a live progress line into every snapshot. Job
settlement is the record's only end: it trims retention to the settled cap
and fires the final output signal, so producers no longer reconcile two
terminal states. pumpJobOutput ports the offset-reader pump beside the
seam. This is the first step of merging the standalone dsh-activity
observation plane into jobs.
2026-09-01 17:45:43 +08:00
pku-xht 3f610869b6 Merge commit '05380955d3d59a536c6c4f12def7c1586daaa613' into auto-review-per-call
# Conflicts:
#	docs/subsystems/session-projection.i18n.yaml
#	docs/subsystems/session-projection.md
#	docs/subsystems/session-projection.zh.md
#	packages/client/ui-conversation/tests/input-bar.client.spec.tsx
#	packages/client/ui-permission-presets/README.i18n.yaml
#	packages/client/ui-permission-presets/README.md
#	packages/client/ui-permission-presets/README.zh.md
#	packages/client/ui-permission-presets/tests/browser-plugin.client.spec.ts
#	packages/client/ui-tool/README.i18n.yaml
#	packages/client/ui-tool/README.md
#	packages/client/ui-tool/README.zh.md
#	packages/client/ui-tool/src/client/tool/components/ToolRow.tsx
#	packages/client/ui-tool/src/client/tool/toolviews/bash-sample.tsx
#	packages/client/ui-tool/tests/tool-row.client.spec.tsx
#	packages/extensions/tool-cordis/src/api-catalog.ts
#	packages/session/session-projection/README.i18n.yaml
#	packages/session/session-projection/README.md
#	packages/session/session-projection/README.zh.md
#	packages/session/session-projection/src/index.ts
#	packages/session/session-projection/tests/registry.spec.ts
2026-08-31 22:07:28 +08:00
pku-xht 02f20b7759 Merge commit '40ef442e90e9d9056982edc605db476a2b760ecd' into auto-review-per-call
# Conflicts:
#	apps/web/tests/shipped-composition.e2e.ts
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/config-catalog.zh.md
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	docs/persistence-catalog.i18n.yaml
#	docs/persistence-catalog.md
#	docs/persistence-catalog.zh.md
#	packages/client/ui-conversation/src/client/locales.ts
#	packages/client/ui-conversation/src/client/skeleton/PermissionSelect.tsx
#	packages/client/ui-conversation/tests/input-bar.client.spec.tsx
#	packages/client/ui-permission-presets/README.i18n.yaml
#	packages/client/ui-permission-presets/README.md
#	packages/client/ui-permission-presets/README.zh.md
#	packages/client/ui-permission-presets/src/client/index.ts
#	packages/client/ui-permission-presets/src/client/locales.ts
#	packages/client/ui-permission-presets/src/client/presentation.ts
#	packages/client/ui-permission-presets/tests/browser-plugin.client.spec.ts
#	packages/core/tools/src/ptc.ts
#	packages/interaction/permission-presets/src/index.ts
2026-08-31 17:25:58 +08:00
pku-xht 07e4ceb011 fix(web): localize Auto review descriptions 2026-08-31 14:18:51 +08:00
Yichen Jiang b684ae215f Merge branch 'worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery 2026-08-31 11:49:23 +08:00
Yichen Jiang 48939ba742 test(ci): pin the activity controller in the Host relay roster
The roster spec mirrors CLIENT_FACE_EXCLUDE; the activity controller
joined the excluded Host relays in the previous commit.
2026-08-31 11:49:00 +08:00
Yichen Jiang 8f031b9a71 fix(ci): declare ui-activity's dsh-session dev dependency under the flattened policy
ActivityListAction imports dsh-session types; the flattened client-face
policy wants that relationship recorded as a devDependency, and the
peer-slimming merge round dropped the entry.
2026-08-31 11:42:51 +08:00
Yichen Jiang f26eb7844e fix(ci): follow the merged kill-detail rendering and pack the refreshed fixtures
- tool-subagent's two job_kill scenarios now see the model's kill reason
  in the killed detail — the registry has merged kill reasons into the
  killed outcome since the human-kill work, and the master merge routed
  subagent aborts through that same settle path; the specs pin the new
  text.
- 112 session fixtures re-recorded by the earlier snapshot refresh
  predate master's canonical packed layout; migrate:packed-session-fixtures
  rewrote them mechanically and the keyless replay stays green.
- ActivityListAction's clear-while-expanded arm gets its missing client
  spec case (per-file coverage gate).
2026-08-31 11:41:17 +08:00
Yichen Jiang 8479c73102 Merge branch 'worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery 2026-08-31 11:41:16 +08:00
Yichen Jiang 8aa2dfa3a5 fix(ci): exempt the activity controller from flattened client-face dependencies
The master merge brought the published dependency policy: a package
declaring dsh.client flattens its non-Cordis peers unless excluded.
api-activity-controller is the same species as the excluded session and
workspace controllers — a Host Remote controller whose host half relays
real runtime peers (dsh-activity for the registry service and its brand
constructor at the wire boundary, dsh-invariants for the companion) —
so it joins CLIENT_FACE_EXCLUDE rather than dropping those peers.
2026-08-31 11:40:11 +08:00
Yichen Jiang 922c80ce66 Merge branch 'worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery
# Conflicts:
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	packages/api/session-controller/src/commands.ts
#	packages/api/session-controller/tests/session.client.spec.ts
#	packages/client/ui-activity/package.json
#	packages/shell/tool-bash/src/index.ts
#	packages/shell/tool-bash/tests/tools.spec.ts
#	packages/shell/tool-pwsh/src/index.ts
2026-08-31 11:22:11 +08:00
Yichen Jiang 6b2cc74984 Merge remote-tracking branch 'origin/master' into worktree/process-plugin-streaming-72f9b3
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/config-catalog.zh.md
#	docs/event-producer-consumer.i18n.yaml
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	packages/api/remotes/package.json
#	packages/client/ui-activity/package.json
#	packages/workflow/tool-workflow/src/index.ts
2026-08-31 11:18:10 +08:00
Yichen Jiang 74fa4be0a3 Merge branch 'worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery
# Conflicts:
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	packages/api/session-controller/src/types.ts
#	packages/api/session-controller/tests/fake-api.client.ts
#	packages/client/connection/src/rpc.ts
#	packages/extensions/cordis-client-runner/src/client/api-catalog.ts
#	packages/extensions/tool-cordis/src/api-catalog.ts
2026-08-29 14:23:22 +08:00
Yichen Jiang e47580f604 Merge remote-tracking branch 'origin/master' into worktree/process-plugin-streaming-72f9b3
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/event-producer-consumer.i18n.yaml
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	packages/client/ui-primitives/README.i18n.yaml
#	packages/client/ui-primitives/tests/use-dismiss-on-outside-pointer.client.spec.tsx
2026-08-29 14:13:36 +08:00
pku-xht 068c6ca3ff test(ui-tool): trim redundant Auto denial matrix 2026-08-29 06:57:15 +08:00
pku-xht e6ae1bc751 refactor(permission): simplify Auto review ownership 2026-08-29 06:24:58 +08:00
pku-xht 64fa60d3d4 fix(permission): close auto review gaps 2026-08-29 05:01:23 +08:00
pku-xht 1912573bde Merge commit '1ffc132ea51cfa57a86ae124ca3de6e650337c8c' into auto-review-per-call
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/config-catalog.zh.md
#	docs/persistence-catalog.i18n.yaml
#	docs/persistence-catalog.md
#	docs/persistence-catalog.zh.md
#	docs/subsystems/permission-presets.i18n.yaml
#	docs/subsystems/permission-presets.md
#	docs/subsystems/permission-presets.zh.md
#	knip.json
#	packages/extensions/tool-cordis/src/api-catalog.ts
#	packages/interaction/permission-presets/README.i18n.yaml
#	packages/interaction/permission-presets/README.md
#	packages/interaction/permission-presets/README.zh.md
#	packages/interaction/permission-presets/src/index.ts
#	packages/interaction/permission-presets/tests/permission-presets.spec.ts
2026-08-29 02:08:28 +08:00
pku-xht b3b7e00449 feat(permission): add Auto review mode 2026-08-29 00:56:21 +08:00
Yichen Jiang 02ef5e408f Merge branch 'worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery
# Conflicts:
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	packages/shell/bash-sandbox/tests/sandbox.spec.ts
#	packages/shell/tool-pwsh/tests/tools.spec.ts
2026-08-28 17:33:17 +08:00
Yichen Jiang 70311bc517 Merge remote-tracking branch 'origin/master' into worktree/process-plugin-streaming-72f9b3
# Conflicts:
#	docs/architecture.i18n.yaml
#	docs/config-catalog.i18n.yaml
#	docs/event-producer-consumer.i18n.yaml
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	knip.json
#	packages/bundle/web-app/cordis.patch.yml
#	packages/bundle/web-app/package.json
#	packages/client/README.i18n.yaml
#	packages/client/README.md
#	packages/client/README.zh.md
#	packages/extensions/cordis-client-runner/src/client/slot-catalog.ts
#	packages/shell/tool-bash/package.json
#	packages/shell/tool-pwsh/package.json
#	packages/workflow/tool-workflow/package.json
#	scripts/verify-package-readme-model-experience.ts
#	tsconfig.base.json
#	tsconfig.client.json
2026-08-28 17:29:41 +08:00
Yichen Jiang 48bbaa3e31 Merge branch 'worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/config-catalog.zh.md
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	packages/api/session-controller/README.i18n.yaml
#	packages/api/session-controller/README.md
#	packages/api/session-controller/README.zh.md
#	packages/api/session-controller/src/types.ts
#	packages/api/session-controller/tests/fake-api.client.ts
#	packages/api/session-controller/tests/test-remote.ts
#	packages/extensions/tool-cordis/src/api-catalog.ts
#	packages/host/apiproxy/src/api/rpc.schema.ts
#	packages/host/apiproxy/src/api/rpc.ts
2026-08-28 10:27:00 +08:00
Yichen Jiang d4683d5552 Merge remote-tracking branch 'origin/master' into worktree/process-plugin-streaming-72f9b3
# Conflicts:
#	docs/capability-seams.i18n.yaml
#	docs/capability-seams.md
#	docs/capability-seams.zh.md
#	docs/config-catalog.i18n.yaml
#	docs/event-producer-consumer.i18n.yaml
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	packages/bundle/web-app/cordis.patch.yml
#	packages/bundle/web-app/package.json
#	packages/client/ui-activity/package.json
#	packages/workflow/tool-workflow/README.i18n.yaml
2026-08-28 10:14:49 +08:00
Yichen Jiang 72efe7f15a Merge branch 'worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery 2026-08-27 21:48:33 +08:00
Yichen Jiang 5dcba9f760 Merge remote-tracking branch 'origin/master' into worktree/process-plugin-streaming-72f9b3
# Conflicts:
#	tsconfig.base.json
2026-08-27 21:48:02 +08:00
Yichen Jiang 9f24670323 test(session-controller): follow the two-argument Session constructor in the killJob specs
The master merge slimmed the client Session constructor to (id, remote,
options); the killJob specs from this branch still passed the FakeApiClient
as a second argument and stopped compiling.
2026-08-27 21:43:34 +08:00
Yichen Jiang df7e779a58 Merge branch 'worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery
# Conflicts:
#	packages/shell/tool-bash/tests/observe.spec.ts
#	packages/shell/tool-pwsh/tests/observe.spec.ts
#	packages/workflow/tool-workflow/tests/activity-mirror.spec.ts
2026-08-27 21:41:57 +08:00
Yichen Jiang e5d5d16dd2 Merge branch 'worktree/process-plugin-streaming-72f9b3' into worktree/job-kill-delivery
# Conflicts:
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	packages/api/session-controller/src/client/sessions/session.ts
#	packages/extensions/cordis-client-runner/src/client/api-catalog.ts
#	packages/extensions/tool-cordis/src/api-catalog.ts
#	packages/host/apiproxy/src/api/rpc.schema.ts
#	packages/session/session-projection-cache/tests/cache.spec.ts
#	packages/shell/tool-bash/tests/observe.spec.ts
#	packages/shell/tool-pwsh/tests/observe.spec.ts
#	snapshots/web/approval-composer/session.jsonl
#	snapshots/web/code-mode-round/session.jsonl
#	snapshots/web/cordis-tool-round/session.jsonl
#	snapshots/web/feedback-command/session.jsonl
#	snapshots/web/fresh-round-trip/session.jsonl
#	snapshots/web/goal-multi-turn-actions/session.jsonl
#	snapshots/web/lifecycle-chrome/session.jsonl
#	snapshots/web/live-interactions/session.jsonl
#	snapshots/web/minimal-preset/session.jsonl
#	snapshots/web/permission-policy-context/session.jsonl
#	snapshots/web/plan-review/session.jsonl
#	snapshots/web/question-composer/session.jsonl
#	snapshots/web/steering/session.jsonl
#	snapshots/web/turn-tail-actions/session.jsonl
#	snapshots/web/web-search-round/session.jsonl
2026-08-27 21:41:16 +08:00
Yichen Jiang 053979cdec test(activity): cover the owner arm and the pwsh outer observation catch
The coverage lanes flag four uncovered locations after the master merge:
the spec.owner spread in tool-bash/tool-pwsh observe, the workflow mirror's
owner spread, and tool-pwsh's outer observation catch. The covering tests
existed only on the stacked job-kill branch; give this branch its own:
an owned background run per shell asserting the fenced ownerSession row,
the owned workflow mirror run, and a throwing open() through the pwsh
outer catch. The windows-only file-reference-local gap reproduces on
master's own windows lane at the merge point and stays upstream.
2026-08-27 21:40:44 +08:00
Yichen Jiang ab75fe2bb6 Merge remote-tracking branch 'origin/master' into worktree/process-plugin-streaming-72f9b3
# Conflicts:
#	docs/capability-seams.i18n.yaml
#	docs/capability-seams.md
#	docs/capability-seams.zh.md
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/config-catalog.zh.md
#	docs/event-producer-consumer.i18n.yaml
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	knip.json
#	packages/api/remotes/src/client/index.ts
#	packages/api/remotes/tsconfig.client.json
#	packages/bundle/web-app/package.json
#	packages/client/ui-chat/src/client/contract/slots.ts
#	packages/client/ui-chat/src/client/conversation-nodes/chat-snapshot-builder.ts
#	packages/client/ui-primitives/README.i18n.yaml
#	packages/client/ui-subagent/README.i18n.yaml
#	packages/extensions/cordis-client-runner/src/client/slot-catalog.ts
#	scripts/gen-doc-graphs.ts
#	tsconfig.client.json
#	tsconfig.host.json
2026-08-27 20:03:20 +08:00
_Kerman 76d5f797a8 docs: refresh module graph 2026-08-27 13:01:00 +08:00
_Kerman 16654bee72 test(session-controller): cover control stream disposal 2026-08-27 13:00:57 +08:00
_Kerman ba51e5483e fix(ui-conversation): dispose Inbox projection subscription 2026-08-27 12:43:11 +08:00
_Kerman 8c8c5b2680 fix(web): restore pending Inbox after restart 2026-08-27 12:37:00 +08:00
_Kerman 6bfda7a0e5 fix(session-controller): address review feedback on cold Inbox commands
- Map an absent persistence backend to queue-item-not-found for updateQueue.
- Re-fence the published Agent after shared cold resume settles.
- Document cold queue activation and regenerate its public API catalog.
- Supersede the attached-only claim in the Web subagent conversations note.
2026-08-27 12:00:00 +08:00
_Kerman 6322bb96e8 fix(session-controller): resume cold sessions for Inbox commands 2026-08-27 11:48:50 +08:00
_Kerman 571736b477 Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-2672
# Conflicts:
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
2026-08-27 10:53:42 +08:00
_Kerman bfaa403b7c docs: refresh Claude SDK notices 2026-08-26 18:10:58 +08:00
_Kerman bfb119850b test: cover projection-aware session helpers 2026-08-26 18:10:52 +08:00
_Kerman 4c9fb910b1 Merge remote-tracking branch 'origin/master' into xtr/durable-inbox-recovery 2026-08-26 17:55:18 +08:00
_Kerman e5a5401228 Merge remote-tracking branch 'origin/master' into xtr/durable-inbox-recovery
# Conflicts:
#	docs/subsystems/session-projection.i18n.yaml
#	docs/subsystems/session-projection.md
#	docs/subsystems/session-projection.zh.md
#	packages/context/agent-instructions/tests/agent-instructions.spec.ts
#	packages/core/agent-loop/README.i18n.yaml
#	packages/core/agent-loop/README.md
#	packages/core/agent-loop/README.zh.md
#	packages/core/agent-loop/tests/cancel.spec.ts
#	packages/core/agent/README.i18n.yaml
#	packages/core/agent/README.md
#	packages/core/agent/README.zh.md
#	packages/llm/llm-retry/tests/retry.spec.ts
#	packages/session/session-projection/README.i18n.yaml
#	packages/session/session-projection/README.md
#	packages/session/session-projection/README.zh.md
2026-08-26 17:54:45 +08:00
_Kerman 5b9b7c59dd fix(session-controller): derive queues from projections 2026-08-26 17:35:55 +08:00
_Kerman fb3f3ff162 fix(agent): validate durable inbox reconstruction 2026-08-26 17:34:36 +08:00
Yichen Jiang 32e9f33fd2 feat(web): tighten task-list controls, fold the settled tail, merge the live meta line
Review of the first hierarchy pass in the browser: the 26px bordered controls
read oversized and the card fill visually stopped short of the stop button.
The controls drop to 20px squares, the live card's inner padding now frames
the dot and both controls on the fill, and the hover wash moves onto the card
itself so nothing escapes it. A live row's second line becomes kind + ticking
duration (the redundant 'running' word only returns through a real detail).
The settled tail folds behind a 'Finished N' toggle while live work exists
(auto-expanded otherwise) with a client-side Clear that hides the current
tail without touching the registry; goldens re-recorded for the new tree.
2026-08-26 17:10:26 +08:00
Yichen Jiang 4edf279ed6 feat(web): raise the task list's control affordance and row hierarchy
Live rows read as filled cards (fill-l2, the kind badge pops on the menu
surface instead), the expand chevron and the stop control become persistent
bordered squares (the stop turns danger on hover), and the popover widens to
500px. The settled tail keeps its flat rows, so running work now outranks it
visually — previously the colored settled dots were the loudest thing in the
list and both controls were bare tertiary glyphs invisible before hover.
2026-08-26 17:00:25 +08:00
Yichen Jiang bb1d472e94 fix(web): make the armed stop press legible without hover
The armed state relied on a color swap through --dsw-alias-label-error, a
token the themes never define, so the confirm step was effectively invisible.
The first press now widens the button into a labeled danger pill (确认停止 /
Confirm stop) tinted with the real state-error token StateDot uses; the
stream-failure notice moves off the same phantom token. Component spec pins
the inline label.
2026-08-26 16:35:11 +08:00
Yichen Jiang 8f3103b511 fix(jobs): address review — error scoping, subagent fence, pending kill
- session.killJob maps job-not-found from the lookup only: jobs.get gates the
  same synchronous span, so a producer-cancel throw now propagates per the
  registry contract (job state unchanged) instead of masquerading as a lookup
  failure (threads r3860226021, r3860226047).
- session.killJob applies the service-wide subagent ownership fence exactly as
  cancel does; a subagent-owned live session rejects with the ownership error
  and the child-owned job stays running (thread r3860226041).
- The stop control stays pending on an admitted kill: the unary response and
  the jobs frames have no cross-carrier ordering, so only the authoritative
  frame (the row leaving the killable set) releases the button, closing the
  duplicate-kill window (thread r3860226028).
- One-line comment on the killReason assignment stating last-writer-wins is
  intended, beside the first-claim-wins reported handling (thread r3860225999).

Host spec pins the producer-throw propagation and the fence; the component
spec pins pending-until-frame; the Agent Note records both refinements.
2026-08-26 16:19:34 +08:00
Yichen Jiang d6bebc5783 feat(shell): converge on execute() and promote timed-out commands to jobs
The executor seam collapses run()/start() (and the planned begin()) into one
resolve() + execute(): the handle IS the live process, and the foreground
result, the background cursor, and the deadline's promotion offer are
projections over the same spawn. ShellExecSpec.onExpiry ('kill' default /
'offer' / 'none') replaces the implicit method split; one stdout budget applies
everywhere, the 'start ignores timeoutMs' wart dies, and sync spawn throws are
contained into the same settled-killed handle as async rejections (result()
rejects with the original error, identity preserved for the sandbox
classification).

The promotion offer settles exactly once and never rejects — offer at an
'offer' deadline while running, undefined when the process settles first — so
'await execution.promotion' alone distinguishes the outcomes. An offer must be
answered synchronously; an unanswered one auto-declines back to the
kill-on-timeout behavior. accept() ends the deadline and detaches the caller's
abort signal; decline() kills and classifies timedOut.

tool-bash and tool-pwsh promote on timeout by default (promoteOnTimeout: true,
inert without run_in_background or a job registry): at the offer the running
handle registers as a job with the same hooks as run_in_background, mirrors
into ctx.activities (the web task list streams it, stop control included), and
the call returns { kind: 'promoted', jobId, timeoutMs, output } carrying the
output so far — the job cursor continues exactly after it. Any promotion
failure declines and falls back to the plain timeout kill. Descriptions and
the timeoutMs schema text advertise the semantics only when they hold;
recorded-session and web snapshot fixtures re-recorded with them.

Also repairs the four CI failures from the human-kill push: ui-activity's
missing dsh-session peer declaration (static + windows observational), the
observe owner-arm/outer-catch and killJob-stub coverage gaps, tool-workflow's
owned-run arm, and the timing-dependent projection-cache interval flush test
(now poll-based for coarse Windows timers).

Peer evidence and rejected alternatives (Codex's session model, a third seam
method, a second threshold knob) in the Agent Note
2026-08-26-shell-execute-timeout-promotion.
2026-08-26 16:11:01 +08:00
Yichen Jiang 51f74910ae feat(jobs): human job kill with an unclaimed terminal report
The web task list gains a two-press stop control on running job rows, built on
one seam change: JobRegistry.kill now takes { reason?, reported? } instead of a
positional reason. reported defaults to true (the model's job_kill claims the
terminal report exactly as before); the web path passes reported: false because
a human kill has no model-visible channel, so the settlement flows through the
existing tool-jobs completion notice (wakeup/inject, budgets, truncation all
unchanged). A recorded kill reason merges into a killed settlement's detail
(producer facts first: 'signal: SIGTERM; cancelled by the user'), so the notice
and the web row both say who stopped the work.

- session-controller: session.killJob Remote beside cancel, live-only Agent
  lookup, job-not-found/jobs-unavailable rejections joined to the closed RPC
  error table; ClientSession.killJob and the ISession face carry it to the UI.
- ui-activity: arm/confirm stop button (3s disarm, pending disable, failure
  hint), rendered only on running job rows; standalone activities keep no kill
  handle and the README limitation now says so.
- The background-job-list web e2e now drives the whole human path through the
  button; goldens show the merged killed detail end to end.
- Agent Note 2026-08-26-human-job-kill records the decision against Kimi's
  suppress-own-notification precedent and Claude Code's silent-kill failure;
  the 2026-08-08 blocker note and the unified-task-list note point at it.
2026-08-26 14:15:44 +08:00
Yichen Jiang 47ee13dd74 fix(ci): repair the four failures the master merge left behind
- live-activity-stream.e2e.ts still seeded from the old
  apps/web/tests/snapshots path and navigated to the unauthenticated
  baseUrl; the merge moved session recordings to snapshots/web/ and put
  browser trust behind scaffold.authenticatedUrl, and both updates reached
  the pre-existing background-job lane but not this branch-new file.
- tool-bash/tool-pwsh observe: the settlement-mapping catch introduced by
  the review fix had no covering test; both specs now drive a throwing
  end() through it.
- useDismissOnOutsidePointer lost its only branch coverage when the
  ui-jobs suite was deleted; the hook now has its own unit spec (outside
  close, inside ignore, closed detach, non-Node target).
- THIRD_PARTY_NOTICES.md regenerated at the merged lockfile's
  claude-agent-sdk 0.3.241: stale 0.3.220 store directories made the local
  generator resolve the old payload, so the committed file disagreed with
  a clean install.
2026-08-26 10:54:23 +08:00
Yichen Jiang c8c3540f15 Merge remote-tracking branch 'origin/master' into worktree/process-plugin-streaming-72f9b3
# Conflicts:
#	docs/capability-seams.i18n.yaml
#	docs/capability-seams.md
#	docs/capability-seams.zh.md
#	packages/bundle/web-app/package.json
#	packages/client/README.i18n.yaml
#	packages/client/README.md
#	packages/client/README.zh.md
#	packages/client/ui-activity/README.i18n.yaml
#	packages/client/ui-chat/src/client/conversation-nodes/retry.ts
#	packages/client/ui-jobs/README.md
#	packages/client/ui-jobs/README.zh.md
#	packages/client/ui-primitives/README.i18n.yaml
#	packages/client/ui-primitives/README.md
#	packages/client/ui-primitives/README.zh.md
#	packages/client/ui-subagent/README.i18n.yaml
#	packages/client/ui-subagent/README.md
#	packages/client/ui-subagent/README.zh.md
#	packages/jobs/jobs/README.i18n.yaml
#	packages/jobs/jobs/README.md
#	packages/jobs/jobs/README.zh.md
#	packages/shell/shell/README.i18n.yaml
#	packages/shell/shell/README.md
#	packages/shell/shell/README.zh.md
#	packages/shell/tool-bash/README.i18n.yaml
#	packages/shell/tool-bash/README.md
#	packages/shell/tool-bash/README.zh.md
#	packages/shell/tool-pwsh/README.i18n.yaml
#	packages/shell/tool-pwsh/README.md
#	packages/shell/tool-pwsh/README.zh.md
#	packages/workflow/tool-workflow/README.i18n.yaml
#	packages/workflow/tool-workflow/README.md
#	packages/workflow/tool-workflow/README.zh.md
2026-08-26 10:17:30 +08:00
_Kerman 5a1292b170 Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-2672
# Conflicts:
#	docs/module-graph.i18n.yaml
2026-08-25 21:56:03 +08:00
_Kerman 6912c41a08 Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-2672
# Conflicts:
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
2026-08-25 21:21:09 +08:00
Yichen Jiang 5ee10b3ebd Merge remote-tracking branch 'origin/master' into worktree/process-plugin-streaming-72f9b3
# Conflicts:
#	packages/client/ui-chat/src/client/chat/ContextInjectionRow.tsx
2026-08-25 16:50:24 +08:00
Yichen Jiang 69d8b6e7ea fix(activity): bind observation cleanup to its generation and settle before mapping the outcome
Both ds-review-bot criticals verified and fixed:

- ClientActivityFeed release closures resolved the entries map at release
  time, not the entry they were minted for. A late release of a superseded
  observation decremented (and could tear down) the successor's stream, and
  the post-dispose model clear could land after a re-observation inside the
  dispose round-trip re-anchored the view — blanking the panel until the
  popover reopened (React StrictMode's double effect hits the same window).
  Releasers now capture their entry, reconcile the map only when it still
  holds that entry, and skip the view clear whenever a successor owns the
  key. Both regressions fail on the previous code.

- The background observation tap mapped the process outcome as soon as the
  pump settled — including its failure path, where the process is usually
  still running: processOutcome requires a settled handle, so an early
  mapping froze 'exit code: 0' onto a live task and first-wins end discarded
  the real terminal state. The tap now awaits proc.done before mapping (the
  promise never rejects) and swallows mapping failures per the module's
  contract, in bash and its pwsh mirror.

Also applied from the same review: the Remote tier's cross-session
visibility is now stated in the controller README, ActivityRead.next
documents its chunk-boundary nature that client concatenation relies on,
mergeRows records the one-activity-per-job assumption, and the 08-24 Agent
Note now reflects the shipped unified task list.
2026-08-25 15:46:15 +08:00
Yichen Jiang f9c3a6c753 fix(activity): banner divider on live output and headings for both task sections
The TerminalBlock banner divider used to key off the running flag from the
days when a running card was banner-only; a running card that streams live
output now needs the same separation, so the divider follows the rendered
body (data-with-body) instead. The task list labels each non-empty section
(Running / Finished) rather than only dividing the settled tail, and the
leading section drops the divider line above its heading.
2026-08-25 14:58:26 +08:00
Yichen Jiang f10572a85d chore(client): regenerate the slot catalog after the master merge 2026-08-25 14:42:20 +08:00
Yichen Jiang 5cd435e917 Merge remote-tracking branch 'origin/master' into worktree/process-plugin-streaming-72f9b3
# Conflicts:
#	docs/config-catalog.i18n.yaml
#	docs/config-catalog.md
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	packages/client/ui-chat/src/client/contract/slots.ts
#	packages/shell/tool-pwsh/package.json
#	packages/workflow/tool-workflow/src/index.ts
#	python/sdk-runtime/package.json
2026-08-25 14:36:33 +08:00
Yichen Jiang e200eadd73 fix(activity): acceptance refinements — header band order and panel presentation
Interactive acceptance produced five presentation decisions:

- Header band order is preset → tasks → subagent catalog. The root-session
  descendant count moves out of the breadcrumb (header.lineage) into the
  actions band (order 30) as SubagentCatalogAction and drops its '/'
  separator — a root session has no hierarchy to breadcrumb. Child
  sessions keep their root/child switcher unchanged.
- The panel's copy control copies the command (TerminalBlock.copyText),
  not the output: a long command ellipsizes in the row, so the control is
  its only complete source, and it stays rendered before any output.
- Commands and output lines wrap in full (--dsl-terminal-command-whitespace
  / --dsl-terminal-line-whitespace: pre-wrap), so the output region never
  scrolls sideways; the region caps at a fixed height and scrolls
  (--dsl-terminal-output-max-height) with maxLines: Infinity disabling the
  head/tail fold.
- The panel draws no run-state dot (TerminalBlock.runStateDot: false) —
  the row above carries the same state — and reclaims the dot gutter via
  --dsl-terminal-gutter, which must target the card element itself because
  the variable is declared on it. The panel's left spine is gone with it.

All TerminalBlock changes are opt-ins (props or --dsl-terminal-* variables);
tool cards keep their shipped fold/ellipsis/dot behavior.
2026-08-25 14:23:12 +08:00
_Kerman e46a2499df Merge remote-tracking branch 'origin/master' into xtr/durable-inbox-recovery
# Conflicts:
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	packages/api/session-controller/tests/session-projections.host.spec.ts
2026-08-25 13:20:42 +08:00
Yichen Jiang 61aadb3abf feat(activity): one session-header task list joining jobs with their activities
Browser acceptance of the activity panel surfaced the product problem: a
background bash registers in both planes, so the header grew two near-
identical popovers — "background jobs" with lifecycle and duration,
"activities" with live output — listing the same work twice.

The service planes stay orthogonal (jobs: model-visible control with a
consuming read cursor; activities: transient non-consuming observation).
The join happens per row in the UI projection instead:

- dsh-client-ui-activity renders the single merged "tasks" list. Each
  jobsBySession row joins the activity carrying its correlation.jobId —
  the job supplies identity, lifecycle (stopping exists only there),
  duration, and the model-visible detail; the activity supplies the
  expandable live-output panel. Standalone activities (workflow runs)
  keep their own rows; without the activity registry, job rows still
  render and the control degrades to the old job list exactly.
- dsh-client-ui-jobs is deleted (pre-release, no shim); the merged entry
  takes its slot order. The job locale namespace folds into activity.
- User-facing copy says "task" (任务): N tasks running / N 个任务进行中.
- Hierarchy: live rows first as two lines (label over kind badge and
  status, ticking duration), a Finished divider when both sections
  exist, settled rows compacted to one de-emphasized line, and the
  output panel hangs behind a spine under its row.

Deliberately not joined: subagent rows stay bare (the subagent panel is
their surface) and foreground commands stay in tool cards.

Both web e2e scenarios now assert one Tasks list; the background-job
scenario's row gained a live-output panel, proving the join end to end.
Agent Note: 2026-08-25-unified-task-list.
2026-08-25 11:58:43 +08:00
Yichen Jiang ddd8baa93a fix(activity): mark evicted heads on fresh observation and fit the popover to the viewport
Browser acceptance against a live scaffold surfaced two defects:

- A fresh observation anchors at the registry's earliest retained byte, so
  the client's gap predicate (anchor behind earliest) never fired for it: a
  viewer who watched eviction live saw the gap notice, while a reload of the
  same activity silently hid that the head was discarded. A fresh view (no
  accumulated text) anchored past offset zero now carries the gap mark;
  resumes keep their recorded state.

- The trigger-anchored popover (left: 0, width 440px) overflowed the right
  viewport edge on narrow windows — max-width alone cannot see the anchor
  offset. The open popover now measures its anchor and shifts left to keep
  the Menu primitive's 12px viewport margin, re-fitting on window resize and
  falling back to the pure CSS anchor when layout reports no width (jsdom).

JobListAction shares the latent overflow; tracked separately.
2026-08-24 23:07:17 +08:00
Yichen Jiang 4a79310339 feat(activity): optional live-output observation seam with a web viewer
Add the activity capability seam: ctx.activities is a pure observation
plane where long-running work (background bash/pwsh, workflow runs) opens a
handle, appends transient output into a byte-offset ring buffer, and settles
exactly once. Nothing model-visible changes: reads are non-consuming and
lossy-by-design (absolute UTF-8 offsets survive eviction and report gaps),
correlation carries {callId, jobId}, and visibility is owner-fenced like jobs.

The seam is strictly optional. Producers tap it through ctx.get('activities')
and contain every observation failure, so an unregistered or broken registry
never affects the underlying job (proven by broken-registry tests).

Ship the full path in one change:
- @deepseek-ai/dsh-activity: Service Definition, pumpActivityOutput pull
  substrate, invariant companion; dsh-activity-local: ring-buffer provider
  with retention config and owner cleanup.
- shell: ShellProcess.observed exposes non-consuming stdout/stderr readers;
  tool-bash/tool-pwsh mirror background jobs into activities.
- tool-workflow: phase/log/agent lines mirrored as a workflow activity.
- api-activity-controller: Typert Remote control (roster baseline+buckets)
  and observe (opened/output/status frames, coalesced and byte-capped)
  streams plus the client feed service with reference-counted observation.
- ui-activity: session-header action rendering live output through
  TerminalBlock, which now shows output while a command is still running.

Docs: activity subsystem page, architecture row, regenerated catalogs, and
the Agent Note (2026-08-24-activity-observation-seam), all bilingual. A
keyless web e2e replays a real run_in_background stream to ARIA goldens.
2026-08-24 22:40:14 +08:00
Yichen Jiang ff5f94d3fb refactor(client): import conversation node types from their declaring package
Adding another client-face project to the client aggregate reshuffles the
typert analyzer's batches, which exposed latent provenance violations in
ui-chat and ui-approval: types consumed through ui-conversation's re-export
path instead of their declaring package, and one slot-contract literal whose
type the analyzer could not name. Import the types from
@deepseek-ai/dsh-client-ui-conversation/client directly and give the approval
interaction kind a named alias so the explicit annotation survives both the
analyzer and lint.
2026-08-24 22:40:00 +08:00
_Kerman 9deabe717f Merge remote-tracking branch 'origin/master' into xtr/durable-inbox-recovery 2026-08-24 13:17:57 +08:00
_Kerman 015d7e0752 docs(session-projection): keep registry contract unchanged 2026-08-24 13:14:21 +08:00
_Kerman 71a179a305 Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-2672 2026-08-24 11:13:56 +08:00
_Kerman 0aee112c6f test(session-projection): scope projection assertions 2026-08-21 13:24:41 +08:00
_Kerman 6b5e8c874c Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-2672 2026-08-21 12:53:36 +08:00
_Kerman b9d6314853 Merge origin/master into xtr/durable-inbox-recovery 2026-08-21 11:39:31 +08:00
_Kerman 09fab78863 test: trim unrelated inbox changes 2026-08-21 11:25:22 +08:00
_Kerman 4d5ccf39ef refactor(agent): remove inbox service 2026-08-21 11:19:36 +08:00
_Kerman 5609922d27 Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-2672 2026-08-20 15:58:12 +08:00
_Kerman 9b0d77b930 Merge remote-tracking branch 'origin/master' into dshw/pr-deepseek-harness-deepseek-harness-2672
# Conflicts:
#	docs/event-producer-consumer.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	docs/module-graph.i18n.yaml
#	docs/module-graph.md
#	docs/module-graph.zh.md
#	packages/core/agent-loop/tests/cancel.spec.ts
2026-08-19 16:05:35 +08:00
_Kerman 4b0af96838 refactor(agent): back Inbox with a durable projection 2026-08-19 14:09:35 +08:00
9203 changed files with 1375230 additions and 164380 deletions

No files matched your search

+45 -5
View File
@@ -1,6 +1,46 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for README.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/README.md
README.md: 8bf1adf875b54eb4580b4d189dfeed07c9f671c0
README.zh.md: ff9bdb358d584d4f4ad0aea295c31d8d8fff9376
/agent-notes:
en: a10991a192c7b55d
zh: c2e5b938ece4f366
/agent-notes/layout-and-naming:
en: 6b38cb0eb38c2baf
zh: 535234fb23fc8921
/agent-notes/classification:
en: 055a5e49f9af3dc2
zh: 9f7c78409cccfded
/agent-notes/archiving-and-deletion:
en: 6c393c7058c787d7
zh: 70ce9ca3bd9c2133
/agent-notes/when-to-write-one:
en: 2beb1b94d8fb633c
zh: 889b5542bb771205
/agent-notes/the-file-format:
en: 601f85df49f80fc7
zh: acbd0955d6543b13
/agent-notes/the-file-format/the-header-block:
en: 16fdaab0c74a5bb5
zh: 2553f145a1eb878f
/agent-notes/the-file-format/the-body-skeleton:
en: 740b7e964b9aec37
zh: 8551ddef1ffa776a
/agent-notes/the-file-format/the-body-skeleton/proposed:
en: acc0c035c5ca6fd7
zh: 8a65816dfac9e580
/agent-notes/the-file-format/the-body-skeleton/implemented:
en: f3523d7e40cc4e2f
zh: 574fa8959f8829a1
/agent-notes/the-file-format/the-body-skeleton/rejected:
en: f0ff5d05191f2315
zh: 3f9df0dd01a5cbed
/agent-notes/the-file-format/alternatives-considered-mandatory:
en: fe1bf385aee54033
zh: 37cb4ea86ec6d99d
/agent-notes/the-file-format/moving-between-lifecycles:
en: d3f18ba194dfb677
zh: 3d202868deda2f31
/agent-notes/the-file-format/chinese-counterparts:
en: d72a33b7c63722b2
zh: f8320c91b1f77ae6
+5 -5
View File
@@ -16,7 +16,7 @@ Every Agent Note has two axes, both encoded in its **path** — `{lifecycle}/{cl
The date in the filename is when the topic was **first proposed** (per git history). Cross-references between Agent Notes use relative markdown links (`[topic](../../implemented/architecture/2026-…-….md)`) — never bare prose or numbers — so they are mechanically checkable and survive moves between folders.
The active lifecycle tree is the working inventory: browse its lifecycle/class folders or search the repository. Do not add a centralized `INDEX.md`; the [no-index Agent Note](implemented/process/2026-07-19-remove-generated-agent-note-index.md) owns the rationale. Low-future-value implemented records move to the separate frozen [`archived/`](archived/AGENTS.md) tree described below.
The active lifecycle tree is the working inventory: browse its lifecycle/class folders or search the repository. Do not add a centralized `INDEX.md`; the [no-index Agent Note](implemented/process/2026-07-19-remove-generated-agent-note-index.md) owns the rationale. Implemented records with historical decision value but little future guidance move to the separate frozen [`archived/`](archived/AGENTS.md) tree described below.
## Classification
@@ -35,17 +35,17 @@ The `architecture` / `process` line: **architecture** is about the source we shi
## Archiving and deletion
Archive an implemented Agent Note when the shipped decision is complete and its rationale is unlikely to guide future work. Keep it active when its alternatives, ownership boundary, negative guarantee, durable or wire semantics, security rule, or reintroduction condition remains useful. Never archive a proposed note: reject an obsolete proposal. Keep a rejected note only while it prevents a plausible mistake; otherwise delete its English, Chinese, and sidecar files together. Use the calibrated [`dsh-archive-agent-notes`](../skills/dsh-archive-agent-notes/SKILL.md) workflow rather than word count, age, or a target quota.
Delete an implemented Agent Note that only describes small UI adjustments or purely mechanical changes; delete its English, Chinese, and sidecar files together and repair or remove inbound links. A local bug fix, performance change, new capability, or substantive behavior decision does not qualify merely because its implementation is small. Archive other implemented notes only when the shipped decision is complete, its rationale is unlikely to guide future work, and the record still has historical decision value. Keep it active when its alternatives, ownership boundary, negative guarantee, durable or wire semantics, security rule, or reintroduction condition remains useful. Never archive a proposed note: reject an obsolete proposal. Keep a rejected note only while it prevents a plausible mistake; otherwise delete its English, Chinese, and sidecar files together. Use the calibrated [`dsh-archive-agent-notes`](../skills/dsh-archive-agent-notes/SKILL.md) workflow rather than word count, age, or a target quota.
The archive is path-encoded as `archived/{class}/yyyy-mm-dd-topic-title.md`; `implemented` is deliberately absent because only implemented notes can enter it. An archival change moves the complete English/Chinese/sidecar triplet, retains `Status: implemented`, inserts the same `Archived: YYYY-MM-DD` line immediately below that status in both language files, re-records the sidecar, and repairs or deletes inbound links. These are the only permitted content changes during archival.
The archive is path-encoded as `archived/{class}/yyyy-mm-dd-topic-title.md`; `implemented` is deliberately absent because only implemented notes can enter it. An archival change moves the complete English/Chinese/sidecar triplet, retains `Status: implemented`, inserts the same `Archived: YYYY-MM-DD` line immediately below that status in both language files, re-records the sidecar, and repairs or deletes inbound links. These are the only permitted content changes during archival. Existing title punctuation, blank-line layout, and language-switcher wording do not block archival; preserve them with the body.
Once sealed, every archived triplet is permanently frozen. Do not edit, translate, reformat, update, move, or delete it, and do not treat it as authority for current behavior. Documentation gates skip archived sources, including their outbound links; active prose may still link into an archived note when it intentionally cites history. [`verify-archived-agent-notes`](../../scripts/verify-archived-agent-notes.ts) enforces the closed class tree, complete triplets, archive metadata, sidecar hashes, and the append-only frozen-content manifest. The [archive-policy Agent Note](implemented/process/2026-07-26-frozen-agent-note-archive.md) owns the rationale.
## When to write one
Every non-trivial change MUST add or update at least one Agent Note in the same PR. A change is non-trivial when it alters behavior, architecture, a contract shared across files or packages, process or tooling, testing strategy, an on-disk, wire, or configuration format, or another decision a maintainer may reasonably revisit. A proposal for substantial future work starts in `proposed/`; a decision already made starts in `implemented/`. Pick the class folder that matches the decision (see [Classification](#classification)).
Add or update an Agent Note in the same PR only for lasting decision rationale that code, tests, and existing documentation do not explain. A proposal for substantial future work starts in `proposed/`; a decision already made starts in `implemented/`. Pick the class folder that matches the decision (see [Classification](#classification)).
Updating the Agent Note that already owns the decision satisfies the rule; do not create a duplicate. Only a purely mechanical or local edit with no change to behavior, contracts, structure, process, or rationale is exempt. An Agent Note is never edited into a *different decision*: supersede it with a new one, and keep both notes cross-linked unless the old note is later fully consolidated under the rule below. Editing an `implemented/` Agent Note to track where its existing decision lives is required, not forbidden; see [implemented/AGENTS.md](implemented/AGENTS.md).
Updating the Agent Note that already owns the decision satisfies the rule; do not create a duplicate. Mechanical or local edits, including local UI presentation and interaction changes, are exempt. An Agent Note is never edited into a *different decision*: supersede it with a new one, and keep both notes cross-linked unless the old note is later fully consolidated under the rule below. Editing an `implemented/` Agent Note to track where its existing decision lives is required, not forbidden; see [implemented/AGENTS.md](implemented/AGENTS.md).
An implemented Agent Note that is fully superseded may be consolidated into the current owning note and deleted. Before deletion, the owner must preserve every unique rationale, alternative, consequence, required verification, and named coverage gap; repair every inbound link; and delete the Chinese counterpart and consistency record in the same change. Partial supersession does not qualify: keep both notes cross-linked and update every fact that remains current. Consolidation must not rewrite the old file into its opposite or rely on git history as the only copy of rationale.
+5 -5
View File
@@ -16,7 +16,7 @@
文件名中的日期是该主题**首次提出**的时间(以 git 历史为准)。Agent Note 之间的交叉引用使用相对 Markdown 链接(`[topic](../../implemented/architecture/2026-…-….md)`),从不使用纯文字或编号,这样既可机械检查,也能在文件夹间移动时保持有效。
活跃生命周期目录树就是工作清单:浏览其生命周期/类别文件夹,或搜索仓库即可。请勿添加集中式 `INDEX.md`;设计理由见[不设索引的 Agent Note](implemented/process/2026-07-19-remove-generated-agent-note-index.zh.md)。未来指导价值较低的已实施记录会移至下文所述、单独冻结的 [`archived/`](archived/AGENTS.md) 目录树。
活跃生命周期目录树就是工作清单:浏览其生命周期/类别文件夹,或搜索仓库即可。请勿添加集中式 `INDEX.md`;设计理由见[不设索引的 Agent Note](implemented/process/2026-07-19-remove-generated-agent-note-index.zh.md)。具有历史决策价值但未来指导价值较低的已实施记录会移至下文所述、单独冻结的 [`archived/`](archived/AGENTS.md) 目录树。
<a id="classification"></a>
@@ -37,9 +37,9 @@
## 归档与删除
当一份 implemented Agent Note 记录的交付决策已经完整落地,且其决策依据不太可能再指导未来工作时,将其归档。如果其中的备选方案、归属边界、否定性保证、持久化语义或协议语义、安全规则,或者重新引入条件仍有价值,则继续作为活跃记录保留。绝不归档 proposed Agent Note:过时的提案应转为 rejected。仅当 rejected Agent Note 仍能避免一种可能发生的错误时保留;否则一并删除其英文、中文和伴随记录文件。请使用经过校准的 [`dsh-archive-agent-notes`](../skills/dsh-archive-agent-notes/SKILL.md) 工作流,不要根据字数、存续时间或目标配额来判断。
仅描述小型 UI 调整或纯机械变更的 implemented Agent Note 直接删除;一并删除英文、中文和伴随记录文件,并修复或移除入站链接。局部 bug 修复、性能变更、新能力或实质行为决策,不会仅因实现规模小就符合删除条件。其他已实施记录只有在交付决策完整落地、其依据不太可能再指导未来工作,但仍具有历史决策价值时才归档。如果其中的备选方案、归属边界、否定性保证、持久化语义或协议语义、安全规则,或者重新引入条件仍有价值,则继续作为活跃记录保留。绝不归档 proposed Agent Note:过时的提案应转为 rejected。仅当 rejected Agent Note 仍能避免一种可能发生的错误时保留;否则一并删除其英文、中文和伴随记录文件。请使用经过校准的 [`dsh-archive-agent-notes`](../skills/dsh-archive-agent-notes/SKILL.md) 工作流,不要根据字数、存续时间或目标配额来判断。
归档路径编码为 `archived/{class}/yyyy-mm-dd-topic-title.md`;其中有意省略 `implemented`,因为只有 implemented Agent Note 可以进入归档。归档变更会移动完整的英文、中文和伴随记录三个文件,保留 `Status: implemented`,在两种语言的文件中紧接该状态行插入相同的 `Archived: YYYY-MM-DD` 行,重新记录伴随记录,并修复或删除入站链接。归档时只允许对内容做这些更改。
归档路径编码为 `archived/{class}/yyyy-mm-dd-topic-title.md`;其中有意省略 `implemented`,因为只有 implemented Agent Note 可以进入归档。归档变更会移动完整的英文、中文和伴随记录三个文件,保留 `Status: implemented`,在两种语言的文件中紧接该状态行插入相同的 `Archived: YYYY-MM-DD` 行,重新记录伴随记录,并修复或删除入站链接。归档时只允许对内容做这些更改。 既有标题标点、空行布局和语言切换栏措辞不阻止归档;与正文一起保留。
封存后,每组归档文件都永久冻结。禁止编辑、翻译、重新格式化、更新、移动或删除,也不得将其视为当前行为的权威依据。文档门禁会跳过归档源文件,包括其中的出站链接;当活跃文档有意引用历史时,仍可链接到归档 Agent Note。[`verify-archived-agent-notes`](../../scripts/verify-archived-agent-notes.ts) 强制执行封闭的类别目录树、完整的三文件配对、归档元数据、伴随记录 hash,以及仅追加的冻结内容 manifest(元数据清单)。[归档政策 Agent Note](implemented/process/2026-07-26-frozen-agent-note-archive.zh.md) 记录了设计依据。
@@ -47,9 +47,9 @@
## 何时需要写一份
每个非平凡变更都必须在同一 PR(Pull Request)中新增或更新至少一份 Agent Note。如果变更修改了行为、架构、跨文件或跨包约定、流程或工具、测试策略、磁盘存储格式、协议格式(wire format)或配置格式,或者维护者可能合理重新审视的其他决策,就属于非平凡变更。对未来重大工作的提案从 `proposed/` 开始;已经做出的决策从 `implemented/` 开始。选择与决策匹配的类别文件夹(见[分类](#classification))。
只有代码、测试和现有文档未能解释的决策理由具有长期价值时,才在同一 PR(Pull Request)中新增或更新 Agent Note。对未来重大工作的提案从 `proposed/` 开始;已经做出的决策从 `implemented/` 开始。选择与决策匹配的类别文件夹(见[分类](#classification))。
更新已经拥有该决策的 Agent Note 即可满足规则;不要创建重复记录。只有不涉及行为、约定、结构、流程或理由变化的纯机械性或局部编辑才可豁免。Agent Note 永远不会被编辑为一个*不同的决策*:用新 Agent Note 取代旧记录,并让两个记录保持互相链接,除非后续依据下方规则完全合并旧记录。编辑 `implemented/` Agent Note 以跟踪其现有决策的所在位置是必需的,而非禁止的;见 [implemented/AGENTS.md](implemented/AGENTS.md)。
更新已经拥有该决策的 Agent Note 即可满足规则;不要创建重复记录。机械性或局部编辑均可豁免,包括局部 UI 展示和交互调整。Agent Note 永远不会被编辑为一个*不同的决策*:用新 Agent Note 取代旧记录,并让两个记录保持互相链接,除非后续依据下方规则完全合并旧记录。编辑 `implemented/` Agent Note 以跟踪其现有决策的所在位置是必需的,而非禁止的;见 [implemented/AGENTS.md](implemented/AGENTS.md)。
被完全取代的 implemented Agent Note 可以合并到当前持有该决策的记录中,并删除原文件。删除前,当前记录必须保存所有独有的决策依据、备选方案、影响、必需的验证和明确指出的覆盖缺口;修复所有入站链接;并在同一变更中删除中文对侧文件和一致性记录。仅部分被取代的记录不符合此条件:保留两个记录并让它们互相链接,同时更新所有仍然适用的事实。合并不得将旧文件改写成与其相反的决策,也不得让 git 历史成为决策依据的唯一副本。
@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-08-03-per-session-agent-presets.md
2026-08-03-per-session-agent-presets.md: a1f2ad294edfdaaf2dab2d02e858e4dcb0a0c746
2026-08-03-per-session-agent-presets.zh.md: b745c22c91b4017131a32796c085a869a2eabaf0
@@ -1,6 +1,7 @@
# Agent Note: A session's agent is composed from a preset cordis.yml
Status: implemented
Archived: 2026-09-18
English | [中文](2026-08-03-per-session-agent-presets.zh.md)
@@ -27,13 +28,13 @@ The presets the deployment ships are the directories under `packages/preset/agen
Mounting is per-session by default. Measured cost for a twelve-row composition is ~3ms and ~600KB per session, so isolation is the cheaper default than any sharing scheme, and a preset authored by a user or by an agent then has the smallest possible blast radius. A preset that genuinely owns an expensive singleton opts into sharing with Cordis's own `isolate` vocabulary: a named realm label is process-global, so two subtrees naming the same label resolve one instance.
Which preset an unnamed session gets is a user setting (`agent-presets.default`) layered over the composition's own `default`, which becomes the `base`. Both layers are needed: the composition value is what a deployment ships and must keep working with no settings provider at all, and the setting is what a person changes without editing a `cordis.yml` they may not own.
The `agent-presets` user-settings namespace carries `modeSelectionEnabled` and `default`. `modeSelectionEnabled` defaults to `true`: the existing new-session picker remains present and an unnamed session resolves to the saved user `default`, or the composition's deployment `default` when none exists. The Web Settings toggle changes only that policy: disabling selection temporarily uses the deployment default, while re-enabling it restores the saved user `default`. This is a deliberate exception to the ordinary user-over-composition settings precedence established in #1539: hiding the chooser disables the user's mode-selection policy without deleting its saved value. The Host policy governs every later session whose caller omits a preset; explicitly named presets and existing sessions remain unchanged. The composition value also keeps the package working with no settings provider, while an enabled user override changes later sessions without editing a deployment-owned `cordis.yml`.
## Consequences
**The effective default is read per resolution, never snapshotted.** A cached value would need a `watch` subscription and a reload path to stay honest, and the resolved scope already re-reads a hot-reloaded document. Reading through is also what makes the boundary correct rather than merely cheap: the new value applies to the next session created, and every running session keeps the composition it was built from. That invariant is the same one the session log enforces from the other side — the header records the id a session was CREATED with and an `agent-preset/selected` event records any later blank-session switch, so a reader resolves the pair (`resolveSessionPreset`) and never the header alone: a resume rebuilds the composition its history was produced under rather than the deployment default at resume time, a cold transcript's presenters resolve in that composition's layer, and the gateway rejects an attempt to adopt a live session under a preset other than the one it currently runs. A snapshot would make the two disagree at exactly the moment the setting changes.
**The effective default is read per resolution, never snapshotted.** A cached value would need a `watch` subscription and a reload path to stay honest, and the resolved scope already re-reads a hot-reloaded document. The Host setting itself applies when an unnamed session is resolved afterwards. An explicit Web Settings action additionally routes its accepted effective default through the existing blank-session selection path only when the captured session id is still current and blank; it never recomposes a running session or rewrites that session's history. The session log enforces the same invariant from the other side — the header records the id a session was CREATED with and an `agent-preset/selected` event records any later blank-session switch, so a reader resolves the pair (`resolveSessionPreset`) and never the header alone: a resume rebuilds the composition its history was produced under rather than the deployment default at resume time, a cold transcript's presenters resolve in that composition's layer, and the gateway rejects an attempt to adopt a live session under a preset other than the one it currently runs. A snapshot would make the two disagree at exactly the moment the setting changes.
**A directly-plugged subtree is invisible to the boot audit.** It never links itself to an `Entry`, so it is absent from `ctx.loader.entries()` and `assertEntriesActivated` cannot see it. The mount audits its own rows instead, reading the tree through an `Include` subclass that publishes it.
**A directly-plugged subtree is invisible to the boot audit.** It never links itself to an `Entry`, so it is absent from `ctx.loader.entries()` and `auditStartupEntries` cannot see it. The mount reads its own rows through an `Include` subclass that publishes the tree and requires every enabled row to activate, independently of the [application startup policy](2026-09-09-consumer-owned-startup-strictness.md).
**A preset can only name a group because the app registers one.** Sharing a realm across rows is a `cordis:group` row, and a preset living outside this workspace — the authored ones under the Harness home, which is the point — cannot resolve `@cordisjs/plugin-group` by name: Node's upward `node_modules` walk never reaches the harness from there. `boot()` therefore registers `cordis:group` beside `cordis:include` as a loader builtin, so both load through the ambient module pipeline rather than through the included tree's own specifier resolution. Without it the `isolate` vocabulary above is expressible one row at a time only, and a provider could never be grouped with its consumers.
@@ -61,11 +62,11 @@ Which preset an unnamed session gets is a user setting (`agent-presets.default`)
**A preset's package names must resolve from the harness, not from the preset.** `EntryTree.import()` resolves a row against its own tree's `baseUrl`, which `Include` sets to the composition's directory. That is right for a relative specifier and fatal for a package name: a locally authored preset lives under the user's home, where Node's upward `node_modules` walk never reaches the installed harness, so every `@deepseek-ai/dsh-*` row fails to import and the whole preset is unmountable. The shipped presets hid this — they sit inside the install. The mount records the host composition's base before plugging the subtree and sends bare specifiers there, leaving relative paths resolving from the preset so its own files still travel with it. The real-composition test writing a preset into a temp root is what found it.
**The preset id is model-visible and must be logged.** It determines the tool set and prompt, so a resumed session has to restore the same composition; recording it is a session fact, not runtime state. It rides the session header beside `cwd`, and the summary carries it so a picker shows what a session actually runs rather than the deployment's current default.
**The preset id is model-visible and must be logged.** It determines the tool set and prompt, so a resumed session has to restore the same composition; recording it is a session fact, not runtime state. It rides the session header beside `cwd`, and the summary carries it so the client surfaces show what a session actually runs rather than the deployment's current default.
**A durable header field is not durable until the provider writes it.** `agentPreset` landed on `SessionHeader` with the right rationale and the JSONL provider omitted it; the derived query index also maps header fields explicitly, so a resumed Session came back with no preset and the surfaces that name it fell silent. `summarizeCold` had the same form — it hand-built the cold list row instead of reusing the shared projection. A field declared durable needs a test that crosses a real store, not only the type that declares it.
**The choice belongs to the screen where it still works.** The composer seat spent almost its whole life disabled, since the preset is fixed once a turn has run. It moved to the new-session screen beside the workspace picker, where the pick is *staged*: that screen precedes the session it applies to, and the stage lands when a session becomes current and is still blank — covering both the session a workspace connect creates and the blank one it reuses, which riding `sessions.create` would miss. It is spent on first use, matching the workspace picker beside it. What a running session runs is then a read-only label in its header: a control there would promise a switch the host refuses outright.
**The choice belongs to the screen where it still works.** The control lives on the new-session screen beside the workspace picker, is present under the default-on Host policy, and disappears only after `modeSelectionEnabled` is disabled. Its pick is *staged*: that screen precedes the session it applies to, and the stage lands when a session becomes current and is still blank — covering both the session a workspace connect creates and the blank one it reuses, which riding `sessions.create` would miss. It is spent on first use, matching the workspace picker beside it; hiding the picker discards a stage that has not reached a session and returns the current blank session to the deployment default through the same selection path. What a running or historical session runs remains a read-only label in its header: a control there would promise a switch the host refuses outright.
**A preset multiplies a cost the host was already paying: nothing disposes an agent.** Measured against the shipped compositions with `--expose-gc`, one live agent holds ~0.17 MB on `minimal` and ~1.31 MB on `standard`/`cordis`, mounting in ~38 ms and ~135 ms; the first agent of a process costs ~7 MB more as Node imports the modules, which every later mount then shares. Growth is strictly linear — 10, 30 and 50 agents give the same per-agent delta — and disposal reclaims essentially all of it (50 `standard` agents held 57.8 MB and returned it). So the object graph does not leak; the lifecycle does. `ApiSessionAgentController` discards the `AgentHandle` returned by the registry, `archiveSession` only edits the workspace registry, `AgentRegistry` has no eviction, and the sole disposal site in the host is the JSON-RPC server's own shutdown. A web host therefore retains every session it has touched, at ~1.3 MB each once presets are composed rather than ~0.2 MB before. Note that pruning the mount registry does not help here: it drops records whose fiber `uid` has cleared, and an agent that never dies never clears one.
@@ -1,6 +1,7 @@
# Agent Note: 会话的 agent 由一份 preset cordis.yml 组装而成
Status: implemented
Archived: 2026-09-18
[English](2026-08-03-per-session-agent-presets.md) | 中文
@@ -27,14 +28,13 @@ Status: implemented
挂载默认按会话进行。实测一份十二行组装每会话约 3ms、约 600KB,因此隔离比任何共享方案都更划算;而由用户或 agent 写出的 preset 也因此拥有尽可能小的影响面。确实自带昂贵单例的 preset,可以用 Cordis 自身的 `isolate` 词汇显式选择共享:命名 realm 的 label 是进程级全局的,因此两棵子树只要写同一个 label 就解析到同一个实例。
未指名 preset 的会话拿到哪一个,是一项用户设置(`agent-presets.default`),叠在组装自身的 `default` 之上——后者成为 `base`。两层都需要:组装里的值是部署交付的东西,在完全没有 settings 提供方时也必须照常工作;而设置是让人不必去改一份可能并不属于自己的 `cordis.yml` 就能调整的东西。
`agent-presets` 用户设置命名空间同时携带 `modeSelectionEnabled` 与 `default`。`modeSelectionEnabled` 默认为 `true`:既有的新建会话选择器保持显示;未指名会话会解析到已保存的用户 `default`,尚未保存时则使用组装中 `default` 指定的部署默认值。Web 设置开关只改变该策略:关闭选择时临时使用部署默认值,再次开启时恢复已保存的用户 `default`。这是对 #1539 所确立“用户值覆盖组装值”这一普通 settings 优先级的有意例外:隐藏选择器会停用用户的模式选择策略,但不会删除其保存值。该 Host 策略适用于此后所有未显式指定 preset 的会话;显式指定及既有会话不受影响。组装值还使本包在没有 settings 提供方时照常工作;选择器开启后,用户可覆盖默认值来改变后续会话,而无需编辑部署所拥有的 `cordis.yml`。
## 后果
**有效默认值在每次解析时读取,绝不保存快照。** 缓存下来就需要一个 `watch` 订阅和一条重载路径才能保持诚实,而解析后的 scope 本来就会重读热重载过的文档。读穿也不只是省事,它让边界本身是对的:新值作用于**下一个新建的会话**,每个运行中的会话保持它被构建时的那份组装。这条不变量正是 session 日志从另一侧执行的同一条——header 记录会话**创建时**的 id,此后空白期的任何切换由 `agent-preset/selected` 事件记录,因此读取方解析的是两者之和(`resolveSessionPreset`)、绝不单看 header:恢复重建的是其历史所产出的那份组装而不是恢复时的部署默认值,冷读记录的 presenter 在那份组装的层里解析,网关也会拒绝把一个活着的会话收编到它当前运行的 preset 以外的 preset 之下。快照会让两者恰好在设置改变的那一刻各说各话。
**有效默认值在每次解析时读取,绝不保存快照。** 缓存下来就需要一个 `watch` 订阅和一条重载路径才能保持诚实,而解析后的 scope 本来就会重读热重载过的文档。Host 设置本身会在此后解析未指名会话时生效。Web Settings 中的明确操作还会把已接受的有效默认值送入既有的空白会话选择链路,但只在操作前捕获的会话 id 仍是当前空白会话时对齐;它绝不会重新组装运行中的会话,也不会改写该会话的历史。session 日志从另一侧执行同一条不变量——header 记录会话**创建时**的 id,此后空白期的任何切换由 `agent-preset/selected` 事件记录,因此读取方解析的是两者之和(`resolveSessionPreset`)、绝不单看 header:恢复重建的是其历史所产出的那份组装而不是恢复时的部署默认值,冷读记录的 presenter 在那份组装的层里解析,网关也会拒绝把一个活着的会话收编到它当前运行的 preset 以外的 preset 之下。快照会让两者恰好在设置改变的那一刻各说各话。
**直接挂载的子树对启动审计不可见。** 它不会把自己关联到 `Entry`,因此不在 `ctx.loader.entries()` 中,`assertEntriesActivated` 也看不到它。改由挂载过程自行校验各行,通过一个会公开自身 tree 的 `Include` 子类读取。
**直接挂载的子树对启动审计不可见。** 它不会把自己关联到 `Entry`,因此不在 `ctx.loader.entries()` 中,`auditStartupEntries` 也看不到它。挂载过程通过一个会公开自身 tree 的 `Include` 子类读取各行,并要求每个启用行都激活,不受[应用启动策略](2026-09-09-consumer-owned-startup-strictness.zh.md)影响。
**preset 能写出 group,是因为 app 注册了它。** 跨行共享 realm 就是一个 `cordis:group` 行,而住在本工作区之外的 preset——也就是 Harness home 下由人或 agent 创作的那些,正是这套设计的目的——无法按名字解析 `@cordisjs/plugin-group`:Node 向上查找 `node_modules` 的路径从那里永远走不到 harness。因此 `boot()` 把 `cordis:group` 与 `cordis:include` 并排注册为 loader builtin,两者都经由环境模块管线加载,而不依赖被包含树自身的说明符解析。没有它,上文那套 `isolate` 词汇就只能一行一行地表达,提供方也永远无法与它的消费方归入同一组。
@@ -62,11 +62,11 @@ Status: implemented
**preset 的包名必须从 harness 解析,而非从 preset 解析。** `EntryTree.import()` 按行所属树的 `baseUrl` 解析,而 `Include` 把它设为组装文件所在的目录。这对相对标识符是对的,对包名却是致命的:本地创作的 preset 位于用户主目录之下,Node 向上查找 `node_modules` 永远够不到已安装的 harness,因此每一个 `@deepseek-ai/dsh-*` 行都会导入失败,整个 preset 无法挂载。随部署提供的 preset 掩盖了这一点——它们本就在安装目录之内。挂载在插入子树之前先记录宿主组装的基址,并把裸标识符送往那里,同时让相对路径继续从 preset 解析,使它自带的文件仍随它一同迁移。发现它的正是那个把 preset 写入临时根目录的真实组装测试。
**preset id 对模型可见,必须写入日志。** 它决定工具集与提示词,因此被恢复的会话必须还原同一份组装;记录它属于会话事实,而非运行时状态。它与 `cwd` 并列写在会话头部,并由会话摘要携带,使选择器显示的是某个会话实际运行的 preset,而非部署当前的默认值。
**preset id 对模型可见,必须写入日志。** 它决定工具集与提示词,因此被恢复的会话必须还原同一份组装;记录它属于会话事实,而非运行时状态。它与 `cwd` 并列写在会话头部,并由会话摘要携带,使客户端界面显示某个会话实际运行的 preset,而非部署当前的默认值。
**持久化 header 字段在 provider 写入前都算不上持久。** `agentPreset` 带着正确理由落在 `SessionHeader` 上,而 JSONL provider 遗漏了它;派生 query index 也显式映射 header 字段,于是恢复后的 Session 没有 preset,所有据以命名它的 surface 随之失声。`summarizeCold` 是同一种形式——它手工拼装 cold list row,而没有复用共享 projection。声明为持久的字段,需要一个跨越真实 store 的测试,而不只是声明它的类型。
**这个选择属于它仍然可用的那个界面。** composer 座位几乎一生都处于禁用状态,因为一旦跑过一个轮次,preset 即固定。它移到了新建会话界面、工作区选择器旁边,选择在那里是**暂存**的:该界面先于它要应用到的会话存在,暂存值在某个会话成为当前会话且仍为空白时落地——这既覆盖工作区连接新建的会话,也覆盖它复用的那个空白会话,而搭 `sessions.create` 的便车会漏掉后者。它一经使用即被清空,与旁边的工作区选择器一致。至于运行中的会话在跑什么,则是其标题旁的一个只读标签:在那里放控件,等于承诺一次宿主会断然拒绝的切换。
**这个选择属于它仍然可用的那个界面。** 控件位于新建会话界面、工作区选择器旁边,在 Host 默认开启策略下直接显示,仅在 `modeSelectionEnabled` 关闭后隐藏。选择在那里是**暂存**的:该界面先于它要应用到的会话存在,暂存值在某个会话成为当前会话且仍为空白时落地——这既覆盖工作区连接新建的会话,也覆盖它复用的那个空白会话,而搭 `sessions.create` 的便车会漏掉后者。它一经使用即被清空,与旁边的工作区选择器一致;隐藏选择器会丢弃尚未到达会话的暂存选择,并通过同一条选择链路把当前空白会话带回部署默认值。至于运行中或历史会话在跑什么,仍由其标题旁的只读标签展示:在那里放控件,等于承诺一次宿主会断然拒绝的切换。
**preset 放大的是宿主本来就在付的代价:没有任何东西会 dispose 一个 agent。** 用 `--expose-gc` 对随附组装实测:一个存活的 agent 在 `minimal` 上约占 0.17 MB、在 `standard`/`cordis` 上约 1.31 MB,挂载耗时分别约 38 ms 与 135 ms;进程里第一个 agent 另需约 7 MB,那是 Node 首次 import 模块的一次性成本,此后每次挂载共享。增长严格线性——10、30、50 个的单个增量一致——且 dispose 后基本全额回收(50 个 `standard` 占住 57.8 MB,释放后全部归还)。所以对象图并不泄漏,缺的是生命周期。`ApiSessionAgentController` 会丢弃注册表返回的 `AgentHandle`,`archiveSession` 只改工作区注册表,`AgentRegistry` 没有驱逐机制,而宿主里唯一一处 dispose 是 JSON-RPC 服务器自身的关停。于是一个 web 宿主会留住它接触过的每一个会话,组装 preset 之后每个约 1.3 MB,而在此之前约 0.2 MB。注意:剪枝挂载注册表在这里没有用——它丢弃的是 fiber `uid` 已清空的记录,而永不死亡的 agent 永远不会清空它。
@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/archived/architecture/2026-09-02-durable-image-offload.md
2026-09-02-durable-image-offload.md: db03e9f52499c1790b3a0c03853f3aea23315bec
2026-09-02-durable-image-offload.zh.md: 2b6d0a4aa65f9a39b88888506f7e85b4cfff48cf
@@ -0,0 +1,56 @@
# Agent Note: Durable image offload by surface replacement
Status: implemented
Archived: 2026-09-10
English | [中文](2026-09-02-durable-image-offload.zh.md)
## Problem
Request-size image offload was recomputed from scratch on every request. Each route collected every image occurrence on the derived surface, oldest first, and once the accumulated bytes exceeded its budget it rounded the excess up to a whole removal quantum and replaced that many oldest occurrences with placeholder text, per the [unified image request pipeline](../feature/2026-08-20-unified-image-request-pipeline.md). Nothing remembered where the previous request stopped; the prefix was stable only because the arithmetic over an append-only history repeated itself.
That stability failed wherever the arithmetic inputs moved. The [Files inline fallback](../../archived/bug-fix/2026-08-21-deepseek-files-inline-fallback.md) rebuilt a request under a 20 MiB inline budget with a 10 MiB quantum, offloading far more images for that one request, and the next request in file mode brought them back. The pi-ai route used a quantum of one byte, so its prefix moved on almost every request. Compaction lowered the total and returned previously offloaded images. A route switch moved every step boundary. Each move changed the model-visible prefix and invalidated the provider cache prefix.
The same recomputation broke the repository invariant that model-visible input is reconstructable from the session log. Which representation was dispatched, the exact derived request-version byte lengths, and the route budgets and quanta were runtime or configuration facts that never entered the log; `request/header` records call config, system prompt, and tools only. Provider usage anchors token totals and cannot recover the image set, and the [route-priced estimate](../../archived/feature/2026-08-24-route-priced-image-request-pressure.md) documented that it did not reproduce the fallback budget. No consumer could pair a logged assistant response with the image set its request carried.
## Decision
The offload of an image occurrence is a durable surface fact recorded the way compaction records its reductions: a `surfaceOp: replace` node.
**Marked copies on the surface.** `ImageBlock` gains `offloaded?: true`. An offloaded occurrence lives in a replacement event of the same type as the node that carried it (`user/message` or `tool/result`) whose content is a copy of the original with those blocks marked; `sourceEventSeqs` points at the replaced node. The session core, its event map, its derivation, and its validation are unchanged. `deriveMessages()` sends the marked block; serialization renders every marked block as `offloadedImageText` with the currently resolved access path and prepares only retained occurrences.
**Only advances.** A replacement never reverts. When a budget grows, a route changes, or compaction lowers the total, the marked copies stay, so the model-visible prefix and the provider cache prefix move only forward.
**Adapters project, never decide.** An image-capable route enforces an `LlmImageRequestBudget` (`representation`, `maxBytes`, `maxImages`, both quanta) over the retained occurrences' exact request-version bytes. When they still exceed the budget, in file mode, under the inline fallback's tighter budget, or under the pi-ai bound, the adapter fails the attempt with `IMAGE_OFFLOAD_REQUIRED` and `LlmFailure.offloadImages` naming how many more oldest occurrences must be offloaded, computed with the shared `requiredImageOffload()`. Nothing plans an offload before dispatch.
**Recovery owned by `dsh-compaction-image-offload`.** Image offload is compaction in another capacity dimension: the provider rejects a request, durable history is reduced, the step retries. The executor is a sibling of `compaction-tool-result-pruner` in the compaction group and listens on the `agent/request-error` waterfall. On `IMAGE_OFFLOAD_REQUIRED` it walks the surface in model request order, marks the first `offloadImages` retained occurrences, and for each node that carried one appends the seam's `compaction/prune` shadow price followed by the marked copy, then returns the `retry` action without spending the provider retry budget or logging `llm/retry`. Assistant nodes carry model output, not input images, and are skipped. When nothing remains to offload it delegates and the failure reaches ordinary recovery. The loop re-runs the step over the replaced surface and logs the fresh `request/header` every surface replacement gets; the agent loop is unchanged.
**Token accounting.** `priceImages` receives the surface's `ImageBlock`s and prices a marked one as its placeholder text; the DeepSeek and replay pricing no longer reproduce any offload arithmetic. The meter needs no new state: the `compaction/prune` event and the replacement reprice the node like a tool-result prune.
**Other consumers.** Compaction reconstructs each selected event through `deriveEventMessage()` and sees the marks. Resume, fork, and replay reproduce the surface from the log. Text-only routes keep their separate whole-history substitution.
## Alternatives considered
**Keep recomputing the offload point per request.** Stable only while the arithmetic inputs held still; the inline fallback, the pi-ai quantum, compaction, and route switches all moved the prefix, and no consumer could reconstruct a historical request's image set.
**Record each request's projection outcome as a log-only event.** Restores reconstructability but not stability: the recorded outcome is not a decision input, so every oscillation still happens and the log merely documents it, with two sources of truth for the offloaded set that can disagree.
**Log the full projected request body.** Everything except the offload decision is already derivable; repeating the history per request grows the log quadratically to record one position.
**A log-only `image/offload` watermark event applied by session derivation.** An earlier revision recorded the offload point as a position (event seq plus block path) and had `Session.deriveMessages()` mark every occurrence at or before it. That gave the session a second mechanism for changing model-visible history next to `surfaceOp: replace`, with its own validation, fold, cache invalidation, and required-on-read event, and placed the logic in the core instead of on the plugin that decides. Issue #3041 asks that a permanent eviction use a surface-changing event rather than a request-projection event; because the offload never reverts, it is one.
**Let each adapter append the replacement.** The adapter owns the budgets but not the session surface; a surface change appended below the loop lets two adapters define the surface differently. Adapters report the count they need instead.
**Plan the offload before dispatch, in the loop or in a plugin.** The loop knows the exact prepared route before deriving each request, so planning there never spends a failed attempt; but it puts a route-specific policy into the one component every profile shares, changes the documented step order, and bypasses the `agent/request-error` waterfall that context-overflow compaction and retry already use for the same repair-and-retry pattern. A pre-step plugin keeps the loop unchanged but cannot see the step's own messages or the first request's route, so the failure path stays necessary, and the plan needs every route to declare its budget on its model info. Handling only the failure costs one attempt per quantum crossing (64 MiB in DeepSeek file mode, 20 MiB on pi-ai) and matches the planned direction: routes will stop checking sizes locally, send every image, and the provider will report what it cannot cache, which is exactly a failure naming an offload point.
**Keep a transient extra offload for the inline fallback and exact-byte overflow.** Would have sent an unlogged projection in exactly the cases the invariant exists for; the failure-and-advance path costs one serialization attempt and keeps every dispatched request derivable from the log.
## Consequences
Offloaded images never return automatically when budgets grow, a larger route is selected, or compaction lowers the total; recovery is the read-only path in the placeholder, which the model uses deliberately. A Files outage or a temporary switch to a small-budget route offloads permanently; both are accepted for the same reason. Each offload copies the carrying node's message into the log; images are references, so the copy is the node's text plus block metadata.
Every dispatched request's image set is determined by the log alone, across file mode, inline fallback, resume, fork, retry, and compaction, and the provider cache prefix no longer oscillates. The execution-world access path embedded in placeholder and handle text is still resolved at serialization time; that gap exists for retained images too and belongs to a separate decision about recording the execution-world mapping. The route-local byte checks are provisional: once the provider reports uncacheable images itself, `requiredImageOffload()` and the route budgets go away while the marked copies and the recovery branch stay as they are.
## Testing
`packages/llm/llm/tests/content.spec.ts` pins arbitrary-depth image traversal, the offload count including the 129-to-64 MiB quantum example, and placeholder projection. `packages/compaction/compaction-image-offload/tests/image-offload.spec.ts` pins the `IMAGE_OFFLOAD_REQUIRED` replace-and-retry path with its `compaction/prune` shadow prices and without a retry event, the untouched original node, request-order counts after an earlier surface replacement, and the exhausted case that delegates downstream. Adapter specs pin placeholder projection, prepared-only-retained reads, and the exact-byte failure with its count; `route-pricing.spec.ts` pins placeholder pricing for a marked replacement. The `inline-image-prompt` TypeScript SDK snapshot replays an authored `IMAGE_OFFLOAD_REQUIRED` attempt through the shipped profile and pins the replacement and the retried request.
@@ -0,0 +1,56 @@
# Agent Note: 以表层替换实现持久的图片 offload
Status: implemented
Archived: 2026-09-10
[English](2026-09-02-durable-image-offload.md) | 中文
## 问题
请求级图片 offload 过去在每次请求时都从头重算。每条路由按最老优先的顺序收集派生表层上的全部图片出现位置,累计字节一旦超过预算,就把超出部分向上取整到整个删除量子,把这么多最老的出现位置替换为占位文本,见[统一图片请求管线](../feature/2026-08-20-unified-image-request-pipeline.zh.md)。没有任何东西记住上一次请求停在哪里,前缀稳定只是因为对 append-only 历史做同样的算术会得到同样的结果。
算术的输入一动,这种稳定就失效。[Files 内联回退](../../archived/bug-fix/2026-08-21-deepseek-files-inline-fallback.md)会用 20 MiB 内联预算和 10 MiB 量子重建请求,那一次省略多得多的图片,下一次 file 模式的请求又把它们带回来。pi-ai 路由的量子是一个字节,前缀几乎每次请求都会移动。compaction 降低总量,让先前省略的图片回归。切换路由会移动每个台阶边界。每一次移动都改变模型可见前缀,并让 provider 的缓存前缀失效。
同样的重算也破坏了仓库不变量:模型可见输入必须能从 session log 重建。实际发出的表示方式、派生请求版本的精确字节长度、路由预算和量子都是运行时或配置事实,从不进入日志,`request/header` 只记录调用配置、系统提示词和工具。provider usage 只锚定 token 总量,恢复不了图片集合,[按路由定价的估计](../../archived/feature/2026-08-24-route-priced-image-request-pressure.md)也写明它不复现回退预算。没有任何消费方能把一条已记录的助手响应和它的请求携带的图片集合配对。
## 决定
一个图片出现位置的省略是一条持久的表层事实,记录方式和 compaction 记录它的缩减一样:一个 `surfaceOp: replace` 节点。
**表层上带标记的副本。** `ImageBlock` 新增 `offloaded?: true`。被省略的出现位置存在于一条与原承载节点同类型的替换事件里(`user/message` 或 `tool/result`),内容是原消息的副本,只把那些块打上标记;`sourceEventSeqs` 指向被替换的节点。session 核心、它的事件表、派生和校验都不变。`deriveMessages()` 原样发送带标记的块;序列化把每个带标记的块渲染为带当前已解析访问路径的 `offloadedImageText`,只准备保留的出现位置。
**只前进。** 替换永不回退。预算变大、路由切换或 compaction 降低总量时,带标记的副本留在原地,所以模型可见前缀和 provider 缓存前缀只向前移动。
**adapter 只投影,不决定。** 支持图片的路由按保留的出现位置的精确请求版本字节执行一个 `LlmImageRequestBudget`(`representation`、`maxBytes`、`maxImages` 与两个量子)。当它们仍超过预算,无论是 file 模式、内联回退更紧的预算还是 pi-ai 上限,adapter 都以 `IMAGE_OFFLOAD_REQUIRED` 让本次尝试失败,并在 `LlmFailure.offloadImages` 中用共享的 `requiredImageOffload()` 算出还需省略多少最老的出现位置。发送前没有任何规划。
**恢复归 `dsh-compaction-image-offload`。** 图片省略是 compaction 在另一个容量维度上的实例:provider 拒绝请求,持久历史被缩减,step 重试。执行器是 compaction 组里 `compaction-tool-result-pruner` 的兄弟包,监听 `agent/request-error` waterfall。收到 `IMAGE_OFFLOAD_REQUIRED` 时,它按模型请求顺序遍历表层,给前 `offloadImages` 个保留的出现位置打标记,为每个承载了其中任一位置的节点先追加 seam 的 `compaction/prune` 影子价格,再追加带标记的副本,然后返回 `retry` 动作,不占提供方重试预算,也不记录 `llm/retry`。assistant 节点承载的是模型输出而不是输入图片,直接跳过。没有可省略的出现位置时向下游委托,失败进入普通恢复路径。循环在替换后的表层上重跑该 step,并像每次表层替换后一样记录新的 `request/header`;agent loop 不变。
**token 记账。** `priceImages` 接收表层的 `ImageBlock`,把带标记的按占位文本定价;DeepSeek 和 replay 的定价不再复现任何 offload 算术。meter 不需要新状态:`compaction/prune` 事件加替换节点,和工具结果剪枝一样重新为该节点定价。
**其他消费方。** compaction 通过 `deriveEventMessage()` 重建每个选中事件,看得到标记。resume、fork 和重放从日志复现表层。纯文本路由保留各自的全历史替换。
## 考虑过的替代方案
**继续每次请求重算 offload 位置。** 只在算术输入不动时稳定,内联回退、pi-ai 量子、compaction 和路由切换都会移动前缀,且没有消费方能重建历史请求的图片集合。
**用 log-only 事件记录每次请求的投影结果。** 恢复了可重建性但没有稳定性:记录的结果不是决策输入,每一种抖动照旧发生,日志只是把它记下来,且省略集合有两个可能不一致的事实来源。
**记录完整的投影后请求体。** 除 offload 决定外一切都已可派生,为记录一个位置而每次请求重复整段历史会让日志平方级增长。
**由 session 派生应用的 log-only `image/offload` 水位事件。** 更早的一版把 offload 点记成一个位置(事件序号加块路径),由 `Session.deriveMessages()` 给位于它及之前的每个出现位置打标记。这让 session 在 `surfaceOp: replace` 之外多出第二种改变模型可见历史的机制,带着自己的校验、折叠、缓存失效和读取时必须识别的事件,并且把逻辑放进了核心而不是做决定的插件。issue #3041 要求永久淘汰使用改变表层的事件而不是请求投影事件;省略永不回退,它就是永久淘汰。
**让各个 adapter 自己追加替换。** adapter 拥有预算,但不拥有会话表层;在循环之下追加表层变更会让两个 adapter 对表层做出不同定义。adapter 改为上报它需要的数量。
**在发送前规划省略,无论放在循环里还是插件里。** 循环在派生每个请求之前就知道精确的已准备路由,在那里规划永远不会多花一次失败的尝试;但这会把一条路由专属的策略放进所有 profile 共用的那个组件,改变已记录的 step 顺序,还绕过了上下文溢出 compaction 和重试已经在用的同一套 `agent/request-error` waterfall。pre-step 插件不改循环,但看不到 step 自己的消息和第一个请求的路由,失败路径仍然必需,而且规划要求每条路由在模型信息上声明预算。只处理失败的代价是每越过一个量子多一次尝试(DeepSeek file 模式 64 MiB,pi-ai 20 MiB),并且和既定方向一致:路由将不再本地检查大小,全部发送,由 provider 报告无法缓存的部分,那正是一个指明省略点的失败。
**为内联回退和精确字节溢出保留临时的额外省略。** 恰好会在不变量所针对的场景发送未记录的投影;失败再推进的路径只多花一次序列化尝试,且让每个已发出请求都可由日志派生。
## 后果
预算变大、选中更大的路由或 compaction 降低总量时,被省略的图片不会自动回归;恢复手段是占位文本中的只读路径,模型需要时主动使用。一次 Files 故障或临时切到小预算路由会永久省略,两者出于同一理由被接受。每次省略会把承载节点的消息复制一份进日志;图片只是引用,复制的是该节点的文本和块元数据。
每个已发出请求的图片集合都仅由日志决定,覆盖 file 模式、内联回退、resume、fork、重试和 compaction,provider 缓存前缀不再来回变化。占位文本和句柄文本里嵌入的执行世界访问路径仍在序列化时解析;这个缺口对保留的图片同样存在,属于另一个关于记录执行世界映射的决定。路由本地的字节检查是过渡实现:provider 自己报告无法缓存的图片之后,`requiredImageOffload()` 和路由预算会被删掉,带标记的副本和恢复分支保持不变。
## 测试
`packages/llm/llm/tests/content.spec.ts` 钉住任意深度的图片遍历、包括 129 到 64 MiB 量子示例在内的省略计数,以及占位投影。`packages/compaction/compaction-image-offload/tests/image-offload.spec.ts` 钉住 `IMAGE_OFFLOAD_REQUIRED` 替换并重试、带 `compaction/prune` 影子价格且不追加重试事件的路径、原节点保持不变、更早一次表层替换之后的请求顺序计数,以及向下游委托的耗尽情况。adapter 测试钉住占位投影、只读取保留图片以及带数量的精确字节失败;`route-pricing.spec.ts` 钉住带标记替换的占位定价。`inline-image-prompt` TypeScript SDK 快照通过发布的 profile 重放一次手工编写的 `IMAGE_OFFLOAD_REQUIRED` 尝试,钉住替换和重试后的请求。
@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-09-09-desktop-in-place-profile.md
2026-09-09-desktop-in-place-profile.md: 57dabc0d03c999b90dc18baa9d833aa90320863a
2026-09-09-desktop-in-place-profile.zh.md: 2b57c49ce45b1937552596cf4f59e0251b2d5774
@@ -0,0 +1,30 @@
# Agent Note: Modify the Desktop profile in place
Status: implemented
Archived: 2026-09-17
English | [中文](2026-09-09-desktop-in-place-profile.zh.md)
## Problem
Staging preserves an old plugin installation but adds profile copying, directory moves, a recovery journal, and rollback state. Local plugin changes accept explicit repair after failure instead of this complexity.
## Decision
Application-owned package retention is qualified by the [production cleanup decision](../bug-fix/2026-09-15-desktop-profile-core-cleanup.md).
Desktop stops the Host and modifies the current profile directly. Shared app-boot cleanup detaches its own fallback links before package changes; the Host’s shared profile runner supplies required links on startup. Package locking and configured lifecycle scripts remain. Upgrades refresh module links without copying plugin files.
Package or Host failures retain partial changes for repair and retry. There is no staging profile, activation journal, directory-swap recovery, or automatic rollback. Existing scratch directories are not interpreted or deleted.
This supersedes staging and rollback in [the packaging decision](2026-08-25-electron-desktop-packaging-and-updates.md), [the bundled-runtime decision](2026-09-08-desktop-bundled-runtime-and-external-plugins.md), and [the immediate-window decision](2026-09-09-desktop-immediate-window-and-direct-start.md). Host boot follows the [thin-wrapper decision](2026-09-10-desktop-web-wrapper.md); release, module ownership, and window lifecycle remain separate decisions.
Desktop delegates installation and lifecycle scripts to pnpm, without a pending-operation startup gate, frozen-lockfile reinstall, or automatic rebuild. Failed package operations preserve partial changes and leave disable, remove, and startup retry available. The Host inherits the user environment, and profiles may use directory links. An unchanged legacy Desktop-generated pnpm configuration is replaced with the Web defaults; customized configuration remains user-owned.
## Alternatives considered
Staging protects the previous installation at the cost of copying and crash recovery. Versioned directories still need preparation, selection, and cleanup. Direct writes give up automatic recovery; reintroduction requires an unattended-recovery product requirement that justifies these costs.
## Consequences
Tests cover offline initialization, in-place upgrades, failure before writes, retained changes after Host failure, partial pnpm failure, restored host links, and exclusive package ownership. Signed application and GUI acceptance remain release-environment checks.
@@ -0,0 +1,30 @@
# Agent Note: 直接修改 Desktop profile
Status: implemented
Archived: 2026-09-17
[English](2026-09-09-desktop-in-place-profile.md) | 中文
## 问题
staging 能保留旧插件安装,但增加 profile 复制、目录移动、恢复日志和回滚状态。本地插件变更接受失败后显式修复,以避免这些复杂度。
## 决策
应用管理包的保留范围受[生产清理决策](../bug-fix/2026-09-15-desktop-profile-core-cleanup.zh.md)限定。
Desktop 停止 Host 后直接修改当前 profile。共享 app-boot 清理在包变更前分离其拥有的模块补全链接;Host 的共享 profile runner 在启动时补全所需链接。包锁及配置允许的生命周期脚本保留。升级刷新模块链接,不复制插件文件。
包操作或 Host 失败会保留部分修改,供修复和重试。不使用 staging profile、激活日志、目录切换恢复或自动回滚。已有临时目录不会被解释或删除。
本记录取代[打包决策](2026-08-25-electron-desktop-packaging-and-updates.zh.md)、[内置运行时决策](2026-09-08-desktop-bundled-runtime-and-external-plugins.zh.md)及[立即显示窗口决策](2026-09-09-desktop-immediate-window-and-direct-start.zh.md)中的暂存与回滚。Host 启动遵循[薄壳决策](2026-09-10-desktop-web-wrapper.zh.md);发布、模块归属与窗口生命周期仍由各自决策负责。
Desktop 将安装和生命周期脚本交给 pnpm,不设置待完成操作启动门禁、不强制按锁文件重装,也不自动重建。包操作失败会保留部分变更,仍可禁用、删除和重试启动。Host 继承用户环境,profile 可以使用目录链接。未经修改的旧版 Desktop 生成 pnpm 配置替换为 Web 默认值;自定义配置仍由用户管理。
## 考虑过的替代方案
staging 以复制和崩溃恢复为代价保护旧安装。版本化目录仍需要准备、选择和清理。直接写入放弃自动恢复;只有无人值守恢复的产品要求能证明这些成本合理时,才重新引入。
## 后果
测试覆盖离线初始化、原地升级、写入前失败、Host 失败后保留修改、pnpm 部分失败、宿主链接恢复及独占包操作。签名应用和 GUI 验收仍由发布环境负责。
@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-09-10-local-office-preview.md
2026-09-10-local-office-preview.md: ea32e37f0b2dcba866b78947c785dcee8e475b29
2026-09-10-local-office-preview.zh.md: a1ac8337a1cf22f5842485c0790c6554635dc125
@@ -0,0 +1,52 @@
# Agent Note: Local Office preview through WASM PDF bytes
Status: implemented
Archived: 2026-09-11
English | [中文](2026-09-10-local-office-preview.zh.md)
## Problem
Office Open XML files are ZIP archives, so text fallback cannot provide a useful preview. Document conversion must stay local without taking focus or adding document content to a model conversation. Engine success alone cannot prove that the input has the claimed format or that a PDF was produced.
## Decision
A [document-render Service Definition](../../../../packages/document/document-render/README.md), a LibreOffice WASM provider, and Client/API consumers form the conversion capability. [Boot composition](../../../../packages/document/document-render-auto/README.md) mounts the provider and Remote controller only when `wasm.artifactDirectory` is configured. Invalid explicit configuration fails initialization. The Office Client registration always exists so an unconfigured Host receives guidance. Availability follows the generated Remote namespace without executable discovery or a duplicate Client flag.
The [WASM provider](../../../../packages/document/document-render-libreoffice-wasm/README.md) uses pinned official LibreOffice source, Emscripten, and a LibreOfficeKit adapter. Each Node Worker owns one engine instance, its pthreads, and its memory filesystem. Terminating the Worker cancels synchronous engine calls; every conversion waits for its Worker to stop before returning. OOXML inspection verifies archive membership, content type, and resource bounds before startup.
A VCL callback requests a font family before substitution or missing Unicode characters during glyph fallback. Host code indexes installed font metadata and copies selected files into engine memory, including complete font collections. Exact installed families precede configured alternatives; original-first fontconfig aliases preserve that ordering inside LibreOffice. Optional initial families use the same resolver. The engine has no Host filesystem mount, and rendering neither installs nor downloads fonts. The [build recipe](../../../../native/libreoffice-wasm/README.md) records source and toolchain revisions, patches, and asset hashes. Engine bundles remain immutable during provider use; a different build uses a new directory.
The [independent engine release](../process/2026-09-11-independent-libreoffice-package.md) owns precompiled npm packaging and keeps engine compilation outside ordinary DSH builds.
The provider returns caller-owned PDF bytes and independent `succeeded`, `timedOut`, and `cancelled` facts. PDF bytes are copied out of engine memory before teardown. The API consumer authorizes the source through [Workspace Files](2026-09-09-workspace-file-read-authority.md), requires successful uninterrupted conversion, and encodes the PDF directly. Source path and freshness version survive the PDF transport. Workspace Files limits source reads; the provider's `maxOutputBytes` alone limits generated PDFs. No temporary PDF or file lease is needed.
The Office Client watches the selected Conversation's existing Deliverables projection and warms recent Office files without opening tabs. Its bounded memory cache checks authorized source metadata on every read and shares pending conversions between background and foreground callers. Only the last departing reader cancels a shared conversion; failures are not cached and connection reset discards cached bytes. [Document Preview](2026-09-08-document-preview-operations.md) owns format selection, loading, cancellation, and the PDF.js Worker.
PDF.js's official TextLayerBuilder owns selection boundaries and copy normalization over the width-fitted canvas, with shared page cleanup and a component-owned resize observer. Its end-of-content marker and stacking rules constrain selection in blank regions; line-break highlighting is suppressed. Per-page cancellation uses the builder's cleanup rather than aborting the first page's signal, because the official selection listeners are shared across pages.
Missing-family observations accompany the PDF through the worker and Remote response. The Office plugin renders a keyed notice above the shared PDF scrollport, so dismissing it removes its layout height. The font resolver intersects explicit source and theme references with actual document requests, excluding engine defaults and font-table inventories; installed aliases and glyph fallback do not by themselves mean a family is absent.
## Alternatives considered
**Keep an installed native LibreOffice provider.** A second provider adds executable discovery, version queries, subprocess supervision, scratch files, and platform-specific confinement. This design uses WASM for all supported Office previews. A native provider needs a demonstrated rendering or deployment requirement that WASM cannot satisfy.
**Return a temporary PDF path.** The Worker already supplies independent PDF bytes. Writing them to disk, authorizing another file read, and maintaining leases adds file ownership without a current consumer. Source authorization and output limits apply directly to the memory result.
**Automate installed Microsoft Office.** Word for Mac requires GUI automation rather than headless conversion, introducing focus changes and per-file operating-system authorization. Native Office automation remains outside this preview capability.
**Use an online converter or download the engine automatically.** Remote conversion uploads document content. Automatic installation adds runtime distribution and update responsibilities; explicit artifact configuration leaves deployment with the operator.
**Convert PDF pages to PNG.** PDF.js already owns PDF presentation. Rasterizing adds another image pipeline and loses the existing PDF controls and selectable text.
**Add a model-facing rendering tool or durable preview events.** Client preview does not supply model input. A model-facing tool requires logged facts and both SDK projections, so it is a separate consumer.
**Scan every font-table entry for warnings.** Font tables include unused styles and templates. Reporting them would make the notice unrelated to rendered content; collection instead starts after engine initialization and ends after PDF save.
## Consequences
The single-provider design assumes WASM covers the required Office rendering behavior; it is not evidence of complete fidelity equivalence with native LibreOffice. Fidelity depends on the engine build and installed fonts. The [real-engine tests](../../../../packages/document/document-render-libreoffice-wasm/tests/libreoffice-wasm.e2e.ts) cover DOCX, XLSX, PPTX, selectable Chinese text, and embedded system fonts; ABI fixtures alone cannot establish rendering fidelity or assembled browser presentation.
WASM instances have substantial memory and startup costs, so the provider bounds concurrency. The [font reuse and image resolution decision](2026-09-11-wasm-preview-font-and-image-budgets.md) owns shared Host metadata, Worker request memoization, and raster export limits; only selected fonts enter engine memory. Large collections require bounded memory growth, and CFF export requires checked stack space. A fatal abort prevents further calls into C++. A device without a font covering a character cannot render it correctly without additional fonts. Owning the WASM build adds compiler compatibility, patch maintenance, and redistribution obligations.
Prewarming consumes conversion resources to reduce foreground waits; entry and byte limits bound retained Client results. Source and PDF bytes remain outside Session storage and persistent caches. The [provider tests](../../../../packages/document/document-render-libreoffice-wasm/tests/provider.spec.ts) cover independent output facts, input/output rejection, queued cancellation, and active Worker termination. Existing preview registry, file read authority, and Session ownership decisions remain active.
@@ -0,0 +1,52 @@
# Agent Note: 通过 WASM PDF 字节进行本地 Office 预览
Status: implemented
Archived: 2026-09-11
[English](2026-09-10-local-office-preview.md) | 中文
## 问题
Office Open XML 文件是 ZIP 归档,因此文本回退无法提供有用的预览。文档转换必须留在本地,不抢占焦点,也不将文档内容放入模型对话。仅凭引擎成功状态无法证明输入具有声明的格式或生成了 PDF。
## 决定
[document-render Service Definition](../../../../packages/document/document-render/README.zh.md)、LibreOffice WASM 提供方及 Client/API 消费方构成转换能力。[启动组合](../../../../packages/document/document-render-auto/README.zh.md)仅在配置 `wasm.artifactDirectory` 时挂载提供方和 Remote 控制器。无效的显式配置会使初始化失败。Office Client 注册始终存在,为未配置的 Host 提供指引。可用性由生成的 Remote 命名空间决定,不发现可执行文件,也不维护重复的 Client 标记。
[WASM 提供方](../../../../packages/document/document-render-libreoffice-wasm/README.zh.md)使用固定的官方 LibreOffice 源码、Emscripten 和 LibreOfficeKit 适配器。每个 Node Worker 拥有一个引擎实例、其 pthread 和内存文件系统。终止 Worker 可取消同步引擎调用;每次转换均在返回前等待 Worker 停止。OOXML 检查在启动前验证归档成员、内容类型和资源限制。
VCL 回调在替换前请求字体族,或在字形回退时请求缺失的 Unicode 字符。Host 代码索引已安装字体元数据,将选中的文件复制到引擎内存,包括完整字体集合。精确匹配的已安装字体优先于配置的替代项;原字体优先的 fontconfig 别名在 LibreOffice 内保留此顺序。可选的初始字体族使用同一解析器。引擎不挂载 Host 文件系统,渲染不安装或下载字体。[构建配方](../../../../native/libreoffice-wasm/README.zh.md)记录源码与工具链版本、补丁及产物哈希。提供方使用期间,引擎包保持不可变;不同构建使用新目录。
[独立引擎发布](../process/2026-09-11-independent-libreoffice-package.zh.md)负责预编译 npm 打包,并将引擎编译与普通 DSH 构建隔离。
提供方返回调用方拥有的 PDF 字节,以及独立的 `succeeded`、`timedOut` 和 `cancelled` 事实。PDF 字节在清理前从引擎内存复制出来。API 消费方通过 [Workspace Files](2026-09-09-workspace-file-read-authority.zh.md)授权源文件,要求转换成功且未被中断,并直接编码 PDF。源路径和新鲜度版本保留在 PDF 传输中。Workspace Files 限制源文件读取;生成 PDF 仅受提供方的 `maxOutputBytes` 限制。无需临时 PDF 或文件租约。
Office Client 观察所选 Conversation 现有的 Deliverables 投影,在不打开 tab 的情况下预转换最近的 Office 文件。有上限的内存缓存每次读取都检查已授权的源文件元数据,并在后台和前台调用方之间共享进行中的转换。仅最后一个退出的读取方取消共享转换;失败不缓存,连接重置丢弃缓存字节。[Document Preview](2026-09-08-document-preview-operations.zh.md)负责格式选择、加载、取消和 PDF.js Worker。
PDF.js 官方 TextLayerBuilder 在适配宽度的 canvas 上负责选择边界和复制规范化,共享页面清理,并使用由组件拥有的 resize observer。其内容结束标记和堆叠规则限制空白区域中的选择;换行高亮被抑制。逐页取消使用 builder 的清理操作,而不 abort 第一页的信号,因为官方选择监听器跨页面共享。
缺失字体族观察值随 PDF 经过 Worker 和 Remote 响应。Office 插件在共享 PDF 滚动区域上方呈现 keyed 提示,关闭时移除其布局高度。字体解析器取源文档及主题显式引用与实际文档请求的交集,排除引擎默认字体和字体表清单;已安装别名和字形回退本身不代表字体族缺失。
## 考虑过的替代方案
**保留已安装的原生 LibreOffice 提供方。** 第二个提供方增加可执行文件发现、版本查询、子进程监督、临时文件和平台特定隔离。本设计将 WASM 用于全部受支持的 Office 预览。引入原生提供方需要证明存在 WASM 无法满足的渲染或部署需求。
**返回临时 PDF 路径。** Worker 已提供独立的 PDF 字节。将其写入磁盘、授权另一处文件读取并维护租约,会增加文件所有权,而没有当前消费方需要这些操作。源文件授权和输出限制直接应用于内存结果。
**自动操作已安装的 Microsoft Office。** Word for Mac 需要 GUI 自动化而非 headless 转换,会引入焦点变化和逐文件操作系统授权。原生 Office 自动化不属于本预览能力。
**使用在线转换器或自动下载引擎。** 远程转换会上传文档内容。自动安装增加运行时分发和更新责任;显式产物配置将部署留给运维者。
**将 PDF 页面转换为 PNG。** PDF.js 已负责 PDF 展示。栅格化增加另一条图像流水线,并失去现有 PDF 控件和可选择文本。
**添加面向模型的渲染工具或持久化预览事件。** Client 预览不提供模型输入。面向模型的工具需要记录事实并更新两种 SDK 投影,因此属于独立消费方。
**扫描全部字体表条目生成提示。** 字体表包含未使用的样式和模板。报告这些条目会使提示与实际渲染内容无关,因此收集从引擎初始化完成后开始,在 PDF 保存后结束。
## 影响
单一提供方设计假设 WASM 覆盖所需的 Office 渲染行为;这不是与原生 LibreOffice 完全等价的保真度证据。保真度取决于引擎构建和已安装字体。[真实引擎测试](../../../../packages/document/document-render-libreoffice-wasm/tests/libreoffice-wasm.e2e.ts)覆盖 DOCX、XLSX、PPTX、可选择中文文本和嵌入系统字体;仅有 ABI fixture 无法证明渲染保真度或完整浏览器展示。
WASM 实例有较高的内存与启动成本,因此提供方限制并发。[字体复用与图像分辨率决策](2026-09-11-wasm-preview-font-and-image-budgets.zh.md)负责共享 Host 元数据、Worker 请求记忆化和栅格导出限制;仅选中字体进入引擎内存。大型集合需要有界内存增长,CFF 导出需要受检查的栈空间。致命 abort 后不再调用 C++。设备没有覆盖某字符的字体时,无法在不添加字体的前提下正确渲染该字符。自行构建 WASM 会增加编译器兼容、补丁维护和再分发义务。
预转换消耗转换资源以减少前台等待;条目数和字节限制约束 Client 保留的结果。源文件和 PDF 字节不进入 Session 存储或持久缓存。[提供方测试](../../../../packages/document/document-render-libreoffice-wasm/tests/provider.spec.ts)覆盖独立输出事实、输入/输出拒绝、排队取消和活跃 Worker 终止。现有预览注册表、文件读权限和 Session 所有权决策保持有效。
@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-09-11-wasm-preview-font-and-image-budgets.md
2026-09-11-wasm-preview-font-and-image-budgets.md: ab33b0bb6e28e5749ac38f36c08bc7539a368515
2026-09-11-wasm-preview-font-and-image-budgets.zh.md: e6ff458e8b68ce08ff5d81ce6767a08a82974a74
@@ -0,0 +1,36 @@
# Agent Note: Font reuse and image resolution in WASM previews
Status: implemented
Archived: 2026-09-11
English | [中文](2026-09-11-wasm-preview-font-and-image-budgets.zh.md)
## Problem
Office conversion repeats font metadata parsing across documents and font matching within one document. Image-heavy documents also spend substantial PDF export time resampling images above preview resolution. These costs need separate controls because font reuse does not reduce image decoding or resampling.
## Decision
The [WASM provider](../../../../packages/document/document-render-libreoffice-wasm/README.md) builds a font metadata snapshot once during initialization. Each conversion Worker receives a structured clone. The Host retains names, face attributes, paths, sizes, and modification times; glyph coverage, request caches, and imported bytes belong to the Worker. Reloading the provider refreshes the snapshot. Workers validate indexed files when reading them, and an already imported font remains usable within that conversion.
Each Worker memoizes complete requests: family, style, weight, italic, width, pitch, language, and ordered code points. The cache stores MEMFS paths and missing-family observations. Hits replay those observations because an initialization request can recur after document font collection starts. Worker termination releases both the cache and engine memory.
Runtime PDF filter options reduce raster images to a configurable `maxImageResolution`, defaulting to 192 DPI. The [shared PDF canvas](../../../../packages/client/ui-sidebar-documentpreview/src/client/pdf/document.ts) renders at 96 CSS DPI times the device pixel ratio; the default covers ratio 2. Text and vector graphics remain scalable. Explicit bookmark export preserves LibreOfficeKit's default when JSON filter options replace its implicit filter data.
The [local Office preview decision](2026-09-10-local-office-preview.md) continues to own conversion lifetime, authorization, missing-font presentation, and PDF transport.
## Alternatives considered
**Index fonts inside every conversion Worker.** This keeps discovery off the Host event loop and sees newly installed fonts immediately, but repeats full-file metadata parsing across previews. A provider snapshot removes that repeated work at the cost of synchronous initialization and explicit reload after font changes.
**Cache only the family name.** Style, language, pitch, and missing characters can select different files. A complete request key retains those distinctions and still captures repeated layout requests.
**Keep 300 DPI for every preview.** Higher raster resolution retains detail for high pixel ratios and magnification but increases image export work. The configurable 192-DPI default follows the common display target without rasterizing text or rebuilding the engine.
## Consequences
Cold provider startup includes indexing and remains separate from conversion deadlines. Shared metadata retains no original font buffers, while each Worker still reads selected fonts and lazily decodes coverage. Installing or replacing fonts requires provider reload; a file changed since indexing can fail a later conversion.
Reducing image resolution trades raster detail at high magnification for less export work. It is not an engine memory cap: LibreOffice can still decode full-resolution source images, load large font collections, or exhaust its build-time WASM memory maximum. No persistent font cache, filesystem watcher, or cross-document engine instance is introduced.
[Font tests](../../../../packages/document/document-render-libreoffice-wasm/tests/fonts.spec.ts) cover complete request keys, repeated missing-family observations, snapshot isolation, and failed imports. [Provider tests](../../../../packages/document/document-render-libreoffice-wasm/tests/provider.spec.ts) cover snapshot reuse and reload. The [real-engine tests](../../../../packages/document/document-render-libreoffice-wasm/tests/libreoffice-wasm.e2e.ts) inspect exported image dimensions with default and overridden DPI settings alongside selectable text and page count; ABI forwarding alone cannot establish filter behavior.
@@ -0,0 +1,36 @@
# Agent Note: WASM 预览的字体复用与图像分辨率
Status: implemented
Archived: 2026-09-11
[English](2026-09-11-wasm-preview-font-and-image-budgets.md) | 中文
## 问题
Office 转换在不同文档间重复解析字体元数据,并在同一文档内重复匹配字体。图片较多的文档还会在 PDF 导出时花费大量时间,重采样高于预览显示分辨率的图像。这些成本需要分别控制,因为字体复用不会减少图像解码或重采样。
## 决策
[WASM 提供方](../../../../packages/document/document-render-libreoffice-wasm/README.zh.md)在初始化时建立一次字体元数据快照。每个转换 Worker 接收结构化克隆。Host 保留名称、字体面属性、路径、大小和修改时间;字形覆盖、请求缓存及导入字节属于 Worker。重新加载提供方会刷新快照。Worker 读取已索引文件时校验文件,已经导入的字体在该次转换内仍可使用。
每个 Worker 记忆化完整请求:字体族、样式、字重、斜体、字宽、字距类型、语言及有序码点。缓存保存 MEMFS 路径和缺失字体族观察值。命中时重放这些观察值,因为初始化请求可能在文档字体收集开始后再次出现。Worker 终止时释放缓存及引擎内存。
运行时 PDF 过滤器选项将栅格图像降低到可配置的 `maxImageResolution`,默认 192 DPI。[共享 PDF 画布](../../../../packages/client/ui-sidebar-documentpreview/src/client/pdf/document.ts)按 96 CSS DPI 乘以设备像素比渲染;默认值覆盖像素比 2。文本和矢量图形仍可缩放。JSON 过滤器选项替换隐含过滤器数据时,显式导出书签保留 LibreOfficeKit 的默认行为。
[本地 Office 预览决策](2026-09-10-local-office-preview.zh.md)继续负责转换生命周期、授权、缺失字体展示和 PDF 传输。
## 考虑过的替代方案
**在每个转换 Worker 内索引字体。** 这会将发现工作移出 Host 事件循环,并立即识别新安装的字体,但会在不同预览间重复读取完整字体文件并解析元数据。提供方快照消除重复工作,代价是同步初始化,以及字体变化后显式重新加载。
**只缓存字体族名称。** 样式、语言、字距类型和缺失字符可能选择不同文件。完整请求键保留这些区别,同时仍能命中重复排版请求。
**所有预览保持 300 DPI。** 更高栅格分辨率保留高像素比及放大时的细节,但增加图像导出工作。可配置的 192 DPI 默认值符合常见显示目标,无需栅格化文本或重新构建引擎。
## 影响
提供方冷启动包含索引成本,不计入转换时限。共享元数据不保留原始字体缓冲区,各 Worker 仍会读取选中字体并按需解码字形覆盖。安装或替换字体后需要重新加载提供方;索引后发生变化的文件可能使后续转换失败。
降低图像分辨率以高倍缩放下的栅格细节换取更少的导出工作。它不是引擎内存上限:LibreOffice 仍可能解码全分辨率原图、加载大型字体集合,或耗尽构建时设定的 WASM 内存上限。此实现不引入持久化字体缓存、文件系统监听器或跨文档引擎实例。
[字体测试](../../../../packages/document/document-render-libreoffice-wasm/tests/fonts.spec.ts)覆盖完整请求键、重复缺失字体族观察值、快照隔离和失败导入。[提供方测试](../../../../packages/document/document-render-libreoffice-wasm/tests/provider.spec.ts)覆盖快照复用和重新加载。[真实引擎测试](../../../../packages/document/document-render-libreoffice-wasm/tests/libreoffice-wasm.e2e.ts)检查默认及覆盖 DPI 设置时的导出图像尺寸、可选择文本和页数;仅验证 ABI 参数转发无法证明过滤器行为。
@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/bug-fix/2026-09-09-content-sized-diagram-previews.md
2026-09-09-content-sized-diagram-previews.md: fec86111a68ec0fbc12ed6514a60c6a243924963
2026-09-09-content-sized-diagram-previews.zh.md: 8880f12853f9e7d2d566fca3a482fd5e17514526
@@ -0,0 +1,26 @@
# Agent Note: Content-sized diagram previews
Status: implemented
Archived: 2026-09-10
English | [中文](2026-09-09-content-sized-diagram-previews.zh.md)
## Problem
Short Graphviz and SVG images leave large empty regions when displayed inside 400px frames. A 59px Graphviz diagram occupies a 400px preview even though its rendered dimensions are already available to the browser.
## Decision
Mermaid, Graphviz, and SVG share the inert image canvas in `SourcePreview`. The browser derives its height from the image, preserves aspect ratio when shrinking to the available width, and adds 16px padding. Source switching retains the image and copying reads the original code. Theme changes regenerate Graphviz colors without introducing a separate sizing observer.
This replaces the diagram-frame choice in [Static Markdown fence previews](../feature/2026-09-09-markdown-static-previews.md); that note continues to own HTML isolation, rendering lifecycle, and license obligations. HTML retains its opaque, script-free, 400px frame. SVG image mode disables scripts, link interaction, and external resource loading without inserting source-controlled markup into the application document.
## Alternatives considered
**Set iframe height to auto.** An iframe does not derive its outer height from its inner document. This still reserves an unrelated viewport.
**Add a frame measurement script or same-origin access.** A diagram already has image dimensions. Extra execution or origin permissions and resize messaging are unnecessary for that content.
## Consequences
Short diagrams occupy only their rendered height and canvas padding. The browser geometry regression compares image and container height in light and dark modes, then verifies proportional scaling in a narrow viewport. Browser security checks include SVG scripts, event handlers, nested HTML, and external images; copy and source toggling remain covered. HTML automatic height remains outside this change because arbitrary document layout has different measurement and isolation requirements.
@@ -0,0 +1,26 @@
# Agent Note: 按内容定高的图表预览
Status: implemented
Archived: 2026-09-10
[English](2026-09-09-content-sized-diagram-previews.md) | 中文
## Problem
较矮的 Graphviz 与 SVG 图片显示在 400px iframe 中时,会留下大块空白。浏览器已经知道图片的渲染尺寸,但一张 59px 高的 Graphviz 图表仍占据 400px 的预览区域。
## Decision
Mermaid、Graphviz 与 SVG 共享 `SourcePreview` 的不可执行图片画布。浏览器根据图片决定高度,在可用宽度不足时按比例缩小,并添加 16px 内边距。源码切换保留图片,复制读取原始代码。主题变化重新生成 Graphviz 配色,无需单独的尺寸观察器。
这替代了[静态 Markdown fence 预览](../feature/2026-09-09-markdown-static-previews.zh.md)中的图表 iframe 选择;该记录继续维护 HTML 隔离、渲染生命周期与许可证义务。HTML 保留不透明来源、禁用脚本的 400px iframe。SVG 图片模式禁用脚本、链接交互与外部资源加载,无需把源码控制的标记插入应用文档。
## Alternatives considered
**把 iframe 高度设为 auto。** iframe 不会根据内部文档决定外部高度,仍然会保留与内容无关的视口。
**添加 iframe 测量脚本或同源访问。** 图表已经具备图片尺寸,不需要额外执行权限、来源权限或尺寸消息协议。
## Consequences
较矮图表只占据渲染高度与画布内边距。浏览器几何回归用例在浅色和深色下比较图片与容器高度,再验证窄视口中的等比例缩放。浏览器安全检查包含 SVG 脚本、事件处理器、嵌套 HTML 与外部图片,并保留复制和源码切换覆盖。HTML 自动高度不属于本次改动,因为任意文档布局具有不同的测量与隔离要求。
@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/bug-fix/2026-09-11-session-controller-fork-turn-cut.md
2026-09-11-session-controller-fork-turn-cut.md: 9223acd4c0c7bbcc84a0bfeb72f3b57d4bf828e2
2026-09-11-session-controller-fork-turn-cut.zh.md: cae022ae97896c0b43633edb310afb305d690b4a
@@ -0,0 +1,30 @@
# Agent Note: Session Controller forks stop at the selected turn end
Status: implemented
Archived: 2026-09-16
English | [中文](2026-09-11-session-controller-fork-turn-cut.zh.md)
## Problem
A user input enters the durable inbox before its `turn/start`. Extending a completed-turn fork through the following between-turn events can copy the next input's insertion without its later removal. Continuing the child then executes an input from beyond the selected turn.
## Decision
The [Session Controller](../../../../packages/api/session-controller/README.md) copies the contiguous prefix through the selected `turn/end`, inclusive. Explicit anchors select the first closing event at or after the anchor; omitted and past-end anchors select the last closing event. No event after that closing event belongs to the seed, including queued input, titles, and model settings.
The lower-level `SessionStore.fork()` retains its explicit stable-event semantics from the [log-only event decision](../simplification/2026-07-28-remove-synthetic-log-only-turns.md). Selecting a completed turn in the controller does not request a later stable event.
## Alternatives considered
**Stop only at the next inbox event.** Event-type exceptions still copy unrelated state changes after the selected turn and require the controller to classify plugin-owned events.
**Copy the tail and clear the child's inbox.** Clearing adds child events to cancel input that lies outside the requested prefix, while still inheriting other state from after the selected turn.
## Consequences
A fork inherits the configuration recorded through its selected turn. Later configuration and title events are excluded. The client may independently assign the child's fork title. Events already inside the selected prefix retain their ordinary replay semantics; this decision does not redefine pending input inserted before the selected closing event.
## Verification
Controller tests execute the production loop and check that sending C after forking A excludes the parent's later B from child history and produces one model request. Message, closing-event, omitted, and past-end anchors share this assertion. Model-routing coverage excludes a later configuration change. The Web message-actions snapshot seeds a queued input after the completed turn and verifies the branch action creates a child without that input or its inbox insertion.
@@ -0,0 +1,30 @@
# Agent Note: Session Controller 分叉截到选中轮次的结束事件
Status: implemented
Archived: 2026-09-16
[English](2026-09-11-session-controller-fork-turn-cut.md) | 中文
## Problem
用户输入会先进入持久化 inbox,再出现对应的 `turn/start`。如果已结束轮次的分叉继续复制后面的轮次间事件,就可能复制下一条输入的入队事件,却没有复制其后的出队事件。继续子会话时,就会执行选中轮次之后的输入。
## Decision
[Session Controller](../../../../packages/api/session-controller/README.zh.md) 复制截至选中 `turn/end` 的连续前缀,并包含该事件。显式锚点选择位于锚点或其后的第一条结束事件;省略锚点或锚点超出日志末尾时,选择最后一条结束事件。结束事件之后的所有事件均不属于种子,包括排队输入、标题和模型设置。
底层 `SessionStore.fork()` 保留[纯日志事件决策](../simplification/2026-07-28-remove-synthetic-log-only-turns.zh.md)规定的显式稳定事件语义。在控制器中选择已结束轮次,不代表请求复制到更晚的稳定事件。
## Alternatives considered
**仅在下一条 inbox 事件处停止。** 按事件类型添加例外仍会复制选中轮次之后的无关状态变化,并要求控制器分类插件所属的事件。
**复制尾部后清空子会话 inbox。** 清空操作会添加子会话事件,以取消本来就在所请求前缀之外的输入,同时仍然继承选中轮次之后的其他状态。
## Consequences
分叉继承截至选中轮次记录的配置。之后的配置和标题事件被排除。客户端可以独立设置子会话的分叉标题。已经位于选中前缀内的事件保留通常的回放语义;本决策不重新定义在选中结束事件之前入队的待处理输入。
## Verification
控制器测试执行生产循环,检查从 A 分叉后发送 C 时,子会话历史不包含父会话后续的 B,并且只产生一次模型请求。消息、结束事件、省略及越界锚点共用此断言。模型路由覆盖排除了后续配置变更。Web 消息操作快照在已结束轮次后植入排队输入,验证分叉操作创建的子会话不包含该输入或其入队事件。
@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/bug-fix/2026-09-16-movable-mandatory-update-window.md
2026-09-16-movable-mandatory-update-window.md: da996e5b37f990ff773e3ec88de0baed3c4b54f3
2026-09-16-movable-mandatory-update-window.zh.md: 15fd4eb2520a39d8259321a747b33c833b56cbb1
@@ -0,0 +1,24 @@
# Agent Note: Movable mandatory-update window
Status: implemented
Archived: 2026-09-18
English | [中文](2026-09-16-movable-mandatory-update-window.zh.md)
## Problem
The Windows mandatory-update page used a frameless modal overlay sized to the product window. The modal disabled its parent, so the parent's native title bar could not be used to move or maximize either window. Closing the overlay was intercepted, leaving no visible exit control.
## Decision
On Windows, mandatory policy uses a separate native framed modal with move, resize, and maximize controls. The parent remains disabled while policy blocks interaction. Closing the modal requests normal application shutdown; it never dismisses policy and resumes the product window. Other platforms retain the existing overlay presentation. The [mandatory-update decision](../feature/2026-09-11-desktop-mandatory-update-client.md) still owns policy and installation authorization.
## Alternatives considered
**Keep the full-content overlay and add a drag region.** A drag region would move the disabled parent indirectly and would not restore native maximize or close controls.
**Let close dismiss the policy page.** That would expose the blocked product window without a fresh no-force policy response.
## Consequences
Windows users can place or maximize the update window and exit the application from its close button. Modal blocking and the second installation approval remain intact. Installer-owned quit disposes the modal before Electron closes windows, so its close guard cannot block installation. The native frame replaces the dimmed full-content overlay on Windows; the ordinary update dialog keeps its existing overlay.
@@ -0,0 +1,24 @@
# Agent Note: 可移动的强更窗口
Status: implemented
Archived: 2026-09-18
[English](2026-09-16-movable-mandatory-update-window.md) | 中文
## Problem
Windows 强更页面原先使用与产品窗口等大的无边框模态覆盖层。模态窗口禁用了父窗口,因此无法使用父窗口的原生标题栏移动或最大化窗口。覆盖层的关闭操作又被拦截,界面上没有可用的退出控件。
## Decision
在 Windows 上,强更策略使用独立的原生有边框模态窗口,支持移动、调整大小和最大化。策略阻塞期间父窗口仍不可操作。关闭模态窗口会请求应用正常退出,不会取消策略并恢复产品窗口。其他平台保留现有覆盖层展示。[强更决策](../feature/2026-09-11-desktop-mandatory-update-client.zh.md)仍负责策略与安装授权。
## Alternatives considered
**保留覆盖整个内容区域的窗口并添加拖动区域。** 拖动区域只能间接移动被禁用的父窗口,也无法恢复原生最大化和关闭控件。
**允许关闭时直接取消策略页面。** 这样会在未取得新的无需强更响应时暴露被阻塞的产品窗口。
## Consequences
Windows 用户可以移动或最大化更新窗口,也可通过关闭按钮退出应用。模态阻塞和第二次安装批准保持不变。安装器接管退出时,壳会在 Electron 关闭窗口前释放模态窗口,避免关闭拦截阻止安装。Windows 上的原生边框取代了遮罩整个内容区域的覆盖层;常规更新弹窗仍使用原有覆盖层。
@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/archived/feature/2026-08-25-unified-task-list.md
2026-08-25-unified-task-list.md: f2f955e36a78eee8fa8ff8a804293bcc37a44acd
2026-08-25-unified-task-list.zh.md: 5a4c51a6cc3d0f331d2559debb73dc02e9cf12c5
@@ -0,0 +1,49 @@
# Agent Note: One session-header task list — jobs joined with activities in the UI projection only
Status: implemented
Archived: 2026-09-03
English | [中文](2026-08-25-unified-task-list.zh.md)
Superseded: the two-roster join described here was removed with the activity seam — the job rows are now the whole roster; see [jobs absorb the record](../architecture/2026-09-01-jobs-absorb-activity-record.md).
## Problem
The [activity observation seam](2026-08-24-activity-observation-seam.md) shipped its Web surface as a second session-header button beside the [background-job list](2026-08-08-web-background-job-display.md). A background bash run registers in both planes — `ctx.jobs` for control and `ctx.activities` for observation — so the same work rendered twice: once in "background jobs" with lifecycle and duration, once in "activities" with expandable live output. Two near-identical popovers with different names for overlapping row sets read as a product accident, and the flat activity rows (live and settled interleaved, single-line, no duration) had no visual hierarchy.
## Decision
The service planes stay orthogonal; the join happens once, per row, in the UI projection.
- **`ctx.jobs` and `ctx.activities` remain separate services.** Jobs are the control plane: model-visible ids, a consuming `readOutput` cursor the model drains, `stopping`, `kill`, and the `reported` completion-notice contract. Activities are the transient observation plane: non-consuming absolute offsets, invisible to the model, gone on restart. Merging the services would force one registry to carry both a consuming and a non-consuming cursor and would blur the "model-visible ⟺ logged" line for a plane designed to stay off the session log.
- **`dsh-client-ui-activity` renders the single merged list; `dsh-client-ui-jobs` is deleted** (pre-release, no compatibility shim), and the merged entry takes the job list's slot order. Each `jobsBySession` row is joined with the activity carrying its `correlation.jobId`: the job supplies identity, lifecycle (`stopping` exists only there), duration, and the model-visible `detail`; the activity supplies the expandable output panel. An activity without a job (a workflow run) keeps its own row; an activity whose job is not in the projection is not dropped. Without the activity registry, job rows still render — they just offer no panel, so the merged control degrades to exactly the old job list.
- **User-facing vocabulary is "task" (任务)** — `N tasks running` / `N 个任务进行中` — because every row is running work to the user, while "background job" excludes workflow runs and "activity" names the internal plane, not the user concept. The dictionary namespace and package names stay `activity`: internal names follow the naming ledger, not display copy.
- **Hierarchy**: live rows first (label over a kind-badge-and-status second line, ticking duration), then settled rows compacted to one de-emphasized line; each non-empty section carries its own heading (Running / Finished). Rows without an observable activity render as static rows with no expansion affordance.
Deliberately not joined: subagent delegation rows stay bare job rows (the subagent panel is their surface), and foreground commands stay in their tool cards — neither gains an activity producer.
## Alternatives considered
- **Merge the services** — rejected for the cursor-semantics and model-visibility reasons above.
- **Keep the job list and bolt output onto it** — leaves workflow runs (activities without jobs) homeless, forcing a second list to survive anyway.
## Refinements from browser acceptance
Driving the merged list in the real app produced four presentation decisions, all scoped to the expanded panel and the header band:
- **The header band order is preset → tasks → subagent catalog.** The root-session descendant count moved out of the breadcrumb (`header.lineage`) into the actions band (order 30) and dropped its `/` separator — a root session has no hierarchy to breadcrumb; child sessions keep their `root / child` switcher where the `/` is real. `SubagentCatalogAction` owns the moved seat; the lineage renderer now renders nothing on roots.
- **The panel's copy control copies the command** (`TerminalBlock.copyText`), not the output: a long command ellipsizes in the row, so the control is its only complete source, while output is selectable text below. Supplying `copyText` also keeps the control rendered before any output exists.
- **The panel scrolls instead of folding**: commands and output lines wrap in full (`--dsl-terminal-command-whitespace` / `--dsl-terminal-line-whitespace: pre-wrap`, so the output region never scrolls sideways) and the output region caps at a fixed height (`--dsl-terminal-output-max-height`) with `maxLines: Infinity` disabling the head/tail fold.
- **The panel draws no run-state dot** (`TerminalBlock.runStateDot: false`) — the row above it already carries the same state — and reclaims the dot gutter via `--dsl-terminal-gutter`. The panel's left spine was dropped with it.
All four land as opt-ins on `TerminalBlock` (props or `--dsl-terminal-*` variables), so tool cards keep their shipped fold/ellipsis/dot behavior unchanged.
## Testing
Component suites cover the join (job lifecycle wins, activity supplies the panel, bare-job rows, standalone activities), sections, durations, and the panel options; `pnpm vitest run packages/client/ui-activity packages/client/ui-primitives packages/client/ui-subagent` runs them. The keyless web e2e pair (`background-job-list`, `live-activity-stream`) replays the merged list end to end against ARIA goldens; `agent-preset-selection` pins the header band order.
## Consequences
- The two web e2e scenarios (`background-job-list`, `live-activity-stream`) now assert one "Tasks" list; the job-list scenario's row gained a live-output panel, which is the join working end to end.
- A human kill control on live rows is still blocked on the jobs `reported` contract question recorded in the job-display note.
- The `job` locale namespace is gone with its package; `activity` owns the merged copy including the duration vocabulary.
@@ -0,0 +1,49 @@
# Agent Note: 会话头部单一任务列表——jobs 与 activity 只在 UI 投影层合并
Status: implemented
Archived: 2026-09-03
[English](2026-08-25-unified-task-list.md) | 中文
Superseded: 本文描述的双名册 join 已随 activity seam 一并移除——job 行现在就是完整名册;见 [jobs 吸收 record](../architecture/2026-09-01-jobs-absorb-activity-record.zh.md)。
## 问题
[activity 观察面](2026-08-24-activity-observation-seam.zh.md)的 Web 呈现落地为[后台任务列表](2026-08-08-web-background-job-display.zh.md)旁边的第二个会话头部按钮。一次后台 bash 会同时登记在两个面里——`ctx.jobs` 负责控制、`ctx.activities` 负责观察——于是同一份工作渲染了两次:一次在"后台任务"里带生命周期与时长,一次在"活动"里带可展开的实时输出。两个行集合高度重叠、名字却不同的近似弹层,读起来像产品事故;而活动列表的扁平行(live 与 settled 混排、单行、无时长)也缺乏视觉层次。
## 决策
服务面保持正交;合并只在 UI 投影层逐行发生一次。
- **`ctx.jobs` 与 `ctx.activities` 仍是两个服务。** jobs 是控制面:模型可见的 id、模型消耗式的 `readOutput` 游标、`stopping`、`kill` 与 `reported` 完成通知契约。activity 是瞬态观察面:非消耗式绝对偏移、模型不可见、重启即无。合并服务会迫使一个注册表同时携带消耗式与非消耗式两种游标,并模糊这个刻意不进 session log 的面与"模型可见 ⟺ 已记录"不变量的边界。
- **`dsh-client-ui-activity` 渲染唯一的合并列表;`dsh-client-ui-jobs` 删除**(预发布阶段,不留兼容层),合并入口占用原 job 列表的 slot 顺位。每个 `jobsBySession` 行与携带其 `correlation.jobId` 的 activity 逐行 join:job 提供身份、生命周期(`stopping` 只存在于此)、时长与模型可见 `detail`;activity 提供可展开的输出面板。没有 job 的 activity(workflow 运行)保留自己的行;job 不在投影里的 activity 也不会被丢弃。没有 activity 注册表时 job 行照常渲染——只是没有面板,合并控件退化为与旧 job 列表完全等价。
- **用户可见词汇统一为"任务"(task)**——`N 个任务进行中` / `N tasks running`——因为对用户而言每一行都是在跑的工作,而"后台任务"排除了 workflow 运行、"活动"命名的是内部面而非用户概念。词典命名空间与包名保持 `activity`:内部名遵循命名台账,不跟随展示文案。
- **层次**:进行中的行在前(命令为主行、kind 徽章加状态为副行、时长每秒跳动),已结束的行折为降权单行;每个非空分组带自己的标题(进行中 / 已结束)。没有可观察 activity 的行渲染为无展开交互的静态行。
刻意不合并的:subagent 委托行保持裸 job 行(subagent 面板是它的呈现面),前台命令留在工具卡片里——两者都不接活动生产者。
## 曾考虑的替代方案
- **合并服务层**——因上述游标语义与模型可见性理由否决。
- **保留 job 列表、把输出挂上去**——workflow 运行(无 job 的 activity)无处安放,第二个列表终究得活下来。
## 浏览器验收带来的细化
在真实应用里驱动合并列表得出四个呈现决策,全部限定在展开面板与头部条带:
- **头部条带顺序为 preset → 任务 → subagent 目录。** 根会话的后代数量从面包屑(`header.lineage`)移入操作区(order 30)并去掉 `/` 分隔符——根会话没有可面包屑的层级;子会话保留 `根 / 子` 切换器,那里的 `/` 是真实层级。移位后的席位由 `SubagentCatalogAction` 拥有;谱系 renderer 在根会话上不再渲染任何东西。
- **面板的复制控件复制命令**(`TerminalBlock.copyText`)而非输出:长命令在行内被省略号截断,控件是它唯一的完整来源,而输出本身就是下方可选中的文本。提供 `copyText` 还让控件在任何输出出现之前就保持渲染。
- **面板以滚动取代折叠**:命令与输出行完整换行(`--dsl-terminal-command-whitespace` / `--dsl-terminal-line-whitespace: pre-wrap`,输出区因此永不横向滚动),输出区以固定高度封顶(`--dsl-terminal-output-max-height`),`maxLines: Infinity` 禁用头尾折叠。
- **面板不画运行状态点**(`TerminalBlock.runStateDot: false`)——上方的行已携带同一状态——并通过 `--dsl-terminal-gutter` 收回状态点落区。面板左侧竖线随之移除。
四项全部以 `TerminalBlock` 的可选项落地(prop 或 `--dsl-terminal-*` 变量),工具卡片保持既有的折叠/省略/状态点行为不变。
## 测试
组件套件覆盖 join(job 生命周期优先、activity 提供面板、裸 job 行、独立 activity)、分段、时长与面板选项;`pnpm vitest run packages/client/ui-activity packages/client/ui-primitives packages/client/ui-subagent` 运行它们。无密钥 web e2e 对(`background-job-list`、`live-activity-stream`)按 ARIA golden 端到端回放合并列表;`agent-preset-selection` 钉住头部条带顺序。
## 后果
- 两个 web e2e 场景(`background-job-list`、`live-activity-stream`)现在断言同一个"任务"列表;job 场景的行获得了实时输出面板,这正是 join 端到端生效的证据。
- live 行上的人工 kill 控件仍被 job-display note 记录的 jobs `reported` 契约问题阻塞。
- `job` 词典命名空间随包一起消失;`activity` 拥有合并后的全部文案,包括时长词汇。
@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/feature/2026-09-08-web-explicit-file-delivery.md
2026-09-08-web-explicit-file-delivery.md: ff2ddeb59ded05b70006dce217df2966eab9d4f2
2026-09-08-web-explicit-file-delivery.zh.md: 85b09ac82c83365b1c198168b78aa7ac84ef216f
@@ -0,0 +1,38 @@
# Agent Note: Web delivers explicit file snapshots
Status: implemented
Archived: 2026-09-08
English | [中文](2026-09-08-web-explicit-file-delivery.zh.md)
## Problem
Workspace links read live paths, so edits or deletion can invalidate a final deliverable. Files created through shell commands also lack first-party editor mutation records. Delivery needs an explicit operation and saved bytes without expanding Session ZIP exports.
## Decision
The [present tool](../../../../packages/fs/tool-present/README.md) owns execution, immutable snapshots, delivery types, and the durable event. The [deliverables plugin](../../../../packages/client/ui-deliverables/README.md) owns authenticated snapshot actions and browser rendering, with type-only imports from the tool’s `./types` entry. The `standard`, `ptc`, and `cordis` presets mount the tool package; `minimal` retains its two-tool training configuration. The existing attachment service saves immutable bytes; successful final `tools/result` notifications append `deliverables/presented` to the calling Session. Native and nested calls use the same recorder. A later enclosing program failure does not undo a completed nested delivery. Blocked tool results publish none.
Download and native-open requests authorize a reference by the viewed Session, event sequence, and file index. The event stores no Session ID, so forked history uses the child's own log. The existing produced-file row keeps its names and behavior. Session ZIP retains delivery events but does not collect their attachment bytes.
Card and closing-mention gestures open a verified private copy with the existing native-command utility. A POST expresses the desktop side effect; GET remains a byte read. Each gesture receives a new copy so application edits cannot corrupt the immutable attachment or alter later opens. Successful copies survive until plugin disposal for applications that read lazily; failed copies are removed immediately, and disposal awaits cancelled work before cleanup.
## Alternatives considered
**A Host tool subpath in the UI package** couples preset installation to browser packaging and requires extra published entries. An ordinary tool package preserves shared filesystem and tool error classes through the repository’s peer dependency rules.
**Live workspace links** cannot preserve a delivered version after edits or deletion. Opening the attachment store’s own path instead would expose immutable saved bytes to application writes.
**Generic artifact fields throughout tools, dispatch, and Session** would broaden unrelated APIs for one Web feature. A plugin-owned event uses existing extension points and avoids parent-result forwarding.
**Tool text as the durable index** is unreliable because post-processing and spill can replace ordinary or nested result text. Each plugin instance retains its own completed snapshots by execution identity and publishes them only on a successful final result. Same-name scoped replacements cannot create or duplicate another instance’s delivery records.
**Descriptor-bound filesystem extensions** would change multiple capability providers. This feature uses existing bounded reads with containment and before/after version checks. Those checks reject ordinary concurrent changes but do not guarantee atomic confinement against swap-and-restore; stronger filesystem guarantees belong to the filesystem provider.
## Consequences
The implementation adds no artifact service or attachment format. Unreferenced snapshots can remain after partial failure; attachment retention remains service-owned. A downstream build must understand the new required event to read the log. The generated Session event inventory records that requirement without changing released format generations.
The delivery event is required-on-read because it is the authorization index for saved bytes, not only display metadata. Skipping it would allow an older reader to reconstruct or fork a Session without its completed deliveries. Unsupported readers refuse that loss instead of silently dropping the references.
Focused tests cover snapshot bytes, invalid inputs, blocked results, HTTP integrity, native-open copy isolation, retry and disposal, turn isolation, and fork-addressed actions. The recorded Web scenario covers nested completion followed by an enclosing failure, source deletion, reload, native-open gestures without browser downloads, and ZIP exclusion.
@@ -0,0 +1,38 @@
# Agent Note: Web 显式交付文件快照
Status: implemented
Archived: 2026-09-08
[English](2026-09-08-web-explicit-file-delivery.md) | 中文
## 问题
工作区链接读取当前路径,因此编辑或删除会使最终交付文件失效。通过 shell 命令创建的文件也没有第一方编辑器修改记录。交付需要显式操作和保存的字节,同时不扩大 Session ZIP 导出内容。
## 决策
[present 工具](../../../../packages/fs/tool-present/README.zh.md)拥有执行、不可变快照、交付类型和持久事件。[交付插件](../../../../packages/client/ui-deliverables/README.zh.md)拥有认证快照操作和浏览器渲染,仅从工具的 `./types` 入口导入类型。`standard`、`ptc` 与 `cordis` preset 挂载工具包;`minimal` 保留双工具训练配置。现有 attachment 服务保存不可变字节;成功的最终 `tools/result` 通知将 `deliverables/presented` 追加到调用方 Session。原生与嵌套调用使用同一个记录器。外层程序随后失败不会撤销已完成的嵌套交付。被阻止的工具结果不发布交付。
下载与原生打开请求通过当前查看的 Session、事件序号与文件索引授权引用。事件不保存 Session ID,因此 fork 历史使用子 Session 自己的日志。现有产出文件行保留其名称和行为。Session ZIP 保留交付事件,但不收集其中引用的 attachment 字节。
卡片和收尾引用操作通过现有 native-command 工具,在默认应用中打开经过校验的私有副本。POST 表达桌面副作用;GET 仍仅读取字节。每次操作创建新副本,避免应用内编辑损坏不可变 attachment 或改变后续打开的内容。成功副本保留到插件释放,以支持延迟读取的应用;失败副本立即删除,释放时先等待取消的操作结束再清理。
## 已考虑的替代方案
**在 UI 包中提供 Host 工具子路径**会将 preset 安装与浏览器打包耦合,并要求额外发布入口。普通工具包通过仓库 peer dependency 规则保留共享的文件系统和工具错误类。
**实时工作区链接**无法在编辑或删除后保留已交付版本。直接打开 attachment 存储路径则会使不可变保存字节暴露于应用写入。
**在工具、dispatch 和 Session 中增加通用 artifact 字段**会为单个 Web 功能扩大无关 API。插件拥有的事件使用现有扩展点,并省去父调用结果转发。
**将工具文本作为持久索引**并不可靠,因为后处理与 spill 可以替换普通或嵌套结果文本。每个插件实例按执行对象保留自身已完成的快照,仅在最终结果成功时发布。同名作用域替代工具不能创建或重复其他实例的交付记录。
**基于文件描述符的文件系统扩展**会修改多个能力提供方。本功能使用现有有界读取,并检查路径包含关系及读取前后的版本。这些校验会拒绝普通并发变化,但不保证对替换后复原提供原子路径限制;更强的文件系统保证属于文件系统提供方。
## 影响
实现不增加 artifact 服务或 attachment 格式。部分失败后可能留下无引用快照;attachment 保留策略仍由服务拥有。下游构建必须理解新必需事件才能读取日志。生成的 Session 事件清单记录该要求,不修改已发布的格式代际。
交付事件要求读取端识别,因为它是保存字节的授权索引,不只是显示元数据。跳过事件会让旧读取端在重建或分叉 Session 时丢失已完成的交付。不支持该事件的读取端拒绝读取,避免静默丢弃引用。
定向测试覆盖快照字节、无效输入、被阻止的结果、HTTP 完整性、原生打开的副本隔离、重试与释放、turn 隔离及使用 fork 地址的操作。录制 Web 场景覆盖嵌套调用完成后外层失败、源文件删除、重新加载、不触发浏览器下载的原生打开操作和 ZIP 排除。
+39
View File
@@ -160,6 +160,9 @@
"architecture/2026-08-01-packaged-ripgrep-search.i18n.yaml": "sha256:43c9128079955e974fe1da3ce1a10779b4f5a25ac3629f92e3b1de847ad45050",
"architecture/2026-08-01-packaged-ripgrep-search.md": "sha256:36cf2d6daa654abced690965338aec4628069dc77be3a1da6368a9b097a59ff4",
"architecture/2026-08-01-packaged-ripgrep-search.zh.md": "sha256:45b2fe8e0d492eeff313d2ef3c98fd69761b3257eee3476b8bf53312e8b6095f",
"architecture/2026-08-03-per-session-agent-presets.i18n.yaml": "sha256:3fe057a67e41f9ce4f5cc8b162e264494b39169588fe9c9e48dcf95fd1b208a1",
"architecture/2026-08-03-per-session-agent-presets.md": "sha256:d4c6c6af11f41b57e95ca359e2cbe09780cb0851037998824a5966cab5e12626",
"architecture/2026-08-03-per-session-agent-presets.zh.md": "sha256:c91248b2d9cc5c51c77e9d195aca5d51a06684971b1afafc60b2def72248afca",
"architecture/2026-08-03-pi-ai-declared-provider-catalog.i18n.yaml": "sha256:c1a59c3c04afada633740c808b98e765ccad09220c4c79d8f4207313c9e9aab6",
"architecture/2026-08-03-pi-ai-declared-provider-catalog.md": "sha256:fae0c59ece887f7d9344b6254d20cc671894074d53eefffb85dbf45b9104d2b6",
"architecture/2026-08-03-pi-ai-declared-provider-catalog.zh.md": "sha256:8032cefedd51b292d810051ff32e8825958e6d90b2e523a374294ef2f859ca1e",
@@ -358,9 +361,21 @@
"architecture/2026-09-01-streamed-tool-call-identity.i18n.yaml": "sha256:5193bf7429a0300f743ea7e6087c3175a7d28c2c468ca1cfd1f77702b68b6399",
"architecture/2026-09-01-streamed-tool-call-identity.md": "sha256:303433b95c22571bf6a801da604b42a4c7231f5f6d07daeb518354f0d7019141",
"architecture/2026-09-01-streamed-tool-call-identity.zh.md": "sha256:53728d3ee06b29d6023e28024fb3ab6fa4a7473ae5e55368cd19690719d120f3",
"architecture/2026-09-02-durable-image-offload.i18n.yaml": "sha256:d06155597e7df4ca4c15a2902ab664d69cc2fde1e7963e61543d20a49930d2b9",
"architecture/2026-09-02-durable-image-offload.md": "sha256:02b7becba3dd73a4e627b85705e8bd5dd55978cb041f4d3a0fd1420a76e4de92",
"architecture/2026-09-02-durable-image-offload.zh.md": "sha256:a0464b8272086d663ee698efd0b2edd6224d40770d7a8fd88a6d8bfe030b2a1d",
"architecture/2026-09-02-protocol-specific-model-listing-discovery.i18n.yaml": "sha256:ba8a62a9fa3263de4162709cb1aaf81f6ad4feee5011d7a5d8b24eb92ad81d30",
"architecture/2026-09-02-protocol-specific-model-listing-discovery.md": "sha256:9db9c47559c17f0e2931b9e646f1d2d17b590df4d5699d4e779ed6d7f65fc371",
"architecture/2026-09-02-protocol-specific-model-listing-discovery.zh.md": "sha256:9a266590d49093a097bcdb5d09865757cdd07625cfaaddce1303046d580551f1",
"architecture/2026-09-09-desktop-in-place-profile.i18n.yaml": "sha256:08543070a32503373d38ca98b7ce96ee60c972302534030c5ba380f19e04fa00",
"architecture/2026-09-09-desktop-in-place-profile.md": "sha256:82bdcad48207c5aecbc9695717aaaa4c8cca90c82ca58884bfa653b60f192290",
"architecture/2026-09-09-desktop-in-place-profile.zh.md": "sha256:f105636c9160c64b12bd1822c8ec81ee744ba27c0b0ab6eeed870561ccd81ce7",
"architecture/2026-09-10-local-office-preview.i18n.yaml": "sha256:a43a2370c7434293ef98d1901a29b7b4b03f400a108c119f3ec5f2f7ca8ca3f8",
"architecture/2026-09-10-local-office-preview.md": "sha256:754cfb4dde9f1ee70e495095f12fc9e3c43af4a959250bb3a59ae44fd32fd763",
"architecture/2026-09-10-local-office-preview.zh.md": "sha256:d8fb9a65f437b585f2dfa2b4aa091634eeabf571e98e881cf7344b7574704e53",
"architecture/2026-09-11-wasm-preview-font-and-image-budgets.i18n.yaml": "sha256:af027c7dae53a181e4d73fd2309f69e9ae3c48df0d3b1dfc53cae274aa60d69e",
"architecture/2026-09-11-wasm-preview-font-and-image-budgets.md": "sha256:44dd52839cdb67644c0dbcbc4beb6f36802628c4a8d17a0aad11db1f9be649ed",
"architecture/2026-09-11-wasm-preview-font-and-image-budgets.zh.md": "sha256:8285432ee1676be8b79a05953c4b6ac4a7ca5d8e701173b3a2b533608b584d0a",
"bug-fix/2026-07-19-windows-atomic-write-dacl-preservation.i18n.yaml": "sha256:8be5b0afd8820c593e2ec254d35fb8c384267814104f6234bb9af824c5f974ba",
"bug-fix/2026-07-19-windows-atomic-write-dacl-preservation.md": "sha256:861e6130e893489271478def5f54f212a106a1580b744e6e40f56356f73c7e10",
"bug-fix/2026-07-19-windows-atomic-write-dacl-preservation.zh.md": "sha256:3549257e06f074591de580ebfaa71284c7c384fb0ffb1963c30258d7a7c26db7",
@@ -736,6 +751,15 @@
"bug-fix/2026-09-03-session-search-result-reveal.i18n.yaml": "sha256:ad9dcedeb25ab3eddbc51660935abaf6e6e92eefb66fd14f8852ba5f30e725b5",
"bug-fix/2026-09-03-session-search-result-reveal.md": "sha256:ce8983a9ffa3d1b59946aeecf0e10177c8316c3621d5d0718a03e8eedcd05fd9",
"bug-fix/2026-09-03-session-search-result-reveal.zh.md": "sha256:cd3ca0290f259a252e0b19fd0f15ac62232847be6f186e16f72652044a034bbe",
"bug-fix/2026-09-09-content-sized-diagram-previews.i18n.yaml": "sha256:a4404fe8e35ca5b6371f9cdb58fea6724cf3e7737bb2db8a3a321d534454b17c",
"bug-fix/2026-09-09-content-sized-diagram-previews.md": "sha256:5239e98e5c057d6f7e10c3f10a0f67273778d99b0c4f10b31a1921c3c6474b80",
"bug-fix/2026-09-09-content-sized-diagram-previews.zh.md": "sha256:c1ee3790a9d5c3561e1d93d5e649afa904c7d19b9d77248c85ef16daccd953e2",
"bug-fix/2026-09-11-session-controller-fork-turn-cut.i18n.yaml": "sha256:4442529ced1c8e48d30f7b50c65ff03eb92dce9815beb438cedbf29f234bce47",
"bug-fix/2026-09-11-session-controller-fork-turn-cut.md": "sha256:a996f24a896c7fc5d81e015db3eae27d8a46c853287572e815623ce35eae1b12",
"bug-fix/2026-09-11-session-controller-fork-turn-cut.zh.md": "sha256:6486f0eacf5067ef9850dc32f1c27b2109a7d4e9e3c498366f5c38742bb53ac5",
"bug-fix/2026-09-16-movable-mandatory-update-window.i18n.yaml": "sha256:e526ce14ae9557e24364e3686778b130090445ef2152d976b7cc93e76eac6401",
"bug-fix/2026-09-16-movable-mandatory-update-window.md": "sha256:67546cea0b3de2b3e32957a508dbde097d91dd919fe067c8dbecb2c65b50c366",
"bug-fix/2026-09-16-movable-mandatory-update-window.zh.md": "sha256:20a0aade6ee71c89e84d70e23c89bb51e8a38c674d103dd43022feabb8d27be3",
"feature/2026-06-14-acp-agent-client-protocol.i18n.yaml": "sha256:006795baa43ae962a8d125cc0f1e9f134bc2ee9fb758b6e7669e3fa0126e1918",
"feature/2026-06-14-acp-agent-client-protocol.md": "sha256:6828c0af74bb3fb96206ca6b21c0e56a000b50e4744aad4bc2c05092f3a5a31b",
"feature/2026-06-14-acp-agent-client-protocol.zh.md": "sha256:ba104e841a1fb84edbd3b6c8119d50445b7785255a7a8d13bb9ac8a2cb4d2e69",
@@ -1357,6 +1381,9 @@
"feature/2026-08-25-loaded-turn-chat-navigation.i18n.yaml": "sha256:86bd02d56cf95ac465d0f6e326ccf75432ffb9c3db47373ae6a795195cff9ea7",
"feature/2026-08-25-loaded-turn-chat-navigation.md": "sha256:0ee1cb6da76b93e467d747aa8ba07697ba648cb213ba52202c51ee1e85dff1a8",
"feature/2026-08-25-loaded-turn-chat-navigation.zh.md": "sha256:5d3e567027fc65241856bf9f9cf0d73a20d53214c49bfbc884ab2ddd19503918",
"feature/2026-08-25-unified-task-list.i18n.yaml": "sha256:fec0d4a3ecf59aafd440bc801c686b14d63152c937f51bebe0da61ff615f6f33",
"feature/2026-08-25-unified-task-list.md": "sha256:30bd4e338a3de2f59af98d512c7878928c61846e6700d6012fc45e51c0bf94df",
"feature/2026-08-25-unified-task-list.zh.md": "sha256:88fce0a52b5387ea98c1f68742c03b2f475c5465c680befb32c587066e52cfce",
"feature/2026-08-26-web-trigger-menu-presentation-polish.i18n.yaml": "sha256:69179f3056c6d5fc35119e83dd7a5af30213502dac3c1f2d4fd43eae96ee2ecf",
"feature/2026-08-26-web-trigger-menu-presentation-polish.md": "sha256:c54e3bbe528d6be711541c61e777e6e4ed4fbc1374df97d846b015d3693679f4",
"feature/2026-08-26-web-trigger-menu-presentation-polish.zh.md": "sha256:7db49018eebbba539838d734a80fbb330e2b73fea3b343900591a3605c6c03b5",
@@ -1381,6 +1408,9 @@
"feature/2026-09-01-web-superellipse-corner-smoothing.i18n.yaml": "sha256:50afdbe5b5e19889918af6d86ab3218c05205be35938b6d33d158c60777e3b58",
"feature/2026-09-01-web-superellipse-corner-smoothing.md": "sha256:b1445101c49e74bbcb4f607af850cd6df105d4034828d0dd47081e8079148f15",
"feature/2026-09-01-web-superellipse-corner-smoothing.zh.md": "sha256:1a278c417c0d7de3b4c3c35061b419303b4a1a0707831c283d8f862ab9b6fd23",
"feature/2026-09-08-web-explicit-file-delivery.i18n.yaml": "sha256:99daae539cc8fd7376ce0265538bee21e1e33f3c0d77c8cc4e011f94b4e9568a",
"feature/2026-09-08-web-explicit-file-delivery.md": "sha256:bb416b1e8be081e6cb6af17792eb1a442172ff114c3a3577e5ef06a77eb57093",
"feature/2026-09-08-web-explicit-file-delivery.zh.md": "sha256:00a642380e1f6ac9d5cd840e021f4e3e4ae68a289cb6344eb3dcd73a6fd81f4d",
"process/2026-06-11-doc-sync-enforcement.i18n.yaml": "sha256:33b6d5874427bd7a2bd82e7e2f4f482b12448b2464aef15a9c57975edb48554d",
"process/2026-06-11-doc-sync-enforcement.md": "sha256:aa2fe83d519fc30d48dff19e596e83c8922aacc9e063e14fe2cc35b769b9100e",
"process/2026-06-11-doc-sync-enforcement.zh.md": "sha256:698017bd35f030fdea3eac51df9e43138c48140f504739d687b7251d13fced2b",
@@ -1531,6 +1561,9 @@
"process/2026-08-08-api-remotes-generated-contract-build.i18n.yaml": "sha256:da10469121712bd6ac4fb1f665ca8bd59597a94b56324d2fe4bdef5235498b6e",
"process/2026-08-08-api-remotes-generated-contract-build.md": "sha256:8c3d7712cce4913cd3c02d1ac2b87def3f7104a7503681afc3c755896ac45d1f",
"process/2026-08-08-api-remotes-generated-contract-build.zh.md": "sha256:e32e1f53c763e769d152c8c41cf8f8977210e82a0d3f7cc7f0421da7e589e9ad",
"process/2026-08-08-automatic-translation-pairing-merges.i18n.yaml": "sha256:5398ef0c48258d3f3a9881e2b34fc4e2086a0b8084b8d7100798dbca6cc39887",
"process/2026-08-08-automatic-translation-pairing-merges.md": "sha256:fb1f3df3246151da920c14fdf195b0cb3bf595a2eed639c84baf70e3f56d36ce",
"process/2026-08-08-automatic-translation-pairing-merges.zh.md": "sha256:9ce7ff6f511ce973637f001b119ce323a5efe0be57cc11d12691aaa36199a8b8",
"process/2026-08-08-lightweight-routine-documentation-translation.i18n.yaml": "sha256:f3b44e6148941de9840ef54be60e60ed6ec32ee04b42a1a472e38838b6aa7b14",
"process/2026-08-08-lightweight-routine-documentation-translation.md": "sha256:264fe2ee2338053a11fe0f0d5ccf12772897fe9fd4f4a7e8a1d6ba226f853e14",
"process/2026-08-08-lightweight-routine-documentation-translation.zh.md": "sha256:3d309e2fc34a6a99bbce4891c32d681e0a23b233791b29a550884f3e753d593c",
@@ -1603,6 +1636,9 @@
"process/2026-09-03-workspace-version-coherence-gate.i18n.yaml": "sha256:ac442dee172d396395b8516d6d38c4fcedbc855d735c86c378aec5c1098ecd8d",
"process/2026-09-03-workspace-version-coherence-gate.md": "sha256:37b63a78506a8741eb04826dc1eea7e3a64c19fd4494c2d7754054a5602d308b",
"process/2026-09-03-workspace-version-coherence-gate.zh.md": "sha256:cfa2c8fe6cf1d4665121a987861b70a91b5b41eb99e7ed192c85760a916fddf6",
"process/2026-09-11-independent-libreoffice-package.i18n.yaml": "sha256:e8d2fe75e05ac53438513a7c51dab6510bcecf644019391ee6650e73961c0f8d",
"process/2026-09-11-independent-libreoffice-package.md": "sha256:1292b409b7b4cbc4420868de5e3b7417b3c855889023ccfd9a61d824bf3019d8",
"process/2026-09-11-independent-libreoffice-package.zh.md": "sha256:384783da1614c7e2ea84ea513013af6b20e9d4545a03cf7fa068415078126932",
"simplification/2026-06-19-drop-mutable-session-summary.i18n.yaml": "sha256:43fe5daadc1491f94a3e34595182cad1591f76b64e1f13b48811b80fd7e53b94",
"simplification/2026-06-19-drop-mutable-session-summary.md": "sha256:01647a5a14aa4e195328d4d39c6d80eb0723739e5a543115314716b280a93560",
"simplification/2026-06-19-drop-mutable-session-summary.zh.md": "sha256:22389e0c29158b1f7a5a43ed6073f8795bb87cf51c04cf83be055359cd65c9f5",
@@ -1750,6 +1786,9 @@
"simplification/2026-08-06-user-bubbles-drop-the-branch-action.i18n.yaml": "sha256:e000606d801984d4ee473779891ffe8c197f64f54b75efd82fb46dc84217cd59",
"simplification/2026-08-06-user-bubbles-drop-the-branch-action.md": "sha256:b93ce0d79ee72306d569d80fd81308a2b5704d95df8854b7cbd2f3d898b3f776",
"simplification/2026-08-06-user-bubbles-drop-the-branch-action.zh.md": "sha256:999e3e1252f771c420506a80b7c0d512b70da6770e3e62bb92169180b4cee3e8",
"simplification/2026-08-08-copy-only-preset-authoring.i18n.yaml": "sha256:43bba45597b198a94e3cbf8df31794239c521ecf002338636dca2c099acd94e1",
"simplification/2026-08-08-copy-only-preset-authoring.md": "sha256:be77d385a3c4db534fbbd5b4a830fcb7f6bcd8401221617859569e2c4d837069",
"simplification/2026-08-08-copy-only-preset-authoring.zh.md": "sha256:4c544a08e741c4a273a89dc2a3fda44dffb46af15d0feb8f7bf8efa816bfbd13",
"simplification/2026-08-08-remove-cli-demo.i18n.yaml": "sha256:1baa8649e186e159afb03f112059f46f7a35c303a6039374db8bc4ca743d4bdf",
"simplification/2026-08-08-remove-cli-demo.md": "sha256:a34ce79b674c67a6a47d99c1fa7141b2ae58e36b99da5989d323d229d1921baa",
"simplification/2026-08-08-remove-cli-demo.zh.md": "sha256:96a2a7cc34c7b0abf71b77d666a6349d681fd8a0d9a9c81e30d2aa538d62797a",
@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/archived/process/2026-08-08-automatic-translation-pairing-merges.md
2026-08-08-automatic-translation-pairing-merges.md: ed693e376d056378b27a8995a6f26fefcdba34b2
2026-08-08-automatic-translation-pairing-merges.zh.md: 827475a92824c22ee6f4c558de81b645c3c2b8dc
@@ -1,6 +1,7 @@
# Agent Note: Automatically compose translation pairing records
Status: implemented
Archived: 2026-09-23
English | [中文](2026-08-08-automatic-translation-pairing-merges.zh.md)
@@ -1,6 +1,7 @@
# Agent Note: 自动组合翻译配对记录
Status: implemented
Archived: 2026-09-23
[English](2026-08-08-automatic-translation-pairing-merges.md) | 中文
@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/process/2026-09-11-independent-libreoffice-package.md
2026-09-11-independent-libreoffice-package.md: 05fd8eb86ffb75b564008eaffda5c98669afee27
2026-09-11-independent-libreoffice-package.zh.md: b2abf61f8a5cf9b247fa2b94697eb90a252d4cff
@@ -0,0 +1,32 @@
# Agent Note: Independent precompiled LibreOffice package
Status: implemented
Archived: 2026-09-11
English | [中文](2026-09-11-independent-libreoffice-package.zh.md)
## Problem
Compiling LibreOffice inside ordinary DSH builds would require every contributor and CI job to acquire its toolchain and repeat a large native build. Desktop also needs immutable engine resources that can travel with its offline installation material.
## Decision
The [engine package](../../../../native/libreoffice-wasm/package.json) has its own version and an asset-only manifest export. Its source directory stays outside the main pnpm workspace. Installation has no lifecycle hook, and packaging verifies an existing successful build without compiling. The [release workflow](../../../../.github/workflows/libreoffice-wasm-release.yml) compiles only on explicit dispatch; publication requires a matching engine version tag and the protected npm environment.
Each tarball contains the engine manifest and assets, corresponding source pins, patches, full source diff, and the built distribution's license and notices. Packaging rejects mismatched build receipts, modified assets, unlisted engine files, missing notices, and bundled fonts. A failure never triggers compilation automatically.
The [local preview decision](../architecture/2026-09-10-local-office-preview.md) continues to own conversion and explicit artifact configuration. This change establishes release machinery; it does not add an unpublished engine dependency to DSH. The existing [Desktop package set](../../../../apps/desktop/scripts/prepare-package-set.ts) remains the intended carrier for a future fixed-version dependency and its offline seed.
## Alternatives considered
**Compile during ordinary builds or package installation.** This puts engine toolchain availability and compilation cost on every consumer, even when the engine version has not changed.
**Extract a general Node conversion library.** Font handling, Worker ownership, and the conversion API can remain with the provider. Moving them is unnecessary to distribute precompiled assets or isolate compilation from DSH CI.
**Link the engine source as a workspace dependency.** Workspace linking would replace a published precompiled package with a source directory that lacks its engine files.
## Consequences
The engine can be compiled and versioned independently of DSH. The package exposes files rather than a conversion API; the provider retains runtime ownership. Ordinary builds remain free of LibreOffice compilation, as checked by the [packaging tests](../../../../scripts/libreoffice-package.spec.ts).
Initial publication and fixed-version consumer integration remain incomplete. A source tree that differs from its recorded recipe cannot produce a release tarball. Real-engine conversion, installation from the packed package, and Desktop offline seed qualification must accompany the first consumed engine release.
@@ -0,0 +1,32 @@
# Agent Note: 独立的预编译 LibreOffice 包
Status: implemented
Archived: 2026-09-11
[English](2026-09-11-independent-libreoffice-package.md) | 中文
## 问题
在普通 DSH 构建中编译 LibreOffice,会要求每个贡献者和 CI job 获取工具链并重复执行大型本机构建。Desktop 也需要能随离线安装材料分发的不可变引擎资源。
## 决策
[引擎包](../../../../native/libreoffice-wasm/package.json)采用独立版本,只导出产物清单。源码目录不属于主 pnpm workspace。安装没有生命周期 hook,打包只校验已有的成功构建,不执行编译。[发布工作流](../../../../.github/workflows/libreoffice-wasm-release.yml)仅在明确调度时编译;发布要求匹配的引擎版本 tag 和受保护的 npm 环境。
每个 tarball 包含引擎清单和产物、对应的源码版本、补丁、完整源码差异,以及构建发行物的许可证和声明。打包拒绝不匹配的构建记录、被修改的产物、未列入清单的引擎文件、缺失的声明和内置字体。失败不会自动触发编译。
[本地预览决策](../architecture/2026-09-10-local-office-preview.zh.md)继续负责转换与显式产物配置。此改动建立发布机制,不向 DSH 添加尚未发布的引擎依赖。现有 [Desktop 包集合](../../../../apps/desktop/scripts/prepare-package-set.ts)仍是未来固定版本依赖及其离线 seed 的预期载体。
## 考虑过的替代方案
**在普通构建或包安装期间编译。** 即使引擎版本没有变化,每个消费方也要承担工具链可用性要求和编译开销。
**抽出通用 Node 转换库。** 字体处理、Worker 所有权和转换 API 可以继续由提供方负责。分发预编译产物及将编译与 DSH CI 隔离不需要迁移这些逻辑。
**将引擎源码链接为 workspace 依赖。** 工作区链接会把已发布的预编译包替换为缺少引擎文件的源码目录。
## 影响
引擎可以独立于 DSH 编译和发布版本。包暴露文件而非转换 API;提供方保留运行时所有权。[打包测试](../../../../scripts/libreoffice-package.spec.ts)检查普通构建不编译 LibreOffice。
首次发布和固定版本消费方接入尚未完成。与记录的配方不一致的源码树不能产生发布 tarball。首个被消费的引擎发行版必须同时完成真实引擎转换、打包安装,以及 Desktop 离线 seed 验证。
@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/archived/simplification/2026-08-08-copy-only-preset-authoring.md
2026-08-08-copy-only-preset-authoring.md: 07f8a6553cf9c70d5289a074b6e6d0d677dd4a28
2026-08-08-copy-only-preset-authoring.zh.md: 58757a9774354b116d235f890beb136034f29904
@@ -1,6 +1,7 @@
# Agent Note: Copy-only preset authoring, and the way into a preset's files
Status: implemented
Archived: 2026-09-20
English | [中文](2026-08-08-copy-only-preset-authoring.zh.md)
@@ -1,6 +1,7 @@
# Agent Note: 仅复制的 preset 创作,与通往 preset 文件的入口
Status: implemented
Archived: 2026-09-20
[English](2026-08-08-copy-only-preset-authoring.md) | 中文
@@ -1,6 +1,19 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-06-11-content-block-vocabulary.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-11-content-block-vocabulary.md
2026-06-11-content-block-vocabulary.md: d7d3f6b43a3f65d1421f026e5b6c2cc1ba1eadd2
2026-06-11-content-block-vocabulary.zh.md: ed4f915dff6dcb6dbc91400f9bfa5384253aea7b
/agent-note-provider-neutral-content-block-vocabulary-owned-by-dsh-llm:
en: 64935f5c8e315004
zh: 6a9cbb4578eaa437
/agent-note-provider-neutral-content-block-vocabulary-owned-by-dsh-llm/problem:
en: 4e81df7bca1c1638
zh: f7483d180a613237
/agent-note-provider-neutral-content-block-vocabulary-owned-by-dsh-llm/decision:
en: 9526dfcf4da1d000
zh: ea2bf79a02b26b39
/agent-note-provider-neutral-content-block-vocabulary-owned-by-dsh-llm/alternatives-considered:
en: 1de2e19e711105e6
zh: a2cd5a64cc4e9e73
/agent-note-provider-neutral-content-block-vocabulary-owned-by-dsh-llm/consequences:
en: 999d10e69e447e44
zh: 38370da5b900ac30
@@ -10,7 +10,7 @@ The harness needs one internal language for messages that the loop, session log,
## Decision
Own the vocabulary: messages are arrays of typed content blocks (`text`, `reasoning`, `tool-call`, `tool-result`), with the union derived from the merge-extensible `ContentBlockMap` so plugins add block types via declaration merging. The same merge-extensible-map pattern types every "stringly" field (`MessageSource`, `FinishReason`, `TurnTrigger`, `TurnEndReason`). Streaming is a raw chunk protocol; `BlockAssembler` is the single shared assembly implementation. Adapters translate to provider wire formats — mapping cost lives in adapters, where it belongs.
Own the vocabulary: user, assistant, and system messages are arrays of typed content blocks (`text`, `reasoning`, `tool-call`), with the union derived from the merge-extensible `ContentBlockMap` so plugins add block types via declaration merging. Tool results are first-class tool-role messages whose own content holds result blocks; released Session format v3 retains the historical `tool-result` content block inside a user-role wrapper, and the adjacent V3-to-V4 edge lifts that wrapper into the first-class role. The same merge-extensible-map pattern types every "stringly" field (`MessageSource`, `FinishReason`, `TurnTrigger`, `TurnEndReason`). Streaming is a raw chunk protocol; `BlockAssembler` is the single shared assembly implementation. Adapters translate to provider wire formats — mapping cost lives in adapters, where it belongs.
In-session context injection (`context/message`) and mid-turn steering originally rendered as tagged user-role envelopes (the system-reminder pattern) rather than a new role, so adapters carry zero burden. Both now project as plain user content with no wrapper; see [the injected-content-envelope Agent Note](../simplification/2026-07-20-unwrap-injected-content-envelopes.md). Live-adapter validation confirms this rendering for current DeepSeek behavior; a future provider-specific mismatch belongs in that adapter rather than a new canonical role.
@@ -10,7 +10,7 @@ harness 需要一套统一的内部消息语言,供 agent loop(智能体循
## 决策
自主拥有词汇:消息是类型化内容块的数组(`text`、`reasoning`、`tool-call`、`tool-result`),其联合类型派生自可合并扩展的 `ContentBlockMap`,插件通过声明合并添加新的块类型。同一可合并扩展映射模式为所有「字符串化」字段提供类型(`MessageSource`、`FinishReason`、`TurnTrigger`、`TurnEndReason`)。流式输出采用原始分片协议;`BlockAssembler` 是唯一的共享组装实现。适配器负责转换为提供方的协议格式(wire format)——映射成本留在适配器中,正是它该在的地方。
自主拥有词汇:user、assistant 与 system 消息是类型化内容块的数组(`text`、`reasoning`、`tool-call`),其联合类型派生自可合并扩展的 `ContentBlockMap`,插件通过声明合并添加新的块类型。Tool result 是一等 tool-role message,结果块属于该 message 自己的 content;已发布的 Session format v3 仍将历史 `tool-result` content block 保存在 user-role 包装中,邻接的 V3 到 V4 边会将该包装提升为一等角色。同一可合并扩展映射模式为所有「字符串化」字段提供类型(`MessageSource`、`FinishReason`、`TurnTrigger`、`TurnEndReason`)。流式输出采用原始分片协议;`BlockAssembler` 是唯一的共享组装实现。适配器负责转换为提供方的协议格式(wire format)——映射成本留在适配器中,正是它该在的地方。
会话内上下文注入(`context/message`)和轮次中途 steering(中途引导)最初渲染为带标签的 user-role 信封(system-reminder 模式),而非引入新角色,因此适配器无需承担额外负担。如今两者都投影为无包装的普通用户内容;见[注入内容信封 Agent Note](../simplification/2026-07-20-unwrap-injected-content-envelopes.zh.md)。实际适配器验证已确认此渲染方式符合当前 DeepSeek 的行为;如果未来某提供方出现不兼容,应在该适配器内处理,而非引入新的规范角色。
@@ -1,6 +1,37 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-06-11-dev-invariants-over-deep-readonly.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-11-dev-invariants-over-deep-readonly.md
2026-06-11-dev-invariants-over-deep-readonly.md: 9adb741db1e26e3a9f750fed60524351159cfeaa
2026-06-11-dev-invariants-over-deep-readonly.zh.md: d352eca985b6594ec5d10c9b73c2ecc18ea458b5
/agent-note-source-owned-session-immutability-and-dev-mode-invariants:
en: 052aa271e87074c0
zh: 3ccffc50fc1a28d4
/agent-note-source-owned-session-immutability-and-dev-mode-invariants/problem:
en: 6ea85a4531d5e59f
zh: b4b568eb347f016a
/agent-note-source-owned-session-immutability-and-dev-mode-invariants/decision:
en: 6e701ec64c3bbfae
zh: b8ed0f1cb7a0477a
/agent-note-source-owned-session-immutability-and-dev-mode-invariants/decision/session-owns-immutable-history:
en: ff47e58c377a8dc0
zh: 5edbe4f3642a3fe6
/agent-note-source-owned-session-immutability-and-dev-mode-invariants/decision/derived-requests-remain-detached:
en: 975df574ee6e6df8
zh: 96d765058482835a
/agent-note-source-owned-session-immutability-and-dev-mode-invariants/decision/package-owned-invariant-companions-check-relationships:
en: a88e3a896eedca91
zh: 03e96c7870cba932
/agent-note-source-owned-session-immutability-and-dev-mode-invariants/alternatives-considered:
en: 6119e2aff3b6be5a
zh: 76136ef5249c23eb
/agent-note-source-owned-session-immutability-and-dev-mode-invariants/alternatives-considered/pervasive-deep-readonly-types:
en: ec54af2931616616
zh: 5fd9bc469a6fd3a5
/agent-note-source-owned-session-immutability-and-dev-mode-invariants/alternatives-considered/development-only-freezing:
en: 85591197bb62eabf
zh: ba69b9ccf596a6d7
/agent-note-source-owned-session-immutability-and-dev-mode-invariants/alternatives-considered/clone-only-when-deriving-messages:
en: a9848dec50664b92
zh: 7c558550b054627b
/agent-note-source-owned-session-immutability-and-dev-mode-invariants/consequences:
en: bcccf7d464a070db
zh: eccd442a21e2c99e
@@ -22,7 +22,7 @@ Responsibility is split between an always-on storage boundary and optional devel
`Session` accepts an event only after one recursive pass has materialized a lossless JSON snapshot. That pass rejects unsupported values and produces the exact detached record that enters the log, so validation and storage cannot observe different values from a stateful getter or retain caller-owned nested references.
The accepted event and all of its descendants are deep-frozen before publication. `append()` returns that owned frozen event, and `session/event` observers and `eventAt(seq)` receive the same record. `snapshotEvents(fromSeq?, toSeqExclusive?)` returns a frozen array snapshot; a previously returned array does not grow after a later append. `seq` and `eventAt()` avoid array materialization when a caller needs only the current length or one event. Seed records pass through the same validation, snapshot, and freeze boundary before construction succeeds.
The accepted event and all of its descendants are deep-frozen before publication. `append()` returns that owned frozen event, and `session/event` observers and `eventAt(seq)` receive the same record. `snapshotEvents(fromSeq?, toSeqExclusive?)` returns a frozen array snapshot; a previously returned array does not grow after a later append. `seq` reads the current length without materializing an array. Synchronous historical readers are deprecated under the [event-read policy](2026-09-09-deprecate-synchronous-session-event-reads.md). Seed records pass through the same validation, snapshot, and freeze boundary before construction succeeds.
This guarantee belongs in `Session`, not in an optional listener, because every composition relies on trustworthy history. A production deployment, a focused test, or a custom embedding receives the same storage semantics whether or not development support plugins are registered.
@@ -53,7 +53,7 @@ Detaching `deriveMessages()` would protect the most common request path but leav
## Consequences
- Every accepted live or seeded session event is detached from caller-owned inputs and deeply immutable before any observer can receive it.
- `snapshotEvents()` exposes stable immutable snapshots instead of the private growing array; `seq` and `eventAt()` serve scalar reads without copying that array.
- Existing `snapshotEvents()` and `eventAt()` callers retain immutable read results while their migration is deferred; `seq` reads the log length without copying the array.
- Request-side mutation cannot reach stored history through derived messages.
- Development builds can enable relational assertions without changing storage behavior, and disposing or filtering a companion does not weaken log immutability.
- `dsh-invariants` configures global enablement plus package allow/block regex lists; each check remains owned and tested by its product package.
@@ -22,7 +22,7 @@ TypeScript readonly 类型不是充分的运行时边界。它们在程序运行
`Session` 仅在一次递归遍历完成无损 JSON 快照的物化之后才接受事件。该遍历拒绝不支持的值,并产出进入日志的已分离的确切记录,因此验证与存储不会从有状态的 getter 观察到不同的值,也不会保留调用方拥有的嵌套引用。
被接受的事件及其所有后代在发布前被深度冻结。`append()` 返回由 Session 拥有的冻结事件,`session/event` 观察者和 `eventAt(seq)` 接收同一记录。`snapshotEvents(fromSeq?, toSeqExclusive?)` 返回冻结的数组快照;先前返回的数组不会因后续 append 而增长。调用方只需要当前长度或单个事件时,`seq` 和 `eventAt()` 不会物化数组。种子记录在构造成功前经过相同的验证、快照与冻结边界。
被接受的事件及其所有后代在发布前被深度冻结。`append()` 返回由 Session 拥有的冻结事件,`session/event` 观察者和 `eventAt(seq)` 接收同一记录。`snapshotEvents(fromSeq?, toSeqExclusive?)` 返回冻结的数组快照;先前返回的数组不会因后续 append 而增长。`seq` 无需物化数组即可读取当前长度。同步历史读取方法按[事件读取策略](2026-09-09-deprecate-synchronous-session-event-reads.zh.md)弃用。种子记录在构造成功前经过相同的验证、快照与冻结边界。
此保证属于 `Session` 而非可选监听器,因为每种组合都依赖可信的历史。无论是否注册了开发支持插件,生产部署、聚焦测试或自定义嵌入都获得相同的存储语义。
@@ -53,7 +53,7 @@ TypeScript readonly 类型不是充分的运行时边界。它们在程序运行
## 后果
- 每个被接受的实时或种子会话事件在任何观察者接收之前,都已从调用方拥有的输入中分离并深度不可变。
- `snapshotEvents()` 暴露稳定的不可变快照,而非持续增长的私有数组;`seq` 和 `eventAt()` 为标量读取提供无需复制数组的路径。
- 现有 `snapshotEvents()` 和 `eventAt()` 调用方在暂缓迁移期间仍获得不可变的读取结果;`seq` 无需复制数组即可读取日志长度。
- 请求侧的修改无法通过派生消息触及已存储的历史。
- 开发构建可以启用关系断言而不改变存储行为;dispose 或过滤一个配套插件不会削弱日志不可变性。
- `dsh-invariants` 配置全局启用状态以及包名允许/阻止 regex 列表;每项检查仍由其产品包拥有并测试。
@@ -1,6 +1,19 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-06-11-event-sourced-sessions.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-11-event-sourced-sessions.md
2026-06-11-event-sourced-sessions.md: b6d17d2db1d9b489f3d4224683b61e62be485014
2026-06-11-event-sourced-sessions.zh.md: 11e5740dc2636fc002ed7158167b1dfbb39a971d
/agent-note-event-sourced-sessions-with-derived-message-history:
en: da3abc821101e4b3
zh: c206fa4830920592
/agent-note-event-sourced-sessions-with-derived-message-history/problem:
en: 63b684d349a48a15
zh: 7603f64b445db129
/agent-note-event-sourced-sessions-with-derived-message-history/decision:
en: d60f161037a10269
zh: 799a15fae2534ec4
/agent-note-event-sourced-sessions-with-derived-message-history/alternatives-considered:
en: 73541e0833eb9559
zh: ddca382d54e498e5
/agent-note-event-sourced-sessions-with-derived-message-history/consequences:
en: d2ea77a5c8e30949
zh: 19dc61cb0d29315f
@@ -1,6 +1,19 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-06-11-microkernel-event-taxonomy.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-11-microkernel-event-taxonomy.md
2026-06-11-microkernel-event-taxonomy.md: 6cacbc30f29c863de0f8ddfa4df7251a64bc80ca
2026-06-11-microkernel-event-taxonomy.zh.md: 1c7919392b835c491b9dc606d46f638a708d2948
/agent-note-microkernel-extension-via-cordis-event-taxonomy-one-concrete-loop:
en: e5775d7ec6f1cdc3
zh: a364697f860a545a
/agent-note-microkernel-extension-via-cordis-event-taxonomy-one-concrete-loop/problem:
en: 3bc74749db819441
zh: 19b5497ed3a9378b
/agent-note-microkernel-extension-via-cordis-event-taxonomy-one-concrete-loop/decision:
en: 2153b0cb5773cb08
zh: 82d7ad1b250cd52d
/agent-note-microkernel-extension-via-cordis-event-taxonomy-one-concrete-loop/alternatives-considered:
en: e528c5a20e0c55a3
zh: 004d3bf06241cc26
/agent-note-microkernel-extension-via-cordis-event-taxonomy-one-concrete-loop/consequences:
en: 6acb80cdaa7c010f
zh: acca672d8094d985
@@ -1,6 +1,22 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-06-13-capability-seams.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-13-capability-seams.md
2026-06-13-capability-seams.md: 3c552c474b499b9f1c9f60242f4773750faadafb
2026-06-13-capability-seams.zh.md: 4e6100a2ce557d91fa18b5630c267f37f1bc0f00
/agent-note-capability-seams-service-definition-service-provider-consumer-roles:
en: 4c1875882be571bb
zh: 90ef4d8b27587c6b
/agent-note-capability-seams-service-definition-service-provider-consumer-roles/problem:
en: 3215928333de66f7
zh: 2c72fcacccf25741
/agent-note-capability-seams-service-definition-service-provider-consumer-roles/decision:
en: 774c54c0d3d9acad
zh: 7dd4bfaf0ba2181b
/agent-note-capability-seams-service-definition-service-provider-consumer-roles/terminology-seam-names-the-trio-not-the-interface:
en: 8dca727800bea2f4
zh: 4c4e028520967ca0
/agent-note-capability-seams-service-definition-service-provider-consumer-roles/alternatives-considered:
en: cf6e4b1f188d9e4a
zh: bf2485a5f539746c
/agent-note-capability-seams-service-definition-service-provider-consumer-roles/consequences:
en: 941d8b343162edea
zh: 70904b0716de151d
@@ -8,7 +8,7 @@ English | [中文](2026-06-13-capability-seams.zh.md)
The harness has swappable capabilities, including shell execution and model providers. A capability has three concerns that change at different rates and for different reasons: the *contract* (what the capability is), the *implementation* (how it runs), and the *consumer API* (what the model and other plugins program against). Bundling them in one package couples those rates of change — swapping a local executor for a sandboxed one would churn the tool schemas the model sees, even though the model-facing contract never changed.
This is distinct from "who provides vs. needs a capability at runtime", which Cordis already answers with services + `inject` (a provider registers `ctx.shell`; a consumer declares `inject: ['bash']` and its fiber pends until the service exists). That mechanism is necessary but doesn't dictate package boundaries; this Agent Note does.
This is distinct from "who provides vs. needs a capability at runtime", which Cordis already answers with services + `inject` (a provider registers `ctx.shell`; a consumer declares `inject: ['shell']` and its fiber pends until the service exists). That mechanism is necessary but doesn't dictate package boundaries; this Agent Note does.
## Decision
@@ -8,7 +8,7 @@ Status: implemented
harness 具有可替换的能力,包括 shell 执行和模型提供方。一项能力涉及三个关注点,它们以不同速率、因不同原因变化:*约定*(这项能力是什么)、*实现*(它如何运行)、*消费方 API*(模型和其他插件面向什么编程)。将三者捆绑在一个包中会耦合这些变化速率——把本地执行器换成沙箱化执行器时,模型看到的工具 schema 也会被搅动,尽管面向模型的约定从未改变。
这与「谁在运行时提供、谁需要一项能力」是不同的问题,后者 Cordis 已通过服务 + `inject` 解决(提供方注册 `ctx.shell`;消费方声明 `inject: ['bash']`,其 fiber 挂起直到服务存在)。该机制是必要的,但不决定包的边界;本 Agent Note 决定的是包的边界。
这与「谁在运行时提供、谁需要一项能力」是不同的问题,后者 Cordis 已通过服务 + `inject` 解决(提供方注册 `ctx.shell`;消费方声明 `inject: ['shell']`,其 fiber 挂起直到服务存在)。该机制是必要的,但不决定包的边界;本 Agent Note 决定的是包的边界。
## 决策
@@ -1,6 +1,19 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-06-13-twin-llm-adapters.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-13-twin-llm-adapters.md
2026-06-13-twin-llm-adapters.md: a4c87325a0b0d1ebe6cf8f95672e5de74ef37d57
2026-06-13-twin-llm-adapters.zh.md: 36996750a16cc95393d727cffee3bcc53573eaf2
/agent-note-two-llm-adapters-as-a-design-verification-twin:
en: dcb28a02ba26cb31
zh: 096d0ab60a3ad638
/agent-note-two-llm-adapters-as-a-design-verification-twin/problem:
en: feb8f5213be03a5c
zh: 5ca85048792db7d8
/agent-note-two-llm-adapters-as-a-design-verification-twin/decision:
en: 0dd6ebb29aebc164
zh: 20065ae72f4d131d
/agent-note-two-llm-adapters-as-a-design-verification-twin/alternatives-considered:
en: c523a9b402588189
zh: bced37eb1040360a
/agent-note-two-llm-adapters-as-a-design-verification-twin/consequences:
en: 71cc34560fc2e012
zh: 91ea73e3e009a9a5
@@ -25,3 +25,5 @@ The rule they enforce: **anything the StreamChunk vocabulary cannot express for
## Consequences
The twin doubles adapter and key-gated e2e maintenance—both cover V4 Flash and Pro across representative reasoning modes—in exchange for continuous seam-neutrality validation and a second implementation example. Both use `apiKey`, `baseURL`, and `models`; the direct-fetch adapter exposes `thinking`/`reasoningEffort`, while pi-ai exposes one `reasoning` level. A future conformance suite could justify retiring one adapter through a superseding Agent Note.
The [Messages adapter](../feature/2026-09-07-deepseek-messages-adapter.md) adds an Anthropic-protocol implementation inside `llm-deepseek`; it preserves the same stream conventions.
@@ -25,3 +25,5 @@ Status: implemented
## 后果
孪生体使适配器和需要密钥的 e2e 维护量翻倍——两者都覆盖 V4 Flash 和 Pro 在各代表性推理(reasoning)模式下的行为——换来的是持续的 seam 中立性验证和第二份实现示例。两个适配器均使用 `apiKey`、`baseURL` 和 `models`;直接 fetch 适配器暴露 `thinking`/`reasoningEffort`,pi-ai 适配器暴露一个 `reasoning` 级别。未来如果有一致性测试套件,可以通过后续 Agent Note 论证退役其中一个适配器。
[Messages 适配器](../feature/2026-09-07-deepseek-messages-adapter.zh.md) 在 `llm-deepseek` 内增加 Anthropic 协议实现,并遵守相同的流约定。
@@ -1,6 +1,19 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-06-14-session-persistence.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-14-session-persistence.md
2026-06-14-session-persistence.md: 55c1bbab94bb7854fd6bbcaace56c30dbcdb01dc
2026-06-14-session-persistence.zh.md: 16546ab61773da47064de8388803e92c8b454eae
/agent-note-session-persistence-as-an-abstract-service-over-the-existing-sessionevent:
en: d7cf18702f4ed830
zh: 7e0cc6db7c90a7bd
/agent-note-session-persistence-as-an-abstract-service-over-the-existing-sessionevent/problem:
en: fa1ffb258aee90f6
zh: c25cead52e72f97d
/agent-note-session-persistence-as-an-abstract-service-over-the-existing-sessionevent/decision:
en: a7076073971de601
zh: 5ea9a87705340d91
/agent-note-session-persistence-as-an-abstract-service-over-the-existing-sessionevent/alternatives-considered:
en: e5c9929ca92cc12e
zh: 3e0668f6a822577c
/agent-note-session-persistence-as-an-abstract-service-over-the-existing-sessionevent/consequences:
en: 4f00ed0b90442440
zh: 994a5b03c862178b
@@ -15,11 +15,11 @@ The [event-sourced model](2026-06-11-event-sourced-sessions.md) makes the append
Persistence is a **capability seam** with an abstract Service Definition ([capability seams](2026-06-13-capability-seams.md), the `dsh-shell` template), not loop or core logic:
1. **Interface** (`dsh-session-persistence`, `ctx.sessionPersistence`) — an abstract `SessionPersistence` service: `create`/`open`/`stat`/`list`/`flush`, with `create`/`open` returning per-session `SessionHandle`s that carry `read`/`append`/`flush`/`close` ([handle-based seam](2026-08-27-handle-based-session-persistence.md)). Its persisted unit IS the existing `SessionEvent` (`{ type, seq, time, data }`), reused verbatim — no conversion type.
2. **Implementation** (`dsh-session-persistence-jsonl`) — an append-only logical JSONL log per session: a `SessionHeader` line followed by storage records that losslessly represent the contiguous `SessionEvent` stream. Current v2 writes one event per row; frozen v0 and v1 readers retain their historical packed-delta representation. [Checksummed Zstandard frames](2026-07-19-zstandard-jsonl-session-logs.md) are the default physical encoding, with raw lines configurable.
2. **Implementation** (`dsh-session-persistence-jsonl`) — an append-only logical JSONL log per session: a `SessionHeader` line followed by storage records that losslessly represent the contiguous `SessionEvent` stream. The current format writes one event per row; frozen v0 and v1 readers retain their historical packed-delta representation. [Checksummed Zstandard frames](2026-07-19-zstandard-jsonl-session-logs.md) are the default physical encoding, with raw lines configurable.
Key durable, contested choices:
- **The canonical durable log persists every current `SessionEvent` losslessly.** In v2, one `assistant/message` or `assistant/attempt` embeds the exact timed provider stream for an attempt; `deriveMessages()` projects only the surface message. Dropping embedded stream members is tempting, but it loses replay, timing, usage, partial-failure, and diagnostic facts. Removing a complete event likewise requires dense renumbering because `seq = log.length` and `events[i].seq === i`; the [v1-to-v2 migration](2026-09-01-v2-embedded-assistant-streams.md) performs that rewrite explicitly rather than filtering the canonical log.
- **The canonical durable log persists every current `SessionEvent` losslessly.** One `assistant/message` or `assistant/attempt` embeds the exact timed provider stream for an attempt; `deriveMessages()` projects only the surface message. Dropping embedded stream members is tempting, but it loses replay, timing, usage, partial-failure, and diagnostic facts. Removing a complete event likewise requires dense renumbering because `seq = log.length` and `events[i].seq === i`; the [v1-to-v2 migration](2026-09-01-v2-embedded-assistant-streams.md) performs that rewrite explicitly rather than filtering the canonical log.
- **Append-only; a crashed turn is closed, never truncated.** Flushed events are never rewritten. The [semantic checkpoint policy](../../../../packages/session/session-checkpoint-policy/README.md) drains the request before model dispatch, a recorded top-level call before tool dispatch, and the complete response/result batch after a step; the loop drains the final turn boundary. Because one interrupted turn may contain substantial valid work, persistence returns its contiguous, parseable events unmodified; the reader owns balancing — resume computes risk-classified error results for unanswered assistant calls, a missing `step/end`, and `turn/end` with `{ kind: 'interrupted' }` (`interruptedTurnClosers`) and appends them through its write handle, while read-only observers add the same closers in memory. The synthetic results keep resumed provider transcripts valid. Only the incomplete fragment of a torn final append is discarded — complete records recovered from it are durably rewritten by the write path before its first new append; a parse error or sequence gap in the committed prefix is corruption and makes the session unloadable.
- **The file backend is canonical while the service remains extensible.** `dsh-session-persistence-jsonl` is the sole first-party provider and passes `runPersistenceContract`; the abstract service remains available to out-of-tree providers. The [JSONL-only persistence decision](../simplification/2026-08-30-jsonl-only-session-persistence.md) owns removal of the first-party database provider and its deliberate compatibility cut.
- **Metadata is out-of-log.** Format version, cwd, and lineage are storage concerns, not replayable conversation state, so they live in a `SessionHeader` owned by `dsh-session` and attached to a `Session` via a new readonly `session.header` — never in `SessionEventMap`, never reaching `deriveMessages()`. `createdAt` is non-negative safe-integer Unix epoch milliseconds: live creation and persistence registration reject fractional values, and JSONL validates the decoded header. The alternative (a merge-extensible `session/meta` event as log line 0) was rejected: an in-log event would ride along with a seeded/forked session for free, but metadata is not replayable state, so the explicit out-of-log header boundary is the cleaner cost. (The header was originally split into an immutable `SessionHeader` plus a mutable `SessionSummary` whose union was `SessionMeta`; the mutable summary was later removed as dead state — see [Drop the mutable session summary](../../archived/simplification/2026-06-19-drop-mutable-session-summary.md).)
@@ -29,7 +29,7 @@ Key durable, contested choices:
Each key choice above records its rejected alternative where the choice is stated: a **stream-filtered canonical log** — loses attempt evidence, while removing events without an explicit migration breaks contiguous sequence numbers; **truncating a crashed turn** — silently destroys a long autonomous run's real work; an **in-log `session/meta` event as log line 0** — metadata is not replayable state; **finite fractional `createdAt` values** — have no producer and diverge from integer Unix-millisecond storage; **hard-injecting `sessionPersistence` into the loop** — would pend non-persistent demos forever.
Format versioning: the header carries a `version`; handles expose only `SESSION_FORMAT_VERSION = 2`. JSONL event-body reads compose the static v0-to-v1 and v1-to-v2 adjacent migration chain before returning a handle; the first edge owns bounded legacy normalization, while the second owns Assistant stream embedding and dense reference remapping. V0 remains at suffixless `session.jsonl[.zstd]`, while positive versions use immutable lowercase `session.vN.jsonl[.zstd]` names ([released Session migration](2026-08-31-released-session-format-migrations.md)). Current-generation append and flush are robust to partial trailing writes; a future provider or write-ahead log needs its own power-loss and recovery contract.
Format versioning: the header carries a `version`; handles expose only the logical format selected by `SESSION_FORMAT_VERSION` ([version authority](../../../../docs/session-format-status.md)). JSONL event-body reads compose the complete static adjacent migration chain before returning a handle; each edge owns its historical transformations. V0 remains at suffixless `session.jsonl[.zstd]`, while positive versions use immutable lowercase `session.vN.jsonl[.zstd]` names ([released Session migration](2026-08-31-released-session-format-migrations.md)). Current-generation append and flush are robust to partial trailing writes; a future provider or write-ahead log needs its own power-loss and recovery contract.
## Consequences
@@ -15,11 +15,11 @@ Status: implemented
持久化是一个具有抽象 Service Definition 的**能力 seam**([能力 seam](2026-06-13-capability-seams.zh.md),`dsh-shell` 模板),而非循环或核心逻辑:
1. **接口**(`dsh-session-persistence`,`ctx.sessionPersistence`):一个抽象的 `SessionPersistence` 服务,提供 `create`/`open`/`stat`/`list`/`flush`,其中 `create`/`open` 返回逐会话的 `SessionHandle`,句柄承载 `read`/`append`/`flush`/`close`([基于句柄的 seam](2026-08-27-handle-based-session-persistence.zh.md))。其持久化单元就是现有的 `SessionEvent`(`{ type, seq, time, data }`),原样复用,无转换类型。
2. **实现**(`dsh-session-persistence-jsonl`):每个会话一个仅追加的逻辑 JSONL 日志:先是一行 `SessionHeader`,随后是无损表示连续 `SessionEvent` 流的存储记录。当前 v2 每个事件写一行;冻结的 v0 与 v1 reader 保留其历史 packed-delta 表示。[带校验和的 Zstandard 帧](2026-07-19-zstandard-jsonl-session-logs.zh.md)是默认物理编码,也可通过配置使用原始行。
2. **实现**(`dsh-session-persistence-jsonl`):每个会话一个仅追加的逻辑 JSONL 日志:先是一行 `SessionHeader`,随后是无损表示连续 `SessionEvent` 流的存储记录。当前格式每个事件写一行;冻结的 v0 与 v1 reader 保留其历史 packed-delta 表示。[带校验和的 Zstandard 帧](2026-07-19-zstandard-jsonl-session-logs.zh.md)是默认物理编码,也可通过配置使用原始行。
长期有效、存在争议的关键选择:
- **规范持久日志无损保留每个当前 `SessionEvent`。** 在 v2 中,一个 `assistant/message` 或 `assistant/attempt` 会嵌入该 attempt 的精确带时间 provider stream;`deriveMessages()` 只投影 surface message。删除嵌入 stream 成员看似诱人,但会丢失 replay、timing、usage、部分失败与诊断事实。移除完整事件同样需要密集重新编号,因为 `seq = log.length` 且 `events[i].seq === i`;[v1 到 v2 迁移](2026-09-01-v2-embedded-assistant-streams.zh.md)会显式执行该改写,而不是过滤规范日志。
- **规范持久日志无损保留每个当前 `SessionEvent`。** 一个 `assistant/message` 或 `assistant/attempt` 会嵌入该 attempt 的精确带时间 provider stream;`deriveMessages()` 只投影 surface message。删除嵌入 stream 成员看似诱人,但会丢失 replay、timing、usage、部分失败与诊断事实。移除完整事件同样需要密集重新编号,因为 `seq = log.length` 且 `events[i].seq === i`;[v1 到 v2 迁移](2026-09-01-v2-embedded-assistant-streams.zh.md)会显式执行该改写,而不是过滤规范日志。
- **仅追加;崩溃的轮次被关闭,而非截断。** 已刷写的事件永不被重写。[语义检查点策略](../../../../packages/session/session-checkpoint-policy/README.zh.md)会在调用模型前排空请求、在调用工具前排空已记录的顶层调用,并在步骤结束后排空完整的响应/结果批次;循环则排空最终轮次边界。由于一个被中断的轮次可能包含大量有效工作,持久化会原样返回其连续、可解析的事件;配平是读方的职责——resume 会为未应答的 assistant 调用计算按风险分类的错误结果、补一个缺失的 `step/end`,以及带 `{ kind: 'interrupted' }` 的 `turn/end`(`interruptedTurnClosers`),并通过其写句柄追加它们,而只读观察方仅在内存中添加同样的收尾事件。合成结果保证恢复后的提供方 transcript(文本记录)仍然有效。只有撕裂的最终 append 中不完整的碎片会被丢弃——从中恢复的完整记录由写路径在第一次新 append 之前持久重写;已提交前缀中的解析错误或序号间隙,属于数据损坏,会使该会话不可加载。
- **文件后端为规范实现,服务保持可扩展。** `dsh-session-persistence-jsonl` 是唯一 first-party provider,并通过 `runPersistenceContract`;抽象服务继续供仓库外 provider 使用。[JSONL-only 持久化决策](../simplification/2026-08-30-jsonl-only-session-persistence.zh.md)负责 first-party 数据库 provider 的删除及其明确 compatibility cut。
- **元数据在日志之外。** 格式版本、cwd 和谱系是存储关注点,不是可回放的对话状态,因此它们存放在 `dsh-session` 拥有的 `SessionHeader` 中,并通过新的只读属性 `session.header` 附加到 `Session` 上——永远不进入 `SessionEventMap`,永远不到达 `deriveMessages()`。`createdAt` 是以 Unix epoch 毫秒表示的非负安全整数:运行时创建和持久化注册会拒绝小数值,JSONL 会验证解码后的 header。替代方案(一个可合并扩展的 `session/meta` 事件作为日志第 0 行)被否决:日志内事件会自然随 seed/fork 的会话携带,但元数据不是可回放状态,因此显式的日志外 header 边界是更清晰的取舍。(header 最初被拆分为不可变的 `SessionHeader` 加可变的 `SessionSummary`,二者的联合类型为 `SessionMeta`;可变 summary 后来因属于死状态而被移除——见 [移除可变会话摘要](../../archived/simplification/2026-06-19-drop-mutable-session-summary.md)。)
@@ -29,7 +29,7 @@ Status: implemented
上述每个关键选择都在陈述处记录了被否决的替代方案:**过滤 stream 的规范日志**会丢失 attempt 证据,而未通过显式迁移移除事件会破坏连续序号;**截断崩溃的轮次**会静默销毁长时间自主运行中的真实工作;**日志内 `session/meta` 事件作为第 0 行**——元数据不是可回放状态;**有限的非整数 `createdAt` 值**没有生产方,且与整数 Unix 毫秒存储不一致;**将 `sessionPersistence` 硬注入循环**会让非持久化的演示永远挂起。
格式版本控制:header 携带 `version`;句柄只暴露 `SESSION_FORMAT_VERSION = 2`。JSONL 的事件正文读取会在返回句柄前组合静态 v0-to-v1 与 v1-to-v2 相邻迁移链;第一条边负责有界 legacy normalization,第二条边负责 Assistant stream 嵌入与密集引用重映射。V0 保留无后缀的 `session.jsonl[.zstd]`,正版本则使用不可变的小写 `session.vN.jsonl[.zstd]` 名称([已发布 Session 迁移](2026-08-31-released-session-format-migrations.zh.md))。当前 generation 的 append 与 flush 能稳健处理不完整尾部写入;未来 provider 或 WAL 必须定义自己的断电与恢复约定。
格式版本控制:header 携带 `version`;句柄只暴露由 `SESSION_FORMAT_VERSION` 选定的逻辑格式([版本真源](../../../../docs/session-format-status.zh.md))。JSONL 的事件正文读取会在返回句柄前组合完整的静态相邻迁移链;每条迁移边拥有自身的历史转换。V0 保留无后缀的 `session.jsonl[.zstd]`,正版本则使用不可变的小写 `session.vN.jsonl[.zstd]` 名称([已发布 Session 迁移](2026-08-31-released-session-format-migrations.zh.md))。当前 generation 的 append 与 flush 能稳健处理不完整尾部写入;未来 provider 或 WAL 必须定义自己的断电与恢复约定。
## 后果
@@ -1,6 +1,37 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-06-18-session-surface.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-18-session-surface.md
2026-06-18-session-surface.md: 93ea55883dedd943fe1ffac67a9842c962ca6dac
2026-06-18-session-surface.zh.md: 54ecb1162bc46007dfcbb7d8cb39075d52171567
/agent-note-session-surface-an-ordered-projection-over-the-event-log:
en: 9ea7a8765e7f3259
zh: 17e0d51645f01edd
/agent-note-session-surface-an-ordered-projection-over-the-event-log/problem:
en: 4f7a9d20d71a6ab3
zh: 958abbdfefec4f21
/agent-note-session-surface-an-ordered-projection-over-the-event-log/decision:
en: a9944b568ec51fad
zh: 6717d30db31b81d7
/agent-note-session-surface-an-ordered-projection-over-the-event-log/decision/top-level-surface-metadata-on-sessionevent:
en: 788fc16ecdedc252
zh: 14d05c2a1272de5d
/agent-note-session-surface-an-ordered-projection-over-the-event-log/decision/surfaceop-two-operations:
en: ff075eec0881094a
zh: 1f7768f28b8996d5
/agent-note-session-surface-an-ordered-projection-over-the-event-log/decision/surfacemanager-delta-based-not-full-rebuild:
en: 0b10fd9c5166d17b
zh: 02de01f70c03f70e
/agent-note-session-surface-an-ordered-projection-over-the-event-log/decision/persistence:
en: 9bb1f81b86b24760
zh: fe4948645dd0c66d
/agent-note-session-surface-an-ordered-projection-over-the-event-log/decision/crash-recovery:
en: ee71f9c0f12b6a0e
zh: 403b1723f808391d
/agent-note-session-surface-an-ordered-projection-over-the-event-log/decision/invariants:
en: 24b1342fb3b5be29
zh: a62692b0250c072a
/agent-note-session-surface-an-ordered-projection-over-the-event-log/alternatives-considered:
en: 193157129e65e487
zh: a0a73b8a9cbd78e6
/agent-note-session-surface-an-ordered-projection-over-the-event-log/consequences:
en: 801b67f8da564a22
zh: 3c0433ed07083050
@@ -37,7 +37,7 @@ Delta processing is O(1) when no new events and O(new events) when new events ar
### Persistence
The fields are serialized as top-level JSON properties. JSONL preserves placement and provenance without a separate column mapping. The [V3 canonical-envelope decision](2026-09-06-v3-canonical-session-envelopes.md) owns exact replacement keys and strict-acceptance rationale; the [V2-to-V3 specification](../../../../packages/session/session-format-v2-to-v3/README.md#canonical-envelopes) owns historical conversion. This note retains ordered-projection ownership and replacement rationale.
The fields are serialized as top-level JSON properties. JSONL preserves placement and source-event references without a separate column mapping. The [V3 canonical-envelope decision](2026-09-06-v3-canonical-session-envelopes.md) owns exact replacement keys and strict-acceptance rationale; the [V2-to-V3 specification](../../../../packages/session/session-format-v2-to-v3/README.md#canonical-envelopes) owns historical conversion. This note retains ordered-projection ownership and replacement rationale.
### Crash recovery
@@ -37,7 +37,7 @@ surface 元数据仅属于四种 surface 事件类型(`system/message`、`user
### 持久化
这些字段作为顶层 JSON 属性序列化。JSONL 无需单独列映射即可保留位置与来源。[V3 规范信封决策](2026-09-06-v3-canonical-session-envelopes.zh.md)负责精确替换键与严格准入依据;[V2 到 V3 规范](../../../../packages/session/session-format-v2-to-v3/README.zh.md#canonical-envelopes)负责历史转换。本文继续负责有序投影的所有权与替换依据。
这些字段作为顶层 JSON 属性序列化。JSONL 无需单独列映射即可保留位置与源事件引用。[V3 规范信封决策](2026-09-06-v3-canonical-session-envelopes.zh.md)负责精确替换键与严格准入依据;[V2 到 V3 规范](../../../../packages/session/session-format-v2-to-v3/README.zh.md#canonical-envelopes)负责历史转换。本文继续负责有序投影的所有权与替换依据。
### 崩溃恢复
@@ -1,6 +1,58 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-06-20-generic-long-running-tool-runtime.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-20-generic-long-running-tool-runtime.md
2026-06-20-generic-long-running-tool-runtime.md: c386d3b338c94e0e5bbf8e99c2c7a30971ba92b7
2026-06-20-generic-long-running-tool-runtime.zh.md: 002514740a15c5961960d20976fc18f7fd8071ff
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools:
en: 56e269b2a2839796
zh: 8fc971036985ac0d
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/problem:
en: 70e26df62568c337
zh: a9e6f5f8a5482d0a
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/decision:
en: 277869395ad6f792
zh: 93f13a97d52f10a5
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/runtime-contract:
en: eeb7ed8eec13668a
zh: 3f236f63c72fbba7
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/authorization-and-owner-lifecycle:
en: 3819a73ca70ecdfd
zh: c1a4f461a4e45978
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/service-api:
en: a1a884816aac3d7f
zh: b21129e5cd93b9a1
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/model-facing-control-api:
en: dd3f4d85d0ec136f
zh: ca4209cb856271dd
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/producer-opt-in:
en: a39343bf6f655051
zh: d9894d39e7f4d6e1
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/producer-integrations:
en: ae4a6d6e0d83d3bd
zh: 9072890ba9374426
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/alternatives-considered:
en: 6119e2aff3b6be5a
zh: e01a6c669a9ec6aa
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/alternatives-considered/per-capability-control-tools:
en: 9781c302dc72fd8e
zh: a78e1dd8da4d8ca8
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/alternatives-considered/an-immediate-abstract-task-runtime-backend:
en: 404a5c7c45a71a55
zh: 213621e4a9618a9c
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/alternatives-considered/consumer-owned-authorization-or-cleanup-events:
en: d99de803718d9ca6
zh: e03a97314851ed0f
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/alternatives-considered/blocking-output-or-a-separate-wait-tool:
en: e3beca50b6a57ce0
zh: a77663b817d33247
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/alternatives-considered/runtime-owned-output-sinks:
en: 42eeeba9d84ae681
zh: 1d540f9740675bee
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/alternatives-considered/random-ids-promotion-or-lifecycle-session-events:
en: e706b1b57241d3d2
zh: 1779b7fa05f48283
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/testing:
en: e891db1723828da8
zh: 657a62ed595bd081
/agent-note-the-background-job-runtime-ctx-jobs-and-generic-task-control-tools/consequences:
en: b95ecd6052465ad3
zh: 1527c38d1b4631d6
@@ -27,7 +27,7 @@ The literal types live on the [tasks subsystem page](../../../../docs/subsystems
The process-local provider also owns bounded admission, whose rationale is recorded in the [bounded background job admission decision](../../archived/bug-fix/2026-08-11-bounded-background-job-admission.md). Its positive-safe-integer `maxConcurrentJobsPerOwner` config defaults to `10`; `start()` derives each exact `Agent` object's active count from `running` and `stopping` records, while every unowned task shares one service bucket. Capacity rejection occurs before `run()` and id allocation, and producer `done` settlement is the only event that releases a stopping task's place. The provider does not queue, preempt, or retain a second mutable count.
`outputLimitBytes` is producer-owned presentation policy, not a registry buffer. The registry validates and projects it unchanged into `JobSnapshot`; generic control APIs apply the cap to complete model-facing output after adding their own status or notice metadata. Omitting it preserves the existing controller behavior, so the runtime does not impose a hidden default on unrelated producer families.
`outputLimitBytes` is producer-owned presentation policy, not a registry buffer. The registry validates and projects it unchanged into `JobView`; generic control APIs apply the cap to complete model-facing output after adding their own status or notice metadata. Omitting it preserves the existing controller behavior, so the runtime does not impose a hidden default on unrelated producer families.
A model-facing producer exposes that committed id in its canonical success value, normally `{ kind: 'background', jobId }`; Native rendering may keep human-readable prose. A pre-aborted background call fails rather than returning a no-op because no task exists to satisfy the promised handle. Once registration publishes the id, cancellation belongs to the task's own controller and the job runtime: later cancellation of the producing tool call must not kill the published task. `job_kill`, owner disposal, and service teardown request cancellation; foreground execution remains coupled to the call's `exec.signal`.
@@ -62,7 +62,7 @@ For contract-compliant producers, `AgentHandle.dispose()` resolves only after ow
- `read(id, caller?)` for a consuming stream delta or an idempotent final result.
- `kill(id, caller?, reason?)` for cancellation.
- `wait(id, timeoutMs, caller?, signal?)` for bounded terminal waiting.
- `onJobDone(listener)` for effect-scoped observation with exact-owner delivery and listener containment.
- `events.subscribe(filter, listener)` for effect-scoped observation of registration, progress, output, settlement, and removal, filtered by owner or owner scope, with listener containment.
- `attachController(name)` for the task-controller availability fence.
`wait` returns the terminal snapshot when the task settles or the live snapshot when its timeout expires. Aborting a wait cancels only that wait. If settlement has already assigned terminal delivery to the waiter, the terminal snapshot still wins. Waiters unregister synchronously on abort so a same-tick settlement cannot suppress a completion notice on behalf of a reader that receives nothing.
@@ -81,7 +81,7 @@ Stream reads share one task-scoped consuming cursor because the owning model is
The system prompt tells the model to retain job ids, continue independent work instead of busy-polling or duplicating a running task, collect relevant tasks before its final answer, and kill work that no longer matters. Completion delivers a logged message to the exact owner's session. A busy owner is injected; an idle owner is woken, under the bounded policy the [idle-owner wake decision](../feature/2026-08-11-background-job-completion-wakes-an-idle-owner.md) owns.
The runtime marks a terminal task `reported` when a read or wait delivers it, when a live waiter has claimed delivery at settlement, or when the model explicitly kills it. Reported tasks do not inject redundant completion notices. Listener failures are logged independently, do not stop later listeners, and are not awaited by waiters or teardown. When a snapshot carries `outputLimitBytes`, `dsh-tool-jobs` preserves UTF-8 boundaries and reuses an existing producer truncation marker rather than duplicating it. Reads reserve status suffixes and retain the output tail; completion notices reserve the stable `background job <id>` prefix and `job_output` instruction before truncating variable kind, label, status, detail, or the truncation marker itself, so the minimum PTY cap still identifies the task to collect. The job controller resolves the caller-visible producer cap in a prepended pre-execute listener before policy can deny or short-circuit dispatch, then applies it through the task definitions' last-mile `finalizeContent` callback so normalized tool errors, outer pipeline failures, and single-text policy results cannot escape the bound; deliberately structured multi-block policy results retain policy ownership of their shape and size.
`dsh-tool-jobs` keeps the delivery ledger: a wait claims the task when it starts (and withdraws if the task outlives the wait) and a `job_kill` claims it when accepted, so a settlement the model already received through a tool result injects no redundant completion notice; teardown settlements and unowned tasks are never announced ([seam consolidation](2026-09-03-jobs-seam-consolidation.md)). Listener failures are logged independently, do not stop later listeners, and are not awaited by waiters or teardown. When a view carries `outputLimitBytes`, `dsh-tool-jobs` preserves UTF-8 boundaries and reuses an existing producer truncation marker rather than duplicating it. Reads reserve status suffixes and retain the output tail; completion notices reserve the stable `background job <id>` prefix and `job_output` instruction before truncating variable kind, label, status, detail, or the truncation marker itself, so the minimum PTY cap still identifies the task to collect. The job controller resolves the caller-visible producer cap in a prepended pre-execute listener before policy can deny or short-circuit dispatch, then applies it through the task definitions' last-mile `finalizeContent` callback so normalized tool errors, outer pipeline failures, and single-text policy results cannot escape the bound; deliberately structured multi-block policy results retain policy ownership of their shape and size.
## Producer opt-in
@@ -105,7 +105,7 @@ Separate bash and subagent output/stop tools duplicate ids, isolation, cleanup,
### An immediate abstract task-runtime backend
The current `JobStart.run()` contract passes in-process callbacks and exact `Agent` objects. A durable backend changes identity, restart, ownership, and observation semantics, so at introduction time the registry stayed one concrete service rather than freezing the wrong boundary. The [task-registry contract Agent Note](../../archived/architecture/2026-07-26-job-registry-seam.md) later separated the contract from the process-local implementation without changing these in-process semantics.
The current `JobSpec.run()` contract returns in-process hooks and pushes output through an in-process `JobHandle`, and owners resolve to live `Agent`s in-process. A durable backend changes identity, restart, ownership, and observation semantics, so at introduction time the registry stayed one concrete service rather than freezing the wrong boundary. The [task-registry contract Agent Note](../../archived/architecture/2026-07-26-job-registry-seam.md) later separated the contract from the process-local implementation without changing these in-process semantics.
### Consumer-owned authorization or cleanup events
@@ -27,7 +27,7 @@ Status: implemented
进程内 Service Provider 还拥有有界准入,其理由记录在[有界后台任务准入决策](../../archived/bug-fix/2026-08-11-bounded-background-job-admission.md)中。它的 `maxConcurrentJobsPerOwner` 配置必须是正的安全整数,默认值为 `10`;`start()` 从 `running` 与 `stopping` 记录派生每个确切 `Agent` 对象的活动数量,而全部无 owner 任务共享一个服务级桶。容量拒绝发生在 `run()` 与 id 分配之前,处于 stopping 的任务只有在生产方 `done` 结算时才释放名额。Service Provider 不排队或抢占任务,也不保留第二份可变计数。
`outputLimitBytes` 是生产方拥有的呈现策略,而非注册表缓冲区。注册表校验该值,并将其原样投影到 `JobSnapshot`;通用任务控制器添加自身的状态或通知元数据后,再将该上限应用于完整的面向模型输出。省略该值时保持现有控制器行为,因此运行时不会向无关的生产方类别施加隐式默认值。
`outputLimitBytes` 是生产方拥有的呈现策略,而非注册表缓冲区。注册表校验该值,并将其原样投影到 `JobView`;通用任务控制器添加自身的状态或通知元数据后,再将该上限应用于完整的面向模型输出。省略该值时保持现有控制器行为,因此运行时不会向无关的生产方类别施加隐式默认值。
面向模型的生产方会在规范成功值中暴露已提交的 id,通常为 `{ kind: 'background', jobId }`;Native 渲染仍可保留便于人类阅读的行文。预先被中止的后台调用会失败,而不是返回空操作,因为不存在可履行所承诺句柄的任务。一旦注册过程发布 id,取消就归任务自身的控制器与任务运行时所有:随后取消生产工具调用不得终止已发布的任务。`job_kill`、所有者资源释放和服务拆除会请求取消;前台执行仍与调用的 `exec.signal` 耦合。
@@ -62,7 +62,7 @@ job id 在运行时全局可见且可预测,因此注册表会授权每次访
- `read(id, caller?)`:消费式流增量或幂等的最终结果。
- `kill(id, caller?, reason?)`:取消。
- `wait(id, timeoutMs, caller?, signal?)`:有界的终止等待。
- `onJobDone(listener)`:effect 作用域内的观察,具有精确所有者投递和监听器隔离。
- `events.subscribe(filter, listener)`:effect 作用域内对注册、进度、输出、结算与移除的观察,按所有者或所有者 scope 过滤,具有监听器隔离。
- `attachController(name)`:任务控制器可用性防线。
`wait` 在任务完成时返回终止快照,在等待超时时返回当前快照。中止一次等待只取消该次等待。如果结算已经将终止投递分配给该等待方,终止快照仍然优先。等待方在中止时同步注销,因此同一 tick 内发生结算时,不会代表一个实际未收到任何内容的读取方压制完成通知。
@@ -81,7 +81,7 @@ job id 在运行时全局可见且可预测,因此注册表会授权每次访
系统提示词要求模型保留 job id、在后台工作运行时继续处理独立工作而非忙轮询或重复启动同一任务、在给出最终答案前收集相关任务,并终止不再重要的工作。完成时,系统会向确切所有者的会话交付一条已记录的消息:繁忙的所有者走注入,空闲的所有者会被唤醒,其有界策略由[空闲所有者唤醒决策](../feature/2026-08-11-background-job-completion-wakes-an-idle-owner.zh.md)负责。
当读取或等待交付终止任务、尚在等待的等待方在结算时认领了投递,或模型显式终止任务时,运行时将终止任务标为 `reported`。已报告的任务不会注入冗余的完成通知。监听器失败会独立记录,不会阻止后续监听器,也不会被等待方或资源销毁过程等待。当快照携带 `outputLimitBytes` 时,`dsh-tool-jobs` 会保持 UTF-8 边界,并复用生产方已有的截断标记,而不会重复添加。读取会为状态后缀预留空间并保留输出尾部;完成通知会先为稳定的 `background job <id>` 前缀与 `job_output` 指令预留空间,再截断可变的 kind、label、status、detail,乃至截断标记本身,因此 PTY 的最小上限仍能标识需要收集的任务。任务控制器在策略有机会拒绝或短路分发之前,于最先执行的 pre-execute 监听器中解析调用方可见的生产方上限;随后通过任务定义最后一道的 `finalizeContent` 回调应用该上限,使规范化的工具错误、外层流水线失败与单文本策略结果都无法绕过该边界;经特意结构化的多块策略结果仍由策略拥有其形状与大小。
`dsh-tool-jobs` 持有投递台账:等待在开始时认领任务(任务比等待活得更久则撤回),`job_kill` 被接受时也认领,因此模型已经通过工具结果收到的结算不会再注入冗余的完成通知;teardown 结算与无主任务从不播报([seam 收敛](2026-09-03-jobs-seam-consolidation.zh.md))。监听器失败会独立记录,不会阻止后续监听器,也不会被等待方或资源销毁过程等待。当视图携带 `outputLimitBytes` 时,`dsh-tool-jobs` 会保持 UTF-8 边界,并复用生产方已有的截断标记,而不会重复添加。读取会为状态后缀预留空间并保留输出尾部;完成通知会先为稳定的 `background job <id>` 前缀与 `job_output` 指令预留空间,再截断可变的 kind、label、status、detail,乃至截断标记本身,因此 PTY 的最小上限仍能标识需要收集的任务。任务控制器在策略有机会拒绝或短路分发之前,于最先执行的 pre-execute 监听器中解析调用方可见的生产方上限;随后通过任务定义最后一道的 `finalizeContent` 回调应用该上限,使规范化的工具错误、外层流水线失败与单文本策略结果都无法绕过该边界;经特意结构化的多块策略结果仍由策略拥有其形状与大小。
## 生产方显式启用
@@ -105,7 +105,7 @@ bash seam 暴露 `resolve`、`run` 和 `start`。`start(spec)` 返回一个 `She
### 立即抽象任务运行时后端
当前 `JobStart.run()` 约定传入进程内回调与确切的 `Agent` 对象。持久化后端会改变身份、重启、所有权与观察语义,因此在引入之时注册表保持为单一具体服务,而非固化错误的边界。[任务注册表约定 Agent Note](../../archived/architecture/2026-07-26-job-registry-seam.md)后来在不改变这些进程内语义的前提下,将约定与进程内实现分离。
当前 `JobSpec.run()` 约定返回进程内钩子并经进程内的 `JobHandle` 推送输出,所有者也在进程内解析为存活的 `Agent`。持久化后端会改变身份、重启、所有权与观察语义,因此在引入之时注册表保持为单一具体服务,而非固化错误的边界。[任务注册表约定 Agent Note](../../archived/architecture/2026-07-26-job-registry-seam.md)后来在不改变这些进程内语义的前提下,将约定与进程内实现分离。
### 由消费方负责授权或清理事件
@@ -1,6 +1,43 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-06-21-bounded-llm-request-recovery.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-21-bounded-llm-request-recovery.md
2026-06-21-bounded-llm-request-recovery.md: b0a4ebb11b76c4c0068490c9924a88b80a8bc99f
2026-06-21-bounded-llm-request-recovery.zh.md: e8c25f9f6410dc12e34a0272e01e874431624c28
/agent-note-bounded-recovery-for-transient-llm-request-failures:
en: fb8e336ecd4bf571
zh: 23e40e4cb224163f
/agent-note-bounded-recovery-for-transient-llm-request-failures/problem:
en: 83a361538a092dae
zh: e8f33cb95d0d3e09
/agent-note-bounded-recovery-for-transient-llm-request-failures/decision:
en: a15c7c13f167e5ac
zh: 63bcc2ef60c2f344
/agent-note-bounded-recovery-for-transient-llm-request-failures/decision/preserve-failure-facts-without-embedding-policy:
en: 943322e6cdbfa440
zh: 82288531f6194ed2
/agent-note-bounded-recovery-for-transient-llm-request-failures/decision/put-retry-policy-on-the-existing-failed-step-extension-point:
en: ed4d295378d94a26
zh: 1fee5ef4947bac8f
/agent-note-bounded-recovery-for-transient-llm-request-failures/decision/make-one-layer-own-visible-attempts:
en: 57dbdd385f48bb3e
zh: 5e15463fae4be582
/agent-note-bounded-recovery-for-transient-llm-request-failures/decision/bound-stalled-streams-where-they-can-be-stopped:
en: f7369086e87192b9
zh: e2839ed8cc5c23b8
/agent-note-bounded-recovery-for-transient-llm-request-failures/decision/keep-attempts-separate-in-the-existing-log:
en: 8f57db4bfd6e1c22
zh: 67ac62217bb68570
/agent-note-bounded-recovery-for-transient-llm-request-failures/out-of-scope:
en: 985720529b56cda2
zh: 8a649bfa9cd8d93f
/agent-note-bounded-recovery-for-transient-llm-request-failures/alternatives-considered:
en: a6d0306740d470ee
zh: 700bd4b0aa58f3e8
/agent-note-bounded-recovery-for-transient-llm-request-failures/verification:
en: db343f335a9d7cad
zh: 49b8300de55dcfeb
/agent-note-bounded-recovery-for-transient-llm-request-failures/consequences:
en: 08659e8606455ada
zh: 862080f8df5f28ec
/agent-note-bounded-recovery-for-transient-llm-request-failures/related:
en: e85a6ad7387c881b
zh: bb8fb4173ffe613d
@@ -1,6 +1,25 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-06-21-mandatory-app-attribution-headers.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-21-mandatory-app-attribution-headers.md
2026-06-21-mandatory-app-attribution-headers.md: 9e0c029dc03c722512680a563c24e470128ee322
2026-06-21-mandatory-app-attribution-headers.zh.md: 1427daf8f6065ec2dee324075a8381a625d9e960
/agent-note-mandatory-user-agent-attribution-for-provider-requests:
en: 3f804e0236d13aba
zh: ef8b1b7b9c3d8376
/agent-note-mandatory-user-agent-attribution-for-provider-requests/problem:
en: f65797760084b93a
zh: d1fb36ef61a93003
/agent-note-mandatory-user-agent-attribution-for-provider-requests/investigation:
en: 5ea11f54f507ba64
zh: 22a83a0714a2fda3
/agent-note-mandatory-user-agent-attribution-for-provider-requests/decision:
en: b3e29e609e3f0966
zh: e3df0cb13df1cd5d
/agent-note-mandatory-user-agent-attribution-for-provider-requests/verification:
en: 567737dbccdb3a2a
zh: be92a5303247b889
/agent-note-mandatory-user-agent-attribution-for-provider-requests/alternatives-considered:
en: 016678c52ef64e51
zh: a113b57b9e9ddeb5
/agent-note-mandatory-user-agent-attribution-for-provider-requests/consequences:
en: a9010e68445a0008
zh: 1ec6104ab2865919
@@ -1,6 +1,76 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-06-24-web-capability-seam.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-24-web-capability-seam.md
2026-06-24-web-capability-seam.md: 8c6c088ea5d7345f9955892b2d6054cfae518bbd
2026-06-24-web-capability-seam.zh.md: 4921c4a4647d180dbb00e6493a19d38584f99bdc
/agent-note-web-capability-seam-stable-tools-over-multiple-providers:
en: ca120635fc40431c
zh: 6be7c5ae3c86cdcc
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/problem:
en: c8b932b02a4e1c80
zh: 96c466be1a521f3f
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/decision:
en: b57eb0f268033ff1
zh: 4143382a50181414
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/package-topology:
en: 5ea3ddfae82df181
zh: 2d05d95e51081696
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/ctx-web-contract:
en: b432f80a424c3e49
zh: faa26925fdd98387
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/provider-availability-and-selection:
en: dff78c46432311a1
zh: 58d5db4c3c85b886
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/search-request-and-result-schema:
en: ec3703b7e7c6b23d
zh: 325755e6e90092da
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/fetch-request-and-result-schema:
en: f734fdc57a6546c9
zh: 027c28cbc584a8c2
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/tool-consumer-behavior:
en: 62127883453dd79c
zh: 01503a8177a0ddab
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/errors:
en: 3440f2b34b93f4a1
zh: 57a8f784c7e26eff
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/testing:
en: 7f73699ac4459432
zh: c16be49ac50c34c8
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/alternatives-considered:
en: 6119e2aff3b6be5a
zh: 76136ef5249c23eb
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/alternatives-considered/let-each-provider-register-its-own-model-facing-tool:
en: e0d84a9b1b9c2123
zh: 9e116a7b96751563
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/alternatives-considered/put-provider-dispatch-directly-in-dsh-tool-web:
en: dc01d014d03b49d2
zh: b956b02f41c62682
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/alternatives-considered/split-search-and-fetch-into-two-seams-dsh-search-dsh-fetch:
en: 3fb72ba3e554f20a
zh: aff5f0add5773388
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/alternatives-considered/choose-the-first-registered-provider:
en: 1800706ea0f6b90b
zh: ced985b7657e2d7f
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/alternatives-considered/treat-firecrawl-exa-tavily-parallel-extraction-as-fetch:
en: fc22e6a8bfaeaa20
zh: 64032ea6ab61b836
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/alternatives-considered/mirror-claude-code-s-url-prompt-webfetch-shape:
en: 56a080de39e96056
zh: ae4d070aa7657503
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/alternatives-considered/validate-dns-and-then-call-an-ordinary-fetch:
en: aa6c1e7e6374a875
zh: 045c8af6cd44c3e1
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/alternatives-considered/block-private-looking-hostname-strings-without-pinning-resolved-addresses:
en: 3d906f3056733479
zh: d652723eb5372007
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/alternatives-considered/require-per-call-approval-before-public-fetches:
en: f8d1fc8e9c9659cf
zh: da5792520e35cba0
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/consequences:
en: 12fd20ba54818215
zh: c1ca000b13666701
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/deferred-work:
en: 48b7b8e7310cd56b
zh: d406cd6a8a649e58
/agent-note-web-capability-seam-stable-tools-over-multiple-providers/open-questions:
en: 63848c6ef9a6ab44
zh: 041b340802091e60
@@ -1,6 +1,43 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-06-26-file-context-as-event-gate.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-26-file-context-as-event-gate.md
2026-06-26-file-context-as-event-gate.md: 2943f11190533f84f3aebea0a25a88372d1204f1
2026-06-26-file-context-as-event-gate.zh.md: 053f4269b13c8583def01c144badd17b10a5a41a
/agent-note-make-dsh-fs-observation-policy-an-event-gate-plugin-not-a-method-interface:
en: 950d6bb4d83b39d8
zh: b40458972583b12b
/agent-note-make-dsh-fs-observation-policy-an-event-gate-plugin-not-a-method-interface/problem:
en: 765a679e88ecda60
zh: fccabc8ee516ea00
/agent-note-make-dsh-fs-observation-policy-an-event-gate-plugin-not-a-method-interface/decision:
en: eb8355d4b7a6c66b
zh: 712c6f932f26a0d3
/agent-note-make-dsh-fs-observation-policy-an-event-gate-plugin-not-a-method-interface/the-policy-is-enforced-by-provider-cas-not-by-dsh-fs-observation-policy-stat:
en: 2edc42b8210c995b
zh: 48f4354c9ec625ee
/agent-note-make-dsh-fs-observation-policy-an-event-gate-plugin-not-a-method-interface/provider-contract-change-the-version-guard-is-optional:
en: a282600f92568e07
zh: 3e6b2bec22c170c6
/agent-note-make-dsh-fs-observation-policy-an-event-gate-plugin-not-a-method-interface/event-vocabulary-owned-by-dsh-fs:
en: f57494c21daf90ea
zh: 1a1f8623dc0cbef3
/agent-note-make-dsh-fs-observation-policy-an-event-gate-plugin-not-a-method-interface/tool-contract-dsh-tool-fs:
en: c7f4457a83739520
zh: f2d55d018c7dab4f
/agent-note-make-dsh-fs-observation-policy-an-event-gate-plugin-not-a-method-interface/policy-plugin-contract-dsh-fs-observation-policy:
en: a239deb5dde631df
zh: 68cc6c954b247596
/agent-note-make-dsh-fs-observation-policy-an-event-gate-plugin-not-a-method-interface/bare-provider-behavior-no-dsh-fs-observation-policy:
en: 5aed537454b78157
zh: 9e8e7108be6a9537
/agent-note-make-dsh-fs-observation-policy-an-event-gate-plugin-not-a-method-interface/supersedes:
en: 5cc21706fd0f00ad
zh: 2b51da75a95f1777
/agent-note-make-dsh-fs-observation-policy-an-event-gate-plugin-not-a-method-interface/verification:
en: 1e3de2836160b4c2
zh: a8af173d161f0949
/agent-note-make-dsh-fs-observation-policy-an-event-gate-plugin-not-a-method-interface/alternatives-considered:
en: 768c09662714cf25
zh: cb641e8a77a2e32c
/agent-note-make-dsh-fs-observation-policy-an-event-gate-plugin-not-a-method-interface/consequences:
en: a1c00220fa5c6ce1
zh: 4691374274aa8df9
@@ -1,6 +1,16 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-06-30-event-domain-semantics.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-06-30-event-domain-semantics.md
2026-06-30-event-domain-semantics.md: 7e0aee220a62777ebe1d8f6a5018aba0f5fa20ee
2026-06-30-event-domain-semantics.zh.md: 14568c7a4660c42cecc47f094373d299380fa563
/agent-note-event-domain-semantics-session-is-the-fact-log-agent-is-the-live-event-channel:
en: e7cdaa7a6029c259
zh: ed13f8158ee0eaeb
/agent-note-event-domain-semantics-session-is-the-fact-log-agent-is-the-live-event-channel/problem:
en: 1222c2b55882b1e5
zh: f81f481f5eb9a684
/agent-note-event-domain-semantics-session-is-the-fact-log-agent-is-the-live-event-channel/decision:
en: ccc0fed9b7388112
zh: 3cc527b11affd941
/agent-note-event-domain-semantics-session-is-the-fact-log-agent-is-the-live-event-channel/consequences:
en: e0c5aa60322e67a1
zh: 7495550f0c863eda
@@ -1,6 +1,37 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-07-02-tool-render-intent-union.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-02-tool-render-intent-union.md
2026-07-02-tool-render-intent-union.md: 52626d3d9200146df95aee7836d37bbaf7e6a9ec
2026-07-02-tool-render-intent-union.zh.md: bc91b89c53c3c43b6c483dc0d4876a00f5a936b7
/agent-note-tagged-render-intent-union-for-tool-call-presentation:
en: 599dd6f91059580e
zh: b6a46767bb4198e6
/agent-note-tagged-render-intent-union-for-tool-call-presentation/problem:
en: 3a4b92dca651b979
zh: 6b10ce7ba3681180
/agent-note-tagged-render-intent-union-for-tool-call-presentation/decision:
en: aff6d789bde63f17
zh: 73782526b46a3ee5
/agent-note-tagged-render-intent-union-for-tool-call-presentation/decision/why-a-tagged-union-beats-the-field-bag:
en: ed7b15039050e65e
zh: a719562b5fcdbd4e
/agent-note-tagged-render-intent-union-for-tool-call-presentation/decision/producer-mapping:
en: c87f22a29caef002
zh: 7bfd28c1df80b8a1
/agent-note-tagged-render-intent-union-for-tool-call-presentation/decision/terminal-fallback-ownership:
en: 0bb2f60726afc4d9
zh: 60040141447b4a2e
/agent-note-tagged-render-intent-union-for-tool-call-presentation/decision/purity-preserved:
en: 1ba6a480967c524d
zh: 90535e843f346bcf
/agent-note-tagged-render-intent-union-for-tool-call-presentation/alternatives-considered:
en: 2cd4801f3162227b
zh: 76afaa23bc2b9eb0
/agent-note-tagged-render-intent-union-for-tool-call-presentation/consequences:
en: 81d8366d826285c2
zh: b437b862794c146e
/agent-note-tagged-render-intent-union-for-tool-call-presentation/non-goals:
en: e9d60967a9b3f9bd
zh: 6dfa9ac30d847879
/agent-note-tagged-render-intent-union-for-tool-call-presentation/related:
en: fe27f777b3728fa4
zh: 4b648dbf731ace00
@@ -1,6 +1,40 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-07-05-prompt-variables-and-tool-guidance-ownership.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-05-prompt-variables-and-tool-guidance-ownership.md
2026-07-05-prompt-variables-and-tool-guidance-ownership.md: 35bb7c6fabc85ae6f93bdbb67e13910eea627ca3
2026-07-05-prompt-variables-and-tool-guidance-ownership.zh.md: 53d69cf45c02f6534334561b626d2c2ae6087c05
/agent-note-prompt-variables-and-tool-guidance-ownership:
en: 6f8b4a9d26ab3e50
zh: 9741e5718e647f0a
/agent-note-prompt-variables-and-tool-guidance-ownership/problem:
en: 8ccef8fbd9260dfe
zh: 106b2bafe969c676
/agent-note-prompt-variables-and-tool-guidance-ownership/decision:
en: c551d888282d9c73
zh: 889b5ca3cdf25aff
/agent-note-prompt-variables-and-tool-guidance-ownership/decision/assemble-context:
en: 46e67248692e333a
zh: 51c5f2c6152c94d7
/agent-note-prompt-variables-and-tool-guidance-ownership/decision/prompt-variables:
en: 04b623ed2879fdf1
zh: c111be62834fda93
/agent-note-prompt-variables-and-tool-guidance-ownership/decision/persona-as-the-order-0-section:
en: c2d32c0ac5d28759
zh: 59cd252ba6da6e59
/agent-note-prompt-variables-and-tool-guidance-ownership/decision/tool-guidance-ownership:
en: 308c0d2ef4e41f56
zh: d38f84a517da20df
/agent-note-prompt-variables-and-tool-guidance-ownership/decision/the-subagent-conversation-history-descriptor:
en: 1cb9644f22918749
zh: fb9fdee133159ab2
/agent-note-prompt-variables-and-tool-guidance-ownership/alternatives-considered:
en: 9a114359d2e8988b
zh: ce39453408b2af7f
/agent-note-prompt-variables-and-tool-guidance-ownership/out-of-scope:
en: bbfecc70d0b457fe
zh: 7f207a37a86484f4
/agent-note-prompt-variables-and-tool-guidance-ownership/shipped-invariants:
en: 31ba63101fca5790
zh: af4ceefab2033142
/agent-note-prompt-variables-and-tool-guidance-ownership/consequences:
en: 993f17bf35f6a2e0
zh: acb429176f0eebcc
@@ -26,7 +26,7 @@ The assembled system prompt had four defects, all of one family: facts the harne
### Prompt variables
Plugins register `{{name}}` values through `ctx.systemPrompt.variable(name, provider)`. Assembly resolves them into the waterfall-visible variable map. Rendering rejects unknown own-property references, registered providers that return `undefined`, malformed complete references, and unbalanced references that still contain a closing `}}`; a lone unmatched `{{` remains prose, and substituted values are not rescanned. Registration rejects invalid or duplicate variable names, and section names are unique.
Plugins register `{{name}}` values through `ctx.systemPrompt.variable(name, provider)`. Assembly resolves them into the waterfall-visible variable map. Rendering rejects unknown own-property references, registered providers that return `undefined`, malformed complete references, and unbalanced references that still contain a closing `}}`; a lone unmatched `{{` remains prose, and substituted values are not rescanned. Registration rejects invalid or duplicate variable names, and section names are unique. Sections may set `interpolate: false` to preserve generated documents literally; `tools:sdk` does so because tool descriptions and schemas may document their own `{{…}}` syntax.
`dsh-agent-loop` registers the two built-ins, both pure projections of the context agent: `model` (= `options.model`) and `cwd` (= `session.header.cwd`). The example personas write `powered by the {{model}} model` — the model name is stated once, in the `model:` config key. `{{cwd}}` is demonstrated in the ACP example only: every ACP session carries the client's cwd, while config-pre-created stdio agents have none (a persona claiming `{{cwd}}` there fails the turn — by design). The variables stay on the loop plugin (unlike the sections below): they are runtime facts of the agents THIS loop drives, and a replacement loop supplies its own.
@@ -47,7 +47,7 @@ Per-tool semantics and selection guidance live in tool descriptions. Prompt sect
- **The loop composes an identity line itself** — hardcodes model-facing prose in the one package that must stay thin ("plugins, not loop changes"), and outside the section pipeline it would be a second composition path. (The identity DOES ship as a code literal — but as an ordinary section registered by `dsh-system-prompt`, whose `system-prompt/assemble` waterfall remains the escape valve for a deployment that must drop it.)
- **Inject the model name via the `agent/request` waterfall** — prompt text would be composed in two places and the earlier rendered persona could disagree with the final routed header. The request plugin that owns late routing must also own any earlier prompt claim about that model.
- **Hand-write the model name in each persona** — duplicates the `model:` key one line above and silently lies after a config edit; the exact disease this decision cures.
- **Lenient interpolation (leave unknown refs verbatim, or substitute empty)** — a typo ships `{{modle}}` (or a hole) to the model and nobody notices until transcript review.
- **Lenient interpolation (leave unknown refs verbatim, or substitute empty)** — a typo ships `{{modle}}` (or a hole) to the model and nobody notices until transcript review. Leaving only unknown names unchanged would still substitute registered names inside tool documentation.
- **Per-instance subagent wording in config** — returns model-facing prose to every deployment × instance, reviving the hand-written-guidance-in-leaf-YAML drift. **Keying wording off the provider NAME** — `providerName` is itself config, so a renamed provider silently gets the wrong words.
- **Resolving the provider at `apply` time (a load-order requirement)** and **section-only subagent wording (lazily resolved at assemble)** — the alternatives to the provider-lifecycle events; both rejected in [the provider-lifecycle-events Agent Note](../../archived/architecture/2026-07-05-subagent-provider-lifecycle-events.md).
@@ -60,7 +60,7 @@ Per-tool semantics and selection guidance live in tool descriptions. Prompt sect
- The tui-agent prompt renders identity, persona with the interpolated model, then fs/shell/web guidance through one assembly path.
- Fork and fresh subagent descriptions reflect whether the provider inherits completed conversation turns; the tool appears, disappears, and is reworded with provider lifecycle changes.
- Unknown, valueless, malformed, or unbalanced variable references name the section and throw; duplicate section, variable, and tool registrations also throw.
- In interpolated sections, unknown, valueless, malformed, or unbalanced variable references name the section and throw; duplicate section, variable, and tool registrations also throw.
- Snapshot replay is prompt-independent: it keys recorded chunk streams by turn and step without comparing the outgoing request.
## Consequences
@@ -69,4 +69,4 @@ Per-tool semantics and selection guidance live in tool descriptions. Prompt sect
- `{{model}}` reflects `AgentOptions.model` at assembly time. A plugin that switches models in the `agent/request` waterfall makes the prompt's claim stale for that step, and one that SUPPLIES the model there (options.model unset — the loop's documented fallback) leaves the variable valueless at render, failing a `{{model}}` persona before the waterfall runs. Both have the same remedy, and it is the ownership rule itself: the plugin that owns the late-bound model fact states it early on the `system-prompt/assemble` waterfall (`assembly.variables['model'] = …`) — one owner, both statements; a loop test pins the supply path end-to-end. Accepted.
- While a bound provider is absent (not yet activated, unloaded, mid-HMR-reload), the subagent tool does not exist and a model request in that window simply lacks it. That is the honest state — the alternative was a registered tool whose description or execution could not be trusted.
- Strictness means a persona can fail a turn at render (e.g. `{{cwd}}` on a cwd-less session). The failure is contained — the turn ends `error`, the loop survives — and it is an authoring error we WANT loud.
- No escape syntax for a literal `{{name}}` in prompt prose yet; add one if a real prompt ever needs it.
- Inline escapes remain unsupported in interpolated text; literal sections need no escaping. PTC unit tests cover both modes and runtime languages, and the recorded `ptc-turn` scenario preserves tool-template examples in the model-visible prompt.
@@ -26,7 +26,7 @@ Status: implemented
### 提示词变量
插件通过 `ctx.systemPrompt.variable(name, provider)` 注册 `{{name}}` 值。组装过程将它们解析到 waterfall 可见的变量映射中。渲染阶段拒绝以下情况:引用未知的自有属性、已注册的提供方返回 `undefined`、格式错误的完整引用、以及仍包含闭合 `}}` 的不平衡引用;孤立的未匹配 `{{` 保留为行文,替换后的值不会被重新扫描。注册阶段拒绝无效或重复的变量名,section 名称也必须唯一。
插件通过 `ctx.systemPrompt.variable(name, provider)` 注册 `{{name}}` 值。组装过程将它们解析到 waterfall 可见的变量映射中。渲染阶段拒绝以下情况:引用未知的自有属性、已注册的提供方返回 `undefined`、格式错误的完整引用、以及仍包含闭合 `}}` 的不平衡引用;孤立的未匹配 `{{` 保留为行文,替换后的值不会被重新扫描。注册阶段拒绝无效或重复的变量名,section 名称也必须唯一。段可设置 `interpolate: false` 来原样保留生成的文档;`tools:sdk` 使用此设置,因为工具描述和 schema 可能会介绍自身的 `{{…}}` 语法。
`dsh-agent-loop` 注册两个内置变量,均为上下文 agent 的纯投影:`model`(= `options.model`)和 `cwd`(= `session.header.cwd`)。示例 persona 写 `powered by the {{model}} model`——模型名称只在 `model:` 配置键中声明一次。`{{cwd}}` 仅在 ACP 示例中演示:每个 ACP 会话携带客户端的 cwd,而配置预创建的 stdio agent 没有 cwd(在那里声称 `{{cwd}}` 的 persona 会导致该轮次失败——这是有意为之)。变量留在 loop 插件上(不同于下面的 section):它们是本循环驱动的 agent 的运行时事实,替换循环自行提供自己的变量。
@@ -47,7 +47,7 @@ Status: implemented
- **循环自行组合一行 identity 文本**:在必须保持精简的那个包(「用插件,不改循环」)中硬编码面向模型的行文,且在 section 流水线之外构成第二条组合路径。(identity 确实以代码字面量交付——但作为 `dsh-system-prompt` 注册的普通 section,其 `system-prompt/assemble` waterfall 仍是部署需要移除它时的逃生阀。)
- **通过 `agent/request` waterfall 注入模型名称**:提示词文本会在两处组合,更早渲染的 persona 也可能与最终已路由 header 不一致。拥有延迟路由的请求插件还必须拥有该模型在提示词中更早出现的声明。
- **在每个 persona 中手写模型名称**:与上方一行的 `model:` 键重复,配置修改后静默失实;正是本决策要治愈的病症。
- **宽松插值(未知引用保留原样或替换为空)**:一个拼写错误 `{{modle}}`(或一个空洞)会被发送给模型,直到 transcript(文本记录)审查时才会被发现。
- **宽松插值(未知引用保留原样或替换为空)**:一个拼写错误 `{{modle}}`(或一个空洞)会被发送给模型,直到 transcript(文本记录)审查时才会被发现。仅保留未知名称仍会替换工具文档中的已注册名称。
- **在配置中为每个 subagent 实例编写措辞**:面向模型的行文回到每个部署 × 实例中,重蹈在 leaf YAML 中手写指导的漂移。**根据提供方名称选择措辞**:`providerName` 本身是配置,重命名提供方后会静默获得错误的措辞。
- **在 `apply` 时解析提供方(加载顺序要求)**与**仅用 section 承载 subagent 措辞(在 assemble 时惰性解析)**:提供方生命周期事件的替代方案;两者均在[提供方生命周期事件 Agent Note](../../archived/architecture/2026-07-05-subagent-provider-lifecycle-events.md)中被否决。
@@ -60,7 +60,7 @@ Status: implemented
- tui-agent 的提示词通过一条组装路径依次渲染 identity、带插值模型名的 persona,然后是 fs/shell/web 指导。
- fork 和 fresh subagent 的描述反映提供方是否继承已完成的对话轮次;工具随提供方生命周期变化而出现、消失和重新措辞。
- 未知、无值、格式错误或不平衡的变量引用会指明 section 名称并抛出异常;重复的 section、变量和工具注册同样抛出异常。
- 在启用插值的段中,未知、无值、格式错误或不平衡的变量引用会指明 section 名称并抛出异常;重复的 section、变量和工具注册同样抛出异常。
- 快照回放与提示词无关:它按轮次和步骤索引已记录的分片流,不比较发出的请求。
## 后果
@@ -69,4 +69,4 @@ Status: implemented
- `{{model}}` 在组装时反映 `AgentOptions.model`。如果一个插件在 `agent/request` waterfall 中切换模型,提示词对该步骤的声明就会过时;如果一个插件在那里提供模型(options.model 未设置——循环文档中记载的回退路径),变量在渲染时无值,包含 `{{model}}` 的 persona 会在 waterfall 运行前失败。两者的补救方式相同,就是归属规则本身:拥有延迟绑定模型事实的插件在 `system-prompt/assemble` waterfall 上提前声明它(`assembly.variables['model'] = …`)——一个归属方,两处声明;一个循环测试端到端固定了 supply 路径。已接受。
- 当一个已绑定的提供方不存在时(尚未激活、已卸载、HMR(热模块替换)重载中),subagent 工具不存在,该窗口内的模型请求中不会包含它。这是诚实的状态——替代方案是注册一个 description 或执行都不可信的工具。
- 严格性意味着 persona 可能在渲染时导致轮次失败(例如在无 cwd 的会话上使用 `{{cwd}}`)。失败是受控的——该轮次以 `error` 结束,循环存活——且这是一个我们希望明确暴露的撰写错误。
- 目前没有在提示词行文中转义字面 `{{name}}` 的语法;如果真实提示词确实需要,再行添加。
- 插值文本仍不支持行内转义;字面文本段无需转义。PTC 单元测试覆盖两种模式和运行时语言,录制的 `ptc-turn` 场景在模型可见的提示词中保留工具模板示例。
@@ -1,6 +1,28 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-07-05-reconstructable-requests.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-05-reconstructable-requests.md
2026-07-05-reconstructable-requests.md: 2f88675a75a72e7fbf105dfbf4f337a4dd80948a
2026-07-05-reconstructable-requests.zh.md: 90008502a6651e38c142b7fb88052c05d46dea76
/agent-note-every-llm-request-is-reconstructable-from-the-session-log:
en: 115dd45f40b0d7d8
zh: 536b5a0399e7d06a
/agent-note-every-llm-request-is-reconstructable-from-the-session-log/problem:
en: f8f31da854a5fe2e
zh: ef88856c2c7bdfb8
/agent-note-every-llm-request-is-reconstructable-from-the-session-log/decision:
en: a15c7c13f167e5ac
zh: 63bcc2ef60c2f344
/agent-note-every-llm-request-is-reconstructable-from-the-session-log/decision/the-principle:
en: 6da15cf986d59a91
zh: 40282908b54295f9
/agent-note-every-llm-request-is-reconstructable-from-the-session-log/decision/the-mechanism:
en: 7d86e5058dbab2fb
zh: 9a97481325c8eded
/agent-note-every-llm-request-is-reconstructable-from-the-session-log/decision/the-minicode-shape-adopted-with-the-event-log-as-the-source:
en: e5f2ffaa3d7de0cc
zh: 5ba6b36787a0e189
/agent-note-every-llm-request-is-reconstructable-from-the-session-log/alternatives-considered:
en: 96f19ecf38fae991
zh: 9692252135ef3476
/agent-note-every-llm-request-is-reconstructable-from-the-session-log/consequences:
en: 0d2e97bc421e67cc
zh: 0a000a69b8cc4b4e
@@ -22,9 +22,9 @@ Prefix-cache stability is corollary #1, not the headline: an append-only log pro
**Messages.** `Session.deriveMessages()` is cached: each surface entry is projected exactly once, when first seen, through the public per-event function `deriveEventMessage(event)`; a surface rewrite (a compaction `replace` — `SurfaceManager.replaceGeneration`) rebuilds. Callers get a fresh array per call over shared, deep-frozen messages: mutating logged history through a projection is unrepresentable (it throws), replacing the old clone-per-call isolation. External reconstructors fold the same public function over a log prefix, so no two paths can disagree.
`EpochHeader` records the request's non-history state: call config and tool schemas. Writers omit `tools: []` and `adapterDefaults: {}`; current acceptance rejects those fields and any `header.system`, rather than repairing them. Whitespace-only system-message content, `config.stop: []`, and nested extensions remain intact. The [V3 canonical-envelope decision](2026-09-06-v3-canonical-session-envelopes.md) owns historical conversion. The rendered system prompt is derived history — the `system/message` event at surface node 0, per the [surface-node Agent Note](2026-09-02-system-prompt-as-surface-node.md) — so a prompt change is a surface replacement rather than a header change. Adapter-supplied effort and token defaults retain their `adapterDefaults` provenance; a Web model selection restored from the log omits an adapter-owned effort so the next resolution cannot reclassify the same effective config as an explicit selection and a false change. `request/header` always writes a full snapshot: the first loop instance uses reason `initial`, later instances use `resume`, an in-instance change uses `change`, and an unchanged envelope beginning an explicitly declared message series or following a surface replacement uses `series`. A `change` snapshot carries `startsSeries: true` when the changed request also starts a series, preserving the two independent facts without a duplicate header. Ordinary append-only later Turns, further same-series Steps, and retries inherit the latest snapshot. `foldRequestHeader` selects the latest snapshot. Legacy `request/header-delta` events and the removed `fallback` reason are rejected when appended or loaded.
`EpochHeader` records the request's non-history state: call config and tool schemas. Writers omit `tools: []` and `adapterDefaults: {}`; current acceptance rejects those fields and any `header.system`, rather than repairing them. Whitespace-only system-message content, `config.stop: []`, and nested extensions remain intact. The [V3 canonical-envelope decision](2026-09-06-v3-canonical-session-envelopes.md) owns historical conversion. The rendered system prompt is derived history — the `system/message` event at surface node 0, per the [surface-node Agent Note](2026-09-02-system-prompt-as-surface-node.md) — so a prompt change is a surface replacement rather than a header change. Adapter-supplied effort and token defaults retain their `adapterDefaults` ownership; a Web model selection restored from the log omits an adapter-owned effort so the next resolution cannot reclassify the same effective config as an explicit selection and a false change. `request/header` always writes a full snapshot: the first loop instance uses reason `initial`, later instances use `resume`, an in-instance change uses `change`, and an unchanged envelope beginning an explicitly declared message series or following a surface replacement uses `series`. A `change` snapshot carries `startsSeries: true` when the changed request also starts a series, preserving the two independent facts without a duplicate header. Ordinary append-only later Turns, further same-series Steps, and retries inherit the latest snapshot. `foldRequestHeader` selects the latest snapshot. Legacy `request/header-delta` events and the removed `fallback` reason are rejected when appended or loaded.
Each proposed step first claims its inbox batch, assembles the system prompt and tools, projects the rendered prompt against the surviving `system/message` node, and runs `agent/pre-step`. Rejection opens no step; enter opens `step/start`, commits a changed prompt as the `system/message` append or node-0 replacement, records the final message batch as `user/message` events, and may use `startsRequestSeries: true` to declare a distinct series. `agent/request` may replace only the frozen call-config seed. The loop records the owed initial, resume, change, or series full snapshot, builds `GenerateOptions` from derived messages (system message first) and that header with no `system` field, and freezes it while leaving `AbortSignal` live. The [request-freeze provenance decision](../simplification/2026-09-06-agent-request-freeze-provenance.md) owns reuse of completed message freezes and per-request local header freezing. The first call config starts from explicit `AgentOptions`, preserving fork overrides and resume reconfiguration; later calls start from the folded header.
Each proposed step first claims its inbox batch, assembles the system prompt and tools, projects the rendered prompt against the surviving `system/message` node, and runs `agent/pre-step`. Rejection opens no step; enter opens `step/start`, commits a changed prompt as the `system/message` append or node-0 replacement, records the final message batch as `user/message` events, and may use `startsRequestSeries: true` to declare a distinct series. `agent/request` may replace only the frozen call-config seed. The loop records the owed initial, resume, change, or series full snapshot, builds `GenerateOptions` from derived messages (system message first) and that header with no `system` field, and freezes it while leaving `AbortSignal` live. The [request-freeze evidence decision](../simplification/2026-09-06-agent-request-freeze-evidence.md) owns reuse of completed message freezes and per-request local header freezing. The first call config starts from explicit `AgentOptions`, preserving fork overrides and resume reconfiguration; later calls start from the folded header.
**The open step is the reconstruction boundary.** Its entered `user/message` batch and any newly written `request/header` precede request dispatch. Injection after the atomic claim joins a later request, while a listener that must affect this request returns messages through `agent/pre-step`. Header reconstruction selects the step's `request/header`, or carries the prior snapshot when no new header is written.
@@ -24,7 +24,7 @@ Status: implemented
`EpochHeader` 记录请求的非历史状态:调用配置和工具 schema。写入方省略 `tools: []` 与 `adapterDefaults: {}`;当前接纳拒绝这些字段以及任何 `header.system`,而不修复它们。仅含空白的系统消息内容、`config.stop: []` 与嵌套扩展保持原样。[V3 规范信封决策](2026-09-06-v3-canonical-session-envelopes.zh.md)负责历史转换。渲染后的系统提示词是派生历史——surface 第 0 号节点上的 `system/message` 事件,见[surface 节点 Agent Note](2026-09-02-system-prompt-as-surface-node.zh.md)——因此提示词变更是 surface 替换而不是 header 变更。适配器提供的推理强度与 token 默认值会保留其 `adapterDefaults` 来源信息;Web 从日志恢复模型选择时会省略适配器持有的推理强度,因此下一次解析不会把相同的有效配置重新归类为显式选择并产生虚假变更。`request/header` 始终写入完整快照:首个循环实例使用 reason `initial`,后续实例使用 `resume`,实例内变更使用 `change`,内容未变的封装显式开启消息序列或跟随表层替换时使用 `series`。如果发生变化的请求同时开启序列,`change` 快照会携带 `startsSeries: true`,无需重复 header 即可保留这两个独立事实。普通的仅追加后续 Turn、同一序列内后续的 Step 与重试沿用最新快照。`foldRequestHeader` 选择最新快照。旧的 `request/header-delta` 事件和已移除的 `fallback` reason 在追加或加载时都会被拒绝。
每个拟议步骤先领取其 inbox 批次,组装系统提示词与工具,把渲染后的提示词与存活的 `system/message` 节点比对投影,再运行 `agent/pre-step`。reject 不打开步骤;enter 打开 `step/start`,把变化的提示词作为 `system/message` 追加或第 0 号节点替换提交,把最终消息批次记录为 `user/message` 事件,并可使用 `startsRequestSeries: true` 声明独立序列。`agent/request` 只能替换冻结的调用配置种子。循环记录所需的 initial、resume、change 或 series 完整快照,从派生消息(系统消息在先)与该不含 `system` 字段的 header 构建 `GenerateOptions`,冻结请求但保持 `AbortSignal` 活跃。[请求冻结来源证明决策](../simplification/2026-09-06-agent-request-freeze-provenance.zh.md)拥有消息完整冻结的复用规则和每次请求的本地 header 冻结规则。首次调用配置从显式的 `AgentOptions` 出发,保留 fork 覆盖和恢复重配置;后续调用从折叠后的 header 出发。
每个拟议步骤先领取其 inbox 批次,组装系统提示词与工具,把渲染后的提示词与存活的 `system/message` 节点比对投影,再运行 `agent/pre-step`。reject 不打开步骤;enter 打开 `step/start`,把变化的提示词作为 `system/message` 追加或第 0 号节点替换提交,把最终消息批次记录为 `user/message` 事件,并可使用 `startsRequestSeries: true` 声明独立序列。`agent/request` 只能替换冻结的调用配置种子。循环记录所需的 initial、resume、change 或 series 完整快照,从派生消息(系统消息在先)与该不含 `system` 字段的 header 构建 `GenerateOptions`,冻结请求但保持 `AbortSignal` 活跃。[请求冻结证据决策](../simplification/2026-09-06-agent-request-freeze-evidence.zh.md)拥有消息完整冻结的复用规则和每次请求的本地 header 冻结规则。首次调用配置从显式的 `AgentOptions` 出发,保留 fork 覆盖和恢复重配置;后续调用从折叠后的 header 出发。
**已打开步骤是重建边界。** 进入步骤的 `user/message` 批次与任何新写入的 `request/header` 都位于请求分派之前。原子领取后发生的注入加入后续请求;必须影响本次请求的监听器则通过 `agent/pre-step` 返回消息。header 重建选择该步骤的 `request/header`,或在无新 header 写入时沿用前一个快照。
@@ -1,6 +1,19 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-07-05-windows-jsonl-durable-publish.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-05-windows-jsonl-durable-publish.md
2026-07-05-windows-jsonl-durable-publish.md: 546cde6086f3c84e22b4d4de144a48bb3425cd4e
2026-07-05-windows-jsonl-durable-publish.zh.md: b99032e9d7e72e2028f39c5af91659278fd81343
/agent-note-windows-native-durable-jsonl-publication:
en: db7fe80708911f2f
zh: 42c6639defea2bde
/agent-note-windows-native-durable-jsonl-publication/problem:
en: dcc3c6238131d302
zh: 4d4e8513a4069af3
/agent-note-windows-native-durable-jsonl-publication/decision:
en: 385565b209f1e739
zh: 0eab0997c49a3c33
/agent-note-windows-native-durable-jsonl-publication/alternatives-considered:
en: 83d5bf5781f89e29
zh: 068835993789e09d
/agent-note-windows-native-durable-jsonl-publication/consequences:
en: 4be0ad03a334c257
zh: 95d473ed5b94e270
@@ -1,6 +1,28 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-07-06-timeout-deadline-library.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-06-timeout-deadline-library.md
2026-07-06-timeout-deadline-library.md: 6f726938731f18386105ff1180c79fef981c95bf
2026-07-06-timeout-deadline-library.zh.md: 48bd7b4b91efd0045c03e3e1e1e9e37656b4dcf6
/agent-note-a-shared-timeout-deadline-primitive-with-hard-kill-left-to-each-capability:
en: 4a9921fef5e65cc8
zh: 672cd27d68310cb1
/agent-note-a-shared-timeout-deadline-primitive-with-hard-kill-left-to-each-capability/problem:
en: 110ff68b35bd43cb
zh: f1cea15fb29a9ae9
/agent-note-a-shared-timeout-deadline-primitive-with-hard-kill-left-to-each-capability/decision:
en: 18645d82d9e40107
zh: 73e510f1ed1106e6
/agent-note-a-shared-timeout-deadline-primitive-with-hard-kill-left-to-each-capability/decision/the-library-api:
en: c62681afef60a0db
zh: 69827b4b3165b3da
/agent-note-a-shared-timeout-deadline-primitive-with-hard-kill-left-to-each-capability/decision/the-division-of-labor:
en: 263c8e17bbc87ba0
zh: d75a74f47713e79f
/agent-note-a-shared-timeout-deadline-primitive-with-hard-kill-left-to-each-capability/decision/how-each-capability-consumes-it:
en: 333eab4967d753ec
zh: dd7537bb82cc717f
/agent-note-a-shared-timeout-deadline-primitive-with-hard-kill-left-to-each-capability/consequences:
en: 832f4dbd93a47f94
zh: 65ada43f9f23a39b
/agent-note-a-shared-timeout-deadline-primitive-with-hard-kill-left-to-each-capability/alternatives-considered:
en: 7b3445622becbd36
zh: bb358acf2ff28e26
@@ -1,6 +1,28 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-07-07-tool-call-timeout-policy.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-07-tool-call-timeout-policy.md
2026-07-07-tool-call-timeout-policy.md: 60d82c1d591f0a32350b1a21ed74e148c4c93576
2026-07-07-tool-call-timeout-policy.zh.md: 49ca7f397d15c1a351cba4837d4d531e54120ea6
/agent-note-tool-call-timeout-policy-as-a-plugin:
en: 46fa7d1eac4fe061
zh: 7a62f8f7b1c66722
/agent-note-tool-call-timeout-policy-as-a-plugin/problem:
en: b5fffa80b58fb184
zh: aadf28f95924b1ad
/agent-note-tool-call-timeout-policy-as-a-plugin/decision:
en: 04889f664ab7657d
zh: 2af5913f5e9c1927
/agent-note-tool-call-timeout-policy-as-a-plugin/decision/the-tools-execute-around-dispatch-extension-point:
en: 8c3b46fa8a48a863
zh: 662eb09bb7542be8
/agent-note-tool-call-timeout-policy-as-a-plugin/decision/the-timeout-policy-plugin:
en: 96f5932514a33e41
zh: 5951d9451ccef1bf
/agent-note-tool-call-timeout-policy-as-a-plugin/decision/existing-tool-adaptation:
en: 43add9b1f723ce89
zh: f3ee56f97faa2e60
/agent-note-tool-call-timeout-policy-as-a-plugin/alternatives-considered:
en: dc6da8743b4266fb
zh: 5c28667d952b230a
/agent-note-tool-call-timeout-policy-as-a-plugin/consequences:
en: f7429a5c1fe6b6a1
zh: 748401be79f89b05
@@ -1,6 +1,46 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-07-08-agent-scope-contexts.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-08-agent-scope-contexts.md
2026-07-08-agent-scope-contexts.md: 45e635b7bc3138d4e90a25a06ff23b3b57a9415e
2026-07-08-agent-scope-contexts.zh.md: aac860734e744843c3b9e7d55e5bc7a150763090
/agent-note-the-agent-is-a-registration-scope:
en: f767894b8308f1a0
zh: 4ff0aead6ee4e27b
/agent-note-the-agent-is-a-registration-scope/problem:
en: 87634b46a5642328
zh: 2adce8b041626437
/agent-note-the-agent-is-a-registration-scope/decision:
en: ac58e62f780b0879
zh: 6b077226de04a8fa
/agent-note-the-agent-is-a-registration-scope/decision/registration-origin-chooses-visibility-and-cleanup:
en: 1ec8e54543272e1b
zh: b5b1695a805574a2
/agent-note-the-agent-is-a-registration-scope/decision/the-operation-chooses-the-view:
en: 2e236d399efdc0b2
zh: 00a7ba20f90862c6
/agent-note-the-agent-is-a-registration-scope/decision/scoped-events-keep-routing-separate-from-event-data:
en: df5f5e4c1de44474
zh: d851c02959d02380
/agent-note-the-agent-is-a-registration-scope/decision/creation-publishes-last-and-disposal-revokes-last:
en: f46920b4945e0e6d
zh: 870a157205883144
/agent-note-the-agent-is-a-registration-scope/security-and-authority-are-non-goals:
en: 5ffc5a8f65ce7dfe
zh: 3362f236356a8033
/agent-note-the-agent-is-a-registration-scope/alternatives-considered:
en: bf43310538280f62
zh: e4940ff47c5d47b5
/agent-note-the-agent-is-a-registration-scope/alternatives-considered/pass-an-agent-option-to-every-registration:
en: 37e7487b1f1eb87a
zh: eeddbaf21eee7ebc
/agent-note-the-agent-is-a-registration-scope/alternatives-considered/filter-events-while-keeping-registries-global:
en: 7eb2628d51ea9ed0
zh: e58f05faf0e95712
/agent-note-the-agent-is-a-registration-scope/alternatives-considered/create-one-service-graph-per-agent:
en: 2fd1c41c3d1bc6ca
zh: cffad44a2c69330e
/agent-note-the-agent-is-a-registration-scope/alternatives-considered/inherit-parent-registration-scopes:
en: 01f989446aab1cf1
zh: 8f5c9018b7b84c94
/agent-note-the-agent-is-a-registration-scope/consequences:
en: 65c8f47d1607b276
zh: 950b86b4682f7a0e
@@ -1,6 +1,40 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-07-08-tool-output-spill-files.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-08-tool-output-spill-files.md
2026-07-08-tool-output-spill-files.md: a80b6cdcb0e731a687d511d38ea288a68a298173
2026-07-08-tool-output-spill-files.zh.md: a995eafc7878b342a2164c5116da1f43ada791a5
/agent-note-tool-output-spill-policy:
en: 06b99197145a4080
zh: 698a61dcd2385985
/agent-note-tool-output-spill-policy/problem:
en: 858cbb874e213697
zh: 1693b618886ac42d
/agent-note-tool-output-spill-policy/decision:
en: 89536b0d2d7b4c92
zh: 341240f445885549
/agent-note-tool-output-spill-policy/decision/spill-seam:
en: 1e92bc9a0548def9
zh: c99cf6878981ba71
/agent-note-tool-output-spill-policy/decision/spill-policy:
en: 3c49c0246188c513
zh: 4b6749c30726903d
/agent-note-tool-output-spill-policy/showcase-web-fetch:
en: d5c334b50f458925
zh: 7631307b5d9fbc55
/agent-note-tool-output-spill-policy/relationship-to-retention-and-early-spill:
en: 7314ba8b0a03c0d9
zh: 8429f79ff3a7bd1f
/agent-note-tool-output-spill-policy/non-goals:
en: f82b5399ecddd8a1
zh: 9675b58631bb5c90
/agent-note-tool-output-spill-policy/deferred:
en: 094f8c71672ea726
zh: 252dbe825d6e34ca
/agent-note-tool-output-spill-policy/testing:
en: c98759345e1aebfa
zh: d1faeadb99bd748a
/agent-note-tool-output-spill-policy/consequences:
en: e023260e52a246d6
zh: 2e49237e564a83da
/agent-note-tool-output-spill-policy/alternatives-considered:
en: d53fb144141de557
zh: 1b851eb64c421803
@@ -22,7 +22,7 @@ A thin spill storage seam plus a default spill policy plugin, in a new `packages
| `@deepseek-ai/dsh-spill-local` | Local backend: private, session-scoped file storage on the host filesystem. |
| `@deepseek-ai/dsh-spill-policy` | Tool-result policy plugin: wraps final text results after dispatch and replaces oversized results with a retained preview plus a spill locator. |
The tool-result Consumer is `dsh-spill-policy`, which consumes final tool results through the `tools/post-execute` waterfall. The model follows the backend-supplied retrieval hint for the returned locator. [Session-reference spill reuse](../bug-fix/2026-09-05-session-reference-spill-reuse.md) adds a direct storage consumer with separate preview, provenance, and failure semantics; it does not change the tool-result policy.
The tool-result Consumer is `dsh-spill-policy`, which consumes final tool results through the `tools/post-execute` waterfall. The model follows the backend-supplied retrieval hint for the returned locator. [Session-reference spill reuse](../bug-fix/2026-09-05-session-reference-spill-reuse.md) adds a direct storage consumer with separate preview, source-description, and failure semantics; it does not change the tool-result policy.
### Spill seam
@@ -66,36 +66,7 @@ interface SpillRef {
### Spill policy
`dsh-spill-policy` is a `tools/post-execute` result transformer with one configuration knob:
```ts ignore-check
interface Config {
/** Omitted means no automatic spill policy. Present means apply to oversized plain text tool results. */
maxInlineBytes?: number
}
```
When `maxInlineBytes` is omitted the plugin registers nothing (a true no-op). When set, it applies a default policy to final plain-text tool results:
1. Let the tool run normally, delegating via `next()` so a downstream listener settles the result first.
2. Flatten the accepted final `ContentBlock[]` only when it is entirely plain text; a result with any non-text block is left untouched.
3. If its UTF-8 byte size is at or below `maxInlineBytes`, leave it unchanged.
4. If it is larger, call `ctx.spillStore.saveText()` with the full final text.
5. Replace the model-facing result with a retained head/tail preview plus the spill reference.
The preview is an implementation default owned by the policy: a head/tail split of `maxInlineBytes` via the retention library's `TextRetainer`. Future config can expose preview sizing only after a second deployment needs it.
The replacement text is intentionally generic because the policy only knows the final formatted tool result, not the tool's internal resource:
```text
<retained preview>
(Omitted N bytes. Full formatted result stored at: /.../session-.../....txt. Use read with offset/limit, or grep this path to search within it.)
```
If `ctx.spillStore.saveText()` fails (permissions, ENOSPC, backend unavailable), or the call has no session owner, or no backend is loaded, the plugin logs the reason and returns the original result unchanged. Spill failure never turns a successful tool call into an `isError` result or hides the inline result.
The policy skips `read` to avoid a circular `read -> spill file -> read again` loop. Additional opt-out configuration is deferred until a real second tool needs it.
`dsh-spill-policy` retains ordered text/image ends under `maxInlineTokens` after post-execute policy accepts the result. `saveText()` stores the complete result with readable image paths; image bytes remain in attachment storage. The [multimodal retention decision](../../implemented/bug-fix/2026-09-21-multimodal-tool-result-retention.md) owns image projection order, atomic image omission, and route pricing. An omitted budget installs no listeners, recovery failures keep the original result, and model-facing `read` results skip retention to avoid a read/spill loop.
## Showcase: web_fetch
@@ -129,7 +100,7 @@ With `dsh-spill-policy` configured, a large formatted fetch result is automatica
- id: spill-policy
name: '@deepseek-ai/dsh-spill-policy'
config:
maxInlineBytes: 50000
maxInlineTokens: 12500
```
This separation is important. `web-fetch-http` still owns resource caps (`maxResponseBytes`, `maxBodyChars`) to protect network, memory, and decoding work. `spill-policy` owns only the model-facing context cap after the result already exists. If the provider already returned `truncated: true`, the spill file contains the full formatted result the tool returned, not the full original webpage; the policy does not claim otherwise.
@@ -186,11 +157,11 @@ The local-backend value proposition depends on the existing `read`/`grep` tools
**Snapshot gap.** No ACP snapshot scenario covers the transcript-visible `web_fetch` spill notice yet. The ACP snapshot harness replays keyless and cannot hit the live web, and a `web_fetch` spill requires a real over-cap HTTP body; a deterministic scenario would need a seeded loopback fetch target the replay tree does not currently wire (the examples do not load `tool-web` at all). The behavior is covered instead by the `dsh-tool-web` integration test against a loopback server. Closing the gap is follow-up work: wire `tool-web` + a seeded fetch target into the ACP example, then record a `web-fetch-spill` scenario.
The policy can become too large if it starts owning tool-specific semantics. It stays narrow: plain-text final results only. Tool-owned early spill remains future work.
The policy can become too large if it starts owning tool-specific semantics. It handles accepted text/image sequences without interpreting tool-specific text. Tool-owned early spill remains future work.
## Alternatives considered
**Require each tool to opt in with a retention declaration.** Rejected: the goal is a default behavior similar to Claude Code's generic tool-result persistence. A single `maxInlineBytes` deployment knob is enough to prove the shape.
**Require each tool to opt in with a retention declaration.** Rejected: the goal is a default behavior similar to Claude Code's generic tool-result persistence. A single `maxInlineTokens` deployment knob is enough to prove the shape.
**Make `tool-results` a broad tool-result platform.** Rejected: a broad package name invites retention policy, result replacement, preview wording, search, and early spill into one seam. The shared storage part is smaller: save text and return a locator plus retrieval hint.
@@ -66,36 +66,7 @@ interface SpillRef {
### spill 策略
`dsh-spill-policy` 是一个 `tools/post-execute` 结果转换器,只提供一个配置项:
```ts ignore-check
interface Config {
/** Omitted means no automatic spill policy. Present means apply to oversized plain text tool results. */
maxInlineBytes?: number
}
```
省略 `maxInlineBytes` 时,插件不会注册任何内容,是真正的无操作。设置该值后,它会对最终的纯文本工具结果应用默认策略:
1. 让工具正常运行,通过 `next()` 委托,使下游监听器先结算结果。
2. 仅当已接受的最终 `ContentBlock[]` 全部是纯文本时,才将其展平;含任何非文本块的结果保持不变。
3. 如果 UTF-8 字节大小不超过 `maxInlineBytes`,保持不变。
4. 如果超出上限,使用完整的最终文本调用 `ctx.spillStore.saveText()`。
5. 把模型可见结果替换为保留的首尾预览和 spill 引用。
预览属于策略所有的实现默认值:以 `maxInlineBytes` 为上限,使用保留库的 `TextRetainer` 进行首尾分割。只有第二个部署证明有此需求后,未来配置才会公开预览大小。
替换文本刻意保持通用,因为策略只知道最终格式化的工具结果,不了解工具的内部资源:
```text
<retained preview>
(Omitted N bytes. Full formatted result stored at: /.../session-.../....txt. Use read with offset/limit, or grep this path to search within it.)
```
如果 `ctx.spillStore.saveText()` 失败(权限、ENOSPC、后端不可用),或调用没有会话所有者,或未加载后端,插件会记录原因并原样返回结果。spill 失败绝不会把成功的工具调用变为 `isError` 结果,也不会隐藏内联结果。
策略跳过 `read`,以避免形成 `read -> spill file -> read again` 循环。额外的选择退出配置要等确实出现第二个有此需求的工具后再引入。
`dsh-spill-policy` 在执行后策略接受结果之后,按 `maxInlineTokens` 对文字和图片共同计量并保留首尾。完整结果仍通过 `saveText()` 保存,图片本体留在附件存储,结果文件记录可读取路径。图片投影顺序、整图省略和模型计量由[图文结果保留决策](../../implemented/bug-fix/2026-09-21-multimodal-tool-result-retention.zh.md)负责。省略配置时不安装监听器,存储失败时保留原结果;`read` 的模型可见结果跳过自动省略,避免重复读取产生循环。
## 示例:web_fetch
@@ -129,7 +100,7 @@ ctx.tools.register(defineTool({
- id: spill-policy
name: '@deepseek-ai/dsh-spill-policy'
config:
maxInlineBytes: 50000
maxInlineTokens: 12500
```
这项分离很重要。`web-fetch-http` 仍负责资源上限(`maxResponseBytes`、`maxBodyChars`),用来保护网络、内存和解码工作。`spill-policy` 只负责结果已经存在后针对模型上下文的上限。如果提供方已经返回 `truncated: true`,spill 文件包含的是工具返回的完整格式化结果,而不是原始网页全文;策略不会做出其他承诺。
@@ -186,11 +157,11 @@ ctx.tools.register(defineTool({
**快照缺口。** 目前没有 ACP 快照场景覆盖 transcript(文本记录)可见的 `web_fetch` spill 提示。ACP 快照 harness 在无密钥环境中回放,无法访问实时 web,而 `web_fetch` spill 需要一个真实的超上限 HTTP 正文;确定性场景需要一个预置的 loopback fetch 目标,但当前回放树尚未接线(示例根本没有加载 `tool-web`)。该行为改由 `dsh-tool-web` 针对 loopback server 的集成测试覆盖。弥补该缺口属于后续工作:把 `tool-web` 和预置 fetch 目标接入 ACP 示例,然后录制 `web-fetch-spill` 场景。
如果策略开始负责工具专用语义,就会膨胀得过大。它的范围保持狭窄:只处理纯文本最终结果。由工具负责的提前 spill 仍留作未来工作。
如果策略开始负责工具专用语义,就会膨胀得过大。它处理已接受的图文序列,不解释工具专用的文字语义。由工具负责的提前 spill 仍留作未来工作。
## 考虑过的替代方案
**要求每个工具通过保留声明选择加入。**不予采纳,因为目标是实现类似 Claude Code 通用工具结果持久化的默认行为。只需一个 `maxInlineBytes` 部署配置项即可验证该形态。
**要求每个工具通过保留声明选择加入。**不予采纳,因为目标是实现类似 Claude Code 通用工具结果持久化的默认行为。只需一个 `maxInlineTokens` 部署配置项即可验证该形态。
**把 `tool-results` 建成宽泛的工具结果平台。** 不予采纳:宽泛的包名会诱使系统把保留策略、结果替换、预览措辞、搜索和提前 spill 合并进一个 seam。可共享的存储部分更小:保存文本,并返回定位符与检索提示。
@@ -1,6 +1,31 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-07-10-after-call-compaction-pressure-and-overflow-recovery.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-10-after-call-compaction-pressure-and-overflow-recovery.md
2026-07-10-after-call-compaction-pressure-and-overflow-recovery.md: 89c8917484c11057ff2e6b55e2311e83f724f7ed
2026-07-10-after-call-compaction-pressure-and-overflow-recovery.zh.md: 48f954f2c4720894548ecab387965d3a3d1799b0
/agent-note-after-call-compaction-pressure-and-context-overflow-recovery:
en: 8bfe0d8b79d9840f
zh: 6921dc88e5ef9c83
/agent-note-after-call-compaction-pressure-and-context-overflow-recovery/problem:
en: 036da3e545debe29
zh: 82e031a3120ca36c
/agent-note-after-call-compaction-pressure-and-context-overflow-recovery/decision:
en: a15c7c13f167e5ac
zh: 63bcc2ef60c2f344
/agent-note-after-call-compaction-pressure-and-context-overflow-recovery/decision/successful-pressure-runs-at-the-next-pre-step-boundary:
en: 5f5a656b38730ec6
zh: aece66b85cc610cf
/agent-note-after-call-compaction-pressure-and-context-overflow-recovery/decision/request-recovery-is-limited-to-the-final-model-boundary:
en: fb7da851bf6a020e
zh: b40dc932d6c3101c
/agent-note-after-call-compaction-pressure-and-context-overflow-recovery/decision/compactionengine-exposes-intent-not-token-accounting:
en: be9505b3d73c7f6b
zh: ed753f1afec2787a
/agent-note-after-call-compaction-pressure-and-context-overflow-recovery/testing:
en: b0e1704bd3724301
zh: 2279353ff615f183
/agent-note-after-call-compaction-pressure-and-context-overflow-recovery/alternatives-considered:
en: 3cb5363732ef5758
zh: 07746411cc80878f
/agent-note-after-call-compaction-pressure-and-context-overflow-recovery/consequences:
en: dfe515fb04127eb5
zh: 1924b2e1e9997910
@@ -1,6 +1,43 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-07-10-single-file-executable-sdk-runtime-distribution.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.md
2026-07-10-single-file-executable-sdk-runtime-distribution.md: 5533c38d635d04c8799658fc1f6bcec8543d1dab
2026-07-10-single-file-executable-sdk-runtime-distribution.zh.md: 05800082034f0d1bd5034fc5bb17f09356d84dd9
/agent-note-single-file-executable-sdk-runtime-distribution-single-exe:
en: 00b5d91d3e44a9f8
zh: eabd3c4b338249b3
/agent-note-single-file-executable-sdk-runtime-distribution-single-exe/problem:
en: 112178b76e5209f6
zh: 68726254ae530566
/agent-note-single-file-executable-sdk-runtime-distribution-single-exe/decision:
en: a15c7c13f167e5ac
zh: 63bcc2ef60c2f344
/agent-note-single-file-executable-sdk-runtime-distribution-single-exe/decision/packaging-route-yao-pkg-pkg-s-sea-mode:
en: f1c2b60e9474111d
zh: 5de398b5e8554429
/agent-note-single-file-executable-sdk-runtime-distribution-single-exe/decision/the-serving-interface-is-a-plugin-inside-the-dsh-application:
en: 5fdde26e9e8c6108
zh: 629559d733c1f0c5
/agent-note-single-file-executable-sdk-runtime-distribution-single-exe/decision/plugin-resolution-the-vfs-holds-a-real-package-tree-the-closure-manifest-is-the-deploy-root:
en: c35ea4b858448b49
zh: 1f8ff0a9f82ca881
/agent-note-single-file-executable-sdk-runtime-distribution-single-exe/decision/build-pipeline-and-artifacts:
en: 53ba44431d2ce411
zh: 4159475549273422
/agent-note-single-file-executable-sdk-runtime-distribution-single-exe/decision/python-sdk-distribution-two-carriers-exe-for-production-node-for-development:
en: 9bd60549d4a52ec0
zh: e2343b7210212ee0
/agent-note-single-file-executable-sdk-runtime-distribution-single-exe/decision/naming-lineage:
en: 31a5aecb8bf828bb
zh: 2dffb6fd2e0f8194
/agent-note-single-file-executable-sdk-runtime-distribution-single-exe/packaged-workflow-and-code-execution:
en: 0426f598f3f44e64
zh: fc66728e17f3bcfb
/agent-note-single-file-executable-sdk-runtime-distribution-single-exe/testing:
en: b3c9820f4dc7c6c8
zh: 3b5768ef1770bfcb
/agent-note-single-file-executable-sdk-runtime-distribution-single-exe/alternatives-considered:
en: 50d965ca81a401ba
zh: 0c6296245b97b9ac
/agent-note-single-file-executable-sdk-runtime-distribution-single-exe/consequences:
en: 601a72b3a7a91fe4
zh: 5baaa866e789923e
@@ -23,6 +23,8 @@ The exe is packaged with the **`--sea` (enhanced SEA) mode** of [@yao-pkg/pkg](h
`@yao-pkg/pkg` is an exact-pinned root `devDependency` invoked as `pnpm exec pkg`, with [`patches/@[email protected]`](../../../../patches/@[email protected]) removing the SEA bootstrap's `patchChildProcess` call. Unpatched, pkg rewrites spawned commands named `node` — including the string after a `-c`/`/c` flag, exactly the Bash tool's `bash -c` form — to the executable itself and stamps `PKG_EXECPATH` into every child environment, so a model-issued `node --version` silently boots the dsh CLI; Node's own SEA layer performs no such rewrite, and a SEA binary cannot impersonate plain Node because it always boots its embedded app. With the call removed, children resolve `node` through PATH like any other process (a machine without Node reports command-not-found honestly), no `PKG_EXECPATH` reaches children, absolute `process.execPath` spawns still re-enter the app, worker threads never applied the hook, and `process.pkg` sidecar selection is untouched.
The same patch makes the SEA bootstrap's native-addon extraction atomic. On the first `dlopen` of an addon inside the VFS, pkg's `patchDlopen` copies the addon's package tree to `$PKG_NATIVE_CACHE_PATH/pkg/<sha256 of the .node file>/` (default `~/.cache/pkg/...`), a per-user directory that every concurrent process of the same executable shares; upstream writes each file straight to its final path with `writeFileSync`, which truncates a file another process may already have mapped and lets that process's `existsSync`/hash check read a half-written file. Concurrent first starts therefore die with SIGBUS on Linux or fail with `ERR_DLOPEN_FAILED: Library not loaded` on sharp's libvips on macOS (#4664). The patch routes the three write sites through a same-directory temporary file and `renameSync`, so a cache path is either absent or complete, every process finishes its own copy pass before it loads, and concurrent renames of identical content need no lock. The cache location, hash keying, and per-file comparison are unchanged, so a consumer that isolates the cache per instance through `PKG_NATIVE_CACHE_PATH` keeps working; worker threads only define the hook and never install it. Measured (linux-x64, node24 target, pkg 6.21.0, a probe that loads sharp with its 18 MB libvips library, 16 concurrent first starts against one empty cache, five rounds): 39 of 80 processes died with SIGBUS before the change and 0 of 80 after it, with no temporary files left behind.
Terminology reminder: pkg's `/snapshot` VFS has nothing to do with this repo's testing-system "snapshot" (ACP replay expected outputs, `$DSH_SNAPSHOT`); this document says "VFS" for the former.
### The serving interface is a plugin inside the dsh application
@@ -38,21 +40,23 @@ The Python client supplies an explicit Harness home and selects the `sdk` profil
Inside the exe's VFS sits a **real package tree in build-artifact form** (each package's `lib/` plus a real `node_modules`). The packaged JSON-RPC entry supplies its installed harness base to app-boot's root Include: relative plugin specifiers resolve from the external configuration directory, while bare package names resolve from the VFS, so a configuration inside another Node project cannot shadow the packaged plugin set. The ordinary development bin leaves bare packages configuration-owned. Bare specifiers in the packaged entry resolve upward along `node_modules` from the entry's position inside the VFS and land inside the VFS naturally. The closed set needs no allowlist code — the set is whatever the VFS has installed, and importing a name outside the set fails.
The deploy root is [`python/sdk-runtime/package.json`](../../../../python/sdk-runtime/package.json) (`dsh-python-runtime-closure`, a pnpm workspace member and a zero-code pure dependency manifest) — the unified source of truth for "which plugins the exe ships" and "what the Python runtime distributes". Adding a plugin to the exe = adding one dependency line to the manifest and repackaging. [`scripts/verify-runtime-closure.ts`](../../../../scripts/verify-runtime-closure.ts) reads every shipped `packages/preset/agent-presets/presets/*/agent.cordis.yml`, evaluates `disabled` conditions that compare `process.platform` for every target in `python/sdk-runtime/platforms.json`, and requires each active workspace plugin at the runtime root through an explicit `workspace:` dependency. It also traverses every workspace package covered by that manifest and requires every non-optional workspace peer, reporting the complete preset or referencing-package → missing-dependency chain; unknown platform conditions remain active so a plugin cannot be omitted by an unsupported expression. `pnpm run hygiene`, CI static, and the single-exe build run it before packaging. Deploy also packs by each package's `files`, so the shared chunks tsdown splits out must be covered by `files`.
The deploy root is [`python/sdk-runtime/package.json`](../../../../python/sdk-runtime/package.json) (`dsh-python-runtime-closure`, a pnpm workspace member and a zero-code pure dependency manifest) — the unified source of truth for "which plugins the exe ships" and "what the Python runtime distributes". Adding a plugin to the exe = adding one dependency line to the manifest and repackaging. [`scripts/verify-runtime-closure.ts`](../../../../scripts/verify-runtime-closure.ts) reads every shipped `packages/bundle/web-app/cordis.patch.yml*/agent.cordis.yml`, evaluates `disabled` conditions that compare `process.platform` for every target in `python/sdk-runtime/platforms.json`, and requires each active workspace plugin at the runtime root through an explicit `workspace:` dependency. It also traverses every workspace package covered by that manifest and requires every non-optional workspace peer, reporting the complete preset or referencing-package → missing-dependency chain; unknown platform conditions remain active so a plugin cannot be omitted by an unsupported expression. `pnpm run hygiene`, CI static, and the single-exe build run it before packaging. Deploy also packs by each package's `files`, so the shared chunks tsdown splits out must be covered by `files`.
The deploy root includes `@deepseek-ai/dsh-mcp-client` as an explicitly supported custom-configuration plugin even though no shipped preset mounts it. An external config can therefore connect to user-supplied stdio and Streamable HTTP MCP servers and register their tools; the distribution does not carry those servers or extend the bridge to MCP Resources and Prompts. The executable and installed-wheel smokes start a temporary stdio server, discover its tool, and complete one model-requested call.
The deploy root includes `@deepseek-ai/dsh-mcp-client` as an explicitly supported custom-configuration plugin even though no shipped preset mounts it. An external config can therefore connect to user-supplied stdio and Streamable HTTP MCP servers and register their tools; the distribution does not carry those servers. The optional resource service provides MCP Resources; MCP Prompts remain unsupported. The executable and installed-wheel smokes start a temporary stdio server, discover its tool, and complete one model-requested call.
The [Office kit](2026-09-14-independent-libreoffice-kit.md) and its installed dependency tree live in `<executable-stem>-office/node_modules`, preserving complete package contents and helper permissions. Top-level `pkg.ignore` excludes kit packages from the SEA archive, including assets selected by dependency `files` fields; small dependencies shared with other consumers remain available in the VFS. The private Python bootstrap uses Node `registerHooks` to resolve the kit entry and its package manifest from the real directory. Native executables and URL Workers therefore retain their ordinary paths without modifying the kit or the public CLI. Missing required packages and missing installed package manifests fail the copy; absent optionals preserve the kit's engine selection.
### Build pipeline and artifacts
[`scripts/build-exe-for-python-sdk.ts`](../../../../scripts/build-exe-for-python-sdk.ts): runtime closure verification → `pnpm run build` → (after clearing) `pnpm --filter dsh-python-runtime-closure deploy --legacy --prod --config.node-linker=hoisted --config.auto-install-peers=false --config.link-workspace-packages=true` **directly into** `python/sdk-runtime/src/deepseek_harness_runtime/runtime/node/`, including [`python/sdk-runtime/runtime-bootstrap.mjs`](../../../../python/sdk-runtime/runtime-bootstrap.mjs) as the carrier-root `runtime-bootstrap.mjs` → restore direct workspace packages omitted by legacy deploy and reject any remaining manifest gap → replace staged dependency symlinks with their target bytes, remove package-manager `.bin` links, and fail if any symlink remains → verify the deployed bootstrap and inject pkg configuration with that bin plus assets covering dynamic profile, bundle, frontend, preset, native-library, and configuration reads → stage the target `node-pty` addon → invoke `pkg --sea` once per target → write `deepseek-harness-sdk-runtime-<platform>-<arch>` under `dist-exe/` and copy it into the runtime directory. The Python runtime owns that bootstrap. It calls the public CLI export for ordinary launches and dispatches a provider-private selection to the same `@deepseek-ai/dsh-subprocess-local/runner` core without changing CLI grammar or adding another executable; the [native-containment decision](2026-08-28-subprocess-native-containment.md) owns that private path. Linux CI rebuilds `pty.node` inside the matching manylinux 2.28 container because legacy deploy omits that install side effect. Every target copies its native `@vscode/ripgrep` binary beside the executable as the required `-rg` sidecar; pkg runtimes select that sidecar through `process.pkg`, while ordinary Node execution uses `@vscode/ripgrep` directly. macOS uses its target prebuild and also emits the required `-spawn-helper`. All four deploy flags are grounded in measurement: `--legacy` is the mandatory path with inject-workspace-packages off; hoisted gives pkg a stable single-instance layout that the explicit materialization pass makes symlink-free; disabling automatic peer installation prevents undeclared peers from expanding the closure; link-workspace-packages selects direct workspace dependencies. [`pnpm-workspace.yaml`](../../../../pnpm-workspace.yaml) overrides the transitive `@deepseek-ai/cosmokit` and `@deepseek-ai/schemastery` semver requests to the pinned vendor sources so legacy deploy never resolves those unpublished names from a registry.
[`scripts/build-exe-for-python-sdk.ts`](../../../../scripts/build-exe-for-python-sdk.ts): runtime closure verification → `pnpm run build` → (after clearing) `pnpm --filter dsh-python-runtime-closure deploy --legacy --prod --config.allow-unused-patches=true --config.node-linker=hoisted --config.auto-install-peers=false --config.link-workspace-packages=true` **directly into** `python/sdk-runtime/src/deepseek_harness_runtime/runtime/node/`, including [`python/sdk-runtime/runtime-bootstrap.mjs`](../../../../python/sdk-runtime/runtime-bootstrap.mjs) as the carrier-root `runtime-bootstrap.mjs` → restore direct workspace packages omitted by legacy deploy and reject any remaining manifest gap → replace staged dependency symlinks with their target bytes, remove package-manager `.bin` links, and fail if any symlink remains → verify the deployed bootstrap and inject pkg configuration with that bin plus assets covering dynamic profile, bundle, frontend, preset, native-library, and configuration reads → stage the target `node-pty` addon → invoke `pkg --sea` once per target → write `deepseek-harness-sdk-runtime-<platform>-<arch>` under `dist-exe/` and copy it with its target-specific Office directory into the runtime directory. The Python runtime owns that bootstrap. It calls the public CLI export for ordinary launches and dispatches a provider-private selection to the same `@deepseek-ai/dsh-subprocess-local/runner` core without changing CLI grammar or adding another executable; the [native-containment decision](2026-08-28-subprocess-native-containment.md) owns that private path. Linux CI rebuilds `pty.node` inside the matching manylinux 2.28 container because legacy deploy omits that install side effect. Every target copies its native `@vscode/ripgrep` binary beside the executable as the required `-rg` sidecar; pkg runtimes select that sidecar through `process.pkg`, while ordinary Node execution uses `@vscode/ripgrep` directly. macOS uses its target prebuild and also emits the required `-spawn-helper`. The deploy flags preserve the measured runtime layout: `--legacy` is the mandatory path with inject-workspace-packages off; hoisted gives pkg a stable single-instance layout that the explicit materialization pass makes symlink-free; disabling automatic peer installation prevents undeclared peers from expanding the closure; link-workspace-packages selects direct workspace dependencies. [`pnpm-workspace.yaml`](../../../../pnpm-workspace.yaml) overrides the transitive `@deepseek-ai/cosmokit` and `@deepseek-ai/schemastery` semver requests to the pinned vendor sources so legacy deploy never resolves those unpublished names from a registry. Production deployment permits unused workspace patches because development-only tools can be absent from its closure; included-package patch failures still fail deployment. Workspace installs retain strict unused-patch validation.
CI: [`.github/workflows/build-exe-for-python-sdk.yml`](../../../../.github/workflows/build-exe-for-python-sdk.yml) runs [installed-wheel validation](../testing/2026-08-23-installed-python-wheel-black-box-ci.md) on Linux/Windows x64 for pull requests and Linux ARM64 plus both macOS architectures for master pushes. The [public publication workflow](../../archived/process/2026-08-11-python-publication-workflow.md) calls it for all five targets; `workflow_dispatch` can still select a subset. Native builds run on linux-x64 / linux-arm64 (`ubuntu-24.04-arm`) / macos-arm64 / macos-x64 (`macos-15-intel`) / win-x64 (`windows-2025`), with `~/.pkg-cache` cached where applicable, and pkg handles macOS ad-hoc signing. Each leg installs the release-shaped SDK and runtime wheels into a clean venv outside the checkout, proves their package and executable provenance, then drives the complete keyless scenario set through the public SDK and direct NDJSON JSON-RPC. Trusted pull requests and master pushes additionally run a real DeepSeek two-turn tool smoke on their selected targets; fork and Dependabot heads receive no key. Linux inspects the executable and native addon's GLIBC requirements and runs an additional manylinux 2.28 smoke, while macOS checks the runtime, ripgrep, and PTY helper architectures and verifies that all three deployment targets fit the wheel tag. A full five-target run retains six artifacts, each containing one release file: the platform-independent SDK wheel and five native runtime wheels; a subset dispatch retains the SDK wheel and selected runtime wheels. Bare executables and source bundles remain intermediate test inputs. [`.gitlab-ci.yml`](../../../../.gitlab-ci.yml) accepts `python-v<repository-version>` tag pipelines whose version matches the root `package.json`, builds one SDK wheel and five native runtime wheels, then a single serialized job checks and publishes all six to the project PyPI registry. The [`python/sdk-runtime` README](../../../../python/sdk-runtime/README.md) owns the Windows target and the explicit exclusion of Windows arm64.
CI: [`.github/workflows/build-exe-for-python-sdk.yml`](../../../../.github/workflows/build-exe-for-python-sdk.yml) runs [installed-wheel validation](../testing/2026-08-23-installed-python-wheel-black-box-ci.md) on Linux/Windows x64 for pull requests and Linux ARM64 plus both macOS architectures for master pushes. The [public publication workflow](../../archived/process/2026-08-11-python-publication-workflow.md) calls it for all five targets; `workflow_dispatch` can still select a subset. Native builds run on linux-x64 / linux-arm64 (`ubuntu-24.04-arm`) / macos-arm64 / macos-x64 (`macos-15-intel`) / win-x64 (`windows-2025`), with `~/.pkg-cache` cached where applicable, and pkg handles macOS ad-hoc signing. Each leg installs the release-shaped SDK and runtime wheels into a clean venv outside the checkout, verifies their package and executable origin, then drives the complete keyless scenario set through the public SDK and direct NDJSON JSON-RPC. Trusted pull requests and master pushes additionally run a real DeepSeek two-turn tool smoke on their selected targets; fork and Dependabot heads receive no key. Linux inspects the executable and native addon's GLIBC requirements and runs an additional manylinux 2.28 smoke, while macOS checks the runtime, ripgrep, and PTY helper architectures and verifies that all three deployment targets fit the wheel tag. A full five-target run retains six artifacts, each containing one release file: the platform-independent SDK wheel and five native runtime wheels; a subset dispatch retains the SDK wheel and selected runtime wheels. Bare executables and source bundles remain intermediate test inputs. [`.gitlab-ci.yml`](../../../../.gitlab-ci.yml) accepts `python-v<repository-version>` tag pipelines whose version matches the root `package.json`, builds one SDK wheel and five native runtime wheels, then a single serialized job checks and publishes all six to the project PyPI registry. The [`python/sdk-runtime` README](../../../../python/sdk-runtime/README.md) owns the Windows target and the explicit exclusion of Windows arm64.
### Python SDK distribution: two carriers, exe for production, node for development
The Python SDK lives at [`python/`](../../../../python/README.md): `python/sdk` is the client and `python/sdk-runtime` is the runtime carrier package. The runtime package's data directory holds the build-injected platform executable with its required `-rg` sidecar and optional macOS helper, plus the build-injected `runtime/node/` closure tree for repository development. `resolve_bundled_launch_args()` selects the executable by default; explicit `DSH_RUNTIME_MODE=node` runs `runtime/node/node_modules/@deepseek-ai/dsh/lib/bin.js` on system Node 22.19 or newer. The node carrier never enters wheel distributions, and neither carrier uses a checked-in complete `cordis.yml`.
The Python SDK lives at [`python/`](../../../../python/README.md): `python/sdk` is the client and `python/sdk-runtime` is the runtime carrier package. The runtime package's data directory holds the build-injected platform executable with its required `-rg` sidecar, `-office/` directory, and optional macOS helper, plus the build-injected `runtime/node/` closure tree for repository development. `resolve_bundled_launch_args()` selects the executable by default; explicit `DSH_RUNTIME_MODE=node` runs `runtime/node/node_modules/@deepseek-ai/dsh/lib/bin.js` on system Node 22.19 or newer. The node carrier never enters wheel distributions, and neither carrier uses a checked-in complete `cordis.yml`.
[`scripts/build-python-release.py`](../../../../scripts/build-python-release.py) reads the authoritative `X.Y.Z` or prerelease version from the repository root `package.json`, converts prereleases to their PEP 440 spelling, and stages both packages at that wheel version, with `deepseek-harness-sdk` depending exactly on the matching `deepseek-harness-runtime-bin`. An optional `python-v<repository-version>` release tag is a consistency assertion and is rejected when it differs from the repository version; the source `pyproject.toml` development sentinel never determines a release version. Staging also carries the repository license into both wheels and the third-party notices into the bundled runtime wheel. The SDK is a `py3-none-any` wheel; each wheel-only runtime package contains one exe and its architecture-matched ripgrep sidecar, and the macOS wheel also contains its architecture-matched spawn helper. Runtime wheels use `py3-none-manylinux_2_28_x86_64`, `py3-none-manylinux_2_28_aarch64`, `py3-none-macosx_14_0_arm64`, `py3-none-macosx_14_0_x86_64`, or `py3-none-win_amd64`; the Hatch hook rejects sdists, universal tags, mixed-platform payloads, missing or extra sidecars, and unsupported platforms. Both macOS tags deliberately declare a conservative 14.0 installation floor: the packaged Node 24 executables declare macOS 13.5, and the x64 PTY helper declares 10.7, but release validation proves the complete payload only against the 14.0 wheel claim rather than promising each observed component minimum as a supported host. The two macOS wheels remain architecture-specific; no universal2 wheel is published.
[`scripts/build-python-release.py`](../../../../scripts/build-python-release.py) reads the authoritative `X.Y.Z` or prerelease version from the repository root `package.json`, converts prereleases to their PEP 440 spelling, and stages both packages at that wheel version, with `deepseek-harness-sdk` depending exactly on the matching `deepseek-harness-runtime-bin`. An optional `python-v<repository-version>` release tag is a consistency assertion and is rejected when it differs from the repository version; the source `pyproject.toml` development sentinel never determines a release version. Staging also carries the repository license into both wheels and the third-party notices into the bundled runtime wheel. The SDK is a `py3-none-any` wheel; each wheel-only runtime package contains one exe, its Office directory, and its architecture-matched ripgrep sidecar, and the macOS wheel also contains its architecture-matched spawn helper. Runtime wheels use `py3-none-manylinux_2_28_x86_64`, `py3-none-manylinux_2_28_aarch64`, `py3-none-macosx_14_0_arm64`, `py3-none-macosx_14_0_x86_64`, or `py3-none-win_amd64`; the Hatch hook rejects sdists, universal tags, mixed-platform payloads, missing or extra sidecars, and unsupported platforms. Both macOS tags deliberately declare a conservative 14.0 installation floor: the packaged Node 24 executables declare macOS 13.5, and the x64 PTY helper declares 10.7, but release validation proves the complete payload only against the 14.0 wheel claim rather than promising each observed component minimum as a supported host. The two macOS wheels remain architecture-specific; no universal2 wheel is published.
The Python client launches the packaged `dsh` command with the selected profile (`sdk` by default), ordered patch files, and an explicit Harness home. The profile owns JSON-RPC serving and application composition; missing homes, profiles, bundles, patches, and server rows fail without an external complete-config fallback.
@@ -60,16 +64,18 @@ The Python client launches the packaged `dsh` command with the selected profile
`dsh-python-runtime-closure` is the private deploy manifest and `deepseek-harness-sdk-runtime-<platform>-<arch>` is the executable family. The wire `serverInfo.name` is `deepseek-harness-sdk-runtime`; the Python distribution names are `deepseek-harness-sdk` / `deepseek-harness-runtime-bin`, while the import modules are `deepseek_harness` / `deepseek_harness_runtime`.
## Disposition of worker-style plugins
## Packaged workflow and code execution
`dsh-workflow-worker-thread` and `dsh-code-runtime-worker-thread` are supported inside the exe. Their built hosts convert the sibling `lib/worker.cjs` URL with `fileURLToPath()` and pass the resulting filesystem string to `Worker`, which is the form pkg's Worker hook resolves inside the VFS. The worker entries are CommonJS because that hook compiles VFS worker files as CommonJS. The workflow engine keeps its data-URL bootstrap for unbuilt source execution; only its built sibling entry uses the filesystem string. The custom-config executable smoke loads both backends, invokes a real `run_code` call and a zero-agent `workflow` call, and requires each worker to return `42` from inside pkg's VFS.
`dsh-workflow-ptc` sends its self-contained guest program through `dsh-ptc-runtime-node`. The shared provider starts a managed child through the executable's private Node bootstrap dispatch, with a dedicated control channel; no separate workflow worker asset is required. The [sandboxed Node decision](2026-09-11-sandboxed-node-ptc-runtime.md) owns process and policy lifetime, and [workflow sandbox reuse](2026-09-13-workflow-ptc-sandbox-reuse.md) owns the workflow adapter.
## Testing
The verification surface has three tiers. Mechanism tier: the measured conclusions for the `--sea` chain are embedded in the Decision sections (ESM dynamic import inside the VFS, single cordis instance, fail-loud config chain, `node:sqlite`, macOS ad-hoc signing runs). SDK tier: the complete keyless pytest suite covers the client protocol against a fake runtime peer, subprocess cleanup, absolute cwd propagation, dual-carrier launch, and carrier resolution; root CI runs it on Python 3.10. End-to-end tier: every platform build installs both wheels into a clean venv outside the checkout, proves matching versions and installed module/executable locations, then completes turns against a mock endpoint through the default SDK path, a custom config, the checked-in standalone minimal composition, and the direct binary protocol, with final text and JSONL checked. The minimal run asserts its exact system prompt and two-tool catalog, retains Bash state across calls, and invokes the editor. The custom config additionally drives `run_code` and a zero-agent `workflow` through their real worker files inside the packaged VFS. The filesystem-search scenario requires the model to call both `glob` and `grep` through the target-native `-rg` sidecar. The spawn-node scenario drives the platform shell tool through a command starting with `node` and requires the machine's own Node version in the tool result with no `PKG_EXECPATH` in the child environment, pinning the packaged runtime against a pkg upgrade that re-records the child-process patch. The MCP scenario starts a temporary external stdio server, deliberately delays its initial `tools/list` response, then immediately starts the first SDK prompt; the prompt must see and call the discovered tool, proving that `initialize` is a real Loader-settlement readiness boundary rather than a timing sleep. The same installed run compares a committed executable-specific snapshot through the Python SDK: a keyless scripted model mounts a Cordis plugin that registers a tool, invokes that tool from `run_code`, runs a direct spawn subagent and a workflow that starts a second spawn child, then unmounts the plugin. The fixture explicitly disables its unused bundled Bash and local skill discovery so its tool set does not depend on repository-external state, and the comparison normalizes opaque message, agent, workflow-run, and session IDs across the SDK result and notification stream plus the parent and two child JSONL logs. Trusted pull requests add a real-provider two-turn file write/read whose external bytes, tool calls, completed reasons, and persisted log must agree. This harness stays separate from ACP's `pnpm run test:snapshot` because the protocols and build artifacts differ.
The verification surface has three tiers. Mechanism tier: the measured conclusions for the `--sea` chain are embedded in the Decision sections (ESM dynamic import inside the VFS, single cordis instance, fail-loud config chain, `node:sqlite`, macOS ad-hoc signing runs). SDK tier: the complete keyless pytest suite covers the client protocol against a fake runtime peer, subprocess cleanup, absolute cwd propagation, dual-carrier launch, and carrier resolution; root CI runs it on Python 3.10. End-to-end tier: every platform build installs both wheels into a clean venv outside the checkout, proves matching versions and installed module/executable locations, then completes turns against a mock endpoint through the default SDK path, a custom config, the checked-in standalone minimal composition, and the direct binary protocol, with final text and JSONL checked. The minimal run asserts its exact system prompt and single shell-tool catalog and retains shell state across calls. The custom config additionally drives `run_code` and a zero-agent `workflow` through the shared packaged Node process bootstrap. The filesystem-search scenario requires the model to call both `glob` and `grep` through the target-native `-rg` sidecar. The spawn-node scenario drives the platform shell tool through a command starting with `node` and requires the machine's own Node version in the tool result with no `PKG_EXECPATH` in the child environment, pinning the packaged runtime against a pkg upgrade that re-records the child-process patch. The MCP scenario starts a temporary external stdio server, deliberately delays its initial `tools/list` response, then immediately starts the first SDK prompt; the prompt must see and call the discovered tool, proving that `initialize` is a real Loader-settlement readiness boundary rather than a timing sleep. The same installed run compares a committed executable-specific snapshot through the Python SDK: a keyless scripted model mounts a Cordis plugin that registers a tool, invokes that tool from `run_code`, runs a direct spawn subagent and a workflow that starts a second spawn child, then unmounts the plugin. The fixture explicitly disables its unused bundled Bash and local skill discovery so its tool set does not depend on repository-external state, and the comparison normalizes opaque message, agent, workflow-run, and session IDs across the SDK result and notification stream plus the parent and two child JSONL logs. Trusted pull requests add a real-provider two-turn file write/read whose external bytes, tool calls, completed reasons, and persisted log must agree. This harness stays separate from ACP's `pnpm run test:snapshot` because the protocols and build artifacts differ.
Manual-driving caveat: the bin treats stdin EOF as "the client is gone" and disposes immediately, so a short-lived pipe aborts an in-flight turn — pipe-driven runs must keep stdin open until the turn ends.
The installed-wheel `sdk-office` scenario copies the target's complete payload to a private temporary directory, requires exactly one target backend (the declared native target, or WASM when no native target is declared), and converts DOCX once through the shipped SDK profile with that engine. It checks that the kit module resolves inside the relocated directory, that conversion reports the expected backend, and that the output contains PDF bytes. Wheel validation checks the declared engine assets and native helper execute bit; CI uploads the completed wheel, so nested helper permissions stay inside the ZIP archive.
## Alternatives considered
**Bare Node native SEA.** The injected main script must be a single CJS file, and the blob carries no filesystem and no module resolution, so a dynamic import of a bare specifier has nothing to resolve against; the only option is compiling plugins statically into the main script and registering them by hand — bypassing standard module resolution and hardcoding the plugin set, contrary to "configuration decides everything". The final route is in fact "the official SEA foundation + pkg's VFS/module-hook layer"; what was rejected is the bare use, not SEA itself.
@@ -84,6 +90,6 @@ Manual-driving caveat: the bin treats stdin EOF as "the client is gone" and disp
## Consequences
**Bought**: zero-dependency single-file distribution on target platforms; plugin semantics strictly identical to running from source (the same real package tree, no transpilation, no registry); the serving interface, the plugin set, and the configuration all converge on two sources of truth — `cordis.yml` plus one dependency manifest; the exe and node carriers share one tree and one semantics, so development verification never waits for packaging; official Node binaries remove the patched-binary supply-chain concern.
**Bought**: no system Node.js dependency on supported targets; plugin semantics strictly identical to running from source (the same real package tree, no transpilation, no registry); the serving interface, the plugin set, and the configuration all converge on two sources of truth — `cordis.yml` plus one dependency manifest; the exe and node carriers share one tree and one semantics, so development verification never waits for packaging; official Node binaries remove the patched-binary supply-chain concern.
**Paid**: artifacts on the order of 174MB with source entering the blob as-is (no bytecode obfuscation; a closed-source distribution requirement needs a separate evaluation); pkg's VFS/module-hook layer remains community-maintained (`@yao-pkg/pkg` is an exact-pinned, pnpm-patched root devDependency; upgrading re-records the patch and is an explicit change); `--sea` is one invocation per target (matching CI's one leg per platform; local multi-platform builds are serial).
**Paid**: large Office engine resources remain external to the SEA archive, and the executable must travel with its required sidecars; source enters the distribution as-is (no bytecode obfuscation; a closed-source distribution requirement needs a separate evaluation); pkg's VFS/module-hook layer remains community-maintained (`@yao-pkg/pkg` is an exact-pinned, pnpm-patched root devDependency; upgrading re-records the patch and is an explicit change); `--sea` is one invocation per target (matching CI's one leg per platform; local multi-platform builds are serial).
@@ -23,6 +23,8 @@ exe 使用 [@yao-pkg/pkg](https://github.com/yao-pkg/pkg)(vercel/pkg 归档后
`@yao-pkg/pkg` 是精确钉版的根 `devDependency`,经 `pnpm exec pkg` 调用,并以 [`patches/@[email protected]`](../../../../patches/@[email protected]) 移除 SEA bootstrap 中的 `patchChildProcess` 调用。未打补丁时,pkg 会把 spawn 的 `node` 命令——包括 `-c`/`/c` 标志后的命令串,恰是 Bash 工具的 `bash -c` 形态——改写为 exe 自身,并向每个子进程环境注入 `PKG_EXECPATH`,模型下发的 `node --version` 会静默启动 dsh CLI;Node 自身的 SEA 层没有这种改写,且 SEA 二进制永远启动内嵌应用、无法充当纯 Node。移除该调用后,子进程像普通进程一样经 PATH 解析 `node`(无 Node 的机器如实报 command not found),子进程环境不再出现 `PKG_EXECPATH`,以 `process.execPath` 绝对路径 spawn 的重入不受影响,worker 线程本来就未应用该钩子,`process.pkg` 侧车选择也不受影响。
同一补丁还把 SEA bootstrap 的原生插件解包改成原子写入。VFS 内的插件首次 `dlopen` 时,pkg 的 `patchDlopen` 会把该插件所在的包目录整棵拷到 `$PKG_NATIVE_CACHE_PATH/pkg/<.node 文件的 sha256>/`(默认 `~/.cache/pkg/...`),这是同一个 exe 的所有并发进程共用的按用户目录;上游用 `writeFileSync` 直接写目标路径,会把另一个进程可能已经映射的文件截断,并让该进程的 `existsSync`/哈希比对读到写了一半的文件。因此并发首次启动在 Linux 上以 SIGBUS 崩溃,在 macOS 上对 sharp 的 libvips 报 `ERR_DLOPEN_FAILED: Library not loaded`(#4664)。补丁让三处写入都经过同目录临时文件加 `renameSync`,于是缓存路径要么不存在、要么完整,每个进程都在加载前走完自己的拷贝,相同内容的并发 rename 不需要锁。缓存位置、哈希键与逐文件比对均未改变,通过 `PKG_NATIVE_CACHE_PATH` 按实例隔离缓存的消费方照常工作;worker 线程只定义该钩子而从不安装。 实测(linux-x64、node24 构建目标、pkg 6.21.0,一个加载 sharp 及其 18 MB libvips 库的探针,16 个进程对同一个空缓存并发首次启动,跑五轮):改动前 80 个进程中 39 个以 SIGBUS 崩溃,改动后 80 个全部正常,且无残留临时文件。
术语提醒:pkg 的 `/snapshot` VFS 与本仓库测试体系的「快照」(ACP(Agent Client Protocol)回放预期输出、`$DSH_SNAPSHOT`)无关,本文用「VFS」指前者。
### 对外服务接口是 dsh 应用中的插件
@@ -38,21 +40,23 @@ Python 客户端提供显式 Harness home,并选择 `sdk` profile 与有序 pa
exe 的 VFS 内是**构建产物形态的真实包树**(各包的 `lib/` + 真实 `node_modules`)。打包专用 JSON-RPC 入口会向 app-boot 的根 Include 提供自身已安装 harness 的基准位置:相对插件说明符从外部配置目录解析,裸包名则从 VFS 解析,因此位于另一个 Node 项目内的配置无法遮蔽已打包的插件集合。普通开发 bin 仍由配置项目提供裸包。打包入口中的裸包名从该入口在 VFS 内的位置沿 `node_modules` 向上解析,自然落在 VFS 内。封闭集不需要白名单代码——VFS 中安装了什么,集合中就有什么;`import()` 集合外的名称会失败。
部署根目录是 [`python/sdk-runtime/package.json`](../../../../python/sdk-runtime/package.json)(`dsh-python-runtime-closure`,pnpm 工作区成员、零代码纯依赖 manifest),也是「exe 安装哪些插件」与「Python 运行时分发什么」的统一真源。向 exe 添加插件,就是在 manifest 中增加一行依赖后重新打包。[`scripts/verify-runtime-closure.ts`](../../../../scripts/verify-runtime-closure.ts) 读取每个已发布的 `packages/preset/agent-presets/presets/*/agent.cordis.yml`,针对 `python/sdk-runtime/platforms.json` 中的每个目标解析比较 `process.platform` 的 `disabled` 条件,并要求该目标启用的每个工作区插件都通过显式的 `workspace:` 依赖列在运行时根目录。它还遍历该 manifest 覆盖的全部工作区包,要求每个非可选的工作区对等依赖(peer dependency)都显式列出,并报告“preset 或引用包 → 缺失依赖”的完整链路;无法识别的平台条件会保持启用,避免因不支持的表达式遗漏插件。`pnpm run hygiene`、CI 静态检查与 single-exe 构建都会在打包前运行该门禁。部署还会依据各包的 `files` 字段打包,因此 tsdown 拆出的共享分片必须被 `files` 覆盖。
部署根目录是 [`python/sdk-runtime/package.json`](../../../../python/sdk-runtime/package.json)(`dsh-python-runtime-closure`,pnpm 工作区成员、零代码纯依赖 manifest),也是「exe 安装哪些插件」与「Python 运行时分发什么」的统一真源。向 exe 添加插件,就是在 manifest 中增加一行依赖后重新打包。[`scripts/verify-runtime-closure.ts`](../../../../scripts/verify-runtime-closure.ts) 读取每个已发布的 `packages/bundle/web-app/cordis.patch.yml*/agent.cordis.yml`,针对 `python/sdk-runtime/platforms.json` 中的每个目标解析比较 `process.platform` 的 `disabled` 条件,并要求该目标启用的每个工作区插件都通过显式的 `workspace:` 依赖列在运行时根目录。它还遍历该 manifest 覆盖的全部工作区包,要求每个非可选的工作区对等依赖(peer dependency)都显式列出,并报告“preset 或引用包 → 缺失依赖”的完整链路;无法识别的平台条件会保持启用,避免因不支持的表达式遗漏插件。`pnpm run hygiene`、CI 静态检查与 single-exe 构建都会在打包前运行该门禁。部署还会依据各包的 `files` 字段打包,因此 tsdown 拆出的共享分片必须被 `files` 覆盖。
部署根目录显式包含 `@deepseek-ai/dsh-mcp-client`,将其作为自定义配置可用的插件,即使随附 preset 均未挂载该插件。外部配置因此可以连接由用户提供的 stdio 与 Streamable HTTP MCP server 并注册其工具;分发物不包含这些 server,也不将桥接范围扩展到 MCP Resources 和 Prompts。可执行程序与已安装 wheel 包的冒烟测试会启动临时 stdio server,发现其工具,并完成一次由模型请求的调用。
部署根目录显式包含 `@deepseek-ai/dsh-mcp-client`,将其作为自定义配置可用的插件,即使随附 preset 均未挂载该插件。外部配置因此可以连接由用户提供的 stdio 与 Streamable HTTP MCP server 并注册其工具;分发物不包含这些 server。可选资源服务提供 MCP Resources;MCP Prompts 仍不受支持。可执行程序与已安装 wheel 包的冒烟测试会启动临时 stdio server,发现其工具,并完成一次由模型请求的调用。
[Office kit](2026-09-14-independent-libreoffice-kit.zh.md) 及其已安装依赖树位于 `<executable-stem>-office/node_modules`,保留完整包内容与辅助程序权限。顶层 `pkg.ignore` 从 SEA 归档排除 kit 包,包括依赖 `files` 字段选中的资源;与其他使用方共享的小型依赖仍可在 VFS 中使用。Python 私有 bootstrap 使用 Node `registerHooks` 从真实目录解析 kit 入口及其包清单。因此原生可执行程序与 URL Worker 保留普通文件路径,无需修改 kit 或公开 CLI。必需包缺失或已安装包缺少清单会使复制失败;未安装的可选包保留 kit 自身的引擎选择规则。
### 构建流水线与产物
[`scripts/build-exe-for-python-sdk.ts`](../../../../scripts/build-exe-for-python-sdk.ts):运行时闭包校验 → `pnpm run build` →(清空后)`pnpm --filter dsh-python-runtime-closure deploy --legacy --prod --config.node-linker=hoisted --config.auto-install-peers=false --config.link-workspace-packages=true` **直接写入** `python/sdk-runtime/src/deepseek_harness_runtime/runtime/node/`,其中包含作为载体根目录 `runtime-bootstrap.mjs` 的 [`python/sdk-runtime/runtime-bootstrap.mjs`](../../../../python/sdk-runtime/runtime-bootstrap.mjs) → 恢复 legacy deploy 遗漏的直接工作区包,并拒绝剩余的 manifest 缺口 → 将暂存依赖中的符号链接替换为目标文件内容,删除包管理器的 `.bin` 链接,并在仍有任何符号链接时失败 → 验证已部署的 bootstrap,并注入以该文件为 bin 的 pkg 配置及覆盖动态读取 profile、bundle、前端、preset、原生库与配置文件的 assets → 暂存目标平台的 `node-pty` addon → 每个构建目标调用一次 `pkg --sea` → 将 `deepseek-harness-sdk-runtime-<platform>-<arch>` 写入 `dist-exe/` 并拷回运行时目录。该 bootstrap 由 Python runtime 拥有;普通启动时它调用公开 CLI export,而提供方私有选择会分派到同一个 `@deepseek-ai/dsh-subprocess-local/runner` 核心,不改变 CLI 语法,也不增加另一个可执行文件;[原生 containment 决策](2026-08-28-subprocess-native-containment.zh.md)负责这条私有路径。Linux CI 会在匹配的 manylinux 2.28 容器中重新构建 `pty.node`,因为 legacy deploy 会遗漏这一安装副作用。每个目标都会把对应的原生 `@vscode/ripgrep` 二进制复制到可执行文件旁,作为必需的 `-rg` 伴随文件;pkg 运行时通过 `process.pkg` 选择该伴随文件,普通 Node 执行则直接使用 `@vscode/ripgrep`。macOS 使用对应目标的预构建产物,并额外生成所需的 `-spawn-helper`。四个部署标志都有实测依据:未启用 `inject-workspace-packages` 时必须使用 `--legacy`;`hoisted` 为 pkg 提供稳定的单实例布局,再由显式物化步骤消除符号链接;关闭对等依赖自动安装可防止未声明的对等依赖扩大闭包;`link-workspace-packages` 选择直接工作区依赖。[`pnpm-workspace.yaml`](../../../../pnpm-workspace.yaml) 将传递的 `@deepseek-ai/cosmokit` 与 `@deepseek-ai/schemastery` semver 请求覆盖到固定的 vendor 源码,使 legacy deploy 不会从注册表解析这些未发布名称。
[`scripts/build-exe-for-python-sdk.ts`](../../../../scripts/build-exe-for-python-sdk.ts):运行时闭包校验 → `pnpm run build` →(清空后)`pnpm --filter dsh-python-runtime-closure deploy --legacy --prod --config.allow-unused-patches=true --config.node-linker=hoisted --config.auto-install-peers=false --config.link-workspace-packages=true` **直接写入** `python/sdk-runtime/src/deepseek_harness_runtime/runtime/node/`,其中包含作为载体根目录 `runtime-bootstrap.mjs` 的 [`python/sdk-runtime/runtime-bootstrap.mjs`](../../../../python/sdk-runtime/runtime-bootstrap.mjs) → 恢复 legacy deploy 遗漏的直接工作区包,并拒绝剩余的 manifest 缺口 → 将暂存依赖中的符号链接替换为目标文件内容,删除包管理器的 `.bin` 链接,并在仍有任何符号链接时失败 → 验证已部署的 bootstrap,并注入以该文件为 bin 的 pkg 配置及覆盖动态读取 profile、bundle、前端、preset、原生库与配置文件的 assets → 暂存目标平台的 `node-pty` addon → 每个构建目标调用一次 `pkg --sea` → 将 `deepseek-harness-sdk-runtime-<platform>-<arch>` 写入 `dist-exe/`,并将它与对应目标的 Office 目录一同拷回运行时目录。该 bootstrap 由 Python runtime 拥有;普通启动时它调用公开 CLI export,而提供方私有选择会分派到同一个 `@deepseek-ai/dsh-subprocess-local/runner` 核心,不改变 CLI 语法,也不增加另一个可执行文件;[原生 containment 决策](2026-08-28-subprocess-native-containment.zh.md)负责这条私有路径。Linux CI 会在匹配的 manylinux 2.28 容器中重新构建 `pty.node`,因为 legacy deploy 会遗漏这一安装副作用。每个目标都会把对应的原生 `@vscode/ripgrep` 二进制复制到可执行文件旁,作为必需的 `-rg` 伴随文件;pkg 运行时通过 `process.pkg` 选择该伴随文件,普通 Node 执行则直接使用 `@vscode/ripgrep`。macOS 使用对应目标的预构建产物,并额外生成所需的 `-spawn-helper`。部署标志都有实测依据:未启用 `inject-workspace-packages` 时必须使用 `--legacy`;`hoisted` 为 pkg 提供稳定的单实例布局,再由显式物化步骤消除符号链接;关闭对等依赖自动安装可防止未声明的对等依赖扩大闭包;`link-workspace-packages` 选择直接工作区依赖。[`pnpm-workspace.yaml`](../../../../pnpm-workspace.yaml) 将传递的 `@deepseek-ai/cosmokit` 与 `@deepseek-ai/schemastery` semver 请求覆盖到固定的 vendor 源码,使 legacy deploy 不会从注册表解析这些未发布名称。 生产部署允许未使用的工作区补丁,因为开发工具可能不属于运行时闭包;闭包内包的补丁应用失败仍会中止部署。工作区安装继续严格校验未使用的补丁。
CI 使用 [`.github/workflows/build-exe-for-python-sdk.yml`](../../../../.github/workflows/build-exe-for-python-sdk.yml):[安装后 wheel 包验证](../testing/2026-08-23-installed-python-wheel-black-box-ci.zh.md)在拉取请求上运行 Linux/Windows x64,在 master 推送上运行 Linux ARM64 与两种 macOS 架构。[公开发布工作流](../../archived/process/2026-08-11-python-publication-workflow.md)调用它构建全部五个目标;`workflow_dispatch` 仍可选择部分目标。linux-x64、linux-arm64(`ubuntu-24.04-arm`)、macos-arm64、macos-x64(`macos-15-intel`)与 win-x64(`windows-2025`)分别进行原生构建,并在适用平台缓存 `~/.pkg-cache`;macOS 的 ad-hoc 签名由 pkg 处理。每个平台都把发布形态的 SDK wheel 包与运行时 wheel 包安装到 checkout 外的干净 venv,证明包与可执行文件来源,再通过公开 SDK 与直接 NDJSON JSON-RPC 运行完整 keyless 场景。可信拉取请求与 master 推送还会在各自选定的目标上运行真实 DeepSeek 双轮工具冒烟测试;fork 与 Dependabot head 不会获得密钥。Linux 会检查可执行文件和原生 addon 各自的 GLIBC 依赖,并额外运行 manylinux 2.28 冒烟测试;macOS 则检查 runtime、ripgrep 与 PTY helper 的架构,并验证三个载荷的部署目标都符合 wheel 包标签。完整构建五个目标时保留 6 个产物,每个产物只含一个发布文件:平台无关的 SDK wheel 包与 5 个原生运行时 wheel 包;手动选择部分目标时保留 SDK wheel 与所选运行时 wheel。裸 exe 与源码包只作为测试中间输入。[`.gitlab-ci.yml`](../../../../.gitlab-ci.yml) 只接受版本与根目录 `package.json` 匹配的 `python-v<repository-version>` 标签流水线,构建一个 SDK wheel 包和 5 个原生运行时 wheel 包,再由单个串行任务校验并将这 6 个文件发布到项目的 PyPI 注册表。[`python/sdk-runtime` README](../../../../python/sdk-runtime/README.zh.md)负责 Windows 目标及对 Windows arm64 的明确排除。
### Python SDK 分发:双载体,exe 用于生产,`node` 用于开发
Python SDK 位于 [`python/`](../../../../python/README.zh.md):`python/sdk` 是客户端,`python/sdk-runtime` 是运行时载体包。运行时包的数据目录包含构建注入的平台可执行文件及其必需的 `-rg` 伴随文件和可选的 macOS helper,以及供仓库开发使用的构建注入 `runtime/node/` 闭包树。`resolve_bundled_launch_args()` 默认选择可执行文件;显式设置 `DSH_RUNTIME_MODE=node` 会在系统 Node 22.19 或更高版本上运行 `runtime/node/node_modules/@deepseek-ai/dsh/lib/bin.js`。node 载体从不进入 wheel 分发,两种载体都不使用检入的完整 `cordis.yml`。
Python SDK 位于 [`python/`](../../../../python/README.zh.md):`python/sdk` 是客户端,`python/sdk-runtime` 是运行时载体包。运行时包的数据目录包含构建注入的平台可执行文件及其必需的 `-rg` 伴随文件、`-office/` 目录和可选的 macOS helper,以及供仓库开发使用的构建注入 `runtime/node/` 闭包树。`resolve_bundled_launch_args()` 默认选择可执行文件;显式设置 `DSH_RUNTIME_MODE=node` 会在系统 Node 22.19 或更高版本上运行 `runtime/node/node_modules/@deepseek-ai/dsh/lib/bin.js`。node 载体从不进入 wheel 分发,两种载体都不使用检入的完整 `cordis.yml`。
[`scripts/build-python-release.py`](../../../../scripts/build-python-release.py) 从仓库根目录的 `package.json` 读取权威的 `X.Y.Z` 或预发布版本,把预发布版本转换为 PEP 440 写法,并以该 wheel 包版本暂存两个包,让 `deepseek-harness-sdk` 精确依赖匹配版本的 `deepseek-harness-runtime-bin`。可选的 `python-v<repository-version>` 发布标签只是一项一致性断言,与仓库版本不同时会被拒绝;源码 `pyproject.toml` 中的开发占位版本从不决定发布版本。暂存过程还会把仓库许可证放入两个 wheel 包,并把第三方声明放入内置运行时 wheel 包。SDK 是 `py3-none-any` wheel 包;每个只提供 wheel 包的运行时包都包含一个 exe 及其架构匹配的 ripgrep 伴随文件,macOS wheel 包还包含与其架构匹配的 spawn helper。运行时 wheel 包使用 `py3-none-manylinux_2_28_x86_64`、`py3-none-manylinux_2_28_aarch64`、`py3-none-macosx_14_0_arm64`、`py3-none-macosx_14_0_x86_64` 或 `py3-none-win_amd64`;Hatch 钩子拒绝 sdist、通用标签、混合平台载荷、伴随文件缺失或多余,以及不支持的平台。两个 macOS 标签都会特意声明保守的 14.0 安装下限:打包后的 Node 24 可执行文件声明 macOS 13.5,x64 PTY helper 声明 10.7,但发布验证只按照 14.0 wheel 声明证明完整载荷,不会把各组件实测的最低版本承诺为受支持宿主。两个 macOS wheel 包仍按架构分别发布,不发布 universal2 wheel 包。
[`scripts/build-python-release.py`](../../../../scripts/build-python-release.py) 从仓库根目录的 `package.json` 读取权威的 `X.Y.Z` 或预发布版本,把预发布版本转换为 PEP 440 写法,并以该 wheel 包版本暂存两个包,让 `deepseek-harness-sdk` 精确依赖匹配版本的 `deepseek-harness-runtime-bin`。可选的 `python-v<repository-version>` 发布标签只是一项一致性断言,与仓库版本不同时会被拒绝;源码 `pyproject.toml` 中的开发占位版本从不决定发布版本。暂存过程还会把仓库许可证放入两个 wheel 包,并把第三方声明放入内置运行时 wheel 包。SDK 是 `py3-none-any` wheel 包;每个只提供 wheel 包的运行时包都包含一个 exe、其 Office 目录及架构匹配的 ripgrep 伴随文件,macOS wheel 包还包含与其架构匹配的 spawn helper。运行时 wheel 包使用 `py3-none-manylinux_2_28_x86_64`、`py3-none-manylinux_2_28_aarch64`、`py3-none-macosx_14_0_arm64`、`py3-none-macosx_14_0_x86_64` 或 `py3-none-win_amd64`;Hatch 钩子拒绝 sdist、通用标签、混合平台载荷、伴随文件缺失或多余,以及不支持的平台。两个 macOS 标签都会特意声明保守的 14.0 安装下限:打包后的 Node 24 可执行文件声明 macOS 13.5,x64 PTY helper 声明 10.7,但发布验证只按照 14.0 wheel 声明证明完整载荷,不会把各组件实测的最低版本承诺为受支持宿主。两个 macOS wheel 包仍按架构分别发布,不发布 universal2 wheel 包。
Python 客户端使用所选 profile(默认 `sdk`)、有序 patch 文件和显式 Harness home 启动打包后的 `dsh` 命令。Profile 负责 JSON-RPC 服务和应用组合;缺失 home、profile、bundle、patch 或 server 配置项都会失败,不存在外部完整配置回退。
@@ -60,17 +64,18 @@ Python 客户端使用所选 profile(默认 `sdk`)、有序 patch 文件和
`dsh-python-runtime-closure` 是私有部署 manifest,`deepseek-harness-sdk-runtime-<platform>-<arch>` 是可执行文件族。协议字段 `serverInfo.name` 是 `deepseek-harness-sdk-runtime`;Python 分发包名是 `deepseek-harness-sdk` / `deepseek-harness-runtime-bin`,导入模块名是 `deepseek_harness` / `deepseek_harness_runtime`。
## 工作线程插件
## 打包后的工作流与代码执行
exe 内支持 `dsh-workflow-worker-thread` 与 `dsh-code-runtime-worker-thread`。两个后端构建后的宿主都通过 `fileURLToPath()` 转换相邻 `lib/worker.cjs` 的 URL,再将所得文件系统字符串传给 `Worker`;pkg 的 Worker 钩子可以用这种形式解析 VFS 内文件。该钩子会把 VFS 内的工作线程文件作为 CommonJS 编译,所以工作线程入口采用 CommonJS。工作流引擎在未构建的源码执行中仍保留 `data:` URL 引导程序,只有构建后的相邻入口使用文件系统字符串。自定义配置的可执行文件冒烟测试会加载两个后端,实际调用 `run_code` 与不启动 agent(智能体)的 `workflow`,并要求两个工作线程都从 pkg 的 VFS 内返回 `42`。
`dsh-workflow-ptc` 通过 `dsh-ptc-runtime-node` 发送自包含 guest 程序。共享提供方通过可执行文件的私有 Node bootstrap 分派启动受管子进程,并使用专用控制通道;不需要独立的工作流 worker 资源。[沙箱 Node 决策](2026-09-11-sandboxed-node-ptc-runtime.zh.md)负责进程与策略生命周期,[工作流沙箱复用](2026-09-13-workflow-ptc-sandbox-reuse.zh.md)负责工作流适配器。
## 测试
验证面分三层。机制层:`--sea` 链路的实测结论内嵌在「决策」各节(VFS 内 ESM 动态 `import()`、单一 Cordis 实例、明确报错的配置链路、`node:sqlite`、macOS ad-hoc 签名可运行)。SDK 层:完整的无密钥 pytest 套件以 mock 运行时对端覆盖客户端协议、子进程清理、绝对 `cwd` 传递、双载体启动与载体解析;根 CI 在 Python 3.10 上运行全部用例。端到端层:每个平台构建都会把两个 wheel 包安装进 checkout 外的干净 venv,证明版本相同以及已安装模块/可执行文件的位置,再通过默认 SDK 路径、自定义配置、仓库内置的独立 minimal 组合和直接二进制协议,对 mock 端点完成轮次,并校验最终文本与 JSONL。minimal 运行会断言其精确系统提示词与双工具目录,跨调用保留 Bash 状态,并调用编辑器。自定义配置还会通过打包进 VFS 的真实工作线程文件执行 `run_code` 和不启动 agent 的 `workflow`。文件系统搜索场景要求模型通过目标平台的 `-rg` 伴随文件调用 `glob` 与 `grep`。spawn-node 场景驱动平台 shell 工具执行以 `node` 开头的命令,要求工具结果给出机器自身的 Node 版本且子进程环境中无 `PKG_EXECPATH`,把打包运行时钉死在「pkg 升级重录 child_process 补丁也不得回归」的行为上。MCP 场景会启动临时外部 stdio server,刻意延迟首次 `tools/list` 响应,随后立即启动第一个 SDK 提示词;该提示词必须看到并调用已发现的工具,从而证明 `initialize` 是真正以 Loader 插件树完全稳定为准的就绪边界,而不是依赖定时 sleep。同一项安装后运行还会经 Python SDK 比较一组检入的 exe 专用快照:无密钥脚本化模型挂载一个会注册工具的 Cordis 插件,从 `run_code` 调用该工具,运行一个直接 spawn 的 subagent 和一个会通过 spawn 启动第二个 subagent 的工作流,随后卸载该插件。该 fixture(测试前置数据)会显式禁用组合包中未使用的 Bash 和本地 skill(技能)发现,使其工具集不依赖仓库外部状态;比较时会规范化 SDK 结果与通知流,以及父会话和两个子会话 JSONL 日志中不透明的消息、agent、工作流运行与会话 ID。可信拉取请求会增加真实提供方双轮文件写入/读取,并要求外部字节、工具调用、已完成原因与持久化日志一致。该 harness 与 ACP 的 `pnpm run test:snapshot` 保持独立,因为二者的协议和构建产物不同。
验证面分三层。机制层:`--sea` 链路的实测结论内嵌在「决策」各节(VFS 内 ESM 动态 `import()`、单一 Cordis 实例、明确报错的配置链路、`node:sqlite`、macOS ad-hoc 签名可运行)。SDK 层:完整的无密钥 pytest 套件以 mock 运行时对端覆盖客户端协议、子进程清理、绝对 `cwd` 传递、双载体启动与载体解析;根 CI 在 Python 3.10 上运行全部用例。端到端层:每个平台构建都会把两个 wheel 包安装进 checkout 外的干净 venv,证明版本相同以及已安装模块/可执行文件的位置,再通过默认 SDK 路径、自定义配置、仓库内置的独立 minimal 组合和直接二进制协议,对 mock 端点完成轮次,并校验最终文本与 JSONL。minimal 运行会断言其精确系统提示词与单个 shell 工具目录,并跨调用保留 shell 状态。自定义配置还会通过共享的打包后 Node 进程 bootstrap 执行 `run_code` 和不启动 agent 的 `workflow`。文件系统搜索场景要求模型通过目标平台的 `-rg` 伴随文件调用 `glob` 与 `grep`。spawn-node 场景驱动平台 shell 工具执行以 `node` 开头的命令,要求工具结果给出机器自身的 Node 版本且子进程环境中无 `PKG_EXECPATH`,把打包运行时钉死在「pkg 升级重录 child_process 补丁也不得回归」的行为上。MCP 场景会启动临时外部 stdio server,刻意延迟首次 `tools/list` 响应,随后立即启动第一个 SDK 提示词;该提示词必须看到并调用已发现的工具,从而证明 `initialize` 是真正以 Loader 插件树完全稳定为准的就绪边界,而不是依赖定时 sleep。同一项安装后运行还会经 Python SDK 比较一组检入的 exe 专用快照:无密钥脚本化模型挂载一个会注册工具的 Cordis 插件,从 `run_code` 调用该工具,运行一个直接 spawn 的 subagent 和一个会通过 spawn 启动第二个 subagent 的工作流,随后卸载该插件。该 fixture(测试前置数据)会显式禁用组合包中未使用的 Bash 和本地 skill(技能)发现,使其工具集不依赖仓库外部状态;比较时会规范化 SDK 结果与通知流,以及父会话和两个子会话 JSONL 日志中不透明的消息、agent、工作流运行与会话 ID。可信拉取请求会增加真实提供方双轮文件写入/读取,并要求外部字节、工具调用、已完成原因与持久化日志一致。该 harness 与 ACP 的 `pnpm run test:snapshot` 保持独立,因为二者的协议和构建产物不同。
手工驱动注意:`bin` 将 stdin EOF 视为「客户端已离开」并立即 dispose,生命周期较短的管道会中止进行中的轮次——管道驱动必须保持 stdin 打开,直到轮次结束。
安装后 wheel 的 `sdk-office` 场景会将目标的完整载荷复制到私有临时目录,要求仅存在一个目标后端(使用已声明的原生目标,未声明原生目标时使用 WASM),并通过随附 SDK profile 使用该引擎转换一次 DOCX。它检查 kit 模块确实解析到迁移后的目录、转换报告预期后端,且输出包含 PDF 字节。wheel 校验会检查声明的引擎资源与原生辅助程序执行位;CI 上传已完成的 wheel,因此嵌套辅助程序权限保留在 ZIP 归档中。
## 曾考虑的替代方案
**裸用 Node 原生 SEA。** 注入的主脚本必须是 CJS 单文件,blob 内没有文件系统与模块解析,因此动态 `import()` 无法解析裸包名;只能把插件静态编译进主脚本并手工注册。这会绕过标准模块解析并硬编码插件集合,与「配置决定一切」相悖。最终路线实际是「官方 SEA 基础 + pkg 的 VFS/模块钩子层」;否决的是裸用方式,而不是 SEA 本身。
@@ -85,6 +90,6 @@ exe 内支持 `dsh-workflow-worker-thread` 与 `dsh-code-runtime-worker-thread`
## 后果
**买到的**:目标平台零依赖的单文件分发;插件语义与源码运行严格一致(同一棵真实包树,无转译、无注册表);对外服务接口、插件集与配置全部收敛到 `cordis.yml` 和一份依赖 manifest 这两个真源;exe 与 `node` 双载体使用同一棵树和相同语义,开发验证无需等待打包;官方 Node 二进制消除了补丁版二进制的供应链顾虑。
**买到的**:受支持目标无需依赖系统 Node.js;插件语义与源码运行严格一致(同一棵真实包树,无转译、无注册表);对外服务接口、插件集与配置全部收敛到 `cordis.yml` 和一份依赖 manifest 这两个真源;exe 与 `node` 双载体使用同一棵树和相同语义,开发验证无需等待打包;官方 Node 二进制消除了补丁版二进制的供应链顾虑。
**付出的**:产物约 174MB,且源码原样进入 blob(没有字节码混淆;闭源分发诉求需要另行评估);pkg 的 VFS/模块钩子层仍由社区维护(`@yao-pkg/pkg` 为精确钉版、带 pnpm 补丁的根 devDependency,升级需重录补丁,属显式改动);`--sea` 每个构建目标调用一次(与 CI 每个平台一个任务相匹配,本地多平台构建串行执行)。
**付出的**:大型 Office 引擎资源保留在 SEA 归档之外,可执行文件必须与必需的伴随文件一起迁移;源码原样进入分发物(没有字节码混淆;闭源分发诉求需要另行评估);pkg 的 VFS/模块钩子层仍由社区维护(`@yao-pkg/pkg` 为精确钉版、带 pnpm 补丁的根 devDependency,升级需重录补丁,属显式改动);`--sea` 每个构建目标调用一次(与 CI 每个平台一个任务相匹配,本地多平台构建串行执行)。
@@ -1,6 +1,157 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-07-12-agent-scope-runtime-design.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-12-agent-scope-runtime-design.md
2026-07-12-agent-scope-runtime-design.md: ca300d4eeeab878a4e41b8e68a669be418617181
2026-07-12-agent-scope-runtime-design.zh.md: 870690d6ace9fefd859557a2e73e88b9b1da6206
/agent-note-agent-scope-runtime-design-and-correctness:
en: b63ecbd21fc1f427
zh: 4990d96d76888802
/agent-note-agent-scope-runtime-design-and-correctness/problem:
en: ae7b688bd991a6df
zh: 73b6b28755852054
/agent-note-agent-scope-runtime-design-and-correctness/decision:
en: cfd6abca8404c7d4
zh: a9372aae85e49f55
/agent-note-agent-scope-runtime-design-and-correctness/cordis-model-context-fiber-effect-receiver-and-waterfall:
en: 4d4bdb629a57139d
zh: 7b4d21d9eb42d94b
/agent-note-agent-scope-runtime-design-and-correctness/cordis-model-context-fiber-effect-receiver-and-waterfall/a-context-is-an-ownership-path-through-one-service-graph:
en: 201a1882518455e2
zh: 830e25eab7ed37db
/agent-note-agent-scope-runtime-design-and-correctness/cordis-model-context-fiber-effect-receiver-and-waterfall/fibers-and-effects-make-cleanup-structural:
en: d0ef6e1b5d453350
zh: 4a774ac9daf20849
/agent-note-agent-scope-runtime-design-and-correctness/cordis-model-context-fiber-effect-receiver-and-waterfall/receivers-route-listeners-waterfalls-compose-decisions:
en: 594e198a8b566049
zh: 50378e7a2a533dff
/agent-note-agent-scope-runtime-design-and-correctness/scope-routing-one-opaque-key-selects-one-layer:
en: fa59d22549e9e44a
zh: 80904729042e87b3
/agent-note-agent-scope-runtime-design-and-correctness/scope-routing-one-opaque-key-selects-one-layer/scope-identity-uses-object-identity:
en: 3a05a7bfb2197f58
zh: fbb599031788b70b
/agent-note-agent-scope-runtime-design-and-correctness/scope-routing-one-opaque-key-selects-one-layer/registry-reads-overlay-one-exact-layer:
en: 28636ae6d55935d7
zh: 33a989f049de2f3e
/agent-note-agent-scope-runtime-design-and-correctness/scope-routing-one-opaque-key-selects-one-layer/fused-dispatch-helpers-prevent-subject-drift:
en: 638e3711206e3c41
zh: 61d370123d30c1ed
/agent-note-agent-scope-runtime-design-and-correctness/agent-creation-one-transaction-owns-the-complete-operation:
en: ef58215c8554180b
zh: 44571074148d2467
/agent-note-agent-scope-runtime-design-and-correctness/agent-creation-one-transaction-owns-the-complete-operation/registry-entries-are-the-only-live-identity-records:
en: 092b49671e83df98
zh: 330ea6e45c4deb99
/agent-note-agent-scope-runtime-design-and-correctness/agent-creation-one-transaction-owns-the-complete-operation/the-transaction-owns-preparation-before-awaiting-it:
en: 3940920908ec6066
zh: 888e36ca43611d30
/agent-note-agent-scope-runtime-design-and-correctness/agent-creation-one-transaction-owns-the-complete-operation/setup-is-trusted-composition-inside-a-private-world:
en: 40a73b8eede856ee
zh: 7dab8f2548cb92ea
/agent-note-agent-scope-runtime-design-and-correctness/agent-creation-one-transaction-owns-the-complete-operation/publication-has-one-ordered-commit-path:
en: 227eff7a5adacd0e
zh: b9ee423c2dd4212f
/agent-note-agent-scope-runtime-design-and-correctness/agent-creation-one-transaction-owns-the-complete-operation/teardown-preserves-work-before-revoking-registrations:
en: 1cbe77cff192815d
zh: 7f517936a8aa469e
/agent-note-agent-scope-runtime-design-and-correctness/session-append-materialize-validate-commit-notify:
en: cc37e93081fea4cb
zh: daf2234f84e4c9bf
/agent-note-agent-scope-runtime-design-and-correctness/session-append-materialize-validate-commit-notify/durable-data-is-materialized-once:
en: d0a57b0ac227d84c
zh: e9ae6ced0e65fe49
/agent-note-agent-scope-runtime-design-and-correctness/session-append-materialize-validate-commit-notify/pre-commit-listeners-can-veto-post-commit-observers-cannot:
en: 15255d3d0b62fac0
zh: c1995d5aa3c78f0a
/agent-note-agent-scope-runtime-design-and-correctness/trust-boundaries-copy-only-when-ownership-actually-changes:
en: 22b381902fe903f3
zh: 8a2efe9a8b458bba
/agent-note-agent-scope-runtime-design-and-correctness/tools-and-prompts-one-view-authoritative-assembly-committed-outcomes:
en: 456ac0359d3c02f6
zh: 9099e15d22139751
/agent-note-agent-scope-runtime-design-and-correctness/tools-and-prompts-one-view-authoritative-assembly-committed-outcomes/one-resolver-defines-the-tool-view:
en: 120e1c79f0b99b1a
zh: 1c21a5b1d6b08235
/agent-note-agent-scope-runtime-design-and-correctness/tools-and-prompts-one-view-authoritative-assembly-committed-outcomes/tool-execution-owns-identity-and-boundary-materialization:
en: 41f1f2ad73d83d73
zh: e6bff63958ede05e
/agent-note-agent-scope-runtime-design-and-correctness/tools-and-prompts-one-view-authoritative-assembly-committed-outcomes/the-assembly-waterfall-owns-the-final-model-visible-composition:
en: 5c5880ccea139058
zh: 3e5b7d10cb4c6ff8
/agent-note-agent-scope-runtime-design-and-correctness/tools-and-prompts-one-view-authoritative-assembly-committed-outcomes/structured-output-commits-only-authoritative-outcomes:
en: a9a711cf31559765
zh: e9083b000fc89128
/agent-note-agent-scope-runtime-design-and-correctness/tools-and-prompts-one-view-authoritative-assembly-committed-outcomes/three-execution-boundaries-are-deliberately-one-way:
en: a109f3fadf338061
zh: 12eb46fe775fa46a
/agent-note-agent-scope-runtime-design-and-correctness/tools-and-prompts-one-view-authoritative-assembly-committed-outcomes/skill-and-approval-services-trust-typed-callers:
en: 9572833d47f779e6
zh: 7ff491d309060030
/agent-note-agent-scope-runtime-design-and-correctness/subagents-publication-is-the-start-promise:
en: b9216021f8f50bcc
zh: fda52f9434cc8191
/agent-note-agent-scope-runtime-design-and-correctness/subagents-publication-is-the-start-promise/the-service-contract-has-one-cancellation-channel:
en: 84a4be83b78c045b
zh: 043e14cf628413cd
/agent-note-agent-scope-runtime-design-and-correctness/subagents-publication-is-the-start-promise/in-process-providers-reuse-the-core-transaction:
en: b5e0b3dcf0dff750
zh: 63905010383781b9
/agent-note-agent-scope-runtime-design-and-correctness/subagents-publication-is-the-start-promise/acp-providers-own-the-process-until-readiness-or-cleanup:
en: aa0c00cee368c7e6
zh: 767539b0f4d56f55
/agent-note-agent-scope-runtime-design-and-correctness/workflows-and-acp-processes-retain-only-independent-async-facts:
en: effbb0acf7f66bed
zh: e0cc9ad6ac0777de
/agent-note-agent-scope-runtime-design-and-correctness/workflows-and-acp-processes-retain-only-independent-async-facts/workflow-children-are-pending-starts-or-published-records:
en: 9f05eed800f3413c
zh: 8230a28a0f94bffa
/agent-note-agent-scope-runtime-design-and-correctness/workflows-and-acp-processes-retain-only-independent-async-facts/terminal-result-and-physical-cleanup-remain-separate:
en: 5ad141c6df9f4fc3
zh: 63effa4f14f3c530
/agent-note-agent-scope-runtime-design-and-correctness/workflows-and-acp-processes-retain-only-independent-async-facts/acp-prompt-settlement-does-not-depend-on-update-delivery:
en: d39f73f50f0370bd
zh: 3889c1db46de560e
/agent-note-agent-scope-runtime-design-and-correctness/correctness-enforcement:
en: 840564e766d2f05c
zh: 059243afea7eb9c0
/agent-note-agent-scope-runtime-design-and-correctness/correctness-enforcement/types-make-the-ordinary-path-hard-to-misuse:
en: 9183eb29dddfd97f
zh: e6ce13295e6c3e65
/agent-note-agent-scope-runtime-design-and-correctness/correctness-enforcement/runtime-invariants-cover-cross-service-facts:
en: fabafbebc0ab4f95
zh: 06d94a98ed5aa40c
/agent-note-agent-scope-runtime-design-and-correctness/correctness-enforcement/generated-artifacts-keep-public-contracts-aligned:
en: d0ddc5f38289225d
zh: 781d910228d5e334
/agent-note-agent-scope-runtime-design-and-correctness/alternatives-considered:
en: 5eef7873a795c8f0
zh: 3e8ba109a6e29ba5
/agent-note-agent-scope-runtime-design-and-correctness/alternatives-considered/use-a-transparent-proxy-as-the-scope-carrier:
en: 199c7345a237e7e9
zh: b262d5ad0c7cb562
/agent-note-agent-scope-runtime-design-and-correctness/alternatives-considered/reserve-agent-and-session-ids-before-setup:
en: 3a8cb6969139dd84
zh: 2913bb68433c9ec7
/agent-note-agent-scope-runtime-design-and-correctness/alternatives-considered/snapshot-every-typed-same-process-argument:
en: 3e1f19f909f8d138
zh: 0727777e34964afe
/agent-note-agent-scope-runtime-design-and-correctness/alternatives-considered/give-readiness-cancellation-and-disposal-separate-controllers:
en: f2c6ecbd139bbdb0
zh: 0ff5b1e192dcb376
/agent-note-agent-scope-runtime-design-and-correctness/alternatives-considered/keep-synchronous-subagent-start-plus-run-started:
en: 7f5669933cb35c9c
zh: c55e35d4c175af36
/agent-note-agent-scope-runtime-design-and-correctness/alternatives-considered/restore-selected-prompt-or-tool-contributions-after-assembly:
en: a2b2e48d9ccda310
zh: 3a4e925fde9d05b0
/agent-note-agent-scope-runtime-design-and-correctness/alternatives-considered/remove-worker-process-lifecycle-guards-with-same-process-hardening:
en: 662e0904d90a3a94
zh: 84c5e49f7cc59b32
/agent-note-agent-scope-runtime-design-and-correctness/consequences:
en: 0d781b2dc4c41ddb
zh: 844652a4aaac37aa
/agent-note-agent-scope-runtime-design-and-correctness/consequences/what-the-design-guarantees:
en: eb2001592d7bd7b1
zh: e534dbb6daa9af32
/agent-note-agent-scope-runtime-design-and-correctness/consequences/costs-and-limits:
en: e9383713d56b9e10
zh: d3ab00aea8ecf4e0
@@ -60,6 +60,8 @@ Product helpers therefore construct the carrier and pass the domain subject sepa
A Cordis waterfall is middleware-style dispatch. Each listener receives `next()`: calling it delegates to the remaining listeners and base operation, while returning without it short-circuits or replaces the downstream result. Waterfalls power prompt assembly and tool policy; ordinary emit events notify synchronously, and parallel events await all listeners without a veto result.
<a id="scope-routing-one-opaque-key-selects-one-layer"></a>
## Scope routing: one opaque key selects one layer
The scope package implements the smallest object needed for Cordis routing. Its carrier holds only a composed service filter and scope predicate, while the package records the opaque key privately and exposes the scope fiber's quiescent disposer separately.
@@ -117,30 +119,28 @@ Publication admits and announces resources in the order required by observers:
1. Enter the session.
2. Enter the agent.
3. Announce `session/created`.
4. Announce `agent/created`.
5. Enable public driving.
6. Emit `agent/session-start`.
7. Start the driver.
4. Await serial `agent/created` listeners.
5. Release queued input to the driver.
The agent never drives before both registries and creation notifications agree. A synchronous listener may veto or dispose an owner; the transaction records publication in progress and waits for that callback stack to unwind before teardown continues. Every creation announcement that begins has a matching disposal announcement during rollback.
The agent never drives before both registries and creation listeners finish. A listener may reject or dispose an owner; the transaction retains the scope and session until dispatch settles before teardown continues. Every creation announcement that begins has a matching disposal announcement during rollback. The [awaited creation decision](2026-09-09-awaited-agent-creation.md) owns asynchronous initializer timing.
The sequence diagram isolates the non-obvious race: a synchronous creation listener can request disposal while the publication call stack still owns both registry entries. Teardown must deactivate immediately but wait for that stack to unwind before stopping and detaching anything.
A creation listener can request disposal while publication still owns both registry entries. Teardown deactivates immediately and waits for the awaited dispatch before stopping and detaching anything.
```mermaid
sequenceDiagram
participant Tx as AgentCreationTransaction
participant Registries
participant Listener as Synchronous listener
participant Listener as Creation listener
participant Driver
Tx->>Tx: mark publication in progress
Tx->>Registries: announce agent/created
Registries->>Listener: invoke inside the same call stack
Registries->>Listener: await listener
Listener->>Tx: dispose reentrantly
Tx->>Tx: deactivate, teardown waits for publication
Tx-->>Listener: disposal request accepted
Listener-->>Registries: return
Registries-->>Tx: announcement unwound
Listener-->>Registries: settle
Registries-->>Tx: dispatch settled
Tx->>Tx: resolve publication settlement
Tx->>Driver: stop and drain
Tx->>Registries: detach agent, then session
@@ -151,7 +151,7 @@ sequenceDiagram
Every teardown request joins one memoized path. The order is:
1. Deactivate creation or driving and let synchronous publication finish.
1. Deactivate creation or driving and await creation dispatch.
2. Stop and drain the driver, discarding any injection that remains pending.
3. Detach the agent.
4. Detach the session.
@@ -160,6 +160,8 @@ Every teardown request joins one memoized path. The order is:
This order lets final agent and session events use the matching scoped listeners and keeps persistence observers attached through the final flush. Scope disposal comes last because registration revocation is the externally visible lifetime boundary.
<a id="session-append-materialize-validate-commit-notify"></a>
## Session append: materialize, validate, commit, notify
Session events cross a durable boundary, so append owns their data. The rest of the algorithm uses one attached entry and one commit point.
@@ -232,6 +234,8 @@ This is a trusted same-process extension point, not an authority boundary. A lis
Scope solves the real isolation problem directly. Structured-output contributions register in the child's exact scope, while PTC mode derives its transport and SDK from the same resolved tool view. A second named-protection system would need another ownership and collision rule across arbitrary schema providers—including providers that intentionally contribute duplicate names—without creating a new trust boundary.
<a id="structured-output-commits-only-authoritative-outcomes"></a>
### Structured output commits only authoritative outcomes
Structured output combines child-scoped composition with a two-phase execution commit. The child registers its `structured_output` tool and instruction before publication; a trusted assembly listener may transform those ordinary contributions and is responsible for preserving the protocol if the child is expected to complete. The tool body validates a candidate and stages it by the current `ToolExecution`, but successful capture is decided only by immutable `tools/result` observations.
@@ -244,6 +248,8 @@ Once a value is pending or committed, a scoped monotonic guard denies later tool
Pure PTC mode's registry contribution omits `structured_output` from native wire schemas and exposes it through the generated SDK. The assembly waterfall may deliberately change that presentation; execution still validates against the child-scoped definition, and the listener owns the consistency of any alternate model-visible route it creates.
<a id="three-execution-boundaries-are-deliberately-one-way"></a>
### Three execution boundaries are deliberately one-way
Prompt assembly is intentionally cooperative, but three execution facts need one-way settlement after their extensible stages:
@@ -294,19 +300,21 @@ Start resolves only after `initialize` and `newSession` succeed. Abort, spawn fa
Worker and child-process bridges need more state than same-process registries because messages, process death, and cleanup can settle independently. Their state is organized around those real facts rather than duplicate cancellation protocols.
<a id="workflow-children-are-pending-starts-or-published-records"></a>
### Workflow children are pending starts or published records
The workflow host keeps pending provider-start promises and published child records. A child moves from pending to published only when async `SubagentRuntime.start()` fulfills; rejected starts clean their partial provider work and produce no child lifecycle pair.
One host-owned AbortController supplies the required signal to pending and live children. Closing workflow admission aborts that signal, so there is no duplicate `ChildCancel` worker RPC or explicit host-side `run.cancel()` fanout. Quiescence waits for both pending starts and published child disposal.
One host-owned AbortController supplies the required signal to pending and live children. Closing workflow admission aborts that signal; quiescence waits for both pending starts and published child disposal. [Workflow sandbox reuse](2026-09-13-workflow-ptc-sandbox-reuse.md) owns PTC process cancellation and the absence of a separate workflow cleanup timer.
The worker boundary still serializes requests and outcomes. The host retains first-terminal-outcome arbitration, exact child accounting, worker-death handling, grace termination, late/duplicate message rejection, and bounded cleanup because result receipt, worker exit, and child quiescence are genuinely independent facts.
PTC serializes requests and outcomes and owns process termination. The workflow adapter retains terminal-outcome arbitration and child ownership because program settlement, process exit and child quiescence remain independent facts.
### Terminal result and physical cleanup remain separate
The workflow result records the first accepted terminal outcome according to the public precedence rules. Cleanup can continue after that result is chosen: live children still need disposal, a worker still needs termination, and a slow external backend may outlive the configured grace bound.
The workflow result records the first accepted terminal outcome according to the public precedence rules. Choosing that outcome does not release resources: the PTC process and live children still need cleanup, and child disposal must fulfill its provider contract.
Public disposal claims its memoized promise before invoking callbacks. Worker death closes admission before processing any queued late child request, synthesizes missing lifecycle ends, and starts child/process cleanup without rewriting an outcome already claimed.
Public disposal joins one cleanup operation. Run settlement closes child admission, synthesizes missing lifecycle ends and cleans up children without rewriting an outcome already claimed.
### ACP prompt settlement does not depend on update delivery
@@ -334,7 +342,7 @@ The plugin does not police trusted setup by scanning registries or reject prompt
The event catalog, service catalog, producer/consumer matrix, configuration catalog, module graph, tool catalog, type-equivalence blocks, and scoped-event resolver map are generated or freshness-gated from source. The [TypeScript semantic-gates Agent Note](../../archived/process/2026-07-14-typescript-program-backed-semantic-gates.md) owns Program construction, semantic event discovery, and resolver-generation rules.
Behavioral tests pin scoped routing and disposal, final-entry collision cleanup, publication rollback, ordered quiescence, durable pre/post-commit behavior, live tool filtering across presentation and execution, cooperative prompt assembly, structured-output commit in native and PTC mode, async subagent startup and signal cancellation, worker terminal arbitration, ACP settlement, and process teardown.
Behavioral tests pin scoped routing and disposal, final-entry collision cleanup, publication rollback, ordered quiescence, durable pre/post-commit behavior, live tool filtering across presentation and execution, cooperative prompt assembly, structured-output commit in native and PTC mode, async subagent startup and signal cancellation, workflow terminal arbitration, ACP settlement, and process teardown.
## Alternatives considered
@@ -119,30 +119,28 @@ Setup 接收完整的子上下文和确切的未发布 Agent,可以等待插
1. 将会话写入注册表。
2. 将 agent 写入注册表。
3. 宣告 `session/created`。
4. 宣告 `agent/created`。
5. 启用公开驱动。
6. 发射 `agent/session-start`。
7. 启动 driver。
4. 等待串行 `agent/created` 监听器。
5. 向驱动器释放已排队输入。
Agent 在两个注册表和创建通知都达成一致之前绝不驱动。同步监听器可以否决或 dispose 一个所有者;事务记录发布进行中,并等待该回调栈展开后再继续拆除。每个已开始的创建宣告在回滚期间都有匹配的销毁宣告。
Agent 在两个注册表与创建监听器都完成前绝不驱动。监听器可以拒绝或 dispose 一个所有者;事务保留作用域与会话,等待分发结算后再继续拆除。每个已开始的创建宣告在回滚期间都有匹配的销毁宣告。[可等待创建决策](2026-09-09-awaited-agent-creation.zh.md)拥有异步初始化器时序。
以下序列图隔离了非显而易见的竞态:同步创建监听器可以在发布调用栈仍拥有两个注册表条目时请求 dispose。拆除必须立即停用,但要等待该栈展开后才停止和分离任何东西。
创建监听器可以在发布仍拥有两个注册表条目时请求 dispose。Teardown 会立即停用,并等待所调用的异步分发完成后才停止和分离资源。
```mermaid
sequenceDiagram
participant Tx as AgentCreationTransaction
participant Registries
participant Listener as Synchronous listener
participant Listener as Creation listener
participant Driver
Tx->>Tx: mark publication in progress
Tx->>Registries: announce agent/created
Registries->>Listener: invoke inside the same call stack
Registries->>Listener: await listener
Listener->>Tx: dispose reentrantly
Tx->>Tx: deactivate, teardown waits for publication
Tx-->>Listener: disposal request accepted
Listener-->>Registries: return
Registries-->>Tx: announcement unwound
Listener-->>Registries: settle
Registries-->>Tx: dispatch settled
Tx->>Tx: resolve publication settlement
Tx->>Driver: stop and drain
Tx->>Registries: detach agent, then session
@@ -153,7 +151,7 @@ sequenceDiagram
每个拆除请求加入一条记忆化路径。顺序为:
1. 停用创建或驱动,让同步发布完成。
1. 停用创建或驱动,并等待创建分发。
2. 停止并排空 driver,丢弃仍处于待处理状态的注入。
3. 分离 agent。
4. 分离会话。
@@ -308,15 +306,15 @@ Worker 和子进程桥接比同进程注册表需要更多状态,因为消息
工作流宿主保持待定的提供方 start promise 和已发布的子级记录。子级仅在异步 `SubagentRuntime.start()` 兑现时才从待定变为已发布;被拒绝的 start 清理其部分提供方工作且不产生子级生命周期对。
一个宿主拥有的 AbortController 向待定和活跃子级提供必需的 signal。关闭工作流准入中止该 signal,因此没有重复的 `ChildCancel` worker RPC 或显式的宿主侧 `run.cancel()` 扇出。完全停稳需要等待待定 start 和已发布子级 dispose 两者。
一个宿主拥有的 AbortController 向待定和活跃子级提供必需的 signal。关闭工作流准入中止该 signal;完全停稳需要等待待定 start 和已发布子级 dispose 两者。[工作流沙箱复用](2026-09-13-workflow-ptc-sandbox-reuse.zh.md)负责 PTC 进程取消和不另设工作流清理定时器的规则。
Worker 边界仍然序列化请求和结果。宿主保留首个终端结果仲裁、精确的子级计数、worker 死亡处理、优雅终止、迟到/重复消息拒绝和有界清理,因为结果接收、worker 退出和子级完全停稳是真正独立的事实。
PTC 序列化请求和结果并负责进程终止。工作流适配器保留终态结果仲裁和子级归属,因为程序结算、进程退出和子级完全停稳仍是独立事实。
### 终端结果与物理清理保持分离
工作流结果按公开优先级规则记录首个被接受的终端结果。该结果选定后清理可以继续:活跃子级仍需 dispose,worker 仍需终止,慢速外部后端可能超出配置的优雅期限。
工作流结果按公开优先级规则记录首个被接受的终端结果。选定结果不会释放资源:PTC 进程和活跃子级仍需清理,子级资源释放必须履行其提供方约定。
公开 dispose 在调用回调之前取得其记忆化 promise 的所有权。Worker 死亡在处理任何排队的迟到子级请求之前关闭准入,合成缺失的生命周期结束,并启动子级/进程清理而不重写已声明的结果。
公开 dispose 汇入同一个清理操作。运行结算关闭子级准入,合成缺失的生命周期结束并清理子级,不重写已经认领的结果。
### ACP 提示词结算不依赖更新投递
@@ -344,7 +342,7 @@ TypeScript 无法管控 JavaScript 强制转换、直接 Cordis dispatch、进
事件目录、服务目录、生产者/消费方矩阵、配置目录、模块图、工具目录、type-equiv 块和作用域事件解析器映射都是从源码生成或受新鲜度门禁约束的。[TypeScript 语义门禁 Agent Note](../../archived/process/2026-07-14-typescript-program-backed-semantic-gates.md) 拥有 Program 构造、语义事件发现和解析器生成规则。
行为测试固定了作用域路由和 dispose、最终写入注册表时的碰撞清理、发布回滚、有序完全停稳、持久化前/后提交行为、跨展示和执行的活跃工具过滤、协作式提示词组装、原生和 PTC mode 中的结构化输出提交、异步 subagent 启动和信号取消、worker 终端仲裁、ACP 结算和进程拆除。
行为测试固定了作用域路由和 dispose、最终写入注册表时的碰撞清理、发布回滚、有序完全停稳、持久化前/后提交行为、跨展示和执行的活跃工具过滤、协作式提示词组装、原生和 PTC mode 中的结构化输出提交、异步 subagent 启动和信号取消、工作流终态仲裁、ACP 结算和进程拆除。
## 曾考虑的替代方案
@@ -1,6 +1,37 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-07-14-provider-routed-llm-adapters.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-14-provider-routed-llm-adapters.md
2026-07-14-provider-routed-llm-adapters.md: 4cc3cc3cdceeefdfea864ccf3465e528e32159c7
2026-07-14-provider-routed-llm-adapters.zh.md: 098a6af7c951c6dee8a1b4f948bc69725e8d189c
/agent-note-provider-routed-llm-adapters-and-a-generic-pi-ai-backend:
en: e57698907c40f783
zh: 47004d8f68af1d7d
/agent-note-provider-routed-llm-adapters-and-a-generic-pi-ai-backend/problem:
en: 2e51f5fa703b0677
zh: 385937219b88c447
/agent-note-provider-routed-llm-adapters-and-a-generic-pi-ai-backend/decision:
en: a15c7c13f167e5ac
zh: 63bcc2ef60c2f344
/agent-note-provider-routed-llm-adapters-and-a-generic-pi-ai-backend/decision/provider-is-the-adapter-registration-key:
en: 4921a060c657b790
zh: 2f9632469c6f0b60
/agent-note-provider-routed-llm-adapters-and-a-generic-pi-ai-backend/decision/explicit-pi-ai-provider-profiles:
en: 5461685553dac663
zh: e5c7e0ad7ac84e29
/agent-note-provider-routed-llm-adapters-and-a-generic-pi-ai-backend/decision/recorded-assistant-route-and-replay-state:
en: 8439e90c9f6d7642
zh: daeda3ce5146c9f5
/agent-note-provider-routed-llm-adapters-and-a-generic-pi-ai-backend/decision/propagate-the-target-through-every-request-producer:
en: ba1908bc1517ed23
zh: 1c9353a422cf74e1
/agent-note-provider-routed-llm-adapters-and-a-generic-pi-ai-backend/alternatives-considered:
en: ad0d610ea92aa9b8
zh: fe09d62762e73f01
/agent-note-provider-routed-llm-adapters-and-a-generic-pi-ai-backend/consequences:
en: a0c98bced8a5e6fb
zh: 23caf082a08ba507
/agent-note-provider-routed-llm-adapters-and-a-generic-pi-ai-backend/testing:
en: 5a36121f12701d08
zh: 90f0f8ed44f7234f
/agent-note-provider-routed-llm-adapters-and-a-generic-pi-ai-backend/risks:
en: 11db2a349f9f26c2
zh: 550d6017d8639854
@@ -30,7 +30,7 @@ A provider has exactly one adapter owner in a Cordis context. `dsh-llm-deepseek`
`dsh-llm-pi-ai` takes one non-empty list of provider profiles. Provider names must be unique within the list and present in pi-ai's `getProviders()` result. Each profile contains the provider name plus optional `apiKey`, `baseURL`, headers, reasoning level and budgets, cache retention, transport, SDK timeouts, a Harness stream-idle timeout, and a provider-owned `retryPolicy`. The adapter forces pi-ai's `maxRetries` to zero so one `stream()` call makes one visible provider attempt, while `dsh-llm-retry` executes the resolved policy at the agent failed-step extension point. Credentials are never global: an explicit key applies only to its profile, while an absent key lets pi-ai resolve its standard environment variable, OAuth token, AWS credential chain, Google ADC, or other provider-native ambient authentication. An explicitly empty key is invalid configuration rather than an environment fallback.
The plugin registers all configured provider names against one `PiAiAdapter` in one all-or-nothing call. A request uses its provider to select the matching profile and finds its model in `getModels(provider)` to obtain the catalog descriptor. An unknown provider fails at plugin load; an unknown model fails before network I/O with `UNKNOWN_MODEL`. The catalog object is never mutated. When a profile supplies `baseURL`, the adapter clones the selected descriptor and overrides only `baseUrl`, so a private endpoint can retain pi-ai's API, capabilities, compatibility flags, context limits, and reasoning map. The private endpoint must implement the selected provider's protocol, and the model id must still exist in the installed pi-ai catalog.
The plugin registers configured provider names against one `PiAiAdapter` in one atomic call. Each immutable request snapshot combines the effective profiles and their serviceable model descriptors. Catalog-external models require an explicit or inferable protocol and endpoint. Stored catalog errors remain visible and repairable under the [settings catalog recovery decision](../bug-fix/2026-09-07-pi-ai-settings-catalog-recovery.md), while writes validate changed providers and requests reject the selected failed model before network I/O.
The adapter calls pi-ai's `streamSimple()` so each catalog model chooses its registered API implementation, including OpenAI Responses instead of Chat Completions where the descriptor says `openai-responses`. Harness temperature, maximum tokens, signal, session id, and the profile's common stream options flow through directly. Profile headers merge with the mandatory Harness attribution headers, with Harness attribution winning its reserved names. The adapter no longer maintains DeepSeek-specific payload rewrites or a provider-protocol matrix.
@@ -54,7 +54,7 @@ Compaction configuration gains `summarizationProvider` beside `summarizationMode
The JSON-RPC runtime receives provider and model explicitly. Its convenience fallback mounts `dsh-llm-deepseek` only for provider `deepseek` when that provider has no registered owner; other missing providers fail without guessing an adapter.
Current v1 seed/load validation rejects request headers and assistant messages that omit required provider/model fields. The frozen v0-to-v1 edge requires the same reconstructable routing identity before migration; it never guesses a missing provider or model, and malformed shapes refuse before publication.
Current seed/load validation rejects request headers and assistant messages that omit required provider/model fields. The frozen v0-to-v1 edge requires the same reconstructable routing identity before migration; it never guesses a missing provider or model, and malformed shapes refuse before publication.
## Alternatives considered
@@ -78,7 +78,7 @@ Current v1 seed/load validation rejects request headers and assistant messages t
- pi-ai credentials, transport knobs, SDK timeouts, and the five-minute-default `streamIdleTimeoutMs` watchdog are scoped per provider profile. Hidden provider retries are disabled; bounded retries belong to the separately composed agent recovery policy.
- `dsh-llm-pi-ai` rejects stop sequences because pi-ai's common stream API cannot express them; the native DeepSeek adapter retains its stop support.
- Replay state is portable only within the adapter instance that owns both the historical and target providers. Cross-provider and cross-model restoration is an adapter responsibility, and another adapter receives provider-neutral history without the opaque state.
- Current v1 Session JSONL requires provider/model on request headers and assistant messages. The v0 edge migrates only frozen shapes that already carry reconstructable request identity.
- Current Session JSONL requires provider/model on request headers and assistant messages. The v0 edge migrates only frozen shapes that already carry reconstructable request identity.
## Testing
@@ -30,7 +30,7 @@ Status: implemented
`dsh-llm-pi-ai` 接受一个非空的提供方配置列表。列表内的提供方名称必须唯一,并且存在于 pi-ai 的 `getProviders()` 结果中。每项配置包含提供方名称,以及可选的 `apiKey`、`baseURL`、headers、推理级别和预算、缓存保留设置、传输方式、SDK 超时、Harness 流空闲超时,以及由提供方拥有的 `retryPolicy`。适配器强制将 pi-ai 的 `maxRetries` 设为零,使一次 `stream()` 调用只发起一次可见的提供方请求;`dsh-llm-retry` 则在 agent 失败步骤扩展点上执行解析后的策略。凭据不设全局值:显式密钥仅对所属配置生效;未提供密钥时,pi-ai 使用标准环境变量、OAuth token、AWS 凭据链、Google ADC 或其他提供方原生环境认证。显式空密钥属于无效配置,不会回退到环境认证。
插件通过一次全有或全无调用,将所有已配置的提供方名称注册到同一个 `PiAiAdapter`。请求按 provider 选择对应配置,并在 `getModels(provider)` 中查找模型以取得目录描述符。未知提供方会在插件加载时失败;未知模型会在网络 I/O 前以 `UNKNOWN_MODEL` 失败。适配器不会修改目录对象。当配置提供 `baseURL` 时,适配器复制选中的描述符,仅覆盖 `baseUrl`,使私有端点保留 pi-ai 的 API、能力、兼容标志、上下文限制与推理映射。私有端点必须实现所选提供方的协议,模型 ID 也仍须存在于已安装的 pi-ai 目录中。
插件通过一次原子调用,将已配置的提供方名称注册到同一个 `PiAiAdapter`。每个不可变请求快照组合有效 profile 与可服务模型的描述符。目录外模型需要显式指定或可推断的协议与端点。根据[设置目录恢复决策](../bug-fix/2026-09-07-pi-ai-settings-catalog-recovery.zh.md),已存储的目录错误保持可见、可修复,写入仍会校验已修改提供方,请求则在网络 I/O 前拒绝所选错误模型。
适配器调用 pi-ai 的 `streamSimple()`,因此每个目录模型会选择其注册的 API 实现;描述符为 `openai-responses` 时使用 OpenAI Responses,而非 Chat Completions。Harness 的 temperature、最大 token 数、signal、session ID,以及提供方配置中的通用流选项均直接传递。配置 headers 与 Harness 强制归因 headers 合并;发生保留名称冲突时,以 Harness 归因为准。适配器不再维护 DeepSeek 专用 payload 重写或提供方协议矩阵。
@@ -54,7 +54,7 @@ pi-ai 回放状态用其成功 `AssistantMessage` 的带版本最小投影填充
JSON-RPC 运行时显式接收提供方与模型。仅当 `deepseek` 提供方没有注册所有者时,其便利回退才会挂载 `dsh-llm-deepseek`;其他缺失的提供方会直接失败,不会猜测适配器。
当前 v1 的 seed/load 验证会拒绝省略必需提供方/模型字段的请求头和助手消息。冻结的 v0-to-v1 迁移边要求迁移前已具备同一套可重建路由身份;它绝不会猜测缺失的提供方或模型,畸形结构会在发布前被拒绝。
当前的 seed/load 验证会拒绝省略必需提供方/模型字段的请求头和助手消息。冻结的 v0-to-v1 迁移边要求迁移前已具备同一套可重建路由身份;它绝不会猜测缺失的提供方或模型,畸形结构会在发布前被拒绝。
## 考虑过的替代方案
@@ -78,7 +78,7 @@ JSON-RPC 运行时显式接收提供方与模型。仅当 `deepseek` 提供方
- pi-ai 凭据、传输选项、SDK 超时,以及默认五分钟的 `streamIdleTimeoutMs` 空闲超时机制均按提供方配置隔离。系统禁用隐藏的提供方重试;有界重试由单独组合的 agent 恢复策略负责。
- pi-ai 的通用流 API 无法表达停止序列,因此 `dsh-llm-pi-ai` 会拒绝停止序列;原生 DeepSeek 适配器仍支持停止序列。
- 仅当历史提供方与目标提供方归同一个适配器实例所有时,回放状态才可移植。适配器负责跨提供方和跨模型恢复;其他适配器只接收不含不透明状态的提供方无关历史。
- 当前 v1 Session JSONL 要求请求头和助手消息都包含提供方/模型。v0 边只迁移已经携带可重建请求身份的冻结结构。
- 当前 Session JSONL 要求请求头和助手消息都包含提供方/模型。v0 边只迁移已经携带可重建请求身份的冻结结构。
## 测试
@@ -1,6 +1,22 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-07-15-agent-initiator-scope.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-15-agent-initiator-scope.md
2026-07-15-agent-initiator-scope.md: ab11da116a463cd706418e797eb58f1bc4ab9b1c
2026-07-15-agent-initiator-scope.zh.md: 343acba5f99379b6d2c3af41368e8fbe90b20611
/agent-note-initiating-agent-scope-over-asynclocalstorage:
en: b0a59e3a34c41826
zh: 7131428a14901d14
/agent-note-initiating-agent-scope-over-asynclocalstorage/problem:
en: a26991200892c735
zh: 04a7dfaca64e3f0c
/agent-note-initiating-agent-scope-over-asynclocalstorage/decision:
en: 43a4f0c503b30d95
zh: a6a780584f94ed73
/agent-note-initiating-agent-scope-over-asynclocalstorage/verification:
en: 312f5c4b843d515e
zh: a8993e3b84844fab
/agent-note-initiating-agent-scope-over-asynclocalstorage/alternatives-considered:
en: fd2ae1369fb3fbc6
zh: e2a3d7f9331fc8ac
/agent-note-initiating-agent-scope-over-asynclocalstorage/consequences:
en: 625c6afc49489e29
zh: ed7e5c5e56c781fb
@@ -1,6 +1,22 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-07-16-explicit-turn-cancellation.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-16-explicit-turn-cancellation.md
2026-07-16-explicit-turn-cancellation.md: 09631349226837d7f93112fe5e9c517f2fee099c
2026-07-16-explicit-turn-cancellation.zh.md: baf039d49578895d53ffae4c6b88d29b3d1563b6
/agent-note-explicit-turn-cancellation-capability:
en: 729ed6291e9d4d2c
zh: 32ae526ef41199da
/agent-note-explicit-turn-cancellation-capability/problem:
en: 0a7826345be2a509
zh: 430fccb5c4d6a5e2
/agent-note-explicit-turn-cancellation-capability/decision:
en: 2c15edb35f38e7e5
zh: fa5145d26e3bff20
/agent-note-explicit-turn-cancellation-capability/verification:
en: a7ab1d06542be1c0
zh: 1687979b7f2460fa
/agent-note-explicit-turn-cancellation-capability/alternatives-considered:
en: bf69bbf7eb280306
zh: a434a0ecb5008b2b
/agent-note-explicit-turn-cancellation-capability/consequences:
en: 1066aff1aec4ed01
zh: 31d6a60496e2e730
@@ -12,7 +12,7 @@ The [initiating Agent scope decision](2026-07-15-agent-initiator-scope.md) inten
## Decision
Agent owns the runtime-only `AgentCancelCause` union `{ kind: 'user' } | { kind: 'parent' }`; `agent.cancel()` defaults to `user`. TypeScript enforces that vocabulary at this typed same-process boundary, with no runtime validator, fallback, or special compatibility contract for untyped callers. An active `TurnCancellation` copies the typed discriminant into a fresh frozen signal reason; idle cancellation has no holder to mutate and does not arm later work.
Agent owns the runtime-only `AgentCancelCause` union `{ kind: 'user' } | { kind: 'parent' } | { kind: 'hook'; reason: string } | { kind: 'disposed' }`, and `agent.cancel()` requires one. TypeScript enforces that vocabulary at this typed same-process boundary, with no runtime validator, fallback, or special compatibility contract for untyped callers. The holder aborts with the caller's own object rather than a detached copy, so a transport reaching that signal can extend it: Node's fetch assigns a `stack` onto the reason it receives. The loop therefore copies the declared fields where the cause becomes durable data. Freezing the cause at `cancel()` is not an alternative — undici performs that assignment from strict-mode code, so a frozen reason makes `fetch` reject with `TypeError: Cannot add property stack` in place of the abort reason. Idle cancellation has no holder to mutate and does not arm later work.
An interrupted live turn ends with the coarse durable `{ kind: 'aborted' }` outcome. The terminal event records what happened to the turn, while the runtime signal identifies who requested cancellation; it does not duplicate `user` or `parent` into replay. Session seed/load rejects legacy aborted records with a reason or any other extra field, so replay cannot reintroduce caller-owned cancellation detail. The process-local `agent/cancel-requested` notification is not durable; a future audit requirement uses a separate durable control-request event so a request and its eventual outcome remain distinct. Durable events contain no stack, signal, error object, free-form cancellation text, or backend-private detail.
@@ -22,7 +22,7 @@ The driver keeps only a cause-less pre-run marker for queued work cancelled befo
The explicit event signatures pass a single payload object: agent-scoped events carry `agent` and `signal` in the payload with `next` last, and the remaining APIs keep `signal` immediately before a waterfall's final `next`. `PreStepContext` and `RequestFailureContext` are retired, with their fields folded into the `agent/pre-step` and `agent/request-error` payloads ([payload-object events](../../archived/architecture/2026-08-06-agent-event-payload-objects.md)). Pre-step entry, request configuration, request-error recovery, model generation, tool execution, approval, turn stopping, and subagent or workflow requests all receive the current signal. Hook bridges must also supply `RunHookOptions.signal`, so a turn cancellation reaches the bash executor's provider-managed termination and join boundary; the [native-containment decision](2026-08-28-subprocess-native-containment.md) owns the supported local scope, Job, and fallback mechanics. `SystemPrompt.assemble()` carries `signal?: AbortSignal` in `AssembleContext` because that object is an explicit request value that can also represent signal-less assembly outside a turn. Listeners may cooperate with the signal but must not retain it to control another turn.
`ctx.agents` continues to carry only the initiating Agent. Ambient Agent presence does not imply liveness, a current turn, or cancellation authority. The cause reader is private to the loop and states the machine-private slot invariant (only `cancel()` aborts a turn controller, always with a canonical frozen cause) instead of re-validating the reason structurally; no public helper reads a cause off an arbitrary signal. Concurrent Agents isolate both their initiator identities and their turn signals; a child driver shadows the parent initiator while its parent request signal still travels through the subagent seam.
`ctx.agents` continues to carry only the initiating Agent. Ambient Agent presence does not imply liveness, a current turn, or cancellation authority. The cause reader is private to the loop and states the machine-private slot invariant (only `cancel()` aborts a turn controller, always with a typed cause) instead of re-validating the reason structurally; no public helper reads a cause off an arbitrary signal. Concurrent Agents isolate both their initiator identities and their turn signals; a child driver shadows the parent initiator while its parent request signal still travels through the subagent seam.
Agent disposal requests the runtime-only `{ kind: 'disposed' }` interruption on the active holder. If cancellation already won the controller reason, the reason cannot be rewritten, so terminal classification first checks lifecycle state: disposed wins, then a supported `user` or `parent` cause becomes the coarse aborted outcome, and unrelated exceptions retain the existing error path. ACP cancellation maps to `user`; in-process spawn and fork propagation map to `parent`. Remote ACP subagents retain their existing wire protocol.
@@ -30,7 +30,7 @@ Cancellation remains cooperative. The loop checks interruption before and after
## Verification
Contract tests verify the typed caller union, frozen detachment, default and first-wins behavior, the coarse Session JSON round trip and legacy-record rejection, ACP `user`, in-process subagent `parent`, and disposal precedence. Loop tests make cooperative listeners wait on the signal at pre-step, system-prompt assembly, request, model stream, request-error recovery, tool execution, and turn stopping; they assert one signal within a turn, a fresh signal across turns, and no cancellation authority during terminal publication or a blocked durability flush. A real hook bridge test cancels and reaps a blocked prompt hook before idle.
Contract tests verify the typed caller union, field copying where the cause becomes durable data, default and first-wins behavior, the coarse Session JSON round trip and legacy-record rejection, ACP `user`, in-process subagent `parent`, and disposal precedence. Loop tests make cooperative listeners wait on the signal at pre-step, system-prompt assembly, request, model stream, request-error recovery, tool execution, and turn stopping; they assert one signal within a turn, a fresh signal across turns, and no cancellation authority during terminal publication or a blocked durability flush. A real hook bridge test cancels and reaps a blocked prompt hook before idle.
Initiator-scope tests assert that every hook still observes the exact Agent and no ambient turn signal, concurrent Agents retain independent identities and signals, and a nested child driver shadows only identity. Race tests cover idle cancellation, pre-run cancellation, replacement submission from a `running` listener, repeated cancellation, and cancel-versus-dispose quiescence.
@@ -12,7 +12,7 @@ Status: implemented
## 决策
Agent 拥有仅用于运行时的 `AgentCancelCause` 联合类型 `{ kind: 'user' } | { kind: 'parent' }`;`agent.cancel()` 默认使用 `user`。TypeScript 在这个类型化的同进程边界中强制执行该词汇,不提供运行时校验器、后备行为,也不为无类型调用方提供特殊兼容性约定。活跃的 `TurnCancellation` 会把类型化判别字段复制为一个全新且已冻结的 signal 原因;空闲状态下没有可修改的持有者,也不会让后续工作预先进入取消状态。
Agent 拥有仅用于运行时的 `AgentCancelCause` 联合类型 `{ kind: 'user' } | { kind: 'parent' } | { kind: 'hook'; reason: string } | { kind: 'disposed' }`,`agent.cancel()` 必须显式传入其一。TypeScript 在这个类型化的同进程边界中强制执行该词汇,不提供运行时校验器、后备行为,也不为无类型调用方提供特殊兼容性约定。持有者中止时携带的是调用方自己的那个对象,而非一份分离的拷贝,因此能接触到该 signal 的传输层可以向其添加属性:Node 的 fetch 会给它收到的 reason 赋一个 `stack`。所以循环在 cause 成为持久数据的那一步拷贝已声明字段。在 `cancel()` 处冻结 cause 并非可选方案——undici 是在严格模式代码中执行该赋值的,被冻结的 reason 会让 `fetch` 以 `TypeError: Cannot add property stack` 取代中止原因而拒绝。空闲状态下没有可修改的持有者,也不会让后续工作预先进入取消状态。
正在运行的轮次被中断后,以粗粒度的持久化结果 `{ kind: 'aborted' }` 结束。终态事件记录轮次发生了什么,运行时 signal 标识谁请求了取消;回放不会重复保存 `user` 或 `parent`。会话 seed/load 会拒绝携带取消原因或任何其他额外字段的旧式中止记录,因此回放无法重新引入由调用方持有的取消细节。仅限进程内的 `agent/cancel-requested` 通知不会持久化;未来若有审计需求,应使用独立的持久化控制请求事件,让请求与最终结果保持为两项事实。持久化事件不包含调用栈、signal、错误对象、自由文本取消原因或后端私有细节。
@@ -22,7 +22,7 @@ AgentLoop 为每个待启动轮次私有地持有一个 `TurnCancellation`。它
显式事件签名传递单个 payload 对象:agent 作用域事件在 payload 中携带 `agent` 和 `signal`,`next` 位于最后;其余 API 保持 `signal` 紧邻 waterfall(瀑布式事件)的最终 `next` 之前。`PreStepContext` 与 `RequestFailureContext` 已退役,其字段并入 `agent/pre-step` 与 `agent/request-error` 的 payload([payload-object 事件](../../archived/architecture/2026-08-06-agent-event-payload-objects.md))。进入 pre-step 时、请求配置、请求错误恢复、模型生成、工具执行、审批、轮次停止以及 subagent 或工作流请求都会收到当前 signal。钩子桥接器也必须提供 `RunHookOptions.signal`,使轮次取消能够到达 Bash 执行器由提供方管理的终止与等待边界;[原生 containment 决策](2026-08-28-subprocess-native-containment.zh.md)负责受支持本地路径上的 scope、Job 与 fallback 机制。`SystemPrompt.assemble()` 在 `AssembleContext` 中携带 `signal?: AbortSignal`,因为该对象是显式请求值,也可表示轮次之外不携带 signal 的组装。监听器可以配合该 signal 取消,但不得保留它来控制其他轮次。
`ctx.agents` 仍只携带发起 Agent。环境中的 Agent 并不代表存活、当前轮次或取消权限。cause 读取器是 loop 私有的,它直接陈述机器私有的 slot 不变量(只有 `cancel()` 会中止轮次控制器,且总是携带规范的冻结 cause),而不是对 reason 做结构化再校验;不存在从任意 signal 读取 cause 的公开辅助函数。并发 Agent 会同时隔离各自的发起方身份和轮次 signal;子驱动会遮蔽父发起方,而父请求 signal 仍通过 subagent seam 传递。
`ctx.agents` 仍只携带发起 Agent。环境中的 Agent 并不代表存活、当前轮次或取消权限。cause 读取器是 loop 私有的,它直接陈述机器私有的 slot 不变量(只有 `cancel()` 会中止轮次控制器,且总是携带类型化的 cause),而不是对 reason 做结构化再校验;不存在从任意 signal 读取 cause 的公开辅助函数。并发 Agent 会同时隔离各自的发起方身份和轮次 signal;子驱动会遮蔽父发起方,而父请求 signal 仍通过 subagent seam 传递。
Agent dispose(资源释放)会在活跃持有者上请求仅用于运行时的 `{ kind: 'disposed' }` 中断。若取消已经先占用控制器的中断原因,该原因便无法改写,因此终态分类会先检查生命周期状态:资源释放结果优先,之后受支持的 `user` 或 `parent` 取消原因形成粗粒度的中止结果,其他异常保留现有错误路径。ACP(Agent Client Protocol)取消映射为 `user`;进程内 spawn 和 fork 的传播映射为 `parent`。远程 ACP subagent 保持现有协议。
@@ -30,7 +30,7 @@ Agent dispose(资源释放)会在活跃持有者上请求仅用于运行时
## 验证
约定测试验证类型化调用方联合类型、冻结且与调用方分离、默认行为与首次请求优先行为、粗粒度的会话 JSON 往返与旧式记录拒绝、ACP `user`、进程内 subagent `parent` 以及 dispose 优先级。AgentLoop 测试让协作式监听器在 pre-step、系统提示词组装、请求、模型流、请求错误恢复、工具执行和轮次停止处等待 signal;并断言同一轮次使用一个 signal,不同轮次使用全新的 signal,终态发布期间和持久化刷新受阻期间不存在取消权限。真实钩子桥接器测试会在报告空闲状态前取消并回收受阻的提示词钩子。
约定测试验证类型化调用方联合类型、在 cause 成为持久数据处拷贝字段、默认行为与首次请求优先行为、粗粒度的会话 JSON 往返与旧式记录拒绝、ACP `user`、进程内 subagent `parent` 以及 dispose 优先级。AgentLoop 测试让协作式监听器在 pre-step、系统提示词组装、请求、模型流、请求错误恢复、工具执行和轮次停止处等待 signal;并断言同一轮次使用一个 signal,不同轮次使用全新的 signal,终态发布期间和持久化刷新受阻期间不存在取消权限。真实钩子桥接器测试会在报告空闲状态前取消并回收受阻的提示词钩子。
发起方作用域测试断言所有钩子仍观察到同一个 Agent 且没有环境中的轮次 signal,并发 Agent 保持独立的身份与 signal,嵌套子驱动只遮蔽身份。竞态测试覆盖空闲状态取消、运行前取消、从 `running` 监听器提交替代提示词、重复取消以及取消与 dispose 竞争下的完全停稳。
@@ -1,6 +1,34 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# Bilingual-pair consistency record for 2026-07-19-cooperative-tool-cancellation.md (docs/i18n/README.md): per heading
# section, a hash of its English and Chinese blocks outside code blocks and generated regions.
# After editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-07-19-cooperative-tool-cancellation.md
2026-07-19-cooperative-tool-cancellation.md: 5ca2b44b24a4af189df27c6f724021a7bf290e2b
2026-07-19-cooperative-tool-cancellation.zh.md: d6d49fb44c5d5629729a8b5b4bad07ea9b2f7ee9
/agent-note-cooperative-tool-cancellation-at-the-registry-boundary:
en: 84c827aa3baa331a
zh: 10cad03e58b10e31
/agent-note-cooperative-tool-cancellation-at-the-registry-boundary/problem:
en: e386b22491b468c1
zh: 82015f5145b679cd
/agent-note-cooperative-tool-cancellation-at-the-registry-boundary/decision:
en: ca66d3b6af50be10
zh: f054b10d0c965e82
/agent-note-cooperative-tool-cancellation-at-the-registry-boundary/decision/mutability-follows-the-pipeline-stage:
en: 0e1399cad4151f87
zh: 960fa0ccbe0f8fea
/agent-note-cooperative-tool-cancellation-at-the-registry-boundary/decision/cancellation-codes-record-whether-dispatch-occurred:
en: c787fba8731ac147
zh: 21b5968ae6f8cd59
/agent-note-cooperative-tool-cancellation-at-the-registry-boundary/decision/pre-aborted-entry-short-circuits-after-materialization:
en: 53362db6a0c71698
zh: 311de45ca26d3fdc
/agent-note-cooperative-tool-cancellation-at-the-registry-boundary/decision/started-work-still-reaches-quiescence:
en: 26e4b71366bebd1b
zh: 10598e12b28c586e
/agent-note-cooperative-tool-cancellation-at-the-registry-boundary/verification:
en: fbd101d4576afa92
zh: 35f5d3c2f6cad6a8
/agent-note-cooperative-tool-cancellation-at-the-registry-boundary/alternatives-considered:
en: 1f205f1a78d4fd5b
zh: 6c17e35da2909302
/agent-note-cooperative-tool-cancellation-at-the-registry-boundary/consequences:
en: 24a9ad2c4c7c86b5
zh: debdd29d272e07ea
Loaded 100 of 9203 files, more files were not shown because too many files have changed in this diff. Show more