@north-light/crouter 0.3.233 → 0.3.235
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/api/dto/nodes.d.ts +11 -0
- 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 +535 -537
- 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 +1 -9
- 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 +10 -23
- 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/human.js +1 -1
- package/dist/commands/memory/__tests__/command-selector-and-mutation-guards.test.js +4 -4
- package/dist/commands/memory/__tests__/memory-list-and-lint-ignore.test.d.ts +1 -0
- package/dist/commands/memory/__tests__/memory-list-and-lint-ignore.test.js +96 -0
- package/dist/commands/memory/delete.js +1 -1
- package/dist/commands/memory/edit.js +6 -3
- package/dist/commands/memory/find.js +2 -2
- package/dist/commands/memory/lint.js +2 -1
- package/dist/commands/memory/list.d.ts +4 -0
- package/dist/commands/memory/list.js +20 -14
- package/dist/commands/memory/move.js +1 -1
- package/dist/commands/memory/read.d.ts +2 -7
- package/dist/commands/memory/read.js +5 -16
- package/dist/commands/memory/shared.d.ts +1 -0
- package/dist/commands/memory/shared.js +17 -8
- package/dist/commands/memory/write.js +8 -4
- package/dist/commands/node/bash.js +2 -1
- package/dist/commands/node/create.js +2 -1
- package/dist/commands/node/inspect.js +11 -10
- package/dist/commands/node/lifecycle.js +5 -13
- package/dist/commands/node/message.js +11 -6
- package/dist/commands/node/subscription.js +7 -2
- package/dist/commands/node/wait.js +9 -4
- 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 +3 -2
- package/dist/commands/pkg/shared.js +0 -2
- package/dist/commands/pkg.js +1 -0
- package/dist/commands/profile/delete.js +2 -1
- package/dist/commands/profile/rename.js +1 -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 +1 -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/commands/sys.js +1 -0
- 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__/cli-help-contract.test.d.ts +1 -0
- package/dist/core/__tests__/cli-help-contract.test.js +150 -0
- 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 +21 -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/__tests__/watchdog-abort-arms-retry.test.js +11 -6
- 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 +61 -19
- 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/meta-file.js +18 -27
- 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.d.ts +8 -0
- package/dist/core/canvas/remote-canvas-source.js +9 -3
- package/dist/core/canvas/render-source.js +31 -13
- package/dist/core/command-manifests/manifest.js +0 -10
- package/dist/core/command-manifests/registry.d.ts +2 -0
- package/dist/core/command-manifests/schema.js +0 -4
- package/dist/core/command-plugins/compose.js +4 -2
- package/dist/core/command-plugins/discovery.d.ts +1 -0
- package/dist/core/command-plugins/discovery.js +1 -1
- package/dist/core/command-plugins/transport/http-invoke.js +0 -14
- package/dist/core/command.js +2 -6
- package/dist/core/config.js +2 -1
- package/dist/core/fault-classifier.js +8 -0
- 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.d.ts +2 -0
- package/dist/core/pagination.js +2 -3
- 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 +11 -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/rebind.js +50 -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.d.ts +2 -2
- package/dist/core/runtime/launch.js +20 -10
- 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/stop-guard.js +28 -16
- 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/frontmatter-validation.d.ts +1 -0
- package/dist/core/substrate/frontmatter-validation.js +1 -1
- 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__/error-seam.test.js +27 -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 +16 -20
- package/dist/daemon/api/handlers/nodes.js +23 -22
- package/dist/daemon/api/handlers/reports.js +1 -1
- package/dist/daemon/api/handlers/reviews.js +1 -6
- package/dist/daemon/api/handlers/worktree.js +6 -22
- package/dist/daemon/api/map.d.ts +4 -2
- package/dist/daemon/api/map.js +22 -8
- 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 +27 -30
- 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 +7 -20
- 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
|
@@ -82,16 +82,17 @@ const nodeList = defineLeaf({
|
|
|
82
82
|
return false;
|
|
83
83
|
return true;
|
|
84
84
|
});
|
|
85
|
-
const nodes =
|
|
85
|
+
const nodes = [];
|
|
86
|
+
for (const row of rows) {
|
|
86
87
|
const detail = await canvasSource.getNode(row.node_id).catch(rethrowAsCliError);
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
const named = { ...row, name: fullName(detail ?? row) };
|
|
89
|
+
if (name === undefined || name === '' || fuzzyMatch(name, named.name))
|
|
90
|
+
nodes.push(named);
|
|
91
|
+
}
|
|
89
92
|
return { nodes };
|
|
90
93
|
},
|
|
91
94
|
});
|
|
92
|
-
// ---------------------------------------------------------------------------
|
|
93
95
|
// node inspect show — a node + its place in the spine
|
|
94
|
-
// ---------------------------------------------------------------------------
|
|
95
96
|
// The renderer receives only the command result, while JSON output bypasses it.
|
|
96
97
|
// Keep remote provenance out of the returned DTO-shaped object without adding a
|
|
97
98
|
// second wire field or mutating the remote response.
|
|
@@ -121,6 +122,7 @@ const nodeShow = defineLeaf({
|
|
|
121
122
|
],
|
|
122
123
|
output: [
|
|
123
124
|
{ name: 'node', type: 'object', required: true, constraint: 'The full node meta (system prompt + every telemetry field). The render surfaces a glanceable slice; `--json` carries the complete dump.' },
|
|
125
|
+
{ name: 'fault', type: 'object', required: true, constraint: 'The active runtime fault projection, or null: {link, kind, retry: {disposition}, since}.' },
|
|
124
126
|
{ name: 'reports', type: 'object[]', required: true, constraint: 'Who this node subscribes to (its reports/down), each enriched with {node_id, name, kind, status, active} — these are typically its spawned children.' },
|
|
125
127
|
{ name: 'managers', type: 'object[]', required: true, constraint: 'Who subscribes to this node (its managers/up), same enriched shape.' },
|
|
126
128
|
{ name: 'artifacts', type: 'object', required: true, constraint: 'Counts of what the node left on disk by corpus: {report, doc, roadmap}. Enumerate them with `node inspect artifacts <id>`.' },
|
|
@@ -188,7 +190,7 @@ const nodeShow = defineLeaf({
|
|
|
188
190
|
if (reports.length > 0)
|
|
189
191
|
hints.push(`Drill into a child/report: \`crtr node inspect show <node_id>\` (${reports.map((r) => r['node_id']).join(', ')}).`);
|
|
190
192
|
hints.push(`Full machine dump (system prompt + all telemetry): \`crtr --json node inspect show ${id}\`.`);
|
|
191
|
-
return { node, reports, managers, artifacts, pending_crons, paths, follow_up: hints.join('\n') };
|
|
193
|
+
return { node, fault: node.fault ?? null, reports, managers, artifacts, pending_crons, paths, follow_up: hints.join('\n') };
|
|
192
194
|
},
|
|
193
195
|
render: (r) => {
|
|
194
196
|
const node = r['node'];
|
|
@@ -197,12 +199,14 @@ const nodeShow = defineLeaf({
|
|
|
197
199
|
const isRemoteShow = remoteShowResults.has(r);
|
|
198
200
|
const alive = isRemoteShow ? 'remote (liveness not checked locally)' : (isPidAlive(pid) ? 'alive' : 'dead');
|
|
199
201
|
const intent = node['intent'] ? `/${String(node['intent'])}` : '';
|
|
202
|
+
const fault = r['fault'];
|
|
200
203
|
const parts = [];
|
|
201
204
|
// 1) Glanceable meta slice — the debug-critical fields, not the full dump.
|
|
202
205
|
parts.push(`# ${fullName(node)} (${id})`);
|
|
203
206
|
const meta = [
|
|
204
207
|
`- kind/mode/lifecycle: ${node['kind']} / ${node['mode']} / ${node['lifecycle']}`,
|
|
205
208
|
`- status: ${node['status']}${intent}`,
|
|
209
|
+
...(fault === null || fault === undefined ? [] : [`- fault: ${String(fault['kind'])} / ${String(fault['retry']?.disposition)} since ${String(fault['since'])}`]),
|
|
206
210
|
`- broker pid: ${pid ?? '(none)'} — ${alive}`,
|
|
207
211
|
`- cwd: ${node['cwd']}`,
|
|
208
212
|
`- host: ${node['host_kind']}` + (node['profile_id'] ? ` · profile ${node['profile_id']}` : ''),
|
|
@@ -233,9 +237,7 @@ const nodeShow = defineLeaf({
|
|
|
233
237
|
return parts.join('\n\n');
|
|
234
238
|
},
|
|
235
239
|
});
|
|
236
|
-
// ---------------------------------------------------------------------------
|
|
237
240
|
// node fork — branch a conversation + durable context into an idle root
|
|
238
|
-
// ---------------------------------------------------------------------------
|
|
239
241
|
export const nodeFork = defineLeaf({
|
|
240
242
|
name: 'fork',
|
|
241
243
|
description: 'fork a node into an independent idle root with the same conversation and durable context',
|
|
@@ -287,9 +289,7 @@ export const nodeFork = defineLeaf({
|
|
|
287
289
|
return `Forked independent idle root ${result['node_id']}.${placement} It will make no model call until its first real user message.`;
|
|
288
290
|
},
|
|
289
291
|
});
|
|
290
|
-
// ---------------------------------------------------------------------------
|
|
291
292
|
// node inspect — read the graph (list, show, context)
|
|
292
|
-
// ---------------------------------------------------------------------------
|
|
293
293
|
export const nodeInspect = defineBranch({
|
|
294
294
|
name: 'inspect',
|
|
295
295
|
description: 'read one node — its graph position, context, and artifacts',
|
|
@@ -297,6 +297,7 @@ export const nodeInspect = defineBranch({
|
|
|
297
297
|
help: {
|
|
298
298
|
name: 'node inspect',
|
|
299
299
|
summary: 'read one node (or the roster) — topology, context dir, and artifacts',
|
|
300
|
+
model: 'Inspection is read-only and never revives a node. The roster is the selection surface; one-node metadata points to progressively heavier views: a parsed broker snapshot, rendered conversation, context browser, or artifact references.',
|
|
300
301
|
},
|
|
301
302
|
children: [nodeList, nodeShow, nodeSnapshotLeaf, nodeTranscriptLeaf, nodeContextLeaf, nodeArtifactsLeaf],
|
|
302
303
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// `crtr node` lifecycle and durable configuration commands.
|
|
2
|
+
import { envNodeId } from '../../shared/env.js';
|
|
2
3
|
import { defineBranch, defineLeaf } from '../../core/command.js';
|
|
3
4
|
import { InputError } from '../../core/io.js';
|
|
4
5
|
import { cliClient, getNodeOrNull, rethrowAsCliError } from '../api-client.js';
|
|
@@ -65,9 +66,7 @@ const nodeRecycle = defineLeaf({
|
|
|
65
66
|
return lines.join('\n');
|
|
66
67
|
},
|
|
67
68
|
});
|
|
68
|
-
// ---------------------------------------------------------------------------
|
|
69
69
|
// node lifecycle close — close a node + cascade-cancel its exclusive subtree (Alt+C → x)
|
|
70
|
-
// ---------------------------------------------------------------------------
|
|
71
70
|
const nodeClose = defineLeaf({
|
|
72
71
|
name: 'close',
|
|
73
72
|
description: 'close a node + cascade-cancel its exclusive subtree (revivable)',
|
|
@@ -110,9 +109,7 @@ const nodeClose = defineLeaf({
|
|
|
110
109
|
return `Closed ${r['node_id']} and its exclusive subtree — ${r['count']} node(s) closed${spared > 0 ? `, ${spared} spared (still managed from outside the subtree)` : ''}.`;
|
|
111
110
|
},
|
|
112
111
|
});
|
|
113
|
-
// ---------------------------------------------------------------------------
|
|
114
112
|
// node config — reconfigure a node's settings headlessly (model/lifecycle/kind/mode/name)
|
|
115
|
-
// ---------------------------------------------------------------------------
|
|
116
113
|
const NODE_CONFIG_MODEL_EFFECT = 'Model change first: a live broker switches immediately over its socket; a dormant node persists the durable model override and launch recipe for its next revive.';
|
|
117
114
|
export const nodeConfig = defineLeaf({
|
|
118
115
|
name: 'config',
|
|
@@ -268,7 +265,7 @@ export const nodePromote = defineLeaf({
|
|
|
268
265
|
effects: ['Flips mode→orchestrator + kind→chosen (lifecycle unchanged unless --resident, which also flips lifecycle→resident); --model durably pins the model tier; rewrites the launch spec to that kind\'s orchestrator persona; seeds context/roadmap.md scaffold if absent.', 'The next model request is gated on appending and persisting your new-role guidance. If a fresh context starts first, its rebuilt baseline carries the new role.'],
|
|
269
266
|
},
|
|
270
267
|
run: async (input) => {
|
|
271
|
-
const id = input['node'] ??
|
|
268
|
+
const id = input['node'] ?? envNodeId();
|
|
272
269
|
if (id === undefined || id === '')
|
|
273
270
|
throw new InputError({ error: 'no_node', message: 'no node to promote (set CRTR_NODE_ID or pass --node)', next: 'Run from inside a node, or pass --node <id>.' });
|
|
274
271
|
const kind = input['kind'];
|
|
@@ -300,7 +297,7 @@ async function resolveLifecycleNode(input, pane) {
|
|
|
300
297
|
if (id === undefined || id === '')
|
|
301
298
|
id = nodeInPane(pane);
|
|
302
299
|
if (id === undefined || id === '')
|
|
303
|
-
id =
|
|
300
|
+
id = envNodeId();
|
|
304
301
|
if (id === undefined || id === '')
|
|
305
302
|
throw new InputError({ error: 'no_node', message: 'no node (set CRTR_NODE_ID, pass --node, or run from the agent\'s pane)', next: 'Run from inside a node, pass --node <id>, or --pane <pane>.' });
|
|
306
303
|
const exists = await getNodeOrNull(id);
|
|
@@ -308,13 +305,11 @@ async function resolveLifecycleNode(input, pane) {
|
|
|
308
305
|
throw new InputError({ error: 'not_found', message: `no node: ${id}`, next: 'List nodes with `crtr node inspect list`.' });
|
|
309
306
|
return id;
|
|
310
307
|
}
|
|
311
|
-
// ---------------------------------------------------------------------------
|
|
312
308
|
// node lifecycle demote — flip a node to TERMINAL in place (the friendly half
|
|
313
309
|
// of the promote/demote pair; bound to Alt+C → d, and → D with --detach). It
|
|
314
310
|
// stays focused and running but now owes a final up the spine. `node config
|
|
315
311
|
// --lifecycle` remains the orthogonal low-level command (it also does resident).
|
|
316
312
|
// See vision F5.
|
|
317
|
-
// ---------------------------------------------------------------------------
|
|
318
313
|
const nodeDemote = defineLeaf({
|
|
319
314
|
name: 'demote',
|
|
320
315
|
description: 'demote a node to terminal in place; it stays focused and running but now owes a final; --detach also closes its viewer (broker keeps running off-screen)',
|
|
@@ -352,9 +347,7 @@ const nodeDemote = defineLeaf({
|
|
|
352
347
|
},
|
|
353
348
|
render: (r) => `Demoted ${r['node_id']} — lifecycle now terminal (in place)${r['detached'] === true ? ', viewer closed (broker still running off-screen)' : ''}.`,
|
|
354
349
|
});
|
|
355
|
-
// ---------------------------------------------------------------------------
|
|
356
350
|
// node lifecycle — recycle, close, or demote a node
|
|
357
|
-
// ---------------------------------------------------------------------------
|
|
358
351
|
export const nodeLifecycle = defineBranch({
|
|
359
352
|
name: 'lifecycle',
|
|
360
353
|
description: 'lifecycle actions — recycle, close, demote, or revive a node',
|
|
@@ -362,12 +355,11 @@ export const nodeLifecycle = defineBranch({
|
|
|
362
355
|
help: {
|
|
363
356
|
name: 'node lifecycle',
|
|
364
357
|
summary: 'end, transition, or revive a node — recycle the pane, close + cascade-cancel a subtree, demote to terminal in place, or revive a dormant node',
|
|
358
|
+
model: 'Lifecycle actions preserve or replace an existing node identity. Finishing is permanent, closing is revivable, demotion changes the completion obligation in place, and revival relaunches a dormant broker. Teardown cascades only through descendants exclusively managed by the affected subtree.',
|
|
365
359
|
},
|
|
366
360
|
children: [nodeRecycle, nodeClose, nodeDemote, nodeReviveLeaf],
|
|
367
361
|
});
|
|
368
|
-
// ---------------------------------------------------------------------------
|
|
369
362
|
// node yield — refresh: discard context, revive fresh in the same mode against roadmap or goal
|
|
370
|
-
// ---------------------------------------------------------------------------
|
|
371
363
|
export const nodeYield = defineLeaf({
|
|
372
364
|
name: 'yield',
|
|
373
365
|
description: 'refresh your context, same mode, against your roadmap or goal',
|
|
@@ -395,7 +387,7 @@ export const nodeYield = defineLeaf({
|
|
|
395
387
|
effects: ['The stophook shuts the process down on next stop and the daemon revives it fresh.', '--kind and/or --model durably reshape the node (kind respecialization, model-tier pin) before the refresh-revive; --promote additionally flips mode→orchestrator and seeds a roadmap scaffold — mode is otherwise left exactly as it was.'],
|
|
396
388
|
},
|
|
397
389
|
run: async (input) => {
|
|
398
|
-
const id =
|
|
390
|
+
const id = envNodeId();
|
|
399
391
|
if (id === undefined || id === '')
|
|
400
392
|
throw new InputError({ error: 'no_node', message: 'no node to yield (CRTR_NODE_ID unset)', next: 'Run from inside a node.' });
|
|
401
393
|
const kind = input['kind'];
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// `crtr node message` — immediate inbox delivery and typed-output requests.
|
|
2
|
+
import { envNodeId } from '../../shared/env.js';
|
|
2
3
|
import { defineBranch, defineLeaf } from '../../core/command.js';
|
|
3
4
|
import { InputError } from '../../core/io.js';
|
|
4
5
|
import { OUTPUT_SCHEMA_CONSTRAINTS, OUTPUT_SCHEMA_TRANSPORT, parseOutputSchemaValue } from '../../core/runtime/structured-output.js';
|
|
@@ -22,7 +23,7 @@ async function resolveMsgTarget(input) {
|
|
|
22
23
|
});
|
|
23
24
|
}
|
|
24
25
|
if (self) {
|
|
25
|
-
const id =
|
|
26
|
+
const id = envNodeId();
|
|
26
27
|
if (id === undefined || id === '') {
|
|
27
28
|
throw new InputError({ error: 'no_node', message: 'no node to target with --self (CRTR_NODE_ID unset)', next: 'Run from inside a node, or pass --to <node-id>.' });
|
|
28
29
|
}
|
|
@@ -55,7 +56,7 @@ function messageRequestParams() {
|
|
|
55
56
|
{ kind: 'stdin', name: 'body', required: false, constraint: 'Visible message body. The schema alone is a complete request.' },
|
|
56
57
|
{ kind: 'flag', name: 'to', type: 'string', required: false, constraint: 'Target an existing node by id. Exactly one of --to or --self is required.' },
|
|
57
58
|
{ kind: 'flag', name: 'self', type: 'bool', required: false, constraint: 'Target the calling node. Exactly one of --to or --self is required.' },
|
|
58
|
-
{ kind: 'flag', name: 'tier', type: 'enum', choices: ['critical', 'urgent', 'normal'], required: false, default: 'normal', constraint: 'Delivery urgency.
|
|
59
|
+
{ kind: 'flag', name: 'tier', type: 'enum', choices: ['critical', 'urgent', 'normal'], required: false, default: 'normal', constraint: 'Delivery urgency. Every accepted tier may revive a dormant target, because the request must be answered; deferred is rejected for that reason.' },
|
|
59
60
|
{ kind: 'flag', name: 'output-schema', type: 'string', required: true, constraint: `JSON Schema the result must satisfy. ${OUTPUT_SCHEMA_TRANSPORT} The target answers through a constrained submit tool, then keeps working. ${OUTPUT_SCHEMA_CONSTRAINTS}` },
|
|
60
61
|
{ kind: 'flag', name: 'situational-context', type: 'string', required: false, constraint: 'Non-empty hidden ambient context delivered beside the message, or alone.' },
|
|
61
62
|
{ kind: 'flag', name: 'reopen', type: 'bool', required: false, hidden: true, constraint: 'Clear a finalized target latch before delivery or fresh revive.' },
|
|
@@ -80,7 +81,7 @@ async function runMessageEngine(input) {
|
|
|
80
81
|
if (outputSchema !== null && tierRaw === 'deferred') {
|
|
81
82
|
throw new InputError({ error: 'output_schema_deferred_tier', message: '--output-schema cannot combine with --tier deferred because the target must answer', field: 'tier', next: 'Use normal, urgent, or critical tier, or drop --output-schema.' });
|
|
82
83
|
}
|
|
83
|
-
const senderFrom =
|
|
84
|
+
const senderFrom = envNodeId();
|
|
84
85
|
const client = cliClient();
|
|
85
86
|
if (!hasBody && !hasSituational && outputSchema === null) {
|
|
86
87
|
throw new InputError({ error: 'empty_body', message: 'a message body is required unless --output-schema or --situational-context is supplied', field: 'body', next: 'Pass the message on stdin, or supply one of the documented alternatives.' });
|
|
@@ -104,7 +105,7 @@ async function runMessageEngine(input) {
|
|
|
104
105
|
const nodeMessageSend = defineLeaf({
|
|
105
106
|
name: 'send',
|
|
106
107
|
description: 'deliver an inbox message to an existing node immediately',
|
|
107
|
-
whenToUse: '
|
|
108
|
+
whenToUse: 'a node that already exists should have information or new direction now — steering a worker mid-task, handing over a finding it needs, correcting a wrong turn, or waking a dormant node with fresh work. The target reads it and decides what to do with it. Use `node message request` instead when you need an answer back in a shape you specify, and `node subscription add` when the target should keep receiving this node’s pushes rather than this one delivery',
|
|
108
109
|
help: {
|
|
109
110
|
name: 'node message send',
|
|
110
111
|
summary: 'deliver an inbox message to an existing node immediately',
|
|
@@ -119,7 +120,7 @@ const nodeMessageSend = defineLeaf({
|
|
|
119
120
|
const nodeMessageRequest = defineLeaf({
|
|
120
121
|
name: 'request',
|
|
121
122
|
description: 'deliver an immediate typed-output request to an existing node',
|
|
122
|
-
whenToUse: '
|
|
123
|
+
whenToUse: 'a node that already exists must hand back one answer in a shape you fix — a choice among options, a structured extraction, a verdict your own logic will branch on — or must be held to answering at all before it goes quiet. Use `node message send` instead when prose in the target’s own judgment is enough, and `node new --output-schema` when no node holds the context yet and the work needs a fresh agent',
|
|
123
124
|
help: {
|
|
124
125
|
name: 'node message request',
|
|
125
126
|
summary: 'deliver an immediate typed-output request to an existing node',
|
|
@@ -138,6 +139,10 @@ export const nodeMessage = defineBranch({
|
|
|
138
139
|
name: 'message',
|
|
139
140
|
description: 'deliver immediate inbox work to an existing node',
|
|
140
141
|
whenToUse: 'you need one immediate delivery: send ordinary information, or request one schema-constrained result',
|
|
141
|
-
help: {
|
|
142
|
+
help: {
|
|
143
|
+
name: 'node message',
|
|
144
|
+
summary: 'deliver one immediate inbox entry to an existing node',
|
|
145
|
+
model: 'Both children append one inbox entry to a node that already exists, targeted by id or --self, and may revive it if it is dormant. They differ in what the delivery obligates. An ordinary message obligates nothing: the target reads it and acts however it judges best. A request installs a one-off submit schema and holds the target awake and owing until it answers; the answer is validated against the schema, written to the target’s result file, and pushed as an update report to the TARGET’S subscribers, so subscribe to it first if the answer has to reach you. Neither child creates that standing relationship — a durable delivery edge is `node subscription`, and work that needs a fresh agent is `node new`.',
|
|
146
|
+
},
|
|
142
147
|
children: [nodeMessageSend, nodeMessageRequest],
|
|
143
148
|
});
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// `crtr node subscription` — push-delivery edge controls.
|
|
2
|
+
import { envNodeId } from '../../shared/env.js';
|
|
2
3
|
import { defineBranch, defineLeaf } from '../../core/command.js';
|
|
3
4
|
import { InputError } from '../../core/io.js';
|
|
4
5
|
import { cliClient, rethrowAsCliError } from '../api-client.js';
|
|
5
6
|
function resolveSubscriber(input) {
|
|
6
|
-
const sub = input['subscriber'] ??
|
|
7
|
+
const sub = input['subscriber'] ?? envNodeId();
|
|
7
8
|
if (sub === undefined || sub === '') {
|
|
8
9
|
throw new InputError({ error: 'no_subscriber', message: 'no subscriber (set CRTR_NODE_ID or pass --subscriber)', field: 'subscriber', next: 'Run from inside a node, or pass --subscriber <id>.' });
|
|
9
10
|
}
|
|
@@ -68,6 +69,10 @@ export const nodeSubscription = defineBranch({
|
|
|
68
69
|
name: 'subscription',
|
|
69
70
|
description: 'manage push-delivery edges between nodes',
|
|
70
71
|
whenToUse: 'you need an ongoing active or passive subscriber-to-publisher delivery edge that spawn did not create, or need to remove one',
|
|
71
|
-
help: {
|
|
72
|
+
help: {
|
|
73
|
+
name: 'node subscription',
|
|
74
|
+
summary: 'add or remove subscriber-to-publisher push-delivery edges',
|
|
75
|
+
model: 'Subscriptions point from a subscriber to a publisher and control future push delivery. Active edges wake on each push; passive edges accumulate pushes for the subscriber’s next turn. Removing either edge stops subsequent delivery without changing messages already received.',
|
|
76
|
+
},
|
|
72
77
|
children: [nodeSubscribe, nodeUnsubscribe],
|
|
73
78
|
});
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
// `crtr node wait` — durable controller and deadline waits.
|
|
2
|
+
import { envNodeId, envProfileId } from '../../shared/env.js';
|
|
2
3
|
import { defineBranch, defineLeaf } from '../../core/command.js';
|
|
3
4
|
import { InputError } from '../../core/io.js';
|
|
4
5
|
import { parseWhen } from '../../core/wake.js';
|
|
5
6
|
import { cliClient, getNodeOrNull, rethrowAsCliError } from '../api-client.js';
|
|
6
7
|
import { shellQuote } from '../surface/node/placement.js';
|
|
7
8
|
function armerId() {
|
|
8
|
-
const id =
|
|
9
|
+
const id = envNodeId();
|
|
9
10
|
if (id === undefined || id === '') {
|
|
10
11
|
throw new InputError({ error: 'no_node', message: 'no node to anchor a deadline cron (CRTR_NODE_ID unset)', next: 'Run from inside a node.' });
|
|
11
12
|
}
|
|
@@ -84,7 +85,7 @@ const nodeWaitDeadline = defineLeaf({
|
|
|
84
85
|
const parsed = parseWhen(until, parseOpts(now, tz));
|
|
85
86
|
if ('error' in parsed)
|
|
86
87
|
throwTimeError(parsed.error);
|
|
87
|
-
const profile =
|
|
88
|
+
const profile = envProfileId();
|
|
88
89
|
// One deadline per node: the arm seam REPLACES this node's pending
|
|
89
90
|
// cancel-on-wake cron rather than stacking a second one (see armCron in
|
|
90
91
|
// core/canvas/crons.ts, where the invariant is enforced for every caller).
|
|
@@ -129,7 +130,7 @@ const nodeWait = defineLeaf({
|
|
|
129
130
|
effects: ['Durably records the controller on this node. The stop guard permits dormancy only while that controller remains active or idle; its next inbox delivery clears the record before the delivery wakes this node.'],
|
|
130
131
|
},
|
|
131
132
|
run: async (input) => {
|
|
132
|
-
const nodeId =
|
|
133
|
+
const nodeId = envNodeId();
|
|
133
134
|
if (nodeId === undefined || nodeId === '')
|
|
134
135
|
throw new InputError({ error: 'no_node', message: 'no node to wait (CRTR_NODE_ID unset)', next: 'Run from inside the terminal node that is blocked.' });
|
|
135
136
|
const node = await getNodeOrNull(nodeId);
|
|
@@ -153,6 +154,10 @@ export const nodeWaitBranch = defineBranch({
|
|
|
153
154
|
name: 'wait',
|
|
154
155
|
description: 'declare a durable controller or deadline wait',
|
|
155
156
|
whenToUse: 'a terminal node must dorm for one named controller, or race its inbox against a self-scheduled deadline',
|
|
156
|
-
help: {
|
|
157
|
+
help: {
|
|
158
|
+
name: 'node wait',
|
|
159
|
+
summary: 'declare durable wait state; choose the event that settles it',
|
|
160
|
+
model: 'Both waits belong to the calling terminal node and settle on one future event. A controller wait records an existing node as the wake source; a deadline wait arms an urgent one-shot cron that races any earlier inbox delivery and is canceled when that delivery wins.',
|
|
161
|
+
},
|
|
157
162
|
children: [nodeWait, nodeWaitDeadline],
|
|
158
163
|
});
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
// and the on-disk existence filter is a local fs read (neither touches canvas
|
|
18
18
|
// state). The /context popup (src/pi-extensions/canvas-context.ts) shells this
|
|
19
19
|
// leaf inside a tmux display-popup. Piped / non-TTY it prints the roster.
|
|
20
|
+
import { envNodeId } from '../shared/env.js';
|
|
20
21
|
import { spawnSync } from 'node:child_process';
|
|
21
22
|
import { existsSync, mkdirSync, mkdtempSync, rmSync, symlinkSync } from 'node:fs';
|
|
22
23
|
import { tmpdir } from 'node:os';
|
|
@@ -106,7 +107,7 @@ export const nodeContextLeaf = defineLeaf({
|
|
|
106
107
|
],
|
|
107
108
|
},
|
|
108
109
|
run: async (input) => {
|
|
109
|
-
const selfId = input['node']?.trim() ||
|
|
110
|
+
const selfId = input['node']?.trim() || envNodeId();
|
|
110
111
|
if (selfId === undefined || selfId === '') {
|
|
111
112
|
throw new InputError({
|
|
112
113
|
error: 'no_node',
|
|
@@ -52,9 +52,7 @@ export function isNowEligibleFault(fault) {
|
|
|
52
52
|
return true;
|
|
53
53
|
return fault.retry.by === 'daemon';
|
|
54
54
|
}
|
|
55
|
-
// ---------------------------------------------------------------------------
|
|
56
55
|
// Local, db-free helpers (inlined so the leaf never imports the canvas barrel)
|
|
57
|
-
// ---------------------------------------------------------------------------
|
|
58
56
|
/** Inlined from `runtime/busy.ts` (which reaches the canvas barrel via `jobDir`):
|
|
59
57
|
* is the node mid-turn right now? `<jobDir>/busy` exists for the span pi is
|
|
60
58
|
* inside a run. `jobDir` here is the pure path helper from paths.js. */
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
// `node new --worktree <base>`; this branch holds the single close
|
|
3
3
|
// verb, symmetric with birth, so a git worktree's whole lifecycle sits under
|
|
4
4
|
// `node`.
|
|
5
|
+
import { envNodeId } from '../shared/env.js';
|
|
5
6
|
import { defineBranch, defineLeaf } from '../core/command.js';
|
|
6
7
|
import { InputError } from '../core/io.js';
|
|
7
8
|
import { ApiError } from '../api/index.js';
|
|
8
9
|
import { cliClient } from './api-client.js';
|
|
9
10
|
function requireCallerNode() {
|
|
10
|
-
const id =
|
|
11
|
+
const id = envNodeId();
|
|
11
12
|
if (id === undefined || id.trim() === '') {
|
|
12
13
|
throw new InputError({
|
|
13
14
|
error: 'no_node_context',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ActionPresentation, ActionRequest, ActionOutcome } from
|
|
1
|
+
import type { ActionPresentation, ActionRequest, ActionOutcome } from './model.js';
|
|
2
2
|
/** How an action reads before it runs — and whether it needs confirming. */
|
|
3
3
|
export declare function presentAction(request: ActionRequest): ActionPresentation;
|
|
4
4
|
/** Actions available for a request's subject right now, in offer order. */
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// Mutations for `crtr pkg browse`. Each action delegates to the same leaf the
|
|
2
2
|
// CLI runs, so the browser and `crtr pkg …` can never drift.
|
|
3
|
-
import { marketAdd, marketRemove, marketUpdate } from
|
|
4
|
-
import { pluginDisable, pluginEnable, pluginInstall, pluginRemove, pluginUpdate, } from
|
|
5
|
-
import { listAllMarketplaces } from
|
|
6
|
-
import { projectScopeRoot } from
|
|
3
|
+
import { marketAdd, marketRemove, marketUpdate } from '../market-manage.js';
|
|
4
|
+
import { pluginDisable, pluginEnable, pluginInstall, pluginRemove, pluginUpdate, } from '../plugin-manage.js';
|
|
5
|
+
import { listAllMarketplaces } from '../../../core/resolver.js';
|
|
6
|
+
import { projectScopeRoot } from '../../../core/scope.js';
|
|
7
7
|
function pluginName(request) {
|
|
8
8
|
return request.entry?.name ?? "plugin";
|
|
9
9
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Catalog, type PluginCapability, type PluginEntry } from
|
|
1
|
+
import { type Catalog, type PluginCapability, type PluginEntry } from './model.js';
|
|
2
2
|
/** Every rail source with its rows: the installed library first, then each
|
|
3
3
|
* registered marketplace. Called on open and after any action that could
|
|
4
4
|
* change install state. Must never throw for a broken marketplace — record it
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
// Catalog reads for `crtr pkg browse`. Everything here is read-only; mutations
|
|
2
2
|
// live in actions.ts.
|
|
3
|
-
import { statSync } from
|
|
4
|
-
import { isAbsolute, join } from
|
|
5
|
-
import { SUBTREE_NAMES, coreCommandPaths } from
|
|
6
|
-
import { discoverPluginCommandCandidates, validateEffectiveCommandPlugins, validatePluginCommands } from
|
|
7
|
-
import { qualifiedTopLevelCommandName } from
|
|
8
|
-
import { listDirs, pathExists, walkFiles } from
|
|
9
|
-
import { currentSha, gitSync } from
|
|
10
|
-
import { listPluginMemoryDocs } from
|
|
11
|
-
import { memoryExtensionEffectiveCatalog, projectEffectiveMemoryExtensions } from
|
|
12
|
-
import { readMarketplaceManifest, readPluginManifest } from
|
|
13
|
-
import { readConfig } from
|
|
14
|
-
import { parseSubstrateDoc } from
|
|
15
|
-
import { projectScopeRoot, userScopeRoot } from
|
|
16
|
-
import { isGitUrl } from
|
|
17
|
-
import { INSTALLED_SOURCE_ID, marketplaceSourceId, } from
|
|
3
|
+
import { statSync } from 'node:fs';
|
|
4
|
+
import { isAbsolute, join } from 'node:path';
|
|
5
|
+
import { SUBTREE_NAMES, coreCommandPaths } from '../../../build-root.js';
|
|
6
|
+
import { discoverPluginCommandCandidates, validateEffectiveCommandPlugins, validatePluginCommands } from '../../../core/command-plugins/discovery.js';
|
|
7
|
+
import { qualifiedTopLevelCommandName } from '../../../core/command-manifests/registry.js';
|
|
8
|
+
import { listDirs, pathExists, walkFiles } from '../../../core/fs-utils.js';
|
|
9
|
+
import { currentSha, gitSync } from '../../../core/git.js';
|
|
10
|
+
import { listPluginMemoryDocs } from '../../../core/memory-resolver.js';
|
|
11
|
+
import { memoryExtensionEffectiveCatalog, projectEffectiveMemoryExtensions } from '../../../core/memory/extensions.js';
|
|
12
|
+
import { readMarketplaceManifest, readPluginManifest } from '../../../core/manifest.js';
|
|
13
|
+
import { readConfig } from '../../../core/config.js';
|
|
14
|
+
import { parseSubstrateDoc } from '../../../core/substrate/schema.js';
|
|
15
|
+
import { projectScopeRoot, userScopeRoot } from '../../../core/scope.js';
|
|
16
|
+
import { isGitUrl } from '../shared.js';
|
|
17
|
+
import { INSTALLED_SOURCE_ID, marketplaceSourceId, } from './model.js';
|
|
18
18
|
function parseSemver(version) {
|
|
19
19
|
const match = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z.-]+)?$/.exec(version);
|
|
20
20
|
return match === null
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { CommandNode, PluginCapability } from
|
|
1
|
+
import type { CommandNode, PluginCapability } from './model.js';
|
|
2
2
|
/** Every line of one command's contract view, wrapped to `width`. */
|
|
3
3
|
export declare function renderCommandView(node: CommandNode, capability: PluginCapability, width: number): string[];
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
//
|
|
4
4
|
// Pure rendering. It returns styled lines already wrapped to `width`; the
|
|
5
5
|
// dossier owns scrolling and never truncates what comes back.
|
|
6
|
-
import { visibleWidth, wrapTextWithAnsi } from
|
|
7
|
-
import { theme, wrapText } from
|
|
8
|
-
import { commandLabel } from
|
|
6
|
+
import { visibleWidth, wrapTextWithAnsi } from '@earendil-works/pi-tui';
|
|
7
|
+
import { theme, wrapText } from '../../../core/tui/panel.js';
|
|
8
|
+
import { commandLabel } from './model.js';
|
|
9
9
|
/** Every line of one command's contract view, wrapped to `width`. */
|
|
10
10
|
export function renderCommandView(node, capability, width) {
|
|
11
11
|
const out = [];
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
// `enter` deeper — a whole memory doc or a whole command contract. The overview
|
|
5
5
|
// is not a teaser: every command node and every memory doc it lists is a real
|
|
6
6
|
// row a cursor can land on and open, and nothing is elided with `+N more`.
|
|
7
|
-
import { truncateToWidth, visibleWidth } from
|
|
8
|
-
import { padAnsi, theme, wrapText } from
|
|
9
|
-
import { renderCommandView } from
|
|
10
|
-
import { renderDocView } from
|
|
11
|
-
import { commandLabel, displayVersion, plural } from
|
|
7
|
+
import { truncateToWidth, visibleWidth } from '@earendil-works/pi-tui';
|
|
8
|
+
import { padAnsi, theme, wrapText } from '../../../core/tui/panel.js';
|
|
9
|
+
import { renderCommandView } from './command-view.js';
|
|
10
|
+
import { renderDocView } from './doc-view.js';
|
|
11
|
+
import { commandLabel, displayVersion, plural } from './model.js';
|
|
12
12
|
/** One labelled row and its explanation. Inline while both fit; otherwise the
|
|
13
13
|
* explanation wraps underneath, hanging under the label rather than resetting
|
|
14
14
|
* to the left margin. Nothing is ever truncated to make it fit. */
|
|
@@ -90,7 +90,7 @@ export class PkgDetailPanel {
|
|
|
90
90
|
get viewing() {
|
|
91
91
|
return this.view.kind !== "overview";
|
|
92
92
|
}
|
|
93
|
-
//
|
|
93
|
+
// navigation
|
|
94
94
|
/** `j`/`k`: move the cursor between selectable rows on the overview, scroll a
|
|
95
95
|
* line inside an opened view — and scroll the overview too when the plugin
|
|
96
96
|
* has nothing selectable to move between. */
|
|
@@ -170,7 +170,7 @@ export class PkgDetailPanel {
|
|
|
170
170
|
this.collapsed.add(key);
|
|
171
171
|
return true;
|
|
172
172
|
}
|
|
173
|
-
//
|
|
173
|
+
// the selectable model
|
|
174
174
|
/** Command rows in display order, skipping the children of folded branches. */
|
|
175
175
|
commandRows() {
|
|
176
176
|
const rows = [];
|
|
@@ -195,7 +195,7 @@ export class PkgDetailPanel {
|
|
|
195
195
|
...capability.docs.map((doc) => ({ kind: "doc", doc })),
|
|
196
196
|
];
|
|
197
197
|
}
|
|
198
|
-
//
|
|
198
|
+
// rendering
|
|
199
199
|
render(width, height, focused) {
|
|
200
200
|
const lines = this.lines(width, focused);
|
|
201
201
|
this.lastLines = lines.length;
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
// Pure rendering. It receives a doc already read from disk and returns styled
|
|
5
5
|
// lines already wrapped to `width`; the dossier owns scrolling and never
|
|
6
6
|
// truncates what comes back.
|
|
7
|
-
import { getMarkdownTheme } from
|
|
8
|
-
import { Markdown, visibleWidth, wrapTextWithAnsi } from
|
|
9
|
-
import { theme, wrapText } from
|
|
7
|
+
import { getMarkdownTheme } from '@earendil-works/pi-coding-agent';
|
|
8
|
+
import { Markdown, visibleWidth, wrapTextWithAnsi } from '@earendil-works/pi-tui';
|
|
9
|
+
import { theme, wrapText } from '../../../core/tui/panel.js';
|
|
10
10
|
/** Every line of one memory doc's reader view, wrapped to `width`. */
|
|
11
11
|
export function renderDocView(doc, width) {
|
|
12
12
|
const out = [];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CatalogSource, PluginEntry } from
|
|
1
|
+
import type { CatalogSource, PluginEntry } from './model.js';
|
|
2
2
|
/** The middle column of the plugin browser. It owns filtering and row position;
|
|
3
3
|
* the shell owns horizontal navigation and actions. */
|
|
4
4
|
export declare class PkgListPanel {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { matchesKey, truncateToWidth, visibleWidth } from
|
|
2
|
-
import { padAnsi, theme, visibleRange } from
|
|
3
|
-
import { displayVersion, plural } from
|
|
1
|
+
import { matchesKey, truncateToWidth, visibleWidth } from '@earendil-works/pi-tui';
|
|
2
|
+
import { padAnsi, theme, visibleRange } from '../../../core/tui/panel.js';
|
|
3
|
+
import { displayVersion, plural } from './model.js';
|
|
4
4
|
/** The middle column of the plugin browser. It owns filtering and row position;
|
|
5
5
|
* the shell owns horizontal navigation and actions. */
|
|
6
6
|
export class PkgListPanel {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Field, InputParam } from
|
|
2
|
-
import type { SurfaceEntry } from
|
|
3
|
-
import type { MemoryExtensionScalar, OwnerRef, Scope } from
|
|
1
|
+
import type { Field, InputParam } from '../../../core/help.js';
|
|
2
|
+
import type { SurfaceEntry } from '../../../core/substrate/schema.js';
|
|
3
|
+
import type { MemoryExtensionScalar, OwnerRef, Scope } from '../../../types.js';
|
|
4
4
|
/** The scopes that can hold a marketplace, and that a plugin can be installed
|
|
5
5
|
* into. Narrower than `Scope`: `builtin` names plugins that ship with crtr, and
|
|
6
6
|
* `listAllMarketplaces()` never yields it, so a builtin marketplace or a
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type Component, type Focusable, type TUI } from
|
|
2
|
-
import { type BindingId, type BindingResolution } from
|
|
1
|
+
import { type Component, type Focusable, type TUI } from '@earendil-works/pi-tui';
|
|
2
|
+
import { type BindingId, type BindingResolution } from '../../../core/keybindings/index.js';
|
|
3
3
|
/** Full-screen plugin browser. The data and mutation boundaries stay in the
|
|
4
4
|
* catalog/actions collaborators, leaving this class responsible for movement,
|
|
5
5
|
* disclosure, and the rendered page grammar. */
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// The `crtr pkg browse` page: a grouped source rail, plugin list, and dossier.
|
|
2
|
-
import { Input, matchesKey, truncateToWidth, visibleWidth, } from
|
|
3
|
-
import { formatGesture, matchesPiTuiInput, } from
|
|
4
|
-
import { runTuiPage } from
|
|
5
|
-
import { PAGE_CHROME_ROWS, columns, framed, padAnsi, pageFrame, theme, visibleRange, } from
|
|
6
|
-
import { availableActions, presentAction, runAction } from
|
|
7
|
-
import { loadCapability, loadCatalog } from
|
|
8
|
-
import { PkgDetailPanel } from
|
|
9
|
-
import { PkgListPanel } from
|
|
10
|
-
import { INSTALLED_SOURCE_ID, marketplaceSourceId, plural, } from
|
|
2
|
+
import { Input, matchesKey, truncateToWidth, visibleWidth, } from '@earendil-works/pi-tui';
|
|
3
|
+
import { formatGesture, matchesPiTuiInput, } from '../../../core/keybindings/index.js';
|
|
4
|
+
import { runTuiPage } from '../../../core/tui/page-host.js';
|
|
5
|
+
import { PAGE_CHROME_ROWS, columns, framed, padAnsi, pageFrame, theme, visibleRange, } from '../../../core/tui/panel.js';
|
|
6
|
+
import { availableActions, presentAction, runAction } from './actions.js';
|
|
7
|
+
import { loadCapability, loadCatalog } from './catalog.js';
|
|
8
|
+
import { PkgDetailPanel } from './detail-panel.js';
|
|
9
|
+
import { PkgListPanel } from './list-panel.js';
|
|
10
|
+
import { INSTALLED_SOURCE_ID, marketplaceSourceId, plural, } from './model.js';
|
|
11
11
|
const RAIL_WIDTH = 22;
|
|
12
12
|
const LIST_WIDTH = 34;
|
|
13
13
|
const RAIL_MIN_TOTAL_WIDTH = 84;
|
|
@@ -96,7 +96,7 @@ export class PkgBrowseShell {
|
|
|
96
96
|
if (this.busy !== undefined)
|
|
97
97
|
clearInterval(this.busy.timer);
|
|
98
98
|
}
|
|
99
|
-
//
|
|
99
|
+
// model selection
|
|
100
100
|
sources() {
|
|
101
101
|
if (this.catalog.sources.length > 0)
|
|
102
102
|
return this.catalog.sources;
|
|
@@ -171,7 +171,7 @@ export class PkgBrowseShell {
|
|
|
171
171
|
clearActionNotice() {
|
|
172
172
|
this.notice = undefined;
|
|
173
173
|
}
|
|
174
|
-
//
|
|
174
|
+
// input
|
|
175
175
|
/** A live filter, an open modal, or a running action holds every key — the
|
|
176
176
|
* one predicate both `handleInput` and the footer consult, so the footer can
|
|
177
177
|
* never advertise a key the filter is swallowing. */
|
|
@@ -279,7 +279,7 @@ export class PkgBrowseShell {
|
|
|
279
279
|
this.syncSource();
|
|
280
280
|
}
|
|
281
281
|
}
|
|
282
|
-
//
|
|
282
|
+
// actions and modals
|
|
283
283
|
/** The focused rail row as an action subject. Carries the marketplace's scope
|
|
284
284
|
* as well as its name: two marketplaces can share a name across the user and
|
|
285
285
|
* project scopes, and without the scope `availableActions` cannot tell which
|
|
@@ -424,7 +424,7 @@ export class PkgBrowseShell {
|
|
|
424
424
|
}
|
|
425
425
|
this.tui.requestRender();
|
|
426
426
|
}
|
|
427
|
-
//
|
|
427
|
+
// rendering
|
|
428
428
|
/** The source rail. It scrolls like the list does: marketplace count is user
|
|
429
429
|
* controlled, so a fixed slice would let the selection sit below the last
|
|
430
430
|
* drawn row, moving invisibly while the badge the user is aiming for never
|