@north-light/crouter 0.3.170 → 0.3.172
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/client.d.ts +37 -11
- package/dist/api/client.js +84 -15
- package/dist/api/dto/human.d.ts +53 -39
- package/dist/api/dto/human.js +2 -3
- package/dist/api/dto/inbox.d.ts +0 -1
- package/dist/api/dto/nodes.d.ts +12 -0
- package/dist/api/dto/review-comments.d.ts +137 -0
- package/dist/api/dto/review-comments.js +5 -0
- package/dist/api/dto/reviews.d.ts +109 -0
- package/dist/api/dto/reviews.js +5 -0
- package/dist/api/index.d.ts +2 -0
- package/dist/api/index.js +2 -0
- package/dist/api/routes.d.ts +17 -4
- package/dist/api/routes.js +21 -5
- package/dist/build-root.d.ts +1 -16
- package/dist/build-root.js +1 -25
- package/dist/builtin-memory/00-runtime-base.md +7 -5
- package/dist/builtin-memory/04-base-worker.md +1 -1
- package/dist/builtin-memory/04-orchestration-kernel.md +7 -7
- package/dist/builtin-memory/05-kinds/design/00-base.md +1 -1
- package/dist/builtin-memory/05-kinds/design/01-orchestrator.md +1 -1
- package/dist/builtin-memory/05-kinds/developer/00-base.md +1 -1
- package/dist/builtin-memory/05-kinds/explore/00-base.md +1 -1
- package/dist/builtin-memory/05-kinds/plan/00-base.md +1 -1
- package/dist/builtin-memory/05-kinds/plan/01-orchestrator.md +1 -1
- package/dist/builtin-memory/05-kinds/review/00-base.md +1 -1
- package/dist/builtin-memory/05-kinds/review/companion/00-base.md +20 -0
- package/dist/builtin-memory/05-kinds/spec/00-base.md +3 -7
- package/dist/builtin-memory/05-kinds/spec/01-orchestrator.md +3 -3
- package/dist/builtin-memory/05-kinds/spec/requirements.md +3 -3
- package/dist/builtin-memory/design.md +2 -2
- package/dist/builtin-memory/insights/capture.md +50 -0
- package/dist/builtin-memory/insights/init.md +45 -0
- package/dist/builtin-memory/insights/listen.md +9 -0
- package/dist/builtin-memory/internal/agent-shaping.md +2 -2
- package/dist/builtin-memory/internal/nodes-and-canvas.md +1 -1
- package/dist/builtin-memory/internal/plugins.md +12 -11
- package/dist/builtin-memory/internal/storage-tiers.md +2 -2
- package/dist/builtin-memory/{planning.md → plan/roadmap.md} +3 -3
- package/dist/builtin-memory/plan.md +19 -0
- package/dist/builtin-memory/spec/guide.md +38 -0
- package/dist/builtin-memory/spec/requirements.md +31 -0
- package/dist/builtin-memory/spec/roadmap.md +35 -0
- package/dist/builtin-memory/spec.md +10 -86
- package/dist/builtin-pi-packages/pi-crtr-extensions/README.md +3 -4
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/provider-rotation.test.ts +49 -5
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.d.ts +56 -0
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +920 -0
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +221 -156
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/statusline.ts +4 -5
- package/dist/cli.js +2 -6
- package/dist/clients/attach/__tests__/attach-chrome-remote.test.js +7 -35
- package/dist/clients/attach/__tests__/attach-keybindings.test.js +32 -16
- package/dist/clients/attach/__tests__/context-message.test.js +142 -6
- package/dist/clients/attach/__tests__/crtr-output.test.js +29 -45
- package/dist/clients/attach/__tests__/diagram.test.js +1 -1
- package/dist/clients/attach/__tests__/file-review-focus.test.js +48 -0
- package/dist/clients/attach/__tests__/group-activity.test.js +266 -0
- package/dist/clients/attach/__tests__/input-controller-extension-command.test.js +32 -0
- package/dist/clients/attach/__tests__/session-identity-refresh.test.js +32 -0
- package/dist/clients/attach/__tests__/titled-editor-preview.test.js +1 -2
- package/dist/clients/attach/chrome/header.d.ts +10 -0
- package/dist/clients/attach/chrome/header.js +30 -0
- package/dist/clients/attach/chrome/recap.d.ts +7 -0
- package/dist/clients/attach/chrome/recap.js +19 -0
- package/dist/clients/attach/chrome/status-line.d.ts +3 -0
- package/dist/clients/attach/chrome/status-line.js +5 -0
- package/dist/clients/attach/chrome/widgets.js +11 -21
- package/dist/clients/attach/command.js +11 -7
- package/dist/clients/attach/config.d.ts +4 -0
- package/dist/clients/attach/config.js +3 -0
- package/dist/clients/attach/input/controller.d.ts +19 -0
- package/dist/clients/attach/input/controller.js +62 -28
- package/dist/clients/attach/input/titled-editor.d.ts +0 -4
- package/dist/clients/attach/input/titled-editor.js +2 -10
- package/dist/clients/attach/overlays/file-review.d.ts +9 -5
- package/dist/clients/attach/overlays/file-review.js +9 -70
- package/dist/clients/attach/overlays/help.d.ts +33 -0
- package/dist/clients/attach/overlays/help.js +204 -0
- package/dist/clients/attach/render/activity-slot.d.ts +4 -0
- package/dist/clients/attach/render/activity-slot.js +13 -0
- package/dist/clients/attach/render/chat-view.d.ts +117 -12
- package/dist/clients/attach/render/chat-view.js +604 -135
- package/dist/clients/attach/render/context-message.d.ts +2 -1
- package/dist/clients/attach/render/context-message.js +17 -13
- package/dist/clients/attach/render/crtr-output.js +1 -3
- package/dist/clients/attach/render/diagram.js +2 -2
- package/dist/clients/attach/render/edit-diff.d.ts +4 -1
- package/dist/clients/attach/render/edit-diff.js +7 -11
- package/dist/clients/attach/render/group-activity.d.ts +32 -0
- package/dist/clients/attach/render/group-activity.js +206 -0
- package/dist/clients/attach/render/group-recap.d.ts +10 -0
- package/dist/clients/attach/render/group-recap.js +93 -0
- package/dist/clients/attach/render/html-markdown.d.ts +17 -0
- package/dist/clients/attach/render/html-markdown.js +228 -0
- package/dist/clients/attach/render/measured-container.d.ts +96 -0
- package/dist/clients/attach/render/measured-container.js +322 -0
- package/dist/clients/attach/render/scroll-animation.d.ts +8 -0
- package/dist/clients/attach/render/scroll-animation.js +80 -0
- package/dist/clients/attach/render/tool-calls.js +6 -6
- package/dist/clients/attach/render/transcript-copy.d.ts +9 -0
- package/dist/clients/attach/render/transcript-copy.js +81 -0
- package/dist/clients/attach/render/viewport.d.ts +29 -0
- package/dist/clients/attach/render/viewport.js +159 -0
- package/dist/clients/attach/session/bindings.d.ts +10 -7
- package/dist/clients/attach/session/bindings.js +23 -8
- package/dist/clients/attach/session/connection.js +4 -5
- package/dist/clients/attach/session/context.d.ts +6 -4
- package/dist/clients/attach/session/frame.d.ts +34 -0
- package/dist/clients/attach/session/frame.js +176 -0
- package/dist/clients/attach/session/frames.d.ts +4 -1
- package/dist/clients/attach/session/frames.js +14 -1
- package/dist/clients/attach/session/identity.js +4 -3
- package/dist/clients/attach/session/input-wiring.d.ts +14 -4
- package/dist/clients/attach/session/input-wiring.js +15 -13
- package/dist/clients/attach/session/invariant.d.ts +9 -0
- package/dist/clients/attach/session/invariant.js +15 -0
- package/dist/clients/attach/session/keys.d.ts +10 -2
- package/dist/clients/attach/session/keys.js +13 -5
- package/dist/clients/attach/session/layout.d.ts +10 -8
- package/dist/clients/attach/session/layout.js +33 -34
- package/dist/clients/attach/session/mouse.d.ts +18 -0
- package/dist/clients/attach/session/mouse.js +64 -0
- package/dist/clients/attach/session/pane-tag.d.ts +3 -0
- package/dist/clients/attach/session/pane-tag.js +51 -8
- package/dist/clients/attach/session/reconnect.d.ts +3 -0
- package/dist/clients/attach/session/reconnect.js +42 -5
- package/dist/clients/attach/session/surface-frame.d.ts +20 -0
- package/dist/clients/attach/session/surface-frame.js +73 -0
- package/dist/clients/attach/session/surface-host.d.ts +64 -0
- package/dist/clients/attach/session/surface-host.js +255 -0
- package/dist/clients/attach/session/whip.d.ts +17 -0
- package/dist/clients/attach/session/whip.js +334 -0
- package/dist/clients/attach/slash/dispatch.d.ts +13 -1
- package/dist/clients/attach/slash/dispatch.js +51 -29
- package/dist/clients/attach/viewer.js +907 -819
- package/dist/clients/conversation/conversation.d.ts +65 -0
- package/dist/clients/conversation/conversation.js +318 -0
- package/dist/clients/conversation/frames.d.ts +30 -0
- package/dist/clients/conversation/frames.js +52 -0
- package/dist/clients/conversation/region.d.ts +51 -0
- package/dist/clients/conversation/region.js +265 -0
- package/dist/clients/conversation/submit.d.ts +38 -0
- package/dist/clients/conversation/submit.js +51 -0
- package/dist/clients/inbox/__tests__/inbox-controller.test.js +247 -0
- package/dist/clients/inbox/__tests__/mount-panel.test.js +776 -0
- package/dist/clients/inbox/controller.d.ts +79 -0
- package/dist/clients/inbox/controller.js +448 -0
- package/dist/clients/inbox/deck-adapter.d.ts +29 -0
- package/dist/clients/inbox/deck-adapter.js +62 -0
- package/dist/clients/inbox/layout.d.ts +8 -0
- package/dist/clients/inbox/layout.js +9 -0
- package/dist/clients/inbox/resolve.d.ts +10 -0
- package/dist/clients/inbox/resolve.js +34 -0
- package/dist/clients/inbox/review/__tests__/editor-roundtrip.test.js +29 -0
- package/dist/clients/inbox/review/__tests__/remap.test.js +196 -0
- package/dist/clients/inbox/review/__tests__/review-core.test.js +341 -0
- package/dist/clients/inbox/review/anchors.d.ts +41 -0
- package/dist/clients/inbox/review/anchors.js +89 -0
- package/dist/clients/inbox/review/columns.d.ts +22 -0
- package/dist/clients/inbox/review/columns.js +40 -0
- package/dist/clients/inbox/review/comments-client.d.ts +66 -0
- package/dist/clients/inbox/review/comments-client.js +98 -0
- package/dist/clients/inbox/review/composition.d.ts +60 -0
- package/dist/clients/inbox/review/composition.js +278 -0
- package/dist/clients/inbox/review/document-region.d.ts +120 -0
- package/dist/clients/inbox/review/document-region.js +902 -0
- package/dist/clients/inbox/review/frame.d.ts +45 -0
- package/dist/clients/inbox/review/frame.js +215 -0
- package/dist/clients/inbox/review/keys.d.ts +67 -0
- package/dist/clients/inbox/review/keys.js +130 -0
- package/dist/clients/inbox/review/launch.d.ts +10 -0
- package/dist/clients/inbox/review/launch.js +129 -0
- package/dist/clients/inbox/review/live-source.d.ts +24 -0
- package/dist/clients/inbox/review/live-source.js +160 -0
- package/dist/clients/inbox/review/nvim.d.ts +13 -0
- package/dist/clients/inbox/review/nvim.js +42 -0
- package/dist/clients/inbox/review/remap.d.ts +51 -0
- package/dist/clients/inbox/review/remap.js +157 -0
- package/dist/clients/inbox/review/review-client.d.ts +30 -0
- package/dist/clients/inbox/review/review-client.js +107 -0
- package/dist/clients/inbox/review/roundtrip.d.ts +5 -0
- package/dist/clients/inbox/review/roundtrip.js +36 -0
- package/dist/clients/inbox/review/state.d.ts +143 -0
- package/dist/clients/inbox/review/state.js +282 -0
- package/dist/clients/inbox/review-adapter.d.ts +29 -0
- package/dist/clients/inbox/review-adapter.js +92 -0
- package/dist/clients/inbox/review-visibility.d.ts +5 -0
- package/dist/clients/inbox/review-visibility.js +19 -0
- package/dist/clients/inbox/surface.d.ts +19 -0
- package/dist/clients/inbox/surface.js +128 -0
- package/dist/clients/inbox/tui/ansi.d.ts +66 -0
- package/dist/clients/inbox/tui/ansi.js +317 -0
- package/dist/clients/inbox/tui/clipboard.d.ts +2 -0
- package/dist/clients/inbox/tui/clipboard.js +26 -0
- package/dist/clients/inbox/tui/input.d.ts +7 -0
- package/dist/clients/inbox/tui/input.js +653 -0
- package/dist/clients/inbox/tui/keys.d.ts +28 -0
- package/dist/clients/inbox/tui/keys.js +111 -0
- package/dist/clients/inbox/tui/panel.d.ts +2 -0
- package/dist/clients/inbox/tui/panel.js +217 -0
- package/dist/clients/inbox/tui/render.d.ts +37 -0
- package/dist/clients/inbox/tui/render.js +476 -0
- package/dist/clients/inbox/tui/types.d.ts +57 -0
- package/dist/clients/inbox/tui/types.js +1 -0
- package/dist/clients/inbox/tui.d.ts +6 -0
- package/dist/clients/inbox/tui.js +74 -0
- package/dist/clients/surfaces/host.d.ts +66 -0
- package/dist/clients/surfaces/host.js +1 -0
- package/dist/clients/surfaces/region.d.ts +16 -0
- package/dist/clients/surfaces/region.js +1 -0
- package/dist/clients/web/__tests__/push-engine.test.js +14 -158
- package/dist/clients/web/dev-server.d.ts +3 -3
- package/dist/clients/web/dev-server.js +9 -23
- package/dist/clients/web/events.js +4 -6
- package/dist/clients/web/push-engine.d.ts +2 -66
- package/dist/clients/web/push-engine.js +30 -161
- package/dist/clients/web/push-registry.d.ts +0 -4
- package/dist/clients/web/push-registry.js +2 -7
- package/dist/clients/web/server.js +3 -35
- package/dist/clients/web/web-client/shared/protocol.d.ts +0 -108
- package/dist/clients/web/web-cmd.js +2 -2
- package/dist/commands/__tests__/human.test.js +27 -15
- package/dist/commands/api-client.js +3 -3
- package/dist/commands/canvas-browse.js +1 -1
- package/dist/commands/canvas-issue.js +1 -1
- package/dist/commands/canvas-use.js +1 -1
- package/dist/commands/human/doc.d.ts +2 -0
- package/dist/commands/human/doc.js +98 -0
- package/dist/commands/human/inbox.d.ts +2 -0
- package/dist/commands/human/inbox.js +101 -0
- package/dist/commands/human/prompts.d.ts +2 -3
- package/dist/commands/human/prompts.js +27 -180
- package/dist/commands/human/queue.d.ts +1 -5
- package/dist/commands/human/queue.js +54 -216
- package/dist/commands/human/review.d.ts +2 -0
- package/dist/commands/human/review.js +298 -0
- package/dist/commands/human/shared.d.ts +2 -69
- package/dist/commands/human/shared.js +1 -181
- package/dist/commands/human.js +15 -20
- package/dist/commands/memory/__tests__/lint.test.d.ts +1 -0
- package/dist/commands/memory/__tests__/lint.test.js +15 -0
- package/dist/commands/memory/delete.js +2 -2
- package/dist/commands/memory/lint.d.ts +1 -0
- package/dist/commands/memory/lint.js +21 -3
- package/dist/commands/memory/read.js +4 -4
- package/dist/commands/node.js +8 -7
- package/dist/commands/pkg/plugin-manage.js +143 -68
- package/dist/commands/surface-inspect.js +2 -2
- package/dist/commands/surface.js +6 -12
- package/dist/commands/sys/__tests__/setup-core.test.js +9 -5
- package/dist/commands/sys/__tests__/setup-front-door.test.js +7 -42
- package/dist/commands/sys/config.js +29 -3
- package/dist/commands/sys/feedback.js +1 -1
- package/dist/commands/sys/setup-core.d.ts +12 -11
- package/dist/commands/sys/setup-core.js +55 -46
- package/dist/commands/sys/setup-wizard.d.ts +4 -1
- package/dist/commands/sys/setup-wizard.js +50 -9
- package/dist/commands/sys/sync-deps.js +1 -1
- package/dist/commands/sys.js +4 -6
- package/dist/core/__tests__/broker-sdk-wiring.test.js +6 -1
- package/dist/core/__tests__/broker-snapshot-history.test.js +9 -1
- package/dist/core/__tests__/dead-node-policy-table.test.js +3 -4
- package/dist/core/__tests__/fixtures/fake-engine.d.ts +8 -5
- package/dist/core/__tests__/fixtures/fake-engine.js +28 -2
- package/dist/core/__tests__/full/broker-provider-retry.test.js +87 -2
- package/dist/core/__tests__/full/broker-whip-interrupt.test.d.ts +1 -0
- package/dist/core/__tests__/full/broker-whip-interrupt.test.js +39 -0
- package/dist/core/__tests__/full/detach-focus.test.js +1 -1
- package/dist/core/__tests__/human-deliver-e2e.test.js +64 -64
- package/dist/core/__tests__/human-deliver.test.js +71 -345
- package/dist/core/__tests__/inline-memory-refs.test.js +2 -12
- package/dist/core/__tests__/memory-resolver-precedence.test.js +12 -15
- package/dist/core/__tests__/migration.test.js +10 -0
- package/dist/core/__tests__/model-pin-durability.test.js +14 -0
- package/dist/core/__tests__/phase4-review-migration.test.d.ts +1 -0
- package/dist/core/__tests__/phase4-review-migration.test.js +100 -0
- package/dist/core/__tests__/phase4-review-store.test.d.ts +1 -0
- package/dist/core/__tests__/phase4-review-store.test.js +143 -0
- package/dist/core/__tests__/remote-canvas-target.test.js +2 -2
- package/dist/core/__tests__/revive.test.js +22 -53
- package/dist/core/__tests__/session-cycles.test.js +48 -18
- package/dist/core/__tests__/spawn-no-kickoff.test.js +8 -12
- package/dist/core/__tests__/stop-guard.test.js +16 -1
- package/dist/core/__tests__/tmux-surface.test.js +21 -25
- package/dist/core/asset-root.d.ts +7 -0
- package/dist/core/asset-root.js +18 -0
- package/dist/core/broker-client/client.d.ts +0 -7
- package/dist/core/broker-client/client.js +4 -10
- package/dist/core/broker-client/transport-relay.d.ts +3 -4
- package/dist/core/broker-client/transport-relay.js +3 -4
- package/dist/core/canvas/__tests__/attention.test.js +1 -1
- package/dist/core/canvas/__tests__/remote-canvas-source.test.js +1 -1
- package/dist/core/canvas/__tests__/remote-transport.test.d.ts +1 -0
- package/dist/core/{view/__tests__/transport-remote.test.js → canvas/__tests__/remote-transport.test.js} +2 -2
- package/dist/core/canvas/__tests__/render-remote.test.js +1 -1
- package/dist/core/canvas/attention.js +4 -4
- package/dist/core/canvas/canvas.d.ts +6 -11
- package/dist/core/canvas/canvas.js +11 -33
- package/dist/core/canvas/db.js +207 -38
- package/dist/core/canvas/extensions.d.ts +1 -1
- package/dist/core/canvas/extensions.js +8 -1
- package/dist/core/canvas/index.d.ts +0 -1
- package/dist/core/canvas/index.js +0 -1
- package/dist/core/canvas/nav-model.d.ts +1 -1
- package/dist/core/canvas/nav-model.js +1 -1
- package/dist/core/canvas/paths.d.ts +5 -0
- package/dist/core/canvas/paths.js +16 -0
- package/dist/core/canvas/remote-canvas-source.js +2 -2
- package/dist/core/canvas/remote-transport.d.ts +7 -0
- package/dist/core/{view/transport-remote.js → canvas/remote-transport.js} +3 -4
- package/dist/core/canvas/source.js +1 -1
- package/dist/core/canvas/status-glyph.js +4 -12
- package/dist/core/canvas/types.d.ts +10 -35
- package/dist/core/clipboard-text.d.ts +8 -0
- package/dist/core/clipboard-text.js +18 -0
- package/dist/core/command-manifests/registry.d.ts +1 -3
- package/dist/core/command-plugins/bundle.d.ts +29 -0
- package/dist/core/command-plugins/bundle.js +198 -0
- package/dist/core/command-plugins/discovery.d.ts +0 -8
- package/dist/core/command-plugins/discovery.js +2 -39
- package/dist/core/command-plugins/transport/http-fetch.d.ts +4 -30
- package/dist/core/command-plugins/transport/http-fetch.js +17 -95
- package/dist/core/command.d.ts +1 -13
- package/dist/core/command.js +1 -16
- package/dist/core/config.d.ts +4 -0
- package/dist/core/config.js +28 -3
- package/dist/core/document-lines.d.ts +4 -0
- package/dist/core/document-lines.js +6 -0
- package/dist/core/feed/feed.d.ts +2 -0
- package/dist/core/feed/feed.js +11 -7
- package/dist/core/human/__tests__/inbox-cancel-worker.d.ts +1 -0
- package/dist/core/human/__tests__/inbox-cancel-worker.js +7 -0
- package/dist/core/human/__tests__/inbox-claim-worker.d.ts +1 -0
- package/dist/core/human/__tests__/inbox-claim-worker.js +17 -0
- package/dist/core/human/__tests__/inbox-core.test.d.ts +1 -0
- package/dist/core/human/__tests__/inbox-core.test.js +144 -0
- package/dist/core/human/__tests__/inbox-stale-claim-worker.d.ts +1 -0
- package/dist/core/human/__tests__/inbox-stale-claim-worker.js +8 -0
- package/dist/core/human/__tests__/visible-paths.test.d.ts +1 -0
- package/dist/{clients/attach → core/human}/__tests__/visible-paths.test.js +9 -0
- package/dist/core/human/claim.d.ts +23 -0
- package/dist/core/human/claim.js +67 -0
- package/dist/core/human/convention.d.ts +30 -0
- package/dist/core/human/convention.js +202 -0
- package/dist/core/human/deck-factories.d.ts +8 -0
- package/dist/core/human/deck-factories.js +15 -0
- package/dist/core/human/deck-schema.d.ts +70 -0
- package/dist/core/human/deck-schema.js +92 -0
- package/dist/core/human/root.d.ts +7 -0
- package/dist/core/human/root.js +37 -0
- package/dist/core/human/scan.d.ts +3 -0
- package/dist/core/human/scan.js +76 -0
- package/dist/core/human/summary.d.ts +8 -0
- package/dist/core/human/summary.js +44 -0
- package/dist/core/human/tickets.d.ts +49 -0
- package/dist/core/human/tickets.js +190 -0
- package/dist/core/human/types.d.ts +136 -0
- package/dist/core/human/types.js +5 -0
- package/dist/{clients/attach → core/human}/visible-paths.d.ts +1 -1
- package/dist/{clients/attach → core/human}/visible-paths.js +3 -2
- package/dist/core/inspector/chrome.d.ts +6 -0
- package/dist/core/inspector/chrome.js +14 -0
- package/dist/core/inspector/contract.d.ts +105 -0
- package/dist/core/inspector/contract.js +1 -0
- package/dist/core/inspector/core.d.ts +4 -5
- package/dist/core/inspector/core.js +3 -5
- package/dist/core/inspector/host.d.ts +46 -0
- package/dist/core/{tui → inspector}/host.js +42 -208
- package/dist/core/inspector/text.d.ts +2 -2
- package/dist/core/inspector/transport.d.ts +6 -0
- package/dist/core/inspector/transport.js +36 -0
- package/dist/core/inspector/tui.d.ts +2 -2
- package/dist/core/inspector/tui.js +15 -15
- package/dist/core/keybindings/__tests__/inbox-affordance.test.js +11 -11
- package/dist/core/keybindings/__tests__/resolve.test.js +10 -19
- package/dist/core/keybindings/attach-control.d.ts +9 -3
- package/dist/core/keybindings/attach-control.js +3 -1
- package/dist/core/keybindings/catalog.d.ts +6 -5
- package/dist/core/keybindings/catalog.js +61 -133
- package/dist/core/keybindings/inbox.d.ts +5 -6
- package/dist/core/keybindings/inbox.js +9 -10
- package/dist/core/keybindings/index.d.ts +3 -3
- package/dist/core/keybindings/index.js +3 -3
- package/dist/core/keybindings/persistence.d.ts +5 -1
- package/dist/core/keybindings/persistence.js +24 -6
- package/dist/core/keybindings/resolve.d.ts +6 -0
- package/dist/core/keybindings/resolve.js +10 -3
- package/dist/core/memory/inline-ref-grammar.js +2 -3
- package/dist/core/memory-resolver.d.ts +27 -29
- package/dist/core/memory-resolver.js +45 -39
- package/dist/core/model-routes.d.ts +33 -0
- package/dist/core/model-routes.js +42 -3
- package/dist/core/preview-registry.js +17 -55
- package/dist/core/profiles/select.js +3 -3
- package/dist/core/{view/remote-canvas-target.d.ts → remote-canvas-target.d.ts} +2 -2
- package/dist/core/{view/remote-canvas-target.js → remote-canvas-target.js} +4 -4
- package/dist/core/review/__tests__/capture-origin.test.d.ts +1 -0
- package/dist/core/review/__tests__/capture-origin.test.js +139 -0
- package/dist/core/review/__tests__/comments.test.d.ts +1 -0
- package/dist/core/review/__tests__/comments.test.js +98 -0
- package/dist/core/review/__tests__/project.test.d.ts +1 -0
- package/dist/core/review/__tests__/project.test.js +71 -0
- package/dist/core/review/__tests__/remap.test.d.ts +1 -0
- package/dist/core/review/__tests__/remap.test.js +159 -0
- package/dist/core/review/__tests__/stage-identity.test.d.ts +1 -0
- package/dist/core/review/__tests__/stage-identity.test.js +140 -0
- package/dist/core/review/birth.d.ts +7 -0
- package/dist/core/review/birth.js +23 -0
- package/dist/core/review/comments.d.ts +69 -0
- package/dist/core/review/comments.js +295 -0
- package/dist/core/review/companion.d.ts +35 -0
- package/dist/core/review/companion.js +205 -0
- package/dist/core/review/document.d.ts +27 -0
- package/dist/core/review/document.js +138 -0
- package/dist/core/review/project.d.ts +13 -0
- package/dist/core/review/project.js +58 -0
- package/dist/core/review/realize.d.ts +19 -0
- package/dist/core/review/realize.js +217 -0
- package/dist/core/review/remap.d.ts +24 -0
- package/dist/core/review/remap.js +156 -0
- package/dist/core/review/signal.d.ts +5 -0
- package/dist/core/review/signal.js +31 -0
- package/dist/core/review/stage.d.ts +26 -0
- package/dist/core/review/stage.js +184 -0
- package/dist/core/review/store.d.ts +46 -0
- package/dist/core/review/store.js +163 -0
- package/dist/core/review/ticket-filter.d.ts +17 -0
- package/dist/core/review/ticket-filter.js +32 -0
- package/dist/core/review/types.d.ts +130 -0
- package/dist/core/review/types.js +23 -0
- package/dist/core/runtime/__tests__/session-visibility.test.d.ts +1 -0
- package/dist/core/runtime/__tests__/session-visibility.test.js +119 -0
- package/dist/core/runtime/bearings.d.ts +5 -17
- package/dist/core/runtime/bearings.js +88 -71
- package/dist/core/runtime/broker-protocol.d.ts +31 -8
- package/dist/core/runtime/broker.d.ts +15 -1
- package/dist/core/runtime/broker.js +573 -141
- package/dist/core/runtime/canvas-extensions.d.ts +4 -5
- package/dist/core/runtime/canvas-extensions.js +5 -5
- package/dist/core/runtime/front-door.js +4 -4
- package/dist/core/runtime/headless-pi.d.ts +24 -0
- package/dist/core/runtime/headless-pi.js +152 -0
- package/dist/core/runtime/kickoff.d.ts +1 -5
- package/dist/core/runtime/kickoff.js +1 -5
- package/dist/core/runtime/model-registry.d.ts +3 -0
- package/dist/core/runtime/model-registry.js +13 -0
- package/dist/core/runtime/naming-persist.d.ts +4 -0
- package/dist/core/runtime/naming-persist.js +27 -1
- package/dist/core/runtime/naming.d.ts +17 -12
- package/dist/core/runtime/naming.js +91 -140
- package/dist/core/runtime/node-read.js +19 -10
- package/dist/core/runtime/nodes.d.ts +9 -14
- package/dist/core/runtime/nodes.js +3 -53
- package/dist/core/runtime/package-health.d.ts +6 -21
- package/dist/core/runtime/package-health.js +12 -123
- package/dist/core/runtime/placement-tmux.d.ts +2 -1
- package/dist/core/runtime/placement-tmux.js +6 -4
- package/dist/core/runtime/placement.d.ts +1 -0
- package/dist/core/runtime/placement.js +4 -8
- package/dist/core/runtime/promote.js +3 -0
- package/dist/core/runtime/recap.d.ts +2 -7
- package/dist/core/runtime/recap.js +35 -69
- package/dist/core/runtime/revive.js +34 -77
- package/dist/core/runtime/session-cycles.d.ts +4 -0
- package/dist/core/runtime/session-cycles.js +14 -1
- package/dist/core/runtime/session-visibility.d.ts +37 -0
- package/dist/core/runtime/session-visibility.js +83 -0
- package/dist/core/runtime/spawn.js +10 -22
- package/dist/core/runtime/stop-guard.d.ts +1 -1
- package/dist/core/runtime/stop-guard.js +18 -13
- package/dist/core/runtime/surface-bg.js +1 -1
- package/dist/core/runtime/tmux-chrome.d.ts +1 -1
- package/dist/core/runtime/tmux-chrome.js +1 -1
- package/dist/core/runtime/tmux.d.ts +35 -7
- package/dist/core/runtime/tmux.js +439 -62
- package/dist/core/runtime/tool-group-summary.d.ts +19 -0
- package/dist/core/runtime/tool-group-summary.js +88 -0
- package/dist/core/scope.d.ts +2 -7
- package/dist/core/scope.js +9 -35
- package/dist/core/substrate/schema.d.ts +2 -2
- package/dist/core/termrender/code-doc.d.ts +12 -0
- package/dist/core/termrender/code-doc.js +92 -0
- package/dist/core/termrender/display.d.ts +12 -0
- package/dist/core/termrender/display.js +19 -0
- package/dist/core/termrender/termrender.d.ts +73 -0
- package/dist/core/termrender/termrender.js +795 -0
- package/dist/core/termrender/version.d.ts +1 -0
- package/dist/core/termrender/version.js +1 -0
- package/dist/core/tui/terminal.js +1 -2
- package/dist/core/user-settings.d.ts +71 -3
- package/dist/core/user-settings.js +83 -1
- package/dist/daemon/api/__tests__/inbox.test.js +44 -133
- package/dist/daemon/api/handlers/human.d.ts +0 -10
- package/dist/daemon/api/handlers/human.js +104 -702
- package/dist/daemon/api/handlers/inbox.js +113 -142
- package/dist/daemon/api/handlers/review-comments.d.ts +2 -0
- package/dist/daemon/api/handlers/review-comments.js +500 -0
- package/dist/daemon/api/handlers/reviews.d.ts +2 -0
- package/dist/daemon/api/handlers/reviews.js +287 -0
- package/dist/daemon/api/map.d.ts +22 -7
- package/dist/daemon/api/map.js +159 -11
- package/dist/daemon/api/server.js +4 -0
- package/dist/daemon/cron-run.js +6 -9
- package/dist/daemon/crtrd.js +17 -33
- package/dist/daemon/fleet.d.ts +1 -8
- package/dist/daemon/fleet.js +4 -30
- package/dist/daemon/human/finish.d.ts +14 -0
- package/dist/daemon/human/finish.js +115 -0
- package/dist/daemon/human/sweep.d.ts +6 -0
- package/dist/daemon/human/sweep.js +49 -0
- package/dist/daemon/messaging/node-message.d.ts +18 -0
- package/dist/daemon/messaging/node-message.js +70 -0
- package/dist/daemon/review/comment-notify.d.ts +26 -0
- package/dist/daemon/review/comment-notify.js +107 -0
- package/dist/daemon/review/deliver.d.ts +7 -0
- package/dist/daemon/review/deliver.js +56 -0
- package/dist/daemon/review/finish.d.ts +22 -0
- package/dist/daemon/review/finish.js +254 -0
- package/dist/daemon/review/sweep.d.ts +11 -0
- package/dist/daemon/review/sweep.js +120 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -2
- package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +42 -64
- package/dist/pi-extensions/__tests__/canvas-recap.test.d.ts +1 -0
- package/dist/pi-extensions/__tests__/canvas-recap.test.js +159 -0
- package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +16 -38
- package/dist/pi-extensions/__tests__/canvas-structured-output.test.d.ts +1 -0
- package/dist/pi-extensions/__tests__/canvas-structured-output.test.js +63 -0
- package/dist/pi-extensions/canvas-context-intro.d.ts +8 -11
- package/dist/pi-extensions/canvas-context-intro.js +50 -104
- package/dist/pi-extensions/canvas-recap.d.ts +15 -2
- package/dist/pi-extensions/canvas-recap.js +192 -69
- package/dist/pi-extensions/canvas-review-boundary.d.ts +59 -0
- package/dist/pi-extensions/canvas-review-boundary.js +81 -0
- package/dist/pi-extensions/canvas-stophook.d.ts +3 -3
- package/dist/pi-extensions/canvas-stophook.js +78 -128
- package/dist/pi-extensions/canvas-structured-output.js +52 -8
- package/dist/shared/generated-context.d.ts +29 -4
- package/dist/shared/generated-context.js +122 -7
- package/dist/shared/tool-groups.d.ts +23 -0
- package/dist/shared/tool-groups.js +60 -0
- package/dist/shared/working-activity.d.ts +8 -0
- package/dist/shared/working-activity.js +26 -0
- package/dist/types.d.ts +36 -2
- package/dist/types.js +51 -0
- package/dist/web-client/assets/index-CCPaLeW7.css +2 -0
- package/dist/web-client/assets/index-kyOWsnZK.js +86 -0
- package/dist/web-client/index.html +2 -2
- package/dist/web-client/sw.js +1 -1
- package/docs/compat/hearth-crtr-v4.md +2 -2
- package/docs/compat/hearth-crtr-v5.md +4 -2
- package/docs/public-api.md +3 -3
- package/package.json +21 -14
- package/runtime.lock.json +4661 -1453
- package/scripts/postinstall.mjs +15 -2
- package/dist/builtin-pi-packages/pi-mode-switch/README.md +0 -36
- package/dist/builtin-pi-packages/pi-mode-switch/bin/mode +0 -36
- package/dist/builtin-pi-packages/pi-mode-switch/extensions/index.ts +0 -449
- package/dist/builtin-pi-packages/pi-mode-switch/package.json +0 -14
- package/dist/builtin-pi-packages/pi-mode-switch/tsconfig.json +0 -9
- package/dist/builtin-views/_lib/states.mjs +0 -161
- package/dist/builtin-views/canvas/core.mjs +0 -657
- package/dist/builtin-views/canvas/text.mjs +0 -58
- package/dist/builtin-views/canvas/tui.mjs +0 -168
- package/dist/builtin-views/canvas/web.jsx +0 -121
- package/dist/builtin-views/chat/core.mjs +0 -684
- package/dist/builtin-views/chat/text.mjs +0 -101
- package/dist/builtin-views/chat/tui.mjs +0 -360
- package/dist/builtin-views/chat/web.jsx +0 -362
- package/dist/builtin-views/git-pr/core.mjs +0 -673
- package/dist/builtin-views/git-pr/text.mjs +0 -84
- package/dist/builtin-views/git-pr/tui.mjs +0 -301
- package/dist/builtin-views/git-pr/web.jsx +0 -216
- package/dist/builtin-views/inbox/_lib/render.mjs +0 -175
- package/dist/builtin-views/inbox/core.mjs +0 -1273
- package/dist/builtin-views/inbox/text.mjs +0 -73
- package/dist/builtin-views/inbox/tui.mjs +0 -314
- package/dist/builtin-views/inbox/web.jsx +0 -188
- package/dist/builtin-views/linkedin/core.mjs +0 -906
- package/dist/builtin-views/linkedin/text.mjs +0 -69
- package/dist/builtin-views/linkedin/tui.mjs +0 -413
- package/dist/builtin-views/linkedin/web.jsx +0 -206
- package/dist/builtin-views/prompt-review/core.mjs +0 -735
- package/dist/builtin-views/prompt-review/text.mjs +0 -15
- package/dist/builtin-views/prompt-review/tui.mjs +0 -196
- package/dist/builtin-views/prompt-review/web.jsx +0 -484
- package/dist/builtin-views/workspace-sidebar/__tests__/core.test.js +0 -50
- package/dist/builtin-views/workspace-sidebar/__tests__/core.test.ts +0 -53
- package/dist/builtin-views/workspace-sidebar/core.mjs +0 -670
- package/dist/builtin-views/workspace-sidebar/text.mjs +0 -53
- package/dist/builtin-views/workspace-sidebar/tui.mjs +0 -141
- package/dist/builtin-views/workspace-sidebar/web.jsx +0 -109
- package/dist/clients/attach/session/mode.d.ts +0 -25
- package/dist/clients/attach/session/mode.js +0 -97
- package/dist/commands/sys/promptstudio.d.ts +0 -2
- package/dist/commands/sys/promptstudio.js +0 -65
- package/dist/commands/view-cycle.d.ts +0 -2
- package/dist/commands/view-cycle.js +0 -130
- package/dist/commands/view-list.d.ts +0 -2
- package/dist/commands/view-list.js +0 -66
- package/dist/commands/view-new.d.ts +0 -2
- package/dist/commands/view-new.js +0 -74
- package/dist/commands/view-pick.d.ts +0 -6
- package/dist/commands/view-pick.js +0 -129
- package/dist/commands/view-run.d.ts +0 -2
- package/dist/commands/view-run.js +0 -214
- package/dist/commands/view.d.ts +0 -2
- package/dist/commands/view.js +0 -31
- package/dist/commands/workspace.d.ts +0 -2
- package/dist/commands/workspace.js +0 -165
- package/dist/core/__tests__/chat-view-reconnect.test.js +0 -105
- package/dist/core/__tests__/full/consult-startup-failure.test.js +0 -124
- package/dist/core/canvas/__tests__/human-work-outbox.test.js +0 -123
- package/dist/core/canvas/human-work-outbox.d.ts +0 -73
- package/dist/core/canvas/human-work-outbox.js +0 -261
- package/dist/core/command-plugins/store.d.ts +0 -16
- package/dist/core/command-plugins/store.js +0 -64
- package/dist/core/keybindings/__tests__/bespoke-consumers.test.js +0 -40
- package/dist/core/runtime/fault-recovery-nudge.d.ts +0 -3
- package/dist/core/runtime/fault-recovery-nudge.js +0 -3
- package/dist/core/tui/__tests__/host-keybindings.test.js +0 -113
- package/dist/core/tui/host.d.ts +0 -66
- package/dist/core/view/__tests__/transport-cache.test.js +0 -62
- package/dist/core/view/bridge.d.ts +0 -10
- package/dist/core/view/bridge.js +0 -31
- package/dist/core/view/chrome.d.ts +0 -9
- package/dist/core/view/chrome.js +0 -22
- package/dist/core/view/contract.d.ts +0 -205
- package/dist/core/view/contract.js +0 -23
- package/dist/core/view/loader.d.ts +0 -31
- package/dist/core/view/loader.js +0 -188
- package/dist/core/view/stream-local.d.ts +0 -3
- package/dist/core/view/stream-local.js +0 -231
- package/dist/core/view/transport-cache.d.ts +0 -8
- package/dist/core/view/transport-cache.js +0 -38
- package/dist/core/view/transport-local.d.ts +0 -7
- package/dist/core/view/transport-local.js +0 -83
- package/dist/core/view/transport-remote.d.ts +0 -2
- package/dist/core/view/transport.d.ts +0 -10
- package/dist/core/view/transport.js +0 -15
- package/dist/pi-extensions/naming-tool.d.ts +0 -24
- package/dist/pi-extensions/naming-tool.js +0 -67
- package/dist/prompts/view.d.ts +0 -7
- package/dist/prompts/view.js +0 -172
- package/dist/web/ViewChrome.d.ts +0 -7
- package/dist/web/ViewChrome.js +0 -28
- package/dist/web/ViewPane.d.ts +0 -39
- package/dist/web/ViewPane.js +0 -48
- package/dist/web/index.d.ts +0 -8
- package/dist/web/index.js +0 -22
- package/dist/web/runtime.d.ts +0 -39
- package/dist/web/runtime.js +0 -232
- package/dist/web/states.d.ts +0 -24
- package/dist/web/states.js +0 -24
- package/dist/web/transport-http.d.ts +0 -5
- package/dist/web/transport-http.js +0 -34
- package/dist/web/transport-stream.d.ts +0 -3
- package/dist/web/transport-stream.js +0 -204
- package/dist/web-client/assets/index-U_NZ66VE.js +0 -79
- package/dist/web-client/assets/index-aaeu4adv.css +0 -2
- /package/dist/{builtin-views/workspace-sidebar/__tests__/core.test.d.ts → clients/attach/__tests__/file-review-focus.test.d.ts} +0 -0
- /package/dist/clients/attach/__tests__/{visible-paths.test.d.ts → group-activity.test.d.ts} +0 -0
- /package/dist/{core/__tests__/chat-view-reconnect.test.d.ts → clients/attach/__tests__/input-controller-extension-command.test.d.ts} +0 -0
- /package/dist/{core/__tests__/full/consult-startup-failure.test.d.ts → clients/attach/__tests__/session-identity-refresh.test.d.ts} +0 -0
- /package/dist/{core/canvas/__tests__/human-work-outbox.test.d.ts → clients/inbox/__tests__/inbox-controller.test.d.ts} +0 -0
- /package/dist/{core/keybindings/__tests__/bespoke-consumers.test.d.ts → clients/inbox/__tests__/mount-panel.test.d.ts} +0 -0
- /package/dist/{core/tui/__tests__/host-keybindings.test.d.ts → clients/inbox/review/__tests__/editor-roundtrip.test.d.ts} +0 -0
- /package/dist/{core/view/__tests__/transport-cache.test.d.ts → clients/inbox/review/__tests__/remap.test.d.ts} +0 -0
- /package/dist/{core/view/__tests__/transport-remote.test.d.ts → clients/inbox/review/__tests__/review-core.test.d.ts} +0 -0
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
// workspace.ts — `crtr workspace enter`: the agent-centric editor layout.
|
|
2
|
-
//
|
|
3
|
-
// Turns the current tmux window into an editor view for attached headless nodes:
|
|
4
|
-
// a narrow LEFT rail (the `workspace-sidebar` view — this graph + other live
|
|
5
|
-
// agents in this cwd, with ⚑ inbox flags) beside a CHAT pane (surface attach).
|
|
6
|
-
// Selecting a node in the rail swaps it into the chat pane.
|
|
7
|
-
//
|
|
8
|
-
// Layout build (the only two driver acts, both through placement's seam):
|
|
9
|
-
// 1. splitWindow(here, before+size) → the rail pane, left of here, runs
|
|
10
|
-
// the workspace-sidebar view host.
|
|
11
|
-
// 2. `crtr surface node focus <node> --pane <here>` → swaps the chat node's attach
|
|
12
|
-
// viewer into here's slot (here's old content relocates to the backstage).
|
|
13
|
-
// The rail finds the chat pane by DISCOVERY (the `@crtr_node` tag attach sets),
|
|
14
|
-
// so it is robust to that swap — no launch-time pane id is threaded into it.
|
|
15
|
-
//
|
|
16
|
-
// Command shape: under `crtr surface workspace`, this is a BRANCH wrapping one
|
|
17
|
-
// leaf: `enter`.
|
|
18
|
-
import { execFile } from 'node:child_process';
|
|
19
|
-
import { defineBranch, defineLeaf } from '../core/command.js';
|
|
20
|
-
import { InputError } from '../core/io.js';
|
|
21
|
-
import { cliCanvasSource } from './api-client.js';
|
|
22
|
-
// NB: node resolution (getNode/listNodes) now reads via the daemon API
|
|
23
|
-
// (cliCanvasSource). The tmux/editor placement helpers below are pure tmux
|
|
24
|
-
// verbs sourced from the canvas-free placement-tmux seam, so this leaf reaches
|
|
25
|
-
// ZERO canvas.db/canvas.js code.
|
|
26
|
-
import { inTmux, currentTmux, splitWindow, piCommand } from '../core/runtime/placement-tmux.js';
|
|
27
|
-
const RAIL_WIDTH = 32;
|
|
28
|
-
/** Newest LIVE (active|idle) forest root started in `cwd` — the default node the
|
|
29
|
-
* chat pane attaches to when `--node` is omitted. A root has no parent inside
|
|
30
|
-
* the cwd-scoped set. Returns null when this cwd has no live root. */
|
|
31
|
-
async function defaultChatNode(cwd) {
|
|
32
|
-
const rows = (await cliCanvasSource().listNodes({ status: ['active', 'idle'] })).filter((r) => r.cwd === cwd);
|
|
33
|
-
if (rows.length === 0)
|
|
34
|
-
return null;
|
|
35
|
-
const ids = new Set(rows.map((r) => r.node_id));
|
|
36
|
-
const roots = rows.filter((r) => r.parent === null || !ids.has(r.parent));
|
|
37
|
-
const pool = roots.length > 0 ? roots : rows;
|
|
38
|
-
pool.sort((a, b) => (a.created < b.created ? 1 : -1)); // newest first
|
|
39
|
-
return pool[0].node_id;
|
|
40
|
-
}
|
|
41
|
-
const workspaceEnterLeaf = defineLeaf({
|
|
42
|
-
name: 'enter',
|
|
43
|
-
description: 'enter the editor view — a node rail beside a chat pane, in this window',
|
|
44
|
-
whenToUse: 'you want to work in the agent-centric editor layout: a left rail listing this graph plus the other live agents in this working directory (with ⚑ inbox flags) beside a chat pane attached to a node. Selecting a node in the rail swaps it into the chat pane. Opens in the current tmux window. tmux-only.',
|
|
45
|
-
help: {
|
|
46
|
-
name: 'workspace enter',
|
|
47
|
-
summary: 'split the current window into a left node-rail (the workspace-sidebar view) + a chat pane (surface attach); ↵ in the rail swaps a node into the chat. tmux-only.',
|
|
48
|
-
params: [
|
|
49
|
-
{
|
|
50
|
-
kind: 'flag',
|
|
51
|
-
name: 'node',
|
|
52
|
-
type: 'string',
|
|
53
|
-
required: false,
|
|
54
|
-
constraint: 'Node to attach in the chat pane. Default: the newest live root in this cwd (rail-only, empty chat, if none).',
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
kind: 'flag',
|
|
58
|
-
name: 'width',
|
|
59
|
-
type: 'int',
|
|
60
|
-
required: false,
|
|
61
|
-
default: RAIL_WIDTH,
|
|
62
|
-
constraint: `Rail width in columns (default ${RAIL_WIDTH}).`,
|
|
63
|
-
},
|
|
64
|
-
],
|
|
65
|
-
output: [
|
|
66
|
-
{ name: 'rail', type: 'string', required: false, constraint: 'tmux pane id of the rail.' },
|
|
67
|
-
{ name: 'chat', type: 'string', required: false, constraint: 'node id attached in the chat pane (absent if none).' },
|
|
68
|
-
{ name: 'note', type: 'string', required: false, constraint: 'Set only on the non-TTY/piped path.' },
|
|
69
|
-
],
|
|
70
|
-
outputKind: 'object',
|
|
71
|
-
effects: [
|
|
72
|
-
'Splits a narrow LEFT pane in the current window running the workspace-sidebar view.',
|
|
73
|
-
'Swaps the chosen (or default) node into the current pane as a chat (`crtr surface node focus`), relocating the current pane to the backstage.',
|
|
74
|
-
'Outside a TTY/tmux: prints a notice and exits 0 (no layout change).',
|
|
75
|
-
],
|
|
76
|
-
},
|
|
77
|
-
run: async (input) => {
|
|
78
|
-
const node = input['node'];
|
|
79
|
-
const width = input['width'] ?? RAIL_WIDTH;
|
|
80
|
-
if (!process.stdout.isTTY) {
|
|
81
|
-
return { note: 'surface workspace enter builds a tmux layout — run it in a tmux pane (a TTY), not a pipe.' };
|
|
82
|
-
}
|
|
83
|
-
if (!inTmux()) {
|
|
84
|
-
throw new InputError({
|
|
85
|
-
error: 'not_in_tmux',
|
|
86
|
-
message: 'surface workspace is tmux-only — run it inside the crtr tmux session',
|
|
87
|
-
next: 'Open it from inside tmux.',
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
const here = currentTmux();
|
|
91
|
-
if (here === null) {
|
|
92
|
-
throw new InputError({
|
|
93
|
-
error: 'no_tmux_location',
|
|
94
|
-
message: 'could not resolve the current tmux pane',
|
|
95
|
-
next: 'Run this inside a tmux pane.',
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
// Resolve the chat node (explicit --node, else newest live root here).
|
|
99
|
-
let chatNode = null;
|
|
100
|
-
if (node !== undefined && node !== '') {
|
|
101
|
-
if ((await cliCanvasSource().getNode(node)) === null) {
|
|
102
|
-
throw new InputError({
|
|
103
|
-
error: 'not_found',
|
|
104
|
-
message: `no node: ${node}`,
|
|
105
|
-
received: node,
|
|
106
|
-
next: 'List nodes with `crtr node inspect list`.',
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
chatNode = node;
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
chatNode = await defaultChatNode(process.cwd());
|
|
113
|
-
}
|
|
114
|
-
// 1. The rail — a narrow split to the LEFT of here. It discovers the chat
|
|
115
|
-
// pane itself (the @crtr_node tag), so no pane id is threaded in.
|
|
116
|
-
const railCmd = piCommand(['surface', 'view', 'run', 'workspace-sidebar', '--target', here.pane], 'crtr');
|
|
117
|
-
const rail = splitWindow(here.pane, {
|
|
118
|
-
cwd: process.cwd(),
|
|
119
|
-
env: {},
|
|
120
|
-
command: railCmd,
|
|
121
|
-
before: true,
|
|
122
|
-
size: Math.max(16, width),
|
|
123
|
-
});
|
|
124
|
-
if (rail === null) {
|
|
125
|
-
throw new InputError({
|
|
126
|
-
error: 'split_failed',
|
|
127
|
-
message: 'tmux could not split the rail pane',
|
|
128
|
-
next: 'Check the tmux server is reachable, then retry.',
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
// 2. The chat — swap the node's attach viewer into here's slot. Best-effort:
|
|
132
|
-
// the rail is already up, so a focus failure degrades to a rail-only view
|
|
133
|
-
// the user can drive (↵ a node) rather than aborting the whole layout.
|
|
134
|
-
if (chatNode !== null) {
|
|
135
|
-
await new Promise((resolve) => {
|
|
136
|
-
execFile('crtr', ['surface', 'node', 'focus', chatNode, '--pane', here.pane], () => resolve());
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
return chatNode !== null ? { rail, chat: chatNode } : { rail };
|
|
140
|
-
},
|
|
141
|
-
render: (result) => {
|
|
142
|
-
if (result['note'] !== undefined)
|
|
143
|
-
return String(result['note']);
|
|
144
|
-
const chat = result['chat'];
|
|
145
|
-
return chat !== undefined
|
|
146
|
-
? `Workspace ready — rail ${result['rail']}, chat attached to ${chat}.`
|
|
147
|
-
: `Workspace ready — rail ${result['rail']}. No live agent here yet; press ↵ on a node in the rail to open one.`;
|
|
148
|
-
},
|
|
149
|
-
});
|
|
150
|
-
export function registerWorkspace() {
|
|
151
|
-
return defineBranch({
|
|
152
|
-
name: 'workspace',
|
|
153
|
-
rootEntry: {
|
|
154
|
-
concept: 'the agent-centric editor view — a node rail beside a chat pane, in one tmux window',
|
|
155
|
-
desc: 'enter the editor layout for attached headless nodes',
|
|
156
|
-
useWhen: 'you want an editor-style workspace in tmux: a left rail of this graph + other live agents in this cwd (with ⚑ inbox flags) next to a chat pane attached to a node, where selecting a node in the rail swaps it into the chat. tmux-only.',
|
|
157
|
-
},
|
|
158
|
-
help: {
|
|
159
|
-
name: 'workspace',
|
|
160
|
-
summary: 'enter the agent-centric editor view (node rail + chat pane) in the current tmux window',
|
|
161
|
-
model: 'The branch is a two-pane editor layout: a narrow left rail and a chat pane. The rail shows this graph plus the other live agents in the working directory, and selecting a node swaps it into chat. tmux-only; piped input prints a notice and exits 0.',
|
|
162
|
-
},
|
|
163
|
-
children: [workspaceEnterLeaf],
|
|
164
|
-
});
|
|
165
|
-
}
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
import { test } from 'node:test';
|
|
3
|
-
// @ts-ignore -- chat core is a plain built view module with no generated .d.ts.
|
|
4
|
-
import core from '../../builtin-views/chat/core.mjs';
|
|
5
|
-
import { openLocalStream } from '../view/stream-local.js';
|
|
6
|
-
// Settle a real async open failure: the channel is returned synchronously, then
|
|
7
|
-
// the terminal error/close arrive on later ticks. The no-node existence check now
|
|
8
|
-
// goes through crtrd's API (an async socket round-trip), not a synchronous db
|
|
9
|
-
// read, so we poll to a real settle instead of a single microtask flush.
|
|
10
|
-
const settle = async (pred, timeoutMs = 5000) => {
|
|
11
|
-
const deadline = Date.now() + timeoutMs;
|
|
12
|
-
while (!pred() && Date.now() < deadline) {
|
|
13
|
-
await new Promise((r) => setTimeout(r, 10));
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
test('local invalid/no-node stream failures close asynchronously after the channel returns', async () => {
|
|
17
|
-
// 'not/valid' fails the synchronous target validation; the second is a valid but
|
|
18
|
-
// nonexistent id whose existence check resolves through the API. Both must report
|
|
19
|
-
// a clear terminal error and then close, and neither may fire before the channel
|
|
20
|
-
// is returned. The exact error KIND for the nonexistent id depends on whether
|
|
21
|
-
// crtrd answers (no-node on a 404) or is unreachable (broker-unavailable once the
|
|
22
|
-
// broker socket refuses) — the product contract is only "clear error + prompt
|
|
23
|
-
// close", so we assert generically on the error/close shape.
|
|
24
|
-
for (const target of ['not/valid', 'definitely-not-a-real-node-review-5362b32']) {
|
|
25
|
-
const events = [];
|
|
26
|
-
const channel = openLocalStream({ kind: 'stream', target, role: 'controller' }, {
|
|
27
|
-
onFrame() {
|
|
28
|
-
events.push('frame');
|
|
29
|
-
},
|
|
30
|
-
onClose(reason) {
|
|
31
|
-
events.push(`close:${reason}`);
|
|
32
|
-
},
|
|
33
|
-
onError(err) {
|
|
34
|
-
events.push(`error:${err.kind}`);
|
|
35
|
-
},
|
|
36
|
-
});
|
|
37
|
-
assert.equal(events.length, 0, `${target}: callbacks stay deferred until after openLocalStream returns`);
|
|
38
|
-
assert.equal(typeof channel.close, 'function', `${target}: channel is returned before failure callbacks fire`);
|
|
39
|
-
await settle(() => events.length >= 2);
|
|
40
|
-
assert.ok(events[0]?.startsWith('error:'), `${target}: reports the terminal open failure as an error`);
|
|
41
|
-
assert.equal(events[1]?.startsWith('close:'), true, `${target}: follows with streamClose`);
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
test('reconnect keeps the requested role while welcome and read_only remain authoritative', () => {
|
|
45
|
-
let current = core.init({ target: 'n1', role: 'controller' });
|
|
46
|
-
const sent = [];
|
|
47
|
-
const requestedRoles = [];
|
|
48
|
-
const closed = [];
|
|
49
|
-
const channels = [
|
|
50
|
-
{ id: 'first-channel', send(frame) { sent.push(frame); }, close() { closed.push('first-channel'); } },
|
|
51
|
-
{ id: 'replacement-channel', send(frame) { sent.push(frame); }, close() { closed.push('replacement-channel'); } },
|
|
52
|
-
];
|
|
53
|
-
let nextChannel = 0;
|
|
54
|
-
const ctx = {
|
|
55
|
-
get state() {
|
|
56
|
-
return current;
|
|
57
|
-
},
|
|
58
|
-
set(next) {
|
|
59
|
-
current = typeof next === 'function' ? next(current) : next;
|
|
60
|
-
},
|
|
61
|
-
connect(_stream, opts) {
|
|
62
|
-
requestedRoles.push(opts.role);
|
|
63
|
-
return channels[nextChannel++];
|
|
64
|
-
},
|
|
65
|
-
dispatch(intent) {
|
|
66
|
-
return core.intents[intent](ctx);
|
|
67
|
-
},
|
|
68
|
-
signal: {
|
|
69
|
-
clearBanner() { },
|
|
70
|
-
setBanner() { },
|
|
71
|
-
setStatus() { },
|
|
72
|
-
setSubtitle() { },
|
|
73
|
-
setMode() { },
|
|
74
|
-
quit() { },
|
|
75
|
-
},
|
|
76
|
-
};
|
|
77
|
-
core.intents.refresh(ctx);
|
|
78
|
-
const firstChannel = current.channel;
|
|
79
|
-
assert.equal(current.desiredRole, 'controller');
|
|
80
|
-
assert.equal(current.conn, 'connecting');
|
|
81
|
-
assert.deepEqual(requestedRoles, ['controller']);
|
|
82
|
-
core.intents.streamOpen(ctx, firstChannel);
|
|
83
|
-
core.intents.streamFrame(ctx, { type: 'welcome', role: 'controller', snapshot: { state: {}, messages: [] } });
|
|
84
|
-
assert.equal(current.role, 'controller');
|
|
85
|
-
assert.equal(current.conn, 'open');
|
|
86
|
-
core.intents.reconnect(ctx);
|
|
87
|
-
assert.deepEqual(closed, ['first-channel']);
|
|
88
|
-
assert.equal(current.desiredRole, 'controller');
|
|
89
|
-
assert.equal(current.channel?.id, 'replacement-channel');
|
|
90
|
-
assert.deepEqual(requestedRoles, ['controller', 'controller']);
|
|
91
|
-
const replacementChannel = current.channel;
|
|
92
|
-
core.intents.streamOpen(ctx, replacementChannel);
|
|
93
|
-
core.intents.streamFrame(ctx, { type: 'welcome', role: 'observer', snapshot: { state: {}, messages: [] } });
|
|
94
|
-
assert.equal(current.role, 'observer', 'welcome.role is authoritative for the active connection');
|
|
95
|
-
assert.equal(current.desiredRole, 'controller', 'the requested controller role survives reconnect');
|
|
96
|
-
assert.equal(current.conn, 'open');
|
|
97
|
-
core.intents.streamClose(ctx, { channelId: 'first-channel', reason: 'closed' });
|
|
98
|
-
assert.equal(current.channel, replacementChannel, 'a stale close cannot clear the replacement channel');
|
|
99
|
-
assert.equal(current.conn, 'open');
|
|
100
|
-
core.intents.streamFrame(ctx, { type: 'error', code: 'read_only' });
|
|
101
|
-
core.intents.setDraft(ctx, 'hello');
|
|
102
|
-
core.intents.submitDraft(ctx);
|
|
103
|
-
assert.deepEqual(sent, [], 'read-only welcome state prevents writes');
|
|
104
|
-
assert.match(current.notices.at(-1).text, /read-only — sending is disabled/);
|
|
105
|
-
});
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
// Run with: node --import tsx/esm --test src/core/__tests__/full/consult-startup-failure.test.ts
|
|
2
|
-
//
|
|
3
|
-
// Regression: an exact-model consultation can reject inside runBroker before
|
|
4
|
-
// session_start. Its durable private-fork claim remains active for lifecycle
|
|
5
|
-
// recovery; the daemon sees the fatal model fault, terminalizes the node, and
|
|
6
|
-
// reconciles the armed receipt so the request receives an error.
|
|
7
|
-
import { after, before, test } from 'node:test';
|
|
8
|
-
import assert from 'node:assert/strict';
|
|
9
|
-
import { mkdtempSync, mkdirSync, realpathSync, rmSync, writeFileSync } from 'node:fs';
|
|
10
|
-
import { tmpdir } from 'node:os';
|
|
11
|
-
import { join } from 'node:path';
|
|
12
|
-
import { readFollowUp, registerInboxRoot, requestFollowUp } from '@crouton-kit/humanloop';
|
|
13
|
-
import { closeDb } from '../../canvas/db.js';
|
|
14
|
-
import { armFollowUpWork, getFollowUpWorkRow } from '../../canvas/human-work-outbox.js';
|
|
15
|
-
import { buildLaunchSpec } from '../../runtime/launch.js';
|
|
16
|
-
import { spawnNode } from '../../runtime/nodes.js';
|
|
17
|
-
import { readFault } from '../../runtime/fault.js';
|
|
18
|
-
import { isPidAlive, runStartupRecoverySweep } from '../../../daemon/crtrd.js';
|
|
19
|
-
import { MAX_RESPAWN_ATTEMPTS } from '../../../daemon/fleet.js';
|
|
20
|
-
import { createHarness } from '../helpers/harness.js';
|
|
21
|
-
let h;
|
|
22
|
-
let stateHome;
|
|
23
|
-
let priorStateHome;
|
|
24
|
-
before(async () => {
|
|
25
|
-
priorStateHome = process.env['XDG_STATE_HOME'];
|
|
26
|
-
stateHome = mkdtempSync(join(tmpdir(), 'crtr-consult-fatal-state-'));
|
|
27
|
-
process.env['XDG_STATE_HOME'] = stateHome;
|
|
28
|
-
h = await createHarness({ headless: true, sessionPrefix: 'crtr-consult-fatal' });
|
|
29
|
-
});
|
|
30
|
-
after(async () => {
|
|
31
|
-
if (h !== undefined)
|
|
32
|
-
await h.dispose();
|
|
33
|
-
rmSync(stateHome, { recursive: true, force: true });
|
|
34
|
-
if (priorStateHome === undefined)
|
|
35
|
-
delete process.env['XDG_STATE_HOME'];
|
|
36
|
-
else
|
|
37
|
-
process.env['XDG_STATE_HOME'] = priorStateHome;
|
|
38
|
-
});
|
|
39
|
-
test('pre-session exact-consult failure is terminalized and delivered by daemon supervision', async () => {
|
|
40
|
-
const bridgeId = h.spawnRoot('consult bridge');
|
|
41
|
-
const interactionRoot = realpathSync(mkdtempSync(join(tmpdir(), 'crtr-consult-fatal-root-')));
|
|
42
|
-
const ticketDir = join(interactionRoot, 'ticket-1');
|
|
43
|
-
mkdirSync(ticketDir);
|
|
44
|
-
// humanloop recognizes registered direct children as tickets only once a
|
|
45
|
-
// request descriptor exists; its contents are immaterial to this follow-up.
|
|
46
|
-
writeFileSync(join(ticketDir, 'deck.json'), '{}\n');
|
|
47
|
-
const benignHandler = { command: process.execPath, args: ['-e', ''] };
|
|
48
|
-
const registeredRoot = registerInboxRoot({
|
|
49
|
-
root: interactionRoot,
|
|
50
|
-
owner: 'crouter',
|
|
51
|
-
handler: benignHandler,
|
|
52
|
-
followUpHandler: benignHandler,
|
|
53
|
-
}).root;
|
|
54
|
-
const request = requestFollowUp(registeredRoot, ticketDir, { question: 'What should change?' });
|
|
55
|
-
const branchFile = join(ticketDir, 'branch-point.jsonl');
|
|
56
|
-
writeFileSync(branchFile, `${JSON.stringify({ type: 'session', id: 'source-session' })}\n`);
|
|
57
|
-
// The fake registry observes this sentinel live. Exact mode therefore rejects
|
|
58
|
-
// this captured model during launch rather than substituting or booting
|
|
59
|
-
// model-less — the production failure that originally stranded the request.
|
|
60
|
-
writeFileSync(join(h.home, 'fake-pi.no-auth'), '1');
|
|
61
|
-
const forkId = 'private-fatal-consult';
|
|
62
|
-
const exactModel = 'openai-codex/unavailable:xhigh';
|
|
63
|
-
const { launch } = buildLaunchSpec('general', 'base', {
|
|
64
|
-
lifecycle: 'terminal',
|
|
65
|
-
hasManager: false,
|
|
66
|
-
model: exactModel,
|
|
67
|
-
modelExact: true,
|
|
68
|
-
cwd: process.cwd(),
|
|
69
|
-
profileId: null,
|
|
70
|
-
});
|
|
71
|
-
armFollowUpWork({ nodeId: forkId, root: registeredRoot, dir: ticketDir, requestId: request.requestId });
|
|
72
|
-
spawnNode({
|
|
73
|
-
nodeId: forkId,
|
|
74
|
-
kind: 'general',
|
|
75
|
-
mode: 'base',
|
|
76
|
-
lifecycle: 'terminal',
|
|
77
|
-
cwd: process.cwd(),
|
|
78
|
-
parent: null,
|
|
79
|
-
spawnedBy: bridgeId,
|
|
80
|
-
forkFrom: branchFile,
|
|
81
|
-
modelOverride: exactModel,
|
|
82
|
-
humanWorkTarget: { work_kind: 'follow_up', root: registeredRoot, dir: ticketDir, request_id: request.requestId },
|
|
83
|
-
privateForkPhase: 'fork_pending',
|
|
84
|
-
privateForkRecipe: { kickoff: request.question },
|
|
85
|
-
launch,
|
|
86
|
-
});
|
|
87
|
-
assert.equal(h.node(forkId)?.pi_pid ?? null, null, 'the persisted claim starts with no broker');
|
|
88
|
-
// This row models a fork_pending claim left by the prior daemon epoch. The
|
|
89
|
-
// explicit startup sweep — not a recurring liveness tick — classifies row 7
|
|
90
|
-
// and launches its bounded fresh retry through the harness-owned fleet.
|
|
91
|
-
await runStartupRecoverySweep(h.fleet);
|
|
92
|
-
await h.waitFor(() => h.node(forkId)?.pi_pid !== null, { label: 'startup sweep launched the durable pending claim' });
|
|
93
|
-
await h.waitFor(() => readFault(forkId)?.kind === 'model-not-found', { label: 'fatal exact-model fault recorded' });
|
|
94
|
-
// A broker writes the launch fault immediately before it exits. Its real
|
|
95
|
-
// ChildProcess exit removes the fleet entry and enqueues a policy job.
|
|
96
|
-
await h.waitFor(() => {
|
|
97
|
-
const pid = h.node(forkId)?.pi_pid;
|
|
98
|
-
return pid !== null && pid !== undefined && !isPidAlive(pid) ? true : null;
|
|
99
|
-
}, { label: 'fatal consult broker exited after recording its launch fault' });
|
|
100
|
-
await h.waitFor(() => !h.fleet.has(forkId) ? true : null, { label: 'fatal consult exit left the live fleet' });
|
|
101
|
-
await h.drainFleet();
|
|
102
|
-
// Design flow B row 7: a fork_pending death is a bounded fresh retry of the
|
|
103
|
-
// immutable fork birth — throttled, NOT an immediate boot failure. Every
|
|
104
|
-
// further short-lived exit increments the same counter, and at
|
|
105
|
-
// MAX_RESPAWN_ATTEMPTS the respawn loop terminalizes: transition('crash') +
|
|
106
|
-
// receipt reconcile + surfaceBootFailure + doctrine wake. The real exit above
|
|
107
|
-
// counted one failure; deliver the remaining short exits synthetically
|
|
108
|
-
// through the sanctioned seam (§H mode b) so the cap is reached without
|
|
109
|
-
// minutes of real backoff — each delivery cancels the pending backoff timer,
|
|
110
|
-
// so no intermediate respawn ever launches.
|
|
111
|
-
for (let i = 1; i < MAX_RESPAWN_ATTEMPTS; i++) {
|
|
112
|
-
await h.deliverExit(forkId, { code: 1, signal: null });
|
|
113
|
-
}
|
|
114
|
-
await h.waitFor(() => {
|
|
115
|
-
closeDb();
|
|
116
|
-
return getFollowUpWorkRow(forkId)?.status === 'errored';
|
|
117
|
-
}, { timeoutMs: 5_000, label: 'fatal consult receipt settled at throttle exhaustion' });
|
|
118
|
-
assert.equal(h.status(forkId), 'dead', 'the failed consult fork is terminalized after the fatal launch fault');
|
|
119
|
-
const followUp = readFollowUp(ticketDir);
|
|
120
|
-
assert.equal(followUp.request?.state, 'terminal', 'the humanloop request is no longer running');
|
|
121
|
-
assert.equal(followUp.result?.requestId, request.requestId);
|
|
122
|
-
assert.equal(followUp.result?.status, 'error');
|
|
123
|
-
rmSync(interactionRoot, { recursive: true, force: true });
|
|
124
|
-
});
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
// human-work-outbox.test.ts — permanent storage compatibility invariants:
|
|
2
|
-
// legacy follow-up receipts remain retryable and prune-safe, while Visual work
|
|
3
|
-
// is uniquely bound and invisible to old follow-up selectors.
|
|
4
|
-
import { test, before, beforeEach, after } from 'node:test';
|
|
5
|
-
import assert from 'node:assert/strict';
|
|
6
|
-
import { mkdtempSync, rmSync, mkdirSync, existsSync } from 'node:fs';
|
|
7
|
-
import { tmpdir } from 'node:os';
|
|
8
|
-
import { join } from 'node:path';
|
|
9
|
-
import { DatabaseSync } from 'node:sqlite';
|
|
10
|
-
import { createNode, getRow, pruneNodes } from '../canvas.js';
|
|
11
|
-
import { closeDb, MIGRATIONS, migrate, openDb } from '../db.js';
|
|
12
|
-
import { nodeDir } from '../paths.js';
|
|
13
|
-
import { pushFinal } from '../../feed/feed.js';
|
|
14
|
-
import { claimVisualWork, getFollowUpWorkRow, getVisualWorkByRequest, listPendingFollowUpWork, reconcileFollowUpWork, reconcileVisualWork, } from '../human-work-outbox.js';
|
|
15
|
-
let home;
|
|
16
|
-
const DAY = 86_400_000;
|
|
17
|
-
const old = () => new Date(Date.now() - 30 * DAY).toISOString();
|
|
18
|
-
const now = () => new Date().toISOString();
|
|
19
|
-
function node(id, over = {}) {
|
|
20
|
-
return {
|
|
21
|
-
node_id: id,
|
|
22
|
-
name: id,
|
|
23
|
-
created: now(),
|
|
24
|
-
cwd: '/tmp/work',
|
|
25
|
-
kind: 'general',
|
|
26
|
-
mode: 'base',
|
|
27
|
-
lifecycle: 'terminal',
|
|
28
|
-
status: 'active',
|
|
29
|
-
...over,
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
function insertLegacyFollowUp(nodeId, dir, root, requestId) {
|
|
33
|
-
openDb()
|
|
34
|
-
.prepare('INSERT INTO consult_outbox (node_id, dir, root, request_id, status, final_report, updated_at) VALUES (?, ?, ?, ?, ?, NULL, ?)')
|
|
35
|
-
.run(nodeId, dir, root, requestId, 'armed', now());
|
|
36
|
-
}
|
|
37
|
-
before(() => {
|
|
38
|
-
home = mkdtempSync(join(tmpdir(), 'crtr-human-work-outbox-'));
|
|
39
|
-
process.env['CRTR_HOME'] = home;
|
|
40
|
-
});
|
|
41
|
-
beforeEach(() => {
|
|
42
|
-
closeDb();
|
|
43
|
-
rmSync(home, { recursive: true, force: true });
|
|
44
|
-
});
|
|
45
|
-
after(() => {
|
|
46
|
-
closeDb();
|
|
47
|
-
rmSync(home, { recursive: true, force: true });
|
|
48
|
-
delete process.env['CRTR_HOME'];
|
|
49
|
-
});
|
|
50
|
-
test('a v18 follow-up row upgrades with its follow_up default', () => {
|
|
51
|
-
mkdirSync(home, { recursive: true });
|
|
52
|
-
const db = new DatabaseSync(join(home, 'v18-canvas.db'));
|
|
53
|
-
try {
|
|
54
|
-
for (const migration of MIGRATIONS.slice(0, 18))
|
|
55
|
-
migration(db);
|
|
56
|
-
db.exec('PRAGMA user_version = 18');
|
|
57
|
-
db.prepare("INSERT INTO consult_outbox (node_id, dir, root, request_id, status, updated_at) VALUES ('legacy-node', '/ticket', '/root', 'legacy-request', 'armed', '2026-01-01T00:00:00.000Z')").run();
|
|
58
|
-
migrate(db);
|
|
59
|
-
const row = db.prepare("SELECT work_kind, status FROM consult_outbox WHERE node_id = 'legacy-node'").get();
|
|
60
|
-
assert.equal(row.work_kind, 'follow_up');
|
|
61
|
-
assert.equal(row.status, 'armed');
|
|
62
|
-
}
|
|
63
|
-
finally {
|
|
64
|
-
db.close();
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
test('legacy follow-up insert, feed promotion, and reconciliation retain their receipt behavior', async () => {
|
|
68
|
-
const root = join(home, 'unregistered-root');
|
|
69
|
-
const dir = join(root, 'ticket-1');
|
|
70
|
-
mkdirSync(dir, { recursive: true });
|
|
71
|
-
createNode(node('fork-1', { status: 'dead' }));
|
|
72
|
-
insertLegacyFollowUp('fork-1', dir, root, 'req-1');
|
|
73
|
-
reconcileFollowUpWork();
|
|
74
|
-
const retryable = getFollowUpWorkRow('fork-1');
|
|
75
|
-
assert.ok(retryable !== null);
|
|
76
|
-
assert.equal(retryable.status, 'armed', 'a rejected follow-up publish stays retryable');
|
|
77
|
-
createNode(node('fork-2', { created: old() }));
|
|
78
|
-
insertLegacyFollowUp('fork-2', dir, root, 'req-2');
|
|
79
|
-
await pushFinal('fork-2', 'follow-up result');
|
|
80
|
-
assert.equal(getFollowUpWorkRow('fork-2')?.status, 'pending');
|
|
81
|
-
assert.deepEqual(listPendingFollowUpWork().map((row) => row.node_id), ['fork-2']);
|
|
82
|
-
const result = pruneNodes({ ttlDays: 14 });
|
|
83
|
-
assert.deepEqual(result.pruned, [], 'a legacy pending receipt preserves its node and report payload');
|
|
84
|
-
assert.ok(getRow('fork-2') !== null);
|
|
85
|
-
assert.ok(existsSync(nodeDir('fork-2')));
|
|
86
|
-
});
|
|
87
|
-
test('Visual claims are unique and legacy armed/pending selectors are blind to them', () => {
|
|
88
|
-
const root = join(home, 'root');
|
|
89
|
-
const dir = join(root, 'ticket-visual');
|
|
90
|
-
mkdirSync(dir, { recursive: true });
|
|
91
|
-
insertLegacyFollowUp('follow-up-1', dir, root, 'follow-up-request');
|
|
92
|
-
const binding = {
|
|
93
|
-
nodeId: 'visual-1',
|
|
94
|
-
dir,
|
|
95
|
-
root,
|
|
96
|
-
requestId: 'visual-request',
|
|
97
|
-
interactionId: 'interaction-1',
|
|
98
|
-
generationId: 'generation-1',
|
|
99
|
-
interactionSnapshot: '{"id":"interaction-1","body":"Visualize this"}',
|
|
100
|
-
handlerCommand: '/absolute/crtr',
|
|
101
|
-
handlerArgs: ['human', '_visual'],
|
|
102
|
-
claimToken: 'claim-token',
|
|
103
|
-
};
|
|
104
|
-
assert.equal(claimVisualWork(binding).created, true);
|
|
105
|
-
assert.equal(claimVisualWork({ ...binding, nodeId: 'unused-duplicate-node' }).created, false);
|
|
106
|
-
assert.throws(() => claimVisualWork({ ...binding, nodeId: 'conflicting-node', generationId: 'generation-2' }), /conflicting Visual work claim/);
|
|
107
|
-
assert.throws(() => openDb()
|
|
108
|
-
.prepare("INSERT INTO consult_outbox (node_id, dir, root, request_id, work_kind, status, updated_at) VALUES (?, ?, ?, ?, 'visual', 'visual_armed', ?)")
|
|
109
|
-
.run('duplicate-visual-node', dir, root, binding.requestId, now()), /UNIQUE constraint failed/);
|
|
110
|
-
assert.equal(getVisualWorkByRequest(dir, binding.requestId)?.status, 'visual_armed');
|
|
111
|
-
createNode(node('visual-1', {
|
|
112
|
-
status: 'canceled',
|
|
113
|
-
human_work_target: { work_kind: 'visual', dir, request_id: binding.requestId, root },
|
|
114
|
-
private_fork_phase: 'fork_pending',
|
|
115
|
-
}));
|
|
116
|
-
reconcileVisualWork();
|
|
117
|
-
assert.equal(getVisualWorkByRequest(dir, binding.requestId)?.status, 'visual_armed', 'the deliberate inert pre-launch fork remains launchable');
|
|
118
|
-
const legacy = openDb()
|
|
119
|
-
.prepare("SELECT node_id FROM consult_outbox WHERE status IN ('armed', 'pending') ORDER BY node_id")
|
|
120
|
-
.all();
|
|
121
|
-
assert.deepEqual(legacy.map((row) => row.node_id), ['follow-up-1']);
|
|
122
|
-
assert.deepEqual(listPendingFollowUpWork(), []);
|
|
123
|
-
});
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
export type HumanWorkKind = 'follow_up' | 'visual';
|
|
2
|
-
export type FollowUpWorkStatus = 'armed' | 'pending' | 'acked' | 'errored' | 'canceled';
|
|
3
|
-
export type VisualWorkStatus = 'visual_armed' | 'visual_pending' | 'visual_retired';
|
|
4
|
-
export type HumanWorkStatus = FollowUpWorkStatus | VisualWorkStatus;
|
|
5
|
-
export interface HumanWorkRow {
|
|
6
|
-
node_id: string;
|
|
7
|
-
dir: string;
|
|
8
|
-
root: string;
|
|
9
|
-
request_id: string;
|
|
10
|
-
work_kind: HumanWorkKind;
|
|
11
|
-
status: HumanWorkStatus;
|
|
12
|
-
final_report: string | null;
|
|
13
|
-
interaction_id: string | null;
|
|
14
|
-
generation_id: string | null;
|
|
15
|
-
interaction_snapshot: string | null;
|
|
16
|
-
handler_command: string | null;
|
|
17
|
-
handler_args_json: string | null;
|
|
18
|
-
claim_token: string | null;
|
|
19
|
-
updated_at: string;
|
|
20
|
-
}
|
|
21
|
-
export interface VisualWorkBinding {
|
|
22
|
-
nodeId: string;
|
|
23
|
-
dir: string;
|
|
24
|
-
root: string;
|
|
25
|
-
requestId: string;
|
|
26
|
-
interactionId: string;
|
|
27
|
-
generationId: string;
|
|
28
|
-
interactionSnapshot: string;
|
|
29
|
-
handlerCommand: string;
|
|
30
|
-
handlerArgs: readonly string[];
|
|
31
|
-
claimToken: string;
|
|
32
|
-
}
|
|
33
|
-
export interface VisualWorkClaim {
|
|
34
|
-
row: HumanWorkRow;
|
|
35
|
-
created: boolean;
|
|
36
|
-
}
|
|
37
|
-
/** Insert a follow-up receipt before its fork launches. `work_kind` is explicit
|
|
38
|
-
* even though the migration default preserves old inserts, so new code never
|
|
39
|
-
* depends on a compatibility default. */
|
|
40
|
-
export declare function armFollowUpWork(opts: {
|
|
41
|
-
nodeId: string;
|
|
42
|
-
dir: string;
|
|
43
|
-
root: string;
|
|
44
|
-
requestId: string;
|
|
45
|
-
}): void;
|
|
46
|
-
/** Promote only follow-up work inside the canonical-final transaction. */
|
|
47
|
-
export declare function promoteFollowUpWork(nodeId: string, finalReportBasename: string): boolean;
|
|
48
|
-
export declare function ackFollowUpWork(nodeId: string): void;
|
|
49
|
-
export declare function errorFollowUpWork(nodeId: string): void;
|
|
50
|
-
export declare function cancelFollowUpWork(nodeId: string): void;
|
|
51
|
-
/** Create or return the one immutable Visual claim for a request. A conflicting
|
|
52
|
-
* duplicate fails closed; a byte-identical duplicate reuses its original row. */
|
|
53
|
-
export declare function claimVisualWork(binding: VisualWorkBinding): VisualWorkClaim;
|
|
54
|
-
/** The future Visual finalizer may promote only its exact armed claim. */
|
|
55
|
-
export declare function promoteVisualWork(nodeId: string, finalReportBasename: string): boolean;
|
|
56
|
-
/** Retire only an exact Visual request binding; cancellation never creates work. */
|
|
57
|
-
export declare function retireVisualWork(dir: string, requestId: string): boolean;
|
|
58
|
-
export declare function getHumanWorkRow(nodeId: string): HumanWorkRow | null;
|
|
59
|
-
export declare function getFollowUpWorkRow(nodeId: string): HumanWorkRow | null;
|
|
60
|
-
export declare function listActiveVisualWorkByDir(dir: string): HumanWorkRow[];
|
|
61
|
-
export declare function getVisualWorkByRequest(dir: string, requestId: string): HumanWorkRow | null;
|
|
62
|
-
export declare function listPendingFollowUpWork(): HumanWorkRow[];
|
|
63
|
-
export declare function listArmedFollowUpWork(): HumanWorkRow[];
|
|
64
|
-
export declare function getActiveFollowUpWorkByRequest(dir: string, requestId: string): HumanWorkRow | null;
|
|
65
|
-
export declare function listActiveFollowUpWorkByDir(dir: string): HumanWorkRow[];
|
|
66
|
-
/** Deliver one pending follow-up receipt. */
|
|
67
|
-
export declare function dispatchFollowUpWork(nodeId: string): void;
|
|
68
|
-
/** Dispatch a checked canonical final as the single correlated Visual result. */
|
|
69
|
-
export declare function dispatchVisualWork(nodeId: string): void;
|
|
70
|
-
/** Reconcile this durable lane after a dead private child or interrupted dispatch. */
|
|
71
|
-
export declare function reconcileVisualWork(): void;
|
|
72
|
-
/** Reconcile only follow-up work. */
|
|
73
|
-
export declare function reconcileFollowUpWork(): void;
|