Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .agents/skills/dsh-ui/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ description: Use when building, styling, or reviewing in-harness UI — the BotH

The in-harness UI is part of the shell, not a standalone app (ADR-0028): style with `--dsw-*` tokens, compose with `ui-primitives`, and copy the native layout contract instead of inventing spacing. **Measure the running shell; do not guess.**

Before designing or reviewing a changed surface, apply the shared [UI design standard](../../../docs/agents/ui-design.md) and its review gate: layout, icons and interaction carry the task; prose supplies only necessary context.

## Build order

1. **Slot wiring** — register through the documented seams: `sidebar.footer.action` for the persistent entry; shadow `sidebar.workspaces` and `main key=conversation` only while a mode is active, reconciling from one store and disposing on exit. Desktop Bot mode also shadows the whole `sidebar` slot at `-1` to draw the Bot mode sidebar (ADR-0203); a shadow cannot re-render the native `sidebar.*` sub-slots, so it must provide its own way out of Bot mode. Keep one entry per concept. Done when the entry appears in the running shell and the shipped UI returns intact when the mode is off.
2. **Tokens** — every colour, font, and radius reads from `--dsw-*` (static/alias/specific layers); dark arrives through `body[data-ds-dark-theme]`. Brand accents stay inside the ≤3-entry alias block. Done when the `styles-tokens` guard passes and a dark pass shows no unreadable text.
3. **Design system** — build Bot-mode surfaces from `packages/client/src/client/ds/` (ADR-0194): `SettingsDialog`, `SettingsSection`, `SettingsRow`, `Select`, `NumberStepper`, `Note`, `EmptyState`, styled with StyleX and the tokens in `ds/tokens.stylex.ts`. Follow its content rules: one title, one line of description and one control per row; switches, choices and steppers apply on change; one text field saves on Enter or blur; at most one primary button; internal ids and revisions stay out of the default view. Visible text follows [UI copy](../../../docs/agents/ui-copy.md). Done when the `design-system-tokens` guard passes and no new `bh-` rule duplicates a component.
3. **Design system** — build Bot-mode surfaces from `packages/client/src/client/ds/` (ADR-0194): `SettingsDialog`, `SettingsSection`, `SettingsRow`, `Select`, `NumberStepper`, `Note`, `EmptyState`, styled with StyleX and the tokens in `ds/tokens.stylex.ts`. Follow its content rules: one title and one control per row, with an optional short description only when it adds a needed fact; switches, choices and steppers apply on change; one text field saves on Enter or blur; at most one primary button; internal ids and revisions stay out of the default view. Visible text follows [UI copy](../../../docs/agents/ui-copy.md). Done when the `design-system-tokens` guard passes and no new `bh-` rule duplicates a component.
4. **Composition** — for a net-new surface or control, pick the closest precedent in `references/design-references.md` before choosing layout; borrow composition, hierarchy, and states, not styling. Done when the PR names the borrowed pattern and every deliberate deviation.
5. **Layout** — apply the native inset contract in `references/native-contract.md`. Done when top-level content measures 16px from both sidebar edges and list-row backgrounds reach the scrollbar gutter.
6. **Primitives & icons** — use the exported set (`Input`, `Tag`, `Pill`, `StateDot`, `Tooltip`, …) and `Icon*Outline16` glyphs where geometry matches; keep a custom icon only where the set has no analogue. Done when controls sit on the shell's grid; record every deliberate omission (for example the 36px capsule `Button`) in the PR.
Expand Down
2 changes: 2 additions & 0 deletions .agents/skills/verify-deepseekbot/features/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

| Feature | Needs a model | Scripted journey | File |
| --- | --- | --- | --- |
| Connect encrypted pairing, resources and native private input | yes for DM/tool/private request | `verify-app` isolated Host and shared native QA | [connect-channel.md](connect-channel.md) |
| Browser Remote Host pairing, icon strip, Host Feed and Host-level settings | only for a reply | `verify-app` two-Host path | [remote-hosts.md](remote-hosts.md) |

| VRM companion Panel | yes for speaking | `scripts/e2e-vrm-companion.mjs` | [vrm-companion.md](vrm-companion.md) |
| Desktop whole-window zoom (controlled S1 / Windows candidate) | no | `scripts/e2e-desktop-zoom-launch.mjs`, `scripts/e2e-desktop-zoom-windows.mjs`, `scripts/e2e-dock-zoom.mjs`, `scripts/e2e-workspace-chrome.mjs` | [desktop-window-zoom.md](desktop-window-zoom.md) |
| Global search: Alt/Option+K, settings results and pinyin matching | no | `verify-app` Bot mode path | [global-search.md](global-search.md) |
Expand Down
27 changes: 27 additions & 0 deletions .agents/skills/verify-deepseekbot/features/connect-channel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Connect encrypted channel

## Sub-features

- Host fingerprint: Devices and `connect-status` expose one stable public identity across restart.
- Pairing: new phone/browser independently compares Host fingerprint; trusted Host approves the exact device key. No ordinary operation works while pending.
- Traffic: DM, image upload/download, avatar, approval, native private input, push registration and logical streams use the channel.
- Failure: changed/missing keys, replay, malformed frames, cancellation, revocation and reconnect fail closed without plaintext Connect fallback.
- Removal: full phone WebView remains absent; Connect Browser/Computer viewers remain unavailable.

## How to get to it (user POV)

Host Settings → Devices shows the Host fingerprint and pending device keys. Pair from the native phone or Add remote in another trusted Host's browser. Compare the complete Host fingerprint with the independent Host display, then compare and approve the device fingerprint on the Host. In chat, open a pending private-input request and choose Fill privately. Activity opens the same native form.

## Driving it with verify-app

Build and launch a named isolated Host with `verify-app`; run doctor with local network/process permissions. Use a second trusted browser Host for remote chat. Enable only a task-owned local connector or specifically authorized real tunnel. Qualify a real phone through the shared QA queue; a browser or Node carrier is not native proof. Use official DeepSeek credentials for a real DM and disposable private input.

Capture HTTP headers/URLs and WebSocket frames at the Connect origin before channel decryption. Compare synthetic sentinels with those bytes; preserve only redacted pass/fail summaries for publication. Read the owning Host's canonical timeline, approval outcome and private-input status. Verify `device-approve-key <receipt> <public-key> --confirm` and `connect-status` against this live Host. Restart the same isolated Profile and verify a stable fingerprint; reconnect must use new ephemeral keys. Revoke the device and verify open streams close.

## Gotchas

- A Node socket mapped from a Connect hostname to a local origin qualifies the application carrier and native DSH dispatch, not Cloudflare reachability or native key storage.
- The mobile QA queue may be paused. Keep iOS/Android/Human checks explicitly unrun rather than claiming web-export pixels as native evidence.
- A browser served through an untrusted intermediary is outside the executable-code trust claim. Origin-local storage is not hardware protection.
- Never capture real credentials or private chats. Only synthetic test input belongs in published evidence.
- Protocol vectors and peer reviews do not constitute an external security audit.
2 changes: 2 additions & 0 deletions .agents/skills/verify-deepseekbot/features/phone-pairing.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ A Human pairs the phone app with their Host by a one-time QR code, and the phone
- `link-errors` words a refusal by how the phone got the offer: a pasted or opened link that is broken, expired or already used says the link is wrong, and a pasted one empties the field; a scan keeps the code wording.
- `manual-input` keeps the empty link field and Pair button above the Android keyboard. A manually scanned or pasted offer registers the phone, loads the Host roster and survives app process restart.
- `cloud-exit` leaves the native pairing modal before opening Cloud services, so Workspaces exposes a visible, operable drawer.
- `fingerprint-steps` opens a fresh encrypted invitation. The scan/link form is replaced by a focused computer verification page with all 64 fingerprint digits, selectable grouped text and native actions. Expand/collapse the explanation without granting trust. A mismatch or Back must cancel without opening a channel; a fresh invitation still works. Explicitly compare with the trusted Host, tap Fingerprints match, then compare the full phone fingerprint with Host Devices and approve only that key. The phone waits without a second trust action and remains cancellable. Check light/dark and default/intermediate/maximum text; compare full fingerprints before scrolling to reachable actions. Both account and direct-link routes use the same verification view.
- `pair-return` uses the existing assigned iOS Simulator: compare the real Connect Host fingerprint, approve the exact displayed device key, then immediately open Chats, Settings (close and reopen) and Activity without restarting/reloading the app. Require no `sheetPresentationController` error or blocked taps. Repeat with the first-use notice unread/read, light/dark and default/intermediate/maximum system text. `apps/mobile/.maestro/sim/pairing-return.yaml` runs the post-approval interaction check without launching or clearing the app; keep native approval and capture evidence alongside it.
- `roster` shows the Host's PersonaBots in the app through the gateway, with the live stream.
- `restart` keeps the phone connected after a Host restart without pairing again.
- `devices` lists each phone with its pairing and last-seen time.
Expand Down
5 changes: 4 additions & 1 deletion .agents/skills/verify-deepseekbot/features/remote-hosts.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ The browser pairs a Remote Host as a Paired Device and reads its Host Feed throu
- `message-body`: remote images, files, rich text and request cards use the existing message body, with authenticated resources and decisions on the source Host.
- `upgrade`: existing browser pairings and the selected tab survive the storage-key rename.
- `remove`: removing a Host forgets its rows, stops its Inbox and releases cached avatar object URLs.
- `secret-route`: Connect private input shows a bilingual trusted-route notice without secret fields. Cancellation remains available; the shared Host client refuses before serialization. Loopback/Tailscale retain submission.
- `secret-route`: pinned Connect pairings carry private input, resources and logical streams through Noise; legacy pairings fail closed. The browser must be served by its own trusted Host. Loopback/Tailscale retain their contract.
- `viewers`: a remote Bot DM opens Browser or Computer when that Bot has access. The shared Host viewer modules read frames and send input to that Host only; closing, switching source or losing the connection tears down the viewer and releases requested control.
- `viewer-control`: queued input belongs to one takeover. Resume or frame loss invalidates it; frame recovery remains read-only even when the Host Feed never disconnected. Remove closes viewers and waits up to five seconds for takeover/release cleanup before revoking the pairing.
- `settings`: right-click a Remote Host icon → Remote settings opens that Host's models, usage and storage. Default model and preset changes use its shared Host client. Usage includes Memory activity, without a link to a This Host Bot page. Storage retains preview, acknowledgement and destructive confirmation.
Expand All @@ -22,6 +22,7 @@ The browser pairs a Remote Host as a Paired Device and reads its Host Feed throu
Discovery uses the Host's notification query, not the Activity display window. Keep more than 30 old mentions and produce a new ordinary DM reply and a non-mention group reply; both must alert once when enabled. Traverse `deepseekbot inbox --notifications` cursors and compare the Host-decided items. Verify stable same-timestamp pagination, a live invalidation during paging, a partial-page failure followed by recovery, and no historical replay. A refused Notification constructor records a bounded redacted `remote-notification-show-*` diagnostic through the existing Client diagnostics surface. Settings apply immediately and close through the normal close control.



## How to get to it (user POV)

Enter Bot mode, then Messages. Open the channel header's add menu and choose Add remote. Paste a link from the other Host's Settings → Devices → Pair a phone. Choose All or the Remote Host icon, then a Bot or group row. Right-click the Host icon and choose Remove to remove it. A remote Bot DM with Browser or Computer access shows the corresponding header button. Open its viewer, choose Pause Bot and take control, interact with the screen or send text, then Resume Bot or Close viewer. Groups have no viewer entry.
Expand Down Expand Up @@ -58,6 +59,8 @@ For message bodies, upload an image and a text file to Host B through its attach
- Dismiss Continue and Skip onboarding overlays before selecting Messages. Retain any failed drive evidence before retrying.

For #2541, pair a Connect Host and open a pending private input card. Confirm the notice in both themes, absence of password fields and working Cancel. Verify marked unary and mux calls return `secret-route-refused`, and ordinary Host Feed traffic still works. The removed `/botharness-device/web/` route must return 404. Use synthetic secrets only; a model quota failure blocks live card creation and must remain an explicit QA gap.

For #2542, independently compare the displayed Host fingerprint, then approve the exact pending device key in Host Settings → Devices. Keep the browser's key/pin/credential in one atomic origin-local record. Open remote chat, send text and an image, approve a tool request and fill a synthetic private request. Correlate visible state with the owning Host's timeline and private-input status. Capture the outer Connect origin before decryption: no device credential, offer, secret, inner path or attachment name may appear. Test revocation, changed pins and stripped capability; none may retry a plaintext Connect path. WebView and Connect viewer URLs remain refused. See [the Connect journey](connect-channel.md) for transport-specific gates.
Activation race regression: while replies are disabled, write 35 old mentions and keep a notification page pending, then enable replies. The switch/CLI write commits only after a complete fresh baseline; old mentions stay silent. After success, send a new group reply and ordinary DM (including tied timestamps in automated fixtures): each alerts once. Fail a page and retry, disable/re-enable, change Host, close settings, revoke permission and dispose while activation waits; failed/cancelled operations cannot commit later. Preserve the original 37-alert failing trace separately from any subsequent pass.

CLI deadline regression: let the real appearance relay refuse at eight seconds, then complete the notification baseline at nine seconds. Browser preferences and persisted storage must remain unchanged, and no late acknowledgement is sent. Repeat after control unmount; a pre-deadline successful write remains operable. Change the app locale while the DOM language is unchanged and verify private-input notification copy follows the bound translator without exposing the input.
Expand Down
31 changes: 31 additions & 0 deletions .github/pr-screenshots/2542/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Connect Noise XK — review evidence

Issue #2542, stacked PR #2547 above Track A #2546. Synthetic accounts and values only.

## Captures

- `private-before-{light,dark}.png`: Track A's existing remote Web card blocks secret input over Connect. Copied without alteration from #2546 evidence; the captured behavior is unchanged at stack base `b842d3ce0750b5085106defef21c4d4eb0112f81`.
- `private-after-{light,dark}.png`: a trusted second Host's browser paired through the actual encrypted channel, after independent Host fingerprint comparison and explicit approval of its exact device key. The remote card shows a masked field and a working submit action. The visible result was **Submitted**, canonical status was **configured**, and the official DeepSeek Bot resumed with `ENCRYPTED-PRIVATE-OK`. No page errors were observed. The driver's final English wait initially expected “Saved”; the captured “Submitted” state was reconciled with canonical state separately.
- `mobile-web-{light,dark}.png` and `mobile-web-saved.png`: Expo Web at 390 × 844, using the real isolated Host through the encrypted carrier. The input is `type=password`; submitting the synthetic value clears the field, renders **已处理**, and settles canonical state to **configured**. The corrected bilingual driver completed with no page errors. These are **Web export captures, not iOS or Android evidence**.

Browser/Host code corresponds to `9a08d65cc114b978b904cc626ab0c8c4c1a6d07e`; the Host implementation is unchanged since `db7fa00`. Mobile export was built at `db7fa00a4dd8dfd501ddea953e1bbb53a5338237`; the form and encrypted wire implementation are unchanged at `9a08d65`. The later commit only adds terminal handling for unsuccessful Connect HTTP responses in push/removal and its regression.

## Runtime scope

Two task-owned DSH `0.2.1-rc.2` Profiles. A synthetic Connect hostname maps locally to the real task-owned Connect origin; no real Cloudflare tunnel or relay deployment is claimed. Actual Device Gateway admission and DSH dispatch were used. Public test vectors use independent Cacophony fixtures; they are not an external cryptographic audit.

Verified: fingerprint + CLI exact-key approval, `connect-status`, encrypted list and synthetic credential set/unset, live roster, image upload with an official DeepSeek reply, byte-identical encrypted attachment download, browser private input, and the Expo Web private-input form. Outer-frame checks found none of the synthetic credential/offer/value/method sentinels. These observations do not prove resistance to every active attack.

Focused tests, static checks, full-suite results and CI status are reported separately in the PR. Native key storage, iOS/Android rendering and lifecycle, real Cloudflare traversal, account enrollment in the deployed relay, accessibility, Human QA and external security audit remain unrun. The native queue is paused by the Human. No merge, release or deployment occurred.

## Real Cloudflare follow-up (2026-10-22)

Runtime code: `683b0cbe9c0f158e80929601f59a312ff5f9c4bf`; this follow-up adds evidence only. See [real-tunnel.md](real-tunnel.md) for method, failure matrix, native build correction and the unresolved first-pairing sheet error. `cf-web-*` captures trusted Web Client submission before/error/success over real Cloudflare. `cf-ios-input/fail/ok` captures the rebuilt native app on the existing QA iOS27, including the real keyboard. All values/accounts are synthetic. No device credential, pairing payload, private key, cloud identity or raw traffic capture is published. These are runtime state evidence; earlier Track A/B comparison images remain above. Physical iPhone, Android, deployed account enrollment, Human QA and external audit are not covered.

## Native pairing fix follow-up (2026-10-22)

[Native pairing report](native-pairing.md) and [redacted results](native-pairing-results.json) supersede the earlier first-pairing limitation: the iOS pairing modal and first-notice transition are fixed, with six light/dark × text-size cases and the Maestro interaction regression passing without a post-pairing restart. Existing QA iOS27 and its qualified native binary were reused. `pair-before.png` records the original error; `pair-*` after images show usable Chats, Activity and the existing QA conversation. This is bounded native pairing acceptance, not a claim that all mobile features, physical iPhone, Android or Human QA are complete.

## Concise native verification follow-up (2026-10-22)

[Fingerprint UI report](fingerprint-ui.md) and [exact-source results](fingerprint-results.json) record the replacement of the long native alert with focused verification and phone-approval steps. Complete selectable fingerprints, native actions and optional details passed six iOS theme/text cases, mismatch and cancellation checks. The previous password matrix remains separate; Android/physical-device/Chinese-rendering/assistive-technology acceptance is not inferred from this run.
Binary file added .github/pr-screenshots/2542/cf-ios-fail.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .github/pr-screenshots/2542/cf-ios-input.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .github/pr-screenshots/2542/cf-ios-ok.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .github/pr-screenshots/2542/cf-ios-sheet.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .github/pr-screenshots/2542/cf-web-before.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .github/pr-screenshots/2542/cf-web-fail.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .github/pr-screenshots/2542/cf-web-ok.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading