@xingular/harness 1.1.1 → 1.3.1-unstable.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 +48 -0
- package/README.md +36 -28
- package/dist/cli.js +10837 -6159
- 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 +18 -4
- package/dist/sdk/agents/planResearch.d.ts +27 -0
- package/dist/sdk/agents/planResearch.js +82 -0
- package/dist/sdk/agents/profiles.d.ts +5 -1
- package/dist/sdk/agents/profiles.js +21 -5
- 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/capabilities/runSnapshot.js +10 -4
- 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 +258 -0
- package/dist/sdk/commands/registry.js +48 -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/shell.d.ts +20 -0
- package/dist/sdk/core/shell.js +73 -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 +20 -0
- package/dist/sdk/core/workspaceBashTool.js +50 -0
- package/dist/sdk/core/workspaceSandbox.d.ts +41 -0
- package/dist/sdk/core/workspaceSandbox.js +360 -0
- package/dist/sdk/core/workspaceWriteOperations.d.ts +33 -0
- package/dist/sdk/core/workspaceWriteOperations.js +224 -0
- package/dist/sdk/doctor/checks.js +71 -12
- 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/hub/hub.js +5 -3
- package/dist/sdk/index.d.ts +8 -3
- package/dist/sdk/index.js +4 -1
- package/dist/sdk/pi/runtime.d.ts +2 -1
- package/dist/sdk/pi/runtime.js +2 -2
- package/dist/sdk/plugins/builtin.js +32 -15
- 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/install.d.ts +6 -2
- package/dist/sdk/plugins/install.js +29 -5
- package/dist/sdk/plugins/inventory.js +6 -5
- 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 -31
- package/dist/sdk/prompt/standard.d.ts +17 -0
- package/dist/sdk/prompt/standard.js +21 -0
- package/dist/sdk/server/methods.js +22 -2
- 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 +7 -2
- package/dist/sdk/sessions/continuation.js +11 -6
- package/dist/sdk/sessions/contracts.d.ts +190 -4
- package/dist/sdk/sessions/contracts.js +71 -8
- 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 +74 -17
- 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 +38 -1
- 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 +225 -22
- package/dist/sdk/sessions/subagentService.d.ts +24 -0
- package/dist/sdk/sessions/subagentService.js +225 -26
- package/dist/sdk/sessions/subagents.d.ts +10 -1
- package/dist/sdk/sessions/subagents.js +4 -0
- package/dist/sdk/sessions/workSlice.d.ts +106 -0
- package/dist/sdk/sessions/workSlice.js +329 -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 +31 -3
- package/dist/sdk/terminal/controller.js +81 -29
- package/dist/sdk/terminal/opentui/ansi.d.ts +25 -0
- package/dist/sdk/terminal/opentui/ansi.js +192 -0
- package/dist/sdk/terminal/opentui/model.d.ts +163 -0
- package/dist/sdk/terminal/opentui/model.js +482 -0
- package/dist/sdk/terminal/opentui/subagentsWidget.d.ts +3 -3
- package/dist/sdk/terminal/opentui/subagentsWidget.js +7 -5
- package/dist/sdk/terminal/opentui/theme.d.ts +43 -0
- package/dist/sdk/terminal/opentui/theme.js +88 -0
- package/dist/sdk/terminal/piExtension.d.ts +6 -1
- package/dist/sdk/terminal/piExtension.js +177 -63
- package/dist/sdk/terminal/standalone.d.ts +7 -0
- package/dist/sdk/terminal/standalone.js +72 -13
- package/dist/sdk/terminal/subagentMonitor.d.ts +28 -6
- package/dist/sdk/terminal/subagentMonitor.js +61 -9
- package/dist/sdk/terminal/terminals.d.ts +26 -2
- package/dist/sdk/terminal/terminals.js +325 -43
- package/dist/sdk/terminal/trajectory.d.ts +6 -1
- package/dist/sdk/terminal/trajectory.js +8 -0
- package/dist/sdk/terminal/tui/annotateCommand.d.ts +1 -1
- package/dist/sdk/terminal/tui/annotateCommand.js +3 -3
- package/dist/sdk/terminal/tui/chrome.d.ts +4 -0
- package/dist/sdk/terminal/tui/chrome.js +13 -0
- package/dist/sdk/terminal/tui/commandPages.d.ts +3 -1
- package/dist/sdk/terminal/tui/commandPages.js +17 -4
- package/dist/sdk/terminal/tui/commands.d.ts +6 -0
- package/dist/sdk/terminal/tui/commands.js +213 -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 +21 -5
- package/dist/sdk/terminal/tui/pages/annotatePage.d.ts +1 -1
- package/dist/sdk/terminal/tui/pages/browserPage.js +5 -4
- package/dist/sdk/terminal/tui/pages/hubPage.d.ts +14 -1
- package/dist/sdk/terminal/tui/pages/hubPage.js +192 -28
- 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 +8 -6
- package/dist/sdk/terminal/tui/pages/pluginsPage.js +206 -28
- package/dist/sdk/terminal/tui/pages/subagentsPage.d.ts +1 -0
- package/dist/sdk/terminal/tui/pages/subagentsPage.js +104 -19
- 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/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/sessionName.d.ts +2 -0
- package/dist/sdk/tools/sessionName.js +5 -3
- package/dist/sdk/tools/spawnSubagent.js +11 -8
- package/dist/sdk/tools/todo.d.ts +15 -0
- package/dist/sdk/tools/todo.js +64 -0
- 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 +9204 -4812
- package/dist/terminal-pi.js +1848 -272
- package/docs/architecture/00-overview.md +1 -1
- package/docs/architecture/01-extension-points.md +1 -1
- package/docs/architecture/02-sessions-and-runs.md +169 -36
- package/docs/architecture/04-prompt.md +55 -15
- package/docs/architecture/06-plugins-and-capabilities.md +36 -15
- package/docs/architecture/07-tools-and-gate.md +131 -25
- package/docs/architecture/08-memory-and-history.md +4 -2
- package/docs/architecture/09-accounts-and-connectors.md +39 -3
- package/docs/architecture/10-server-protocol.md +71 -9
- package/docs/architecture/11-terminal.md +148 -60
- 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 +58 -8
- package/docs/architecture/README.md +20 -17
- package/docs/architecture/proposals/PROP-0006-run-checklist.md +2 -0
- 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 +258 -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/PROP-0044-work-slice-defaults.md +93 -0
- package/docs/architecture/proposals/PROP-0045-rename-checklist-to-todo.md +132 -0
- package/docs/architecture/proposals/PROP-0046-progress-aware-stall-guards.md +82 -0
- package/docs/architecture/proposals/PROP-0047-plugins-hub-separation.md +122 -0
- package/docs/architecture/proposals/README.md +24 -6
- 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/decisions/ADR-0039-progress-aware-stall-guards.md +39 -0
- package/docs/decisions/ADR-0040-architecture-change-workflow.md +31 -0
- package/docs/decisions/ADR-0041-plugins-hub-separation.md +41 -0
- package/docs/decisions/ADR-0042-windows-shell-without-sandbox.md +40 -0
- package/docs/decisions/ADR-0043-parents-continue-stopped-subagents.md +49 -0
- package/docs/doctor.md +14 -1
- 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 +83 -27
- package/docs/releases/1.1.1.md +28 -0
- package/docs/releases/1.2.0.md +49 -0
- package/docs/releases/1.3.0.md +21 -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 +162 -82
- package/package.json +4 -3
- package/dist/sdk/tools/checklist.d.ts +0 -9
- package/dist/sdk/tools/checklist.js +0 -54
|
@@ -34,32 +34,56 @@ Screen: transcript above the composer, centred dialogs, full-screen resource bro
|
|
|
34
34
|
`--conditions=browser` and `dist/terminal-opentui.js`; no global `pi` is needed.
|
|
35
35
|
- The `piExtension` path is the final prepared extension argument; the runtime loads it as the
|
|
36
36
|
final trusted inline factory.
|
|
37
|
+
- Each terminal `begin` returns the run's pinned `workspaceRoot` to that extension. Native file
|
|
38
|
+
writes use the same revalidated atomic helper and OS write scope as SDK sessions. Terminal Bash,
|
|
39
|
+
including initial `!` commands, defaults to the workspace sandbox and external-hard-link scan;
|
|
40
|
+
`!outside <command>` requests human-only approval before that exact command runs once; its full
|
|
41
|
+
escaped command is available in scrollable approval details, and an undersized terminal denies
|
|
42
|
+
the request. The eligible Full Permission switch is the only standing boundary bypass; remembered
|
|
43
|
+
per-tool grants do not widen it, and command output never triggers approval or replay.
|
|
37
44
|
- The terminal compiles its prompt once (`compile` + `render`) and keeps that pack; each run
|
|
38
|
-
records a copy (page 04).
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
45
|
+
records a copy (page 04). The shared compaction checkpoint extension reintroduces the active
|
|
46
|
+
request and latest todo list into post-compaction model context until the run settles.
|
|
47
|
+
- Normal mode keeps `ask_user` out of the active tool set. An attended plan request enables the
|
|
48
|
+
shared tool alongside its read-only set and restores the normal set on success, failure or
|
|
49
|
+
interruption. There is no terminal-only question alias (PROP-0040).
|
|
50
|
+
- A plan request keeps `bash` in its active set; each call runs in the sandbox's read-only scope
|
|
51
|
+
(PROP-0043). A user `!` command is refused while a plan request runs.
|
|
52
|
+
- Current standalone source defaults: `~/.xingular-harness/{data,state}`; `npm run dev` uses
|
|
53
|
+
`~/.xingular-harness-dev/{data,state}`. The standalone development launch uses a file SecretStore
|
|
54
|
+
under its resolved development state directory, even when its profile names a host backend; it
|
|
55
|
+
does not use or alter host credentials. `--variant <scope>` explicitly selects a variant head.
|
|
56
|
+
PROP-0040 approves a shared Harness-owned interactive profile, neutral default scope and
|
|
57
|
+
credential backend; adoption and runtime verification remain in progress. Until that lands,
|
|
58
|
+
matching roots/scopes is explicit and matching roots alone does not share host Keychain secrets.
|
|
59
|
+
- `Launch.standard` supplies the shared role and folder text. History, Wiki and skill model tools
|
|
60
|
+
use the session socket; enabled output-trim/budget-guard hooks load through `firstParty.list`.
|
|
61
|
+
Pi CLI built-ins (llama.cpp, codemode, tool-search and MCP) are not loaded as a terminal-only
|
|
62
|
+
resource path. Harness MCP remains available.
|
|
44
63
|
- An empty conversation shows a centered welcome using `env.productName` (default `Xingular Agent`):
|
|
45
64
|
the first letter of a multiword name is the orange block mark and its remaining words are letter-spaced
|
|
46
65
|
in blue. The welcome adds a greeting, tagline and `/help` hint without replacing the composer or
|
|
47
66
|
status bar. Explicit host product names use the same generic formatting.
|
|
48
67
|
- `xagent --worktree [name]` (`-w`) starts in a new managed worktree of the current repository,
|
|
49
68
|
or in the named one, and prunes older managed worktrees (PROP-0016). A session that names a
|
|
50
|
-
worktree holds it for its whole life. `/worktree`
|
|
51
|
-
the frontend there (`TerminalRelaunch.cwd`),
|
|
52
|
-
working folder.
|
|
53
|
-
- Slash-command aliases share one registry entry: `/session (resume)`
|
|
54
|
-
|
|
69
|
+
worktree holds it for its whole life. `/worktree` opens the worktree page; selecting
|
|
70
|
+
one switches folders by asking the host to restart the frontend there (`TerminalRelaunch.cwd`),
|
|
71
|
+
as a new conversation: Pi keeps one history per working folder.
|
|
72
|
+
- Slash-command aliases share one registry entry: `/session (resume)` opens the full-screen, searchable
|
|
73
|
+
saved-session page with unnumbered title and metadata rows; `/history (tree)` navigates branches in
|
|
74
|
+
the current session, and `/btw (side)` asks a side
|
|
55
75
|
question through the Harness `SideQuestions` service. It uses the same account/model/effort,
|
|
56
76
|
mirrors the main run's redacted prompt and public evidence, starts a separate tool-free run, and
|
|
57
77
|
leaves the main conversation untouched. The dock streams, scrolls and copies the complete answer.
|
|
58
78
|
Aliases remain callable and searchable, but help and palette show only the canonical
|
|
59
|
-
entry.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
79
|
+
entry. `/usage:` and `/usage:analysis` open the usage page's Analysis tab, and `/usage:limit`
|
|
80
|
+
opens its Limits tab (PROP-0042); both are plugin-owned namespaced routes. The usage page is a
|
|
81
|
+
centered dialog: each window is a label and reset line above a quota-left bar coloured green at
|
|
82
|
+
50% or more left, amber from 20–49%, and red below 20%. `commands.list`
|
|
83
|
+
publishes the effective routes; the browser-safe core catalogue is `commands/registry.ts`. First-class Harness commands are unprefixed and live in that registry,
|
|
84
|
+
independently of plugin command metadata. Every plugin-owned command uses
|
|
85
|
+
`/<owner-prefix>:<command>`; the namespace root is offered only by plugins that declare a default
|
|
86
|
+
command. Prompt templates and `/skill:<name>` keep their existing forms.
|
|
63
87
|
|
|
64
88
|
## Invariants
|
|
65
89
|
|
|
@@ -80,20 +104,37 @@ Screen: transcript above the composer, centred dialogs, full-screen resource bro
|
|
|
80
104
|
revoked code needs review and a fresh terminal.
|
|
81
105
|
- **INV-TUI-6** `sessions.run` stays the embedding and unattended path. The terminal keeps a
|
|
82
106
|
persistent child instead of opening a session per turn.
|
|
83
|
-
- **INV-TUI-7**
|
|
84
|
-
plugin
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
107
|
+
- **INV-TUI-7** Harness core commands use unprefixed names and are registered independently of
|
|
108
|
+
feature-plugin command metadata. This includes `/doctor`, `/worktree`, `/trajectory`, `/subagents`
|
|
109
|
+
and `/agents`; `/history` remains session-branch navigation, and `/mcp` remains a Connections
|
|
110
|
+
shortcut. Every plugin-owned terminal command uses `/<owner-prefix>:<command>`, for required and
|
|
111
|
+
optional built-ins and Pi extensions alike. Completions, help and dispatch use the same stable
|
|
112
|
+
owner prefix. Prefixes are unique to an owner; a prefix collision or duplicate command within an
|
|
113
|
+
owner is rejected with owner diagnostics. `/skill:<name>` remains reserved for skill invocation.
|
|
114
|
+
For one release, the former owner-qualified and `/plugin:<command>` forms of promoted Harness
|
|
115
|
+
commands remain hidden compatibility aliases; aliases are not listed in help or completion.
|
|
116
|
+
- **INV-TUI-8** Terminal sessions use the Harness-pinned workspace root and the same write
|
|
117
|
+
boundary as SDK sessions. Native file mutations use revalidated atomic replacement under an OS
|
|
118
|
+
scope; default Bash scans for external hard-link aliases and runs inside the sandbox. The terminal
|
|
119
|
+
cannot widen the boundary through its socket or native extension. `!outside <command>` requests
|
|
120
|
+
human-only approval before one execution; the terminal shows the complete escaped command and
|
|
121
|
+
denies the request if it cannot display details and choices together. stdout/stderr cannot trigger
|
|
122
|
+
approval or replay. Missing enforcement fails closed. Full Permission bypasses the boundary only
|
|
123
|
+
for eligible interactive
|
|
124
|
+
user runs and does not override hard policy denials, read-only or plan mode, unattended work, or
|
|
125
|
+
refinement restrictions.
|
|
89
126
|
|
|
90
127
|
## Source map
|
|
91
128
|
|
|
92
129
|
`src/terminal/**`. Decisions: ADR-0001, [ADR-0004](../decisions/ADR-0004-fullscreen-terminal-layout.md)
|
|
93
|
-
(superseded), ADR-0006, [ADR-0021](../decisions/ADR-0021-required-command-namespaces.md)
|
|
130
|
+
(superseded), ADR-0006, [ADR-0021](../decisions/ADR-0021-required-command-namespaces.md)
|
|
131
|
+
(superseded by [ADR-0031](../decisions/ADR-0031-plugin-command-owner-namespaces.md)),
|
|
94
132
|
[ADR-0024](../decisions/ADR-0024-xagent-command.md),
|
|
95
133
|
[ADR-0027](../decisions/ADR-0027-connected-sketch-display.md),
|
|
96
|
-
[ADR-0028](../decisions/ADR-0028-xingular-agent-product-identity.md)
|
|
134
|
+
[ADR-0028](../decisions/ADR-0028-xingular-agent-product-identity.md),
|
|
135
|
+
[ADR-0031](../decisions/ADR-0031-plugin-command-owner-namespaces.md),
|
|
136
|
+
[ADR-0034](../decisions/ADR-0034-first-class-harness-terminal-commands.md),
|
|
137
|
+
[ADR-0036](../decisions/ADR-0036-workspace-write-operation-boundary.md). Experiments:
|
|
97
138
|
EXP-0001, EXP-0002 in `../experiments/`.
|
|
98
139
|
|
|
99
140
|
## Session name in the working line (PROP-0010)
|
|
@@ -115,19 +156,29 @@ on close. No command text is sent to the conversation model. See [Doctor](../doc
|
|
|
115
156
|
|
|
116
157
|
## Resource browser (PROP-0013)
|
|
117
158
|
|
|
118
|
-
`/harness` owns
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
159
|
+
`/harness` owns broad navigation for Foundation, Variant, Skills, Plugins, Connections, Tools and
|
|
160
|
+
Library. `/skills`, `/connections` (`/mcp`), `/tools` and `/components` are shortcuts into that
|
|
161
|
+
browser. `/plugins` opens the focused local plugin manager (Plugins, Trust and Packages tabs); `/hub`
|
|
162
|
+
opens the separate Community catalog (Catalog and Installed tabs). The Hub Catalog shows Community
|
|
163
|
+
entries across supported types; Installed retains receipts from every channel with its channel
|
|
164
|
+
visible. Registry/document entries offer bounded payload Preview; Pi packages do not. Current
|
|
165
|
+
availability in `/harness` comes from the live resource loader and active tool registry,
|
|
166
|
+
independently of saved configuration and the latest variant head.
|
|
122
167
|
|
|
123
168
|
Every `terminal.browser.*` call requires the private control key, including bounded resource
|
|
124
|
-
inspection, local imports, connection management and browser settings.
|
|
125
|
-
|
|
126
|
-
|
|
169
|
+
inspection, local imports, connection management and browser settings. Direct plugin package
|
|
170
|
+
install/update/remove and attachment/trust/settings actions use protected `plugins.*`; Hub catalog
|
|
171
|
+
list/install/uninstall use protected `hub.*`. Hub-owned package removal keeps the receipt and
|
|
172
|
+
resource ownership in the Hub service. These routes are adapters to the existing services, not
|
|
173
|
+
another loader, attachment store, gate or secret store. Browsing neither executes plugin code nor
|
|
174
|
+
connects MCP.
|
|
127
175
|
The browser uses the full terminal with persistent section tabs (PROP-0014); wide screens keep
|
|
128
176
|
inventory beside details, actions and content, while compact screens keep inline details under
|
|
129
|
-
the same tabs.
|
|
130
|
-
|
|
177
|
+
the same tabs. The separate `/plugins` and `/hub` pages also use full-screen layouts with persistent
|
|
178
|
+
section tabs, responsive inventory/details panes and their existing protected operations. Other
|
|
179
|
+
command pages remain centered except `/settings`, `/accounts`, `/plugins` and `/hub`, which use
|
|
180
|
+
full-screen page layouts.
|
|
181
|
+
Accounts keeps Accounts/Pools tabs, search and account-service operations.
|
|
131
182
|
Wide terminals show selected-account details beside the list; Enter or a primary click opens grouped
|
|
132
183
|
actions in that inspector. Compact terminals replace the list with a full-page account detail view
|
|
133
184
|
and its grouped actions. Enter opens the selected account; Escape returns to the list while
|
|
@@ -166,7 +217,9 @@ Every choice uses one shared measured layout: a marker gutter, a one-third label
|
|
|
166
217
|
gap, and the remaining description cell. Column boundaries align across all rows at every terminal
|
|
167
218
|
width, including compact widths. Text wraps within its cell; a missing description keeps its cell
|
|
168
219
|
and columns never stack. Recommendation text uses `(Rec.)` when the label column is fewer than 14
|
|
169
|
-
cells. Below 60 terminal columns, the dock uses a compact hint.
|
|
220
|
+
cells. Below 60 terminal columns, the dock uses a compact hint. Multi-select choices use `✓`
|
|
221
|
+
when selected and `○` when unselected, matching checklist glyphs; single-choice options remain
|
|
222
|
+
numbered.
|
|
170
223
|
|
|
171
224
|
The dock body has bounded height and vertical scrolling; question tabs and answer/action controls
|
|
172
225
|
stay outside that scrolling region. PageUp/PageDown scroll the body and Ctrl+Home/End jump to its
|
|
@@ -200,54 +253,89 @@ contract is unchanged. See [PROP-0025](proposals/PROP-0025-contextual-question-w
|
|
|
200
253
|
PTY verification is retained in `docs/evidence/terminal-wireframe-normalization/`; it establishes
|
|
201
254
|
cell topology for bounded fixtures, not every emulator/font or live-model sketch quality.
|
|
202
255
|
|
|
203
|
-
##
|
|
256
|
+
## Web annotations commands (PROP-0017)
|
|
204
257
|
|
|
205
|
-
`/
|
|
206
|
-
reopen, share with this session or stop sharing, and delete. `/
|
|
207
|
-
opens a visible capture browser (its own window and profile, separate from the agent's browser),
|
|
208
|
-
|
|
209
|
-
terminal. A note is private until shared; this session's agent then reads it with `page_notes_list`
|
|
258
|
+
`/annotate:notes` lists the Web annotations kept in the data root, with search, and offers reveal, edit, resolve or
|
|
259
|
+
reopen, share with this session or stop sharing, and delete. `/annotate:` opens the default capture pane;
|
|
260
|
+
`/annotate:annotate [url]` is its explicit command form. It opens a visible capture browser (its own window and profile, separate from the agent's browser), where the person can annotate the whole page,
|
|
261
|
+
select text, or click an element there. An annotation is private until shared; this session's agent then reads it with `page_notes_list`
|
|
210
262
|
and `page_notes_read`.
|
|
211
263
|
|
|
212
|
-
|
|
264
|
+
The annotate pane (PROP-0018) is a full-screen page beside the window being inspected.
|
|
213
265
|
|
|
214
266
|
- **Ways to start it:**
|
|
215
|
-
- `/
|
|
216
|
-
- `/
|
|
217
|
-
- `/
|
|
267
|
+
- `/annotate:` or `/annotate:annotate [url]`: the capture browser
|
|
268
|
+
- `/annotate:annotate --app <DevTools address | port> [name]`: an app's own windows over its DevTools port
|
|
269
|
+
- `/annotate:annotate --bridge [name]`: app windows that load the page bridge script, which the pane shows
|
|
218
270
|
- **The inspector** (`i`) outlines components on hover. A click or a text drag opens a popover in the page with Create annotation, Ask agent to fix, and Proceed now.
|
|
219
271
|
- **Sections:** Queue, Sent and fixed (with the agent's summary), and Saved.
|
|
220
272
|
- **Other keys:** `s` sends the queue as one run of this session, confirming notes that came from a page-world script first; `x` takes a note out of the queue; `t` picks a window.
|
|
221
273
|
- **Routes:** `terminal.annotations.target|attach|windows|selectWindow|inspect|stopInspect|next|queue|dequeue|confirm|send` act only on this terminal's session and need the control key.
|
|
222
274
|
|
|
223
|
-
##
|
|
224
|
-
|
|
225
|
-
Terminal sessions register the shared `
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
275
|
+
## Todo list (PROP-0006, PROP-0045, PAR-001)
|
|
276
|
+
|
|
277
|
+
Terminal sessions register the shared `todo_write` tool. The extension validates each list with
|
|
278
|
+
the same tool code and sends it as `todo` telemetry; the controller emits it as `todo.updated` on the
|
|
279
|
+
active run, so `runs.todo` and continuation read terminal runs too. The gate treats it as read-only,
|
|
280
|
+
plan mode allows it, and terminal children inherit it. The transcript shows each write as a todo
|
|
281
|
+
block (`✓` done, `●` in progress (warning yellow), `○` pending) under a `Todo · n of m done` header
|
|
282
|
+
instead of a tool row; a failed or malformed call stays a tool row. `/todo` reads the latest
|
|
283
|
+
non-side-question run of this terminal's native session and appends the same card as a snapshot,
|
|
284
|
+
without a model request; an empty list is a one-line notice. `/checklist` remains its alias for one
|
|
285
|
+
release.
|
|
286
|
+
|
|
287
|
+
## Work-slice checkpoint (PROP-0041)
|
|
288
|
+
|
|
289
|
+
Terminal replies carry the same work-slice guard as structured runs: 320 tool calls or 60 minutes,
|
|
290
|
+
with no new-token limit by default (PROP-0044), then a refusal that asks for `checkpoint_write`. The
|
|
291
|
+
extension registers the shared tool and sends it as `checkpoint` telemetry, which the controller
|
|
292
|
+
records as `checkpoint` on the
|
|
293
|
+
active run, so an App reading the same session sees the handoff. Terminal replies are not
|
|
294
|
+
auto-continued: at the boundary the person decides, which is what the terminal's own turn model
|
|
295
|
+
already does. The run record says `interrupted` with terminal reason `slice_complete` (or `stalled`
|
|
296
|
+
when the guard ended it), so a host can continue it; a checkpoint card in the transcript is not built
|
|
297
|
+
yet (PAR-004). Start the terminal with `XINGULAR_WORK_SLICE=off` to launch a reply with no
|
|
298
|
+
boundary at all; it is not persisted, so the next launch without it restores the guard.
|
|
231
299
|
|
|
232
300
|
## Subagent activity monitor
|
|
233
301
|
|
|
234
302
|
During an active parent run, the terminal polls a private read-only monitor once per second. It
|
|
235
303
|
projects the flat set of child and nested-child runs with task, status, elapsed time, the latest
|
|
236
304
|
tool name, the child's agent profile (name and colour, PROP-0029), the title the parent gave it
|
|
237
|
-
(PROP-0030),
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
305
|
+
(PROP-0030), counts from the child's own todo list, the pinned account label, effective model and
|
|
306
|
+
effort, and cumulative usage totals. Model and effort come from the volatile launch selection; the
|
|
307
|
+
latest provider-reported model supersedes the launch model when usage is available. Usage is an
|
|
308
|
+
explicit projection of token, cache, cost, request-count and context-window totals. Per-request
|
|
309
|
+
payloads and reasoning summaries do not enter the monitor. The child's own `session_name` is not
|
|
310
|
+
projected; it names the child's session, not its row. Tool summaries, other arguments, output and
|
|
311
|
+
todo item text never enter the monitor. The latest completed tool name remains visible across
|
|
312
|
+
one-second snapshots until new tool or response activity replaces it. The monitor exposes no
|
|
313
|
+
controls to steer or stop children.
|
|
242
314
|
|
|
243
315
|
The live rows sit under the status line, after one blank row, with no heading. Each row reads, in
|
|
244
316
|
order: the status mark (`○` queued, a running row that shows the working spinner's frame in the profile's colour (warning for a copy of the parent), `●` waiting in the accent,
|
|
245
317
|
`✓` done, `✕` failed, `!` stopped), the profile name in its colour (`subagent`, muted, for a copy
|
|
246
318
|
of the parent), the title the parent gave the child (PROP-0030), and `n of m tasks` when the child
|
|
247
|
-
keeps a
|
|
248
|
-
terminal cuts the title first. `/subagents` opens the searchable full roster with
|
|
249
|
-
|
|
250
|
-
|
|
319
|
+
keeps a todo list. Active rows come first, at most three, then `+N more · /subagents`; a narrow
|
|
320
|
+
terminal cuts the title first. `/subagents` opens the searchable full roster, with a colored
|
|
321
|
+
profile and normal-color title on its first line, then muted account, model, effort and usage
|
|
322
|
+
metadata on its second line. One blank row separates each two-line entry. Narrow rows truncate this
|
|
323
|
+
lower-priority summary without hiding the title.
|
|
324
|
+
At parent settlement, the terminal makes a final monitor read and keeps the latest parent's rows
|
|
325
|
+
visible until the next parent run starts.
|
|
326
|
+
|
|
327
|
+
The monitor also projects the parent run itself as a `main` row (profile `main`, a reserved name,
|
|
328
|
+
in the theme's primary colour) with the same account, model, effort, usage, activity and todo
|
|
329
|
+
fields. The `/subagents` page pins it first and counts only children in its header; the rows under
|
|
330
|
+
the status line omit it, since the status line already describes the main agent.
|
|
331
|
+
|
|
332
|
+
Every turn marks its run on the native branch (`xingular-subagent-owner`), and `ready` sends those
|
|
333
|
+
owners. When a conversation opens or is switched to with no run active, the monitor is rebuilt from
|
|
334
|
+
the branch's latest top-level run in this folder and its descendants, by folding their saved events
|
|
335
|
+
with their final status. Runs a stopped process left active were already marked `interrupted`.
|
|
336
|
+
The rows show under the status line and on the page until the next parent run starts (ADR-0043).
|
|
337
|
+
The projection remains read-only and scoped to one parent run; a switch to a conversation with no
|
|
338
|
+
such run clears it, as does terminal disposal. It is not a persisted event or public server method.
|
|
251
339
|
|
|
252
340
|
## Agent profiles (PROP-0029)
|
|
253
341
|
|
|
@@ -25,10 +25,12 @@ index.
|
|
|
25
25
|
plugins/<name>/ packages kept with the data (06)
|
|
26
26
|
trash/plugins/ removed packages (06)
|
|
27
27
|
hub/ installed documents and provenance (09)
|
|
28
|
-
runs/<id>/ run.json, events.jsonl, owner.json, subagents.json, context.json, caller.json, capabilities.json, mcp-context.json (02)
|
|
28
|
+
runs/<id>/ run.json (including optional legacy-compatible workspaceRoot), events.jsonl, owner.json, subagents.json, context.json, caller.json, capabilities.json, mcp-context.json (02)
|
|
29
|
+
# `checkpoint` and `heartbeat` are run events in the same events.jsonl; a bounded reply emits one
|
|
30
|
+
# heartbeat per 30 seconds (about 60 KB an hour) and no side file (PROP-0041).
|
|
29
31
|
config/ plugin-attachments.json and settings the harness reads (06)
|
|
30
32
|
agents/<name>.md a person's global agent profiles; agents/profiles.ts owns it (02, PROP-0029)
|
|
31
|
-
index.sqlite derived index (FTS5) (08)
|
|
33
|
+
index.sqlite derived index (FTS5, recall, usage ledger) (08, PROP-0042)
|
|
32
34
|
projects.json read only: the application owns it
|
|
33
35
|
|
|
34
36
|
<state dir>/
|
|
@@ -48,6 +50,25 @@ index.
|
|
|
48
50
|
harness.log standalone terminal diagnostics
|
|
49
51
|
```
|
|
50
52
|
|
|
53
|
+
The interactive profile is a credential-free, versioned selection file at
|
|
54
|
+
`~/.xingular-harness/profile.json`, owned by `src/core/interactiveProfile.ts`. It selects the
|
|
55
|
+
interactive defaults: data root, state directory, default variant scope, and a credential-backend
|
|
56
|
+
descriptor. With no selected profile, the defaults are `~/.xingular-harness/data`,
|
|
57
|
+
`~/.xingular-harness/state`, scope `default`, and the state directory's owner-only file secret
|
|
58
|
+
store. A host may provide a stable host-backed secret adapter instead; the profile stores only its
|
|
59
|
+
identifier, never credentials. If that adapter is unavailable, startup fails rather than falling
|
|
60
|
+
back to a different store.
|
|
61
|
+
|
|
62
|
+
Explicit roots or variant scopes take precedence over the selected profile; the selected profile
|
|
63
|
+
precedes caller-supplied legacy defaults. Explicit adoption creates the profile file without
|
|
64
|
+
replacing an existing selection and does not create, copy, merge, or migrate data roots or
|
|
65
|
+
credentials. Existing account, variant, and session pins remain authoritative for their saved
|
|
66
|
+
runs; the profile selects defaults for new interactive work. `scripts/dev.mjs` and a development
|
|
67
|
+
interactive profile use `~/.xingular-harness-dev/{data,state}` and a separate profile file, not the
|
|
68
|
+
production defaults. The standalone development launch always selects a file SecretStore under its
|
|
69
|
+
resolved development state directory, even if that profile names a host backend; it does not use or
|
|
70
|
+
alter host credentials.
|
|
71
|
+
|
|
51
72
|
Side-question runs use the ordinary `runs/<id>/` records. Their temporary Pi native history is
|
|
52
73
|
created under the operating system temporary directory and removed when the run ends; it is not
|
|
53
74
|
retained in the data root or state directory.
|
|
@@ -68,6 +89,13 @@ retained in the data root or state directory.
|
|
|
68
89
|
as it was when a migration fails, and the failure is reported in `Recovery.migrationError`.
|
|
69
90
|
- **INV-STO-6** Writes of shared JSON files are atomic (`core/fs.ts::atomicWrite`, `writeJson`).
|
|
70
91
|
- **INV-STO-7** Files holding trust or secrets are owner-only (`0600`).
|
|
92
|
+
- **INV-STO-8** `core/interactiveProfile.ts` owns the credential-free selection of interactive
|
|
93
|
+
roots, default variant scope, and credential-backend descriptor. Explicit roots/scopes win; a
|
|
94
|
+
selected profile wins over legacy defaults. Adoption never replaces a selection or merges roots,
|
|
95
|
+
and a missing host credential adapter never silently downgrades to a file store. The standalone
|
|
96
|
+
development launch explicitly selects its isolated file store; this is not a fallback for normal
|
|
97
|
+
interactive profiles. Profile defaults do not replace the account, variant, or other pins on saved
|
|
98
|
+
runs.
|
|
71
99
|
|
|
72
100
|
## Source map
|
|
73
101
|
|
|
@@ -18,6 +18,21 @@ synthetic page. Their input runs only after live-check confirmation, and their r
|
|
|
18
18
|
released on completion, timeout or cancellation. Computer interaction needs a host-provided
|
|
19
19
|
isolated surface; without one it is blocked.
|
|
20
20
|
|
|
21
|
+
## Shared browser contract and native WebKit limits (PROP-0040)
|
|
22
|
+
|
|
23
|
+
`browser/contracts.ts` owns the backend-neutral names and input schemas for `browser_*` tools;
|
|
24
|
+
providers adapt those definitions rather than inventing host-specific selectors. The isolated Harness
|
|
25
|
+
backend supports accessibility snapshots and snapshot-scoped refs. A native WebKit host backend
|
|
26
|
+
currently supports navigation, tab management, visible-text reads and page-level scrolling without a
|
|
27
|
+
ref. It does not support accessibility snapshots, snapshot refs or ref-based click/type/select/scroll,
|
|
28
|
+
browser screenshots, browser waits or keyboard presses.
|
|
29
|
+
|
|
30
|
+
For an unsupported operation the native provider returns an explicit `browser_unsupported` refusal
|
|
31
|
+
with “Nothing was done”; it never treats a snapshot ref as a selector and never silently switches to
|
|
32
|
+
the isolated browser. The isolated Harness browser is an independent backend, not an automatic
|
|
33
|
+
fallback for the native provider. A host plugin's `surfaces` description labels that fallback and its
|
|
34
|
+
limits; it does not assert full browser parity.
|
|
35
|
+
|
|
21
36
|
Plugin ownership and the Foundation boundary are recorded in PROP-0012, ADR-0014 and PROP-0020.
|
|
22
37
|
World providers are assembled through `BuiltinPluginRegistry`; no eighth extension point is added.
|
|
23
38
|
|
|
@@ -39,7 +54,13 @@ terminal, or in a host's own web view running the same page helper (`annotations
|
|
|
39
54
|
- A queued note is shared with its session.
|
|
40
55
|
- `annotations/delivery.ts` sends a batch as one instruction, and sends notes the person asked for while the session was busy when its run ends.
|
|
41
56
|
- The agent reports a fix with `page_notes_mark_fixed`, the only page-note tool that writes. It never resolves a note or changes grants.
|
|
42
|
-
- **Targets.**
|
|
57
|
+
- **Targets.** Element targets prefer semantic role/name/text. A visually empty element may still be
|
|
58
|
+
annotated when it has a specific CSS selector (ID, test ID, classes, and a structural path when
|
|
59
|
+
needed); bare tag selectors are not enough. Reveal checks for one live match and preserves any
|
|
60
|
+
captured semantic/context evidence, otherwise reporting ambiguous or unresolved. Text annotations
|
|
61
|
+
continue to use quote plus context, not screen coordinates.
|
|
62
|
+
- Besides the browser window, capture can use an app's own windows:
|
|
43
63
|
- **DevTools port:** an app started with a DevTools port, on a loopback address only. It uses the app's existing windows, routes nothing, and never closes the app.
|
|
44
64
|
- **Page bridge:** a loopback server whose script an app loads while it is developed (`annotations/bridge.ts`), for web views without a DevTools port.
|
|
65
|
+
- **Web components (PROP-0038).** The helper walks the composed tree: open shadow roots and slotted content can be picked, selected and revealed, and such targets carry `tree: 'composed'`. Targets without it resolve by the document-only rules as before. Closed shadow roots and frames stay out of reach, and the inspector says why it refuses something.
|
|
45
66
|
- **Trust.** In Chromium targets the helper runs in an isolated script world, so the page cannot forge a comment. A send from the bridge, or from a host web view without isolation, waits for the person to confirm it.
|
|
@@ -17,7 +17,7 @@ terminal command or page, a host screen.
|
|
|
17
17
|
|---|---|---|
|
|
18
18
|
| Foundation service | A member of `Harness` with server methods | `sessions`, `accounts`, `apps`, `worktrees` (PROP-0016), agent profiles (`agents.*`, PROP-0029) |
|
|
19
19
|
| Built-in feature plugin | A module in `BuiltinPluginRegistry` (`plugins/builtin.ts`) that may supply a `WorldPart`, server methods and terminal commands | web tools, browser tools, annotations, worktrees |
|
|
20
|
-
| First-party plugin | A descriptor in the registry (`plugins/builtin.ts`) | lessons,
|
|
20
|
+
| First-party plugin | A descriptor in the registry (`plugins/builtin.ts`) | lessons, todo |
|
|
21
21
|
| Terminal surface | A command, page or dialog in `terminal/` | `/plan`, `/doctor`, the resource browser |
|
|
22
22
|
| Host surface | A host screen built on the same methods and tools | the App's chat, Capability and Harness screens |
|
|
23
23
|
| Host-backed backend | An operating-system object only a host has, behind a generic Harness contract | the App's WebKit tabs, macOS computer bridge, keychain |
|
|
@@ -27,14 +27,42 @@ terminal command or page, a host screen.
|
|
|
27
27
|
|
|
28
28
|
- A capability is reachable through server methods (page 10) and, where a model uses it, through a
|
|
29
29
|
tool that passes the gate (page 07). Both front ends use the same methods; neither has a private
|
|
30
|
-
path to Harness state.
|
|
31
|
-
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
path to Harness state. Foundation context behavior, including bounded checkpoint restoration after
|
|
31
|
+
compaction (PROP-0033), is shared by terminal and embedded sessions; a host does not reimplement it.
|
|
32
|
+
The direct `/plugins` page manages local plugin state and package lifecycle; `/hub` presents the
|
|
33
|
+
Community catalog and all installed Hub receipts. These are distinct presentations of existing
|
|
34
|
+
Harness services, not host-only capabilities. The broad `/harness` browser remains available.
|
|
35
|
+
- Workspace write scope is Harness-owned on both surfaces. Each run pins a canonical root after
|
|
36
|
+
worktree selection; reads retain OS-permission scope, while native file writes and shell
|
|
37
|
+
filesystem effects default to that root; the filesystem root itself is not a valid workspace.
|
|
38
|
+
Native mutations revalidate their canonical target and atomically replace the file under an OS
|
|
39
|
+
write scope. Default Bash scans for external hard-link
|
|
40
|
+
aliases and runs under an OS sandbox that prevents its own processes from creating cross-boundary
|
|
41
|
+
hard links; on macOS the sandbox denies hard-link creation entirely, including within the
|
|
42
|
+
workspace. `workspaceWriteScope: 'outside'` (terminal `!outside <command>`) requests a human-only
|
|
43
|
+
approval before one execution, showing the complete escaped command in scrollable terminal details
|
|
44
|
+
and denying if the terminal is too small. Output never triggers approval or retry. Hosts may
|
|
45
|
+
tighten or deny policy but cannot silently waive the boundary. Only the eligible Full Permission
|
|
46
|
+
switch may answer automatically under its existing restrictions. A same-user peer process outside
|
|
47
|
+
Harness is not controlled by this rule. `workspaceRoot` is additive and legacy run records may
|
|
48
|
+
omit it.
|
|
49
|
+
- Harness core terminal commands use unprefixed names and are registered independently of feature
|
|
50
|
+
plugin command metadata. This includes `/doctor`, `/worktree`, `/trajectory`, `/subagents` and
|
|
51
|
+
`/agents`; `/history` remains session-branch navigation, and `/mcp` remains a Connections shortcut.
|
|
52
|
+
Every plugin-owned terminal command uses `/<owner-prefix>:<command>`, for required and optional
|
|
53
|
+
built-ins and Pi extensions alike. Built-in prefixes are stable registry metadata; Pi package
|
|
54
|
+
extensions use a normalized package name or the package's `harness.commandPrefix`, and loose
|
|
55
|
+
extensions use their normalized extension name. Prefix collisions and duplicate commands within
|
|
56
|
+
one owner are rejected with owner diagnostics. Built-in plugin modules may declare a default
|
|
57
|
+
command for their namespace root. The former owner-qualified and `/plugin:<command>` forms of
|
|
58
|
+
promoted Harness commands remain hidden compatibility aliases for one release. Prompt templates
|
|
59
|
+
and `/skill:<name>` keep their existing forms. Built-in plugin categories remain documented in
|
|
60
|
+
page 06, not public metadata.
|
|
35
61
|
- A capability may be limited to a run mode when Harness resolves the callable set; the register
|
|
36
62
|
records that restriction for both surfaces. `ask_user` is available only in attended plan runs,
|
|
37
|
-
|
|
63
|
+
with no terminal-only question alias (PROP-0040). Plan-mode delegation
|
|
64
|
+
is limited to named profiles whose effective tool and plugin allowlists qualify for read-only
|
|
65
|
+
research; both terminal and host use the same gate and child-capability narrowing.
|
|
38
66
|
- Question choice sketches use one optional validated event contract: up to 80 printable ASCII
|
|
39
67
|
columns by 24 LF-separated lines (1,943 bytes maximum; page 02). Both surfaces use the same
|
|
40
68
|
literal ASCII source, persisted unchanged, in one shared preview with access to overflow; neither
|
|
@@ -56,6 +84,27 @@ terminal command or page, a host screen.
|
|
|
56
84
|
- Side questions use one Harness service on both surfaces. Each caller supplies its visible
|
|
57
85
|
transcript projection; Harness adds the parent run's effective prompt and public events, then
|
|
58
86
|
starts an independent tool-free run.
|
|
87
|
+
- PROP-0040 defines one shared launch/command contract: `Launch.standard`, `commands.list`,
|
|
88
|
+
saved-history controls and tracked `SessionRunInput.command` runs. Hosts present these rather
|
|
89
|
+
than approximating navigation with a fork. A listed command or handler is not proof of acceptance.
|
|
90
|
+
The current host `/session` picker reads a host-owned session catalog rather than a shared Harness
|
|
91
|
+
catalog (PAR-008), and read-only command pages do not stand in for unsupported management methods.
|
|
92
|
+
The register records command routes individually; parity remains open until each route passes
|
|
93
|
+
acceptance.
|
|
94
|
+
- Read-only `get_capabilities` is implemented in structured sessions and the terminal. Structured
|
|
95
|
+
sessions report tools filtered by the run's frozen capability set and actual registered schemas;
|
|
96
|
+
the terminal reports Pi's active tools and schemas, applying its plan-mode allowed set when active.
|
|
97
|
+
It is in the shared plan-mode allowlist and grants no permission. Hosts use this Harness tool rather
|
|
98
|
+
than defining a duplicate.
|
|
99
|
+
- `browser/contracts.ts` owns shared backend-neutral browser schemas. A native WebKit host backend
|
|
100
|
+
still lacks accessibility snapshots and snapshot-ref interactions, browser screenshots, waits and
|
|
101
|
+
keyboard input; unsupported calls return an explicit refusal before effects and do not trigger an
|
|
102
|
+
automatic backend switch (page 13, PAR-015).
|
|
103
|
+
- Shared interactive defaults, profile adoption, credentials and a cross-surface session catalog
|
|
104
|
+
remain in progress under PROP-0040. Existing pins and explicit profile choices win; adoption must
|
|
105
|
+
not merge stores, copy credentials or silently downgrade the secret backend.
|
|
106
|
+
- `PluginDescriptor.surfaces` / `Plugin.surfaces` optionally describe a host preference, terminal
|
|
107
|
+
fallback/unavailability and reason. This labels add-ons, not plugin categories or permissions.
|
|
59
108
|
- The register of capabilities and their surfaces is [`docs/parity.md`](../parity.md). It is
|
|
60
109
|
descriptive; the invariants below are binding.
|
|
61
110
|
- A host keeps its own register of host-only surfaces. The Harness names no host surface.
|
|
@@ -86,4 +135,5 @@ None of its own. Each capability stores its data as its own page says.
|
|
|
86
135
|
`src/harness.ts` (services), `src/world/world.ts` (world parts), `src/plugins/builtin.ts`
|
|
87
136
|
(first-party descriptors), `src/terminal/` (terminal surfaces), `src/server/methods.ts` (methods).
|
|
88
137
|
Decision: [PROP-0015](proposals/PROP-0015-one-capability-surface.md),
|
|
89
|
-
[ADR-0017](../decisions/ADR-0017-one-capability-surface.md)
|
|
138
|
+
[ADR-0017](../decisions/ADR-0017-one-capability-surface.md),
|
|
139
|
+
[ADR-0036](../decisions/ADR-0036-workspace-write-operation-boundary.md).
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
# Harness architecture specification
|
|
2
2
|
|
|
3
|
-
**Status:** binding. **As of:** 2026-10-
|
|
3
|
+
**Status:** binding. **As of:** 2026-10-27, checked against `src/` on branch `release/1.0.0`.
|
|
4
4
|
|
|
5
5
|
This folder is the core specification of `@xingular/harness`. Code must conform to it. A change
|
|
6
|
-
that
|
|
7
|
-
[Changing the architecture](#changing-the-architecture)).
|
|
6
|
+
that alters what it says must update the affected pages in the same change (see
|
|
7
|
+
[Changing the architecture](#changing-the-architecture)). Proposals are optional design records,
|
|
8
|
+
not prerequisites or approval gates.
|
|
8
9
|
|
|
9
10
|
Other documents explain and record; this folder decides. Where another document disagrees with a
|
|
10
11
|
page here, this page wins, and the disagreement is listed under [Known drift](#known-drift).
|
|
@@ -64,7 +65,7 @@ current behavior.
|
|
|
64
65
|
|
|
65
66
|
| Word | Meaning |
|
|
66
67
|
|---|---|
|
|
67
|
-
| **Foundation** | The fixed half of the harness: code and invariants that no edit, improver or adoption can change. Changes by release
|
|
68
|
+
| **Foundation** | The fixed half of the harness: code and invariants that no edit, improver or adoption can change. Changes by release; contract changes update the specification and may use an optional proposal as a design record. |
|
|
68
69
|
| **Agent Mode** | A planned foundation-level work style, with at most one mode active at a time. Plugins remain independently stackable contributions. This is distinct from plan mode and existing `mode` fields; it is not a runtime contract ([FW-0001](../future-work.md#fw-0001-agent-modes-starting-with-router-agent-mode)). |
|
|
69
70
|
| **Variant** | The mutating half: one tree of eight components (c1–c8) for one scope. Formerly "harness tree". |
|
|
70
71
|
| **Component** | One of c1–c8 inside a variant (system prompt, guardrails, memory, tool guidance, subagents, skills, scripts, plugins). |
|
|
@@ -86,24 +87,24 @@ Every coding agent and contributor follows these steps.
|
|
|
86
87
|
2. **Within the spec: just do it.** If the change fits every contract and invariant, make it. If it
|
|
87
88
|
adds detail without changing a rule (a new server method in an existing group, a new optional
|
|
88
89
|
field), update the page in the same commit.
|
|
89
|
-
3. **Outside the spec:
|
|
90
|
-
layer boundary, an extension point, or the storage layout,
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
4. **
|
|
94
|
-
|
|
95
|
-
lasting one. A rejected proposal keeps its file with status `Rejected`.
|
|
90
|
+
3. **Outside the spec: implement and update.** If the change alters a contract, an invariant, a
|
|
91
|
+
layer boundary, an extension point, or the storage layout, implement the requested change and
|
|
92
|
+
update affected pages in the same change. A proposal may document the design, but is optional
|
|
93
|
+
and does not gate implementation.
|
|
94
|
+
4. **Record lasting decisions.** Add an ADR in `../decisions/` when the choice is a lasting one.
|
|
95
|
+
Proposals may be added to the index when useful; no `Accepted` status is required before work.
|
|
96
96
|
5. **Drift is reported, not fixed silently.** If code and a page already disagree, add the item to
|
|
97
|
-
[Known drift](#known-drift) and tell the user.
|
|
98
|
-
|
|
97
|
+
[Known drift](#known-drift) and tell the user. When resolving drift within the requested scope,
|
|
98
|
+
update the code and spec together and record the rationale; do not silently change unrelated
|
|
99
|
+
behavior.
|
|
99
100
|
|
|
100
|
-
When unsure whether a change alters the architecture,
|
|
101
|
-
proposal.
|
|
101
|
+
When unsure whether a change alters the architecture, read the affected pages and update them in
|
|
102
|
+
the same change. Use a proposal only when it helps explain the design.
|
|
102
103
|
|
|
103
104
|
## Known drift
|
|
104
105
|
|
|
105
|
-
Disagreements found while writing this specification.
|
|
106
|
-
|
|
106
|
+
Disagreements found while writing this specification. Record their evidence here and report them;
|
|
107
|
+
resolve relevant drift by updating the implementation and specification together in the same change.
|
|
107
108
|
|
|
108
109
|
| ID | Where | What disagrees |
|
|
109
110
|
|---|---|---|
|
|
@@ -123,3 +124,5 @@ proposal, or a correction to the other document).
|
|
|
123
124
|
| D-14 | 12-storage layout | Page 12 lists browser settings under `<state dir>/browser/`, while `browser/config.ts` stores configuration in `<state dir>/browser.json`; browser profiles and downloads use the `browser/` directory. The layout needs an owner decision before either side is changed. |
|
|
124
125
|
| D-15 | Terminal sketch verification status — resolved 2026-10-24 by PROP-0028 | Pages 11 and 14 and `terminal-tui.md` said connected-sketch implementation verification was pending, while retained PTY evidence and PAR-014 recorded it as verified. Updated the docs to distinguish deterministic fixture verification from owner visual acceptance, every-emulator rendering and live-model sketch quality. |
|
|
125
126
|
| D-16 | Terminal slash-command highlighting — resolved 2026-10-24 | `terminal-tui.md` specified accent coloring for recognized leading commands while typing, but the OpenTUI composer only styled attachment labels. User-message bubbles also lacked command-token styling. The renderer now uses the active command registry for both surfaces. |
|
|
127
|
+
| D-17 | `PROP-0039`, `ADR-0036`, `INV-GATE-3/8` | Implementation is in progress in the 1.2.0 worktree: native writes revalidate canonical targets and atomically replace files under an OS write scope; default Bash fails closed on external hard-link aliases and runs in a sandbox that prevents new cross-boundary links; outside-scope Bash requires approval before one execution and command output never triggers approval or replay. The filesystem root is rejected as a workspace, and approval details expose the complete command. Launcher selection uses fixed system paths. Same-user peer processes remain outside this boundary. Focused macOS tests, full Harness CI, App compatibility checks, and PTY verification at 40x20, 80x24, and 100x30 pass. Linux sandbox integration remains unverified locally because this Darwin host has no `bwrap` and Colima is stopped; both CI workflows now install bubblewrap and `scripts/ci.sh` fails if it is absent, but an Ubuntu run is still required. No candidate, tag, or publication exists. |
|
|
128
|
+
| D-18 | `core/index.ts` migration 5 | The `run_stats` table has no writer in the Harness. PROP-0042's `usage_requests` ledger is the analytics source; whether to drop the older table is open. |
|
|
@@ -9,6 +9,8 @@ affects: [02-sessions-and-runs.md, 06-plugins-and-capabilities.md, 07-tools-and-
|
|
|
9
9
|
|
|
10
10
|
# PROP-0006: A run checklist the model writes, recorded as a run event
|
|
11
11
|
|
|
12
|
+
> Renamed to todo by [PROP-0045](PROP-0045-rename-checklist-to-todo.md). The names below are historical.
|
|
13
|
+
|
|
12
14
|
## Problem
|
|
13
15
|
|
|
14
16
|
A run has no structured record of progress. `goal` on a run is opaque text, and plan mode ends
|
|
@@ -3,7 +3,7 @@ id: PROP-0017
|
|
|
3
3
|
title: Page annotations as a Harness capability, captured in the headed browser or a host's web view
|
|
4
4
|
status: Implemented
|
|
5
5
|
created: 2026-10-23
|
|
6
|
-
updated: 2026-10-
|
|
6
|
+
updated: 2026-10-25
|
|
7
7
|
affects: [INV-STO-3, INV-SRV-1, 07-tools-and-gate.md, 10-server-protocol.md, 11-terminal.md, 12-storage.md, 13-world-tools.md, 14-surfaces-and-parity.md]
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -41,7 +41,11 @@ grants, history }`, the format of the App store, so existing notes import unchan
|
|
|
41
41
|
- `source`: `{ url, title, capturedAt }` plus an optional opaque `surface` string from the capturing
|
|
42
42
|
front end.
|
|
43
43
|
- `target`: `page`, `text { exact, prefix, suffix, start, end }` (Unicode code points over
|
|
44
|
-
normalised page text), or `element { tag, role, name, text, context, selector }`.
|
|
44
|
+
normalised page text), or `element { tag, role, name, text, context, selector }`. Element capture
|
|
45
|
+
prefers role/name/text; when an otherwise empty visual element has no semantic label, it may use
|
|
46
|
+
a specific CSS selector (ID, test ID, classes, and a structural path when needed), never a bare
|
|
47
|
+
tag. Resolution uses that selector only when it identifies one allowed element and the captured
|
|
48
|
+
semantics/context still agree; stale or duplicate targets remain unresolved or ambiguous.
|
|
45
49
|
- `status`: `open` or `resolved`. `version` increases on every change; update and delete name the
|
|
46
50
|
version they expect (compare-and-swap). The last 100 change receipts are kept, without earlier
|
|
47
51
|
bodies. At most 10,000 notes.
|
|
@@ -51,7 +51,7 @@ A note gains an optional `delivery`:
|
|
|
51
51
|
- ⌘/Ctrl+Enter is Proceed now; with Shift it is queue.
|
|
52
52
|
- Everything is drawn in a closed shadow root.
|
|
53
53
|
- The page never receives the press or click on what is inspected, nor anything typed in the popover.
|
|
54
|
-
- Inputs, secrets, `[data-sensitive]` elements, frames, shadow roots and custom elements are never picked, as in PROP-0017.
|
|
54
|
+
- Inputs, secrets, `[data-sensitive]` elements, frames, shadow roots and custom elements are never picked, as in PROP-0017. (Open shadow roots and readable custom elements became pickable in [PROP-0038](PROP-0038-annotate-open-shadow-roots.md).)
|
|
55
55
|
- The inspector stays on after each comment.
|
|
56
56
|
- A new operation, `next`, returns `{ active, documentId, url, title, result }`, one comment at a time.
|
|
57
57
|
- `toast` shows a short status in the page.
|