@north-light/crouter 0.3.232 → 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-memory/internal/memory-loading.md +4 -3
- 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.d.ts +1 -1
- package/dist/commands/memory/shared.js +7 -10
- 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.d.ts +1 -0
- package/dist/core/substrate/__tests__/surface-match-pre-command.test.js +92 -0
- package/dist/core/substrate/frontmatter-validation.js +1 -1
- package/dist/core/substrate/injected-store.d.ts +6 -0
- package/dist/core/substrate/injected-store.js +24 -0
- package/dist/core/substrate/on-read.d.ts +17 -1
- package/dist/core/substrate/on-read.js +36 -2
- package/dist/core/substrate/render.js +0 -12
- package/dist/core/substrate/schema.d.ts +3 -3
- package/dist/core/substrate/schema.js +4 -16
- package/dist/core/substrate/surface-match.d.ts +19 -0
- package/dist/core/substrate/surface-match.js +60 -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/__tests__/pre-command-gate.test.d.ts +1 -0
- package/dist/pi-extensions/__tests__/pre-command-gate.test.js +220 -0
- 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.d.ts +14 -0
- package/dist/pi-extensions/canvas-doc-substrate.js +77 -5
- 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
|
@@ -16,6 +16,7 @@ import { writeFileSync } from 'node:fs';
|
|
|
16
16
|
import { homedir } from 'node:os';
|
|
17
17
|
import { dirname, join } from 'node:path';
|
|
18
18
|
import { ensureDir, pathExists, readText, removePath } from '../fs-utils.js';
|
|
19
|
+
import { envNoExports } from '../../shared/env.js';
|
|
19
20
|
import { builtinExportPairs, legacyExportArtifacts } from './builtins.js';
|
|
20
21
|
const SKIP_SUBCOMMANDS = new Set([
|
|
21
22
|
'help',
|
|
@@ -73,11 +74,11 @@ function removeIfOurs(path, target, markerPrefix) {
|
|
|
73
74
|
}
|
|
74
75
|
/** Render and write every built-in export artifact to every present host, while
|
|
75
76
|
* pruning legacy generated artifacts that should no longer be surfaced.
|
|
76
|
-
* Best-effort:
|
|
77
|
-
*
|
|
77
|
+
* Best-effort: reports errors without breaking an unrelated `crtr` command.
|
|
78
|
+
* Kill switch: `CRTR_NO_EXPORTS=1`. */
|
|
78
79
|
export function pruneLegacyExports(argv = process.argv) {
|
|
79
80
|
try {
|
|
80
|
-
if (
|
|
81
|
+
if (envNoExports())
|
|
81
82
|
return;
|
|
82
83
|
if (shouldSkipAllForArgv(argv))
|
|
83
84
|
return;
|
|
@@ -90,10 +91,8 @@ export function pruneLegacyExports(argv = process.argv) {
|
|
|
90
91
|
}
|
|
91
92
|
}
|
|
92
93
|
catch (e) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
process.stderr.write(`crtr: exports prune error: ${msg}\n`);
|
|
96
|
-
}
|
|
94
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
95
|
+
process.stderr.write(`crtr: exports prune error: ${msg}\n`);
|
|
97
96
|
}
|
|
98
97
|
}
|
|
99
98
|
/** Write every built-in export artifact to every present host. Split from the
|
|
@@ -103,7 +102,7 @@ export function pruneLegacyExports(argv = process.argv) {
|
|
|
103
102
|
* for building the full command tree just to reach a no-op. */
|
|
104
103
|
export function provisionExports(root, argv = process.argv) {
|
|
105
104
|
try {
|
|
106
|
-
if (
|
|
105
|
+
if (envNoExports())
|
|
107
106
|
return;
|
|
108
107
|
if (shouldSkipAllForArgv(argv))
|
|
109
108
|
return;
|
|
@@ -119,9 +118,7 @@ export function provisionExports(root, argv = process.argv) {
|
|
|
119
118
|
}
|
|
120
119
|
}
|
|
121
120
|
catch (e) {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
process.stderr.write(`crtr: exports error: ${msg}\n`);
|
|
125
|
-
}
|
|
121
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
122
|
+
process.stderr.write(`crtr: exports error: ${msg}\n`);
|
|
126
123
|
}
|
|
127
124
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type PageCommentAnchor, type PageResponses, type PageSlot } from './page-schema.js';
|
|
2
2
|
export type PageAnswer = {
|
|
3
3
|
title: string;
|
|
4
4
|
subtitle?: string;
|
|
@@ -34,7 +34,7 @@ export type PageAnswerGroup = {
|
|
|
34
34
|
}[];
|
|
35
35
|
};
|
|
36
36
|
/** Stored responses predating the `whole` anchor's removal still carry it; answers keep rendering them. */
|
|
37
|
-
export type LegacyCommentAnchor =
|
|
37
|
+
export type LegacyCommentAnchor = PageCommentAnchor | {
|
|
38
38
|
kind: 'whole';
|
|
39
39
|
};
|
|
40
40
|
export type PageAnswerComment = {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { atomicWriteJson, atomicWriteText } from '../fs-utils.js';
|
|
2
|
+
export { atomicWriteJson, atomicWriteText };
|
|
1
3
|
/** The authored page source path, derived from the persisted dialect. */
|
|
2
4
|
export declare function pagePath(dir: string, dialect?: 'jsx' | 'html'): string;
|
|
3
5
|
/** The compiled module the Gateway evaluates for JSX pages. */
|
|
@@ -24,11 +26,6 @@ export declare function isResolved(dir: string): boolean;
|
|
|
24
26
|
export declare function isClaimed(dir: string): boolean;
|
|
25
27
|
/** Resolve and verify a ticket directory without a registry. */
|
|
26
28
|
export declare function requireTicket(dir: string): string;
|
|
27
|
-
/** Replace one file's contents in a single rename, so a concurrent reader —
|
|
28
|
-
* the tmux inbox watcher, or crtrd serving a ticket read — sees either the old
|
|
29
|
-
* bytes or the new ones and never a truncated file mid-write. */
|
|
30
|
-
export declare function atomicWriteText(path: string, contents: string): void;
|
|
31
|
-
export declare function atomicWriteJson(path: string, value: unknown): void;
|
|
32
29
|
/** Publish one immutable JSON record without replacing an existing winner. */
|
|
33
30
|
export declare function publishJsonExclusive(path: string, value: unknown): boolean;
|
|
34
31
|
export declare function clearProgress(dir: string): void;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { existsSync, linkSync, mkdirSync, readFileSync, realpathSync,
|
|
1
|
+
import { existsSync, linkSync, mkdirSync, readFileSync, realpathSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { dirname } from 'node:path';
|
|
3
|
+
import { atomicWriteJson, atomicWriteText } from '../fs-utils.js';
|
|
4
|
+
export { atomicWriteJson, atomicWriteText };
|
|
3
5
|
/** The authored page source path, derived from the persisted dialect. */
|
|
4
6
|
export function pagePath(dir, dialect = 'jsx') { return `${dir}/page.${dialect === 'jsx' ? 'tsx' : 'html'}`; }
|
|
5
7
|
/** The compiled module the Gateway evaluates for JSX pages. */
|
|
@@ -51,18 +53,6 @@ export function requireTicket(dir) {
|
|
|
51
53
|
}
|
|
52
54
|
return canonicalDir;
|
|
53
55
|
}
|
|
54
|
-
/** Replace one file's contents in a single rename, so a concurrent reader —
|
|
55
|
-
* the tmux inbox watcher, or crtrd serving a ticket read — sees either the old
|
|
56
|
-
* bytes or the new ones and never a truncated file mid-write. */
|
|
57
|
-
export function atomicWriteText(path, contents) {
|
|
58
|
-
const tmp = `${path}.${process.pid}.${Math.random().toString(16).slice(2)}.tmp`;
|
|
59
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
60
|
-
writeFileSync(tmp, contents, { mode: 0o600 });
|
|
61
|
-
renameSync(tmp, path);
|
|
62
|
-
}
|
|
63
|
-
export function atomicWriteJson(path, value) {
|
|
64
|
-
atomicWriteText(path, `${JSON.stringify(value, null, 2)}\n`);
|
|
65
|
-
}
|
|
66
56
|
/** Publish one immutable JSON record without replacing an existing winner. */
|
|
67
57
|
export function publishJsonExclusive(path, value) {
|
|
68
58
|
const tmp = `${path}.${process.pid}.${Math.random().toString(16).slice(2)}.tmp`;
|
|
@@ -2,14 +2,14 @@ import { z } from 'zod';
|
|
|
2
2
|
import { BUILTIN_PAGE_KINDS } from './page-catalog.js';
|
|
3
3
|
import type { ProductPageComponents } from '../../types.js';
|
|
4
4
|
export declare const PAGE_SLOT_ID_PATTERN: RegExp;
|
|
5
|
-
export declare const
|
|
5
|
+
export declare const pageCommentAnchorSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
6
6
|
kind: z.ZodLiteral<"option">;
|
|
7
7
|
optionId: z.ZodString;
|
|
8
8
|
}, z.core.$strict>, z.ZodObject<{
|
|
9
9
|
kind: z.ZodLiteral<"row">;
|
|
10
10
|
rowId: z.ZodString;
|
|
11
11
|
}, z.core.$strict>], "kind">;
|
|
12
|
-
export type
|
|
12
|
+
export type PageCommentAnchor = z.infer<typeof pageCommentAnchorSchema>;
|
|
13
13
|
export declare const commentSchema: z.ZodObject<{
|
|
14
14
|
id: z.ZodString;
|
|
15
15
|
anchor: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
@@ -17,11 +17,11 @@ function uniqueIds(items, ctx, label) {
|
|
|
17
17
|
// one of a question's options, or a table row. Feedback on rendered page content — including
|
|
18
18
|
// the question text itself — is a ticket-level feedback comment (feedback.ts), not part of
|
|
19
19
|
// any response.
|
|
20
|
-
export const
|
|
20
|
+
export const pageCommentAnchorSchema = z.discriminatedUnion('kind', [
|
|
21
21
|
z.object({ kind: z.literal('option'), optionId: itemIdSchema }).strict(),
|
|
22
22
|
z.object({ kind: z.literal('row'), rowId: itemIdSchema }).strict(),
|
|
23
23
|
]);
|
|
24
|
-
export const commentSchema = z.object({ id: z.string().min(1), anchor:
|
|
24
|
+
export const commentSchema = z.object({ id: z.string().min(1), anchor: pageCommentAnchorSchema, text: z.string() }).strict();
|
|
25
25
|
export const optionSchema = z.object({ id: itemIdSchema, label: z.string().min(1), description: z.string().optional(), recommended: z.boolean().optional() }).strict();
|
|
26
26
|
export const optionsConfigSchema = z.object({
|
|
27
27
|
label: z.string().optional(),
|
package/dist/core/human/root.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { realpathSync } from 'node:fs';
|
|
2
2
|
import { createHash } from 'node:crypto';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { nodeDir, nodesRoot } from '../canvas/paths.js';
|
|
4
|
+
import { activityPath, signalActivity, watchActivity } from '../activity-signal.js';
|
|
5
5
|
export function ticketsRoot() {
|
|
6
6
|
return nodesRoot();
|
|
7
7
|
}
|
|
@@ -17,29 +17,12 @@ export function ticketDir(ticketId) {
|
|
|
17
17
|
return nodeDir(ticketId);
|
|
18
18
|
}
|
|
19
19
|
export function inboxActivityPath() {
|
|
20
|
-
return
|
|
20
|
+
return activityPath('inbox-activity');
|
|
21
21
|
}
|
|
22
22
|
/** Signal one durable ticket mutation to every open inbox without watching every ticket directory. */
|
|
23
23
|
export function signalInboxActivity() {
|
|
24
|
-
|
|
25
|
-
mkdirSync(dirname(inboxActivityPath()), { recursive: true, mode: 0o700 });
|
|
26
|
-
writeFileSync(inboxActivityPath(), `${Date.now()}\n`, { mode: 0o600 });
|
|
27
|
-
}
|
|
28
|
-
catch {
|
|
29
|
-
// A later inbox scan is still authoritative.
|
|
30
|
-
}
|
|
24
|
+
signalActivity('inbox-activity');
|
|
31
25
|
}
|
|
32
26
|
export function watchInboxActivity(onChange) {
|
|
33
|
-
|
|
34
|
-
try {
|
|
35
|
-
mkdirSync(dirname(activityPath), { recursive: true, mode: 0o700 });
|
|
36
|
-
const watcher = watch(dirname(activityPath), (_event, filename) => {
|
|
37
|
-
if (String(filename) === basename(activityPath))
|
|
38
|
-
onChange();
|
|
39
|
-
});
|
|
40
|
-
return () => watcher.close();
|
|
41
|
-
}
|
|
42
|
-
catch {
|
|
43
|
-
return () => { };
|
|
44
|
-
}
|
|
27
|
+
return watchActivity('inbox-activity', onChange);
|
|
45
28
|
}
|
package/dist/core/human/scan.js
CHANGED
|
@@ -7,6 +7,10 @@ import { pageAwaitsResponse, pageOverviewActions } from './page-schema.js';
|
|
|
7
7
|
import { parsePage } from './page.js';
|
|
8
8
|
import { pageTicketState, readTicketResult } from './tickets.js';
|
|
9
9
|
import { ticketsRoot } from './root.js';
|
|
10
|
+
import { emitEvent } from '../events/emit.js';
|
|
11
|
+
function errorText(error) {
|
|
12
|
+
return error instanceof Error ? error.message : String(error);
|
|
13
|
+
}
|
|
10
14
|
function claimSummary(dir) {
|
|
11
15
|
const claim = readJsonOrNull(claimPath(dir));
|
|
12
16
|
if (claim === null || typeof claim.host !== 'string' || typeof claim.claimedAt !== 'string' || typeof claim.heartbeatAt !== 'string')
|
|
@@ -94,7 +98,14 @@ export function scanInbox() {
|
|
|
94
98
|
}
|
|
95
99
|
if (isResolved(dir))
|
|
96
100
|
continue;
|
|
97
|
-
|
|
101
|
+
let item;
|
|
102
|
+
try {
|
|
103
|
+
item = reviewSummary(dir, basename(dir)) ?? pageSummary(dir, basename(dir));
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
emitEvent({ level: 'warn', event: 'human.scan.ticket_unreadable', fields: { ticket_id: basename(dir), error: errorText(error) } });
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
98
109
|
if (item !== null && (item.kind !== 'page' || item.inbox))
|
|
99
110
|
items.push(item);
|
|
100
111
|
}
|
|
@@ -124,13 +135,19 @@ export function scanPageHistory(nodeId) {
|
|
|
124
135
|
catch {
|
|
125
136
|
continue;
|
|
126
137
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
138
|
+
try {
|
|
139
|
+
const summary = pageSummary(dir, basename(dir));
|
|
140
|
+
if (summary === null)
|
|
141
|
+
continue;
|
|
142
|
+
if (nodeId !== undefined && summary.source.nodeId !== nodeId)
|
|
143
|
+
continue;
|
|
144
|
+
const result = summary.state === 'resolved' ? readTicketResult(dir) : null;
|
|
145
|
+
items.push({ ...summary, ...(result?.kind === 'page' ? { answerDigest: result.summary.replace(/\s+/g, ' ').trim() } : {}) });
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
emitEvent({ level: 'warn', event: 'human.scan.ticket_unreadable', fields: { ticket_id: basename(dir), error: errorText(error) } });
|
|
131
149
|
continue;
|
|
132
|
-
|
|
133
|
-
items.push({ ...summary, ...(result?.kind === 'page' ? { answerDigest: result.summary.replace(/\s+/g, ' ').trim() } : {}) });
|
|
150
|
+
}
|
|
134
151
|
}
|
|
135
152
|
return items.sort((a, b) => Date.parse(a.emittedAt) - Date.parse(b.emittedAt) || a.id.localeCompare(b.id));
|
|
136
153
|
}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import type { ReviewDescriptor, TicketResult } from './types.js';
|
|
2
2
|
import type { ProductPageComponents } from '../../types.js';
|
|
3
3
|
import { type PageDelivery, type PageManifest, type PageResponses, type PageSource } from './page-schema.js';
|
|
4
|
-
/** Strict decoder for the only canonical final marker.
|
|
4
|
+
/** Strict decoder for the only canonical final marker. Only a missing file reads
|
|
5
|
+
* as absent — a corrupt (unparseable) response is a real anomaly and throws,
|
|
6
|
+
* since silently treating it as "no result yet" would mask data loss instead
|
|
7
|
+
* of surfacing it to whichever caller owns the failure boundary. */
|
|
5
8
|
export declare function readTicketResult(dir: string): TicketResult | null;
|
|
6
9
|
export interface SubmitPageOptions {
|
|
7
10
|
dir: string;
|
|
@@ -27,14 +27,20 @@ const pageResultSchema = z.object({ schema: z.literal('crtr.page-response/v1'),
|
|
|
27
27
|
const pageProgressSchema = z.object({ kind: z.literal('page'), responses: z.record(z.string(), slotResponseSchema), savedAt: iso }).strict();
|
|
28
28
|
const reviewResultSchema = z.object({ schema: z.literal('humanloop.review-response/v1'), kind: z.literal('review'), result: feedbackSchema, completedAt: iso }).strict();
|
|
29
29
|
const canceledResultSchema = z.object({ schema: z.literal('humanloop.cancel/v1'), kind: z.literal('canceled'), canceledAt: iso, reason: z.string().optional(), actor: z.string().optional(), disposition: z.enum(['canceled', 'dismissed']).optional() }).strict();
|
|
30
|
-
/** Strict decoder for the only canonical final marker.
|
|
30
|
+
/** Strict decoder for the only canonical final marker. Only a missing file reads
|
|
31
|
+
* as absent — a corrupt (unparseable) response is a real anomaly and throws,
|
|
32
|
+
* since silently treating it as "no result yet" would mask data loss instead
|
|
33
|
+
* of surfacing it to whichever caller owns the failure boundary. */
|
|
31
34
|
export function readTicketResult(dir) {
|
|
35
|
+
const path = responsePath(dir);
|
|
36
|
+
if (!existsSync(path))
|
|
37
|
+
return null;
|
|
32
38
|
let raw;
|
|
33
39
|
try {
|
|
34
|
-
raw = JSON.parse(readFileSync(
|
|
40
|
+
raw = JSON.parse(readFileSync(path, 'utf8'));
|
|
35
41
|
}
|
|
36
|
-
catch {
|
|
37
|
-
|
|
42
|
+
catch (error) {
|
|
43
|
+
throw new Error(`corrupt ticket result: ${path}`, { cause: error });
|
|
38
44
|
}
|
|
39
45
|
const page = pageResultSchema.safeParse(raw);
|
|
40
46
|
if (page.success)
|
|
@@ -246,7 +252,10 @@ function completePageLocked(dir, responses, claimToken, opts) {
|
|
|
246
252
|
const result = { schema: 'crtr.page-response/v1', kind: 'page', responses: parsedResponses, summary: buildPageSummary(manifest, parsedResponses), completedAt: opts.completedAt ?? new Date().toISOString(), ...(opts.actor === undefined ? {} : { actor: opts.actor }) };
|
|
247
253
|
const won = exclusiveResult(dir, result);
|
|
248
254
|
clearOwnedWork(dir, claimToken);
|
|
249
|
-
|
|
255
|
+
// Lost the race: the winner's result must already be on disk, so a null read
|
|
256
|
+
// here is an anomaly worth surfacing rather than silently falling back to
|
|
257
|
+
// this loser's own uncommitted result.
|
|
258
|
+
return { won, result: won ? result : (readTicketResult(dir) ?? (() => { throw new Error(`lost the completion race but no winning result is on disk: ${dir}`); })()) };
|
|
250
259
|
}
|
|
251
260
|
export function completePage(dir, responses, claimToken, opts = {}) {
|
|
252
261
|
const ticket = requireTicket(dir);
|
|
@@ -288,7 +297,12 @@ export function cancelTicket(dir, opts = {}) {
|
|
|
288
297
|
requireCancelablePage(ticket);
|
|
289
298
|
const result = { schema: 'humanloop.cancel/v1', kind: 'canceled', canceledAt: new Date().toISOString(), ...(opts.reason === undefined ? {} : { reason: opts.reason }), ...(opts.actor === undefined ? {} : { actor: opts.actor }), ...(opts.disposition === undefined ? {} : { disposition: opts.disposition }) };
|
|
290
299
|
const won = exclusiveResult(ticket, result);
|
|
291
|
-
|
|
300
|
+
// Same anomaly as completePageLocked: losing the race with no winning
|
|
301
|
+
// result on disk means the ticket state is broken, not just contended.
|
|
302
|
+
return {
|
|
303
|
+
status: won ? 'canceled' : 'already_resolved',
|
|
304
|
+
result: won ? result : (readTicketResult(ticket) ?? (() => { throw new Error(`lost the cancellation race but no winning result is on disk: ${ticket}`); })()),
|
|
305
|
+
};
|
|
292
306
|
});
|
|
293
307
|
if (canceled.status === 'canceled')
|
|
294
308
|
signalInboxActivity();
|
package/dist/core/io.js
CHANGED
|
@@ -9,9 +9,7 @@ import { ExitCode } from '../types.js';
|
|
|
9
9
|
import { PREVIEW_RESULT_PATH_ENV } from './preview-result-path.js';
|
|
10
10
|
import { renderError } from './render.js';
|
|
11
11
|
import { ApiError } from '../api/index.js';
|
|
12
|
-
// ---------------------------------------------------------------------------
|
|
13
12
|
// output mode — prose (default) vs raw JSON (--json global, for tooling)
|
|
14
|
-
// ---------------------------------------------------------------------------
|
|
15
13
|
let jsonOutput = false;
|
|
16
14
|
let preview;
|
|
17
15
|
/** A preview is bounded UI metadata, never a bulk-data channel. One
|
|
@@ -98,9 +96,7 @@ export class InputError extends CrtrError {
|
|
|
98
96
|
this.payload = payload;
|
|
99
97
|
}
|
|
100
98
|
}
|
|
101
|
-
// ---------------------------------------------------------------------------
|
|
102
99
|
// stdin
|
|
103
|
-
// ---------------------------------------------------------------------------
|
|
104
100
|
/** Read raw stdin to EOF. Returns empty string when stdin is a TTY (no pipe).
|
|
105
101
|
* Called by the argv parser for leaves declaring a `stdin` parameter. */
|
|
106
102
|
export async function readStdinRaw() {
|
|
@@ -148,9 +144,7 @@ export async function peekStdinRaw(timeoutMs = 200) {
|
|
|
148
144
|
process.stdin.resume();
|
|
149
145
|
});
|
|
150
146
|
}
|
|
151
|
-
// ---------------------------------------------------------------------------
|
|
152
147
|
// stdout — the result, nothing else
|
|
153
|
-
// ---------------------------------------------------------------------------
|
|
154
148
|
/** Raw-JSON mirror of a single-shot response (the `--json` escape hatch). The
|
|
155
149
|
* default path renders the result as prose instead — see render.ts. */
|
|
156
150
|
export function emit(obj) {
|
|
@@ -192,15 +186,11 @@ export function writeStdout(s) {
|
|
|
192
186
|
}
|
|
193
187
|
});
|
|
194
188
|
}
|
|
195
|
-
// ---------------------------------------------------------------------------
|
|
196
189
|
// stderr — diagnostics the agent MAY capture, never the result
|
|
197
|
-
// ---------------------------------------------------------------------------
|
|
198
190
|
export function diag(message) {
|
|
199
191
|
process.stderr.write(message + '\n');
|
|
200
192
|
}
|
|
201
|
-
// ---------------------------------------------------------------------------
|
|
202
193
|
// errors
|
|
203
|
-
// ---------------------------------------------------------------------------
|
|
204
194
|
function payloadOf(e) {
|
|
205
195
|
if (e instanceof InputError)
|
|
206
196
|
return e.payload;
|
|
@@ -259,7 +249,6 @@ function jsonSafeResult(result) {
|
|
|
259
249
|
message: 'The completed primary result could not be represented as JSON.',
|
|
260
250
|
};
|
|
261
251
|
}
|
|
262
|
-
// ---------------------------------------------------------------------------
|
|
263
252
|
// ApiError → clean CLI error — the ONE shared translation (plan C-5)
|
|
264
253
|
//
|
|
265
254
|
// A daemon `ApiError` is NOT a `CrtrError`, so left unhandled it falls through
|
|
@@ -268,7 +257,6 @@ function jsonSafeResult(result) {
|
|
|
268
257
|
// error the pre-API leaves surfaced, so every re-plumbed verb shares one
|
|
269
258
|
// contract instead of re-implementing the mapping per command. io.ts importing
|
|
270
259
|
// `ApiError` from `src/api` is canvas-clean (src/api is Node-built-ins only).
|
|
271
|
-
// ---------------------------------------------------------------------------
|
|
272
260
|
/** Map a daemon HTTP status to the stable CLI error code the pre-API leaves
|
|
273
261
|
* used, so agent-facing error contracts survive the re-plumb. Used only as the
|
|
274
262
|
* fallback when the server did NOT round-trip a full structured payload. */
|
|
@@ -4,12 +4,10 @@
|
|
|
4
4
|
// (a project's declaration, an installed plugin's mount prefix, or empty), and
|
|
5
5
|
// its canonical name — the only address resolution accepts — is namespace ⊕
|
|
6
6
|
// local. Pure and side-effect free.
|
|
7
|
-
// ---------------------------------------------------------------------------
|
|
8
7
|
// Segment normalization — the optional `NN-` ordering pin. A physical path may
|
|
9
8
|
// carry a two-digit prefix on any segment (`00-runtime-base/`, `01-spine/`)
|
|
10
9
|
// purely to pin structural order against natural sort. The prefix is NEVER part
|
|
11
10
|
// of identity: only the physical path keeps it.
|
|
12
|
-
// ---------------------------------------------------------------------------
|
|
13
11
|
const NUMERIC_PREFIX_RE = /^\d{2}-/;
|
|
14
12
|
const SEGMENT_RE = /^[A-Za-z0-9._-]+$/;
|
|
15
13
|
/** The filename (and path segment) whose document fronts its directory. */
|
|
@@ -85,9 +83,7 @@ export function physicalRelativePathFor(localName, representation) {
|
|
|
85
83
|
}
|
|
86
84
|
return representation === 'directory-index' ? `${local}/${INDEX_SEGMENT}.md` : `${local}.md`;
|
|
87
85
|
}
|
|
88
|
-
// ---------------------------------------------------------------------------
|
|
89
86
|
// Local name and canonical composition.
|
|
90
|
-
// ---------------------------------------------------------------------------
|
|
91
87
|
/** A document's explicit frontmatter `name` as a local name — normalized with
|
|
92
88
|
* one trailing `INDEX` collapsed — or `null` when it carries none. */
|
|
93
89
|
export function explicitLocalName(fm) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Authoritative broker-side inventory for inline memory references. It uses one
|
|
2
2
|
// target view, exact canonical winners, and the canonical tree for directory
|
|
3
3
|
// browse names; gates, rungs, and slash flags do not affect referenceability.
|
|
4
|
+
import { envNodeId, envProfileId } from '../../shared/env.js';
|
|
4
5
|
import { loadMemoryTargetView } from '../memory-resolver.js';
|
|
5
6
|
import { buildMemoryTree } from './tree.js';
|
|
6
7
|
import { memoryExtensionEffectiveCatalog, projectEffectiveMemoryExtensions } from './extensions.js';
|
|
@@ -21,8 +22,8 @@ const SCOPE_SORT_RANK = {
|
|
|
21
22
|
export function buildRefInventory() {
|
|
22
23
|
const target = {
|
|
23
24
|
cwd: process.cwd(),
|
|
24
|
-
profileId:
|
|
25
|
-
nodeId:
|
|
25
|
+
profileId: envProfileId() || null,
|
|
26
|
+
nodeId: envNodeId() || null,
|
|
26
27
|
};
|
|
27
28
|
const view = loadMemoryTargetView(target, { quiet: true });
|
|
28
29
|
const winners = new Map();
|
package/dist/core/memory/lint.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
// a non-fatal authoring smell, `notice` is inspection data (duplicate stores are
|
|
11
11
|
// legitimate, so equal-canonical candidates across stores are reported, never
|
|
12
12
|
// failed).
|
|
13
|
+
import { envNodeId, envProfileId } from '../../shared/env.js';
|
|
13
14
|
import { basename, join, matchesGlob, relative, sep } from 'node:path';
|
|
14
15
|
import { pathExists, readText, realpathOrSelf, walkFiles } from '../fs-utils.js';
|
|
15
16
|
import { parseFrontmatterGeneric } from '../frontmatter.js';
|
|
@@ -51,7 +52,6 @@ function makeResult(findings, checked, documents, storesLinted) {
|
|
|
51
52
|
notices: findings.filter((f) => f.severity === 'notice'),
|
|
52
53
|
};
|
|
53
54
|
}
|
|
54
|
-
// ---------------------------------------------------------------------------
|
|
55
55
|
// Body-length caps, measured in WORDS (frontmatter excluded). Words, not lines:
|
|
56
56
|
// house style writes each paragraph as ONE logical line and lets the editor
|
|
57
57
|
// soft-wrap, so a line count measures wrapping style rather than context cost.
|
|
@@ -68,7 +68,6 @@ function makeResult(findings, checked, documents, storesLinted) {
|
|
|
68
68
|
// composes into an agent's persona — are structurally exempt: an agent reads its
|
|
69
69
|
// whole persona by construction. Suppression elsewhere is deliberate and
|
|
70
70
|
// per-doc: `lint-ignore: length`, surfaced ONLY by the finding itself.
|
|
71
|
-
// ---------------------------------------------------------------------------
|
|
72
71
|
const BOOT_CONTENT_MAX_WORDS = 1000;
|
|
73
72
|
const EVENT_CONTENT_MAX_WORDS = 1000;
|
|
74
73
|
const BOOT_PREVIEW_MAX_WORDS = 3000;
|
|
@@ -116,9 +115,7 @@ export function lintShortPreviewBody(fm, body) {
|
|
|
116
115
|
const noun = previewEvents.length === 1 ? 'entry delivers' : 'entries deliver';
|
|
117
116
|
return `body is ${words} words but the ${previewEvents.join('/')} ${noun} \`preview\`; use \`at: content\` so agents receive the whole rule without a separate memory read`;
|
|
118
117
|
}
|
|
119
|
-
// ---------------------------------------------------------------------------
|
|
120
118
|
// Reference resolution: what a `[[link]]` or a `memory-read` route may name.
|
|
121
|
-
// ---------------------------------------------------------------------------
|
|
122
119
|
/** Every canonical name a reference may target in a corpus: each document's
|
|
123
120
|
* exact identity plus every canonical directory, because reading a directory
|
|
124
121
|
* answers with its own document and its listing. Derived from the canonical
|
|
@@ -455,8 +452,8 @@ function lintMemoryReadEntry(entry, doc, fm, resolvable, mounted, add) {
|
|
|
455
452
|
function ambientTarget() {
|
|
456
453
|
return {
|
|
457
454
|
cwd: process.cwd(),
|
|
458
|
-
profileId:
|
|
459
|
-
nodeId:
|
|
455
|
+
profileId: envProfileId() || null,
|
|
456
|
+
nodeId: envNodeId() || null,
|
|
460
457
|
};
|
|
461
458
|
}
|
|
462
459
|
/** Lint every store a target sees, then the diagnostics only the merged view
|
|
@@ -242,6 +242,11 @@ export declare function createMemoryDocSnapshot(target?: MemoryTarget): MemoryDo
|
|
|
242
242
|
/** Resolve several canonical names over one memory-source snapshot. Failed
|
|
243
243
|
* names are omitted so callers can preserve their per-document error behavior. */
|
|
244
244
|
export declare function resolveMemoryDocs(names: readonly string[]): Map<string, MemoryDoc>;
|
|
245
|
+
/** Load the body at an already-resolved memory path with the same frontmatter
|
|
246
|
+
* stripping and in-node path interpolation as `memory read`. Callers that
|
|
247
|
+
* already have the resolved path (such as slash-command discovery) avoid
|
|
248
|
+
* re-walking every memory store for each document. */
|
|
249
|
+
export declare function readMemoryDocContent(path: string, includeFrontmatter?: boolean): string;
|
|
245
250
|
/** The address winner for an exact canonical name in the ambient target. */
|
|
246
251
|
export declare function resolveMemoryDoc(rawName: string, opts?: MemoryResolutionOpts): MemoryDoc;
|
|
247
252
|
/** Resolve a memory document as ANOTHER node would see it — the same precedence
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { envNodeId, envProfileId } from '../shared/env.js';
|
|
1
2
|
import { dirname, join, relative, sep } from 'node:path';
|
|
2
3
|
import { readdirSync } from 'node:fs';
|
|
3
4
|
import { CRTR_DIR_NAME } from '../types.js';
|
|
4
5
|
import { pathExists, readText, realpathOrSelf, walkFiles } from './fs-utils.js';
|
|
5
6
|
import { parseFrontmatterGeneric } from './frontmatter.js';
|
|
7
|
+
import { interpolateNodePaths } from './canvas/paths.js';
|
|
6
8
|
import { listInstalledPlugins, listInstalledPluginsInRoot } from './resolver.js';
|
|
7
9
|
import { notFound, usage } from './errors.js';
|
|
8
10
|
import { warn } from './output.js';
|
|
@@ -19,18 +21,16 @@ import { associateRepository } from './memory/repository-association.js';
|
|
|
19
21
|
function ambientTarget() {
|
|
20
22
|
return {
|
|
21
23
|
cwd: process.cwd(),
|
|
22
|
-
profileId:
|
|
23
|
-
nodeId:
|
|
24
|
+
profileId: envProfileId() || null,
|
|
25
|
+
nodeId: envNodeId() || null,
|
|
24
26
|
};
|
|
25
27
|
}
|
|
26
28
|
/** The selected profile id from the process env, or '' when none. */
|
|
27
29
|
function selectedProfileId() {
|
|
28
30
|
return ambientTarget().profileId ?? '';
|
|
29
31
|
}
|
|
30
|
-
// ---------------------------------------------------------------------------
|
|
31
32
|
// Store discovery: which physical stores a target sees, in what order, and
|
|
32
33
|
// whether each one's namespace lets it mount.
|
|
33
|
-
// ---------------------------------------------------------------------------
|
|
34
34
|
/** The memory scopes in resolution precedence: node > project stack > profile >
|
|
35
35
|
* user > builtin. Node is included only when the target names one and ranks
|
|
36
36
|
* NEAREST — a node doc overrides any wider scope. Project is included only when
|
|
@@ -291,10 +291,8 @@ export function nativeMemoryStoresInPrecedence(scope, includeDescendants = false
|
|
|
291
291
|
.filter((store) => store.mountStatus === 'ready' && store.scope !== 'builtin' && store.plugin === undefined)
|
|
292
292
|
.map((store) => ({ scope: store.scope, memoryDir: store.storeRoot, store }));
|
|
293
293
|
}
|
|
294
|
-
// ---------------------------------------------------------------------------
|
|
295
294
|
// Document loading: one store's markdown files become canonically-identified
|
|
296
295
|
// documents.
|
|
297
|
-
// ---------------------------------------------------------------------------
|
|
298
296
|
function firstLine(e) {
|
|
299
297
|
return (e instanceof Error ? e.message : String(e)).split('\n')[0] ?? '';
|
|
300
298
|
}
|
|
@@ -375,9 +373,7 @@ export function loadStoreMemoryDocs(store, quiet = false) {
|
|
|
375
373
|
export function listPluginMemoryDocs(plugin, scope, quiet = false, projectMemory = NEUTRAL_PROJECT_MEMORY) {
|
|
376
374
|
return loadStoreMemoryDocs(pluginStoreDescriptor(plugin, scope, projectMemory), quiet);
|
|
377
375
|
}
|
|
378
|
-
// ---------------------------------------------------------------------------
|
|
379
376
|
// Views: exact canonical resolution over a loaded corpus.
|
|
380
|
-
// ---------------------------------------------------------------------------
|
|
381
377
|
/** The canonical form of a query: empty segments dropped. An `NN-` ordering
|
|
382
378
|
* prefix is physical-path-only and is NOT stripped here — a canonical name
|
|
383
379
|
* never carries one, so `04-base` is simply no document's address. */
|
|
@@ -462,9 +458,7 @@ export function loadMemoryTargetView(target, opts = {}) {
|
|
|
462
458
|
export function loadMemoryStoreView(store, quiet = false) {
|
|
463
459
|
return { store, ...makeView([store], loadStoreMemoryDocs(store, quiet)) };
|
|
464
460
|
}
|
|
465
|
-
// ---------------------------------------------------------------------------
|
|
466
461
|
// Corpus listing.
|
|
467
|
-
// ---------------------------------------------------------------------------
|
|
468
462
|
/** All project-scoped docs visible from an explicit node workspace/profile — the
|
|
469
463
|
* project-only slice of a `MemoryTarget` view, used where only workspace docs
|
|
470
464
|
* are wanted (a workspace-open render). For a full-precedence target-addressed
|
|
@@ -507,6 +501,16 @@ export function createMemoryDocSnapshot(target = ambientTarget()) {
|
|
|
507
501
|
export function resolveMemoryDocs(names) {
|
|
508
502
|
return createMemoryDocSnapshot().resolve(names);
|
|
509
503
|
}
|
|
504
|
+
/** Load the body at an already-resolved memory path with the same frontmatter
|
|
505
|
+
* stripping and in-node path interpolation as `memory read`. Callers that
|
|
506
|
+
* already have the resolved path (such as slash-command discovery) avoid
|
|
507
|
+
* re-walking every memory store for each document. */
|
|
508
|
+
export function readMemoryDocContent(path, includeFrontmatter = false) {
|
|
509
|
+
const raw = readText(path);
|
|
510
|
+
const content = includeFrontmatter ? raw : parseFrontmatterGeneric(raw).body;
|
|
511
|
+
const nodeId = envNodeId();
|
|
512
|
+
return nodeId ? interpolateNodePaths(content, nodeId) : content;
|
|
513
|
+
}
|
|
510
514
|
/** The address winner for an exact canonical name in the ambient target. */
|
|
511
515
|
export function resolveMemoryDoc(rawName, opts = {}) {
|
|
512
516
|
return resolveMemoryDocForTarget(rawName, ambientTarget(), opts);
|
|
@@ -541,10 +545,8 @@ export function resolveMemoryCandidatesForTarget(rawName, target, opts = {}) {
|
|
|
541
545
|
export function resolveMemoryDocInStore(rawName, store, opts = {}) {
|
|
542
546
|
return loadMemoryStoreView(store, true).resolve(rawName, opts);
|
|
543
547
|
}
|
|
544
|
-
// ---------------------------------------------------------------------------
|
|
545
548
|
// Physical sidecar lookup: the revision log mirrors the doc tree, so it is
|
|
546
549
|
// addressed by PHYSICAL path segments, not by canonical identity.
|
|
547
|
-
// ---------------------------------------------------------------------------
|
|
548
550
|
/** Find the direct child of `dir` — an `ext` file (matched on name minus
|
|
549
551
|
* extension) or a directory — whose NORMALIZED display name equals
|
|
550
552
|
* `segment`. An exact literal match (no prefix to strip) wins over a
|
package/dist/core/pagination.js
CHANGED
|
@@ -11,9 +11,7 @@
|
|
|
11
11
|
// item after it is returned correctly).
|
|
12
12
|
import { CrtrError } from './errors.js';
|
|
13
13
|
import { ExitCode } from '../types.js';
|
|
14
|
-
// ---------------------------------------------------------------------------
|
|
15
14
|
// Cursor encoding / decoding
|
|
16
|
-
// ---------------------------------------------------------------------------
|
|
17
15
|
/** Encodes a stable sort key into an opaque base64url cursor token. */
|
|
18
16
|
export function encodeCursor(key) {
|
|
19
17
|
const json = JSON.stringify({ k: key });
|
|
@@ -14,6 +14,9 @@ export declare const HELP_ICON: string;
|
|
|
14
14
|
* paints lives in one file: terminal for `bash`, file-text for `read`, floppy for
|
|
15
15
|
* `write` (content committed to disk), pencil-square for `edit`. */
|
|
16
16
|
export declare const TOOL_ICON: Readonly<Record<'bash' | 'read' | 'write' | 'edit', string>>;
|
|
17
|
+
/** Per-leaf overrides, keyed by full leaf help-name path (e.g. "memory
|
|
18
|
+
* lint"), same shape as SUPPRESS_OUTPUT_LEAVES. */
|
|
19
|
+
export declare const LEAF_ICON_CP: Record<string, number>;
|
|
17
20
|
/** Resolve the Nerd Font glyph for a command's argv tokens: the longest
|
|
18
21
|
* matching LEAF_ICON_CP prefix, else the tokens[0] family glyph, else the
|
|
19
22
|
* generic ◆ fallback for an unmapped family. */
|
|
@@ -29,7 +32,18 @@ export interface CrtrPreview {
|
|
|
29
32
|
jsonl?: Record<string, unknown>[];
|
|
30
33
|
error?: Record<string, unknown>;
|
|
31
34
|
}
|
|
35
|
+
type SummaryInput = {
|
|
36
|
+
result?: Record<string, unknown>;
|
|
37
|
+
jsonl?: Record<string, unknown>[];
|
|
38
|
+
error?: Record<string, unknown>;
|
|
39
|
+
};
|
|
40
|
+
type Summarizer = (input: SummaryInput, tokens: readonly string[]) => SummaryLine[] | null;
|
|
41
|
+
export declare const SUMMARIZERS: ReadonlyArray<{
|
|
42
|
+
path: string;
|
|
43
|
+
run: Summarizer;
|
|
44
|
+
}>;
|
|
32
45
|
/** Summarize an exact CLI result record. The recorded path is authoritative:
|
|
33
46
|
* shell tokenization is used only for an invocation's static icon/help chrome,
|
|
34
47
|
* never to identify or decode the returned leaf data. */
|
|
35
48
|
export declare function summarizePath(preview: CrtrPreview, tokens?: readonly string[]): SummaryLine[] | null;
|
|
49
|
+
export {};
|
|
@@ -42,12 +42,10 @@ export function suppressOutputForPath(tokens) {
|
|
|
42
42
|
}
|
|
43
43
|
return false;
|
|
44
44
|
}
|
|
45
|
-
// ---------------------------------------------------------------------------
|
|
46
45
|
// Icon registry (rule 12, inline-ui-placement: real Nerd Font glyphs, not the
|
|
47
46
|
// generic ◆ diamond). Every leaf's glyph is looked up first in LEAF_ICON_CP
|
|
48
47
|
// (longest-prefix match, same shape as SUPPRESS_OUTPUT_LEAVES); an unmapped
|
|
49
48
|
// leaf falls back to its root family's glyph in FAMILY_ICON_CP.
|
|
50
|
-
// ---------------------------------------------------------------------------
|
|
51
49
|
/** question-circle — the header glyph for a `-h`/`--help` invocation,
|
|
52
50
|
* regardless of which command's help was requested. */
|
|
53
51
|
const HELP_ICON_CP = 0xf059;
|
|
@@ -83,7 +81,7 @@ const FAMILY_ICON_CP = {
|
|
|
83
81
|
};
|
|
84
82
|
/** Per-leaf overrides, keyed by full leaf help-name path (e.g. "memory
|
|
85
83
|
* lint"), same shape as SUPPRESS_OUTPUT_LEAVES. */
|
|
86
|
-
const LEAF_ICON_CP = {
|
|
84
|
+
export const LEAF_ICON_CP = {
|
|
87
85
|
'canvas dashboard': 0xf0e4,
|
|
88
86
|
'canvas snapshot': 0xf030,
|
|
89
87
|
'canvas browse': 0xf14e,
|
|
@@ -345,7 +343,7 @@ function summarizeProfileList(input) {
|
|
|
345
343
|
...profiles.slice(0, 5).map((profile) => ({ text: `${stringField(profile, 'name')} · ${numberField(profile, 'projects_count')} projects`, tone: 'muted' })),
|
|
346
344
|
];
|
|
347
345
|
}
|
|
348
|
-
const SUMMARIZERS = [
|
|
346
|
+
export const SUMMARIZERS = [
|
|
349
347
|
{ path: 'memory read', run: summarizeMemoryRead },
|
|
350
348
|
{ path: 'memory list', run: summarizeArray('docs') },
|
|
351
349
|
{ path: 'memory find', run: summarizeArray('hits', 'hits') },
|