@north-light/crouter 0.3.312 → 0.3.314
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 +27 -30
- package/dist/api/client.js +80 -67
- package/dist/api/dto/broker-ops.d.ts +10 -20
- package/dist/api/dto/canvas.d.ts +1 -10
- package/dist/api/dto/health.d.ts +113 -0
- package/dist/api/dto/human-requests.d.ts +14 -3
- package/dist/api/dto/human.d.ts +2 -48
- package/dist/api/dto/human.js +3 -2
- package/dist/api/dto/inbox.d.ts +14 -0
- package/dist/api/dto/mail.d.ts +43 -0
- package/dist/api/dto/nodes.d.ts +11 -8
- package/dist/api/dto/recovery.d.ts +96 -0
- package/dist/api/dto/reviews.d.ts +2 -2
- package/dist/api/routes.d.ts +9 -6
- package/dist/api/routes.js +11 -11
- package/dist/build-root.d.ts +4 -0
- package/dist/build-root.js +11 -1
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/integration/provider-rotation.test.ts +35 -47
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.d.ts +1 -1
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +12 -5
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +12 -5
- package/dist/cli.js +10 -1
- package/dist/clients/__tests__/helpers/human-daemon.d.ts +11 -0
- package/dist/clients/__tests__/helpers/human-daemon.js +60 -0
- package/dist/clients/attach/chrome/canvas-panels.js +1 -1
- package/dist/clients/attach/chrome/inbox-strip.d.ts +3 -3
- package/dist/clients/attach/chrome/inbox-strip.js +17 -9
- package/dist/clients/attach/chrome/ticket-panel.d.ts +2 -2
- package/dist/clients/attach/chrome/ticket-panel.js +77 -46
- package/dist/clients/attach/overlays/graph.js +6 -9
- package/dist/clients/attach/render/chat-view.d.ts +5 -4
- package/dist/clients/attach/render/chat-view.js +22 -13
- package/dist/clients/attach/render/page-block.d.ts +11 -7
- package/dist/clients/attach/render/page-block.js +64 -55
- package/dist/clients/attach/viewer.js +757 -746
- package/dist/clients/inbox/__tests__/integration/inbox-controller.test.js +56 -56
- package/dist/clients/inbox/__tests__/integration/stale-row-activation.test.js +45 -32
- package/dist/clients/inbox/controller.d.ts +42 -14
- package/dist/clients/inbox/controller.js +240 -124
- package/dist/clients/inbox/dto-adapt.d.ts +28 -0
- package/dist/clients/inbox/dto-adapt.js +93 -0
- package/dist/clients/inbox/page-adapter.d.ts +5 -4
- package/dist/clients/inbox/page-adapter.js +12 -12
- package/dist/clients/inbox/resolve.d.ts +10 -5
- package/dist/clients/inbox/resolve.js +13 -12
- package/dist/clients/inbox/review/review-client.d.ts +0 -1
- package/dist/clients/inbox/review/review-client.js +0 -4
- package/dist/clients/inbox/review-adapter.d.ts +2 -1
- package/dist/clients/inbox/review-adapter.js +3 -5
- package/dist/clients/inbox/surface.d.ts +2 -2
- package/dist/clients/inbox/surface.js +19 -8
- package/dist/clients/inbox/tui.d.ts +3 -3
- package/dist/commands/__tests__/human.test.js +31 -15
- package/dist/commands/__tests__/integration/dashboard-snapshot.test.js +36 -11
- package/dist/commands/{sys/__tests__ → __tests__/integration}/migrate.test.js +142 -36
- package/dist/commands/__tests__/revive-now-gate.test.js +2 -0
- package/dist/commands/api-client.d.ts +5 -4
- package/dist/commands/api-client.js +13 -7
- package/dist/commands/canvas-history/shared.js +1 -1
- package/dist/commands/canvas-history.js +1 -1
- package/dist/commands/canvas-roster.js +1 -1
- package/dist/commands/canvas.js +1 -2
- package/dist/commands/human/feedback.js +20 -17
- package/dist/commands/human/prompts.js +45 -36
- package/dist/commands/human/queue.js +73 -123
- package/dist/commands/human/review.js +6 -16
- package/dist/commands/memory/__tests__/command-selector-and-mutation-guards.test.js +2 -0
- package/dist/commands/memory/__tests__/memory-list-and-lint-ignore.test.js +2 -0
- package/dist/commands/memory/__tests__/repository-root-lint.test.js +2 -0
- package/dist/commands/node-inspect-artifacts.js +1 -1
- package/dist/commands/node-lifecycle-revive.d.ts +2 -2
- package/dist/commands/node-lifecycle-revive.js +9 -19
- package/dist/commands/pkg/plugin-manage.js +0 -1
- package/dist/commands/profile/show.js +4 -12
- package/dist/commands/surface-tmux-spread.js +1 -5
- package/dist/commands/sys/__tests__/config-model-ladders.test.js +23 -30
- package/dist/commands/sys/__tests__/sync-project-guidance.test.js +37 -11
- package/dist/commands/sys/branch.d.ts +2 -0
- package/dist/commands/sys/branch.js +19 -0
- package/dist/commands/sys/config.js +106 -33
- package/dist/commands/sys/daemon.d.ts +2 -0
- package/dist/commands/sys/daemon.js +130 -7
- package/dist/commands/sys/doctor.js +5 -15
- package/dist/commands/sys/migrate.js +21 -92
- package/dist/commands/sys/setup-settings-runner.js +4 -2
- package/dist/commands/sys.js +2 -15
- package/dist/core/__tests__/boot-fault-attempt.test.js +23 -1
- package/dist/core/__tests__/boot.test.js +32 -25
- package/dist/core/__tests__/broker-launch-candidates.test.js +49 -0
- package/dist/core/__tests__/canvas-inbox-watcher-hold.test.js +149 -176
- package/dist/core/__tests__/canvas-inbox-watcher-naming.test.js +59 -10
- package/dist/core/__tests__/canvas-inbox-watcher.test.js +76 -20
- package/dist/core/__tests__/canvas.test.js +18 -47
- package/dist/core/__tests__/child-death-wake.test.js +29 -7
- package/dist/core/__tests__/cli-help-contract.test.js +2 -0
- package/dist/core/__tests__/close.test.js +29 -10
- package/dist/core/__tests__/collectible.test.js +2 -1
- package/dist/core/__tests__/config-change-delta.test.js +2 -0
- package/dist/core/__tests__/context-intro.test.js +13 -1
- package/dist/core/__tests__/cron-armed-context-failure.test.js +17 -12
- package/dist/core/__tests__/cron-held-settlement.test.js +21 -3
- package/dist/core/__tests__/cron-node-sink-parked-root.test.js +29 -10
- package/dist/core/__tests__/cron-self-cancel-delivery.test.js +14 -2
- package/dist/core/__tests__/cron-timeout-descendants.test.js +13 -1
- package/dist/core/__tests__/daemon-boot.test.js +51 -14
- package/dist/core/__tests__/fixtures/fake-engine.d.ts +1 -1
- package/dist/core/__tests__/fixtures/fake-engine.js +8 -3
- package/dist/core/__tests__/focuses.test.js +10 -5
- package/dist/core/__tests__/helpers/harness.js +50 -18
- package/dist/core/__tests__/history-inbox.test.js +12 -16
- package/dist/core/__tests__/human-action-delivery.test.js +48 -28
- package/dist/core/__tests__/human-actions.test.js +7 -3
- package/dist/core/__tests__/inline-memory-refs.test.js +7 -2
- package/dist/core/__tests__/integration/broker-fork-seam.test.js +37 -10
- package/dist/core/__tests__/integration/broker-sdk-wiring.test.js +42 -0
- package/dist/core/__tests__/integration/broker-snapshot-history.test.js +42 -29
- package/dist/core/__tests__/integration/broker-wedge-supervision.test.js +36 -35
- package/dist/core/__tests__/integration/command-plugins.test.js +15 -6
- package/dist/core/__tests__/integration/deferred-no-wake.test.js +113 -92
- package/dist/core/__tests__/integration/fresh-home-commands.test.js +49 -0
- package/dist/core/__tests__/integration/host-teardown-process-group.test.js +9 -5
- package/dist/core/__tests__/integration/lifecycle-hooks.test.js +16 -3
- package/dist/core/__tests__/integration/plugin-revalidate.test.js +4 -0
- package/dist/core/__tests__/integration/profile-pause.test.js +4 -4
- package/dist/core/__tests__/integration/refresh-stall-recycle.test.js +9 -12
- package/dist/core/__tests__/integration/revive.test.js +67 -21
- package/dist/core/__tests__/integration/spawn-root.test.js +51 -8
- package/dist/core/__tests__/integration/subscription-delivery.test.js +33 -21
- package/dist/core/__tests__/integration/worktree-land.test.js +5 -2
- package/dist/core/__tests__/integration/worktree-reap.test.js +15 -1
- package/dist/core/__tests__/kickoff.test.js +36 -39
- package/dist/core/__tests__/lifecycle-terminal-reasons.test.js +2 -1
- package/dist/core/__tests__/lifecycle.test.js +2 -1
- package/dist/core/__tests__/live-lifecycle-prompt.test.js +13 -1
- package/dist/core/__tests__/memory-resolver-precedence.test.js +2 -0
- package/dist/core/__tests__/migration.test.js +145 -31
- package/dist/core/__tests__/model-pin-durability.test.js +4 -1
- package/dist/core/__tests__/model-routes-config.test.js +13 -5
- package/dist/core/__tests__/node-outcome.test.js +93 -26
- package/dist/core/__tests__/on-read-crouter-home-fence.test.js +2 -1
- package/dist/core/__tests__/on-read-dedup-resume.test.js +2 -1
- package/dist/core/__tests__/on-read-nested-store.test.js +2 -1
- package/dist/core/__tests__/passive-subscription.test.js +50 -157
- package/dist/core/__tests__/plugin-kinds.test.js +6 -4
- package/dist/core/__tests__/plugin-link-symlinked-scope-root.test.js +6 -1
- package/dist/core/__tests__/plugin-page-components.test.js +6 -4
- package/dist/core/__tests__/preview-registry-sync.test.js +2 -0
- package/dist/core/__tests__/profile-project-memory-delivery.test.js +4 -1
- package/dist/core/__tests__/prune.test.js +11 -5
- package/dist/core/__tests__/push-final-guard.test.js +14 -7
- package/dist/core/__tests__/relaunch-root.test.js +30 -2
- package/dist/core/__tests__/remote-canvas-target.test.js +7 -1
- package/dist/core/__tests__/repository-root-identity.test.js +4 -0
- package/dist/core/__tests__/review-model-floor.test.js +6 -3
- package/dist/core/__tests__/revive-all.test.js +13 -3
- package/dist/core/__tests__/revive-capacity.test.js +26 -4
- package/dist/core/__tests__/revive-parked-fresh.test.js +31 -8
- package/dist/core/__tests__/seam/broker-attach-stream.test.js +1 -1
- package/dist/core/__tests__/seam/broker-cap-freeze.test.js +4 -3
- package/dist/core/__tests__/seam/broker-crash-teardown.test.js +11 -14
- package/dist/core/__tests__/seam/broker-provider-retry.test.js +85 -71
- package/dist/core/__tests__/seam/dormancy-release.test.js +33 -19
- package/dist/core/__tests__/seam/held-deferred-human-prompt.test.js +7 -5
- package/dist/core/__tests__/seam/inbox-reference-guidance.test.js +20 -6
- package/dist/core/__tests__/seam/node-outcome-delivery.test.js +27 -3
- package/dist/core/__tests__/spawn-worktree-id-conflict.test.js +2 -1
- package/dist/core/__tests__/stop-guard.test.js +2 -1
- package/dist/core/__tests__/subscription-pool-credential-guard.test.js +4 -3
- package/dist/core/__tests__/warm-claim-preference-snapshot.test.js +18 -4
- package/dist/core/__tests__/yield-ensures-daemon.test.js +2 -1
- package/dist/core/bootstrap.js +2 -0
- package/dist/core/broker-client/__tests__/transport-socket.test.js +51 -6
- package/dist/core/broker-client/transport-socket.d.ts +1 -0
- package/dist/core/broker-client/transport-socket.js +13 -5
- package/dist/core/canvas/__tests__/attention.test.js +29 -35
- package/dist/core/canvas/__tests__/history-transcript.test.js +6 -6
- package/dist/core/canvas/__tests__/render-remote.test.js +25 -9
- package/dist/core/canvas/attention.d.ts +2 -5
- package/dist/core/canvas/attention.js +15 -64
- package/dist/core/canvas/boot.d.ts +6 -7
- package/dist/core/canvas/boot.js +5 -9
- package/dist/core/canvas/canvas.d.ts +13 -109
- package/dist/core/canvas/canvas.js +140 -401
- package/dist/core/canvas/crons.d.ts +2 -0
- package/dist/core/canvas/crons.js +16 -15
- package/dist/core/canvas/daemon-owner.js +10 -0
- package/dist/core/canvas/db.d.ts +2 -2
- package/dist/core/canvas/db.js +2 -18
- package/dist/core/canvas/deliveries.d.ts +104 -0
- package/dist/core/canvas/deliveries.js +354 -0
- package/dist/core/canvas/executions.d.ts +29 -0
- package/dist/core/canvas/executions.js +68 -0
- package/dist/core/canvas/history.js +35 -35
- package/dist/core/canvas/index.d.ts +3 -1
- package/dist/core/canvas/index.js +3 -1
- package/dist/core/canvas/migrations.js +20 -12
- package/dist/core/canvas/nav-model.js +1 -3
- package/dist/core/canvas/nav-render.d.ts +4 -4
- package/dist/core/canvas/nav-render.js +11 -21
- package/dist/core/canvas/node-sql-migration.d.ts +3 -0
- package/dist/core/canvas/node-sql-migration.js +261 -0
- package/dist/core/canvas/paths.d.ts +2 -16
- package/dist/core/canvas/paths.js +2 -31
- package/dist/core/canvas/recovery.d.ts +76 -0
- package/dist/core/canvas/recovery.js +588 -0
- package/dist/core/canvas/remote-canvas-source.js +4 -0
- package/dist/core/canvas/render-source.d.ts +16 -27
- package/dist/core/canvas/render-source.js +16 -45
- package/dist/core/canvas/sessions.d.ts +33 -0
- package/dist/core/canvas/sessions.js +78 -0
- package/dist/core/canvas/types.d.ts +33 -33
- package/dist/core/canvas/types.js +2 -5
- package/dist/core/canvas/waits.d.ts +18 -0
- package/dist/core/canvas/waits.js +70 -0
- package/dist/core/canvas/worktrees.d.ts +40 -0
- package/dist/core/canvas/worktrees.js +93 -0
- package/dist/core/command.js +11 -0
- package/dist/core/config.d.ts +17 -12
- package/dist/core/config.js +106 -155
- package/dist/core/feed/__tests__/inbox-migrate.test.js +27 -31
- package/dist/core/feed/feed.d.ts +0 -6
- package/dist/core/feed/feed.js +68 -56
- package/dist/core/feed/inbox.d.ts +7 -81
- package/dist/core/feed/inbox.js +46 -378
- package/dist/core/feed/messages.d.ts +58 -0
- package/dist/core/feed/messages.js +217 -0
- package/dist/core/fs-utils.d.ts +4 -0
- package/dist/core/fs-utils.js +21 -1
- package/dist/core/human/answer.d.ts +1 -1
- package/dist/core/human/answer.js +1 -1
- package/dist/core/human/claim.d.ts +1 -1
- package/dist/core/human/claim.js +2 -4
- package/dist/core/human/component-docs.js +1 -1
- package/dist/core/human/feedback-companion.js +3 -2
- package/dist/core/human/feedback.d.ts +5 -8
- package/dist/core/human/feedback.js +57 -85
- package/dist/core/human/page-authoring.d.ts +30 -0
- package/dist/core/human/page-authoring.js +19 -0
- package/dist/core/human/requests.d.ts +136 -0
- package/dist/core/human/requests.js +515 -0
- package/dist/core/human/root.d.ts +0 -7
- package/dist/core/human/root.js +0 -17
- package/dist/core/human/scan.d.ts +2 -7
- package/dist/core/human/scan.js +48 -132
- package/dist/core/human/summary.d.ts +1 -1
- package/dist/core/human/summary.js +1 -1
- package/dist/core/human/tickets.d.ts +23 -83
- package/dist/core/human/tickets.js +92 -243
- package/dist/core/human/types.d.ts +5 -1
- package/dist/core/installed-plugins.js +8 -3
- package/dist/core/keybindings/__tests__/resolve.test.js +19 -17
- package/dist/core/locked-file.d.ts +6 -3
- package/dist/core/locked-file.js +36 -9
- package/dist/core/memory/extensions.js +2 -0
- package/dist/core/preview-registry.js +0 -1
- package/dist/core/profiles/__tests__/env-store.test.js +2 -0
- package/dist/core/profiles/default-binding.d.ts +0 -4
- package/dist/core/profiles/default-binding.js +12 -58
- package/dist/core/profiles/env-store.js +8 -3
- package/dist/core/profiles/manifest.d.ts +2 -37
- package/dist/core/profiles/manifest.js +35 -161
- package/dist/core/profiles/select.js +3 -0
- package/dist/core/review/__tests__/capture-origin.test.js +13 -2
- package/dist/core/review/__tests__/comments.test.js +28 -10
- package/dist/core/review/__tests__/remap.test.js +28 -10
- package/dist/core/review/__tests__/stage-identity.test.js +17 -7
- package/dist/core/review/birth.d.ts +1 -1
- package/dist/core/review/birth.js +34 -5
- package/dist/core/review/comments.js +1 -1
- package/dist/core/review/document.js +1 -1
- package/dist/core/review/project.d.ts +5 -1
- package/dist/core/review/project.js +14 -36
- package/dist/core/review/realize.d.ts +3 -6
- package/dist/core/review/realize.js +51 -168
- package/dist/core/review/remap.js +1 -1
- package/dist/core/review/stage.d.ts +3 -2
- package/dist/core/review/stage.js +2 -3
- package/dist/core/review/store.d.ts +3 -21
- package/dist/core/review/store.js +140 -186
- package/dist/core/review/types.d.ts +0 -1
- package/dist/core/runtime/__tests__/install-id-cache-scoping.test.js +9 -5
- package/dist/core/runtime/__tests__/spawn-env.test.js +8 -9
- package/dist/core/runtime/broker/auth-reload.js +9 -10
- package/dist/core/runtime/broker/daemon-ops.d.ts +25 -8
- package/dist/core/runtime/broker/daemon-ops.js +42 -9
- package/dist/core/runtime/broker/extension-abort.d.ts +3 -0
- package/dist/core/runtime/broker/extension-abort.js +11 -0
- package/dist/core/runtime/broker/fault-retry.d.ts +15 -6
- package/dist/core/runtime/broker/fault-retry.js +142 -95
- package/dist/core/runtime/broker/inbox.d.ts +4 -32
- package/dist/core/runtime/broker/inbox.js +4 -92
- package/dist/core/runtime/broker/rebind.d.ts +1 -0
- package/dist/core/runtime/broker/rebind.js +21 -12
- package/dist/core/runtime/broker-persona-guidance.d.ts +1 -1
- package/dist/core/runtime/broker-persona-guidance.js +2 -13
- package/dist/core/runtime/broker.js +28 -22
- package/dist/core/runtime/close.d.ts +3 -9
- package/dist/core/runtime/close.js +16 -27
- package/dist/core/runtime/fault.d.ts +3 -93
- package/dist/core/runtime/fault.js +9 -419
- package/dist/core/runtime/kickoff.d.ts +3 -6
- package/dist/core/runtime/kickoff.js +12 -18
- package/dist/core/runtime/launch.js +1 -1
- package/dist/core/runtime/lifecycle.js +40 -7
- package/dist/core/runtime/placement.js +2 -2
- package/dist/core/runtime/recycle.js +8 -2
- package/dist/core/runtime/reset.js +22 -6
- package/dist/core/runtime/revive.js +226 -218
- package/dist/core/runtime/spawn.js +14 -3
- package/dist/core/scoped-state/db.d.ts +18 -0
- package/dist/core/scoped-state/db.js +135 -0
- package/dist/core/scoped-state/migrate.d.ts +8 -0
- package/dist/core/scoped-state/migrate.js +181 -0
- package/dist/core/scoped-state/paths.d.ts +9 -0
- package/dist/core/scoped-state/paths.js +27 -0
- package/dist/core/scoped-state/profiles.d.ts +12 -0
- package/dist/core/scoped-state/profiles.js +62 -0
- package/dist/core/scoped-state/providers.d.ts +16 -0
- package/dist/core/scoped-state/providers.js +8 -0
- package/dist/core/scoped-state/schema.d.ts +3 -0
- package/dist/core/scoped-state/schema.js +26 -0
- package/dist/core/scoped-state/settings.d.ts +28 -0
- package/dist/core/scoped-state/settings.js +82 -0
- package/dist/core/subscription-state.d.ts +29 -48
- package/dist/core/subscription-state.js +176 -712
- package/dist/core/worktree-close.js +4 -4
- package/dist/core/worktree-mutation-async.js +2 -2
- package/dist/core/worktree-sweep.js +11 -16
- package/dist/core/worktree.js +6 -12
- package/dist/daemon/__tests__/autostart-storm.test.js +1 -39
- package/dist/daemon/__tests__/helpers/source-daemon.d.ts +2 -2
- package/dist/daemon/__tests__/helpers/source-daemon.js +7 -6
- package/dist/daemon/__tests__/integration/migration-startup.test.js +59 -26
- package/dist/daemon/__tests__/node-deadline-lane.test.js +2 -1
- package/dist/daemon/__tests__/node-outcome-birth-invariants.test.js +39 -15
- package/dist/daemon/__tests__/node-outcome-delivery.test.js +39 -10
- package/dist/daemon/__tests__/reconciler-signature.test.js +2 -2
- package/dist/daemon/__tests__/subtree-filter-freshness.test.js +2 -2
- package/dist/daemon/api/__tests__/broker-settle-park.test.js +17 -12
- package/dist/daemon/api/__tests__/canvas-snapshot-fields.test.js +27 -5
- package/dist/daemon/api/__tests__/model-config.test.js +8 -8
- package/dist/daemon/api/__tests__/node-create-description.test.js +22 -5
- package/dist/daemon/api/__tests__/node-model-validation.test.js +21 -1
- package/dist/daemon/api/__tests__/nodes-activity-query.test.js +10 -12
- package/dist/daemon/api/__tests__/profile-launch-gates.test.js +4 -1
- package/dist/daemon/api/__tests__/profile-metadata-route.test.js +4 -1
- package/dist/daemon/api/__tests__/reopen-delivery.test.js +26 -8
- package/dist/daemon/api/__tests__/seam/api-server.test.js +24 -32
- package/dist/daemon/api/__tests__/seam/b10-attach-modelauth.test.js +4 -1
- package/dist/daemon/api/__tests__/seam/leaf-api-parity.test.js +5 -4
- package/dist/daemon/api/__tests__/seam/profile-delete.test.js +27 -41
- package/dist/daemon/api/__tests__/submit-result.test.js +3 -2
- package/dist/daemon/api/bridge.js +1 -1
- package/dist/daemon/api/handlers/bash-jobs.js +6 -7
- package/dist/daemon/api/handlers/broker-ops.js +47 -84
- package/dist/daemon/api/handlers/broker-recovery.d.ts +4 -0
- package/dist/daemon/api/handlers/broker-recovery.js +251 -0
- package/dist/daemon/api/handlers/canvas.js +2 -44
- package/dist/daemon/api/handlers/daemon.js +41 -0
- package/dist/daemon/api/handlers/feedback-comments.js +2 -2
- package/dist/daemon/api/handlers/health.js +10 -5
- package/dist/daemon/api/handlers/human-requests.js +168 -188
- package/dist/daemon/api/handlers/human.js +3 -151
- package/dist/daemon/api/handlers/inbox-page.d.ts +4 -0
- package/dist/daemon/api/handlers/inbox-page.js +89 -0
- package/dist/daemon/api/handlers/inbox.js +21 -120
- package/dist/daemon/api/handlers/messages.d.ts +1 -0
- package/dist/daemon/api/handlers/messages.js +73 -15
- package/dist/daemon/api/handlers/node-outcomes.js +58 -13
- package/dist/daemon/api/handlers/nodes.js +7 -13
- package/dist/daemon/api/handlers/reviews.js +4 -29
- package/dist/daemon/api/map.d.ts +25 -3
- package/dist/daemon/api/map.js +84 -14
- package/dist/daemon/api/server.js +68 -9
- package/dist/daemon/control.d.ts +18 -0
- package/dist/daemon/cron/disposition.d.ts +2 -0
- package/dist/daemon/cron/disposition.js +8 -5
- package/dist/daemon/cron/settle.js +37 -13
- package/dist/daemon/cron/sinks.d.ts +18 -1
- package/dist/daemon/cron/sinks.js +47 -93
- package/dist/daemon/crtrd-cli.js +4 -19
- package/dist/daemon/crtrd.d.ts +2 -0
- package/dist/daemon/crtrd.js +206 -81
- package/dist/daemon/fleet.js +5 -6
- package/dist/daemon/human/finish.d.ts +12 -24
- package/dist/daemon/human/finish.js +88 -285
- package/dist/daemon/human/settle.d.ts +40 -0
- package/dist/daemon/human/settle.js +89 -0
- package/dist/daemon/human/sweep.d.ts +20 -5
- package/dist/daemon/human/sweep.js +56 -60
- package/dist/daemon/manage.d.ts +21 -16
- package/dist/daemon/manage.js +85 -51
- package/dist/daemon/messaging/node-message.d.ts +1 -1
- package/dist/daemon/messaging/node-message.js +9 -12
- package/dist/daemon/park-activity.js +3 -3
- package/dist/daemon/reconcilers/bash-deadline.js +6 -7
- package/dist/daemon/reconcilers/broker-supervision.d.ts +1 -1
- package/dist/daemon/reconcilers/broker-supervision.js +41 -19
- package/dist/daemon/reconcilers/controller-death.js +6 -18
- package/dist/daemon/reconcilers/delivery-lane.d.ts +9 -0
- package/dist/daemon/reconcilers/delivery-lane.js +130 -0
- package/dist/daemon/reconcilers/live-obligation.js +3 -3
- package/dist/daemon/reconcilers/node-deadline.js +1 -1
- package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.d.ts +1 -1
- package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +10 -12
- package/dist/daemon/reconcilers/node-lifecycle/tick.js +5 -5
- package/dist/daemon/reconcilers/node-lifecycle/wants-execution.js +1 -1
- package/dist/daemon/reconcilers/pending-review-submit.js +3 -3
- package/dist/daemon/reconcilers/storage-maintenance.d.ts +2 -8
- package/dist/daemon/reconcilers/storage-maintenance.js +13 -43
- package/dist/daemon/review/companion.js +5 -11
- package/dist/daemon/review/deliver.d.ts +1 -5
- package/dist/daemon/review/deliver.js +3 -52
- package/dist/daemon/review/finish.d.ts +2 -27
- package/dist/daemon/review/finish.js +79 -263
- package/dist/daemon/review/sweep.d.ts +3 -10
- package/dist/daemon/review/sweep.js +13 -131
- package/dist/daemon/startup-policy.d.ts +0 -5
- package/dist/daemon/startup-policy.js +0 -5
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -1
- package/dist/migrations/__tests__/activation-concurrency.test.js +3 -2
- package/dist/migrations/__tests__/activation.test.js +9 -6
- package/dist/migrations/activation.d.ts +3 -2
- package/dist/migrations/activation.js +2 -4
- package/dist/migrations/corpus.d.ts +2 -5
- package/dist/migrations/corpus.js +9 -20
- package/dist/migrations/runner.d.ts +3 -1
- package/dist/migrations/runner.js +6 -2
- package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +21 -89
- package/dist/pi-extensions/__tests__/canvas-goal-capture-envelope.test.js +4 -2
- package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +51 -33
- package/dist/pi-extensions/__tests__/canvas-stophook-context-nudge.test.js +16 -2
- package/dist/pi-extensions/__tests__/pre-command-gate.test.js +13 -1
- package/dist/pi-extensions/canvas-inbox-watcher.js +98 -244
- package/dist/pi-extensions/canvas-passive-context.d.ts +4 -8
- package/dist/pi-extensions/canvas-passive-context.js +85 -37
- package/dist/pi-extensions/canvas-stophook.js +47 -31
- package/dist/shared/env.d.ts +1 -0
- package/dist/shared/env.js +3 -0
- package/package.json +1 -1
- package/runtime.lock.json +5 -5
- package/dist/clients/attach/__tests__/page-block.test.js +0 -54
- package/dist/clients/inbox/review-visibility.d.ts +0 -5
- package/dist/clients/inbox/review-visibility.js +0 -19
- package/dist/commands/canvas-rebuild-index.d.ts +0 -2
- package/dist/commands/canvas-rebuild-index.js +0 -46
- package/dist/core/__tests__/human-cancel-guard.test.js +0 -110
- package/dist/core/__tests__/human-deliver.test.js +0 -256
- package/dist/core/__tests__/human-node-not-supervised.test.d.ts +0 -1
- package/dist/core/__tests__/human-node-not-supervised.test.js +0 -89
- package/dist/core/__tests__/integration/human-deliver-e2e.test.d.ts +0 -1
- package/dist/core/__tests__/integration/human-deliver-e2e.test.js +0 -131
- package/dist/core/__tests__/phase4-review-store.test.d.ts +0 -1
- package/dist/core/__tests__/phase4-review-store.test.js +0 -144
- package/dist/core/__tests__/watchdog-abort-arms-retry.test.d.ts +0 -1
- package/dist/core/__tests__/watchdog-abort-arms-retry.test.js +0 -110
- package/dist/core/canvas/human-deliveries.d.ts +0 -39
- package/dist/core/canvas/human-deliveries.js +0 -75
- package/dist/core/canvas/node-outcome-deliveries.d.ts +0 -64
- package/dist/core/canvas/node-outcome-deliveries.js +0 -159
- package/dist/core/feed/passive.d.ts +0 -3
- package/dist/core/feed/passive.js +0 -53
- package/dist/core/human/__tests__/inbox-cancel-worker.d.ts +0 -1
- package/dist/core/human/__tests__/inbox-cancel-worker.js +0 -7
- package/dist/core/human/__tests__/inbox-claim-worker.d.ts +0 -1
- package/dist/core/human/__tests__/inbox-claim-worker.js +0 -17
- package/dist/core/human/__tests__/inbox-stale-claim-worker.d.ts +0 -1
- package/dist/core/human/__tests__/inbox-stale-claim-worker.js +0 -8
- package/dist/core/human/__tests__/integration/inbox-core.test.d.ts +0 -1
- package/dist/core/human/__tests__/integration/inbox-core.test.js +0 -145
- package/dist/core/human/__tests__/page-tickets.test.d.ts +0 -1
- package/dist/core/human/__tests__/page-tickets.test.js +0 -161
- package/dist/core/review/ticket-filter.d.ts +0 -17
- package/dist/core/review/ticket-filter.js +0 -21
- package/dist/core/runtime/broker/passive.d.ts +0 -17
- package/dist/core/runtime/broker/passive.js +0 -44
- package/dist/core/runtime/busy.d.ts +0 -46
- package/dist/core/runtime/busy.js +0 -150
- package/dist/daemon/__tests__/startup-block-marker.test.d.ts +0 -1
- package/dist/daemon/__tests__/startup-block-marker.test.js +0 -86
- package/dist/daemon/api/__tests__/review-terminal-conflict.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/review-terminal-conflict.test.js +0 -98
- package/dist/daemon/human/deliver-action.d.ts +0 -3
- package/dist/daemon/human/deliver-action.js +0 -9
- package/dist/daemon/node-outcome/deliver-outcome.d.ts +0 -3
- package/dist/daemon/node-outcome/deliver-outcome.js +0 -9
- package/dist/daemon/reconcilers/human-delivery-lane.d.ts +0 -10
- package/dist/daemon/reconcilers/human-delivery-lane.js +0 -41
- package/dist/daemon/reconcilers/node-outcome-delivery-lane.d.ts +0 -10
- package/dist/daemon/reconcilers/node-outcome-delivery-lane.js +0 -41
- package/dist/daemon/startup-block-marker.d.ts +0 -25
- package/dist/daemon/startup-block-marker.js +0 -99
- /package/dist/{clients/attach/__tests__/page-block.test.d.ts → api/dto/mail.js} +0 -0
- /package/dist/{commands/sys/__tests__/migrate.test.d.ts → api/dto/recovery.js} +0 -0
- /package/dist/{core/__tests__/human-cancel-guard.test.d.ts → commands/__tests__/integration/migrate.test.d.ts} +0 -0
- /package/dist/core/__tests__/{human-deliver.test.d.ts → integration/fresh-home-commands.test.d.ts} +0 -0
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { existsSync, readFileSync, readdirSync, realpathSync } from 'node:fs';
|
|
3
|
+
import { join, resolve } from 'node:path';
|
|
4
|
+
import { nodesRoot } from './paths.js';
|
|
5
|
+
const REQUIRED_META_FIELDS = ['node_id', 'name', 'created', 'cwd', 'kind', 'mode', 'lifecycle'];
|
|
6
|
+
function columns(db, table) {
|
|
7
|
+
return new Set(db.prepare(`PRAGMA table_info(${table})`).all().map(({ name }) => name));
|
|
8
|
+
}
|
|
9
|
+
function addNodeColumns(db) {
|
|
10
|
+
const known = columns(db, 'nodes');
|
|
11
|
+
const additions = [
|
|
12
|
+
['title', 'TEXT'], ['icon', 'TEXT'], ['spawned_by', 'TEXT'], ['creator', 'TEXT'], ['fork_from', 'TEXT'], ['fork_source_file', 'TEXT'],
|
|
13
|
+
['passive_default', 'INTEGER NOT NULL DEFAULT 0 CHECK (passive_default IN (0,1))'], ['cycle_pending', 'INTEGER NOT NULL DEFAULT 0 CHECK (cycle_pending IN (0,1))'],
|
|
14
|
+
['model_override', 'TEXT'], ['persona_ack_json', 'TEXT'], ['review_binding_json', 'TEXT'], ['launch_config_json', 'TEXT'],
|
|
15
|
+
];
|
|
16
|
+
for (const [name, definition] of additions) {
|
|
17
|
+
if (!known.has(name))
|
|
18
|
+
db.exec(`ALTER TABLE nodes ADD COLUMN ${name} ${definition}`);
|
|
19
|
+
}
|
|
20
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_nodes_cycle_pending ON nodes(cycle_pending) WHERE cycle_pending = 1');
|
|
21
|
+
}
|
|
22
|
+
function canonical(path) {
|
|
23
|
+
const absolute = resolve(path);
|
|
24
|
+
return existsSync(absolute) ? realpathSync(absolute) : absolute;
|
|
25
|
+
}
|
|
26
|
+
function json(value, field, path) {
|
|
27
|
+
if (value === undefined)
|
|
28
|
+
return null;
|
|
29
|
+
const encoded = JSON.stringify(value);
|
|
30
|
+
if (encoded === undefined)
|
|
31
|
+
throw new Error(`cannot serialize ${field} in ${path}`);
|
|
32
|
+
return encoded;
|
|
33
|
+
}
|
|
34
|
+
function requiredString(meta, key, path) {
|
|
35
|
+
const value = meta[key];
|
|
36
|
+
if (typeof value !== 'string')
|
|
37
|
+
throw new Error(`cannot import node metadata ${path}: ${key} must be a string`);
|
|
38
|
+
return value;
|
|
39
|
+
}
|
|
40
|
+
function optionalString(meta, key, path) {
|
|
41
|
+
const value = meta[key];
|
|
42
|
+
if (value === undefined || value === null)
|
|
43
|
+
return null;
|
|
44
|
+
if (typeof value !== 'string')
|
|
45
|
+
throw new Error(`cannot import node metadata ${path}: ${key} must be a string or null`);
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
48
|
+
function optionalNumber(meta, key, path) {
|
|
49
|
+
const value = meta[key];
|
|
50
|
+
if (value === undefined || value === null)
|
|
51
|
+
return null;
|
|
52
|
+
if (typeof value !== 'number' || !Number.isFinite(value))
|
|
53
|
+
throw new Error(`cannot import node metadata ${path}: ${key} must be a finite number or null`);
|
|
54
|
+
return value;
|
|
55
|
+
}
|
|
56
|
+
function optionalObject(value, field, path) {
|
|
57
|
+
if (value === undefined || value === null)
|
|
58
|
+
return undefined;
|
|
59
|
+
if (typeof value !== 'object' || Array.isArray(value))
|
|
60
|
+
throw new Error(`cannot import ${field} from ${path}: expected an object`);
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
63
|
+
function readMetas() {
|
|
64
|
+
if (!existsSync(nodesRoot()))
|
|
65
|
+
return [];
|
|
66
|
+
const result = [];
|
|
67
|
+
for (const entry of readdirSync(nodesRoot(), { withFileTypes: true })) {
|
|
68
|
+
if (!entry.isDirectory())
|
|
69
|
+
continue;
|
|
70
|
+
const path = join(nodesRoot(), entry.name, 'meta.json');
|
|
71
|
+
if (!existsSync(path))
|
|
72
|
+
continue;
|
|
73
|
+
let meta;
|
|
74
|
+
try {
|
|
75
|
+
meta = JSON.parse(readFileSync(path, 'utf8'));
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
throw new Error(`cannot import node metadata ${path}: ${error.message}`);
|
|
79
|
+
}
|
|
80
|
+
for (const key of REQUIRED_META_FIELDS) {
|
|
81
|
+
if (meta[key] === undefined || meta[key] === null)
|
|
82
|
+
throw new Error(`cannot import node metadata ${path}: missing required ${key}`);
|
|
83
|
+
}
|
|
84
|
+
if (typeof meta['node_id'] !== 'string' || meta['node_id'] !== entry.name)
|
|
85
|
+
throw new Error(`cannot import node metadata ${path}: node_id does not match its directory`);
|
|
86
|
+
result.push({ path, meta });
|
|
87
|
+
}
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
function sqlOnlyPaths(db) {
|
|
91
|
+
const has = columns(db, 'nodes').has('pi_session_file');
|
|
92
|
+
if (!has)
|
|
93
|
+
return new Map();
|
|
94
|
+
return new Map(db.prepare('SELECT node_id, pi_session_file FROM nodes WHERE pi_session_file IS NOT NULL').all().map(({ node_id, pi_session_file }) => [node_id, pi_session_file]));
|
|
95
|
+
}
|
|
96
|
+
function createTables(db) {
|
|
97
|
+
db.exec(`
|
|
98
|
+
CREATE TABLE IF NOT EXISTS sessions (
|
|
99
|
+
binding_id TEXT PRIMARY KEY,
|
|
100
|
+
session_id TEXT,
|
|
101
|
+
node_id TEXT NOT NULL REFERENCES nodes(node_id) ON DELETE CASCADE,
|
|
102
|
+
transcript_path TEXT,
|
|
103
|
+
source_session_id TEXT,
|
|
104
|
+
fork_entry_id TEXT,
|
|
105
|
+
created_at TEXT NOT NULL,
|
|
106
|
+
bound_at TEXT NOT NULL,
|
|
107
|
+
unbound_at TEXT
|
|
108
|
+
);
|
|
109
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_node ON sessions(node_id, created_at);
|
|
110
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_session ON sessions(session_id);
|
|
111
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_sessions_live_node ON sessions(node_id) WHERE unbound_at IS NULL;
|
|
112
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_sessions_live_transcript ON sessions(transcript_path) WHERE unbound_at IS NULL AND transcript_path IS NOT NULL;
|
|
113
|
+
CREATE TABLE IF NOT EXISTS executions (
|
|
114
|
+
execution_id TEXT PRIMARY KEY,
|
|
115
|
+
node_id TEXT NOT NULL REFERENCES nodes(node_id) ON DELETE CASCADE,
|
|
116
|
+
daemon_epoch TEXT,
|
|
117
|
+
pid INTEGER,
|
|
118
|
+
process_identity TEXT,
|
|
119
|
+
state TEXT NOT NULL CHECK (state IN ('launching','running','exited')),
|
|
120
|
+
started_at TEXT NOT NULL,
|
|
121
|
+
ended_at TEXT,
|
|
122
|
+
exit_reason TEXT,
|
|
123
|
+
CHECK ((state = 'exited') = (ended_at IS NOT NULL))
|
|
124
|
+
);
|
|
125
|
+
CREATE INDEX IF NOT EXISTS idx_executions_node ON executions(node_id, started_at);
|
|
126
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_executions_live_node ON executions(node_id) WHERE state != 'exited';
|
|
127
|
+
CREATE TABLE IF NOT EXISTS worktrees (
|
|
128
|
+
node_id TEXT PRIMARY KEY REFERENCES nodes(node_id) ON DELETE CASCADE,
|
|
129
|
+
state TEXT NOT NULL CHECK (state IN ('open','closed','abandoned')),
|
|
130
|
+
cleanup_state TEXT CHECK (cleanup_state IS NULL OR cleanup_state IN ('pending','complete')),
|
|
131
|
+
path TEXT NOT NULL,
|
|
132
|
+
branch TEXT NOT NULL,
|
|
133
|
+
repo_root TEXT NOT NULL,
|
|
134
|
+
base_ref TEXT NOT NULL,
|
|
135
|
+
base_sha TEXT NOT NULL,
|
|
136
|
+
created_at TEXT NOT NULL,
|
|
137
|
+
closed_at TEXT,
|
|
138
|
+
next_attempt_at TEXT,
|
|
139
|
+
attempts INTEGER NOT NULL DEFAULT 0 CHECK (attempts >= 0),
|
|
140
|
+
quarantined INTEGER NOT NULL DEFAULT 0 CHECK (quarantined IN (0,1)),
|
|
141
|
+
sweep_reason TEXT,
|
|
142
|
+
sweep_detail TEXT,
|
|
143
|
+
sweep_last_at TEXT,
|
|
144
|
+
sweep_observed_json TEXT,
|
|
145
|
+
abandoned_json TEXT,
|
|
146
|
+
land_intent_json TEXT,
|
|
147
|
+
disposal_json TEXT
|
|
148
|
+
);
|
|
149
|
+
CREATE INDEX IF NOT EXISTS idx_worktrees_sweep ON worktrees(state, cleanup_state, next_attempt_at);
|
|
150
|
+
`);
|
|
151
|
+
}
|
|
152
|
+
function importMetas(db, entries, retainedPaths) {
|
|
153
|
+
const update = db.prepare(`INSERT INTO nodes (node_id, name, description, cycles, kind, mode, lifecycle, cwd, host_kind, profile_id, parent, created, title, icon, spawned_by, creator, fork_from, fork_source_file, passive_default, cycle_pending, model_override, persona_ack_json, review_binding_json, launch_config_json) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(node_id) DO UPDATE SET name=excluded.name, description=excluded.description, cycles=excluded.cycles, kind=excluded.kind, mode=excluded.mode, lifecycle=excluded.lifecycle, cwd=excluded.cwd, host_kind=excluded.host_kind, profile_id=excluded.profile_id, parent=excluded.parent, title=excluded.title, icon=excluded.icon, spawned_by=excluded.spawned_by, creator=excluded.creator, fork_from=excluded.fork_from, fork_source_file=excluded.fork_source_file, passive_default=excluded.passive_default, cycle_pending=excluded.cycle_pending, model_override=excluded.model_override, persona_ack_json=excluded.persona_ack_json, review_binding_json=excluded.review_binding_json, launch_config_json=excluded.launch_config_json`);
|
|
154
|
+
for (const { path, meta } of entries) {
|
|
155
|
+
const nodeId = requiredString(meta, 'node_id', path);
|
|
156
|
+
const indexedPath = retainedPaths.get(nodeId);
|
|
157
|
+
const metadataPath = optionalString(meta, 'pi_session_file', path);
|
|
158
|
+
if (indexedPath !== undefined && metadataPath !== null && canonical(indexedPath) !== canonical(metadataPath)) {
|
|
159
|
+
throw new Error(`cannot import node metadata ${path}: pi_session_file conflicts with indexed path ${indexedPath}`);
|
|
160
|
+
}
|
|
161
|
+
update.run(nodeId, requiredString(meta, 'name', path), optionalString(meta, 'description', path), optionalNumber(meta, 'cycles', path), requiredString(meta, 'kind', path), requiredString(meta, 'mode', path), requiredString(meta, 'lifecycle', path), requiredString(meta, 'cwd', path), optionalString(meta, 'host_kind', path), optionalString(meta, 'profile_id', path), optionalString(meta, 'parent', path), requiredString(meta, 'created', path), optionalString(meta, 'title', path), optionalString(meta, 'icon', path), optionalString(meta, 'spawned_by', path), optionalString(meta, 'creator', path), optionalString(meta, 'fork_from', path), optionalString(meta, 'fork_source_file', path), meta['passive_default'] === true ? 1 : 0, meta['cycle_pending'] === true ? 1 : 0, optionalString(meta, 'model_override', path), json(meta['persona_ack'], 'persona_ack', path), json(meta['review_binding'], 'review_binding', path), json(meta['launch'], 'launch', path));
|
|
162
|
+
// A readable metadata row without a session path must not consume the old
|
|
163
|
+
// indexed path: importSessions uses that path as its SQL fallback.
|
|
164
|
+
if (metadataPath !== null)
|
|
165
|
+
retainedPaths.delete(nodeId);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function importEdges(db, entries) {
|
|
169
|
+
const known = new Set(db.prepare('SELECT node_id FROM nodes').all().map(({ node_id }) => node_id));
|
|
170
|
+
const insert = db.prepare("INSERT INTO edges (type, from_id, to_id, active, created) VALUES ('spawned_by', ?, ?, 1, ?) ON CONFLICT(type, from_id, to_id) DO NOTHING");
|
|
171
|
+
for (const { meta } of entries) {
|
|
172
|
+
const nodeId = meta['node_id'];
|
|
173
|
+
const owner = typeof meta['spawned_by'] === 'string' ? meta['spawned_by'] : typeof meta['parent'] === 'string' ? meta['parent'] : null;
|
|
174
|
+
if (owner !== null && known.has(nodeId) && known.has(owner))
|
|
175
|
+
insert.run(nodeId, owner, new Date().toISOString());
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
function importSessions(db, entries, retainedPaths) {
|
|
179
|
+
const insert = db.prepare('INSERT INTO sessions (binding_id, session_id, node_id, transcript_path, source_session_id, fork_entry_id, created_at, bound_at, unbound_at) VALUES (?, ?, ?, ?, NULL, NULL, ?, ?, NULL)');
|
|
180
|
+
const seen = new Map();
|
|
181
|
+
for (const { path, meta } of entries) {
|
|
182
|
+
const nodeId = requiredString(meta, 'node_id', path);
|
|
183
|
+
const indexedPath = retainedPaths.get(nodeId);
|
|
184
|
+
const rawPath = typeof meta['pi_session_file'] === 'string' ? meta['pi_session_file'] : indexedPath;
|
|
185
|
+
const sessionId = typeof meta['pi_session_id'] === 'string' ? meta['pi_session_id'] : null;
|
|
186
|
+
if (rawPath === undefined && sessionId === null)
|
|
187
|
+
continue;
|
|
188
|
+
const transcript = rawPath === undefined ? null : canonical(rawPath);
|
|
189
|
+
if (transcript !== null) {
|
|
190
|
+
const owner = seen.get(transcript);
|
|
191
|
+
if (owner !== undefined)
|
|
192
|
+
throw new Error(`cannot import duplicate live transcript ${transcript}: ${owner}, ${nodeId}`);
|
|
193
|
+
seen.set(transcript, nodeId);
|
|
194
|
+
}
|
|
195
|
+
const created = requiredString(meta, 'created', path);
|
|
196
|
+
insert.run(randomUUID(), sessionId, nodeId, transcript, created, created);
|
|
197
|
+
if (indexedPath !== undefined)
|
|
198
|
+
retainedPaths.delete(nodeId);
|
|
199
|
+
}
|
|
200
|
+
for (const [nodeId, rawPath] of retainedPaths) {
|
|
201
|
+
const transcript = canonical(rawPath);
|
|
202
|
+
const owner = seen.get(transcript);
|
|
203
|
+
if (owner !== undefined)
|
|
204
|
+
throw new Error(`cannot import duplicate live transcript ${transcript}: ${owner}, ${nodeId}`);
|
|
205
|
+
seen.set(transcript, nodeId);
|
|
206
|
+
const created = db.prepare('SELECT created FROM nodes WHERE node_id = ?').get(nodeId)?.created;
|
|
207
|
+
if (created !== undefined)
|
|
208
|
+
insert.run(randomUUID(), null, nodeId, transcript, created, created);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
function importWorktrees(db, entries) {
|
|
212
|
+
const insert = db.prepare('INSERT INTO worktrees (node_id, state, cleanup_state, path, branch, repo_root, base_ref, base_sha, created_at, closed_at, next_attempt_at, attempts, quarantined, sweep_reason, sweep_detail, sweep_last_at, sweep_observed_json, abandoned_json, land_intent_json, disposal_json) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)');
|
|
213
|
+
for (const { path, meta } of entries) {
|
|
214
|
+
const wt = optionalObject(meta['managed_worktree'], 'managed worktree', path);
|
|
215
|
+
if (wt === undefined)
|
|
216
|
+
continue;
|
|
217
|
+
const sweep = optionalObject(wt['sweep'], 'managed_worktree.sweep', path);
|
|
218
|
+
insert.run(requiredString(meta, 'node_id', path), requiredString(wt, 'state', path), optionalString(wt, 'cleanup', path), requiredString(wt, 'path', path), requiredString(wt, 'branch', path), requiredString(wt, 'repo_root', path), requiredString(wt, 'base_ref', path), requiredString(wt, 'base_sha', path), requiredString(wt, 'created', path), optionalString(wt, 'closed', path), sweep === undefined ? null : optionalString(sweep, 'next_attempt', path), sweep === undefined ? 0 : optionalNumber(sweep, 'attempts', path) ?? 0, sweep?.['quarantined'] === true ? 1 : 0, sweep === undefined ? null : optionalString(sweep, 'reason', path), sweep === undefined ? null : optionalString(sweep, 'detail', path), sweep === undefined ? null : optionalString(sweep, 'last_attempt', path), json(sweep?.['observed'], 'managed_worktree.sweep.observed', path), json(wt['abandoned'], 'managed_worktree.abandoned', path), json(wt['land_intent'], 'managed_worktree.land_intent', path), json(wt['disposal'], 'managed_worktree.disposal', path));
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
function importExecutions(db) {
|
|
222
|
+
const old = columns(db, 'nodes');
|
|
223
|
+
if (!old.has('pi_pid'))
|
|
224
|
+
return;
|
|
225
|
+
const rows = db.prepare('SELECT node_id, pi_pid, pi_pid_identity, launched_at, created FROM nodes WHERE pi_pid IS NOT NULL').all();
|
|
226
|
+
const insert = db.prepare("INSERT INTO executions (execution_id, node_id, daemon_epoch, pid, process_identity, state, started_at, ended_at, exit_reason) VALUES (?, ?, NULL, ?, ?, 'running', ?, NULL, NULL)");
|
|
227
|
+
for (const row of rows)
|
|
228
|
+
insert.run(randomUUID(), row.node_id, row.pi_pid, row.pi_pid_identity, row.launched_at ?? row.created);
|
|
229
|
+
}
|
|
230
|
+
function validate(db, priorRows) {
|
|
231
|
+
const rows = db.prepare('SELECT COUNT(*) AS count FROM nodes').get().count;
|
|
232
|
+
if (rows < priorRows)
|
|
233
|
+
throw new Error('node import removed an existing SQL row');
|
|
234
|
+
const foreignKeys = db.prepare('PRAGMA foreign_key_check').all();
|
|
235
|
+
if (foreignKeys.length > 0)
|
|
236
|
+
throw new Error('node import foreign key check failed');
|
|
237
|
+
}
|
|
238
|
+
function dropLegacyColumnsAndCreateView(db) {
|
|
239
|
+
db.exec('DROP INDEX IF EXISTS idx_nodes_pi_session_file');
|
|
240
|
+
const known = columns(db, 'nodes');
|
|
241
|
+
for (const name of ['pi_session_file', 'pi_pid', 'pi_pid_identity'])
|
|
242
|
+
if (known.has(name))
|
|
243
|
+
db.exec(`ALTER TABLE nodes DROP COLUMN ${name}`);
|
|
244
|
+
db.exec('DROP VIEW IF EXISTS node_rows');
|
|
245
|
+
db.exec(`CREATE VIEW node_rows AS SELECT n.*, CASE WHEN e.state = 'running' THEN e.pid ELSE NULL END AS pi_pid, CASE WHEN e.state = 'running' THEN e.process_identity ELSE NULL END AS pi_pid_identity, s.session_id AS pi_session_id, s.transcript_path AS pi_session_file FROM nodes n LEFT JOIN executions e ON e.node_id = n.node_id AND e.state != 'exited' LEFT JOIN sessions s ON s.node_id = n.node_id AND s.unbound_at IS NULL`);
|
|
246
|
+
}
|
|
247
|
+
/** Imported by the shared appended consolidation transaction. The caller owns the transaction and user_version. */
|
|
248
|
+
export function importNodeSqlAuthority(db) {
|
|
249
|
+
const priorRows = db.prepare('SELECT COUNT(*) AS count FROM nodes').get().count;
|
|
250
|
+
const retainedPaths = sqlOnlyPaths(db);
|
|
251
|
+
const entries = readMetas();
|
|
252
|
+
addNodeColumns(db);
|
|
253
|
+
createTables(db);
|
|
254
|
+
importMetas(db, entries, retainedPaths);
|
|
255
|
+
importEdges(db, entries);
|
|
256
|
+
importSessions(db, entries, retainedPaths);
|
|
257
|
+
importWorktrees(db, entries);
|
|
258
|
+
importExecutions(db);
|
|
259
|
+
validate(db, priorRows);
|
|
260
|
+
dropLegacyColumnsAndCreateView(db);
|
|
261
|
+
}
|
|
@@ -3,12 +3,7 @@
|
|
|
3
3
|
* visible top-level dir; `canvas/` keeps node-graph runtime state separate from
|
|
4
4
|
* durable user content (memory/plugins/marketplaces/config) at the scope root. */
|
|
5
5
|
export declare function crtrHome(): string;
|
|
6
|
-
/**
|
|
7
|
-
* canvas home, beside the node data it indexes. Guest deployments (Blaxel
|
|
8
|
-
* volumes, local-docker mounts) put the whole canvas home on durable
|
|
9
|
-
* block storage, which supports SQLite's advisory fcntl/WAL locking like any
|
|
10
|
-
* local disk — so the db shares the node data's location and survives a
|
|
11
|
-
* sandbox recreate together with `nodes/`. */
|
|
6
|
+
/** The canvas home requires durable storage with SQLite WAL locking support. */
|
|
12
7
|
export declare function canvasDbPath(): string;
|
|
13
8
|
export declare function onDiskMigrationLockPath(): string;
|
|
14
9
|
export declare function onDiskMigrationMarkerPath(): string;
|
|
@@ -61,17 +56,8 @@ export declare function reportsDir(nodeId: string): string;
|
|
|
61
56
|
export declare function messagesDir(nodeId: string): string;
|
|
62
57
|
export declare function nodeMetaPath(nodeId: string): string;
|
|
63
58
|
export declare function inboxPath(nodeId: string): string;
|
|
64
|
-
/**
|
|
65
|
-
* card, restated by the session-start bearings (see
|
|
66
|
-
* `runtime/situational-context.ts`), upserted in place rather than appended so
|
|
67
|
-
* only the newest applet/situation state is ever carried. Lives beside
|
|
68
|
-
* meta.json/inbox.jsonl (node-runtime state) rather than under context/ (the
|
|
69
|
-
* user-authored artifact store), because it is ambient machine state, not a
|
|
70
|
-
* document a human wrote. */
|
|
59
|
+
/** Rendered ambient context lives outside the user-authored context directory. */
|
|
71
60
|
export declare function situationalContextPath(nodeId: string): string;
|
|
72
|
-
/** Passive-subscription accumulator. Pushes from publishers this node subscribes
|
|
73
|
-
* to PASSIVELY land here instead of inbox.jsonl — the inbox-watcher never polls
|
|
74
|
-
* it, so they never wake the node. Drained as XML pre-text on the next message. */
|
|
75
61
|
export declare function passivePath(nodeId: string): string;
|
|
76
62
|
export declare function transcriptPath(nodeId: string): string;
|
|
77
63
|
export declare function sessionPtrPath(nodeId: string): string;
|
|
@@ -1,18 +1,3 @@
|
|
|
1
|
-
// The `~/.crouter/canvas/` layout. One global, cwd-agnostic home for the whole canvas.
|
|
2
|
-
//
|
|
3
|
-
// ~/.crouter/canvas/
|
|
4
|
-
// canvas.db sqlite (WAL) — topology only (nodes + edges)
|
|
5
|
-
// nodes/<node_id>/
|
|
6
|
-
// meta.json source of truth for the node's row
|
|
7
|
-
// context/ roadmap.md, initial-prompt.md, explore-*.md, artifacts
|
|
8
|
-
// job/ log.jsonl (canonical broker events), telemetry.json and fault (current state), broker.log (raw residue)
|
|
9
|
-
// reports/ append-only push history (<ts>-<kind>.md)
|
|
10
|
-
// messages/ overflow bodies for inbox entries too long to inline
|
|
11
|
-
// inbox.jsonl messages + coalesced subscription feed
|
|
12
|
-
// transcript.jsonl mirror/pointer of the pi session
|
|
13
|
-
// session.ptr pi session id/path
|
|
14
|
-
//
|
|
15
|
-
// `CRTR_HOME` overrides the root (used by tests and isolated runs).
|
|
16
1
|
import { homedir } from 'node:os';
|
|
17
2
|
import { join } from 'node:path';
|
|
18
3
|
import { mkdirSync } from 'node:fs';
|
|
@@ -27,12 +12,7 @@ export function crtrHome() {
|
|
|
27
12
|
? override
|
|
28
13
|
: join(homedir(), CRTR_DIR_NAME, 'canvas');
|
|
29
14
|
}
|
|
30
|
-
/**
|
|
31
|
-
* canvas home, beside the node data it indexes. Guest deployments (Blaxel
|
|
32
|
-
* volumes, local-docker mounts) put the whole canvas home on durable
|
|
33
|
-
* block storage, which supports SQLite's advisory fcntl/WAL locking like any
|
|
34
|
-
* local disk — so the db shares the node data's location and survives a
|
|
35
|
-
* sandbox recreate together with `nodes/`. */
|
|
15
|
+
/** The canvas home requires durable storage with SQLite WAL locking support. */
|
|
36
16
|
export function canvasDbPath() {
|
|
37
17
|
return join(crtrHome(), 'canvas.db');
|
|
38
18
|
}
|
|
@@ -143,19 +123,10 @@ export function nodeMetaPath(nodeId) {
|
|
|
143
123
|
export function inboxPath(nodeId) {
|
|
144
124
|
return join(nodeDir(nodeId), 'inbox.jsonl');
|
|
145
125
|
}
|
|
146
|
-
/**
|
|
147
|
-
* card, restated by the session-start bearings (see
|
|
148
|
-
* `runtime/situational-context.ts`), upserted in place rather than appended so
|
|
149
|
-
* only the newest applet/situation state is ever carried. Lives beside
|
|
150
|
-
* meta.json/inbox.jsonl (node-runtime state) rather than under context/ (the
|
|
151
|
-
* user-authored artifact store), because it is ambient machine state, not a
|
|
152
|
-
* document a human wrote. */
|
|
126
|
+
/** Rendered ambient context lives outside the user-authored context directory. */
|
|
153
127
|
export function situationalContextPath(nodeId) {
|
|
154
128
|
return join(nodeDir(nodeId), 'situational-context.md');
|
|
155
129
|
}
|
|
156
|
-
/** Passive-subscription accumulator. Pushes from publishers this node subscribes
|
|
157
|
-
* to PASSIVELY land here instead of inbox.jsonl — the inbox-watcher never polls
|
|
158
|
-
* it, so they never wake the node. Drained as XML pre-text on the next message. */
|
|
159
130
|
export function passivePath(nodeId) {
|
|
160
131
|
return join(nodeDir(nodeId), 'passive.jsonl');
|
|
161
132
|
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { DatabaseSync } from 'node:sqlite';
|
|
2
|
+
import { type Fault, type FaultKind, type FaultLink, type FaultProviderError, type FaultRetry } from '../fault-classifier.js';
|
|
3
|
+
export type { Fault, FaultKind, FaultLink, FaultProviderError, FaultRetry } from '../fault-classifier.js';
|
|
4
|
+
export declare const FAULT_QUIET_MS: number;
|
|
5
|
+
export interface FaultRecordInput {
|
|
6
|
+
link: FaultLink;
|
|
7
|
+
op: string;
|
|
8
|
+
kind: FaultKind;
|
|
9
|
+
retry: FaultRetry;
|
|
10
|
+
message: string;
|
|
11
|
+
operation_id?: string;
|
|
12
|
+
since?: string;
|
|
13
|
+
anchorEntryId?: string;
|
|
14
|
+
providerError?: FaultProviderError;
|
|
15
|
+
}
|
|
16
|
+
export interface StoredFault extends Fault {
|
|
17
|
+
faultId: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ProviderRetryEpisode {
|
|
20
|
+
state: 'pending' | 'admitted' | 'invalidated';
|
|
21
|
+
sessionId: string | null;
|
|
22
|
+
fault: StoredFault;
|
|
23
|
+
}
|
|
24
|
+
export interface TransportPoisonVerdict {
|
|
25
|
+
consecutivePasses: number;
|
|
26
|
+
routes: string[];
|
|
27
|
+
}
|
|
28
|
+
export interface BootFaultAttempt {
|
|
29
|
+
explanation(): string | null;
|
|
30
|
+
}
|
|
31
|
+
export declare function parseProviderError(value: unknown): FaultProviderError | undefined;
|
|
32
|
+
export declare function openTurn(executionId: string, _opts: {
|
|
33
|
+
reason: 'agent-start' | 'prompt-unsettled';
|
|
34
|
+
}): boolean;
|
|
35
|
+
export declare function recordTurnProgress(executionId: string): boolean;
|
|
36
|
+
export declare function closeTurn(executionId: string, opts: {
|
|
37
|
+
endReason: 'settled' | 'teardown-aborted';
|
|
38
|
+
}): boolean;
|
|
39
|
+
export declare function recordTransportPoisonVerdict(executionId: string, verdict: TransportPoisonVerdict): boolean;
|
|
40
|
+
export declare function readTransportPoisonVerdict(nodeId: string): TransportPoisonVerdict | null;
|
|
41
|
+
export declare function readLiveTurn(nodeId: string): {
|
|
42
|
+
busy: boolean;
|
|
43
|
+
progressAt: string | null;
|
|
44
|
+
} | null;
|
|
45
|
+
export declare function readInterruptedTurn(nodeId: string): {
|
|
46
|
+
interrupted: boolean;
|
|
47
|
+
progressAt: string | null;
|
|
48
|
+
} | null;
|
|
49
|
+
export declare function recordFault(nodeId: string, input: FaultRecordInput): StoredFault | null;
|
|
50
|
+
export declare function clearFault(nodeId: string, opts?: {
|
|
51
|
+
link?: FaultLink;
|
|
52
|
+
preserveEpisode?: boolean;
|
|
53
|
+
}): boolean;
|
|
54
|
+
export declare function readFault(nodeId: string): StoredFault | null;
|
|
55
|
+
export declare function recordPendingEpisode(nodeId: string, input: {
|
|
56
|
+
sessionId: string;
|
|
57
|
+
input: FaultRecordInput;
|
|
58
|
+
}): StoredFault | null;
|
|
59
|
+
export declare function admitEpisode(nodeId: string, input: {
|
|
60
|
+
sessionId: string;
|
|
61
|
+
faultId: string;
|
|
62
|
+
retry: FaultRetry;
|
|
63
|
+
}): boolean;
|
|
64
|
+
export declare function reopenEpisode(nodeId: string, input: {
|
|
65
|
+
sessionId: string;
|
|
66
|
+
}): boolean;
|
|
67
|
+
export declare function invalidateEpisode(nodeId: string, input: {
|
|
68
|
+
sessionId: string;
|
|
69
|
+
}): boolean;
|
|
70
|
+
export declare function clearEpisode(nodeId: string, input: {
|
|
71
|
+
sessionId: string;
|
|
72
|
+
}): boolean;
|
|
73
|
+
export declare function readEpisode(nodeId: string): ProviderRetryEpisode | null;
|
|
74
|
+
export declare function beginBootFaultAttempt(nodeId: string): BootFaultAttempt;
|
|
75
|
+
/** Import legacy witness and recovery files inside the parent's one shared consolidation transaction. */
|
|
76
|
+
export declare function migrateRecoveryWitnesses(db: DatabaseSync): void;
|