@north-light/crouter 0.3.233 → 0.3.234
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.js +16 -15
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/integration/provider-rotation.test.ts +1 -1
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/claude-plugin-commands.ts +14 -17
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/crtr-commands/index.ts +7 -11
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/frontmatter-rules/index.ts +8 -8
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/memory-slash-commands.ts +10 -11
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/pi-shell-runner.ts +2 -2
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.d.ts +3 -3
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +7 -7
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +8 -8
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/statusline.ts +6 -6
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/sysprompt-window.ts +3 -3
- package/dist/builtin-pi-packages/pi-crtr-extensions/lib/subscription-state.ts +1 -1
- package/dist/clients/attach/chrome/ticket-panel.js +15 -2
- package/dist/clients/attach/overlays/graph.js +0 -3
- package/dist/clients/attach/overlays/mcp.js +1 -2
- package/dist/clients/attach/render/chat-view.js +0 -12
- package/dist/clients/attach/render/crtr-output.js +0 -2
- package/dist/clients/attach/render/tool-calls.js +0 -6
- package/dist/clients/attach/slash/dispatch.js +8 -11
- package/dist/clients/attach/viewer.js +532 -534
- package/dist/clients/conversation/projection.js +0 -2
- package/dist/clients/inbox/controller.js +22 -3
- package/dist/clients/inbox/review/companion-pane.js +0 -4
- package/dist/clients/inbox/review-adapter.js +0 -7
- package/dist/clients/inbox/tui/slots.d.ts +3 -3
- package/dist/clients/inbox/tui/types.d.ts +2 -2
- package/dist/commands/api-client.js +0 -8
- package/dist/commands/attention.js +0 -8
- package/dist/commands/canvas-browse.js +2 -1
- package/dist/commands/canvas-config.js +0 -10
- package/dist/commands/canvas-history.js +2 -1
- package/dist/commands/cron.js +5 -18
- package/dist/commands/dashboard.js +0 -2
- package/dist/commands/human/feedback.js +2 -1
- package/dist/commands/human/prompts.js +2 -5
- package/dist/commands/human/queue.js +2 -7
- package/dist/commands/human/request.js +0 -14
- package/dist/commands/human/review.js +2 -1
- package/dist/commands/memory/__tests__/command-selector-and-mutation-guards.test.js +4 -4
- package/dist/commands/memory/find.js +2 -2
- package/dist/commands/memory/lint.js +2 -1
- package/dist/commands/memory/read.d.ts +2 -7
- package/dist/commands/memory/read.js +5 -16
- package/dist/commands/memory/shared.js +4 -7
- package/dist/commands/memory/write.js +4 -3
- package/dist/commands/node/bash.js +2 -1
- package/dist/commands/node/create.js +2 -1
- package/dist/commands/node/inspect.js +0 -6
- package/dist/commands/node/lifecycle.js +4 -13
- package/dist/commands/node/message.js +3 -2
- package/dist/commands/node/subscription.js +2 -1
- package/dist/commands/node/wait.js +4 -3
- package/dist/commands/node-context.js +2 -1
- package/dist/commands/node-lifecycle-revive.js +0 -2
- package/dist/commands/node-worktree.js +2 -1
- package/dist/commands/pkg/browse/actions.d.ts +1 -1
- package/dist/commands/pkg/browse/actions.js +4 -4
- package/dist/commands/pkg/browse/catalog.d.ts +1 -1
- package/dist/commands/pkg/browse/catalog.js +15 -15
- package/dist/commands/pkg/browse/command-view.d.ts +1 -1
- package/dist/commands/pkg/browse/command-view.js +3 -3
- package/dist/commands/pkg/browse/detail-panel.d.ts +1 -1
- package/dist/commands/pkg/browse/detail-panel.js +8 -8
- package/dist/commands/pkg/browse/doc-view.d.ts +1 -1
- package/dist/commands/pkg/browse/doc-view.js +3 -3
- package/dist/commands/pkg/browse/list-panel.d.ts +1 -1
- package/dist/commands/pkg/browse/list-panel.js +3 -3
- package/dist/commands/pkg/browse/model.d.ts +3 -3
- package/dist/commands/pkg/browse/shell.d.ts +2 -2
- package/dist/commands/pkg/browse/shell.js +13 -13
- package/dist/commands/pkg/plugin-manage.js +2 -1
- package/dist/commands/pkg/shared.js +0 -2
- package/dist/commands/profile/delete.js +2 -1
- package/dist/commands/push.js +2 -3
- package/dist/commands/revive.js +0 -2
- package/dist/commands/surface/node/placement.js +2 -1
- package/dist/commands/surface-edit.js +2 -1
- package/dist/commands/sys/config.js +0 -4
- package/dist/commands/sys/daemon.js +0 -10
- package/dist/commands/sys/doctor.js +3 -2
- package/dist/commands/sys/panels/broker-limits-panel.d.ts +2 -2
- package/dist/commands/sys/panels/broker-limits-panel.js +4 -4
- package/dist/commands/sys/panels/dependencies-panel.d.ts +2 -2
- package/dist/commands/sys/panels/dependencies-panel.js +2 -2
- package/dist/commands/sys/panels/keybindings-panel.d.ts +1 -1
- package/dist/commands/sys/panels/keybindings-panel.js +5 -5
- package/dist/commands/sys/panels/models-panel.d.ts +4 -4
- package/dist/commands/sys/panels/models-panel.js +11 -10
- package/dist/commands/sys/panels/plugins-panel.d.ts +2 -2
- package/dist/commands/sys/panels/plugins-panel.js +2 -2
- package/dist/commands/sys/panels/prefs-panel.d.ts +2 -2
- package/dist/commands/sys/panels/prefs-panel.js +4 -4
- package/dist/commands/sys/panels/profiles-panel.d.ts +1 -1
- package/dist/commands/sys/panels/profiles-panel.js +14 -13
- package/dist/commands/sys/panels/provider-panel.d.ts +3 -3
- package/dist/commands/sys/panels/provider-panel.js +8 -8
- package/dist/commands/sys/settings-shell.d.ts +3 -3
- package/dist/commands/sys/settings-shell.js +15 -15
- package/dist/commands/sys/setup-settings-runner.d.ts +3 -3
- package/dist/commands/sys/setup-settings-runner.js +5 -5
- package/dist/commands/sys/setup-wizard.d.ts +4 -4
- package/dist/commands/sys/setup-wizard.js +8 -8
- package/dist/commands/sys/support/prepare.js +4 -4
- package/dist/commands/sys/support/submit.js +2 -2
- package/dist/commands/sys/sync-deps.js +0 -2
- package/dist/commands/sys/sync-project-guidance.js +2 -1
- package/dist/commands/sys/sysprompt.js +2 -1
- package/dist/core/__tests__/boot.test.js +0 -8
- package/dist/core/__tests__/broker-extension-canvas-db-boundary.test.js +23 -1
- package/dist/core/__tests__/canvas-db-boundary.test.d.ts +1 -0
- package/dist/core/__tests__/canvas-db-boundary.test.js +46 -0
- package/dist/core/__tests__/canvas.test.js +1 -1
- package/dist/core/__tests__/child-death-wake.test.js +0 -2
- package/dist/core/__tests__/cron-armed-context-failure.test.d.ts +1 -0
- package/dist/core/__tests__/cron-armed-context-failure.test.js +145 -0
- package/dist/core/__tests__/daemon-wedge.test.js +0 -4
- package/dist/core/__tests__/dead-node-policy-table.test.js +0 -4
- package/dist/core/__tests__/fixtures/fake-engine.js +4 -14
- package/dist/core/__tests__/fixtures/fake-pi-host.js +5 -5
- package/dist/core/__tests__/focuses.test.js +0 -6
- package/dist/core/__tests__/fs-utils.test.d.ts +1 -0
- package/dist/core/__tests__/fs-utils.test.js +50 -0
- package/dist/core/__tests__/helpers/harness.js +1 -1
- package/dist/core/__tests__/inline-memory-refs.test.js +0 -2
- package/dist/core/__tests__/integration/broker-fork-seam.test.js +0 -2
- package/dist/core/__tests__/integration/broker-sdk-wiring.test.js +3 -16
- package/dist/core/__tests__/integration/command-plugins.test.js +0 -24
- package/dist/core/__tests__/integration/deferred-no-wake.test.js +0 -6
- package/dist/core/__tests__/integration/flagship-lifecycle.test.js +0 -26
- package/dist/core/__tests__/integration/live-mutation-verbs.test.js +0 -4
- package/dist/core/__tests__/integration/live-mutation.test.js +1 -5
- package/dist/core/__tests__/integration/refresh-stall-recycle.test.js +1 -5
- package/dist/core/__tests__/integration/revive.test.js +0 -12
- package/dist/core/__tests__/integration/subscription-delivery.test.js +0 -6
- package/dist/core/__tests__/integration/tmux-surface.test.js +24 -8
- package/dist/core/__tests__/integration/worktree-reap.test.js +0 -6
- package/dist/core/__tests__/lifecycle.test.js +0 -18
- package/dist/core/__tests__/memory-resolver-precedence.test.js +1 -1
- package/dist/core/__tests__/migration.test.js +2 -2
- package/dist/core/__tests__/on-read-dedup-resume.test.js +3 -3
- package/dist/core/__tests__/pid-identity-match.test.js +1 -1
- package/dist/core/__tests__/plugin-kinds.test.js +1 -1
- package/dist/core/__tests__/plugin-page-components.test.js +1 -1
- package/dist/core/__tests__/preview-registry-sync.test.js +42 -1
- package/dist/core/__tests__/respawn-throttle.test.js +0 -4
- package/dist/core/__tests__/revive-all.test.js +5 -5
- package/dist/core/__tests__/revive-parked-fresh.test.js +62 -11
- package/dist/core/__tests__/seam/broker-attach-multiclient.test.js +0 -8
- package/dist/core/__tests__/seam/broker-attach-stream.test.js +0 -8
- package/dist/core/__tests__/seam/broker-crash-teardown.test.js +0 -2
- package/dist/core/__tests__/tmux-driver-boundary.test.d.ts +1 -0
- package/dist/core/__tests__/tmux-driver-boundary.test.js +50 -0
- package/dist/core/activity-signal.d.ts +7 -0
- package/dist/core/activity-signal.js +38 -0
- package/dist/core/auto-update.js +2 -1
- package/dist/core/bootstrap.js +2 -1
- package/dist/core/canvas/__tests__/remote-canvas-source.test.js +1 -1
- package/dist/core/canvas/__tests__/remote-transport.test.js +1 -1
- package/dist/core/canvas/__tests__/render-remote.test.js +1 -1
- package/dist/core/canvas/browse/app.js +3 -2
- package/dist/core/canvas/browse/model.d.ts +1 -1
- package/dist/core/canvas/browse/model.js +0 -4
- package/dist/core/canvas/canvas.d.ts +22 -0
- package/dist/core/canvas/canvas.js +50 -18
- package/dist/core/canvas/crons.js +0 -6
- package/dist/core/canvas/db.d.ts +14 -20
- package/dist/core/canvas/db.js +30 -1332
- package/dist/core/canvas/focuses.js +0 -4
- package/dist/core/canvas/history.js +2 -1
- package/dist/core/canvas/migrations.d.ts +20 -0
- package/dist/core/canvas/migrations.js +1339 -0
- package/dist/core/canvas/nav-model.js +1 -11
- package/dist/core/canvas/nav-render.js +0 -8
- package/dist/core/canvas/remote-canvas-source.js +0 -2
- package/dist/core/canvas/render-source.js +31 -13
- package/dist/core/command-manifests/manifest.js +0 -10
- package/dist/core/command-manifests/schema.js +0 -4
- package/dist/core/command-plugins/transport/http-invoke.js +0 -14
- package/dist/core/command.js +0 -4
- package/dist/core/config.js +2 -1
- package/dist/core/feed/inbox.d.ts +10 -0
- package/dist/core/feed/inbox.js +18 -12
- package/dist/core/fs-utils.d.ts +9 -2
- package/dist/core/fs-utils.js +7 -15
- package/dist/core/help.js +0 -8
- package/dist/core/host-exports/export.d.ts +2 -2
- package/dist/core/host-exports/export.js +9 -12
- package/dist/core/human/answer.d.ts +2 -2
- package/dist/core/human/convention.d.ts +2 -5
- package/dist/core/human/convention.js +3 -13
- package/dist/core/human/page-schema.d.ts +2 -2
- package/dist/core/human/page-schema.js +2 -2
- package/dist/core/human/root.js +6 -23
- package/dist/core/human/scan.js +24 -7
- package/dist/core/human/tickets.d.ts +4 -1
- package/dist/core/human/tickets.js +20 -6
- package/dist/core/io.js +0 -12
- package/dist/core/memory/identity.js +0 -4
- package/dist/core/memory/inline-ref-inventory.js +3 -2
- package/dist/core/memory/lint.js +3 -6
- package/dist/core/memory-resolver.d.ts +5 -0
- package/dist/core/memory-resolver.js +14 -12
- package/dist/core/pagination.js +0 -2
- package/dist/core/preview-registry.d.ts +14 -0
- package/dist/core/preview-registry.js +2 -4
- package/dist/core/preview-result-path.js +2 -1
- package/dist/core/profiles/manifest.d.ts +37 -5
- package/dist/core/profiles/manifest.js +44 -24
- package/dist/core/profiles/select.js +0 -4
- package/dist/core/review/signal.js +4 -23
- package/dist/core/review/ticket-filter.d.ts +3 -3
- package/dist/core/review/ticket-filter.js +4 -9
- package/dist/core/runtime/__tests__/engine-route.test.js +1 -1
- package/dist/core/runtime/__tests__/spawn-env.test.js +0 -8
- package/dist/core/runtime/bearings-render.d.ts +56 -0
- package/dist/core/runtime/bearings-render.js +241 -0
- package/dist/core/runtime/bearings.d.ts +2 -17
- package/dist/core/runtime/bearings.js +12 -198
- package/dist/core/runtime/broker/auth-reload.d.ts +39 -0
- package/dist/core/runtime/broker/auth-reload.js +149 -0
- package/dist/core/runtime/broker/engine-drive.d.ts +26 -0
- package/dist/core/runtime/broker/engine-drive.js +257 -0
- package/dist/core/runtime/broker/engine-routing.d.ts +143 -0
- package/dist/core/runtime/broker/engine-routing.js +211 -0
- package/dist/core/runtime/broker/event-projection.js +3 -2
- package/dist/core/runtime/broker/fault-retry.js +5 -4
- package/dist/core/runtime/broker/frame-client.d.ts +38 -0
- package/dist/core/runtime/broker/frame-client.js +129 -0
- package/dist/core/runtime/broker/frame-dispatch.d.ts +12 -189
- package/dist/core/runtime/broker/frame-dispatch.js +89 -1476
- package/dist/core/runtime/broker/frame-engine-control.d.ts +20 -0
- package/dist/core/runtime/broker/frame-engine-control.js +231 -0
- package/dist/core/runtime/broker/frame-memory-refs.d.ts +19 -0
- package/dist/core/runtime/broker/frame-memory-refs.js +41 -0
- package/dist/core/runtime/broker/frame-model-query.d.ts +13 -0
- package/dist/core/runtime/broker/frame-model-query.js +69 -0
- package/dist/core/runtime/broker/frame-read.d.ts +19 -0
- package/dist/core/runtime/broker/frame-read.js +116 -0
- package/dist/core/runtime/broker/frame-replies.d.ts +24 -0
- package/dist/core/runtime/broker/frame-replies.js +64 -0
- package/dist/core/runtime/broker/frame-session.d.ts +34 -0
- package/dist/core/runtime/broker/frame-session.js +203 -0
- package/dist/core/runtime/broker/turn-ignition.d.ts +42 -0
- package/dist/core/runtime/broker/turn-ignition.js +74 -0
- package/dist/core/runtime/broker-extension-render.js +9 -85
- package/dist/core/runtime/broker-protocol.js +0 -4
- package/dist/core/runtime/broker-sdk.js +2 -1
- package/dist/core/runtime/broker.d.ts +1 -1
- package/dist/core/runtime/broker.js +5 -23
- package/dist/core/runtime/fault.js +3 -2
- package/dist/core/runtime/headless-pi.js +3 -2
- package/dist/core/runtime/host.js +2 -3
- package/dist/core/runtime/kickoff.js +0 -4
- package/dist/core/runtime/launch-target.js +2 -1
- package/dist/core/runtime/launch.js +3 -6
- package/dist/core/runtime/lifecycle.js +17 -26
- package/dist/core/runtime/managed-provider-cooling.d.ts +1 -1
- package/dist/core/runtime/naming.js +0 -2
- package/dist/core/runtime/nodes.js +2 -1
- package/dist/core/runtime/persona.js +0 -6
- package/dist/core/runtime/placement-tmux.js +2 -5
- package/dist/core/runtime/placement.js +4 -11
- package/dist/core/runtime/recap.js +4 -3
- package/dist/core/runtime/reopen.js +4 -7
- package/dist/core/runtime/reset.js +0 -4
- package/dist/core/runtime/resume-root.js +0 -2
- package/dist/core/runtime/revive.js +17 -13
- package/dist/core/runtime/session-list-cache.js +2 -2
- package/dist/core/runtime/shell-expansion.js +0 -2
- package/dist/core/runtime/spawn.js +0 -2
- package/dist/core/runtime/stream-watchdog.d.ts +0 -1
- package/dist/core/runtime/stream-watchdog.js +13 -18
- package/dist/core/runtime/tmux-bindings.js +0 -2
- package/dist/core/runtime/tmux-driver.d.ts +12 -0
- package/dist/core/runtime/tmux-driver.js +18 -13
- package/dist/core/runtime/warm-pool.js +0 -4
- package/dist/core/scope.js +4 -3
- package/dist/core/spawn.js +2 -3
- package/dist/core/subscription-state.js +10 -17
- package/dist/core/substrate/__tests__/surface-match-pre-command.test.js +3 -3
- package/dist/core/substrate/render.js +0 -12
- package/dist/core/substrate/schema.js +0 -12
- package/dist/core/substrate/surface-match.js +0 -2
- package/dist/core/termrender/display.js +2 -1
- package/dist/core/tui/page-host.d.ts +3 -3
- package/dist/core/tui/page-host.js +4 -4
- package/dist/core/tui/panel.js +3 -3
- package/dist/core/wake.js +0 -12
- package/dist/core/worktree.js +0 -2
- package/dist/daemon/__tests__/reconciler-signature.test.d.ts +1 -0
- package/dist/daemon/__tests__/reconciler-signature.test.js +36 -0
- package/dist/daemon/api/__tests__/seam/api-server.test.js +2 -16
- package/dist/daemon/api/__tests__/seam/b10-attach-modelauth.test.js +3 -11
- package/dist/daemon/api/__tests__/seam/leaf-api-parity.test.js +0 -6
- package/dist/daemon/api/handlers/attach.js +2 -1
- package/dist/daemon/api/handlers/broker-ops.js +3 -6
- package/dist/daemon/api/handlers/canvas.js +12 -18
- package/dist/daemon/api/handlers/feedback-comments.js +0 -8
- package/dist/daemon/api/handlers/health.js +3 -2
- package/dist/daemon/api/handlers/human-requests.js +0 -10
- package/dist/daemon/api/handlers/human.js +1 -5
- package/dist/daemon/api/handlers/inbox.js +0 -18
- package/dist/daemon/api/handlers/memory.js +1 -1
- package/dist/daemon/api/handlers/messages.js +4 -8
- package/dist/daemon/api/handlers/nodes.js +10 -21
- package/dist/daemon/api/handlers/reports.js +1 -1
- package/dist/daemon/api/handlers/reviews.js +1 -6
- package/dist/daemon/api/map.js +0 -6
- package/dist/daemon/api/router.js +0 -4
- package/dist/daemon/api/server.js +2 -5
- package/dist/daemon/boot-migrations.d.ts +14 -0
- package/dist/daemon/boot-migrations.js +31 -0
- package/dist/daemon/cron/armed-context.d.ts +21 -0
- package/dist/daemon/cron/armed-context.js +100 -0
- package/dist/daemon/cron/capture.d.ts +20 -0
- package/dist/daemon/cron/capture.js +45 -0
- package/dist/daemon/cron/disposition.d.ts +19 -0
- package/dist/daemon/cron/disposition.js +52 -0
- package/dist/daemon/cron/escalation.d.ts +12 -0
- package/dist/daemon/cron/escalation.js +124 -0
- package/dist/daemon/cron/held.d.ts +4 -0
- package/dist/daemon/cron/held.js +20 -0
- package/dist/daemon/cron/lease-recovery.d.ts +3 -0
- package/dist/daemon/cron/lease-recovery.js +119 -0
- package/dist/daemon/cron/live-runs.d.ts +11 -0
- package/dist/daemon/cron/live-runs.js +23 -0
- package/dist/daemon/cron/passes.d.ts +11 -0
- package/dist/daemon/cron/passes.js +78 -0
- package/dist/daemon/cron/settle.d.ts +28 -0
- package/dist/daemon/cron/settle.js +37 -0
- package/dist/daemon/cron/sinks.d.ts +2 -0
- package/dist/daemon/cron/sinks.js +100 -0
- package/dist/daemon/cron-run.d.ts +5 -41
- package/dist/daemon/cron-run.js +193 -882
- package/dist/daemon/crtrd-cli.js +2 -1
- package/dist/daemon/crtrd.js +22 -22
- package/dist/daemon/fleet.js +0 -4
- package/dist/daemon/human/deliver-action.js +2 -1
- package/dist/daemon/human/sweep.js +15 -4
- package/dist/daemon/manage.d.ts +2 -2
- package/dist/daemon/manage.js +4 -13
- package/dist/daemon/pidfile.js +2 -2
- package/dist/daemon/reconcilers/broker-supervision.js +26 -29
- package/dist/daemon/reconcilers/dormant-inbox.d.ts +1 -1
- package/dist/daemon/reconcilers/dormant-inbox.js +2 -1
- package/dist/daemon/reconcilers/live-obligation.js +2 -2
- package/dist/daemon/reconcilers/pending-review-submit.d.ts +1 -1
- package/dist/daemon/reconcilers/pending-review-submit.js +2 -1
- package/dist/daemon/reconcilers/storage-maintenance.d.ts +2 -1
- package/dist/daemon/reconcilers/storage-maintenance.js +2 -1
- package/dist/daemon/review/companion.js +2 -2
- package/dist/daemon/review/sweep.js +8 -3
- package/dist/migrations/001-surfaces-frontmatter.js +0 -6
- package/dist/migrations/corpus.js +2 -5
- package/dist/migrations/registry.js +15 -2
- package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +0 -4
- package/dist/pi-extensions/broker-local.js +2 -1
- package/dist/pi-extensions/canvas-bash-valve.js +3 -17
- package/dist/pi-extensions/canvas-context-intro.js +2 -7
- package/dist/pi-extensions/canvas-doc-substrate.js +2 -3
- package/dist/pi-extensions/canvas-goal-capture.js +2 -1
- package/dist/pi-extensions/canvas-inbox-watcher.js +5 -12
- package/dist/pi-extensions/canvas-passive-context.js +2 -5
- package/dist/pi-extensions/canvas-preview-result.js +2 -1
- package/dist/pi-extensions/canvas-prompt-scrub.js +2 -1
- package/dist/pi-extensions/canvas-recap.js +3 -16
- package/dist/pi-extensions/canvas-review-boundary.js +2 -5
- package/dist/pi-extensions/canvas-stophook.js +2 -26
- package/dist/pi-extensions/canvas-structured-output.js +2 -1
- package/dist/pi-extensions/canvas-tool-guide.js +2 -1
- package/dist/shared/__tests__/env-boundary.test.d.ts +1 -0
- package/dist/shared/__tests__/env-boundary.test.js +93 -0
- package/dist/shared/env.d.ts +68 -0
- package/dist/shared/env.js +171 -0
- package/package.json +3 -1
- package/runtime.lock.json +2 -2
- package/dist/core/canvas/render.d.ts +0 -47
- package/dist/core/canvas/render.js +0 -245
package/dist/daemon/crtrd-cli.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// raw fatal boundary; a winning daemon stays alive through its scheduled loop.
|
|
4
4
|
import '../suppress-experimental-warnings.js';
|
|
5
5
|
import { runDaemon } from './crtrd.js';
|
|
6
|
+
import { envCrtrdTcp } from '../shared/env.js';
|
|
6
7
|
/** Extract `--tcp <host:port>` (or `--tcp=<host:port>`) from argv; falls back to
|
|
7
8
|
* `CRTRD_TCP`. Absent → unix socket only (§4.1). */
|
|
8
9
|
function parseTcpArg(argv) {
|
|
@@ -13,6 +14,6 @@ function parseTcpArg(argv) {
|
|
|
13
14
|
if (arg !== undefined && arg.startsWith('--tcp='))
|
|
14
15
|
return arg.slice('--tcp='.length);
|
|
15
16
|
}
|
|
16
|
-
return
|
|
17
|
+
return envCrtrdTcp();
|
|
17
18
|
}
|
|
18
19
|
await runDaemon({ tcp: parseTcpArg(process.argv.slice(2)) });
|
package/dist/daemon/crtrd.js
CHANGED
|
@@ -71,7 +71,7 @@ import { setInstallId } from '../core/runtime/nodes.js';
|
|
|
71
71
|
import { claimDaemonOwnership, releaseDaemonOwnership } from '../core/canvas/daemon-owner.js';
|
|
72
72
|
import { prewarmRecentRecipes, reapStaleSpares } from '../core/runtime/warm-pool.js';
|
|
73
73
|
import { DaemonFleet } from './fleet.js';
|
|
74
|
-
import {
|
|
74
|
+
import { BOOT_MIGRATIONS } from './boot-migrations.js';
|
|
75
75
|
import { emitEvent } from '../core/events/emit.js';
|
|
76
76
|
import { operationIdContext } from '../core/events/operation-id.js';
|
|
77
77
|
import { bindDaemonEventSource } from '../core/events/source.js';
|
|
@@ -88,7 +88,6 @@ import { ensureOnDiskMigrations } from '../migrations/activation.js';
|
|
|
88
88
|
export function brokerCommandDeclaresCanvasHome(command, home) {
|
|
89
89
|
return command.includes(` --canvas-home ${home} `);
|
|
90
90
|
}
|
|
91
|
-
// ---------------------------------------------------------------------------
|
|
92
91
|
// Startup epoch census (design flow C step 1): before this daemon writes its
|
|
93
92
|
// readiness mirror, reap every broker of a PRIOR epoch on its own canvas.
|
|
94
93
|
// Ownership is never adopted across epochs — a prior daemon's ChildProcess
|
|
@@ -96,7 +95,6 @@ export function brokerCommandDeclaresCanvasHome(command, home) {
|
|
|
96
95
|
// let the startup recovery sweep reclassify their rows through the policy
|
|
97
96
|
// table. A broker whose argv carries NO `--epoch` tag is a legacy-generation
|
|
98
97
|
// broker and gets the same verdict (reap): it predates epoch ownership.
|
|
99
|
-
// ---------------------------------------------------------------------------
|
|
100
98
|
/** The `--epoch <id>` tag host.ts stamps into every broker's argv, or null
|
|
101
99
|
* for a legacy/untagged broker (which the census treats as prior-epoch). */
|
|
102
100
|
export function brokerCommandEpoch(command) {
|
|
@@ -113,7 +111,11 @@ async function reapPriorEpochBrokers(epoch) {
|
|
|
113
111
|
// No process table — the census cannot run. The startup recovery sweep
|
|
114
112
|
// still reclassifies rows; a surviving prior-epoch broker is at worst a
|
|
115
113
|
// duplicate engine risk the next daemon boot's census retries.
|
|
116
|
-
emitEvent({
|
|
114
|
+
emitEvent({
|
|
115
|
+
level: 'error',
|
|
116
|
+
event: 'daemon.census.snapshot_failed',
|
|
117
|
+
fields: { invariant: 'prior-epoch brokers are reaped before readiness' },
|
|
118
|
+
});
|
|
117
119
|
return;
|
|
118
120
|
}
|
|
119
121
|
const home = crtrHome();
|
|
@@ -177,7 +179,6 @@ async function reapPriorEpochBrokers(epoch) {
|
|
|
177
179
|
fields: { prior_epoch_brokers: victims.length, sigtermed, sigkilled },
|
|
178
180
|
});
|
|
179
181
|
}
|
|
180
|
-
// ---------------------------------------------------------------------------
|
|
181
182
|
// Daemon-shutdown fleet teardown (invariant 2: no broker outlives the daemon
|
|
182
183
|
// epoch that launched it). SIGTERM every live entry, race each handle's real
|
|
183
184
|
// exit against ONE shared bounded grace, then SIGKILL each survivor's captured
|
|
@@ -185,7 +186,6 @@ async function reapPriorEpochBrokers(epoch) {
|
|
|
185
186
|
// startup recovery sweep classifies them through the policy table, exactly as
|
|
186
187
|
// it would after a daemon crash, so clean shutdown and crash converge on one
|
|
187
188
|
// recovery path.
|
|
188
|
-
// ---------------------------------------------------------------------------
|
|
189
189
|
const FLEET_TEARDOWN_GRACE_MS = 5_000;
|
|
190
190
|
async function teardownFleet(fleet) {
|
|
191
191
|
const entries = Array.from(fleet.entries());
|
|
@@ -270,9 +270,7 @@ export async function runStartupRecoverySweep(fleet) {
|
|
|
270
270
|
});
|
|
271
271
|
}
|
|
272
272
|
}
|
|
273
|
-
// ---------------------------------------------------------------------------
|
|
274
273
|
// Pidfile
|
|
275
|
-
// ---------------------------------------------------------------------------
|
|
276
274
|
function writePidfile() {
|
|
277
275
|
// Ensure the pidfile parent exists before writing.
|
|
278
276
|
mkdirSync(dirname(pidfilePath()), { recursive: true });
|
|
@@ -341,8 +339,8 @@ export async function superviseTick(now = Date.now(), lifecycle = directTickLife
|
|
|
341
339
|
dormantInbox.run(now, { rows, fleet, hasBrokerCapacity });
|
|
342
340
|
cronLane.run(now, { lifecycle, hasBrokerCapacity });
|
|
343
341
|
humanDeliveryLane.run(now, { lifecycle });
|
|
344
|
-
pendingReviewSubmit.run({ lifecycle });
|
|
345
|
-
storageMaintenance.run(now);
|
|
342
|
+
pendingReviewSubmit.run(now, { lifecycle });
|
|
343
|
+
storageMaintenance.run(now, {});
|
|
346
344
|
}
|
|
347
345
|
/** Start the supervisor loop after winning the authoritative canvas claim.
|
|
348
346
|
*
|
|
@@ -446,7 +444,6 @@ export async function runDaemon(opts = {}) {
|
|
|
446
444
|
process.off('exit', onExit);
|
|
447
445
|
}
|
|
448
446
|
}
|
|
449
|
-
// -------------------------------------------------------------------------
|
|
450
447
|
// Handover — the daemon replaces ITSELF (POST /v1/daemon/restart)
|
|
451
448
|
//
|
|
452
449
|
// The routine reason to restart crtrd is to put a newly selected runtime
|
|
@@ -462,7 +459,6 @@ export async function runDaemon(opts = {}) {
|
|
|
462
459
|
// pi persisting the tool result. It is NOT a correctness fallback; a broker
|
|
463
460
|
// SIGTERMed mid-turn still gets `abortAndExit`'s own bounded persistence
|
|
464
461
|
// window, and the successor's startup recovery sweep resumes it either way.
|
|
465
|
-
// -------------------------------------------------------------------------
|
|
466
462
|
const HANDOVER_ACK_GRACE_MS = 1_000;
|
|
467
463
|
let handoverArmed = false;
|
|
468
464
|
/** Arm the handover. Idempotent: a retry while one is already scheduled
|
|
@@ -684,17 +680,21 @@ export async function runDaemon(opts = {}) {
|
|
|
684
680
|
});
|
|
685
681
|
}
|
|
686
682
|
});
|
|
687
|
-
//
|
|
688
|
-
//
|
|
689
|
-
//
|
|
683
|
+
// Boot-time filesystem repairs (design: src/daemon/boot-migrations.ts) run
|
|
684
|
+
// unconditionally, in order, before supervision can revive anything.
|
|
685
|
+
// Today's one entry is the pre-cutover inbox-identity migration: rows
|
|
686
|
+
// without identities or ISO-timestamp cursors are fatal to the strict
|
|
687
|
+
// reader and crash-loop every legacy broker at inbox seed.
|
|
690
688
|
operationIdContext.fresh(() => {
|
|
691
|
-
const
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
689
|
+
for (const migration of BOOT_MIGRATIONS) {
|
|
690
|
+
const result = migration.apply();
|
|
691
|
+
if (result.changed) {
|
|
692
|
+
emitEvent({
|
|
693
|
+
level: 'info',
|
|
694
|
+
event: 'daemon.boot_migration.applied',
|
|
695
|
+
fields: { migration: migration.id, ...result.summary },
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
698
|
}
|
|
699
699
|
});
|
|
700
700
|
// Startup epoch census (design flow C step 1): reap every prior-epoch
|
package/dist/daemon/fleet.js
CHANGED
|
@@ -23,10 +23,8 @@ import { hasPendingWake } from './reconcilers/live-obligation.js';
|
|
|
23
23
|
import { reviveNode } from '../core/runtime/revive.js';
|
|
24
24
|
import { pushUrgent } from '../core/feed/feed.js';
|
|
25
25
|
import { emitEvent } from '../core/events/emit.js';
|
|
26
|
-
// ---------------------------------------------------------------------------
|
|
27
26
|
// Shared crash helpers (moved from crtrd.ts — the fleet's policy paths are now
|
|
28
27
|
// their primary consumers; crtrd imports them back for its surviving passes).
|
|
29
|
-
// ---------------------------------------------------------------------------
|
|
30
28
|
/** Surface a vehicle that never booted (or exhausted its respawn budget).
|
|
31
29
|
*
|
|
32
30
|
* A pi that dies before its first session_start (so `pi_session_id` was never
|
|
@@ -111,9 +109,7 @@ export function classifyDeadNode(row, busy, pendingWake = true) {
|
|
|
111
109
|
return 'respawn-fresh'; // row 7: bounded ordinary fork-birth retry
|
|
112
110
|
return 'boot-failure'; // row 8
|
|
113
111
|
}
|
|
114
|
-
// ---------------------------------------------------------------------------
|
|
115
112
|
// Respawn throttle (replaces the stranded-relaunch counters, event-driven)
|
|
116
|
-
// ---------------------------------------------------------------------------
|
|
117
113
|
/** An exit with uptime at or above this resets the consecutive-failure
|
|
118
114
|
* counter before classification; a shorter-lived exit increments it. */
|
|
119
115
|
export const HEALTHY_UPTIME_MS = 60_000;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { envHomeOverride } from '../../shared/env.js';
|
|
1
2
|
import { spawn } from 'node:child_process';
|
|
2
3
|
import { settleActionDelivery, } from '../../core/canvas/human-deliveries.js';
|
|
3
4
|
import { killProcessGroup } from '../../core/canvas/pid.js';
|
|
@@ -158,7 +159,7 @@ function actionDeliveryEnv(cwd) {
|
|
|
158
159
|
const env = buildOperationalEnvBase({ targetCwd: cwd, targetProfileId: null });
|
|
159
160
|
// Runtime identity, not host state: an action that calls `crtr` must reach
|
|
160
161
|
// the daemon that delivered to it, exactly as a cron body does.
|
|
161
|
-
const canvasHome =
|
|
162
|
+
const canvasHome = envHomeOverride();
|
|
162
163
|
if (canvasHome !== undefined && canvasHome !== '')
|
|
163
164
|
env['CRTR_HOME'] = canvasHome;
|
|
164
165
|
return env;
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
import { readdirSync, statSync } from 'node:fs';
|
|
1
|
+
import { existsSync, readdirSync, statSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { getRow } from '../../core/canvas/canvas.js';
|
|
4
4
|
import { getReviewByBridge } from '../../core/review/store.js';
|
|
5
5
|
import { emitEvent } from '../../core/events/emit.js';
|
|
6
|
+
import { reviewPath } from '../../core/human/convention.js';
|
|
6
7
|
import { ticketsRoot } from '../../core/human/root.js';
|
|
7
8
|
import { readTicketResult } from '../../core/human/tickets.js';
|
|
8
|
-
import { deliverTerminalResult, releaseActionDelivery, settleFeedbackCompanion } from './finish.js';
|
|
9
|
+
import { cancelHumanTicket, deliverTerminalResult, releaseActionDelivery, settleFeedbackCompanion } from './finish.js';
|
|
10
|
+
/** No surface can open a review ticket that has no canonical row, so cancellation is its
|
|
11
|
+
* only reachable end. Boot runs this before API traffic, and a row is committed before its
|
|
12
|
+
* ticket is published, so an in-flight review is never mistaken for one of these. */
|
|
13
|
+
const UNBACKED_REVIEW_REASON = 'this review predates canonical review records and cannot be opened; re-file the review';
|
|
9
14
|
function isTerminalBridge(status) {
|
|
10
15
|
return status === 'done' || status === 'dead' || status === 'canceled';
|
|
11
16
|
}
|
|
@@ -21,12 +26,18 @@ export async function reconcileUndeliveredTickets() {
|
|
|
21
26
|
if (!statSync(dir).isDirectory())
|
|
22
27
|
continue;
|
|
23
28
|
scanned += 1;
|
|
29
|
+
const canonical = getReviewByBridge(entry) !== null;
|
|
24
30
|
const ticketResult = readTicketResult(dir);
|
|
25
|
-
if (ticketResult === null)
|
|
31
|
+
if (ticketResult === null) {
|
|
32
|
+
if (!canonical && existsSync(reviewPath(dir))) {
|
|
33
|
+
await cancelHumanTicket(entry, { reason: UNBACKED_REVIEW_REASON, actor: 'system' });
|
|
34
|
+
delivered += 1;
|
|
35
|
+
}
|
|
26
36
|
continue;
|
|
37
|
+
}
|
|
27
38
|
// Canonical reviews own terminal delivery and bridge retirement. Their
|
|
28
39
|
// finisher retries only when its winning operation is explicitly repeated.
|
|
29
|
-
if (
|
|
40
|
+
if (canonical)
|
|
30
41
|
continue;
|
|
31
42
|
// A terminal page ticket retires its feedback companion whether or not a
|
|
32
43
|
// reply bridge exists: inbox-only pages have no bridge row, yet the
|
package/dist/daemon/manage.d.ts
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* singleton supervisor, never "a node" itself, so none of this belongs in its
|
|
8
8
|
* env regardless of whether today's code happens to read it — and at least one
|
|
9
9
|
* of these IS actively read: `host.ts`'s broker-engine resolution falls back to
|
|
10
|
-
* `
|
|
11
|
-
* so nothing overrides it per child launch), so a daemon that inherits a
|
|
10
|
+
* `envBrokerEngine()`'s raw `CRTR_BROKER_ENGINE` read verbatim (nodeEnv() never
|
|
11
|
+
* sets that key, so nothing overrides it per child launch), so a daemon that inherits a
|
|
12
12
|
* stale/dev override throws inside `headlessBrokerHost.launch()` on EVERY
|
|
13
13
|
* relaunch it ever attempts, for its whole lifetime — the 2026-07-06 diagnosis
|
|
14
14
|
* root cause behind 19 nodes killed with "failed to relaunch and is now dead". */
|
package/dist/daemon/manage.js
CHANGED
|
@@ -15,9 +15,8 @@ import { hostExecPath } from '../core/runtime/branded-host.js';
|
|
|
15
15
|
// reaches openDb) so the CLI daemon front door stays canvas.db-free (plan B-0).
|
|
16
16
|
import { isDaemonRunning, readPidfile, isPidAlive } from './pidfile.js';
|
|
17
17
|
import { DAEMON_STARTUP_WINDOW_MS } from './startup-policy.js';
|
|
18
|
-
|
|
18
|
+
import { envNoDaemonAutostart } from '../shared/env.js';
|
|
19
19
|
// Daemon env sanitization
|
|
20
|
-
// ---------------------------------------------------------------------------
|
|
21
20
|
/** Env keys that must NEVER reach the daemon process. Restarting crtrd is
|
|
22
21
|
* overwhelmingly done from inside an agent node's own bash tool (`crtr sys
|
|
23
22
|
* daemon stop && start`), which inherits that node's FULL env — its identity
|
|
@@ -27,8 +26,8 @@ import { DAEMON_STARTUP_WINDOW_MS } from './startup-policy.js';
|
|
|
27
26
|
* singleton supervisor, never "a node" itself, so none of this belongs in its
|
|
28
27
|
* env regardless of whether today's code happens to read it — and at least one
|
|
29
28
|
* of these IS actively read: `host.ts`'s broker-engine resolution falls back to
|
|
30
|
-
* `
|
|
31
|
-
* so nothing overrides it per child launch), so a daemon that inherits a
|
|
29
|
+
* `envBrokerEngine()`'s raw `CRTR_BROKER_ENGINE` read verbatim (nodeEnv() never
|
|
30
|
+
* sets that key, so nothing overrides it per child launch), so a daemon that inherits a
|
|
32
31
|
* stale/dev override throws inside `headlessBrokerHost.launch()` on EVERY
|
|
33
32
|
* relaunch it ever attempts, for its whole lifetime — the 2026-07-06 diagnosis
|
|
34
33
|
* root cause behind 19 nodes killed with "failed to relaunch and is now dead". */
|
|
@@ -76,9 +75,7 @@ export function sanitizedDaemonEnv() {
|
|
|
76
75
|
delete env[key];
|
|
77
76
|
return env;
|
|
78
77
|
}
|
|
79
|
-
// ---------------------------------------------------------------------------
|
|
80
78
|
// Entry point resolution
|
|
81
|
-
// ---------------------------------------------------------------------------
|
|
82
79
|
/** Locate the package or generation root from a regular build, the standalone
|
|
83
80
|
* attach bundle, or a tsx source checkout. */
|
|
84
81
|
function generationRoot() {
|
|
@@ -117,9 +114,7 @@ async function resolveDaemonLaunch() {
|
|
|
117
114
|
}
|
|
118
115
|
return [result.runtime.entryPath];
|
|
119
116
|
}
|
|
120
|
-
// ---------------------------------------------------------------------------
|
|
121
117
|
// Stray-daemon sweep
|
|
122
|
-
// ---------------------------------------------------------------------------
|
|
123
118
|
/** A crtrd declares its owning canvas in argv, so ownership is an exact match
|
|
124
119
|
* on this process's canvas home. Untagged daemons retain their own
|
|
125
120
|
* supervision and are never counted or killed here. */
|
|
@@ -191,9 +186,7 @@ export function sweepStrayDaemons(keepPid) {
|
|
|
191
186
|
}
|
|
192
187
|
return strays;
|
|
193
188
|
}
|
|
194
|
-
// ---------------------------------------------------------------------------
|
|
195
189
|
// daemon launch — low-level spawn/exec
|
|
196
|
-
// ---------------------------------------------------------------------------
|
|
197
190
|
/** Replace PID 1 with the selected daemon generation. Docker keeps a container
|
|
198
191
|
* alive only while PID 1 lives, so a handover there must preserve its pid. */
|
|
199
192
|
export async function execDaemon() {
|
|
@@ -376,9 +369,7 @@ export async function spawnDaemon() {
|
|
|
376
369
|
}
|
|
377
370
|
return { started: true, pid };
|
|
378
371
|
}
|
|
379
|
-
// ---------------------------------------------------------------------------
|
|
380
372
|
// ensureDaemon — fire-and-forget front-door helper
|
|
381
|
-
// ---------------------------------------------------------------------------
|
|
382
373
|
/** Whether autostart is suppressed for this invocation. `--no-autostart` or
|
|
383
374
|
* `CRTR_NO_DAEMON_AUTOSTART=1` forces fail-loud on a cold socket (spec §7.1) —
|
|
384
375
|
* for environments that manage crtrd externally and want the diagnostic, and
|
|
@@ -393,7 +384,7 @@ export async function spawnDaemon() {
|
|
|
393
384
|
* explicit `crtr sys daemon start` calls `spawnDaemon` directly and is
|
|
394
385
|
* deliberately unaffected. */
|
|
395
386
|
export function autostartDisabled() {
|
|
396
|
-
return
|
|
387
|
+
return envNoDaemonAutostart() || process.argv.includes('--no-autostart');
|
|
397
388
|
}
|
|
398
389
|
/** Start the daemon if it is not already running. No-op if already up, or if
|
|
399
390
|
* autostart is suppressed for this invocation.
|
package/dist/daemon/pidfile.js
CHANGED
|
@@ -13,13 +13,13 @@ import { existsSync, readFileSync } from 'node:fs';
|
|
|
13
13
|
import { join } from 'node:path';
|
|
14
14
|
import { crtrHome } from '../core/canvas/paths.js';
|
|
15
15
|
import { isPidAlive } from '../core/canvas/pid.js';
|
|
16
|
+
import { envPidfileOverride } from '../shared/env.js';
|
|
16
17
|
// Re-exported so `isPidAlive` stays reachable from the daemon layer's public
|
|
17
18
|
// surface (crtrd.ts already re-exports it; callers may reach it either way).
|
|
18
19
|
export { isPidAlive };
|
|
19
20
|
/** Absolute path to crtrd's pidfile. `CRTR_PIDFILE` overrides for tests. */
|
|
20
21
|
export function pidfilePath() {
|
|
21
|
-
|
|
22
|
-
return override !== undefined && override !== '' ? override : join(crtrHome(), 'crtrd.pid');
|
|
22
|
+
return envPidfileOverride() ?? join(crtrHome(), 'crtrd.pid');
|
|
23
23
|
}
|
|
24
24
|
/** Read the pid stored in the pidfile, or null if absent / malformed. */
|
|
25
25
|
export function readPidfile() {
|
|
@@ -17,7 +17,7 @@ import { reloadAuthLive } from '../../core/runtime/auth-reload.js';
|
|
|
17
17
|
import { readConfig } from '../../core/config.js';
|
|
18
18
|
import { emitEvent } from '../../core/events/emit.js';
|
|
19
19
|
import { operationIdContext } from '../../core/events/operation-id.js';
|
|
20
|
-
import {
|
|
20
|
+
import { hasUnseenWakeMail } from '../../core/feed/inbox.js';
|
|
21
21
|
import { activeBackgroundBashJobs } from '../../core/bash-jobs.js';
|
|
22
22
|
import { focusOf } from '../../core/runtime/placement.js';
|
|
23
23
|
import { hasAttachedBrokerViewers } from '../../core/runtime/broker/client-registry.js';
|
|
@@ -26,18 +26,12 @@ import { BrokerUnreachableError } from '../../core/runtime/broker-request.js';
|
|
|
26
26
|
import { formatCard, PARK_SUMMARY_PROMPT } from '../../shared/generated-context.js';
|
|
27
27
|
import { beginPendingPark, consumePendingPark, pendingParkIds, pendingParkStartedAt } from '../park-pending.js';
|
|
28
28
|
import { applyParkEvent, parkEvent } from './live-obligation.js';
|
|
29
|
+
import { envMaxLiveBrokers, envNoDaemonAutostart, envTestParkSummaryGraceMs, envTestUnattendedParkMs, envWarnLiveBrokers, } from '../../shared/env.js';
|
|
29
30
|
const execFileAsync = promisify(execFile);
|
|
30
|
-
function configuredPositiveInteger(name, fallback) {
|
|
31
|
-
const raw = process.env[name];
|
|
32
|
-
if (raw === undefined || raw === '')
|
|
33
|
-
return fallback;
|
|
34
|
-
const n = Number(raw);
|
|
35
|
-
return Number.isSafeInteger(n) && n >= 1 ? n : fallback;
|
|
36
|
-
}
|
|
37
31
|
export function brokerThresholdsForDaemon() {
|
|
38
32
|
const configured = readConfig('user').brokerThresholds;
|
|
39
|
-
const automaticReviveCap =
|
|
40
|
-
const warning =
|
|
33
|
+
const automaticReviveCap = envMaxLiveBrokers() ?? configured.automaticReviveCap;
|
|
34
|
+
const warning = envWarnLiveBrokers() ?? configured.warning;
|
|
41
35
|
return { warning: Math.min(warning, automaticReviveCap), automaticReviveCap };
|
|
42
36
|
}
|
|
43
37
|
export const YIELD_STALL_GRACE_MS = 3 * 60_000;
|
|
@@ -51,18 +45,12 @@ const DEFAULT_UNATTENDED_PARK_MS = 15 * 60_000;
|
|
|
51
45
|
// stuck parking turn cannot hold a broker for a whole extra clock period.
|
|
52
46
|
const DEFAULT_PARK_SUMMARY_GRACE_MS = 5 * 60_000;
|
|
53
47
|
export function unattendedParkMsForDaemon() {
|
|
54
|
-
|
|
55
|
-
if (raw === undefined)
|
|
48
|
+
if (!envNoDaemonAutostart())
|
|
56
49
|
return DEFAULT_UNATTENDED_PARK_MS;
|
|
57
|
-
|
|
58
|
-
return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_UNATTENDED_PARK_MS;
|
|
50
|
+
return envTestUnattendedParkMs() ?? DEFAULT_UNATTENDED_PARK_MS;
|
|
59
51
|
}
|
|
60
52
|
export function parkSummaryGraceMsForDaemon() {
|
|
61
|
-
|
|
62
|
-
if (raw === undefined)
|
|
63
|
-
return DEFAULT_PARK_SUMMARY_GRACE_MS;
|
|
64
|
-
const parsed = Number(raw);
|
|
65
|
-
return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_PARK_SUMMARY_GRACE_MS;
|
|
53
|
+
return envTestParkSummaryGraceMs() ?? DEFAULT_PARK_SUMMARY_GRACE_MS;
|
|
66
54
|
}
|
|
67
55
|
export function yieldStallVerdict(piPidAlive, intent, busy, stalledFor) {
|
|
68
56
|
if (piPidAlive !== true)
|
|
@@ -152,7 +140,7 @@ export class BrokerSupervisionReconciler {
|
|
|
152
140
|
lastOverCapWarnAt = Number.NEGATIVE_INFINITY;
|
|
153
141
|
lastCapacityLogAt = Number.NEGATIVE_INFINITY;
|
|
154
142
|
async run(now, ctx) {
|
|
155
|
-
await this.handleAuthReload(
|
|
143
|
+
await this.handleAuthReload(ctx.fleet);
|
|
156
144
|
const thresholds = brokerThresholdsForDaemon();
|
|
157
145
|
if (ctx.fleet.size() >= thresholds.warning && ctx.lifecycle.acceptsDetachedWork()) {
|
|
158
146
|
const warning = operationIdContext.fresh(() => this.warnOverCapInTmux(ctx.fleet.size(), thresholds.warning, thresholds.automaticReviveCap));
|
|
@@ -218,7 +206,7 @@ export class BrokerSupervisionReconciler {
|
|
|
218
206
|
&& (fault.retry.nextAt !== undefined || nextFaultRetry(fault, now) !== null);
|
|
219
207
|
if (activeAutoProviderRetry)
|
|
220
208
|
return true;
|
|
221
|
-
return
|
|
209
|
+
return hasUnseenWakeMail(id);
|
|
222
210
|
}
|
|
223
211
|
handleUnattendedParking(id, row, livePid, now, ctx) {
|
|
224
212
|
// An unclaimed warm-pool spare is not a conversation: the booted broker it
|
|
@@ -371,14 +359,19 @@ export class BrokerSupervisionReconciler {
|
|
|
371
359
|
timeout: 2000,
|
|
372
360
|
});
|
|
373
361
|
}
|
|
374
|
-
catch {
|
|
375
|
-
|
|
362
|
+
catch (err) {
|
|
363
|
+
emitEvent({
|
|
364
|
+
level: 'error',
|
|
365
|
+
event: 'broker.capacity.tmux_display_failed',
|
|
366
|
+
error: err,
|
|
367
|
+
fields: { client },
|
|
368
|
+
});
|
|
376
369
|
}
|
|
377
370
|
}
|
|
378
371
|
}));
|
|
379
372
|
}
|
|
380
|
-
catch {
|
|
381
|
-
|
|
373
|
+
catch (err) {
|
|
374
|
+
emitEvent({ level: 'error', event: 'broker.capacity.tmux_list_clients_failed', error: err });
|
|
382
375
|
}
|
|
383
376
|
}
|
|
384
377
|
handleYieldStall(row, pid, now) {
|
|
@@ -521,8 +514,13 @@ export class BrokerSupervisionReconciler {
|
|
|
521
514
|
message: label,
|
|
522
515
|
});
|
|
523
516
|
}
|
|
524
|
-
catch {
|
|
525
|
-
|
|
517
|
+
catch (err) {
|
|
518
|
+
emitEvent({
|
|
519
|
+
level: 'error',
|
|
520
|
+
event: 'broker.wedge.fault_record_failed',
|
|
521
|
+
...(isSafeNodeId(id) ? { node_id: id } : { fields: { affected_node_id: id } }),
|
|
522
|
+
error: err,
|
|
523
|
+
});
|
|
526
524
|
}
|
|
527
525
|
fanDoctrineWake(id, subscribersOf(id), label, {
|
|
528
526
|
reason: 'child-wedged',
|
|
@@ -584,8 +582,7 @@ export class BrokerSupervisionReconciler {
|
|
|
584
582
|
message: firstLine,
|
|
585
583
|
});
|
|
586
584
|
}
|
|
587
|
-
async handleAuthReload(
|
|
588
|
-
void now;
|
|
585
|
+
async handleAuthReload(fleet) {
|
|
589
586
|
let mtimeMs = 0;
|
|
590
587
|
for (const path of piCredentialPaths()) {
|
|
591
588
|
try {
|
|
@@ -10,7 +10,7 @@ export interface DormantInboxContext extends ControllerDeathContext {
|
|
|
10
10
|
hasBrokerCapacity(): boolean;
|
|
11
11
|
}
|
|
12
12
|
export declare class ControllerDeathReconciler {
|
|
13
|
-
run(
|
|
13
|
+
run(now: number, ctx: ControllerDeathContext): void;
|
|
14
14
|
}
|
|
15
15
|
export declare class DormantInboxReconciler {
|
|
16
16
|
private readonly relaunchState;
|
|
@@ -18,7 +18,8 @@ const IDLE_RELEASE_RELAUNCH_MAX_ATTEMPTS = 6;
|
|
|
18
18
|
const IDLE_RELEASE_RELAUNCH_MAX_BACKOFF_MS = 10 * 60_000;
|
|
19
19
|
const IDLE_RELEASE_RELAUNCH_BASE_MS = 20_000;
|
|
20
20
|
export class ControllerDeathReconciler {
|
|
21
|
-
run(
|
|
21
|
+
run(now, ctx) {
|
|
22
|
+
void now; // no time-gating here — the death check is already-controller-status-driven; the param is kept for six-way call-site uniformity, matching every other reconciler's run(now, ctx) shape.
|
|
22
23
|
// Settle every wait whose controller has ended, independent of the waiter's
|
|
23
24
|
// current status. Active and focused terminal nodes own a live inbox
|
|
24
25
|
// watcher; idle-released nodes are revived by the following reconciler.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { hasActiveLiveSubscription, hasLiveMessageWait, hasLiveSubscriber, hasPendingCancelOnWakeCron, subscribersOf, } from '../../core/canvas/index.js';
|
|
2
2
|
import { fullName } from '../../core/canvas/labels.js';
|
|
3
3
|
import { countTickets } from '../../core/canvas/attention.js';
|
|
4
|
-
import { readCursor, readInboxSince } from '../../core/feed/inbox.js';
|
|
4
|
+
import { hasUnseenWakeMail, readCursor, readInboxSince } from '../../core/feed/inbox.js';
|
|
5
5
|
import { readOutputRequest } from '../../core/runtime/structured-output.js';
|
|
6
6
|
import { focusOf } from '../../core/runtime/placement.js';
|
|
7
7
|
import { hasAttachedBrokerViewers } from '../../core/runtime/broker/client-registry.js';
|
|
@@ -26,7 +26,7 @@ export function hasLiveObligation(nodeId) {
|
|
|
26
26
|
export function hasPendingWake(nodeId) {
|
|
27
27
|
if (hasLiveObligation(nodeId))
|
|
28
28
|
return true;
|
|
29
|
-
if (
|
|
29
|
+
if (hasUnseenWakeMail(nodeId))
|
|
30
30
|
return true;
|
|
31
31
|
return focusOf(nodeId) !== null || hasAttachedBrokerViewers(nodeId);
|
|
32
32
|
}
|
|
@@ -11,7 +11,8 @@ import { operationIdContext } from '../../core/events/operation-id.js';
|
|
|
11
11
|
import { listSubmitRequestedReviews } from '../../core/review/store.js';
|
|
12
12
|
import { completeRequestedSubmit } from '../review/finish.js';
|
|
13
13
|
export class PendingReviewSubmitReconciler {
|
|
14
|
-
run(ctx) {
|
|
14
|
+
run(now, ctx) {
|
|
15
|
+
void now; // this pass lists submit-requested reviews unconditionally — nothing here is time-gated; the param is kept for six-way call-site uniformity, matching every other reconciler's run(now, ctx) shape.
|
|
15
16
|
if (!ctx.lifecycle.acceptsDetachedWork())
|
|
16
17
|
return;
|
|
17
18
|
let pending;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
export declare const DEAD_REAP_GRACE_MS: number;
|
|
2
|
+
export type StorageMaintenanceContext = Record<string, never>;
|
|
2
3
|
/** Recurring storage cleanup. The in-memory throttle clocks intentionally reset
|
|
3
4
|
* on daemon boot, so the first tick runs both full sweeps. */
|
|
4
5
|
export declare class StorageMaintenanceReconciler {
|
|
5
6
|
private lastSpareSweepAt;
|
|
6
7
|
private lastGhostSweepAt;
|
|
7
|
-
run(now: number): void;
|
|
8
|
+
run(now: number, ctx: StorageMaintenanceContext): void;
|
|
8
9
|
/** Drop rows whose on-disk node dir is gone. Such a row can never be revived,
|
|
9
10
|
* focused, or closed — every one of those resolves the node through meta.json —
|
|
10
11
|
* so it sits in the roster jamming the surfaces that try. One readdir per sweep. */
|
|
@@ -16,7 +16,8 @@ const GHOST_SWEEP_INTERVAL_MS = 60 * 1000;
|
|
|
16
16
|
export class StorageMaintenanceReconciler {
|
|
17
17
|
lastSpareSweepAt = Number.NEGATIVE_INFINITY;
|
|
18
18
|
lastGhostSweepAt = Number.NEGATIVE_INFINITY;
|
|
19
|
-
run(now) {
|
|
19
|
+
run(now, ctx) {
|
|
20
|
+
void ctx; // no consumer today — kept only for six-way call-site uniformity
|
|
20
21
|
// Placement reap MUST precede focus GC, so GC catches a focus row the reap
|
|
21
22
|
// strands. Both run after dormant-inbox reconciliation, so a same-tick
|
|
22
23
|
// revive has already had the chance to re-anchor its focus.
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
// the wait exists to protect.
|
|
15
15
|
import { getNode } from '../../core/canvas/canvas.js';
|
|
16
16
|
import { isPidAlive } from '../../core/canvas/pid.js';
|
|
17
|
-
import {
|
|
17
|
+
import { hasUnseenWakeMail } from '../../core/feed/inbox.js';
|
|
18
18
|
import { isBusy } from '../../core/runtime/busy.js';
|
|
19
19
|
/** Is the companion inside a turn right now? */
|
|
20
20
|
export function companionMidTurn(nodeId) {
|
|
@@ -27,7 +27,7 @@ export function companionMidTurn(nodeId) {
|
|
|
27
27
|
* excluded for the same reason the settlement policy excludes it: it never
|
|
28
28
|
* starts a turn of its own. */
|
|
29
29
|
export function companionHasQueuedWork(nodeId) {
|
|
30
|
-
return
|
|
30
|
+
return hasUnseenWakeMail(nodeId);
|
|
31
31
|
}
|
|
32
32
|
/** Would submitting right now step on the companion's work? */
|
|
33
33
|
export function companionStillWorking(nodeId) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync, readdirSync, rmSync } from 'node:fs';
|
|
2
2
|
import { basename } from 'node:path';
|
|
3
|
+
import { emitEvent } from '../../core/events/emit.js';
|
|
3
4
|
import { reviewPath } from '../../core/human/convention.js';
|
|
4
5
|
import { ticketDir } from '../../core/human/root.js';
|
|
5
6
|
import { submitReview } from '../../core/human/tickets.js';
|
|
@@ -91,8 +92,10 @@ export async function sweepReviews() {
|
|
|
91
92
|
catch (error) {
|
|
92
93
|
// A missing immutable branch is an expected recovery outcome: realization
|
|
93
94
|
// cancels the binding and never captures a replacement branch.
|
|
94
|
-
if (!(error instanceof ReviewOperationError && error.code === 'branch_lost'))
|
|
95
|
+
if (!(error instanceof ReviewOperationError && error.code === 'branch_lost')) {
|
|
96
|
+
emitEvent({ level: 'warn', event: 'daemon.review_sweep.realize_failed', fields: { review_id: review.review_id, error: errorText(error) } });
|
|
95
97
|
failed += 1;
|
|
98
|
+
}
|
|
96
99
|
}
|
|
97
100
|
}
|
|
98
101
|
try {
|
|
@@ -102,7 +105,8 @@ export async function sweepReviews() {
|
|
|
102
105
|
]);
|
|
103
106
|
collected = collectOrphanReviewDirectories(reviewIds);
|
|
104
107
|
}
|
|
105
|
-
catch {
|
|
108
|
+
catch (error) {
|
|
109
|
+
emitEvent({ level: 'warn', event: 'daemon.review_sweep.collect_orphans_failed', fields: { error: errorText(error) } });
|
|
106
110
|
failed += 1;
|
|
107
111
|
}
|
|
108
112
|
for (const review of listReviews({ state: 'approved' })) {
|
|
@@ -123,7 +127,8 @@ export async function sweepReviews() {
|
|
|
123
127
|
try {
|
|
124
128
|
republishTicketReview(review);
|
|
125
129
|
}
|
|
126
|
-
catch {
|
|
130
|
+
catch (error) {
|
|
131
|
+
emitEvent({ level: 'warn', event: 'daemon.review_sweep.republish_failed', fields: { review_id: review.review_id, error: errorText(error) } });
|
|
127
132
|
failed += 1;
|
|
128
133
|
}
|
|
129
134
|
}
|
|
@@ -19,9 +19,7 @@ import { parse as parseYaml } from 'yaml';
|
|
|
19
19
|
import { parseFrontmatterGeneric } from '../core/frontmatter.js';
|
|
20
20
|
import { appendRenderedKey, dropTopLevelKeys, proveFrontmatterRoundTrip, rebuildDocSource, } from './frontmatter-splice.js';
|
|
21
21
|
const OLD_FIELDS = ['system-prompt-visibility', 'file-read-visibility', 'applies-to', 'read-when'];
|
|
22
|
-
// ---------------------------------------------------------------------------
|
|
23
22
|
// Frozen old-schema parsing (pre-cut substrate/schema.ts semantics).
|
|
24
|
-
// ---------------------------------------------------------------------------
|
|
25
23
|
const RUNGS = ['none', 'name', 'preview', 'content'];
|
|
26
24
|
function rungRank(r) {
|
|
27
25
|
return RUNGS.indexOf(r);
|
|
@@ -67,12 +65,10 @@ function classify(doc) {
|
|
|
67
65
|
hasOldFields: OLD_FIELDS.some((k) => k in fm),
|
|
68
66
|
};
|
|
69
67
|
}
|
|
70
|
-
// ---------------------------------------------------------------------------
|
|
71
68
|
// Frozen boot-ceiling walk (pre-cut substrate/ceiling.ts), per store: a
|
|
72
69
|
// directory INDEX's rung caps every descendant's boot rung; the migration
|
|
73
70
|
// bakes the effective (post-ceiling) rung into each doc so the rendered boot
|
|
74
71
|
// tree is preserved once the ceiling machinery is deleted.
|
|
75
|
-
// ---------------------------------------------------------------------------
|
|
76
72
|
function buildCeiling(docs) {
|
|
77
73
|
const m = new Map();
|
|
78
74
|
for (const d of docs) {
|
|
@@ -129,11 +125,9 @@ function planEntries(d, bootRung) {
|
|
|
129
125
|
}
|
|
130
126
|
return entries;
|
|
131
127
|
}
|
|
132
|
-
// ---------------------------------------------------------------------------
|
|
133
128
|
// Serialization: cut the dead keys' exact line spans out of the raw
|
|
134
129
|
// frontmatter text, append the rendered `surfaces:` block, re-parse to prove
|
|
135
130
|
// the splice is meaning-preserving.
|
|
136
|
-
// ---------------------------------------------------------------------------
|
|
137
131
|
function migratedYaml(rawYaml, entries, docPath) {
|
|
138
132
|
let out = dropTopLevelKeys(rawYaml, OLD_FIELDS, docPath);
|
|
139
133
|
if (entries.length > 0)
|