@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
|
@@ -11,7 +11,7 @@ import assert from 'node:assert/strict';
|
|
|
11
11
|
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
12
12
|
import { tmpdir } from 'node:os';
|
|
13
13
|
import { join } from 'node:path';
|
|
14
|
-
import { closeDb } from '../canvas/db.js';
|
|
14
|
+
import { closeDb, migrate, openDb } from '../canvas/db.js';
|
|
15
15
|
import { resetScopeCache } from '../scope.js';
|
|
16
16
|
import { spawnNode } from '../runtime/nodes.js';
|
|
17
17
|
import { renderOnReadDocs, renderWorkspaceOpenDocs } from '../substrate/on-read-node.js';
|
|
@@ -36,6 +36,7 @@ beforeEach(() => {
|
|
|
36
36
|
process.env['HOME'] = fakeHome;
|
|
37
37
|
canvasHome = mkdtempSync(join(tmpdir(), 'crtr-nested-canvas-'));
|
|
38
38
|
process.env['CRTR_HOME'] = canvasHome;
|
|
39
|
+
migrate(openDb());
|
|
39
40
|
});
|
|
40
41
|
after(() => {
|
|
41
42
|
closeDb();
|
|
@@ -1,49 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
// 1. A passive subscriber's pushes land in passive.jsonl, NOT inbox.jsonl
|
|
3
|
-
// (so the inbox-watcher never wakes it); an active subscriber's land in
|
|
4
|
-
// inbox.jsonl as before.
|
|
5
|
-
// 2. the broker drain reads + clears the accumulator (surfaces exactly once).
|
|
6
|
-
// 3. canvas-passive-context formats drained entries as timestamped XML and
|
|
7
|
-
// transforms an `input` event into pre-text + the original message.
|
|
8
|
-
//
|
|
9
|
-
// Run: node --import tsx/esm --test src/core/__tests__/passive-subscription.test.ts
|
|
10
|
-
import { test, before, beforeEach, afterEach, after } from 'node:test';
|
|
1
|
+
import { after, before, beforeEach, test } from 'node:test';
|
|
11
2
|
import assert from 'node:assert/strict';
|
|
12
|
-
import { mkdtempSync, mkdirSync, rmSync
|
|
3
|
+
import { mkdtempSync, mkdirSync, rmSync } from 'node:fs';
|
|
13
4
|
import { tmpdir } from 'node:os';
|
|
14
5
|
import { basename, join } from 'node:path';
|
|
15
6
|
import { createNode, subscribe } from '../canvas/canvas.js';
|
|
16
7
|
import { armCron, getCron } from '../canvas/crons.js';
|
|
17
|
-
import { closeDb } from '../canvas/db.js';
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
8
|
+
import { closeDb, migrate, openDb } from '../canvas/db.js';
|
|
9
|
+
import { acknowledgeNodeMail, claimNodeMail, hasUnseenWakeMail } from '../canvas/deliveries.js';
|
|
10
|
+
import { beginExecution } from '../canvas/executions.js';
|
|
20
11
|
import { push } from '../feed/feed.js';
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import { drainBrokerPassive } from '../runtime/broker/passive.js';
|
|
24
|
-
import { readLeaf } from '../../commands/canvas-history/read.js';
|
|
25
|
-
import registerCanvasPassiveContext from '../../pi-extensions/canvas-passive-context.js';
|
|
12
|
+
import { nodeMailEntry } from '../feed/inbox.js';
|
|
13
|
+
import { formatPassive } from '../../pi-extensions/canvas-passive-context.js';
|
|
26
14
|
let home;
|
|
27
|
-
function readPassiveEntries(nodeId) {
|
|
28
|
-
const path = passivePath(nodeId);
|
|
29
|
-
if (!existsSync(path))
|
|
30
|
-
return [];
|
|
31
|
-
return readFileSync(path, 'utf8').split('\n').filter(Boolean).map((line) => JSON.parse(line));
|
|
32
|
-
}
|
|
33
|
-
// The one test that resolves an emitted feed ref drives `canvas history read`'s
|
|
34
|
-
// leaf (`readLeaf`), a thin CLI forwarder to crtrd since the API re-plumb. Stand
|
|
35
|
-
// up a real in-process `createApiServer()` on the isolated CRTR_HOME's socket so
|
|
36
|
-
// that read resolves through the genuine daemon seam — no autostarted
|
|
37
|
-
// subprocess, no mock client.
|
|
38
|
-
let server;
|
|
39
|
-
async function waitForSocket(path) {
|
|
40
|
-
for (let i = 0; i < 200; i++) {
|
|
41
|
-
if (existsSync(path))
|
|
42
|
-
return;
|
|
43
|
-
await new Promise((r) => setTimeout(r, 25));
|
|
44
|
-
}
|
|
45
|
-
throw new Error(`api socket never bound at ${path}`);
|
|
46
|
-
}
|
|
47
15
|
function node(id, over = {}) {
|
|
48
16
|
return {
|
|
49
17
|
node_id: id,
|
|
@@ -57,53 +25,44 @@ function node(id, over = {}) {
|
|
|
57
25
|
...over,
|
|
58
26
|
};
|
|
59
27
|
}
|
|
28
|
+
function execution(nodeId) {
|
|
29
|
+
return beginExecution(nodeId, { daemonEpoch: 'test' });
|
|
30
|
+
}
|
|
60
31
|
before(() => {
|
|
61
32
|
home = mkdtempSync(join(tmpdir(), 'crtr-passive-'));
|
|
62
33
|
process.env['CRTR_HOME'] = home;
|
|
63
34
|
});
|
|
64
|
-
beforeEach(
|
|
35
|
+
beforeEach(() => {
|
|
65
36
|
closeDb();
|
|
66
37
|
rmSync(home, { recursive: true, force: true });
|
|
67
38
|
mkdirSync(home, { recursive: true });
|
|
68
|
-
|
|
69
|
-
await waitForSocket(apiSocketPath());
|
|
70
|
-
});
|
|
71
|
-
afterEach(async () => {
|
|
72
|
-
await server?.close();
|
|
39
|
+
migrate(openDb());
|
|
73
40
|
});
|
|
74
41
|
after(() => {
|
|
75
42
|
closeDb();
|
|
76
43
|
rmSync(home, { recursive: true, force: true });
|
|
77
44
|
delete process.env['CRTR_HOME'];
|
|
78
|
-
delete process.env['CRTR_NODE_ID'];
|
|
79
45
|
});
|
|
80
|
-
test('passive
|
|
46
|
+
test('a passive subscriber receives a non-waking SQL delivery with the canonical report ref', async () => {
|
|
81
47
|
createNode(node('pub'));
|
|
82
48
|
createNode(node('observer'));
|
|
83
|
-
subscribe('observer', 'pub', false);
|
|
49
|
+
subscribe('observer', 'pub', false);
|
|
84
50
|
const result = await push('pub', { kind: 'update', body: 'first observation\nmore detail' });
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
assert.equal(
|
|
90
|
-
const
|
|
91
|
-
assert.equal(
|
|
92
|
-
assert.equal(
|
|
93
|
-
assert.equal(result.reportPath
|
|
94
|
-
|
|
95
|
-
assert.equal(existsSync(inboxPath('observer')), false);
|
|
96
|
-
assert.equal(readInboxSince('observer').length, 0);
|
|
97
|
-
// It landed in the passive accumulator instead.
|
|
98
|
-
assert.equal(acc.length, 1);
|
|
99
|
-
assert.equal(acc[0].from, 'pub');
|
|
100
|
-
assert.equal(acc[0].label, 'first observation');
|
|
101
|
-
assert.match(acc[0].ref ?? '', /^pub:reports\/\d{8}T\d{9}-[0-9a-f]{8}-update\.md$/, 'report refs use a compact random suffix');
|
|
51
|
+
const executionId = execution('observer');
|
|
52
|
+
const claim = claimNodeMail('observer', executionId, 'passive');
|
|
53
|
+
assert.equal(hasUnseenWakeMail('observer'), false, 'passive mail does not wake a node');
|
|
54
|
+
assert.equal(claim.action, 'claimed');
|
|
55
|
+
assert.equal(claim.deliveries.length, 1);
|
|
56
|
+
const entry = nodeMailEntry(claim.deliveries[0]);
|
|
57
|
+
assert.equal(entry.from, 'pub');
|
|
58
|
+
assert.equal(entry.label, 'first observation');
|
|
59
|
+
assert.equal(entry.ref, `pub:reports/${basename(result.reportPath)}`);
|
|
60
|
+
assert.match(entry.ref ?? '', /^pub:reports\/\d{8}T\d{9}-[0-9a-f]{8}-update\.md$/);
|
|
102
61
|
});
|
|
103
|
-
test('active
|
|
62
|
+
test('an active subscriber receives waking SQL mail and clears its deadline', async () => {
|
|
104
63
|
createNode(node('pub'));
|
|
105
64
|
createNode(node('worker-mgr'));
|
|
106
|
-
subscribe('worker-mgr', 'pub', true);
|
|
65
|
+
subscribe('worker-mgr', 'pub', true);
|
|
107
66
|
armCron({
|
|
108
67
|
cron_id: 'manager-deadline',
|
|
109
68
|
name: 'manager deadline',
|
|
@@ -126,102 +85,36 @@ test('active push still lands in inbox.jsonl (wakes) and clears the manager dead
|
|
|
126
85
|
tier: 'normal',
|
|
127
86
|
});
|
|
128
87
|
await push('pub', { kind: 'update', body: 'active report' });
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
assert.equal(
|
|
132
|
-
assert.equal(
|
|
133
|
-
assert.
|
|
134
|
-
assert.equal(getCron('manager-deadline'), null, 'the child report won the deadline race');
|
|
135
|
-
});
|
|
136
|
-
test('a deferred update still lands in an active subscriber inbox at deferred tier', async () => {
|
|
137
|
-
createNode(node('pub'));
|
|
138
|
-
// Resident: deferred mail to a TERMINAL target is bumped to urgent by the
|
|
139
|
-
// shipped tier bump, so only a resident subscriber shows the requested tier.
|
|
140
|
-
createNode(node('worker-mgr', { lifecycle: 'resident' }));
|
|
141
|
-
subscribe('worker-mgr', 'pub', true); // ACTIVE
|
|
142
|
-
await push('pub', { kind: 'update', deliveryTier: 'deferred', body: 'active report' });
|
|
143
|
-
assert.equal(existsSync(passivePath('worker-mgr')), false);
|
|
144
|
-
const inbox = readInboxSince('worker-mgr');
|
|
145
|
-
assert.equal(inbox.length, 1);
|
|
146
|
-
assert.equal(inbox[0].from, 'pub');
|
|
147
|
-
assert.equal(inbox[0].tier, 'deferred', 'requested delivery urgency reaches the subscriber unchanged');
|
|
148
|
-
assert.equal(inbox[0].kind, 'update', 'the stored report kind is untouched by delivery urgency');
|
|
149
|
-
assert.match(inbox[0].ref ?? '', /^pub:reports\/.+-update\.md$/);
|
|
88
|
+
const claim = claimNodeMail('worker-mgr', execution('worker-mgr'), 'wake');
|
|
89
|
+
assert.equal(hasUnseenWakeMail('worker-mgr'), true);
|
|
90
|
+
assert.equal(getCron('manager-deadline'), null, 'the report won the deadline race');
|
|
91
|
+
assert.equal(claim.deliveries.length, 1);
|
|
92
|
+
assert.equal(nodeMailEntry(claim.deliveries[0]).from, 'pub');
|
|
150
93
|
});
|
|
151
|
-
test('
|
|
94
|
+
test('a passive delivery is acknowledged only after it has been claimed', async () => {
|
|
152
95
|
createNode(node('pub'));
|
|
153
|
-
createNode(node('active-sub'));
|
|
154
|
-
createNode(node('passive-sub'));
|
|
155
|
-
subscribe('active-sub', 'pub', true);
|
|
156
|
-
subscribe('passive-sub', 'pub', false);
|
|
157
|
-
const res = await push('pub', { kind: 'urgent', body: 'something happened' });
|
|
158
|
-
assert.deepEqual(new Set(res.deliveredTo), new Set(['active-sub', 'passive-sub']));
|
|
159
|
-
assert.equal(readInboxSince('active-sub').length, 1);
|
|
160
|
-
assert.equal(existsSync(passivePath('active-sub')), false);
|
|
161
|
-
assert.equal(readPassiveEntries('passive-sub').length, 1);
|
|
162
|
-
assert.equal(existsSync(inboxPath('passive-sub')), false);
|
|
163
|
-
});
|
|
164
|
-
test('broker passive drain reads then clears (surfaces exactly once)', () => {
|
|
165
|
-
createNode(node('observer'));
|
|
166
|
-
appendPassive('observer', { from: 'a', tier: 'normal', kind: 'update', label: 'one' });
|
|
167
|
-
appendPassive('observer', { from: 'b', tier: 'normal', kind: 'update', label: 'two' });
|
|
168
|
-
const drained = drainBrokerPassive('observer');
|
|
169
|
-
assert.equal(drained.length, 2);
|
|
170
|
-
assert.deepEqual(drained.map((e) => e.label), ['one', 'two']); // oldest first
|
|
171
|
-
// Cleared — a second drain is empty.
|
|
172
|
-
assert.equal(drainBrokerPassive('observer').length, 0);
|
|
173
|
-
assert.equal(readPassiveEntries('observer').length, 0);
|
|
174
|
-
});
|
|
175
|
-
test('broker passive drain tolerates a corrupt line — keeps every good entry, loses only the bad one', () => {
|
|
176
96
|
createNode(node('observer'));
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
assert.
|
|
97
|
+
subscribe('observer', 'pub', false);
|
|
98
|
+
await push('pub', { kind: 'update', body: 'one' });
|
|
99
|
+
await push('pub', { kind: 'update', body: 'two' });
|
|
100
|
+
const executionId = execution('observer');
|
|
101
|
+
const claim = claimNodeMail('observer', executionId, 'passive');
|
|
102
|
+
assert.deepEqual(claim.deliveries.map((delivery) => nodeMailEntry(delivery).label), ['one', 'two']);
|
|
103
|
+
const receipt = acknowledgeNodeMail('observer', executionId, claim.deliveries.map((delivery) => ({
|
|
104
|
+
deliveryId: delivery.deliveryId,
|
|
105
|
+
attempts: delivery.attempts,
|
|
106
|
+
disposition: 'acknowledged',
|
|
107
|
+
})));
|
|
108
|
+
assert.deepEqual(receipt.results.map((result) => result.outcome), ['acknowledged', 'acknowledged']);
|
|
109
|
+
assert.deepEqual(claimNodeMail('observer', executionId, 'passive').deliveries, []);
|
|
189
110
|
});
|
|
190
|
-
|
|
191
|
-
return { on(e, h) { if (e === 'input')
|
|
192
|
-
this.handler = h; } };
|
|
193
|
-
}
|
|
194
|
-
test('input handler injects drained backlog as pre-text, then clears it', async () => {
|
|
111
|
+
test('passive SQL mail retains the existing timestamped backlog rendering', async () => {
|
|
195
112
|
createNode(node('pub'));
|
|
196
113
|
createNode(node('observer'));
|
|
197
114
|
subscribe('observer', 'pub', false);
|
|
198
115
|
await push('pub', { kind: 'update', body: 'the body of the report\nsecond line' });
|
|
199
|
-
|
|
200
|
-
const
|
|
201
|
-
|
|
202
|
-
assert.
|
|
203
|
-
// First message → backlog drains in as pre-text before the user's text.
|
|
204
|
-
const out = await pi.handler({ type: 'input', text: 'hey what happened', source: 'interactive' });
|
|
205
|
-
assert.equal(out.action, 'transform');
|
|
206
|
-
assert.match(out.text, /<passive-subscription-backlog/);
|
|
207
|
-
assert.match(out.text, /the body of the report/); // dereferenced report body
|
|
208
|
-
assert.match(out.text, /hey what happened$/); // original message preserved at the end
|
|
209
|
-
// Second message → nothing accumulated → left untouched.
|
|
210
|
-
const out2 = await pi.handler({ type: 'input', text: 'still there?', source: 'interactive' });
|
|
211
|
-
assert.ok(out2 === undefined || out2.action === 'continue');
|
|
212
|
-
// Oversized canonical reports must leave an actionable reader command in the
|
|
213
|
-
// truncation tail, using the exact ref emitted into the passive feed.
|
|
214
|
-
await push('pub', { kind: 'update', body: 'oversized report line '.repeat(250) });
|
|
215
|
-
const oversizedRef = readPassiveEntries('observer')[0].ref;
|
|
216
|
-
const out3 = await pi.handler({ type: 'input', text: 'show me the rest', source: 'interactive' });
|
|
217
|
-
assert.equal(out3.action, 'transform');
|
|
218
|
-
assert.ok(out3.text.includes(`crtr canvas history read ${oversizedRef}`), 'truncation tail names the canonical reader and emitted ref');
|
|
219
|
-
});
|
|
220
|
-
test('input handler is inert when nothing is accumulated', async () => {
|
|
221
|
-
createNode(node('observer'));
|
|
222
|
-
process.env['CRTR_NODE_ID'] = 'observer';
|
|
223
|
-
const pi = makeFakePi();
|
|
224
|
-
registerCanvasPassiveContext(pi);
|
|
225
|
-
const out = await pi.handler({ type: 'input', text: 'plain message', source: 'interactive' });
|
|
226
|
-
assert.ok(out === undefined || out.action === 'continue');
|
|
116
|
+
const claim = claimNodeMail('observer', execution('observer'), 'passive');
|
|
117
|
+
const text = formatPassive(claim.deliveries.map(nodeMailEntry));
|
|
118
|
+
assert.match(text, /<passive-subscription-backlog/);
|
|
119
|
+
assert.match(text, /the body of the report/);
|
|
227
120
|
});
|
|
@@ -17,7 +17,8 @@ import { tmpdir } from 'node:os';
|
|
|
17
17
|
import { join } from 'node:path';
|
|
18
18
|
import * as tar from 'tar';
|
|
19
19
|
import { resetScopeCache } from '../scope.js';
|
|
20
|
-
import { readMergedLaunchConfig } from '../config.js';
|
|
20
|
+
import { readMergedLaunchConfig, updateRawConfigAtomically, writeRawConfig } from '../config.js';
|
|
21
|
+
import { initializeFreshScopedStore } from '../scoped-state/migrate.js';
|
|
21
22
|
import { validatePluginBundle } from '../command-plugins/bundle.js';
|
|
22
23
|
let isolatedHome;
|
|
23
24
|
let isolatedCwd;
|
|
@@ -32,6 +33,7 @@ beforeEach(() => {
|
|
|
32
33
|
isolatedCwd = realpathSync(mkdtempSync(join(tmpdir(), 'crtr-plugin-kinds-cwd-')));
|
|
33
34
|
process.env.HOME = isolatedHome;
|
|
34
35
|
process.chdir(isolatedCwd);
|
|
36
|
+
initializeFreshScopedStore({ kind: 'user', root: join(isolatedHome, '.crouter') });
|
|
35
37
|
resetScopeCache();
|
|
36
38
|
});
|
|
37
39
|
afterEach(() => {
|
|
@@ -76,7 +78,7 @@ test('the scope\u2019s own config.json overrides its plugins; a disabled plugin
|
|
|
76
78
|
const root = userRoot();
|
|
77
79
|
plantPlugin(root, 'northlight', { 'applet-builder': { whenToUse: 'plugin gloss', model: 'anthropic/strong' } });
|
|
78
80
|
plantPlugin(root, 'zzz-disabled', { ghost: { whenToUse: 'never registers' } });
|
|
79
|
-
|
|
81
|
+
updateRawConfigAtomically('user', () => ({
|
|
80
82
|
plugins: { 'zzz-disabled': { enabled: false } },
|
|
81
83
|
kinds: { 'applet-builder': { model: 'openai/medium' } },
|
|
82
84
|
}));
|
|
@@ -91,7 +93,7 @@ test('a whenToUse-only entry re-glosses an existing kind without stripping its m
|
|
|
91
93
|
// Now every entry field-merges over an existing kind; only a NEW kind
|
|
92
94
|
// requires whenToUse (a whenToUse-less new kind is dropped).
|
|
93
95
|
const root = userRoot();
|
|
94
|
-
|
|
96
|
+
updateRawConfigAtomically('user', () => ({ kinds: { explore: { whenToUse: 'custom explore gloss' }, 'new-glossless': { model: 'openai/light' } } }));
|
|
95
97
|
const kinds = readMergedLaunchConfig().kinds;
|
|
96
98
|
assert.equal(kinds['explore']?.whenToUse, 'custom explore gloss');
|
|
97
99
|
assert.equal(kinds['explore']?.model, 'openai/light'); // builtin tier survives
|
|
@@ -100,7 +102,7 @@ test('a whenToUse-only entry re-glosses an existing kind without stripping its m
|
|
|
100
102
|
});
|
|
101
103
|
test('a project-root plugin layers above user config, and the project config above the plugin', () => {
|
|
102
104
|
const uRoot = userRoot();
|
|
103
|
-
|
|
105
|
+
writeRawConfig('user', { kinds: { shared: { whenToUse: 'user gloss', model: 'openai/light' } } });
|
|
104
106
|
const pRoot = projectRoot();
|
|
105
107
|
plantPlugin(pRoot, 'proj-plugin', { shared: { model: 'anthropic/strong' }, 'proj-kind': { whenToUse: 'project plugin kind' } });
|
|
106
108
|
writeFileSync(join(pRoot, 'config.json'), JSON.stringify({ kinds: { 'proj-kind': { model: 'openai/medium' } } }));
|
|
@@ -11,8 +11,11 @@ import assert from 'node:assert/strict';
|
|
|
11
11
|
import { mkdtempSync, mkdirSync, rmSync, symlinkSync, writeFileSync } from 'node:fs';
|
|
12
12
|
import { tmpdir } from 'node:os';
|
|
13
13
|
import { join } from 'node:path';
|
|
14
|
+
import { realpathSync } from 'node:fs';
|
|
14
15
|
import { linkOrCopy } from '../fs-utils.js';
|
|
15
16
|
import { listInstalledPluginsInRoot } from '../resolver.js';
|
|
17
|
+
import { closeScopedStores } from '../scoped-state/db.js';
|
|
18
|
+
import { initializeFreshScopedStore } from '../scoped-state/migrate.js';
|
|
16
19
|
describe('plugin link through a symlinked scope-root ancestor', () => {
|
|
17
20
|
test('the installed plugin resolves on the next invocation', () => {
|
|
18
21
|
const base = mkdtempSync(join(tmpdir(), 'crtr-plugin-link-'));
|
|
@@ -28,10 +31,12 @@ describe('plugin link through a symlinked scope-root ancestor', () => {
|
|
|
28
31
|
symlinkSync(join('physical', 'home'), join(base, 'home'), 'dir');
|
|
29
32
|
const scopeRootPath = join(base, 'home', '.crouter');
|
|
30
33
|
mkdirSync(join(scopeRootPath, 'plugins'), { recursive: true });
|
|
34
|
+
initializeFreshScopedStore({ kind: 'user', root: scopeRootPath });
|
|
31
35
|
linkOrCopy(source, join(scopeRootPath, 'plugins', 'search'));
|
|
32
|
-
assert.deepEqual(listInstalledPluginsInRoot('user', scopeRootPath).map((p) => p.name), ['search']);
|
|
36
|
+
assert.deepEqual(listInstalledPluginsInRoot('user', realpathSync(scopeRootPath)).map((p) => p.name), ['search']);
|
|
33
37
|
}
|
|
34
38
|
finally {
|
|
39
|
+
closeScopedStores();
|
|
35
40
|
rmSync(base, { recursive: true, force: true });
|
|
36
41
|
}
|
|
37
42
|
});
|
|
@@ -15,7 +15,8 @@ import { tmpdir } from 'node:os';
|
|
|
15
15
|
import { join } from 'node:path';
|
|
16
16
|
import * as tar from 'tar';
|
|
17
17
|
import { resetScopeCache } from '../scope.js';
|
|
18
|
-
import { resolvePageComponents } from '../config.js';
|
|
18
|
+
import { resolvePageComponents, updateRawConfigAtomically, writeRawConfig } from '../config.js';
|
|
19
|
+
import { initializeFreshScopedStore } from '../scoped-state/migrate.js';
|
|
19
20
|
import { validatePluginBundle } from '../command-plugins/bundle.js';
|
|
20
21
|
let isolatedHome;
|
|
21
22
|
let isolatedCwd;
|
|
@@ -30,6 +31,7 @@ beforeEach(() => {
|
|
|
30
31
|
isolatedCwd = realpathSync(mkdtempSync(join(tmpdir(), 'crtr-page-components-cwd-')));
|
|
31
32
|
process.env.HOME = isolatedHome;
|
|
32
33
|
process.chdir(isolatedCwd);
|
|
34
|
+
initializeFreshScopedStore({ kind: 'user', root: join(isolatedHome, '.crouter') });
|
|
33
35
|
resetScopeCache();
|
|
34
36
|
});
|
|
35
37
|
afterEach(() => {
|
|
@@ -60,7 +62,7 @@ test('an enabled user-scope plugin contributes its page components; a disabled o
|
|
|
60
62
|
{ kind: 'applet-card', display: true },
|
|
61
63
|
]);
|
|
62
64
|
plantPlugin(root, 'zzz-disabled', ['ghost']);
|
|
63
|
-
|
|
65
|
+
writeRawConfig('user', { plugins: { 'zzz-disabled': { enabled: false } } });
|
|
64
66
|
const components = resolvePageComponents();
|
|
65
67
|
assert.deepEqual(components, [
|
|
66
68
|
{ kind: 'connector', description: 'Connector decision', useWhen: 'Use for a connector decision.', doc: 'Product contract.' },
|
|
@@ -70,9 +72,9 @@ test('an enabled user-scope plugin contributes its page components; a disabled o
|
|
|
70
72
|
test('user config entries and plugin contributions resolve together, and a colliding kind is rejected', () => {
|
|
71
73
|
const root = userRoot();
|
|
72
74
|
plantPlugin(root, 'northlight', ['connector']);
|
|
73
|
-
|
|
75
|
+
updateRawConfigAtomically('user', () => ({ page_components: ['approval'] }));
|
|
74
76
|
assert.deepEqual(resolvePageComponents().map((component) => component.kind), ['approval', 'connector']);
|
|
75
|
-
|
|
77
|
+
updateRawConfigAtomically('user', () => ({ page_components: ['connector'] }));
|
|
76
78
|
assert.throws(() => resolvePageComponents(), /page component kind "connector" is registered by both config.json and plugin "northlight"/);
|
|
77
79
|
});
|
|
78
80
|
test('two plugins whose kinds derive one JSX tag are rejected, naming both sources', () => {
|
|
@@ -16,6 +16,7 @@ import { tmpdir } from 'node:os';
|
|
|
16
16
|
import { join } from 'node:path';
|
|
17
17
|
import { buildRoot } from '../../build-root.js';
|
|
18
18
|
import { SUPPRESS_OUTPUT_LEAVES, LEAF_ICON_CP, SUMMARIZERS } from '../preview-registry.js';
|
|
19
|
+
import { ensureScopeInitialized } from '../config.js';
|
|
19
20
|
import { resetScopeCache } from '../scope.js';
|
|
20
21
|
// buildRoot() composes external command-plugin branches from the effective
|
|
21
22
|
// enabled plugins (user scope + project ancestors). Pin HOME + profile to an
|
|
@@ -31,6 +32,7 @@ before(() => {
|
|
|
31
32
|
process.env['HOME'] = home;
|
|
32
33
|
delete process.env['CRTR_PROFILE_ID'];
|
|
33
34
|
resetScopeCache();
|
|
35
|
+
ensureScopeInitialized('user', join(home, '.crouter'));
|
|
34
36
|
});
|
|
35
37
|
after(() => {
|
|
36
38
|
if (realHome !== undefined)
|
|
@@ -18,9 +18,10 @@ import assert from 'node:assert/strict';
|
|
|
18
18
|
import { mkdtempSync, mkdirSync, realpathSync, rmSync, writeFileSync } from 'node:fs';
|
|
19
19
|
import { tmpdir } from 'node:os';
|
|
20
20
|
import { dirname, join } from 'node:path';
|
|
21
|
-
import { closeDb } from '../canvas/db.js';
|
|
21
|
+
import { closeDb, migrate, openDb } from '../canvas/db.js';
|
|
22
22
|
import { resetScopeCache } from '../scope.js';
|
|
23
23
|
import { createProfile } from '../profiles/manifest.js';
|
|
24
|
+
import { initializeFreshScopedStore } from '../scoped-state/migrate.js';
|
|
24
25
|
import { spawnNode } from '../runtime/nodes.js';
|
|
25
26
|
import { memoryDir } from '../runtime/memory.js';
|
|
26
27
|
import { clearSessionCache } from '../substrate/session-cache.js';
|
|
@@ -115,6 +116,8 @@ before(() => {
|
|
|
115
116
|
canvasHome = realpathSync(mkdtempSync(join(tmpdir(), 'crtr-ppm-canvas-')));
|
|
116
117
|
process.env['HOME'] = home;
|
|
117
118
|
process.env['CRTR_HOME'] = canvasHome;
|
|
119
|
+
initializeFreshScopedStore({ kind: 'user', root: join(home, '.crouter') });
|
|
120
|
+
migrate(openDb());
|
|
118
121
|
// A project store answers only under the namespace its root INDEX.md
|
|
119
122
|
// declares; without that declaration the store does not mount at all.
|
|
120
123
|
const store = (slug, namespace) => {
|
|
@@ -3,8 +3,9 @@ import assert from 'node:assert/strict';
|
|
|
3
3
|
import { mkdtempSync, rmSync, existsSync } from 'node:fs';
|
|
4
4
|
import { tmpdir } from 'node:os';
|
|
5
5
|
import { join } from 'node:path';
|
|
6
|
-
import { createNode, getRow, subscribe,
|
|
7
|
-
import { closeDb, openDb } from '../canvas/db.js';
|
|
6
|
+
import { createNode, getRow, subscribe, recordSpawn, subscribersOf, subscriptionsOf, pruneNodes, pruneToLimit, transitionStatusIntent, } from '../canvas/canvas.js';
|
|
7
|
+
import { closeDb, migrate, openDb } from '../canvas/db.js';
|
|
8
|
+
import { beginExecution, recordExecutionPid } from '../canvas/executions.js';
|
|
8
9
|
import { nodeDir } from '../canvas/paths.js';
|
|
9
10
|
let home;
|
|
10
11
|
const DAY = 86_400_000;
|
|
@@ -33,6 +34,10 @@ function totalEdges() {
|
|
|
33
34
|
function markCollectibleTerminal(nodeId) {
|
|
34
35
|
transitionStatusIntent(nodeId, { terminal_reason: 'closed' });
|
|
35
36
|
}
|
|
37
|
+
function recordExecution(nodeId, pid) {
|
|
38
|
+
const executionId = beginExecution(nodeId, { daemonEpoch: 'test' });
|
|
39
|
+
recordExecutionPid(executionId, nodeId, pid);
|
|
40
|
+
}
|
|
36
41
|
/** The standard fixture: three prunable terminal nodes (old), three survivors
|
|
37
42
|
* (two old-but-live, one recent-but-dead), and edges that touch a pruned node
|
|
38
43
|
* so cascade is observable. */
|
|
@@ -55,6 +60,7 @@ before(() => {
|
|
|
55
60
|
beforeEach(() => {
|
|
56
61
|
closeDb();
|
|
57
62
|
rmSync(home, { recursive: true, force: true });
|
|
63
|
+
migrate(openDb());
|
|
58
64
|
});
|
|
59
65
|
after(() => {
|
|
60
66
|
closeDb();
|
|
@@ -146,7 +152,7 @@ test('count pruning keeps all live nodes even when liveCount exceeds the cap', (
|
|
|
146
152
|
// fall beyond rank 5 and are pruned.
|
|
147
153
|
for (let i = 0; i < 5; i++) {
|
|
148
154
|
createNode(node(`live-${i}`, { status: 'active', created: at(i) }));
|
|
149
|
-
|
|
155
|
+
recordExecution(`live-${i}`, process.pid); // process.pid is alive → isPidAlive true
|
|
150
156
|
}
|
|
151
157
|
createNode(node('old-a', { status: 'dead', created: at(100) }));
|
|
152
158
|
createNode(node('old-b', { status: 'done', created: at(101) }));
|
|
@@ -164,7 +170,7 @@ test('count pruning deletes the oldest terminal nodes beyond max(cap, liveCount)
|
|
|
164
170
|
// Ranked by recency DESC: live-0, term-0, term-1 (top 3, kept), then
|
|
165
171
|
// term-2, term-3, term-4 (rank >= 3, pruned).
|
|
166
172
|
createNode(node('live-0', { status: 'idle', created: at(0) }));
|
|
167
|
-
|
|
173
|
+
recordExecution('live-0', process.pid);
|
|
168
174
|
for (let i = 0; i < 5; i++) {
|
|
169
175
|
const id = `term-${i}`;
|
|
170
176
|
createNode(node(id, { status: 'dead', created: at(10 + i) }));
|
|
@@ -185,7 +191,7 @@ test('count pruning deletes the oldest terminal nodes beyond max(cap, liveCount)
|
|
|
185
191
|
});
|
|
186
192
|
test('count pruning dry-run reports candidates without deleting rows or dirs', () => {
|
|
187
193
|
createNode(node('live-0', { status: 'idle', created: at(0) }));
|
|
188
|
-
|
|
194
|
+
recordExecution('live-0', process.pid);
|
|
189
195
|
for (let i = 0; i < 5; i++) {
|
|
190
196
|
const id = `term-${i}`;
|
|
191
197
|
createNode(node(id, { status: 'dead', created: at(10 + i) }));
|
|
@@ -4,21 +4,28 @@ import { mkdtempSync, rmSync, mkdirSync } from 'node:fs';
|
|
|
4
4
|
import { tmpdir } from 'node:os';
|
|
5
5
|
import { join } from 'node:path';
|
|
6
6
|
import { createNode, getNode, setStatus } from '../canvas/canvas.js';
|
|
7
|
-
import { closeDb } from '../canvas/db.js';
|
|
7
|
+
import { closeDb, openDb, migrate } from '../canvas/db.js';
|
|
8
8
|
import { InputError } from '../io.js';
|
|
9
9
|
import { messageRoutes } from '../../daemon/api/handlers/messages.js';
|
|
10
10
|
import { pushFinal, FinalizationError } from '../feed/feed.js';
|
|
11
11
|
import { assertNotFinalized, assertFinalizedForReopen, commitReopen } from '../runtime/reopen.js';
|
|
12
12
|
import { reviveNode } from '../runtime/revive.js';
|
|
13
13
|
import { headlessBrokerHost } from '../runtime/host.js';
|
|
14
|
-
|
|
14
|
+
function nodeMailCount(nodeId) {
|
|
15
|
+
return Number(openDb().prepare(`SELECT COUNT(*) AS count FROM deliveries
|
|
16
|
+
WHERE destination_kind = 'node_inbox' AND destination_id = ?`).get(nodeId).count);
|
|
17
|
+
}
|
|
15
18
|
import { writeGoal } from '../runtime/kickoff.js';
|
|
16
19
|
import { situationalContextPath } from '../canvas/paths.js';
|
|
17
20
|
let home;
|
|
18
21
|
const prevNodeId = process.env['CRTR_NODE_ID'];
|
|
19
22
|
function node(id) { return { node_id: id, name: id, created: new Date().toISOString(), cwd: '/tmp/work', kind: 'general', mode: 'base', lifecycle: 'terminal', status: 'active' }; }
|
|
20
23
|
before(() => { home = mkdtempSync(join(tmpdir(), 'crtr-pushfinal-')); process.env['CRTR_HOME'] = home; });
|
|
21
|
-
beforeEach(() => {
|
|
24
|
+
beforeEach(() => {
|
|
25
|
+
closeDb();
|
|
26
|
+
rmSync(home, { recursive: true, force: true });
|
|
27
|
+
migrate(openDb());
|
|
28
|
+
});
|
|
22
29
|
after(() => { closeDb(); rmSync(home, { recursive: true, force: true }); delete process.env['CRTR_HOME']; if (prevNodeId === undefined)
|
|
23
30
|
delete process.env['CRTR_NODE_ID'];
|
|
24
31
|
else
|
|
@@ -66,13 +73,13 @@ test('a finalized node re-tasked via node message send without --reopen is rejec
|
|
|
66
73
|
const firstFinal = getNode(id)?.final_report;
|
|
67
74
|
assert.ok(firstFinal);
|
|
68
75
|
// A message to the now-finalized node, no --reopen: rejected before the
|
|
69
|
-
// handler ever reaches
|
|
76
|
+
// handler ever creates a delivery or reaches reviveNode. Prove BOTH: the latch is
|
|
70
77
|
// untouched, AND (per #340's Minor finding) no side effect landed first —
|
|
71
78
|
// spy on the exact revive seam reviveNode calls (headlessBrokerHost.launch,
|
|
72
79
|
// the same seam revive.test.ts already uses to instrument reviveNode without
|
|
73
80
|
// a real engine) and assert it was never invoked, plus the inbox is
|
|
74
81
|
// unchanged.
|
|
75
|
-
const inboxBefore =
|
|
82
|
+
const inboxBefore = nodeMailCount(id);
|
|
76
83
|
const originalLaunch = headlessBrokerHost.launch;
|
|
77
84
|
let launchCalls = 0;
|
|
78
85
|
headlessBrokerHost.launch = ((...args) => { launchCalls++; return originalLaunch(...args); });
|
|
@@ -84,7 +91,7 @@ test('a finalized node re-tasked via node message send without --reopen is rejec
|
|
|
84
91
|
}
|
|
85
92
|
assert.equal(launchCalls, 0, 'a rejected retask must never attempt a revive');
|
|
86
93
|
assert.equal(getNode(id)?.final_report, firstFinal, 'a rejected retask must not touch the latch');
|
|
87
|
-
assert.equal(
|
|
94
|
+
assert.equal(nodeMailCount(id), inboxBefore, 'a rejected retask must not create a delivery');
|
|
88
95
|
// The successful path, driven through the ACTUAL daemon message handler (the
|
|
89
96
|
// real seam --reopen now lives behind, not a direct call into the gate
|
|
90
97
|
// internals) — stub the revive seam so no real engine process is spawned,
|
|
@@ -105,7 +112,7 @@ test('a finalized node re-tasked via node message send without --reopen is rejec
|
|
|
105
112
|
headlessBrokerHost.launch = originalLaunch;
|
|
106
113
|
}
|
|
107
114
|
assert.equal(getNode(id)?.final_report, null, '--reopen cleared the latch through the real handler seam');
|
|
108
|
-
assert.equal(
|
|
115
|
+
assert.equal(nodeMailCount(id), inboxBefore + 1, 'the re-task message created one durable delivery');
|
|
109
116
|
// The re-tasked node can now finish its new mandate and re-latch cleanly.
|
|
110
117
|
process.env['CRTR_NODE_ID'] = id;
|
|
111
118
|
await pushFinal(id, 'round 2 verdict');
|
|
@@ -15,13 +15,19 @@ import { CrtrClient } from '../../api/client.js';
|
|
|
15
15
|
import { createApiServer } from '../../daemon/api/server.js';
|
|
16
16
|
import registerCanvasStophook from '../../pi-extensions/canvas-stophook.js';
|
|
17
17
|
import { createNode, getNode, subscribe } from '../canvas/canvas.js';
|
|
18
|
-
import {
|
|
18
|
+
import { beginExecution, recordExecutionPid } from '../canvas/executions.js';
|
|
19
|
+
import { closeDb, migrate, openDb } from '../canvas/db.js';
|
|
20
|
+
import { resetScopeCache } from '../scope.js';
|
|
21
|
+
import { closeScopedStores } from '../scoped-state/db.js';
|
|
22
|
+
import { initializeFreshScopedStore } from '../scoped-state/migrate.js';
|
|
19
23
|
import { apiSocketPath } from '../canvas/paths.js';
|
|
20
24
|
import { brokerCapReached, resetFleetForTests } from '../runtime/fleet.js';
|
|
21
25
|
import { buildPiArgv } from '../runtime/launch.js';
|
|
22
26
|
import { relaunchRoot } from '../runtime/reset.js';
|
|
23
27
|
import { bindTestFleet } from './helpers/fleet.js';
|
|
24
28
|
let home;
|
|
29
|
+
let tf;
|
|
30
|
+
const previousHome = process.env['HOME'];
|
|
25
31
|
function node(id, over = {}) {
|
|
26
32
|
return {
|
|
27
33
|
node_id: id,
|
|
@@ -67,16 +73,30 @@ function makeDeps(pid) {
|
|
|
67
73
|
}
|
|
68
74
|
before(() => {
|
|
69
75
|
home = mkdtempSync(join(tmpdir(), 'crtr-relaunch-'));
|
|
70
|
-
process.env['
|
|
76
|
+
process.env['HOME'] = home;
|
|
77
|
+
process.env['CRTR_HOME'] = join(home, 'canvas');
|
|
71
78
|
});
|
|
72
79
|
beforeEach(() => {
|
|
73
80
|
closeDb();
|
|
81
|
+
closeScopedStores();
|
|
74
82
|
rmSync(home, { recursive: true, force: true });
|
|
83
|
+
resetScopeCache();
|
|
84
|
+
initializeFreshScopedStore({ kind: 'user', root: join(home, '.crouter') });
|
|
85
|
+
migrate(openDb());
|
|
86
|
+
tf = bindTestFleet();
|
|
75
87
|
});
|
|
76
88
|
after(() => {
|
|
77
89
|
closeDb();
|
|
90
|
+
closeScopedStores();
|
|
91
|
+
tf.fleet.dispose();
|
|
92
|
+
resetFleetForTests();
|
|
78
93
|
rmSync(home, { recursive: true, force: true });
|
|
79
94
|
delete process.env['CRTR_HOME'];
|
|
95
|
+
if (previousHome === undefined)
|
|
96
|
+
delete process.env['HOME'];
|
|
97
|
+
else
|
|
98
|
+
process.env['HOME'] = previousHome;
|
|
99
|
+
resetScopeCache();
|
|
80
100
|
});
|
|
81
101
|
test('relaunchRoot parks the old root done and mints a fresh active root, reaping descendants', async () => {
|
|
82
102
|
// root → child → grandchild (a parent that subscribes to its workers).
|
|
@@ -169,6 +189,10 @@ test('root /new capacity refusal reaches the attached human through broker UI no
|
|
|
169
189
|
process.env['CRTR_NODE_ID'] = 'root';
|
|
170
190
|
createNode(node('root', { parent: null, lifecycle: 'resident' }));
|
|
171
191
|
const tf = bindTestFleet();
|
|
192
|
+
const executionId = beginExecution('root', { daemonEpoch: tf.fleet.epoch() });
|
|
193
|
+
assert.equal(recordExecutionPid(executionId, 'root', process.pid), 'recorded');
|
|
194
|
+
const previousExecutionId = process.env['CRTR_EXECUTION_ID'];
|
|
195
|
+
process.env['CRTR_EXECUTION_ID'] = executionId;
|
|
172
196
|
const never = new Promise(() => { });
|
|
173
197
|
tf.fleet.register('filler-a', { pid: 700_001, exited: never });
|
|
174
198
|
tf.fleet.register('filler-b', { pid: 700_002, exited: never });
|
|
@@ -207,6 +231,10 @@ test('root /new capacity refusal reaches the attached human through broker UI no
|
|
|
207
231
|
resetFleetForTests();
|
|
208
232
|
delete process.env['CRTR_MAX_LIVE_BROKERS'];
|
|
209
233
|
delete process.env['CRTR_NODE_ID'];
|
|
234
|
+
if (previousExecutionId === undefined)
|
|
235
|
+
delete process.env['CRTR_EXECUTION_ID'];
|
|
236
|
+
else
|
|
237
|
+
process.env['CRTR_EXECUTION_ID'] = previousExecutionId;
|
|
210
238
|
}
|
|
211
239
|
});
|
|
212
240
|
test('relaunchRoot is a no-op for a non-root child and an already-parked root', async () => {
|