@north-light/crouter 0.3.173 → 0.3.175
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/memory/write.js +13 -12
- 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,134 +0,0 @@
|
|
|
1
|
-
// rebuild-coalescer.test.ts — proves `createCoalescedRebuilder` (`../rebuild-coalescer.ts`)
|
|
2
|
-
// collapses a burst of triggers into ONE rebuild call, and single-flights a
|
|
3
|
-
// trigger that lands while a rebuild is already in flight into exactly one
|
|
4
|
-
// trailing rebuild rather than a second overlapping one. This is the fix for
|
|
5
|
-
// the N+1-per-event amplification `canvas browse`'s remote SSE path used to
|
|
6
|
-
// have (see app.ts) — WITHOUT the coalescer (i.e. calling `rebuild()` directly
|
|
7
|
-
// on every trigger), these assertions fail: a burst of 5 triggers would count
|
|
8
|
-
// 5 rebuild calls, not 1.
|
|
9
|
-
import { test } from 'node:test';
|
|
10
|
-
import assert from 'node:assert/strict';
|
|
11
|
-
import { createCoalescedRebuilder } from '../rebuild-coalescer.js';
|
|
12
|
-
import { wireEventStreamRebuild } from '../app.js';
|
|
13
|
-
function deferred() {
|
|
14
|
-
let resolve;
|
|
15
|
-
const promise = new Promise((r) => { resolve = r; });
|
|
16
|
-
return { promise, resolve };
|
|
17
|
-
}
|
|
18
|
-
test('a burst of triggers within the debounce window collapses into ONE rebuild call', async () => {
|
|
19
|
-
let calls = 0;
|
|
20
|
-
const rebuilder = createCoalescedRebuilder(async () => { calls += 1; }, 30);
|
|
21
|
-
// Five triggers fired synchronously, well inside the debounce window.
|
|
22
|
-
for (let i = 0; i < 5; i++)
|
|
23
|
-
rebuilder.trigger();
|
|
24
|
-
await new Promise((r) => setTimeout(r, 100));
|
|
25
|
-
assert.equal(calls, 1, 'a burst of 5 triggers must produce exactly 1 rebuild, not 5');
|
|
26
|
-
});
|
|
27
|
-
test('a trigger landing while a rebuild is in flight coalesces into exactly one trailing rebuild', async () => {
|
|
28
|
-
let calls = 0;
|
|
29
|
-
const gate = deferred();
|
|
30
|
-
const rebuilder = createCoalescedRebuilder(async () => {
|
|
31
|
-
calls += 1;
|
|
32
|
-
if (calls === 1)
|
|
33
|
-
await gate.promise; // hold the first rebuild "in flight"
|
|
34
|
-
}, 10);
|
|
35
|
-
rebuilder.trigger();
|
|
36
|
-
await new Promise((r) => setTimeout(r, 30)); // let the debounce fire and the first rebuild start
|
|
37
|
-
assert.equal(calls, 1, 'the first rebuild should now be in flight');
|
|
38
|
-
// A burst of events lands WHILE the rebuild is running — must coalesce into
|
|
39
|
-
// exactly one trailing rebuild, never one overlapping rebuild per event.
|
|
40
|
-
rebuilder.trigger();
|
|
41
|
-
rebuilder.trigger();
|
|
42
|
-
rebuilder.trigger();
|
|
43
|
-
await new Promise((r) => setTimeout(r, 30));
|
|
44
|
-
assert.equal(calls, 1, 'events during an in-flight rebuild must not start an overlapping rebuild yet');
|
|
45
|
-
gate.resolve(); // let the first rebuild finish
|
|
46
|
-
await new Promise((r) => setTimeout(r, 30));
|
|
47
|
-
assert.equal(calls, 2, 'exactly one trailing rebuild must run after the in-flight one finished — not 3');
|
|
48
|
-
});
|
|
49
|
-
test('stop() cancels a pending debounce timer so no rebuild fires', async () => {
|
|
50
|
-
let calls = 0;
|
|
51
|
-
const rebuilder = createCoalescedRebuilder(async () => { calls += 1; }, 20);
|
|
52
|
-
rebuilder.trigger();
|
|
53
|
-
rebuilder.stop();
|
|
54
|
-
await new Promise((r) => setTimeout(r, 60));
|
|
55
|
-
assert.equal(calls, 0, 'stop() must cancel the debounced rebuild before it fires');
|
|
56
|
-
});
|
|
57
|
-
// Integration-shaped proof: drive the coalescer with a rebuild function that
|
|
58
|
-
// actually hits a remote-canvas-shaped mock server (the same shelling contract
|
|
59
|
-
// RemoteCanvasSource uses), and count SERVER request rounds — not just JS call
|
|
60
|
-
// counts — across a burst of SSE-style triggers.
|
|
61
|
-
test('a burst of SSE-style triggers produces ONE round of remote requests, not N', async () => {
|
|
62
|
-
const { createServer } = await import('node:http');
|
|
63
|
-
const { RemoteCanvasSource } = await import('../../remote-canvas-source.js');
|
|
64
|
-
let hits = 0;
|
|
65
|
-
const server = createServer((req, res) => {
|
|
66
|
-
const chunks = [];
|
|
67
|
-
req.on('data', (c) => chunks.push(c));
|
|
68
|
-
req.on('end', () => {
|
|
69
|
-
hits += 1;
|
|
70
|
-
res.writeHead(200, { 'content-type': 'application/json' });
|
|
71
|
-
res.end(JSON.stringify({ ok: true, exitCode: 0, stdout: JSON.stringify({ nodes: [] }), stderr: '' }));
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
// The server MUST close in a `finally` — a listening TCP server keeps its
|
|
75
|
-
// process's event loop non-empty forever. Under `node --test`, every test
|
|
76
|
-
// file is its own child process; if an assertion in this test throws before
|
|
77
|
-
// the old inline `server.close()` at the end of the function ran, the
|
|
78
|
-
// server (and the process) never exited, wedging one `--test-concurrency`
|
|
79
|
-
// slot permanently and hanging the whole suite (see the CI-hang postmortem).
|
|
80
|
-
try {
|
|
81
|
-
await new Promise((r) => server.listen(0, '127.0.0.1', r));
|
|
82
|
-
const addr = server.address();
|
|
83
|
-
const port = typeof addr === 'object' && addr !== null ? addr.port : 0;
|
|
84
|
-
const source = new RemoteCanvasSource(`http://127.0.0.1:${port}`, 'tok');
|
|
85
|
-
const rebuilder = createCoalescedRebuilder(async () => {
|
|
86
|
-
source.invalidate();
|
|
87
|
-
await source.listNodes(); // one round of remote requests, mirroring app.ts's rebuildSnapshot
|
|
88
|
-
}, 20);
|
|
89
|
-
for (let i = 0; i < 6; i++)
|
|
90
|
-
rebuilder.trigger();
|
|
91
|
-
// Poll for the request to land instead of sleeping a fixed duration —
|
|
92
|
-
// deterministic under CI's variable CPU load, and doesn't slow down the
|
|
93
|
-
// common case (returns as soon as the debounce + request round trip land).
|
|
94
|
-
const deadline = Date.now() + 2000;
|
|
95
|
-
while (hits < 1 && Date.now() < deadline) {
|
|
96
|
-
await new Promise((r) => setTimeout(r, 10));
|
|
97
|
-
}
|
|
98
|
-
assert.equal(hits, 1, 'a burst of 6 SSE events must produce ONE round of remote requests, not 6');
|
|
99
|
-
}
|
|
100
|
-
finally {
|
|
101
|
-
server.closeAllConnections();
|
|
102
|
-
await new Promise((r) => server.close(() => r()));
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
// Integration proof for browse/app.ts's ACTUAL wiring — not the coalescer
|
|
106
|
-
// helper in isolation. Every test above instantiates `createCoalescedRebuilder`
|
|
107
|
-
// directly, which would stay green even if `app.ts` invoked a per-event
|
|
108
|
-
// rebuild without ever calling the coalescer. This test instead drives
|
|
109
|
-
// `wireEventStreamRebuild`, the exported function `runBrowse` calls to set up
|
|
110
|
-
// its SSE handler, with a fake event stream shaped like the real
|
|
111
|
-
// `RemoteEventStream` (subscribe/start only, no network) — if
|
|
112
|
-
// `wireEventStreamRebuild` is ever changed to call `rebuild` directly per
|
|
113
|
-
// event instead of routing through the coalescer, this test goes red.
|
|
114
|
-
test('wireEventStreamRebuild (the exported app.ts SSE handler) routes a burst of events through the coalescer, not one rebuild per event', async () => {
|
|
115
|
-
let calls = 0;
|
|
116
|
-
const listeners = new Set();
|
|
117
|
-
const fakeEventStream = {
|
|
118
|
-
subscribe: (fn) => {
|
|
119
|
-
listeners.add(fn);
|
|
120
|
-
return () => listeners.delete(fn);
|
|
121
|
-
},
|
|
122
|
-
start: () => { },
|
|
123
|
-
};
|
|
124
|
-
const { unsubscribe } = wireEventStreamRebuild(fakeEventStream, async () => { calls += 1; });
|
|
125
|
-
// A burst of 6 simulated SSE events, well inside the coalescer's debounce
|
|
126
|
-
// window (default 200ms) — must collapse into ONE rebuild round.
|
|
127
|
-
for (let i = 0; i < 6; i++) {
|
|
128
|
-
for (const fn of listeners)
|
|
129
|
-
fn('nodes');
|
|
130
|
-
}
|
|
131
|
-
await new Promise((r) => setTimeout(r, 260));
|
|
132
|
-
assert.equal(calls, 1, 'a burst of 6 events through the app.ts wiring must produce exactly 1 rebuild, not 6 — if this fails, app.ts stopped routing SSE events through the coalescer');
|
|
133
|
-
unsubscribe();
|
|
134
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import { test } from 'node:test';
|
|
2
|
-
import assert from 'node:assert/strict';
|
|
3
|
-
import { buildTree, flatten } from '../model.js';
|
|
4
|
-
import { renderFrame, detectColorCaps } from '../render.js';
|
|
5
|
-
// ── Fixture ───────────────────────────────────────────────────────────────────
|
|
6
|
-
function row(node_id, name, status, opts = {}) {
|
|
7
|
-
return { node_id, name, status, kind: 'general', mode: 'base', ctx_tokens: 0, asks: 0, cwd: '/tmp/proj', created: '2026-01-01T00:00:00.000Z', ...opts };
|
|
8
|
-
}
|
|
9
|
-
const ROWS = [
|
|
10
|
-
row('root1', 'alpha', 'active'),
|
|
11
|
-
row('idle1', 'bravo', 'idle'),
|
|
12
|
-
row('done1', 'charlie', 'done', { ctx_tokens: 120_000 }), // ≥100k → red ctx
|
|
13
|
-
row('dead1', 'delta', 'dead'),
|
|
14
|
-
row('canc1', 'echo', 'canceled', { asks: 3 }),
|
|
15
|
-
];
|
|
16
|
-
const ROOT_IDS = ['root1', 'idle1', 'done1', 'dead1', 'canc1'];
|
|
17
|
-
const childIdsOf = () => [];
|
|
18
|
-
function tree() {
|
|
19
|
-
return buildTree(ROWS, ROOT_IDS, childIdsOf);
|
|
20
|
-
}
|
|
21
|
-
const SIZE = { cols: 100, rows: 24 };
|
|
22
|
-
const ON = { color: true, color256: true };
|
|
23
|
-
const OFF = { color: false, color256: false };
|
|
24
|
-
function state(over = {}) {
|
|
25
|
-
const t = tree();
|
|
26
|
-
const visible = flatten(t, { collapsed: new Set(), tab: 'All', query: over.query ?? '' });
|
|
27
|
-
return {
|
|
28
|
-
tree: t,
|
|
29
|
-
visible,
|
|
30
|
-
tab: 'All',
|
|
31
|
-
cursor: 0,
|
|
32
|
-
scrollOffset: 0,
|
|
33
|
-
query: '',
|
|
34
|
-
search: false,
|
|
35
|
-
totalNodes: t.nodes.size,
|
|
36
|
-
cwdScope: null,
|
|
37
|
-
profileScope: undefined,
|
|
38
|
-
sort: 'tree',
|
|
39
|
-
preview: false,
|
|
40
|
-
residentsOnly: false,
|
|
41
|
-
pinned: new Set(),
|
|
42
|
-
...over,
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
const ESC = '\x1b[';
|
|
46
|
-
/** Any hue (color) SGR: fg 30–37/90–97, bg 40–47/100–107, or 256/truecolor sel. */
|
|
47
|
-
const HUE_RE = /\x1b\[(3\d|4\d|9\d|10\d|38;|48;)/;
|
|
48
|
-
// ── (a) color enabled → status hue present, glyph still there ──────────────────
|
|
49
|
-
test('all-dirs view retains the project column while profile scope is active', () => {
|
|
50
|
-
const out = renderFrame(state({ profileScope: 'crouter-12345678', cwdScope: null, cursor: -1 }), SIZE, OFF);
|
|
51
|
-
assert.ok(out.includes('PROJECT'), 'all-dirs column header remains visible');
|
|
52
|
-
assert.ok(out.includes('~proj'), 'each row retains its cwd basename');
|
|
53
|
-
});
|
|
54
|
-
test('color on: each status glyph carries its hue, glyph kept', () => {
|
|
55
|
-
// cursor off the rows we assert so lineBase doesn't wrap the glyph code.
|
|
56
|
-
const out = renderFrame(state({ cursor: -1 }), SIZE, ON);
|
|
57
|
-
assert.ok(out.includes(`${ESC}32m●`), 'active → green ●');
|
|
58
|
-
assert.ok(out.includes(`${ESC}33m○`), 'idle → yellow ○');
|
|
59
|
-
assert.ok(out.includes(`${ESC}36m✓`), 'done → cyan ✓');
|
|
60
|
-
assert.ok(out.includes(`${ESC}31m✗`), 'dead → red ✗');
|
|
61
|
-
assert.ok(out.includes(`${ESC}90m⊘`), 'canceled → gray ⊘');
|
|
62
|
-
});
|
|
63
|
-
test('color on: ctx ≥100k row is red; asks are bright-yellow', () => {
|
|
64
|
-
const out = renderFrame(state({ cursor: -1 }), SIZE, ON);
|
|
65
|
-
// ctx is a right-aligned fixed-width column now, so the red span carries padding.
|
|
66
|
-
assert.ok(out.includes(`${ESC}31m`) && out.includes('120k'), 'ctx ≥100k → red');
|
|
67
|
-
assert.ok(out.includes(`${ESC}93m`), 'asks → bright-yellow');
|
|
68
|
-
assert.ok(out.includes('⚑3'), 'flag glyph kept');
|
|
69
|
-
});
|
|
70
|
-
test('color on: cursor row uses a 256-color background (not full reverse)', () => {
|
|
71
|
-
const out = renderFrame(state({ cursor: 0 }), SIZE, ON);
|
|
72
|
-
assert.ok(out.includes(`${ESC}48;5;236m`), 'subtle dark-gray cursor bg');
|
|
73
|
-
// and the status glyph hue still reads on the selected row
|
|
74
|
-
assert.ok(out.includes(`${ESC}32m●`), 'glyph hue survives on cursor row');
|
|
75
|
-
});
|
|
76
|
-
// ── (b) NO_COLOR → no hue SGR, but the glyphs (the real encoding) remain ───────
|
|
77
|
-
test('color off: no hue SGR emitted, but every status glyph remains', () => {
|
|
78
|
-
const out = renderFrame(state({ cursor: -1 }), SIZE, OFF);
|
|
79
|
-
assert.ok(!HUE_RE.test(out), `expected no color SGR, got: ${JSON.stringify(out.match(HUE_RE))}`);
|
|
80
|
-
for (const g of ['●', '○', '✓', '✗', '⊘']) {
|
|
81
|
-
assert.ok(out.includes(g), `glyph ${g} kept without color`);
|
|
82
|
-
}
|
|
83
|
-
assert.ok(out.includes('⚑3'), 'flag glyph kept without color');
|
|
84
|
-
// structural SGR is still allowed (dim separators/footer, reverse cursor).
|
|
85
|
-
assert.ok(out.includes(`${ESC}2m`), 'dim (structural) still used');
|
|
86
|
-
});
|
|
87
|
-
test('color off: cursor row falls back to reverse (structural, no hue)', () => {
|
|
88
|
-
const out = renderFrame(state({ cursor: 0 }), SIZE, OFF);
|
|
89
|
-
assert.ok(out.includes(`${ESC}7m`), 'reverse cursor fallback');
|
|
90
|
-
assert.ok(!HUE_RE.test(out), 'still no hue under no-color');
|
|
91
|
-
});
|
|
92
|
-
// ── (c) query → the matched substring is highlighted ───────────────────────────
|
|
93
|
-
test('color on: matched chars in a row name get the bright-cyan highlight', () => {
|
|
94
|
-
// query 'lph' matches 'alpha' (a-LPH-a). The matched run is highlighted.
|
|
95
|
-
const out = renderFrame(state({ query: 'lph', cursor: -1 }), SIZE, ON);
|
|
96
|
-
assert.ok(out.includes(`${ESC}96mlph`), 'matched substring → bright-cyan');
|
|
97
|
-
});
|
|
98
|
-
test('color off: match highlight degrades to bold (no hue), name intact', () => {
|
|
99
|
-
const out = renderFrame(state({ query: 'lph', cursor: -1 }), SIZE, OFF);
|
|
100
|
-
assert.ok(!HUE_RE.test(out), 'no hue under no-color even with a query');
|
|
101
|
-
assert.ok(out.includes(`${ESC}1mlph`), 'matched chars bold as the no-color affordance');
|
|
102
|
-
});
|
|
103
|
-
// ── detectColorCaps gate ───────────────────────────────────────────────────────
|
|
104
|
-
test('detectColorCaps: honors NO_COLOR, TERM=dumb, and non-TTY', () => {
|
|
105
|
-
assert.deepEqual(detectColorCaps({ isTTY: true }, { TERM: 'xterm-256color', COLORTERM: 'truecolor' }), { color: true, color256: true });
|
|
106
|
-
assert.equal(detectColorCaps({ isTTY: true }, { TERM: 'xterm-256color', NO_COLOR: '1' }).color, false);
|
|
107
|
-
assert.equal(detectColorCaps({ isTTY: true }, { TERM: 'dumb' }).color, false);
|
|
108
|
-
assert.equal(detectColorCaps({ isTTY: false }, { TERM: 'xterm-256color' }).color, false);
|
|
109
|
-
// basic color but no 256 → color on, color256 off (reverse cursor fallback).
|
|
110
|
-
assert.deepEqual(detectColorCaps({ isTTY: true }, { TERM: 'xterm' }), { color: true, color256: false });
|
|
111
|
-
});
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export interface CoalescedRebuilder {
|
|
2
|
-
/** Called on every SSE event. Cheap — only schedules/marks work. */
|
|
3
|
-
trigger: () => void;
|
|
4
|
-
/** Cancels any pending debounce timer (does not abort an in-flight rebuild). */
|
|
5
|
-
stop: () => void;
|
|
6
|
-
}
|
|
7
|
-
export declare function createCoalescedRebuilder(rebuild: () => Promise<void>, debounceMs?: number): CoalescedRebuilder;
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
// rebuild-coalescer.ts — single-flight + debounce coalescing for a burst of
|
|
2
|
-
// SSE-triggered rebuilds (`canvas browse`'s remote path — see app.ts).
|
|
3
|
-
//
|
|
4
|
-
// A remote `RemoteEventStream` `nodes`/`inbox` event means "invalidate + re-pull
|
|
5
|
-
// the tree", which for a remote source costs one `node inspect list` plus N
|
|
6
|
-
// `node inspect show` round trips. A burst of events (several nodes changing at
|
|
7
|
-
// once) must NOT fan into one overlapping rebuild per event — it must collapse
|
|
8
|
-
// to one rebuild per burst. This module is the pure, TTY-free coalescing policy
|
|
9
|
-
// so it can be unit-tested without the raw-mode stdin loop in app.ts:
|
|
10
|
-
//
|
|
11
|
-
// - `trigger()` debounces a burst into ONE rebuild call after `debounceMs` of
|
|
12
|
-
// quiet.
|
|
13
|
-
// - if a rebuild is already in flight when the debounce fires (or another
|
|
14
|
-
// trigger lands mid-rebuild), it does NOT launch an overlapping rebuild —
|
|
15
|
-
// it marks exactly one trailing rebuild to run immediately after the
|
|
16
|
-
// in-flight one finishes.
|
|
17
|
-
//
|
|
18
|
-
// Net effect: N events in a burst → 1 rebuild (or, if the burst spans an
|
|
19
|
-
// in-flight rebuild, 2: the one already running + one trailing catch-up) —
|
|
20
|
-
// never N overlapping rebuilds.
|
|
21
|
-
export function createCoalescedRebuilder(rebuild, debounceMs = 200) {
|
|
22
|
-
let timer;
|
|
23
|
-
let inFlight = false;
|
|
24
|
-
let pending = false;
|
|
25
|
-
const run = () => {
|
|
26
|
-
inFlight = true;
|
|
27
|
-
void rebuild().finally(() => {
|
|
28
|
-
inFlight = false;
|
|
29
|
-
if (pending) {
|
|
30
|
-
// A trailing catch-up was armed while this rebuild ran — fire it
|
|
31
|
-
// immediately (no further debounce: the just-finished rebuild WAS the
|
|
32
|
-
// quiet period), collapsing every event that landed mid-flight into
|
|
33
|
-
// exactly one follow-up rebuild, not one per event.
|
|
34
|
-
pending = false;
|
|
35
|
-
run();
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
};
|
|
39
|
-
const trigger = () => {
|
|
40
|
-
if (inFlight) {
|
|
41
|
-
// Already rebuilding — mark one trailing catch-up instead of starting a
|
|
42
|
-
// second overlapping rebuild or re-arming the debounce timer (which
|
|
43
|
-
// would keep pushing the catch-up back on every further event).
|
|
44
|
-
pending = true;
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
if (timer !== undefined)
|
|
48
|
-
return; // already debounced in this quiet window
|
|
49
|
-
timer = setTimeout(() => {
|
|
50
|
-
timer = undefined;
|
|
51
|
-
run();
|
|
52
|
-
}, debounceMs);
|
|
53
|
-
};
|
|
54
|
-
const stop = () => {
|
|
55
|
-
if (timer !== undefined) {
|
|
56
|
-
clearTimeout(timer);
|
|
57
|
-
timer = undefined;
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
return { trigger, stop };
|
|
61
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
export type RemoteEventKind = 'nodes' | 'inbox';
|
|
2
|
-
export interface RemoteEventStreamOptions {
|
|
3
|
-
/** Initial reconnect backoff (ms). Default 1000; injectable so tests don't
|
|
4
|
-
* have to wait out the production backoff window. */
|
|
5
|
-
initialBackoffMs?: number;
|
|
6
|
-
/** Reconnect backoff cap (ms). Default 30_000. */
|
|
7
|
-
backoffCapMs?: number;
|
|
8
|
-
}
|
|
9
|
-
export declare class RemoteEventStream {
|
|
10
|
-
private readonly previewEndpoint;
|
|
11
|
-
private readonly relayToken;
|
|
12
|
-
private controller;
|
|
13
|
-
private stopped;
|
|
14
|
-
private readonly listeners;
|
|
15
|
-
private readonly initialBackoffMs;
|
|
16
|
-
private backoffMs;
|
|
17
|
-
private readonly BACKOFF_CAP_MS;
|
|
18
|
-
private reconnectTimer;
|
|
19
|
-
constructor(previewEndpoint: string, relayToken: string, opts?: RemoteEventStreamOptions);
|
|
20
|
-
subscribe(fn: (kind: RemoteEventKind) => void): () => void;
|
|
21
|
-
start(): void;
|
|
22
|
-
stop(): void;
|
|
23
|
-
private loop;
|
|
24
|
-
}
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
// remote-event-stream.ts — a Node SSE client over a remote canvas's
|
|
2
|
-
// `/__crtr/events` endpoint, driving cache invalidation + re-render for a
|
|
3
|
-
// remote-backed `canvas browse`/viewer. No new npm dependency: Node 18+
|
|
4
|
-
// `fetch` returns a web-standard `ReadableStream` body, read manually with
|
|
5
|
-
// `getReader()` + `TextDecoder` and split on the SSE `\n\n` event delimiter.
|
|
6
|
-
export class RemoteEventStream {
|
|
7
|
-
previewEndpoint;
|
|
8
|
-
relayToken;
|
|
9
|
-
controller;
|
|
10
|
-
stopped = false;
|
|
11
|
-
listeners = new Set();
|
|
12
|
-
initialBackoffMs;
|
|
13
|
-
backoffMs;
|
|
14
|
-
BACKOFF_CAP_MS;
|
|
15
|
-
reconnectTimer;
|
|
16
|
-
constructor(previewEndpoint, relayToken, opts = {}) {
|
|
17
|
-
this.previewEndpoint = previewEndpoint;
|
|
18
|
-
this.relayToken = relayToken;
|
|
19
|
-
this.initialBackoffMs = opts.initialBackoffMs ?? 1000;
|
|
20
|
-
this.backoffMs = this.initialBackoffMs;
|
|
21
|
-
this.BACKOFF_CAP_MS = opts.backoffCapMs ?? 30_000;
|
|
22
|
-
}
|
|
23
|
-
subscribe(fn) {
|
|
24
|
-
this.listeners.add(fn);
|
|
25
|
-
return () => this.listeners.delete(fn);
|
|
26
|
-
}
|
|
27
|
-
start() {
|
|
28
|
-
this.stopped = false;
|
|
29
|
-
void this.loop();
|
|
30
|
-
}
|
|
31
|
-
stop() {
|
|
32
|
-
this.stopped = true;
|
|
33
|
-
this.controller?.abort();
|
|
34
|
-
if (this.reconnectTimer !== undefined) {
|
|
35
|
-
clearTimeout(this.reconnectTimer);
|
|
36
|
-
this.reconnectTimer = undefined;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
async loop() {
|
|
40
|
-
while (!this.stopped) {
|
|
41
|
-
this.controller = new AbortController();
|
|
42
|
-
try {
|
|
43
|
-
const res = await fetch(new URL('/__crtr/events', this.previewEndpoint), {
|
|
44
|
-
headers: { authorization: `Bearer ${this.relayToken}` },
|
|
45
|
-
signal: this.controller.signal,
|
|
46
|
-
});
|
|
47
|
-
if (!res.ok || !res.body)
|
|
48
|
-
throw new Error(`events ${res.status}`);
|
|
49
|
-
this.backoffMs = this.initialBackoffMs; // reset on a successful connect
|
|
50
|
-
const reader = res.body.getReader();
|
|
51
|
-
const decoder = new TextDecoder();
|
|
52
|
-
let buf = '';
|
|
53
|
-
while (true) {
|
|
54
|
-
const { done, value } = await reader.read();
|
|
55
|
-
if (done)
|
|
56
|
-
break;
|
|
57
|
-
buf += decoder.decode(value, { stream: true });
|
|
58
|
-
let idx;
|
|
59
|
-
while ((idx = buf.indexOf('\n\n')) >= 0) {
|
|
60
|
-
const rawEvent = buf.slice(0, idx);
|
|
61
|
-
buf = buf.slice(idx + 2);
|
|
62
|
-
for (const line of rawEvent.split('\n')) {
|
|
63
|
-
if (!line.startsWith('data:'))
|
|
64
|
-
continue; // skip comments (: ping, : connected)
|
|
65
|
-
try {
|
|
66
|
-
const payload = JSON.parse(line.slice(5).trim());
|
|
67
|
-
if (payload.kind === 'nodes' || payload.kind === 'inbox') {
|
|
68
|
-
for (const l of this.listeners)
|
|
69
|
-
l(payload.kind);
|
|
70
|
-
}
|
|
71
|
-
// unknown kind → silently ignored (forward-compat)
|
|
72
|
-
}
|
|
73
|
-
catch {
|
|
74
|
-
// malformed data line — ignore
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
catch {
|
|
81
|
-
// connection error/abort — fall through to backoff+retry unless stopped
|
|
82
|
-
}
|
|
83
|
-
if (this.stopped)
|
|
84
|
-
return;
|
|
85
|
-
await new Promise((resolve) => {
|
|
86
|
-
this.reconnectTimer = setTimeout(() => {
|
|
87
|
-
this.reconnectTimer = undefined;
|
|
88
|
-
resolve();
|
|
89
|
-
}, this.backoffMs);
|
|
90
|
-
});
|
|
91
|
-
this.backoffMs = Math.min(this.backoffMs * 2, this.BACKOFF_CAP_MS);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { test } from 'node:test';
|
|
2
|
-
import assert from 'node:assert/strict';
|
|
3
|
-
import { coalesce } from '../inbox.js';
|
|
4
|
-
// Guards the contract that a human typing directly into a node's box is a
|
|
5
|
-
// CONVERSATION TURN, not a notification: coalesce() delivers those words
|
|
6
|
-
// verbatim (no "From … — N updates" digest header, no `[message]` kind tag),
|
|
7
|
-
// so the dormant wake path reads identically to the live path. Every other
|
|
8
|
-
// sender keeps the digest framing.
|
|
9
|
-
function entry(over) {
|
|
10
|
-
return {
|
|
11
|
-
entry_id: '0'.repeat(31) + '1',
|
|
12
|
-
operation_id: 'op',
|
|
13
|
-
ts: '2026-01-01T00:00:00.000Z',
|
|
14
|
-
from: null,
|
|
15
|
-
tier: 'normal',
|
|
16
|
-
kind: 'message',
|
|
17
|
-
label: 'hi',
|
|
18
|
-
...over,
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
test('a lone human message renders verbatim — no digest framing', () => {
|
|
22
|
-
const out = coalesce([entry({ from: 'human', label: 'hi', data: { body: 'hi' } })]);
|
|
23
|
-
assert.equal(out, 'hi');
|
|
24
|
-
assert.doesNotMatch(out, /From human/);
|
|
25
|
-
assert.doesNotMatch(out, /update/);
|
|
26
|
-
assert.doesNotMatch(out, /\[message\]/);
|
|
27
|
-
});
|
|
28
|
-
test('a multi-line human message keeps its body verbatim', () => {
|
|
29
|
-
const body = 'first line\n\nsecond paragraph';
|
|
30
|
-
const out = coalesce([entry({ from: 'human', label: 'first line', data: { body } })]);
|
|
31
|
-
assert.equal(out, body);
|
|
32
|
-
});
|
|
33
|
-
test('a non-human sender still gets the digest header', () => {
|
|
34
|
-
const out = coalesce([entry({ from: 'mqifzplr-0753bde3', label: 'go', data: { body: 'go' } })]);
|
|
35
|
-
assert.match(out, /^From mqifzplr-0753bde3 — 1 update:/);
|
|
36
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
// Regression: a report/skeleton write for an EMPTY node id used to resolve
|
|
2
|
-
// reportsDir('') → `nodes/reports` and silently mint a stray non-node sibling
|
|
3
|
-
// under nodes/. That stray entry broke the full-tier test harness's node-dir
|
|
4
|
-
// counter (`expected exactly 1 new node dir, got [<id>, reports]` — the rare
|
|
5
|
-
// flake on CI run 27459304455). The boundary now refuses an empty node id loudly
|
|
6
|
-
// instead of writing garbage. This locks that in.
|
|
7
|
-
import { test } from 'node:test';
|
|
8
|
-
import assert from 'node:assert/strict';
|
|
9
|
-
import { mkdtempSync, existsSync, rmSync } from 'node:fs';
|
|
10
|
-
import { join } from 'node:path';
|
|
11
|
-
import { tmpdir } from 'node:os';
|
|
12
|
-
import { push } from '../feed.js';
|
|
13
|
-
import { ensureNodeDirs, nodesRoot } from '../../canvas/paths.js';
|
|
14
|
-
test('push() rejects an empty nodeId and creates no stray nodes/reports dir', async () => {
|
|
15
|
-
const home = mkdtempSync(join(tmpdir(), 'crtr-emptyguard-'));
|
|
16
|
-
const orig = process.env['CRTR_HOME'];
|
|
17
|
-
process.env['CRTR_HOME'] = home;
|
|
18
|
-
try {
|
|
19
|
-
await assert.rejects(() => push('', { kind: 'update', body: 'orphan report' }), /empty nodeId/);
|
|
20
|
-
assert.equal(existsSync(join(nodesRoot(), 'reports')), false, 'no stray nodes/reports dir was created');
|
|
21
|
-
}
|
|
22
|
-
finally {
|
|
23
|
-
if (orig === undefined)
|
|
24
|
-
delete process.env['CRTR_HOME'];
|
|
25
|
-
else
|
|
26
|
-
process.env['CRTR_HOME'] = orig;
|
|
27
|
-
rmSync(home, { recursive: true, force: true });
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
test('ensureNodeDirs() rejects an empty nodeId and creates no stray skeleton dirs', () => {
|
|
31
|
-
const home = mkdtempSync(join(tmpdir(), 'crtr-emptyguard-'));
|
|
32
|
-
const orig = process.env['CRTR_HOME'];
|
|
33
|
-
process.env['CRTR_HOME'] = home;
|
|
34
|
-
try {
|
|
35
|
-
assert.throws(() => ensureNodeDirs(''), /non-empty path segment/);
|
|
36
|
-
assert.equal(existsSync(join(nodesRoot(), 'reports')), false, 'no stray nodes/reports dir was created');
|
|
37
|
-
}
|
|
38
|
-
finally {
|
|
39
|
-
if (orig === undefined)
|
|
40
|
-
delete process.env['CRTR_HOME'];
|
|
41
|
-
else
|
|
42
|
-
process.env['CRTR_HOME'] = orig;
|
|
43
|
-
rmSync(home, { recursive: true, force: true });
|
|
44
|
-
}
|
|
45
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
// Regression: crouter must not leave its old generated `crtr-skills` Agent Skill
|
|
2
|
-
// installed in pi/Claude host skill dirs after memory became the first-class
|
|
3
|
-
// guidance surface. The legacy bundle caused pi to inject an <available_skills>
|
|
4
|
-
// block that described SKILL.md as current crouter behavior.
|
|
5
|
-
//
|
|
6
|
-
// Run: node --import tsx/esm --test src/core/host-exports/__tests__/export-prunes-boot-skill.test.ts
|
|
7
|
-
import { test, beforeEach, afterEach } from 'node:test';
|
|
8
|
-
import assert from 'node:assert/strict';
|
|
9
|
-
import { mkdtempSync, rmSync, mkdirSync, writeFileSync, existsSync, readFileSync } from 'node:fs';
|
|
10
|
-
import { tmpdir } from 'node:os';
|
|
11
|
-
import { join } from 'node:path';
|
|
12
|
-
import { defineBranch, defineLeaf, defineRoot } from '../../command.js';
|
|
13
|
-
import { provisionExports, pruneLegacyExports } from '../export.js';
|
|
14
|
-
let home;
|
|
15
|
-
let prevHome;
|
|
16
|
-
let prevNoExports;
|
|
17
|
-
beforeEach(() => {
|
|
18
|
-
prevHome = process.env.HOME;
|
|
19
|
-
prevNoExports = process.env.CRTR_NO_EXPORTS;
|
|
20
|
-
home = mkdtempSync(join(tmpdir(), 'crtr-export-prune-'));
|
|
21
|
-
process.env.HOME = home;
|
|
22
|
-
delete process.env.CRTR_NO_EXPORTS;
|
|
23
|
-
mkdirSync(join(home, '.pi', 'agent', 'skills', 'crtr-skills'), { recursive: true });
|
|
24
|
-
mkdirSync(join(home, '.claude', 'skills', 'crtr-skills'), { recursive: true });
|
|
25
|
-
writeFileSync(join(home, '.pi', 'agent', 'skills', 'crtr-skills', 'SKILL.md'), '---\nname: crtr-skills\n---\n\n<!-- crtr-boot-skill v2 -->\n', 'utf8');
|
|
26
|
-
writeFileSync(join(home, '.claude', 'skills', 'crtr-skills', 'SKILL.md'), '---\nname: crtr-skills\n---\n\nuser-customized, no crtr marker\n', 'utf8');
|
|
27
|
-
});
|
|
28
|
-
afterEach(() => {
|
|
29
|
-
if (prevHome === undefined)
|
|
30
|
-
delete process.env.HOME;
|
|
31
|
-
else
|
|
32
|
-
process.env.HOME = prevHome;
|
|
33
|
-
if (prevNoExports === undefined)
|
|
34
|
-
delete process.env.CRTR_NO_EXPORTS;
|
|
35
|
-
else
|
|
36
|
-
process.env.CRTR_NO_EXPORTS = prevNoExports;
|
|
37
|
-
rmSync(home, { recursive: true, force: true });
|
|
38
|
-
});
|
|
39
|
-
const root = defineRoot({
|
|
40
|
-
tagline: 'fixture',
|
|
41
|
-
globals: [],
|
|
42
|
-
subtrees: [
|
|
43
|
-
defineBranch({
|
|
44
|
-
name: 'fixture',
|
|
45
|
-
help: { name: 'fixture', summary: 'fixture' },
|
|
46
|
-
rootEntry: { concept: 'fixture', desc: 'fixture', useWhen: 'fixture' },
|
|
47
|
-
children: [
|
|
48
|
-
defineLeaf({
|
|
49
|
-
name: 'demo',
|
|
50
|
-
help: {
|
|
51
|
-
name: 'fixture demo',
|
|
52
|
-
summary: 'demo',
|
|
53
|
-
output: [],
|
|
54
|
-
outputKind: 'object',
|
|
55
|
-
effects: ['None. Read-only.'],
|
|
56
|
-
},
|
|
57
|
-
slash: {
|
|
58
|
-
name: 'demo',
|
|
59
|
-
description: 'demo command',
|
|
60
|
-
body: 'run demo',
|
|
61
|
-
},
|
|
62
|
-
run: async () => ({}),
|
|
63
|
-
}),
|
|
64
|
-
],
|
|
65
|
-
}),
|
|
66
|
-
],
|
|
67
|
-
});
|
|
68
|
-
test('provisionExports prunes marker-bearing legacy boot skills and still writes slash commands', () => {
|
|
69
|
-
// cli.ts calls both, in this order, on any non-bare invocation.
|
|
70
|
-
pruneLegacyExports(['node', 'crtr', 'fixture']);
|
|
71
|
-
provisionExports(root, ['node', 'crtr', 'fixture']);
|
|
72
|
-
assert.equal(existsSync(join(home, '.pi', 'agent', 'skills', 'crtr-skills', 'SKILL.md')), false, 'marker-bearing pi crtr-skills bundle should be removed');
|
|
73
|
-
assert.equal(existsSync(join(home, '.claude', 'skills', 'crtr-skills', 'SKILL.md')), true, 'markerless user-owned Claude skill should not be removed');
|
|
74
|
-
assert.match(readFileSync(join(home, '.pi', 'agent', 'prompts', 'demo.md'), 'utf8'), /<!-- crtr-mode-cmd v1 -->/, 'pi slash-command export should still be provisioned');
|
|
75
|
-
assert.match(readFileSync(join(home, '.claude', 'commands', 'demo.md'), 'utf8'), /<!-- crtr-mode-cmd v1 -->/, 'Claude slash-command export should still be provisioned');
|
|
76
|
-
});
|
|
77
|
-
test('bare front-door argv prunes legacy boot skills before pi can start', () => {
|
|
78
|
-
// Bare `crtr`: cli.ts prunes BEFORE the front door boots, and the write pass
|
|
79
|
-
// (which runs only after the front door declines) is a no-op for bare argv.
|
|
80
|
-
pruneLegacyExports(['node', 'crtr']);
|
|
81
|
-
provisionExports(root, ['node', 'crtr']);
|
|
82
|
-
assert.equal(existsSync(join(home, '.pi', 'agent', 'skills', 'crtr-skills', 'SKILL.md')), false, 'bare crtr must remove stale pi crtr-skills before booting pi');
|
|
83
|
-
assert.equal(existsSync(join(home, '.pi', 'agent', 'prompts', 'demo.md')), false, 'bare front-door pruning must not provision slash-command prompts');
|
|
84
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
import { mkdtempSync, writeFileSync } from 'node:fs';
|
|
3
|
-
import { tmpdir } from 'node:os';
|
|
4
|
-
import { join } from 'node:path';
|
|
5
|
-
import test from 'node:test';
|
|
6
|
-
import { checkReviewableFile, extractFilePaths } from '../visible-paths.js';
|
|
7
|
-
test('extractFilePaths finds existing paths, strips positions, and deduplicates', () => {
|
|
8
|
-
const root = mkdtempSync(join(tmpdir(), 'crtr-visible-paths-'));
|
|
9
|
-
const file = join(root, 'example.ts');
|
|
10
|
-
writeFileSync(file, 'export {};\n');
|
|
11
|
-
assert.deepEqual(extractFilePaths([`${file}:12:3 and again ${file}`], root), [file]);
|
|
12
|
-
});
|
|
13
|
-
test('checkReviewableFile rejects non-files and binary text', () => {
|
|
14
|
-
const root = mkdtempSync(join(tmpdir(), 'crtr-reviewable-file-'));
|
|
15
|
-
const binary = join(root, 'binary.dat');
|
|
16
|
-
writeFileSync(binary, Buffer.from([0x61, 0, 0x62]));
|
|
17
|
-
assert.deepEqual(checkReviewableFile(root), { ok: false, reason: 'not a file' });
|
|
18
|
-
assert.deepEqual(checkReviewableFile(binary), { ok: false, reason: 'file is not UTF-8 text' });
|
|
19
|
-
});
|
|
20
|
-
test('checkReviewableFile admits a newline-terminated document at the 5,000-line limit and rejects 5,001', () => {
|
|
21
|
-
const root = mkdtempSync(join(tmpdir(), 'crtr-reviewable-limit-'));
|
|
22
|
-
const atLimit = join(root, 'at-limit.md');
|
|
23
|
-
const overLimit = join(root, 'over-limit.md');
|
|
24
|
-
writeFileSync(atLimit, 'line\n'.repeat(5000));
|
|
25
|
-
writeFileSync(overLimit, 'line\n'.repeat(5001));
|
|
26
|
-
assert.deepEqual(checkReviewableFile(atLimit), { ok: true });
|
|
27
|
-
assert.deepEqual(checkReviewableFile(overLimit), { ok: false, reason: 'file is too long to review (5,000 line limit)' });
|
|
28
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|