@north-light/crouter 0.3.172 → 0.3.174
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/bin/runtime-selector.mjs +8 -1
- package/dist/api/__tests__/{client.test.js → serial/client.test.js} +2 -135
- package/dist/api/client.d.ts +12 -21
- package/dist/api/client.js +22 -31
- package/dist/api/dto/broker-ops.d.ts +158 -0
- package/dist/api/dto/broker-ops.js +6 -0
- package/dist/api/dto/crons.d.ts +6 -0
- package/dist/api/dto/human.d.ts +7 -1
- package/dist/api/dto/inbox.d.ts +1 -71
- package/dist/api/dto/inbox.js +1 -9
- package/dist/api/dto/nodes.d.ts +6 -7
- package/dist/api/dto/reviews.d.ts +1 -11
- package/dist/api/routes.d.ts +7 -4
- package/dist/api/routes.js +8 -5
- package/dist/build-root.js +3 -3
- package/dist/builtin-memory/04-base-worker.md +1 -4
- package/dist/builtin-memory/05-kinds/advisor/00-base.md +1 -5
- package/dist/builtin-memory/05-kinds/advisor/01-orchestrator.md +2 -7
- package/dist/builtin-memory/05-kinds/design/00-base.md +1 -6
- package/dist/builtin-memory/05-kinds/developer/00-base.md +1 -6
- package/dist/builtin-memory/05-kinds/explore/00-base.md +1 -4
- package/dist/builtin-memory/05-kinds/explore/01-orchestrator.md +1 -2
- package/dist/builtin-memory/05-kinds/general/00-base.md +1 -3
- package/dist/builtin-memory/05-kinds/plan/00-base.md +1 -6
- package/dist/builtin-memory/05-kinds/plan/reviewers/00-base.md +1 -2
- package/dist/builtin-memory/05-kinds/plan/reviewers/architecture-fit.md +1 -3
- package/dist/builtin-memory/05-kinds/plan/reviewers/code-smells.md +1 -3
- package/dist/builtin-memory/05-kinds/plan/reviewers/pattern-consistency.md +1 -3
- package/dist/builtin-memory/05-kinds/plan/reviewers/requirements-coverage.md +1 -3
- package/dist/builtin-memory/05-kinds/plan/reviewers/security.md +1 -4
- package/dist/builtin-memory/05-kinds/review/companion/00-base.md +2 -3
- package/dist/builtin-memory/05-kinds/spec/00-base.md +1 -2
- package/dist/builtin-memory/advisor/council.md +1 -6
- package/dist/builtin-memory/design.md +2 -7
- package/dist/builtin-memory/development.md +9 -14
- package/dist/builtin-memory/internal/marketplaces.md +2 -6
- package/dist/builtin-memory/internal/nodes-and-canvas.md +1 -1
- package/dist/builtin-memory/internal/plugins.md +2 -8
- package/dist/builtin-memory/internal/storage-tiers.md +1 -2
- package/dist/builtin-memory/testing.md +41 -0
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/{provider-rotation.test.ts → serial/provider-rotation.test.ts} +106 -177
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/claude-plugin-commands.ts +5 -15
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/frontmatter-rules/index.ts +1 -28
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/memory-slash-commands.ts +43 -88
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +55 -0
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +60 -0
- package/dist/cli.js +2 -2
- package/dist/clients/attach/__tests__/attach-remote-readonly.test.js +37 -131
- package/dist/clients/attach/__tests__/chat-view-snapshot-ordering.test.js +71 -152
- package/dist/clients/attach/__tests__/context-message.test.js +16 -174
- package/dist/clients/attach/__tests__/crtr-output.test.js +36 -2069
- package/dist/clients/attach/__tests__/diagram.test.js +2 -2
- package/dist/clients/attach/__tests__/edit-diff.test.js +0 -4
- package/dist/clients/attach/__tests__/file-review-focus.test.js +2 -1
- package/dist/clients/attach/__tests__/group-activity.test.js +40 -229
- package/dist/clients/attach/__tests__/oauth-dialog-lifecycle.test.js +26 -76
- package/dist/clients/attach/__tests__/prompt-preview.test.js +4 -70
- package/dist/clients/attach/__tests__/ref-autocomplete.test.js +11 -125
- package/dist/clients/attach/__tests__/titled-editor-preview.test.js +14 -205
- package/dist/clients/attach/command.d.ts +2 -1
- package/dist/clients/attach/command.js +81 -76
- package/dist/clients/attach/input/capabilities.d.ts +27 -0
- package/dist/clients/attach/input/capabilities.js +96 -0
- package/dist/clients/attach/input/controller.d.ts +20 -182
- package/dist/clients/attach/input/controller.js +128 -537
- package/dist/clients/attach/input/overlay-owner.d.ts +41 -0
- package/dist/clients/attach/input/overlay-owner.js +199 -0
- package/dist/clients/attach/overlays/file-review.d.ts +0 -4
- package/dist/clients/attach/overlays/file-review.js +13 -5
- package/dist/clients/attach/overlays/graph.js +2 -10
- package/dist/clients/attach/render/chat-view.d.ts +4 -3
- package/dist/clients/attach/render/chat-view.js +39 -33
- package/dist/clients/attach/render/group-activity.d.ts +1 -0
- package/dist/clients/attach/render/group-activity.js +20 -13
- package/dist/clients/attach/render/group-recap.js +12 -3
- package/dist/clients/attach/session/connection.js +9 -15
- package/dist/clients/attach/session/editor-inventory.d.ts +6 -5
- package/dist/clients/attach/session/editor-inventory.js +7 -8
- package/dist/clients/attach/session/file-links.d.ts +13 -0
- package/dist/clients/attach/session/file-links.js +107 -0
- package/dist/clients/attach/session/frame.d.ts +3 -0
- package/dist/clients/attach/session/frame.js +10 -1
- package/dist/clients/attach/session/frames.js +2 -3
- package/dist/clients/attach/session/input-wiring.d.ts +4 -1
- package/dist/clients/attach/session/input-wiring.js +15 -14
- package/dist/clients/attach/session/mouse.d.ts +6 -1
- package/dist/clients/attach/session/mouse.js +8 -5
- package/dist/clients/attach/session/profile-files.js +18 -12
- package/dist/clients/attach/session/reconnect.js +1 -1
- package/dist/clients/attach/session/state-sync.js +1 -2
- package/dist/clients/attach/session/surface-host.d.ts +3 -2
- package/dist/clients/attach/session/surface-host.js +4 -4
- package/dist/clients/attach/slash/dispatch.d.ts +8 -31
- package/dist/clients/attach/slash/dispatch.js +34 -81
- package/dist/clients/attach/viewer.js +820 -860
- package/dist/clients/conversation/projection.d.ts +79 -0
- package/dist/clients/conversation/projection.js +341 -0
- package/dist/clients/inbox/__tests__/serial/inbox-controller.test.js +159 -0
- package/dist/clients/inbox/__tests__/serial/mount-panel.test.js +151 -0
- package/dist/clients/inbox/controller.d.ts +0 -4
- package/dist/clients/inbox/controller.js +0 -2
- package/dist/clients/inbox/review/__tests__/review-core.test.js +4 -293
- package/dist/clients/inbox/review/__tests__/teardown-notice.test.js +100 -0
- package/dist/clients/inbox/review/comments-client.d.ts +3 -2
- package/dist/clients/inbox/review/comments-client.js +12 -12
- package/dist/clients/inbox/review/companion-pane.d.ts +30 -0
- package/dist/clients/inbox/review/companion-pane.js +86 -0
- package/dist/clients/inbox/review/document-surface.d.ts +182 -0
- package/dist/clients/inbox/review/{document-region.js → document-surface.js} +252 -48
- package/dist/clients/inbox/review/frame.js +5 -4
- package/dist/clients/inbox/review/launch.d.ts +8 -8
- package/dist/clients/inbox/review/launch.js +52 -92
- package/dist/clients/inbox/review/nvim.d.ts +2 -0
- package/dist/clients/inbox/review/nvim.js +14 -12
- package/dist/clients/inbox/review/review-client.d.ts +12 -8
- package/dist/clients/inbox/review/review-client.js +46 -35
- package/dist/clients/inbox/review-adapter.d.ts +3 -10
- package/dist/clients/inbox/review-adapter.js +27 -19
- package/dist/clients/inbox/surface.d.ts +0 -4
- package/dist/clients/inbox/surface.js +0 -2
- package/dist/clients/surfaces/host.d.ts +11 -3
- package/dist/commands/__tests__/api-client-cold-start-diagnostic.test.js +7 -34
- package/dist/commands/__tests__/human.test.js +11 -322
- package/dist/commands/api-client.d.ts +5 -5
- package/dist/commands/api-client.js +6 -85
- package/dist/commands/canvas-browse.js +3 -29
- package/dist/commands/canvas-config.js +1 -1
- package/dist/commands/canvas-use.js +3 -3
- package/dist/commands/canvas.js +1 -1
- package/dist/commands/cron.js +5 -1
- package/dist/commands/human/queue.d.ts +0 -4
- package/dist/commands/human/queue.js +7 -40
- package/dist/commands/memory/list.d.ts +14 -0
- package/dist/commands/memory/list.js +35 -31
- package/dist/commands/memory/read.d.ts +7 -0
- package/dist/commands/memory/read.js +14 -8
- package/dist/commands/node/bash.d.ts +1 -0
- package/dist/commands/node/bash.js +198 -0
- package/dist/commands/node/create.d.ts +23 -0
- package/dist/commands/node/create.js +207 -0
- package/dist/commands/node/inspect.d.ts +2 -0
- package/dist/commands/node/inspect.js +302 -0
- package/dist/commands/node/lifecycle.d.ts +4 -0
- package/dist/commands/node/lifecycle.js +415 -0
- package/dist/commands/node/message.d.ts +1 -0
- package/dist/commands/node/message.js +164 -0
- package/dist/commands/node/pyramid.d.ts +2 -0
- package/dist/commands/node/pyramid.js +79 -0
- package/dist/commands/node/subscription.d.ts +1 -0
- package/dist/commands/node/subscription.js +82 -0
- package/dist/commands/node/wait.d.ts +1 -0
- package/dist/commands/node/wait.js +159 -0
- package/dist/commands/node-lifecycle-revive.js +10 -57
- package/dist/commands/node.d.ts +0 -42
- package/dist/commands/node.js +11 -2065
- package/dist/commands/search.js +1 -1
- package/dist/commands/surface/node/cycle.d.ts +1 -0
- package/dist/commands/surface/node/cycle.js +83 -0
- package/dist/commands/surface/node/focus.d.ts +1 -0
- package/dist/commands/surface/node/focus.js +67 -0
- package/dist/commands/surface/node/id.d.ts +1 -0
- package/dist/commands/surface/node/id.js +38 -0
- package/dist/commands/surface/node/pin.d.ts +1 -0
- package/dist/commands/surface/node/pin.js +42 -0
- package/dist/commands/surface/node/placement.d.ts +46 -0
- package/dist/commands/surface/node/placement.js +124 -0
- package/dist/commands/surface-node.js +4 -1
- package/dist/commands/surface-reload.js +1 -2
- package/dist/commands/surface-tmux-spread.js +1 -1
- package/dist/commands/surface.js +5 -20
- package/dist/commands/sys/__tests__/setup-core.test.js +18 -271
- package/dist/commands/sys/config.js +6 -6
- package/dist/commands/sys/logs.js +1 -1
- package/dist/commands/sys/panels/broker-limits-panel.d.ts +17 -0
- package/dist/commands/sys/panels/broker-limits-panel.js +104 -0
- package/dist/commands/sys/panels/dependencies-panel.d.ts +14 -0
- package/dist/commands/sys/panels/dependencies-panel.js +80 -0
- package/dist/commands/sys/panels/keybindings-panel.d.ts +56 -0
- package/dist/commands/sys/panels/keybindings-panel.js +703 -0
- package/dist/commands/sys/panels/keys-panel.d.ts +16 -0
- package/dist/commands/sys/panels/keys-panel.js +60 -0
- package/dist/commands/sys/panels/models-panel.d.ts +77 -0
- package/dist/commands/sys/panels/models-panel.js +647 -0
- package/dist/commands/sys/panels/panel.d.ts +45 -0
- package/dist/commands/sys/panels/panel.js +137 -0
- package/dist/commands/sys/panels/plugins-panel.d.ts +16 -0
- package/dist/commands/sys/panels/plugins-panel.js +80 -0
- package/dist/commands/sys/panels/prefs-panel.d.ts +21 -0
- package/dist/commands/sys/panels/prefs-panel.js +85 -0
- package/dist/commands/sys/panels/provider-panel.d.ts +62 -0
- package/dist/commands/sys/panels/provider-panel.js +538 -0
- package/dist/commands/sys/settings-shell.d.ts +55 -0
- package/dist/commands/sys/settings-shell.js +400 -0
- package/dist/commands/sys/settings.d.ts +2 -0
- package/dist/commands/sys/settings.js +31 -0
- package/dist/commands/sys/setup-core.d.ts +3 -33
- package/dist/commands/sys/setup-core.js +27 -78
- package/dist/commands/sys/setup-settings-runner.d.ts +24 -0
- package/dist/commands/sys/setup-settings-runner.js +63 -0
- package/dist/commands/sys/setup-wizard.d.ts +26 -125
- package/dist/commands/sys/setup-wizard.js +209 -2473
- package/dist/commands/sys/setup.js +5 -7
- package/dist/commands/sys.js +3 -2
- package/dist/core/__tests__/broker-extension-canvas-db-boundary.test.js +50 -0
- package/dist/core/__tests__/broker-launch-candidates.test.js +20 -9
- package/dist/core/__tests__/broker-preflight.test.js +1 -1
- package/dist/core/__tests__/canvas-inbox-watcher-hold.test.js +108 -27
- package/dist/core/__tests__/canvas-inbox-watcher.test.js +14 -0
- package/dist/core/__tests__/canvas.test.js +2 -36
- package/dist/core/__tests__/close.test.js +14 -3
- package/dist/core/__tests__/context-intro.test.js +32 -143
- package/dist/core/__tests__/cron-broker-capacity.test.js +22 -3
- package/dist/core/__tests__/daemon-boot.test.js +2 -20
- package/dist/core/__tests__/daemon-wedge.test.js +1 -1
- package/dist/core/__tests__/dead-node-policy-table.test.js +1 -18
- package/dist/core/__tests__/fixtures/fake-engine.d.ts +1 -1
- package/dist/core/__tests__/fixtures/fake-engine.js +2 -2
- package/dist/core/__tests__/fixtures/fake-pi-host.js +2 -2
- package/dist/core/__tests__/focuses.test.js +4 -98
- package/dist/core/__tests__/helpers/broker-clients.d.ts +0 -3
- package/dist/core/__tests__/helpers/broker-clients.js +0 -14
- package/dist/core/__tests__/helpers/harness.d.ts +0 -8
- package/dist/core/__tests__/helpers/harness.js +7 -87
- package/dist/core/__tests__/helpers/viewer-panes.js +1 -1
- package/dist/core/__tests__/inline-memory-refs.test.js +5 -134
- package/dist/core/__tests__/kickoff.test.js +1 -1
- package/dist/core/__tests__/memory-resolver-precedence.test.js +29 -1
- package/dist/core/__tests__/migration.test.js +35 -48
- package/dist/core/__tests__/on-read-dedup-resume.test.js +22 -12
- package/dist/core/__tests__/passive-subscription.test.js +26 -49
- package/dist/core/__tests__/preview-registry-sync.test.js +1 -2
- package/dist/core/__tests__/prune.test.js +94 -1
- package/dist/core/__tests__/review-model-floor.test.js +0 -32
- package/dist/core/__tests__/seam/broker-attach-multiclient.test.js +255 -0
- package/dist/core/__tests__/{full → seam}/broker-attach-stream.test.js +39 -7
- package/dist/core/__tests__/{full → seam}/broker-crash-teardown.test.js +30 -29
- package/dist/core/__tests__/{full → seam}/broker-pane-resolution.test.js +54 -5
- package/dist/core/__tests__/{full → seam}/broker-provider-retry.test.js +134 -82
- package/dist/core/__tests__/{full → seam}/broker-whip-interrupt.test.js +15 -4
- package/dist/core/__tests__/{full/idle-release-settlement.test.js → seam/dormancy-release.test.js} +69 -17
- package/dist/core/__tests__/{full/yield-message-transaction.test.js → seam/yield-refresh-transaction.test.js} +31 -9
- package/dist/core/__tests__/secrets.test.js +1 -7
- package/dist/core/__tests__/{broker-fork-seam.test.js → serial/broker-fork-seam.test.js} +58 -7
- package/dist/core/__tests__/{broker-sdk-wiring.test.js → serial/broker-sdk-wiring.test.js} +18 -162
- package/dist/core/__tests__/{broker-snapshot-history.test.js → serial/broker-snapshot-history.test.js} +9 -9
- package/dist/core/__tests__/{command-plugins.test.js → serial/command-plugins.test.js} +105 -15
- package/dist/core/__tests__/{deferred-no-wake.test.js → serial/deferred-no-wake.test.js} +23 -20
- package/dist/core/__tests__/{flagship-lifecycle.test.js → serial/flagship-lifecycle.test.js} +7 -7
- package/dist/core/__tests__/{host-teardown-process-group.test.js → serial/host-teardown-process-group.test.js} +6 -6
- package/dist/core/__tests__/{human-deliver-e2e.test.js → serial/human-deliver-e2e.test.js} +12 -12
- package/dist/core/__tests__/{live-mutation.test.js → serial/live-mutation.test.js} +5 -5
- package/dist/core/__tests__/{refresh-stall-recycle.test.js → serial/refresh-stall-recycle.test.js} +5 -14
- package/dist/core/__tests__/{revive.test.js → serial/revive.test.js} +15 -100
- package/dist/core/__tests__/{spawn-root.test.js → serial/spawn-root.test.js} +32 -15
- package/dist/core/__tests__/serial/subscription-delivery.test.js +126 -0
- package/dist/core/__tests__/serial/tmux-surface.test.js +256 -0
- package/dist/core/__tests__/{worktree.test.js → serial/worktree.test.js} +15 -15
- package/dist/core/__tests__/session-model.test.js +0 -18
- package/dist/core/__tests__/spawn-worktree-id-conflict.test.js +9 -0
- package/dist/core/__tests__/watchdog-abort-arms-retry.test.js +50 -0
- package/dist/core/broker-client/__tests__/transport-relay.test.js +15 -16
- package/dist/core/broker-client/__tests__/transport-socket.test.js +28 -0
- package/dist/core/broker-client/client.d.ts +2 -2
- package/dist/core/broker-client/client.js +4 -7
- package/dist/core/broker-client/transport-relay.d.ts +13 -19
- package/dist/core/broker-client/transport-relay.js +19 -34
- package/dist/core/broker-client/transport-socket.d.ts +2 -2
- package/dist/core/broker-client/transport-socket.js +9 -2
- package/dist/core/broker-client/transport.d.ts +7 -3
- package/dist/core/broker-client/transport.js +4 -4
- package/dist/core/canvas/__tests__/attention.test.js +1 -18
- package/dist/core/canvas/__tests__/remote-canvas-source.test.js +7 -64
- package/dist/core/canvas/__tests__/remote-transport.test.js +2 -3
- package/dist/core/canvas/__tests__/render-remote.test.js +7 -52
- package/dist/core/canvas/browse/app.d.ts +2 -17
- package/dist/core/canvas/browse/app.js +16 -88
- package/dist/core/canvas/browse/model.d.ts +0 -4
- package/dist/core/canvas/browse/model.js +1 -12
- package/dist/core/canvas/browse/render.js +6 -3
- package/dist/core/canvas/crons.d.ts +8 -5
- package/dist/core/canvas/crons.js +7 -6
- package/dist/core/canvas/extensions.d.ts +7 -3
- package/dist/core/canvas/extensions.js +16 -4
- package/dist/core/canvas/nav-model.d.ts +0 -4
- package/dist/core/canvas/nav-model.js +2 -14
- package/dist/core/canvas/node-order.d.ts +3 -0
- package/dist/core/canvas/node-order.js +12 -0
- package/dist/core/canvas/remote-canvas-source.d.ts +3 -6
- package/dist/core/canvas/remote-canvas-source.js +8 -15
- package/dist/core/command.js +11 -4
- package/dist/core/config.js +3 -1
- package/dist/core/events/envelope.js +1 -1
- package/dist/core/events/read.js +7 -21
- package/dist/core/events/source.d.ts +0 -2
- package/dist/core/events/source.js +0 -16
- package/dist/core/events/types.d.ts +1 -1
- package/dist/core/fault-classifier.d.ts +1 -1
- package/dist/core/feed/passive.d.ts +0 -11
- package/dist/core/feed/passive.js +1 -62
- package/dist/core/human/__tests__/{inbox-core.test.js → serial/inbox-core.test.js} +6 -6
- package/dist/core/keybindings/__tests__/resolve.test.js +1 -96
- package/dist/core/keybindings/background-bash.js +3 -4
- package/dist/core/keybindings/catalog.js +1 -1
- package/dist/core/memory/inline-ref-grammar.js +3 -3
- package/dist/core/memory-resolver.d.ts +11 -25
- package/dist/core/memory-resolver.js +51 -33
- package/dist/core/model-routes.d.ts +15 -0
- package/dist/core/model-routes.js +12 -0
- package/dist/core/pool-credential-store.js +1 -1
- package/dist/core/preview-registry.js +8 -9
- package/dist/core/profiles/__tests__/root-profile.test.js +4 -14
- package/dist/core/review/realize.d.ts +0 -13
- package/dist/core/review/realize.js +0 -40
- package/dist/core/review/types.d.ts +1 -1
- package/dist/core/runtime/__tests__/engine-route.test.js +2 -2
- package/dist/core/runtime/bearings.js +1 -11
- package/dist/core/runtime/broker/client-registry.d.ts +33 -0
- package/dist/core/runtime/broker/client-registry.js +164 -0
- package/dist/core/runtime/broker/daemon-ops.d.ts +19 -0
- package/dist/core/runtime/broker/daemon-ops.js +49 -0
- package/dist/core/runtime/broker/event-projection.d.ts +42 -0
- package/dist/core/runtime/broker/event-projection.js +178 -0
- package/dist/core/runtime/broker/fault-retry.d.ts +39 -0
- package/dist/core/runtime/broker/fault-retry.js +277 -0
- package/dist/core/runtime/broker/frame-dispatch.d.ts +238 -0
- package/dist/core/runtime/broker/frame-dispatch.js +1537 -0
- package/dist/core/runtime/broker/inbox.d.ts +22 -0
- package/dist/core/runtime/broker/inbox.js +167 -0
- package/dist/core/runtime/broker/passive.d.ts +16 -0
- package/dist/core/runtime/broker/passive.js +44 -0
- package/dist/core/runtime/broker/read-ops.d.ts +23 -0
- package/dist/core/runtime/broker/read-ops.js +150 -0
- package/dist/core/runtime/broker/rebind.d.ts +74 -0
- package/dist/core/runtime/broker/rebind.js +211 -0
- package/dist/core/runtime/broker/tool-groups.d.ts +39 -0
- package/dist/core/runtime/broker/tool-groups.js +244 -0
- package/dist/core/runtime/broker-extension-render.d.ts +11 -0
- package/dist/core/runtime/broker-extension-render.js +181 -0
- package/dist/core/runtime/broker-persona-guidance.d.ts +13 -0
- package/dist/core/runtime/broker-persona-guidance.js +58 -0
- package/dist/core/runtime/broker-protocol.d.ts +1 -1
- package/dist/core/runtime/broker-protocol.js +1 -1
- package/dist/core/runtime/broker.d.ts +5 -196
- package/dist/core/runtime/broker.js +276 -3059
- package/dist/core/runtime/canvas-extensions.js +11 -2
- package/dist/core/runtime/fault.js +1 -1
- package/dist/core/runtime/model-selection.d.ts +9 -0
- package/dist/core/runtime/model-selection.js +12 -0
- package/dist/core/runtime/model-swap.d.ts +3 -3
- package/dist/core/runtime/model-swap.js +33 -25
- package/dist/core/runtime/placement-tmux.d.ts +3 -14
- package/dist/core/runtime/placement-tmux.js +11 -80
- package/dist/core/runtime/placement.d.ts +4 -2
- package/dist/core/runtime/placement.js +7 -12
- package/dist/core/runtime/promote.d.ts +14 -1
- package/dist/core/runtime/promote.js +1 -1
- package/dist/core/runtime/reset.d.ts +1 -1
- package/dist/core/runtime/roadmap.js +1 -1
- package/dist/core/runtime/spawn.d.ts +8 -0
- package/dist/core/runtime/spawn.js +36 -6
- package/dist/core/runtime/stop-guard.d.ts +4 -3
- package/dist/core/runtime/stop-guard.js +36 -18
- package/dist/core/runtime/stop-signals.d.ts +4 -1
- package/dist/core/runtime/stream-watchdog.js +4 -5
- package/dist/core/runtime/structured-output.d.ts +15 -2
- package/dist/core/runtime/structured-output.js +35 -12
- package/dist/core/runtime/tmux-bindings.d.ts +25 -0
- package/dist/core/runtime/tmux-bindings.js +682 -0
- package/dist/core/runtime/tmux-chrome.d.ts +2 -1
- package/dist/core/runtime/tmux-chrome.js +3 -2
- package/dist/core/runtime/{tmux.d.ts → tmux-driver.d.ts} +18 -26
- package/dist/core/runtime/tmux-driver.js +598 -0
- package/dist/core/runtime/view-socket.d.ts +14 -0
- package/dist/core/runtime/view-socket.js +83 -0
- package/dist/core/session-model/session-state.d.ts +1 -2
- package/dist/core/session-model/session-state.js +5 -8
- package/dist/core/spawn.d.ts +1 -1
- package/dist/core/spawn.js +2 -2
- package/dist/core/substrate/gate.d.ts +1 -1
- package/dist/core/substrate/on-read-pure.d.ts +7 -0
- package/dist/core/substrate/on-read-pure.js +272 -0
- package/dist/core/termrender/termrender.js +32 -2
- package/dist/core/user-settings.d.ts +23 -1
- package/dist/core/user-settings.js +18 -1
- package/dist/daemon/api/__tests__/node-model-validation.test.js +134 -0
- package/dist/daemon/api/__tests__/review-terminal-conflict.test.js +98 -0
- package/dist/daemon/api/__tests__/{full → seam}/api-server.test.js +6 -48
- package/dist/daemon/api/__tests__/{full → seam}/b10-attach-modelauth.test.js +17 -44
- package/dist/daemon/api/__tests__/{full/push-parity.test.js → seam/leaf-api-parity.test.js} +61 -42
- package/dist/daemon/api/bridge.js +40 -81
- package/dist/daemon/api/handlers/broker-ops.d.ts +2 -0
- package/dist/daemon/api/handlers/broker-ops.js +383 -0
- package/dist/daemon/api/handlers/crons.js +9 -4
- package/dist/daemon/api/handlers/files.js +6 -7
- package/dist/daemon/api/handlers/inbox.js +2 -340
- package/dist/daemon/api/handlers/nodes.d.ts +10 -1
- package/dist/daemon/api/handlers/nodes.js +74 -39
- package/dist/daemon/api/handlers/review-comments.js +5 -1
- package/dist/daemon/api/handlers/reviews.js +0 -19
- package/dist/daemon/api/map.js +25 -4
- package/dist/daemon/api/router.js +2 -3
- package/dist/daemon/api/server.js +5 -7
- package/dist/daemon/cron-run.d.ts +4 -0
- package/dist/daemon/cron-run.js +30 -13
- package/dist/daemon/crtrd.d.ts +3 -58
- package/dist/daemon/crtrd.js +28 -1244
- package/dist/daemon/manage.js +0 -1
- package/dist/daemon/reconcilers/broker-supervision.d.ts +50 -0
- package/dist/daemon/reconcilers/broker-supervision.js +549 -0
- package/dist/daemon/reconcilers/cron-lane.d.ts +10 -0
- package/dist/daemon/reconcilers/cron-lane.js +32 -0
- package/dist/daemon/reconcilers/dormant-inbox.d.ts +18 -0
- package/dist/daemon/reconcilers/dormant-inbox.js +143 -0
- package/dist/daemon/reconcilers/storage-maintenance.d.ts +22 -0
- package/dist/daemon/reconcilers/storage-maintenance.js +213 -0
- package/dist/daemon/review/finish.js +2 -5
- package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +34 -53
- package/dist/pi-extensions/__tests__/canvas-recap.test.js +16 -113
- package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +72 -99
- package/dist/pi-extensions/__tests__/canvas-stophook-context-nudge.test.js +29 -12
- package/dist/pi-extensions/broker-local.d.ts +20 -0
- package/dist/pi-extensions/broker-local.js +89 -0
- package/dist/pi-extensions/canvas-context-intro.d.ts +3 -3
- package/dist/pi-extensions/canvas-context-intro.js +22 -11
- package/dist/pi-extensions/canvas-doc-substrate.js +17 -34
- package/dist/pi-extensions/canvas-goal-capture.js +7 -12
- package/dist/pi-extensions/canvas-inbox-watcher.js +124 -139
- package/dist/pi-extensions/canvas-passive-context.d.ts +3 -3
- package/dist/pi-extensions/canvas-passive-context.js +22 -18
- package/dist/pi-extensions/canvas-recap.d.ts +2 -2
- package/dist/pi-extensions/canvas-recap.js +48 -21
- package/dist/pi-extensions/canvas-review-boundary.js +10 -4
- package/dist/pi-extensions/canvas-stophook.d.ts +0 -5
- package/dist/pi-extensions/canvas-stophook.js +149 -431
- package/dist/pi-extensions/canvas-structured-output.js +52 -30
- package/dist/pi-extensions/envelope-merge.d.ts +13 -0
- package/dist/pi-extensions/envelope-merge.js +29 -0
- package/dist/shared/working-activity.d.ts +3 -2
- package/dist/shared/working-activity.js +3 -2
- package/dist/types.d.ts +6 -5
- package/dist/types.js +2 -2
- package/docs/compat/hearth-crtr-v1.md +4 -12
- package/docs/compat/hearth-crtr-v2.md +3 -11
- package/docs/compat/hearth-crtr-v3.md +4 -12
- package/docs/compat/hearth-crtr-v4.md +3 -11
- package/docs/compat/hearth-crtr-v5.md +3 -11
- package/docs/public-api.md +3 -7
- package/package.json +7 -49
- package/runtime.lock.json +2766 -14533
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/claude-plugin-commands.test.ts +0 -49
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/memory-slash-commands.test.ts +0 -194
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/statusline.test.ts +0 -68
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/frontmatter-rules/test.ts +0 -119
- package/dist/clients/attach/__tests__/attach-chrome-remote.test.js +0 -439
- package/dist/clients/attach/__tests__/attach-keybindings.test.js +0 -170
- package/dist/clients/attach/__tests__/crtr-output-coverage.test.js +0 -57
- package/dist/clients/attach/__tests__/editor-frame-title.test.js +0 -19
- package/dist/clients/attach/__tests__/input-controller-extension-command.test.js +0 -32
- package/dist/clients/attach/__tests__/markdown-headings.test.js +0 -35
- package/dist/clients/attach/__tests__/session-identity-refresh.test.js +0 -32
- package/dist/clients/conversation/conversation.d.ts +0 -65
- package/dist/clients/conversation/conversation.js +0 -318
- package/dist/clients/conversation/frames.d.ts +0 -30
- package/dist/clients/conversation/frames.js +0 -52
- package/dist/clients/conversation/region.d.ts +0 -51
- package/dist/clients/conversation/region.js +0 -265
- package/dist/clients/inbox/__tests__/inbox-controller.test.js +0 -247
- package/dist/clients/inbox/__tests__/mount-panel.test.js +0 -776
- package/dist/clients/inbox/review/__tests__/remap.test.js +0 -196
- package/dist/clients/inbox/review/columns.d.ts +0 -22
- package/dist/clients/inbox/review/columns.js +0 -40
- package/dist/clients/inbox/review/composition.d.ts +0 -60
- package/dist/clients/inbox/review/composition.js +0 -278
- package/dist/clients/inbox/review/document-region.d.ts +0 -120
- package/dist/clients/surfaces/region.d.ts +0 -16
- package/dist/clients/web/__tests__/push-engine.test.js +0 -158
- package/dist/clients/web/__tests__/push-registry.test.d.ts +0 -1
- package/dist/clients/web/__tests__/push-registry.test.js +0 -177
- package/dist/clients/web/dev-server.d.ts +0 -7
- package/dist/clients/web/dev-server.js +0 -46
- package/dist/clients/web/events.d.ts +0 -19
- package/dist/clients/web/events.js +0 -163
- package/dist/clients/web/push-engine.d.ts +0 -44
- package/dist/clients/web/push-engine.js +0 -125
- package/dist/clients/web/push-registry.d.ts +0 -85
- package/dist/clients/web/push-registry.js +0 -373
- package/dist/clients/web/server.d.ts +0 -19
- package/dist/clients/web/server.js +0 -661
- package/dist/clients/web/web-client/shared/protocol.d.ts +0 -214
- package/dist/clients/web/web-client/shared/protocol.js +0 -8
- package/dist/clients/web/web-cmd.d.ts +0 -2
- package/dist/clients/web/web-cmd.js +0 -141
- package/dist/commands/__tests__/api-canvas-source.test.d.ts +0 -1
- package/dist/commands/__tests__/api-canvas-source.test.js +0 -37
- package/dist/commands/__tests__/canvas-config.test.d.ts +0 -1
- package/dist/commands/__tests__/canvas-config.test.js +0 -107
- package/dist/commands/__tests__/node-no-kickoff-flag.test.d.ts +0 -1
- package/dist/commands/__tests__/node-no-kickoff-flag.test.js +0 -73
- package/dist/commands/__tests__/node-worktree-flag.test.d.ts +0 -1
- package/dist/commands/__tests__/node-worktree-flag.test.js +0 -49
- package/dist/commands/__tests__/search-contents.test.d.ts +0 -1
- package/dist/commands/__tests__/search-contents.test.js +0 -52
- package/dist/commands/memory/__tests__/lint.test.d.ts +0 -1
- package/dist/commands/memory/__tests__/lint.test.js +0 -15
- package/dist/commands/sys/__tests__/config-broker-thresholds.test.d.ts +0 -1
- package/dist/commands/sys/__tests__/config-broker-thresholds.test.js +0 -95
- package/dist/commands/sys/__tests__/config-keybindings.test.d.ts +0 -1
- package/dist/commands/sys/__tests__/config-keybindings.test.js +0 -55
- package/dist/commands/sys/__tests__/helpers/setup-runtime.d.ts +0 -5
- package/dist/commands/sys/__tests__/helpers/setup-runtime.js +0 -19
- package/dist/commands/sys/__tests__/setup-front-door.test.d.ts +0 -1
- package/dist/commands/sys/__tests__/setup-front-door.test.js +0 -102
- package/dist/commands/sys/__tests__/setup-models.test.d.ts +0 -1
- package/dist/commands/sys/__tests__/setup-models.test.js +0 -205
- package/dist/commands/sys/__tests__/setup-providers-viewport.test.d.ts +0 -1
- package/dist/commands/sys/__tests__/setup-providers-viewport.test.js +0 -155
- package/dist/commands/sys/__tests__/sync-deps.test.d.ts +0 -1
- package/dist/commands/sys/__tests__/sync-deps.test.js +0 -179
- package/dist/commands/sys/__tests__/sync-import.test.d.ts +0 -1
- package/dist/commands/sys/__tests__/sync-import.test.js +0 -315
- package/dist/core/__tests__/base-worker-prompt.test.d.ts +0 -1
- package/dist/core/__tests__/base-worker-prompt.test.js +0 -57
- package/dist/core/__tests__/command-plugins-surfaces.test.d.ts +0 -1
- package/dist/core/__tests__/command-plugins-surfaces.test.js +0 -359
- package/dist/core/__tests__/connection-reconnect-resume.test.d.ts +0 -1
- package/dist/core/__tests__/connection-reconnect-resume.test.js +0 -36
- package/dist/core/__tests__/finalization-migration.test.d.ts +0 -1
- package/dist/core/__tests__/finalization-migration.test.js +0 -38
- package/dist/core/__tests__/fixtures/extra-extension.d.ts +0 -1
- package/dist/core/__tests__/fixtures/extra-extension.js +0 -3
- package/dist/core/__tests__/fixtures/spawn-proof-target.test.d.ts +0 -1
- package/dist/core/__tests__/fixtures/spawn-proof-target.test.js +0 -15
- package/dist/core/__tests__/fork.test.d.ts +0 -1
- package/dist/core/__tests__/fork.test.js +0 -108
- package/dist/core/__tests__/full/broker-attach-limits.test.d.ts +0 -1
- package/dist/core/__tests__/full/broker-attach-limits.test.js +0 -147
- package/dist/core/__tests__/full/broker-deliver-ack.test.d.ts +0 -1
- package/dist/core/__tests__/full/broker-deliver-ack.test.js +0 -73
- package/dist/core/__tests__/full/broker-dialogs.test.d.ts +0 -1
- package/dist/core/__tests__/full/broker-dialogs.test.js +0 -180
- package/dist/core/__tests__/full/broker-display-snapshot.test.d.ts +0 -1
- package/dist/core/__tests__/full/broker-display-snapshot.test.js +0 -75
- package/dist/core/__tests__/full/broker-dormant-wake.test.d.ts +0 -1
- package/dist/core/__tests__/full/broker-dormant-wake.test.js +0 -130
- package/dist/core/__tests__/full/broker-model-changed-broadcast.test.d.ts +0 -1
- package/dist/core/__tests__/full/broker-model-changed-broadcast.test.js +0 -57
- package/dist/core/__tests__/full/broker-navigate-tree-rewelcome.test.d.ts +0 -1
- package/dist/core/__tests__/full/broker-navigate-tree-rewelcome.test.js +0 -80
- package/dist/core/__tests__/full/cascade-close.test.d.ts +0 -1
- package/dist/core/__tests__/full/cascade-close.test.js +0 -240
- package/dist/core/__tests__/full/detach-focus.test.d.ts +0 -1
- package/dist/core/__tests__/full/detach-focus.test.js +0 -126
- package/dist/core/__tests__/full/idle-release-settlement.test.d.ts +0 -1
- package/dist/core/__tests__/full/issue-146-yield-spawn-focus.test.d.ts +0 -1
- package/dist/core/__tests__/full/issue-146-yield-spawn-focus.test.js +0 -107
- package/dist/core/__tests__/full/park-clock-release.test.d.ts +0 -1
- package/dist/core/__tests__/full/park-clock-release.test.js +0 -56
- package/dist/core/__tests__/full/yield-message-transaction.test.d.ts +0 -1
- package/dist/core/__tests__/memory-index-render.test.d.ts +0 -1
- package/dist/core/__tests__/memory-index-render.test.js +0 -60
- package/dist/core/__tests__/model-routes.test.d.ts +0 -1
- package/dist/core/__tests__/model-routes.test.js +0 -41
- package/dist/core/__tests__/on-read-identity.test.d.ts +0 -1
- package/dist/core/__tests__/on-read-identity.test.js +0 -61
- package/dist/core/__tests__/phase4-review-migration.test.d.ts +0 -1
- package/dist/core/__tests__/phase4-review-migration.test.js +0 -100
- package/dist/core/__tests__/prune-to-limit.test.d.ts +0 -1
- package/dist/core/__tests__/prune-to-limit.test.js +0 -126
- package/dist/core/__tests__/reset.test.d.ts +0 -1
- package/dist/core/__tests__/reset.test.js +0 -69
- package/dist/core/__tests__/spawn-no-kickoff.test.d.ts +0 -1
- package/dist/core/__tests__/spawn-no-kickoff.test.js +0 -115
- package/dist/core/__tests__/steer-note.test.d.ts +0 -1
- package/dist/core/__tests__/steer-note.test.js +0 -41
- package/dist/core/__tests__/subcommand-tier.test.d.ts +0 -1
- package/dist/core/__tests__/subcommand-tier.test.js +0 -99
- package/dist/core/__tests__/subscription-delivery.test.js +0 -211
- package/dist/core/__tests__/test-runner-cheap-sharding.test.d.ts +0 -1
- package/dist/core/__tests__/test-runner-cheap-sharding.test.js +0 -97
- package/dist/core/__tests__/tmux-surface.test.js +0 -484
- package/dist/core/__tests__/wake-bearings.test.d.ts +0 -1
- package/dist/core/__tests__/wake-bearings.test.js +0 -102
- package/dist/core/canvas/__tests__/remote-event-stream.test.d.ts +0 -1
- package/dist/core/canvas/__tests__/remote-event-stream.test.js +0 -146
- package/dist/core/canvas/__tests__/source-resolve.test.d.ts +0 -1
- package/dist/core/canvas/__tests__/source-resolve.test.js +0 -77
- package/dist/core/canvas/browse/__tests__/model.test.d.ts +0 -1
- package/dist/core/canvas/browse/__tests__/model.test.js +0 -290
- package/dist/core/canvas/browse/__tests__/rebuild-coalescer.test.d.ts +0 -1
- package/dist/core/canvas/browse/__tests__/rebuild-coalescer.test.js +0 -134
- package/dist/core/canvas/browse/__tests__/render.test.d.ts +0 -1
- package/dist/core/canvas/browse/__tests__/render.test.js +0 -111
- package/dist/core/canvas/browse/rebuild-coalescer.d.ts +0 -7
- package/dist/core/canvas/browse/rebuild-coalescer.js +0 -61
- package/dist/core/canvas/remote-event-stream.d.ts +0 -24
- package/dist/core/canvas/remote-event-stream.js +0 -94
- package/dist/core/feed/__tests__/coalesce-human.test.d.ts +0 -1
- package/dist/core/feed/__tests__/coalesce-human.test.js +0 -36
- package/dist/core/feed/__tests__/empty-node-guard.test.d.ts +0 -1
- package/dist/core/feed/__tests__/empty-node-guard.test.js +0 -45
- package/dist/core/host-exports/__tests__/export-prunes-boot-skill.test.d.ts +0 -1
- package/dist/core/host-exports/__tests__/export-prunes-boot-skill.test.js +0 -84
- package/dist/core/human/__tests__/visible-paths.test.d.ts +0 -1
- package/dist/core/human/__tests__/visible-paths.test.js +0 -28
- package/dist/core/keybindings/__tests__/inbox-affordance.test.d.ts +0 -1
- package/dist/core/keybindings/__tests__/inbox-affordance.test.js +0 -38
- package/dist/core/review/__tests__/project.test.d.ts +0 -1
- package/dist/core/review/__tests__/project.test.js +0 -71
- package/dist/core/runtime/__tests__/command-expansion.test.d.ts +0 -1
- package/dist/core/runtime/__tests__/command-expansion.test.js +0 -25
- package/dist/core/runtime/__tests__/session-visibility.test.d.ts +0 -1
- package/dist/core/runtime/__tests__/session-visibility.test.js +0 -119
- package/dist/core/runtime/__tests__/spawn-at-given-id.test.d.ts +0 -1
- package/dist/core/runtime/__tests__/spawn-at-given-id.test.js +0 -34
- package/dist/core/runtime/tmux.js +0 -1314
- package/dist/daemon/api/__tests__/full/push-parity.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/full/worktree-parity.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/full/worktree-parity.test.js +0 -160
- package/dist/daemon/api/__tests__/inbox.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/inbox.test.js +0 -489
- package/dist/web-client/apple-touch-icon.png +0 -0
- package/dist/web-client/assets/fragment-mono-latin-400-normal-BYwT3kSJ.woff +0 -0
- package/dist/web-client/assets/fragment-mono-latin-400-normal-yxdJ5AmL.woff2 +0 -0
- package/dist/web-client/assets/fragment-mono-latin-ext-400-normal-BbKYyvR9.woff2 +0 -0
- package/dist/web-client/assets/fragment-mono-latin-ext-400-normal-CT4YFKeK.woff +0 -0
- package/dist/web-client/assets/index-CCPaLeW7.css +0 -2
- package/dist/web-client/assets/index-kyOWsnZK.js +0 -86
- package/dist/web-client/assets/martian-mono-cyrillic-wght-normal-B84CD5C_.woff2 +0 -0
- package/dist/web-client/assets/martian-mono-latin-ext-wght-normal-DlL6xMw5.woff2 +0 -0
- package/dist/web-client/assets/martian-mono-latin-wght-normal-5W32yIyr.woff2 +0 -0
- package/dist/web-client/assets/workbox-window.prod.es5-Bd17z0YL.js +0 -2
- package/dist/web-client/icon-192.png +0 -0
- package/dist/web-client/icon-512.png +0 -0
- package/dist/web-client/icon-maskable-512.png +0 -0
- package/dist/web-client/index.html +0 -17
- package/dist/web-client/manifest.webmanifest +0 -1
- package/dist/web-client/sw.js +0 -1
- /package/dist/api/__tests__/{client.test.d.ts → serial/client.test.d.ts} +0 -0
- /package/dist/clients/inbox/__tests__/{inbox-controller.test.d.ts → serial/inbox-controller.test.d.ts} +0 -0
- /package/dist/clients/inbox/__tests__/{mount-panel.test.d.ts → serial/mount-panel.test.d.ts} +0 -0
- /package/dist/clients/{attach/__tests__/attach-chrome-remote.test.d.ts → inbox/review/__tests__/teardown-notice.test.d.ts} +0 -0
- /package/dist/{clients/attach/__tests__/attach-keybindings.test.d.ts → core/__tests__/broker-extension-canvas-db-boundary.test.d.ts} +0 -0
- /package/dist/{clients/attach/__tests__/crtr-output-coverage.test.d.ts → core/__tests__/seam/broker-attach-multiclient.test.d.ts} +0 -0
- /package/dist/core/__tests__/{full → seam}/broker-attach-stream.test.d.ts +0 -0
- /package/dist/core/__tests__/{full → seam}/broker-crash-teardown.test.d.ts +0 -0
- /package/dist/core/__tests__/{full → seam}/broker-pane-resolution.test.d.ts +0 -0
- /package/dist/core/__tests__/{full → seam}/broker-provider-retry.test.d.ts +0 -0
- /package/dist/core/__tests__/{full → seam}/broker-whip-interrupt.test.d.ts +0 -0
- /package/dist/{clients/attach/__tests__/editor-frame-title.test.d.ts → core/__tests__/seam/dormancy-release.test.d.ts} +0 -0
- /package/dist/{clients/attach/__tests__/input-controller-extension-command.test.d.ts → core/__tests__/seam/yield-refresh-transaction.test.d.ts} +0 -0
- /package/dist/core/__tests__/{broker-fork-seam.test.d.ts → serial/broker-fork-seam.test.d.ts} +0 -0
- /package/dist/core/__tests__/{broker-sdk-wiring.test.d.ts → serial/broker-sdk-wiring.test.d.ts} +0 -0
- /package/dist/core/__tests__/{broker-snapshot-history.test.d.ts → serial/broker-snapshot-history.test.d.ts} +0 -0
- /package/dist/core/__tests__/{command-plugins.test.d.ts → serial/command-plugins.test.d.ts} +0 -0
- /package/dist/core/__tests__/{deferred-no-wake.test.d.ts → serial/deferred-no-wake.test.d.ts} +0 -0
- /package/dist/core/__tests__/{flagship-lifecycle.test.d.ts → serial/flagship-lifecycle.test.d.ts} +0 -0
- /package/dist/core/__tests__/{host-teardown-process-group.test.d.ts → serial/host-teardown-process-group.test.d.ts} +0 -0
- /package/dist/core/__tests__/{human-deliver-e2e.test.d.ts → serial/human-deliver-e2e.test.d.ts} +0 -0
- /package/dist/core/__tests__/{live-mutation.test.d.ts → serial/live-mutation.test.d.ts} +0 -0
- /package/dist/core/__tests__/{refresh-stall-recycle.test.d.ts → serial/refresh-stall-recycle.test.d.ts} +0 -0
- /package/dist/core/__tests__/{revive.test.d.ts → serial/revive.test.d.ts} +0 -0
- /package/dist/core/__tests__/{spawn-root.test.d.ts → serial/spawn-root.test.d.ts} +0 -0
- /package/dist/core/__tests__/{subscription-delivery.test.d.ts → serial/subscription-delivery.test.d.ts} +0 -0
- /package/dist/core/__tests__/{tmux-surface.test.d.ts → serial/tmux-surface.test.d.ts} +0 -0
- /package/dist/core/__tests__/{worktree.test.d.ts → serial/worktree.test.d.ts} +0 -0
- /package/dist/{clients/attach/__tests__/markdown-headings.test.d.ts → core/__tests__/watchdog-abort-arms-retry.test.d.ts} +0 -0
- /package/dist/{clients/attach/__tests__/session-identity-refresh.test.d.ts → core/broker-client/__tests__/transport-socket.test.d.ts} +0 -0
- /package/dist/core/human/__tests__/{inbox-core.test.d.ts → serial/inbox-core.test.d.ts} +0 -0
- /package/dist/{clients/inbox/review/__tests__/remap.test.d.ts → daemon/api/__tests__/node-model-validation.test.d.ts} +0 -0
- /package/dist/{clients/surfaces/region.js → daemon/api/__tests__/review-terminal-conflict.test.d.ts} +0 -0
- /package/dist/daemon/api/__tests__/{full → seam}/api-server.test.d.ts +0 -0
- /package/dist/daemon/api/__tests__/{full → seam}/b10-attach-modelauth.test.d.ts +0 -0
- /package/dist/{clients/web/__tests__/push-engine.test.d.ts → daemon/api/__tests__/seam/leaf-api-parity.test.d.ts} +0 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// Run with: npm run test:serial
|
|
2
|
+
//
|
|
3
|
+
// THE DAEMON WAKE HALF of delivery-vs-wake, on a graph >=2 levels deep. Routing
|
|
4
|
+
// itself (active → inbox.jsonl, passive → passive.jsonl) is owned by
|
|
5
|
+
// passive-subscription.test.ts; what this file owns is the decision ONE real
|
|
6
|
+
// `superviseTick` makes on that routing: the ACTIVE subscriber of a finished
|
|
7
|
+
// target is revived, the PASSIVE subscriber on the same target is not.
|
|
8
|
+
//
|
|
9
|
+
// HEADLESS / FABRICATED DRIVE (foundation-spec §C.15 + §E). All nodes are
|
|
10
|
+
// broker-hosted (paneless), so the topology and dormant states are fabricated
|
|
11
|
+
// directly rather than booted — a released broker's dormancy is an EXITED
|
|
12
|
+
// process (status=idle, intent=idle-release, pi_pid dead). A daemon revive is
|
|
13
|
+
// observed via getNode().cycles, which reviveNode bumps together with
|
|
14
|
+
// transition('revive') BEFORE it spawns, so the model effect is instant.
|
|
15
|
+
//
|
|
16
|
+
// HOW IT FAILS IF THE SPLIT REGRESSES: after T's pushFinal, one h.tick() must
|
|
17
|
+
// revive the ACTIVE subscriber B (cycles bumps, status→active) while the PASSIVE
|
|
18
|
+
// subscriber P stays idle with cycles==0. If routing breaks, either B's entry
|
|
19
|
+
// never reaches its inbox (the 2nd-pass gate finds nothing → B not revived) or P
|
|
20
|
+
// gets an inbox entry and IS woken — both go red here.
|
|
21
|
+
//
|
|
22
|
+
// Graph (T is two hops under A):
|
|
23
|
+
// A (resident root — the user's virtual front door)
|
|
24
|
+
// └── B (terminal) A→B active seed ── ACTIVE subscriber of T
|
|
25
|
+
// ├── T (terminal) B→T active seed ── THE TARGET (level 2)
|
|
26
|
+
// ├── K (terminal) B→K active seed ── keepalive (stays active)
|
|
27
|
+
// └── P (terminal) B→P active seed ── PASSIVE subscriber of T
|
|
28
|
+
// P→T passive (wired via subscribe(P,T,false))
|
|
29
|
+
// P→K active (the tie that legitimizes P's own release)
|
|
30
|
+
import { test } from 'node:test';
|
|
31
|
+
import assert from 'node:assert/strict';
|
|
32
|
+
import { spawnSync } from 'node:child_process';
|
|
33
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
34
|
+
import { createHarness } from '../helpers/harness.js';
|
|
35
|
+
import { closeDb } from '../../canvas/db.js';
|
|
36
|
+
import { subscribe } from '../../canvas/canvas.js';
|
|
37
|
+
import { pushFinal } from '../../feed/feed.js';
|
|
38
|
+
import { passivePath } from '../../canvas/paths.js';
|
|
39
|
+
// A pid reaped (dead) by the time spawnSync returns — a released broker's exited
|
|
40
|
+
// process (the headless analog of a closed pane).
|
|
41
|
+
function deadPid() {
|
|
42
|
+
const r = spawnSync('true', [], { stdio: 'ignore' });
|
|
43
|
+
return r.pid ?? 0x7ffffffe;
|
|
44
|
+
}
|
|
45
|
+
// LOCAL helper: read a node's PASSIVE accumulator (passive.jsonl) straight off
|
|
46
|
+
// the data layer, mirroring the harness's own `inbox()` reader. The harness
|
|
47
|
+
// exposes inbox() but NOT passive() — this fills that gap.
|
|
48
|
+
function passive(nodeId) {
|
|
49
|
+
closeDb();
|
|
50
|
+
const path = passivePath(nodeId);
|
|
51
|
+
if (!existsSync(path))
|
|
52
|
+
return [];
|
|
53
|
+
return readFileSync(path, 'utf8').split('\n').filter(Boolean).map((line) => JSON.parse(line));
|
|
54
|
+
}
|
|
55
|
+
// `{node_id, active}` arrays → a stable comparable set of `id:active|passive`.
|
|
56
|
+
function edgeSet(arr) {
|
|
57
|
+
return new Set(arr.map((e) => `${e.node_id}:${e.active ? 'active' : 'passive'}`));
|
|
58
|
+
}
|
|
59
|
+
test('one daemon tick revives the active subscriber of a finished target and leaves the passive one dormant', { timeout: 30_000 }, async () => {
|
|
60
|
+
const h = await createHarness({ headless: true, sessionPrefix: 'crtr-subdeliv' });
|
|
61
|
+
try {
|
|
62
|
+
// ===================================================================
|
|
63
|
+
// Build the graph by FABRICATION (no boots). A is a resident root
|
|
64
|
+
// (inline, daemon-untouched); B/T/K/P are broker nodes whose liveness
|
|
65
|
+
// fields are set directly. Each parent→child spine edge is wired ACTIVE.
|
|
66
|
+
// ===================================================================
|
|
67
|
+
const A = h.spawnRoot('front door'); // resident root, active, no placement
|
|
68
|
+
// T (the target) and K (keepalive) are LIVE-active workers; B and P start
|
|
69
|
+
// already DORMANT (idle-released, broker exited = dead pid) — exactly the
|
|
70
|
+
// post-stop state the delivery split is judged against.
|
|
71
|
+
const T = h.fabricateBrokerNode({ status: 'active', pi_pid: deadPid(), pi_session_id: 'sess-T' });
|
|
72
|
+
const K = h.fabricateBrokerNode({ status: 'active', pi_pid: deadPid(), pi_session_id: 'sess-K' });
|
|
73
|
+
const B = h.fabricateBrokerNode({ status: 'idle', intent: 'idle-release', pi_pid: deadPid(), pi_session_id: 'sess-B' });
|
|
74
|
+
const P = h.fabricateBrokerNode({ status: 'idle', intent: 'idle-release', pi_pid: deadPid(), pi_session_id: 'sess-P' });
|
|
75
|
+
// Spine seeds: A→B, B→T, B→K, B→P all ACTIVE (subscriber, publisher).
|
|
76
|
+
subscribe(A, B, true);
|
|
77
|
+
subscribe(B, T, true);
|
|
78
|
+
subscribe(B, K, true);
|
|
79
|
+
subscribe(B, P, true);
|
|
80
|
+
// PASSIVE axis under test: P passively subscribes to T; P actively to K
|
|
81
|
+
// (the only tie that legitimizes P's own idle-release).
|
|
82
|
+
subscribe(P, T, false);
|
|
83
|
+
subscribe(P, K, true);
|
|
84
|
+
assert.deepEqual(edgeSet(h.subscribers(T)), new Set([`${B}:active`, `${P}:passive`]), 'T has B(active) + P(passive) as subscribers — the same-target split');
|
|
85
|
+
// Pre-push baseline: keepalive up, nothing delivered, nothing revived.
|
|
86
|
+
assert.equal(h.status(K), 'active', 'K active (keepalive holds P legitimately dormant)');
|
|
87
|
+
assert.equal(h.inbox(B).length, 0, 'B inbox empty before the push');
|
|
88
|
+
assert.equal(passive(P).length, 0, 'P passive accumulator empty before the push');
|
|
89
|
+
assert.equal(h.node(B).cycles ?? 0, 0, 'B not yet revived');
|
|
90
|
+
assert.equal(h.node(P).cycles ?? 0, 0, 'P not yet revived');
|
|
91
|
+
// ===================================================================
|
|
92
|
+
// T FINISHES via the model layer — the precondition the daemon decides on:
|
|
93
|
+
// B's pointer lands in inbox.jsonl (the wake channel), P's in passive.jsonl.
|
|
94
|
+
// ===================================================================
|
|
95
|
+
await pushFinal(T, 'TARGET-FINAL-BODY: the worker completed');
|
|
96
|
+
closeDb();
|
|
97
|
+
assert.ok(h.inbox(B).find((e) => e.from === T && e.kind === 'final'), 'ACTIVE subscriber B: T-final pointer delivered to inbox.jsonl');
|
|
98
|
+
assert.equal(h.inbox(P).length, 0, 'PASSIVE subscriber P: inbox.jsonl stays empty (no wake channel)');
|
|
99
|
+
assert.equal(passive(P).length, 1, 'PASSIVE subscriber P: exactly one passive entry');
|
|
100
|
+
// ===================================================================
|
|
101
|
+
// The DAEMON decision pass. Its 2nd pass revives an idle-released node
|
|
102
|
+
// ONLY on an unseen INBOX entry. B has one (active) → REVIVED. P has none
|
|
103
|
+
// (its entry went to passive.jsonl) → stays idle. Decided in ONE tick.
|
|
104
|
+
// ===================================================================
|
|
105
|
+
await h.tick();
|
|
106
|
+
// ACTIVE subscriber: WOKEN — reviveNode bumped cycles + transition(revive).
|
|
107
|
+
{
|
|
108
|
+
const b = h.node(B);
|
|
109
|
+
assert.equal(b.cycles ?? 0, 1, 'ACTIVE subscriber B: daemon pass-2 REVIVED (cycles bumped to 1)');
|
|
110
|
+
assert.equal(b.status, 'active', 'B revive → active');
|
|
111
|
+
assert.equal(b.intent ?? null, null, 'B intent cleared by revive');
|
|
112
|
+
}
|
|
113
|
+
// PASSIVE subscriber: NOT WOKEN — the same tick did NOT revive P.
|
|
114
|
+
{
|
|
115
|
+
const p = h.node(P);
|
|
116
|
+
assert.equal(p.cycles ?? 0, 0, 'PASSIVE subscriber P: NOT revived (cycles still 0)');
|
|
117
|
+
assert.equal(p.status, 'idle', 'P STILL idle — daemon did NOT wake it');
|
|
118
|
+
assert.equal(p.intent, 'idle-release', 'P still intent=idle-release (untouched)');
|
|
119
|
+
}
|
|
120
|
+
assert.equal(passive(P).length, 1, "P's passive entry is still pending (drained only on its next message)");
|
|
121
|
+
assert.equal(h.inbox(P).length, 0, "P's inbox still empty");
|
|
122
|
+
}
|
|
123
|
+
finally {
|
|
124
|
+
await h.dispose();
|
|
125
|
+
}
|
|
126
|
+
});
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
// Run with: npm run test:serial
|
|
2
|
+
//
|
|
3
|
+
// STEP 2 of the placement/focus migration: guards on the tmux Surface (driver).
|
|
4
|
+
//
|
|
5
|
+
// 1. The §2.2 HARD DRIVER INVARIANT (GREEN now): every create/placement verb
|
|
6
|
+
// in the driver — after the broker-host cut gutted the engine-in-pane
|
|
7
|
+
// relocate verbs (U9 deleted swap-pane/break-pane/join-pane/move-pane),
|
|
8
|
+
// the survivors are new-window / split-window / respawn-pane — MUST pass an
|
|
9
|
+
// explicit `-t` target.
|
|
10
|
+
// Omitting `-t` lets tmux resolve against its GLOBAL current session, which
|
|
11
|
+
// can leak a pane into a user session — the exact unbidden-window bug this
|
|
12
|
+
// redesign kills. This guards the bug's blast radius and should pass today.
|
|
13
|
+
//
|
|
14
|
+
// 2. The §5.1 driver-import lint guard (ENFORCED as of Step 8): every other
|
|
15
|
+
// module reaches the driver through placement's re-exports or the
|
|
16
|
+
// tmux-chrome seam, so the only direct importers are placement.ts,
|
|
17
|
+
// placement-tmux.ts, tmux-chrome.ts, and tmux-bindings.ts.
|
|
18
|
+
import { test } from 'node:test';
|
|
19
|
+
import assert from 'node:assert/strict';
|
|
20
|
+
import { readFileSync, readdirSync, statSync } from 'node:fs';
|
|
21
|
+
import { spawnSync } from 'node:child_process';
|
|
22
|
+
import { fileURLToPath } from 'node:url';
|
|
23
|
+
import { dirname, join, basename } from 'node:path';
|
|
24
|
+
import { ensureSession } from '../../runtime/placement.js';
|
|
25
|
+
import { installTmuxBindings } from '../../runtime/tmux-chrome.js';
|
|
26
|
+
import { resolveKeybindings } from '../../keybindings/index.js';
|
|
27
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
28
|
+
const SRC_ROOT = join(__dirname, '..', '..', '..'); // .../src
|
|
29
|
+
const TMUX_DRIVER_TS = join(SRC_ROOT, 'core', 'runtime', 'tmux-driver.ts');
|
|
30
|
+
/** The placement verbs the §2.2 invariant governs. (swap-pane/break-pane/
|
|
31
|
+
* join-pane/move-pane were deleted with the engine-in-pane host in the broker
|
|
32
|
+
* cut; kept in the match set so a regression that re-introduces an untargeted
|
|
33
|
+
* one is still caught.) */
|
|
34
|
+
const PLACEMENT_VERBS = [
|
|
35
|
+
'new-window',
|
|
36
|
+
'split-window',
|
|
37
|
+
'swap-pane',
|
|
38
|
+
'break-pane',
|
|
39
|
+
'join-pane',
|
|
40
|
+
'move-pane',
|
|
41
|
+
'respawn-pane',
|
|
42
|
+
];
|
|
43
|
+
/** The smallest `[ … ]` array literal that encloses `matchIdx`: scan back to the
|
|
44
|
+
* nearest `[` (the array open — the verb is always its first element), then
|
|
45
|
+
* forward with bracket-depth counting to the matching `]` (handles nested
|
|
46
|
+
* arrays like splitWindow's `? [] : ['-h']`). Returns the array source slice. */
|
|
47
|
+
function enclosingArray(src, matchIdx) {
|
|
48
|
+
let open = matchIdx;
|
|
49
|
+
while (open >= 0 && src[open] !== '[')
|
|
50
|
+
open--;
|
|
51
|
+
assert.ok(open >= 0, `no enclosing [ for the verb at index ${matchIdx}`);
|
|
52
|
+
let depth = 0;
|
|
53
|
+
for (let i = open; i < src.length; i++) {
|
|
54
|
+
if (src[i] === '[')
|
|
55
|
+
depth++;
|
|
56
|
+
else if (src[i] === ']') {
|
|
57
|
+
depth--;
|
|
58
|
+
if (depth === 0)
|
|
59
|
+
return src.slice(open, i + 1);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
throw new Error('unbalanced [ ] while bracket-matching the verb array');
|
|
63
|
+
}
|
|
64
|
+
test('§2.2 driver invariant: every placement verb in tmux-driver.ts passes an explicit -t target', () => {
|
|
65
|
+
const src = readFileSync(TMUX_DRIVER_TS, 'utf8');
|
|
66
|
+
// Match only the QUOTED JS string forms (`'new-window'`, …) — these are real
|
|
67
|
+
// args-array elements; the jsdoc prose mentions the verbs unquoted / in
|
|
68
|
+
// backticks, so this never trips on a comment.
|
|
69
|
+
const re = new RegExp(`'(${PLACEMENT_VERBS.join('|')})'`, 'g');
|
|
70
|
+
let found = 0;
|
|
71
|
+
for (let m = re.exec(src); m !== null; m = re.exec(src)) {
|
|
72
|
+
found++;
|
|
73
|
+
const verb = m[1];
|
|
74
|
+
const arr = enclosingArray(src, m.index);
|
|
75
|
+
// The invariant is "name a specific tmux object, never fall back to the
|
|
76
|
+
// GLOBAL current one". `-t` targets a destination; `break-pane` (and the
|
|
77
|
+
// deleted swap/join/move-pane) instead name their SOURCE with `-s` — which
|
|
78
|
+
// satisfies the invariant identically. Accept either explicit target flag.
|
|
79
|
+
assert.ok(arr.includes(`'-t'`) || arr.includes(`'-s'`), `tmux verb '${verb}' is invoked WITHOUT an explicit -t/-s target — a latent ` +
|
|
80
|
+
`instance of the unbidden-window bug (§2.2). Offending args array:\n${arr}`);
|
|
81
|
+
}
|
|
82
|
+
// Sanity: the driver really does contain placement verbs (so a refactor that
|
|
83
|
+
// renames them can't make this assertion vacuously pass). The broker cut left
|
|
84
|
+
// three (new-window / split-window / respawn-pane).
|
|
85
|
+
assert.ok(found >= 3, `expected to scan ≥3 placement verbs, saw ${found}`);
|
|
86
|
+
});
|
|
87
|
+
// ---------------------------------------------------------------------------
|
|
88
|
+
// Lint guard — §5.1, ENFORCED. The driver (tmux-driver.ts) is imported only by
|
|
89
|
+
// placement.ts, placement-tmux.ts, tmux-chrome.ts, and tmux-bindings.ts. Every
|
|
90
|
+
// other module — runtime, daemon, commands, stophook, and tests — must route
|
|
91
|
+
// through those sanctioned seams.
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
/** Every `.ts` file under `src` (recursively), excluding nothing. */
|
|
94
|
+
function allTsFiles(dir) {
|
|
95
|
+
const out = [];
|
|
96
|
+
for (const entry of readdirSync(dir)) {
|
|
97
|
+
const p = join(dir, entry);
|
|
98
|
+
if (statSync(p).isDirectory())
|
|
99
|
+
out.push(...allTsFiles(p));
|
|
100
|
+
else if (entry.endsWith('.ts'))
|
|
101
|
+
out.push(p);
|
|
102
|
+
}
|
|
103
|
+
return out;
|
|
104
|
+
}
|
|
105
|
+
/** Files (basename) sanctioned to import the driver, per §2.1. */
|
|
106
|
+
const ALLOWED_IMPORTERS = new Set(['placement.ts', 'placement-tmux.ts', 'tmux-chrome.ts', 'tmux-bindings.ts']);
|
|
107
|
+
function importsDriver(file) {
|
|
108
|
+
const src = readFileSync(file, 'utf8');
|
|
109
|
+
// A specifier whose basename is exactly `tmux-driver.js` (so
|
|
110
|
+
// `tmux-bindings.js` is not matched). Covers `from '...'` and `import('...')`.
|
|
111
|
+
return [...src.matchAll(/(?:from|import\s*\()\s*'([^']+)'/g)].some((m) => basename(m[1]) === 'tmux-driver.js');
|
|
112
|
+
}
|
|
113
|
+
test('§5.1 lint: only sanctioned seams import the tmux driver', () => {
|
|
114
|
+
const offenders = allTsFiles(SRC_ROOT)
|
|
115
|
+
.filter((f) => !ALLOWED_IMPORTERS.has(basename(f)))
|
|
116
|
+
.filter(importsDriver)
|
|
117
|
+
.map((f) => f.slice(SRC_ROOT.length + 1));
|
|
118
|
+
assert.deepEqual(offenders, [], `modules importing tmux-driver.ts directly: ${offenders.join(', ')}`);
|
|
119
|
+
});
|
|
120
|
+
function isolatedTmux(socket, args) {
|
|
121
|
+
const result = spawnSync('tmux', ['-S', socket, ...args], { encoding: 'utf8' });
|
|
122
|
+
return { status: result.status, stdout: result.stdout ?? '', stderr: result.stderr ?? '' };
|
|
123
|
+
}
|
|
124
|
+
function tmuxBinding(socket, table, key) {
|
|
125
|
+
const result = isolatedTmux(socket, ['list-keys', '-T', table]);
|
|
126
|
+
if (result.status !== 0)
|
|
127
|
+
return null;
|
|
128
|
+
return result.stdout.split('\n').find((line) => {
|
|
129
|
+
const match = line.match(/^bind-key\s+(?:-r\s+)?-T\s+\S+\s+(\S+)\s+/);
|
|
130
|
+
return match?.[1] === key;
|
|
131
|
+
}) ?? null;
|
|
132
|
+
}
|
|
133
|
+
test('tmux repairs corrupt bracketed-paste caps without replacing user overrides', (t) => {
|
|
134
|
+
if (spawnSync('tmux', ['-V']).status !== 0) {
|
|
135
|
+
t.skip('tmux is unavailable');
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const name = `crtr-bracketed-paste-${process.pid}-${Date.now()}`;
|
|
139
|
+
// `-f /dev/null`: boot a config-less isolated server so these binding tests are
|
|
140
|
+
// hermetic. Without it the server sources the developer's ~/.tmux.conf, whose
|
|
141
|
+
// own root-table bindings (e.g. M-j) pre-occupy keys these tests rebind onto —
|
|
142
|
+
// the installer then correctly refuses to clobber the foreign binding and the
|
|
143
|
+
// assertion fails on the dev's machine but not on a config-less CI runner.
|
|
144
|
+
const boot = spawnSync('tmux', ['-L', name, '-f', '/dev/null', 'new-session', '-d', '-s', 'test'], { encoding: 'utf8' });
|
|
145
|
+
assert.equal(boot.status, 0, boot.stderr);
|
|
146
|
+
const socket = spawnSync('tmux', ['-L', name, 'display-message', '-p', '#{socket_path}'], { encoding: 'utf8' }).stdout.trim();
|
|
147
|
+
assert.notEqual(socket, '');
|
|
148
|
+
const priorTmux = process.env['TMUX'];
|
|
149
|
+
process.env['TMUX'] = `${socket},1,0`;
|
|
150
|
+
try {
|
|
151
|
+
assert.equal(isolatedTmux(socket, ['set-option', '-s', 'terminal-overrides', 'xterm*:Tc']).status, 0);
|
|
152
|
+
assert.equal(isolatedTmux(socket, ['set-option', '-sga', 'terminal-overrides', '*:Enbp=E[?2004h:Dsbp=E[?2004l']).status, 0);
|
|
153
|
+
ensureSession('test', process.cwd());
|
|
154
|
+
const repaired = isolatedTmux(socket, ['show-options', '-s', 'terminal-overrides']);
|
|
155
|
+
assert.equal(repaired.status, 0, repaired.stderr);
|
|
156
|
+
assert.match(repaired.stdout, /xterm\*:Tc/, 'unrelated user override must remain');
|
|
157
|
+
assert.match(repaired.stdout, /Enbp=\\+E\[\?2004h/, 'a valid Enbp override must be appended');
|
|
158
|
+
ensureSession('test', process.cwd());
|
|
159
|
+
assert.equal(isolatedTmux(socket, ['show-options', '-s', 'terminal-overrides']).stdout, repaired.stdout, 'valid Enbp must make the repair idempotent');
|
|
160
|
+
}
|
|
161
|
+
finally {
|
|
162
|
+
if (priorTmux === undefined)
|
|
163
|
+
delete process.env['TMUX'];
|
|
164
|
+
else
|
|
165
|
+
process.env['TMUX'] = priorTmux;
|
|
166
|
+
isolatedTmux(socket, ['kill-server']);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
test('tmux installer remaps owned pairs and preserves occupied user bindings', (t) => {
|
|
170
|
+
if (spawnSync('tmux', ['-V']).status !== 0) {
|
|
171
|
+
t.skip('tmux is unavailable');
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
const name = `crtr-keybindings-${process.pid}-${Date.now()}`;
|
|
175
|
+
const boot = spawnSync('tmux', ['-L', name, '-f', '/dev/null', 'new-session', '-d', '-s', 'test'], { encoding: 'utf8' });
|
|
176
|
+
assert.equal(boot.status, 0, boot.stderr);
|
|
177
|
+
const socketResult = spawnSync('tmux', ['-L', name, 'display-message', '-p', '#{socket_path}'], { encoding: 'utf8' });
|
|
178
|
+
const socket = socketResult.stdout.trim();
|
|
179
|
+
assert.notEqual(socket, '');
|
|
180
|
+
const priorTmux = process.env['TMUX'];
|
|
181
|
+
process.env['TMUX'] = `${socket},1,0`;
|
|
182
|
+
try {
|
|
183
|
+
const first = installTmuxBindings(resolveKeybindings());
|
|
184
|
+
assert.equal(first.ok, true, JSON.stringify(first.diagnostics));
|
|
185
|
+
assert.ok(first.installed.some((pair) => pair.table === 'root' && pair.key === 'M-]'));
|
|
186
|
+
const defaultMenu = tmuxBinding(socket, 'root', 'M-c') ?? '';
|
|
187
|
+
assert.match(defaultMenu, /display-menu/);
|
|
188
|
+
// The inbox toggle installs at its default key (alt+i → M-i) in the same sweep.
|
|
189
|
+
assert.match(tmuxBinding(socket, 'root', 'M-i') ?? '', /crtr human inbox toggle/);
|
|
190
|
+
const remapped = installTmuxBindings(resolveKeybindings({
|
|
191
|
+
'crtr.tmux.menu.open': ['alt+shift+z'],
|
|
192
|
+
'crtr.tmux.menu.graph': ['shift+z'],
|
|
193
|
+
'crtr.tmux.menu-global.fold-tools': ['alt+shift+f'],
|
|
194
|
+
'crtr.tmux.node.next': [],
|
|
195
|
+
}));
|
|
196
|
+
assert.equal(remapped.ok, true, JSON.stringify(remapped.diagnostics));
|
|
197
|
+
assert.equal(tmuxBinding(socket, 'root', 'M-c'), null);
|
|
198
|
+
assert.equal(tmuxBinding(socket, 'root', 'M-]'), null);
|
|
199
|
+
assert.equal(tmuxBinding(socket, 'root', 'M-F'), null);
|
|
200
|
+
assert.equal(tmuxBinding(socket, 'root', 'M-S-f'), null);
|
|
201
|
+
const foldTools = tmuxBinding(socket, 'root', 'M-S-F') ?? '';
|
|
202
|
+
assert.match(foldTools, /fold-tools/);
|
|
203
|
+
assert.doesNotMatch(foldTools, /#\{pane_id\}/);
|
|
204
|
+
const menu = tmuxBinding(socket, 'root', 'M-S-Z') ?? '';
|
|
205
|
+
assert.match(menu, /canvas graph/);
|
|
206
|
+
assert.match(menu, /Z/);
|
|
207
|
+
assert.match(menu, /"Alt\+Shift\+Z to close" M-S-Z refresh-client/);
|
|
208
|
+
const again = installTmuxBindings(resolveKeybindings({
|
|
209
|
+
'crtr.tmux.menu.open': ['alt+shift+y'],
|
|
210
|
+
'crtr.tmux.node.next': [],
|
|
211
|
+
}));
|
|
212
|
+
assert.equal(again.ok, true, JSON.stringify(again.diagnostics));
|
|
213
|
+
isolatedTmux(socket, ['bind-key', '-T', 'root', 'M-S-Z', 'display-message', 'user-owned']);
|
|
214
|
+
const occupied = installTmuxBindings(resolveKeybindings({ 'crtr.tmux.menu.open': ['alt+shift+z'] }));
|
|
215
|
+
assert.equal(occupied.ok, true);
|
|
216
|
+
assert.ok(occupied.diagnostics.some((diagnostic) => diagnostic.code === 'occupied' && diagnostic.bindingId === 'crtr.tmux.menu.open'));
|
|
217
|
+
assert.match(tmuxBinding(socket, 'root', 'M-S-Z') ?? '', /user-owned/);
|
|
218
|
+
}
|
|
219
|
+
finally {
|
|
220
|
+
if (priorTmux === undefined)
|
|
221
|
+
delete process.env['TMUX'];
|
|
222
|
+
else
|
|
223
|
+
process.env['TMUX'] = priorTmux;
|
|
224
|
+
isolatedTmux(socket, ['kill-server']);
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
test('tmux installer reads pair-array manifests and replaces owned pairs', (t) => {
|
|
228
|
+
if (spawnSync('tmux', ['-V']).status !== 0) {
|
|
229
|
+
t.skip('tmux is unavailable');
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
const name = `crtr-pair-manifest-${process.pid}-${Date.now()}`;
|
|
233
|
+
const boot = spawnSync('tmux', ['-L', name, '-f', '/dev/null', 'new-session', '-d', '-s', 'test'], { encoding: 'utf8' });
|
|
234
|
+
assert.equal(boot.status, 0, boot.stderr);
|
|
235
|
+
const socket = spawnSync('tmux', ['-L', name, 'display-message', '-p', '#{socket_path}'], { encoding: 'utf8' }).stdout.trim();
|
|
236
|
+
assert.notEqual(socket, '');
|
|
237
|
+
const priorTmux = process.env['TMUX'];
|
|
238
|
+
process.env['TMUX'] = `${socket},1,0`;
|
|
239
|
+
try {
|
|
240
|
+
// Current-scope releases wrote the pair array before wrappers were added.
|
|
241
|
+
isolatedTmux(socket, ['set-option', '-s', '@crtr_keybindings_manifest', JSON.stringify([{ table: 'root', key: 'M-i' }])]);
|
|
242
|
+
isolatedTmux(socket, ['bind-key', '-T', 'root', 'M-i', 'run-shell', '-b', 'crtr human inbox toggle --quiet']);
|
|
243
|
+
const result = installTmuxBindings(resolveKeybindings());
|
|
244
|
+
assert.equal(result.ok, true, JSON.stringify(result.diagnostics));
|
|
245
|
+
assert.ok(!result.diagnostics.some((d) => d.bindingId === 'crtr.tmux.inbox.toggle'), JSON.stringify(result.diagnostics));
|
|
246
|
+
assert.match(tmuxBinding(socket, 'root', 'M-i') ?? '', /crtr human inbox toggle/);
|
|
247
|
+
assert.match(tmuxBinding(socket, 'root', 'M-c') ?? '', /background running bash/);
|
|
248
|
+
}
|
|
249
|
+
finally {
|
|
250
|
+
if (priorTmux === undefined)
|
|
251
|
+
delete process.env['TMUX'];
|
|
252
|
+
else
|
|
253
|
+
process.env['TMUX'] = priorTmux;
|
|
254
|
+
isolatedTmux(socket, ['kill-server']);
|
|
255
|
+
}
|
|
256
|
+
});
|
|
@@ -4,11 +4,11 @@ import { mkdtempSync, mkdirSync, rmSync, existsSync, readdirSync, statSync, writ
|
|
|
4
4
|
import { spawn } from 'node:child_process';
|
|
5
5
|
import { tmpdir } from 'node:os';
|
|
6
6
|
import { join } from 'node:path';
|
|
7
|
-
import { gitSync } from '
|
|
8
|
-
import { push } from '
|
|
9
|
-
import { createManagedWorktree, closeManagedWorktree, managedWorktreePath, rollbackManagedWorktree, setWorktreeCleanupRunnerForTest } from '
|
|
10
|
-
import { createNode, getNode } from '
|
|
11
|
-
import { closeDb } from '
|
|
7
|
+
import { gitSync } from '../../git.js';
|
|
8
|
+
import { push } from '../../feed/feed.js';
|
|
9
|
+
import { createManagedWorktree, closeManagedWorktree, managedWorktreePath, rollbackManagedWorktree, setWorktreeCleanupRunnerForTest } from '../../worktree.js';
|
|
10
|
+
import { createNode, getNode } from '../../canvas/canvas.js';
|
|
11
|
+
import { closeDb } from '../../canvas/db.js';
|
|
12
12
|
let home;
|
|
13
13
|
let remoteDir;
|
|
14
14
|
let sourceDir;
|
|
@@ -93,7 +93,7 @@ test('closeManagedWorktree recreates the worktree path as a tombstone dir so the
|
|
|
93
93
|
assert.equal(meta?.cwd, wt.repo_root, 'closed node cwd must repoint to the repo root, not the removed worktree path');
|
|
94
94
|
});
|
|
95
95
|
test('two concurrent creates from linked worktrees serialize on their shared repository', async () => {
|
|
96
|
-
const worktreeModule = new URL('
|
|
96
|
+
const worktreeModule = new URL('../../worktree.ts', import.meta.url).href;
|
|
97
97
|
const createFrom = (cwd, nodeId) => new Promise((resolve, reject) => {
|
|
98
98
|
const script = `import { createManagedWorktree } from ${JSON.stringify(worktreeModule)}; createManagedWorktree(${JSON.stringify(cwd)}, ${JSON.stringify(nodeId)});`;
|
|
99
99
|
const child = spawn(process.execPath, ['--import', 'tsx/esm', '--input-type=module', '--eval', script], { env: { ...process.env, CRTR_HOME: home }, stdio: 'pipe' });
|
|
@@ -410,7 +410,7 @@ test('close still blocks on real .crouter/memory/ work — a tracked-file edit a
|
|
|
410
410
|
// (autoDropCleanManagedWorktree) must close it without requiring an explicit
|
|
411
411
|
// `node worktree close`.
|
|
412
412
|
test('autoDropCleanManagedWorktree drops a clean, zero-commit worktree', async () => {
|
|
413
|
-
const { autoDropCleanManagedWorktree } = await import('
|
|
413
|
+
const { autoDropCleanManagedWorktree } = await import('../../worktree.js');
|
|
414
414
|
const nodeId = 'wt-auto-drop-empty';
|
|
415
415
|
const wt = createManagedWorktree(sourceDir, nodeId);
|
|
416
416
|
createNode(node(nodeId, { cwd: wt.path, managed_worktree: wt }));
|
|
@@ -435,7 +435,7 @@ test('autoDropCleanManagedWorktree drops a clean, zero-commit worktree', async (
|
|
|
435
435
|
// The same real-commit case close already protects: a worktree with actual
|
|
436
436
|
// unlanded work must NEVER be auto-dropped by push-final.
|
|
437
437
|
test('autoDropCleanManagedWorktree refuses a worktree with a real commit ahead of base', async () => {
|
|
438
|
-
const { autoDropCleanManagedWorktree } = await import('
|
|
438
|
+
const { autoDropCleanManagedWorktree } = await import('../../worktree.js');
|
|
439
439
|
const nodeId = 'wt-auto-drop-real-work';
|
|
440
440
|
const wt = createManagedWorktree(sourceDir, nodeId);
|
|
441
441
|
createNode(node(nodeId, { cwd: wt.path, managed_worktree: wt }));
|
|
@@ -450,7 +450,7 @@ test('autoDropCleanManagedWorktree refuses a worktree with a real commit ahead o
|
|
|
450
450
|
// Real uncommitted (non-crtr-bookkeeping) changes must also refuse auto-drop,
|
|
451
451
|
// even with zero commits.
|
|
452
452
|
test('autoDropCleanManagedWorktree refuses a worktree with real uncommitted changes', async () => {
|
|
453
|
-
const { autoDropCleanManagedWorktree } = await import('
|
|
453
|
+
const { autoDropCleanManagedWorktree } = await import('../../worktree.js');
|
|
454
454
|
const nodeId = 'wt-auto-drop-dirty';
|
|
455
455
|
const wt = createManagedWorktree(sourceDir, nodeId);
|
|
456
456
|
createNode(node(nodeId, { cwd: wt.path, managed_worktree: wt }));
|
|
@@ -465,7 +465,7 @@ test('autoDropCleanManagedWorktree refuses a worktree with real uncommitted chan
|
|
|
465
465
|
// ever going through crtr's own close path). This must auto-drop and, above
|
|
466
466
|
// all, must never lose the work — it stays reachable from the moved base.
|
|
467
467
|
test('autoDropCleanManagedWorktree drops a branch with real commits already contained in a moved base (#327)', async () => {
|
|
468
|
-
const { autoDropCleanManagedWorktree } = await import('
|
|
468
|
+
const { autoDropCleanManagedWorktree } = await import('../../worktree.js');
|
|
469
469
|
const repo = mkdtempSync(join(tmpdir(), 'crtr-worktree-327-'));
|
|
470
470
|
run(['init', '-b', 'main'], repo);
|
|
471
471
|
run(['config', 'user.email', 'test@example.com'], repo);
|
|
@@ -498,7 +498,7 @@ test('autoDropCleanManagedWorktree drops a branch with real commits already cont
|
|
|
498
498
|
// auto-drop rather than guess — the SAME guard `resolveLandableBase` already
|
|
499
499
|
// gives the explicit close path.
|
|
500
500
|
test('autoDropCleanManagedWorktree refuses when the recorded base branch no longer resolves', async () => {
|
|
501
|
-
const { autoDropCleanManagedWorktree } = await import('
|
|
501
|
+
const { autoDropCleanManagedWorktree } = await import('../../worktree.js');
|
|
502
502
|
const repo = mkdtempSync(join(tmpdir(), 'crtr-worktree-missingbase-'));
|
|
503
503
|
run(['init', '-b', 'main'], repo);
|
|
504
504
|
run(['config', 'user.email', 'test@example.com'], repo);
|
|
@@ -531,7 +531,7 @@ test('autoDropCleanManagedWorktree refuses when the recorded base branch no long
|
|
|
531
531
|
// compare-and-delete must refuse, leaving the branch (and the new commit)
|
|
532
532
|
// fully intact.
|
|
533
533
|
test('the atomic delete refuses when a commit lands on the branch between the predicate and cleanup', async () => {
|
|
534
|
-
const { proveCleanEmptyManagedWorktree, autoDropCleanManagedWorktreeLocked } = await import('
|
|
534
|
+
const { proveCleanEmptyManagedWorktree, autoDropCleanManagedWorktreeLocked } = await import('../../worktree.js');
|
|
535
535
|
const nodeId = 'wt-race-branch-commit';
|
|
536
536
|
const wt = createManagedWorktree(sourceDir, nodeId);
|
|
537
537
|
createNode(node(nodeId, { cwd: wt.path, managed_worktree: wt }));
|
|
@@ -561,7 +561,7 @@ test('the atomic delete refuses when a commit lands on the branch between the pr
|
|
|
561
561
|
// before the delete must catch this even though the branch itself never
|
|
562
562
|
// moved.
|
|
563
563
|
test('the re-verified base containment refuses when the base is rewritten between the predicate and cleanup', async () => {
|
|
564
|
-
const { proveCleanEmptyManagedWorktree, autoDropCleanManagedWorktreeLocked } = await import('
|
|
564
|
+
const { proveCleanEmptyManagedWorktree, autoDropCleanManagedWorktreeLocked } = await import('../../worktree.js');
|
|
565
565
|
const repo = mkdtempSync(join(tmpdir(), 'crtr-worktree-race-base-'));
|
|
566
566
|
run(['init', '-b', 'main'], repo);
|
|
567
567
|
run(['config', 'user.email', 'test@example.com'], repo);
|
|
@@ -605,7 +605,7 @@ test('the re-verified base containment refuses when the base is rewritten betwee
|
|
|
605
605
|
// to reproduce this exact Critical against `6de1c8d`.
|
|
606
606
|
// ---------------------------------------------------------------------------
|
|
607
607
|
test('auto-drop atomic delete refuses when the base is force-reset between the live ancestry check and the ref transaction', async () => {
|
|
608
|
-
const { proveCleanEmptyManagedWorktree, autoDropCleanManagedWorktreeLocked } = await import('
|
|
608
|
+
const { proveCleanEmptyManagedWorktree, autoDropCleanManagedWorktreeLocked } = await import('../../worktree.js');
|
|
609
609
|
const repo = mkdtempSync(join(tmpdir(), 'crtr-worktree-auto-drop-base-window-'));
|
|
610
610
|
run(['init', '-b', 'main'], repo);
|
|
611
611
|
run(['config', 'user.email', 'test@example.com'], repo);
|
|
@@ -717,7 +717,7 @@ PATH="$CRTR_TEST_REAL_PATH" exec git "$@"
|
|
|
717
717
|
// transaction, which bypasses Git's own checked-out-branch protection.
|
|
718
718
|
// ---------------------------------------------------------------------------
|
|
719
719
|
test('auto-drop refuses and preserves the branch and checkout when checkout removal is refused after the clean predicate', async () => {
|
|
720
|
-
const { proveCleanEmptyManagedWorktree, autoDropCleanManagedWorktreeLocked } = await import('
|
|
720
|
+
const { proveCleanEmptyManagedWorktree, autoDropCleanManagedWorktreeLocked } = await import('../../worktree.js');
|
|
721
721
|
const nodeId = 'wt-auto-drop-removal-refused';
|
|
722
722
|
const wt = createManagedWorktree(sourceDir, nodeId);
|
|
723
723
|
createNode(node(nodeId, { cwd: wt.path, managed_worktree: wt }));
|
|
@@ -94,24 +94,6 @@ test('a notify is never a dialog, and never disturbs one that is pending', () =>
|
|
|
94
94
|
assert.equal(reduce(asked, { type: 'extension_ui_dismiss', id: 'other' }), asked);
|
|
95
95
|
assert.equal(reduce(asked, { type: 'extension_ui_dismiss', id: 'ask-1' }).dialog, null);
|
|
96
96
|
});
|
|
97
|
-
test('frames that carry no session state return the SAME state reference', () => {
|
|
98
|
-
const s0 = reduce(initialSessionState(), welcome());
|
|
99
|
-
const inert = [
|
|
100
|
-
{ type: 'error', code: 'read_only', message: 'read-only' },
|
|
101
|
-
{ type: 'ack', for: 'get_commands', ok: true, detail: '[]' },
|
|
102
|
-
{ type: 'bash_start', command: 'ls' },
|
|
103
|
-
{ type: 'bash_output', chunk: 'a\n' },
|
|
104
|
-
{ type: 'bash_end', exitCode: 0, cancelled: false, truncated: false },
|
|
105
|
-
];
|
|
106
|
-
for (const f of inert) {
|
|
107
|
-
assert.equal(reduce(s0, f), s0, `${f.type} must not allocate a new state`);
|
|
108
|
-
}
|
|
109
|
-
// Slice identity is what viewers repaint off: an engine-only change must leave
|
|
110
|
-
// the display slice untouched by reference.
|
|
111
|
-
const started = reduce(s0, { type: 'agent_start' });
|
|
112
|
-
assert.notEqual(started, s0);
|
|
113
|
-
assert.equal(started.display, s0.display, 'an engine change must not dirty the display slice');
|
|
114
|
-
});
|
|
115
97
|
test('a welcome is a COMPLETE catch-up: a re-welcome drops a dead broker s levels and queue', () => {
|
|
116
98
|
const s0 = fold(initialSessionState(), [
|
|
117
99
|
welcome(),
|
|
@@ -57,3 +57,12 @@ test('a --worktree spawn at an already-existing node id throws and leaves NO wor
|
|
|
57
57
|
assert.equal(getNode(nodeId).kind, 'general');
|
|
58
58
|
assert.equal(getNode(nodeId).managed_worktree, undefined);
|
|
59
59
|
});
|
|
60
|
+
test('spawnNode({ nodeId }): a hyphen-less opaque id spawns at the exact given id', () => {
|
|
61
|
+
// Regression for the reviewed opaque-id-contract violation: the old validator
|
|
62
|
+
// required >=2 hyphen segments and rejected a hyphen-less id outright,
|
|
63
|
+
// contradicting the design's "opaque, never parsed for structure" ID scheme
|
|
64
|
+
// that remote and cloud spawns depend on.
|
|
65
|
+
const meta = spawnNode({ kind: 'general', cwd: '/tmp/work', nodeId: 'remote42' });
|
|
66
|
+
assert.equal(meta.node_id, 'remote42');
|
|
67
|
+
assert.notEqual(getNode('remote42'), null);
|
|
68
|
+
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { after, before, test } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { mkdtempSync, rmSync } from 'node:fs';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import { FaultRetry } from '../runtime/broker/fault-retry.js';
|
|
7
|
+
import { readFault } from '../runtime/fault.js';
|
|
8
|
+
let home;
|
|
9
|
+
before(() => {
|
|
10
|
+
home = mkdtempSync(join(tmpdir(), 'crtr-watchdog-abort-retry-'));
|
|
11
|
+
process.env['CRTR_HOME'] = home;
|
|
12
|
+
});
|
|
13
|
+
after(() => {
|
|
14
|
+
rmSync(home, { recursive: true, force: true });
|
|
15
|
+
});
|
|
16
|
+
test('only a watchdog-stamped aborted settlement records an automatic connection fault', () => {
|
|
17
|
+
const settleAbort = (nodeId, stagedWatchdogAbort) => {
|
|
18
|
+
const session = {
|
|
19
|
+
sessionManager: { getLeafId: () => 'leaf-entry' },
|
|
20
|
+
model: undefined,
|
|
21
|
+
};
|
|
22
|
+
const generation = {
|
|
23
|
+
id: 1,
|
|
24
|
+
session,
|
|
25
|
+
fallback: { blocked: false },
|
|
26
|
+
stagedProviderAgentEnd: {
|
|
27
|
+
messages: [{ role: 'assistant', stopReason: 'aborted', errorMessage: 'Request was aborted' }],
|
|
28
|
+
},
|
|
29
|
+
stagedWatchdogAbort,
|
|
30
|
+
stagedOverflowFailure: null,
|
|
31
|
+
executingTools: new Set(),
|
|
32
|
+
};
|
|
33
|
+
const retry = new FaultRetry({
|
|
34
|
+
nodeId,
|
|
35
|
+
currentSession: () => session,
|
|
36
|
+
installedGeneration: () => generation,
|
|
37
|
+
});
|
|
38
|
+
retry.publishSettledProviderFault(generation);
|
|
39
|
+
return { retry, generation };
|
|
40
|
+
};
|
|
41
|
+
const watchdog = settleAbort('watchdog-node', true);
|
|
42
|
+
const fault = readFault('watchdog-node');
|
|
43
|
+
assert.equal(fault?.link, 'pi→provider');
|
|
44
|
+
assert.equal(fault?.kind, 'connection');
|
|
45
|
+
assert.deepEqual(fault?.retry, { disposition: 'auto', by: 'daemon' });
|
|
46
|
+
assert.equal(watchdog.retry.isActiveAutoFault(fault), true);
|
|
47
|
+
assert.equal(watchdog.generation.stagedWatchdogAbort, false, 'settlement consumes the one-shot provenance');
|
|
48
|
+
settleAbort('human-node', false);
|
|
49
|
+
assert.equal(readFault('human-node'), null, 'an otherwise-identical human abort must not arm recovery');
|
|
50
|
+
});
|