@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
package/docs/README.md
CHANGED
|
@@ -17,6 +17,9 @@ change the binding architecture or describe implemented capabilities.
|
|
|
17
17
|
|
|
18
18
|
| ID | Record | Type | Status | Related |
|
|
19
19
|
|---|---|---|---|---|
|
|
20
|
+
| ADR-0047 | [A link a person clicks opens with the system's handler](decisions/ADR-0047-links-open-with-the-os-handler.md) | Decision | Implemented in the Harness, the terminal and the App; acceptance not certified | [10 Server protocol](architecture/10-server-protocol.md), [parity register](parity.md) |
|
|
21
|
+
| ADR-0046 | [Hash-bound plugin proposal review](decisions/ADR-0046-hash-bound-plugin-proposals.md) | Decision | Harness API and model proposal tool implemented; review surfaces pending | [06 Plugins](architecture/06-plugins-and-capabilities.md), [parity register](parity.md) |
|
|
22
|
+
| ADR-0045 | [Release-owned plugin-authoring skill](decisions/ADR-0045-default-plugin-authoring-skill.md) | Decision | Implemented as an on-demand resource | [06 Plugins](architecture/06-plugins-and-capabilities.md) |
|
|
20
23
|
| PROP-0026 | [Connect structural sketch lines in the terminal display](architecture/proposals/PROP-0026-connected-sketch-display.md) | Proposal | Implemented; working tree and isolated fixtures verified | [ADR-0027](decisions/ADR-0027-connected-sketch-display.md), [11 Terminal](architecture/11-terminal.md), [parity register](parity.md) |
|
|
21
24
|
| ADR-0027 | [Project structural ASCII sketch lines into connected terminal borders](decisions/ADR-0027-connected-sketch-display.md) | Decision | Accepted; working tree and isolated fixtures verified | [PROP-0026](architecture/proposals/PROP-0026-connected-sketch-display.md), [14 Surfaces and parity](architecture/14-surfaces-and-parity.md) |
|
|
22
25
|
| FW-0001 | [Agent Modes, starting with Router Agent Mode](future-work.md#fw-0001-agent-modes-starting-with-router-agent-mode) | Future work | Candidate; requires architecture proposal before implementation | [Architecture glossary](architecture/README.md#glossary), [Feature guide](features/README.md#planned-agent-modes) |
|
|
@@ -134,7 +134,7 @@ Modules with no member of their own: `variant/` (functions over the variant stor
|
|
|
134
134
|
| Letter | The harness owns |
|
|
135
135
|
|---|---|
|
|
136
136
|
| **E** Execution | Isolated account folders, the Pi session, the terminal launch spec |
|
|
137
|
-
| **T** Tools | History, trajectory, Wiki notes, skill loading, `ask_user`, the run
|
|
137
|
+
| **T** Tools | History, trajectory, Wiki notes, skill loading, `ask_user`, the run todo list, the connected-apps broker, the tool gate |
|
|
138
138
|
| **C** Context | The compiler, stable prefix and updates, the versioned variant (c1–c8), skills, on-demand Wiki notes |
|
|
139
139
|
| **L** Lifecycle | Run state, interrupt, recovery, approvals and questions, subagents, refinement |
|
|
140
140
|
| **O** Observability | Validated run events saved per run; usage counters |
|
|
@@ -50,7 +50,7 @@ harness forwards to the policy and never reads.
|
|
|
50
50
|
## Invariants
|
|
51
51
|
|
|
52
52
|
- **INV-EXT-1** There are seven extension points. Adding, removing or changing the shape of one is
|
|
53
|
-
an architecture change
|
|
53
|
+
an architecture change; update this page and affected contracts in the same change.
|
|
54
54
|
- **INV-EXT-2** Every extension point is optional. The harness runs with none of them supplied.
|
|
55
55
|
- **INV-EXT-3** An extension point carries data or decisions the application owns. It never
|
|
56
56
|
carries an application's name or a branch for one application (`INV-BND-3`).
|
|
@@ -13,7 +13,7 @@ records everything the run does as validated events.
|
|
|
13
13
|
|---|---|---|
|
|
14
14
|
| `Sessions` | `sessions/sessions.ts` | Starts a turn: `run(input: SessionRunInput)`, `provide(provider)`. Builds the gate. |
|
|
15
15
|
| `runTurn`, `piSessionFactory`, `loadResources` | `sessions/runner.ts` | Opens the Pi session, loads resources in a fixed order, streams events, settles the run. |
|
|
16
|
-
| compaction checkpoint | `sessions/compactionCheckpoint.ts` | Restores the active request's bounded goal,
|
|
16
|
+
| compaction checkpoint | `sessions/compactionCheckpoint.ts` | Restores the active request's bounded goal, todo list and plan instructions to model context after compaction. |
|
|
17
17
|
| `RunRegistry`, `ActiveRun` | `sessions/registry.ts` | Live runs: `emit`, `requestApproval`, `requestAnswer(s)`, `onInterrupt`, `onSteer`, `finish`; `listen` for observers. |
|
|
18
18
|
| run store functions | `sessions/runStore.ts` | `saveRun`, `updateRun`, `persistEvent`, `appendEvent`, `readEvents`, `markInterruptedRuns`, `runFamily`, `listRuns`. |
|
|
19
19
|
| `RunRecord`, `RunEvent`, schemas | `sessions/contracts.ts` | The one contract every session shares. |
|
|
@@ -55,7 +55,7 @@ A session that cannot open ends its run as `failed` and returns `nativeSessionId
|
|
|
55
55
|
`message.completed`, `message.steered`, `tool.started`, `tool.completed`, `retry.started`,
|
|
56
56
|
`retry.ended`, `compaction.started`, `compaction.ended`, `approval.requested`,
|
|
57
57
|
`approval.resolved`, `question.requested`, `question.answered`, `extension.notice`,
|
|
58
|
-
`reaction.added`, `agent.message`, `
|
|
58
|
+
`reaction.added`, `agent.message`, `todo.updated`, `artifact.added`, `file.changed`, `usage.updated`,
|
|
59
59
|
`account.status`, `status.changed`, `failed`, `completed`. Each has a payload schema in
|
|
60
60
|
`runEventPayloadSchemas`.
|
|
61
61
|
- **Workspace root** (`RunRecord.workspaceRoot`) is the canonical root whose filesystem effects
|
|
@@ -76,9 +76,10 @@ A session that cannot open ends its run as `failed` and returns `nativeSessionId
|
|
|
76
76
|
across alternatives; generation quality is guidance, not a schema guarantee. Old events remain
|
|
77
77
|
valid without a data rewrite; readers with the old bounds must update before accepting larger
|
|
78
78
|
sketches. `question.answered` and `QuestionAnswer` are unchanged.
|
|
79
|
-
- **
|
|
80
|
-
`
|
|
81
|
-
items. The latest event replaces every earlier one; `
|
|
79
|
+
- **Todo list** (PROP-0006, renamed by PROP-0045): `todo.updated` carries the whole list the model
|
|
80
|
+
last wrote with `todo_write`, `{ items: { text, status: pending | in_progress | completed }[] }`, at
|
|
81
|
+
most 50 items. The latest event replaces every earlier one; `todoOf(events)` reads it. The
|
|
82
|
+
pre-rename `checklist.updated` is still read so old runs keep their list, and is never written.
|
|
82
83
|
- **`RunRecord`** fields are listed in `sessions/contracts.ts`. `mode`, `harness`, `sessionType`,
|
|
83
84
|
`worktreeId`, `attachmentCount`, `exitCode`, `handoffId` and `trigger` belong to the
|
|
84
85
|
application: stored and returned, and only `mode` and `trigger` are read.
|
|
@@ -97,12 +98,24 @@ A session that cannot open ends its run as `failed` and returns `nativeSessionId
|
|
|
97
98
|
`results` for the host (`sessions.spawnSubagent` is a compatibility alias). Child runs have
|
|
98
99
|
`relation: 'subagent'` and `parentRunId`. Nesting defaults to 1, at most 3 (`subagentDepth`).
|
|
99
100
|
The child's record carries `title`, the short name the parent gave it (PROP-0030).
|
|
101
|
+
`spawn_subagent { continue: <runId> }` (`subagents.spawn { continue }`) continues a child that
|
|
102
|
+
stopped before finishing as a new child run with `continueFrom`. It reopens the first link's
|
|
103
|
+
history folder and keeps the earlier child's session id, profile, title, account, variant version
|
|
104
|
+
and frozen capability set, which must still lie within the parent's; `agent` and `tools` are
|
|
105
|
+
refused with it, and the newest link of a chain is the one continued (ADR-0043). Children an
|
|
106
|
+
earlier reply left stopped are delivered before the next reply's first request, each with a
|
|
107
|
+
note that it can be continued; a stopped child that was continued is reported through its
|
|
108
|
+
continuation. Every run record carries the launch `model` and `effort`, superseded by the model
|
|
109
|
+
the session opened with.
|
|
100
110
|
- **Agent profiles** (PROP-0029). `agent` names a profile: built-in (`worker`, `explorer`),
|
|
101
111
|
`<data root>/agents/<name>.md`, `<project>/.xingular/agents/<name>.md`, or a c5 definition of
|
|
102
|
-
the parent's variant, later sources winning (`agents/profiles.ts`). A
|
|
112
|
+
the parent's variant, later sources winning (`agents/profiles.ts`). A switched-on package's
|
|
113
|
+
profiles (page 06) then fill names nobody else took; the run resolves them once at start into
|
|
114
|
+
`packageProfiles`, and its children resolve their profiles from that list. A profile narrows the
|
|
103
115
|
child's tools and plugins (`agents/narrow.ts`), may choose its variant, model and effort, and
|
|
104
116
|
frames it with a "Your role" section. The child's record carries `profile`; the spawn result
|
|
105
|
-
carries `agent` and any `unavailableTools`.
|
|
117
|
+
carries `agent` and any `unavailableTools`. `main` is reserved for the main agent's row: no
|
|
118
|
+
profile file or variant definition may take it. A run that may spawn lists every profile in its
|
|
106
119
|
`subagents` section.
|
|
107
120
|
- **Plan mode** (`plan: true`). The stable system prompt is unchanged. An attended plan run may
|
|
108
121
|
include `ask_user` and `spawn_subagent` / `wait_subagents`, subject to the caller's frozen
|
|
@@ -122,15 +135,15 @@ A session that cannot open ends its run as `failed` and returns `nativeSessionId
|
|
|
122
135
|
The reply ends with one `<proposed_plan>` block.
|
|
123
136
|
- **Compaction checkpoint** (PROP-0033, ADR-0032). After compaction, an active run's model context
|
|
124
137
|
receives a bounded, ephemeral checkpoint with the current user request and the latest validated
|
|
125
|
-
|
|
138
|
+
todo list or applicable plan instructions, when either is available to restore. It is re-added to
|
|
126
139
|
each request while that run continues;
|
|
127
140
|
its state is cleared when the run settles or the session branch changes. The message changes no
|
|
128
141
|
tools, permissions, run events or native history. An interrupted run still uses the durable
|
|
129
|
-
|
|
142
|
+
todo list and normal continuation path.
|
|
130
143
|
- **Continuation** (PROP-0007). `continuationOf(root, runId, sessionDir?)` (`runs.continuation`)
|
|
131
144
|
says whether a stopped run can be continued: `resumable`, a `reason` when not (`not_found`,
|
|
132
145
|
`active`, `completed`, `no_history`, `history_missing`), the exact native history to reopen,
|
|
133
|
-
the pinned account, variant version and capability set, the
|
|
146
|
+
the pinned account, variant version and capability set, the todo list, unanswered approvals and
|
|
134
147
|
questions, the last tool and whether it finished, and subagents that did not finish.
|
|
135
148
|
`SessionRunInput.continueFrom` starts a **new** run from it: it reopens that history, records
|
|
136
149
|
`resumedFromRunId`, pins the same account, variant version and capability set (anything different
|
|
@@ -138,7 +151,8 @@ A session that cannot open ends its run as `failed` and returns `nativeSessionId
|
|
|
138
151
|
`continuation_unavailable`). If the earlier snapshot includes `ask_user`, an automatic or
|
|
139
152
|
refinement-triggered continuation fails with `continuation_mismatch` rather than narrowing it.
|
|
140
153
|
Empty text defaults to "Continue from where you stopped.", and the new run adds
|
|
141
|
-
a dynamic `continuation` section (order 26) saying where the earlier run stopped
|
|
154
|
+
a dynamic `continuation` section (order 26) saying where the earlier run stopped and that its
|
|
155
|
+
unfinished subagents can be continued with `spawn_subagent { continue }`. The next run
|
|
142
156
|
without `continueFrom` withdraws it. `Recovery.interruptedRunIds` lists the runs `open` marked
|
|
143
157
|
interrupted.
|
|
144
158
|
- **Worktrees** (PROP-0016). When `run.worktreeId` names a worktree in the Harness registry
|
|
@@ -203,7 +217,9 @@ is approved but remains in progress; no completed cross-surface catalog is impli
|
|
|
203
217
|
and never applied or relayed.
|
|
204
218
|
- **INV-RUN-4** A restarted harness never restarts model work. On `open`, runs left active are
|
|
205
219
|
marked `interrupted` unless another live process owns them (`owner.json`). Recovery of a
|
|
206
|
-
subagent needs the same account, caller, working folder and history branch
|
|
220
|
+
subagent needs the same account, caller, working folder and history branch; the history branch
|
|
221
|
+
(owner marker and native history id), not the host's session id, ties a parent to an earlier
|
|
222
|
+
one. A stopped subagent is continued only by its parent, through `spawn_subagent { continue }`. Continuing is always
|
|
207
223
|
a new run with `continueFrom`; it pins the earlier run's account, variant version and capability
|
|
208
224
|
set, and the earlier run's record is never reopened. The application asks for it, or the earlier
|
|
209
225
|
run's work-slice policy does when the reply stopped at its budget (PROP-0041); a run started
|
|
@@ -225,11 +241,15 @@ is approved but remains in progress; no completed cross-surface catalog is impli
|
|
|
225
241
|
plan may include `ask_user`, `spawn_subagent` and `wait_subagents`, subject to the frozen caller
|
|
226
242
|
capabilities; newly resolved normal, automatic, probe, improver and reflection runs omit
|
|
227
243
|
`ask_user`. Plan-mode spawning requires a named profile whose effective explicit tool and plugin
|
|
228
|
-
allowlists qualify for read-only research. The
|
|
229
|
-
|
|
244
|
+
allowlists qualify for read-only research. The prompt lists only profiles whose intersection with
|
|
245
|
+
the parent's frozen tools and plugin contributions includes a research evidence tool. An omitted
|
|
246
|
+
`tools` override inherits that safe intersection; an explicit override can only narrow it. The
|
|
247
|
+
child inherits plan mode and is narrowed to the intersection of the parent's frozen capabilities,
|
|
248
|
+
the profile and the plan research set; it has no
|
|
230
249
|
connectors, user questions, writes, commands or nested subagents. The plan run itself may run
|
|
231
|
-
Bash only in the OS-enforced read-only scope (PROP-0043, ADR-0038)
|
|
232
|
-
|
|
250
|
+
Bash only in the OS-enforced read-only scope (PROP-0043, ADR-0038); research children cannot run
|
|
251
|
+
commands. Generic browser actions and connected-app calls remain unavailable in plan mode. The
|
|
252
|
+
gate refuses unsafe calls before approvals, and the service rechecks before launch. The terminal activates plan-eligible
|
|
233
253
|
tools only for a plan request, then restores its normal set. Provider-cache effects of the tool-list
|
|
234
254
|
difference are not assumed (page 04, `INV-PRM-8`).
|
|
235
255
|
- **INV-RUN-9** Subagent results reach the parent at native turn boundaries, at most once
|
|
@@ -245,28 +265,39 @@ is approved but remains in progress; no completed cross-surface catalog is impli
|
|
|
245
265
|
surface's visible transcript and selected references. It excludes hidden reasoning and attachment
|
|
246
266
|
bytes, never reads the main native history, and never changes or steers the parent. Its own run
|
|
247
267
|
record and events use the normal store contract (PROP-0019).
|
|
248
|
-
- **INV-RUN-13** A reply is a bounded work slice (PROP-0041). The foundation defaults are
|
|
249
|
-
calls
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
268
|
+
- **INV-RUN-13** A reply is a bounded work slice (PROP-0041). The foundation defaults are 320 tool
|
|
269
|
+
calls and 60 minutes, whichever comes first, with no new-token limit (PROP-0044). A token cap is
|
|
270
|
+
available with `workSlice.maxNewTokens`, counted on new input, cache writes and output and never on
|
|
271
|
+
the cached prefix: a few large reads pass any small cap before useful work, so the tool calls and
|
|
272
|
+
the clock are the bound and the token count is only a ceiling for whoever asks for one. At the
|
|
273
|
+
limit the guard refuses the next tool call. When `checkpoint_write` is available, it requests a
|
|
274
|
+
checkpoint and leaves handoff calls callable; otherwise a plan-research child must stop with a
|
|
275
|
+
concise partial research report, and the runner derives a checkpoint from run evidence. A
|
|
276
|
+
non-handoff tool call after the refusal ends the reply. A budget-ended reply is `interrupted` with
|
|
277
|
+
terminal reason `slice_complete`; a reply ended by a stall guard is `stalled`.
|
|
278
|
+
The targeted stall guard identifies calls by name and every argument; three identical calls cause
|
|
279
|
+
one refusal, and a repeated trigger ends the reply. A Bash check that fails twice is a trigger. The
|
|
280
|
+
guard counts only successful native `edit`/`write` results (`isError === false`) with a path toward
|
|
281
|
+
the four-edit per-path churn limit; the next edit is refused, and a repeated trigger ends the
|
|
282
|
+
reply. Failed or blocked edits do not count. A successful edit/write clears failed-check counts,
|
|
283
|
+
identical Bash-check repeat counts and the pending nudge, but leaves edit counts and other
|
|
284
|
+
repeated-call counts intact. A passing check clears edit counts. The general 25-call file/check
|
|
285
|
+
no-progress trigger is removed. `todo_write` is bookkeeping: it is exempt from repeated-call
|
|
286
|
+
detection and does not reset loop state, but counts toward the tool-call budget. Third-compaction
|
|
287
|
+
thrash detection remains. Plan-research children without `checkpoint_write` receive the configured
|
|
288
|
+
bound without a new capability and do not auto-continue. A new run continues it only up to the
|
|
289
|
+
policy's slice cap, only after a slice that changed a file, passed a check or recorded a finished
|
|
290
|
+
item, and never after a checkpoint that is `blocked`. A run may turn the guard off with
|
|
291
|
+
`workSlice.enabled: false`, and a launch may set `XINGULAR_WORK_SLICE=off` for every run in that
|
|
292
|
+
process; with it off a reply has no boundary — no checkpoint, no continuation, no stall notes — and
|
|
293
|
+
ends only when the model stops or a person interrupts.
|
|
263
294
|
- **INV-RUN-14** A run event stream carries `checkpoint` (the handoff `checkpoint_write` records or
|
|
264
295
|
the harness derives from the run's own evidence when the model wrote none) and `heartbeat`
|
|
265
296
|
(steps, elapsed time, last tool, compactions, slice, and the call budget). A heartbeat older than
|
|
266
297
|
five minutes while the owner process lives marks the run `interrupted` with reason `stalled`; a
|
|
267
298
|
run that never emitted one keeps the 30-minute silence rule. The watchdog never restarts work.
|
|
268
299
|
- **INV-RUN-12** A post-compaction checkpoint is a bounded context projection of the active request,
|
|
269
|
-
the latest validated
|
|
300
|
+
the latest validated todo list and applicable plan instructions. It is compiled by
|
|
270
301
|
`prompt/compile.ts`, supplied only to model requests in the active run, and never persists hidden
|
|
271
302
|
reasoning or changes permissions, stable prompt text, native history or run-event schemas. Its
|
|
272
303
|
in-memory state is cleared when the run settles or the active session branch changes
|
|
@@ -290,16 +321,22 @@ Decisions: [ADR-0002](../decisions/ADR-0002-native-subagent-lifecycle.md) (super
|
|
|
290
321
|
[ADR-0022](../decisions/ADR-0022-plan-only-question-tools.md),
|
|
291
322
|
[ADR-0023](../decisions/ADR-0023-contextual-side-question-runs.md),
|
|
292
323
|
[ADR-0026](../decisions/ADR-0026-contextual-question-wireframes.md),
|
|
293
|
-
[ADR-0033](../decisions/ADR-0033-plan-mode-research-delegation.md)
|
|
324
|
+
[ADR-0033](../decisions/ADR-0033-plan-mode-research-delegation.md),
|
|
325
|
+
[ADR-0039](../decisions/ADR-0039-progress-aware-stall-guards.md).
|
|
294
326
|
|
|
295
327
|
## Native session names (PROP-0010)
|
|
296
328
|
|
|
297
329
|
`session_name({ name: string })` adds or revises the current Pi session's name in embedded
|
|
298
|
-
and terminal execution. The agent
|
|
299
|
-
|
|
330
|
+
and terminal execution. The agent normally calls it once before its first other tool call when a
|
|
331
|
+
request needs tools or changes state, and revises it only when the overall objective changes,
|
|
332
|
+
including a manual name. When a top-level attended session starts unnamed, the harness also
|
|
333
|
+
derives a provisional name from a substantive first request before the first model request;
|
|
334
|
+
greetings, thanks and short conversational replies stay unnamed. The model may revise the
|
|
335
|
+
provisional name. Agent-submitted names are imperative sentences
|
|
300
336
|
of at most six whitespace-separated words; whitespace is normalized, and empty names,
|
|
301
337
|
terminal escapes, non-whitespace controls and longer names fail without writing. Identical
|
|
302
338
|
names are a no-op. Pi's native session-info history is the only storage; continuation and
|
|
303
339
|
reopen preserve it. Each child names only itself. There is no additional model request or
|
|
304
|
-
run-event schema. The normal capability selection and host gate apply;
|
|
340
|
+
run-event schema. The normal capability selection and host gate apply; a refused or failed
|
|
341
|
+
provisional name leaves the session unnamed and never fails the run. `harnessTools: false`
|
|
305
342
|
omits the tool. Plan mode permits it as session metadata maintenance.
|
|
@@ -60,9 +60,7 @@ The surface is `PI_SURFACE` (`variant/surface.ts`), the one surface this harness
|
|
|
60
60
|
- **INV-FND-2** A variant changes only by committing a new validated version (`commit` →
|
|
61
61
|
`validate`, `INV-VAR-2`), and a refinement moves a head only when a person adopts
|
|
62
62
|
(`INV-REF-6`). There is no other door.
|
|
63
|
-
- **INV-VAR-1**
|
|
64
|
-
instructions. The application adds its own sections through `Launch` (page 01); no other
|
|
65
|
-
harness code adds instruction text.
|
|
63
|
+
- **INV-VAR-1** Variant instructions are versioned per scope. The application adds its own sections through `Launch` (page 01). The release-owned `plugin-authoring` skill is also available on demand in structured and terminal sessions, including existing variants; its body is not always-on. A variant skill with the same name takes precedence. It is shipped as a package resource and does not mutate pinned versions.
|
|
66
64
|
- **INV-VAR-2** Every saved version is validated (`commit` → `validate`). An invalid variant is
|
|
67
65
|
refused with every problem listed.
|
|
68
66
|
- **INV-VAR-3** A version is never edited. A change is a new version; `restore` moves the head
|
|
@@ -16,7 +16,7 @@ keeps provider caching effective across turns.
|
|
|
16
16
|
| `render(env, pack)` → `string` | One string for a session that takes a single prompt. |
|
|
17
17
|
| `sessionLaunch(env, caller, launch, historyFile, variant)` → `{ system, update, pack }` | SDK sessions: stable prefix plus an update with only the dynamic sections that changed since the last delivered snapshot. |
|
|
18
18
|
| `deliveredSnapshot(sessionFile)` | Reads the last delivered snapshot on the active history branch; a compaction forces a fresh one. |
|
|
19
|
-
| `renderCompactionCheckpoint` | Compiles a bounded current-request,
|
|
19
|
+
| `renderCompactionCheckpoint` | Compiles a bounded current-request, todo list and plan-state message for post-compaction model requests. |
|
|
20
20
|
| `saveForSession`, `copyToRun` | Terminal sessions keep the pack they started with and copy it to each run. |
|
|
21
21
|
| `record`, `load`, `packPath` | The pack each run was given, at `runs/<id>/context.json`. |
|
|
22
22
|
| `toolGroups`, `fit`, `clip` | The tool manifest by group; cutting text to a budget at a paragraph boundary. |
|
|
@@ -28,8 +28,7 @@ A `ContextPack` holds `sections: Section[]` (each with `id`, `title`,
|
|
|
28
28
|
|
|
29
29
|
## Section order
|
|
30
30
|
|
|
31
|
-
`SECTION_ORDER`: `harnessIdentity` 5, `system` 25, `guardrails` 40, `memory` 45, `references`
|
|
32
|
-
50, `subagents` 64, `scripts` 66, `wiki` 80, `tools` 90, `reporting` 95. Application sections
|
|
31
|
+
`SECTION_ORDER`: `harnessIdentity` 5, `system` 25, `sessionState` 30, `guardrails` 40, `memory` 45, `references` 50, `subagents` 64, `scripts` 66, `wiki` 80, `tools` 90, `reporting` 95. Application sections
|
|
33
32
|
sit among them by their `order`; plan mode uses `plan` at 25. Ties keep insertion order.
|
|
34
33
|
When a run may spawn, the dynamic `subagents` section lists every profile it can start (built-in,
|
|
35
34
|
global, project and variant c5 names) and replaces the variant's own list (PROP-0029). Normal-mode
|
|
@@ -37,10 +36,19 @@ guidance in that section explains when delegation is worth its overhead, profile
|
|
|
37
36
|
self-contained briefs, independent parallel work, and parent ownership of integration. Plan mode
|
|
38
37
|
lists only effective profiles eligible for read-only research and requires a named profile; keeping
|
|
39
38
|
this section dynamic leaves the stable system prompt unchanged across modes. The `tools`
|
|
40
|
-
section has a Progress paragraph whenever `
|
|
41
|
-
|
|
39
|
+
section has a Progress paragraph whenever `todo_write` is available: it asks for `todo_write` before
|
|
40
|
+
the first other tool call when work has several steps, asks for the list to stay current, then
|
|
41
|
+
requests a final update before the reply. Only fully completed work is
|
|
42
42
|
marked completed; unfinished or blocked steps remain accurate (PROP-0006).
|
|
43
43
|
|
|
44
|
+
`session-state` is a built-in dynamic section at order 30 when a top-level run supplies it. It
|
|
45
|
+
names the current session or says “unnamed”, shows this run's todo (empty at the start) and a
|
|
46
|
+
previous run's list as context, and says whether this is the first turn. It describes only tools
|
|
47
|
+
in the frozen set: the name line appears only with `session_name`, and the todo line only with
|
|
48
|
+
`todo_write`. It never enters the stable prefix. Structured sessions deliver it through
|
|
49
|
+
`sessionLaunch` and the changed-section rule; the terminal appends the same text as a request-time
|
|
50
|
+
custom message.
|
|
51
|
+
|
|
44
52
|
The fixed `harness-identity` section says `You are an AI agent running in <productName>.` and uses
|
|
45
53
|
`env.productName` (default `Xingular Agent`). `Launch.standard: { cwd, project?: { name } | null }` requests shared role and working-folder
|
|
46
54
|
sections from `prompt/standard.ts`; the compiler supplies common connections, file and annotation
|
|
@@ -81,7 +89,7 @@ compile ──► pack ──► stable sections ──► system prompt (+ "Con
|
|
|
81
89
|
`references` is always resent when present, because it belongs to the current request.
|
|
82
90
|
- After successful compaction, the foundation checkpoint extension detects the compacted context and
|
|
83
91
|
uses `renderCompactionCheckpoint` to append one hidden, ephemeral context message to each model
|
|
84
|
-
request while the active run continues, when a
|
|
92
|
+
request while the active run continues, when a todo list or applicable plan instructions exist.
|
|
85
93
|
It contains only the current request and available state. It is not written to native history, and its state is
|
|
86
94
|
discarded when the run settles or the branch changes.
|
|
87
95
|
- The session appends the update as a hidden custom message and saves its snapshot in the
|
|
@@ -113,8 +121,8 @@ file SecretStore with a host Keychain. See [parity](../parity.md).
|
|
|
113
121
|
instructions. SDK sessions use `sessionLaunch`; terminal sessions use `compile` + `render`.
|
|
114
122
|
- **INV-PRM-2** The system prompt holds only stable text: identity, role, the variant's sections, the
|
|
115
123
|
harness's reporting guidance, tool guidance and the tool manifest. Changing state never enters it.
|
|
116
|
-
- **INV-PRM-3** `references`, `wiki`, and every section the application marks
|
|
117
|
-
delivered as context updates in native history, never in the system prompt.
|
|
124
|
+
- **INV-PRM-3** `session-state`, `references`, `wiki`, and every section the application marks
|
|
125
|
+
`dynamic` are delivered as context updates in native history, never in the system prompt.
|
|
118
126
|
- **INV-PRM-4** An update carries only changed dynamic sections, so an unchanged turn appends
|
|
119
127
|
nothing. A compaction on the active branch forces the full snapshot again.
|
|
120
128
|
- **INV-PRM-5** The pack only describes tools the caller can call (the frozen capability set).
|
|
@@ -149,12 +157,15 @@ what this page states is binding. Adopting parts of that draft is an architectur
|
|
|
149
157
|
## Source map
|
|
150
158
|
|
|
151
159
|
`src/prompt/compile.ts`, `src/sessions/sessions.ts` (calls `sessionLaunch`),
|
|
152
|
-
`src/terminal/terminals.ts` (calls `compile` + `render`), `src/
|
|
153
|
-
|
|
160
|
+
`src/terminal/terminals.ts` (calls `compile` + `render`), `src/sessions/sessionState.ts`
|
|
161
|
+
(the native name reader and state shape), `src/variant/materialise.ts` (variant sections),
|
|
162
|
+
`src/sessions/planMode.ts` (`plan` section).
|
|
154
163
|
|
|
155
164
|
## Session naming guidance (PROP-0010)
|
|
156
165
|
|
|
157
|
-
The Session tool group describes `session_name` when available:
|
|
158
|
-
|
|
166
|
+
The Session tool group describes `session_name` when available: call it once before the first
|
|
167
|
+
other tool call when a request needs tools or changes state, with an imperative sentence of at
|
|
168
|
+
most six words, and revise only when the objective changes.
|
|
159
169
|
This is fixed foundation guidance. The current name stays in native session metadata and
|
|
160
|
-
the terminal snapshot; it
|
|
170
|
+
the terminal snapshot; it may appear in the request-scoped `session-state` update, but it is never
|
|
171
|
+
interpolated into the stable system prompt.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
## Purpose
|
|
4
4
|
|
|
5
5
|
A *plugin* is a bundle with a title, a description and contributions: instructions, skills,
|
|
6
|
-
commands, tools, connections, code (a Pi extension) and themes. A Pi package is a plugin as it is;
|
|
6
|
+
commands, subagent profiles (`agent`), tools, connections, code (a Pi extension) and themes. A Pi package is a plugin as it is;
|
|
7
7
|
so are the harness's own parts, the application's parts, a person's registry, the folder every
|
|
8
8
|
account shares, and what a working folder brings. This part decides what a session loads, who has
|
|
9
9
|
what switched on, which code may run, and what reaches one caller. A *capability set* is the
|
|
@@ -22,6 +22,7 @@ callable result for one run.
|
|
|
22
22
|
| `FIRST_PARTY_PLUGINS` | `plugins/firstParty.ts` | `output-trim`, `budget-guard`: inline extensions shipped switched off. `lessons`: switched off; its contribution turns on reflection after a run (page 08, PROP-0008) and loads no Pi code. |
|
|
23
23
|
| `Hooks` | `plugins/hooks.ts` | Runs a package's hooks file after a write. |
|
|
24
24
|
| install / trust | `plugins/install.ts`, `plugins/trust.ts` | Install through Pi's package manager with scripts off; trust code by hash. |
|
|
25
|
+
| proposals | `plugins/proposals.ts` | Validate and store inert proposals; preview, reject or accept a hash-bound review. |
|
|
25
26
|
| inventory / api | `plugins/inventory.ts`, `plugins/api.ts` | `plugins.list`, `plugins.inventory`, attach, trust. |
|
|
26
27
|
| capability api | `capabilities/api.ts`, `capabilities/types.ts` | `list`, `resolve`, `toolIntersection`, `inventory`, `attach`. |
|
|
27
28
|
| run snapshot | `capabilities/runSnapshot.ts` | `freezeRun`, `loadRun`, `capabilitySet`. |
|
|
@@ -29,8 +30,9 @@ callable result for one run.
|
|
|
29
30
|
## Contracts
|
|
30
31
|
|
|
31
32
|
- **Loading.** `Plugins.loading({ cwd, agentDir, caller, contributions, install? })` returns
|
|
32
|
-
`extensionPaths`, `skillPaths`, `promptPaths`, `themePaths`, `builtins` (legacy shape; no Pi CLI built-ins selected), `hooks`,
|
|
33
|
-
`found`, `detached`, `projectCode`, `packageCode`.
|
|
33
|
+
`extensionPaths`, `skillPaths`, `promptPaths`, `themePaths`, `profilePaths`, `builtins` (legacy shape; no Pi CLI built-ins selected), `hooks`,
|
|
34
|
+
`found`, `detached`, `projectCode`, `packageCode`. `profilePaths` are read by the harness for
|
|
35
|
+
subagent profiles (page 02); Pi is never given them. A session opens Pi with its own discovery off
|
|
34
36
|
and only these paths; a terminal receives them as `--extension`, `--skill`,
|
|
35
37
|
`--prompt-template` and `--theme` after `--no-extensions --no-skills --no-prompt-templates
|
|
36
38
|
--no-themes`. Pi still reads `AGENTS.md` and `SYSTEM.md` itself.
|
|
@@ -45,10 +47,39 @@ callable result for one run.
|
|
|
45
47
|
- **Attachments.** `config/plugin-attachments.json` holds `global`, `agents`, `projects` (each
|
|
46
48
|
`{ on, off }`) and `settings` per plugin. The narrowest scope that says something wins: agent,
|
|
47
49
|
then project, then everywhere. With no entry an item keeps its default.
|
|
48
|
-
- **Package metadata.** A Pi package may declare `"harness": { "extends": [...], "hooks": "./hooks.mjs", "commandPrefix": "my-tools" }`.
|
|
50
|
+
- **Package metadata.** A Pi package may declare `"harness": { "extends": [...], "hooks": "./hooks.mjs", "commandPrefix": "my-tools", "agents": "./agents" }`.
|
|
51
|
+
A package without a `package.json` name is named, described and versioned by the first of
|
|
52
|
+
`plugin.json`, `.claude-plugin/plugin.json`, `.codex-plugin/plugin.json`, so an agent plugin
|
|
53
|
+
written for other harnesses installs as it is.
|
|
54
|
+
- **Package subagent profiles.** An installed package's agents folder (`agents/` unless
|
|
55
|
+
`harness.agents` names another) brings each Markdown file whose frontmatter has a `name` and a
|
|
56
|
+
`description` as an `agent` contribution (at most 50). It is text: it needs no trust and follows
|
|
57
|
+
its switch like a skill. The profile is named by its frontmatter, not its file. Fields only other
|
|
58
|
+
harnesses understand are dropped (`agents/profiles.ts`, `parsePackageProfile`): their tool names
|
|
59
|
+
are translated (`Read`→`read`, `Glob`→`find`, …), a model without a provider is left to the
|
|
60
|
+
parent, `plugins` and `variant` are never taken, and a tool list of which nothing translates
|
|
61
|
+
keeps the child read-only. A package profile never replaces a built-in, person's, project's or
|
|
62
|
+
variant's profile of the same name; the listing reports it as a problem instead.
|
|
49
63
|
`commandPrefix` is optional; in the terminal, commands otherwise use a normalized package name as
|
|
50
64
|
their owner prefix. Prefixes use lowercase letters, digits and hyphens, starting with a letter;
|
|
51
65
|
`plugin` and `skill` are reserved. See page 11 for the command route and collision rules.
|
|
66
|
+
- **Plugin authoring.** `plugin_propose` creates a pending proposal, not an installation. The
|
|
67
|
+
release-owned `plugin-authoring` skill is available on demand in structured and terminal sessions;
|
|
68
|
+
a pinned variant's skill of the same name wins. It adds no trust or permission
|
|
69
|
+
([ADR-0045](../decisions/ADR-0045-default-plugin-authoring-skill.md)).
|
|
70
|
+
- **Proposal review.** `plugins/proposals.ts` validates a lowercase package name, nonempty description,
|
|
71
|
+
and 1–100 UTF-8 text files (256 KiB each, 1 MiB total). It accepts `README.md`, extensions
|
|
72
|
+
(`.ts`, `.js`, `.mjs`), Markdown skills, prompts and agents, and JSON themes in their respective
|
|
73
|
+
directories; paths must be safe and cannot contain `.git` or `node_modules`. A
|
|
74
|
+
`skills/<name>/SKILL.md` needs matching name and nonempty description frontmatter. The Harness
|
|
75
|
+
generates `package.json`; it is not supplied by the proposal. Preview revalidates the stored data
|
|
76
|
+
and computes SHA-256 over name, description, generated manifest and sorted file entries. Accept
|
|
77
|
+
and reject require the current preview hash and pending status; stale reviews fail.
|
|
78
|
+
Acceptance rechecks after adoption and listing, refuses an existing package name or already-trusted
|
|
79
|
+
identical package code, stages and publishes under `<data root>/plugins/<name>`, clears old
|
|
80
|
+
attachment decisions for that package and explicitly switches it off globally. It grants no code
|
|
81
|
+
trust or permission; reject retains the proposal as rejected. These are trusted caller review
|
|
82
|
+
operations, not model tools. See [ADR-0046](../decisions/ADR-0046-hash-bound-plugin-proposals.md).
|
|
52
83
|
- **Hooks.** A package declares `"harness": { "extends": [...], "hooks": "./hooks.mjs" }`. Events:
|
|
53
84
|
`wiki.page.saved`, `history.run.ended`. A hook has 30 seconds; its errors are kept in
|
|
54
85
|
`plugin-hooks.json`. `ctx.call(connection, tool, args)` reaches only a connected app that is on
|
|
@@ -114,6 +145,7 @@ callable result for one run.
|
|
|
114
145
|
```text
|
|
115
146
|
<data root>/config/plugin-attachments.json (registry-enabled.json read until the first change)
|
|
116
147
|
<data root>/plugins/<name>/ packages kept with the data; removal moves to trash/plugins/
|
|
148
|
+
<data root>/plugin-proposals/<id>.json proposed text, hash and review status
|
|
117
149
|
<state dir>/plugin-trust.json trusted code, by hash
|
|
118
150
|
<state dir>/plugin-registered.json what each extension registered last time
|
|
119
151
|
<state dir>/plugin-hooks.json hooks and their last run
|
|
@@ -134,13 +166,17 @@ metadata or availability:
|
|
|
134
166
|
| Foundation | Accounts, sessions and run recording, prompt and variant validation, gate, plugin loading/trust/attachments, resource browser, server and terminal frameworks | Release-owned infrastructure and security contracts |
|
|
135
167
|
| World | Web search/read tools, browser tools, page annotations | The isolated browser engine and network policy remain Foundation services |
|
|
136
168
|
| Memory | Wiki, history and trajectory | Storage and run records remain Foundation-owned services |
|
|
137
|
-
| Automation | Subagents, ask-user,
|
|
169
|
+
| Automation | Subagents, ask-user, todo, lessons and refinement | Run lifecycle, capability narrowing and approval gate remain Foundation-owned |
|
|
138
170
|
| Integrations | Connected apps/MCP and Hub | Connector credentials and plugin installation remain behind Foundation services |
|
|
139
171
|
| Operations | Doctor, worktrees and usage | Diagnostics, repository operations and usage analytics remain Harness-managed services |
|
|
140
172
|
|
|
141
|
-
## Terminal resource inspection
|
|
173
|
+
## Terminal plugin and resource inspection
|
|
142
174
|
|
|
143
|
-
The
|
|
144
|
-
registration. A saved on/off state does not prove a resource loaded; origins and owners
|
|
145
|
-
same-name resources.
|
|
146
|
-
|
|
175
|
+
The broad `/harness` browser joins saved plugin/contribution metadata with actual session skills and
|
|
176
|
+
tool registration. A saved on/off state does not prove a resource loaded; origins and owners
|
|
177
|
+
distinguish same-name resources. `/plugins` is a focused local manager with Plugins, Trust and
|
|
178
|
+
Packages tabs. It uses the existing plugin services for switching, trust, settings, package install,
|
|
179
|
+
update and removal. `/hub` is a distinct Community catalog surface; it does not load code or add a
|
|
180
|
+
second loader. Hub-owned package removal through `plugins.remove` delegates to Hub so the exact
|
|
181
|
+
receipt and its resources stay consistent. No second discovery or enablement mechanism is
|
|
182
|
+
introduced (PROP-0013, PROP-0047).
|
|
@@ -16,9 +16,9 @@ person without letting remembered per-tool grants widen that boundary.
|
|
|
16
16
|
| `dispatch` | `tools/dispatch.ts` | One entry point for every History, Wiki and skill call, from a Pi tool, the server or a terminal. |
|
|
17
17
|
| `harnessTools` | `tools/harnessTools.ts` | The definitions as `ToolSpec`s for one session. |
|
|
18
18
|
| `askUserTool` (`ask_user`) | `tools/askUser.ts` | Stops an attended plan run and asks up to five related questions with choices and concise 1–2 word labels; absent from newly resolved normal runs. |
|
|
19
|
-
| `
|
|
19
|
+
| `todoTool` (`todo_write`) | `tools/todo.ts` | Writes the run's whole todo list as a `todo.updated` event (PROP-0006, renamed by PROP-0045). Read-only for the gate, so plan mode allows it. Terminal sessions register the same tool; it reaches the run through the `todo` telemetry call. The prompt's Progress group asks the model to call it before the first other tool call when work has several steps, keep it current, and write one final update before replying; unfinished work is not automatically marked complete. The pre-rename `checklist.updated` event is still read, never written. |
|
|
20
20
|
| `subagentTools` | `tools/spawnSubagent.ts` | `spawn_subagent` (requires a short `title`, PROP-0030) and `wait_subagents`; normal-mode descriptions guide selective, bounded delegation, while plan-mode spawns require a named eligible read-only research profile. |
|
|
21
|
-
| `annotationsPart` (`page_notes_list`, `page_notes_read
|
|
21
|
+
| `annotationsPart` (`page_notes_list`, `page_notes_read`) | `annotations/part.ts` | Read-only world tools over the page notes a person shared with the session or agent (PROP-0017, PROP-0048). |
|
|
22
22
|
| `webTools` | `web/tools.ts` | `web_search` (Brave, key from the secret store), `web_fetch` (checked public reads). An application provides them as a provider. |
|
|
23
23
|
| gate | `sessions/sessions.ts::gate`, `sessions/runner.ts` | `ToolGate { ask, check }`, loaded as the last extension (`xagent-approvals`). |
|
|
24
24
|
| `Approvals`, `decide`, `grant`, `approvalKey` | `sessions/approvals.ts` | Standing approvals. |
|
|
@@ -26,7 +26,7 @@ person without letting remembered per-tool grants widen that boundary.
|
|
|
26
26
|
Harness tools: `get_capabilities` (read-only current-run discovery), `history_search`, `history_read`,
|
|
27
27
|
`trajectory_search`, `trajectory_read`, `wiki_search`, `wiki_read`, `wiki_list`, `wiki_write`
|
|
28
28
|
(not in the default set), `skill_load`, `ask_user` (attended plan runs and pinned continuations only),
|
|
29
|
-
`
|
|
29
|
+
`todo_write`, `plugin_propose`. Broker:
|
|
30
30
|
`mcp_list_tools`, `mcp_call_tool`. Native Pi tools: `read`, `grep`, `find`,
|
|
31
31
|
`ls`, `edit`, `write`, `bash`.
|
|
32
32
|
|
|
@@ -45,6 +45,17 @@ when plan mode is active it reports the plan's allowed tool set. `sessions/planM
|
|
|
45
45
|
the shared read-only allowlist. Host sessions use this Harness tool rather than defining a duplicate.
|
|
46
46
|
It reports availability, never permission, and every call remains subject to the gate.
|
|
47
47
|
|
|
48
|
+
## Plugin proposal security
|
|
49
|
+
|
|
50
|
+
`plugin_propose { name, description, files }` is a write-classified Harness tool, subject to the
|
|
51
|
+
normal capability and per-call gate, and creates only a pending proposal in the Harness data root.
|
|
52
|
+
It does not accept, install, enable or trust a plugin. Proposal text is untrusted, including skill
|
|
53
|
+
instructions; preview and human review are needed before acceptance. Acceptance is a separate
|
|
54
|
+
trusted-caller API, bound to the reviewed content hash; it does not execute package code, grant
|
|
55
|
+
trust or bypass the loader, attachment controls, capability restrictions or gate. Text contributions
|
|
56
|
+
can load once enabled without code trust, so review their instructions as well as executable files.
|
|
57
|
+
See page 06 and [ADR-0046](../decisions/ADR-0046-hash-bound-plugin-proposals.md).
|
|
58
|
+
|
|
48
59
|
## Native file paths
|
|
49
60
|
|
|
50
61
|
The read-only `read`, `grep`, `find` and `ls` tools accept paths relative to the working folder,
|
|
@@ -76,6 +87,18 @@ never replayed after partial effects. Full Permission is the explicit eligible-r
|
|
|
76
87
|
Unsupported or unavailable sandbox enforcement fails closed. A side-question run has an empty
|
|
77
88
|
capability set and no tools (PROP-0019).
|
|
78
89
|
|
|
90
|
+
**Windows** has no write-boundary sandbox the harness can use, so the Bash tool treats every
|
|
91
|
+
command there as an outside request: a human-only one-call approval (or an eligible Full
|
|
92
|
+
Permission answer), then the command runs once without a sandbox. Plan-mode Bash is refused,
|
|
93
|
+
because a read-only scope cannot be enforced. Commands run in Git Bash when it is installed
|
|
94
|
+
(`%ProgramFiles%\Git\bin\bash.exe`, then `bash.exe` on `PATH`, never the WSL launcher in
|
|
95
|
+
`System32`), otherwise in PowerShell (`pwsh.exe`, then Windows PowerShell). The tool keeps the name
|
|
96
|
+
`bash`; its description names the shell. Native `edit` and `write` run their atomic helper with
|
|
97
|
+
Node directly, without an OS guard: the target is still canonicalized, authorized, revalidated and
|
|
98
|
+
replaced by rename, and outside targets still need their approval, but a junction or symlink swap
|
|
99
|
+
between the check and the rename is not prevented
|
|
100
|
+
([ADR-0042](../decisions/ADR-0042-windows-shell-without-sandbox.md)).
|
|
101
|
+
|
|
79
102
|
## The gate, per call
|
|
80
103
|
|
|
81
104
|
For native `edit` and `write`, the canonical target check is added to policy scope before approval;
|
|
@@ -96,6 +119,7 @@ policy.authorize(call) throws ─► refuse
|
|
|
96
119
|
outside native file target ─► human-only one-call approval; eligible Full Permission may answer
|
|
97
120
|
Bash workspace scope ─► hard-link scan, OS sandbox, run once
|
|
98
121
|
Bash outside scope ─► pre-execution human-only approval, then run once unconfined
|
|
122
|
+
Bash on Windows (no sandbox) ─► as outside scope; plan-mode Bash refused
|
|
99
123
|
trigger probe, improver, reflection or unattended ─► refuse anything requiring a person
|
|
100
124
|
run.requestApproval(...) ─► standing approvals may answer where eligible, else the person
|
|
101
125
|
denied ─► refuse; never replay a command
|
|
@@ -131,6 +155,8 @@ the switch and global tools.
|
|
|
131
155
|
Full Permission switch can answer automatically under its existing restrictions. In plan mode, Bash
|
|
132
156
|
runs only in the read-only scope (PROP-0043): no writes but a discarded temp folder, no network,
|
|
133
157
|
no signals outside the sandbox, no macOS mach services; Full Permission and `outside` never apply.
|
|
158
|
+
On Windows, which has no sandbox, every Bash call takes the `outside` path and plan-mode Bash is
|
|
159
|
+
refused (ADR-0042).
|
|
134
160
|
- **INV-GATE-4** Refinement runs (`probe`, `improver`) never ask a person; what would need one is
|
|
135
161
|
refused, never queued (`INV-REF-4`).
|
|
136
162
|
- **INV-GATE-5** SDK tools are registered only if their names are in the run's frozen capability
|
|
@@ -155,6 +181,7 @@ the switch and global tools.
|
|
|
155
181
|
same choice as `!outside <command>`. Full Permission is the only standing boundary bypass and
|
|
156
182
|
remains subject to host policy, authorization, read-only, plan, unattended, probe, improver and
|
|
157
183
|
reflection restrictions. The rule does not protect against a peer process running as the same user.
|
|
184
|
+
On Windows the atomic replacement runs without an OS-enforced scope (ADR-0042).
|
|
158
185
|
|
|
159
186
|
## Data
|
|
160
187
|
|
|
@@ -164,16 +191,23 @@ the switch and global tools.
|
|
|
164
191
|
|
|
165
192
|
`src/tools/*.ts`, `src/web/*.ts`, `src/sessions/sessions.ts`, `src/sessions/runner.ts`,
|
|
166
193
|
`src/sessions/workspaceBoundary.ts`, `src/sessions/initialBash.ts`, `src/core/workspaceBashTool.ts`,
|
|
167
|
-
`src/core/
|
|
168
|
-
`src/sessions/policy.ts`.
|
|
194
|
+
`src/core/shell.ts`, `src/core/workspaceSandbox.ts`, `src/core/workspaceWriteOperations.ts`,
|
|
195
|
+
`src/sessions/approvals.ts`, `src/sessions/policy.ts`. Decisions:
|
|
196
|
+
[ADR-0036](../decisions/ADR-0036-workspace-write-operation-boundary.md),
|
|
197
|
+
[ADR-0042](../decisions/ADR-0042-windows-shell-without-sandbox.md).
|
|
169
198
|
|
|
170
199
|
## Session naming (PROP-0010)
|
|
171
200
|
|
|
172
201
|
`session_name` (`tools/sessionName.ts`) binds to the current native session. It maintains
|
|
173
202
|
only Pi session metadata and is explicitly plan-safe, while still subject to capability
|
|
174
|
-
selection and the host policy. The
|
|
175
|
-
|
|
176
|
-
|
|
203
|
+
selection and the host policy. The prompt asks for it once before the first other tool call when
|
|
204
|
+
a request needs tools or changes state. When a top-level attended session starts unnamed, the
|
|
205
|
+
harness also derives a provisional name from its first substantive request and sets it through
|
|
206
|
+
Pi before the first model request; a host gate refusal or a failed write leaves the session
|
|
207
|
+
unnamed and never fails the run. The model may revise the provisional name. The terminal
|
|
208
|
+
registers the same definition through its Pi bridge; standalone policy permits naming without
|
|
209
|
+
approval. See page 02 for validation and persistence. It is a foundation tool, not mutable
|
|
210
|
+
variant data.
|
|
177
211
|
|
|
178
212
|
## Diagnostic probes
|
|
179
213
|
|
|
@@ -181,3 +215,10 @@ persistence. It is a foundation tool, not mutable variant data.
|
|
|
181
215
|
intersect current capabilities, and execute tool calls through the existing gate. Calls that
|
|
182
216
|
require an additional per-call approval report blocked; batch diagnostic consent does not grant
|
|
183
217
|
standing permission. No raw tool inputs, results, or screenshots enter diagnostic findings.
|
|
218
|
+
|
|
219
|
+
A live check may also run one command the harness wrote itself, when the capability it diagnoses is
|
|
220
|
+
a native Pi tool rather than a harness tool: the shell check runs `printf` through the same
|
|
221
|
+
workspace root, hard-link scan and write-boundary sandbox as a Bash call, and reports only the exit
|
|
222
|
+
status. It passes the gate first, and a diagnostic never widens the boundary — Full Permission,
|
|
223
|
+
an outside-workspace request and a host bypass are all refused for it — so a boundary that stops
|
|
224
|
+
the command before the shell starts is reported as blocked with the boundary's own reason.
|
|
@@ -38,7 +38,10 @@ skills, prompts, rules and Pi packages.
|
|
|
38
38
|
- **`apps.expose(tools)`** offers the application's own tools through the broker, which is how a
|
|
39
39
|
terminal session reaches them.
|
|
40
40
|
- **Hub.** `hub.list`, `get`, `preview`, `install`, `uninstall`, `readDocument`. Pi packages need
|
|
41
|
-
an exact npm version or a full Git commit. Documents are saved as inert JSON.
|
|
41
|
+
an exact npm version or a full Git commit. Documents are saved as inert JSON. The `/hub` Catalog
|
|
42
|
+
view filters Community entries for display; the service and other callers retain the full catalog.
|
|
43
|
+
Installed shows receipts from every channel. On page entry, cached/bundled content is shown before
|
|
44
|
+
a remote refresh, and origin, refresh time and failure status remain visible (PROP-0047).
|
|
42
45
|
|
|
43
46
|
## Invariants
|
|
44
47
|
|
|
@@ -62,7 +65,10 @@ skills, prompts, rules and Pi packages.
|
|
|
62
65
|
nothing of it is stored.
|
|
63
66
|
- **INV-MCP-4** Hub installation grants no attachment, trust, credential or permission. Writes
|
|
64
67
|
are serialized; existing registry files are never overwritten; uninstall removes only the exact
|
|
65
|
-
receipt's resources and revokes its attachment choices.
|
|
68
|
+
receipt's resources and revokes its attachment choices. Every removal route for a Hub-owned Pi
|
|
69
|
+
package, including `plugins.remove`, goes through Hub's receipt-owning uninstall operation. A
|
|
70
|
+
floating plugin-package update must not change a Hub-owned package; replacement uses an explicit
|
|
71
|
+
exact catalog version (PROP-0047).
|
|
66
72
|
|
|
67
73
|
## Data
|
|
68
74
|
|