@xingular/harness 0.1.7 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +36 -13
  3. package/dist/cli.js +10728 -8033
  4. package/dist/terminal-pi.js +365 -24
  5. package/docs/README.md +3 -0
  6. package/docs/decisions/ADR-0002-native-subagent-lifecycle.md +49 -0
  7. package/docs/decisions/ADR-0003-shared-asynchronous-subagents.md +70 -0
  8. package/docs/decisions/ADR-0004-fullscreen-terminal-layout.md +49 -0
  9. package/docs/decisions/ADR-0005-app-provided-oauth-clients.md +54 -0
  10. package/docs/terminal-tui.md +109 -13
  11. package/package.json +5 -4
  12. package/src/accounts/accounts.test.ts +87 -1
  13. package/src/accounts/accounts.ts +120 -18
  14. package/src/core/bus.test.ts +22 -0
  15. package/src/core/bus.ts +17 -2
  16. package/src/harness.ts +12 -2
  17. package/src/hub/hub.test.ts +49 -1
  18. package/src/hub/hub.ts +122 -6
  19. package/src/hub/schema.ts +13 -1
  20. package/src/index.ts +7 -2
  21. package/src/mcp/connections.ts +39 -12
  22. package/src/mcp/service.test.ts +49 -3
  23. package/src/mcp/service.ts +14 -3
  24. package/src/mcp/types.ts +10 -0
  25. package/src/memory/curation.test.ts +44 -1
  26. package/src/memory/dispatch.ts +5 -0
  27. package/src/memory/maintenance.test.ts +17 -1
  28. package/src/memory/maintenance.ts +169 -8
  29. package/src/memory/recall.ts +2 -1
  30. package/src/memory/trajectory.test.ts +178 -0
  31. package/src/memory/trajectory.ts +220 -0
  32. package/src/memory/wiki.ts +2 -1
  33. package/src/memory/wikiIndex.ts +3 -2
  34. package/src/plugins/builtin.ts +4 -2
  35. package/src/plugins/catalogue.test.ts +1 -1
  36. package/src/server/methods.ts +8 -0
  37. package/src/server/server.test.ts +20 -1
  38. package/src/sessions/approvals.test.ts +49 -0
  39. package/src/sessions/approvals.ts +26 -4
  40. package/src/sessions/conversation.test.ts +56 -0
  41. package/src/sessions/lineageJoin.ts +1 -1
  42. package/src/sessions/planMode.test.ts +40 -0
  43. package/src/sessions/planMode.ts +57 -0
  44. package/src/sessions/registry.ts +38 -7
  45. package/src/sessions/runStore.ts +14 -0
  46. package/src/sessions/runner.ts +9 -3
  47. package/src/sessions/sessions.test.ts +69 -7
  48. package/src/sessions/sessions.ts +47 -39
  49. package/src/sessions/subagentService.test.ts +159 -0
  50. package/src/sessions/subagentService.ts +236 -0
  51. package/src/sessions/subagents.ts +97 -0
  52. package/src/terminal/controller.ts +73 -10
  53. package/src/terminal/piExtension.ts +42 -6
  54. package/src/terminal/socket.test.ts +23 -0
  55. package/src/terminal/socket.ts +42 -18
  56. package/src/terminal/standalone.ts +12 -0
  57. package/src/terminal/terminal.test.ts +150 -15
  58. package/src/terminal/terminals.ts +113 -5
  59. package/src/terminal/trajectory.test.ts +66 -0
  60. package/src/terminal/trajectory.ts +44 -0
  61. package/src/terminal/tui/application.test.ts +206 -9
  62. package/src/terminal/tui/application.ts +251 -81
  63. package/src/terminal/tui/commands.test.ts +70 -9
  64. package/src/terminal/tui/commands.ts +99 -7
  65. package/src/terminal/tui/editor.test.ts +56 -27
  66. package/src/terminal/tui/editor.ts +64 -19
  67. package/src/terminal/tui/keybindings.test.ts +7 -0
  68. package/src/terminal/tui/keybindings.ts +9 -1
  69. package/src/terminal/tui/planMode.test.ts +10 -0
  70. package/src/terminal/tui/planMode.ts +2 -0
  71. package/src/terminal/tui/runtime.socket.test.ts +77 -3
  72. package/src/terminal/tui/runtime.test.ts +10 -0
  73. package/src/terminal/tui/runtime.ts +24 -9
  74. package/src/terminal/tui/screen.test.ts +143 -0
  75. package/src/terminal/tui/screen.ts +121 -0
  76. package/src/terminal/tui/skillInvocation.test.ts +71 -0
  77. package/src/terminal/tui/skillInvocation.ts +51 -0
  78. package/src/terminal/tui/status.test.ts +24 -46
  79. package/src/terminal/tui/status.ts +42 -69
  80. package/src/terminal/tui/theme.ts +18 -7
  81. package/src/terminal/tui/trajectoryPanel.test.ts +99 -0
  82. package/src/terminal/tui/trajectoryPanel.ts +226 -0
  83. package/src/terminal/tui/transcript.test.ts +14 -0
  84. package/src/terminal/tui/transcript.ts +11 -0
  85. package/src/terminal/tui/ui.ts +2 -2
  86. package/src/terminal/tui/welcome.ts +4 -4
  87. package/src/terminal/tui/workingStatus.test.ts +44 -0
  88. package/src/terminal/tui/workingStatus.ts +238 -0
  89. package/src/tools/definitions.ts +42 -1
  90. package/src/tools/maintenance.ts +6 -1
  91. package/src/tools/spawnSubagent.ts +40 -85
  92. package/src/tools/types.ts +4 -0
  93. package/docs/evidence/terminal-2026-10-17/120x40-completed-transcript.ansi.gz +0 -0
  94. package/docs/evidence/terminal-2026-10-17/40x20-settings-interaction.ansi.gz +0 -0
  95. package/docs/evidence/terminal-2026-10-17/40x20-settings-keyboard.ansi.gz +0 -0
  96. package/docs/evidence/terminal-2026-10-17/40x20-welcome.ansi.gz +0 -0
  97. package/docs/evidence/terminal-2026-10-17/80x24-approval-0.ansi.gz +0 -0
  98. package/docs/evidence/terminal-2026-10-17/80x24-question.ansi.gz +0 -0
  99. package/docs/evidence/terminal-2026-10-17/verification.json +0 -130
  100. package/docs/evidence/terminal-2026-10-17-followup/120x40-completed-transcript.ansi.gz +0 -0
  101. package/docs/evidence/terminal-2026-10-17-followup/40x20-settings-interaction.ansi.gz +0 -0
  102. package/docs/evidence/terminal-2026-10-17-followup/40x20-settings-keyboard.ansi.gz +0 -0
  103. package/docs/evidence/terminal-2026-10-17-followup/40x20-welcome.ansi.gz +0 -0
  104. package/docs/evidence/terminal-2026-10-17-followup/80x24-approval-0.ansi.gz +0 -0
  105. package/docs/evidence/terminal-2026-10-17-followup/80x24-plugin-light.ansi.gz +0 -0
  106. package/docs/evidence/terminal-2026-10-17-followup/80x24-question-batch.ansi.gz +0 -0
  107. package/docs/evidence/terminal-2026-10-17-followup/80x24-question.ansi.gz +0 -0
  108. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-approval-0.ansi.gz +0 -0
  109. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-plugin-light.ansi.gz +0 -0
  110. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-question-batch.ansi.gz +0 -0
  111. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/80x24-question.ansi.gz +0 -0
  112. package/docs/evidence/terminal-2026-10-17-followup/app-bundle/verification.json +0 -95
  113. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-approval-0.ansi.gz +0 -0
  114. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-plugin-light.ansi.gz +0 -0
  115. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-question-batch.ansi.gz +0 -0
  116. package/docs/evidence/terminal-2026-10-17-followup/global-install/80x24-question.ansi.gz +0 -0
  117. package/docs/evidence/terminal-2026-10-17-followup/global-install/README.md +0 -27
  118. package/docs/evidence/terminal-2026-10-17-followup/global-install/shell-command-80x24.ansi.gz +0 -0
  119. package/docs/evidence/terminal-2026-10-17-followup/global-install/shell-command.json +0 -18
  120. package/docs/evidence/terminal-2026-10-17-followup/global-install/verification.json +0 -95
  121. package/docs/evidence/terminal-2026-10-17-followup/harness-reference-80x24.json.gz +0 -0
  122. package/docs/evidence/terminal-2026-10-17-followup/harness-reference-final-80x24.json.gz +0 -0
  123. package/docs/evidence/terminal-2026-10-17-followup/harness-reference-scenario.json +0 -60
  124. package/docs/evidence/terminal-2026-10-17-followup/live-codex/README.md +0 -24
  125. package/docs/evidence/terminal-2026-10-17-followup/live-codex/complete-80x24.ansi.gz +0 -0
  126. package/docs/evidence/terminal-2026-10-17-followup/live-codex/verification.json +0 -57
  127. package/docs/evidence/terminal-2026-10-17-followup/omp-reference-80x24-early.json.gz +0 -0
  128. package/docs/evidence/terminal-2026-10-17-followup/omp-reference-80x24.json.gz +0 -0
  129. package/docs/evidence/terminal-2026-10-17-followup/omp-reference-scenario.json +0 -58
  130. package/docs/evidence/terminal-2026-10-17-followup/omp-supplemental-static.json.gz +0 -0
  131. package/docs/evidence/terminal-2026-10-17-followup/rea-artifacts.json +0 -320
  132. package/docs/evidence/terminal-2026-10-17-followup/reference-comparison.json +0 -30
  133. package/docs/evidence/terminal-2026-10-17-followup/reference-comparison.md +0 -133
  134. package/docs/evidence/terminal-2026-10-17-followup/reference-source-observations.json +0 -20
  135. package/docs/evidence/terminal-2026-10-17-followup/verification.json +0 -207
package/CHANGELOG.md CHANGED
@@ -2,6 +2,26 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 2.1.0 - 2026-10-19
6
+
7
+ - Add per-request plan mode to SDK session runs: instructions arrive as a dynamic context update, and the tool gate refuses calls outside the read-only set. The terminal uses `/plan`, `/plan on`, and `/plan off` to narrow its active tools.
8
+ - Add bounded, UTF-8-safe Hub payload previews, explicit installed/changed/incomplete receipt states, and receipt-scoped uninstall that removes owned resources, including local edits within those paths.
9
+ - Highlight recognized leading slash commands in the terminal composer with the selected theme's link color, including enabled `/skill:name` invocations; unknown commands remain plain.
10
+
11
+ ## 2.0.0 - 2026-10-18
12
+
13
+ - Let a connected app sign in with an OAuth client the application registered itself (`oauthClient: 'app'`), supplied through `HarnessOptions.oauthClients` and never stored; `connections.appClients` reports which catalog entries a build can sign in for. See [ADR-0005](docs/decisions/ADR-0005-app-provided-oauth-clients.md).
14
+ - Invoke a skill in the terminal as `$name` instead of `/skill:name`: the completion offers the loaded skills at a `$`, and a leading `$name` is sent to the model as that skill. A typed `/skill:name` still works, and `$` followed by a number or an unknown name stays ordinary text.
15
+ - Keep a stored key or sign-in when a terminal that began before it was saved ends, and let several terminals of one account share its auth.json across processes: a terminal saves only what its own Pi changed, and the last terminal out removes the file.
16
+ - Give every session bounded `trajectory_search` and `trajectory_read` tools for inspecting recorded run events without exposing credentials, attachments, or provider reasoning.
17
+ - Show terminal notices, such as mode changes, errors and the keyboard list, as rows in the conversation instead of above the composer; queued messages stay in the dock.
18
+ - Step the terminal's thinking effort with Shift+Up and Shift+Down within the levels the model supports. Shift+Tab toggles a read-only plan mode that withdraws changing tools until it is switched back.
19
+ - Show the product lockup above the terminal transcript only until the chat has a user message; a resumed session with history starts without it, and a header from a trusted extension is never hidden.
20
+ - Keep the terminal composer on the last rows in fullscreen while the transcript scrolls above it; `tuiMode: regular` keeps the flowing layout, and leaving fullscreen copies the conversation into scrollback.
21
+ - Add one native asynchronous subagent service for SDK, RPC and standalone terminal callers, with selective waits, parent joins, typed history receipts and explicit-resume recovery.
22
+ - Preserve capability ceilings and route child approvals/questions through the owning terminal; release pending interactions before SDK abort.
23
+ - Show a stable rotating work verb with an animated status glyph and keep the completion duration until the next turn.
24
+
5
25
  - Harness owns the standalone terminal frontend, using persistent Pi 1.2.0 sessions and the inspected Oh My Pi 18.11.3 presentation.
6
26
  - Add titanium and light themes, native session navigation, local command help and completion, account/plugin/Hub controls, and trusted extension UI hosting.
7
27
  - Keep account isolation, exact prepared context and resource selection, the final tool gate, native histories and Harness run recording.
package/README.md CHANGED
@@ -8,7 +8,7 @@ needs to work for someone over time, and nothing about any particular applicatio
8
8
  | Accounts | `src/accounts/` | Several isolated Pi accounts and pools, sign-in, model lists, health and limits. A session keeps the account it started with. |
9
9
  | Sessions | `src/sessions/` | Pi SDK turns, run records and `events.jsonl`, interrupt, approvals, questions, recovery after a crash. |
10
10
  | Prompt | `src/prompt/` | The system prompt compiled from sections with budgets and profiles; a stable prefix, and changing state delivered as updates in native history. |
11
- | Memory | `src/memory/` | The Wiki: pages, facts, memory blocks, revisions, proposals with an evidence gate, undo, an Inbox, recall over past runs, and sleep-time consolidation. |
11
+ | Memory | `src/memory/` | The Wiki: pages, facts, memory blocks, revisions, proposals with an evidence gate, undo, an Inbox, history recall, run trajectory inspection, and sleep-time consolidation. |
12
12
  | Skills | `src/skills/` | Skills, prompts, and rules: a person's own in the data root, and built-in ones shipped with the harness or the application. |
13
13
  | Plugins | `src/plugins/` | What a Pi session loads, chosen by the harness and never by Pi's own discovery; trust for a working folder's code; the list of every plugin and what reaches one caller. |
14
14
  | Tools | `src/tools/` | Tool definitions, the memory tools, `ask_user`; a gate that asks the application's policy, then standing approvals, then the person. |
@@ -21,11 +21,23 @@ The [documentation index](docs/README.md) links current terminal architecture an
21
21
 
22
22
  ### Session options for applications
23
23
 
24
- - `subagents: { maxDepth }` offers `spawn_subagent`: the model may start a child run of the same caller (`relation: 'subagent'`). The child has no more tools than the parent and settles before the tool returns.
24
+ - Interactive sessions offer `spawn_subagent` and `wait_subagents` by default. `subagents: null` disables them; `{ maxDepth }` configures native nesting (default one, maximum three), independently of the host caller depth. Unattended sessions remain disabled unless the host explicitly supplies subagent options. A frozen capability set can narrow these tools further.
25
+ - `harness.subagents.spawn({ parentRunId, brief, tools?, wait? })` opens a fresh child of the same caller with no wider capabilities. It returns `{ runId, nativeSessionId }` once open; `wait: true` also waits for settlement. `harness.subagents.wait({ parentRunId, runIds? })` joins selected direct children, or the current children when omitted, and returns their outcomes. `results` reads the same bounded outcome records without waiting. RPC exposes `subagents.spawn`, `subagents.wait`, and `subagents.results`; `sessions.spawnSubagent` remains a compatibility alias.
26
+ - The model's `spawn_subagent` returns immediately by default; `wait: true` returns an inline result. `wait_subagents` joins selected children. The SDK and standalone terminal share this execution service. Terminal calls use its private control channel, including when connected apps are disabled.
27
+ - Parents receive results at native turn boundaries and join outstanding children before completing. Typed native-history receipts prevent duplicate automatic delivery; explicit waits can reread results. Ownership is recorded before startup so an explicit resume can recover even a lost spawn return. Startup reservations without a run become interrupted outcomes. A restarted Harness never restarts model work automatically. Recovery requires the same recorded account, caller, working folder, and selected history branch. Session IDs are opaque; consumers follow `parentRunId` and `relation`.
25
28
  - `providers: false` runs a session with the harness's own tools only.
26
- - On the caller, `vaultAccess: 'propose'` writes no memory directly, and `recallExcludeAgents` hides those agents' conversations from recall.
29
+ - On the caller, `vaultAccess: 'propose'` writes no memory directly, and `recallExcludeAgents` hides those agents' conversations from history and trajectory tools.
27
30
  - `maintenanceRunTrigger: false` (a harness option) leaves memory to explicit proposals and scheduled merges.
28
31
 
32
+ Every session also gets `trajectory_search` and `trajectory_read` from the built-in History plugin.
33
+ Search lists runs in the current data root, including active runs, with filters and a continuation
34
+ cursor. Read returns pages of the canonical execution events, including captured prompt/context,
35
+ tool, decision, retry, compaction, and usage evidence. Active runs show the latest events saved so
36
+ far; settled reads stop at the first outcome. Payloads are bounded and marked when truncated, and
37
+ the tools omit account identifiers, credential fields, attachment bytes, native adapter payloads,
38
+ and provider reasoning text or summaries.
39
+ They report recorded evidence without scoring runs, and do not backfill older records.
40
+
29
41
  ## Using it from Node
30
42
 
31
43
  ```ts
@@ -256,8 +268,8 @@ again to load the new frontend. A package version alone cannot distinguish an un
256
268
  build from an older installed build with the same version.
257
269
 
258
270
  This opens the Harness-owned terminal frontend in the current working directory. Its
259
- presentation follows the inspected Oh My Pi 18.11.3 titanium and light palettes, centered welcome, filled
260
- status band and curved `╰─` prompt, with Harness identity and existing capabilities. Harness
271
+ presentation follows the inspected Oh My Pi 18.11.3 titanium and light palettes, centered welcome,
272
+ colored text statusline and curved `╰─` prompt, with Harness identity and existing capabilities. Harness
261
273
  owns screen composition, editing/input dispatch, scrolling, command routing and plugin UI;
262
274
  Pi supplies the persistent execution runtime, native history and rich content components.
263
275
  The existing isolated account, compiled context, approval gate, telemetry and Wiki/socket
@@ -266,7 +278,10 @@ commands remain behind the terminal. No Pi `InteractiveMode` is constructed.
266
278
  `/resume` stays inside the prepared history and working folder; `/import` accepts an explicitly
267
279
  selected native JSONL file only for the same working folder. Cancel an active response before
268
280
  changing or reloading a session. Full OMP visual parity is not established by the current
269
- verification. See [terminal architecture and evidence](docs/terminal-tui.md),
281
+ verification. `/permissions` reviews device-local Pi terminal grants and the Full Permission switch;
282
+ tool grants apply across terminal sessions sharing this Harness state, and Full Permission requires
283
+ confirmation. `/trajectory` opens recorded runs for the current native conversation, with event
284
+ navigation and a detail inspector. See [terminal architecture and evidence](docs/terminal-tui.md),
270
285
  [the decision](docs/decisions/ADR-0001-owned-terminal.md), and [third-party notices](NOTICE.md).
271
286
 
272
287
  ### `/accounts` in the terminal
@@ -295,7 +310,7 @@ command. The explicit `terminal` command is an alias for the default launch. Use
295
310
  wiki/ home.md, library/, projects/<slug>/, facts/, blocks/, revisions, inbox, log
296
311
  registry/ skills/, prompts/, rules/ (a person's own; never copied)
297
312
  plugins/<name>/ packages kept with a person's data; each is found as an installed plugin
298
- runs/<id>/ run.json, events.jsonl, context.json, caller.json
313
+ runs/<id>/ run.json, events.jsonl, context.json, caller.json, subagents.json (reserved child IDs)
299
314
  config/ context profiles, what is switched on for whom (plugin-attachments.json),
300
315
  settings the harness reads
301
316
  index.sqlite a rebuildable index of Wiki entries and runs (FTS5)
@@ -309,6 +324,7 @@ command. The explicit `terminal` command is an alias for the default launch. Use
309
324
  plugin-hooks.json what each hooks file listens for and how its last run went
310
325
  connections.json connected apps (secrets are in the SecretStore)
311
326
  run/ the session socket and the terminal commands
327
+ harness.log diagnostics from the standalone terminal, kept off its screen
312
328
  ```
313
329
 
314
330
  The files are the source of truth; `index.sqlite` can be deleted and rebuilt
@@ -332,14 +348,18 @@ Node 22.19 or newer.
332
348
  `xingular-harness hub list [--refresh]`, `hub show publisher/name@version`, and
333
349
  `hub install publisher/name@version` browse and install exact catalog versions. `/hub` offers the
334
350
  same review in the interactive terminal, using its private control key for installation. Both the
335
- terminal and embedding applications use `hub.list`, `hub.get`, `hub.install`, and `hub.readDocument`.
336
- `hub.get { id, version, preview: true }` verifies data payload bytes without installing them.
351
+ terminal and embedding applications use `hub.list`, `hub.get`, `hub.preview`, `hub.install`,
352
+ `hub.uninstall`, and `hub.readDocument`. `hub.get { id, version, preview: true }` verifies data
353
+ payload bytes without installing them. `hub.preview { id, version, offset }` returns bounded,
354
+ UTF-8-safe pages of up to 16 KiB from a verified payload.
337
355
 
338
356
  Registry bundles import complete skills or single Markdown prompts/rules, disabled. Pi packages
339
357
  reuse the existing installer and require an exact npm version or full GitHub commit. Documents
340
358
  are saved as inert JSON for a compatible host to interpret; the harness does not apply them.
341
359
  Installation grants no attachment, trust, credentials, or permission. Writes are serialized and
342
- existing registry files are never overwritten.
360
+ existing registry files are never overwritten. Receipts report whether their resources are intact;
361
+ uninstall removes only the exact receipt's resources, including local edits within those paths, and
362
+ revokes its attachment choices.
343
363
 
344
364
  Installed documents and provenance live under `<data root>/hub/`; the catalog cache is
345
365
  `<state dir>/hub/catalog.json`. An offline snapshot ships with the package. Explicit refresh keeps
@@ -358,9 +378,12 @@ An embedding application may set `externalMaintenance: true`, supply trusted `Ca
358
378
  `vaultAccess` (`self` or `curator`), and register `maintenanceTools`/`MAINTENANCE_PLUGIN`.
359
379
  Self callers directly edit only their own writable persona/notes; shared knowledge and text-resource
360
380
  writes become persistent proposals. Curator tools read original evidence, compare captured target
361
- revisions, apply reviewed changes, persist receipts and undo without overwriting later edits.
381
+ revisions, read all host-assigned requests together, and apply reconciled Wiki proposals as one
382
+ undoable change set. Resource proposals keep their own receipts; executable proposals remain inert
383
+ until the user reviews/trusts them. Later user edits are never overwritten.
362
384
  `maintenance.list`, `maintenance.review` and `maintenance.retry` let the host dispatch its own
363
385
  recorded sessions. Curator runs do not recursively queue maintenance. Optional assigned IDs freeze
364
386
  which requests a batch may claim. These fields are trusted host context, never model arguments.
365
- Executable proposals remain inert until the user reviews/trusts them. Standalone callers that omit
366
- this option retain the existing lifecycle and direct-write contract.
387
+ `maintenance_read_batch` reads those assigned requests together; `maintenance_apply_batch` records
388
+ one decision for each and applies the evidence-checked Wiki set atomically. Standalone callers that
389
+ omit this option retain the existing lifecycle and direct-write contract.