The Agent network card leaves the Context tab's foot for a page of its own —
the Fleet / 编队 tab, right of Context (order 30). The card is unchanged,
but both mounts now read one shared `useContextSession` data path and fold
the current agent's figures with one `agentSelfOf`, so the panel and the tab
cannot disagree; the Fleet page keeps the same cold-start retry note and the
same baseline gate. The tab label key splits into `tab.context` / `tab.fleet`.
The right Sidebar's Context panel keeps the card inline — its column has no
room for a tab of its own — so the center Context tab renders it only for the
sidebar host, and nothing else leaves that tab.
The stats board's Agent Network cell used to scroll to the card further down
the same page; it now activates the Fleet tab (activateContextTab is
generalized to activateViewTab). Its miss arm is unreachable for our own
tabs: the board and the Fleet tab ride the same placement gate.
The bundle smoke's fake registry now records `register()` calls instead of an
inject callback's return value, matching the real registry — one inject may
declare several registrations, which the second tab exposed.
Apply the AGENTS.md comments guideline to every .ts under tests/: remove
what the code already expresses, keep only what it cannot.
Removed: spec-header coverage inventories the describe/test tree already
names; comments restating the next line's assertion or its message; helper
JSDoc whose body already says it; within-file duplicates; five stale
claims (trendChart's "six aggregated turns" against agg.length === 8,
agentGraph's "six categories" against CATS' seven, fold-timing's "cheapest
call LAST" against a loop that feeds it first, fold-surface's unreachable
plain-JSON note, contextView's "two turns" for a one-turn fixture).
Kept and condensed: the projection-freeze class, strict wire/state-schema
hazards, retention and pricing windows, pairing rules, hostile-input
rationale, fixture and expectation-array ground truth, jsdom mechanics,
and issue-numbered regressions.
Comment lines 2604 -> 2014 (-22%); 85 module headers kept, 30 coverage
inventories dropped; every surviving comment line is within the 140-column
limit, with 36 wrapped lines joined onto fuller ones.
No logic, string, identifier, import or directive changed: a comment-strip
gate proves each file's comment-free code is byte-identical to HEAD, and a
line-level proof pairs all 845 changed lines with an unchanged code part.
pnpm run lint && pnpm run test (106 files / 2061 tests, per-file 100%
coverage) && pnpm run build all pass.
Merge consecutive short comment lines in tests/** up to the 140-col limit
without touching their text: comment-stripped content, comment text (whitespace
normalised) and line-comment runs are all proven identical per file. This is the
line-count half of the cleanup only; the content pass over tests/** is still
outstanding.
The supported set is now the two V4-generation lines (0.1.7-rc.2+ and
0.2.0-rc.2+): the manifest's dshReleases, the peer floors (>=0.1.7-rc.2,
cordis ^4.0.4 — both lines vendor 4.0.4), the devDependency pins, the
baseline matrix, the release workflow's tag fetch, and the compatibility
docs.
With every supported line on session format V4, the V3-only paths leave:
the fold reads the tool result's first-class message alone (source.callId
pairing, message.isError — the admission validation refuses any row whose
data.error outlives it); the settings.register host face module is gone
(the Config-form entry schema serves the preferences); the client drops
the settingsScope/settings.plugin.item card seat, the retired sessions.open
jump fallback, the legacy icon spellings, and the settings-dialog leg of
the settings jump; the history page's tool/result mapper reads the V4
message (its V3 wrapper reads were dropping result content on supported
lines); the cache probe rides the 2-arg cachedSnapshot face. The baseline
gate stays: a below-floor harness composes the fallback units and the
upgrade prompt, and an undetectable version still fails open.
Verified: pnpm run lint:fix && pnpm run test && pnpm run build green (1918
tests, 100% per-file coverage); the compat matrix passes against the real
dsh sources at both baseline tags; live on dsh 0.2.0-rc.2 the plugin
composes, the Plugins-page preference card renders and round-trips a
write, the insights warm-up fills the heatmap, and the session jump and
Context tab work end to end.
dsh's 0.1.6 selection refactor moved session selection to the view owner:
uiWorkspace.openSession is the verb the built-in sidebar's row click uses,
and the sessions service no longer carries open(). The plugin's jump (the
Context Dashboard's session cards and the Agent network card's nodes) still
called the retired sessions.open spelling, so on 0.1.7-rc.2 the panel closed
but no session opened — silently, by the verb's fail-soft design.
One shared openSessionVia (services.ts) now serves both call sites: it
re-proves both faces per call, prefers the view owner's verb (invoked bound
to the service instance), and keeps the retired sessions.open as the
degradation path. The per-baseline sessionNav seam pins both spellings
presence-as-declared in the real-code matrix, and the always-on client-face
probe drives the jump through each generation's exact composition (the V4
baseline serves no sessions-side selection at all — the exact shape issue
#90 died on).
The supported range is now two baselines - dsh-v0.1.5-rc.1 (session
format V3) and dsh-v0.1.7-rc.2 (V4) - enforced by the runtime gate at
BASELINE_DSH_VERSION = 0.1.5-rc.1; below it the fallback units and the
upgrade modal take over (0.1.2/0.1.3 hosts were previously served by the
real folds).
The pre-V3 log shapes are dead code on every supported harness: the
running harness migrates historical logs on every read path (or refuses
the session wholesale), and 0.1.5-rc.1 rejects a request/header carrying
header.system outright. The fold therefore drops the V0/V2-only paths -
the header.system envelope system prompt, assistant/chunk floods,
{start, end} replacement endpoints, tool/code-dispatch - and the state
fields only they wrote (systemsFromHeader, the stepStart decode
accumulators). stateVersion stays 20: no supported log folds
differently, and pre-V3-era cached rows are discarded by the projection
cache's identity gate (and the strict stepStart sub-schema) instead of
served. The headers unit folds metadata-only epochs (envelope
systemTokens write dropped; the v1 cached-row read-compat and its pinned
stateVersion 1 stay); replaceRangeOf speaks startSeq/endSeq only; the
browser's epoch fetch maps request/header to tools and system/message to
the prompt text.
tests/baselines.ts re-fits to the two entries (the right Sidebar seam is
required on both), the compat matrix drives both tags' REAL sources
(canonical logs re-shaped to V3, the hostile probe renumbered past them),
and the version fixtures pin the new floor. Manifest: dshReleases
{0.1.5-rc.1, 0.1.7-rc.2}, dsh peers >=0.1.5-rc.1 (satisfies the 0.1.7
admission check under includePrerelease), devDeps pinned to the
0.1.5-rc.1 surface plus the ui-primitives runtime closure the client
lane inlines (test-only), and the release workflow fetches the two tags.
docs/compatibility.md is rewritten around the two-line matrix; README,
AGENTS.md and the issue template follow.
Also riding this move, from the audit pass: the fold re-proves an inject
source's form before it books the event record (the harness validates
`kind` but not `form` - a hostile one previously failed the strict
wire/state schemas on every delivery, the #44 freeze class), the headers
unit guards a data-less envelope (it has no try/catch of its own), the
schemastery schema annotations drop the explicit z<T> wrappers the 3.18.4
Mode generics reject, and the version-history note records why
stateVersion is deliberately not bumped.
The Plugin / GitHub / Settings labels open with siDeepseek, siGithub,
and the harness's IconSettingsOutline14 gear, riding currentColor at the
label's baseline. simple-icons is a dev-only dependency pinned to the
harness ui-primitives' own 16.31.0 and tree-shakes into lib/client.js as
exactly the two mark paths, so no runtime dependency is added and the
marks are identical to the harness's own SiteGlyph artwork.
The fold buckets all three skill-content shapes the harness injects — the
<available_skills> catalog digest, a user-explicit /name invocation's
instructions message, and the content a skill-tool load returns — into a
new 'skill' composition category instead of burying them in inject/tool
(closes#66). Skill-tool loads keep their tool identity stamped, so the
call tallies, hit counts, and failure marking are unchanged.
stateVersion 18 → 19: the per-category sums change shape, so cached rows
refold from the durable log on upgrade (docs/compatibility.md).
The trend chart, overview, Token donut, stats, and the Context browser all
gain the seventh bucket (orange-500); the browser's skill section pins its
rows like injects, so long sessions keep listing what the sums count.
Clicking a file name in the File Activity card now opens the file's preview
tab in the right Sidebar — the shipped document-preview viewer, reached the
same way the built-in Files sidebar reaches it — on harnesses that serve that
column (dsh 0.1.5-rc.1+). The address is built with the harness's own
browser-safe `fileAddressFor`, inlined by the client bundle exactly as the
Sidebar's file types inline it, so a path under the workspace collapses to the
session-relative spelling and every route to one file settles on one tab.
The capability is OPTIONAL by contract, like the tab registration itself: the
opener reads `ctx.sidebarRight.openResource` through the runtime boundary and
re-proves it per call, and reports whether the column took the address. An
absent column, a face that refuses the address, or an unencodable log path
falls through to the pre-existing system-open behavior, so an older line is
fully functional and nothing becomes an inert click. Pattern rows and
directory targets are never previewable.
Adds the `@deepseek-ai/dsh-util-workspace-path` dev dependency (itself
browser-safe), allows it in the client bundle purity gate, pins the
resource-navigation seam in the compat matrix, and covers the address builder,
the card's preview-then-fallback click, and the optional opener per baseline.
Bundle the colourful document sheet as the plugin's own icon and fill the
right-Sidebar tab type's two glyph seats with it, the way the shipped files
type does: the guide capsule's `icon`, and a new `sidebar.right.pane.tab.title`
registration that draws the emblem beside the chip label.
The chip's close control sits out of flow over the title's last 14px and an
active chip fades the 16px before it, so the shipped files chip stays readable
only by its short label. The label now carries a trailing gutter so that fade
lands past the text instead of on the last glyphs.
Registration turns rollback-safe (each disposer is tracked) so a partial
failure unwinds cleanly, and the obsolete primitives-icon resilience spec goes
with the icon read it guarded.
Every rich detail section (system prompt, tool schema descriptions,
messages, tool results, compaction summaries, and the same cards inside
the /context modal) gains an icon-only copy control beside the Raw/MD
switch. It copies the section's exact SOURCE text, never the rendered
markdown, via the harness's own writeClipboard primitive; success flips
the glyph to a check for a beat, a rejected write claims no success, and
a repeat click inside the window is a no-op — the shipped code-block
control's behavior. Both icons and the writer are platform-module
exports present on all three supported baselines.
The added control tipped the head's trailing group out of the clipped
section card at the narrowest pane, so rich-text heads now fold that
group onto a second line under width pressure. The wrap is scoped to
those heads: the call-name head must stay one line (long MCP names
ellipsize instead).
Every client file reached hooks and element types through the central
require seam (src/client/react.ts) and spelled them React.useState /
ReactNS.ReactElement. Import the members directly instead — named value
imports for hooks, inline type-only imports for element types — and let
the bundler own the single require('react'), which is exactly what the
platform module table answers.
This needs JSX off the classic runtime (it required a React identifier
in every tsx scope): tsconfig moves to jsx: react-jsx, so the bundle
sources jsx from 'react/jsx-runtime', already seeded by every supported
harness (verified against the dsh-v0.1.2-rc.1 platform.ts). The bundle
smoke's fake module table gains the specifier to stay a faithful shell
stand-in. h() survives as a local createElement alias at the slot
render-prop seams and the lightbox portal imports createPortal from
react-dom directly.
Verified: the built client.js requires react, react/jsx-runtime, and
react-dom exactly once each; the compat lane (bundle smoke + the
real-baseline matrix) passes against the fresh artifacts; the full gate
stays green with per-file coverage at 100%.
The install/runtime compatibility floor moves from 0.1.1-rc2+ and
0.1.2-alpha2+ to 0.1.2-rc.1+. The 0.1.1 line and the 0.1.2-alpha previews
leave the support matrix, so every pre-0.1.2 fallback they existed for is
removed outright:
- client history: drop the legacy `connection.api.sessions.history` face,
the `result`-nested envelope, and the `events` rows field — the gateway
`remote.session.page` face and its ClientResult envelope are the only
served shapes.
- client image loader: drop the pre-0.1.2 `conversation.resolveImage` face;
`uiConversation.imageUrl` only.
- client node join: drop the pre-0.1.2 `useSession.nodes` seat;
`useChat`'s ChatSnapshot `legacy.nodes` only (UseSessionLike removed).
- tests/baselines.ts: single baseline `v0.1.2-rc.1`; HostSeam dropped (the
registry generation hard-codes header-passing init and seq-0 eager
seeding, now mirrored with the exact `init(header, inheritedEventCount)`
arity); ClientSeam slimmed to the consumed probes.
- deps: devDeps re-pinned to the 0.1.2-rc.1 generation (types compile
against the real rc.1 surfaces); cordis ^4.0.2 and schemastery ^3.18.2
per the rc.1 peer requirements; dsh-scope/dsh-invariants declared as dev
deps; peer floors >=0.1.2-rc.1; dshReleases table trimmed.
- release workflow fetches only the dsh-v0.1.2-rc.1 tag; docs updated
(AGENTS.md, README, docs/compatibility.md).
- verified against the rc.1 sources: the tool-attribution map (names and
packages, incl. the documented `subagent_fork` alias), MCP naming, the
page/imageUrl/legacy.nodes faces, and the registry contract.
The target-content fetch read the 0.1.2+ gateway history face with
ctx.get('remote.session') and then dereferenced .page on the returned
value. A cordis traced-service proxy read off a fiber that never
declared the service throws on property access ("cannot get property
\"remote.session\" without inject") — the guard around ctx.get alone
cannot catch it, and the exception escapes the Context tab render and
takes the whole web client down.
The remote face is now resolved through the DECLARED inject instead:
apply() registers a ctx.inject(['remote', 'remote.session']) callback
(the dsh idiom — both names together, because the traced remote proxy
resolves .session through the context), binding the page verb into a
slot the fetchers prefer. Both names together stay absent on the
pre-0.1.2 line, where the callback never fires and the legacy
connection face carries the reads. Every service property chain is
additionally re-proven (readKeysOf: remote.session.page and
connection.api.sessions.history degrade at the first throwing getter
instead of ever throwing), matching the no-white-screen contract.
package.json now declares @deepseek-ai/dsh-api-remotes in
dsh.client.inject, so the graph composes the namespace-mounting bundle
before this plugin (skip-safe on 0.1.1, where the row does not exist).
Drop the test:bundle / test:compat scripts. The bundle smoke moves into
the `compat` vitest project (tests/compat/bundle.spec.ts): the
__ModuleLoader__ handoff, the CSS channel, slot/trigger registrations,
and HMR safety over the BUILT lib/client.js — so `pnpm test` runs the
whole verification (host, client, built artifacts, real-code compat
matrix) in one pass with the per-file 100% coverage gate. The
built-artifact specs skip cleanly when lib/ is absent; the release
workflow builds before Test, so they always run there.
Also drop the standalone Bundle smoke step from the release workflow
and refresh the docs/comments that referenced the removed scripts.
tests/baselines.ts is the single source of truth for the supported dsh
baselines and their seam faces. Three layers verify them:
- always-on host registry-contract drivers over the REAL projection
definitions (plain-JSON cache-write gate, wire delivery, checkpoint
restore, init-header tolerance) — the recurring host incidents,
- always-on client-face matrix (nodes seat, image loader service,
history face + envelope, markdown chrome, full tab render) — the
recurring client incidents,
- the `compat` vitest project: stages the REAL harness sources at each
baseline tag, boots the tag's registry on the cordis release that line
vendors, applies the BUILT plugin, and probes slots/faces/vocabulary/
platform table from the tag's sources. The release workflow fetches
the baseline tags before `pnpm test` so the matrix always runs there.
Adding a future baseline = one tests/baselines.ts entry + one fetched
tag; a failing probe names the seam to re-fit.