@north-light/crouter 0.3.197 → 0.3.199
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/dist/api/client.d.ts +19 -19
- package/dist/api/client.js +29 -37
- package/dist/api/dto/broker-ops.d.ts +3 -1
- package/dist/api/dto/broker.d.ts +13 -2
- package/dist/api/dto/broker.js +4 -4
- package/dist/api/dto/human.d.ts +6 -5
- package/dist/api/dto/inbox.d.ts +126 -33
- package/dist/api/dto/nodes.d.ts +8 -2
- package/dist/api/dto/profiles.d.ts +23 -0
- package/dist/api/dto/profiles.js +2 -2
- package/dist/api/dto/worktree.d.ts +3 -5
- package/dist/api/routes.d.ts +3 -5
- package/dist/api/routes.js +4 -6
- package/dist/builtin-memory/00-runtime-base.md +8 -8
- package/dist/builtin-memory/01-spine/01-no-manager.md +1 -1
- package/dist/builtin-memory/02-lifecycle/00-terminal.md +3 -3
- package/dist/builtin-memory/04-orchestration-kernel.md +6 -6
- package/dist/builtin-memory/05-kinds/design/00-base.md +1 -1
- package/dist/builtin-memory/05-kinds/plan/reviewers/security.md +2 -2
- package/dist/builtin-memory/05-kinds/review/00-base.md +2 -2
- package/dist/builtin-memory/05-kinds/review/01-orchestrator.md +1 -1
- package/dist/builtin-memory/05-kinds/spec/01-orchestrator.md +1 -1
- package/dist/builtin-memory/insights/capture.md +2 -2
- package/dist/builtin-memory/insights/init.md +3 -3
- package/dist/builtin-memory/internal/INDEX.md +1 -1
- package/dist/builtin-memory/internal/memory-loading.md +1 -1
- package/dist/builtin-memory/internal/nodes-and-canvas.md +3 -3
- package/dist/builtin-memory/internal/plugins.md +59 -2
- package/dist/builtin-memory/internal/storage-tiers.md +3 -1
- package/dist/builtin-memory/spec/roadmap.md +2 -2
- package/dist/builtin-memory/testing.md +1 -1
- package/dist/builtin-memory/wedged-child-on-runaway-bash.md +1 -1
- package/dist/clients/attach/chrome/bash-jobs.js +3 -3
- package/dist/clients/attach/render/chat-view.d.ts +29 -9
- package/dist/clients/attach/render/chat-view.js +64 -35
- package/dist/clients/attach/render/markdown-source.js +0 -6
- package/dist/clients/attach/render/page-block.d.ts +34 -0
- package/dist/clients/attach/render/page-block.js +226 -0
- package/dist/clients/attach/render/tool-calls.js +16 -2
- package/dist/clients/attach/session/whip.d.ts +2 -0
- package/dist/clients/attach/session/whip.js +2 -0
- package/dist/clients/attach/viewer.js +1419 -982
- package/dist/clients/conversation/projection.js +18 -3
- package/dist/clients/inbox/__tests__/serial/inbox-controller.test.js +9 -6
- package/dist/clients/inbox/__tests__/serial/mount-panel.test.js +13 -14
- package/dist/clients/inbox/controller.js +10 -16
- package/dist/clients/inbox/page-adapter.d.ts +3 -4
- package/dist/clients/inbox/page-adapter.js +3 -4
- package/dist/clients/inbox/resolve.d.ts +1 -1
- package/dist/clients/inbox/resolve.js +3 -3
- package/dist/clients/inbox/review/document-surface.js +3 -1
- package/dist/clients/inbox/review/state.d.ts +2 -1
- package/dist/clients/inbox/review/state.js +5 -16
- package/dist/clients/inbox/tui/input.js +37 -19
- package/dist/clients/inbox/tui/panel.js +5 -31
- package/dist/clients/inbox/tui/render.d.ts +11 -0
- package/dist/clients/inbox/tui/render.js +101 -36
- package/dist/clients/inbox/tui/slots.d.ts +4 -4
- package/dist/clients/inbox/tui/slots.js +19 -44
- package/dist/clients/inbox/tui/types.d.ts +6 -10
- package/dist/clients/inbox/tui.js +2 -2
- package/dist/commands/__tests__/human.test.js +118 -24
- package/dist/commands/__tests__/node-message.test.js +14 -0
- package/dist/commands/attention.js +4 -4
- package/dist/commands/canvas-browse.js +1 -1
- package/dist/commands/canvas-snapshot.js +1 -1
- package/dist/commands/canvas.js +1 -1
- package/dist/commands/dashboard.js +1 -1
- package/dist/commands/human/{doc.d.ts → components.d.ts} +1 -1
- package/dist/commands/human/components.js +77 -0
- package/dist/commands/human/feedback.d.ts +2 -0
- package/dist/commands/human/feedback.js +108 -0
- package/dist/commands/human/prompts.d.ts +17 -8
- package/dist/commands/human/prompts.js +217 -226
- package/dist/commands/human/queue.js +57 -88
- package/dist/commands/human/shared.d.ts +4 -15
- package/dist/commands/human/shared.js +19 -61
- package/dist/commands/human.js +32 -19
- package/dist/commands/memory/origin.js +2 -2
- package/dist/commands/node/bash.js +4 -4
- package/dist/commands/node/inspect.js +3 -3
- package/dist/commands/node/lifecycle.js +1 -1
- package/dist/commands/node/message.js +2 -2
- package/dist/commands/node-worktree.js +8 -8
- package/dist/commands/pkg/browse.js +1 -1
- package/dist/commands/pkg/plugin-manage.js +129 -10
- package/dist/commands/profile/delete.js +41 -15
- package/dist/commands/profile.js +1 -1
- package/dist/commands/push.js +1 -1
- package/dist/commands/surface/node/focus.js +29 -14
- package/dist/commands/surface-edit.js +3 -3
- package/dist/commands/surface-inbox.d.ts +2 -0
- package/dist/commands/{human/inbox.js → surface-inbox.js} +14 -18
- package/dist/commands/surface.js +2 -1
- package/dist/commands/sys/doctor.js +60 -3
- package/dist/commands/sys/feedback.js +79 -25
- package/dist/commands/sys/settings.js +1 -1
- package/dist/core/__tests__/cron-broker-capacity.test.js +1 -1
- package/dist/core/__tests__/daemon-boot.test.js +7 -4
- package/dist/core/__tests__/dead-node-policy-table.test.js +20 -36
- package/dist/core/__tests__/extension-abort.test.js +5 -2
- package/dist/core/__tests__/fixtures/fake-engine.d.ts +13 -2
- package/dist/core/__tests__/fixtures/fake-engine.js +47 -3
- package/dist/core/__tests__/human-cancel-guard.test.js +31 -10
- package/dist/core/__tests__/human-deliver.test.js +41 -45
- package/dist/core/__tests__/human-node-not-supervised.test.js +1 -1
- package/dist/core/__tests__/plugin-page-components.test.js +157 -0
- package/dist/core/__tests__/seam/broker-crash-teardown.test.js +13 -11
- package/dist/core/__tests__/seam/dormancy-release.test.js +103 -4
- package/dist/core/__tests__/serial/flagship-lifecycle.test.js +2 -2
- package/dist/core/__tests__/serial/human-deliver-e2e.test.js +12 -16
- package/dist/core/__tests__/serial/live-mutation.test.js +1 -1
- package/dist/core/__tests__/serial/tmux-surface.test.js +4 -2
- package/dist/core/__tests__/serial/worktree.test.js +24 -198
- package/dist/core/__tests__/session-cycles.test.js +22 -0
- package/dist/core/__tests__/stop-guard.test.js +4 -4
- package/dist/core/__tests__/watchdog-abort-arms-retry.test.js +19 -4
- package/dist/core/bash-jobs.d.ts +6 -0
- package/dist/core/bash-jobs.js +10 -0
- package/dist/core/canvas/__tests__/attention.test.js +8 -5
- package/dist/core/canvas/__tests__/render-remote.test.js +5 -5
- package/dist/core/canvas/attention.js +8 -6
- package/dist/core/canvas/browse/app.d.ts +1 -1
- package/dist/core/canvas/browse/app.js +21 -3
- package/dist/core/canvas/browse/model.d.ts +8 -2
- package/dist/core/canvas/browse/model.js +11 -4
- package/dist/core/canvas/browse/render.d.ts +4 -0
- package/dist/core/canvas/browse/render.js +5 -1
- package/dist/core/canvas/canvas.d.ts +33 -0
- package/dist/core/canvas/canvas.js +92 -0
- package/dist/core/canvas/crons.d.ts +9 -0
- package/dist/core/canvas/crons.js +51 -0
- package/dist/core/canvas/node-order.d.ts +22 -1
- package/dist/core/canvas/node-order.js +26 -1
- package/dist/core/canvas/render-source.d.ts +5 -0
- package/dist/core/canvas/render-source.js +1 -0
- package/dist/core/canvas/types.d.ts +9 -3
- package/dist/core/command-plugins/bundle.d.ts +6 -1
- package/dist/core/command-plugins/bundle.js +26 -13
- package/dist/core/command.js +8 -12
- package/dist/core/config.d.ts +47 -1
- package/dist/core/config.js +138 -4
- package/dist/core/help.d.ts +3 -0
- package/dist/core/help.js +1 -1
- package/dist/core/human/__tests__/page-catalog.test.d.ts +1 -0
- package/dist/core/human/__tests__/page-catalog.test.js +20 -0
- package/dist/core/human/__tests__/page-tickets.test.js +68 -34
- package/dist/core/human/__tests__/page.test.js +60 -119
- package/dist/core/human/__tests__/serial/inbox-core.test.js +6 -16
- package/dist/core/human/answer-text.d.ts +3 -0
- package/dist/core/human/answer-text.js +98 -0
- package/dist/core/human/answer.d.ts +53 -0
- package/dist/core/human/answer.js +119 -0
- package/dist/core/human/component-docs.d.ts +18 -0
- package/dist/core/human/component-docs.js +434 -0
- package/dist/core/human/convention.d.ts +17 -3
- package/dist/core/human/convention.js +36 -5
- package/dist/core/human/feedback-companion.d.ts +20 -0
- package/dist/core/human/feedback-companion.js +98 -0
- package/dist/core/human/feedback.d.ts +65 -0
- package/dist/core/human/feedback.js +116 -0
- package/dist/core/human/page-catalog.d.ts +56 -5
- package/dist/core/human/page-catalog.js +151 -22
- package/dist/core/human/page-errors.d.ts +4 -0
- package/dist/core/human/page-errors.js +7 -0
- package/dist/core/human/page-eval.d.ts +20 -0
- package/dist/core/human/page-eval.js +123 -0
- package/dist/core/human/page-schema.d.ts +48 -116
- package/dist/core/human/page-schema.js +100 -72
- package/dist/core/human/page-synth.d.ts +2 -4
- package/dist/core/human/page-synth.js +20 -7
- package/dist/core/human/page.d.ts +13 -21
- package/dist/core/human/page.js +147 -391
- package/dist/core/human/review-schema.d.ts +1 -0
- package/dist/core/human/review-schema.js +1 -1
- package/dist/core/human/root.d.ts +6 -2
- package/dist/core/human/root.js +12 -4
- package/dist/core/human/scan.d.ts +3 -3
- package/dist/core/human/scan.js +21 -21
- package/dist/core/human/summary.d.ts +2 -6
- package/dist/core/human/summary.js +3 -59
- package/dist/core/human/tickets.d.ts +22 -15
- package/dist/core/human/tickets.js +90 -28
- package/dist/core/human/types.d.ts +14 -2
- package/dist/core/keybindings/catalog.d.ts +2 -2
- package/dist/core/keybindings/catalog.js +1 -0
- package/dist/core/preview-registry.js +8 -10
- package/dist/core/profiles/default-binding.d.ts +4 -0
- package/dist/core/profiles/default-binding.js +24 -0
- package/dist/core/profiles/deletion-reservation.d.ts +8 -0
- package/dist/core/profiles/deletion-reservation.js +38 -0
- package/dist/core/profiles/manifest.d.ts +3 -0
- package/dist/core/profiles/manifest.js +12 -0
- package/dist/core/profiles/select.js +2 -2
- package/dist/core/review/realize.js +12 -4
- package/dist/core/review/store.d.ts +6 -0
- package/dist/core/review/store.js +31 -0
- package/dist/core/runtime/bearings.d.ts +0 -4
- package/dist/core/runtime/bearings.js +4 -62
- package/dist/core/runtime/bin-contributions.d.ts +44 -0
- package/dist/core/runtime/bin-contributions.js +186 -0
- package/dist/core/runtime/boot-root.js +6 -1
- package/dist/core/runtime/broker/client-registry.d.ts +4 -0
- package/dist/core/runtime/broker/client-registry.js +13 -1
- package/dist/core/runtime/broker/extension-abort.d.ts +1 -1
- package/dist/core/runtime/broker/extension-abort.js +4 -2
- package/dist/core/runtime/broker/fault-retry.js +4 -0
- package/dist/core/runtime/broker/frame-dispatch.d.ts +3 -1
- package/dist/core/runtime/broker/frame-dispatch.js +5 -6
- package/dist/core/runtime/broker/read-ops.d.ts +1 -1
- package/dist/core/runtime/broker/read-ops.js +2 -2
- package/dist/core/runtime/broker/rebind.d.ts +1 -0
- package/dist/core/runtime/broker/rebind.js +6 -1
- package/dist/core/runtime/broker-extension-render.js +19 -0
- package/dist/core/runtime/broker-protocol.d.ts +14 -0
- package/dist/core/runtime/broker.d.ts +1 -1
- package/dist/core/runtime/broker.js +25 -12
- package/dist/core/runtime/busy.d.ts +4 -3
- package/dist/core/runtime/busy.js +4 -3
- package/dist/core/runtime/front-door-env.d.ts +5 -0
- package/dist/core/runtime/front-door-env.js +16 -0
- package/dist/core/runtime/front-door.d.ts +1 -5
- package/dist/core/runtime/front-door.js +2 -5
- package/dist/core/runtime/host.d.ts +1 -1
- package/dist/core/runtime/invocation.d.ts +6 -0
- package/dist/core/runtime/invocation.js +10 -0
- package/dist/core/runtime/kickoff.js +34 -0
- package/dist/core/runtime/launch.d.ts +2 -6
- package/dist/core/runtime/node-read.js +4 -1
- package/dist/core/runtime/nodes.js +2 -0
- package/dist/core/runtime/promote.d.ts +1 -0
- package/dist/core/runtime/promote.js +3 -1
- package/dist/core/runtime/session-cycles.d.ts +6 -0
- package/dist/core/runtime/session-cycles.js +15 -1
- package/dist/core/runtime/session-visibility.d.ts +17 -8
- package/dist/core/runtime/session-visibility.js +19 -10
- package/dist/core/runtime/spawn-env.d.ts +9 -1
- package/dist/core/runtime/spawn-env.js +62 -2
- package/dist/core/runtime/spawn.js +4 -4
- package/dist/core/runtime/stop-guard.d.ts +2 -2
- package/dist/core/runtime/stop-guard.js +2 -2
- package/dist/core/runtime/stop-signals.d.ts +1 -1
- package/dist/core/runtime/stop-signals.js +2 -2
- package/dist/core/runtime/tmux-bindings.js +1 -1
- package/dist/core/session-model/session-state.d.ts +4 -3
- package/dist/core/session-model/session-state.js +14 -1
- package/dist/core/user-settings.d.ts +36 -2
- package/dist/core/user-settings.js +56 -14
- package/dist/core/worktree.d.ts +15 -45
- package/dist/core/worktree.js +59 -261
- package/dist/daemon/api/__tests__/seam/profile-delete.test.d.ts +1 -0
- package/dist/daemon/api/__tests__/seam/profile-delete.test.js +386 -0
- package/dist/daemon/api/handlers/bash-jobs.js +1 -1
- package/dist/daemon/api/handlers/broker-ops.js +9 -5
- package/dist/daemon/api/handlers/feedback-comments.d.ts +2 -0
- package/dist/daemon/api/handlers/feedback-comments.js +207 -0
- package/dist/daemon/api/handlers/human.js +24 -20
- package/dist/daemon/api/handlers/inbox.d.ts +10 -0
- package/dist/daemon/api/handlers/inbox.js +48 -109
- package/dist/daemon/api/handlers/profiles.js +11 -29
- package/dist/daemon/api/map.d.ts +6 -1
- package/dist/daemon/api/map.js +23 -0
- package/dist/daemon/api/server.js +3 -1
- package/dist/daemon/companion-retire.d.ts +2 -0
- package/dist/daemon/companion-retire.js +33 -0
- package/dist/daemon/cron-run.js +29 -17
- package/dist/daemon/crtrd.js +1 -1
- package/dist/daemon/fleet.d.ts +22 -10
- package/dist/daemon/fleet.js +43 -24
- package/dist/daemon/human/finish.d.ts +12 -6
- package/dist/daemon/human/finish.js +134 -54
- package/dist/daemon/human/sweep.js +9 -3
- package/dist/daemon/profile-delete.d.ts +7 -0
- package/dist/daemon/profile-delete.js +306 -0
- package/dist/daemon/reconcilers/broker-supervision.js +14 -9
- package/dist/daemon/reconcilers/dormant-inbox.js +11 -6
- package/dist/daemon/reconcilers/live-obligation.d.ts +21 -1
- package/dist/daemon/reconcilers/live-obligation.js +30 -2
- package/dist/daemon/reconcilers/storage-maintenance.d.ts +5 -0
- package/dist/daemon/reconcilers/storage-maintenance.js +28 -1
- package/dist/daemon/review/deliver.js +3 -3
- package/dist/daemon/review/finish.d.ts +0 -2
- package/dist/daemon/review/finish.js +1 -29
- package/dist/daemon/review/sweep.js +12 -1
- package/dist/pi-extensions/__tests__/canvas-bash-valve.test.js +56 -1
- package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +4 -4
- package/dist/pi-extensions/canvas-bash-valve.d.ts +9 -1
- package/dist/pi-extensions/canvas-bash-valve.js +31 -13
- package/dist/pi-extensions/canvas-inbox-watcher.js +1 -1
- package/dist/pi-extensions/canvas-review-boundary.d.ts +4 -0
- package/dist/pi-extensions/canvas-review-boundary.js +18 -9
- package/dist/pi-extensions/canvas-stophook.js +4 -4
- package/dist/shared/generated-context.js +2 -2
- package/dist/types.d.ts +61 -5
- package/dist/types.js +8 -2
- package/package.json +4 -4
- package/runtime.lock.json +5 -33
- package/scripts/install-runtime.mjs +19 -24
- package/dist/builtin-memory/init.md +0 -38
- package/dist/builtin-memory/plan.md +0 -19
- package/dist/builtin-memory/spec.md +0 -19
- package/dist/clients/attach/render/html-markdown.d.ts +0 -13
- package/dist/clients/attach/render/html-markdown.js +0 -206
- package/dist/commands/human/doc.js +0 -144
- package/dist/commands/human/inbox.d.ts +0 -2
- package/dist/core/human/__tests__/page-render.test.js +0 -49
- package/dist/core/human/markdown-html.d.ts +0 -8
- package/dist/core/human/markdown-html.js +0 -581
- package/dist/core/human/page-render.d.ts +0 -3
- package/dist/core/human/page-render.js +0 -131
- package/dist/pages/bundle.css +0 -1
- package/dist/pages/bundle.js +0 -1347
- package/dist/pages/comments.d.ts +0 -43
- package/dist/pages/comments.js +0 -125
- package/dist/pages/elements/cards.d.ts +0 -17
- package/dist/pages/elements/cards.js +0 -802
- package/dist/pages/elements/chart.js +0 -648
- package/dist/pages/elements/options.d.ts +0 -21
- package/dist/pages/elements/options.js +0 -629
- package/dist/pages/elements/pages.d.ts +0 -24
- package/dist/pages/elements/pages.js +0 -355
- package/dist/pages/elements/slot.d.ts +0 -21
- package/dist/pages/elements/slot.js +0 -105
- package/dist/pages/elements/table.d.ts +0 -19
- package/dist/pages/elements/table.js +0 -935
- package/dist/pages/elements/text.d.ts +0 -25
- package/dist/pages/elements/text.js +0 -968
- package/dist/pages/entry.d.ts +0 -8
- package/dist/pages/entry.js +0 -8
- package/dist/pages/host.d.ts +0 -158
- package/dist/pages/host.js +0 -182
- package/dist/pages/register.d.ts +0 -2
- package/dist/pages/register.js +0 -3
- package/dist/pages/slot-config.d.ts +0 -36
- package/dist/pages/slot-config.js +0 -50
- package/dist/pages/types.d.ts +0 -98
- package/dist/pages/types.js +0 -23
- /package/dist/{core/human/__tests__/page-render.test.d.ts → commands/__tests__/node-message.test.d.ts} +0 -0
- /package/dist/{pages/elements/chart.d.ts → core/__tests__/plugin-page-components.test.d.ts} +0 -0
|
@@ -38,21 +38,26 @@ function syntheticBoundary(timestamp) {
|
|
|
38
38
|
/**
|
|
39
39
|
* Project snapshot messages to the visible window for a review companion.
|
|
40
40
|
*
|
|
41
|
+
* A companion passes its binding's review id so the slice starts at ITS OWN
|
|
42
|
+
* boundary marker: a node forked from another companion inherits that
|
|
43
|
+
* companion's earlier marker, and slicing at the first marker of any review
|
|
44
|
+
* would reveal the origin companion's transcript.
|
|
45
|
+
*
|
|
41
46
|
* Contract (in evaluation order):
|
|
42
|
-
* 1.
|
|
43
|
-
*
|
|
44
|
-
* the person.
|
|
45
|
-
* 2. Not a
|
|
46
|
-
* nodes are not filtered.
|
|
47
|
-
* 3.
|
|
47
|
+
* 1. This binding's marker present (any marker when the node has no binding) →
|
|
48
|
+
* slice from the **first** occurrence (marker included) to the end.
|
|
49
|
+
* Everything before the marker is inherited context, hidden from the person.
|
|
50
|
+
* 2. Not a companion (`boundaryReviewId` undefined) → return input unchanged
|
|
51
|
+
* (same reference). Ordinary nodes are not filtered.
|
|
52
|
+
* 3. Bound but no matching marker → a leading compaction summary is replaced
|
|
48
53
|
* with a synthetic boundary while its retained tail remains visible. Every
|
|
49
54
|
* other markerless shape fails closed with the synthetic boundary alone.
|
|
50
55
|
*/
|
|
51
56
|
export function visibleMessages(messages, opts) {
|
|
52
|
-
const markerIndex = messages.findIndex((message) => isReviewBoundary(message));
|
|
57
|
+
const markerIndex = messages.findIndex((message) => isReviewBoundary(message, opts.boundaryReviewId));
|
|
53
58
|
if (markerIndex !== -1)
|
|
54
59
|
return messages.slice(markerIndex);
|
|
55
|
-
if (
|
|
60
|
+
if (opts.boundaryReviewId === undefined)
|
|
56
61
|
return messages;
|
|
57
62
|
const [first, ...retainedTail] = messages;
|
|
58
63
|
if (first?.role === 'compactionSummary') {
|
|
@@ -68,14 +73,18 @@ export function visibleMessages(messages, opts) {
|
|
|
68
73
|
* boundary is crossed, its complete descendant subtree remains navigable. An
|
|
69
74
|
* absent boundary produces an empty tree, so picker previews never disclose an
|
|
70
75
|
* inherited entry before a mutation guard can reject its selection.
|
|
76
|
+
*
|
|
77
|
+
* `boundaryReviewId` selects only this binding's marker as a root, so a
|
|
78
|
+
* companion forked from another companion never navigates into the inherited
|
|
79
|
+
* subtree rooted at the origin's earlier marker.
|
|
71
80
|
*/
|
|
72
|
-
export function boundaryRootedTree(tree) {
|
|
81
|
+
export function boundaryRootedTree(tree, boundaryReviewId) {
|
|
73
82
|
const retainSubtree = (node) => ({
|
|
74
83
|
...node,
|
|
75
84
|
children: node.children.map(retainSubtree),
|
|
76
85
|
});
|
|
77
86
|
const project = (node) => {
|
|
78
|
-
if (isReviewBoundary(node.entry))
|
|
87
|
+
if (isReviewBoundary(node.entry, boundaryReviewId))
|
|
79
88
|
return [retainSubtree(node)];
|
|
80
89
|
return node.children.flatMap(project);
|
|
81
90
|
};
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import type { PiInvocation } from './
|
|
1
|
+
import type { PiInvocation } from './invocation.js';
|
|
2
|
+
/** The unshimmed PATH admitted from the host. Broker and cron shells resolve
|
|
3
|
+
* crouter-owned executables from this value, while commands those shells run
|
|
4
|
+
* still receive the shim-prepended PATH. */
|
|
5
|
+
export declare const ADMITTED_HOST_PATH_ENV = "CRTR_ADMITTED_HOST_PATH";
|
|
6
|
+
/** Resolve a regular executable against a shell PATH without executing it.
|
|
7
|
+
* The result is absolute, or null when no PATH entry supplies the command. */
|
|
8
|
+
export declare function resolvePathExecutable(name: string, env: NodeJS.ProcessEnv, cwd: string): string | null;
|
|
9
|
+
export declare function resolveAdmittedHostCommand(name: string, env: NodeJS.ProcessEnv, cwd: string): string;
|
|
2
10
|
/** Sources A–C: the operational base shared by the broker boundary (this
|
|
3
11
|
* module's `buildBrokerEnv`) and cron executor — the single shared definition
|
|
4
12
|
* of "non-secret host state the runtime exposes to any spawned shell." Does not include
|
|
@@ -15,6 +15,13 @@
|
|
|
15
15
|
// `spawnEnv.allow` entry. `inv.env` (D) is crtr-constructed and trusted, so
|
|
16
16
|
// it overlays unconditionally, layered after E.
|
|
17
17
|
//
|
|
18
|
+
// One name IS rewritten rather than merely admitted: `PATH`. Bare-binary
|
|
19
|
+
// contributions (`bin` in a plugin manifest or a scope `config.json`) are
|
|
20
|
+
// materialized into a crouter-owned shim directory by
|
|
21
|
+
// `core/runtime/bin-contributions.ts`, and that directory is PREPENDED here so
|
|
22
|
+
// a declared bare command wins its name in every node's bash. The admitted
|
|
23
|
+
// host PATH stays intact behind it.
|
|
24
|
+
//
|
|
18
25
|
// `GIT_*` is deliberately absent from the allowlist: the whole namespace is an
|
|
19
26
|
// auth/config-injection surface (`GIT_CONFIG_KEY_*`/`GIT_CONFIG_VALUE_*`,
|
|
20
27
|
// `GIT_ASKPASS`, `GIT_SSH_COMMAND`), not a non-secret operational family, and
|
|
@@ -22,9 +29,12 @@
|
|
|
22
29
|
// `~/.gitconfig`, reached through the allowlisted `HOME`; SSH remotes via the
|
|
23
30
|
// allowlisted `SSH_AUTH_SOCK`). A deliberate `GIT_*` need goes through
|
|
24
31
|
// `spawnEnv.allow`.
|
|
32
|
+
import { statSync } from 'node:fs';
|
|
33
|
+
import { delimiter, resolve } from 'node:path';
|
|
25
34
|
import { readMergedLaunchConfig } from '../config.js';
|
|
26
35
|
import { readProfileEnvVars } from '../profiles/env-store.js';
|
|
27
|
-
import {
|
|
36
|
+
import { binShimDirFor } from './bin-contributions.js';
|
|
37
|
+
import { FRONT_DOOR_ENV } from './front-door-env.js';
|
|
28
38
|
/** A1 — literal env-var names copied verbatim (no value inspection): a login
|
|
29
39
|
* shell plus dev toolchain needs exactly these, and none of them can carry a
|
|
30
40
|
* credential. */
|
|
@@ -54,6 +64,39 @@ const OPERATIONAL_LITERAL_NAMES = new Set([
|
|
|
54
64
|
* file-backed in `auth.json`, never an env value). `GIT_` is NOT here — see
|
|
55
65
|
* module comment. */
|
|
56
66
|
const OPERATIONAL_PREFIXES = ['LC_', 'XDG_', 'PI_'];
|
|
67
|
+
/** The unshimmed PATH admitted from the host. Broker and cron shells resolve
|
|
68
|
+
* crouter-owned executables from this value, while commands those shells run
|
|
69
|
+
* still receive the shim-prepended PATH. */
|
|
70
|
+
export const ADMITTED_HOST_PATH_ENV = 'CRTR_ADMITTED_HOST_PATH';
|
|
71
|
+
/** Resolve a regular executable against a shell PATH without executing it.
|
|
72
|
+
* The result is absolute, or null when no PATH entry supplies the command. */
|
|
73
|
+
export function resolvePathExecutable(name, env, cwd) {
|
|
74
|
+
const pathValue = env['PATH'];
|
|
75
|
+
if (pathValue === undefined || pathValue === '')
|
|
76
|
+
return null;
|
|
77
|
+
for (const directory of pathValue.split(delimiter)) {
|
|
78
|
+
const candidate = resolve(cwd, directory === '' ? '.' : directory, name);
|
|
79
|
+
try {
|
|
80
|
+
const stat = statSync(candidate);
|
|
81
|
+
if (stat.isFile() && (stat.mode & 0o111) !== 0)
|
|
82
|
+
return candidate;
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// Keep searching exactly as PATH resolution does.
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
export function resolveAdmittedHostCommand(name, env, cwd) {
|
|
91
|
+
const pathValue = env[ADMITTED_HOST_PATH_ENV] ?? env['PATH'];
|
|
92
|
+
if (pathValue === undefined || pathValue === '') {
|
|
93
|
+
throw new Error(`cannot resolve crouter-owned ${name}: the admitted host PATH is empty`);
|
|
94
|
+
}
|
|
95
|
+
const command = resolvePathExecutable(name, { PATH: pathValue }, cwd);
|
|
96
|
+
if (command !== null)
|
|
97
|
+
return command;
|
|
98
|
+
throw new Error(`cannot resolve crouter-owned ${name} from the admitted host PATH`);
|
|
99
|
+
}
|
|
57
100
|
/** A2 — proxy var names. Admitted only when the value's URL authority carries
|
|
58
101
|
* no userinfo component (no `user@` / `user:pass@`) — the one value-inspected
|
|
59
102
|
* entry in the whole builder, because a proxy var is the single operational
|
|
@@ -151,6 +194,21 @@ export function buildOperationalEnvBase(opts) {
|
|
|
151
194
|
out[key] = value;
|
|
152
195
|
}
|
|
153
196
|
}
|
|
197
|
+
// Preserve the unshimmed admitted host PATH across broker and cron children.
|
|
198
|
+
// A nested `crtr` launched from an agent inherits this constructed value,
|
|
199
|
+
// rather than mistaking its shim-prepended PATH for the host path.
|
|
200
|
+
const admittedHostPath = host[ADMITTED_HOST_PATH_ENV] ?? out['PATH'];
|
|
201
|
+
if (admittedHostPath !== undefined && admittedHostPath !== '')
|
|
202
|
+
out[ADMITTED_HOST_PATH_ENV] = admittedHostPath;
|
|
203
|
+
// Bare-binary contributions (`core/runtime/bin-contributions.ts`): the shim
|
|
204
|
+
// dir holding one symlink per declared bare command, PREPENDED so a
|
|
205
|
+
// contribution wins its name, with the host PATH admitted above left intact
|
|
206
|
+
// behind it. Resolved from the TARGET's own cwd/profile like source C.
|
|
207
|
+
const shimDir = binShimDirFor(opts.targetCwd, opts.targetProfileId);
|
|
208
|
+
if (shimDir !== null) {
|
|
209
|
+
const hostPath = out['PATH'];
|
|
210
|
+
out['PATH'] = hostPath === undefined || hostPath === '' ? shimDir : `${shimDir}:${hostPath}`;
|
|
211
|
+
}
|
|
154
212
|
return out;
|
|
155
213
|
}
|
|
156
214
|
/** The one authoritative broker child env: sources A–C (the operational
|
|
@@ -170,10 +228,12 @@ export function buildOperationalEnvBase(opts) {
|
|
|
170
228
|
export function buildBrokerEnv(inv) {
|
|
171
229
|
const targetCwd = inv.env['CRTR_NODE_CWD'] ?? process.cwd();
|
|
172
230
|
const targetProfileId = inv.env['CRTR_PROFILE_ID'] || null;
|
|
231
|
+
const operational = buildOperationalEnvBase({ targetCwd, targetProfileId });
|
|
173
232
|
return {
|
|
174
|
-
...
|
|
233
|
+
...operational,
|
|
175
234
|
...readProfileEnvVars(targetProfileId),
|
|
176
235
|
...inv.env,
|
|
236
|
+
[ADMITTED_HOST_PATH_ENV]: operational[ADMITTED_HOST_PATH_ENV],
|
|
177
237
|
[FRONT_DOOR_ENV]: '1',
|
|
178
238
|
};
|
|
179
239
|
}
|
|
@@ -401,15 +401,15 @@ export async function spawnChildPrepared(opts, beforeBrokerLaunch) {
|
|
|
401
401
|
// have bound view.sock yet. Hand the attach pane CRTR_ATTACH_WAIT_MS so
|
|
402
402
|
// it self-polls the socket until it accepts instead of connecting once,
|
|
403
403
|
// finding a cold socket, and closing the pane instantly — the exact
|
|
404
|
-
// mechanism bootRoot uses.
|
|
405
|
-
// viewer
|
|
406
|
-
//
|
|
404
|
+
// mechanism bootRoot uses. A child with a kickoff prompt marks its
|
|
405
|
+
// initial viewer for whip_mode; ordinary focus/attach paths stay
|
|
406
|
+
// silent. No pre-wait in this CLI subprocess.
|
|
407
407
|
const viewer = openViewerWindow(meta.node_id, parentViewer.session ?? '', {
|
|
408
408
|
name: fullName(meta),
|
|
409
409
|
cwd: opts.cwd,
|
|
410
410
|
besidePane: parentViewer.pane,
|
|
411
411
|
waitForBroker: true,
|
|
412
|
-
initialWhip:
|
|
412
|
+
initialWhip: hasKickoff,
|
|
413
413
|
});
|
|
414
414
|
if (viewer !== null && viewer.pane !== null && viewer.pane !== '') {
|
|
415
415
|
session = viewer.session;
|
|
@@ -2,8 +2,8 @@ export { STALL_REPROMPT } from '../../shared/generated-context.js';
|
|
|
2
2
|
export interface StopSignals {
|
|
3
3
|
/** Did the node call `push --final` (finish) this turn? */
|
|
4
4
|
pushedFinal: boolean;
|
|
5
|
-
/** Did the node call `crtr ask` (escalate to the
|
|
6
|
-
|
|
5
|
+
/** Did the node call `crtr ask` (escalate to the user) this turn? */
|
|
6
|
+
requestedHumanReply: boolean;
|
|
7
7
|
}
|
|
8
8
|
export type StopAction = {
|
|
9
9
|
action: 'allow';
|
|
@@ -37,7 +37,7 @@ function formatInvalidStructuredOutputReprompt(error) {
|
|
|
37
37
|
`1. Remove the invalid file (the output-schema.json in your node directory has been corrupted)\n` +
|
|
38
38
|
`2. Fix the corruption if you know the original request schema\n\n` +
|
|
39
39
|
`After resolving the file, retry the submission. ` +
|
|
40
|
-
`If this is unexpected, escalate to the
|
|
40
|
+
`If this is unexpected, escalate to the user using \`crtr human send\`.`);
|
|
41
41
|
}
|
|
42
42
|
/** Decide what to do when a node stops. crtrd supplies every current-canvas
|
|
43
43
|
* fact; the broker contributes only whether its Pi-owned background job registry
|
|
@@ -45,7 +45,7 @@ function formatInvalidStructuredOutputReprompt(error) {
|
|
|
45
45
|
export function evaluateStop(nodeId, signals, backgroundJobsRunning = activeBackgroundBashJobs(contextDir(nodeId)).length > 0) {
|
|
46
46
|
if (signals.pushedFinal)
|
|
47
47
|
return { action: 'allow', reason: 'finished' };
|
|
48
|
-
if (signals.
|
|
48
|
+
if (signals.requestedHumanReply)
|
|
49
49
|
return { action: 'allow', reason: 'escalated' };
|
|
50
50
|
// A pending structured-output request overrides every stored-state dormancy
|
|
51
51
|
// path: a post-final one-off follow-up still owes `submit` before it may stop.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { jobDir } from '../canvas/paths.js';
|
|
4
|
-
const SIGNALS = ['pushedFinal', '
|
|
4
|
+
const SIGNALS = ['pushedFinal', 'requestedHumanReply'];
|
|
5
5
|
function signalPath(nodeId, signal) {
|
|
6
6
|
return join(jobDir(nodeId), `.${signal}`);
|
|
7
7
|
}
|
|
@@ -24,7 +24,7 @@ export function markStopSignal(nodeId, signal) {
|
|
|
24
24
|
/** Consume command outcomes from this broker's just-settled turn. Markers from
|
|
25
25
|
* an earlier crashed broker are discarded rather than bleeding into its successor. */
|
|
26
26
|
export function consumeStopSignals(nodeId) {
|
|
27
|
-
const signals = { pushedFinal: false,
|
|
27
|
+
const signals = { pushedFinal: false, requestedHumanReply: false };
|
|
28
28
|
for (const signal of SIGNALS) {
|
|
29
29
|
const path = signalPath(nodeId, signal);
|
|
30
30
|
if (!existsSync(path))
|
|
@@ -522,7 +522,7 @@ function restoreWrappedBinding(wrapper) {
|
|
|
522
522
|
// not the sealed generation that installed it. The neighboring `crtr surface node cycle` builders
|
|
523
523
|
// share that property.
|
|
524
524
|
export function inboxToggleTmuxCommand() {
|
|
525
|
-
return ['run-shell', '-b', 'crtr
|
|
525
|
+
return ['run-shell', '-b', 'crtr surface inbox --quiet --tmux-socket "#{socket_path}" --tmux-client "#{client_name}" --target-pane "#{pane_id}"'];
|
|
526
526
|
}
|
|
527
527
|
function actionCommand(id) {
|
|
528
528
|
switch (id) {
|
|
@@ -24,9 +24,10 @@ export interface SessionState {
|
|
|
24
24
|
/** Live context occupancy in prompt tokens: seeded from the snapshot's
|
|
25
25
|
* contextUsage, then tracked off each assistant `message_end`. */
|
|
26
26
|
contextTokens: number | undefined;
|
|
27
|
-
/** Queued steering + follow-up messages
|
|
28
|
-
*
|
|
29
|
-
*
|
|
27
|
+
/** Queued steering + follow-up messages: seeded from `welcome.snapshot.queued`
|
|
28
|
+
* and tracked off `queue_update`. Every welcome REPLACES this — the attaching
|
|
29
|
+
* broker's own queue is the whole truth, so a dead broker's rows never survive
|
|
30
|
+
* and a client attaching mid-queue still sees what is waiting. */
|
|
30
31
|
queued: Array<{
|
|
31
32
|
text: string;
|
|
32
33
|
}>;
|
|
@@ -48,7 +48,7 @@ export function applySnapshot(frame) {
|
|
|
48
48
|
agentDir: frame.agentDir,
|
|
49
49
|
engine: snapshot.state,
|
|
50
50
|
contextTokens: contextUsage?.tokens ?? undefined,
|
|
51
|
-
queued:
|
|
51
|
+
queued: snapshotQueued(snapshot),
|
|
52
52
|
display: {
|
|
53
53
|
statuses: { ...display.statuses },
|
|
54
54
|
widgets: Object.fromEntries(Object.entries(display.widgets).map(([k, w]) => [k, { lines: [...w.lines], placement: w.placement }])),
|
|
@@ -140,6 +140,19 @@ export function reduce(state, frame) {
|
|
|
140
140
|
return state;
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
|
+
/** The queue a `welcome` reports, composed exactly as `queue_update` composes
|
|
144
|
+
* it. Absent on a snapshot from a broker generation older than the field, and
|
|
145
|
+
* on an offline node (no engine, so no queue) — both mean nothing is waiting. */
|
|
146
|
+
function snapshotQueued(snapshot) {
|
|
147
|
+
const queued = snapshot.queued;
|
|
148
|
+
if (typeof queued !== 'object' || queued === null)
|
|
149
|
+
return [];
|
|
150
|
+
const { steering, followUp } = queued;
|
|
151
|
+
return [...texts(steering), ...texts(followUp)].map((text) => ({ text }));
|
|
152
|
+
}
|
|
153
|
+
function texts(value) {
|
|
154
|
+
return Array.isArray(value) ? value.filter((entry) => typeof entry === 'string') : [];
|
|
155
|
+
}
|
|
143
156
|
/** Apply a partial patch to pi's state, preserving reference identity when the
|
|
144
157
|
* patch changes nothing (and when no welcome has seeded `engine` yet). */
|
|
145
158
|
function patchEngine(state, patch) {
|
|
@@ -147,10 +147,40 @@ export declare const CONFIG_SETTINGS_COVERAGE: {
|
|
|
147
147
|
setFromString: (config: ScopeConfig, raw: string) => string | null;
|
|
148
148
|
};
|
|
149
149
|
};
|
|
150
|
+
page_surface: {
|
|
151
|
+
surface: "settings";
|
|
152
|
+
setting: {
|
|
153
|
+
key: "page_surface";
|
|
154
|
+
label: string;
|
|
155
|
+
description: string;
|
|
156
|
+
valueConstraint: string;
|
|
157
|
+
applies: string;
|
|
158
|
+
group: "display";
|
|
159
|
+
order: number;
|
|
160
|
+
format: (config: ScopeConfig) => "on" | "off";
|
|
161
|
+
cycle: (config: ScopeConfig) => void;
|
|
162
|
+
setFromString: (config: ScopeConfig, raw: string) => string | null;
|
|
163
|
+
};
|
|
164
|
+
};
|
|
150
165
|
whip_messages: {
|
|
151
166
|
surface: "specialized";
|
|
152
167
|
owner: string;
|
|
153
168
|
};
|
|
169
|
+
whip_message_mode: {
|
|
170
|
+
surface: "settings";
|
|
171
|
+
setting: {
|
|
172
|
+
key: "whip_message_mode";
|
|
173
|
+
label: string;
|
|
174
|
+
description: string;
|
|
175
|
+
valueConstraint: string;
|
|
176
|
+
applies: string;
|
|
177
|
+
group: "display";
|
|
178
|
+
order: number;
|
|
179
|
+
format: (config: ScopeConfig) => "random" | "go faster";
|
|
180
|
+
cycle: (config: ScopeConfig, delta: number) => void;
|
|
181
|
+
setFromString: (config: ScopeConfig, raw: string) => string | null;
|
|
182
|
+
};
|
|
183
|
+
};
|
|
154
184
|
mouse_mode_default: {
|
|
155
185
|
surface: "settings";
|
|
156
186
|
setting: {
|
|
@@ -196,10 +226,10 @@ export declare const CONFIG_SETTINGS_COVERAGE: {
|
|
|
196
226
|
setFromString: (config: ScopeConfig, raw: string) => string | null;
|
|
197
227
|
};
|
|
198
228
|
};
|
|
199
|
-
|
|
229
|
+
bash_tool_purpose: {
|
|
200
230
|
surface: "settings";
|
|
201
231
|
setting: {
|
|
202
|
-
key: "
|
|
232
|
+
key: "bash_tool_purpose";
|
|
203
233
|
label: string;
|
|
204
234
|
description: string;
|
|
205
235
|
valueConstraint: string;
|
|
@@ -292,6 +322,10 @@ export declare const CONFIG_SETTINGS_COVERAGE: {
|
|
|
292
322
|
surface: "specialized";
|
|
293
323
|
owner: string;
|
|
294
324
|
};
|
|
325
|
+
bin: {
|
|
326
|
+
surface: "specialized";
|
|
327
|
+
owner: string;
|
|
328
|
+
};
|
|
295
329
|
};
|
|
296
330
|
/** The exhaustive top-level key list used by config persistence and help. */
|
|
297
331
|
export declare const SCOPE_CONFIG_KEYS: (keyof ScopeConfig)[];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CONDENSED_HISTORY_MODES, MOUSE_MODE_DEFAULTS } from '../types.js';
|
|
1
|
+
import { CONDENSED_HISTORY_MODES, MOUSE_MODE_DEFAULTS, WHIP_MESSAGE_MODES } from '../types.js';
|
|
2
2
|
function cycleChoice(choices, current, delta) {
|
|
3
3
|
const index = choices.indexOf(current);
|
|
4
4
|
const start = index >= 0 ? index : 0;
|
|
@@ -158,7 +158,7 @@ export const CONFIG_SETTINGS_COVERAGE = {
|
|
|
158
158
|
valueConstraint: 'true|false',
|
|
159
159
|
applies: 'Applies on the next turn end.',
|
|
160
160
|
group: 'display',
|
|
161
|
-
order:
|
|
161
|
+
order: 41,
|
|
162
162
|
format: (config) => config.completion_bell ? 'on' : 'off',
|
|
163
163
|
cycle: (config) => { config.completion_bell = !config.completion_bell; },
|
|
164
164
|
setFromString: (config, raw) => {
|
|
@@ -176,7 +176,7 @@ export const CONFIG_SETTINGS_COVERAGE = {
|
|
|
176
176
|
setting: {
|
|
177
177
|
key: 'whip_mode',
|
|
178
178
|
label: 'Whip mode',
|
|
179
|
-
description: 'Play the whip animation when you send a prompt and when an
|
|
179
|
+
description: 'Play the whip animation when you send a prompt and when a viewer opens for an agent with an initial prompt.',
|
|
180
180
|
valueConstraint: 'true|false',
|
|
181
181
|
applies: 'Applies on the next attach.',
|
|
182
182
|
group: 'display',
|
|
@@ -192,7 +192,48 @@ export const CONFIG_SETTINGS_COVERAGE = {
|
|
|
192
192
|
},
|
|
193
193
|
},
|
|
194
194
|
},
|
|
195
|
+
page_surface: {
|
|
196
|
+
surface: 'settings',
|
|
197
|
+
setting: {
|
|
198
|
+
key: 'page_surface',
|
|
199
|
+
label: 'Page human surface',
|
|
200
|
+
description: 'Prompt agents to use JSX pages by default for structured or interactive content shown to you.',
|
|
201
|
+
valueConstraint: 'true|false',
|
|
202
|
+
applies: 'Applies when human command help is assembled.',
|
|
203
|
+
group: 'display',
|
|
204
|
+
order: 37,
|
|
205
|
+
format: (config) => config.page_surface ? 'on' : 'off',
|
|
206
|
+
cycle: (config) => { config.page_surface = !config.page_surface; },
|
|
207
|
+
setFromString: (config, raw) => {
|
|
208
|
+
const value = booleanFromString(raw, 'page_surface');
|
|
209
|
+
if (typeof value === 'string')
|
|
210
|
+
return value;
|
|
211
|
+
config.page_surface = value;
|
|
212
|
+
return null;
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
},
|
|
195
216
|
whip_messages: { surface: 'specialized', owner: 'sys config set whip_messages' },
|
|
217
|
+
whip_message_mode: {
|
|
218
|
+
surface: 'settings',
|
|
219
|
+
setting: {
|
|
220
|
+
key: 'whip_message_mode',
|
|
221
|
+
label: 'Whip message',
|
|
222
|
+
description: 'What the whip action sends: a random line from whip_messages, or the fixed “Go faster”.',
|
|
223
|
+
valueConstraint: WHIP_MESSAGE_MODES.join('|'),
|
|
224
|
+
applies: 'Applies on the next attach.',
|
|
225
|
+
group: 'display',
|
|
226
|
+
order: 40,
|
|
227
|
+
format: (config) => config.whip_message_mode === 'go-faster' ? 'go faster' : 'random',
|
|
228
|
+
cycle: (config, delta) => { config.whip_message_mode = cycleChoice(WHIP_MESSAGE_MODES, config.whip_message_mode, delta); },
|
|
229
|
+
setFromString: (config, raw) => {
|
|
230
|
+
if (!WHIP_MESSAGE_MODES.includes(raw))
|
|
231
|
+
return `whip_message_mode must be one of: ${WHIP_MESSAGE_MODES.join('|')}`;
|
|
232
|
+
config.whip_message_mode = raw;
|
|
233
|
+
return null;
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
},
|
|
196
237
|
mouse_mode_default: {
|
|
197
238
|
surface: 'settings',
|
|
198
239
|
setting: {
|
|
@@ -254,23 +295,23 @@ export const CONFIG_SETTINGS_COVERAGE = {
|
|
|
254
295
|
},
|
|
255
296
|
},
|
|
256
297
|
},
|
|
257
|
-
|
|
298
|
+
bash_tool_purpose: {
|
|
258
299
|
surface: 'settings',
|
|
259
300
|
setting: {
|
|
260
|
-
key: '
|
|
261
|
-
label: '
|
|
262
|
-
description: '
|
|
301
|
+
key: 'bash_tool_purpose',
|
|
302
|
+
label: 'Bash purpose field',
|
|
303
|
+
description: 'Expose the optional purpose label to agents in the bash tool schema. Off removes the field without disabling the bash valve.',
|
|
263
304
|
valueConstraint: 'true|false',
|
|
264
|
-
applies: 'Applies on the next
|
|
305
|
+
applies: 'Applies on the next node session.',
|
|
265
306
|
group: 'display',
|
|
266
|
-
order:
|
|
267
|
-
format: (config) => config.
|
|
268
|
-
cycle: (config) => { config.
|
|
307
|
+
order: 25,
|
|
308
|
+
format: (config) => config.bash_tool_purpose ? 'on' : 'off',
|
|
309
|
+
cycle: (config) => { config.bash_tool_purpose = !config.bash_tool_purpose; },
|
|
269
310
|
setFromString: (config, raw) => {
|
|
270
|
-
const value = booleanFromString(raw, '
|
|
311
|
+
const value = booleanFromString(raw, 'bash_tool_purpose');
|
|
271
312
|
if (typeof value === 'string')
|
|
272
313
|
return value;
|
|
273
|
-
config.
|
|
314
|
+
config.bash_tool_purpose = value;
|
|
274
315
|
return null;
|
|
275
316
|
},
|
|
276
317
|
},
|
|
@@ -344,9 +385,10 @@ export const CONFIG_SETTINGS_COVERAGE = {
|
|
|
344
385
|
modelRoutes: { surface: 'specialized', owner: 'Models route declarations' },
|
|
345
386
|
modelRouting: { surface: 'specialized', owner: 'Models route declarations' },
|
|
346
387
|
kinds: { surface: 'specialized', owner: 'Models tab and kind registry' },
|
|
347
|
-
page_components: { surface: 'specialized', owner: 'Page component catalog: product-registered page
|
|
388
|
+
page_components: { surface: 'specialized', owner: 'Page component catalog: product-registered page component kinds' },
|
|
348
389
|
remoteCanvas: { surface: 'specialized', owner: 'canvas config commands' },
|
|
349
390
|
spawnEnv: { surface: 'specialized', owner: 'spawn environment allow-list' },
|
|
391
|
+
bin: { surface: 'specialized', owner: 'bare-binary contributions on every node PATH' },
|
|
350
392
|
};
|
|
351
393
|
/** The exhaustive top-level key list used by config persistence and help. */
|
|
352
394
|
export const SCOPE_CONFIG_KEYS = Object.keys(CONFIG_SETTINGS_COVERAGE);
|
package/dist/core/worktree.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { type GitResult, type GitSyncOptions } from './git.js';
|
|
2
1
|
import { type NodeMeta, type ManagedWorktree } from './canvas/index.js';
|
|
3
2
|
export interface WorktreeCommandResult {
|
|
4
3
|
ok: boolean;
|
|
@@ -23,32 +22,24 @@ export interface CloseManagedWorktreeResult {
|
|
|
23
22
|
branch: string;
|
|
24
23
|
worktree_path: string;
|
|
25
24
|
landed_sha: string;
|
|
26
|
-
/**
|
|
27
|
-
*
|
|
28
|
-
* closed, push-final is unblocked); `worktree_remove_error` carries the
|
|
29
|
-
* manual cleanup note. */
|
|
25
|
+
/** Always false for a live caller: cleanup is deliberately pending until
|
|
26
|
+
* the caller exits and the reported manual command can safely remove it. */
|
|
30
27
|
worktree_removed: boolean;
|
|
31
28
|
worktree_remove_error?: string;
|
|
32
|
-
/**
|
|
33
|
-
* afterward — same non-fatal treatment as worktree_removed. */
|
|
29
|
+
/** Always false while the pending-cleanup checkout has this branch checked out. */
|
|
34
30
|
branch_deleted: boolean;
|
|
35
31
|
branch_delete_error?: string;
|
|
36
32
|
}
|
|
37
33
|
export declare function closeManagedWorktree(nodeId: string): CloseManagedWorktreeResult;
|
|
38
|
-
type WorktreeCleanupRunner = (args: string[], cwd: string, options: GitSyncOptions) => GitResult;
|
|
39
|
-
/** Test seam for the bounded post-land cleanup regression. */
|
|
40
|
-
export declare function setWorktreeCleanupRunnerForTest(runner?: WorktreeCleanupRunner): void;
|
|
41
34
|
/** Recovery guidance for a vanished checkout whose refs do not prove that its
|
|
42
35
|
* work is delivered. This deliberately never recommends `worktree close`:
|
|
43
36
|
* that command cannot operate on the absent checkout. */
|
|
44
37
|
export declare function missingWorktreeRecoveryHint(wt: ManagedWorktree): string;
|
|
45
38
|
interface CleanEmptyProof {
|
|
46
|
-
/** The branch's HEAD SHA at the moment this was proven clean
|
|
47
|
-
*
|
|
39
|
+
/** The branch's HEAD SHA at the moment this was proven clean and contained
|
|
40
|
+
* in the current base. */
|
|
48
41
|
branchSha: string;
|
|
49
|
-
/** The base
|
|
50
|
-
* re-checked immediately before the destructive delete, since the proof
|
|
51
|
-
* and the delete are two different points in time. */
|
|
42
|
+
/** The current base tip, retained for race diagnostics. */
|
|
52
43
|
baseSha: string;
|
|
53
44
|
}
|
|
54
45
|
/** Fix B's shared "nothing to land" test — the SAME clean-worktree definition
|
|
@@ -58,20 +49,11 @@ interface CleanEmptyProof {
|
|
|
58
49
|
* be a git-ancestor of (or equal to) the CURRENT tip of its recorded base
|
|
59
50
|
* branch — i.e. landing it would be a pure no-op. Any ambiguity (missing
|
|
60
51
|
* path, mid-rebase, wrong branch, an unresolvable base, or a real ancestry
|
|
61
|
-
* divergence) returns null: this function only ever proves
|
|
52
|
+
* divergence) returns null: this function only ever proves a no-op land
|
|
62
53
|
* when a live git check establishes it, never on a heuristic guess, so real
|
|
63
|
-
* unlanded work always falls through to the
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
* re-proves containment against the LIVE base immediately before the
|
|
67
|
-
* destructive delete, refuses outright if the checkout cannot be removed,
|
|
68
|
-
* and conditions the delete itself on BOTH `branchSha` and that same live
|
|
69
|
-
* base SHA via `bestEffortDeleteBranchWithBaseProof`'s atomic multi-ref
|
|
70
|
-
* transaction — those checks, not this one, are what close the TOCTOU gap.
|
|
71
|
-
* Exported (alongside
|
|
72
|
-
* `autoDropCleanManagedWorktreeLocked`) purely so regression tests can
|
|
73
|
-
* inject a race in the window between proving and cleanup; production code
|
|
74
|
-
* must always go through `autoDropCleanManagedWorktree`. */
|
|
54
|
+
* unlanded work always falls through to the explicit-close guard. The locked
|
|
55
|
+
* path re-checks this predicate before recording deferred cleanup; production
|
|
56
|
+
* code must always go through `autoDropCleanManagedWorktree`. */
|
|
75
57
|
export declare function proveCleanEmptyManagedWorktree(wt: ManagedWorktree): CleanEmptyProof | null;
|
|
76
58
|
export interface AutoDroppedWorktree {
|
|
77
59
|
node_id: string;
|
|
@@ -82,22 +64,10 @@ export interface AutoDroppedWorktree {
|
|
|
82
64
|
branch_deleted: boolean;
|
|
83
65
|
branch_delete_error?: string;
|
|
84
66
|
}
|
|
85
|
-
/**
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
* refuses: the caller (`autoDropCleanManagedWorktree`, and `push final`
|
|
90
|
-
* above it) then falls through to the existing `open_managed_worktree`
|
|
91
|
-
* guard exactly as if this worktree had never looked droppable. In every
|
|
92
|
-
* refusal case the branch, and every commit reachable from it, is
|
|
93
|
-
* unconditionally preserved — that is the actual safety property this
|
|
94
|
-
* function guarantees. A checkout-removal refusal in particular must be
|
|
95
|
-
* treated as a full refusal, not a partial success: if the checkout cannot
|
|
96
|
-
* be removed (e.g. a file reappeared after the clean predicate ran), the
|
|
97
|
-
* branch is still checked out somewhere, so this function must never reach
|
|
98
|
-
* the ref-deletion transaction or mutate managed-worktree state — both the
|
|
99
|
-
* branch and the live checkout stay fully recoverable and the caller's
|
|
100
|
-
* `open_managed_worktree` guard fires. */
|
|
67
|
+
/** Re-check a clean auto-drop before closing its record. `push final` runs
|
|
68
|
+
* inside the owner broker, so it has the same destructive-cwd boundary as
|
|
69
|
+
* explicit close: removal and branch deletion are deferred until that owner
|
|
70
|
+
* has exited. */
|
|
101
71
|
export declare function autoDropCleanManagedWorktreeLocked(nodeId: string, wt: ManagedWorktree, proof: CleanEmptyProof): AutoDroppedWorktree | null;
|
|
102
72
|
/** `push final`'s escape hatch: a managed worktree that has
|
|
103
73
|
* nothing to land is auto-dropped instead of blocking on an explicit
|
|
@@ -106,7 +76,7 @@ export declare function autoDropCleanManagedWorktreeLocked(nodeId: string, wt: M
|
|
|
106
76
|
* that never had anything to close in the first place (a read-only
|
|
107
77
|
* review node). Returns null and changes nothing when the worktree is not
|
|
108
78
|
* PROVABLY empty-and-clean by `proveCleanEmptyManagedWorktree`, OR when a
|
|
109
|
-
* concurrent mutation invalidates that proof before the
|
|
79
|
+
* concurrent mutation invalidates that proof before the record is closed
|
|
110
80
|
* (see `autoDropCleanManagedWorktreeLocked`); the caller's existing
|
|
111
81
|
* `open_managed_worktree` guard then still applies unchanged — real
|
|
112
82
|
* commits, real uncommitted changes, and a lost race all require the
|