@north-light/crouter 0.3.312 → 0.3.313
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 +746 -735
- 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/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/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 +7 -0
- package/dist/core/scoped-state/db.js +92 -0
- package/dist/core/scoped-state/migrate.d.ts +11 -0
- package/dist/core/scoped-state/migrate.js +198 -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.d.ts +0 -1
- 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
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { before, after, test } from "node:test";
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
3
|
import { spawn } from "node:child_process";
|
|
4
|
-
import { existsSync,
|
|
4
|
+
import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
5
5
|
import { LockedJsonFile } from "../../../../../core/locked-file.ts";
|
|
6
|
+
import { initializeFreshScopedStore } from "../../../../../core/scoped-state/migrate.ts";
|
|
7
|
+
import { writeRawConfig } from "../../../../../core/config.ts";
|
|
6
8
|
import { expandModelCandidates } from "../../../../../core/model-routes.ts";
|
|
7
9
|
import type { SubscriptionCredential } from "../../../lib/subscription-state.ts";
|
|
8
|
-
import {
|
|
10
|
+
import { join } from "node:path";
|
|
9
11
|
import { tmpdir } from "node:os";
|
|
10
12
|
|
|
11
13
|
// Child processes reach crouter's locked-file primitive by absolute URL: they run under
|
|
@@ -24,44 +26,32 @@ const previousModelIntent = process.env.CRTR_MODEL_INTENT;
|
|
|
24
26
|
const previousNodeCwd = process.env.CRTR_NODE_CWD;
|
|
25
27
|
|
|
26
28
|
function writeLadderConfig() {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
anthropic: {
|
|
35
|
-
ultra: "anthropic/claude-fable-5:high",
|
|
36
|
-
strong: "anthropic/claude-opus-4-8:high",
|
|
37
|
-
medium: "anthropic/claude-sonnet-4-6:high",
|
|
38
|
-
light: "anthropic/custom-light-x",
|
|
39
|
-
},
|
|
40
|
-
openai: {
|
|
41
|
-
ultra: "openai-codex/gpt-5.6-sol:max",
|
|
42
|
-
strong: "openai-codex/gpt-5.6-sol:high",
|
|
43
|
-
medium: "openai-codex/gpt-5.6-terra:medium",
|
|
44
|
-
light: "openai-codex/gpt-5.6-luna:low",
|
|
45
|
-
},
|
|
46
|
-
},
|
|
29
|
+
writeRawConfig("user", {
|
|
30
|
+
modelLadders: {
|
|
31
|
+
anthropic: {
|
|
32
|
+
ultra: "anthropic/claude-fable-5:high",
|
|
33
|
+
strong: "anthropic/claude-opus-4-8:high",
|
|
34
|
+
medium: "anthropic/claude-sonnet-4-6:high",
|
|
35
|
+
light: "anthropic/custom-light-x",
|
|
47
36
|
},
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
37
|
+
openai: {
|
|
38
|
+
ultra: "openai-codex/gpt-5.6-sol:max",
|
|
39
|
+
strong: "openai-codex/gpt-5.6-sol:high",
|
|
40
|
+
medium: "openai-codex/gpt-5.6-terra:medium",
|
|
41
|
+
light: "openai-codex/gpt-5.6-luna:low",
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
});
|
|
53
45
|
}
|
|
54
46
|
|
|
55
47
|
function writeSameModelRouteConfig() {
|
|
56
|
-
|
|
57
|
-
mkdirSync(dirname(configPath), { recursive: true });
|
|
58
|
-
writeFileSync(configPath, `${JSON.stringify({
|
|
48
|
+
writeRawConfig("user", {
|
|
59
49
|
modelRoutes: {
|
|
60
|
-
primary: { family: "openai", credentialSource: "primary", providerId: "openai-codex", models: { strong: "openai-codex/gpt-5.6-sol:high" } },
|
|
61
|
-
alternate: { family: "openai", credentialSource: "alternate", providerId: "anthropic", models: { strong: "anthropic/gpt-5.6-sol:high" } },
|
|
50
|
+
primary: { family: "openai", credentialSource: "primary", providerId: "openai-codex", models: { ultra: "openai-codex/gpt-5.6-sol:high", strong: "openai-codex/gpt-5.6-sol:high", medium: "openai-codex/gpt-5.6-sol:high", light: "openai-codex/gpt-5.6-sol:high" } },
|
|
51
|
+
alternate: { family: "openai", credentialSource: "alternate", providerId: "anthropic", models: { ultra: "anthropic/gpt-5.6-sol:high", strong: "anthropic/gpt-5.6-sol:high", medium: "anthropic/gpt-5.6-sol:high", light: "anthropic/gpt-5.6-sol:high" } },
|
|
62
52
|
},
|
|
63
53
|
modelRouting: { credentialSourceOrder: ["primary", "alternate"], familyOrder: ["openai"] },
|
|
64
|
-
}
|
|
54
|
+
});
|
|
65
55
|
}
|
|
66
56
|
|
|
67
57
|
function credential(label: string, overrides: Partial<SubscriptionCredential> = {}): SubscriptionCredential {
|
|
@@ -121,6 +111,8 @@ before(async () => {
|
|
|
121
111
|
process.env.HOME = home;
|
|
122
112
|
process.env.PI_CODING_AGENT_DIR = join(home, ".pi", "agent");
|
|
123
113
|
process.env.CRTR_NODE_CWD = nodeCwd;
|
|
114
|
+
initializeFreshScopedStore({ kind: "user", root: join(home, ".crouter") });
|
|
115
|
+
initializeFreshScopedStore({ kind: "provider", root: process.env.PI_CODING_AGENT_DIR });
|
|
124
116
|
helpers = await import("../../../lib/subscription-state.ts");
|
|
125
117
|
providerManagement = await import("../../../../../core/provider-management.ts");
|
|
126
118
|
rotationModule = await import("../../provider-rotation.ts");
|
|
@@ -363,7 +355,7 @@ test("the synthesized ladder registry preserves family preference before configu
|
|
|
363
355
|
family: "anthropic",
|
|
364
356
|
strength: "strong",
|
|
365
357
|
spec: "anthropic/claude-opus-4-8:high",
|
|
366
|
-
},
|
|
358
|
+
}, nodeCwd, null);
|
|
367
359
|
|
|
368
360
|
assert.deepEqual(candidates.map((candidate) => `${candidate.family}/${candidate.strength}`), [
|
|
369
361
|
"anthropic/strong", "openai/strong", "anthropic/medium", "openai/medium",
|
|
@@ -473,7 +465,7 @@ test("a stale success cannot reopen a slot cooled down by a newer 429", async ()
|
|
|
473
465
|
test("pool mutations take the cross-process pool-file lock", async () => {
|
|
474
466
|
await resetRotationState();
|
|
475
467
|
await helpers.writeSubscriptionPool("openai-codex", [credential("work")]);
|
|
476
|
-
const poolFile = join(home, ".pi", "agent", "openai-codex-
|
|
468
|
+
const poolFile = join(home, ".pi", "agent", "openai-codex-credentials.json");
|
|
477
469
|
|
|
478
470
|
const lockHolder = spawn(
|
|
479
471
|
process.execPath,
|
|
@@ -531,14 +523,8 @@ await backend.withLockAsync(async () => {
|
|
|
531
523
|
readyTimer = setTimeout(() => reject(new Error("lock-holder did not signal readiness within 60s")), 60_000);
|
|
532
524
|
}),
|
|
533
525
|
]);
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
// single asynchronous lock path waits without blocking the event loop, then commits once
|
|
537
|
-
// the holder releases.
|
|
538
|
-
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
539
|
-
lockHolder.stdin!.write("release\n");
|
|
540
|
-
lockHolder.stdin!.end();
|
|
541
|
-
const pool = await mutation;
|
|
526
|
+
// Health is SQL-only, so the credential-file lock cannot delay it.
|
|
527
|
+
const pool = await within(helpers.markSubscriptionAttempt("openai-codex", "work", 123), 1_000, "health write waited on the credential-file lock");
|
|
542
528
|
assert.equal(pool[0].lastAttemptAt, 123);
|
|
543
529
|
} finally {
|
|
544
530
|
if (readyTimer) clearTimeout(readyTimer);
|
|
@@ -806,6 +792,7 @@ function makeRotationCtx(modelIntent?: string) {
|
|
|
806
792
|
const ctx = {
|
|
807
793
|
model: { provider: "openai-codex", id: "gpt-5.6-sol", api: "openai-codex-responses" },
|
|
808
794
|
thinkingLevel: "high",
|
|
795
|
+
cwd: nodeCwd,
|
|
809
796
|
ui: { setStatus() {} },
|
|
810
797
|
modelRegistry: {
|
|
811
798
|
find(provider: string, id: string) {
|
|
@@ -1376,7 +1363,7 @@ test("self-terminates after consecutive transport-only exhausted passes; an HTTP
|
|
|
1376
1363
|
const terminateCalls: string[] = [];
|
|
1377
1364
|
let resolveTerminated: (tried: string) => void;
|
|
1378
1365
|
const terminated = new Promise<string>((resolve) => { resolveTerminated = resolve; });
|
|
1379
|
-
rotationModule.__setTerminatePoisonedProcessForTest((tried) => {
|
|
1366
|
+
rotationModule.__setTerminatePoisonedProcessForTest(async (tried) => {
|
|
1380
1367
|
terminateCalls.push(tried);
|
|
1381
1368
|
resolveTerminated(tried);
|
|
1382
1369
|
return true;
|
|
@@ -1837,13 +1824,14 @@ test("emits an actionable 'not authenticated' error without switching models whe
|
|
|
1837
1824
|
assert.match(emitted[0].error.errorMessage, /All provider routes exhausted \(tried openai\)/);
|
|
1838
1825
|
});
|
|
1839
1826
|
|
|
1840
|
-
// The builtin ladder is available
|
|
1841
|
-
//
|
|
1827
|
+
// The builtin ladder is available with no user configuration, so a config-less user can still
|
|
1828
|
+
// resolve cross-provider fallbacks.
|
|
1842
1829
|
test("degrades gracefully via the builtin ladder when a config-less user has no cross-provider credentials", async () => {
|
|
1843
1830
|
await resetRotationState();
|
|
1844
|
-
|
|
1831
|
+
writeRawConfig("user", {});
|
|
1845
1832
|
|
|
1846
1833
|
const ctx = {
|
|
1834
|
+
cwd: nodeCwd,
|
|
1847
1835
|
model: { provider: "anthropic", id: "claude-opus-4-8", api: "anthropic-messages" },
|
|
1848
1836
|
ui: { setStatus() {} },
|
|
1849
1837
|
modelRegistry: {
|
|
@@ -21,7 +21,7 @@ declare function defaultSleep(ms: number): Promise<void>;
|
|
|
21
21
|
/** Test-only seam: override the sleep implementation used for in-place/wait-out retries. Pass undefined to restore the default. */
|
|
22
22
|
export declare function __setSleepForTest(fn: typeof defaultSleep | undefined): void;
|
|
23
23
|
export declare const POISONED_TRANSPORT_PASS_LIMIT = 2;
|
|
24
|
-
declare function defaultTerminatePoisonedProcess(tried: string): boolean
|
|
24
|
+
declare function defaultTerminatePoisonedProcess(tried: string): Promise<boolean>;
|
|
25
25
|
/** Test-only seam: override poisoned-process self-termination. Pass undefined to restore the default. */
|
|
26
26
|
export declare function __setTerminatePoisonedProcessForTest(fn: typeof defaultTerminatePoisonedProcess | undefined): void;
|
|
27
27
|
/** Test-only seam for the bounded, non-fatal subscription bookkeeping path. */
|
|
@@ -6,7 +6,7 @@ import { readMergedLaunchConfig } from '../../../core/config.js';
|
|
|
6
6
|
import { expandModelCandidates, modelRequestFromConfig, probeRouteAvailability } from '../../../core/model-routes.js';
|
|
7
7
|
import { envModelExact, envNodeId } from '../../../shared/env.js';
|
|
8
8
|
import { ManagedProviderCoolingError } from '../../../core/runtime/managed-provider-cooling.js';
|
|
9
|
-
import {
|
|
9
|
+
import { recordBrokerTurn } from '../../../core/runtime/broker/daemon-ops.js';
|
|
10
10
|
import { recognizeProviderError } from '../../../core/provider-error-recognition.js';
|
|
11
11
|
import { normalizeProviderFailure, providerFailureDiagnostic } from '../../../core/provider-failure.js';
|
|
12
12
|
// A response without Retry-After proves only that THIS attempt was throttled; it
|
|
@@ -110,7 +110,7 @@ export function __setSleepForTest(fn) {
|
|
|
110
110
|
// offline box parks the node until the network returns instead of spending its
|
|
111
111
|
// respawn budget (daemon/fleet.ts, `deferRespawnWhileOffline`).
|
|
112
112
|
export const POISONED_TRANSPORT_PASS_LIMIT = 2;
|
|
113
|
-
function defaultTerminatePoisonedProcess(tried) {
|
|
113
|
+
async function defaultTerminatePoisonedProcess(tried) {
|
|
114
114
|
// Only the broker process itself may self-terminate: runBroker stamps
|
|
115
115
|
// CRTR_BROKER_PID with its own pid at boot. Any other host (tests, tooling)
|
|
116
116
|
// keeps the ordinary terminal-error path.
|
|
@@ -118,9 +118,16 @@ function defaultTerminatePoisonedProcess(tried) {
|
|
|
118
118
|
return false;
|
|
119
119
|
const routes = tried.split(', ').filter((route) => route !== '');
|
|
120
120
|
const nodeId = envNodeId();
|
|
121
|
-
if (nodeId
|
|
122
|
-
|
|
121
|
+
if (nodeId === undefined || routes.length === 0) {
|
|
122
|
+
throw new Error('poisoned broker is missing CRTR_NODE_ID or attempted routes');
|
|
123
123
|
}
|
|
124
|
+
await recordBrokerTurn(nodeId, {
|
|
125
|
+
event: 'exit-diagnostic',
|
|
126
|
+
exit_diagnostic: {
|
|
127
|
+
schema: 'crtr.execution-exit-diagnostic/v1',
|
|
128
|
+
transport_poison: { consecutive_passes: POISONED_TRANSPORT_PASS_LIMIT, routes },
|
|
129
|
+
},
|
|
130
|
+
});
|
|
124
131
|
logRotation(`process transport poisoned: ${POISONED_TRANSPORT_PASS_LIMIT} consecutive route-queue passes failed with no HTTP response (tried ${tried}); exiting so the daemon respawns this broker fresh`);
|
|
125
132
|
process.kill(process.pid, "SIGTERM");
|
|
126
133
|
return true;
|
|
@@ -705,7 +712,7 @@ async function runManagedProvider(state, model, context, options, stream) {
|
|
|
705
712
|
const tried = [...attemptedRoutes].join(', ');
|
|
706
713
|
if (lastTransientFailure !== undefined) {
|
|
707
714
|
state.transportOnlyExhaustedPasses = sawHttpEvidence ? 0 : state.transportOnlyExhaustedPasses + 1;
|
|
708
|
-
if (state.transportOnlyExhaustedPasses >= POISONED_TRANSPORT_PASS_LIMIT && activeTerminatePoisonedProcess(tried)) {
|
|
715
|
+
if (state.transportOnlyExhaustedPasses >= POISONED_TRANSPORT_PASS_LIMIT && await activeTerminatePoisonedProcess(tried)) {
|
|
709
716
|
// The stream is deliberately left OPEN: the SIGTERM handler sees a live
|
|
710
717
|
// turn, so it either certifies a clean abort (→ the daemon respawns and
|
|
711
718
|
// resumes with a continuation prompt) or marks the turn dirty (→ the
|
|
@@ -42,7 +42,7 @@ import type { ProviderOptionsConfig } from '../../../types.js';
|
|
|
42
42
|
import { expandModelCandidates, modelRequestFromConfig, probeRouteAvailability } from '../../../core/model-routes.js';
|
|
43
43
|
import { envModelExact, envNodeId } from '../../../shared/env.js';
|
|
44
44
|
import { ManagedProviderCoolingError } from '../../../core/runtime/managed-provider-cooling.js';
|
|
45
|
-
import {
|
|
45
|
+
import { recordBrokerTurn } from '../../../core/runtime/broker/daemon-ops.js';
|
|
46
46
|
import { recognizeProviderError, type ProviderErrorSignal } from '../../../core/provider-error-recognition.js';
|
|
47
47
|
import { normalizeProviderFailure, providerFailureDiagnostic, type NormalizedProviderFailure } from '../../../core/provider-failure.js';
|
|
48
48
|
|
|
@@ -213,16 +213,23 @@ export function __setSleepForTest(fn: typeof defaultSleep | undefined): void {
|
|
|
213
213
|
// respawn budget (daemon/fleet.ts, `deferRespawnWhileOffline`).
|
|
214
214
|
export const POISONED_TRANSPORT_PASS_LIMIT = 2;
|
|
215
215
|
|
|
216
|
-
function defaultTerminatePoisonedProcess(tried: string): boolean {
|
|
216
|
+
async function defaultTerminatePoisonedProcess(tried: string): Promise<boolean> {
|
|
217
217
|
// Only the broker process itself may self-terminate: runBroker stamps
|
|
218
218
|
// CRTR_BROKER_PID with its own pid at boot. Any other host (tests, tooling)
|
|
219
219
|
// keeps the ordinary terminal-error path.
|
|
220
220
|
if (process.env["CRTR_BROKER_PID"] !== String(process.pid)) return false;
|
|
221
221
|
const routes = tried.split(', ').filter((route) => route !== '');
|
|
222
222
|
const nodeId = envNodeId();
|
|
223
|
-
if (nodeId
|
|
224
|
-
|
|
223
|
+
if (nodeId === undefined || routes.length === 0) {
|
|
224
|
+
throw new Error('poisoned broker is missing CRTR_NODE_ID or attempted routes');
|
|
225
225
|
}
|
|
226
|
+
await recordBrokerTurn(nodeId, {
|
|
227
|
+
event: 'exit-diagnostic',
|
|
228
|
+
exit_diagnostic: {
|
|
229
|
+
schema: 'crtr.execution-exit-diagnostic/v1',
|
|
230
|
+
transport_poison: { consecutive_passes: POISONED_TRANSPORT_PASS_LIMIT, routes },
|
|
231
|
+
},
|
|
232
|
+
});
|
|
226
233
|
logRotation(
|
|
227
234
|
`process transport poisoned: ${POISONED_TRANSPORT_PASS_LIMIT} consecutive route-queue passes failed with no HTTP response (tried ${tried}); exiting so the daemon respawns this broker fresh`,
|
|
228
235
|
);
|
|
@@ -892,7 +899,7 @@ async function runManagedProvider(
|
|
|
892
899
|
const tried = [...attemptedRoutes].join(', ');
|
|
893
900
|
if (lastTransientFailure !== undefined) {
|
|
894
901
|
state.transportOnlyExhaustedPasses = sawHttpEvidence ? 0 : state.transportOnlyExhaustedPasses + 1;
|
|
895
|
-
if (state.transportOnlyExhaustedPasses >= POISONED_TRANSPORT_PASS_LIMIT && activeTerminatePoisonedProcess(tried)) {
|
|
902
|
+
if (state.transportOnlyExhaustedPasses >= POISONED_TRANSPORT_PASS_LIMIT && await activeTerminatePoisonedProcess(tried)) {
|
|
896
903
|
// The stream is deliberately left OPEN: the SIGTERM handler sees a live
|
|
897
904
|
// turn, so it either certifies a clean abort (→ the daemon respawns and
|
|
898
905
|
// resumes with a continuation prompt) or marks the turn dirty (→ the
|
package/dist/cli.js
CHANGED
|
@@ -3,12 +3,13 @@ import './suppress-experimental-warnings.js';
|
|
|
3
3
|
import { openSync } from 'node:fs';
|
|
4
4
|
import { enableCompileCache } from 'node:module';
|
|
5
5
|
import { fileURLToPath } from 'node:url';
|
|
6
|
-
import { resolveRoot } from './build-root.js';
|
|
6
|
+
import { isDaemonControlInvocation, resolveDaemonControlRoot, resolveRoot } from './build-root.js';
|
|
7
7
|
import { maybeBootRoot } from './core/runtime/front-door.js';
|
|
8
8
|
import { maybeAutoUpdate } from './core/auto-update.js';
|
|
9
9
|
import { ensureProjectScope } from './core/bootstrap.js';
|
|
10
10
|
import { provisionExports, pruneLegacyExports } from './core/host-exports/export.js';
|
|
11
11
|
import { revalidateBundlePlugins } from './core/command-plugins/revalidate.js';
|
|
12
|
+
import { runCli } from './core/command.js';
|
|
12
13
|
import { dispatchWithStaleRecovery } from './core/manifest-recovery.js';
|
|
13
14
|
import { installStdoutErrorPolicy } from './core/stdout-errors.js';
|
|
14
15
|
import { handle } from './core/io.js';
|
|
@@ -47,6 +48,14 @@ async function main() {
|
|
|
47
48
|
// bootRoot exec'd pi inline and exited; unreachable.
|
|
48
49
|
}
|
|
49
50
|
mark('cli.front_door_passed');
|
|
51
|
+
// Daemon control must remain callable immediately after an upgrade: its
|
|
52
|
+
// selected successor performs the user/provider store conversion, so this
|
|
53
|
+
// dispatch cannot first read scoped settings, installed plugins, or hooks.
|
|
54
|
+
// The compact tree reuses the daemon definitions and the normal dispatcher.
|
|
55
|
+
if (isDaemonControlInvocation(process.argv)) {
|
|
56
|
+
await runCli(await resolveDaemonControlRoot(), process.argv);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
50
59
|
// Bring installed bundle plugins back in step with their endpoints before the
|
|
51
60
|
// tree is built, so a package this pass replaces is the one this invocation
|
|
52
61
|
// dispatches against. TTL-gated and non-fatal — see revalidate.ts.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface HumanDaemon {
|
|
2
|
+
/** The isolated canvas home, and the value of both `CRTR_HOME` and `HOME`. */
|
|
3
|
+
home: string;
|
|
4
|
+
/** A scratch directory for the page sources a fixture authors. */
|
|
5
|
+
sources: string;
|
|
6
|
+
dispose(): Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
/** Bind the human routes on an isolated home's socket. Every environment
|
|
9
|
+
* change is undone by `dispose`, so a fixture can run beside the developer's
|
|
10
|
+
* own canvas without touching it. */
|
|
11
|
+
export declare function startHumanDaemon(prefix: string): Promise<HumanDaemon>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// A crtrd the human client surfaces can actually talk to.
|
|
2
|
+
//
|
|
3
|
+
// The inbox and the attach viewer now read every page and request over the
|
|
4
|
+
// daemon's human routes, so a fixture that exercises them needs a daemon on the
|
|
5
|
+
// socket `cliClient()` resolves. It gets the REAL route tables rather than a
|
|
6
|
+
// re-implementation: the projections under test are the daemon's, and a second
|
|
7
|
+
// copy of them in a fixture would pass while the shipped ones drifted.
|
|
8
|
+
//
|
|
9
|
+
// The routes read an on-disk canvas, so the helper also stands up an isolated
|
|
10
|
+
// home with the canvas schema and the scope store crtrd installs at startup —
|
|
11
|
+
// opening a page resolves its components from scope settings rooted at HOME.
|
|
12
|
+
import { createServer } from 'node:http';
|
|
13
|
+
import { mkdtempSync, realpathSync, rmSync } from 'node:fs';
|
|
14
|
+
import { tmpdir } from 'node:os';
|
|
15
|
+
import { join } from 'node:path';
|
|
16
|
+
import { migrate, openDb } from '#core/canvas/db';
|
|
17
|
+
import { resetScopeCache } from '#core/scope';
|
|
18
|
+
import { initializeFreshScopedStore } from '#core/scoped-state/migrate';
|
|
19
|
+
import { Router } from '#daemon/api/router';
|
|
20
|
+
import { humanRequestRoutes } from '#daemon/api/handlers/human-requests';
|
|
21
|
+
import { inboxRoutes } from '#daemon/api/handlers/inbox';
|
|
22
|
+
/** Bind the human routes on an isolated home's socket. Every environment
|
|
23
|
+
* change is undone by `dispose`, so a fixture can run beside the developer's
|
|
24
|
+
* own canvas without touching it. */
|
|
25
|
+
export async function startHumanDaemon(prefix) {
|
|
26
|
+
// Canonical, because a request row stores its directory as given while every
|
|
27
|
+
// read path resolves one first: a home behind a symlink (every macOS tmpdir)
|
|
28
|
+
// would make the two disagree.
|
|
29
|
+
const home = realpathSync(mkdtempSync(join(tmpdir(), `${prefix}-`)));
|
|
30
|
+
const sources = mkdtempSync(join(tmpdir(), `${prefix}-src-`));
|
|
31
|
+
const previousHome = process.env['HOME'];
|
|
32
|
+
const previousCrtrHome = process.env['CRTR_HOME'];
|
|
33
|
+
process.env['HOME'] = home;
|
|
34
|
+
process.env['CRTR_HOME'] = home;
|
|
35
|
+
resetScopeCache();
|
|
36
|
+
initializeFreshScopedStore({ kind: 'user', root: join(home, '.crouter') });
|
|
37
|
+
migrate(openDb());
|
|
38
|
+
const router = new Router().registerAll(inboxRoutes).registerAll(humanRequestRoutes);
|
|
39
|
+
const server = createServer((req, res) => { void router.handle(req, res); });
|
|
40
|
+
await new Promise((resolve) => server.listen(join(home, 'crtrd.sock'), resolve));
|
|
41
|
+
return {
|
|
42
|
+
home,
|
|
43
|
+
sources,
|
|
44
|
+
async dispose() {
|
|
45
|
+
server.closeAllConnections();
|
|
46
|
+
await new Promise((resolve) => server.close(() => resolve()));
|
|
47
|
+
rmSync(home, { recursive: true, force: true });
|
|
48
|
+
rmSync(sources, { recursive: true, force: true });
|
|
49
|
+
if (previousCrtrHome === undefined)
|
|
50
|
+
delete process.env['CRTR_HOME'];
|
|
51
|
+
else
|
|
52
|
+
process.env['CRTR_HOME'] = previousCrtrHome;
|
|
53
|
+
if (previousHome === undefined)
|
|
54
|
+
delete process.env['HOME'];
|
|
55
|
+
else
|
|
56
|
+
process.env['HOME'] = previousHome;
|
|
57
|
+
resetScopeCache();
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
@@ -151,7 +151,7 @@ export async function buildCanvasPanelLines(nodeId, asks, palette, source, crons
|
|
|
151
151
|
const kind = faint(nameCell(n?.kind ?? '', KIND_W));
|
|
152
152
|
const tokens = muted(padStartVisible(tokensCell(id, remote), TOK_W));
|
|
153
153
|
const badges = `${cycleBadge(n)}${await childBadgeFor(n)}${liveBelowBadgeFor(n)}${askBadge(id, asks)}${activityCell(id, n, remote)}`;
|
|
154
|
-
const line = ` ${direction} ${nodeGlyph(n
|
|
154
|
+
const line = ` ${direction} ${nodeGlyph(n)} ${name} ${kind} ${tokens}${badges}`;
|
|
155
155
|
return truncate(line);
|
|
156
156
|
};
|
|
157
157
|
const reportIds = [...(mgr !== undefined ? [mgr] : []), ...live];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Container } from '@earendil-works/pi-tui';
|
|
2
|
-
import type
|
|
2
|
+
import { type InboxRow } from '../../inbox/dto-adapt.js';
|
|
3
3
|
import type { AttachSession } from '../session/context.js';
|
|
4
4
|
export type StripSession = Pick<AttachSession, 'nodeId' | 'remote' | 'canvasSource' | 'tui' | 'pal'>;
|
|
5
5
|
export interface InboxStripHooks {
|
|
@@ -8,7 +8,7 @@ export interface InboxStripHooks {
|
|
|
8
8
|
/** Drop the below-editor roster's highlight — the two lists are mutually exclusive. */
|
|
9
9
|
exitRoster: () => void;
|
|
10
10
|
/** Open this ticket — the inline ticket panel, or its fallbacks. */
|
|
11
|
-
openTicket: (ticket:
|
|
11
|
+
openTicket: (ticket: InboxRow) => void;
|
|
12
12
|
/** True while the ticket panel is open — it IS the expanded notification,
|
|
13
13
|
* so the strip's own rows hide rather than duplicate the flag. */
|
|
14
14
|
suppressed: () => boolean;
|
|
@@ -26,6 +26,6 @@ export interface InboxStrip {
|
|
|
26
26
|
/** True while the strip holds the highlight. */
|
|
27
27
|
active(): boolean;
|
|
28
28
|
/** The cached pending tickets, for the inbox surface's scan merge. */
|
|
29
|
-
pendingTickets():
|
|
29
|
+
pendingTickets(): InboxRow[];
|
|
30
30
|
}
|
|
31
31
|
export declare function createInboxStrip(s: StripSession, hooks: InboxStripHooks): InboxStrip;
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
// child ticket is present in the surface it seats.
|
|
14
14
|
import { Container, Text, decodeKittyPrintable, matchesKey } from '@earendil-works/pi-tui';
|
|
15
15
|
import { DynamicBorder } from '@earendil-works/pi-coding-agent';
|
|
16
|
-
import {
|
|
16
|
+
import { byNewestFirst, inboxRowFromDTO } from '../../inbox/dto-adapt.js';
|
|
17
|
+
import { cliClient } from '../../../commands/api-client.js';
|
|
17
18
|
import { fillBar, fillWidth, navLabel, stripSgr, truncate, REVERSE, YELLOW, RESET } from '../../../core/canvas/nav-render.js';
|
|
18
19
|
/** Ticket rows shown at once; the window follows the selection. */
|
|
19
20
|
const MAX_ROWS = 3;
|
|
@@ -91,14 +92,21 @@ export function createInboxStrip(s, hooks) {
|
|
|
91
92
|
// Same pending merge the inbox surface does — inbox-projected tickets plus
|
|
92
93
|
// reply-bearing no-inbox pages — but for every subtree node, then scoped to
|
|
93
94
|
// tickets whose origin is in the subtree.
|
|
94
|
-
// ONE page-history
|
|
95
|
-
//
|
|
96
|
-
//
|
|
97
|
-
//
|
|
95
|
+
// ONE home-wide page-history read for the whole subtree, filtered by origin
|
|
96
|
+
// here. Asking the daemon per node would repeat the same O(all tickets)
|
|
97
|
+
// projection N times for a result that is just the union over subtree
|
|
98
|
+
// origins.
|
|
99
|
+
const client = cliClient();
|
|
100
|
+
const [inbox, history] = await Promise.all([client.listHumanInbox(), client.getInboxHistory()]);
|
|
98
101
|
const merged = new Map();
|
|
99
|
-
for (const item of
|
|
100
|
-
|
|
101
|
-
|
|
102
|
+
for (const item of inbox.tickets) {
|
|
103
|
+
const row = inboxRowFromDTO(item);
|
|
104
|
+
merged.set(row.dir, row);
|
|
105
|
+
}
|
|
106
|
+
for (const item of history.tickets) {
|
|
107
|
+
const page = inboxRowFromDTO(item);
|
|
108
|
+
if (page.kind !== 'page')
|
|
109
|
+
continue;
|
|
102
110
|
if (page.source.nodeId === undefined || !nodes.has(page.source.nodeId))
|
|
103
111
|
continue;
|
|
104
112
|
if (page.state !== 'pending' || !page.awaitsResponse || page.inbox)
|
|
@@ -108,7 +116,7 @@ export function createInboxStrip(s, hooks) {
|
|
|
108
116
|
}
|
|
109
117
|
tickets = [...merged.values()]
|
|
110
118
|
.filter((t) => t.source.nodeId !== undefined && nodes.has(t.source.nodeId))
|
|
111
|
-
.sort(
|
|
119
|
+
.sort(byNewestFirst);
|
|
112
120
|
// The selected row may have vanished (answered, canceled) — drop back to
|
|
113
121
|
// the editor so no ghost highlight lingers.
|
|
114
122
|
if (selDir !== undefined && !tickets.some((t) => t.dir === selDir))
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Component } from '@earendil-works/pi-tui';
|
|
2
|
-
import type {
|
|
2
|
+
import type { InboxRow } from '../../inbox/dto-adapt.js';
|
|
3
3
|
import type { AttachSession } from '../session/context.js';
|
|
4
4
|
export type PanelSession = Pick<AttachSession, 'tui' | 'pal'>;
|
|
5
5
|
export interface TicketPanelHooks {
|
|
@@ -17,7 +17,7 @@ export interface TicketPanel {
|
|
|
17
17
|
/** Mounted once into the frame's `ticketPanel` slot; empty while closed. */
|
|
18
18
|
readonly component: Component;
|
|
19
19
|
/** Open a ticket's page inline; review/unreadable tickets fall back. */
|
|
20
|
-
open(ticket:
|
|
20
|
+
open(ticket: InboxRow): Promise<void>;
|
|
21
21
|
/** Panel key routing — consumes EVERY chunk while open. */
|
|
22
22
|
handleKey(data: string): boolean;
|
|
23
23
|
close(): void;
|