@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
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { DatabaseSync } from 'node:sqlite';
|
|
2
|
+
import { type CommentAnchor, type CommentAuthorKind, type CommentStatus, type ReviewComment, type ReviewCommentEvent } from './types.js';
|
|
3
|
+
interface Actor {
|
|
4
|
+
kind: CommentAuthorKind;
|
|
5
|
+
node_id: string | null;
|
|
6
|
+
}
|
|
7
|
+
interface CommentMutationArgs {
|
|
8
|
+
actor: Actor;
|
|
9
|
+
operation_id: string;
|
|
10
|
+
if_revision?: number;
|
|
11
|
+
}
|
|
12
|
+
export declare function createComment(args: {
|
|
13
|
+
review_id: string;
|
|
14
|
+
text: string;
|
|
15
|
+
anchor: CommentAnchor;
|
|
16
|
+
line_text: string;
|
|
17
|
+
doc_hash: string;
|
|
18
|
+
actor: Actor;
|
|
19
|
+
operation_id: string;
|
|
20
|
+
}): {
|
|
21
|
+
comment: ReviewComment;
|
|
22
|
+
changed: true;
|
|
23
|
+
};
|
|
24
|
+
export declare function editComment(commentIdValue: string, args: {
|
|
25
|
+
text: string;
|
|
26
|
+
actor: Actor;
|
|
27
|
+
operation_id: string;
|
|
28
|
+
if_revision?: number;
|
|
29
|
+
}): {
|
|
30
|
+
comment: ReviewComment;
|
|
31
|
+
changed: boolean;
|
|
32
|
+
};
|
|
33
|
+
export declare function resolveComment(commentIdValue: string, args: CommentMutationArgs): {
|
|
34
|
+
comment: ReviewComment;
|
|
35
|
+
changed: boolean;
|
|
36
|
+
};
|
|
37
|
+
export declare function reopenComment(commentIdValue: string, args: CommentMutationArgs): {
|
|
38
|
+
comment: ReviewComment;
|
|
39
|
+
changed: boolean;
|
|
40
|
+
};
|
|
41
|
+
export declare function deleteComment(commentIdValue: string, args: CommentMutationArgs): {
|
|
42
|
+
comment: ReviewComment;
|
|
43
|
+
changed: boolean;
|
|
44
|
+
};
|
|
45
|
+
export declare function listComments(reviewId: string, opts?: {
|
|
46
|
+
status?: CommentStatus | 'all';
|
|
47
|
+
}): ReviewComment[];
|
|
48
|
+
export declare function getComment(commentIdValue: string): ReviewComment | null;
|
|
49
|
+
export declare function listCommentEvents(commentIdValue: string): ReviewCommentEvent[];
|
|
50
|
+
export declare function listReviewEvents(reviewId: string, opts: {
|
|
51
|
+
since_seq?: number;
|
|
52
|
+
limit?: number;
|
|
53
|
+
}): {
|
|
54
|
+
events: ReviewCommentEvent[];
|
|
55
|
+
next_since_seq: number;
|
|
56
|
+
};
|
|
57
|
+
export declare function snapshotCommentsLocked(db: DatabaseSync, reviewId: string): {
|
|
58
|
+
comments: import('../human/types.js').FeedbackComment[];
|
|
59
|
+
total: number;
|
|
60
|
+
unresolved: number;
|
|
61
|
+
};
|
|
62
|
+
export declare function appendDeliveryEvent(args: {
|
|
63
|
+
review_id: string;
|
|
64
|
+
comment_id: string;
|
|
65
|
+
kind: 'notified' | 'notify_failed';
|
|
66
|
+
payload: unknown;
|
|
67
|
+
operation_id: string;
|
|
68
|
+
}): void;
|
|
69
|
+
export {};
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import { randomBytes } from 'node:crypto';
|
|
2
|
+
import { openDb, withCanvasWrite } from '../canvas/db.js';
|
|
3
|
+
import { nowIso } from '../fs-utils.js';
|
|
4
|
+
import { signalReviewActivity } from './signal.js';
|
|
5
|
+
import { COMMENT_EVENTS_PAGE_DEFAULT, COMMENT_EVENTS_PAGE_MAX, COMMENT_LINE_TEXT_MAX, COMMENT_TEXT_MAX, LIVE_COMMENTS_MAX, ReviewOperationError, } from './types.js';
|
|
6
|
+
function commentFromRow(row) {
|
|
7
|
+
return {
|
|
8
|
+
comment_id: row.comment_id,
|
|
9
|
+
review_id: row.review_id,
|
|
10
|
+
status: row.status,
|
|
11
|
+
revision: row.revision,
|
|
12
|
+
text: row.text,
|
|
13
|
+
anchor: {
|
|
14
|
+
line: row.anchor_line,
|
|
15
|
+
end_line: row.anchor_end_line,
|
|
16
|
+
...(row.anchor_col_start === null ? {} : { col_start: row.anchor_col_start }),
|
|
17
|
+
...(row.anchor_col_end === null ? {} : { col_end: row.anchor_col_end }),
|
|
18
|
+
...(row.anchor_quote === null ? {} : { quote: row.anchor_quote }),
|
|
19
|
+
},
|
|
20
|
+
anchor_state: row.anchor_state,
|
|
21
|
+
anchor_line_text: row.anchor_line_text,
|
|
22
|
+
anchor_doc_hash: row.anchor_doc_hash,
|
|
23
|
+
author: { kind: row.author_kind, node_id: row.author_node_id },
|
|
24
|
+
updated_by: { kind: row.updated_by_kind, node_id: row.updated_by_node_id },
|
|
25
|
+
created_at: row.created_at,
|
|
26
|
+
updated_at: row.updated_at,
|
|
27
|
+
resolved_at: row.resolved_at,
|
|
28
|
+
deleted_at: row.deleted_at,
|
|
29
|
+
created_seq: row.created_seq,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function eventFromRow(row) {
|
|
33
|
+
return {
|
|
34
|
+
seq: row.seq,
|
|
35
|
+
review_id: row.review_id,
|
|
36
|
+
comment_id: row.comment_id,
|
|
37
|
+
kind: row.kind,
|
|
38
|
+
state_change: row.state_change === 0 ? 0 : 1,
|
|
39
|
+
revision_after: row.revision_after,
|
|
40
|
+
actor: { kind: row.actor_kind, node_id: row.actor_node_id },
|
|
41
|
+
at: row.at,
|
|
42
|
+
operation_id: row.operation_id,
|
|
43
|
+
...(row.payload === null ? {} : { payload: JSON.parse(row.payload) }),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function json(value) {
|
|
47
|
+
return JSON.stringify(value);
|
|
48
|
+
}
|
|
49
|
+
function commentId() {
|
|
50
|
+
let id;
|
|
51
|
+
do
|
|
52
|
+
id = randomBytes(16).toString('hex');
|
|
53
|
+
while (/^0+$/.test(id));
|
|
54
|
+
return id;
|
|
55
|
+
}
|
|
56
|
+
function trimText(text) {
|
|
57
|
+
const trimmed = text.trim();
|
|
58
|
+
if (trimmed === '')
|
|
59
|
+
throw new Error('comment text must not be empty');
|
|
60
|
+
const received = Buffer.byteLength(trimmed, 'utf8');
|
|
61
|
+
if (received > COMMENT_TEXT_MAX) {
|
|
62
|
+
throw new ReviewOperationError('text_too_long', 'comment text exceeds the maximum length', {
|
|
63
|
+
limit: COMMENT_TEXT_MAX,
|
|
64
|
+
received,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return trimmed;
|
|
68
|
+
}
|
|
69
|
+
function truncateUtf8(text, maxBytes) {
|
|
70
|
+
if (Buffer.byteLength(text, 'utf8') <= maxBytes)
|
|
71
|
+
return text;
|
|
72
|
+
const marker = '… [truncated]';
|
|
73
|
+
const markerBytes = Buffer.byteLength(marker, 'utf8');
|
|
74
|
+
const bytes = Buffer.from(text, 'utf8');
|
|
75
|
+
let end = Math.max(0, maxBytes - markerBytes);
|
|
76
|
+
while (end > 0 && (bytes[end] & 0xc0) === 0x80)
|
|
77
|
+
end -= 1;
|
|
78
|
+
return `${bytes.subarray(0, end).toString('utf8')}${marker}`;
|
|
79
|
+
}
|
|
80
|
+
function getStoredComment(db, commentIdValue) {
|
|
81
|
+
return db.prepare('SELECT * FROM review_comments WHERE comment_id = ?').get(commentIdValue) ?? null;
|
|
82
|
+
}
|
|
83
|
+
function requireStoredComment(db, commentIdValue) {
|
|
84
|
+
const row = getStoredComment(db, commentIdValue);
|
|
85
|
+
if (row === null) {
|
|
86
|
+
throw new ReviewOperationError('unknown_comment', 'comment was not found', { received: commentIdValue });
|
|
87
|
+
}
|
|
88
|
+
return row;
|
|
89
|
+
}
|
|
90
|
+
function assertReviewExists(db, reviewId) {
|
|
91
|
+
const row = db.prepare('SELECT review_id FROM reviews WHERE review_id = ?').get(reviewId);
|
|
92
|
+
if (row === undefined) {
|
|
93
|
+
throw new ReviewOperationError('unknown_review', 'review was not found', { received: reviewId });
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function assertRevision(row, expected) {
|
|
97
|
+
if (expected !== undefined && expected !== row.revision) {
|
|
98
|
+
throw new ReviewOperationError('stale_comment', 'comment revision is stale', {
|
|
99
|
+
revision: row.revision,
|
|
100
|
+
text: row.text,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function appendStateEvent(db, args) {
|
|
105
|
+
const result = db.prepare(`
|
|
106
|
+
INSERT INTO review_comment_events
|
|
107
|
+
(review_id, comment_id, kind, state_change, revision_after, actor_kind, actor_node_id, at, operation_id, payload)
|
|
108
|
+
VALUES (?, ?, ?, 1, ?, ?, ?, ?, ?, ?)
|
|
109
|
+
`).run(args.row.review_id, args.row.comment_id, args.kind, args.row.revision, args.actor.kind, args.actor.node_id, args.at, args.operation_id, json(args.payload));
|
|
110
|
+
return Number(result.lastInsertRowid);
|
|
111
|
+
}
|
|
112
|
+
function updateComment(db, row, fields, actor, at) {
|
|
113
|
+
const revision = row.revision + 1;
|
|
114
|
+
db.prepare(`
|
|
115
|
+
UPDATE review_comments
|
|
116
|
+
SET status = ?, revision = ?, text = ?, updated_by_kind = ?, updated_by_node_id = ?,
|
|
117
|
+
updated_at = ?, resolved_at = ?, deleted_at = ?
|
|
118
|
+
WHERE comment_id = ?
|
|
119
|
+
`).run(fields.status ?? row.status, revision, fields.text ?? row.text, actor.kind, actor.node_id, at, fields.resolved_at === undefined ? row.resolved_at : fields.resolved_at, fields.deleted_at === undefined ? row.deleted_at : fields.deleted_at, row.comment_id);
|
|
120
|
+
return { ...row, ...fields, revision, updated_by_kind: actor.kind, updated_by_node_id: actor.node_id, updated_at: at };
|
|
121
|
+
}
|
|
122
|
+
function completeMutation(result) {
|
|
123
|
+
if (result.changed)
|
|
124
|
+
signalReviewActivity();
|
|
125
|
+
return result;
|
|
126
|
+
}
|
|
127
|
+
export function createComment(args) {
|
|
128
|
+
const result = withCanvasWrite((db) => {
|
|
129
|
+
assertReviewExists(db, args.review_id);
|
|
130
|
+
const live = db.prepare("SELECT COUNT(*) AS count FROM review_comments WHERE review_id = ? AND status != 'deleted'").get(args.review_id);
|
|
131
|
+
if (Number(live.count) >= LIVE_COMMENTS_MAX) {
|
|
132
|
+
throw new ReviewOperationError('comment_limit_reached', 'review comment limit reached', {
|
|
133
|
+
limit: LIVE_COMMENTS_MAX,
|
|
134
|
+
live: Number(live.count),
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
const text = trimText(args.text);
|
|
138
|
+
const lineText = truncateUtf8(args.line_text, COMMENT_LINE_TEXT_MAX);
|
|
139
|
+
const at = nowIso();
|
|
140
|
+
let id = commentId();
|
|
141
|
+
while (getStoredComment(db, id) !== null)
|
|
142
|
+
id = commentId();
|
|
143
|
+
const inserted = db.prepare(`
|
|
144
|
+
INSERT INTO review_comments
|
|
145
|
+
(comment_id, review_id, status, revision, text, anchor_line, anchor_end_line,
|
|
146
|
+
anchor_col_start, anchor_col_end, anchor_quote, anchor_line_text, anchor_doc_hash, anchor_state,
|
|
147
|
+
author_kind, author_node_id, updated_by_kind, updated_by_node_id, created_at,
|
|
148
|
+
updated_at, resolved_at, deleted_at, created_seq)
|
|
149
|
+
VALUES (?, ?, 'open', 1, ?, ?, ?, ?, ?, ?, ?, ?, 'live', ?, ?, ?, ?, ?, ?, NULL, NULL, 0)
|
|
150
|
+
`).run(id, args.review_id, text, args.anchor.line, args.anchor.end_line, args.anchor.col_start ?? null, args.anchor.col_end ?? null, args.anchor.quote ?? null, lineText, args.doc_hash, args.actor.kind, args.actor.node_id, args.actor.kind, args.actor.node_id, at, at);
|
|
151
|
+
if (inserted.changes !== 1)
|
|
152
|
+
throw new Error('failed to insert review comment');
|
|
153
|
+
const row = getStoredComment(db, id);
|
|
154
|
+
const seq = appendStateEvent(db, {
|
|
155
|
+
row,
|
|
156
|
+
kind: 'created',
|
|
157
|
+
actor: args.actor,
|
|
158
|
+
operation_id: args.operation_id,
|
|
159
|
+
at,
|
|
160
|
+
payload: { text, anchor: args.anchor, line_text: lineText, doc_hash: args.doc_hash },
|
|
161
|
+
});
|
|
162
|
+
db.prepare('UPDATE review_comments SET created_seq = ? WHERE comment_id = ?').run(seq, id);
|
|
163
|
+
return { comment: commentFromRow({ ...row, created_seq: seq }), changed: true };
|
|
164
|
+
});
|
|
165
|
+
signalReviewActivity();
|
|
166
|
+
return result;
|
|
167
|
+
}
|
|
168
|
+
export function editComment(commentIdValue, args) {
|
|
169
|
+
const result = withCanvasWrite((db) => {
|
|
170
|
+
const row = requireStoredComment(db, commentIdValue);
|
|
171
|
+
if (row.status === 'deleted')
|
|
172
|
+
throw new ReviewOperationError('comment_deleted', 'comment is a deleted tombstone', { comment_id: row.comment_id, deleted_at: row.deleted_at });
|
|
173
|
+
const text = trimText(args.text);
|
|
174
|
+
if (row.text === text)
|
|
175
|
+
return { comment: commentFromRow(row), changed: false };
|
|
176
|
+
assertRevision(row, args.if_revision);
|
|
177
|
+
const at = nowIso();
|
|
178
|
+
const previousAnchor = commentFromRow(row).anchor;
|
|
179
|
+
const updated = updateComment(db, row, { text }, args.actor, at);
|
|
180
|
+
appendStateEvent(db, {
|
|
181
|
+
row: updated,
|
|
182
|
+
kind: 'edited',
|
|
183
|
+
actor: args.actor,
|
|
184
|
+
operation_id: args.operation_id,
|
|
185
|
+
at,
|
|
186
|
+
payload: {
|
|
187
|
+
previous_text: row.text,
|
|
188
|
+
text,
|
|
189
|
+
previous_anchor: previousAnchor,
|
|
190
|
+
anchor: commentFromRow(updated).anchor,
|
|
191
|
+
},
|
|
192
|
+
});
|
|
193
|
+
return { comment: commentFromRow(updated), changed: true };
|
|
194
|
+
});
|
|
195
|
+
return completeMutation(result);
|
|
196
|
+
}
|
|
197
|
+
function transitionComment(commentIdValue, args, target, kind) {
|
|
198
|
+
const result = withCanvasWrite((db) => {
|
|
199
|
+
const row = requireStoredComment(db, commentIdValue);
|
|
200
|
+
if (row.status === 'deleted') {
|
|
201
|
+
if (target === 'deleted')
|
|
202
|
+
return { comment: commentFromRow(row), changed: false };
|
|
203
|
+
throw new ReviewOperationError('comment_deleted', 'comment is a deleted tombstone', { comment_id: row.comment_id, deleted_at: row.deleted_at });
|
|
204
|
+
}
|
|
205
|
+
if (row.status === target)
|
|
206
|
+
return { comment: commentFromRow(row), changed: false };
|
|
207
|
+
assertRevision(row, args.if_revision);
|
|
208
|
+
const at = nowIso();
|
|
209
|
+
const updated = updateComment(db, row, {
|
|
210
|
+
status: target,
|
|
211
|
+
resolved_at: target === 'resolved' ? at : target === 'open' ? null : undefined,
|
|
212
|
+
deleted_at: target === 'deleted' ? at : undefined,
|
|
213
|
+
}, args.actor, at);
|
|
214
|
+
appendStateEvent(db, {
|
|
215
|
+
row: updated,
|
|
216
|
+
kind,
|
|
217
|
+
actor: args.actor,
|
|
218
|
+
operation_id: args.operation_id,
|
|
219
|
+
at,
|
|
220
|
+
payload: {
|
|
221
|
+
previous_status: row.status,
|
|
222
|
+
status: target,
|
|
223
|
+
previous_text: row.text,
|
|
224
|
+
text: updated.text,
|
|
225
|
+
previous_anchor: commentFromRow(row).anchor,
|
|
226
|
+
anchor: commentFromRow(updated).anchor,
|
|
227
|
+
},
|
|
228
|
+
});
|
|
229
|
+
return { comment: commentFromRow(updated), changed: true };
|
|
230
|
+
});
|
|
231
|
+
return completeMutation(result);
|
|
232
|
+
}
|
|
233
|
+
export function resolveComment(commentIdValue, args) {
|
|
234
|
+
return transitionComment(commentIdValue, args, 'resolved', 'resolved');
|
|
235
|
+
}
|
|
236
|
+
export function reopenComment(commentIdValue, args) {
|
|
237
|
+
return transitionComment(commentIdValue, args, 'open', 'reopened');
|
|
238
|
+
}
|
|
239
|
+
export function deleteComment(commentIdValue, args) {
|
|
240
|
+
return transitionComment(commentIdValue, args, 'deleted', 'deleted');
|
|
241
|
+
}
|
|
242
|
+
export function listComments(reviewId, opts) {
|
|
243
|
+
const db = openDb();
|
|
244
|
+
const status = opts?.status;
|
|
245
|
+
const rows = status === undefined
|
|
246
|
+
? db.prepare("SELECT * FROM review_comments WHERE review_id = ? AND status != 'deleted' ORDER BY anchor_line, created_seq").all(reviewId)
|
|
247
|
+
: status === 'all'
|
|
248
|
+
? db.prepare('SELECT * FROM review_comments WHERE review_id = ? ORDER BY anchor_line, created_seq').all(reviewId)
|
|
249
|
+
: db.prepare('SELECT * FROM review_comments WHERE review_id = ? AND status = ? ORDER BY anchor_line, created_seq').all(reviewId, status);
|
|
250
|
+
return rows.map(commentFromRow);
|
|
251
|
+
}
|
|
252
|
+
export function getComment(commentIdValue) {
|
|
253
|
+
const row = getStoredComment(openDb(), commentIdValue);
|
|
254
|
+
return row === null ? null : commentFromRow(row);
|
|
255
|
+
}
|
|
256
|
+
export function listCommentEvents(commentIdValue) {
|
|
257
|
+
const rows = openDb().prepare('SELECT * FROM review_comment_events WHERE comment_id = ? ORDER BY seq').all(commentIdValue);
|
|
258
|
+
return rows.map(eventFromRow);
|
|
259
|
+
}
|
|
260
|
+
export function listReviewEvents(reviewId, opts) {
|
|
261
|
+
const since = opts.since_seq ?? 0;
|
|
262
|
+
const limit = Math.min(Math.max(opts.limit ?? COMMENT_EVENTS_PAGE_DEFAULT, 1), COMMENT_EVENTS_PAGE_MAX);
|
|
263
|
+
const rows = openDb().prepare('SELECT * FROM review_comment_events WHERE review_id = ? AND seq > ? ORDER BY seq LIMIT ?').all(reviewId, since, limit);
|
|
264
|
+
const events = rows.map(eventFromRow);
|
|
265
|
+
return { events, next_since_seq: events.length === 0 ? since : events[events.length - 1].seq };
|
|
266
|
+
}
|
|
267
|
+
export function snapshotCommentsLocked(db, reviewId) {
|
|
268
|
+
const rows = db.prepare("SELECT * FROM review_comments WHERE review_id = ? AND status != 'deleted' ORDER BY anchor_line, created_seq").all(reviewId);
|
|
269
|
+
const comments = rows.map((row) => ({
|
|
270
|
+
id: row.comment_id,
|
|
271
|
+
line: row.anchor_line,
|
|
272
|
+
endLine: row.anchor_end_line,
|
|
273
|
+
...(row.anchor_quote === null ? {} : { quote: row.anchor_quote }),
|
|
274
|
+
...(row.anchor_col_start === null ? {} : { colStart: row.anchor_col_start }),
|
|
275
|
+
...(row.anchor_col_end === null ? {} : { colEnd: row.anchor_col_end }),
|
|
276
|
+
lineText: row.anchor_line_text,
|
|
277
|
+
comment: row.text,
|
|
278
|
+
createdAt: row.created_at,
|
|
279
|
+
}));
|
|
280
|
+
return { comments, total: rows.length, unresolved: rows.filter((row) => row.status === 'open').length };
|
|
281
|
+
}
|
|
282
|
+
export function appendDeliveryEvent(args) {
|
|
283
|
+
withCanvasWrite((db) => {
|
|
284
|
+
assertReviewExists(db, args.review_id);
|
|
285
|
+
const row = requireStoredComment(db, args.comment_id);
|
|
286
|
+
if (row.review_id !== args.review_id)
|
|
287
|
+
throw new ReviewOperationError('unknown_comment', 'comment was not found', { received: args.comment_id });
|
|
288
|
+
db.prepare(`
|
|
289
|
+
INSERT INTO review_comment_events
|
|
290
|
+
(review_id, comment_id, kind, state_change, revision_after, actor_kind, actor_node_id, at, operation_id, payload)
|
|
291
|
+
VALUES (?, ?, ?, 0, NULL, 'system', NULL, ?, ?, ?)
|
|
292
|
+
`).run(args.review_id, args.comment_id, args.kind, nowIso(), args.operation_id, json(args.payload));
|
|
293
|
+
});
|
|
294
|
+
signalReviewActivity();
|
|
295
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type InitialModelRegistryLike } from '../model-routes.js';
|
|
2
|
+
export interface OriginCapture {
|
|
3
|
+
sourceFile: string;
|
|
4
|
+
sourceSessionId: string;
|
|
5
|
+
leafId: string;
|
|
6
|
+
modelSpec: string;
|
|
7
|
+
}
|
|
8
|
+
export interface ReviewCompanionSpec {
|
|
9
|
+
nodeId: string;
|
|
10
|
+
reviewId: string;
|
|
11
|
+
originNodeId: string;
|
|
12
|
+
branchFile: string;
|
|
13
|
+
targetFile: string;
|
|
14
|
+
modelSpec: string;
|
|
15
|
+
cwd: string;
|
|
16
|
+
profileId: string | null;
|
|
17
|
+
}
|
|
18
|
+
type ExactModel = {
|
|
19
|
+
provider: string;
|
|
20
|
+
id: string;
|
|
21
|
+
};
|
|
22
|
+
type ExactModelRegistry = InitialModelRegistryLike<ExactModel>;
|
|
23
|
+
/** Capture an origin without launching it or acquiring its broker's writer role. */
|
|
24
|
+
export declare function captureOrigin(originNodeId: string, deps?: {
|
|
25
|
+
registry?: ExactModelRegistry;
|
|
26
|
+
}): Promise<OriginCapture>;
|
|
27
|
+
/** Materialize the immutable review fork, reusing only an already-valid branch. */
|
|
28
|
+
export declare function materializeReviewBranch(reviewId: string, capture: OriginCapture): string;
|
|
29
|
+
/** Create the ordinary, promptless companion node. Realization owns its launch. */
|
|
30
|
+
export declare function spawnReviewCompanion(spec: ReviewCompanionSpec): void;
|
|
31
|
+
/** A companion is bound only when its session coordinates and visible boundary are durable. */
|
|
32
|
+
export declare function isReviewCompanionBound(nodeId: string): boolean;
|
|
33
|
+
/** Wait for the durable companion bind without owning companion liveness. */
|
|
34
|
+
export declare function awaitCompanionBind(nodeId: string, deadlineMs: number): Promise<boolean>;
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { basename, isAbsolute, resolve } from 'node:path';
|
|
4
|
+
import { BrokerClient } from '../broker-client/index.js';
|
|
5
|
+
import { getNode } from '../canvas/index.js';
|
|
6
|
+
import { ensureReviewDir, reviewBranchPath } from '../canvas/paths.js';
|
|
7
|
+
import { expandModelCandidates, selectInitialModelRoute } from '../model-routes.js';
|
|
8
|
+
import { buildLaunchSpec } from '../runtime/launch.js';
|
|
9
|
+
import { openModelRegistry } from '../runtime/model-registry.js';
|
|
10
|
+
import { isBrokerLive } from '../runtime/model-swap.js';
|
|
11
|
+
import { spawnNode } from '../runtime/nodes.js';
|
|
12
|
+
import { SessionManager } from '../runtime/broker-sdk.js';
|
|
13
|
+
import { materializeSessionBranchAt } from '../runtime/session-branch.js';
|
|
14
|
+
import { isReviewBoundary } from '../runtime/session-visibility.js';
|
|
15
|
+
import { ReviewOperationError } from './types.js';
|
|
16
|
+
const EXACT_MODEL_SPEC = /^[^/\s:]+\/[^/\s:]+:(?:off|minimal|low|medium|high|xhigh|max)$/;
|
|
17
|
+
const BIND_POLL_MS = 100;
|
|
18
|
+
function originMissing(originNodeId) {
|
|
19
|
+
return new ReviewOperationError('review_origin_missing', 'review origin was not found', { origin_node_id: originNodeId });
|
|
20
|
+
}
|
|
21
|
+
function originUnforkable(originNodeId, reason, detail = {}) {
|
|
22
|
+
return new ReviewOperationError('review_origin_unforkable', 'review origin has no forkable exact session', {
|
|
23
|
+
origin_node_id: originNodeId,
|
|
24
|
+
reason,
|
|
25
|
+
...detail,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
async function validateCapture(originNodeId, value, registry) {
|
|
29
|
+
if (!isAbsolute(value.sourceFile) || !existsSync(value.sourceFile) || value.sourceSessionId === '' || value.leafId === null || value.leafId === '') {
|
|
30
|
+
throw originUnforkable(originNodeId, 'no_forkable_session');
|
|
31
|
+
}
|
|
32
|
+
if (value.modelSpec === null || !EXACT_MODEL_SPEC.test(value.modelSpec)) {
|
|
33
|
+
throw originUnforkable(originNodeId, 'model_unresolvable');
|
|
34
|
+
}
|
|
35
|
+
const selection = selectInitialModelRoute({ kind: 'exact', spec: value.modelSpec }, registry ?? await openModelRegistry(), { cwd: value.cwd, profileId: value.profileId });
|
|
36
|
+
if (selection.selected === undefined) {
|
|
37
|
+
throw originUnforkable(originNodeId, 'model_unresolvable', {
|
|
38
|
+
model_reason: selection.rejected[0]?.reason,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
sourceFile: value.sourceFile,
|
|
43
|
+
sourceSessionId: value.sourceSessionId,
|
|
44
|
+
leafId: value.leafId,
|
|
45
|
+
modelSpec: value.modelSpec,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/** Read the broker's fork coordinate through its observer-only protocol path.
|
|
49
|
+
* This connection can inspect a streaming origin but has no writer authority. */
|
|
50
|
+
function captureLiveOrigin(originNodeId) {
|
|
51
|
+
return new Promise((resolveCapture, reject) => {
|
|
52
|
+
const client = new BrokerClient(originNodeId);
|
|
53
|
+
let settled = false;
|
|
54
|
+
function finish(action) {
|
|
55
|
+
if (settled)
|
|
56
|
+
return;
|
|
57
|
+
settled = true;
|
|
58
|
+
client.close();
|
|
59
|
+
action();
|
|
60
|
+
}
|
|
61
|
+
client.on('error', (error) => finish(() => reject(error)));
|
|
62
|
+
client.on('close', () => finish(() => reject(new Error('origin broker closed before fork coordinates were read'))));
|
|
63
|
+
client.on('connect', () => {
|
|
64
|
+
client.send({ type: 'hello', role: 'observer', client_id: randomUUID() });
|
|
65
|
+
void client.request({ type: 'get_human_fork_coordinates' })
|
|
66
|
+
.then((frame) => {
|
|
67
|
+
if (frame.kind !== 'human_fork_coordinates') {
|
|
68
|
+
finish(() => reject(new Error('origin broker returned an unexpected fork-coordinate response')));
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
finish(() => resolveCapture(frame));
|
|
72
|
+
})
|
|
73
|
+
.catch((error) => finish(() => reject(error)));
|
|
74
|
+
});
|
|
75
|
+
client.connect();
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
/** Capture an origin without launching it or acquiring its broker's writer role. */
|
|
79
|
+
export async function captureOrigin(originNodeId, deps = {}) {
|
|
80
|
+
const node = getNode(originNodeId);
|
|
81
|
+
if (node === null)
|
|
82
|
+
throw originMissing(originNodeId);
|
|
83
|
+
if (isBrokerLive(node)) {
|
|
84
|
+
const coordinates = await captureLiveOrigin(originNodeId);
|
|
85
|
+
return validateCapture(originNodeId, {
|
|
86
|
+
...coordinates,
|
|
87
|
+
cwd: node.cwd,
|
|
88
|
+
profileId: node.profile_id,
|
|
89
|
+
}, deps.registry);
|
|
90
|
+
}
|
|
91
|
+
const sourceFile = typeof node.pi_session_file === 'string' ? node.pi_session_file : '';
|
|
92
|
+
let sourceSessionId = '';
|
|
93
|
+
let leafId = null;
|
|
94
|
+
let modelSpec = null;
|
|
95
|
+
if (isAbsolute(sourceFile) && existsSync(sourceFile)) {
|
|
96
|
+
let session;
|
|
97
|
+
try {
|
|
98
|
+
session = SessionManager.open(sourceFile);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return validateCapture(originNodeId, {
|
|
102
|
+
sourceFile,
|
|
103
|
+
sourceSessionId,
|
|
104
|
+
leafId,
|
|
105
|
+
modelSpec,
|
|
106
|
+
cwd: node.cwd,
|
|
107
|
+
profileId: node.profile_id,
|
|
108
|
+
}, deps.registry);
|
|
109
|
+
}
|
|
110
|
+
sourceSessionId = session.getSessionId();
|
|
111
|
+
leafId = session.getLeafId();
|
|
112
|
+
const launchSpec = node.launch?.model;
|
|
113
|
+
const parsed = typeof launchSpec === 'string'
|
|
114
|
+
? expandModelCandidates({ kind: 'exact', spec: launchSpec }, node.cwd, node.profile_id)[0]
|
|
115
|
+
: undefined;
|
|
116
|
+
if (parsed !== undefined) {
|
|
117
|
+
const thinking = parsed.thinkingLevel ?? (session.buildSessionContext().thinkingLevel || 'off');
|
|
118
|
+
modelSpec = `${parsed.providerId}/${parsed.modelId}:${thinking}`;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return validateCapture(originNodeId, {
|
|
122
|
+
sourceFile,
|
|
123
|
+
sourceSessionId,
|
|
124
|
+
leafId,
|
|
125
|
+
modelSpec,
|
|
126
|
+
cwd: node.cwd,
|
|
127
|
+
profileId: node.profile_id,
|
|
128
|
+
}, deps.registry);
|
|
129
|
+
}
|
|
130
|
+
/** Materialize the immutable review fork, reusing only an already-valid branch. */
|
|
131
|
+
export function materializeReviewBranch(reviewId, capture) {
|
|
132
|
+
ensureReviewDir(reviewId);
|
|
133
|
+
const branchFile = reviewBranchPath(reviewId);
|
|
134
|
+
if (existsSync(branchFile)) {
|
|
135
|
+
const branch = SessionManager.open(branchFile);
|
|
136
|
+
if (branch.getSessionFile() === resolve(branchFile) && branch.getSessionId() !== '')
|
|
137
|
+
return branchFile;
|
|
138
|
+
}
|
|
139
|
+
materializeSessionBranchAt(capture, branchFile);
|
|
140
|
+
return branchFile;
|
|
141
|
+
}
|
|
142
|
+
/** Create the ordinary, promptless companion node. Realization owns its launch. */
|
|
143
|
+
export function spawnReviewCompanion(spec) {
|
|
144
|
+
if (!isAbsolute(spec.branchFile) || !isAbsolute(spec.targetFile)) {
|
|
145
|
+
throw new Error('review companion requires absolute branch and target paths');
|
|
146
|
+
}
|
|
147
|
+
if (!EXACT_MODEL_SPEC.test(spec.modelSpec)) {
|
|
148
|
+
throw new Error('review companion requires an exact model spec');
|
|
149
|
+
}
|
|
150
|
+
const { launch } = buildLaunchSpec('review/companion', 'base', {
|
|
151
|
+
lifecycle: 'resident',
|
|
152
|
+
hasManager: false,
|
|
153
|
+
model: spec.modelSpec,
|
|
154
|
+
modelExact: true,
|
|
155
|
+
cwd: spec.cwd,
|
|
156
|
+
profileId: spec.profileId,
|
|
157
|
+
});
|
|
158
|
+
spawnNode({
|
|
159
|
+
nodeId: spec.nodeId,
|
|
160
|
+
kind: 'review/companion',
|
|
161
|
+
mode: 'base',
|
|
162
|
+
lifecycle: 'resident',
|
|
163
|
+
cwd: spec.cwd,
|
|
164
|
+
profile_id: spec.profileId,
|
|
165
|
+
parent: spec.originNodeId,
|
|
166
|
+
subscribe: false,
|
|
167
|
+
forkFrom: spec.branchFile,
|
|
168
|
+
modelOverride: spec.modelSpec,
|
|
169
|
+
reviewBinding: {
|
|
170
|
+
review_id: spec.reviewId,
|
|
171
|
+
origin_node_id: spec.originNodeId,
|
|
172
|
+
branch_file: spec.branchFile,
|
|
173
|
+
target_file: spec.targetFile,
|
|
174
|
+
},
|
|
175
|
+
name: `review ${basename(spec.targetFile)}`,
|
|
176
|
+
launch,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
/** A companion is bound only when its session coordinates and visible boundary are durable. */
|
|
180
|
+
export function isReviewCompanionBound(nodeId) {
|
|
181
|
+
const node = getNode(nodeId);
|
|
182
|
+
const binding = node?.review_binding;
|
|
183
|
+
const sessionFile = node?.pi_session_file;
|
|
184
|
+
if (binding == null || node?.pi_session_id == null || typeof sessionFile !== 'string' || !existsSync(sessionFile)) {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
try {
|
|
188
|
+
return SessionManager.open(sessionFile).getEntries().some((entry) => isReviewBoundary(entry, binding.review_id));
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/** Wait for the durable companion bind without owning companion liveness. */
|
|
195
|
+
export async function awaitCompanionBind(nodeId, deadlineMs) {
|
|
196
|
+
const deadline = Date.now() + Math.max(0, deadlineMs);
|
|
197
|
+
for (;;) {
|
|
198
|
+
if (isReviewCompanionBound(nodeId))
|
|
199
|
+
return true;
|
|
200
|
+
const remaining = deadline - Date.now();
|
|
201
|
+
if (remaining <= 0)
|
|
202
|
+
return false;
|
|
203
|
+
await new Promise((resolveWait) => setTimeout(resolveWait, Math.min(BIND_POLL_MS, remaining)));
|
|
204
|
+
}
|
|
205
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { DatabaseSync } from 'node:sqlite';
|
|
2
|
+
import type { ReviewRecord } from './types.js';
|
|
3
|
+
import { type CommentAnchor } from './types.js';
|
|
4
|
+
type SourcePhase = 'submit' | 'comment';
|
|
5
|
+
/** Read the reviewed document once, preserving the exact bytes used for its digest. */
|
|
6
|
+
export declare function readReviewSource(file: string, phase?: SourcePhase): {
|
|
7
|
+
bytes: Buffer;
|
|
8
|
+
sha256: string;
|
|
9
|
+
lines: string[];
|
|
10
|
+
};
|
|
11
|
+
/** Require both the caller's rendered source and the persisted range coordinate base to be current. */
|
|
12
|
+
export declare function requireCurrentDocument(review: ReviewRecord, expected_doc_hash: string): {
|
|
13
|
+
bytes: Buffer;
|
|
14
|
+
sha256: string;
|
|
15
|
+
lines: string[];
|
|
16
|
+
};
|
|
17
|
+
/** Verify a create-time source precondition from the review row held by the caller's canvas write transaction. */
|
|
18
|
+
export declare function requireCurrentDocumentLocked(db: DatabaseSync, review_id: string, expected_doc_hash: string): {
|
|
19
|
+
bytes: Buffer;
|
|
20
|
+
sha256: string;
|
|
21
|
+
lines: string[];
|
|
22
|
+
};
|
|
23
|
+
/** Reject malformed ranges rather than normalizing them into a different anchor. */
|
|
24
|
+
export declare function validateAnchorShape(anchor: CommentAnchor): void;
|
|
25
|
+
/** Capture the full source range used to render an anchor, without silently clamping it. */
|
|
26
|
+
export declare function captureAnchorText(lines: string[], anchor: CommentAnchor): string;
|
|
27
|
+
export {};
|