@xingular/harness 1.1.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/README.md +28 -25
- package/dist/cli.js +6675 -2501
- package/dist/sdk/accounts/accounts.d.ts +27 -3
- package/dist/sdk/accounts/accounts.js +78 -24
- package/dist/sdk/accounts/secrets.d.ts +12 -0
- package/dist/sdk/accounts/secrets.js +114 -7
- package/dist/sdk/accounts/store.d.ts +26 -1
- package/dist/sdk/accounts/store.js +1 -1
- package/dist/sdk/agents/builtin.js +15 -1
- package/dist/sdk/agents/planResearch.d.ts +5 -0
- package/dist/sdk/agents/planResearch.js +19 -0
- package/dist/sdk/agents/profiles.d.ts +2 -1
- package/dist/sdk/agents/profiles.js +9 -4
- package/dist/sdk/annotations/pageScript.js +349 -48
- package/dist/sdk/annotations/part.js +34 -23
- package/dist/sdk/annotations/store.d.ts +7 -0
- package/dist/sdk/annotations/store.js +13 -5
- package/dist/sdk/browser/backend.d.ts +16 -0
- package/dist/sdk/browser/backend.js +17 -0
- package/dist/sdk/browser/contracts.d.ts +19 -0
- package/dist/sdk/browser/contracts.js +116 -0
- package/dist/sdk/browser/tools.d.ts +1 -4
- package/dist/sdk/browser/tools.js +14 -91
- package/dist/sdk/cli.js +5 -4
- package/dist/sdk/commands/list.d.ts +3 -0
- package/dist/sdk/commands/list.js +75 -0
- package/dist/sdk/commands/registry.d.ts +250 -0
- package/dist/sdk/commands/registry.js +47 -0
- package/dist/sdk/commands/routes.d.ts +16 -0
- package/dist/sdk/commands/routes.js +33 -0
- package/dist/sdk/core/commandBudget.d.ts +23 -0
- package/dist/sdk/core/commandBudget.js +57 -0
- package/dist/sdk/core/index.js +17 -1
- package/dist/sdk/core/interactiveProfile.d.ts +46 -0
- package/dist/sdk/core/interactiveProfile.js +143 -0
- package/dist/sdk/core/workspace.d.ts +13 -0
- package/dist/sdk/core/workspace.js +88 -0
- package/dist/sdk/core/workspaceBashTool.d.ts +4 -0
- package/dist/sdk/core/workspaceBashTool.js +36 -0
- package/dist/sdk/core/workspaceSandbox.d.ts +31 -0
- package/dist/sdk/core/workspaceSandbox.js +320 -0
- package/dist/sdk/core/workspaceWriteOperations.d.ts +22 -0
- package/dist/sdk/core/workspaceWriteOperations.js +206 -0
- package/dist/sdk/doctor/types.d.ts +2 -2
- package/dist/sdk/harness.d.ts +7 -0
- package/dist/sdk/harness.js +42 -2
- package/dist/sdk/index.d.ts +6 -1
- package/dist/sdk/index.js +3 -0
- package/dist/sdk/pi/runtime.d.ts +2 -1
- package/dist/sdk/pi/runtime.js +2 -2
- package/dist/sdk/plugins/builtin.js +29 -12
- package/dist/sdk/plugins/builtinRegistry.d.ts +10 -3
- package/dist/sdk/plugins/builtinRegistry.js +30 -8
- package/dist/sdk/plugins/catalogue.js +2 -1
- package/dist/sdk/plugins/commandPrefix.d.ts +8 -0
- package/dist/sdk/plugins/commandPrefix.js +21 -0
- package/dist/sdk/plugins/firstParty.d.ts +1 -1
- package/dist/sdk/plugins/firstParty.js +8 -2
- package/dist/sdk/plugins/inventory.js +4 -3
- package/dist/sdk/plugins/manifest.d.ts +2 -0
- package/dist/sdk/plugins/manifest.js +2 -1
- package/dist/sdk/plugins/surfaces.d.ts +5 -0
- package/dist/sdk/plugins/surfaces.js +11 -0
- package/dist/sdk/plugins/types.d.ts +15 -0
- package/dist/sdk/prompt/compile.d.ts +14 -0
- package/dist/sdk/prompt/compile.js +65 -29
- package/dist/sdk/prompt/standard.d.ts +17 -0
- package/dist/sdk/prompt/standard.js +21 -0
- package/dist/sdk/server/methods.js +18 -0
- package/dist/sdk/server/remote.js +36 -11
- package/dist/sdk/sessions/compactionCheckpoint.d.ts +11 -0
- package/dist/sdk/sessions/compactionCheckpoint.js +79 -0
- package/dist/sdk/sessions/continuation.d.ts +3 -0
- package/dist/sdk/sessions/continuation.js +5 -1
- package/dist/sdk/sessions/contracts.d.ts +168 -0
- package/dist/sdk/sessions/contracts.js +59 -1
- package/dist/sdk/sessions/control.d.ts +72 -0
- package/dist/sdk/sessions/control.js +158 -0
- package/dist/sdk/sessions/initialBash.d.ts +7 -0
- package/dist/sdk/sessions/initialBash.js +7 -0
- package/dist/sdk/sessions/planMode.d.ts +14 -3
- package/dist/sdk/sessions/planMode.js +73 -16
- package/dist/sdk/sessions/registry.d.ts +1 -1
- package/dist/sdk/sessions/registry.js +2 -2
- package/dist/sdk/sessions/runStore.d.ts +14 -0
- package/dist/sdk/sessions/runStore.js +35 -0
- package/dist/sdk/sessions/runner.d.ts +40 -2
- package/dist/sdk/sessions/runner.js +161 -13
- package/dist/sdk/sessions/sessions.d.ts +23 -3
- package/dist/sdk/sessions/sessions.js +202 -17
- package/dist/sdk/sessions/subagentService.d.ts +9 -0
- package/dist/sdk/sessions/subagentService.js +63 -4
- package/dist/sdk/sessions/workSlice.d.ts +103 -0
- package/dist/sdk/sessions/workSlice.js +297 -0
- package/dist/sdk/sessions/workspaceBoundary.d.ts +15 -0
- package/dist/sdk/sessions/workspaceBoundary.js +46 -0
- package/dist/sdk/terminal/browserControl.js +2 -1
- package/dist/sdk/terminal/controller.d.ts +11 -3
- package/dist/sdk/terminal/controller.js +40 -13
- package/dist/sdk/terminal/opentui/theme.d.ts +43 -0
- package/dist/sdk/terminal/opentui/theme.js +87 -0
- package/dist/sdk/terminal/piExtension.d.ts +6 -1
- package/dist/sdk/terminal/piExtension.js +154 -54
- package/dist/sdk/terminal/standalone.d.ts +7 -0
- package/dist/sdk/terminal/standalone.js +72 -13
- package/dist/sdk/terminal/subagentMonitor.d.ts +11 -2
- package/dist/sdk/terminal/subagentMonitor.js +32 -1
- package/dist/sdk/terminal/terminals.d.ts +19 -2
- package/dist/sdk/terminal/terminals.js +245 -35
- package/dist/sdk/terminal/tui/annotateCommand.d.ts +1 -1
- package/dist/sdk/terminal/tui/annotateCommand.js +3 -3
- package/dist/sdk/terminal/tui/commandPages.d.ts +3 -1
- package/dist/sdk/terminal/tui/commandPages.js +3 -0
- package/dist/sdk/terminal/tui/commands.d.ts +2 -0
- package/dist/sdk/terminal/tui/commands.js +205 -124
- package/dist/sdk/terminal/tui/list.d.ts +14 -1
- package/dist/sdk/terminal/tui/list.js +96 -14
- package/dist/sdk/terminal/tui/pageOverlay.js +13 -4
- package/dist/sdk/terminal/tui/pages/annotatePage.d.ts +1 -1
- package/dist/sdk/terminal/tui/pages/notesPage.d.ts +5 -5
- package/dist/sdk/terminal/tui/pages/notesPage.js +18 -18
- package/dist/sdk/terminal/tui/pages/pluginsPage.d.ts +0 -5
- package/dist/sdk/terminal/tui/pages/pluginsPage.js +9 -3
- package/dist/sdk/terminal/tui/pages/subagentsPage.d.ts +1 -0
- package/dist/sdk/terminal/tui/pages/subagentsPage.js +98 -16
- package/dist/sdk/terminal/tui/pages/usagePage.d.ts +43 -0
- package/dist/sdk/terminal/tui/pages/usagePage.js +370 -0
- package/dist/sdk/terminal/tui/piAdapter.d.ts +1 -2
- package/dist/sdk/terminal/tui/piAdapter.js +3 -5
- package/dist/sdk/terminal/tui/pluginCommands.d.ts +2 -0
- package/dist/sdk/terminal/tui/pluginCommands.js +13 -9
- package/dist/sdk/terminal/tui/runtime.js +23 -3
- package/dist/sdk/terminal/tui/sessionPicker.d.ts +40 -0
- package/dist/sdk/terminal/tui/sessionPicker.js +141 -0
- package/dist/sdk/tools/checklist.js +1 -0
- package/dist/sdk/tools/checkpoint.d.ts +27 -0
- package/dist/sdk/tools/checkpoint.js +154 -0
- package/dist/sdk/tools/getCapabilities.d.ts +31 -0
- package/dist/sdk/tools/getCapabilities.js +34 -0
- package/dist/sdk/tools/spawnSubagent.js +4 -3
- package/dist/sdk/usage/analytics.d.ts +20 -0
- package/dist/sdk/usage/analytics.js +151 -0
- package/dist/sdk/usage/ledger.d.ts +38 -0
- package/dist/sdk/usage/ledger.js +142 -0
- package/dist/sdk/usage/limits/adapters.d.ts +11 -0
- package/dist/sdk/usage/limits/adapters.js +349 -0
- package/dist/sdk/usage/limits/capture.d.ts +8 -0
- package/dist/sdk/usage/limits/capture.js +47 -0
- package/dist/sdk/usage/limits/http.d.ts +12 -0
- package/dist/sdk/usage/limits/http.js +51 -0
- package/dist/sdk/usage/limits/normalize.d.ts +15 -0
- package/dist/sdk/usage/limits/normalize.js +211 -0
- package/dist/sdk/usage/limits/service.d.ts +30 -0
- package/dist/sdk/usage/limits/service.js +176 -0
- package/dist/sdk/usage/limits/types.d.ts +65 -0
- package/dist/sdk/usage/limits/types.js +1 -0
- package/dist/sdk/usage/serverMethods.d.ts +3 -0
- package/dist/sdk/usage/serverMethods.js +22 -0
- package/dist/sdk/usage/service.d.ts +32 -0
- package/dist/sdk/usage/service.js +66 -0
- package/dist/sdk/usage/settings.d.ts +7 -0
- package/dist/sdk/usage/settings.js +28 -0
- package/dist/sdk/usage/types.d.ts +60 -0
- package/dist/sdk/usage/types.js +4 -0
- package/dist/terminal-opentui.js +5207 -1883
- package/dist/terminal-pi.js +1658 -271
- package/docs/architecture/02-sessions-and-runs.md +128 -26
- package/docs/architecture/04-prompt.md +50 -12
- package/docs/architecture/06-plugins-and-capabilities.md +24 -7
- package/docs/architecture/07-tools-and-gate.md +104 -24
- package/docs/architecture/08-memory-and-history.md +4 -2
- package/docs/architecture/09-accounts-and-connectors.md +31 -1
- package/docs/architecture/10-server-protocol.md +58 -3
- package/docs/architecture/11-terminal.md +105 -42
- package/docs/architecture/12-storage.md +30 -2
- package/docs/architecture/13-world-tools.md +22 -1
- package/docs/architecture/14-surfaces-and-parity.md +54 -7
- package/docs/architecture/README.md +3 -1
- package/docs/architecture/proposals/PROP-0017-page-annotations.md +6 -2
- package/docs/architecture/proposals/PROP-0018-annotation-queue-and-app-targets.md +1 -1
- package/docs/architecture/proposals/PROP-0031-plugin-command-owner-namespaces.md +54 -0
- package/docs/architecture/proposals/PROP-0032-planning-quality.md +196 -0
- package/docs/architecture/proposals/PROP-0033-compaction-plan-checkpoints.md +75 -0
- package/docs/architecture/proposals/PROP-0034-conversation-fast-mode.md +120 -0
- package/docs/architecture/proposals/PROP-0035-retain-subagent-status.md +47 -0
- package/docs/architecture/proposals/PROP-0036-first-class-harness-commands.md +59 -0
- package/docs/architecture/proposals/PROP-0037-workspace-write-boundary.md +63 -0
- package/docs/architecture/proposals/PROP-0038-annotate-open-shadow-roots.md +73 -0
- package/docs/architecture/proposals/PROP-0039-workspace-boundary-hardening.md +139 -0
- package/docs/architecture/proposals/PROP-0040-one-launch-path.md +87 -0
- package/docs/architecture/proposals/PROP-0041-bounded-work-slices.md +247 -0
- package/docs/architecture/proposals/PROP-0042-usage-and-provider-limits.md +127 -0
- package/docs/architecture/proposals/PROP-0043-read-only-plan-bash.md +74 -0
- package/docs/architecture/proposals/README.md +14 -0
- package/docs/decisions/ADR-0001-owned-terminal.md +1 -1
- package/docs/decisions/ADR-0021-required-command-namespaces.md +1 -1
- package/docs/decisions/ADR-0031-plugin-command-owner-namespaces.md +37 -0
- package/docs/decisions/ADR-0032-compaction-run-checkpoints.md +33 -0
- package/docs/decisions/ADR-0033-plan-mode-research-delegation.md +47 -0
- package/docs/decisions/ADR-0034-first-class-harness-terminal-commands.md +25 -0
- package/docs/decisions/ADR-0035-one-launch-path.md +40 -0
- package/docs/decisions/ADR-0036-workspace-write-operation-boundary.md +54 -0
- package/docs/decisions/ADR-0037-usage-ledger-and-provider-limits.md +44 -0
- package/docs/decisions/ADR-0038-plan-bash-os-read-only.md +29 -0
- package/docs/experiments/EXP-0003-performance-audit/data/session-runtime-replication.json +420 -0
- package/docs/experiments/EXP-0003-performance-audit/data/session-runtime.json +420 -0
- package/docs/experiments/EXP-0003-performance-audit/data/terminal-compact.json +376 -0
- package/docs/experiments/EXP-0003-performance-audit/data/terminal-history.json +422 -0
- package/docs/experiments/EXP-0003-performance-audit/data/terminal-question.json +95 -0
- package/docs/experiments/EXP-0003-performance-audit/data/terminal-wide.json +1036 -0
- package/docs/experiments/EXP-0003-performance-audit/plan.md +109 -0
- package/docs/experiments/EXP-0003-performance-audit/results.md +151 -0
- package/docs/handoff-2026-10-25-app-parity-and-solo-tabs.md +202 -0
- package/docs/parity.md +80 -24
- package/docs/releases/1.1.1.md +28 -0
- package/docs/releases/1.2.0.md +49 -0
- package/docs/releases/4.0.0.md +10 -9
- package/docs/releases/README.md +35 -30
- package/docs/study/00-index.md +3 -0
- package/docs/study/STUDY-0003-long-horizon-runs.md +210 -0
- package/docs/terminal-tui.md +100 -59
- package/package.json +4 -3
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: EXP-0003
|
|
3
|
+
title: Layered Xingular terminal and Harness runtime performance audit
|
|
4
|
+
status: completed
|
|
5
|
+
created: 2026-10-25
|
|
6
|
+
updated: 2026-10-25
|
|
7
|
+
related: [EXP-0002]
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# EXP-0003 — Layered performance audit
|
|
11
|
+
|
|
12
|
+
## Question and falsifiable hypothesis
|
|
13
|
+
|
|
14
|
+
How much of the user-visible delay belongs to terminal input/rendering, fresh-process startup, and
|
|
15
|
+
Harness session orchestration? After the OpenTUI work in EXP-0002, the hypothesis is that steady
|
|
16
|
+
keystroke-to-screen latency is comparable to Pi and OpenCode, while the Harness layers show up more
|
|
17
|
+
strongly in cold startup and memory. A long transcript should not materially increase Harness input
|
|
18
|
+
latency.
|
|
19
|
+
|
|
20
|
+
The comparison can falsify this: if Harness p95 grows after history, stays above OpenCode during
|
|
21
|
+
streaming, or Harness session calls contribute large repeatable latency with the injected session,
|
|
22
|
+
those are separate regression candidates.
|
|
23
|
+
|
|
24
|
+
## Targets and controls
|
|
25
|
+
|
|
26
|
+
- **Xingular Harness:** built `node dist/cli.js`, with temporary `--state` and `--data` roots, an
|
|
27
|
+
isolated API-key account, and a loopback OpenAI-compatible model.
|
|
28
|
+
- **Pure Pi:** `@earendil-works/pi-coding-agent` 1.2.0 with an isolated `PI_CODING_AGENT_DIR`.
|
|
29
|
+
- **OpenCode:** v2.1.4 with `--standalone`, isolated XDG roots and a loopback-compatible provider.
|
|
30
|
+
- Each terminal target runs in its own PTY and temporary profile. A local deterministic SSE provider
|
|
31
|
+
supplies the same fixture response to all targets. No external provider, OAuth profile, or
|
|
32
|
+
credential is used.
|
|
33
|
+
- Main terminal runs use a 160×45 PTY, 35 ms key interval, two rounds of 30 typed characters and
|
|
34
|
+
five independent launches for idle, stream and burst. The first eight keys in each round are
|
|
35
|
+
excluded from latency scoring; each idle run therefore scores 44 keys and each stream/burst run
|
|
36
|
+
scores 22. Target order rotates between repeats.
|
|
37
|
+
- History uses three launches per target. Each history is an 80-turn local tool loop (about 240
|
|
38
|
+
transcript messages) before typing is measured. The question scenario is Harness-only and uses
|
|
39
|
+
plan mode. A separate 80×24 run checks a compact terminal once per target; it is sensitivity data,
|
|
40
|
+
not a repeated comparison.
|
|
41
|
+
- The runtime benchmark runs in a separate Node process with temporary state/data and a deterministic
|
|
42
|
+
injected session. It measures SDK import, Harness initialization, cold/warm `terminal.prepare`,
|
|
43
|
+
run-to-first-persisted-delta/completion, and one local tool-event path. It does not start Bun or a
|
|
44
|
+
real model.
|
|
45
|
+
|
|
46
|
+
## Metrics
|
|
47
|
+
|
|
48
|
+
- Input latency is the time between writing a key to the PTY and the first time its typed prefix is
|
|
49
|
+
visible on a `pyte` virtual screen (p50/p95/p99/max). Missed keys are reported separately. This
|
|
50
|
+
includes the PTY and `pyte` parser, not a terminal emulator's physical paint.
|
|
51
|
+
- Startup is measured from process launch to first output, first nonblank visible screen, and a
|
|
52
|
+
quiet screen (750 ms with no further output). Process-tree RSS is sampled at that initial stable
|
|
53
|
+
screen. CPU and RSS are process-tree measurements; typing CPU is measured over the typing window.
|
|
54
|
+
- Terminal comparison summaries take the median of each run's metric (including each run's p95); they
|
|
55
|
+
are not pooled per-key percentiles. Session-runtime summaries use the median of measured samples.
|
|
56
|
+
- No credentialed run is required. The profiler rejects `--real` unless it is exactly one Xingular
|
|
57
|
+
run; this audit does not invoke `--real`.
|
|
58
|
+
|
|
59
|
+
## Reproduction
|
|
60
|
+
|
|
61
|
+
Build the CLI and create an isolated Python environment for the PTY screen parser:
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
npm run build
|
|
65
|
+
python3 -m venv /tmp/harness-perf-venv
|
|
66
|
+
/tmp/harness-perf-venv/bin/python -m pip install -r scripts/requirements-performance.txt
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Main repeated comparison:
|
|
70
|
+
|
|
71
|
+
```sh
|
|
72
|
+
/tmp/harness-perf-venv/bin/python scripts/profile-terminal-latency.py \
|
|
73
|
+
--targets xingular,pi,opencode --repeats 5 --scenarios idle,stream,burst \
|
|
74
|
+
--rounds 2 --length 30 --interval 0.035 --width 160 --height 45 \
|
|
75
|
+
--warm-idle-seconds 2 --idle-seconds 2 --stream-seconds 4 \
|
|
76
|
+
--output /tmp/harness-perf-wide
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
History and compact-terminal sensitivity runs:
|
|
80
|
+
|
|
81
|
+
```sh
|
|
82
|
+
/tmp/harness-perf-venv/bin/python scripts/profile-terminal-latency.py \
|
|
83
|
+
--targets xingular,pi,opencode --repeats 3 --scenarios history \
|
|
84
|
+
--rounds 2 --length 30 --interval 0.035 --width 160 --height 45 \
|
|
85
|
+
--warm-idle-seconds 1 --idle-seconds 1 --stream-seconds 2 \
|
|
86
|
+
--output /tmp/harness-perf-history
|
|
87
|
+
|
|
88
|
+
/tmp/harness-perf-venv/bin/python scripts/profile-terminal-latency.py \
|
|
89
|
+
--targets xingular,pi,opencode --repeats 1 --scenarios idle,stream,burst \
|
|
90
|
+
--rounds 2 --length 30 --interval 0.035 --width 80 --height 24 \
|
|
91
|
+
--warm-idle-seconds 2 --idle-seconds 1 --stream-seconds 4 \
|
|
92
|
+
--output /tmp/harness-perf-compact
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Harness-only question latency and deterministic runtime overhead:
|
|
96
|
+
|
|
97
|
+
```sh
|
|
98
|
+
/tmp/harness-perf-venv/bin/python scripts/profile-terminal-latency.py \
|
|
99
|
+
--targets xingular --repeats 1 --scenarios question --rounds 2 --length 30 \
|
|
100
|
+
--width 160 --height 45 --warm-idle-seconds 1 --idle-seconds 1 \
|
|
101
|
+
--stream-seconds 3 --output /tmp/harness-perf-question
|
|
102
|
+
|
|
103
|
+
npm run profile:session-runtime -- --iterations 5 --warmup 1 \
|
|
104
|
+
--output /tmp/harness-session-runtime.json
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
For terminal behavior verification, run `python scripts/verify-terminal.py` with the same Python
|
|
108
|
+
environment. `npm run profile:terminal-input` measures the local draft-control socket separately;
|
|
109
|
+
it is not a substitute for the PTY latency run.
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# EXP-0003 — Results
|
|
2
|
+
|
|
3
|
+
- **Status:** audit completed; one terminal behavior verification check failed (details below).
|
|
4
|
+
- **Run date:** 2026-10-25.
|
|
5
|
+
- **Code:** base commit `6f72a07` with a dirty worktree (81 changed/untracked paths were present).
|
|
6
|
+
Product changes in that worktree predate this audit; this audit added benchmark tooling and report
|
|
7
|
+
artifacts only.
|
|
8
|
+
- **Machine/runtime:** macOS 27.0, arm64, 8 logical CPUs; Node v26.8.2; Bun 1.4.2; Harness
|
|
9
|
+
1.1.1; Pi 1.2.0; OpenCode v2.1.4; Python 3.12.12; pyte 0.8.2.
|
|
10
|
+
- **Credentials/network:** terminal comparisons used a loopback model in isolated temporary
|
|
11
|
+
profiles. The session-runtime benchmark used an injected deterministic session. No provider,
|
|
12
|
+
OAuth credential, or user profile was used; `--real` was not run.
|
|
13
|
+
|
|
14
|
+
Raw terminal and runtime JSON is in [`data/`](data/): `terminal-wide.json`,
|
|
15
|
+
`terminal-history.json`, `terminal-compact.json`, `terminal-question.json`,
|
|
16
|
+
`session-runtime.json`, and `session-runtime-replication.json`. The OpenCode executable field is
|
|
17
|
+
normalized to `opencode` to avoid publishing a machine-specific path; measurements are unchanged.
|
|
18
|
+
|
|
19
|
+
## Terminal comparison
|
|
20
|
+
|
|
21
|
+
Main repeated comparison: 160×45 PTY, five launches per target, 2 rounds of 30 characters at 35 ms
|
|
22
|
+
per key, 2 s warm-idle and 2 s idle measurement. The table shows the median of per-launch values;
|
|
23
|
+
latency is milliseconds p50/p95 and CPU is process-tree CPU during the typing window. Every target
|
|
24
|
+
had zero missed keys.
|
|
25
|
+
|
|
26
|
+
| Scenario | Target | p50 / p95 (ms) | CPU (%) |
|
|
27
|
+
|---|---|---:|---:|
|
|
28
|
+
| Idle typing | Xingular | 5.11 / 9.98 | 7.7 |
|
|
29
|
+
| | Pure Pi | 5.32 / 6.39 | 3.1 |
|
|
30
|
+
| | OpenCode | 7.17 / 10.41 | 26.5 |
|
|
31
|
+
| After ~240 transcript messages | Xingular | 5.09 / 10.05 | 8.9 |
|
|
32
|
+
| | Pure Pi | 5.44 / 10.34 | 4.3 |
|
|
33
|
+
| | OpenCode | 9.47 / 12.70 | 32.6 |
|
|
34
|
+
| Regular stream | Xingular | 9.13 / 19.91 | 14.2 |
|
|
35
|
+
| | Pure Pi | 3.18 / 22.26 | 10.5 |
|
|
36
|
+
| | OpenCode | 10.02 / 24.87 | 41.5 |
|
|
37
|
+
| Burst stream | Xingular | 5.01 / 10.73 | 12.3 |
|
|
38
|
+
| | Pure Pi | 4.72 / 6.31 | 5.5 |
|
|
39
|
+
| | OpenCode | 10.42 / 21.85 | 33.2 |
|
|
40
|
+
|
|
41
|
+
History setup took a median 7.5 s for Xingular, 6.5 s for Pi, and 9.8 s for OpenCode. Xingular's
|
|
42
|
+
idle p95 was 9.98 ms before history and 10.05 ms after it, so this run found no meaningful
|
|
43
|
+
history-related typing regression. The median streaming p95 was lower than both comparisons; burst
|
|
44
|
+
p95 was below OpenCode but above Pi. Xingular idle p95 was roughly on par with OpenCode and 1.56×
|
|
45
|
+
Pure Pi; burst p95 was 1.70× Pure Pi. Thus the prior EXP-0002 p95 criterion of “no worse than
|
|
46
|
+
OpenCode” held for these four scenarios, while “within 1.5× Pi” did not hold for idle or burst.
|
|
47
|
+
|
|
48
|
+
The five-run p95 ranges show why the medians should not be read as precise rankings: idle ranges
|
|
49
|
+
were 9.64–10.19 ms (Xingular), 6.04–9.92 ms (Pi), and 9.58–11.08 ms (OpenCode); stream ranges
|
|
50
|
+
were 18.32–20.25, 22.02–23.38, and 19.00–26.36 ms; burst ranges were 8.87–12.08, 5.81–33.23,
|
|
51
|
+
and 12.86–26.00 ms respectively. Each run scores 44 idle keys and 22 stream/burst keys; p95 values
|
|
52
|
+
are medians of per-run p95, not pooled per-key percentiles.
|
|
53
|
+
|
|
54
|
+
### Fresh launch and memory
|
|
55
|
+
|
|
56
|
+
`first visible` is the first nonblank PTY screen; `stable screen` is measured after 750 ms without
|
|
57
|
+
output. Process-tree RSS is sampled at that initial stable screen.
|
|
58
|
+
|
|
59
|
+
| Target | First visible (ms) | Stable screen (ms) | Process-tree RSS (MiB) |
|
|
60
|
+
|---|---:|---:|---:|
|
|
61
|
+
| Xingular | 2,814 | 3,768 | 392 |
|
|
62
|
+
| Pure Pi | 261 | 1,035 | 134 |
|
|
63
|
+
| OpenCode | 304 | 1,107 | 489 |
|
|
64
|
+
|
|
65
|
+
On this machine, Xingular's end-to-end first-visible time was about 10.8× Pi and 9.3× OpenCode;
|
|
66
|
+
its process-tree RSS was about 2.9× Pi and 0.8× OpenCode. This launch comparison includes the
|
|
67
|
+
Harness CLI and its terminal child, while Pi and OpenCode have different process architectures. It
|
|
68
|
+
measures the user-visible path, not the renderer alone. A separate 80×24 single-run sensitivity
|
|
69
|
+
check showed idle p95 of 4.66/5.08/8.11 ms and stream p95 of 10.95/5.72/18.61 ms for
|
|
70
|
+
Xingular/Pi/OpenCode respectively; it supports the same broad pattern but is not a repeated result.
|
|
71
|
+
|
|
72
|
+
The Harness-only plan-question scenario passed after the profiler was changed to enter plan mode:
|
|
73
|
+
44 keys, no misses, p50 5.03 ms, p95 9.53 ms (one run; not a cross-target comparison). The raw
|
|
74
|
+
record is `data/terminal-question.json`.
|
|
75
|
+
|
|
76
|
+
A separate 2 s post-warm-up idle-resource window in the wide run measured median process-tree CPU
|
|
77
|
+
of 2.0% for Xingular, 0.5% for Pi, and 1.5% for OpenCode. These short windows are coarse and should
|
|
78
|
+
not be treated as a stable ranking.
|
|
79
|
+
|
|
80
|
+
## Harness runtime overhead
|
|
81
|
+
|
|
82
|
+
Two invocations of the isolated runtime benchmark contributed ten measured samples per warm
|
|
83
|
+
operation (five iterations and one warmup per invocation). It imports the built SDK and uses a fake
|
|
84
|
+
session seam; these values exclude model/provider latency and real Pi startup.
|
|
85
|
+
|
|
86
|
+
| Operation | Median | Sample range |
|
|
87
|
+
|---|---:|---:|
|
|
88
|
+
| Warm `terminal.prepare` | 9.65 ms | 7.69–11.78 ms |
|
|
89
|
+
| `sessions.run` to first persisted delta | 25.65 ms | 21.78–29.44 ms |
|
|
90
|
+
| `sessions.run` to completion | 33.86 ms | 27.96–39.06 ms |
|
|
91
|
+
| Tool run to `tool.started` | 29.12 ms | 25.74–31.92 ms |
|
|
92
|
+
| Tool run to `tool.completed` | 29.50 ms | 26.12–47.31 ms |
|
|
93
|
+
| Tool run to completion | 38.96 ms | 37.07–58.24 ms |
|
|
94
|
+
|
|
95
|
+
Across the two process starts, SDK import was 246–347 ms and Harness initialization was 27.8–28.5
|
|
96
|
+
ms. Cold `terminal.prepare` varied substantially, from 261 to 1,158 ms; its description includes
|
|
97
|
+
first socket-listener setup. Treat the warm path as the repeatable figure and cold preparation as a
|
|
98
|
+
signal to instrument further, not as a stable estimate. Every run verified the persisted event
|
|
99
|
+
sequence; the temporary state/data roots were removed.
|
|
100
|
+
|
|
101
|
+
## CPU profile notes
|
|
102
|
+
|
|
103
|
+
Profiles were captured separately from the comparison runs and are not included in their latency
|
|
104
|
+
medians. A one-run Bun profile of Xingular during startup and streaming (16.19 s, 846 samples) had
|
|
105
|
+
highest self-time in terminal output writing (`writeBuffered` 14.0%, Node `_write` 9.3%), key
|
|
106
|
+
matching (`matchesKey` 5.6%), OpenTUI stdout draining (4.5%), and the terminal socket `send` (3.2%).
|
|
107
|
+
This identifies output/key/event plumbing worth inspecting, but does not isolate one application
|
|
108
|
+
function as the cause of input latency.
|
|
109
|
+
|
|
110
|
+
A separate one-run Node profile of the Harness process (6.98 s, 5,576 samples) was 69% idle in the
|
|
111
|
+
profiler, with `spawnSync` at 11.2% and `readdir` at 3.2%. This is consistent with a startup path
|
|
112
|
+
that includes process and I/O waits rather than being dominated by one CPU-heavy JavaScript loop;
|
|
113
|
+
it is not a phase-by-phase startup trace. Profiles are diagnostic single runs and profiling itself
|
|
114
|
+
adds overhead.
|
|
115
|
+
|
|
116
|
+
## Verification
|
|
117
|
+
|
|
118
|
+
- `npm run typecheck` — passed.
|
|
119
|
+
- `npm test` — passed: 150 test files, 1,140 tests passed, 3 skipped.
|
|
120
|
+
- `npm run build` — passed.
|
|
121
|
+
- `npm run prove` — passed all 15 standalone proof cases.
|
|
122
|
+
- `npm run profile:terminal-input` — passed; 120 local draft-control socket requests, p50 0.022 ms,
|
|
123
|
+
p95 0.053 ms. This measures the socket path, not key-to-screen rendering.
|
|
124
|
+
- `profile-terminal-latency.py --real --targets pi` — rejected before launch as intended; `--real`
|
|
125
|
+
is restricted to one Xingular run.
|
|
126
|
+
- `python scripts/verify-terminal.py` — **failed** during `/settings` at a narrow terminal width.
|
|
127
|
+
The verifier expected `Esc close` on the last row; the observed footer was truncated to
|
|
128
|
+
`Enter change · type to search · Tab/`. This is a terminal behavior verification failure, not a
|
|
129
|
+
performance measurement. No product UI code was changed as part of this audit.
|
|
130
|
+
|
|
131
|
+
## Conclusions and follow-up
|
|
132
|
+
|
|
133
|
+
- **Steady typing:** competitive with OpenCode at 160×45, especially for streaming p95; history
|
|
134
|
+
does not increase Xingular's measured p95. Xingular still trails Pi on idle and burst p95, and
|
|
135
|
+
has higher CPU than Pi while typing/streaming.
|
|
136
|
+
- **Fresh start:** the clearest gap. Xingular takes about 2.8 s to first visible output and uses
|
|
137
|
+
about 392 MiB at the initial screen. The runtime benchmark makes warm Harness preparation look
|
|
138
|
+
inexpensive, but cold preparation is variable. Break startup into Node CLI, Harness account and
|
|
139
|
+
context setup, terminal preparation, Bun launch, and first render before attributing or optimizing
|
|
140
|
+
the gap.
|
|
141
|
+
- **Next measurements:** add phase markers for fresh startup and process-by-process RSS; repeat on a
|
|
142
|
+
slower machine; investigate burst input alongside `matchesKey`/output writes; and triage the
|
|
143
|
+
narrow `/settings` footer verification failure separately.
|
|
144
|
+
|
|
145
|
+
## Limits
|
|
146
|
+
|
|
147
|
+
One arm64 machine and a dirty worktree; no clean-commit A/B or slower-device run. The loopback stream
|
|
148
|
+
is regular and excludes network/provider delay. PTY/pyte timing excludes physical terminal paint.
|
|
149
|
+
The compact-screen and question results are single runs. CPU profiles are single instrumented runs.
|
|
150
|
+
The runtime benchmark's session is injected and deterministic, so it measures Harness runtime and
|
|
151
|
+
persistence costs, not real model inference or the complete Pi AgentSession startup path.
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# Handoff: App parity with the Harness, and the Solo sidebar and tabs (updated 2026-11-19)
|
|
2
|
+
|
|
3
|
+
The scoped implementation and documentation are in place; full parity acceptance remains open.
|
|
4
|
+
Nothing is committed. The working trees contain substantial pre-existing uncommitted work; preserve
|
|
5
|
+
it and do not revert unrelated files.
|
|
6
|
+
|
|
7
|
+
| Repository | Branch | State |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| `Xingular Agent/Harness` | `release/1.0.0` | Code and architecture docs updated; typecheck, full tests and `prove` pass |
|
|
10
|
+
| `Xingular UI` | (current) | Shared tab-manager change; typecheck and full tests pass |
|
|
11
|
+
| `Xingular Agent/App` | `app-as-frontend` | Profile safety, commands, Solo tabs, browser refusal and docs updated; automated checks pass |
|
|
12
|
+
| `Xingular Workspace` | (current) | Shared-UI consumers typecheck and UI check pass; four test failures were observed |
|
|
13
|
+
|
|
14
|
+
Approved plan: `~/.claude/plans/i-wanna-make-change-velvet-nova.md`.
|
|
15
|
+
|
|
16
|
+
## What the owner asked for
|
|
17
|
+
|
|
18
|
+
1. Solo sidebar: **Project › Session**, with no folder or worktree level. People never configure
|
|
19
|
+
worktrees. A new session runs in the project folder, as `xagent` does in a terminal.
|
|
20
|
+
2. Each session card has two rows: the title, then a muted row such as `2h ago · 5.1MB`.
|
|
21
|
+
3. One shared top bar over the chat, with tabs and an icon-only view switch:
|
|
22
|
+
- **Split**: every open session is its own panel (the earlier behaviour).
|
|
23
|
+
- **Single**: one panel; clicking a tab replaces what it shows.
|
|
24
|
+
4. The sidebar shows which sessions are open. A middle click on a tab closes it. Closing a tab
|
|
25
|
+
only closes the tab; it never archives the session.
|
|
26
|
+
5. Every Harness terminal slash command works in the App.
|
|
27
|
+
6. The prompt, runtime, plugins and skills are the same in both front ends. Features that work
|
|
28
|
+
better in the App (annotate capture, the WebKit browser, computer control) are labelled as
|
|
29
|
+
add-ons in their plugin descriptions.
|
|
30
|
+
|
|
31
|
+
Choices the owner made:
|
|
32
|
+
- Parity: same core, plus labelled add-ons.
|
|
33
|
+
- Build every command now.
|
|
34
|
+
- Closing a tab only closes it.
|
|
35
|
+
|
|
36
|
+
## Done
|
|
37
|
+
|
|
38
|
+
### Harness
|
|
39
|
+
|
|
40
|
+
- **Shared command registry.** `src/commands/registry.ts` holds `CORE_COMMANDS`, plain data, each
|
|
41
|
+
with `kind` (session, page or local) and `methods`. The terminal's `BUILTINS` now comes from it
|
|
42
|
+
(`src/terminal/tui/commands.ts`).
|
|
43
|
+
- **`commands.list` server method** (`src/commands/list.ts`). It returns core commands, built-in
|
|
44
|
+
plugin commands (`annotate:…`), extension commands with their owner prefix, prompt templates
|
|
45
|
+
and `skill:` entries.
|
|
46
|
+
- **Session control methods** (`src/sessions/control.ts`, wired in `src/server/methods.ts`):
|
|
47
|
+
- `sessions.tree`, `sessions.navigate` (no summary; the move is saved as a `xingular-navigation`
|
|
48
|
+
custom entry so the next turn opens on it)
|
|
49
|
+
- `sessions.fork`, `sessions.clone` (both into a `targetDir`)
|
|
50
|
+
- `sessions.rename`, `sessions.lastReply`, `sessions.export` (JSONL)
|
|
51
|
+
- `sessions.reload`
|
|
52
|
+
- **Session command runs.** `SessionRunInput.command` / `TurnParams.command` accepts `compact`,
|
|
53
|
+
`navigate` (with a summary) or `export` (HTML). `runTurn` runs the command instead of a prompt
|
|
54
|
+
and skips the context update. `checkCommand` in `src/sessions/sessions.ts` validates it.
|
|
55
|
+
- **One launch path for prompts and tools:**
|
|
56
|
+
- `Launch.standard` (`src/prompt/standard.ts`) adds the same role, working-folder (with the
|
|
57
|
+
project name) and connections text for every front end.
|
|
58
|
+
- The terminal always uses it; the App now asks for it.
|
|
59
|
+
- The terminal-only `xagent-wiki` wording is gone from `compile.ts`. There is one files-and-shell
|
|
60
|
+
paragraph for every caller, and a standard session always gets it.
|
|
61
|
+
- A new Annotations tool group carries the `page_notes_*` guidance, moved from the App.
|
|
62
|
+
- **The terminal gets the same tools:**
|
|
63
|
+
- The Harness History, Wiki and skill tools go over the socket (`ownTools` in
|
|
64
|
+
`src/terminal/terminals.ts`), which closes PAR-002.
|
|
65
|
+
- Output trim and Budget guard load in the terminal (`firstParty.list` socket call plus
|
|
66
|
+
`piExtension.ts`), which closes PAR-006. Budget guard now resets its count per reply
|
|
67
|
+
(`agent_start`).
|
|
68
|
+
- The terminal-only `ask_user_question` alias is removed; `ask_user` covers it.
|
|
69
|
+
- The `pi` command's own extensions (llama.cpp, codemode, tool-search, mcp) are no longer loaded
|
|
70
|
+
in the terminal, because a host session cannot have them. See `catalogue.ts` and
|
|
71
|
+
`inventory.ts`.
|
|
72
|
+
- **`xagent --variant <scope>`** (`src/terminal/standalone.ts`, `src/cli.ts`). With the App's
|
|
73
|
+
`--data`, the terminal runs on the same variant as an App agent.
|
|
74
|
+
- **Add-on labels.** New `PluginDescriptor.surfaces` / `Plugin.surfaces` field
|
|
75
|
+
`{ preferred: 'host', terminal: 'fallback' | 'unavailable', note }`, with helpers in
|
|
76
|
+
`src/plugins/surfaces.ts`.
|
|
77
|
+
- The annotations plugin is labelled. The layer check forbids naming the App inside the
|
|
78
|
+
Harness, so its text says "a desktop app built on this harness".
|
|
79
|
+
- The terminal's `/plugins` and `/harness` pages show the note and a badge.
|
|
80
|
+
- **New exports** in `src/index.ts`: the registry, `SessionCommand`, `SessionTree`,
|
|
81
|
+
`PluginSurfaces`, `describePlugin`, `STANDARD_CONNECTIONS`.
|
|
82
|
+
- **Tests:**
|
|
83
|
+
- Added: `src/commands/registry.test.ts`, `src/sessions/control.test.ts`,
|
|
84
|
+
`src/prompt/surfaceParity.test.ts` (a terminal and a host session compile to identical text
|
|
85
|
+
and tool groups), and session-command tests in `sessions.test.ts`.
|
|
86
|
+
- Updated: terminal, catalogue, standalone, runtime-socket and lifecycle tests.
|
|
87
|
+
|
|
88
|
+
### Xingular UI
|
|
89
|
+
|
|
90
|
+
- `WorkspaceTabManager` (`src/ui/document-workspace.tsx`): new `addLabel`, and `activeTabId` may
|
|
91
|
+
be `null`. Test added in `tests/workspace-tabs.test.tsx`. Middle-click close already existed.
|
|
92
|
+
|
|
93
|
+
### App
|
|
94
|
+
|
|
95
|
+
- **Solo model rewritten:**
|
|
96
|
+
- `src/modes/solo/soloLayout.ts` (version 2): one layout across projects. Every open tab has a
|
|
97
|
+
pane; `view` is `split` or `single`. Functions: `openSoloTab`, `closeSoloTab`, `focusSoloTab`,
|
|
98
|
+
`visibleSoloTree`, `restoreSoloLayout` (migrates version 1).
|
|
99
|
+
- `soloWorkspaceState.ts`: storage key `…:v2`, migrated from the v1 key.
|
|
100
|
+
- `soloThreads.ts`: `groupSoloProjects`, `projectDefaultGroup`, `tabGroup`, `tabProjectId`.
|
|
101
|
+
- **Sidebar** (`SoloThreadList.tsx`):
|
|
102
|
+
- Project › Session, with two-row cards (`sessionMeta`) and an open/active indicator
|
|
103
|
+
(`data-open`, `data-active`, `data-solo-open-indicator`).
|
|
104
|
+
- Each session's ⋯ menu has Archive and Remove.
|
|
105
|
+
- The project's + button starts a session in the project's default folder group.
|
|
106
|
+
- The group rows and worktree controls are removed, and `SoloGroupDialog.tsx` is deleted.
|
|
107
|
+
- **Center** (`SoloCenter.tsx`):
|
|
108
|
+
- `SoloTabBar` and `SoloViewToggle` sit in the shared `PageFrame` compact header, wired in
|
|
109
|
+
`SoloWorkspace.tsx`.
|
|
110
|
+
- Per-pane headers are removed.
|
|
111
|
+
- ⌘W / ⌘T now call `closeFocusedTab` / `newSession` (`src/shell/frameControls.ts`,
|
|
112
|
+
`src/App.tsx`).
|
|
113
|
+
- **Session size.** `ThreadSummary.size_bytes` (Rust `history_bytes` in `agents.rs`) and
|
|
114
|
+
`sizeBytes` in `shared/contracts.ts`. `formatSessionSize` in `shared/files.ts` matches the
|
|
115
|
+
terminal's format.
|
|
116
|
+
- **Slash commands from the Harness:**
|
|
117
|
+
- `src/modes/solo/soloCommands.ts` has a handler for every non-sending core command.
|
|
118
|
+
`soloCommands.test.ts` fails if the registry gains one without a handler.
|
|
119
|
+
- `SoloCommandPicker.tsx` is the picker or page dialog.
|
|
120
|
+
- `SoloConversation.tsx`:
|
|
121
|
+
- The `/` menu and highlighting come from `commands.list`.
|
|
122
|
+
- Aliases (`/side`, `/tree`, `/resume`) work.
|
|
123
|
+
- A bare `/plan` toggles a persistent plan mode, and a bare `/btw` dismisses the side question.
|
|
124
|
+
- `chatCommands.ts` is reduced to `isStopCommand` and `chatCommandInput`. The duplicate
|
|
125
|
+
extension-command helpers in `pluginModel.ts` are removed.
|
|
126
|
+
- **Host side:**
|
|
127
|
+
- New Tauri commands in `src-tauri/src/agents.rs`, registered in `lib.rs`: `session_tree`,
|
|
128
|
+
`session_fork`, `session_clone` (fork and clone copy the transcript too), `session_rename`,
|
|
129
|
+
`session_compact`, `session_export`, `session_reload`.
|
|
130
|
+
- New sidecar `agent.command` (`createSessionCommand` in `sidecar/src/agentRuns.ts`).
|
|
131
|
+
- `RENDERER_METHODS` (`src-tauri/src/harness.rs`) gained `commands.list`, `doctor.*`,
|
|
132
|
+
`worktrees.list/status` and `agents.list/get`.
|
|
133
|
+
- Bridge: `bridge.commands`, `bridge.session` and `bridge.harnessPages` in
|
|
134
|
+
`src/bridge/commands.ts`. The schemas are in `shared/sessionCommands.ts`.
|
|
135
|
+
- **Prompt:**
|
|
136
|
+
- `src-tauri/src/prompts.rs` no longer writes identity, role, working-project or its own
|
|
137
|
+
connections text.
|
|
138
|
+
- It keeps only the add-on groups: App browser and computer, Files, Capabilities, Reactions.
|
|
139
|
+
- It adds a `folder-access` section for trusted folders.
|
|
140
|
+
- `agents.rs` sets `launch.standard = { cwd }`.
|
|
141
|
+
- **Plugin labels:**
|
|
142
|
+
- `sidecar/src/appPlugins.ts` labels every App part as an add-on, with `surfaces`.
|
|
143
|
+
- `app-identity` and `app-web-guidance` are removed, and `app-folder-access` is added.
|
|
144
|
+
- The Plugins screen shows a "Better in the app" or "App only" badge (`pluginModel.ts`,
|
|
145
|
+
`PluginCatalog.tsx`, `PluginInspector.tsx`).
|
|
146
|
+
- The plugin schema gains `surfaces`.
|
|
147
|
+
- **Guide demo** (`src/modes/guide/SoloWorkspaceExample.tsx`) and the Playwright fixtures and
|
|
148
|
+
specs (`tests/browser/solo-*.{fixture.tsx,spec.ts}`) are rewritten.
|
|
149
|
+
- **Shared interactive profile and root safety:** production App and standalone use the Harness
|
|
150
|
+
profile at `~/.xingular-harness/profile.json`; development uses the isolated
|
|
151
|
+
`~/.xingular-harness-dev/profile.json`. Existing App roots are adopted by reference, explicit
|
|
152
|
+
`dataRoot` overrides remain authoritative, and conflicting populated roots block startup rather
|
|
153
|
+
than merge. Historical account/variant/path/cwd pins are not rewritten. Legacy App Support moves
|
|
154
|
+
only if the destination is absent; if both trees exist, startup reports a recovery error and
|
|
155
|
+
leaves both untouched. Development paths are checked against production, including symlink
|
|
156
|
+
traversal. The App resolves the selected host credential backend through Keychain and fails
|
|
157
|
+
closed; the terminal also fails closed without a host adapter. Disposable App identifiers remain
|
|
158
|
+
blocked until an isolated Keychain adapter exists. Sidecar startup requires and validates the
|
|
159
|
+
selected profile and state-directory paths. Coverage is in `sidecar/src/profile.test.ts` and
|
|
160
|
+
`src-tauri/src/{state.rs,host.rs,secrets.rs}`.
|
|
161
|
+
- **Browser safety:** unsupported native WebKit operations (refs, accessibility snapshots,
|
|
162
|
+
screenshots, waits, and key presses) return an explicit refusal before effects; the App does not
|
|
163
|
+
switch automatically to the isolated Harness browser.
|
|
164
|
+
- **Current App documentation:** accepted ADR-0033 records Project › Session and shared tabs;
|
|
165
|
+
ADR-0027 and the obsolete pane-header portion of ADR-0031 are marked superseded. FEAT-0010,
|
|
166
|
+
FEAT-0018, the Solo glossary, architecture/implementation pages, and this handoff now describe
|
|
167
|
+
shared profile defaults, remaining gaps, and current verification.
|
|
168
|
+
|
|
169
|
+
## Check results (2026-11-19)
|
|
170
|
+
|
|
171
|
+
| Check | Result |
|
|
172
|
+
|---|---|
|
|
173
|
+
| Harness `npm run typecheck` | pass |
|
|
174
|
+
| Harness `npm test` | pass: 163 files, 1,255 passed, 3 skipped |
|
|
175
|
+
| Harness `npm run prove` | pass: build and standalone proof suite; no provider request |
|
|
176
|
+
| App `npm run typecheck` | pass |
|
|
177
|
+
| App `npm test` | pass: renderer 90 files/586 tests; sidecar 11 files/86 tests |
|
|
178
|
+
| App `npm run check:layers` | pass |
|
|
179
|
+
| App `npm run check:ui` | pass: 38 recorded findings, baseline 38 |
|
|
180
|
+
| App `cargo test` | pass: 186 passed, 1 ignored; compiler warnings remain |
|
|
181
|
+
| App `cargo test --features dev-profile` | pass: 189 passed, 1 ignored; compiler warnings remain |
|
|
182
|
+
| App Playwright | pass: all 61 tests with installed Chrome |
|
|
183
|
+
| Xingular UI typecheck and `npm test` | pass: 21 files, 124 tests; the package has no `check:ui` script |
|
|
184
|
+
| Xingular Workspace typecheck | pass |
|
|
185
|
+
| Xingular Workspace `check:ui` | pass: 79 findings, baseline 87 |
|
|
186
|
+
| Xingular Workspace `npm run test:run` | **4 failed, 993 passed**: three `assistantService.test.ts` cases hit the Harness Pi-version guard (requires Pi 1.2.0, found 1.4.0), leaving the fake provider's `release` callback unset; one `commandPaletteNoteItem.test.ts` assertion expects an inline SVG style string that is absent |
|
|
187
|
+
| Xingular Workspace `electron-vite build` | pass (targeted tab-E2E run) |
|
|
188
|
+
| Xingular Workspace tab Playwright (three selected tests) | **3 failed before tab assertions**: shared `launchWithFixture` clicked the Notes sidebar control, then `expectNotePanelReady` timed out. The run used temporary `HOME`, `TMPDIR`, vault and user-data paths; no root cause was established |
|
|
189
|
+
|
|
190
|
+
Browser command: `PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" npx playwright test --reporter=list`.
|
|
191
|
+
|
|
192
|
+
No provider calls or owner profiles were used. Tests use fixture or temporary data. The Workspace test failures were not changed as part of this task; the shared-tab tests in Xingular UI and App Playwright passed.
|
|
193
|
+
|
|
194
|
+
## Remaining gaps and decisions
|
|
195
|
+
|
|
196
|
+
1. **Parity acceptance is not complete.** The source routes and command handlers are present, but each fixed core command still needs its own acceptance. `PAR-002` (Harness History/Wiki/skill tools) and `PAR-006` (first-party hooks) are implemented on both surfaces but acceptance has not been recertified. `get_capabilities` is now Harness-owned; the App has no duplicate tool.
|
|
197
|
+
2. **The session catalog remains separate (`PAR-008`).** App `/session` lists App-owned Solo threads; terminal `/session` lists native Pi histories. The read-only audit recommends a Harness-owned catalog of opaque references to existing native histories—not merging or copying transcripts or IDs. Keep logical/App and native Pi IDs distinct; retain the exact locator privately, preserve account/path/cwd guards, fail rather than substitute an unknown account, and serialize shared writes. This is a recommendation, not an implementation; do not claim `/session` parity.
|
|
198
|
+
3. **Other registered gaps remain:** `PAR-001` App checklist surface; `PAR-003` continuation; `PAR-004` terminal variant/refinement actions; `PAR-005` App-only Wiki browsing; `PAR-007` host-backed computer/files capabilities; `PAR-009` shared recent-folder choice; `PAR-010` Solo `/agents` detail/management; `PAR-011` native WebKit annotation-gesture acceptance; `PAR-012` Solo worktree status/create/remove; and `PAR-015` native WebKit browser coverage. Unsupported browser refs, accessibility snapshots, screenshots, waits, and key presses explicitly refuse before effects; there is no automatic switch to the isolated Harness browser.
|
|
199
|
+
4. **Profile interoperability is intentionally bounded.** Production App and standalone share profile-selected data/state defaults; explicit roots, `--variant`, and historical run pins remain authoritative. The App's per-agent variant is still an App-supplied override. App credentials use the host Keychain backend; a frontend without that host adapter fails closed, and disposable App identifiers are blocked until an isolated Keychain adapter exists. Shared roots do not mean credential-store copying or automatic account substitution.
|
|
200
|
+
5. **Native App acceptance was not performed.** The full Playwright suite ran against isolated browser fixtures, not a Tauri window. No real-model request or user profile was used; the native Keychain and WebKit surfaces therefore remain unverified in a running App.
|
|
201
|
+
6. **Workspace test failures need a separate follow-up.** `assistantService.test.ts` requires the pinned Pi runtime but this Workspace installation resolves Pi 1.4.0; `commandPaletteNoteItem.test.ts` has an SVG markup expectation mismatch. Typecheck and `check:ui` pass.
|
|
202
|
+
7. **Commits:** one per repository, in order Harness → Xingular UI → App, only when the owner asks. No files were committed in this work.
|