@xingular/harness 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -5
- package/README.md +75 -21
- package/dist/cli.js +17421 -8711
- package/dist/sdk/accounts/accounts.d.ts +27 -3
- package/dist/sdk/accounts/accounts.js +78 -24
- package/dist/sdk/accounts/secrets.d.ts +12 -0
- package/dist/sdk/accounts/secrets.js +114 -7
- package/dist/sdk/accounts/store.d.ts +26 -1
- package/dist/sdk/accounts/store.js +1 -1
- package/dist/sdk/agents/builtin.d.ts +2 -0
- package/dist/sdk/agents/builtin.js +48 -0
- package/dist/sdk/agents/narrow.d.ts +13 -0
- package/dist/sdk/agents/narrow.js +29 -0
- package/dist/sdk/agents/planResearch.d.ts +5 -0
- package/dist/sdk/agents/planResearch.js +19 -0
- package/dist/sdk/agents/profiles.d.ts +81 -0
- package/dist/sdk/agents/profiles.js +226 -0
- package/dist/sdk/annotations/bridge.d.ts +42 -0
- package/dist/sdk/annotations/bridge.js +264 -0
- package/dist/sdk/annotations/capture.d.ts +116 -0
- package/dist/sdk/annotations/capture.js +308 -0
- package/dist/sdk/annotations/delivery.d.ts +72 -0
- package/dist/sdk/annotations/delivery.js +130 -0
- package/dist/sdk/annotations/inspect.d.ts +10 -0
- package/dist/sdk/annotations/inspect.js +33 -0
- package/dist/sdk/annotations/isolated.d.ts +6 -0
- package/dist/sdk/annotations/isolated.js +51 -0
- package/dist/sdk/annotations/pageScript.d.ts +28 -0
- package/dist/sdk/annotations/pageScript.js +871 -0
- package/dist/sdk/annotations/part.d.ts +10 -0
- package/dist/sdk/annotations/part.js +155 -0
- package/dist/sdk/annotations/queue.d.ts +4 -0
- package/dist/sdk/annotations/queue.js +40 -0
- package/dist/sdk/annotations/serverMethods.d.ts +3 -0
- package/dist/sdk/annotations/serverMethods.js +62 -0
- package/dist/sdk/annotations/store.d.ts +167 -0
- package/dist/sdk/annotations/store.js +394 -0
- package/dist/sdk/browser/backend.d.ts +16 -0
- package/dist/sdk/browser/backend.js +17 -0
- package/dist/sdk/browser/contracts.d.ts +19 -0
- package/dist/sdk/browser/contracts.js +116 -0
- package/dist/sdk/browser/index.d.ts +14 -3
- package/dist/sdk/browser/index.js +11 -4
- package/dist/sdk/browser/serverMethods.d.ts +3 -0
- package/dist/sdk/browser/serverMethods.js +7 -0
- package/dist/sdk/browser/session.d.ts +1 -0
- package/dist/sdk/browser/session.js +45 -9
- package/dist/sdk/browser/tools.d.ts +1 -4
- package/dist/sdk/browser/tools.js +14 -91
- package/dist/sdk/cli.js +24 -15
- package/dist/sdk/commands/list.d.ts +3 -0
- package/dist/sdk/commands/list.js +75 -0
- package/dist/sdk/commands/registry.d.ts +250 -0
- package/dist/sdk/commands/registry.js +47 -0
- package/dist/sdk/commands/routes.d.ts +16 -0
- package/dist/sdk/commands/routes.js +33 -0
- package/dist/sdk/core/bus.js +1 -1
- package/dist/sdk/core/commandBudget.d.ts +23 -0
- package/dist/sdk/core/commandBudget.js +57 -0
- package/dist/sdk/core/env.d.ts +1 -1
- package/dist/sdk/core/env.js +1 -1
- package/dist/sdk/core/index.js +17 -1
- package/dist/sdk/core/interactiveProfile.d.ts +46 -0
- package/dist/sdk/core/interactiveProfile.js +143 -0
- package/dist/sdk/core/workspace.d.ts +13 -0
- package/dist/sdk/core/workspace.js +88 -0
- package/dist/sdk/core/workspaceBashTool.d.ts +4 -0
- package/dist/sdk/core/workspaceBashTool.js +36 -0
- package/dist/sdk/core/workspaceSandbox.d.ts +31 -0
- package/dist/sdk/core/workspaceSandbox.js +320 -0
- package/dist/sdk/core/workspaceWriteOperations.d.ts +22 -0
- package/dist/sdk/core/workspaceWriteOperations.js +206 -0
- package/dist/sdk/doctor/serverMethods.d.ts +3 -0
- package/dist/sdk/doctor/serverMethods.js +8 -0
- package/dist/sdk/doctor/types.d.ts +2 -2
- package/dist/sdk/harness.d.ts +22 -0
- package/dist/sdk/harness.js +84 -5
- package/dist/sdk/history/recall.js +8 -8
- package/dist/sdk/history/serverMethods.d.ts +3 -0
- package/dist/sdk/history/serverMethods.js +8 -0
- package/dist/sdk/hub/cli.d.ts +1 -1
- package/dist/sdk/hub/cli.js +1 -1
- package/dist/sdk/hub/schema.d.ts +1 -1
- package/dist/sdk/hub/serverMethods.d.ts +3 -0
- package/dist/sdk/hub/serverMethods.js +11 -0
- package/dist/sdk/index.d.ts +16 -1
- package/dist/sdk/index.js +10 -0
- package/dist/sdk/mcp/connections.js +14 -7
- package/dist/sdk/mcp/serverMethods.d.ts +3 -0
- package/dist/sdk/mcp/serverMethods.js +22 -0
- package/dist/sdk/pi/runtime.d.ts +2 -1
- package/dist/sdk/pi/runtime.js +2 -2
- package/dist/sdk/plugins/builtin.d.ts +1 -0
- package/dist/sdk/plugins/builtin.js +145 -33
- package/dist/sdk/plugins/builtinRegistry.d.ts +60 -0
- package/dist/sdk/plugins/builtinRegistry.js +71 -0
- package/dist/sdk/plugins/catalogue.js +2 -1
- package/dist/sdk/plugins/cli.d.ts +1 -1
- package/dist/sdk/plugins/cli.js +4 -3
- package/dist/sdk/plugins/commandPrefix.d.ts +8 -0
- package/dist/sdk/plugins/commandPrefix.js +21 -0
- package/dist/sdk/plugins/firstParty.d.ts +1 -1
- package/dist/sdk/plugins/firstParty.js +8 -2
- package/dist/sdk/plugins/inventory.js +4 -3
- package/dist/sdk/plugins/manifest.d.ts +2 -0
- package/dist/sdk/plugins/manifest.js +2 -1
- package/dist/sdk/plugins/surfaces.d.ts +5 -0
- package/dist/sdk/plugins/surfaces.js +11 -0
- package/dist/sdk/plugins/types.d.ts +15 -0
- package/dist/sdk/prompt/compile.d.ts +19 -2
- package/dist/sdk/prompt/compile.js +79 -26
- package/dist/sdk/prompt/standard.d.ts +17 -0
- package/dist/sdk/prompt/standard.js +21 -0
- package/dist/sdk/refine/cli.d.ts +1 -1
- package/dist/sdk/refine/cli.js +2 -2
- package/dist/sdk/refine/serverMethods.d.ts +3 -0
- package/dist/sdk/refine/serverMethods.js +20 -0
- package/dist/sdk/server/methods.js +27 -86
- package/dist/sdk/server/params.d.ts +4 -0
- package/dist/sdk/server/params.js +11 -0
- package/dist/sdk/server/remote.js +36 -11
- package/dist/sdk/sessions/compactionCheckpoint.d.ts +11 -0
- package/dist/sdk/sessions/compactionCheckpoint.js +79 -0
- package/dist/sdk/sessions/continuation.d.ts +3 -0
- package/dist/sdk/sessions/continuation.js +5 -1
- package/dist/sdk/sessions/contracts.d.ts +185 -0
- package/dist/sdk/sessions/contracts.js +101 -4
- package/dist/sdk/sessions/control.d.ts +72 -0
- package/dist/sdk/sessions/control.js +158 -0
- package/dist/sdk/sessions/initialBash.d.ts +7 -0
- package/dist/sdk/sessions/initialBash.js +7 -0
- package/dist/sdk/sessions/planMode.d.ts +18 -4
- package/dist/sdk/sessions/planMode.js +82 -16
- package/dist/sdk/sessions/reasoningSummaries.d.ts +2 -2
- package/dist/sdk/sessions/reasoningSummaries.js +3 -3
- package/dist/sdk/sessions/registry.d.ts +2 -1
- package/dist/sdk/sessions/registry.js +6 -3
- package/dist/sdk/sessions/runIndex.js +7 -7
- package/dist/sdk/sessions/runStore.d.ts +14 -0
- package/dist/sdk/sessions/runStore.js +38 -1
- package/dist/sdk/sessions/runner.d.ts +40 -2
- package/dist/sdk/sessions/runner.js +163 -15
- package/dist/sdk/sessions/sessions.d.ts +40 -8
- package/dist/sdk/sessions/sessions.js +279 -27
- package/dist/sdk/sessions/sideQuestionServerMethods.d.ts +3 -0
- package/dist/sdk/sessions/sideQuestionServerMethods.js +19 -0
- package/dist/sdk/sessions/sideQuestions.d.ts +66 -0
- package/dist/sdk/sessions/sideQuestions.js +290 -0
- package/dist/sdk/sessions/subagentServerMethods.d.ts +3 -0
- package/dist/sdk/sessions/subagentServerMethods.js +41 -0
- package/dist/sdk/sessions/subagentService.d.ts +22 -2
- package/dist/sdk/sessions/subagentService.js +93 -16
- package/dist/sdk/sessions/subagents.d.ts +9 -1
- package/dist/sdk/sessions/subagents.js +19 -0
- package/dist/sdk/sessions/workSlice.d.ts +103 -0
- package/dist/sdk/sessions/workSlice.js +297 -0
- package/dist/sdk/sessions/workspaceBoundary.d.ts +15 -0
- package/dist/sdk/sessions/workspaceBoundary.js +46 -0
- package/dist/sdk/terminal/browser.d.ts +62 -0
- package/dist/sdk/terminal/browser.js +41 -0
- package/dist/sdk/terminal/browserControl.d.ts +29 -0
- package/dist/sdk/terminal/browserControl.js +187 -0
- package/dist/sdk/terminal/commandHelp.d.ts +17 -0
- package/dist/sdk/terminal/commandHelp.js +20 -0
- package/dist/sdk/terminal/controller.d.ts +15 -1
- package/dist/sdk/terminal/controller.js +67 -8
- package/dist/sdk/terminal/opentui/subagentsWidget.d.ts +28 -0
- package/dist/sdk/terminal/opentui/subagentsWidget.js +52 -0
- package/dist/sdk/terminal/opentui/theme.d.ts +43 -0
- package/dist/sdk/terminal/opentui/theme.js +87 -0
- package/dist/sdk/terminal/piExtension.d.ts +6 -1
- package/dist/sdk/terminal/piExtension.js +169 -84
- package/dist/sdk/terminal/socket.d.ts +6 -3
- package/dist/sdk/terminal/socket.js +40 -9
- package/dist/sdk/terminal/standalone.d.ts +9 -0
- package/dist/sdk/terminal/standalone.js +118 -19
- package/dist/sdk/terminal/subagentMonitor.d.ts +47 -0
- package/dist/sdk/terminal/subagentMonitor.js +152 -0
- package/dist/sdk/terminal/terminals.d.ts +60 -7
- package/dist/sdk/terminal/terminals.js +598 -47
- package/dist/sdk/terminal/trajectory.js +2 -2
- package/dist/sdk/terminal/tui/annotateCommand.d.ts +3 -0
- package/dist/sdk/terminal/tui/annotateCommand.js +22 -0
- package/dist/sdk/terminal/tui/commandPages.d.ts +7 -1
- package/dist/sdk/terminal/tui/commandPages.js +57 -6
- package/dist/sdk/terminal/tui/commands.d.ts +10 -4
- package/dist/sdk/terminal/tui/commands.js +269 -65
- package/dist/sdk/terminal/tui/dialogGeometry.d.ts +2 -2
- package/dist/sdk/terminal/tui/dialogGeometry.js +4 -2
- package/dist/sdk/terminal/tui/dialogs.d.ts +6 -1
- package/dist/sdk/terminal/tui/dialogs.js +9 -2
- package/dist/sdk/terminal/tui/list.d.ts +14 -1
- package/dist/sdk/terminal/tui/list.js +96 -14
- package/dist/sdk/terminal/tui/modelPicker.js +1 -6
- package/dist/sdk/terminal/tui/page.d.ts +3 -0
- package/dist/sdk/terminal/tui/pageOverlay.js +27 -7
- package/dist/sdk/terminal/tui/pages/accountsPage.d.ts +26 -4
- package/dist/sdk/terminal/tui/pages/accountsPage.js +264 -36
- package/dist/sdk/terminal/tui/pages/agentsPage.d.ts +74 -0
- package/dist/sdk/terminal/tui/pages/agentsPage.js +190 -0
- package/dist/sdk/terminal/tui/pages/annotatePage.d.ts +94 -0
- package/dist/sdk/terminal/tui/pages/annotatePage.js +341 -0
- package/dist/sdk/terminal/tui/pages/browserPage.d.ts +87 -0
- package/dist/sdk/terminal/tui/pages/browserPage.js +738 -0
- package/dist/sdk/terminal/tui/pages/doctorPage.d.ts +2 -0
- package/dist/sdk/terminal/tui/pages/doctorPage.js +103 -15
- package/dist/sdk/terminal/tui/pages/notesPage.d.ts +75 -0
- package/dist/sdk/terminal/tui/pages/notesPage.js +201 -0
- package/dist/sdk/terminal/tui/pages/pluginsPage.d.ts +0 -5
- package/dist/sdk/terminal/tui/pages/pluginsPage.js +9 -3
- package/dist/sdk/terminal/tui/pages/settingsPage.d.ts +8 -0
- package/dist/sdk/terminal/tui/pages/settingsPage.js +16 -1
- package/dist/sdk/terminal/tui/pages/subagentsPage.d.ts +24 -0
- package/dist/sdk/terminal/tui/pages/subagentsPage.js +152 -0
- package/dist/sdk/terminal/tui/pages/trajectoryPage.d.ts +12 -5
- package/dist/sdk/terminal/tui/pages/trajectoryPage.js +156 -83
- package/dist/sdk/terminal/tui/pages/usagePage.d.ts +43 -0
- package/dist/sdk/terminal/tui/pages/usagePage.js +370 -0
- package/dist/sdk/terminal/tui/pages/worktreesPage.d.ts +72 -0
- package/dist/sdk/terminal/tui/pages/worktreesPage.js +203 -0
- package/dist/sdk/terminal/tui/piAdapter.d.ts +1 -2
- package/dist/sdk/terminal/tui/piAdapter.js +3 -5
- package/dist/sdk/terminal/tui/planMode.d.ts +1 -1
- package/dist/sdk/terminal/tui/planMode.js +1 -1
- package/dist/sdk/terminal/tui/pluginCommands.d.ts +16 -0
- package/dist/sdk/terminal/tui/pluginCommands.js +31 -0
- package/dist/sdk/terminal/tui/questions.d.ts +2 -0
- package/dist/sdk/terminal/tui/runtime.js +27 -5
- package/dist/sdk/terminal/tui/sessionPicker.d.ts +40 -0
- package/dist/sdk/terminal/tui/sessionPicker.js +141 -0
- package/dist/sdk/terminal/tui/settingsModel.d.ts +2 -0
- package/dist/sdk/terminal/tui/settingsModel.js +32 -2
- package/dist/sdk/terminal/tui/sideQuestion.d.ts +26 -26
- package/dist/sdk/terminal/tui/sideQuestion.js +131 -98
- package/dist/sdk/terminal/tui/ui.d.ts +2 -0
- package/dist/sdk/terminal/tui/ui.js +1 -0
- package/dist/sdk/tools/askUser.js +26 -8
- package/dist/sdk/tools/checklist.js +3 -2
- package/dist/sdk/tools/checkpoint.d.ts +27 -0
- package/dist/sdk/tools/checkpoint.js +154 -0
- package/dist/sdk/tools/getCapabilities.d.ts +31 -0
- package/dist/sdk/tools/getCapabilities.js +34 -0
- package/dist/sdk/tools/harnessTools.d.ts +2 -0
- package/dist/sdk/tools/harnessTools.js +1 -1
- package/dist/sdk/tools/spawnSubagent.js +14 -4
- package/dist/sdk/usage/analytics.d.ts +20 -0
- package/dist/sdk/usage/analytics.js +151 -0
- package/dist/sdk/usage/ledger.d.ts +38 -0
- package/dist/sdk/usage/ledger.js +142 -0
- package/dist/sdk/usage/limits/adapters.d.ts +11 -0
- package/dist/sdk/usage/limits/adapters.js +349 -0
- package/dist/sdk/usage/limits/capture.d.ts +8 -0
- package/dist/sdk/usage/limits/capture.js +47 -0
- package/dist/sdk/usage/limits/http.d.ts +12 -0
- package/dist/sdk/usage/limits/http.js +51 -0
- package/dist/sdk/usage/limits/normalize.d.ts +15 -0
- package/dist/sdk/usage/limits/normalize.js +211 -0
- package/dist/sdk/usage/limits/service.d.ts +30 -0
- package/dist/sdk/usage/limits/service.js +176 -0
- package/dist/sdk/usage/limits/types.d.ts +65 -0
- package/dist/sdk/usage/limits/types.js +1 -0
- package/dist/sdk/usage/serverMethods.d.ts +3 -0
- package/dist/sdk/usage/serverMethods.js +22 -0
- package/dist/sdk/usage/service.d.ts +32 -0
- package/dist/sdk/usage/service.js +66 -0
- package/dist/sdk/usage/settings.d.ts +7 -0
- package/dist/sdk/usage/settings.js +28 -0
- package/dist/sdk/usage/types.d.ts +60 -0
- package/dist/sdk/usage/types.js +4 -0
- package/dist/sdk/web/part.d.ts +10 -0
- package/dist/sdk/web/part.js +6 -0
- package/dist/sdk/web/serverMethods.d.ts +3 -0
- package/dist/sdk/web/serverMethods.js +7 -0
- package/dist/sdk/wiki/serverMethods.d.ts +3 -0
- package/dist/sdk/wiki/serverMethods.js +26 -0
- package/dist/sdk/worktrees/cli.d.ts +11 -0
- package/dist/sdk/worktrees/cli.js +146 -0
- package/dist/sdk/worktrees/copy.d.ts +9 -0
- package/dist/sdk/worktrees/copy.js +111 -0
- package/dist/sdk/worktrees/git.d.ts +16 -0
- package/dist/sdk/worktrees/git.js +81 -0
- package/dist/sdk/worktrees/serverMethods.d.ts +3 -0
- package/dist/sdk/worktrees/serverMethods.js +30 -0
- package/dist/sdk/worktrees/service.d.ts +73 -0
- package/dist/sdk/worktrees/service.js +483 -0
- package/dist/sdk/worktrees/setup.d.ts +23 -0
- package/dist/sdk/worktrees/setup.js +65 -0
- package/dist/sdk/worktrees/types.d.ts +91 -0
- package/dist/sdk/worktrees/types.js +1 -0
- package/dist/sdk/world/cli.d.ts +2 -2
- package/dist/sdk/world/cli.js +6 -6
- package/dist/sdk/world/world.d.ts +3 -1
- package/dist/sdk/world/world.js +8 -9
- package/dist/terminal-opentui.js +16456 -5966
- package/dist/terminal-pi.js +1579 -573
- package/docs/README.md +22 -2
- package/docs/architecture/00-overview.md +28 -16
- package/docs/architecture/02-sessions-and-runs.md +184 -25
- package/docs/architecture/03-variants.md +10 -2
- package/docs/architecture/04-prompt.md +65 -7
- package/docs/architecture/06-plugins-and-capabilities.md +57 -4
- package/docs/architecture/07-tools-and-gate.md +112 -17
- package/docs/architecture/08-memory-and-history.md +4 -2
- package/docs/architecture/09-accounts-and-connectors.md +39 -1
- package/docs/architecture/10-server-protocol.md +168 -4
- package/docs/architecture/11-terminal.md +251 -8
- package/docs/architecture/12-storage.md +45 -3
- package/docs/architecture/13-world-tools.md +49 -6
- package/docs/architecture/14-surfaces-and-parity.md +136 -0
- package/docs/architecture/README.md +17 -4
- package/docs/architecture/proposals/PROP-0006-run-checklist.md +4 -2
- package/docs/architecture/proposals/PROP-0013-resource-browser.md +58 -0
- package/docs/architecture/proposals/PROP-0014-fullscreen-browser-tabs.md +58 -0
- package/docs/architecture/proposals/PROP-0015-one-capability-surface.md +88 -0
- package/docs/architecture/proposals/PROP-0016-managed-worktrees.md +156 -0
- package/docs/architecture/proposals/PROP-0017-page-annotations.md +131 -0
- package/docs/architecture/proposals/PROP-0018-annotation-queue-and-app-targets.md +179 -0
- package/docs/architecture/proposals/PROP-0019-contextual-side-questions.md +122 -0
- package/docs/architecture/proposals/PROP-0020-builtin-feature-plugins.md +105 -0
- package/docs/architecture/proposals/PROP-0021-command-namespaces-and-duplicates.md +99 -0
- package/docs/architecture/proposals/PROP-0022-plan-only-questions.md +102 -0
- package/docs/architecture/proposals/PROP-0023-xagent-cli-name.md +61 -0
- package/docs/architecture/proposals/PROP-0024-question-sketch-previews.md +130 -0
- package/docs/architecture/proposals/PROP-0025-contextual-question-wireframes.md +49 -0
- package/docs/architecture/proposals/PROP-0026-connected-sketch-display.md +94 -0
- package/docs/architecture/proposals/PROP-0027-xingular-agent-product-identity.md +60 -0
- package/docs/architecture/proposals/PROP-0028-normalize-question-wireframes.md +55 -0
- package/docs/architecture/proposals/PROP-0029-agent-profiles.md +124 -0
- package/docs/architecture/proposals/PROP-0030-subagent-title.md +86 -0
- package/docs/architecture/proposals/PROP-0031-plugin-command-owner-namespaces.md +54 -0
- package/docs/architecture/proposals/PROP-0032-planning-quality.md +196 -0
- package/docs/architecture/proposals/PROP-0033-compaction-plan-checkpoints.md +75 -0
- package/docs/architecture/proposals/PROP-0034-conversation-fast-mode.md +120 -0
- package/docs/architecture/proposals/PROP-0035-retain-subagent-status.md +47 -0
- package/docs/architecture/proposals/PROP-0036-first-class-harness-commands.md +59 -0
- package/docs/architecture/proposals/PROP-0037-workspace-write-boundary.md +63 -0
- package/docs/architecture/proposals/PROP-0038-annotate-open-shadow-roots.md +73 -0
- package/docs/architecture/proposals/PROP-0039-workspace-boundary-hardening.md +139 -0
- package/docs/architecture/proposals/PROP-0040-one-launch-path.md +87 -0
- package/docs/architecture/proposals/PROP-0041-bounded-work-slices.md +247 -0
- package/docs/architecture/proposals/PROP-0042-usage-and-provider-limits.md +127 -0
- package/docs/architecture/proposals/PROP-0043-read-only-plan-bash.md +74 -0
- package/docs/architecture/proposals/README.md +39 -0
- package/docs/decisions/ADR-0001-owned-terminal.md +1 -1
- package/docs/decisions/ADR-0009-xharness-command.md +6 -5
- package/docs/decisions/ADR-0014-public-release-baseline.md +3 -2
- package/docs/decisions/ADR-0015-resource-browser.md +28 -0
- package/docs/decisions/ADR-0016-fullscreen-browser-tabs.md +31 -0
- package/docs/decisions/ADR-0017-one-capability-surface.md +34 -0
- package/docs/decisions/ADR-0018-builtin-feature-plugins.md +35 -0
- package/docs/decisions/ADR-0019-managed-git-worktrees.md +31 -0
- package/docs/decisions/ADR-0020-page-annotations.md +37 -0
- package/docs/decisions/ADR-0021-required-command-namespaces.md +40 -0
- package/docs/decisions/ADR-0022-plan-only-question-tools.md +34 -0
- package/docs/decisions/ADR-0023-contextual-side-question-runs.md +35 -0
- package/docs/decisions/ADR-0024-xagent-command.md +40 -0
- package/docs/decisions/ADR-0025-question-choice-sketches.md +49 -0
- package/docs/decisions/ADR-0026-contextual-question-wireframes.md +58 -0
- package/docs/decisions/ADR-0027-connected-sketch-display.md +60 -0
- package/docs/decisions/ADR-0028-xingular-agent-product-identity.md +56 -0
- package/docs/decisions/ADR-0029-normalized-question-wireframe-borders.md +33 -0
- package/docs/decisions/ADR-0030-agent-profiles.md +43 -0
- package/docs/decisions/ADR-0031-plugin-command-owner-namespaces.md +37 -0
- package/docs/decisions/ADR-0032-compaction-run-checkpoints.md +33 -0
- package/docs/decisions/ADR-0033-plan-mode-research-delegation.md +47 -0
- package/docs/decisions/ADR-0034-first-class-harness-terminal-commands.md +25 -0
- package/docs/decisions/ADR-0035-one-launch-path.md +40 -0
- package/docs/decisions/ADR-0036-workspace-write-operation-boundary.md +54 -0
- package/docs/decisions/ADR-0037-usage-ledger-and-provider-limits.md +44 -0
- package/docs/decisions/ADR-0038-plan-bash-os-read-only.md +29 -0
- package/docs/doctor.md +10 -4
- package/docs/experiments/EXP-0003-performance-audit/data/session-runtime-replication.json +420 -0
- package/docs/experiments/EXP-0003-performance-audit/data/session-runtime.json +420 -0
- package/docs/experiments/EXP-0003-performance-audit/data/terminal-compact.json +376 -0
- package/docs/experiments/EXP-0003-performance-audit/data/terminal-history.json +422 -0
- package/docs/experiments/EXP-0003-performance-audit/data/terminal-question.json +95 -0
- package/docs/experiments/EXP-0003-performance-audit/data/terminal-wide.json +1036 -0
- package/docs/experiments/EXP-0003-performance-audit/plan.md +109 -0
- package/docs/experiments/EXP-0003-performance-audit/results.md +151 -0
- package/docs/features/README.md +26 -0
- package/docs/features/interfaces/README.md +1 -1
- package/docs/future-work.md +48 -0
- package/docs/handoff-2026-10-25-app-parity-and-solo-tabs.md +202 -0
- package/docs/parity.md +134 -0
- package/docs/releases/1.0.0.md +2 -2
- package/docs/releases/1.1.1.md +28 -0
- package/docs/releases/1.2.0.md +49 -0
- package/docs/releases/4.0.0.md +47 -0
- package/docs/releases/README.md +37 -27
- package/docs/study/00-index.md +8 -0
- package/docs/study/STUDY-0003-long-horizon-runs.md +210 -0
- package/docs/study/autonomous-engineering-sources.md +277 -0
- package/docs/study/autonomy-sources.md +147 -0
- package/docs/study/proactive-autonomy.md +408 -0
- package/docs/study/tui-resource-browser.md +78 -0
- package/docs/terminal-tui.md +386 -113
- package/package.json +6 -5
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: PROP-0036
|
|
3
|
+
title: First-class Harness terminal commands
|
|
4
|
+
status: Implemented
|
|
5
|
+
created: 2026-10-25
|
|
6
|
+
updated: 2026-10-25
|
|
7
|
+
affects: [INV-PLG-10, INV-TUI-7, 06-plugins-and-capabilities.md, 11-terminal.md, 14-surfaces-and-parity.md, terminal-tui.md, parity, ADR-0031]
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# PROP-0036: First-class Harness terminal commands
|
|
11
|
+
|
|
12
|
+
## Problem
|
|
13
|
+
|
|
14
|
+
Harness-owned pages for subagents, agent profiles, recorded-run inspection, diagnostics and worktrees are currently exposed through `BuiltinPluginRegistry` command metadata. This couples their terminal command namespace and discoverability to a feature-plugin registry even though these required features are not optional plugin toggles. It also makes ordinary Harness commands appear as plugin commands in help and completion.
|
|
15
|
+
|
|
16
|
+
Evidence: `src/plugins/builtin.ts` registers these commands on the `subagents`, `history`, `doctor` and `worktrees` modules; `src/terminal/tui/pluginCommands.ts` maps them to pages; `src/terminal/tui/commands.ts` builds canonical namespaced completion and dispatch from `BuiltinPluginRegistry`.
|
|
17
|
+
|
|
18
|
+
## Affected rules
|
|
19
|
+
|
|
20
|
+
- **INV-PLG-10** currently couples a built-in feature's descriptor, tools, server methods and terminal command metadata to one registry owner. Plugin-owned commands should remain with their feature modules, but Harness core commands should be owned by the terminal's core command registry.
|
|
21
|
+
- **INV-TUI-7** requires every plugin-owned command to use an owner prefix. The commands in this proposal become Harness core commands, not plugin-owned commands; all other plugin and extension commands retain owner-qualified routes.
|
|
22
|
+
- **14 Surfaces and parity, Contracts** describes the current terminal command namespace. The command changes are presentation only and add no capability or server method.
|
|
23
|
+
|
|
24
|
+
## Proposal
|
|
25
|
+
|
|
26
|
+
Register these routes directly in the core terminal command table and dispatch them to the existing Harness pages:
|
|
27
|
+
|
|
28
|
+
- `/doctor` opens readiness diagnostics.
|
|
29
|
+
- `/worktree` opens managed worktrees.
|
|
30
|
+
- `/trajectory [run-id]` opens recorded runs and events.
|
|
31
|
+
- `/subagents` opens the subagent roster; `/agents` opens agent profiles.
|
|
32
|
+
|
|
33
|
+
Keep `/history` (and its `/tree` alias) for session branch navigation. Keep `/mcp` and `/connections` as first-class entries into the Connections browser. All other core commands stay unprefixed. Plugin-owned built-in and extension commands continue to use `/<owner-prefix>:<command>`; annotations retain their `annotate` namespace and default route.
|
|
34
|
+
|
|
35
|
+
The `doctor`, `worktrees`, `history` and `subagents` feature descriptors remain registered and required. Their services, server methods, tools and capability behavior do not move. Only their terminal command metadata and dispatch move to the core command registry. Core commands reserve their names under the existing terminal command collision policy.
|
|
36
|
+
|
|
37
|
+
For one release, accept the prior owner-qualified and `/plugin:<command>` forms for the routes being promoted as hidden compatibility aliases. Do not show aliases in help or completion. Remove them after the compatibility release.
|
|
38
|
+
|
|
39
|
+
## Alternatives
|
|
40
|
+
|
|
41
|
+
- Keep these routes under owner prefixes. Rejected: it keeps core terminal actions classified as plugin commands and exposes redundant namespaces for required Harness features.
|
|
42
|
+
- Remove the feature descriptors from `BuiltinPluginRegistry`. Rejected: those descriptors still own Harness tools, server methods and capability contributions; only terminal command ownership needs to change.
|
|
43
|
+
- Replace `/history` with the trajectory page. Rejected: `/history` already navigates the current session's branches. Keep it and expose the run trajectory as `/trajectory`.
|
|
44
|
+
- Do nothing. Rejected: help, completion and dispatch continue to treat these core pages as plugin-owned commands.
|
|
45
|
+
|
|
46
|
+
## Consequences
|
|
47
|
+
|
|
48
|
+
Help, completion, slash recognition and dispatch use the core command table for the promoted commands. The `/mcp` command remains in that table and keeps its Connections behavior. Plugin command-prefix collision checks remain in force for plugin-owned commands. No capability set, server protocol, account data, run record or stored resource changes.
|
|
49
|
+
|
|
50
|
+
## Migration
|
|
51
|
+
|
|
52
|
+
No stored-data migration. Accept the previous qualified forms as hidden aliases for one release; scripts and keybindings should use the bare canonical names. `/history` remains the branch picker and `/trajectory` is the recorded-run page.
|
|
53
|
+
|
|
54
|
+
## Checks
|
|
55
|
+
|
|
56
|
+
- Registry and terminal tests cover bare routes, help, completion, slash recognition, compatibility aliases, prompt-name collisions, `/history`, `/mcp` and unchanged plugin namespace routing.
|
|
57
|
+
- Harness `npm run typecheck`, `npm test` (150 files; 1,143 passed, 3 skipped) and `npm run prove` passed.
|
|
58
|
+
- Xingular Agent `npm run typecheck`, `npm test` (App and sidecar suites: 634 passed; signing tests: 7 passed, 1 skipped), `npm run check:layers` and `cargo test` (167 passed, 1 ignored) passed.
|
|
59
|
+
- Isolated terminal PTY checks passed for `/help`, composer modes, and the `/trajectory` Runs/Events page. `/help` screen-layout assertions were skipped because optional `pyte` is unavailable.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: PROP-0037
|
|
3
|
+
title: Default filesystem writes to the active project workspace
|
|
4
|
+
status: Implemented
|
|
5
|
+
created: 2026-11-19
|
|
6
|
+
updated: 2026-11-19
|
|
7
|
+
affects: [INV-GATE-1, INV-GATE-3, INV-GATE-8, INV-RUN-1, INV-TUI-8, 02-sessions-and-runs.md, 04-prompt.md, 07-tools-and-gate.md, 10-server-protocol.md, 11-terminal.md, 12-storage.md, 14-surfaces-and-parity.md, parity]
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# PROP-0037: Default filesystem writes to the active project workspace
|
|
11
|
+
|
|
12
|
+
> **Implementation update:** This proposal records the original pathname-check and
|
|
13
|
+
> denial-triggered-retry design. Security review found those details bypassable; accepted
|
|
14
|
+
> [PROP-0039](PROP-0039-workspace-boundary-hardening.md) replaces them with operation-time atomic
|
|
15
|
+
> writes and explicit pre-execution outside-scope approval. Follow the current contracts in
|
|
16
|
+
> [07 Tools and the gate](../07-tools-and-gate.md) and [11 Terminal](../11-terminal.md).
|
|
17
|
+
|
|
18
|
+
## Problem
|
|
19
|
+
|
|
20
|
+
Harness tells the model that read-only file tools can use any path the process can read, and that the working folder is not a repository boundary (`src/prompt/compile.ts`; `docs/architecture/07-tools-and-gate.md`, Native file paths). The same page says `edit`, `write` and `bash` pass through the existing gate and policy, but that gate has no built-in workspace-root rule. The SDK's `ToolPolicy` is optional, and the terminal's default approval flow is not a filesystem sandbox (`src/sessions/policy.ts`, `src/sessions/sessions.ts`, `src/terminal/terminals.ts`). Thus a session has no Harness-wide default that keeps model-initiated file mutations in its project.
|
|
21
|
+
|
|
22
|
+
## Affected rules
|
|
23
|
+
|
|
24
|
+
- **INV-GATE-8**, as it stands: “Native read-only file access is bounded by process and operating-system permissions, not by the repository root. Absolute and `~` paths are valid inputs. This does not change the gate or permissions for writes and commands.” The first two sentences remain; the final sentence changes because the Harness will scope writes and shell file effects.
|
|
25
|
+
- **INV-GATE-3**, as it stands: “Order is fixed: capability and plan-mode refusals, then the policy's scope and authorize, then standing approvals, then the person, then authorize again.” The mandatory workspace check must join this ordering without allowing a host policy to silently broaden it; an approved one-call escape must be authorized before the operation runs.
|
|
26
|
+
- **INV-RUN-1**, as it stands: “A run pins one account, one variant version and one capability set when it starts. None of them changes during the run.” A run will also pin its resolved workspace-write root so a continuation or later filesystem change cannot silently widen its scope.
|
|
27
|
+
- **INV-TUI-8**, added by implementation: the terminal uses the same Harness-pinned root and workspace-write policy as SDK sessions; it cannot widen the boundary through its private socket or native extension.
|
|
28
|
+
|
|
29
|
+
## Proposal
|
|
30
|
+
|
|
31
|
+
1. **Preserve broad reads.** Read-only filesystem tools retain their existing process/OS-permission behavior. The write boundary applies to model-controlled filesystem mutations, not to reads.
|
|
32
|
+
2. **Resolve one trusted workspace root per run.** After Harness has selected the effective `cwd` (including a managed worktree), resolve the nearest ancestor containing `.git`, canonicalize it, and store it as `RunRecord.workspaceRoot`. If there is no Git repository, use the canonical `cwd`. A worktree is its own active workspace. Do not infer the root from model-supplied tool arguments or an unvalidated `projectId`.
|
|
33
|
+
3. **Default file writes to that root.** Native `edit` and `write` calls may mutate paths inside the root. Resolve paths canonically and reject symlink/path escapes. Paths outside it require approval for that operation. A per-tool remembered grant does not authorize an outside write.
|
|
34
|
+
4. **Enforce shell writes, not just shell-call names.** Run model Bash—including the initial `!` command—under an OS-enforced workspace-write sandbox. Shell commands may read as before but may write only under `workspaceRoot`; `/tmp` and other external paths are outside the default write scope. A denied outside write produces a clear denial and a one-shot escalation path for that command. Approval reruns only that command with the wider access needed. Fail closed when workspace-mode enforcement is unavailable; never silently run it unconfined.
|
|
35
|
+
5. **Use existing approval controls.** Outside writes require a person’s one-call approval. Mark the request human-only so remembered grants cannot answer it. The existing Full Permission switch may automatically grant this explicitly eligible escape; it is off by default. Preserve hard policy denials and the existing read-only, plan, unattended, probe, improver and reflection restrictions. Full Permission does not add tools or bypass those restrictions.
|
|
36
|
+
6. **Keep artifacts in the project by default.** Files created for the task, including deliverables, belong inside the active workspace. Prefer an existing project convention such as `artifacts/` or `outputs/` when present; do not require or create a universal output folder. An explicitly approved outside write remains possible.
|
|
37
|
+
7. **Make the policy Harness-owned and shared.** Apply the same root and decision in SDK sessions and the standalone terminal. Host `ToolPolicy` may impose stricter limits, but cannot waive the Harness boundary except through the same explicit approval path. Connected-app and other non-filesystem side effects remain governed by their existing tool policies.
|
|
38
|
+
|
|
39
|
+
## Alternatives
|
|
40
|
+
|
|
41
|
+
- **Prompt-only “write in the repo” guidance.** Rejected: it expresses a preference but does not prevent absolute paths, symlink escapes or shell commands from writing elsewhere.
|
|
42
|
+
- **Rely only on the host `ToolPolicy`.** Rejected: it is optional and host-specific, so terminal and embedded sessions could differ.
|
|
43
|
+
- **Check only `edit`/`write` paths or parse Bash strings.** Rejected: shell commands can write through arbitrary programs, redirection, subprocesses and indirect paths; string inspection is not a reliable boundary.
|
|
44
|
+
- **Allow all OS temp directories by default.** Rejected for this proposal: the requested default is project-only. A temp location outside the workspace needs the same approval as any other outside write.
|
|
45
|
+
- **Do nothing.** Keeps the existing broad behavior and leaves repository scope to prompt guidance or host configuration.
|
|
46
|
+
|
|
47
|
+
## Consequences
|
|
48
|
+
|
|
49
|
+
- Add an optional, backward-compatible `workspaceRoot` field to `RunRecord`; new runs set it, old records remain readable, and continuations of older runs derive it from their recorded working directory. No separate workspace registry or output directory is introduced.
|
|
50
|
+
- The native file tools and shell need different enforcement mechanisms: canonical target checks for file mutations and an OS sandbox for shell subprocesses. The same workspace policy and approval semantics must be used by SDK and terminal paths.
|
|
51
|
+
- The `RunRecord` schema is returned over the server protocol, so embedding hosts and sidecar schemas must tolerate the additive field. The Harness remains responsible for computing it; a host cannot nominate an arbitrary wider root.
|
|
52
|
+
- Workspace mode fails closed on unsupported or unavailable sandbox backends. A person can still explicitly authorize one outside operation, or use the existing Full Permission switch where permitted.
|
|
53
|
+
- Standard commands that need to write outside the project (including to `/tmp`) may need an approved one-shot retry. Project-local artifact/output conventions continue to work without extra approval.
|
|
54
|
+
|
|
55
|
+
## Migration
|
|
56
|
+
|
|
57
|
+
No stored files are rewritten. Parsers accept older run records without `workspaceRoot`; a continuation derives the root from the earlier record's `workingDirectory` and stores it on the new run. New runs pin the effective root after worktree selection. Existing remembered tool grants remain stored but do not satisfy outside-write approvals. The current Full Permission switch remains off/on as configured; it is the only standing choice that may approve a boundary escape, and read-only or unattended facts continue to disable it.
|
|
58
|
+
|
|
59
|
+
## Checks
|
|
60
|
+
|
|
61
|
+
- Workspace resolution, canonical file-write inspection, session/terminal approvals and sandbox tests cover Git roots, worktrees, non-Git folders, symlink escapes, broad reads, remembered-grant rejection, eligible Full Permission, hard restrictions, fail-closed behavior and one-shot retries. Passed.
|
|
62
|
+
- Harness `npm run typecheck`, full `npm test` (153 files; 1,167 passed, 3 skipped), and `npm run prove` passed on 2026-11-19.
|
|
63
|
+
- The App sidecar contract verifies `runs.find` returns the pinned root. App `npm run typecheck`, `npm test` (571 renderer and 67 sidecar tests passed; 7 development-signing tests passed, 1 skipped), `npm run check:layers`, and `cd src-tauri && cargo test` (169 passed, 1 ignored) passed. Rust compilation emitted warnings.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: PROP-0038
|
|
3
|
+
title: Annotate inside open shadow roots
|
|
4
|
+
status: Implemented
|
|
5
|
+
created: 2026-10-25
|
|
6
|
+
updated: 2026-10-25
|
|
7
|
+
affects: [13-world-tools.md, 12-storage.md (note target), PROP-0017, PROP-0018, parity]
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# PROP-0038: Annotate inside open shadow roots
|
|
11
|
+
|
|
12
|
+
Requested by the owner on 2026-10-25 after the inspector did nothing on reddit.com; they approved
|
|
13
|
+
this design in the same session.
|
|
14
|
+
|
|
15
|
+
## Problem
|
|
16
|
+
|
|
17
|
+
Sites built from web components keep their content in shadow roots. Reddit's posts, comments and
|
|
18
|
+
feed are `shreddit-*` elements with open shadow roots. The page helper (`annotations/pageScript.ts`)
|
|
19
|
+
refused anything whose root node is not `document`, anything under an element with a shadow root, and
|
|
20
|
+
any custom-element tag (PROP-0017, PROP-0018: "frames, shadow roots and custom elements are never
|
|
21
|
+
picked"). Its text stream (`TreeWalker` over `document.body`) and element lookup
|
|
22
|
+
(`document.getElementsByTagName`) never entered a shadow root. On such sites the inspector drew no
|
|
23
|
+
outline, ignored clicks and said nothing. In WebKit, `getRangeAt` reports a selection inside a shadow
|
|
24
|
+
root as a collapsed point on its host, so text capture could not work there either.
|
|
25
|
+
|
|
26
|
+
## Proposal
|
|
27
|
+
|
|
28
|
+
1. **Walk the composed tree.** New helper primitives walk open shadow roots and slotted content in
|
|
29
|
+
rendered order (`composedParent`, `flatChildren`, a bounded composed text stream). Visibility and
|
|
30
|
+
the excluded-content rules are checked on composed ancestors, and `aria-labelledby` ids are looked up
|
|
31
|
+
in the element's own root. Closed shadow roots stay unreadable, and light text a closed component
|
|
32
|
+
does not render is left out. Frames are never entered.
|
|
33
|
+
2. **Version the target.** Text and element targets captured this way carry `tree: 'composed'`. A
|
|
34
|
+
target without it (every note saved before) is captured, stored and resolved by the document-only
|
|
35
|
+
rules exactly as before, so a saved note never changes what it points at, and a composed note can
|
|
36
|
+
never match a light-DOM node through the old path. The store accepts only the literal `'composed'`
|
|
37
|
+
and never on a page target.
|
|
38
|
+
3. **Selections across trees.** Selections are read with `Selection.getComposedRanges` (dictionary
|
|
39
|
+
form, then variadic). Boundary points map to stream positions through the composed walk, so a
|
|
40
|
+
selection may start in the page and end inside a component. A selection that spans a visible form
|
|
41
|
+
field or private content is refused. A selection that grows over such content no longer leaves the
|
|
42
|
+
last acceptable selection behind; this also fixes the document-only path. Without
|
|
43
|
+
`getComposedRanges` the helper keeps the document-only capture.
|
|
44
|
+
4. **Matches and marks.** A composed text match is a list of per-text-node ranges, since a `Range`
|
|
45
|
+
cannot span trees. Element candidates come from the document and every open shadow root, with the
|
|
46
|
+
same 2 000-candidate cap and equality rules. Context at the top of a shadow root is the component
|
|
47
|
+
that holds it. Marks clip to scrollports inside components and follow their scrolls and mutations.
|
|
48
|
+
5. **Inspector.** The inspector picks the nearest annotatable element on the event's composed path, so
|
|
49
|
+
an icon gives way to its button, and content inside open components is reachable. A custom element
|
|
50
|
+
is pickable when it carries readable text or a label. It says why when it refuses, in a muted chip
|
|
51
|
+
and a toast on click: form fields and private content, embedded frames, or a component whose
|
|
52
|
+
contents are private.
|
|
53
|
+
6. **Agents.** `page_notes_read` adds that a composed target lies inside a page component, where a
|
|
54
|
+
document-wide selector will not reach it.
|
|
55
|
+
|
|
56
|
+
## Out of scope
|
|
57
|
+
|
|
58
|
+
Iframes (cross-origin frames are unreachable by page script) and closed shadow roots.
|
|
59
|
+
|
|
60
|
+
## Migration
|
|
61
|
+
|
|
62
|
+
None. Existing notes have no `tree` and keep the old behaviour. Hosts that validate targets strictly
|
|
63
|
+
accept the optional field (the App's `shared/browserAnnotations.ts`).
|
|
64
|
+
|
|
65
|
+
## Checks
|
|
66
|
+
|
|
67
|
+
`src/annotations/pageScript.test.ts` (headless Chromium) adds a web-component fixture: picks inside
|
|
68
|
+
open roots, slotted and nested content, duplicate controls told apart by context, text inside and
|
|
69
|
+
across roots, refusal over a field, hints for fields and a closed component, and identical
|
|
70
|
+
legacy/composed captures on a page without components. `store.test.ts` covers the marker. In the App's
|
|
71
|
+
isolated probe instance (real WKWebView), text inside a component and text crossing into one were
|
|
72
|
+
captured, saved, resolved and revealed. Inspector clicks in WKWebView need real pointer input and were
|
|
73
|
+
not exercised there.
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: PROP-0039
|
|
3
|
+
title: Harden workspace writes against inode escapes and unverified retries
|
|
4
|
+
status: Accepted
|
|
5
|
+
created: 2026-10-26
|
|
6
|
+
updated: 2026-10-26
|
|
7
|
+
affects: [INV-GATE-3, INV-GATE-8, INV-TUI-8, 02-sessions-and-runs.md, 07-tools-and-gate.md, 11-terminal.md, 14-surfaces-and-parity.md, parity]
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# PROP-0039: Harden workspace writes against inode escapes and unverified retries
|
|
11
|
+
|
|
12
|
+
## Problem
|
|
13
|
+
|
|
14
|
+
PROP-0037 promises that model-controlled writes stay inside the pinned workspace unless a person
|
|
15
|
+
approves an escape. The current implementation checks canonical pathnames, but Pi performs native
|
|
16
|
+
`write` and `edit` operations afterward using ordinary filesystem calls. A hard link keeps an
|
|
17
|
+
in-workspace pathname while sharing an outside inode, and a parent symlink can change after the
|
|
18
|
+
check. Source review found both cases can bypass the intended approval boundary.
|
|
19
|
+
|
|
20
|
+
The Bash sandbox also exposes the live workspace as a writable path. A macOS integration
|
|
21
|
+
reproduction created a hard link from a file outside the workspace to a name inside it, then ran a
|
|
22
|
+
sandboxed Bash write through the in-workspace name. The command succeeded and the outside alias
|
|
23
|
+
contained the new content. Linux behavior has not yet been reproduced locally.
|
|
24
|
+
|
|
25
|
+
Finally, `workspaceSandbox.ts` infers a sandbox denial from matching text anywhere in captured
|
|
26
|
+
stdout/stderr. A command controls that output; the text can prompt for an unconfined retry even when
|
|
27
|
+
no sandbox denial occurred. Approval is still required, but the prompt's reason is not verified and
|
|
28
|
+
approval replays the entire command.
|
|
29
|
+
|
|
30
|
+
A separate launcher-selection issue was fixed in the 1.2.0 working tree: the sandbox launcher now
|
|
31
|
+
comes only from fixed system paths, with a fake-PATH regression test. This does not resolve the
|
|
32
|
+
remaining findings. No candidate, tag, or publication has been created.
|
|
33
|
+
|
|
34
|
+
## Affected rules
|
|
35
|
+
|
|
36
|
+
- **INV-GATE-3**, as it stands: “Bash first passes the gate's scope and authorization, then executes
|
|
37
|
+
only inside the OS sandbox; a detected write denial may enter a separate one-shot approval before
|
|
38
|
+
retry. The policy may tighten or deny a call, but cannot waive the boundary. Outside file writes
|
|
39
|
+
and sandbox-denied Bash retries cannot use remembered per-tool approval; only the eligible Full
|
|
40
|
+
Permission switch can answer automatically.” The output-triggered retry is replaced by an
|
|
41
|
+
explicit pre-execution scope request.
|
|
42
|
+
- **INV-GATE-8**, as it stands: “Native reads are bounded by process and operating-system
|
|
43
|
+
permissions, not by the workspace root; absolute and `~` paths are valid. Every run pins its
|
|
44
|
+
canonical `workspaceRoot`. Native `edit` and `write` targets must resolve inside it by default,
|
|
45
|
+
with symlink escapes refused; outside targets require one-call approval and cannot use remembered
|
|
46
|
+
tool grants. Bash, including the initial `!` command, is OS-sandboxed to write only inside that
|
|
47
|
+
root while retaining broad reads. Sandbox denial permits at most one retry after explicit
|
|
48
|
+
approval. Full Permission is the only standing boundary bypass and remains subject to host
|
|
49
|
+
policy, authorization, and read-only, plan, unattended, probe, improver and reflection
|
|
50
|
+
restrictions. Missing enforcement fails closed.” The rule must define containment by the actual
|
|
51
|
+
filesystem effect, not just the path string.
|
|
52
|
+
- **INV-TUI-8**: the terminal must present the same safe write and pre-execution approval behavior
|
|
53
|
+
as SDK sessions.
|
|
54
|
+
|
|
55
|
+
## Proposal
|
|
56
|
+
|
|
57
|
+
1. **Keep workspace-only as the default.** Each run continues to pin its canonical workspace root.
|
|
58
|
+
Reads remain broad as today.
|
|
59
|
+
2. **Enforce native writes at the operation.** Harness supplies the `write` and `edit` tools with
|
|
60
|
+
safe filesystem operations instead of delegating their mutations to Pi's default in-place
|
|
61
|
+
`fsWriteFile`. The operation revalidates the pinned target and performs an atomic replacement
|
|
62
|
+
under the OS-enforced workspace boundary. Replacing the in-workspace directory entry rather
|
|
63
|
+
than truncating a shared inode prevents a hard-link alias from changing an outside file. A
|
|
64
|
+
symlink or parent-directory swap cannot widen the operation's OS write scope. Outside targets
|
|
65
|
+
retain their existing human-only, one-call approval; the helper receives only that approved
|
|
66
|
+
canonical target. Tool names and model-facing schemas stay the same.
|
|
67
|
+
3. **Fail closed on external hard links for sandboxed Bash.** Before a default Bash call, inspect the
|
|
68
|
+
workspace for regular-file inodes whose link count exceeds the names found inside the workspace.
|
|
69
|
+
If the scan is incomplete or finds a possible outside alias, do not run the command; explain that
|
|
70
|
+
the alias must be removed or copied. The OS sandbox must also prevent the model's sandboxed
|
|
71
|
+
processes from creating a cross-boundary hard link. If a backend cannot establish both
|
|
72
|
+
conditions, it fails closed. A local process outside Harness with the same user's filesystem
|
|
73
|
+
permissions is not controlled by this rule; if protection from such peer processes is required,
|
|
74
|
+
that needs a separate inode-isolated workspace/snapshot design.
|
|
75
|
+
4. **Ask before broad Bash writes, never infer from output.** Add an explicit
|
|
76
|
+
`workspaceWriteScope` choice to the Harness-owned Bash call, defaulting to `workspace`. A call
|
|
77
|
+
requesting `outside` is approved before it runs, as a human-only, nonrememberable operation; the
|
|
78
|
+
approval presentation must expose the complete command (scrollable in the terminal). The
|
|
79
|
+
eligible Full Permission switch may answer only under its existing restrictions. After approval,
|
|
80
|
+
run that exact command once with broader filesystem access. stdout/stderr text never triggers
|
|
81
|
+
approval or an automatic retry, and a denied command is never replayed after partial effects.
|
|
82
|
+
5. **Keep other gates intact.** Plan, read-only, unattended, probe, improver and reflection
|
|
83
|
+
restrictions, host policy, authorization, and the tool capability set remain in force. Outside
|
|
84
|
+
writes and broad Bash calls cannot use remembered per-tool grants.
|
|
85
|
+
|
|
86
|
+
## Alternatives
|
|
87
|
+
|
|
88
|
+
- **Keep pathname checks and the output regex.** Rejected: hard links are invisible to `realpath`,
|
|
89
|
+
native operations race after validation, and command output is not evidence of a sandbox event.
|
|
90
|
+
- **Only reject files with `nlink > 1` for native writes.** Rejected: a link can be added after the
|
|
91
|
+
check, and the native operation remains subject to path swaps.
|
|
92
|
+
- **Run every shell call in a private copy-on-write workspace and commit changes back.** This gives
|
|
93
|
+
stronger inode isolation, including against peer processes, but changes shell visibility,
|
|
94
|
+
writeback/conflict behavior, metadata, storage use, and performance. It remains the alternative
|
|
95
|
+
if protection from same-user processes outside Harness is required.
|
|
96
|
+
- **Remove all outside-write capability.** Rejected for now: the existing contract intentionally
|
|
97
|
+
supports explicitly approved escapes. The proposed pre-execution request preserves that choice
|
|
98
|
+
without guessing from output.
|
|
99
|
+
- **Do nothing.** Leaves the default workspace boundary bypassable.
|
|
100
|
+
|
|
101
|
+
## Consequences
|
|
102
|
+
|
|
103
|
+
- The public server protocol and stored `RunRecord` layout need no new fields. The Bash tool schema
|
|
104
|
+
gains an optional scope choice; existing calls default to the current workspace-only behavior.
|
|
105
|
+
- SDK sessions and the standalone terminal must register the same safe native tools and apply the
|
|
106
|
+
same pre-execution Bash gate. Terminal approval remains available through its existing inbox.
|
|
107
|
+
- Atomic replacement changes the inode for a written path. The implementation must preserve normal
|
|
108
|
+
file mode behavior where possible and document any platform metadata that cannot be retained.
|
|
109
|
+
- Reject the filesystem root as an active workspace; otherwise every path is inside the pinned root
|
|
110
|
+
and the boundary provides no containment.
|
|
111
|
+
- A workspace containing a possible external hard link cannot use default sandboxed Bash until it
|
|
112
|
+
is repaired. Explicit outside scope remains a separate, visible approval, not a way to silently
|
|
113
|
+
reuse remembered grants.
|
|
114
|
+
- The boundary protects model-controlled operations inside Harness. Other local processes running
|
|
115
|
+
with the same user's filesystem permissions remain outside this proposal's protection. On macOS,
|
|
116
|
+
the OS sandbox denies all hard-link creation by sandboxed Bash, including links entirely inside the
|
|
117
|
+
workspace.
|
|
118
|
+
|
|
119
|
+
## Migration
|
|
120
|
+
|
|
121
|
+
No stored runs or workspace data are rewritten. Old sessions continue to pin the same workspace
|
|
122
|
+
root. Existing Bash calls omit `workspaceWriteScope` and therefore remain workspace-only; a command
|
|
123
|
+
that needs broader writes must be issued again with an explicit outside scope and approved before
|
|
124
|
+
execution. Existing outside-write approvals remain per-call and are not migrated into standing
|
|
125
|
+
grants.
|
|
126
|
+
|
|
127
|
+
## Checks
|
|
128
|
+
|
|
129
|
+
- Add adversarial tests for native hard-link writes, symlink/parent swaps between validation and
|
|
130
|
+
mutation, shell writes through pre-existing external hard links, and cross-boundary hard-link
|
|
131
|
+
creation on macOS and Linux.
|
|
132
|
+
- Verify command output containing denial-like text cannot request approval or rerun a command;
|
|
133
|
+
verify explicit outside scope asks before execution and runs at most once after approval.
|
|
134
|
+
- Verify the complete requested command is visible in outside-scope approval details, and Full
|
|
135
|
+
Permission and all read-only, plan, unattended, refinement, authorization, and host policy
|
|
136
|
+
restrictions remain intact in SDK and terminal paths.
|
|
137
|
+
- Run Harness `npm run typecheck`, `npm test`, and `npm run prove`; run the App compatibility checks
|
|
138
|
+
and inspect the relevant terminal behavior. Exercise the sandbox integration tests on macOS and
|
|
139
|
+
Linux before release.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: PROP-0040
|
|
3
|
+
title: One launch path and command contract across front ends
|
|
4
|
+
status: Accepted
|
|
5
|
+
created: 2026-11-19
|
|
6
|
+
updated: 2026-11-19
|
|
7
|
+
affects: [INV-EXT-1, INV-RUN-1, INV-VAR-4, INV-PLG-11, INV-PAR-1, INV-PAR-2, INV-STO-3, 01-extension-points.md, 02-sessions-and-runs.md, 03-variants.md, 04-prompt.md, 06-plugins-and-capabilities.md, 07-tools-and-gate.md, 10-server-protocol.md, 11-terminal.md, 12-storage.md, 13-world-tools.md, 14-surfaces-and-parity.md]
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# PROP-0040: One launch path and command contract across front ends
|
|
11
|
+
|
|
12
|
+
## Problem
|
|
13
|
+
|
|
14
|
+
The approved App parity and Solo tabs handoff implemented a shared command registry and standard
|
|
15
|
+
prompt sections, but the actual terminal still loads Pi command built-ins, terminal run records
|
|
16
|
+
omit variant pins, session operations differ across front ends, and native browser schemas differ.
|
|
17
|
+
Matching data roots alone does not share credentials: the terminal defaults to a file SecretStore
|
|
18
|
+
while a host may supply its Keychain. Existing compiler-only tests do not establish runtime parity.
|
|
19
|
+
|
|
20
|
+
## Affected rules
|
|
21
|
+
|
|
22
|
+
- INV-PAR-1: every capability a person uses in a host is a Harness capability with a terminal surface.
|
|
23
|
+
- INV-PAR-2: both surfaces must pass acceptance before a capability is complete.
|
|
24
|
+
- INV-RUN-1 and INV-VAR-4: runs retain account, variant and capability pins.
|
|
25
|
+
- INV-EXT-1: extension-point changes require a proposal; native backends remain tool providers.
|
|
26
|
+
- INV-STO-3: storage layout changes are explicit and owned by one Harness module.
|
|
27
|
+
- INV-PLG-11: plugin categories remain internal; surface availability is optional metadata, not a category.
|
|
28
|
+
|
|
29
|
+
## Proposal
|
|
30
|
+
|
|
31
|
+
The owner approved “Complete App parity and Solo tabs”, including one shared interactive default,
|
|
32
|
+
on 2026-11-19. This proposal records that design; implementation status is tracked separately.
|
|
33
|
+
|
|
34
|
+
1. Core commands are browser-safe data in `commands/registry.ts`. `commands.list` resolves the
|
|
35
|
+
effective scope's trusted plugin commands, prompts and skills with identical namespace and
|
|
36
|
+
collision rules. A menu entry alone does not prove command acceptance.
|
|
37
|
+
2. Saved-history controls cover tree, navigate, fork, clone, rename, last reply and JSONL export.
|
|
38
|
+
Commands requiring a live session use `SessionRunInput.command`: compact, summarized navigation
|
|
39
|
+
and HTML export. They retain normal run lifecycle, busy fencing, cancellation and pins.
|
|
40
|
+
3. `Launch.standard` supplies shared role, working-folder and connection wording. Tool and prompt
|
|
41
|
+
differences must be attributable to declared add-ons or explicit caller policy, not a front end.
|
|
42
|
+
4. Interactive defaults are Harness-owned: data root, state directory, neutral default variant
|
|
43
|
+
scope and credential backend. Explicit roots/scopes and existing session/continuation pins win.
|
|
44
|
+
No App-specific discovery, automatic root merge, account substitution, credential downgrade or
|
|
45
|
+
OAuth-store copying is permitted. Adoption of conflicting populated profiles is explicit.
|
|
46
|
+
5. Both surfaces load Harness-trusted resources and first-party hooks. Terminal-only Pi built-ins
|
|
47
|
+
and `ask_user_question` are removed; attended plan mode uses `ask_user`.
|
|
48
|
+
6. Browser contracts are backend-neutral and owned by Harness; the isolated and native host
|
|
49
|
+
backends share names, schemas, safety metadata and ref freshness. A backend must report an
|
|
50
|
+
unsupported operation honestly, never reinterpret a snapshot ref as a selector.
|
|
51
|
+
7. `get_capabilities` is a read-only Harness tool bound to the current run's frozen callable set
|
|
52
|
+
and actual registered schemas. Discovery never grants permission or accepts caller identity.
|
|
53
|
+
8. Optional `PluginDescriptor.surfaces` / `Plugin.surfaces` metadata is
|
|
54
|
+
`{ preferred: 'host', terminal: 'fallback' | 'unavailable', note }`. Generic host-backed
|
|
55
|
+
capabilities retain Harness ownership; inspection shows fallback/unavailable reasons.
|
|
56
|
+
9. Shared session references/catalog registration belong to Harness. Existing host transcript
|
|
57
|
+
presentation remains host-owned; native entry identities, not positional message counts,
|
|
58
|
+
connect navigation and fork to that presentation.
|
|
59
|
+
|
|
60
|
+
## Alternatives
|
|
61
|
+
|
|
62
|
+
- Do nothing: leaves command names that only approximate the advertised capabilities.
|
|
63
|
+
- Match roots manually: rejected by the owner's explicit choice of one shared default.
|
|
64
|
+
- Put browser contracts or session orchestration in the host: violates INV-PAR-1.
|
|
65
|
+
- Merge existing stores automatically: unsafe for account pins, credentials and conflicting variants.
|
|
66
|
+
|
|
67
|
+
## Consequences
|
|
68
|
+
|
|
69
|
+
Server methods and SDK fields are additive. Existing session histories and account IDs remain valid.
|
|
70
|
+
Terminal run records gain variant identity. Host browser adapters implement the common contract;
|
|
71
|
+
legacy native routes may remain non-model-visible compatibility aliases for one release. Metadata
|
|
72
|
+
labels do not certify acceptance or waive the gate.
|
|
73
|
+
|
|
74
|
+
## Migration
|
|
75
|
+
|
|
76
|
+
Keep explicit custom roots and historical pins. Seed only an absent default scope through validated
|
|
77
|
+
variant APIs. Shared profile adoption must preserve originals, report conflicts/failure, and never
|
|
78
|
+
silently select an empty replacement. Credentials remain in their owning backend. Shared processes
|
|
79
|
+
must coordinate credential refresh and respect live run owners. Development/disposable profiles
|
|
80
|
+
remain isolated from production. No migration is exercised on owner data during implementation.
|
|
81
|
+
|
|
82
|
+
## Checks
|
|
83
|
+
|
|
84
|
+
Harness typecheck, full tests and prove; deterministic terminal verification; App renderer/sidecar,
|
|
85
|
+
layer/UI and Rust checks; full browser fixtures; shared UI and both consuming applications' checks.
|
|
86
|
+
Runtime parity compares actual prepared launches, tool schemas and recorded pins. Native WebKit
|
|
87
|
+
acceptance uses an isolated profile. Real-provider/cache checks require separate owner permission.
|