Commit Graph
521 Commits
Author SHA1 Message Date
Bowen Liang 14ecf44ce4 refactor(client): drop the Context Trend card's subtitle hint
The "✂ marks compaction/prune, Step/Turn switches granularity" caption
restated controls that are already visible in the card's own title row,
so it only crowded the header. The subtitle span now renders solely for
the transient focus state ("Showing {cat} only"), and the unused
trend.hint key leaves both dictionaries.
2026-09-08 19:35:41 +08:00
Bowen Liang 40a054b99b fix(client): guard the DNA bar against a stale hover key
A snapshot push can drop the band under a resting pointer (compaction,
tail slide out of the served window) without a mouseleave, and the dead
key exact-matched nothing: the whole strip sat dimmed with nothing lit
— the very state the open-category pin's breakdown gate rules out.
Honor a band hover only while its key names a rendered band, so the
mirror/pin fallbacks resume underneath.

Also correct the hover-link comment: DNA hovers stay on the bar and
never report back to the overview (the link is one-way in DNA mode,
as the existing test already pins).
2026-09-08 05:25:32 +08:00
Bowen Liang 5af019ef02 docs: update installation instructions in README to include DeepSeek Harness link 2026-09-08 00:41:54 +08:00
Bowen Liang 1875ff7aad docs: update README to include NPM package link for dsh-context 2026-09-08 00:39:26 +08:00
Bowen Liang 466d96e3a2 chore: release v0.46.0 2026-09-08 00:25:53 +08:00
Bowen Liang 481783de4e feat(client): keep the open category lit in the browser's composition bar
The browser's accordion already focuses the Context trend chart on the
open category; the composition bar now holds the same highlight as a
resting state — category mode lights the category's segment, DNA mode
lights the category's bands as a group (the parts' group key). A
pointer hover overrides the pin and the pin resumes on leave; the pin
drops while a previewed/picked step holds nothing for the category, so
the bar never reads all-dimmed with nothing lit. No tooltip floats for
the pin: category mode mounts no tip slot, and the group-keyed pin
exact-matches no DNA band.
2026-09-08 00:09:55 +08:00
Bowen Liang 568d837f80 feat(client): add a DNA mode to the Context browser's composition bar
A title-row toggle redraws the composition bar as one band per context
item — the system prompt, every tool schema, every surface message — in
prompt order (the header prefix first, then the message flow by seq),
the order the model reads the context and the order items joined it.
The header epoch's own seq is bookkeeping (dsh logs request/header at
dispatch of the first request using it), never an ordering key: a
mid-session refresh must not park the schemas behind the tool results
they describe.

Bands floor at 0.35% of the occupied region so a tiny item stays a
hoverable filament (tooltips still report true shares); hovering names
the item with its time, a mirrored category hover lights the category's
bands as a group, and clicking a band opens its category + element row
below, scrolling it into view.
2026-09-07 23:58:34 +08:00
Bowen Liang d52c43ae18 fix(client): plot raw fold figures in the trend chart so constant categories stay flat
The trend bars multiplied every category by a per-request anchor factor
(provider prompt / heuristic total). That factor drifts with the heuristic's
ratio error as the context composition changes, so categories that never
change — the system prompt, tool schemas — plotted as steadily growing
(1668→1789 on a real log whose fold value is a constant 1851), and the delta
mode invented non-zero changes for them. The same screen already shows the
raw figures everywhere else (step detail, browser, overview), and dsh's own
token-meter breakdown projection serves un-rescaled heuristics per request,
so drop the anchor: segments, axis, tooltip and the focused view all plot the
fold's figures directly. Provider usage stays visible in the step detail's
Actual Prompt / Output / Cache chips.
2026-09-07 22:49:55 +08:00
bowenliang123 2454ebb582 chore: release v0.45.0 2026-09-07 15:45:42 +08:00
bowenliang123 3a404b696e fix(client): keep the browser's on-demand fetchers reactive to the history face
A mount could race the declared inject (a watch rebuild remounts the
Context tab and the /context modal before the injected fiber re-fires),
and the fetchers snapshot the absent face once — the browser then stuck
on the static degradation for its whole lifetime, with no details
renderable in any category. The face now lives behind a
subscribe+useSyncExternalStore seat (useHistoryFace), and both
components rebuild their fetchers when it lands or is revoked, so an
open section auto-fetches without any user action. The /context modal
also gains the session image loader the tab already wires, so
attachment cards stop degrading to metadata-only there.
2026-09-07 15:38:40 +08:00
bowenliang123 ba074e078e fix(host): backfill pre-step message ids so stripped messages cannot brick sessions
A durable `user/message` event lacking a non-empty string `data.id` passes
the runtime append unchecked but makes the harness refuse the whole session
at its next load (`... lacks an identified message`, issue #51). The archived
wrap-up notice carried a rebuild signature (role-first key order, `id` and
`summary` stripped) that no shipped harness producer emits, so the strip
happens upstream of the append, outside both audited codebases.

Guard the durability boundary from the plugin side: a prepended
`agent/pre-step` listener runs last in the waterfall and mints a `dshctx-`
prefixed id for any decision message that would persist unidentified,
leaving everything else — including the decision's reference identity —
verbatim, and failing open on hostile entries. The seam is pinned per
baseline (the event dispatch, the user/message append that consumes it,
and the prepend option) in the real-code matrix.
2026-09-07 15:12:33 +08:00
bowenliang123 a05e2819af fix(client): size the turn strip to the scroll content instead of the viewport
As an in-flow child of the horizontal scroller, .lc-turns capped at the
viewport width (clientWidth) and its overflow:hidden clipped every turn
block past the first screen: on a scrollable chart the strip stopped
mid-bars, and the visible-slice-centered label could drift off or vanish
beyond the clip edge. Give the strip the same max-content/min-width
sizing as .lc-chart so it always spans the full column grid; the label
centering needs no change.
2026-09-07 14:41:09 +08:00
bowenliang123 4ac3bba1cf docs: modify codegraph instructions in AGENTS.md 2026-09-07 14:09:48 +08:00
bowenliang123 bcbbc3367f feat(client): focus the trend chart bars on the browser's open category
Expanding a category in the Context browser now plots every trend bar on
that category alone: the axis rescales to the category's own max (provider
anchor preserved) in both total and delta modes, the hover tip names the
category, and the card subtitle reads "Showing {cat} only" until the
category collapses. The /context modal keeps its unfocused chart.
2026-09-07 13:45:41 +08:00
bowenliang123 1eb10e64e2 refactor(client): drop the T prefix from turn strip labels
The strip label is now the bare turn number (the block's hover title
keeps "T{n}"). Without the prefix, one/two-digit turns fit the 10px
base font at the fixed 16px column pitch with no shrink; the uniform
shrink now kicks in from three-digit turns (7px) and floors at 6px for
four-digit ones.
2026-09-07 12:39:15 +08:00
bowenliang123 47cfff6884 fix(client): shrink turn labels to one strip-wide font size instead of thinning them
At the fixed 16px column pitch even a single-digit "T1" at the 10px base
font grazed its neighbour, so the collision chain hid every other label
(the blank T2/T4 blocks in the turn strip). Keep every label on the
single line: the render pass now picks one font size for the whole
strip — the largest at which the tightest adjacent label pair still
clears the gap (analytic glyph-width estimate, no measurement, 6px
floor) — and the measured chain in updateTurnLabels stays only as the
last-resort guard past the floor.
2026-09-07 12:29:47 +08:00
Bowen Liang 4d144147a0 refactor(client): import React members directly, dropping the central react module
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%.
2026-09-07 08:59:03 +08:00
Bowen Liang e7e19dbff5 chore: release v0.44.0 2026-09-07 00:37:17 +08:00
Bowen Liang 65de63600d feat: add the pnpm web command to restart the dsh web server 2026-09-07 00:16:05 +08:00
Bowen Liang 5b43b27de3 docs: add development server instructions to AGENTS.md 2026-09-07 00:03:00 +08:00
Bowen Liang 2d371dc72c fix(client): refit the system-open affordance to the session RPC seam
The File Activity card's hover-underline + click-to-open affordance died
with the harness connection refactor: the hostDescription.canOpenPath
fact and the connection.api.host.openPath RPC that the capability probe
and opener read no longer exist on any supported harness line, so the
probe answered false everywhere and every file name rendered inert.

Re-point both at the session controller's workspace-opener remotes
(session/canOpenWorkspacePath / session/openWorkspacePath) over the
generic '/api' channel — the same Connection RPC the split timeline's
detail channel rides — with the wire contract proved against a live
host: `args` must be a plain object keyed by the remote's declared
parameter names (an array is rejected host-side), and the capability is
now an RPC round-trip instead of a synchronous host fact, so it lands
in view state behind the harness's own isLoopback gate; a probe that
settles after unmount drops its answer. The shared connection-RPC
resolution is deduped into rpcCallOf, which makeDetailFetcher reuses.
2026-09-06 23:52:51 +08:00
Bowen Liang 282856fac4 feat(client): drop the subtitle hints from the stats, token, and timing cards
Remove the lc-card-sub hint line under the Context Stats, Token Stats, and
Timing Stats card titles, and retire the now-unused stats.hint / timing.hint /
tokens.hint keys from both dictionaries.
2026-09-06 23:21:48 +08:00
Bowen Liang 2b187af6e6 fix(client): hide the shell's width handles beside the scroller, not inside it
The transcript-width strips are the shared scroller's following SIBLINGS
(children of the skeleton body), not its descendants, so the earlier
attempt's descendant combinator silently matched nothing and #50 stayed
broken. Select them with `~` and fold the modal case into the same rule:
while `.lc-root` (the Context tab) or `.lc-modal-backdrop` (the modal, on
any tab) is mounted the handles are hidden, and unmounting restores them.
This also replaces the modal z-index seat lift — hiding the z-8 strips
beats lifting the z-7 seat above them.

Fixes #50
2026-09-06 23:08:55 +08:00
Bowen Liang d847304dbb docs: update CodeGraph command in AGENTS.md for improved usage instructions 2026-09-06 22:19:26 +08:00
Bowen Liang 750562878c docs: enhance CodeGraph section in AGENTS.md with initialization and usage instructions 2026-09-06 22:12:42 +08:00
Bowen Liang 7a2a0ceba9 docs: enhance CodeGraph section in AGENTS.md with initialization and usage instructions 2026-09-06 22:10:02 +08:00
Bowen Liang 6b8387df74 docs: add CodeGraph usage guidelines to AGENTS.md 2026-09-06 22:01:08 +08:00
Bowen Liang 218a80c5ce docs: update AGENTS.md with enhanced guidelines for DeepSeek Harness usage 2026-09-06 21:59:54 +08:00
Bowen Liang 7ffb13af91 chore: align @types/react-dom to 18.x matching the dsh web baseline 2026-09-06 21:10:45 +08:00
Bowen Liang 1d5a68e6aa chore: replace native pre-commit hook with husky running pnpm test 2026-09-06 21:10:45 +08:00
Bowen Liang b13ad55501 fix(host): serve the timeline detail for cold sessions (viewed, never entered)
The detail endpoint resolved sessions through the live store's
`sessions.get()` only — but a session that is merely VIEWED never enters
it (`SessionStore.prepare` with a persistence seed deliberately does not
register), so every cold session answered the typed null and the Context
tab parked on the retryable failure note. On a gappy durable log this was
unrecoverable by construction.

The handler now follows the harness's own ladder: live sessions still read
the registry's current fold state via `stateOf`; a store miss observes the
session through `ctx.sessionQuery.observeSession()` (the observation
carries the complete immutable log) and folds the detail from init —
cheap, since a cold log is static and the client's per-session store reads
it once per page view. The lease disposes promptly; an absent sessionQuery
face, an unobservable session, or a rejecting read keep the typed-null /
failure-envelope degradation.
2026-09-06 12:03:34 +08:00
Bowen Liang 6faf8f16bf feat: count the searched target alongside the matched files in the op log
A grep/glob with the complete matched-file meta rowed ONLY per hit file —
the searched path (or the workspace-wide pattern) vanished from the File
Activity card entirely. Both now book: the call's target row first (the
searched path, carrying the pattern(+include) detail; a pathless search
rows the pattern itself, marked as a pattern), then one row per matched
file with its hit count. The degenerate single-file search (the target IS
the matched file) keeps one row. Truncated or malformed metas keep the
honest fallback (the call target only).

The fold's op-log semantics change, so stateVersion bumps to 15 and cached
rows refold.

Verified: 1147 tests, per-file 100% coverage; live on a grep-heavy session
the card counts 80 search ops — the searched directories row alongside
their per-file hits (plus a deterministic fold over the real log: 6 target
rows + 107 hit rows).
2026-09-06 12:03:07 +08:00
Bowen Liang 5c99a476f3 feat: fold the file-operation log host-side (full-log File Activity coverage)
The File Activity card derived its ops client-side from the served tool
nodes joined with the conversation WINDOW: a call whose arguments had aged
out of the loaded tail named no target and vanished from the card silently,
so the "up to latest" scope actually covered only the chat window. The join
was also the only meta/subCalls carrier, and the per-call op assembly was
written twice (top-level and Code-Mode nested paths).

The derivation moves to the host fold, which sees every lifecycle event with
its full payload: `tool/call` arms name + raw arguments (the pending-call
map's entries grow `argsRaw`), `tool/result` books the ops off the armed
arguments plus the result's presentation meta (grep's by-file match groups,
glob's path list, read's exact window), and `tool/code-dispatch` buffers
nested Code-Mode ops under their run_code root until the parent result
flushes them with `parent` + the program description. The log is bounded
(`maxFileOps`, default 400) with a `fileOpsFloor` coverage stamp, rides the
detail payload (and the inline value on channel-less hosts), and is plain
JSON end to end. stateVersion bumps to 14; cached rows refold from the log
to rebuild the op log.

The per-call parsing is ONE shared module (shared/fileOps.ts — opsOfCall
plus the kind/path/delta/read-window/search-attribution primitives),
consumed by the host fold and by the client's inline-generation fallback
(the legacy window derivation stays for old hosts, now through the same
parser, closing the duplicated assembly). The client aggregates + filters
(`activityOfOps` joins the archive's `gone` stamps at render time; nested
ops scope by their parent result's seq, matching the legacy node-level
rule); the card, its chips, rows, deltas, and locate bridge render
unchanged.

Verified: 1142 tests with per-file 100% coverage (new parser matrix,
fold-ops, aggregation, end-to-end through the real registry + detail
endpoint); the compat vocabulary probe gains tool/code-dispatch (present at
the 0.1.2-rc.1 tag). Live on the real deployment: the big session's card
grew from 4 window-bound files to 37 files / 135 ops spanning every turn,
and folding the real Code-Mode logs books nested ops with parent + program
stamps (e.g. 136 nested reads across one session, errors flagged).

Known upstream boundary (unchanged): `tool/code-dispatch` persists no
result meta, so nested reads keep the limit-estimate footprint and nested
searches the call-target form until the harness carries meta there.
2026-09-06 09:47:26 +08:00
Bowen Liang 62ae0f9c69 perf: split the context timeline into a slim wire head plus an on-demand detail channel
The contextTimeline projection value rode every harness delivery channel
WHOLE: each session.list row, every control baseline, every follow
snapshot, and a full-value broadcast on every state change (with a
full-value schema parse per push). The heavy collections (request records,
context events, the served surface window, the removed-node archive) are
only ever rendered by an OPEN Context tab/modal, so they moved off the
wire value.

Wire head (buildTimelineHead, ~1KB): the composition breakdown, the stats
board's precomputed counters (turns/steps/injects/compactions/prunes), the
newest request's billing summary (the headline's derived anchor), the
timing/cost totals, and `detailRev` — a revision marker that bumps exactly
on detail-mutating folds, the open tab's refetch signal.

Detail channel (host/detail.ts): the pre-v0.9 generic Connection RPC shape
returns as one narrow endpoint, `/dsh-context` `detail`, serving the
collections off the registry's live fold state (`stateOf` — no second
fold, no private copy). A nested `ctx.inject(['connection', 'sessions'])`
arms it load-order-free; a deployment whose faces never compose keeps the
inline wire value unchanged. The baseline-gate fallback path is untouched.

Client (client/timelineSource.ts): one per-session detail store shared by
the tab and the /context modal — fetch on open, then debounced
trailing-edge refetches whenever the pushed detailRev outruns the served
detail (single-flight, latest-wins by revision, refold reset, failure
backoff, absence stops trailing). Detail-driven cards show a pending/retry
note instead of a misleading empty state; the counters and headline render
off the head immediately. Both wire generations are reconciled per value
(new client + old host renders the inline value untouched; old client + new
host degrades to empty charts in the stale-watch window, never a white
screen). The chat-jump relay holds its one-shot pin until the detail lands.

Fold state keeps the full shape: no stateVersion bump, no cached-row
invalidation (the slim view is recomputed per read for cold checkpoints).
Compat matrix gains the detail-channel seam probes (HostConnectionRpc,
the browser caller, the registry stateOf), verified against the
0.1.2-rc.1 tag.

Measured over 263 real session logs from a live deployment, plus live RPC:
- per-session wire value: 84–150KB (top sessions) -> 0.6–0.9KB (~100-165x)
- all sessions aggregate (session.list rows / control baselines):
  4.4MB -> 0.2MB (~22x)
- per-client push traffic over one big session's lifetime:
  157MB -> 1.8MB (~87x), and the per-push full-value zod parse shrinks
  by the same factor
- detail payloads now flow only for the session being viewed, only while
  its tab/modal is open (120KB measured live for the biggest session);
  background sessions cost zero detail traffic

Verified visually against the running harness (big/small/cold sessions,
a live turn refreshing in place, past-step reconstruction, header epoch
and tool schema reads, the /context modal, the Agent network card) with
byte-identical card output. 1110 tests, per-file 100% coverage.
2026-09-06 04:08:20 +08:00
Bowen Liang 3faf027330 docs: distill the layout & responsive rules to general guidance 2026-09-05 22:40:48 +08:00
Bowen Liang 37f096ca2a docs: add the layout & responsive rules to AGENTS.md 2026-09-05 22:23:38 +08:00
Bowen Liang cb93e4c74c refactor: share the settings vocabulary and dedupe the client fetch/overlay patterns
- The settings preference vocabulary (DefaultGranularity/DefaultTrendMode/
  DefaultFileSort/PluginSettings/SettingsField) was declared in both
  host/settings.ts and client/settings.ts — declared once in
  shared/types.ts now, re-exported at both ends.
- The Context browser's two fetch-on-miss state machines (row content,
  header epoch) were line-identical and had already drifted (the row
  read's idle note said 'no content') — one useFetchOnMiss hook plus one
  fetchMissNote helper (components/fetchOnMiss.tsx).
- The /context modal and the upgrade gate duplicated the capture-phase
  Escape handling; useEscapeClose (components/escapeClose.ts) is the one
  overlay contract, and the gate gains the modal's focus restore.
- The five/four identical useProjection reads in contextView/contextModal
  collapse into services.ts's projectionOf; agentTree drops its private
  asRecord copy for the exported one.
- agentTree's compact duration formatter is renamed fmtDurationCompact —
  same name as format.ts's locale-aware fmtDuration with different
  behavior was an import trap.
- Dead surface removed: Snapshot.occupancy (unfolded since 0.11 and
  undeliverable under the strict wire schema), CAT_COLORS,
  HistoryEventLike, and three exports nothing consumed (EVENT_ICONS,
  ContextViewProps, the FileSort alias).
- Comment drift fixed: the conversation join has a single useChat seat
  since the matrix narrowed to 0.1.2-rc.1+ (three sites), and
  services.ts's header no longer claims the module is type-only.
2026-09-05 22:19:01 +08:00
Bowen Liang 8205075877 fix(client): re-prove the meter projections at the boundary and catch settings write rejections
- tokenUsageOf/contextPressureOf were blind casts: any record passed.
  tokenUsage now requires the strict four-bucket wire shape (a partial
  value would silently undercount the billed total); contextPressure
  re-proves each of its three independent last-wins fields and no longer
  lets state-internal fields (surfaceTokens) ride along.
- headersOf now validates every tool entry (name string, finite tokens,
  plugin string when present) — a junk row threw on the browser's blind
  tool.name/tokens reads, blanking the card instead of degrading.
- timelineOf's fast path required Array.isArray but not record entries:
  a null/primitive element passed through and threw downstream
  (req.seq on null). Junk entries now take the sanitizing slow path.
- The settings scope write promise rejects on transport failure (dsh
  keeps only its queue tail fulfilled) — catch it and roll the
  optimistic echo back to the scope's truth instead of floating an
  unhandled rejection.
2026-09-05 22:17:54 +08:00
Bowen Liang dda9e7a43c release: v0.43.0 2026-09-05 21:06:43 +08:00
Bowen Liang 85d5083c2f fix(client): fold the Context tab layout for narrow panes
The head row's four stat cards were pinned to one line at every pane
width: on phone-sized panes each card squeezed to ~70px and every
label, donut and legend crushed together. The row now folds
4-across -> 2x2 -> single-column off a row-level container query, and
every tab card is a shared lc-card query container driving its own
internal reflow:

- stats card: the 8-cell grid folds to 2 columns below 320px card
  width, so the longer English labels never ellipsize
- events card: rows wrap to two lines below 380px — icon + kind +
  label on line 1, the at/tokens/time tail intact on line 2, killing
  the horizontal scrollbar
- file card: the same two-line wrap for file rows (no more
  one-character-wide vertical path strip); the purpose chips flow to
  two lines instead of clipping
- .lc-col floor capped at the row width via min(280px, 100%)

Wide panes keep the established four-across identity unchanged.
Verified visually at 1920/1280/768/390px in both locales; the
/context modal sits outside .lc-root and is unaffected.

Fixes #48
2026-09-05 21:05:21 +08:00
Bowen Liang c7604d0fad release: v0.42.0
Bump the version for release.
2026-09-05 02:27:27 +08:00
Bowen Liang 9eea05142e docs: name both registry init arguments in the projection contract mirror
The dsh 0.1.2-rc.1 registry hands a fresh fold init(header: SessionHeader,
inheritedEventCount: SessionLogOffset) — the mirrored contract comment
claimed the header alone. The zero-argument init already satisfies either
reading; this realigns the prose with the pinned baseline's source.
2026-09-05 02:24:33 +08:00
Bowen Liang eeed793257 docs: add the outdated-comment upkeep rule to AGENTS.md 2026-09-05 00:55:35 +08:00
Bowen Liang 3e0673319c test: give the compat matrix driver hook the driver's 60s budget
A cold stage dir (fresh clone, cache miss, dependency re-pin) runs a
real npm install inside the beforeAll, which the 10s default hook
ceiling kills; align the hook with the driver spawn's own 60s timeout.
2026-09-05 00:55:05 +08:00
Bowen Liang 197c6a5600 docs: realign stale comments with the dsh 0.1.2-rc.1 baseline
- services.ts module doc: the client does call one RPC — the gateway
  history page read (remote.session.page) that fetches a request-header
  epoch's content on demand; drop the 'no longer calls any RPC' claim
  left from the v0.9 data-path migration
- services.ts ImageRefLike: normalization on rc.1 is a
  deployment-resolvable policy (defaults: 2048x2048 total-pixel budget,
  8192px long edge), not the 0.1.1-line long-edge 2048px cap
- compat.ts: the below-baseline fallback units still emit the pre-0.1.1
  { schema, view } aliases (only the real units are modern-shape-only),
  uncontradicting fallback.ts
- headers.ts / shared/types.ts: no supported-baseline harness path
  writes the header entry plugin field (ToolSchema carries none); the
  read stays defensive for foreign/newer producers
2026-09-05 00:55:00 +08:00
Bowen Liang 8b434f2dbe feat: gate below-baseline harnesses to fallback data with an upgrade modal
At apply time the host probes the running harness's version (the
dshHomePath-anchored profiles mirror first, the plugin's module anchor
second) and compares it against BASELINE_DSH_VERSION 0.1.2-rc.1 — with
release > rc > beta > alpha ordering at equal X.Y.Z. A harness below the
baseline gets fallback projection units (both registry contract
generations) that fold nothing and serve zeroed data plus an
`unsupported` wire record; the client keeps rendering the blank cards
and pops a per-session-dismissable modal naming both versions and urging
the update. A detection failure or an unparseable version fails open, so
a probe misfire can never blank a working deployment.
2026-09-05 00:23:22 +08:00
bowenliang123 fbf32ecc67 feat(client): open the Context tab from the chat stats line
The harness stats row (the composer dock's own `stats` entry) gains a
hover underline and opens the Context tab on click or Enter/Space. The
plugin mounts an invisible sibling entry on the officially plugin-facing
`conversation.composer.dock` seat; its anchor spots the single stats row
beside it inside the slot anchor, decorates it in place, and re-spots it
on dock churn (the row mounts only after the first stats exist, and
tooltip bubbles come and go beside it). A drag-selection click is
ignored so copying the numbers never switches tabs.

Every shape without a spotless row degrades to a silent feature-off:
a missing dock seat, ambiguous candidates (other plugins' entries,
crash faces, non-HTML markup), and rows that throw mid-wiring — and
unmount strips every mark and listener. The seat is pinned in the
compat matrix (SLOT_SEAMS) and the bundle smoke counts the new entry.
2026-09-04 18:27:01 +08:00
bowenliang123 33068ee1c9 compat: narrow the support matrix to dsh 0.1.2-rc.1+
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.
2026-09-04 17:23:08 +08:00
bowenliang123 d5d0fbda85 chore: add a bug report issue template 2026-09-04 13:51:46 +08:00
bowenliang123 7f4793211d docs: remove codegraph instructions in AGENTS.md 2026-09-04 13:42:32 +08:00