@north-light/crouter 0.3.173 → 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} +27 -179
- 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 +7 -1
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +9 -1
- 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
|
@@ -1,484 +0,0 @@
|
|
|
1
|
-
// Run with: node --import tsx/esm --test src/core/__tests__/tmux-surface.test.ts
|
|
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 "only placement.ts / tmux-chrome.ts import tmux.ts" lint guard
|
|
15
|
-
// (ENFORCED as of Step 8): every other module reaches the driver through
|
|
16
|
-
// placement's re-exports or the tmux-chrome seam, so the only direct
|
|
17
|
-
// importers are placement.ts + tmux-chrome.ts (tmux.ts itself excluded).
|
|
18
|
-
import { test } from 'node:test';
|
|
19
|
-
import assert from 'node:assert/strict';
|
|
20
|
-
import { readFileSync, readdirSync, statSync, mkdtempSync, mkdirSync, writeFileSync, existsSync } from 'node:fs';
|
|
21
|
-
import { spawnSync } from 'node:child_process';
|
|
22
|
-
import { tmpdir } from 'node:os';
|
|
23
|
-
import { fileURLToPath } from 'node:url';
|
|
24
|
-
import { dirname, join, basename } from 'node:path';
|
|
25
|
-
import { ensureSession } from '../runtime/placement.js';
|
|
26
|
-
import { installTmuxBindings, legacyInboxKeyFile } from '../runtime/tmux-chrome.js';
|
|
27
|
-
import { ATTACH_CONTROL_BINDINGS, resolveKeybindings } from '../keybindings/index.js';
|
|
28
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
29
|
-
const SRC_ROOT = join(__dirname, '..', '..'); // .../src
|
|
30
|
-
const TMUX_TS = join(SRC_ROOT, 'core', 'runtime', 'tmux.ts');
|
|
31
|
-
/** The placement verbs the §2.2 invariant governs. (swap-pane/break-pane/
|
|
32
|
-
* join-pane/move-pane were deleted with the engine-in-pane host in the broker
|
|
33
|
-
* cut; kept in the match set so a regression that re-introduces an untargeted
|
|
34
|
-
* one is still caught.) */
|
|
35
|
-
const PLACEMENT_VERBS = [
|
|
36
|
-
'new-window',
|
|
37
|
-
'split-window',
|
|
38
|
-
'swap-pane',
|
|
39
|
-
'break-pane',
|
|
40
|
-
'join-pane',
|
|
41
|
-
'move-pane',
|
|
42
|
-
'respawn-pane',
|
|
43
|
-
];
|
|
44
|
-
/** The smallest `[ … ]` array literal that encloses `matchIdx`: scan back to the
|
|
45
|
-
* nearest `[` (the array open — the verb is always its first element), then
|
|
46
|
-
* forward with bracket-depth counting to the matching `]` (handles nested
|
|
47
|
-
* arrays like splitWindow's `? [] : ['-h']`). Returns the array source slice. */
|
|
48
|
-
function enclosingArray(src, matchIdx) {
|
|
49
|
-
let open = matchIdx;
|
|
50
|
-
while (open >= 0 && src[open] !== '[')
|
|
51
|
-
open--;
|
|
52
|
-
assert.ok(open >= 0, `no enclosing [ for the verb at index ${matchIdx}`);
|
|
53
|
-
let depth = 0;
|
|
54
|
-
for (let i = open; i < src.length; i++) {
|
|
55
|
-
if (src[i] === '[')
|
|
56
|
-
depth++;
|
|
57
|
-
else if (src[i] === ']') {
|
|
58
|
-
depth--;
|
|
59
|
-
if (depth === 0)
|
|
60
|
-
return src.slice(open, i + 1);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
throw new Error('unbalanced [ ] while bracket-matching the verb array');
|
|
64
|
-
}
|
|
65
|
-
test('§2.2 driver invariant: every placement verb in tmux.ts passes an explicit -t target', () => {
|
|
66
|
-
const src = readFileSync(TMUX_TS, 'utf8');
|
|
67
|
-
// Match only the QUOTED JS string forms (`'new-window'`, …) — these are real
|
|
68
|
-
// args-array elements; the jsdoc prose mentions the verbs unquoted / in
|
|
69
|
-
// backticks, so this never trips on a comment.
|
|
70
|
-
const re = new RegExp(`'(${PLACEMENT_VERBS.join('|')})'`, 'g');
|
|
71
|
-
let found = 0;
|
|
72
|
-
for (let m = re.exec(src); m !== null; m = re.exec(src)) {
|
|
73
|
-
found++;
|
|
74
|
-
const verb = m[1];
|
|
75
|
-
const arr = enclosingArray(src, m.index);
|
|
76
|
-
// The invariant is "name a specific tmux object, never fall back to the
|
|
77
|
-
// GLOBAL current one". `-t` targets a destination; `break-pane` (and the
|
|
78
|
-
// deleted swap/join/move-pane) instead name their SOURCE with `-s` — which
|
|
79
|
-
// satisfies the invariant identically. Accept either explicit target flag.
|
|
80
|
-
assert.ok(arr.includes(`'-t'`) || arr.includes(`'-s'`), `tmux verb '${verb}' is invoked WITHOUT an explicit -t/-s target — a latent ` +
|
|
81
|
-
`instance of the unbidden-window bug (§2.2). Offending args array:\n${arr}`);
|
|
82
|
-
}
|
|
83
|
-
// Sanity: the driver really does contain placement verbs (so a refactor that
|
|
84
|
-
// renames them can't make this assertion vacuously pass). The broker cut left
|
|
85
|
-
// three (new-window / split-window / respawn-pane).
|
|
86
|
-
assert.ok(found >= 3, `expected to scan ≥3 placement verbs, saw ${found}`);
|
|
87
|
-
});
|
|
88
|
-
// ---------------------------------------------------------------------------
|
|
89
|
-
// Lint guard — §5.1, ENFORCED. The driver (tmux.ts) is imported ONLY by
|
|
90
|
-
// placement.ts (the sanctioned model-over-driver, which re-exports the verbs
|
|
91
|
-
// other modules need) and the tmux-chrome.ts chrome seam. Every other module —
|
|
92
|
-
// runtime, daemon, commands, stophook, AND tests — must route through those.
|
|
93
|
-
// ---------------------------------------------------------------------------
|
|
94
|
-
/** Every `.ts` file under `src` (recursively), excluding nothing. */
|
|
95
|
-
function allTsFiles(dir) {
|
|
96
|
-
const out = [];
|
|
97
|
-
for (const entry of readdirSync(dir)) {
|
|
98
|
-
const p = join(dir, entry);
|
|
99
|
-
if (statSync(p).isDirectory())
|
|
100
|
-
out.push(...allTsFiles(p));
|
|
101
|
-
else if (entry.endsWith('.ts'))
|
|
102
|
-
out.push(p);
|
|
103
|
-
}
|
|
104
|
-
return out;
|
|
105
|
-
}
|
|
106
|
-
/** Files (basename) sanctioned to import the driver, per §2.1. */
|
|
107
|
-
const ALLOWED_IMPORTERS = new Set(['tmux.ts', 'placement.ts', 'placement-tmux.ts', 'tmux-chrome.ts']);
|
|
108
|
-
function importsDriver(file) {
|
|
109
|
-
const src = readFileSync(file, 'utf8');
|
|
110
|
-
// A specifier whose basename is exactly `tmux.js` (so `tmux-chrome.js` is NOT
|
|
111
|
-
// matched). Covers `from '...'` and `import('...')`.
|
|
112
|
-
return [...src.matchAll(/(?:from|import\s*\()\s*'([^']+)'/g)].some((m) => basename(m[1]) === 'tmux.js');
|
|
113
|
-
}
|
|
114
|
-
test('§5.1 lint: only placement.ts / tmux-chrome.ts import the tmux driver', () => {
|
|
115
|
-
const offenders = allTsFiles(SRC_ROOT)
|
|
116
|
-
.filter((f) => !ALLOWED_IMPORTERS.has(basename(f)))
|
|
117
|
-
.filter(importsDriver)
|
|
118
|
-
.map((f) => f.slice(SRC_ROOT.length + 1));
|
|
119
|
-
assert.deepEqual(offenders, [], `modules importing tmux.ts directly: ${offenders.join(', ')}`);
|
|
120
|
-
});
|
|
121
|
-
function isolatedTmux(socket, args) {
|
|
122
|
-
const result = spawnSync('tmux', ['-S', socket, ...args], { encoding: 'utf8' });
|
|
123
|
-
return { status: result.status, stdout: result.stdout ?? '', stderr: result.stderr ?? '' };
|
|
124
|
-
}
|
|
125
|
-
function tmuxBinding(socket, table, key) {
|
|
126
|
-
const result = isolatedTmux(socket, ['list-keys', '-T', table]);
|
|
127
|
-
if (result.status !== 0)
|
|
128
|
-
return null;
|
|
129
|
-
return result.stdout.split('\n').find((line) => {
|
|
130
|
-
const match = line.match(/^bind-key\s+(?:-r\s+)?-T\s+\S+\s+(\S+)\s+/);
|
|
131
|
-
return match?.[1] === key;
|
|
132
|
-
}) ?? null;
|
|
133
|
-
}
|
|
134
|
-
test('tmux repairs corrupt bracketed-paste caps without replacing user overrides', (t) => {
|
|
135
|
-
if (spawnSync('tmux', ['-V']).status !== 0) {
|
|
136
|
-
t.skip('tmux is unavailable');
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
const name = `crtr-bracketed-paste-${process.pid}-${Date.now()}`;
|
|
140
|
-
// `-f /dev/null`: boot a config-less isolated server so these binding tests are
|
|
141
|
-
// hermetic. Without it the server sources the developer's ~/.tmux.conf, whose
|
|
142
|
-
// own root-table bindings (e.g. M-j) pre-occupy keys these tests rebind onto —
|
|
143
|
-
// the installer then correctly refuses to clobber the foreign binding and the
|
|
144
|
-
// assertion fails on the dev's machine but not on a config-less CI runner.
|
|
145
|
-
const boot = spawnSync('tmux', ['-L', name, '-f', '/dev/null', 'new-session', '-d', '-s', 'test'], { encoding: 'utf8' });
|
|
146
|
-
assert.equal(boot.status, 0, boot.stderr);
|
|
147
|
-
const socket = spawnSync('tmux', ['-L', name, 'display-message', '-p', '#{socket_path}'], { encoding: 'utf8' }).stdout.trim();
|
|
148
|
-
assert.notEqual(socket, '');
|
|
149
|
-
const priorTmux = process.env['TMUX'];
|
|
150
|
-
process.env['TMUX'] = `${socket},1,0`;
|
|
151
|
-
try {
|
|
152
|
-
assert.equal(isolatedTmux(socket, ['set-option', '-s', 'terminal-overrides', 'xterm*:Tc']).status, 0);
|
|
153
|
-
assert.equal(isolatedTmux(socket, ['set-option', '-sga', 'terminal-overrides', '*:Enbp=E[?2004h:Dsbp=E[?2004l']).status, 0);
|
|
154
|
-
ensureSession('test', process.cwd());
|
|
155
|
-
const repaired = isolatedTmux(socket, ['show-options', '-s', 'terminal-overrides']);
|
|
156
|
-
assert.equal(repaired.status, 0, repaired.stderr);
|
|
157
|
-
assert.match(repaired.stdout, /xterm\*:Tc/, 'unrelated user override must remain');
|
|
158
|
-
assert.match(repaired.stdout, /Enbp=\\+E\[\?2004h/, 'a valid Enbp override must be appended');
|
|
159
|
-
ensureSession('test', process.cwd());
|
|
160
|
-
assert.equal(isolatedTmux(socket, ['show-options', '-s', 'terminal-overrides']).stdout, repaired.stdout, 'valid Enbp must make the repair idempotent');
|
|
161
|
-
}
|
|
162
|
-
finally {
|
|
163
|
-
if (priorTmux === undefined)
|
|
164
|
-
delete process.env['TMUX'];
|
|
165
|
-
else
|
|
166
|
-
process.env['TMUX'] = priorTmux;
|
|
167
|
-
isolatedTmux(socket, ['kill-server']);
|
|
168
|
-
}
|
|
169
|
-
});
|
|
170
|
-
test('tmux installer remaps owned pairs and preserves occupied user bindings', (t) => {
|
|
171
|
-
if (spawnSync('tmux', ['-V']).status !== 0) {
|
|
172
|
-
t.skip('tmux is unavailable');
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
const name = `crtr-keybindings-${process.pid}-${Date.now()}`;
|
|
176
|
-
const boot = spawnSync('tmux', ['-L', name, '-f', '/dev/null', 'new-session', '-d', '-s', 'test'], { encoding: 'utf8' });
|
|
177
|
-
assert.equal(boot.status, 0, boot.stderr);
|
|
178
|
-
const socketResult = spawnSync('tmux', ['-L', name, 'display-message', '-p', '#{socket_path}'], { encoding: 'utf8' });
|
|
179
|
-
const socket = socketResult.stdout.trim();
|
|
180
|
-
assert.notEqual(socket, '');
|
|
181
|
-
const priorTmux = process.env['TMUX'];
|
|
182
|
-
process.env['TMUX'] = `${socket},1,0`;
|
|
183
|
-
try {
|
|
184
|
-
isolatedTmux(socket, ['bind-key', '-T', 'root', 'M-]', 'run-shell', `crtr surface node cycle --dir next --pane '#{pane_id}' >/dev/null 2>&1`]);
|
|
185
|
-
const first = installTmuxBindings(resolveKeybindings());
|
|
186
|
-
assert.equal(first.ok, true, JSON.stringify(first.diagnostics));
|
|
187
|
-
assert.ok(first.installed.some((pair) => pair.table === 'root' && pair.key === 'M-]'));
|
|
188
|
-
const defaultMenu = tmuxBinding(socket, 'root', 'M-c') ?? '';
|
|
189
|
-
assert.match(defaultMenu, /display-menu/);
|
|
190
|
-
assert.match(defaultMenu, /copy node id/);
|
|
191
|
-
assert.match(defaultMenu, /surface node id --pane \{pane\}/);
|
|
192
|
-
assert.match(defaultMenu, /fork into idle root/);
|
|
193
|
-
assert.match(defaultMenu, /node fork --pane #\{pane_id\}/);
|
|
194
|
-
const headings = ['-#[bold]Explore', '-#[bold]Current node', '-#[bold]Lifecycle', '-#[bold]System'];
|
|
195
|
-
for (const heading of headings)
|
|
196
|
-
assert.ok(defaultMenu.includes(heading), `missing heading ${heading}`);
|
|
197
|
-
assert.deepEqual(headings.map((heading) => defaultMenu.indexOf(heading)), [...headings.map((heading) => defaultMenu.indexOf(heading))].sort((a, b) => a - b), 'prefix-menu groups should stay in their intended order');
|
|
198
|
-
// Each later group is preceded by a horizontal-rule separator (a lone empty
|
|
199
|
-
// item name between the previous group and the header).
|
|
200
|
-
assert.ok((defaultMenu.match(/'' "-#\[bold\]/g) ?? []).length >= 3, defaultMenu);
|
|
201
|
-
assert.ok(defaultMenu.indexOf('promote to orchestrator') > defaultMenu.indexOf('-#[bold]Lifecycle'));
|
|
202
|
-
assert.match(defaultMenu, /"create ›" c .*display-menu.*idea.*bug/);
|
|
203
|
-
assert.match(defaultMenu, /"Alt\+C to close" M-c refresh-client/);
|
|
204
|
-
const explore = defaultMenu.indexOf('-#[bold]Explore');
|
|
205
|
-
const currentNode = defaultMenu.indexOf('-#[bold]Current node');
|
|
206
|
-
const lifecycle = defaultMenu.indexOf('-#[bold]Lifecycle');
|
|
207
|
-
const system = defaultMenu.indexOf('-#[bold]System');
|
|
208
|
-
for (const item of ['find node', 'canvas graph', 'go to manager', 'inspect ›', 'display ›']) {
|
|
209
|
-
assert.ok(defaultMenu.indexOf(item) > explore && defaultMenu.indexOf(item) < currentNode, `${item} belongs in Explore`);
|
|
210
|
-
}
|
|
211
|
-
assert.match(defaultMenu, /"inspect ›" i .*display-menu.*metadata.*context \+ reports/);
|
|
212
|
-
for (const item of ['background running bash', 'copy node id']) {
|
|
213
|
-
assert.ok(defaultMenu.indexOf(item) > currentNode && defaultMenu.indexOf(item) < lifecycle, `${item} belongs to the current node`);
|
|
214
|
-
}
|
|
215
|
-
assert.ok(defaultMenu.indexOf('fork into idle root') > lifecycle && defaultMenu.indexOf('fork into idle root') < system, 'fork belongs in Lifecycle');
|
|
216
|
-
assert.match(defaultMenu, /"display ›" z .*display-menu.*fold finished tool calls/);
|
|
217
|
-
assert.match(defaultMenu, /"attach viewer ›" a .*display-menu.*search profile files/);
|
|
218
|
-
// File review is reachable from the top-level menu and alt+shift+R only:
|
|
219
|
-
// its attach-submenu selector ships unbound, so the row must not render.
|
|
220
|
-
assert.doesNotMatch(defaultMenu, /"review a file" r /);
|
|
221
|
-
assert.match(defaultMenu, /send-keys -l/);
|
|
222
|
-
assert.match(defaultMenu, /crtr\.attach\.profile-files/, 'the menu path must work while the profile-files direct binding is disabled by default');
|
|
223
|
-
// Matched with its selector, so the Explore group's "display ›" item
|
|
224
|
-
// cannot satisfy this assertion by substring.
|
|
225
|
-
assert.ok(defaultMenu.indexOf('settings , ') > system, 'settings belongs in System');
|
|
226
|
-
assert.ok(defaultMenu.indexOf('create ›') > system, 'create belongs in System');
|
|
227
|
-
// The inbox toggle installs at its default key (alt+i → M-i) in the same sweep.
|
|
228
|
-
assert.match(tmuxBinding(socket, 'root', 'M-i') ?? '', /crtr human inbox toggle/);
|
|
229
|
-
const attachMenuDisabled = Object.fromEntries(ATTACH_CONTROL_BINDINGS.map(({ menuId }) => [menuId, []]));
|
|
230
|
-
const withoutAttach = installTmuxBindings(resolveKeybindings(attachMenuDisabled));
|
|
231
|
-
assert.equal(withoutAttach.ok, true, JSON.stringify(withoutAttach.diagnostics));
|
|
232
|
-
const menuWithoutAttach = tmuxBinding(socket, 'root', 'M-c') ?? '';
|
|
233
|
-
assert.doesNotMatch(menuWithoutAttach, /attach viewer ›/, 'an empty attach submenu must hide its opener');
|
|
234
|
-
assert.doesNotMatch(menuWithoutAttach, /search profile files/);
|
|
235
|
-
const remapped = installTmuxBindings(resolveKeybindings({
|
|
236
|
-
'crtr.tmux.menu.open': ['alt+shift+z'],
|
|
237
|
-
'crtr.tmux.menu.graph': ['shift+z'],
|
|
238
|
-
'crtr.tmux.menu-global.fold-tools': ['alt+shift+f'],
|
|
239
|
-
'crtr.tmux.node.next': [],
|
|
240
|
-
}));
|
|
241
|
-
assert.equal(remapped.ok, true, JSON.stringify(remapped.diagnostics));
|
|
242
|
-
assert.equal(tmuxBinding(socket, 'root', 'M-c'), null);
|
|
243
|
-
assert.equal(tmuxBinding(socket, 'root', 'M-]'), null);
|
|
244
|
-
assert.equal(tmuxBinding(socket, 'root', 'M-F'), null);
|
|
245
|
-
assert.equal(tmuxBinding(socket, 'root', 'M-S-f'), null);
|
|
246
|
-
const foldTools = tmuxBinding(socket, 'root', 'M-S-F') ?? '';
|
|
247
|
-
assert.match(foldTools, /fold-tools/);
|
|
248
|
-
assert.doesNotMatch(foldTools, /#\{pane_id\}/);
|
|
249
|
-
const menu = tmuxBinding(socket, 'root', 'M-S-Z') ?? '';
|
|
250
|
-
assert.match(menu, /canvas graph/);
|
|
251
|
-
assert.match(menu, /Z/);
|
|
252
|
-
assert.match(menu, /"Alt\+Shift\+Z to close" M-S-Z refresh-client/);
|
|
253
|
-
const again = installTmuxBindings(resolveKeybindings({
|
|
254
|
-
'crtr.tmux.menu.open': ['alt+shift+y'],
|
|
255
|
-
'crtr.tmux.node.next': [],
|
|
256
|
-
}));
|
|
257
|
-
assert.equal(again.ok, true, JSON.stringify(again.diagnostics));
|
|
258
|
-
isolatedTmux(socket, ['bind-key', '-T', 'root', 'M-S-Z', 'display-message', 'user-owned']);
|
|
259
|
-
const occupied = installTmuxBindings(resolveKeybindings({ 'crtr.tmux.menu.open': ['alt+shift+z'] }));
|
|
260
|
-
assert.equal(occupied.ok, true);
|
|
261
|
-
assert.ok(occupied.diagnostics.some((diagnostic) => diagnostic.code === 'occupied' && diagnostic.bindingId === 'crtr.tmux.menu.open'));
|
|
262
|
-
assert.match(tmuxBinding(socket, 'root', 'M-S-Z') ?? '', /user-owned/);
|
|
263
|
-
}
|
|
264
|
-
finally {
|
|
265
|
-
if (priorTmux === undefined)
|
|
266
|
-
delete process.env['TMUX'];
|
|
267
|
-
else
|
|
268
|
-
process.env['TMUX'] = priorTmux;
|
|
269
|
-
isolatedTmux(socket, ['kill-server']);
|
|
270
|
-
}
|
|
271
|
-
});
|
|
272
|
-
test('tmux installer replaces an untracked stale crouter menu even when a partial manifest exists', (t) => {
|
|
273
|
-
if (spawnSync('tmux', ['-V']).status !== 0) {
|
|
274
|
-
t.skip('tmux is unavailable');
|
|
275
|
-
return;
|
|
276
|
-
}
|
|
277
|
-
const name = `crtr-stale-menu-${process.pid}-${Date.now()}`;
|
|
278
|
-
const boot = spawnSync('tmux', ['-L', name, 'new-session', '-d', '-s', 'test'], { encoding: 'utf8' });
|
|
279
|
-
assert.equal(boot.status, 0, boot.stderr);
|
|
280
|
-
const socket = spawnSync('tmux', ['-L', name, 'display-message', '-p', '#{socket_path}'], { encoding: 'utf8' }).stdout.trim();
|
|
281
|
-
assert.notEqual(socket, '');
|
|
282
|
-
const priorTmux = process.env['TMUX'];
|
|
283
|
-
process.env['TMUX'] = `${socket},1,0`;
|
|
284
|
-
try {
|
|
285
|
-
// Upgrade fixture: a later installer started a manifest with only M-i while
|
|
286
|
-
// the older crouter M-c menu remained live but untracked. Its crouter-only
|
|
287
|
-
// markers prove ownership; it deliberately lacks the new background item.
|
|
288
|
-
isolatedTmux(socket, ['set-option', '-s', '@crtr_keybindings_manifest', JSON.stringify([{ table: 'root', key: 'M-i' }])]);
|
|
289
|
-
isolatedTmux(socket, [
|
|
290
|
-
'bind-key', '-T', 'root', 'M-c', 'display-menu',
|
|
291
|
-
'promote to orchestrator', 'o', "run-shell 'crtr canvas chord'",
|
|
292
|
-
'new issue / todo', 'i', 'display-message stale',
|
|
293
|
-
]);
|
|
294
|
-
const stale = tmuxBinding(socket, 'root', 'M-c') ?? '';
|
|
295
|
-
assert.match(stale, /crtr canvas chord/);
|
|
296
|
-
assert.doesNotMatch(stale, /background running bash/);
|
|
297
|
-
const result = installTmuxBindings(resolveKeybindings());
|
|
298
|
-
assert.equal(result.ok, true, JSON.stringify(result.diagnostics));
|
|
299
|
-
assert.ok(!result.diagnostics.some((d) => d.bindingId === 'crtr.tmux.menu.open'), JSON.stringify(result.diagnostics));
|
|
300
|
-
assert.match(tmuxBinding(socket, 'root', 'M-c') ?? '', /background running bash/);
|
|
301
|
-
}
|
|
302
|
-
finally {
|
|
303
|
-
if (priorTmux === undefined)
|
|
304
|
-
delete process.env['TMUX'];
|
|
305
|
-
else
|
|
306
|
-
process.env['TMUX'] = priorTmux;
|
|
307
|
-
isolatedTmux(socket, ['kill-server']);
|
|
308
|
-
}
|
|
309
|
-
});
|
|
310
|
-
test('tmux installer rebinds/disables the inbox toggle and adopts the legacy hl-owned M-i', (t) => {
|
|
311
|
-
if (spawnSync('tmux', ['-V']).status !== 0) {
|
|
312
|
-
t.skip('tmux is unavailable');
|
|
313
|
-
return;
|
|
314
|
-
}
|
|
315
|
-
const name = `crtr-inbox-${process.pid}-${Date.now()}`;
|
|
316
|
-
const boot = spawnSync('tmux', ['-L', name, '-f', '/dev/null', 'new-session', '-d', '-s', 'test'], { encoding: 'utf8' });
|
|
317
|
-
assert.equal(boot.status, 0, boot.stderr);
|
|
318
|
-
const socket = spawnSync('tmux', ['-L', name, 'display-message', '-p', '#{socket_path}'], { encoding: 'utf8' }).stdout.trim();
|
|
319
|
-
assert.notEqual(socket, '');
|
|
320
|
-
const priorTmux = process.env['TMUX'];
|
|
321
|
-
const priorState = process.env['XDG_STATE_HOME'];
|
|
322
|
-
const stateHome = mkdtempSync(join(tmpdir(), 'crtr-inbox-state-'));
|
|
323
|
-
process.env['TMUX'] = `${socket},1,0`;
|
|
324
|
-
process.env['XDG_STATE_HOME'] = stateHome;
|
|
325
|
-
try {
|
|
326
|
-
// Fixture: a surviving hl-owned M-i binding plus its flat inbox-key file —
|
|
327
|
-
// the arrangement crouter's key ownership replaces — with no crouter
|
|
328
|
-
// manifest yet. First reconciliation must take over M-i (crouter's inbox
|
|
329
|
-
// toggle, tracked in the manifest) rather than report it foreign.
|
|
330
|
-
isolatedTmux(socket, ['bind-key', '-T', 'root', 'M-i', 'run-shell', '-b', 'hl inbox toggle --quiet --tmux-socket "#{socket_path}"']);
|
|
331
|
-
const legacyKeyDir = join(stateHome, 'humanloop');
|
|
332
|
-
mkdirSync(legacyKeyDir, { recursive: true });
|
|
333
|
-
const legacyKeyFile = join(legacyKeyDir, 'inbox-key');
|
|
334
|
-
writeFileSync(legacyKeyFile, 'M-i\n');
|
|
335
|
-
const first = installTmuxBindings(resolveKeybindings());
|
|
336
|
-
assert.equal(first.ok, true, JSON.stringify(first.diagnostics));
|
|
337
|
-
// Adopted, not foreign: M-i is now crouter's inbox toggle, no occupied diag.
|
|
338
|
-
assert.ok(!first.diagnostics.some((d) => d.bindingId === 'crtr.tmux.inbox.toggle'), JSON.stringify(first.diagnostics));
|
|
339
|
-
assert.match(tmuxBinding(socket, 'root', 'M-i') ?? '', /crtr human inbox toggle/);
|
|
340
|
-
assert.ok(first.installed.some((pair) => pair.table === 'root' && pair.key === 'M-i'));
|
|
341
|
-
// The obsolete flat key file is deleted by the cleanup.
|
|
342
|
-
assert.equal(existsSync(legacyKeyFile), false, 'legacy inbox-key file should be removed');
|
|
343
|
-
// Rebind to a custom key: the old M-i (crouter-owned via the manifest) is
|
|
344
|
-
// dropped and the new key carries the same inbox command.
|
|
345
|
-
const rebound = installTmuxBindings(resolveKeybindings({ 'crtr.tmux.inbox.toggle': ['alt+j'] }));
|
|
346
|
-
assert.equal(rebound.ok, true, JSON.stringify(rebound.diagnostics));
|
|
347
|
-
assert.equal(tmuxBinding(socket, 'root', 'M-i'), null);
|
|
348
|
-
assert.match(tmuxBinding(socket, 'root', 'M-j') ?? '', /crtr human inbox toggle/);
|
|
349
|
-
// Disable via empty gesture list: no inbox key installed at all, no error.
|
|
350
|
-
const disabled = installTmuxBindings(resolveKeybindings({ 'crtr.tmux.inbox.toggle': [] }));
|
|
351
|
-
assert.equal(disabled.ok, true, JSON.stringify(disabled.diagnostics));
|
|
352
|
-
assert.equal(tmuxBinding(socket, 'root', 'M-i'), null);
|
|
353
|
-
assert.equal(tmuxBinding(socket, 'root', 'M-j'), null);
|
|
354
|
-
}
|
|
355
|
-
finally {
|
|
356
|
-
if (priorTmux === undefined)
|
|
357
|
-
delete process.env['TMUX'];
|
|
358
|
-
else
|
|
359
|
-
process.env['TMUX'] = priorTmux;
|
|
360
|
-
if (priorState === undefined)
|
|
361
|
-
delete process.env['XDG_STATE_HOME'];
|
|
362
|
-
else
|
|
363
|
-
process.env['XDG_STATE_HOME'] = priorState;
|
|
364
|
-
isolatedTmux(socket, ['kill-server']);
|
|
365
|
-
}
|
|
366
|
-
});
|
|
367
|
-
test('tmux installer adopts the legacy hl-owned inbox key when a crouter manifest already exists', (t) => {
|
|
368
|
-
if (spawnSync('tmux', ['-V']).status !== 0) {
|
|
369
|
-
t.skip('tmux is unavailable');
|
|
370
|
-
return;
|
|
371
|
-
}
|
|
372
|
-
const name = `crtr-inbox-upgrade-${process.pid}-${Date.now()}`;
|
|
373
|
-
const boot = spawnSync('tmux', ['-L', name, '-f', '/dev/null', 'new-session', '-d', '-s', 'test'], { encoding: 'utf8' });
|
|
374
|
-
assert.equal(boot.status, 0, boot.stderr);
|
|
375
|
-
const socket = spawnSync('tmux', ['-L', name, 'display-message', '-p', '#{socket_path}'], { encoding: 'utf8' }).stdout.trim();
|
|
376
|
-
assert.notEqual(socket, '');
|
|
377
|
-
const priorTmux = process.env['TMUX'];
|
|
378
|
-
const priorState = process.env['XDG_STATE_HOME'];
|
|
379
|
-
const stateHome = mkdtempSync(join(tmpdir(), 'crtr-inbox-state-'));
|
|
380
|
-
process.env['TMUX'] = `${socket},1,0`;
|
|
381
|
-
process.env['XDG_STATE_HOME'] = stateHome;
|
|
382
|
-
try {
|
|
383
|
-
// Contract: an hl-owned inbox binding not tracked in the manifest must be
|
|
384
|
-
// adopted even when a crouter manifest already exists. Force
|
|
385
|
-
// `manifest.existed = true` with a non-empty option, then seed an untracked
|
|
386
|
-
// hl-owned M-i binding + its key file.
|
|
387
|
-
isolatedTmux(socket, ['set-option', '-s', '@crtr_keybindings_manifest', '[]']);
|
|
388
|
-
isolatedTmux(socket, ['bind-key', '-T', 'root', 'M-i', 'run-shell', '-b', 'hl inbox toggle --quiet --tmux-socket "#{socket_path}"']);
|
|
389
|
-
const legacyKeyDir = join(stateHome, 'humanloop');
|
|
390
|
-
mkdirSync(legacyKeyDir, { recursive: true });
|
|
391
|
-
const legacyKeyFile = join(legacyKeyDir, 'inbox-key');
|
|
392
|
-
writeFileSync(legacyKeyFile, 'M-i\n');
|
|
393
|
-
const result = installTmuxBindings(resolveKeybindings());
|
|
394
|
-
assert.equal(result.ok, true, JSON.stringify(result.diagnostics));
|
|
395
|
-
// Cleanup ran despite the existing manifest: M-i is crouter's tracked inbox
|
|
396
|
-
// toggle, no occupied/foreign diagnostic, and the key file is gone.
|
|
397
|
-
assert.ok(!result.diagnostics.some((d) => d.bindingId === 'crtr.tmux.inbox.toggle'), JSON.stringify(result.diagnostics));
|
|
398
|
-
assert.match(tmuxBinding(socket, 'root', 'M-i') ?? '', /crtr human inbox toggle/);
|
|
399
|
-
assert.ok(result.installed.some((pair) => pair.table === 'root' && pair.key === 'M-i'));
|
|
400
|
-
assert.equal(existsSync(legacyKeyFile), false, 'legacy inbox-key file should be removed');
|
|
401
|
-
}
|
|
402
|
-
finally {
|
|
403
|
-
if (priorTmux === undefined)
|
|
404
|
-
delete process.env['TMUX'];
|
|
405
|
-
else
|
|
406
|
-
process.env['TMUX'] = priorTmux;
|
|
407
|
-
if (priorState === undefined)
|
|
408
|
-
delete process.env['XDG_STATE_HOME'];
|
|
409
|
-
else
|
|
410
|
-
process.env['XDG_STATE_HOME'] = priorState;
|
|
411
|
-
isolatedTmux(socket, ['kill-server']);
|
|
412
|
-
}
|
|
413
|
-
});
|
|
414
|
-
test('tmux installer removes a legacy custom inbox key recorded in the state file', (t) => {
|
|
415
|
-
if (spawnSync('tmux', ['-V']).status !== 0) {
|
|
416
|
-
t.skip('tmux is unavailable');
|
|
417
|
-
return;
|
|
418
|
-
}
|
|
419
|
-
const name = `crtr-inbox-custom-${process.pid}-${Date.now()}`;
|
|
420
|
-
const boot = spawnSync('tmux', ['-L', name, '-f', '/dev/null', 'new-session', '-d', '-s', 'test'], { encoding: 'utf8' });
|
|
421
|
-
assert.equal(boot.status, 0, boot.stderr);
|
|
422
|
-
const socket = spawnSync('tmux', ['-L', name, 'display-message', '-p', '#{socket_path}'], { encoding: 'utf8' }).stdout.trim();
|
|
423
|
-
assert.notEqual(socket, '');
|
|
424
|
-
const priorTmux = process.env['TMUX'];
|
|
425
|
-
const priorState = process.env['XDG_STATE_HOME'];
|
|
426
|
-
const stateHome = mkdtempSync(join(tmpdir(), 'crtr-inbox-state-'));
|
|
427
|
-
process.env['TMUX'] = `${socket},1,0`;
|
|
428
|
-
process.env['XDG_STATE_HOME'] = stateHome;
|
|
429
|
-
try {
|
|
430
|
-
// Contract: an hl-owned binding at a non-default key named by the state
|
|
431
|
-
// file must be located via that file and unbound (its value is never
|
|
432
|
-
// imported as a crouter gesture), leaving crouter's configured M-i the only
|
|
433
|
-
// installed inbox key even when a crouter manifest already exists.
|
|
434
|
-
isolatedTmux(socket, ['set-option', '-s', '@crtr_keybindings_manifest', '[]']);
|
|
435
|
-
isolatedTmux(socket, ['bind-key', '-T', 'root', 'M-z', 'run-shell', '-b', 'hl inbox toggle --quiet --tmux-socket "#{socket_path}"']);
|
|
436
|
-
const legacyKeyDir = join(stateHome, 'humanloop');
|
|
437
|
-
mkdirSync(legacyKeyDir, { recursive: true });
|
|
438
|
-
const legacyKeyFile = join(legacyKeyDir, 'inbox-key');
|
|
439
|
-
writeFileSync(legacyKeyFile, 'M-z\n');
|
|
440
|
-
const result = installTmuxBindings(resolveKeybindings());
|
|
441
|
-
assert.equal(result.ok, true, JSON.stringify(result.diagnostics));
|
|
442
|
-
// The orphaned custom-key binding is gone — not left as an untracked live
|
|
443
|
-
// shortcut — and was not imported into crouter's config (M-z stays unbound).
|
|
444
|
-
assert.equal(tmuxBinding(socket, 'root', 'M-z'), null, 'legacy custom key must be unbound');
|
|
445
|
-
assert.match(tmuxBinding(socket, 'root', 'M-i') ?? '', /crtr human inbox toggle/);
|
|
446
|
-
assert.equal(existsSync(legacyKeyFile), false, 'legacy inbox-key file should be removed');
|
|
447
|
-
}
|
|
448
|
-
finally {
|
|
449
|
-
if (priorTmux === undefined)
|
|
450
|
-
delete process.env['TMUX'];
|
|
451
|
-
else
|
|
452
|
-
process.env['TMUX'] = priorTmux;
|
|
453
|
-
if (priorState === undefined)
|
|
454
|
-
delete process.env['XDG_STATE_HOME'];
|
|
455
|
-
else
|
|
456
|
-
process.env['XDG_STATE_HOME'] = priorState;
|
|
457
|
-
isolatedTmux(socket, ['kill-server']);
|
|
458
|
-
}
|
|
459
|
-
});
|
|
460
|
-
test('legacyInboxKeyFile resolves under the OS home when HOME and XDG_STATE_HOME are unset', () => {
|
|
461
|
-
const priorHome = process.env['HOME'];
|
|
462
|
-
const priorState = process.env['XDG_STATE_HOME'];
|
|
463
|
-
delete process.env['HOME'];
|
|
464
|
-
delete process.env['XDG_STATE_HOME'];
|
|
465
|
-
try {
|
|
466
|
-
const resolved = legacyInboxKeyFile();
|
|
467
|
-
// Must be an absolute OS-home path (via os.homedir()), never cwd-relative —
|
|
468
|
-
// otherwise cleanup would miss the real file and could delete an unrelated
|
|
469
|
-
// file under the current directory.
|
|
470
|
-
assert.ok(resolved.startsWith('/'), `expected an absolute path, got ${resolved}`);
|
|
471
|
-
assert.ok(resolved.endsWith(join('.local', 'state', 'humanloop', 'inbox-key')), resolved);
|
|
472
|
-
assert.ok(!resolved.startsWith(join(process.cwd(), '.local')), `must not resolve relative to cwd: ${resolved}`);
|
|
473
|
-
}
|
|
474
|
-
finally {
|
|
475
|
-
if (priorHome === undefined)
|
|
476
|
-
delete process.env['HOME'];
|
|
477
|
-
else
|
|
478
|
-
process.env['HOME'] = priorHome;
|
|
479
|
-
if (priorState === undefined)
|
|
480
|
-
delete process.env['XDG_STATE_HOME'];
|
|
481
|
-
else
|
|
482
|
-
process.env['XDG_STATE_HOME'] = priorState;
|
|
483
|
-
}
|
|
484
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
// Run with: node --import tsx/esm --test src/core/__tests__/wake-bearings.test.ts
|
|
2
|
-
//
|
|
3
|
-
// Cron-birth self-knowledge (the <crtr-wake> provenance block). These checks
|
|
4
|
-
// cover one-shot and recurring birth prose, including a reaped armer, plus the
|
|
5
|
-
// absence of cron provenance on an ordinary revive.
|
|
6
|
-
import { test, before, after, beforeEach } from 'node:test';
|
|
7
|
-
import assert from 'node:assert/strict';
|
|
8
|
-
import { mkdtempSync, rmSync } from 'node:fs';
|
|
9
|
-
import { tmpdir } from 'node:os';
|
|
10
|
-
import { join } from 'node:path';
|
|
11
|
-
import { createNode } from '../canvas/canvas.js';
|
|
12
|
-
import { closeDb } from '../canvas/db.js';
|
|
13
|
-
import { buildWakeBearings } from '../runtime/bearings.js';
|
|
14
|
-
import { buildReviveKickoff, drainBearings } from '../runtime/kickoff.js';
|
|
15
|
-
let home;
|
|
16
|
-
function node(id) {
|
|
17
|
-
return {
|
|
18
|
-
node_id: id,
|
|
19
|
-
name: id,
|
|
20
|
-
created: new Date().toISOString(),
|
|
21
|
-
cwd: '/tmp/work',
|
|
22
|
-
kind: 'general',
|
|
23
|
-
mode: 'base',
|
|
24
|
-
lifecycle: 'terminal',
|
|
25
|
-
status: 'active',
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
const ARMED = '2026-06-08T13:30:00.000Z';
|
|
29
|
-
before(() => {
|
|
30
|
-
home = mkdtempSync(join(tmpdir(), 'crtr-wake-bearings-'));
|
|
31
|
-
process.env['CRTR_HOME'] = home;
|
|
32
|
-
});
|
|
33
|
-
beforeEach(() => {
|
|
34
|
-
closeDb();
|
|
35
|
-
rmSync(home, { recursive: true, force: true });
|
|
36
|
-
});
|
|
37
|
-
after(() => {
|
|
38
|
-
closeDb();
|
|
39
|
-
rmSync(home, { recursive: true, force: true });
|
|
40
|
-
delete process.env['CRTR_HOME'];
|
|
41
|
-
});
|
|
42
|
-
// --- buildWakeBearings: one per kind / cadence variant ----------------------
|
|
43
|
-
test('node_birth one-shot: names a deferred birth + the armer, and says it does not recur', () => {
|
|
44
|
-
const o = {
|
|
45
|
-
kind: 'node_birth',
|
|
46
|
-
ownerId: 'arm-1',
|
|
47
|
-
ownerName: 'release-orch',
|
|
48
|
-
armedAt: ARMED,
|
|
49
|
-
recur: null,
|
|
50
|
-
};
|
|
51
|
-
const b = buildWakeBearings(o);
|
|
52
|
-
assert.ok(b.startsWith('<crtr-wake>') && b.endsWith('</crtr-wake>'));
|
|
53
|
-
assert.match(b, /BORN by a scheduled wake/);
|
|
54
|
-
assert.match(b, /deferred birth/);
|
|
55
|
-
// Armer named ROLE-explicitly so the newborn never reads the id as its own.
|
|
56
|
-
assert.match(b, /armed by node arm-1 \("release-orch"\)/);
|
|
57
|
-
assert.match(b, /only run, not a recurring job/);
|
|
58
|
-
assert.match(b, /Your task follows\./);
|
|
59
|
-
});
|
|
60
|
-
test('node_birth cron: surfaces the cadence + frames it as one run of a standing job', () => {
|
|
61
|
-
const o = {
|
|
62
|
-
kind: 'node_birth',
|
|
63
|
-
ownerId: 'arm-1',
|
|
64
|
-
ownerName: 'nightly',
|
|
65
|
-
armedAt: ARMED,
|
|
66
|
-
recur: JSON.stringify({ cron: '0 9 * * *', tz: 'America/New_York' }),
|
|
67
|
-
};
|
|
68
|
-
const b = buildWakeBearings(o);
|
|
69
|
-
assert.match(b, /recurring spawn-cron armed by node arm-1 \("nightly"\)/);
|
|
70
|
-
// The cadence renders via the shared cadenceDisplay (matches `wake list`).
|
|
71
|
-
assert.match(b, /firing cron `0 9 \* \* \*` \(America\/New_York\)/);
|
|
72
|
-
assert.match(b, /one run of a standing job, not a one-off/);
|
|
73
|
-
assert.match(b, /inherit nothing from prior runs but this task/);
|
|
74
|
-
});
|
|
75
|
-
test('node_birth interval cron: renders the every-N cadence', () => {
|
|
76
|
-
const o = {
|
|
77
|
-
kind: 'node_birth',
|
|
78
|
-
ownerId: 'arm-1',
|
|
79
|
-
ownerName: 'poller',
|
|
80
|
-
armedAt: ARMED,
|
|
81
|
-
recur: JSON.stringify({ every: '6h' }),
|
|
82
|
-
};
|
|
83
|
-
assert.match(buildWakeBearings(o), /firing every 6h/);
|
|
84
|
-
});
|
|
85
|
-
test('node_birth with a reaped armer: renders the bare id, no name, never crashes', () => {
|
|
86
|
-
const o = {
|
|
87
|
-
kind: 'node_birth',
|
|
88
|
-
ownerId: 'gone-9',
|
|
89
|
-
ownerName: undefined, // armer no longer exists → no resolved name
|
|
90
|
-
armedAt: ARMED,
|
|
91
|
-
recur: JSON.stringify({ every: '12h' }),
|
|
92
|
-
};
|
|
93
|
-
const b = buildWakeBearings(o);
|
|
94
|
-
assert.match(b, /armed by node gone-9 \(now gone\)/); // bare id, flagged reaped
|
|
95
|
-
assert.doesNotMatch(b, /\("/); // never an empty/dangling name
|
|
96
|
-
});
|
|
97
|
-
test('an ordinary fresh revive (no wakeReason) carries NO wake block', () => {
|
|
98
|
-
const id = 'b2';
|
|
99
|
-
const meta = createNode(node(id));
|
|
100
|
-
const msg = buildReviveKickoff(meta, drainBearings(meta));
|
|
101
|
-
assert.doesNotMatch(msg, /<crtr-wake>/);
|
|
102
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|