Commit Graph
320 Commits
Author SHA1 Message Date
Bowen Liang 5cc028ff00 feat(client): replace history paging with seq-targeted content fetch
The Context browser joined full content against the chat conversation
window; when a surface node's seq sat outside it, the fallback paged
blindly backwards through session.loadOlder() (up to 20 pages of 50
messages prepended into the shared chat window) and finally dead-ended
on a static note.

sessions.history already supports seq-anchored pages cut on whole
append-origin message boundaries, so ONE call with beforeSeq: seq + 1
returns exactly the page holding the event whenever the durable log
still has it. The browser now:

- fetches on miss with that single anchored read and maps the raw page
  into the node shapes it already renders (new client/historyPage.ts:
  user messages, assistant blocks, tool results paired with their
  in-page call head, compaction checkpoints with their summary);
- merges fetched nodes under the zero-cost window join (join wins);
- reports honest states instead of one dead end: loading, absent from
  the session log (compacted or cleared), failed with a retry button;
- drops the sessions.provide contribution and the MAX_AUTO_PAGES
  machinery entirely - the chat scrollback is never mutated again.

Hosts without the connection api keep the static preview-plus-hint
degradation.
2026-08-26 03:34:24 +08:00
Bowen Liang 5a2b742d50 docs(AGENTS.md): clarify pnpm coverage requirement
Document the intent of the pnpm coverage check: ensure code coverage is
literally 100%.
2026-08-26 02:18:55 +08:00
Bowen Liang eb9c9b0352 ci: test without a build step; verify packaging via the bundle smoke script
The source-level suite needs no lib/ artifacts, so PR checks test
first and build afterwards solely to feed scripts/bundle-smoke.mjs;
the release workflow gains the same smoke step between test and
publish.
2026-08-26 00:59:15 +08:00
Bowen Liang a9b6d287fe test: remove the legacy bundle-dependent suite
All 19 root-level specs and the fake-React viewBed helper are
superseded by the source-level suite (606 tests, 100% per-file
coverage). The packaging behaviors they pinned (bundle handoff, CSS
channel, HMR disposal) live on in scripts/bundle-smoke.mjs.
2026-08-26 00:58:57 +08:00
Bowen Liang f106b720ac test: rebuild the suite at source level with 100% per-file coverage gates
The old suite exercised the built lib/ bundle, so v8 remapped almost
nothing (8% src coverage) and every run needed a build first. The new
suite imports src/ directly under two vitest projects (node for
host/shared, jsdom for client), rendering real React 18 trees against
the real dictionaries and ui-primitives, with faithful in-memory
harness faces (cordis inject/effect, locale chain, slots, sessions
provide) instead of plugin mocks.

- 43 fine-grained, stateless, single-module spec files (606 tests)
  forked across workers: ~2.5s wall, no build step
- v8 thresholds at 100/100/100/100 per file over src/**
- host specs drive the real projection definitions (init/apply/view)
  plus one full cordis + SessionStore + SessionProjectionRegistry
  integration; the framework's snapshotJsonValue pins the
  projection-cache precondition on every intermediate fold state
- oxlint's src ruleset now covers tests/** as well
- typecheck covers the tests via tsconfig.tests.json
2026-08-26 00:58:39 +08:00
Bowen Liang f45bd7e8d2 chore(scripts): move diff-fold out of tests/ and drop its lib/ dependency
The session-log divergence check runs under bun against src/ directly,
tracking the working tree instead of the last build. Also add
scripts/bundle-smoke.mjs (pnpm run test:bundle): the one check that
must exercise the built bundle — module-loader handoff, CSS channel
tagging, registration disposal and HMR style-tag semantics in jsdom
with real React.
2026-08-26 00:57:58 +08:00
Bowen Liang ba586e18f7 test(src): annotate evidence-backed dead branches for strict v8 coverage
Every annotation carries its evidence inline (guard dominance chains,
the 8:1 aspect clamp making the wide-solve arm unreachable, a
500k-dimension fuzz with zero hits). browser.tsx also drops two
redundant `?? null` in JSX render positions — undefined and null
render identically.
2026-08-26 00:57:28 +08:00
Bowen Liang 4e5e71a96c fix(client): widen slot-face types to the harness's real call shapes
SlotRegistration.inject is invoked without a session id for root-scope
keyed slots (settings.plugin.item), and slot components receive
harness-injected props beyond sessionId (useProjection, hooks). The
narrower types made the plugin's own registrations fail a strict
typecheck of the test harness's faithful slot registry.
2026-08-26 00:57:08 +08:00
Bowen Liang ecd9af93a8 feat(client): open the system prompt row by default when its category is clicked 2026-08-25 23:08:31 +08:00
Bowen Liang 2300167abc update coding instruction for pre-commit actions 2026-08-25 23:01:44 +08:00
Bowen Liang 61098c2a4c update coding instruction for pre-commit actions 2026-08-25 21:38:47 +08:00
Bowen Liang 9a64d2ab48 Add vitest coverage command with HTML report
Introduce `pnpm run coverage` to run vitest with v8 instrumentation,
generate a browsable HTML report under ./coverage/, and gate it from
git. Scope coverage to the src tree only: lib/ is the tsdown build
artifact and has no executable surface to cover. Exclusions are
limited to pure type modules (ambient .d.ts, src/shared/types.ts,
src/host/compat.ts) so the summary reflects runnable code.
2026-08-25 21:13:38 +08:00
Bowen Liang 7ee5e8c8df feat(client): unify step brief rows with the context browser's tag+preview anatomy
Brief lines now decompose every node into a fact tag plus preview text,
mirroring the browser element row a click reveals: tool inputs lead with
the tool NAME chip, replies chip their call breadcrumb, injections tag
the form, user messages tag image attachments. Inputs and the reply share
one nodeChip renderer — compact clickable chips for inputs, a single
row-grown chip for the reply.
2026-08-25 21:05:10 +08:00
Bowen Liang a20f9a028a feat(client): show line count on all raw/markdown sections in context browser 2026-08-25 20:27:01 +08:00
Bowen Liang 5aca062963 chore: switch npm run to pnpm run in scripts and comments 2026-08-25 19:55:15 +08:00
bowenliang123 8531298303 chore: bump version to 0.32.0 2026-08-25 15:20:46 +08:00
bowenliang123 353930f4ea docs(release_template): update section header for consistency in formatting 2026-08-25 15:08:25 +08:00
bowenliang123 ebd2c78673 docs(readme): rewrite the Context Trend section around the step brief
New hero screenshot (context-trend.png) showing the User/In/Response
rows; the section is now bulleted with the step brief first. Drop the
stale history-step-hover.png (unreferenced, predates the tooltip's
reply preview).
2026-08-25 15:04:24 +08:00
bowenliang123 b3c5440637 feat(client): rename cards to Current Context / Context Trend (当前上下文 / 上下文趋势)
'History' in dsh names the chat message log itself, so the trend card's
old names (Context History / 历史趋势) read as a message list; the new
names align the two locales and match what the card shows. The overview
card follows the same pairing (当前构成 -> 当前上下文, already
'Current Context' in English).
2026-08-25 15:04:23 +08:00
bowenliang123 a7e3c0aa79 feat(trend): step brief under the history chart — turn opener, step inputs, and reply at a glance
Each history bar now carries its semantic identity below the detail head,
derived client-side from the served surface nodes (a request's seq IS its
response's node seq):

- User row: the message that opened the turn, recalled on any of its steps
- In row: what newly entered the context (tool-result chips, err dots)
- Response row: the reply text, the call breadcrumb for text-less replies,
  and the call suffix recovered via the conversation join for text+calls
  replies (the fold keeps calls only on text-less nodes)

Plus: one-line reply previews in the chart tooltip, and a click-to-reveal
bridge that opens the row's node in the Context browser (one-shot nodeFocus
prop, same hand-back pattern as toolFocus; reply nodes resolve on the NEXT
step's surface, per the assemble seq window).

No host/wire changes; steps beyond node/archive retention degrade silently.
Shared call-argument summaries extracted to callSummary.ts (browser reuses).
2026-08-25 14:39:54 +08:00
bowenliang123 7e522ea342 chore: bump version to 0.31.1 2026-08-25 12:52:09 +08:00
bowenliang123 c2484f899a fix(detail): unify detail-num widths so delta rows don't jump on hover
The number column flipped between 44px (zero) and 52px (+n/-n) every
time the user hovered a different bar in delta mode, shifting every
neighbouring row by 8px. Lift tabular-nums and the wider width onto the
base .lc-detail-num; the zero cell right-aligns in the same slot.

Fixes #19 (number column half).
2026-08-25 11:42:54 +08:00
bowenliang123 3ff9252b5d fix(chart): reserve scrollbar gutter so the card height stays invariant
scrollbar-gutter: stable keeps the horizontal gutter unconditionally, so
the trend chart card no longer jumps when the overflow toggle fires
(solid-scrollbar platforms: Win/Linux Chromium). The 8px padding-bottom
stays as a safety net for browsers that under-reserve.

Fixes #19 (chart card half).
2026-08-25 11:42:44 +08:00
bowenliang123 e94b3e400f style(client): right-align card sub-hint within title row 2026-08-25 10:00:38 +08:00
Bowen Liang 4a072f0c55 refactor(client): trim post-audit redundancies, no behavior change
- contextView: drop the tick-based locale re-render subscription; the
  harness slot outlet subscribes the LocaleFace revision and re-renders
  every entry on a locale switch (verified back to dsh 0.1.0-rc.7), and
  the bound t reads the active locale at call time
- browser: delete the never-read catColor map; countOf now takes the
  prebuilt byCat/prevByCat maps instead of rebuilding byCatOf per call
  (up to 13 map builds per render)
- categories: export CAT_COLORS built once from CATS; nodes reuses it
  instead of rebuilding per render
- trendChart: deltaOf rest-destructures prompt/output out instead of
  spread + two deletes
- statsBoard: hoist the pure cell helper to module scope
- services: drop the now-unconsumed LocaleService.subscribe face member
- tests: shift ContextView hook-slot indices after the tick removal,
  drop the dead stats.recycleSub fixture key and the dead locale
  subscribe stub
2026-08-25 00:13:26 +08:00
Bowen Liang 79950c9822 fix(browser): mark killed/failed job_output status lines as failed
job_output always terminates its read with the tool-jobs status line
[status: killed] / [status: failed, detail], and a background job that
dies settles with isError false — so the read showed a green OK for a
dead job. tailStatusOf now treats the two terminal failure statuses as
failures; completed/running/stopping stay notices.

This goes beyond the official chat UI, which renders job_output as a
generic card and shows OK too.
2026-08-24 23:22:39 +08:00
Bowen Liang 3f37450a0f fix(browser): mark persistent-shell death markers as failed
tool-bash-persistent/tool-pwsh-persistent append shell-death markers at
the end of a result's text with isError still false: [shell killed by
signal: X] and [shell exited: code N] ride LAST, after the [exit code: N]
of the command whose failure killed the shell — so the command marker
alone no longer anchors at the end and was missed.

tailStatusOf now parses the shell marker first and re-checks the
preceding text for the command's exit code, so the pill still surfaces
it. A clean shell exit (code 0 or code-less) loses the session but is
treated as a notice, not a command failure.
2026-08-24 23:20:44 +08:00
Bowen Liang bb5a83d61c fix(browser): mark tool results with trailing exit/signal markers as failed
dsh settles a failing command as a completed call (isError stays false;
the exit status is result data), so err/isError alone never flags a
non-zero exit and the context browser showed a green OK where the chat
row shows red. Mirror the chat's terminalFailed: a result is failed when
its text ends with dsh's [exit code: N] or [killed by signal: X] marker.

The exit-code match is now end-anchored like dsh's parseExitStatus, so
marker text quoted inside the output (e.g. a cat'ed log) is not a
failure, and the FAILED pill always surfaces the parsed exit code
instead of gating it behind err.
2026-08-24 23:02:51 +08:00
Bowen Liang 8574ba51c1 docs(readme): document delta trend mode, vs-previous-turn diff, and tool result rendering 2026-08-24 22:42:13 +08:00
Bowen Liang 796e4f7a54 chore: bump version to 0.31.0 2026-08-24 22:08:10 +08:00
Bowen Liang efcdd37cb7 feat(trend): make delta mode signed end to end
Delta mode previously took per-category magnitudes for the bars while
the detail panel below still showed cumulative totals. Now:

- The chart draws diverging stacks: growth piles up from a solid zero
  baseline, shrinkage hangs down from it, with the zero line splitting
  the bar area proportionally so the px-per-token scale is identical on
  both sides. Axis reads +max / 0 / -max.
- The detail panel pairs the active request with the previous displayed
  record (same pairing as the chart): a signed net chip replaces the
  provider usage pills, category rows show signed figures on the
  success/error tokens, and each row's mini bar diverges from a center
  zero hairline, echoing the chart.
2026-08-24 22:06:56 +08:00
Bowen Liang 9938fb7cef style: wrap long comments to satisfy max-len lint rule 2026-08-24 20:57:52 +08:00
Bowen Liang 928043bfeb docs: add linting step to code review process in AGENTS.md 2026-08-24 20:56:34 +08:00
bowenliang123 46e52d136c chore: bump version to 0.30.3 2026-08-24 18:24:56 +08:00
bowenliang123 6e19c8e950 refactor(trend): rename the diff display mode to delta
Aligns with the token-meter vocabulary of recent dsh releases (signed
token delta) and with the existing zh label 增量. UI labels, i18n keys,
settings schema, client logic and tests all switch from diff to delta.
The settings schema is now loose on defaultTrendMode so a stale
persisted value degrades to the default instead of throwing, and the
client ignores unrecognized values the same way.
2026-08-24 18:24:52 +08:00
bowenliang123 9db79ca69d chore: bump version to 0.30.2 2026-08-24 18:12:35 +08:00
bowenliang123 55a675ef8b style(detail): tidy the trend detail head row
Restyle the request detail header for a cleaner, more consistent look:
- even 8px gaps and center-aligned items on the single wrapping row
- time pinned right with tabular figures
- provider figures (actual prompt / output / cache) as uniform neutral
  pills with tabular numbers, replacing the plain spans and the two
  same-green accent colors
- marker chip tinted with the warn color, matching the event list chips
2026-08-24 18:12:12 +08:00
bowenliang123 0d052f243c chore: bump version to 0.30.1 2026-08-24 18:10:23 +08:00
bowenliang123 c3c6015a95 feat: step-level cache hit rate on the step detail line
Drop the heuristic estimate from the step header; show the provider-reported
cache-hit share of the billed prompt (cacheRead / prompt, truncated to two
decimals) instead. The host folds each request's cacheReadTokens into its
record (stateVersion 9); the stats board reuses the same formula via a shared
format helper.
2026-08-24 17:57:50 +08:00
bowenliang123 1e1dc14cd1 chore: bump version to 0.30.0 2026-08-24 17:19:41 +08:00
bowenliang123 d0b8f0daa0 chore(config): trim comments in build config, scripts and docs tooling
Compress the CSS-channel note in tsdown.config.ts, the vitest lane
explainer and the release workflow header; fix the install-hooks header
(git only consults .git/hooks when core.hooksPath is unset); slim the
social-preview generator and bundle-patch comments.
2026-08-24 17:16:40 +08:00
bowenliang123 89fc5674c7 chore(tests): strip comment noise in the test suite
Remove assertion restatements, act narrations and decorative section
markers; keep fixture math, harness-gotcha rationale and slot maps.
Fix stale comments: ctxSlots maps (trendMode shift), a dangling fixture
fragment, and the cardRig 'expanded via header' claim.
2026-08-24 17:16:34 +08:00
bowenliang123 0eea57067a chore(client): strip comment noise in the client half
Apply the full-repo comment audit to client logic and components: drop
narration-style JSDoc and duplicated cross-file comments, keep only
non-obvious contracts (module-table require, projection keys, hooks
rules, no-white-screen guarantees). Fix stale claims: locale fallback
chain (en, not zh), unfounded 'harness block vocabulary' mirror, kind-chip
tint mapping, stats tooltip z-index, onToolFocus parenthetical.
2026-08-24 17:16:31 +08:00
bowenliang123 aaf1aa50a3 chore(host): strip comment noise in host and shared modules
Apply the full-repo comment audit to the host half and shared wire types:
delete restatements and decorative headers, compress rationale comments to
one line, and fix stale references (agent-loop buildRequest, live-surface
image cell, five->four priced categories). Kept only contract notes,
invariants (plain-JSON precondition, shadow-seqs protocol) and verified
dsh-mirror pins.
2026-08-24 17:16:27 +08:00
bowenliang123 79db9bd5d9 test(chart): align trend-chart assertions with the current render
The turn strip renders each label inside a nested `lc-turn-label` span
(added with the scroll-centering work), so the label assertions must read
through textOf instead of expecting a bare string. The scroll/layout
handlers also call updateTurnLabels (querySelectorAll over the scroller),
which the fake scroll elements must stub — an empty querySelectorAll keeps
the label-centering a no-op without touching the asserted behaviors.
2026-08-24 15:49:09 +08:00
bowenliang123 1164371424 docs: update AGENTS.md with pre-commit checklist and best practices 2026-08-24 15:44:10 +08:00
bowenliang123 d7486585fe style(browser): wrap markdown and long tokens in detail cards
Markdown cards render soft line breaks (a single newline now breaks the
line via white-space: pre-line — two newlines still separate paragraphs)
and long unbroken tokens wrap in place: the section card gets min-width: 0
so it shrinks below its content, the body adds overflow-wrap: anywhere
with horizontal overflow hidden, and code blocks keep pre-wrap with
overflow-wrap so long code lines wrap instead of scrolling sideways.
2026-08-24 15:38:40 +08:00
bowenliang123 c23ff27ac4 feat(browser): red run-state dot on failed tool-result rows
A failed tool result now leads its collapsed row with the chat's red
run-state dot (6px core, 10px halo) right after the chevron, so the
failure scans without expanding. The failure state comes from the fold's
`err` stamp OR the conversation snapshot's `isError` — the mismatch
matters: dsh only stamps the event envelope's `error` info
conditionally, while the snapshot block always carries `isError`. The
redundant ⚠ suffix on the tool-name chip is dropped (the dot marks
failures), and per-row conversation lookups are hoisted into one `conv`
for the merged condition.
2026-08-24 15:37:58 +08:00
bowenliang123 66c964d0ee feat(browser): tool-result detail cards — run-state pill, line count and raw/markdown switch
The call half of an expanded tool result drops its argument-count badge
(the rows below already show the arguments); the head's right edge now
carries a run-state pill — green OK by default, red Failed with the
payload's terminal `exit N` code when the fold's `err` stamp or the
snapshot's `isError` marks a failure (exit recovered from the dsh
`[exit code: N]` marker). The payload card heads its line count before
the raw/markdown switch (switch stays at the far right), and its text now
renders through the same switchable prose anatomy as every other detail
section instead of the fixed dim raw view.
2026-08-24 15:36:06 +08:00
akouandClaude Opus 5 78bbb0fbdf docs: add dshfind badge to README (#15)
dsh-context is listed on dshfind (a DeepSeek Harness plugin directory)
and currently carries the "Featured" mark there. The badge links back to
the listing page.


Claude-Session: https://claude.ai/code/session_01Qj6wERPu4n2to3KmBXcVEz

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 09:52:48 +08:00