@xingular/harness 1.2.0 → 1.3.1-unstable.1
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 +63 -0
- package/README.md +26 -17
- package/builtin/skills/plugin-authoring/SKILL.md +34 -0
- package/dist/cli.js +7362 -6239
- package/dist/sdk/agents/builtin.js +3 -3
- package/dist/sdk/agents/planResearch.d.ts +23 -1
- package/dist/sdk/agents/planResearch.js +71 -8
- package/dist/sdk/agents/profiles.d.ts +16 -4
- package/dist/sdk/agents/profiles.js +75 -12
- package/dist/sdk/annotations/bridge.d.ts +2 -0
- package/dist/sdk/annotations/bridge.js +4 -0
- package/dist/sdk/annotations/capture.d.ts +44 -2
- package/dist/sdk/annotations/capture.js +104 -3
- package/dist/sdk/annotations/delivery.d.ts +24 -17
- package/dist/sdk/annotations/delivery.js +82 -49
- package/dist/sdk/annotations/inspect.js +7 -6
- package/dist/sdk/annotations/pageScript.js +4 -4
- package/dist/sdk/annotations/part.d.ts +0 -2
- package/dist/sdk/annotations/part.js +4 -33
- package/dist/sdk/annotations/queue.d.ts +2 -2
- package/dist/sdk/annotations/queue.js +12 -7
- package/dist/sdk/annotations/serverMethods.js +11 -7
- package/dist/sdk/annotations/store.d.ts +13 -21
- package/dist/sdk/annotations/store.js +47 -37
- package/dist/sdk/capabilities/runSnapshot.js +10 -4
- package/dist/sdk/commands/list.js +2 -0
- package/dist/sdk/commands/registry.d.ts +11 -3
- package/dist/sdk/commands/registry.js +3 -2
- package/dist/sdk/core/links.d.ts +51 -0
- package/dist/sdk/core/links.js +155 -0
- package/dist/sdk/core/shell.d.ts +20 -0
- package/dist/sdk/core/shell.js +73 -0
- package/dist/sdk/core/workspaceBashTool.d.ts +17 -1
- package/dist/sdk/core/workspaceBashTool.js +16 -2
- package/dist/sdk/core/workspaceSandbox.d.ts +10 -0
- package/dist/sdk/core/workspaceSandbox.js +52 -12
- package/dist/sdk/core/workspaceWriteOperations.d.ts +11 -0
- package/dist/sdk/core/workspaceWriteOperations.js +26 -8
- package/dist/sdk/doctor/checks.js +71 -12
- package/dist/sdk/harness.d.ts +5 -0
- package/dist/sdk/harness.js +11 -6
- package/dist/sdk/hub/hub.js +5 -3
- package/dist/sdk/index.d.ts +3 -2
- package/dist/sdk/index.js +2 -1
- package/dist/sdk/plugins/builtin.js +14 -9
- package/dist/sdk/plugins/builtinRegistry.d.ts +3 -1
- package/dist/sdk/plugins/builtinRegistry.js +9 -3
- package/dist/sdk/plugins/discover.d.ts +7 -1
- package/dist/sdk/plugins/discover.js +41 -2
- package/dist/sdk/plugins/identity.js +1 -1
- package/dist/sdk/plugins/install.d.ts +6 -2
- package/dist/sdk/plugins/install.js +29 -5
- package/dist/sdk/plugins/inventory.js +3 -3
- package/dist/sdk/plugins/manifest.d.ts +2 -0
- package/dist/sdk/plugins/manifest.js +21 -4
- package/dist/sdk/plugins/plugins.d.ts +2 -0
- package/dist/sdk/plugins/plugins.js +1 -0
- package/dist/sdk/plugins/proposals.d.ts +17 -0
- package/dist/sdk/plugins/proposals.js +147 -0
- package/dist/sdk/plugins/types.d.ts +1 -1
- package/dist/sdk/plugins/types.js +1 -1
- package/dist/sdk/prompt/compile.d.ts +13 -4
- package/dist/sdk/prompt/compile.js +46 -20
- package/dist/sdk/prompt/standard.d.ts +1 -1
- package/dist/sdk/prompt/standard.js +1 -1
- package/dist/sdk/server/methods.js +14 -2
- package/dist/sdk/sessions/compactionCheckpoint.d.ts +3 -3
- package/dist/sdk/sessions/compactionCheckpoint.js +12 -12
- package/dist/sdk/sessions/continuation.d.ts +4 -2
- package/dist/sdk/sessions/continuation.js +7 -6
- package/dist/sdk/sessions/contracts.d.ts +22 -4
- package/dist/sdk/sessions/contracts.js +12 -7
- package/dist/sdk/sessions/planMode.js +2 -2
- package/dist/sdk/sessions/runStore.js +3 -1
- package/dist/sdk/sessions/runner.js +2 -2
- package/dist/sdk/sessions/sessionState.d.ts +13 -0
- package/dist/sdk/sessions/sessionState.js +31 -0
- package/dist/sdk/sessions/sessions.d.ts +7 -0
- package/dist/sdk/sessions/sessions.js +73 -15
- package/dist/sdk/sessions/subagentService.d.ts +15 -0
- package/dist/sdk/sessions/subagentService.js +195 -55
- package/dist/sdk/sessions/subagents.d.ts +10 -1
- package/dist/sdk/sessions/subagents.js +4 -0
- package/dist/sdk/sessions/workSlice.d.ts +8 -5
- package/dist/sdk/sessions/workSlice.js +77 -45
- package/dist/sdk/terminal/controller.d.ts +20 -0
- package/dist/sdk/terminal/controller.js +43 -18
- 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 +2 -0
- package/dist/sdk/terminal/opentui/theme.js +2 -0
- package/dist/sdk/terminal/piExtension.js +98 -15
- package/dist/sdk/terminal/subagentMonitor.d.ts +17 -4
- package/dist/sdk/terminal/subagentMonitor.js +29 -8
- package/dist/sdk/terminal/terminals.d.ts +16 -0
- package/dist/sdk/terminal/terminals.js +130 -26
- 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 +5 -1
- package/dist/sdk/terminal/tui/annotateCommand.js +21 -7
- package/dist/sdk/terminal/tui/annotateSend.d.ts +30 -0
- package/dist/sdk/terminal/tui/annotateSend.js +40 -0
- 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 +1 -1
- package/dist/sdk/terminal/tui/commandPages.js +16 -11
- package/dist/sdk/terminal/tui/commands.d.ts +4 -0
- package/dist/sdk/terminal/tui/commands.js +12 -2
- package/dist/sdk/terminal/tui/dialogs.js +1 -0
- package/dist/sdk/terminal/tui/pageOverlay.d.ts +3 -0
- package/dist/sdk/terminal/tui/pageOverlay.js +25 -7
- package/dist/sdk/terminal/tui/pages/agentsPage.js +5 -2
- package/dist/sdk/terminal/tui/pages/annotatePage.d.ts +70 -16
- package/dist/sdk/terminal/tui/pages/annotatePage.js +349 -115
- 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/pluginsPage.d.ts +14 -1
- package/dist/sdk/terminal/tui/pages/pluginsPage.js +295 -25
- package/dist/sdk/terminal/tui/pages/subagentsPage.js +8 -5
- package/dist/sdk/terminal/tui/pages/usagePage.d.ts +4 -2
- package/dist/sdk/terminal/tui/pages/usagePage.js +39 -12
- package/dist/sdk/terminal/tui/pluginCommands.d.ts +1 -1
- package/dist/sdk/terminal/tui/pluginCommands.js +13 -3
- package/dist/sdk/tools/defaultSkills.d.ts +4 -0
- package/dist/sdk/tools/defaultSkills.js +20 -0
- package/dist/sdk/tools/definitions.d.ts +3 -1
- package/dist/sdk/tools/definitions.js +17 -1
- package/dist/sdk/tools/dispatch.js +12 -0
- package/dist/sdk/tools/harnessTools.js +1 -1
- package/dist/sdk/tools/sessionName.d.ts +9 -0
- package/dist/sdk/tools/sessionName.js +58 -11
- package/dist/sdk/tools/spawnSubagent.js +9 -7
- package/dist/sdk/tools/todo.d.ts +15 -0
- package/dist/sdk/tools/todo.js +64 -0
- package/dist/sdk/world/world.d.ts +0 -2
- package/dist/terminal-opentui.js +3331 -1584
- package/dist/terminal-pi.js +421 -133
- package/docs/README.md +3 -0
- 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 +73 -36
- package/docs/architecture/03-variants.md +1 -3
- package/docs/architecture/04-prompt.md +24 -13
- package/docs/architecture/06-plugins-and-capabilities.md +46 -10
- package/docs/architecture/07-tools-and-gate.md +49 -8
- package/docs/architecture/09-accounts-and-connectors.md +8 -2
- package/docs/architecture/10-server-protocol.md +68 -16
- package/docs/architecture/11-terminal.md +94 -45
- package/docs/architecture/12-storage.md +1 -0
- package/docs/architecture/13-world-tools.md +8 -6
- package/docs/architecture/14-surfaces-and-parity.md +4 -1
- package/docs/architecture/README.md +20 -18
- package/docs/architecture/proposals/PROP-0006-run-checklist.md +2 -0
- package/docs/architecture/proposals/PROP-0018-annotation-queue-and-app-targets.md +6 -2
- package/docs/architecture/proposals/PROP-0041-bounded-work-slices.md +32 -21
- 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/PROP-0048-simple-annotate.md +85 -0
- package/docs/architecture/proposals/README.md +11 -6
- 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/decisions/ADR-0044-annotations-pending-or-sent.md +24 -0
- package/docs/decisions/ADR-0045-default-plugin-authoring-skill.md +9 -0
- package/docs/decisions/ADR-0046-hash-bound-plugin-proposals.md +20 -0
- package/docs/decisions/ADR-0047-links-open-with-the-os-handler.md +47 -0
- package/docs/doctor.md +14 -1
- package/docs/parity.md +16 -13
- package/docs/releases/1.3.0.md +21 -0
- package/docs/releases/1.3.1-unstable.1.md +8 -0
- package/docs/releases/README.md +9 -6
- package/docs/terminal-tui.md +127 -65
- package/package.json +1 -1
- package/dist/sdk/terminal/tui/pages/notesPage.d.ts +0 -75
- package/dist/sdk/terminal/tui/pages/notesPage.js +0 -201
- package/dist/sdk/tools/checklist.d.ts +0 -9
- package/dist/sdk/tools/checklist.js +0 -55
|
@@ -40,7 +40,9 @@ harness → host { v: 1, id, call, params } host → harness { v: 1
|
|
|
40
40
|
`plugins.describe`.
|
|
41
41
|
- `refine.start` takes `{ task, k?, mode?, improver?, executor?, baseVersion?, retainWorkspaces?, id? }`;
|
|
42
42
|
`refine.candidates` returns each execution with `workspace: string | null` (page 05, PROP-0002, PROP-0003).
|
|
43
|
-
- `runs.
|
|
43
|
+
- `runs.todo { runId }` returns the run's latest todo list, `[]` when it wrote none (PROP-0006,
|
|
44
|
+
renamed by PROP-0045). `runs.checklist` is the deprecated pre-rename alias.
|
|
45
|
+
- `runs.continuation` returns `todo`; `checklist` remains a deprecated mirror of it for one release.
|
|
44
46
|
- Run records include optional nullable `workspaceRoot`, the canonical root whose files a run may
|
|
45
47
|
modify by default (page 02). New Harness runs set it; older records may omit it. Hosts must
|
|
46
48
|
tolerate the additive field and must not nominate or widen the root.
|
|
@@ -49,15 +51,18 @@ harness → host { v: 1, id, call, params } host → harness { v: 1
|
|
|
49
51
|
and refuses an existing file; `agents.remove { cwd?, name, scope }` deletes a person's own file.
|
|
50
52
|
`subagents.spawn` takes `agent` as a profile name and returns `agent` and `unavailableTools`
|
|
51
53
|
(PROP-0029). It takes an optional `title` (at most six words); without one the child's title is
|
|
52
|
-
the first line of its brief (PROP-0030).
|
|
54
|
+
the first line of its brief (PROP-0030). With `continue: <runId>` it continues a stopped child of
|
|
55
|
+
this conversation instead (no `agent` or `tools`; `brief` and `title` optional) and returns
|
|
56
|
+
`continued`, the run it continued (ADR-0043).
|
|
53
57
|
- `runs.continuation { runId, sessionDir? }` returns a `Continuation` (its `checkpoint` is the last
|
|
54
58
|
work-slice handoff), and `sessions.run` accepts `continueFrom` (page 02, PROP-0007) and `workSlice`
|
|
55
59
|
(PROP-0041). `harness.status` reports `recovery.interruptedRunIds`.
|
|
56
60
|
- `workSlice { enabled?, maxToolCalls?, maxMinutes?, maxNewTokens?, maxSlices?, continue? }` on
|
|
57
|
-
`sessions.run` bounds that reply; absent uses
|
|
58
|
-
automatic continuation. A token cap counts new input, cache writes and output, never the
|
|
59
|
-
prefix. `enabled: false` turns the guard off for that run;
|
|
60
|
-
launching process turns it off for every run in it, and nothing is
|
|
61
|
+
`sessions.run` bounds that reply; absent uses 320 calls, 60 minutes, no new-token cap, 8 slices and
|
|
62
|
+
automatic continuation. A token cap, when set, counts new input, cache writes and output, never the
|
|
63
|
+
cached prefix (PROP-0044). `enabled: false` turns the guard off for that run;
|
|
64
|
+
`XINGULAR_WORK_SLICE=off` in the launching process turns it off for every run in it, and nothing is
|
|
65
|
+
persisted. The policy is
|
|
61
66
|
carried into the continuation. A value outside its range is refused with `invalid_request` before
|
|
62
67
|
the run record is written.
|
|
63
68
|
- The run-event stream adds `checkpoint` (the bounded handoff) and `heartbeat` (steps, elapsed time,
|
|
@@ -65,6 +70,24 @@ harness → host { v: 1, id, call, params } host → harness { v: 1
|
|
|
65
70
|
relayed in order (INV-RUN-3).
|
|
66
71
|
- Errors carry a stable `code`, a message and an optional hint (`core/errors.ts`).
|
|
67
72
|
|
|
73
|
+
## Plugin proposals
|
|
74
|
+
|
|
75
|
+
| Method | Input | Reply |
|
|
76
|
+
|---|---|---|
|
|
77
|
+
| `plugins.proposals.create` | `{ name, description, files }` (path-to-text object) | pending `Proposal` |
|
|
78
|
+
| `plugins.proposals.list` | `{}` | `Proposal[]`, including decided records |
|
|
79
|
+
| `plugins.proposals.preview` | `{ id }` | revalidated `Proposal` with current content hash |
|
|
80
|
+
| `plugins.proposals.accept` | `{ id, hash }` | accepted `Proposal` |
|
|
81
|
+
| `plugins.proposals.reject` | `{ id, hash }` | rejected `Proposal` |
|
|
82
|
+
|
|
83
|
+
A `Proposal` has `id`, `name`, `description`, `files`, generated `manifest`, `hash`, `createdAt`,
|
|
84
|
+
`status` and optional `decidedAt`. Both decisions require the pending proposal's current preview
|
|
85
|
+
hash; acceptance installs it switched off without trusting code. These methods expose trusted host
|
|
86
|
+
operations, not an assertion that a host has built a review UI. Protected terminal control routes
|
|
87
|
+
`plugins.proposals.list|preview|accept|reject` delegate to the same service when configured; they
|
|
88
|
+
require the terminal control key. The model tool can create only. Validation and trust details are
|
|
89
|
+
on page 06.
|
|
90
|
+
|
|
68
91
|
## Usage (PROP-0042)
|
|
69
92
|
|
|
70
93
|
| Method | Input | Reply |
|
|
@@ -183,11 +206,14 @@ from preparation, never from the request.
|
|
|
183
206
|
| `terminal.browser.connections.save` | `{ input: ConnectionInput }` | Existing safe `Connection` record |
|
|
184
207
|
| `terminal.browser.connections.test\|signIn\|signOut\|remove` | `{ id }` | Existing connection service result |
|
|
185
208
|
| `terminal.usage.summary\|limits` | `{ scope, period, timezoneOffsetMinutes }` / `{ refresh? }` | Existing usage service result, scoped to this terminal's account and project |
|
|
209
|
+
| `terminal.usage.allLimits` | `{ refresh? }` | All-account provider limits; refresh reads providers due under the configured cache interval, without changing the pinned account |
|
|
186
210
|
| `terminal.usage.headers` | `{ provider, status, headers }` | `{}`; only limit-bearing headers, throttled, stored as an account limit reading |
|
|
187
211
|
|
|
188
|
-
Protected `plugins.install { source }
|
|
189
|
-
|
|
190
|
-
|
|
212
|
+
Protected `plugins.install { source }`, `plugins.update { pluginId? }` and
|
|
213
|
+
`plugins.remove { pluginId }` delegate to the package service. Removing a Hub-owned package routes
|
|
214
|
+
through Hub's receipt-aware uninstall; a floating update refuses Hub-owned packages, while an
|
|
215
|
+
update-all skips them. Optional matching callbacks extend `PluginControl`; hosts without them
|
|
216
|
+
receive a clear unsupported-operation error. No protocol version or persisted schema changes.
|
|
191
217
|
|
|
192
218
|
## Worktrees (PROP-0016)
|
|
193
219
|
|
|
@@ -224,14 +250,18 @@ same service through `terminal.worktrees.*` routes, which need the control key (
|
|
|
224
250
|
| `annotations.revokeBinding` | `{ binding }` | `{ revoked }` |
|
|
225
251
|
| `annotations.import` | `{ notes }` | `{ imported, skipped }` (ids kept) |
|
|
226
252
|
| `annotations.pageScript` | `{}` | `{ script }`: the page helper, with `__ARGS__` for one operation |
|
|
227
|
-
| `annotations.
|
|
228
|
-
| `annotations.
|
|
229
|
-
| `annotations.
|
|
230
|
-
| `annotations.
|
|
231
|
-
| `annotations.
|
|
253
|
+
| `annotations.markPending` | `{ id, sessionId, expectedVersion? }` | `Note`, shared with the session and unsent (PROP-0018, PROP-0048) |
|
|
254
|
+
| `annotations.confirm` | `{ id, expectedVersion? }` | `Note` |
|
|
255
|
+
| `annotations.confirmAll` | `{ sessionId }` | `{ notes }`: every page-origin note of the session, confirmed |
|
|
256
|
+
| `annotations.pending` | `{ sessionId }` | `{ notes }`, unsent, oldest first |
|
|
257
|
+
| `annotations.clear` | `{ sessionId }` | `{ notes }`: the session's unsent notes, resolved and no longer shared with it |
|
|
258
|
+
| `annotations.createAndAct` | `{ note, action: save \| send, sessionId?, trusted? }` | `{ note, send }`; with a session the note is always shared; `send` sends all unsent notes; an untrusted note waits for `confirm` |
|
|
259
|
+
| `annotations.compose` | `{ sessionId, ids?, prompt? }` | `{ text, ids }`: one message for a host's own `sessions.run`, with the person's request last |
|
|
232
260
|
| `annotations.delivered` | `{ ids, sessionId, runId }` | `{ notes }`, marked sent |
|
|
233
|
-
| `annotations.send` | `{ sessionId, ids? }` | `{ state: sent \| busy \| host \| empty,
|
|
261
|
+
| `annotations.send` | `{ sessionId, ids?, prompt? }` | `{ state: sent \| busy \| host \| empty, …; empty has unconfirmed }` |
|
|
234
262
|
| `annotations.capture.attach` | `{ key, kind: web \| cdp \| bridge, endpoint?, name? }` | `{ kind, app, windows, bridge? }` |
|
|
263
|
+
| `annotations.capture.discover` | `{}` | `{ apps: [{ endpoint, port, name, browser, electron, windows }] }`: apps on a loopback DevTools port |
|
|
264
|
+
| `annotations.capture.launch` | `{ key, path, args? }` | `{ kind: cdp, app, windows, endpoint }`: starts the app with a DevTools port and attaches |
|
|
235
265
|
| `annotations.capture.target` | `{ key }` | `{ kind, app, inspecting, windows }` |
|
|
236
266
|
| `annotations.capture.selectWindow` | `{ key, window }` | `{}` |
|
|
237
267
|
| `annotations.capture.open` | `{ key, url? }` | `{ url, title }` |
|
|
@@ -240,9 +270,31 @@ same service through `terminal.worktrees.*` routes, which need the control key (
|
|
|
240
270
|
| `annotations.capture.release` | `{ key }` | `{}` |
|
|
241
271
|
| `annotations.bridge.start` | `{}` | `{ port, token, scriptUrl, snippet }` |
|
|
242
272
|
|
|
243
|
-
Notices: `annotations.changed { sessionId, ids }` after any
|
|
273
|
+
Notices: `annotations.changed { sessionId, ids }` after any share, send or clear;
|
|
244
274
|
`annotations.ready { sessionId, ids }` when a host session's waiting notes should be sent now.
|
|
245
275
|
|
|
246
276
|
Errors: `version_conflict`, `not_found`, `annotation_limit`, `invalid_request`, `invalid_data`. The
|
|
247
277
|
terminal reaches the same store through `terminal.annotations.*`, which shares only with its own
|
|
248
278
|
session and needs the control key (`INV-TUI-4`).
|
|
279
|
+
|
|
280
|
+
## Links (ADR-0047)
|
|
281
|
+
|
|
282
|
+
A link a person clicks is a person's action, not a model tool call: nothing here is in
|
|
283
|
+
`HARNESS_TOOLS`, so the gate, standing approvals and redaction never see it. `core/links.ts` holds
|
|
284
|
+
the one allowlist both front ends use, and `openLink` is the only door into the operating system.
|
|
285
|
+
|
|
286
|
+
| Method | Input | Reply |
|
|
287
|
+
|---|---|---|
|
|
288
|
+
| `links.open` | `{ target, base? }` | `OpenedTarget`: `{ kind: "web", url }`, `{ kind: "mail", address }`, `{ kind: "file", path }` or `{ kind: "directory", path }` |
|
|
289
|
+
|
|
290
|
+
`target` is what the link says; `base` is the absolute folder a relative target is resolved
|
|
291
|
+
against, and without it a relative target is refused. `linkTarget` classifies without touching the
|
|
292
|
+
filesystem (`http`/`https`, `mailto`, `file`, an absolute path, or a relative path under `base`),
|
|
293
|
+
and `openableTarget` then checks what it names: a regular file or a directory, never an application
|
|
294
|
+
bundle, an installer, or a launchable script, and never a file with an executable bit set, because
|
|
295
|
+
`xdg-open` runs one. The address is passed to `open`/`xdg-open`/`rundll32` as one argument, never
|
|
296
|
+
through a shell.
|
|
297
|
+
|
|
298
|
+
Errors: `link_not_openable`, with a message a person can read, and `invalid_request` when `target`
|
|
299
|
+
is missing. The opener is `HarnessOptions.linkOpener`, so a host with its own native opener keeps
|
|
300
|
+
the policy and replaces only the spawn.
|
|
@@ -43,7 +43,7 @@ Screen: transcript above the composer, centred dialogs, full-screen resource bro
|
|
|
43
43
|
per-tool grants do not widen it, and command output never triggers approval or replay.
|
|
44
44
|
- The terminal compiles its prompt once (`compile` + `render`) and keeps that pack; each run
|
|
45
45
|
records a copy (page 04). The shared compaction checkpoint extension reintroduces the active
|
|
46
|
-
request and latest
|
|
46
|
+
request and latest todo list into post-compaction model context until the run settles.
|
|
47
47
|
- Normal mode keeps `ask_user` out of the active tool set. An attended plan request enables the
|
|
48
48
|
shared tool alongside its read-only set and restores the normal set on success, failure or
|
|
49
49
|
interruption. There is no terminal-only question alias (PROP-0040).
|
|
@@ -77,14 +77,18 @@ Screen: transcript above the composer, centred dialogs, full-screen resource bro
|
|
|
77
77
|
leaves the main conversation untouched. The dock streams, scrolls and copies the complete answer.
|
|
78
78
|
Aliases remain callable and searchable, but help and palette show only the canonical
|
|
79
79
|
entry. `/usage:` and `/usage:analysis` open the usage page's Analysis tab, and `/usage:limit`
|
|
80
|
-
opens its Limits tab (PROP-0042);
|
|
81
|
-
|
|
80
|
+
opens its Limits tab (PROP-0042); `/usage:accounts` opens the All accounts limits tab. These are plugin-owned namespaced routes. All-account refresh reads due providers using their own account credentials without switching the session account. The usage page is a
|
|
81
|
+
full-screen page with a top tab strip: each window is a label and reset line above a quota-left bar coloured green at
|
|
82
82
|
50% or more left, amber from 20–49%, and red below 20%. `commands.list`
|
|
83
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
84
|
independently of plugin command metadata. Every plugin-owned command uses
|
|
85
85
|
`/<owner-prefix>:<command>`; the namespace root is offered only by plugins that declare a default
|
|
86
86
|
command. Prompt templates and `/skill:<name>` keep their existing forms.
|
|
87
87
|
|
|
88
|
+
The `/plugins` Proposals tab previews the complete stored files and generated manifest before
|
|
89
|
+
confirmation. Accept and reject pass the preview hash through the control-key-protected socket;
|
|
90
|
+
the proposal service checks it again. Acceptance leaves the package switched off and untrusted.
|
|
91
|
+
|
|
88
92
|
## Invariants
|
|
89
93
|
|
|
90
94
|
- **INV-TUI-1** OpenTUI is the only terminal frontend. Pi's `InteractiveMode` is never constructed
|
|
@@ -96,7 +100,7 @@ Screen: transcript above the composer, centred dialogs, full-screen resource bro
|
|
|
96
100
|
their existing layers. The terminal adds no second path for any of them; its runs are written
|
|
97
101
|
through the controller and the run store.
|
|
98
102
|
- **INV-TUI-4** Changes made through the session socket (`plugins.attach|detach|trust|untrust|configure`,
|
|
99
|
-
`accounts.*`, Hub installs, `terminal.browser.*`, `terminal.worktrees.*`,
|
|
103
|
+
`plugins.proposals.*`, `accounts.*`, Hub installs, `terminal.browser.*`, `terminal.worktrees.*`,
|
|
100
104
|
`terminal.annotations.*`, `terminal.sideQuestions.*`) require the control key the trusted terminal process claimed once
|
|
101
105
|
(`control.claim`). The session's shell can read the session token, so the token alone is never
|
|
102
106
|
enough.
|
|
@@ -144,6 +148,13 @@ The native `session_info_changed` event invalidates the frontend's cached snapsh
|
|
|
144
148
|
refreshes the working line. Both the active and retained completion line append
|
|
145
149
|
` – <name>` after duration and token rate, for example
|
|
146
150
|
`Working (2m, 50 tok/s) – Add web browser integrations`. Unnamed sessions omit the suffix.
|
|
151
|
+
A substantive first turn also receives a provisional name through the terminal policy; a refused
|
|
152
|
+
or failed name leaves the session unnamed.
|
|
153
|
+
|
|
154
|
+
Each user turn appends a hidden `xingular-session-state` custom message with the current name,
|
|
155
|
+
this run's empty todo, and the previous run's todo as context. The message is request-only and
|
|
156
|
+
never changes the compiled stable pack. A first turn is marked as such; later turns say the todo
|
|
157
|
+
list resets for each run.
|
|
147
158
|
Names use the existing terminal text sanitization, remain outside the verb shimmer, and
|
|
148
159
|
truncate at the right edge. Manual `/name` and existing long names remain supported.
|
|
149
160
|
|
|
@@ -156,19 +167,29 @@ on close. No command text is sent to the conversation model. See [Doctor](../doc
|
|
|
156
167
|
|
|
157
168
|
## Resource browser (PROP-0013)
|
|
158
169
|
|
|
159
|
-
`/harness` owns
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
170
|
+
`/harness` owns broad navigation for Foundation, Variant, Skills, Plugins, Connections, Tools and
|
|
171
|
+
Library. `/skills`, `/connections` (`/mcp`), `/tools` and `/components` are shortcuts into that
|
|
172
|
+
browser. `/plugins` opens the focused local plugin manager (Plugins, Trust and Packages tabs); `/hub`
|
|
173
|
+
opens the separate Community catalog (Catalog and Installed tabs). The Hub Catalog shows Community
|
|
174
|
+
entries across supported types; Installed retains receipts from every channel with its channel
|
|
175
|
+
visible. Registry/document entries offer bounded payload Preview; Pi packages do not. Current
|
|
176
|
+
availability in `/harness` comes from the live resource loader and active tool registry,
|
|
177
|
+
independently of saved configuration and the latest variant head.
|
|
163
178
|
|
|
164
179
|
Every `terminal.browser.*` call requires the private control key, including bounded resource
|
|
165
|
-
inspection, local imports, connection management and browser settings.
|
|
166
|
-
|
|
167
|
-
|
|
180
|
+
inspection, local imports, connection management and browser settings. Direct plugin package
|
|
181
|
+
install/update/remove and attachment/trust/settings actions use protected `plugins.*`; Hub catalog
|
|
182
|
+
list/install/uninstall use protected `hub.*`. Hub-owned package removal keeps the receipt and
|
|
183
|
+
resource ownership in the Hub service. These routes are adapters to the existing services, not
|
|
184
|
+
another loader, attachment store, gate or secret store. Browsing neither executes plugin code nor
|
|
185
|
+
connects MCP.
|
|
168
186
|
The browser uses the full terminal with persistent section tabs (PROP-0014); wide screens keep
|
|
169
187
|
inventory beside details, actions and content, while compact screens keep inline details under
|
|
170
|
-
the same tabs.
|
|
171
|
-
|
|
188
|
+
the same tabs. The separate `/plugins` and `/hub` pages also use full-screen layouts with persistent
|
|
189
|
+
section tabs, responsive inventory/details panes and their existing protected operations. Other
|
|
190
|
+
command pages remain centered except `/settings`, `/accounts`, `/plugins`, `/hub` and `/usage:`, which use
|
|
191
|
+
full-screen page layouts.
|
|
192
|
+
Accounts keeps Accounts/Pools tabs, search and account-service operations.
|
|
172
193
|
Wide terminals show selected-account details beside the list; Enter or a primary click opens grouped
|
|
173
194
|
actions in that inspector. Compact terminals replace the list with a full-page account detail view
|
|
174
195
|
and its grouped actions. Enter opens the selected account; Escape returns to the list while
|
|
@@ -243,39 +264,56 @@ contract is unchanged. See [PROP-0025](proposals/PROP-0025-contextual-question-w
|
|
|
243
264
|
PTY verification is retained in `docs/evidence/terminal-wireframe-normalization/`; it establishes
|
|
244
265
|
cell topology for bounded fixtures, not every emulator/font or live-model sketch quality.
|
|
245
266
|
|
|
246
|
-
## Web annotations commands (PROP-0017)
|
|
267
|
+
## Web annotations commands (PROP-0017, PROP-0018, PROP-0048)
|
|
247
268
|
|
|
248
|
-
`/annotate
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
and `page_notes_read`.
|
|
269
|
+
`/annotate:` opens the annotate page, a full-screen page with two tabs. `/annotate:notes` opens it on
|
|
270
|
+
**All annotations**: every annotation in the data root, with search, and reveal, edit, resolve or
|
|
271
|
+
reopen, share with this session or stop sharing, and delete. An annotation is private until shared;
|
|
272
|
+
this session's agent then reads it with `page_notes_list` and `page_notes_read`.
|
|
253
273
|
|
|
254
|
-
The
|
|
274
|
+
The **Annotate** tab is the panel beside the window being inspected.
|
|
255
275
|
|
|
256
276
|
- **Ways to start it:**
|
|
257
|
-
- `/annotate
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
-
|
|
261
|
-
|
|
262
|
-
-
|
|
263
|
-
- **
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
277
|
+
- `/annotate: [url]`: the capture browser (its own window and profile, separate from the agent's
|
|
278
|
+
browser). With no address, the page returns to the window that is still open, with its URL and
|
|
279
|
+
the inspector on, and asks for one in its own inline field only when no window is open.
|
|
280
|
+
- `/annotate: --app [port | address] [name]`: an app's own windows over its DevTools port. With no
|
|
281
|
+
port, the page lists the apps answering on one (`annotations.capture.discover`).
|
|
282
|
+
- `/annotate: --bridge [name]`: app windows that load the page bridge script, which the page shows.
|
|
283
|
+
- **The inspector** (`i`) outlines components on hover. A click or a text drag opens a popover in
|
|
284
|
+
the page with **Annotate** and **Annotate & send**. Every annotation is shared with this session
|
|
285
|
+
at once.
|
|
286
|
+
- **Groups:** Unsent (n) and Sent, for this session.
|
|
287
|
+
- **Other keys:** `s` sends every unsent annotation as one run of this session, confirming the
|
|
288
|
+
page-origin ones once first; `o` types a page address; `a` lists apps with a DevTools port, with
|
|
289
|
+
*Start an app with a DevTools port*, *Type a DevTools port*, *Use the page bridge*; `t` picks a
|
|
290
|
+
window; `Tab` switches tab. A key pressed while the page is busy gets a notice, never nothing.
|
|
291
|
+
- **Commands:** `/annotate:submit <request>` sends the unsent annotations with the request after
|
|
292
|
+
them; `/annotate:clear` resolves the unsent ones and stops sharing them.
|
|
293
|
+
- **Routes:** `terminal.annotations.target|attach|windows|selectWindow|inspect|stopInspect|next|confirm|confirmAll|send|clear|discover|launch`
|
|
294
|
+
act only on this terminal's session and need the control key.
|
|
295
|
+
|
|
296
|
+
A page that opens a dialog as it starts gets it above itself: `PageOverlay` starts its page when the
|
|
297
|
+
host reports the overlay mounted.
|
|
298
|
+
|
|
299
|
+
## Todo list (PROP-0006, PROP-0045, PAR-001)
|
|
300
|
+
|
|
301
|
+
Terminal sessions register the shared `todo_write` tool. The extension validates each list with
|
|
302
|
+
the same tool code and sends it as `todo` telemetry; the controller emits it as `todo.updated` on the
|
|
303
|
+
active run, so `runs.todo` and continuation read terminal runs too. The gate treats it as read-only,
|
|
304
|
+
plan mode allows it, and terminal children inherit it. The transcript shows each write as a todo
|
|
305
|
+
block (`✓` done, `●` in progress (warning yellow), `○` pending) under a `Todo · n of m done` header
|
|
306
|
+
instead of a tool row; a failed or malformed call stays a tool row. `/todo` reads the latest
|
|
307
|
+
non-side-question run of this terminal's native session and appends the same card as a snapshot,
|
|
308
|
+
without a model request; an empty list is a one-line notice. `/checklist` remains its alias for one
|
|
309
|
+
release.
|
|
273
310
|
|
|
274
311
|
## Work-slice checkpoint (PROP-0041)
|
|
275
312
|
|
|
276
|
-
Terminal replies carry the same work-slice guard as structured runs:
|
|
277
|
-
|
|
278
|
-
tool and sends it as `checkpoint` telemetry, which the controller
|
|
313
|
+
Terminal replies carry the same work-slice guard as structured runs: 320 tool calls or 60 minutes,
|
|
314
|
+
with no new-token limit by default (PROP-0044), then a refusal that asks for `checkpoint_write`. The
|
|
315
|
+
extension registers the shared tool and sends it as `checkpoint` telemetry, which the controller
|
|
316
|
+
records as `checkpoint` on the
|
|
279
317
|
active run, so an App reading the same session sees the handoff. Terminal replies are not
|
|
280
318
|
auto-continued: at the boundary the person decides, which is what the terminal's own turn model
|
|
281
319
|
already does. The run record says `interrupted` with terminal reason `slice_complete` (or `stalled`
|
|
@@ -288,13 +326,13 @@ boundary at all; it is not persisted, so the next launch without it restores the
|
|
|
288
326
|
During an active parent run, the terminal polls a private read-only monitor once per second. It
|
|
289
327
|
projects the flat set of child and nested-child runs with task, status, elapsed time, the latest
|
|
290
328
|
tool name, the child's agent profile (name and colour, PROP-0029), the title the parent gave it
|
|
291
|
-
(PROP-0030), counts from the child's own
|
|
329
|
+
(PROP-0030), counts from the child's own todo list, the pinned account label, effective model and
|
|
292
330
|
effort, and cumulative usage totals. Model and effort come from the volatile launch selection; the
|
|
293
331
|
latest provider-reported model supersedes the launch model when usage is available. Usage is an
|
|
294
332
|
explicit projection of token, cache, cost, request-count and context-window totals. Per-request
|
|
295
333
|
payloads and reasoning summaries do not enter the monitor. The child's own `session_name` is not
|
|
296
334
|
projected; it names the child's session, not its row. Tool summaries, other arguments, output and
|
|
297
|
-
|
|
335
|
+
todo item text never enter the monitor. The latest completed tool name remains visible across
|
|
298
336
|
one-second snapshots until new tool or response activity replaces it. The monitor exposes no
|
|
299
337
|
controls to steer or stop children.
|
|
300
338
|
|
|
@@ -302,15 +340,26 @@ The live rows sit under the status line, after one blank row, with no heading. E
|
|
|
302
340
|
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,
|
|
303
341
|
`✓` done, `✕` failed, `!` stopped), the profile name in its colour (`subagent`, muted, for a copy
|
|
304
342
|
of the parent), the title the parent gave the child (PROP-0030), and `n of m tasks` when the child
|
|
305
|
-
keeps a
|
|
343
|
+
keeps a todo list. Active rows come first, at most three, then `+N more · /subagents`; a narrow
|
|
306
344
|
terminal cuts the title first. `/subagents` opens the searchable full roster, with a colored
|
|
307
345
|
profile and normal-color title on its first line, then muted account, model, effort and usage
|
|
308
346
|
metadata on its second line. One blank row separates each two-line entry. Narrow rows truncate this
|
|
309
347
|
lower-priority summary without hiding the title.
|
|
310
348
|
At parent settlement, the terminal makes a final monitor read and keeps the latest parent's rows
|
|
311
|
-
visible until the next parent run starts.
|
|
312
|
-
|
|
313
|
-
|
|
349
|
+
visible until the next parent run starts.
|
|
350
|
+
|
|
351
|
+
The monitor also projects the parent run itself as a `main` row (profile `main`, a reserved name,
|
|
352
|
+
in the theme's primary colour) with the same account, model, effort, usage, activity and todo
|
|
353
|
+
fields. The `/subagents` page pins it first and counts only children in its header; the rows under
|
|
354
|
+
the status line omit it, since the status line already describes the main agent.
|
|
355
|
+
|
|
356
|
+
Every turn marks its run on the native branch (`xingular-subagent-owner`), and `ready` sends those
|
|
357
|
+
owners. When a conversation opens or is switched to with no run active, the monitor is rebuilt from
|
|
358
|
+
the branch's latest top-level run in this folder and its descendants, by folding their saved events
|
|
359
|
+
with their final status. Runs a stopped process left active were already marked `interrupted`.
|
|
360
|
+
The rows show under the status line and on the page until the next parent run starts (ADR-0043).
|
|
361
|
+
The projection remains read-only and scoped to one parent run; a switch to a conversation with no
|
|
362
|
+
such run clears it, as does terminal disposal. It is not a persisted event or public server method.
|
|
314
363
|
|
|
315
364
|
## Agent profiles (PROP-0029)
|
|
316
365
|
|
|
@@ -23,6 +23,7 @@ index.
|
|
|
23
23
|
legacy/ an earlier Wiki's data, moved once (08)
|
|
24
24
|
registry/ skills/, prompts/, rules/: the component library (03)
|
|
25
25
|
plugins/<name>/ packages kept with the data (06)
|
|
26
|
+
plugin-proposals/<id>.json pending and decided proposal text, hash and status; owned by plugins/proposals.ts (06)
|
|
26
27
|
trash/plugins/ removed packages (06)
|
|
27
28
|
hub/ installed documents and provenance (09)
|
|
28
29
|
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)
|
|
@@ -48,19 +48,21 @@ it. A tool returns only notes a person shared with the calling session or agent;
|
|
|
48
48
|
and element names are marked untrusted. Capture happens in a visible capture browser in the
|
|
49
49
|
terminal, or in a host's own web view running the same page helper (`annotations.pageScript`).
|
|
50
50
|
|
|
51
|
-
**Inspector,
|
|
51
|
+
**Inspector, sending and app targets (PROP-0018, PROP-0048).**
|
|
52
52
|
|
|
53
|
-
- **Inspector.** In the page helper's inspector, hovering outlines a component and a click (or a drag over text) opens a comment popover inside the page, with
|
|
54
|
-
-
|
|
55
|
-
- `annotations/delivery.ts` sends
|
|
56
|
-
|
|
53
|
+
- **Inspector.** In the page helper's inspector, hovering outlines a component and a click (or a drag over text) opens a comment popover inside the page, with two choices: Annotate and Annotate & send.
|
|
54
|
+
- With a session, every note is shared with it at once and is pending (unsent) until sent.
|
|
55
|
+
- `annotations/delivery.ts` sends all of a session's pending notes as one message, with the
|
|
56
|
+
person's request last when given, and sends notes held back while the session was busy when its
|
|
57
|
+
run ends, trying again while the session still answers busy.
|
|
58
|
+
- The page-note tools are read-only. Only the person resolves a note.
|
|
57
59
|
- **Targets.** Element targets prefer semantic role/name/text. A visually empty element may still be
|
|
58
60
|
annotated when it has a specific CSS selector (ID, test ID, classes, and a structural path when
|
|
59
61
|
needed); bare tag selectors are not enough. Reveal checks for one live match and preserves any
|
|
60
62
|
captured semantic/context evidence, otherwise reporting ambiguous or unresolved. Text annotations
|
|
61
63
|
continue to use quote plus context, not screen coordinates.
|
|
62
64
|
- Besides the browser window, capture can use an app's own windows:
|
|
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.
|
|
65
|
+
- **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. `discover` probes loopback ports 9222–9230 and ports used before (a Node inspector is skipped); `launchApp` starts a program (the one inside a macOS `.app`) with `--remote-debugging-port` on a free loopback port and attaches. A started app keeps running.
|
|
64
66
|
- **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
67
|
- **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.
|
|
66
68
|
- **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 |
|
|
@@ -29,6 +29,9 @@ terminal command or page, a host screen.
|
|
|
29
29
|
tool that passes the gate (page 07). Both front ends use the same methods; neither has a private
|
|
30
30
|
path to Harness state. Foundation context behavior, including bounded checkpoint restoration after
|
|
31
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.
|
|
32
35
|
- Workspace write scope is Harness-owned on both surfaces. Each run pins a canonical root after
|
|
33
36
|
worktree selection; reads retain OS-permission scope, while native file writes and shell
|
|
34
37
|
filesystem effects default to that root; the filesystem root itself is not a valid workspace.
|
|
@@ -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,29 +87,29 @@ 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
|
|---|---|---|
|
|
110
111
|
| D-1 | `AGENTS.md` (before this spec), `INV-RUN-6` | The old rule said only `sessions/runStore.ts` writes `runs/<id>/`. In code, four other harness modules also write side files there: `prompt/compile.ts` (`context.json`), `sessions/sessions.ts` (`caller.json`), `capabilities/runSnapshot.ts` (`capabilities.json`), `mcp/service.ts` (`mcp-context.json`). The spec states the rule the code keeps (see `INV-RUN-6`); whether to route all of them through `runStore.ts` is open. |
|
|
111
|
-
| D-2 |
|
|
112
|
+
| D-2 | Plugin proposal review surfaces | `plugin_propose` and hash-bound proposal APIs now exist; a terminal review UI is pending and no App review UI is claimed. See [PAR-017](../parity.md#gaps). |
|
|
112
113
|
| D-3 | `README.md` "External curation" | Describes `externalMaintenance`, `vaultAccess`, `MAINTENANCE_PLUGIN`, `maintenance.*` methods and tools. None exist in `src/`. |
|
|
113
114
|
| D-4 | `INV-BND-2` | Several names carry an application's name: the context message type `xingular-context`, the approval extension `xagent-approvals`, the MCP client name `xagent`, and the terminal commands `xagent-wiki` / `xagent-mcp`. The default product name `Xingular Agent` is allowed; these are not. |
|
|
114
115
|
| D-5 | `INV-BND-2` | `RunRecord` carries `worktreeId` and `handoffId`, which are application concepts. They are stored and returned, never read, and are documented as the application's fields. Since PROP-0016 (2026-10-23) `worktreeId` has Harness meaning when it names a registered worktree; only `handoffId` remains an application field. |
|
|
@@ -124,4 +125,5 @@ proposal, or a correction to the other document).
|
|
|
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. |
|
|
126
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-19 | Provider limits layout | Page 09 describes a centered Limits dialog; page 11 and `src/terminal/tui/pages/usagePage.ts` describe and implement a full-screen page. |
|
|
127
129
|
| 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
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
---
|
|
2
2
|
id: PROP-0018
|
|
3
3
|
title: Inspector-style page notes, a fix queue to the agent, and app windows as capture targets
|
|
4
|
-
status: Implemented
|
|
4
|
+
status: Implemented; queue, three-button popover and page_notes_mark_fixed superseded by PROP-0048
|
|
5
5
|
created: 2026-10-23
|
|
6
|
-
updated: 2026-10-
|
|
6
|
+
updated: 2026-10-27
|
|
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
|
|
|
10
10
|
# PROP-0018: Inspector, fix queue and app targets for page notes
|
|
11
11
|
|
|
12
|
+
> The fix queue, its three-button popover and `page_notes_mark_fixed` were replaced by
|
|
13
|
+
> [PROP-0048](PROP-0048-simple-annotate.md): a note is pending or sent, and the popover has Annotate
|
|
14
|
+
> and Annotate & send.
|
|
15
|
+
|
|
12
16
|
Requested by the owner on 2026-10-23. They chose these four things:
|
|
13
17
|
- the popover's three choices: Save, Queue, Send now
|
|
14
18
|
- the popover drawn inside the page
|