Commit Graph

3035 Commits

Author SHA1 Message Date
creatixchu
b9cbe2f029 fix(connection): fail the load on a trustedHosts entry that is not a bare authority
WHATWG parsing would quietly read a hostname out of harness.internal/path or
user@harness.internal, authorizing the typo's hostname; other typos would sit
silently ignored until requests 403. Refuse every URL part beyond host[:port]
at plugin load.
2026-07-28 15:57:02 +08:00
07akioni
fff09b2a41 Merge branch 'master' into feat/toolcall-open
Keep openFile path links (no tool-row sidebar handoff) while taking master's
cwd-relative summaries, running sweep, and expandable chevron polish.
2026-07-28 15:55:22 +08:00
_Kerman
1d4d6f881c Merge branch 'master' into xtr/identified-immutable-messages 2026-07-28 15:52:16 +08:00
_Kerman
019b0abb68 Merge remote-tracking branch 'origin/master' into xtr/identified-immutable-messages
# Conflicts:
#	.agents/notes/implemented/architecture/2026-07-24-separate-context-injection-from-turn-execution.i18n.yaml
#	docs/cordis-catalog/services.md
#	docs/core-data-structures/core.i18n.yaml
#	docs/core-data-structures/session.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/persistence-catalog.md
#	packages/core/session/README.i18n.yaml
#	packages/session-title/session-title/tests/persistence.spec.ts
2026-07-28 15:45:53 +08:00
creatixchu
7fd2abd828 feat(host): directory-picker capability seam with dialog and browse backends
The web GUI's folder picking was hardwired to one interaction: a native
OS chooser compiled into the gateway, unusable for remote deployments
and swappable only by editing apiproxy source.

Directory picking becomes a three-package capability seam in
packages/host: ctx.directoryPicker returns a discriminated capability —
dialog (the extracted native chooser; host-display only) or browse
(new: one-level listing + child creation over Node stdlib, hidden flags
host-stamped, symlinks followed, ancestry crumbs; remote-capable). The
gateway injects the seam, advertises the kind via
host.describe.directoryPicker, serves host.listDirectory /
host.createDirectory under browse, and answers
directory-picker-unavailable across kinds. cordis.yml is the swap
point; apps/cli keeps dialog mounted, so behavior is unchanged until
the in-app browser PR flips the default. The connection fixture serves
a deterministic browse tree; WorkspacesService gains the browse calls
the browser UI will drive. Decision record:
.agents/notes/implemented/architecture/2026-07-28-directory-picker-capability-seam.md
2026-07-28 15:44:53 +08:00
_Kerman
40c29495af Merge branch 'master' into xtr/trajectory-inspection-ui 2026-07-28 15:41:45 +08:00
Tianyi Cui
d70cb63833 Merge remote-tracking branch 'origin/master' into worktree/replayable-gate-plans-20260727 2026-07-28 15:41:26 +08:00
_Kerman
14c3d2ef9c Merge remote-tracking branch 'github/master' into xtr/trajectory-inspection-ui
# Conflicts:
#	packages/client/ui-primitives/src/Menu.tsx
2026-07-28 15:41:03 +08:00
creatixchu
01eea07bab fix(connection): keep LAN serving working under the /api browser-trust fence
Markerless requests pass on any Host (a non-browser sender is the principal
and forges headers anyway); browser Host matching gains port-less entries and
WHATWG normalization; dsh derives LAN IP-literal authorities for an
all-interfaces bind and web grows --trusted-host for named ones.
2026-07-28 15:40:02 +08:00
Tianyi Cui
108374772f Merge branch 'master' into xtr/remove-append-out-of-band 2026-07-28 15:36:20 +08:00
Tianyi Cui
2a5137f0e9 Merge branch 'master' into worktree/sandbox-master-only-20260728 2026-07-28 15:35:36 +08:00
Tianyi Cui
09a65125ba Merge remote-tracking branch 'origin/master' into worktree/replayable-gate-plans-20260727 2026-07-28 15:34:30 +08:00
_Kerman
102ebb8772 Merge branch 'master' into xtr/remove-append-out-of-band 2026-07-28 15:33:34 +08:00
Tianyi Cui
cbbd888cab simplify gate graph validation 2026-07-28 15:33:20 +08:00
_Kerman
b1af35145b fix: enforce message snapshot invariants 2026-07-28 15:33:00 +08:00
_Kerman
0cd28959e8 Merge branch 'master' into xtr/remove-append-out-of-band 2026-07-28 15:32:42 +08:00
Tianyi Cui
0a09924c00 Merge remote-tracking branch 'origin/master' into worktree/sandbox-master-only-20260728 2026-07-28 15:28:53 +08:00
imccyu
0bc9fa9546 Merge branch 'master' into fix/web-ui-optimization 2026-07-28 15:26:38 +08:00
Tianyi Cui
f85736e814 ci: run sandbox matrix on master only 2026-07-28 15:26:00 +08:00
_Kerman
833a58784f docs(session): refresh invariant metadata 2026-07-28 15:22:16 +08:00
_Kerman
f074444cf0 Merge remote-tracking branch 'origin/master' into xtr/remove-append-out-of-band 2026-07-28 15:19:00 +08:00
_Kerman
a39ffb095a fix(session): preserve plugin turn invariants 2026-07-28 15:18:48 +08:00
imccyu
ee9627f232 Merge remote-tracking branch 'origin/master' into fix/web-ui-optimization 2026-07-28 15:06:17 +08:00
Chinesezjc
fb5c4ef4e3 Merge remote-tracking branch 'origin/master' into feat/scrollbar-tokens 2026-07-28 15:02:38 +08:00
Chinesezjc
c3e9690b2e fix(ui-theme): gate the standard scrollbar properties behind the missing WebKit pseudo-element
A non-`auto` `scrollbar-width` or `scrollbar-color` makes Chromium and Safari
discard every `::-webkit-scrollbar*` rule for that element, including
`::-webkit-scrollbar-thumb:hover`. Declaring both unconditionally left the
hover tokens rendering nowhere: the engines implementing the hover
pseudo-element are exactly the ones the standard properties silence, and
Firefox has no hover pseudo-element to fall back on. Both hover tokens and all
four elevated surfaces' hover rebinds were therefore dead code.

Measured in chromium on probe elements with `scrollbar-gutter: stable`: an 8px
`::-webkit-scrollbar` alone reserved a 30px band, and adding
`scrollbar-width: thin` dropped it to the 10px `thin` reserves.

The standard properties now sit inside `@supports not
selector(::-webkit-scrollbar)`, so Firefox takes them and WebKit-based engines
take the pseudo-elements. The WebKit rules stay ungated: an engine without
those pseudo-elements drops them as unknown selectors, and gating them would
hide them from an engine that implements them without `selector()` — the
pre-16.4 Safari the ungated form serves correctly.

Three unit assertions pin the split by source offset, which the existing
at-rule-flattening parser cannot see. The web e2e now reads the path chromium
actually takes: the `auto` standard properties as the gate's signature, the
pseudo-element sizing and track, the indirection variables resolved per
throwaway probe, and the hover declaration as cascade rule text — chromium
folds the `:hover` rule into `getComputedStyle(el,
'::-webkit-scrollbar-thumb')`, so no computed query separates the states.
2026-07-28 15:02:20 +08:00
_Kerman
0a3d38bb08 Merge remote-tracking branch 'origin/master' into xtr/identified-immutable-messages
# Conflicts:
#	docs/event-producer-consumer.md
2026-07-28 14:59:40 +08:00
Tianyi Cui
6a763e4b3c Merge branch 'master' into worktree/ci-flake-followup-20260728 2026-07-28 14:58:47 +08:00
Chinesezjc
540cb59585 Merge branch 'master' into feat/web-terminal-card 2026-07-28 14:58:28 +08:00
Chinesezjc
5081697aaf feat(web): render bash tool output as a terminal card
The bash tool already declares the `card: 'terminal'` render intent for
both its call and its result, and host/connection/runtime already deliver
it to the browser as callView/resultView. The Web client ignored it:
rows derived from raw args, and the details panel flattened every tool's
content into one soft-wrapping `<pre>`. Column-aligned output folded into
a paragraph and a long listing stretched the panel without bound.

`TerminalBlock` (ui-primitives) renders a command as a terminal surface:
a shortened-cwd prompt line, output at `white-space: pre` in a
horizontally scrolling box, a head/tail height cap with an expand
control, an exit-code/signal status pill, and a copy control for the raw
output. ANSI SGR runs are parsed with `anser` and resolved onto `--dsw-*`
theme tokens, with literal rgb kept for values the design system has no
token for. Geometry and fonts mirror CodeBlock; the clipboard write both
need moved into a package-internal `clipboard.ts`.

Both Web render sites for a bash call consume the intent through one
derivation (`terminal-card-model.ts`), so they cannot disagree about a
command, its cwd, or its exit status: the keyed BashRow carries the card
resident below its summary row, and the render-site fallback row keeps it
behind its existing expand control. Rows cap at 8 lines against the
panel's 16.

Inline output in the chat row reverses this package's stated
no-inline-output convention, on the owner's explicit decision; the Agent
Note records the reversal and its bound.

Tests: TerminalBlock/ansi/clipboard unit specs, ui-conversation wiring
specs at every render site, a built-client-graph snapshot covering both
chat-row shapes, and a real-browser e2e asserting the no-wrap layout and
the page's own Clipboard API.
2026-07-28 14:58:06 +08:00
creatixchu
01d68dee4e fix(connection): fence every /api request behind one browser-trust check
The only browser-trust guard covered host.pickDirectory, while the
consequential methods (session.prompt drives bash) accepted any Host —
open to DNS rebinding, where a rebound page reads and writes the API as
if same-origin and only the Host header betrays the attacker's domain.

The pickDirectory-specific loopback guard becomes a prefix-wide fence:
Host must be loopback or an exact host[:port] from the new trustedHosts
config, an attached Origin must equal that authority, and explicit
cross-site markers are refused; requests without browser markers (curl,
tests, native clients) pass, because without a browser there is no
confused deputy. The loopback-socket check is dropped — binding policy
expresses reachability, and the fence is not an auth layer. The Agent
Note records the full threat model and the alternatives.
2026-07-28 14:56:45 +08:00
Tianyi Cui
fa18977ebd Merge remote-tracking branch 'origin/master' into worktree/pr742-retarget-20260728 2026-07-28 14:51:20 +08:00
Tianyi Cui
eeaf4c7220 fix(ci): stabilize readiness timing boundaries 2026-07-28 14:49:59 +08:00
NI0317
57cf137918 fix(fs-search): keep broad glob samples representative
Remove the duplicate model-facing list tool from this branch; directory orientation remains available through bash ls. Keep the glob sampling fix, add a real ACP composition snapshot, and narrow the decision record to the shipped bug fix.
2026-07-28 14:42:59 +08:00
_Kerman
cee0666a4d refactor(session): remove synthetic log-only turns 2026-07-28 14:41:51 +08:00
_Kerman
64b9535c31 refactor(client): replace patched JSON tree dependency 2026-07-28 14:37:00 +08:00
07akioni
b926044c13 feat: click file name to open file in toolcall, remove hover bg of toolcall, do not trigger sidebar any more (follow designer's instruction) 2026-07-28 14:24:41 +08:00
_Kerman
f5ec71f5b1 Merge remote-tracking branch 'origin/master' into xtr/identified-immutable-messages
# Conflicts:
#	.agents/notes/implemented/feature/2026-07-21-cross-session-references.i18n.yaml
#	packages/context/session-reference/README.i18n.yaml
#	packages/context/session-reference/README.md
#	packages/context/session-reference/README.zh.md
#	packages/context/session-reference/src/index.ts
2026-07-28 13:58:06 +08:00
_Kerman
fbf87e660c refactor: identify and freeze messages at creation 2026-07-28 13:55:59 +08:00
_Kerman
028ac5c2f6 refactor(client): isolate trajectory history reads 2026-07-28 13:50:46 +08:00
NI0317
4b5b22d42f Merge remote-tracking branch 'origin/master' into feature/directory-listing-tool
Master had advanced 392 commits. Every conflict was a derived artifact both
sides had regenerated — `docs/tool-catalog.md`, four recorded headless
session logs, and one TUI terminal expectation — so each was resolved by
taking master's version and re-running the generator and the keyless
snapshot refresh on the merged tree. No source file conflicted.

The new `examples/jsonrpc-agent` fixtures keep master's scrubbed
`{{system}}` / `{{tools}}` headers: that suite scrubs request headers, so a
new tool changes nothing there and the refresh output was discarded.
2026-07-28 13:48:28 +08:00
Chinesezjc
a6b0cd6f8d Merge remote-tracking branch 'origin/master' into feat/scrollbar-tokens 2026-07-28 13:43:11 +08:00
Hypatia May
43e81390a3 refactor(web): source the search result bound from its protocol constant
`ConnectionHandle.sessionSearchResultLimit` mirrored
`SESSION_SEARCH_RESULT_LIMIT` as per-connection state, giving one fact two
homes in the same module and implying a transport-varying or server-negotiated
bound that the response schema's fixed `max` forbids. `SessionsService` now
reads the constant directly and its constructor drops the parameter; the
connection handle and its unreachable `/client` value re-export go away.

The import comes from the inline-safe wire layer rather than the connection
plugin's `/client` surface, which the bundle-purity gate rejects for value
imports.
2026-07-28 13:34:23 +08:00
NI0317
451c21a5b6 fix(fs): quote a listed name only when it would misreport the listing
The review made every name a JSON string with `<`, `>`, and `&` escaped. The
hazards behind that are real and each is now covered: a control character
splits one entry across lines, `</` closes the envelope, and a regular file
named `x@` reads as a socket named `x` under the non-regular marker.

Quote those, and only those. `list` is the tool an agent reaches for first
and its output sits in every transcript, so `"archive"/` on every ordinary
line is a permanent cost for a case that almost never occurs. A name is now
emitted verbatim unless it matches a control character, a leading quote, a
backslash, `</`, or a trailing `@`, and is otherwise a JSON string with `</`
neutralized — the delimiter treatment `dsh-workspace-context` already applies
to instruction text, extended to an interpolated path as its
`instruction-frame-paths` TODO asks.
2026-07-28 13:16:24 +08:00
NI0317
717852423f fix(fs): harden directory listing and glob sampling 2026-07-28 13:01:26 +08:00
Yif
3134f2d430 doc: agent note for the web conversation polish sweep 2026-07-28 12:36:29 +08:00
Hypatia May
9ca0241d5d feat(web): add durable session metrics (round 1) 2026-07-28 12:10:48 +08:00
imccyu
b5168bbf86 feat(ui-slots): bind inject hooks compartments into use<Name> selector hooks
Registrant-private reactive facts previously reached components as raw
observables that each component subscribed by hand (InputBar notices/
lexicon via uSES, SettingsRoot via a version/subscribe/getter triple).
The inject face now carries a reserved hooks compartment of bare
sources; the renderer binds each into a use<Name> selector hook through
the same machinery as the provide channel, so components consume
useNotices/useLexicon/useSections and never see a subscription
primitive. InputBar and SettingsRoot are the first two consumers.
2026-07-28 12:09:48 +08:00
imccyu
c4df0628db docs(notes): record reactive provide projection and lexicon subscription decisions 2026-07-28 12:09:48 +08:00
Chinesezjc
474b88e362 docs: record the plugin-bundle rebuild trap in the scrollbar note
Verifying browser-visible plugin CSS needs a rebuild build:web does not
perform: WorkspaceBrowser.module.css never reaches apps/web/dist, because
ui-workspace loads as a runtime plugin with its CSS inlined into
lib/client.js by that package's own bundle script. A negative control that
reruns only build:web exercises a stale bundle and passes with the
declaration removed, which reads as a vacuous test rather than an invalid
control. No script in the web lane does this rebuild, so every scroll-region
or plugin-CSS change hits the same trap.
2026-07-28 12:09:18 +08:00
NI0317
a9c0e00620 docs: record the directory-listing and glob-sampling decision
Agent Note for the two changes: what the session log showed, what ordering
can and cannot fix (measured, correcting the first diagnosis), why the page
is sampled only past the cap, why `list` is needed alongside it, and the
alternatives each one beat.
2026-07-28 12:06:25 +08:00