@xingular/harness 1.0.0 → 1.1.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.
Files changed (257) hide show
  1. package/CHANGELOG.md +33 -5
  2. package/README.md +70 -19
  3. package/dist/cli.js +10321 -5785
  4. package/dist/sdk/agents/builtin.d.ts +2 -0
  5. package/dist/sdk/agents/builtin.js +34 -0
  6. package/dist/sdk/agents/narrow.d.ts +13 -0
  7. package/dist/sdk/agents/narrow.js +29 -0
  8. package/dist/sdk/agents/profiles.d.ts +80 -0
  9. package/dist/sdk/agents/profiles.js +221 -0
  10. package/dist/sdk/annotations/bridge.d.ts +42 -0
  11. package/dist/sdk/annotations/bridge.js +264 -0
  12. package/dist/sdk/annotations/capture.d.ts +116 -0
  13. package/dist/sdk/annotations/capture.js +308 -0
  14. package/dist/sdk/annotations/delivery.d.ts +72 -0
  15. package/dist/sdk/annotations/delivery.js +130 -0
  16. package/dist/sdk/annotations/inspect.d.ts +10 -0
  17. package/dist/sdk/annotations/inspect.js +33 -0
  18. package/dist/sdk/annotations/isolated.d.ts +6 -0
  19. package/dist/sdk/annotations/isolated.js +51 -0
  20. package/dist/sdk/annotations/pageScript.d.ts +28 -0
  21. package/dist/sdk/annotations/pageScript.js +570 -0
  22. package/dist/sdk/annotations/part.d.ts +10 -0
  23. package/dist/sdk/annotations/part.js +144 -0
  24. package/dist/sdk/annotations/queue.d.ts +4 -0
  25. package/dist/sdk/annotations/queue.js +40 -0
  26. package/dist/sdk/annotations/serverMethods.d.ts +3 -0
  27. package/dist/sdk/annotations/serverMethods.js +62 -0
  28. package/dist/sdk/annotations/store.d.ts +160 -0
  29. package/dist/sdk/annotations/store.js +386 -0
  30. package/dist/sdk/browser/index.d.ts +14 -3
  31. package/dist/sdk/browser/index.js +11 -4
  32. package/dist/sdk/browser/serverMethods.d.ts +3 -0
  33. package/dist/sdk/browser/serverMethods.js +7 -0
  34. package/dist/sdk/browser/session.d.ts +1 -0
  35. package/dist/sdk/browser/session.js +45 -9
  36. package/dist/sdk/cli.js +19 -11
  37. package/dist/sdk/core/bus.js +1 -1
  38. package/dist/sdk/core/env.d.ts +1 -1
  39. package/dist/sdk/core/env.js +1 -1
  40. package/dist/sdk/doctor/serverMethods.d.ts +3 -0
  41. package/dist/sdk/doctor/serverMethods.js +8 -0
  42. package/dist/sdk/harness.d.ts +15 -0
  43. package/dist/sdk/harness.js +44 -5
  44. package/dist/sdk/history/recall.js +8 -8
  45. package/dist/sdk/history/serverMethods.d.ts +3 -0
  46. package/dist/sdk/history/serverMethods.js +8 -0
  47. package/dist/sdk/hub/cli.d.ts +1 -1
  48. package/dist/sdk/hub/cli.js +1 -1
  49. package/dist/sdk/hub/schema.d.ts +1 -1
  50. package/dist/sdk/hub/serverMethods.d.ts +3 -0
  51. package/dist/sdk/hub/serverMethods.js +11 -0
  52. package/dist/sdk/index.d.ts +10 -0
  53. package/dist/sdk/index.js +7 -0
  54. package/dist/sdk/mcp/connections.js +14 -7
  55. package/dist/sdk/mcp/serverMethods.d.ts +3 -0
  56. package/dist/sdk/mcp/serverMethods.js +22 -0
  57. package/dist/sdk/plugins/builtin.d.ts +1 -0
  58. package/dist/sdk/plugins/builtin.js +128 -33
  59. package/dist/sdk/plugins/builtinRegistry.d.ts +53 -0
  60. package/dist/sdk/plugins/builtinRegistry.js +49 -0
  61. package/dist/sdk/plugins/cli.d.ts +1 -1
  62. package/dist/sdk/plugins/cli.js +4 -3
  63. package/dist/sdk/prompt/compile.d.ts +5 -2
  64. package/dist/sdk/prompt/compile.js +25 -8
  65. package/dist/sdk/refine/cli.d.ts +1 -1
  66. package/dist/sdk/refine/cli.js +2 -2
  67. package/dist/sdk/refine/serverMethods.d.ts +3 -0
  68. package/dist/sdk/refine/serverMethods.js +20 -0
  69. package/dist/sdk/server/methods.js +9 -86
  70. package/dist/sdk/server/params.d.ts +4 -0
  71. package/dist/sdk/server/params.js +11 -0
  72. package/dist/sdk/sessions/contracts.d.ts +17 -0
  73. package/dist/sdk/sessions/contracts.js +42 -3
  74. package/dist/sdk/sessions/planMode.d.ts +5 -2
  75. package/dist/sdk/sessions/planMode.js +12 -3
  76. package/dist/sdk/sessions/reasoningSummaries.d.ts +2 -2
  77. package/dist/sdk/sessions/reasoningSummaries.js +3 -3
  78. package/dist/sdk/sessions/registry.d.ts +1 -0
  79. package/dist/sdk/sessions/registry.js +4 -1
  80. package/dist/sdk/sessions/runIndex.js +7 -7
  81. package/dist/sdk/sessions/runStore.js +3 -1
  82. package/dist/sdk/sessions/runner.js +2 -2
  83. package/dist/sdk/sessions/sessions.d.ts +17 -5
  84. package/dist/sdk/sessions/sessions.js +79 -12
  85. package/dist/sdk/sessions/sideQuestionServerMethods.d.ts +3 -0
  86. package/dist/sdk/sessions/sideQuestionServerMethods.js +19 -0
  87. package/dist/sdk/sessions/sideQuestions.d.ts +66 -0
  88. package/dist/sdk/sessions/sideQuestions.js +290 -0
  89. package/dist/sdk/sessions/subagentServerMethods.d.ts +3 -0
  90. package/dist/sdk/sessions/subagentServerMethods.js +41 -0
  91. package/dist/sdk/sessions/subagentService.d.ts +13 -2
  92. package/dist/sdk/sessions/subagentService.js +34 -16
  93. package/dist/sdk/sessions/subagents.d.ts +9 -1
  94. package/dist/sdk/sessions/subagents.js +19 -0
  95. package/dist/sdk/terminal/browser.d.ts +62 -0
  96. package/dist/sdk/terminal/browser.js +41 -0
  97. package/dist/sdk/terminal/browserControl.d.ts +29 -0
  98. package/dist/sdk/terminal/browserControl.js +186 -0
  99. package/dist/sdk/terminal/commandHelp.d.ts +17 -0
  100. package/dist/sdk/terminal/commandHelp.js +20 -0
  101. package/dist/sdk/terminal/controller.d.ts +7 -1
  102. package/dist/sdk/terminal/controller.js +34 -2
  103. package/dist/sdk/terminal/opentui/subagentsWidget.d.ts +28 -0
  104. package/dist/sdk/terminal/opentui/subagentsWidget.js +52 -0
  105. package/dist/sdk/terminal/piExtension.js +33 -48
  106. package/dist/sdk/terminal/socket.d.ts +6 -3
  107. package/dist/sdk/terminal/socket.js +40 -9
  108. package/dist/sdk/terminal/standalone.d.ts +2 -0
  109. package/dist/sdk/terminal/standalone.js +50 -10
  110. package/dist/sdk/terminal/subagentMonitor.d.ts +38 -0
  111. package/dist/sdk/terminal/subagentMonitor.js +121 -0
  112. package/dist/sdk/terminal/terminals.d.ts +42 -6
  113. package/dist/sdk/terminal/terminals.js +359 -18
  114. package/dist/sdk/terminal/trajectory.js +2 -2
  115. package/dist/sdk/terminal/tui/annotateCommand.d.ts +3 -0
  116. package/dist/sdk/terminal/tui/annotateCommand.js +22 -0
  117. package/dist/sdk/terminal/tui/commandPages.d.ts +5 -1
  118. package/dist/sdk/terminal/tui/commandPages.js +54 -6
  119. package/dist/sdk/terminal/tui/commands.d.ts +8 -4
  120. package/dist/sdk/terminal/tui/commands.js +181 -58
  121. package/dist/sdk/terminal/tui/dialogGeometry.d.ts +2 -2
  122. package/dist/sdk/terminal/tui/dialogGeometry.js +4 -2
  123. package/dist/sdk/terminal/tui/dialogs.d.ts +6 -1
  124. package/dist/sdk/terminal/tui/dialogs.js +9 -2
  125. package/dist/sdk/terminal/tui/modelPicker.js +1 -6
  126. package/dist/sdk/terminal/tui/page.d.ts +3 -0
  127. package/dist/sdk/terminal/tui/pageOverlay.js +17 -6
  128. package/dist/sdk/terminal/tui/pages/accountsPage.d.ts +26 -4
  129. package/dist/sdk/terminal/tui/pages/accountsPage.js +264 -36
  130. package/dist/sdk/terminal/tui/pages/agentsPage.d.ts +74 -0
  131. package/dist/sdk/terminal/tui/pages/agentsPage.js +190 -0
  132. package/dist/sdk/terminal/tui/pages/annotatePage.d.ts +94 -0
  133. package/dist/sdk/terminal/tui/pages/annotatePage.js +341 -0
  134. package/dist/sdk/terminal/tui/pages/browserPage.d.ts +87 -0
  135. package/dist/sdk/terminal/tui/pages/browserPage.js +738 -0
  136. package/dist/sdk/terminal/tui/pages/doctorPage.d.ts +2 -0
  137. package/dist/sdk/terminal/tui/pages/doctorPage.js +103 -15
  138. package/dist/sdk/terminal/tui/pages/notesPage.d.ts +75 -0
  139. package/dist/sdk/terminal/tui/pages/notesPage.js +201 -0
  140. package/dist/sdk/terminal/tui/pages/settingsPage.d.ts +8 -0
  141. package/dist/sdk/terminal/tui/pages/settingsPage.js +16 -1
  142. package/dist/sdk/terminal/tui/pages/subagentsPage.d.ts +23 -0
  143. package/dist/sdk/terminal/tui/pages/subagentsPage.js +70 -0
  144. package/dist/sdk/terminal/tui/pages/trajectoryPage.d.ts +12 -5
  145. package/dist/sdk/terminal/tui/pages/trajectoryPage.js +156 -83
  146. package/dist/sdk/terminal/tui/pages/worktreesPage.d.ts +72 -0
  147. package/dist/sdk/terminal/tui/pages/worktreesPage.js +203 -0
  148. package/dist/sdk/terminal/tui/planMode.d.ts +1 -1
  149. package/dist/sdk/terminal/tui/planMode.js +1 -1
  150. package/dist/sdk/terminal/tui/pluginCommands.d.ts +14 -0
  151. package/dist/sdk/terminal/tui/pluginCommands.js +27 -0
  152. package/dist/sdk/terminal/tui/questions.d.ts +2 -0
  153. package/dist/sdk/terminal/tui/runtime.js +4 -2
  154. package/dist/sdk/terminal/tui/settingsModel.d.ts +2 -0
  155. package/dist/sdk/terminal/tui/settingsModel.js +32 -2
  156. package/dist/sdk/terminal/tui/sideQuestion.d.ts +26 -26
  157. package/dist/sdk/terminal/tui/sideQuestion.js +131 -98
  158. package/dist/sdk/terminal/tui/ui.d.ts +2 -0
  159. package/dist/sdk/terminal/tui/ui.js +1 -0
  160. package/dist/sdk/tools/askUser.js +26 -8
  161. package/dist/sdk/tools/checklist.js +2 -2
  162. package/dist/sdk/tools/harnessTools.d.ts +2 -0
  163. package/dist/sdk/tools/harnessTools.js +1 -1
  164. package/dist/sdk/tools/spawnSubagent.js +13 -4
  165. package/dist/sdk/web/part.d.ts +10 -0
  166. package/dist/sdk/web/part.js +6 -0
  167. package/dist/sdk/web/serverMethods.d.ts +3 -0
  168. package/dist/sdk/web/serverMethods.js +7 -0
  169. package/dist/sdk/wiki/serverMethods.d.ts +3 -0
  170. package/dist/sdk/wiki/serverMethods.js +26 -0
  171. package/dist/sdk/worktrees/cli.d.ts +11 -0
  172. package/dist/sdk/worktrees/cli.js +146 -0
  173. package/dist/sdk/worktrees/copy.d.ts +9 -0
  174. package/dist/sdk/worktrees/copy.js +111 -0
  175. package/dist/sdk/worktrees/git.d.ts +16 -0
  176. package/dist/sdk/worktrees/git.js +81 -0
  177. package/dist/sdk/worktrees/serverMethods.d.ts +3 -0
  178. package/dist/sdk/worktrees/serverMethods.js +30 -0
  179. package/dist/sdk/worktrees/service.d.ts +73 -0
  180. package/dist/sdk/worktrees/service.js +483 -0
  181. package/dist/sdk/worktrees/setup.d.ts +23 -0
  182. package/dist/sdk/worktrees/setup.js +65 -0
  183. package/dist/sdk/worktrees/types.d.ts +91 -0
  184. package/dist/sdk/worktrees/types.js +1 -0
  185. package/dist/sdk/world/cli.d.ts +2 -2
  186. package/dist/sdk/world/cli.js +6 -6
  187. package/dist/sdk/world/world.d.ts +3 -1
  188. package/dist/sdk/world/world.js +8 -9
  189. package/dist/terminal-opentui.js +14540 -7374
  190. package/dist/terminal-pi.js +285 -666
  191. package/docs/README.md +22 -2
  192. package/docs/architecture/00-overview.md +28 -16
  193. package/docs/architecture/02-sessions-and-runs.md +72 -15
  194. package/docs/architecture/03-variants.md +10 -2
  195. package/docs/architecture/04-prompt.md +26 -6
  196. package/docs/architecture/06-plugins-and-capabilities.md +39 -3
  197. package/docs/architecture/07-tools-and-gate.md +21 -6
  198. package/docs/architecture/09-accounts-and-connectors.md +8 -0
  199. package/docs/architecture/10-server-protocol.md +111 -2
  200. package/docs/architecture/11-terminal.md +185 -5
  201. package/docs/architecture/12-storage.md +15 -1
  202. package/docs/architecture/13-world-tools.md +28 -6
  203. package/docs/architecture/14-surfaces-and-parity.md +89 -0
  204. package/docs/architecture/README.md +15 -4
  205. package/docs/architecture/proposals/PROP-0006-run-checklist.md +4 -2
  206. package/docs/architecture/proposals/PROP-0013-resource-browser.md +58 -0
  207. package/docs/architecture/proposals/PROP-0014-fullscreen-browser-tabs.md +58 -0
  208. package/docs/architecture/proposals/PROP-0015-one-capability-surface.md +88 -0
  209. package/docs/architecture/proposals/PROP-0016-managed-worktrees.md +156 -0
  210. package/docs/architecture/proposals/PROP-0017-page-annotations.md +127 -0
  211. package/docs/architecture/proposals/PROP-0018-annotation-queue-and-app-targets.md +179 -0
  212. package/docs/architecture/proposals/PROP-0019-contextual-side-questions.md +122 -0
  213. package/docs/architecture/proposals/PROP-0020-builtin-feature-plugins.md +105 -0
  214. package/docs/architecture/proposals/PROP-0021-command-namespaces-and-duplicates.md +99 -0
  215. package/docs/architecture/proposals/PROP-0022-plan-only-questions.md +102 -0
  216. package/docs/architecture/proposals/PROP-0023-xagent-cli-name.md +61 -0
  217. package/docs/architecture/proposals/PROP-0024-question-sketch-previews.md +130 -0
  218. package/docs/architecture/proposals/PROP-0025-contextual-question-wireframes.md +49 -0
  219. package/docs/architecture/proposals/PROP-0026-connected-sketch-display.md +94 -0
  220. package/docs/architecture/proposals/PROP-0027-xingular-agent-product-identity.md +60 -0
  221. package/docs/architecture/proposals/PROP-0028-normalize-question-wireframes.md +55 -0
  222. package/docs/architecture/proposals/PROP-0029-agent-profiles.md +124 -0
  223. package/docs/architecture/proposals/PROP-0030-subagent-title.md +86 -0
  224. package/docs/architecture/proposals/README.md +25 -0
  225. package/docs/decisions/ADR-0009-xharness-command.md +6 -5
  226. package/docs/decisions/ADR-0014-public-release-baseline.md +3 -2
  227. package/docs/decisions/ADR-0015-resource-browser.md +28 -0
  228. package/docs/decisions/ADR-0016-fullscreen-browser-tabs.md +31 -0
  229. package/docs/decisions/ADR-0017-one-capability-surface.md +34 -0
  230. package/docs/decisions/ADR-0018-builtin-feature-plugins.md +35 -0
  231. package/docs/decisions/ADR-0019-managed-git-worktrees.md +31 -0
  232. package/docs/decisions/ADR-0020-page-annotations.md +37 -0
  233. package/docs/decisions/ADR-0021-required-command-namespaces.md +40 -0
  234. package/docs/decisions/ADR-0022-plan-only-question-tools.md +34 -0
  235. package/docs/decisions/ADR-0023-contextual-side-question-runs.md +35 -0
  236. package/docs/decisions/ADR-0024-xagent-command.md +40 -0
  237. package/docs/decisions/ADR-0025-question-choice-sketches.md +49 -0
  238. package/docs/decisions/ADR-0026-contextual-question-wireframes.md +58 -0
  239. package/docs/decisions/ADR-0027-connected-sketch-display.md +60 -0
  240. package/docs/decisions/ADR-0028-xingular-agent-product-identity.md +56 -0
  241. package/docs/decisions/ADR-0029-normalized-question-wireframe-borders.md +33 -0
  242. package/docs/decisions/ADR-0030-agent-profiles.md +43 -0
  243. package/docs/doctor.md +10 -4
  244. package/docs/features/README.md +26 -0
  245. package/docs/features/interfaces/README.md +1 -1
  246. package/docs/future-work.md +48 -0
  247. package/docs/parity.md +78 -0
  248. package/docs/releases/1.0.0.md +2 -2
  249. package/docs/releases/4.0.0.md +46 -0
  250. package/docs/releases/README.md +20 -15
  251. package/docs/study/00-index.md +5 -0
  252. package/docs/study/autonomous-engineering-sources.md +277 -0
  253. package/docs/study/autonomy-sources.md +147 -0
  254. package/docs/study/proactive-autonomy.md +408 -0
  255. package/docs/study/tui-resource-browser.md +78 -0
  256. package/docs/terminal-tui.md +325 -93
  257. package/package.json +3 -3
@@ -12,7 +12,7 @@ to the host for the extension points the host supplies.
12
12
  | Type / function | Module | Role |
13
13
  |---|---|---|
14
14
  | `RpcPeer`, `Transport`, `stdioTransport`, `PROTOCOL_VERSION` | `server/rpc.ts` | Framing, requests, replies, host calls. |
15
- | `methods(harness)` | `server/methods.ts` | The method table. |
15
+ | `methods(harness)` | `server/methods.ts` | Merges Foundation handlers with built-in plugin handlers from `BuiltinPluginRegistry` and rejects overlapping ownership. |
16
16
  | `serve`, `attach` | `server/serve.ts` | Registers the table, forwards events and notices. |
17
17
  | `remoteSecrets`, remote policy, directory, tools | `server/remote.ts` | Extension points supplied by the host over the protocol. |
18
18
  | CLI `serve` | `src/cli.ts` | `serve --state <dir> --data <dir> --name <product> [--builtins <dir>] [--host-secrets] [--host-policy] [--host-tools] [--host-directory]`. |
@@ -27,9 +27,13 @@ harness → host { v: 1, id, call, params } host → harness { v: 1
27
27
  ```
28
28
 
29
29
  - stdout carries only protocol lines; diagnostics go to stderr.
30
+ - Run events use the validated, persisted payload schemas in page 02. `question.requested` may carry
31
+ the optional bounded ASCII sketch metadata described there; the server relays it without changing
32
+ answer payloads or the protocol framing (PROP-0024).
30
33
  - `harness.methods` lists every method. Groups in the table: `accounts`, `harnesses`, `runs`,
31
34
  `connections`, `plugins`, `wiki`, `refine`, `capabilities`, `hub`, `terminal`, `approvals`,
32
- `harness`, `subagents`, `sessions`, `library`, `recall`, `context`.
35
+ `harness`, `subagents`, `agents`, `sessions`, `sideQuestions`, `library`, `recall`, `context`,
36
+ `worktrees`, `annotations`.
33
37
  - Host calls (only with the matching `--host-*` flag): `secrets.get|set|delete`,
34
38
  `policy.scope|authorize|approval|connections`, `tools.call`. The host registers tools with
35
39
  `tools.register` and names with `directory.set`, and describes its parts with
@@ -37,6 +41,12 @@ harness → host { v: 1, id, call, params } host → harness { v: 1
37
41
  - `refine.start` takes `{ task, k?, mode?, improver?, executor?, baseVersion?, retainWorkspaces?, id? }`;
38
42
  `refine.candidates` returns each execution with `workspace: string | null` (page 05, PROP-0002, PROP-0003).
39
43
  - `runs.checklist { runId }` returns the run's latest checklist, `[]` when it wrote none (PROP-0006).
44
+ - `agents.list { cwd? }` returns `{ profiles, problems }`; `agents.get { cwd?, name }` one profile;
45
+ `agents.create { cwd?, name, scope: 'global' | 'project', from? }` writes the template or a copy
46
+ and refuses an existing file; `agents.remove { cwd?, name, scope }` deletes a person's own file.
47
+ `subagents.spawn` takes `agent` as a profile name and returns `agent` and `unavailableTools`
48
+ (PROP-0029). It takes an optional `title` (at most six words); without one the child's title is
49
+ the first line of its brief (PROP-0030).
40
50
  - `runs.continuation { runId, sessionDir? }` returns a `Continuation`, and `sessions.run` accepts
41
51
  `continueFrom` (page 02, PROP-0007). `harness.status` reports `recovery.interruptedRunIds`.
42
52
  - Errors carry a stable `code`, a message and an optional hint (`core/errors.ts`).
@@ -56,6 +66,10 @@ harness → host { v: 1, id, call, params } host → harness { v: 1
56
66
  variants, the Wiki, the prompt, connected apps, a recorded session, a plugin hook and the
57
67
  refinement demo. The App's sidecar tests parse every reply with its schemas and must pass too.
58
68
 
69
+ Built-in feature modules may contribute handlers through `BuiltinPluginRegistry`, but the
70
+ `methods(harness)` result remains the public contract. Plugin module ownership does not rename
71
+ methods or change their params, result shapes or authorization paths (PROP-0020).
72
+
59
73
  ## Source map
60
74
 
61
75
  `src/server/*.ts`, `src/cli.ts`, `src/core/errors.ts`, `scripts/prove-standalone.mjs`.
@@ -78,7 +92,102 @@ account/model, findings, and available live-check notices. Findings distinguish
78
92
  `live` and statuses `pass`, `warning`, `fail`, `disabled`, `blocked`, `unverified`. Schemas and
79
93
  Node types are exported. Jobs are in-memory until shutdown; real live-run records remain.
80
94
 
95
+ ## Side questions (PROP-0019)
96
+
97
+ | Method | Input | Reply |
98
+ |---|---|---|
99
+ | `sideQuestions.start` | `{ question, cwd, caller, context?: { instructions?, transcript?, references? }, parentRunId?, parentSessionId?, accountId?, model?, effort?, runId?, sessionId? }` | `{ runId, sessionId, nativeSessionId }` |
100
+ | `sideQuestions.read` | `{ runId, sessionId, afterSequence? }` | `{ run: RunRecord, events: RunEvent[] }` |
101
+ | `sideQuestions.interrupt` | `{ runId, sessionId }` | `{ runId }` |
102
+
103
+ The Harness builds bounded context from the parent's persisted effective prompt and public events
104
+ plus the surface's visible transcript. Read and interrupt require the side run's session id. The
105
+ standalone terminal exposes the same operations through control-key-protected
106
+ `terminal.sideQuestions.*` calls; its caller identity, account and working folder come from terminal
107
+ preparation, not client-supplied values.
108
+
81
109
  Remote `tools.register` may include `diagnostics: [{ id, category, title, tools, probe?: { notice,
82
110
  tool, input, contains } }]`. The host answers `tools.diagnose({ id, context })` with `{ status,
83
111
  evidence, remedy? }` for local inspection. A probe is a declared registered tool call through
84
112
  the gate, with an expected response marker; it cannot supply arbitrary executable code.
113
+
114
+ ## Private terminal resource controls (PROP-0013)
115
+
116
+ These methods are session-socket controls, not additions to the public host RPC table. All
117
+ require the claimed terminal control key; account, working directory and variant pin come
118
+ from preparation, never from the request.
119
+
120
+ | Method | Input | Reply |
121
+ |---|---|---|
122
+ | `terminal.browser.config` | `{}` | `{ allowPrivate }`, the device-local private-address setting |
123
+ | `terminal.browser.configure` | `{ allowPrivate: boolean }` | `{ allowPrivate }`, updated setting |
124
+ | `terminal.browser.snapshot` | `{ refresh?: boolean }` | `BrowserSnapshot`: resources, plugins, safe connection records, pinned/latest variant identity and Hub overview |
125
+ | `terminal.browser.read` | `{ id, latest?: boolean }` | `{ content }`, bounded enumerated resource content |
126
+ | `terminal.browser.importSkill` | `{ path }` | `{}`, validated bounded local bundle imported into the existing library |
127
+ | `terminal.browser.hubPreview` | `{ id, version, offset? }` | Existing `HubPreviewPage` |
128
+ | `terminal.browser.hubDocument` | `{ id, version }` | Existing verified installed document |
129
+ | `terminal.browser.connections.appClients` | `{}` | Existing available application OAuth catalog IDs |
130
+ | `terminal.browser.connections.save` | `{ input: ConnectionInput }` | Existing safe `Connection` record |
131
+ | `terminal.browser.connections.test\|signIn\|signOut\|remove` | `{ id }` | Existing connection service result |
132
+
133
+ Protected `plugins.install { source }` and `plugins.remove { pluginId }` delegate to the package
134
+ service. Optional matching callbacks extend `PluginControl`; hosts without them receive a clear
135
+ unsupported-operation error. No protocol version or persisted schema changes.
136
+
137
+ ## Worktrees (PROP-0016)
138
+
139
+ | Method | Input | Reply |
140
+ |---|---|---|
141
+ | `worktrees.list` | `{ repo? }` | active `WorktreeRecord[]` (of the repository `repo` is in) |
142
+ | `worktrees.removed` | `{ repo? }` | removed records that `restore` can bring back |
143
+ | `worktrees.status` | `{ id }` | `WorktreeStatus`: exists, head, changed paths, commits since it started |
144
+ | `worktrees.create` | `{ repo, name?, baseRef?, branch?, kind?, carryChanges?, setup? }` | `{ worktree, carried, included, setup }` |
145
+ | `worktrees.branch` | `{ id, name }` | the record, on branch `<prefix><name>` |
146
+ | `worktrees.handoff` | `{ id, direction: "toSource" \| "toWorktree", move? }` | `{ direction, patched, copied, stash }` |
147
+ | `worktrees.remove` | `{ id, force? }` | `{ worktree, snapshot }` |
148
+ | `worktrees.restore` | `{ id }` | the record |
149
+ | `worktrees.prune` | `{ repo?, keep? }` | `{ removed, failed }` |
150
+ | `worktrees.adopt` | `{ path }` | the record (kind `permanent`, origin `adopted`) |
151
+ | `worktrees.setup.trust` | `{ repo, hash }` | `{}` |
152
+
153
+ Errors: `not_a_repository`, `repository_empty`, `worktree_exists`, `branch_exists`,
154
+ `worktree_in_use`, `worktree_has_work`, `worktree_removed`, `worktree_missing`, `not_a_worktree`,
155
+ `handoff_target_dirty`, `handoff_conflict`, `git_failed`, `git_unavailable`. The terminal reaches the
156
+ same service through `terminal.worktrees.*` routes, which need the control key (`INV-TUI-4`).
157
+
158
+ ## Page notes (PROP-0017)
159
+
160
+ | Method | Input | Reply |
161
+ |---|---|---|
162
+ | `annotations.list` | `{ url?, query?, status?, offset?, limit? }` | `{ notes, total }`, newest first |
163
+ | `annotations.read` | `{ id }` | `Note` |
164
+ | `annotations.create` | `{ source, target, body, tags? }` | `Note` (private) |
165
+ | `annotations.update` | `{ id, expectedVersion, patch: { body?, tags?, status?, target? } }` | `Note` |
166
+ | `annotations.delete` | `{ id, expectedVersion }` | `{}` |
167
+ | `annotations.share` | `{ id, principal: { sessionId } \| { agentId }, binding? }` | `Note` |
168
+ | `annotations.unshare` | `{ id, principal }` | `Note` |
169
+ | `annotations.revokeBinding` | `{ binding }` | `{ revoked }` |
170
+ | `annotations.import` | `{ notes }` | `{ imported, skipped }` (ids kept) |
171
+ | `annotations.pageScript` | `{}` | `{ script }`: the page helper, with `__ARGS__` for one operation |
172
+ | `annotations.queue` | `{ id, sessionId, expectedVersion?, autoSend? }` | `Note`, shared with the session and queued (PROP-0018) |
173
+ | `annotations.dequeue` / `annotations.confirm` | `{ id, expectedVersion? }` | `Note` |
174
+ | `annotations.queued` | `{ sessionId }` | `{ notes }`, oldest first |
175
+ | `annotations.createAndAct` | `{ note, action: save \| queue \| send, sessionId?, trusted? }` | `{ note, send }`; an untrusted send waits for `confirm` |
176
+ | `annotations.compose` | `{ sessionId, ids? }` | `{ text, ids }`: one instruction for a host's own `sessions.run` |
177
+ | `annotations.delivered` | `{ ids, sessionId, runId }` | `{ notes }`, marked sent |
178
+ | `annotations.send` | `{ sessionId, ids? }` | `{ state: sent \| busy \| host \| empty, … }` |
179
+ | `annotations.capture.attach` | `{ key, kind: web \| cdp \| bridge, endpoint?, name? }` | `{ kind, app, windows, bridge? }` |
180
+ | `annotations.capture.target` | `{ key }` | `{ kind, app, inspecting, windows }` |
181
+ | `annotations.capture.selectWindow` | `{ key, window }` | `{}` |
182
+ | `annotations.capture.open` | `{ key, url? }` | `{ url, title }` |
183
+ | `annotations.capture.inspect` / `stopInspect` | `{ key }` | `{ captureId }` / `{}` |
184
+ | `annotations.capture.next` | `{ key, sessionId?, surface? }` | `{ active, trusted, app, note, send, message, … }` |
185
+ | `annotations.capture.release` | `{ key }` | `{}` |
186
+ | `annotations.bridge.start` | `{}` | `{ port, token, scriptUrl, snippet }` |
187
+
188
+ Notices: `annotations.changed { sessionId, ids }` after any queue, send or fix;
189
+ `annotations.ready { sessionId, ids }` when a host session's waiting notes should be sent now.
190
+
191
+ Errors: `version_conflict`, `not_found`, `annotation_limit`, `invalid_request`, `invalid_data`. The
192
+ terminal reaches the same store through `terminal.annotations.*`, which shares only with its own
193
+ session and needs the control key (`INV-TUI-4`).
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Purpose
4
4
 
5
- The harness owns a generic interactive terminal application (`xharness`) over a
5
+ The harness owns a generic interactive terminal application (`xagent`) over a
6
6
  persistent Pi session on a variant. It is the standalone way to use the harness, and an
7
7
  embedding application can host it in its own PTY. Detail, screen layout and verification evidence
8
8
  are in [`../terminal-tui.md`](../terminal-tui.md); this page states the binding parts.
@@ -24,20 +24,42 @@ Harness parent: account + compiled context + trusted resources + run writer
24
24
  | launch specification / session socket
25
25
  Harness terminal child (Bun): OpenTUI application + persistent Pi AgentSessionRuntime
26
26
  | typed native events / plugin UI callbacks
27
- Screen: transcript above the composer, centred page dialogs
27
+ Screen: transcript above the composer, centred dialogs, full-screen resource browser
28
28
  ```
29
29
 
30
30
  ## Contracts
31
31
 
32
- - The published executable is `xharness`; with no command it starts the interactive terminal. `terminal` remains an explicit alias, and `serve` remains the host-facing RPC path.
32
+ - The published executable is `xagent`; `xharness` is not retained as a compatibility alias. With no command, `xagent` starts the interactive terminal. `terminal` remains an explicit alias, and `serve` remains the host-facing RPC path.
33
33
  - `TerminalAssets` is `{ node, cli, piExtension, openTui }`. The command is Bun with
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
37
  - The terminal compiles its prompt once (`compile` + `render`) and keeps that pack; each run
38
38
  records a copy (page 04).
39
+ - Normal mode keeps `ask_user` and `ask_user_question` out of the active tool set. A plan request
40
+ enables the registered question tools alongside its read-only set and restores the normal set on
41
+ success, failure or interruption. See page 02 and the [terminal guide](../terminal-tui.md).
39
42
  - Standalone defaults: `~/.xingular-harness/{data,state}`; `npm run dev` uses
40
43
  `~/.xingular-harness-dev/{data,state}`.
44
+ - An empty conversation shows a centered welcome using `env.productName` (default `Xingular Agent`):
45
+ the first letter of a multiword name is the orange block mark and its remaining words are letter-spaced
46
+ in blue. The welcome adds a greeting, tagline and `/help` hint without replacing the composer or
47
+ status bar. Explicit host product names use the same generic formatting.
48
+ - `xagent --worktree [name]` (`-w`) starts in a new managed worktree of the current repository,
49
+ 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` switches folders by asking the host to restart
51
+ the frontend there (`TerminalRelaunch.cwd`), as a new conversation: Pi keeps one history per
52
+ working folder.
53
+ - Slash-command aliases share one registry entry: `/session (resume)` switches saved sessions,
54
+ `/history (tree)` navigates branches in the current session, and `/btw (side)` asks a side
55
+ question through the Harness `SideQuestions` service. It uses the same account/model/effort,
56
+ mirrors the main run's redacted prompt and public evidence, starts a separate tool-free run, and
57
+ leaves the main conversation untouched. The dock streams, scrolls and copies the complete answer.
58
+ Aliases remain callable and searchable, but help and palette show only the canonical
59
+ entry. Commands owned by required built-in plugins and core terminal commands are unprefixed.
60
+ Optional built-in plugin and Pi extension commands use `/plugin:<command>`. A bare command or
61
+ prompt owns its name; a colliding `/plugin:<command>` is omitted and rejected with a hint to use
62
+ the bare command. Prompt templates and `/skill:<name>` otherwise keep their existing forms.
41
63
 
42
64
  ## Invariants
43
65
 
@@ -50,18 +72,29 @@ Screen: transcript above the composer, centred page dialogs
50
72
  their existing layers. The terminal adds no second path for any of them; its runs are written
51
73
  through the controller and the run store.
52
74
  - **INV-TUI-4** Changes made through the session socket (`plugins.attach|detach|trust|untrust|configure`,
53
- `accounts.*`, Hub installs) require the control key the trusted terminal process claimed once
75
+ `accounts.*`, Hub installs, `terminal.browser.*`, `terminal.worktrees.*`,
76
+ `terminal.annotations.*`, `terminal.sideQuestions.*`) require the control key the trusted terminal process claimed once
54
77
  (`control.claim`). The session's shell can read the session token, so the token alone is never
55
78
  enough.
56
79
  - **INV-TUI-5** Every resource reload revalidates the original trusted selection; changed or
57
80
  revoked code needs review and a fresh terminal.
58
81
  - **INV-TUI-6** `sessions.run` stays the embedding and unattended path. The terminal keeps a
59
82
  persistent child instead of opening a session per turn.
83
+ - **INV-TUI-7** Required built-in plugin commands use their unprefixed names; optional built-in
84
+ plugin commands and Pi extension commands use `/plugin:<command>`. Completions and help show each
85
+ command in its canonical namespace. Bare core commands, aliases, required built-in commands and
86
+ loaded prompts reserve their names; a colliding prefixed command is hidden and rejected with a hint
87
+ to use the bare command. Duplicate extension names are rejected with owner diagnostics. Old
88
+ prefixed forms of required built-in commands are not aliases.
60
89
 
61
90
  ## Source map
62
91
 
63
92
  `src/terminal/**`. Decisions: ADR-0001, [ADR-0004](../decisions/ADR-0004-fullscreen-terminal-layout.md)
64
- (superseded), ADR-0006. Experiments: EXP-0001, EXP-0002 in `../experiments/`.
93
+ (superseded), ADR-0006, [ADR-0021](../decisions/ADR-0021-required-command-namespaces.md),
94
+ [ADR-0024](../decisions/ADR-0024-xagent-command.md),
95
+ [ADR-0027](../decisions/ADR-0027-connected-sketch-display.md),
96
+ [ADR-0028](../decisions/ADR-0028-xingular-agent-product-identity.md). Experiments:
97
+ EXP-0001, EXP-0002 in `../experiments/`.
65
98
 
66
99
  ## Session name in the working line (PROP-0010)
67
100
 
@@ -79,3 +112,150 @@ truncate at the right edge. Manual `/name` and existing long names remain suppor
79
112
  Live checks opens an explicit selection followed by account/model, destination, cost and isolation
80
113
  confirmation. The page polls structured reports, retains findings after cancellation, and cancels
81
114
  on close. No command text is sent to the conversation model. See [Doctor](../doctor.md).
115
+
116
+ ## Resource browser (PROP-0013)
117
+
118
+ `/harness` owns shared navigation for Foundation, Variant, Skills, Plugins, Connections, Tools
119
+ and Library. `/skills`, `/plugins`, `/connections` (`/mcp`), `/tools`, `/hub` and `/components`
120
+ are shortcuts into that browser. Current availability comes from the live resource loader and
121
+ active tool registry, independently of saved configuration and the latest variant head.
122
+
123
+ Every `terminal.browser.*` call requires the private control key, including bounded resource
124
+ inspection, local imports, connection management and browser settings. Package install/remove use protected
125
+ `plugins.install|remove`. These are adapters to the existing services, not another loader,
126
+ attachment store, gate or secret store. Browsing neither executes plugin code nor connects MCP.
127
+ The browser uses the full terminal with persistent section tabs (PROP-0014); wide screens keep
128
+ inventory beside details, actions and content, while compact screens keep inline details under
129
+ the same tabs. Other command pages remain centered except `/settings` and `/accounts`, which use
130
+ full-screen page layouts. Accounts keeps Accounts/Pools tabs, search and account-service operations.
131
+ Wide terminals show selected-account details beside the list; Enter or a primary click opens grouped
132
+ actions in that inspector. Compact terminals replace the list with a full-page account detail view
133
+ and its grouped actions. Enter opens the selected account; Escape returns to the list while
134
+ preserving its section, query and selection across navigation and resizing. Tab/Shift+Tab moves focus
135
+ between tabs, the list and (when open) actions; Left/Right changes a focused tab and Up/Down moves
136
+ the focused list or action list. Account actions retain their Session, Account, Sign-in and Remove
137
+ groups; pool actions remain grouped under Manage and Remove. See the
138
+ [terminal guide](../terminal-tui.md#blocks-and-pages) for layout and interaction.
139
+
140
+ `/settings` is a full-screen page with category tabs, search, settings list and the device-local
141
+ Browser tab for `allowPrivate`. Enabling private address access requires confirmation and allows both
142
+ agent browsing and annotation capture to reach localhost and private networks. It is off by default.
143
+
144
+ ## Worktrees command (PROP-0016)
145
+
146
+ `/worktree` opens a page of the managed worktrees of the repository the session works in: make a
147
+ managed or permanent worktree, switch the terminal to one (or back to the main checkout), create a
148
+ branch on a detached one, hand changes off in either direction, remove one (with a snapshot when it
149
+ holds work, never the one this terminal uses), restore a removed one, prune older ones, and trust
150
+ the repository's setup script. The page calls `terminal.worktrees.*` routes, which use the same
151
+ `Worktrees` service as the `worktrees.*` server methods. `xagent worktree <command>` offers the
152
+ same actions from a shell.
153
+
154
+ ## Question dock
155
+
156
+ Pending questions appear in a flat block above the composer, with a tab for each 1–2 word question
157
+ label above its title. Tabs can be clicked; Left/Right also switch questions and preserve staged
158
+ answers. The header has no pager or collapse control, and the dock stays expanded until the answer
159
+ is submitted or Escape cancels the pending question. While it is active, the chat composer and its
160
+ lower status bar are hidden. `n` opens a note for the focused selected choice; Tab and Shift+Tab
161
+ navigate existing note fields, the free-text answer and the action without creating notes. Notes
162
+ and the “Something else” answer wrap across lines. Choice recommendations remain visual only and
163
+ never preselect an answer.
164
+
165
+ Every choice uses one shared measured layout: a marker gutter, a one-third label cell, a two-cell
166
+ gap, and the remaining description cell. Column boundaries align across all rows at every terminal
167
+ width, including compact widths. Text wraps within its cell; a missing description keeps its cell
168
+ 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.
170
+
171
+ The dock body has bounded height and vertical scrolling; question tabs and answer/action controls
172
+ stay outside that scrolling region. PageUp/PageDown scroll the body and Ctrl+Home/End jump to its
173
+ beginning/end while the dock is active, rather than scrolling the transcript. Focused choices and
174
+ note fields are brought into view. Ordinary arrows retain question/choice navigation; Shift+arrows
175
+ pan the sketch horizontally or vertically.
176
+
177
+ When a question sets `uiSketch: true`, one shared border-only monospace preview below the choices
178
+ shows the hovered or focused choice's ASCII wireframe, with no visible caption or extra left rule.
179
+ Sketch source supports up to 80 columns by 24 lines (page 02) and remains literal ASCII in
180
+ persistence. The terminal uses a bounded structural display projection: recognized ASCII table-border
181
+ rows—including a title between horizontal runs—and enclosed vertical table edges become connected
182
+ box-drawing glyphs, while internal framed tables retain their original widths and positions. For a
183
+ high-confidence frame with matched `+` corners, missing or slightly displaced side edges may be
184
+ filled or moved only through whitespace to the established boundary columns; interior text is never
185
+ moved or overwritten, and conflicting or ambiguous rows remain literal. Bare standalone hyphen
186
+ divider rows expand to `max(panel viewport width, original sketch widest line)` and join the outer
187
+ single-line preview frame with `├` and `┤`. This is not a global `+|-` substitution: prose, content
188
+ operators, ordinary pipes and unrecognized rows remain literal. Source sketches and all persisted
189
+ whitespace remain unchanged; only the display projection adjusts recognized boundary cells.
190
+
191
+ There is no wrapping, reflow, truncation or markup interpretation. A bounded two-axis viewport makes
192
+ all overflow reachable by panning. Moving focus changes the preview without changing the staged
193
+ answer. Projected glyphs and expanded dividers never enter persisted events or answers; the wire
194
+ contract is unchanged. See [PROP-0025](proposals/PROP-0025-contextual-question-wireframes.md),
195
+ [ADR-0026](../decisions/ADR-0026-contextual-question-wireframes.md) and the approved display amendment
196
+ [PROP-0026](proposals/PROP-0026-connected-sketch-display.md) /
197
+ [ADR-0027](../decisions/ADR-0027-connected-sketch-display.md), and
198
+ [PROP-0028](proposals/PROP-0028-normalize-question-wireframes.md) /
199
+ [ADR-0029](../decisions/ADR-0029-normalized-question-wireframe-borders.md). Isolated production
200
+ PTY verification is retained in `docs/evidence/terminal-wireframe-normalization/`; it establishes
201
+ cell topology for bounded fixtures, not every emulator/font or live-model sketch quality.
202
+
203
+ ## Page notes commands (PROP-0017)
204
+
205
+ `/plugin:notes` lists the page notes kept in the data root, with search, and offers reveal, edit, resolve or
206
+ reopen, share with this session or stop sharing, and delete. `/plugin:annotate [url]` starts a new note: it
207
+ opens a visible capture browser (its own window and profile, separate from the agent's browser), and
208
+ the person notes the whole page, selects text, or clicks an element there, then confirms in the
209
+ terminal. A note is private until shared; this session's agent then reads it with `page_notes_list`
210
+ and `page_notes_read`.
211
+
212
+ `/plugin:annotate` is the annotate pane (PROP-0018): a full-screen page beside the window being inspected.
213
+
214
+ - **Ways to start it:**
215
+ - `/plugin:annotate [url]`: the browser window
216
+ - `/plugin:annotate --app <DevTools address | port> [name]`: an app's own windows over its DevTools port
217
+ - `/plugin:annotate --bridge [name]`: app windows that load the page bridge script, which the pane shows
218
+ - **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
+ - **Sections:** Queue, Sent and fixed (with the agent's summary), and Saved.
220
+ - **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
+ - **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
+
223
+ ## Checklist (PROP-0006, PAR-001)
224
+
225
+ Terminal sessions register the shared `checklist_write` tool. The extension validates each list
226
+ with the same tool code and sends it as `checklist` telemetry; the controller emits it as
227
+ `checklist.updated` on the active run, so `runs.checklist` and continuation read terminal runs too.
228
+ The gate treats it as read-only, plan mode allows it, and terminal children inherit it. The
229
+ transcript shows each write as a checklist block (`✓` done, `●` in progress (warning yellow), `○` pending) under a
230
+ `Checklist · n of m done` header instead of a tool row; a failed or malformed call stays a tool row.
231
+
232
+ ## Subagent activity monitor
233
+
234
+ During an active parent run, the terminal polls a private read-only monitor once per second. It
235
+ projects the flat set of child and nested-child runs with task, status, elapsed time, the latest
236
+ tool name, the child's agent profile (name and colour, PROP-0029), the title the parent gave it
237
+ (PROP-0030), and counts from the child's own checklist. The child's own `session_name` is not
238
+ projected; it names the child's session, not its row. Tool summaries, other
239
+ arguments, output and checklist item text never enter the monitor. The latest completed tool name
240
+ remains visible across one-second snapshots until new tool or response activity replaces it. The
241
+ monitor exposes no controls to steer or stop children.
242
+
243
+ The live rows sit under the status line, after one blank row, with no heading. Each row reads, in
244
+ 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
+ `✓` done, `✕` failed, `!` stopped), the profile name in its colour (`subagent`, muted, for a copy
246
+ of the parent), the title the parent gave the child (PROP-0030), and `n of m tasks` when the child
247
+ keeps a checklist. Active rows come first, at most three, then `+N more · /subagents`; a narrow
248
+ terminal cuts the title first. `/subagents` opens the searchable full roster with the same fields.
249
+ Finished rows remain until the parent run settles. The projection is volatile and scoped to that
250
+ parent run; it is not a persisted event or public server method.
251
+
252
+ ## Agent profiles (PROP-0029)
253
+
254
+ `/agents` opens the Agents page over `terminal.agents.list|create|remove`, which call the same
255
+ `agents/profiles.ts` functions as `agents.*`. It lists built-in, global, project and variant
256
+ profiles, and files that cannot be read. The detail pane shows the colour, description, tools,
257
+ plugins, variant, model, effort, file and instructions. Enter on a row offers: for a person's own
258
+ profile, edit (opens the file in `$VISUAL`/`$EDITOR` with the renderer suspended), copy and delete
259
+ (confirmed); for a built-in or variant profile, copy. New profile asks for a name and a place
260
+ (project or global), writes the template and opens it. The terminal passes its pinned variant to
261
+ `Subagents.register`, so the variant's c5 names are profiles there too.
@@ -16,6 +16,7 @@ index.
16
16
  refine/<id>/ summary.json, task.json, variants/, rollouts/, sessions/, context/, selection/, reflection/, improver/, or matrix.json + suite.json for evaluation matrices (05)
17
17
  rollouts/<label>/workspace/ only when started with retainWorkspaces
18
18
  library/<scope>/<area>/ INDEX.md, variants/<task>/{variant/, EXPERIENCE.md} (05)
19
+ annotations/<id>.json page notes (13, PROP-0017)
19
20
  wiki/ home.md, library/ (library/lessons/ from the lessons plugin), projects/<slug>/ (08)
20
21
  reflection/improver/lesson-<run id>/ a reflection's native history and reply (08)
21
22
  wiki-history/ earlier versions of notes (08)
@@ -26,6 +27,7 @@ index.
26
27
  hub/ installed documents and provenance (09)
27
28
  runs/<id>/ run.json, events.jsonl, owner.json, subagents.json, context.json, caller.json, capabilities.json, mcp-context.json (02)
28
29
  config/ plugin-attachments.json and settings the harness reads (06)
30
+ agents/<name>.md a person's global agent profiles; agents/profiles.ts owns it (02, PROP-0029)
29
31
  index.sqlite derived index (FTS5) (08)
30
32
  projects.json read only: the application owns it
31
33
 
@@ -36,10 +38,20 @@ index.
36
38
  plugin-trust.json, variant-plugin-trust.json, plugin-registered.json, plugin-hooks.json (03, 06)
37
39
  connections.json connected apps, no secrets (09)
38
40
  hub/catalog.json catalog cache (09)
39
- run/ the session socket and terminal commands (11)
41
+ run/ terminal commands, and one session socket per Harness process,
42
+ harness-<pid>-<random>.sock; files of ended processes are pruned (11)
43
+ worktrees.json managed worktree registry (02, PROP-0016)
44
+ worktrees/<repo>/<name>/ managed worktree checkouts; worktrees/logs/ setup output (PROP-0016)
45
+ worktree-setup-trust.json trusted setup-script hashes, owner-only (PROP-0016)
46
+ browser/ isolated browser settings and profiles (13)
47
+ notes-bridge.json the page bridge's port and token, kept so an app's script tag stays valid (13, PROP-0018)
40
48
  harness.log standalone terminal diagnostics
41
49
  ```
42
50
 
51
+ Side-question runs use the ordinary `runs/<id>/` records. Their temporary Pi native history is
52
+ created under the operating system temporary directory and removed when the run ends; it is not
53
+ retained in the data root or state directory.
54
+
43
55
  ## Invariants
44
56
 
45
57
  - **INV-STO-1** Device-local state (credentials, approvals, trust, connections, sockets) is never
@@ -50,6 +62,8 @@ index.
50
62
  through that module's functions. A new top-level folder or a new file in `runs/<id>/` is an
51
63
  architecture change.
52
64
  - **INV-STO-4** `projects.json` belongs to the application; the harness only reads it.
65
+ Project agent profiles live in the repository at `<project>/.xingular/agents/<name>.md`; the
66
+ harness writes them only through `agents.create` and `agents.remove` (PROP-0029).
53
67
  - **INV-STO-5** Migrations of stored data are one-way and safe: the old data is backed up or left
54
68
  as it was when a migration fails, and the failure is reported in `Recovery.migrationError`.
55
69
  - **INV-STO-6** Writes of shared JSON files are atomic (`core/fs.ts::atomicWrite`, `writeJson`).
@@ -1,10 +1,12 @@
1
1
  # 13 World tools
2
2
 
3
- The foundation supplies generic web and isolated browser tools through the existing tool-provider
4
- surface. Web requests use the public-address guard. Each browser session owns its context and
5
- profile; its tools pass the same capability and policy gate as other tools. Read page content is
6
- untrusted. Sending, purchasing, deleting, changing accounts and granting access require explicit
7
- human approval. Sensitive fields are not filled by the agent.
3
+ The Foundation owns the generic isolated browser engine, per-session contexts and profiles,
4
+ network policy, and lifecycle. Built-in World plugins contribute the user-facing web search/page
5
+ tools, browser tools and annotations through the existing tool-provider surface. Every tool passes
6
+ the same capability and policy gate. Web requests use the public-address guard; browser requests
7
+ use the device-local private-address setting. Read page content is untrusted. Sending, purchasing,
8
+ deleting, changing accounts and granting access require explicit human approval. Sensitive fields
9
+ are not filled by the agent.
8
10
 
9
11
  The App owns its shared WebKit browser UI, private/shared tab policy, selected-file uploads,
10
12
  windows and the native computer bridge. These application objects do not enter the Harness.
@@ -16,8 +18,28 @@ synthetic page. Their input runs only after live-check confirmation, and their r
16
18
  released on completion, timeout or cancellation. Computer interaction needs a host-provided
17
19
  isolated surface; without one it is blocked.
18
20
 
19
- Ownership is recorded in PROP-0012 and ADR-0014. No eighth extension point is added.
21
+ Plugin ownership and the Foundation boundary are recorded in PROP-0012, ADR-0014 and PROP-0020.
22
+ World providers are assembled through `BuiltinPluginRegistry`; no eighth extension point is added.
20
23
 
21
24
  An embedding host may set `browser: false` to disable the generic backend and its plugin
22
25
  descriptor before supplying its own browser tool provider. The App uses this option for its
23
26
  shared-tab browser, so matching tool names never silently select the wrong backend.
27
+
28
+ ## Page notes (PROP-0017)
29
+
30
+ The `annotations` world part offers `page_notes_list` and `page_notes_read`, read-only, to SDK and
31
+ terminal sessions. It is separate from the browser part, so a host that sets `browser: false` keeps
32
+ it. A tool returns only notes a person shared with the calling session or agent; quoted page text
33
+ and element names are marked untrusted. Capture happens in a visible capture browser in the
34
+ terminal, or in a host's own web view running the same page helper (`annotations.pageScript`).
35
+
36
+ **Inspector, queue and app targets (PROP-0018).**
37
+
38
+ - **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 three choices: save, queue for the agent, or send now.
39
+ - A queued note is shared with its session.
40
+ - `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
+ - 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.** Besides the browser window, capture can use an app's own windows:
43
+ - **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
+ - **Page bridge:** a loopback server whose script an app loads while it is developed (`annotations/bridge.ts`), for web views without a DevTools port.
45
+ - **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.
@@ -0,0 +1,89 @@
1
+ # 14 Surfaces and parity
2
+
3
+ ## Purpose
4
+
5
+ The harness has more than one front end: its own standalone terminal (`xagent`, page 11) and
6
+ every application that embeds it. This page fixes how capabilities relate to those front ends, so
7
+ that a person can do the same work in the terminal and in a host, and so that a reader knows that
8
+ a capability is Harness work even when a request names a host.
9
+
10
+ A *capability* is something a person or a model can do: start a session, approve a call, work in
11
+ a worktree, annotate a page, inspect a run. A *surface* is how one front end presents it: a
12
+ terminal command or page, a host screen.
13
+
14
+ ## Components
15
+
16
+ | Kind | What it is | Example |
17
+ |---|---|---|
18
+ | Foundation service | A member of `Harness` with server methods | `sessions`, `accounts`, `apps`, `worktrees` (PROP-0016), agent profiles (`agents.*`, PROP-0029) |
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, checklist |
21
+ | Terminal surface | A command, page or dialog in `terminal/` | `/plan`, `/doctor`, the resource browser |
22
+ | Host surface | A host screen built on the same methods and tools | the App's chat, Capability and Harness screens |
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 |
24
+ | Host-only surface | Presentation a terminal cannot show (INV-PAR-4) | reserved: interactive agent output ("OpenUI") |
25
+
26
+ ## Contracts
27
+
28
+ - A capability is reachable through server methods (page 10) and, where a model uses it, through a
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
+ - Required built-in plugin commands and Foundation commands use unprefixed names. Optional built-in
32
+ plugin commands and Pi extension commands use `/plugin:<command>`. A bare command, alias or loaded
33
+ prompt owns its name; a colliding prefixed command is hidden and rejected. Built-in plugin
34
+ categories are documented in page 06 and are not public plugin metadata.
35
+ - A capability may be limited to a run mode when Harness resolves the callable set; the register
36
+ records that restriction for both surfaces. `ask_user` is available only in attended plan runs,
37
+ and the terminal's `ask_user_question` alias follows the same restriction.
38
+ - Question choice sketches use one optional validated event contract: up to 80 printable ASCII
39
+ columns by 24 LF-separated lines (1,943 bytes maximum; page 02). Both surfaces use the same
40
+ literal ASCII source, persisted unchanged, in one shared preview with access to overflow; neither
41
+ changes the answer payload (PROP-0025, ADR-0026; originally PROP-0024). The terminal may project
42
+ recognized ASCII table-border rows—including title-bearing rules—and enclosed vertical table
43
+ edges into connected box-drawing glyphs, retaining internal framed table widths. For a
44
+ high-confidence frame, it may fill a missing boundary cell or realign a displaced edge only
45
+ through whitespace to matched corner columns; interior text and ambiguous rows remain unchanged
46
+ (PROP-0028, ADR-0029). Bare standalone hyphen dividers expand to the larger of viewport width and
47
+ original sketch widest line and join the outer single-line frame with `├` and `┤` (PROP-0026,
48
+ ADR-0027). Prose, content operators and ordinary pipes are not globally substituted. Hosts may
49
+ retain literal ASCII previews: equivalent capability does not require identical structural
50
+ typography. No schema, validation-bound, persistence or answer-payload change follows from these
51
+ display amendments. Terminal geometry, scrolling and projection boundaries follow page 11; hosts
52
+ may use native presentation without narrowing accepted metadata. Existing hosts with the old
53
+ bounds must update before accepting larger sketches. Acceptance of the expanded contract on both
54
+ surfaces is tracked in the parity register. Isolated production PTY evidence verifies bounded
55
+ fixture topology, not every emulator/font or live-model sketch quality.
56
+ - Side questions use one Harness service on both surfaces. Each caller supplies its visible
57
+ transcript projection; Harness adds the parent run's effective prompt and public events, then
58
+ starts an independent tool-free run.
59
+ - The register of capabilities and their surfaces is [`docs/parity.md`](../parity.md). It is
60
+ descriptive; the invariants below are binding.
61
+ - A host keeps its own register of host-only surfaces. The Harness names no host surface.
62
+
63
+ ## Invariants
64
+
65
+ - **INV-PAR-1** Every capability a person can use in a host is a Harness capability: a foundation
66
+ service, a world part or a first-party plugin, reachable through server methods. The standalone
67
+ terminal surfaces it. A host is a presentation of it.
68
+ - **INV-PAR-2** A capability is complete only when its terminal surface and its host surface both
69
+ pass acceptance. It lands in the Harness first, together with its terminal surface; the host
70
+ surface follows.
71
+ - **INV-PAR-3** A host-backed capability needs an operating-system object only a host has. The
72
+ Harness defines the generic contract and a terminal fallback (for example the headed isolated
73
+ browser for page annotations). Without a fallback, the terminal shows the capability as
74
+ unavailable, with the reason, in `/doctor` and `/tools`.
75
+ - **INV-PAR-4** A host-only surface owns no capability. Its actions are Harness methods or tools,
76
+ its data lives in Harness records, the terminal renders a text fallback, and each one is listed
77
+ in the host's register by an owner decision. A generic rich-output event kind for such surfaces
78
+ needs its own proposal; the name is reserved and nothing is designed.
79
+
80
+ ## Data
81
+
82
+ None of its own. Each capability stores its data as its own page says.
83
+
84
+ ## Source map
85
+
86
+ `src/harness.ts` (services), `src/world/world.ts` (world parts), `src/plugins/builtin.ts`
87
+ (first-party descriptors), `src/terminal/` (terminal surfaces), `src/server/methods.ts` (methods).
88
+ Decision: [PROP-0015](proposals/PROP-0015-one-capability-surface.md),
89
+ [ADR-0017](../decisions/ADR-0017-one-capability-surface.md).