@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
|
@@ -11,19 +11,17 @@ import { defineLeaf } from '../../core/command.js';
|
|
|
11
11
|
export const BROKER_LIMIT_OVERRIDE_PRECEDENCE = 'Valid CRTR_WARN_LIVE_BROKERS and CRTR_MAX_LIVE_BROKERS environment overrides take precedence over their corresponding configured limits.';
|
|
12
12
|
export const sysSetupLeaf = defineLeaf({
|
|
13
13
|
name: 'setup',
|
|
14
|
-
description: '
|
|
15
|
-
whenToUse: 'you
|
|
14
|
+
description: 'bootstrap a fresh machine — provider login, companion packages, system dependencies, Exa key',
|
|
15
|
+
whenToUse: 'you are setting up crouter on a machine for the first time and need credentials and installs in place. Use sys settings to change configuration on an installed machine, and sys config set for scriptable edits.',
|
|
16
16
|
help: {
|
|
17
17
|
name: 'sys setup',
|
|
18
|
-
summary: '
|
|
18
|
+
summary: 'run the first-run installer: provider login, companion packages, system dependencies, Exa key',
|
|
19
19
|
inputNote: 'No input parameters.',
|
|
20
20
|
output: [],
|
|
21
21
|
outputKind: 'object',
|
|
22
22
|
effects: [
|
|
23
|
-
'Opens a pi-tui
|
|
24
|
-
'
|
|
25
|
-
'Saves validated keybinding changes atomically in the user config and refreshes crouter-owned tmux bindings without overwriting occupied user keys.',
|
|
26
|
-
`Saves positive-integer broker warning and automatic-revive hard-cap values under user config brokerThresholds; crtrd reads them on its next supervision tick. ${BROKER_LIMIT_OVERRIDE_PRECEDENCE}`,
|
|
23
|
+
'Opens a four-step pi-tui installer. Step one logs in to a model provider (pi\'s real OAuth/API-key flow, same as in-app /login) so a fresh install has credentials before running any node.',
|
|
24
|
+
'The remaining steps collect companion package installs, system dependency installs, and an Exa API key, then confirm them all at once.',
|
|
27
25
|
'Runs the bundled pi CLI to install the selected companion packages, writes EXA_API_KEY to ~/.crouter/exa.key when provided, and prints a summary.',
|
|
28
26
|
'The companion-package list includes crtr marketplace plugins (currently `capture`), checked by default and installed into the user scope when left checked. An unreachable marketplace is reported as skipped rather than failing setup.',
|
|
29
27
|
'On every invocation (best-effort, idempotent), refreshes crouter-owned tmux bindings and registers known nodes\' interaction roots so resolved tickets can call back into the asking node. The inbox popup toggle is a crouter-owned keybinding, editable on the keybindings tab.',
|
package/dist/commands/sys.js
CHANGED
|
@@ -5,6 +5,7 @@ import { daemonBranch } from './sys/daemon.js';
|
|
|
5
5
|
import { sysDoctorLeaf } from './sys/doctor.js';
|
|
6
6
|
import { sysFeedbackLeaf } from './sys/feedback.js';
|
|
7
7
|
import { sysLogsLeaf } from './sys/logs.js';
|
|
8
|
+
import { sysSettingsLeaf } from './sys/settings.js';
|
|
8
9
|
import { sysSetupLeaf } from './sys/setup.js';
|
|
9
10
|
import { supportBranch } from './sys/support.js';
|
|
10
11
|
import { sysSyspromptLeaf } from './sys/sysprompt.js';
|
|
@@ -16,13 +17,13 @@ export function registerSys() {
|
|
|
16
17
|
name: 'sys',
|
|
17
18
|
rootEntry: {
|
|
18
19
|
concept: 'crtr configuration, diagnostics, and self-management',
|
|
19
|
-
desc: 'config, setup, doctor, sysprompt, prompt-review, sync, update, version, feedback, logs, support, daemon',
|
|
20
|
+
desc: 'settings, config, setup, doctor, sysprompt, prompt-review, sync, update, version, feedback, logs, support, daemon',
|
|
20
21
|
useWhen: 'managing the crtr installation, inspecting diagnostics, or operating the crtrd supervisor process',
|
|
21
22
|
},
|
|
22
23
|
help: {
|
|
23
24
|
name: 'sys',
|
|
24
25
|
summary: 'crtr system configuration, settings, diagnostics, and self-management',
|
|
25
26
|
},
|
|
26
|
-
children: [configBranch, sysSetupLeaf, sysDoctorLeaf, sysSyspromptLeaf, promptReviewLeaf, sysFeedbackLeaf, sysLogsLeaf, supportBranch, sysUpdateLeaf, sysVersionLeaf, sysSyncBranch, daemonBranch],
|
|
27
|
+
children: [sysSettingsLeaf, configBranch, sysSetupLeaf, sysDoctorLeaf, sysSyspromptLeaf, promptReviewLeaf, sysFeedbackLeaf, sysLogsLeaf, supportBranch, sysUpdateLeaf, sysVersionLeaf, sysSyncBranch, daemonBranch],
|
|
27
28
|
});
|
|
28
29
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// The shipped Pi extensions execute in broker processes, which must never load
|
|
2
|
+
// canvas.db code. This walks each shipped extension's local static import graph
|
|
3
|
+
// and rejects any reach to the single DB accessor module.
|
|
4
|
+
import { test } from 'node:test';
|
|
5
|
+
import assert from 'node:assert/strict';
|
|
6
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
7
|
+
import { dirname, join, normalize, resolve } from 'node:path';
|
|
8
|
+
import ts from 'typescript';
|
|
9
|
+
import { CANVAS_EXTENSION_NAMES } from '../canvas/extensions.js';
|
|
10
|
+
const SOURCE_ROOT = resolve(process.cwd(), 'src');
|
|
11
|
+
const DB_MODULE = normalize(join(SOURCE_ROOT, 'core/canvas/db.ts'));
|
|
12
|
+
function resolveLocalImport(from, specifier) {
|
|
13
|
+
if (!specifier.startsWith('.'))
|
|
14
|
+
return null;
|
|
15
|
+
const stem = resolve(dirname(from), specifier).replace(/\.js$/, '');
|
|
16
|
+
for (const candidate of [`${stem}.ts`, join(stem, 'index.ts')]) {
|
|
17
|
+
if (existsSync(candidate))
|
|
18
|
+
return normalize(candidate);
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
function importsOf(file) {
|
|
23
|
+
const source = readFileSync(file, 'utf8');
|
|
24
|
+
return ts.preProcessFile(source, true, true).importedFiles
|
|
25
|
+
.map((reference) => resolveLocalImport(file, reference.fileName))
|
|
26
|
+
.filter((target) => target !== null);
|
|
27
|
+
}
|
|
28
|
+
function dbReach(root) {
|
|
29
|
+
const pending = [{ file: root, path: [root] }];
|
|
30
|
+
const seen = new Set([root]);
|
|
31
|
+
while (pending.length > 0) {
|
|
32
|
+
const current = pending.pop();
|
|
33
|
+
if (current.file === DB_MODULE)
|
|
34
|
+
return current.path;
|
|
35
|
+
for (const imported of importsOf(current.file)) {
|
|
36
|
+
if (seen.has(imported))
|
|
37
|
+
continue;
|
|
38
|
+
seen.add(imported);
|
|
39
|
+
pending.push({ file: imported, path: [...current.path, imported] });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
test('every shipped broker extension is transitively canvas.db-free', () => {
|
|
45
|
+
for (const name of CANVAS_EXTENSION_NAMES) {
|
|
46
|
+
const root = join(SOURCE_ROOT, 'pi-extensions', `${name}.ts`);
|
|
47
|
+
const reach = dbReach(root);
|
|
48
|
+
assert.equal(reach, null, `${name} reaches canvas.db through:\n${reach?.join('\n')}`);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
@@ -5,7 +5,9 @@ import { tmpdir } from 'node:os';
|
|
|
5
5
|
import { dirname, join } from 'node:path';
|
|
6
6
|
import { fileURLToPath } from 'node:url';
|
|
7
7
|
import { createAgentSessionFromServices, createAgentSessionServices, SessionManager, VERSION } from '../runtime/broker-sdk.js';
|
|
8
|
-
import { buildBrokerSession
|
|
8
|
+
import { buildBrokerSession } from '../runtime/broker.js';
|
|
9
|
+
import { unregisteredConcreteModel } from '../model-routes.js';
|
|
10
|
+
import { isUnknownModel } from '../runtime/model-selection.js';
|
|
9
11
|
import { resolveProviderCandidates } from '../subscription-state.js';
|
|
10
12
|
const realEngine = { createAgentSessionServices, createAgentSessionFromServices, SessionManager, VERSION };
|
|
11
13
|
const C3_EXT = join(dirname(fileURLToPath(import.meta.url)), 'fixtures', 'c3-custom-provider-ext.ts');
|
|
@@ -89,6 +91,21 @@ function resolve(options) {
|
|
|
89
91
|
})),
|
|
90
92
|
};
|
|
91
93
|
}
|
|
94
|
+
test('an unregistered concrete recipe is a permanent failure, but missing auth is not', () => {
|
|
95
|
+
// The two outcomes route differently at launch: an unregistered model can
|
|
96
|
+
// never boot and must fault, while a registered model with no configured auth
|
|
97
|
+
// is recoverable once credentials arrive.
|
|
98
|
+
const known = { provider: 'openai-codex', id: 'o-strong' };
|
|
99
|
+
const registry = {
|
|
100
|
+
find: (providerId, modelId) => providerId === known.provider && modelId === known.id ? known : undefined,
|
|
101
|
+
hasConfiguredAuth: () => false,
|
|
102
|
+
};
|
|
103
|
+
const unknown = unregisteredConcreteModel({ kind: 'concrete', spec: 'openai-codex/fast' }, registry, { profileId: null });
|
|
104
|
+
assert.equal(unknown?.reason, 'unregistered');
|
|
105
|
+
assert.equal(unknown?.candidate.providerId, 'openai-codex');
|
|
106
|
+
assert.equal(unknown?.candidate.modelId, 'fast');
|
|
107
|
+
assert.equal(unregisteredConcreteModel({ kind: 'concrete', spec: 'openai-codex/o-strong' }, registry, { profileId: null }), undefined, 'a registered model remains recoverable even when it has no configured auth');
|
|
108
|
+
});
|
|
92
109
|
test('launch candidate resolver keeps a healthy explicit provider pin ahead of authenticated alternatives', () => {
|
|
93
110
|
const result = resolve({ requested: 'anthropic/requested', available: [alternative, requested], modelProviderPinned: true });
|
|
94
111
|
assert.equal(result.model, requested);
|
|
@@ -102,7 +119,7 @@ test('launch candidate resolver selects a non-managed candidate as automatic fal
|
|
|
102
119
|
{ spec: 'missing/missing', reason: 'not registered' },
|
|
103
120
|
]);
|
|
104
121
|
});
|
|
105
|
-
test('broker launch
|
|
122
|
+
test('broker launch rejects an unregistered concrete model even when a non-managed provider is available', async () => {
|
|
106
123
|
const cwd = mkdtempSync(join(tmpdir(), 'crtr-launch-candidate-'));
|
|
107
124
|
try {
|
|
108
125
|
const engine = {
|
|
@@ -119,13 +136,7 @@ test('broker launch keeps an unregistered concrete model pinned even when a non-
|
|
|
119
136
|
return { ...services, modelRuntime };
|
|
120
137
|
},
|
|
121
138
|
};
|
|
122
|
-
|
|
123
|
-
try {
|
|
124
|
-
assert.equal(`${session.model?.provider}/${session.model?.id}`, 'unknown/unknown');
|
|
125
|
-
}
|
|
126
|
-
finally {
|
|
127
|
-
session.dispose();
|
|
128
|
-
}
|
|
139
|
+
await assert.rejects(buildBrokerSession(engine, { cwd, extensionPaths: [C3_EXT], model: 'missing/missing' }), /FATAL: model 'missing\/missing' is not registered/);
|
|
129
140
|
}
|
|
130
141
|
finally {
|
|
131
142
|
rmSync(cwd, { recursive: true, force: true });
|
|
@@ -62,7 +62,7 @@ test('preflightBrokerLaunch rejects missing or duplicate mandatory canvas hooks
|
|
|
62
62
|
const missing = { argv: ['hello'], env: { CRTR_BROKER_ENGINE: FAKE_ENGINE } };
|
|
63
63
|
assert.throws(() => preflightBrokerLaunch('preflight-missing-hook', missing, '/tmp/work'), /canvas extension.*found 0/i);
|
|
64
64
|
const duplicate = { argv: [...validArgv(), '-e', CANVAS_EXTENSIONS[0], 'hello'], env: { CRTR_BROKER_ENGINE: FAKE_ENGINE } };
|
|
65
|
-
assert.throws(() => preflightBrokerLaunch('preflight-duplicate-hook', duplicate, '/tmp/work'), /canvas extension
|
|
65
|
+
assert.throws(() => preflightBrokerLaunch('preflight-duplicate-hook', duplicate, '/tmp/work'), /duplicate mandatory canvas extension basename canvas-inbox-watcher/i);
|
|
66
66
|
});
|
|
67
67
|
test('preflightBrokerLaunch validates the exact broker engine env passed to the detached broker', () => {
|
|
68
68
|
const nodeId = 'preflight-empty-engine';
|
|
@@ -13,8 +13,11 @@ import registerCanvasInboxWatcher from '../../pi-extensions/canvas-inbox-watcher
|
|
|
13
13
|
import { appendInbox, readCursor } from '../feed/inbox.js';
|
|
14
14
|
import { drainBearings } from '../runtime/kickoff.js';
|
|
15
15
|
import { appendSituationalContext } from '../runtime/situational-context.js';
|
|
16
|
-
import { createNode, getNode, setIntent } from '../canvas/canvas.js';
|
|
16
|
+
import { createNode, getNode, recordPid, setIntent } from '../canvas/canvas.js';
|
|
17
17
|
import { closeDb } from '../canvas/db.js';
|
|
18
|
+
import { createApiServer } from '../../daemon/api/server.js';
|
|
19
|
+
import { CrtrClient } from '../../api/client.js';
|
|
20
|
+
import { ApiError } from '../../api/errors.js';
|
|
18
21
|
// Drive the watcher's injectable cadence seam (CRTR_WATCHER_TICK_MS /
|
|
19
22
|
// CRTR_WATCHER_DEBOUNCE_MS) at a fast tempo so the test sleeps milliseconds, not
|
|
20
23
|
// seconds. SETTLE_MS still allows a resolve+seed tick, a read tick, and the
|
|
@@ -26,13 +29,15 @@ let origHome;
|
|
|
26
29
|
let origNode;
|
|
27
30
|
const homes = [];
|
|
28
31
|
const disposers = [];
|
|
32
|
+
let server;
|
|
29
33
|
/** Point CRTR_HOME at a fresh temp canvas root and bind CRTR_NODE_ID. */
|
|
30
34
|
function freshNode(nodeId) {
|
|
31
|
-
const home = join(tmpdir(), `crtr-
|
|
35
|
+
const home = join(tmpdir(), `crtr-w-${Math.random().toString(36).slice(2, 8)}`);
|
|
32
36
|
mkdirSync(home, { recursive: true });
|
|
33
37
|
homes.push(home);
|
|
34
38
|
process.env['CRTR_HOME'] = home;
|
|
35
39
|
process.env['CRTR_NODE_ID'] = nodeId;
|
|
40
|
+
server = createApiServer();
|
|
36
41
|
}
|
|
37
42
|
function makeFakePi() {
|
|
38
43
|
const handlers = {};
|
|
@@ -42,7 +47,7 @@ function makeFakePi() {
|
|
|
42
47
|
on(e, h) { handlers[e] = h; },
|
|
43
48
|
sendUserMessage(content, options) { this.injected.push({ content, deliverAs: options?.deliverAs }); },
|
|
44
49
|
sendMessage(message) { this.sentMessages.push(message); },
|
|
45
|
-
fire(e, ev, ctx) { handlers[e]?.(ev, ctx); },
|
|
50
|
+
async fire(e, ev, ctx) { await handlers[e]?.(ev, ctx); },
|
|
46
51
|
};
|
|
47
52
|
}
|
|
48
53
|
// Fire agent_settled — the authoritative durable-commit boundary in the
|
|
@@ -51,9 +56,9 @@ function makeFakePi() {
|
|
|
51
56
|
// unconditionally regardless of queue state, so `pending: true` exercises that
|
|
52
57
|
// the commit still lands rather than being vetoed. See `shutdown()` below for
|
|
53
58
|
// the one boundary where `hasPendingMessages()` still gates a commit.
|
|
54
|
-
function settle(pi, opts = {}) {
|
|
59
|
+
async function settle(pi, opts = {}) {
|
|
55
60
|
const pending = opts.pending === true;
|
|
56
|
-
pi.fire('agent_settled', { type: 'agent_settled' }, { isIdle: () => true, hasPendingMessages: () => pending });
|
|
61
|
+
await pi.fire('agent_settled', { type: 'agent_settled' }, { isIdle: () => true, hasPendingMessages: () => pending });
|
|
57
62
|
}
|
|
58
63
|
// Fire session_shutdown — pi's graceful-teardown safety net for a settle that
|
|
59
64
|
// never fired before exit. The real handler takes NO event ctx of its own; it
|
|
@@ -65,19 +70,37 @@ function settle(pi, opts = {}) {
|
|
|
65
70
|
// itself. `pending` maps to pi's `hasPendingMessages()`: true exercises the
|
|
66
71
|
// retained HOLD (an unconsumed queued send would die with the process, so the
|
|
67
72
|
// commit is declined); false (default) commits normally.
|
|
68
|
-
function shutdown(pi, opts = {}) {
|
|
73
|
+
async function shutdown(pi, opts = {}) {
|
|
69
74
|
const pending = opts.pending === true;
|
|
70
|
-
pi.fire('agent_end', { type: 'agent_end', messages: [] }, { isIdle: () => false, hasPendingMessages: () => pending });
|
|
71
|
-
pi.fire('session_shutdown', {}, undefined);
|
|
75
|
+
await pi.fire('agent_end', { type: 'agent_end', messages: [] }, { isIdle: () => false, hasPendingMessages: () => pending });
|
|
76
|
+
await pi.fire('session_shutdown', {}, undefined);
|
|
72
77
|
}
|
|
73
78
|
const wait = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
74
79
|
// Register the watcher, then fire session_start — the real lifecycle gate
|
|
75
80
|
// that arms its poll interval and initial tick (see canvas-inbox-watcher.ts).
|
|
76
81
|
// registerCanvasInboxWatcher() alone only wires up handlers; without this the
|
|
77
82
|
// watcher never polls or sends anything.
|
|
83
|
+
function ensureWatcherNode() {
|
|
84
|
+
const nodeId = process.env['CRTR_NODE_ID'];
|
|
85
|
+
if (nodeId === undefined || getNode(nodeId) !== null)
|
|
86
|
+
return;
|
|
87
|
+
createNode({
|
|
88
|
+
node_id: nodeId,
|
|
89
|
+
name: nodeId,
|
|
90
|
+
created: new Date().toISOString(),
|
|
91
|
+
cwd: '/tmp',
|
|
92
|
+
kind: 'general',
|
|
93
|
+
mode: 'base',
|
|
94
|
+
lifecycle: 'terminal',
|
|
95
|
+
status: 'active',
|
|
96
|
+
});
|
|
97
|
+
recordPid(nodeId, process.pid);
|
|
98
|
+
}
|
|
78
99
|
function registerWatcher(pi) {
|
|
100
|
+
ensureWatcherNode();
|
|
101
|
+
recordPid(process.env['CRTR_NODE_ID'], process.pid);
|
|
79
102
|
const dispose = registerCanvasInboxWatcher(pi);
|
|
80
|
-
pi.fire('session_start', { type: 'session_start' }, undefined);
|
|
103
|
+
void pi.fire('session_start', { type: 'session_start' }, undefined);
|
|
81
104
|
return dispose;
|
|
82
105
|
}
|
|
83
106
|
let origTick;
|
|
@@ -90,9 +113,12 @@ before(() => {
|
|
|
90
113
|
process.env['CRTR_WATCHER_TICK_MS'] = String(TICK_MS);
|
|
91
114
|
process.env['CRTR_WATCHER_DEBOUNCE_MS'] = String(DEBOUNCE_MS);
|
|
92
115
|
});
|
|
93
|
-
afterEach(() => {
|
|
116
|
+
afterEach(async () => {
|
|
94
117
|
while (disposers.length > 0)
|
|
95
118
|
disposers.pop()();
|
|
119
|
+
await server?.close();
|
|
120
|
+
server = undefined;
|
|
121
|
+
closeDb();
|
|
96
122
|
});
|
|
97
123
|
after(() => {
|
|
98
124
|
if (origHome === undefined)
|
|
@@ -119,7 +145,7 @@ after(() => {
|
|
|
119
145
|
}
|
|
120
146
|
});
|
|
121
147
|
describe('canvas inbox watcher — hold + idle delivery', () => {
|
|
122
|
-
test('refresh-yield in flight:
|
|
148
|
+
test('refresh-yield in flight: a handoff remains uncommitted for the replacement conversation', async () => {
|
|
123
149
|
freshNode('node-refresh');
|
|
124
150
|
closeDb(); // rebind the canvas db to this test's fresh home
|
|
125
151
|
const meta = {
|
|
@@ -135,12 +161,66 @@ describe('canvas inbox watcher — hold + idle delivery', () => {
|
|
|
135
161
|
await wait(TICK_MS + 100);
|
|
136
162
|
appendInbox('node-refresh', { from: 'child-x', tier: 'urgent', kind: 'final', label: 'done' });
|
|
137
163
|
await wait(SETTLE_MS);
|
|
138
|
-
assert.equal(pi.injected.length,
|
|
139
|
-
// The
|
|
140
|
-
//
|
|
164
|
+
assert.equal(pi.injected.length, 1, 'the live broker receives the handoff before its durable cursor boundary');
|
|
165
|
+
// The cursor operation decides the refresh hold at its durable commit
|
|
166
|
+
// boundary; clearing intent does not manufacture a second handoff.
|
|
141
167
|
setIntent('node-refresh', null);
|
|
142
168
|
await wait(SETTLE_MS);
|
|
143
|
-
assert.equal(pi.injected.length, 1, 'the
|
|
169
|
+
assert.equal(pi.injected.length, 1, 'the same handoff is not delivered twice');
|
|
170
|
+
});
|
|
171
|
+
test('replacement session binding holds a late old-broker cursor commit', async () => {
|
|
172
|
+
freshNode('node-refresh-replacement');
|
|
173
|
+
closeDb();
|
|
174
|
+
const meta = {
|
|
175
|
+
node_id: 'node-refresh-replacement', name: 'r', created: new Date().toISOString(),
|
|
176
|
+
cwd: '/tmp', kind: 'general', mode: 'base', lifecycle: 'resident',
|
|
177
|
+
status: 'active', intent: 'refresh',
|
|
178
|
+
};
|
|
179
|
+
createNode(meta);
|
|
180
|
+
const entry = appendInbox(meta.node_id, { from: 'child-x', tier: 'normal', kind: 'update', label: 'handoff before replacement' });
|
|
181
|
+
recordPid(meta.node_id, 101);
|
|
182
|
+
const client = CrtrClient.forLocalSocket({ autostart: false });
|
|
183
|
+
// The replacement binds first, consuming refresh and recording its own
|
|
184
|
+
// process generation. The old broker's delayed request must still hold.
|
|
185
|
+
await client.bindBrokerSession(meta.node_id, {
|
|
186
|
+
piSessionId: 'replacement-session', sessionFile: '/tmp/replacement.jsonl',
|
|
187
|
+
pid: 202, reason: 'startup', reviewBoundaryIds: [],
|
|
188
|
+
});
|
|
189
|
+
const oldResult = await client.advanceBrokerInboxCursor(meta.node_id, {
|
|
190
|
+
throughEntryId: entry.entry_id, brokerPid: 101,
|
|
191
|
+
});
|
|
192
|
+
assert.deepEqual(oldResult, { action: 'hold_refresh' });
|
|
193
|
+
assert.equal(readCursor(meta.node_id), undefined, 'the stale broker cannot consume the replacement replay');
|
|
194
|
+
const replacementResult = await client.advanceBrokerInboxCursor(meta.node_id, {
|
|
195
|
+
throughEntryId: entry.entry_id, brokerPid: 202,
|
|
196
|
+
});
|
|
197
|
+
assert.deepEqual(replacementResult, { action: 'advanced' });
|
|
198
|
+
assert.equal(readCursor(meta.node_id), entry.entry_id, 'only the replacement broker advances the durable cursor');
|
|
199
|
+
});
|
|
200
|
+
test('cursor rejects a nonexistent or backward physical entry', async () => {
|
|
201
|
+
freshNode('node-cursor-physical-boundary');
|
|
202
|
+
closeDb();
|
|
203
|
+
const meta = {
|
|
204
|
+
node_id: 'node-cursor-physical-boundary', name: 'r', created: new Date().toISOString(),
|
|
205
|
+
cwd: '/tmp', kind: 'general', mode: 'base', lifecycle: 'resident', status: 'active',
|
|
206
|
+
};
|
|
207
|
+
createNode(meta);
|
|
208
|
+
recordPid(meta.node_id, 303);
|
|
209
|
+
const first = appendInbox(meta.node_id, { from: 'child-x', tier: 'normal', kind: 'update', label: 'first' });
|
|
210
|
+
const second = appendInbox(meta.node_id, { from: 'child-x', tier: 'normal', kind: 'update', label: 'second' });
|
|
211
|
+
const client = CrtrClient.forLocalSocket({ autostart: false });
|
|
212
|
+
const rejected = (request) => client
|
|
213
|
+
.advanceBrokerInboxCursor(meta.node_id, request)
|
|
214
|
+
.then(() => assert.fail('cursor request should fail'))
|
|
215
|
+
.catch((error) => {
|
|
216
|
+
assert.ok(error instanceof ApiError);
|
|
217
|
+
assert.equal(error.status, 400);
|
|
218
|
+
});
|
|
219
|
+
await rejected({ throughEntryId: 'f'.repeat(32), brokerPid: 303 });
|
|
220
|
+
assert.equal(readCursor(meta.node_id), undefined, 'a well-shaped unknown id cannot poison the cursor');
|
|
221
|
+
await client.advanceBrokerInboxCursor(meta.node_id, { throughEntryId: second.entry_id, brokerPid: 303 });
|
|
222
|
+
await rejected({ throughEntryId: first.entry_id, brokerPid: 303 });
|
|
223
|
+
assert.equal(readCursor(meta.node_id), second.entry_id, 'a late commit cannot move the durable cursor backward');
|
|
144
224
|
});
|
|
145
225
|
test('refresh-yield replays a handoff that reached the discarded conversation', async () => {
|
|
146
226
|
freshNode('node-refresh-handoff');
|
|
@@ -161,7 +241,7 @@ describe('canvas inbox watcher — hold + idle delivery', () => {
|
|
|
161
241
|
// Yield discards that conversation before it can act on the queued handoff.
|
|
162
242
|
// Its settle must leave the entry durable for the fresh revive's kickoff.
|
|
163
243
|
setIntent(meta.node_id, 'refresh');
|
|
164
|
-
settle(pi);
|
|
244
|
+
await settle(pi);
|
|
165
245
|
assert.equal(readCursor(meta.node_id), undefined, 'the discarded conversation cannot commit its inbox handoff');
|
|
166
246
|
const bearings = drainBearings(getNode(meta.node_id));
|
|
167
247
|
assert.match(bearings.unreadDigest ?? '', /handoff at yield/, 'the fresh revive receives the uncommitted handoff');
|
|
@@ -205,6 +285,7 @@ describe('canvas inbox watcher — action-gated startup (session_start arm)', ()
|
|
|
205
285
|
// Registration alone (the extension factory, before Pi has bound actions)
|
|
206
286
|
// must be side-effect-free: no timer armed, no tick run, no action attempted
|
|
207
287
|
// — even across several tick+debounce windows.
|
|
288
|
+
ensureWatcherNode();
|
|
208
289
|
disposers.push(registerCanvasInboxWatcher(pi));
|
|
209
290
|
await wait(TICK_MS * 5 + DEBOUNCE_MS + 50);
|
|
210
291
|
assert.equal(sendAttempts, 0, 'no action call is attempted before session_start arms the watcher');
|
|
@@ -218,7 +299,7 @@ describe('canvas inbox watcher — action-gated startup (session_start arm)', ()
|
|
|
218
299
|
assert.equal(sendAttempts, 1, 'exactly one action attempt once session_start arms the watcher');
|
|
219
300
|
assert.equal(pi.injected.length, 1, 'exactly one handoff once actions are bound');
|
|
220
301
|
assert.equal(readCursor('node-action-gate'), undefined, 'still uncommitted until agent_settled');
|
|
221
|
-
settle(pi);
|
|
302
|
+
await settle(pi);
|
|
222
303
|
assert.equal(readCursor('node-action-gate'), entry.entry_id, 'cursor committed at agent_settled');
|
|
223
304
|
// A repeated session_start (e.g. a resume) must not re-arm a second
|
|
224
305
|
// interval or re-run the initial tick — no duplicate delivery.
|
|
@@ -302,7 +383,7 @@ describe('canvas inbox watcher — durable cursor (at-least-once)', () => {
|
|
|
302
383
|
assert.equal(readCursor('node-cursor-committed'), undefined, 'not yet committed before the settle');
|
|
303
384
|
// The turn settles with pi's queue drained (the followUp was consumed) —
|
|
304
385
|
// THAT commits the cursor.
|
|
305
|
-
settle(pi1);
|
|
386
|
+
await settle(pi1);
|
|
306
387
|
assert.equal(readCursor('node-cursor-committed'), entry.entry_id, 'cursor committed to disk at agent_settled');
|
|
307
388
|
const pi2 = makeFakePi();
|
|
308
389
|
disposers.push(registerWatcher(pi2));
|
|
@@ -323,7 +404,7 @@ describe('canvas inbox watcher — durable cursor (at-least-once)', () => {
|
|
|
323
404
|
// of acceptance — the cursor stays put until the turn settles. (One rule: no
|
|
324
405
|
// immediate idle-path commit.)
|
|
325
406
|
assert.equal(readCursor('node-cursor-idle'), undefined, 'idle send does not commit on the fire-and-forget return');
|
|
326
|
-
settle(pi);
|
|
407
|
+
await settle(pi);
|
|
327
408
|
assert.equal(readCursor('node-cursor-idle'), entry.entry_id, 'idle-path delivery commits at the turn it started settling');
|
|
328
409
|
});
|
|
329
410
|
test('synchronous send throw then agent_settled: durable cursor NOT advanced past the re-buffered entry, fresh watcher re-delivers', async () => {
|
|
@@ -339,7 +420,7 @@ describe('canvas inbox watcher — durable cursor (at-least-once)', () => {
|
|
|
339
420
|
await wait(SETTLE_MS);
|
|
340
421
|
assert.equal(pi1.injected.length, 0, 'the failing send delivered nothing');
|
|
341
422
|
// agent_settled must NOT commit past the still-re-buffered (never-handed-off) entry.
|
|
342
|
-
settle(pi1);
|
|
423
|
+
await settle(pi1);
|
|
343
424
|
assert.equal(readCursor('node-cursor-failsend'), undefined, 'durable cursor not advanced past a re-buffered, never-delivered entry');
|
|
344
425
|
const pi2 = makeFakePi();
|
|
345
426
|
disposers.push(registerWatcher(pi2));
|
|
@@ -363,7 +444,7 @@ describe('canvas inbox watcher — durable cursor (at-least-once)', () => {
|
|
|
363
444
|
// The abort-generated agent_end/settle must not commit the pending critical
|
|
364
445
|
// entry (it is re-buffered, never handed off).
|
|
365
446
|
pi1.fire('agent_end', { type: 'agent_end', messages: [] }, { isIdle: () => true });
|
|
366
|
-
settle(pi1);
|
|
447
|
+
await settle(pi1);
|
|
367
448
|
assert.equal(readCursor('node-cursor-critical'), undefined, 'abort-generated settle does not commit the pending critical entry before its retry');
|
|
368
449
|
const pi2 = makeFakePi();
|
|
369
450
|
disposers.push(registerWatcher(pi2));
|
|
@@ -390,7 +471,7 @@ describe('canvas inbox watcher — durable cursor (at-least-once)', () => {
|
|
|
390
471
|
await wait(70); // B read into the buffer but < 200ms debounce → not yet flushed
|
|
391
472
|
// A's turn settles while B is still debouncing in the buffer. The commit must
|
|
392
473
|
// clamp below the still-buffered B and land on A only.
|
|
393
|
-
settle(pi1);
|
|
474
|
+
await settle(pi1);
|
|
394
475
|
assert.equal(readCursor('node-cursor-batchB'), a.entry_id, 'commit lands on handed-off batch A');
|
|
395
476
|
assert.notEqual(readCursor('node-cursor-batchB'), b.entry_id, 'commit does not cross the still-buffered batch B');
|
|
396
477
|
const pi2 = makeFakePi();
|
|
@@ -423,7 +504,7 @@ describe('canvas inbox watcher — durable cursor (at-least-once)', () => {
|
|
|
423
504
|
assert.equal(readCursor('node-cursor-failhold'), undefined, 'a failure agent_end does not commit');
|
|
424
505
|
// The settle commits even though the context reports pending sends —
|
|
425
506
|
// agent_settled no longer declines on hasPendingMessages().
|
|
426
|
-
settle(pi1, { pending: true });
|
|
507
|
+
await settle(pi1, { pending: true });
|
|
427
508
|
assert.equal(readCursor('node-cursor-failhold'), entry.entry_id, 'agent_settled commits unconditionally, even when hasPendingMessages() reports pending');
|
|
428
509
|
const pi2 = makeFakePi();
|
|
429
510
|
disposers.push(registerWatcher(pi2));
|
|
@@ -452,7 +533,7 @@ describe('canvas inbox watcher — durable cursor (at-least-once)', () => {
|
|
|
452
533
|
await wait(SETTLE_MS);
|
|
453
534
|
assert.equal(pi.injected.length, 1, 'the active conversation received the handoff before refresh');
|
|
454
535
|
setIntent(meta.node_id, 'refresh');
|
|
455
|
-
shutdown(pi, { pending: false });
|
|
536
|
+
await shutdown(pi, { pending: false });
|
|
456
537
|
assert.equal(readCursor(meta.node_id), undefined, 'a refresh keeps the shutdown handoff uncommitted for replay');
|
|
457
538
|
});
|
|
458
539
|
test('session_shutdown still holds while hasPendingMessages() reports pending (no agent_settled fired)', async () => {
|
|
@@ -466,7 +547,7 @@ describe('canvas inbox watcher — durable cursor (at-least-once)', () => {
|
|
|
466
547
|
assert.equal(pi1.injected.length, 1, 'delivered mid-turn as a followUp');
|
|
467
548
|
// session_shutdown fires with no prior agent_settled, and the context
|
|
468
549
|
// reports an unconsumed queued send — the hold declines the commit.
|
|
469
|
-
shutdown(pi1, { pending: true });
|
|
550
|
+
await shutdown(pi1, { pending: true });
|
|
470
551
|
assert.equal(readCursor('node-cursor-shutdownhold'), undefined, 'session_shutdown declines to commit while pi reports pending sends');
|
|
471
552
|
dispose();
|
|
472
553
|
// A fresh watcher re-reads and re-delivers, then a drained settle commits.
|
|
@@ -475,7 +556,7 @@ describe('canvas inbox watcher — durable cursor (at-least-once)', () => {
|
|
|
475
556
|
await wait(SETTLE_MS);
|
|
476
557
|
assert.equal(pi2.injected.length, 1, 'a fresh watcher re-reads and re-delivers the never-committed entry');
|
|
477
558
|
assert.match(pi2.injected[0].content, /still queued at shutdown/);
|
|
478
|
-
settle(pi2);
|
|
559
|
+
await settle(pi2);
|
|
479
560
|
assert.equal(readCursor('node-cursor-shutdownhold'), entry.entry_id, 'the redelivered entry commits once the fresh watcher settles cleanly');
|
|
480
561
|
});
|
|
481
562
|
// Situational custom sends do not enter pi's user steer/followUp queue, so
|
|
@@ -496,7 +577,7 @@ describe('canvas inbox watcher — durable cursor (at-least-once)', () => {
|
|
|
496
577
|
await wait(SETTLE_MS);
|
|
497
578
|
assert.equal(pi1.sentMessages.length, 1, 'the hidden custom message was sent');
|
|
498
579
|
assert.equal(readCursor('node-cursor-situational'), undefined, 'not committed before the settle');
|
|
499
|
-
settle(pi1);
|
|
580
|
+
await settle(pi1);
|
|
500
581
|
assert.equal(readCursor('node-cursor-situational'), entry.entry_id, 'the situational handoff commits at the drained settle');
|
|
501
582
|
});
|
|
502
583
|
});
|
|
@@ -109,6 +109,20 @@ test('coalesce inlines short report bodies with a trailing artifact pointer and
|
|
|
109
109
|
assert.doesNotMatch(spilled, /Dereference a ref with/);
|
|
110
110
|
closeDb();
|
|
111
111
|
});
|
|
112
|
+
test('a human message coalesces verbatim — a conversation turn, not a digest', () => {
|
|
113
|
+
// A human typing directly into a node's box is a CONVERSATION TURN, so the
|
|
114
|
+
// dormant wake path must read identically to the live path: no "From … — N
|
|
115
|
+
// updates" header, no `[message]` kind tag. Every other sender keeps framing.
|
|
116
|
+
const body = 'first line\n\nsecond paragraph';
|
|
117
|
+
const human = coalesce([
|
|
118
|
+
finalizeInboxEntry({ from: 'human', tier: 'normal', kind: 'message', label: 'first line', data: { body } }),
|
|
119
|
+
]);
|
|
120
|
+
assert.equal(human, body);
|
|
121
|
+
const agent = coalesce([
|
|
122
|
+
finalizeInboxEntry({ from: 'mqifzplr-0753bde3', tier: 'normal', kind: 'message', label: 'go', data: { body: 'go' } }),
|
|
123
|
+
]);
|
|
124
|
+
assert.match(agent, /^From mqifzplr-0753bde3 — 1 update:/);
|
|
125
|
+
});
|
|
112
126
|
let origTick;
|
|
113
127
|
let origDebounce;
|
|
114
128
|
before(() => {
|
|
@@ -3,9 +3,9 @@ import assert from 'node:assert/strict';
|
|
|
3
3
|
import { mkdtempSync, rmSync, existsSync, readFileSync, writeFileSync, statSync } from 'node:fs';
|
|
4
4
|
import { tmpdir } from 'node:os';
|
|
5
5
|
import { join } from 'node:path';
|
|
6
|
-
import { createNode, getNode, getRow, updateNode, setStatus,
|
|
6
|
+
import { createNode, getNode, getRow, updateNode, setStatus, subscribe, unsubscribe, setSubscriptionActive, recordSpawn, subscribersOf, subscriptionsOf, view, hasActiveLiveSubscription, rebuildIndex, } from '../canvas/canvas.js';
|
|
7
7
|
import { closeDb } from '../canvas/db.js';
|
|
8
|
-
import {
|
|
8
|
+
import { nodeMetaPath } from '../canvas/paths.js';
|
|
9
9
|
let home;
|
|
10
10
|
function node(id, over = {}) {
|
|
11
11
|
return {
|
|
@@ -34,32 +34,11 @@ after(() => {
|
|
|
34
34
|
rmSync(home, { recursive: true, force: true });
|
|
35
35
|
delete process.env['CRTR_HOME'];
|
|
36
36
|
});
|
|
37
|
-
test('createNode scaffolds dirs, writes meta, indexes the row', () => {
|
|
38
|
-
createNode(node('a'));
|
|
39
|
-
assert.ok(existsSync(contextDir('a')));
|
|
40
|
-
assert.ok(existsSync(reportsDir('a')));
|
|
41
|
-
assert.ok(existsSync(jobDir('a')));
|
|
42
|
-
assert.ok(existsSync(nodeMetaPath('a')));
|
|
43
|
-
const meta = getNode('a');
|
|
44
|
-
assert.equal(meta?.node_id, 'a');
|
|
45
|
-
assert.equal(meta?.kind, 'general');
|
|
46
|
-
const row = getRow('a');
|
|
47
|
-
assert.equal(row?.node_id, 'a');
|
|
48
|
-
assert.equal(row?.status, 'active');
|
|
49
|
-
});
|
|
50
37
|
test('meta.json is the source of truth on disk', () => {
|
|
51
38
|
createNode(node('a', { kind: 'developer' }));
|
|
52
39
|
const raw = JSON.parse(readFileSync(nodeMetaPath('a'), 'utf8'));
|
|
53
40
|
assert.equal(raw.kind, 'developer');
|
|
54
41
|
});
|
|
55
|
-
test('updateNode merges meta and re-indexes the row', () => {
|
|
56
|
-
createNode(node('a'));
|
|
57
|
-
updateNode('a', { mode: 'orchestrator', lifecycle: 'resident' });
|
|
58
|
-
assert.equal(getNode('a')?.mode, 'orchestrator');
|
|
59
|
-
assert.equal(getRow('a')?.lifecycle, 'resident');
|
|
60
|
-
// unspecified fields preserved
|
|
61
|
-
assert.equal(getNode('a')?.kind, 'general');
|
|
62
|
-
});
|
|
63
42
|
// Regression: cycle_pending is an IDENTITY field (meta.json-only, no db
|
|
64
43
|
// column — like pi_session_file) written by reviveNode/canvas-stophook and
|
|
65
44
|
// read back by reviveNode's locked launch arbitration. writeMeta only persists
|
|
@@ -73,19 +52,6 @@ test('cycle_pending survives the updateNode/getNode meta.json round-trip', () =>
|
|
|
73
52
|
updateNode('a', { cycle_pending: false });
|
|
74
53
|
assert.equal(getNode('a')?.cycle_pending, false);
|
|
75
54
|
});
|
|
76
|
-
test('setStatus updates both meta and row', () => {
|
|
77
|
-
createNode(node('a'));
|
|
78
|
-
setStatus('a', 'done');
|
|
79
|
-
assert.equal(getNode('a')?.status, 'done');
|
|
80
|
-
assert.equal(getRow('a')?.status, 'done');
|
|
81
|
-
});
|
|
82
|
-
test('listNodes filters by status', () => {
|
|
83
|
-
createNode(node('a', { status: 'active' }));
|
|
84
|
-
createNode(node('b', { status: 'idle' }));
|
|
85
|
-
createNode(node('c', { status: 'done' }));
|
|
86
|
-
assert.equal(listNodes().length, 3);
|
|
87
|
-
assert.deepEqual(listNodes({ status: ['active', 'idle'] }).map((n) => n.node_id).sort(), ['a', 'b']);
|
|
88
|
-
});
|
|
89
55
|
test('subscription spine: subscribersOf / subscriptionsOf', () => {
|
|
90
56
|
createNode(node('mgr'));
|
|
91
57
|
createNode(node('w1'));
|
|
@@ -3,7 +3,7 @@ import assert from 'node:assert/strict';
|
|
|
3
3
|
import { mkdtempSync, rmSync, mkdirSync, writeFileSync, existsSync, readdirSync } from 'node:fs';
|
|
4
4
|
import { tmpdir } from 'node:os';
|
|
5
5
|
import { join } from 'node:path';
|
|
6
|
-
import { createNode, getNode, subscribe } from '../canvas/canvas.js';
|
|
6
|
+
import { createNode, getNode, subscribe, subscriptionsOf } from '../canvas/canvas.js';
|
|
7
7
|
import { nodeDir } from '../canvas/paths.js';
|
|
8
8
|
import { closeDb } from '../canvas/db.js';
|
|
9
9
|
import { closeNode } from '../runtime/close.js';
|
|
@@ -69,7 +69,7 @@ test('closes the root and its exclusive descendants; spares a shared node', () =
|
|
|
69
69
|
// Closed nodes → canceled + intent cleared. (Broker-host cut: nodes carry NO
|
|
70
70
|
// engine pane/window/session — the viewer lives in the focuses table and is
|
|
71
71
|
// torn down asynchronously when the broker socket drops, so close no longer
|
|
72
|
-
// nulls a meta `pane`; viewer teardown is covered in the
|
|
72
|
+
// nulls a meta `pane`; viewer teardown is covered in the compiled-seam broker
|
|
73
73
|
// lifecycle suite.)
|
|
74
74
|
for (const id of ['N', 'A', 'C']) {
|
|
75
75
|
const m = getNode(id);
|
|
@@ -80,6 +80,17 @@ test('closes the root and its exclusive descendants; spares a shared node', () =
|
|
|
80
80
|
assert.equal(getNode('B').status, 'active');
|
|
81
81
|
assert.equal(getNode('M').status, 'active');
|
|
82
82
|
});
|
|
83
|
+
test('closing a middle node preserves its subscription edge and child provenance', () => {
|
|
84
|
+
createNode(node('A'));
|
|
85
|
+
createNode(node('B', { parent: 'A' }));
|
|
86
|
+
createNode(node('C', { parent: 'B' }));
|
|
87
|
+
spawnEdge('A', 'B');
|
|
88
|
+
spawnEdge('B', 'C');
|
|
89
|
+
closeNode('B');
|
|
90
|
+
assert.deepEqual(subscriptionsOf('B').map(({ node_id, active }) => ({ node_id, active })), [{ node_id: 'C', active: true }]);
|
|
91
|
+
assert.equal(getNode('B')?.parent, 'A');
|
|
92
|
+
assert.equal(getNode('C')?.parent, 'B');
|
|
93
|
+
});
|
|
83
94
|
test('kill order is leaves-first, root-last ("cascades up")', () => {
|
|
84
95
|
for (const id of ['N', 'A', 'C'])
|
|
85
96
|
createNode(node(id));
|
|
@@ -249,6 +260,6 @@ test('reaping an empty child still notifies a surviving external manager', () =>
|
|
|
249
260
|
// routes through the synchronous tearDownNode — it sends the broker `shutdown`
|
|
250
261
|
// frame (headlessBrokerHost.teardown) and the viewer pane/focus row close on
|
|
251
262
|
// their own when the broker socket drops (GC'd by the daemon + focusOf prune).
|
|
252
|
-
// That async viewer teardown is covered by the
|
|
263
|
+
// That async viewer teardown is covered by the compiled-seam broker-crash-teardown /
|
|
253
264
|
// broker-lifecycle suite, which runs a real broker; it cannot be unit-tested
|
|
254
265
|
// without one.
|