@north-light/crouter 0.3.318 → 0.3.319
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/README.md +0 -3
- package/dist/api/client.js +2 -912
- package/dist/api/dto/attach.js +0 -13
- package/dist/api/dto/bash-jobs.js +1 -9
- package/dist/api/dto/broker-ops.js +0 -6
- package/dist/api/dto/broker.js +0 -20
- package/dist/api/dto/canvas.js +0 -2
- package/dist/api/dto/chat-inventory.js +0 -11
- package/dist/api/dto/common.js +1 -15
- package/dist/api/dto/config.js +0 -3
- package/dist/api/dto/crons.js +1 -10
- package/dist/api/dto/files.js +0 -7
- package/dist/api/dto/focus.js +0 -10
- package/dist/api/dto/health.js +0 -2
- package/dist/api/dto/human-requests.js +0 -4
- package/dist/api/dto/human.js +0 -4
- package/dist/api/dto/inbox.js +0 -4
- package/dist/api/dto/lifecycle.js +0 -3
- package/dist/api/dto/mail.js +0 -1
- package/dist/api/dto/memory.js +0 -6
- package/dist/api/dto/messages.js +0 -2
- package/dist/api/dto/model-config.js +0 -1
- package/dist/api/dto/modelauth.js +0 -4
- package/dist/api/dto/node-outcomes.js +0 -2
- package/dist/api/dto/nodes.js +0 -3
- package/dist/api/dto/profiles.js +1 -4
- package/dist/api/dto/recovery.js +0 -1
- package/dist/api/dto/reports.js +0 -2
- package/dist/api/dto/review-comments.js +0 -5
- package/dist/api/dto/reviews.js +0 -5
- package/dist/api/dto/subscriptions.js +0 -2
- package/dist/api/dto/worktree.js +0 -6
- package/dist/api/errors.js +1 -40
- package/dist/api/index.js +1 -33
- package/dist/api/plugin-manifest-schema.js +0 -23
- package/dist/api/routes.js +1 -147
- package/dist/build-root.js +1 -198
- package/dist/cli.js +3 -99
- package/dist/clients/attach/ansi-cells.js +1 -137
- package/dist/clients/attach/chrome/bash-jobs.js +1 -31
- package/dist/clients/attach/chrome/canvas-panels.js +1 -194
- package/dist/clients/attach/chrome/completion-bell.js +1 -89
- package/dist/clients/attach/chrome/cron-wait.js +1 -34
- package/dist/clients/attach/chrome/git-info.js +2 -44
- package/dist/clients/attach/chrome/header.js +1 -30
- package/dist/clients/attach/chrome/inbox-strip.js +1 -199
- package/dist/clients/attach/chrome/recap.js +1 -19
- package/dist/clients/attach/chrome/review-wait.js +1 -22
- package/dist/clients/attach/chrome/roster.js +4 -275
- package/dist/clients/attach/chrome/status-line.js +1 -117
- package/dist/clients/attach/chrome/ticket-panel.js +1 -280
- package/dist/clients/attach/chrome/widgets.js +1 -51
- package/dist/clients/attach/command.js +1 -107
- package/dist/clients/attach/config.js +1 -274
- package/dist/clients/attach/input/capabilities.js +1 -104
- package/dist/clients/attach/input/clipboard-image.js +3 -220
- package/dist/clients/attach/input/completion-frecency.js +1 -141
- package/dist/clients/attach/input/controller.js +7 -377
- package/dist/clients/attach/input/overlay-owner.js +1 -199
- package/dist/clients/attach/input/ref-autocomplete.js +2 -176
- package/dist/clients/attach/input/titled-editor.js +4 -859
- package/dist/clients/attach/overlays/auth.js +2 -271
- package/dist/clients/attach/overlays/dialogs.js +2 -102
- package/dist/clients/attach/overlays/file-review.js +2 -128
- package/dist/clients/attach/overlays/graph.js +1 -661
- package/dist/clients/attach/overlays/help.js +1 -211
- package/dist/clients/attach/overlays/mcp.js +1 -302
- package/dist/clients/attach/overlays/pickers.js +1 -163
- package/dist/clients/attach/render/activity-slot.js +1 -13
- package/dist/clients/attach/render/assistant-message.js +1 -56
- package/dist/clients/attach/render/card-presentation.js +5 -218
- package/dist/clients/attach/render/chat-view.js +5 -1708
- package/dist/clients/attach/render/condensed-history.js +1 -60
- package/dist/clients/attach/render/context-message.js +1 -63
- package/dist/clients/attach/render/crtr-output.js +17 -905
- package/dist/clients/attach/render/diagram.js +7 -111
- package/dist/clients/attach/render/edit-diff.js +5 -304
- package/dist/clients/attach/render/glyph-codepoints.js +1 -42
- package/dist/clients/attach/render/group-activity.js +2 -263
- package/dist/clients/attach/render/group-recap.js +1 -152
- package/dist/clients/attach/render/markdown-source.js +5 -266
- package/dist/clients/attach/render/measured-container.js +1 -322
- package/dist/clients/attach/render/page-block.js +1 -183
- package/dist/clients/attach/render/scroll-animation.js +1 -80
- package/dist/clients/attach/render/tool-calls.js +3 -361
- package/dist/clients/attach/render/transcript-copy.js +2 -81
- package/dist/clients/attach/render/transcript-search.js +1 -152
- package/dist/clients/attach/render/viewport.js +1 -184
- package/dist/clients/attach/session/banner.js +1 -29
- package/dist/clients/attach/session/bindings.js +1 -71
- package/dist/clients/attach/session/chrome-refresh.js +1 -94
- package/dist/clients/attach/session/connection.js +1 -186
- package/dist/clients/attach/session/context.js +0 -16
- package/dist/clients/attach/session/editor-frame.js +1 -142
- package/dist/clients/attach/session/editor-inventory.js +6 -160
- package/dist/clients/attach/session/file-links.js +1 -68
- package/dist/clients/attach/session/focus-events.js +1 -12
- package/dist/clients/attach/session/frame.js +1 -214
- package/dist/clients/attach/session/frames.js +1 -188
- package/dist/clients/attach/session/identity.js +1 -26
- package/dist/clients/attach/session/input-wiring.js +1 -140
- package/dist/clients/attach/session/invariant.js +1 -15
- package/dist/clients/attach/session/keys.js +1 -77
- package/dist/clients/attach/session/layout.js +1 -59
- package/dist/clients/attach/session/mouse.js +1 -78
- package/dist/clients/attach/session/pane-focus.js +1 -42
- package/dist/clients/attach/session/pane-tag.js +1 -112
- package/dist/clients/attach/session/pi-assets.js +1 -24
- package/dist/clients/attach/session/pi-oauth-flows.js +1 -21
- package/dist/clients/attach/session/profile-files.js +1 -228
- package/dist/clients/attach/session/reconnect.js +1 -175
- package/dist/clients/attach/session/selection.js +3 -108
- package/dist/clients/attach/session/state-sync.js +1 -67
- package/dist/clients/attach/session/surface-frame.js +1 -73
- package/dist/clients/attach/session/surface-host.js +1 -255
- package/dist/clients/attach/session/teardown.js +5 -94
- package/dist/clients/attach/session/transcript-search.js +3 -151
- package/dist/clients/attach/session/whip-achievements.js +2 -145
- package/dist/clients/attach/session/whip.js +1 -362
- package/dist/clients/attach/slash/dispatch.js +1 -706
- package/dist/clients/attach/slash/prompt-preview.js +1 -121
- package/dist/clients/attach/viewer.js +441 -441
- package/dist/clients/conversation/projection.js +1 -324
- package/dist/clients/conversation/submit.js +1 -51
- package/dist/clients/inbox/controller.js +1 -701
- package/dist/clients/inbox/dto-adapt.js +1 -93
- package/dist/clients/inbox/layout.js +1 -9
- package/dist/clients/inbox/page-adapter.js +1 -55
- package/dist/clients/inbox/resolve.js +1 -35
- package/dist/clients/inbox/review/anchors.js +1 -89
- package/dist/clients/inbox/review/comments-client.js +1 -98
- package/dist/clients/inbox/review/companion-pane.js +1 -82
- package/dist/clients/inbox/review/document-surface.js +2 -1188
- package/dist/clients/inbox/review/frame.js +1 -216
- package/dist/clients/inbox/review/keys.js +1 -123
- package/dist/clients/inbox/review/launch.js +1 -151
- package/dist/clients/inbox/review/live-source.js +1 -160
- package/dist/clients/inbox/review/nvim.js +1 -44
- package/dist/clients/inbox/review/remap.js +1 -157
- package/dist/clients/inbox/review/review-client.js +1 -123
- package/dist/clients/inbox/review/roundtrip.js +3 -36
- package/dist/clients/inbox/review/state.js +4 -315
- package/dist/clients/inbox/review-adapter.js +1 -43
- package/dist/clients/inbox/surface.js +1 -152
- package/dist/clients/inbox/tui/ansi.js +3 -321
- package/dist/clients/inbox/tui/input.js +5 -392
- package/dist/clients/inbox/tui/keys.js +1 -104
- package/dist/clients/inbox/tui/page-body.js +1 -66
- package/dist/clients/inbox/tui/panel.js +1 -84
- package/dist/clients/inbox/tui/render.js +2 -368
- package/dist/clients/inbox/tui/slots.js +3 -134
- package/dist/clients/inbox/tui/types.js +0 -1
- package/dist/clients/inbox/tui.js +1 -86
- package/dist/clients/surfaces/host.js +0 -1
- package/dist/commands/api-client.js +4 -290
- package/dist/commands/attention.js +1 -215
- package/dist/commands/canvas-browse.js +1 -70
- package/dist/commands/canvas-config.js +2 -192
- package/dist/commands/canvas-history/grep.js +7 -85
- package/dist/commands/canvas-history/read.js +3 -50
- package/dist/commands/canvas-history/search.js +10 -99
- package/dist/commands/canvas-history/shared.js +1 -139
- package/dist/commands/canvas-history/stats.js +6 -68
- package/dist/commands/canvas-history.js +1 -32
- package/dist/commands/canvas-issue.js +14 -149
- package/dist/commands/canvas-prune.js +1 -108
- package/dist/commands/canvas-roster.js +1 -69
- package/dist/commands/canvas-snapshot.js +1 -34
- package/dist/commands/canvas-use.js +1 -61
- package/dist/commands/canvas.js +1 -49
- package/dist/commands/chord.js +1 -241
- package/dist/commands/cron.js +11 -534
- package/dist/commands/dashboard.js +1 -85
- package/dist/commands/human/components.js +3 -77
- package/dist/commands/human/feedback.js +1 -112
- package/dist/commands/human/prompts.js +1 -331
- package/dist/commands/human/queue.js +1 -191
- package/dist/commands/human/request.js +1 -266
- package/dist/commands/human/review.js +1 -288
- package/dist/commands/human/shared.js +1 -67
- package/dist/commands/human.js +4 -60
- package/dist/commands/memory/delete.js +1 -100
- package/dist/commands/memory/edit.js +21 -219
- package/dist/commands/memory/find.js +2 -244
- package/dist/commands/memory/history.js +5 -199
- package/dist/commands/memory/lint.js +1 -107
- package/dist/commands/memory/list.js +1 -142
- package/dist/commands/memory/move.js +1 -223
- package/dist/commands/memory/origin.js +1 -130
- package/dist/commands/memory/read.js +6 -232
- package/dist/commands/memory/shared.js +12 -802
- package/dist/commands/memory/write.js +13 -235
- package/dist/commands/memory.js +1 -30
- package/dist/commands/node/bash.js +5 -245
- package/dist/commands/node/create.js +3 -332
- package/dist/commands/node/inspect.js +12 -300
- package/dist/commands/node/lifecycle.js +2 -453
- package/dist/commands/node/message.js +1 -161
- package/dist/commands/node/outcome.js +4 -134
- package/dist/commands/node/pyramid.js +2 -79
- package/dist/commands/node/subscription.js +1 -78
- package/dist/commands/node/wait.js +7 -163
- package/dist/commands/node-context.js +2 -159
- package/dist/commands/node-inspect-artifacts.js +8 -109
- package/dist/commands/node-lifecycle-revive.js +1 -217
- package/dist/commands/node-snapshot.js +1 -37
- package/dist/commands/node-transcript.js +1 -62
- package/dist/commands/node-worktree.js +1 -138
- package/dist/commands/node.js +1 -29
- package/dist/commands/pkg/browse/actions.js +1 -198
- package/dist/commands/pkg/browse/catalog.js +1 -466
- package/dist/commands/pkg/browse/command-view.js +1 -191
- package/dist/commands/pkg/browse/detail-panel.js +1 -402
- package/dist/commands/pkg/browse/doc-view.js +1 -89
- package/dist/commands/pkg/browse/list-panel.js +2 -168
- package/dist/commands/pkg/browse/model.js +1 -36
- package/dist/commands/pkg/browse/shell.js +1 -640
- package/dist/commands/pkg/browse.js +1 -27
- package/dist/commands/pkg/market-inspect.js +1 -141
- package/dist/commands/pkg/market-manage.js +1 -327
- package/dist/commands/pkg/market.js +1 -14
- package/dist/commands/pkg/plugin-inspect.js +1 -168
- package/dist/commands/pkg/plugin-manage.js +17 -1109
- package/dist/commands/pkg/plugin.js +1 -14
- package/dist/commands/pkg/shared.js +1 -62
- package/dist/commands/pkg.js +1 -21
- package/dist/commands/profile/default.js +1 -139
- package/dist/commands/profile/delete.js +1 -66
- package/dist/commands/profile/env.js +3 -188
- package/dist/commands/profile/kind.js +2 -35
- package/dist/commands/profile/list.js +1 -43
- package/dist/commands/profile/meta.js +1 -67
- package/dist/commands/profile/new.js +1 -115
- package/dist/commands/profile/pause.js +1 -59
- package/dist/commands/profile/project.js +1 -113
- package/dist/commands/profile/rename.js +1 -38
- package/dist/commands/profile/show.js +1 -52
- package/dist/commands/profile.js +1 -35
- package/dist/commands/push.js +9 -265
- package/dist/commands/revive.js +10 -181
- package/dist/commands/surface/node/cycle.js +1 -83
- package/dist/commands/surface/node/focus.js +1 -81
- package/dist/commands/surface/node/id.js +1 -38
- package/dist/commands/surface/node/pin.js +1 -42
- package/dist/commands/surface/node/placement.js +1 -134
- package/dist/commands/surface-edit.js +1 -157
- package/dist/commands/surface-inbox.js +1 -98
- package/dist/commands/surface-inspect.js +1 -39
- package/dist/commands/surface-node.js +1 -19
- package/dist/commands/surface-reload.js +2 -134
- package/dist/commands/surface-tmux-spread.js +1 -214
- package/dist/commands/surface.js +1 -28
- package/dist/commands/sys/branch.js +1 -19
- package/dist/commands/sys/config.js +1 -353
- package/dist/commands/sys/context/admin/actions.js +2 -246
- package/dist/commands/sys/context/admin/detail-panel.js +1 -247
- package/dist/commands/sys/context/admin/docs-panel.js +1 -191
- package/dist/commands/sys/context/admin/list-view.js +1 -183
- package/dist/commands/sys/context/admin/model.js +1 -229
- package/dist/commands/sys/context/admin/rail-panel.js +1 -227
- package/dist/commands/sys/context/admin/read-view.js +2 -194
- package/dist/commands/sys/context/admin/shell.js +1 -910
- package/dist/commands/sys/context/admin.js +2 -126
- package/dist/commands/sys/context/doc.js +3 -197
- package/dist/commands/sys/context/prompt-review.js +11 -291
- package/dist/commands/sys/context/resolve.js +10 -489
- package/dist/commands/sys/context/sysprompt.js +5 -96
- package/dist/commands/sys/context.js +1 -20
- package/dist/commands/sys/daemon.js +1 -313
- package/dist/commands/sys/doctor.js +1 -617
- package/dist/commands/sys/feedback.js +7 -228
- package/dist/commands/sys/logs.js +3 -129
- package/dist/commands/sys/migrate.js +1 -94
- package/dist/commands/sys/panels/broker-limits-panel.js +2 -110
- package/dist/commands/sys/panels/dependencies-panel.js +1 -80
- package/dist/commands/sys/panels/keybindings-panel.js +1 -703
- package/dist/commands/sys/panels/models-panel.js +1 -1133
- package/dist/commands/sys/panels/plugins-panel.js +1 -80
- package/dist/commands/sys/panels/prefs-panel.js +1 -85
- package/dist/commands/sys/panels/profiles-panel.js +1 -601
- package/dist/commands/sys/panels/provider-panel.js +1 -538
- package/dist/commands/sys/settings-shell.js +1 -400
- package/dist/commands/sys/settings.js +1 -46
- package/dist/commands/sys/setup-core.js +6 -579
- package/dist/commands/sys/setup-settings-runner.js +1 -16
- package/dist/commands/sys/setup-wizard.js +1 -279
- package/dist/commands/sys/setup.js +1 -34
- package/dist/commands/sys/shared.js +1 -81
- package/dist/commands/sys/support/prepare.js +3 -239
- package/dist/commands/sys/support/submit.js +6 -524
- package/dist/commands/sys/support.js +1 -18
- package/dist/commands/sys/sync-deps.js +15 -498
- package/dist/commands/sys/sync-project-guidance.js +4 -481
- package/dist/commands/sys/sync-shared.js +1 -49
- package/dist/commands/sys/sync-skills.js +2 -311
- package/dist/commands/sys/sync.js +1 -18
- package/dist/commands/sys/update.js +1 -147
- package/dist/commands/sys/worktrees.js +5 -53
- package/dist/commands/sys.js +1 -18
- package/dist/core/activity-signal.js +2 -38
- package/dist/core/asset-root.js +1 -18
- package/dist/core/auth-file.js +2 -179
- package/dist/core/auth-interaction.js +3 -94
- package/dist/core/auto-update.js +4 -94
- package/dist/core/bash-guard.js +11 -393
- package/dist/core/bash-jobs.js +7 -411
- package/dist/core/bootstrap.js +2 -53
- package/dist/core/broker-client/client.js +1 -184
- package/dist/core/broker-client/index.js +1 -13
- package/dist/core/broker-client/transport-relay.js +1 -157
- package/dist/core/broker-client/transport-socket.js +1 -179
- package/dist/core/broker-client/transport.js +1 -26
- package/dist/core/canvas/attention.js +1 -47
- package/dist/core/canvas/boot-id.js +1 -26
- package/dist/core/canvas/boot.js +1 -186
- package/dist/core/canvas/browse/app.js +3 -919
- package/dist/core/canvas/browse/model.js +1 -477
- package/dist/core/canvas/browse/pins.js +1 -29
- package/dist/core/canvas/browse/render.js +3 -1055
- package/dist/core/canvas/canvas.js +15 -922
- package/dist/core/canvas/crons.js +11 -481
- package/dist/core/canvas/daemon-owner.js +2 -146
- package/dist/core/canvas/db.js +2 -100
- package/dist/core/canvas/deliveries.js +22 -283
- package/dist/core/canvas/delivery-contract.js +1 -8
- package/dist/core/canvas/executions.js +1 -68
- package/dist/core/canvas/extensions.js +1 -83
- package/dist/core/canvas/focuses.js +1 -77
- package/dist/core/canvas/history.js +24 -860
- package/dist/core/canvas/index.js +1 -15
- package/dist/core/canvas/install-id.js +1 -84
- package/dist/core/canvas/labels.js +1 -43
- package/dist/core/canvas/meta-file.js +1 -89
- package/dist/core/canvas/migrations.js +41 -1150
- package/dist/core/canvas/nav-model.js +1 -231
- package/dist/core/canvas/nav-render.js +1 -260
- package/dist/core/canvas/node-order.js +1 -37
- package/dist/core/canvas/node-recap.js +2 -67
- package/dist/core/canvas/node-sql-migration.js +2 -209
- package/dist/core/canvas/paths.js +1 -153
- package/dist/core/canvas/pid.js +4 -683
- package/dist/core/canvas/recovery.js +3 -565
- package/dist/core/canvas/remote-canvas-source.js +1 -288
- package/dist/core/canvas/remote-transport.js +1 -57
- package/dist/core/canvas/render-source.js +10 -635
- package/dist/core/canvas/sessions.js +1 -78
- package/dist/core/canvas/source.js +1 -47
- package/dist/core/canvas/status-glyph.js +1 -132
- package/dist/core/canvas/telemetry.js +1 -35
- package/dist/core/canvas/types.js +1 -6
- package/dist/core/canvas/waits.js +4 -68
- package/dist/core/canvas/worktrees.js +1 -93
- package/dist/core/clipboard-text.js +1 -57
- package/dist/core/command-hooks/artifact.js +1 -145
- package/dist/core/command-hooks/catalog.js +1 -38
- package/dist/core/command-hooks/compose.js +1 -99
- package/dist/core/command-hooks/discovery.js +1 -228
- package/dist/core/command-hooks/help.js +1 -18
- package/dist/core/command-hooks/index.js +1 -7
- package/dist/core/command-hooks/lifecycle-catalog.js +1 -9
- package/dist/core/command-hooks/lifecycle-create.js +1 -51
- package/dist/core/command-hooks/report.js +1 -28
- package/dist/core/command-hooks/schema.js +1 -157
- package/dist/core/command-hooks/transport/exec-invoke.js +1 -276
- package/dist/core/command-hooks/transport/exec-lifecycle.js +1 -211
- package/dist/core/command-manifests/manifest.js +1 -324
- package/dist/core/command-manifests/registry.js +1 -118
- package/dist/core/command-manifests/schema.js +1 -736
- package/dist/core/command-plugins/bundle.js +1 -261
- package/dist/core/command-plugins/compose.js +1 -65
- package/dist/core/command-plugins/discovery.js +1 -245
- package/dist/core/command-plugins/endpoint.js +1 -48
- package/dist/core/command-plugins/extensions.js +1 -166
- package/dist/core/command-plugins/help-addenda.js +1 -44
- package/dist/core/command-plugins/presence.js +1 -17
- package/dist/core/command-plugins/revalidate.js +2 -152
- package/dist/core/command-plugins/transport/exec-invoke.js +1 -215
- package/dist/core/command-plugins/transport/http-fetch.js +1 -68
- package/dist/core/command-plugins/transport/http-invoke.js +3 -546
- package/dist/core/command.js +10 -739
- package/dist/core/config.js +1 -1059
- package/dist/core/document-lines.js +3 -6
- package/dist/core/env-name.js +1 -9
- package/dist/core/errors.js +1 -52
- package/dist/core/events/emit.js +1 -17
- package/dist/core/events/envelope.js +1 -84
- package/dist/core/events/errors.js +1 -69
- package/dist/core/events/index.js +1 -4
- package/dist/core/events/operation-id.js +1 -24
- package/dist/core/events/read.js +1 -623
- package/dist/core/events/serialize.js +1 -199
- package/dist/core/events/source.js +1 -31
- package/dist/core/events/types.js +1 -11
- package/dist/core/exclusive-lock.js +1 -197
- package/dist/core/fault-classifier.js +1 -96
- package/dist/core/feed/feed.js +7 -202
- package/dist/core/feed/inbox-migrate.js +3 -135
- package/dist/core/feed/inbox.js +10 -122
- package/dist/core/feed/messages.js +6 -212
- package/dist/core/frontmatter.js +1 -35
- package/dist/core/fs-utils.js +3 -202
- package/dist/core/git.js +2 -103
- package/dist/core/help.js +9 -310
- package/dist/core/host-exports/builtins.js +9 -68
- package/dist/core/host-exports/export.js +3 -124
- package/dist/core/human/action-binding.js +1 -40
- package/dist/core/human/answer-text.js +5 -100
- package/dist/core/human/answer.js +1 -119
- package/dist/core/human/claim.js +3 -67
- package/dist/core/human/completion.js +1 -27
- package/dist/core/human/component-docs.js +78 -272
- package/dist/core/human/convention.js +2 -82
- package/dist/core/human/feedback-companion.js +1 -106
- package/dist/core/human/feedback.js +1 -88
- package/dist/core/human/page-authoring.js +1 -19
- package/dist/core/human/page-catalog.js +1 -172
- package/dist/core/human/page-errors.js +1 -7
- package/dist/core/human/page-eval.js +1 -125
- package/dist/core/human/page-html-markdown.js +8 -260
- package/dist/core/human/page-markdown.js +17 -295
- package/dist/core/human/page-schema.js +1 -373
- package/dist/core/human/page-synth.js +8 -27
- package/dist/core/human/page.js +1 -198
- package/dist/core/human/requests.js +15 -466
- package/dist/core/human/review-schema.js +1 -34
- package/dist/core/human/root.js +1 -11
- package/dist/core/human/scan.js +1 -69
- package/dist/core/human/summary.js +1 -5
- package/dist/core/human/tickets.js +1 -171
- package/dist/core/human/types.js +0 -1
- package/dist/core/human/visible-paths.js +1 -77
- package/dist/core/human-actions.js +1 -101
- package/dist/core/inspector/chrome.js +1 -14
- package/dist/core/inspector/contract.js +0 -1
- package/dist/core/inspector/core.js +2 -295
- package/dist/core/inspector/host.js +4 -538
- package/dist/core/inspector/model.js +2 -226
- package/dist/core/inspector/text.js +6 -45
- package/dist/core/inspector/transport.js +1 -36
- package/dist/core/inspector/tui.js +2 -295
- package/dist/core/installed-plugins.js +1 -78
- package/dist/core/io.js +7 -356
- package/dist/core/keybindings/attach-control.js +1 -42
- package/dist/core/keybindings/background-bash.js +1 -33
- package/dist/core/keybindings/catalog.js +1 -256
- package/dist/core/keybindings/inbox.js +1 -25
- package/dist/core/keybindings/index.js +1 -7
- package/dist/core/keybindings/match.js +1 -127
- package/dist/core/keybindings/persistence.js +1 -49
- package/dist/core/keybindings/resolve.js +1 -348
- package/dist/core/keybindings/types.js +0 -1
- package/dist/core/locked-file.js +1 -118
- package/dist/core/log.js +3 -27
- package/dist/core/manifest-recovery.js +1 -72
- package/dist/core/manifest-stale.js +1 -39
- package/dist/core/manifest.js +1 -20
- package/dist/core/memory/doc-link-grammar.js +2 -109
- package/dist/core/memory/extensions.js +1 -221
- package/dist/core/memory/history.js +6 -268
- package/dist/core/memory/identity.js +1 -181
- package/dist/core/memory/inline-ref-grammar.js +1 -98
- package/dist/core/memory/inline-ref-guidance.js +2 -35
- package/dist/core/memory/inline-ref-inventory.js +1 -59
- package/dist/core/memory/lint.js +2 -671
- package/dist/core/memory/project-namespace.js +2 -85
- package/dist/core/memory/repository-association.js +1 -129
- package/dist/core/memory/tree.js +1 -93
- package/dist/core/memory-resolver.js +2 -611
- package/dist/core/model-config.js +1 -107
- package/dist/core/model-routes.js +1 -201
- package/dist/core/nested-stores.js +2 -166
- package/dist/core/output.js +7 -99
- package/dist/core/pagination.js +1 -88
- package/dist/core/plugin-swap-lock.js +1 -31
- package/dist/core/pool-credential-store.js +1 -116
- package/dist/core/predicate.js +1 -191
- package/dist/core/preview-registry.js +2 -411
- package/dist/core/preview-result-path.js +1 -26
- package/dist/core/profiles/default-binding.js +1 -24
- package/dist/core/profiles/deletion-reservation.js +1 -42
- package/dist/core/profiles/env-store.js +2 -162
- package/dist/core/profiles/fuzzy-match.js +1 -92
- package/dist/core/profiles/manifest.js +1 -574
- package/dist/core/profiles/select.js +35 -741
- package/dist/core/profiles/state-block.js +3 -17
- package/dist/core/provider-error-recognition.js +1 -74
- package/dist/core/provider-failure.js +1 -86
- package/dist/core/provider-management.js +1 -22
- package/dist/core/remote-canvas-target.js +1 -30
- package/dist/core/render.js +18 -138
- package/dist/core/resolver.js +1 -111
- package/dist/core/review/birth.js +1 -52
- package/dist/core/review/comments.js +5 -279
- package/dist/core/review/companion.js +1 -215
- package/dist/core/review/document.js +2 -138
- package/dist/core/review/project.js +1 -36
- package/dist/core/review/realize.js +1 -71
- package/dist/core/review/remap.js +4 -141
- package/dist/core/review/signal.js +1 -12
- package/dist/core/review/stage.js +1 -184
- package/dist/core/review/store.js +1 -168
- package/dist/core/review/types.js +1 -23
- package/dist/core/runtime/advertised-command-invocation.js +1 -233
- package/dist/core/runtime/auth-reload.js +1 -67
- package/dist/core/runtime/banner.js +1 -51
- package/dist/core/runtime/bearings-render.js +18 -250
- package/dist/core/runtime/bearings.js +7 -194
- package/dist/core/runtime/bin-contributions.js +2 -186
- package/dist/core/runtime/boot-root.js +1 -107
- package/dist/core/runtime/branded-host.js +2 -264
- package/dist/core/runtime/broker/auth-reload.js +1 -157
- package/dist/core/runtime/broker/client-registry.js +1 -179
- package/dist/core/runtime/broker/daemon-ops.js +1 -88
- package/dist/core/runtime/broker/engine-drive.js +1 -354
- package/dist/core/runtime/broker/engine-routing.js +1 -211
- package/dist/core/runtime/broker/event-projection.js +1 -193
- package/dist/core/runtime/broker/extension-abort.js +1 -36
- package/dist/core/runtime/broker/fault-retry.js +1 -588
- package/dist/core/runtime/broker/frame-client.js +1 -132
- package/dist/core/runtime/broker/frame-dispatch.js +1 -183
- package/dist/core/runtime/broker/frame-engine-control.js +1 -231
- package/dist/core/runtime/broker/frame-memory-refs.js +1 -41
- package/dist/core/runtime/broker/frame-model-query.js +1 -69
- package/dist/core/runtime/broker/frame-read.js +1 -116
- package/dist/core/runtime/broker/frame-replies.js +1 -64
- package/dist/core/runtime/broker/frame-session.js +4 -203
- package/dist/core/runtime/broker/held-deferred-inbox.js +1 -13
- package/dist/core/runtime/broker/inbox.js +13 -163
- package/dist/core/runtime/broker/node-named.js +1 -27
- package/dist/core/runtime/broker/read-ops.js +1 -171
- package/dist/core/runtime/broker/rebind.js +1 -318
- package/dist/core/runtime/broker/tool-groups.js +1 -246
- package/dist/core/runtime/broker/turn-admission.js +1 -31
- package/dist/core/runtime/broker/turn-ignition.js +1 -84
- package/dist/core/runtime/broker-cli.js +3 -81
- package/dist/core/runtime/broker-extension-render.js +5 -135
- package/dist/core/runtime/broker-inventory.js +1 -116
- package/dist/core/runtime/broker-persona-guidance.js +4 -154
- package/dist/core/runtime/broker-protocol.js +3 -152
- package/dist/core/runtime/broker-request.js +1 -85
- package/dist/core/runtime/broker-sdk.js +1 -129
- package/dist/core/runtime/broker.js +1 -1214
- package/dist/core/runtime/canvas-extensions.js +1 -96
- package/dist/core/runtime/chat-inventory-rows.js +1 -105
- package/dist/core/runtime/close.js +1 -265
- package/dist/core/runtime/command-expansion.js +9 -104
- package/dist/core/runtime/command-surface.js +1 -117
- package/dist/core/runtime/connectivity.js +1 -73
- package/dist/core/runtime/deliver-live.js +1 -88
- package/dist/core/runtime/fault-recovery.js +1 -83
- package/dist/core/runtime/fault.js +1 -17
- package/dist/core/runtime/fleet.js +1 -58
- package/dist/core/runtime/front-door-env.js +1 -16
- package/dist/core/runtime/front-door.js +7 -183
- package/dist/core/runtime/headless-pi.js +1 -161
- package/dist/core/runtime/host.js +1 -457
- package/dist/core/runtime/interactive-deliver.js +1 -51
- package/dist/core/runtime/invocation.js +0 -10
- package/dist/core/runtime/kickoff.js +30 -327
- package/dist/core/runtime/launch-config-worker.js +1 -12
- package/dist/core/runtime/launch-prompt.js +4 -13
- package/dist/core/runtime/launch-target.js +1 -55
- package/dist/core/runtime/launch.js +1 -483
- package/dist/core/runtime/lifecycle.js +2 -213
- package/dist/core/runtime/managed-provider-cooling.js +1 -62
- package/dist/core/runtime/memory.js +1 -17
- package/dist/core/runtime/model-registry.js +1 -13
- package/dist/core/runtime/model-selection.js +1 -135
- package/dist/core/runtime/model-swap.js +1 -86
- package/dist/core/runtime/naming.js +14 -298
- package/dist/core/runtime/nerd-font.js +2 -127
- package/dist/core/runtime/node-read.js +2 -386
- package/dist/core/runtime/nodes.js +1 -331
- package/dist/core/runtime/outcome-document.js +1 -97
- package/dist/core/runtime/package-health.js +4 -99
- package/dist/core/runtime/persona.js +2 -55
- package/dist/core/runtime/pi-cli.js +1 -65
- package/dist/core/runtime/pi-vendored.js +1 -66
- package/dist/core/runtime/placement-tmux.js +1 -81
- package/dist/core/runtime/placement.js +1 -386
- package/dist/core/runtime/promote.js +1 -174
- package/dist/core/runtime/prospective-inventory-cli.js +3 -61
- package/dist/core/runtime/prospective-inventory.js +2 -88
- package/dist/core/runtime/recap.js +27 -103
- package/dist/core/runtime/recycle.js +1 -190
- package/dist/core/runtime/reopen.js +1 -138
- package/dist/core/runtime/reset.js +1 -245
- package/dist/core/runtime/resume-root.js +10 -290
- package/dist/core/runtime/revive-all.js +1 -107
- package/dist/core/runtime/revive.js +4 -544
- package/dist/core/runtime/roadmap.js +4 -38
- package/dist/core/runtime/session-branch.js +1 -46
- package/dist/core/runtime/session-cycles.js +1 -110
- package/dist/core/runtime/session-list-cache.js +1 -406
- package/dist/core/runtime/session-visibility.js +1 -99
- package/dist/core/runtime/shell-expansion.js +9 -100
- package/dist/core/runtime/situational-context.js +2 -67
- package/dist/core/runtime/situational-live.js +1 -41
- package/dist/core/runtime/spawn-env.js +1 -255
- package/dist/core/runtime/spawn.js +3 -577
- package/dist/core/runtime/stamp/channel.js +1 -76
- package/dist/core/runtime/stamp/protocol.js +1 -113
- package/dist/core/runtime/stop-guard.js +7 -116
- package/dist/core/runtime/stop-signals.js +1 -46
- package/dist/core/runtime/stream-watchdog.js +1 -134
- package/dist/core/runtime/structured-output.js +4 -156
- package/dist/core/runtime/surface-bg.js +1 -85
- package/dist/core/runtime/tmux-bindings.js +4 -730
- package/dist/core/runtime/tmux-chrome.js +1 -5
- package/dist/core/runtime/tmux-driver.js +7 -637
- package/dist/core/runtime/tool-group-summary.js +6 -85
- package/dist/core/runtime/turn-visibility.js +1 -31
- package/dist/core/runtime/view-socket.js +1 -83
- package/dist/core/runtime/warm-pool.js +1 -395
- package/dist/core/scope.js +1 -254
- package/dist/core/scoped-state/db.js +1 -135
- package/dist/core/scoped-state/migrate.js +3 -181
- package/dist/core/scoped-state/paths.js +1 -27
- package/dist/core/scoped-state/profiles.js +1 -62
- package/dist/core/scoped-state/providers.js +1 -8
- package/dist/core/scoped-state/schema.js +3 -16
- package/dist/core/scoped-state/settings.js +1 -82
- package/dist/core/secrets.js +2 -55
- package/dist/core/self-update.js +1 -71
- package/dist/core/session-model/session-state.js +1 -180
- package/dist/core/shell-segments.js +4 -169
- package/dist/core/spawn.js +1 -26
- package/dist/core/stdout-errors.js +1 -14
- package/dist/core/subscription-state.js +3 -193
- package/dist/core/substrate/frontmatter-validation.js +1 -105
- package/dist/core/substrate/gate-explain.js +1 -424
- package/dist/core/substrate/gate.js +1 -26
- package/dist/core/substrate/index.js +1 -30
- package/dist/core/substrate/injected-store.js +1 -249
- package/dist/core/substrate/listings.js +1 -115
- package/dist/core/substrate/on-read-node.js +1 -36
- package/dist/core/substrate/on-read.js +9 -315
- package/dist/core/substrate/plan.js +1 -266
- package/dist/core/substrate/render-node.js +1 -30
- package/dist/core/substrate/render.js +65 -689
- package/dist/core/substrate/schema.js +1 -186
- package/dist/core/substrate/session-cache.js +1 -83
- package/dist/core/substrate/subject-fields.js +1 -35
- package/dist/core/substrate/subject.js +1 -47
- package/dist/core/substrate/surface-match.js +1 -242
- package/dist/core/termrender/code-doc.js +5 -92
- package/dist/core/termrender/display.js +2 -56
- package/dist/core/termrender/termrender.js +14 -719
- package/dist/core/termrender/version.js +1 -1
- package/dist/core/timing.js +2 -94
- package/dist/core/tui/draw.js +2 -378
- package/dist/core/tui/fuzzy.js +1 -38
- package/dist/core/tui/markdown.js +3 -407
- package/dist/core/tui/page-host.js +1 -74
- package/dist/core/tui/panel.js +1 -137
- package/dist/core/tui/terminal.js +2 -100
- package/dist/core/user-settings.js +1 -454
- package/dist/core/wake.js +1 -296
- package/dist/core/worktree-close.js +6 -228
- package/dist/core/worktree-containment.js +3 -48
- package/dist/core/worktree-landing.js +4 -56
- package/dist/core/worktree-mutation-async.js +10 -280
- package/dist/core/worktree-quarantine.js +1 -54
- package/dist/core/worktree-sweep.js +6 -453
- package/dist/core/worktree.js +18 -899
- package/dist/daemon/api/bridge.js +8 -418
- package/dist/daemon/api/handlers/attach.js +1 -65
- package/dist/daemon/api/handlers/bash-jobs.js +2 -91
- package/dist/daemon/api/handlers/broker-ops.js +1 -447
- package/dist/daemon/api/handlers/broker-recovery.js +1 -251
- package/dist/daemon/api/handlers/canvas.js +6 -490
- package/dist/daemon/api/handlers/chat-inventory.js +1 -25
- package/dist/daemon/api/handlers/crons.js +1 -373
- package/dist/daemon/api/handlers/daemon.js +1 -76
- package/dist/daemon/api/handlers/feedback-comments.js +3 -199
- package/dist/daemon/api/handlers/files.js +1 -63
- package/dist/daemon/api/handlers/focus.js +1 -92
- package/dist/daemon/api/handlers/health.js +1 -76
- package/dist/daemon/api/handlers/human-requests.js +1 -379
- package/dist/daemon/api/handlers/human.js +1 -3
- package/dist/daemon/api/handlers/inbox-page.js +1 -89
- package/dist/daemon/api/handlers/inbox.js +1 -301
- package/dist/daemon/api/handlers/memory.js +1 -50
- package/dist/daemon/api/handlers/messages.js +2 -506
- package/dist/daemon/api/handlers/model-config.js +1 -44
- package/dist/daemon/api/handlers/modelauth.js +1 -165
- package/dist/daemon/api/handlers/node-outcomes.js +1 -181
- package/dist/daemon/api/handlers/nodes.js +1 -939
- package/dist/daemon/api/handlers/profiles.js +1 -140
- package/dist/daemon/api/handlers/prospective-chat-inventory.js +1 -59
- package/dist/daemon/api/handlers/reports.js +16 -332
- package/dist/daemon/api/handlers/review-comments.js +1 -465
- package/dist/daemon/api/handlers/reviews.js +1 -200
- package/dist/daemon/api/handlers/subscriptions.js +1 -53
- package/dist/daemon/api/handlers/validate.js +1 -58
- package/dist/daemon/api/handlers/worktree.js +1 -39
- package/dist/daemon/api/map.js +2 -735
- package/dist/daemon/api/router.js +1 -190
- package/dist/daemon/api/server.js +11 -408
- package/dist/daemon/boot-migrations.js +1 -31
- package/dist/daemon/companion-retire.js +1 -34
- package/dist/daemon/control.js +1 -22
- package/dist/daemon/cron/armed-context.js +1 -100
- package/dist/daemon/cron/capture.js +2 -45
- package/dist/daemon/cron/disposition.js +1 -55
- package/dist/daemon/cron/escalation.js +3 -124
- package/dist/daemon/cron/held.js +1 -20
- package/dist/daemon/cron/lease-recovery.js +1 -119
- package/dist/daemon/cron/live-runs.js +1 -23
- package/dist/daemon/cron/passes.js +1 -58
- package/dist/daemon/cron/settle.js +1 -61
- package/dist/daemon/cron/sinks.js +2 -59
- package/dist/daemon/cron-run.js +1 -405
- package/dist/daemon/crtrd-cli.js +1 -23
- package/dist/daemon/crtrd.js +8 -854
- package/dist/daemon/delivery/run-delivery.js +1 -164
- package/dist/daemon/fleet.js +17 -475
- package/dist/daemon/human/finish.js +10 -179
- package/dist/daemon/human/settle.js +1 -89
- package/dist/daemon/human/sweep.js +1 -66
- package/dist/daemon/manage.js +2 -595
- package/dist/daemon/messaging/node-message.js +1 -99
- package/dist/daemon/park-activity.js +1 -30
- package/dist/daemon/park-pending.js +1 -52
- package/dist/daemon/pidfile.js +1 -37
- package/dist/daemon/profile-delete.js +1 -306
- package/dist/daemon/reconcilers/bash-deadline.js +1 -80
- package/dist/daemon/reconcilers/broker-supervision.js +4 -761
- package/dist/daemon/reconcilers/controller-death.js +1 -14
- package/dist/daemon/reconcilers/cron-lane.js +1 -29
- package/dist/daemon/reconcilers/delivery-lane.js +1 -130
- package/dist/daemon/reconcilers/live-obligation.js +1 -87
- package/dist/daemon/reconcilers/managed-worktree-sweep.js +1 -202
- package/dist/daemon/reconcilers/node-deadline.js +1 -82
- package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +1 -172
- package/dist/daemon/reconcilers/node-lifecycle/respawn-policy.js +1 -59
- package/dist/daemon/reconcilers/node-lifecycle/terminating.js +1 -12
- package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -146
- package/dist/daemon/reconcilers/node-lifecycle/wants-execution.js +1 -11
- package/dist/daemon/reconcilers/pending-review-submit.js +1 -36
- package/dist/daemon/reconcilers/storage-maintenance.js +1 -207
- package/dist/daemon/review/comment-notify.js +2 -109
- package/dist/daemon/review/companion.js +1 -29
- package/dist/daemon/review/deliver.js +3 -8
- package/dist/daemon/review/finish.js +1 -122
- package/dist/daemon/review/sweep.js +1 -18
- package/dist/daemon/startup-policy.js +1 -1
- package/dist/daemon/supervise-cadence.js +1 -6
- package/dist/hook-authoring.js +5 -447
- package/dist/hook-process.js +1 -34
- package/dist/index.js +1 -52
- package/dist/migrations/001-surfaces-frontmatter.js +1 -161
- package/dist/migrations/002-profile-project-memory.js +1 -72
- package/dist/migrations/003-repository-root-memory-identity/front-door.js +11 -231
- package/dist/migrations/003-repository-root-memory-identity/index.js +5 -513
- package/dist/migrations/003-repository-root-memory-identity/references.js +5 -469
- package/dist/migrations/003-repository-root-memory-identity/repository-facts.js +3 -349
- package/dist/migrations/activation.js +2 -89
- package/dist/migrations/convergent.js +2 -82
- package/dist/migrations/corpus.js +3 -483
- package/dist/migrations/frontmatter-splice.js +8 -176
- package/dist/migrations/profile-manifests.js +2 -70
- package/dist/migrations/registry.js +1 -42
- package/dist/migrations/runner.js +1 -85
- package/dist/migrations/types.js +0 -24
- package/dist/pi-extensions/broker-local.js +2 -106
- package/dist/pi-extensions/canvas-bash-valve.js +7 -461
- package/dist/pi-extensions/canvas-context-intro.js +2 -113
- package/dist/pi-extensions/canvas-doc-substrate.js +9 -178
- package/dist/pi-extensions/canvas-goal-capture.js +1 -83
- package/dist/pi-extensions/canvas-inbox-watcher.js +1 -1010
- package/dist/pi-extensions/canvas-passive-context.js +14 -203
- package/dist/pi-extensions/canvas-preview-result.js +2 -72
- package/dist/pi-extensions/canvas-prompt-scrub.js +2 -54
- package/dist/pi-extensions/canvas-recap.js +11 -405
- package/dist/pi-extensions/canvas-review-boundary.js +3 -63
- package/dist/pi-extensions/canvas-stamp.js +2 -77
- package/dist/pi-extensions/canvas-stophook.js +1 -643
- package/dist/pi-extensions/canvas-structured-output.js +13 -35
- package/dist/pi-extensions/canvas-tool-guide.js +9 -78
- package/dist/pi-extensions/envelope-merge.js +8 -29
- package/dist/prompts/review.js +20 -42
- package/dist/shared/birth-announcement.js +1 -25
- package/dist/shared/crtr-version.js +1 -18
- package/dist/shared/env.js +1 -214
- package/dist/shared/generated-context.js +11 -226
- package/dist/shared/predicates.js +1 -4
- package/dist/shared/shell-quote.js +1 -5
- package/dist/shared/tool-groups.js +1 -64
- package/dist/shared/working-activity.js +1 -27
- package/dist/suppress-experimental-warnings.js +1 -15
- package/dist/types.js +1 -185
- package/docs/public-api.md +10 -9
- package/package.json +5 -4
- package/runtime.lock.json +5 -5
- package/dist/api/__tests__/integration/client.test.d.ts +0 -1
- package/dist/api/__tests__/integration/client.test.js +0 -163
- package/dist/builtin-pi-packages/pi-crtr-extensions/__tests__/insights-active-init.test.ts +0 -98
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/crtr-commands.test.ts +0 -93
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/integration/provider-rotation.test.ts +0 -2530
- package/dist/clients/__tests__/helpers/human-daemon.d.ts +0 -11
- package/dist/clients/__tests__/helpers/human-daemon.js +0 -60
- package/dist/clients/attach/__tests__/attach-remote-readonly.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/attach-remote-readonly.test.js +0 -97
- package/dist/clients/attach/__tests__/bash-call-width.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/bash-call-width.test.js +0 -38
- package/dist/clients/attach/__tests__/chat-view-snapshot-ordering.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/chat-view-snapshot-ordering.test.js +0 -175
- package/dist/clients/attach/__tests__/completion-frecency.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/completion-frecency.test.js +0 -35
- package/dist/clients/attach/__tests__/context-message.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/context-message.test.js +0 -130
- package/dist/clients/attach/__tests__/crtr-output.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/crtr-output.test.js +0 -68
- package/dist/clients/attach/__tests__/diagram.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/diagram.test.js +0 -42
- package/dist/clients/attach/__tests__/edit-diff.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/edit-diff.test.js +0 -31
- package/dist/clients/attach/__tests__/frame-selection.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/frame-selection.test.js +0 -84
- package/dist/clients/attach/__tests__/group-activity.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/group-activity.test.js +0 -165
- package/dist/clients/attach/__tests__/oauth-dialog-lifecycle.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/oauth-dialog-lifecycle.test.js +0 -83
- package/dist/clients/attach/__tests__/pane-tag-successor.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/pane-tag-successor.test.js +0 -56
- package/dist/clients/attach/__tests__/profile-files.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/profile-files.test.js +0 -21
- package/dist/clients/attach/__tests__/prompt-preview.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/prompt-preview.test.js +0 -21
- package/dist/clients/attach/__tests__/ref-autocomplete.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/ref-autocomplete.test.js +0 -64
- package/dist/clients/attach/__tests__/titled-editor-paste.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/titled-editor-paste.test.js +0 -114
- package/dist/clients/attach/__tests__/titled-editor-preview.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/titled-editor-preview.test.js +0 -83
- package/dist/clients/inbox/__tests__/integration/inbox-controller.test.d.ts +0 -1
- package/dist/clients/inbox/__tests__/integration/inbox-controller.test.js +0 -81
- package/dist/clients/inbox/__tests__/integration/mount-panel.test.d.ts +0 -1
- package/dist/clients/inbox/__tests__/integration/mount-panel.test.js +0 -135
- package/dist/clients/inbox/__tests__/integration/stale-row-activation.test.d.ts +0 -1
- package/dist/clients/inbox/__tests__/integration/stale-row-activation.test.js +0 -66
- package/dist/clients/inbox/review/__tests__/editor-roundtrip.test.d.ts +0 -1
- package/dist/clients/inbox/review/__tests__/editor-roundtrip.test.js +0 -35
- package/dist/clients/inbox/review/__tests__/review-core.test.d.ts +0 -1
- package/dist/clients/inbox/review/__tests__/review-core.test.js +0 -52
- package/dist/clients/inbox/review/__tests__/teardown-notice.test.d.ts +0 -1
- package/dist/clients/inbox/review/__tests__/teardown-notice.test.js +0 -100
- package/dist/commands/__tests__/api-client-cold-start-diagnostic.test.d.ts +0 -1
- package/dist/commands/__tests__/api-client-cold-start-diagnostic.test.js +0 -69
- package/dist/commands/__tests__/human.test.d.ts +0 -1
- package/dist/commands/__tests__/human.test.js +0 -172
- package/dist/commands/__tests__/integration/dashboard-snapshot.test.d.ts +0 -1
- package/dist/commands/__tests__/integration/dashboard-snapshot.test.js +0 -237
- package/dist/commands/__tests__/integration/migrate.test.d.ts +0 -1
- package/dist/commands/__tests__/integration/migrate.test.js +0 -1330
- package/dist/commands/__tests__/node-message.test.d.ts +0 -1
- package/dist/commands/__tests__/node-message.test.js +0 -112
- package/dist/commands/__tests__/node-new.test.d.ts +0 -1
- package/dist/commands/__tests__/node-new.test.js +0 -58
- package/dist/commands/__tests__/revive-now-gate.test.d.ts +0 -1
- package/dist/commands/__tests__/revive-now-gate.test.js +0 -62
- package/dist/commands/__tests__/seam/daemon-status.test.d.ts +0 -1
- package/dist/commands/__tests__/seam/daemon-status.test.js +0 -29
- package/dist/commands/__tests__/surface-reload-target.test.d.ts +0 -1
- package/dist/commands/__tests__/surface-reload-target.test.js +0 -21
- package/dist/commands/memory/__tests__/command-selector-and-mutation-guards.test.d.ts +0 -1
- package/dist/commands/memory/__tests__/command-selector-and-mutation-guards.test.js +0 -379
- package/dist/commands/memory/__tests__/memory-list-and-lint-ignore.test.d.ts +0 -1
- package/dist/commands/memory/__tests__/memory-list-and-lint-ignore.test.js +0 -124
- package/dist/commands/memory/__tests__/repository-root-lint.test.d.ts +0 -1
- package/dist/commands/memory/__tests__/repository-root-lint.test.js +0 -148
- package/dist/commands/sys/__tests__/config-model-ladders.test.d.ts +0 -1
- package/dist/commands/sys/__tests__/config-model-ladders.test.js +0 -114
- package/dist/commands/sys/__tests__/setup-core.test.d.ts +0 -1
- package/dist/commands/sys/__tests__/setup-core.test.js +0 -45
- package/dist/commands/sys/__tests__/sync-project-guidance.test.d.ts +0 -1
- package/dist/commands/sys/__tests__/sync-project-guidance.test.js +0 -244
- package/dist/core/__tests__/bash-guard.test.d.ts +0 -1
- package/dist/core/__tests__/bash-guard.test.js +0 -190
- package/dist/core/__tests__/boot-fault-attempt.test.d.ts +0 -1
- package/dist/core/__tests__/boot-fault-attempt.test.js +0 -105
- package/dist/core/__tests__/boot.test.d.ts +0 -1
- package/dist/core/__tests__/boot.test.js +0 -274
- package/dist/core/__tests__/branded-host-concurrency.test.d.ts +0 -1
- package/dist/core/__tests__/branded-host-concurrency.test.js +0 -72
- package/dist/core/__tests__/broker-extension-canvas-db-boundary.test.d.ts +0 -1
- package/dist/core/__tests__/broker-extension-canvas-db-boundary.test.js +0 -75
- package/dist/core/__tests__/broker-launch-candidates.test.d.ts +0 -1
- package/dist/core/__tests__/broker-launch-candidates.test.js +0 -311
- package/dist/core/__tests__/broker-preflight.test.d.ts +0 -1
- package/dist/core/__tests__/broker-preflight.test.js +0 -95
- package/dist/core/__tests__/broker-stream-watchdog-floor.test.d.ts +0 -1
- package/dist/core/__tests__/broker-stream-watchdog-floor.test.js +0 -82
- package/dist/core/__tests__/broker-turn-admission.test.d.ts +0 -1
- package/dist/core/__tests__/broker-turn-admission.test.js +0 -44
- package/dist/core/__tests__/canvas-db-boundary.test.d.ts +0 -1
- package/dist/core/__tests__/canvas-db-boundary.test.js +0 -46
- package/dist/core/__tests__/canvas-inbox-watcher-hold.test.d.ts +0 -1
- package/dist/core/__tests__/canvas-inbox-watcher-hold.test.js +0 -710
- package/dist/core/__tests__/canvas-inbox-watcher-naming.test.d.ts +0 -1
- package/dist/core/__tests__/canvas-inbox-watcher-naming.test.js +0 -310
- package/dist/core/__tests__/canvas-inbox-watcher.test.d.ts +0 -1
- package/dist/core/__tests__/canvas-inbox-watcher.test.js +0 -397
- package/dist/core/__tests__/canvas.test.d.ts +0 -1
- package/dist/core/__tests__/canvas.test.js +0 -138
- package/dist/core/__tests__/child-death-wake.test.d.ts +0 -1
- package/dist/core/__tests__/child-death-wake.test.js +0 -153
- package/dist/core/__tests__/cli-help-contract.test.d.ts +0 -1
- package/dist/core/__tests__/cli-help-contract.test.js +0 -152
- package/dist/core/__tests__/close.test.d.ts +0 -1
- package/dist/core/__tests__/close.test.js +0 -284
- package/dist/core/__tests__/collectible.test.d.ts +0 -1
- package/dist/core/__tests__/collectible.test.js +0 -89
- package/dist/core/__tests__/config-change-delta.test.d.ts +0 -1
- package/dist/core/__tests__/config-change-delta.test.js +0 -108
- package/dist/core/__tests__/context-intro.test.d.ts +0 -1
- package/dist/core/__tests__/context-intro.test.js +0 -123
- package/dist/core/__tests__/cron-armed-context-failure.test.d.ts +0 -1
- package/dist/core/__tests__/cron-armed-context-failure.test.js +0 -150
- package/dist/core/__tests__/cron-held-settlement.test.d.ts +0 -1
- package/dist/core/__tests__/cron-held-settlement.test.js +0 -240
- package/dist/core/__tests__/cron-node-sink-parked-root.test.d.ts +0 -1
- package/dist/core/__tests__/cron-node-sink-parked-root.test.js +0 -166
- package/dist/core/__tests__/cron-self-cancel-delivery.test.d.ts +0 -1
- package/dist/core/__tests__/cron-self-cancel-delivery.test.js +0 -84
- package/dist/core/__tests__/cron-timeout-descendants.test.d.ts +0 -1
- package/dist/core/__tests__/cron-timeout-descendants.test.js +0 -114
- package/dist/core/__tests__/daemon-boot.test.d.ts +0 -1
- package/dist/core/__tests__/daemon-boot.test.js +0 -422
- package/dist/core/__tests__/daemon-wedge.test.d.ts +0 -1
- package/dist/core/__tests__/daemon-wedge.test.js +0 -106
- package/dist/core/__tests__/dead-node-policy-table.test.d.ts +0 -1
- package/dist/core/__tests__/dead-node-policy-table.test.js +0 -77
- package/dist/core/__tests__/events-contract.test.d.ts +0 -1
- package/dist/core/__tests__/events-contract.test.js +0 -76
- package/dist/core/__tests__/extension-abort.test.d.ts +0 -1
- package/dist/core/__tests__/extension-abort.test.js +0 -21
- package/dist/core/__tests__/fault-classifier.test.d.ts +0 -1
- package/dist/core/__tests__/fault-classifier.test.js +0 -138
- package/dist/core/__tests__/fixtures/api-server-host.d.ts +0 -1
- package/dist/core/__tests__/fixtures/api-server-host.js +0 -47
- package/dist/core/__tests__/fixtures/c3-custom-provider-ext.d.ts +0 -2
- package/dist/core/__tests__/fixtures/c3-custom-provider-ext.js +0 -34
- package/dist/core/__tests__/fixtures/c5-command-boundary-ext.d.ts +0 -2
- package/dist/core/__tests__/fixtures/c5-command-boundary-ext.js +0 -32
- package/dist/core/__tests__/fixtures/fake-engine.d.ts +0 -347
- package/dist/core/__tests__/fixtures/fake-engine.js +0 -1509
- package/dist/core/__tests__/fixtures/fake-pi-host.d.ts +0 -2
- package/dist/core/__tests__/fixtures/fake-pi-host.js +0 -311
- package/dist/core/__tests__/fixtures/memory-slash-live-probe.d.ts +0 -1
- package/dist/core/__tests__/fixtures/memory-slash-live-probe.js +0 -75
- package/dist/core/__tests__/fixtures/metadata-migration-race.d.ts +0 -1
- package/dist/core/__tests__/fixtures/metadata-migration-race.js +0 -49
- package/dist/core/__tests__/focuses.test.d.ts +0 -1
- package/dist/core/__tests__/focuses.test.js +0 -113
- package/dist/core/__tests__/fs-utils.test.d.ts +0 -1
- package/dist/core/__tests__/fs-utils.test.js +0 -50
- package/dist/core/__tests__/helpers/broker-clients.d.ts +0 -43
- package/dist/core/__tests__/helpers/broker-clients.js +0 -174
- package/dist/core/__tests__/helpers/fleet.d.ts +0 -12
- package/dist/core/__tests__/helpers/fleet.js +0 -50
- package/dist/core/__tests__/helpers/harness.d.ts +0 -124
- package/dist/core/__tests__/helpers/harness.js +0 -806
- package/dist/core/__tests__/helpers/viewer-panes.d.ts +0 -12
- package/dist/core/__tests__/helpers/viewer-panes.js +0 -133
- package/dist/core/__tests__/history-inbox.test.d.ts +0 -1
- package/dist/core/__tests__/history-inbox.test.js +0 -121
- package/dist/core/__tests__/human-action-delivery.test.d.ts +0 -1
- package/dist/core/__tests__/human-action-delivery.test.js +0 -162
- package/dist/core/__tests__/human-actions.test.d.ts +0 -1
- package/dist/core/__tests__/human-actions.test.js +0 -120
- package/dist/core/__tests__/inline-memory-refs.test.d.ts +0 -1
- package/dist/core/__tests__/inline-memory-refs.test.js +0 -225
- package/dist/core/__tests__/integration/broker-fork-seam.test.d.ts +0 -1
- package/dist/core/__tests__/integration/broker-fork-seam.test.js +0 -193
- package/dist/core/__tests__/integration/broker-sdk-wiring.test.d.ts +0 -1
- package/dist/core/__tests__/integration/broker-sdk-wiring.test.js +0 -750
- package/dist/core/__tests__/integration/broker-snapshot-history.test.d.ts +0 -1
- package/dist/core/__tests__/integration/broker-snapshot-history.test.js +0 -288
- package/dist/core/__tests__/integration/broker-wedge-supervision.test.d.ts +0 -1
- package/dist/core/__tests__/integration/broker-wedge-supervision.test.js +0 -103
- package/dist/core/__tests__/integration/command-plugins.test.d.ts +0 -1
- package/dist/core/__tests__/integration/command-plugins.test.js +0 -1200
- package/dist/core/__tests__/integration/deferred-no-wake.test.d.ts +0 -1
- package/dist/core/__tests__/integration/deferred-no-wake.test.js +0 -610
- package/dist/core/__tests__/integration/flagship-lifecycle.test.d.ts +0 -1
- package/dist/core/__tests__/integration/flagship-lifecycle.test.js +0 -264
- package/dist/core/__tests__/integration/fresh-home-commands.test.d.ts +0 -1
- package/dist/core/__tests__/integration/fresh-home-commands.test.js +0 -49
- package/dist/core/__tests__/integration/git-optional-locks.test.d.ts +0 -1
- package/dist/core/__tests__/integration/git-optional-locks.test.js +0 -81
- package/dist/core/__tests__/integration/host-teardown-process-group.test.d.ts +0 -1
- package/dist/core/__tests__/integration/host-teardown-process-group.test.js +0 -480
- package/dist/core/__tests__/integration/lifecycle-hooks.test.d.ts +0 -1
- package/dist/core/__tests__/integration/lifecycle-hooks.test.js +0 -498
- package/dist/core/__tests__/integration/live-mutation-verbs.test.d.ts +0 -1
- package/dist/core/__tests__/integration/live-mutation-verbs.test.js +0 -180
- package/dist/core/__tests__/integration/live-mutation.test.d.ts +0 -1
- package/dist/core/__tests__/integration/live-mutation.test.js +0 -173
- package/dist/core/__tests__/integration/plugin-revalidate.test.d.ts +0 -1
- package/dist/core/__tests__/integration/plugin-revalidate.test.js +0 -359
- package/dist/core/__tests__/integration/profile-pause.test.d.ts +0 -1
- package/dist/core/__tests__/integration/profile-pause.test.js +0 -115
- package/dist/core/__tests__/integration/refresh-stall-recycle.test.d.ts +0 -1
- package/dist/core/__tests__/integration/refresh-stall-recycle.test.js +0 -151
- package/dist/core/__tests__/integration/revive.test.d.ts +0 -1
- package/dist/core/__tests__/integration/revive.test.js +0 -615
- package/dist/core/__tests__/integration/spawn-root.test.d.ts +0 -1
- package/dist/core/__tests__/integration/spawn-root.test.js +0 -536
- package/dist/core/__tests__/integration/subscription-delivery.test.d.ts +0 -1
- package/dist/core/__tests__/integration/subscription-delivery.test.js +0 -132
- package/dist/core/__tests__/integration/tmux-surface.test.d.ts +0 -1
- package/dist/core/__tests__/integration/tmux-surface.test.js +0 -330
- package/dist/core/__tests__/integration/worktree-land.test.d.ts +0 -1
- package/dist/core/__tests__/integration/worktree-land.test.js +0 -607
- package/dist/core/__tests__/integration/worktree-reap.test.d.ts +0 -1
- package/dist/core/__tests__/integration/worktree-reap.test.js +0 -842
- package/dist/core/__tests__/kickoff.test.d.ts +0 -1
- package/dist/core/__tests__/kickoff.test.js +0 -196
- package/dist/core/__tests__/lifecycle-terminal-reasons.test.d.ts +0 -1
- package/dist/core/__tests__/lifecycle-terminal-reasons.test.js +0 -62
- package/dist/core/__tests__/lifecycle.test.d.ts +0 -1
- package/dist/core/__tests__/lifecycle.test.js +0 -176
- package/dist/core/__tests__/live-lifecycle-prompt.test.d.ts +0 -1
- package/dist/core/__tests__/live-lifecycle-prompt.test.js +0 -63
- package/dist/core/__tests__/memory-resolver-precedence.test.d.ts +0 -1
- package/dist/core/__tests__/memory-resolver-precedence.test.js +0 -228
- package/dist/core/__tests__/migration.test.d.ts +0 -1
- package/dist/core/__tests__/migration.test.js +0 -946
- package/dist/core/__tests__/model-pin-durability.test.d.ts +0 -1
- package/dist/core/__tests__/model-pin-durability.test.js +0 -195
- package/dist/core/__tests__/model-routes-config.test.d.ts +0 -1
- package/dist/core/__tests__/model-routes-config.test.js +0 -150
- package/dist/core/__tests__/nested-store-discovery.test.d.ts +0 -1
- package/dist/core/__tests__/nested-store-discovery.test.js +0 -89
- package/dist/core/__tests__/node-outcome.test.d.ts +0 -1
- package/dist/core/__tests__/node-outcome.test.js +0 -246
- package/dist/core/__tests__/on-read-crouter-home-fence.test.d.ts +0 -1
- package/dist/core/__tests__/on-read-crouter-home-fence.test.js +0 -66
- package/dist/core/__tests__/on-read-dedup-resume.test.d.ts +0 -1
- package/dist/core/__tests__/on-read-dedup-resume.test.js +0 -132
- package/dist/core/__tests__/on-read-nested-store.test.d.ts +0 -1
- package/dist/core/__tests__/on-read-nested-store.test.js +0 -135
- package/dist/core/__tests__/parse-argv-stdin-secret.test.d.ts +0 -1
- package/dist/core/__tests__/parse-argv-stdin-secret.test.js +0 -68
- package/dist/core/__tests__/passive-subscription.test.d.ts +0 -1
- package/dist/core/__tests__/passive-subscription.test.js +0 -120
- package/dist/core/__tests__/pid-identity-match.test.d.ts +0 -1
- package/dist/core/__tests__/pid-identity-match.test.js +0 -145
- package/dist/core/__tests__/pid-zombie.test.d.ts +0 -1
- package/dist/core/__tests__/pid-zombie.test.js +0 -42
- package/dist/core/__tests__/plugin-kinds.test.d.ts +0 -1
- package/dist/core/__tests__/plugin-kinds.test.js +0 -182
- package/dist/core/__tests__/plugin-link-symlinked-scope-root.test.d.ts +0 -1
- package/dist/core/__tests__/plugin-link-symlinked-scope-root.test.js +0 -43
- package/dist/core/__tests__/plugin-page-components.test.d.ts +0 -1
- package/dist/core/__tests__/plugin-page-components.test.js +0 -159
- package/dist/core/__tests__/preview-mirror-cap.test.d.ts +0 -1
- package/dist/core/__tests__/preview-mirror-cap.test.js +0 -53
- package/dist/core/__tests__/preview-registry-sync.test.d.ts +0 -1
- package/dist/core/__tests__/preview-registry-sync.test.js +0 -107
- package/dist/core/__tests__/profile-project-memory-delivery.test.d.ts +0 -1
- package/dist/core/__tests__/profile-project-memory-delivery.test.js +0 -644
- package/dist/core/__tests__/prospective-inventory-capability-parity.test.d.ts +0 -1
- package/dist/core/__tests__/prospective-inventory-capability-parity.test.js +0 -91
- package/dist/core/__tests__/prune.test.d.ts +0 -1
- package/dist/core/__tests__/prune.test.js +0 -243
- package/dist/core/__tests__/push-final-guard.test.d.ts +0 -1
- package/dist/core/__tests__/push-final-guard.test.js +0 -191
- package/dist/core/__tests__/relaunch-root.test.d.ts +0 -1
- package/dist/core/__tests__/relaunch-root.test.js +0 -249
- package/dist/core/__tests__/remote-canvas-target.test.d.ts +0 -1
- package/dist/core/__tests__/remote-canvas-target.test.js +0 -93
- package/dist/core/__tests__/repository-association.test.d.ts +0 -1
- package/dist/core/__tests__/repository-association.test.js +0 -153
- package/dist/core/__tests__/repository-root-identity.test.d.ts +0 -1
- package/dist/core/__tests__/repository-root-identity.test.js +0 -223
- package/dist/core/__tests__/respawn-throttle.test.d.ts +0 -1
- package/dist/core/__tests__/respawn-throttle.test.js +0 -20
- package/dist/core/__tests__/review-model-floor.test.d.ts +0 -1
- package/dist/core/__tests__/review-model-floor.test.js +0 -83
- package/dist/core/__tests__/revive-all.test.d.ts +0 -1
- package/dist/core/__tests__/revive-all.test.js +0 -157
- package/dist/core/__tests__/revive-capacity.test.d.ts +0 -1
- package/dist/core/__tests__/revive-capacity.test.js +0 -184
- package/dist/core/__tests__/revive-parked-fresh.test.d.ts +0 -1
- package/dist/core/__tests__/revive-parked-fresh.test.js +0 -176
- package/dist/core/__tests__/scope-crouter-home-fence.test.d.ts +0 -1
- package/dist/core/__tests__/scope-crouter-home-fence.test.js +0 -55
- package/dist/core/__tests__/seam/broker-attach-multiclient.test.d.ts +0 -1
- package/dist/core/__tests__/seam/broker-attach-multiclient.test.js +0 -262
- package/dist/core/__tests__/seam/broker-attach-stream.test.d.ts +0 -1
- package/dist/core/__tests__/seam/broker-attach-stream.test.js +0 -176
- package/dist/core/__tests__/seam/broker-cap-freeze.test.d.ts +0 -1
- package/dist/core/__tests__/seam/broker-cap-freeze.test.js +0 -155
- package/dist/core/__tests__/seam/broker-crash-teardown.test.d.ts +0 -1
- package/dist/core/__tests__/seam/broker-crash-teardown.test.js +0 -131
- package/dist/core/__tests__/seam/broker-pane-resolution.test.d.ts +0 -1
- package/dist/core/__tests__/seam/broker-pane-resolution.test.js +0 -204
- package/dist/core/__tests__/seam/broker-provider-retry.test.d.ts +0 -1
- package/dist/core/__tests__/seam/broker-provider-retry.test.js +0 -686
- package/dist/core/__tests__/seam/broker-startup-diagnostics.test.d.ts +0 -1
- package/dist/core/__tests__/seam/broker-startup-diagnostics.test.js +0 -82
- package/dist/core/__tests__/seam/broker-whip-interrupt.test.d.ts +0 -1
- package/dist/core/__tests__/seam/broker-whip-interrupt.test.js +0 -50
- package/dist/core/__tests__/seam/deadline-wake-delivery.test.d.ts +0 -1
- package/dist/core/__tests__/seam/deadline-wake-delivery.test.js +0 -138
- package/dist/core/__tests__/seam/dormancy-release.test.d.ts +0 -1
- package/dist/core/__tests__/seam/dormancy-release.test.js +0 -516
- package/dist/core/__tests__/seam/held-deferred-human-prompt.test.d.ts +0 -1
- package/dist/core/__tests__/seam/held-deferred-human-prompt.test.js +0 -65
- package/dist/core/__tests__/seam/inbox-reference-guidance.test.d.ts +0 -1
- package/dist/core/__tests__/seam/inbox-reference-guidance.test.js +0 -84
- package/dist/core/__tests__/seam/memory-slash-node-relative-inventory.test.d.ts +0 -1
- package/dist/core/__tests__/seam/memory-slash-node-relative-inventory.test.js +0 -160
- package/dist/core/__tests__/seam/node-outcome-delivery.test.d.ts +0 -1
- package/dist/core/__tests__/seam/node-outcome-delivery.test.js +0 -177
- package/dist/core/__tests__/seam/prospective-inventory-stdout.test.d.ts +0 -1
- package/dist/core/__tests__/seam/prospective-inventory-stdout.test.js +0 -31
- package/dist/core/__tests__/seam/reopen-invalidated-worktree.test.d.ts +0 -1
- package/dist/core/__tests__/seam/reopen-invalidated-worktree.test.js +0 -60
- package/dist/core/__tests__/seam/self-close-teardown.test.d.ts +0 -1
- package/dist/core/__tests__/seam/self-close-teardown.test.js +0 -49
- package/dist/core/__tests__/seam/yield-refresh-transaction.test.d.ts +0 -1
- package/dist/core/__tests__/seam/yield-refresh-transaction.test.js +0 -100
- package/dist/core/__tests__/secrets.test.d.ts +0 -1
- package/dist/core/__tests__/secrets.test.js +0 -49
- package/dist/core/__tests__/self-update.test.d.ts +0 -1
- package/dist/core/__tests__/self-update.test.js +0 -46
- package/dist/core/__tests__/session-branch.test.d.ts +0 -1
- package/dist/core/__tests__/session-branch.test.js +0 -61
- package/dist/core/__tests__/session-cycles.test.d.ts +0 -1
- package/dist/core/__tests__/session-cycles.test.js +0 -133
- package/dist/core/__tests__/session-model.test.d.ts +0 -1
- package/dist/core/__tests__/session-model.test.js +0 -111
- package/dist/core/__tests__/spawn-worktree-id-conflict.test.d.ts +0 -1
- package/dist/core/__tests__/spawn-worktree-id-conflict.test.js +0 -71
- package/dist/core/__tests__/stdin-body-no-discard.test.d.ts +0 -1
- package/dist/core/__tests__/stdin-body-no-discard.test.js +0 -33
- package/dist/core/__tests__/stdout-errors.test.d.ts +0 -1
- package/dist/core/__tests__/stdout-errors.test.js +0 -16
- package/dist/core/__tests__/stop-guard.test.d.ts +0 -1
- package/dist/core/__tests__/stop-guard.test.js +0 -237
- package/dist/core/__tests__/stream-watchdog.test.d.ts +0 -1
- package/dist/core/__tests__/stream-watchdog.test.js +0 -154
- package/dist/core/__tests__/subscription-pool-credential-guard.test.d.ts +0 -1
- package/dist/core/__tests__/subscription-pool-credential-guard.test.js +0 -95
- package/dist/core/__tests__/tmux-driver-boundary.test.d.ts +0 -1
- package/dist/core/__tests__/tmux-driver-boundary.test.js +0 -50
- package/dist/core/__tests__/warm-claim-preference-snapshot.test.d.ts +0 -1
- package/dist/core/__tests__/warm-claim-preference-snapshot.test.js +0 -54
- package/dist/core/__tests__/worktree-landing.test.d.ts +0 -1
- package/dist/core/__tests__/worktree-landing.test.js +0 -11
- package/dist/core/__tests__/yield-ensures-daemon.test.d.ts +0 -1
- package/dist/core/__tests__/yield-ensures-daemon.test.js +0 -55
- package/dist/core/broker-client/__tests__/transport-relay.test.d.ts +0 -1
- package/dist/core/broker-client/__tests__/transport-relay.test.js +0 -214
- package/dist/core/broker-client/__tests__/transport-socket.test.d.ts +0 -1
- package/dist/core/broker-client/__tests__/transport-socket.test.js +0 -73
- package/dist/core/canvas/__tests__/attention.test.d.ts +0 -1
- package/dist/core/canvas/__tests__/attention.test.js +0 -83
- package/dist/core/canvas/__tests__/history-transcript.test.d.ts +0 -1
- package/dist/core/canvas/__tests__/history-transcript.test.js +0 -102
- package/dist/core/canvas/__tests__/remote-canvas-source.test.d.ts +0 -1
- package/dist/core/canvas/__tests__/remote-canvas-source.test.js +0 -328
- package/dist/core/canvas/__tests__/remote-transport.test.d.ts +0 -1
- package/dist/core/canvas/__tests__/remote-transport.test.js +0 -97
- package/dist/core/canvas/__tests__/render-remote.test.d.ts +0 -1
- package/dist/core/canvas/__tests__/render-remote.test.js +0 -243
- package/dist/core/canvas/__tests__/session-window.test.d.ts +0 -1
- package/dist/core/canvas/__tests__/session-window.test.js +0 -70
- package/dist/core/feed/__tests__/inbox-migrate.test.d.ts +0 -1
- package/dist/core/feed/__tests__/inbox-migrate.test.js +0 -49
- package/dist/core/human/__tests__/page-catalog.test.d.ts +0 -1
- package/dist/core/human/__tests__/page-catalog.test.js +0 -20
- package/dist/core/human/__tests__/page-html-markdown.test.d.ts +0 -1
- package/dist/core/human/__tests__/page-html-markdown.test.js +0 -48
- package/dist/core/human/__tests__/page.test.d.ts +0 -1
- package/dist/core/human/__tests__/page.test.js +0 -92
- package/dist/core/keybindings/__tests__/resolve.test.d.ts +0 -1
- package/dist/core/keybindings/__tests__/resolve.test.js +0 -171
- package/dist/core/profiles/__tests__/env-store.test.d.ts +0 -1
- package/dist/core/profiles/__tests__/env-store.test.js +0 -99
- package/dist/core/profiles/__tests__/fuzzy-match.test.d.ts +0 -1
- package/dist/core/profiles/__tests__/fuzzy-match.test.js +0 -51
- package/dist/core/profiles/__tests__/root-profile.test.d.ts +0 -1
- package/dist/core/profiles/__tests__/root-profile.test.js +0 -59
- package/dist/core/review/__tests__/capture-origin.test.d.ts +0 -1
- package/dist/core/review/__tests__/capture-origin.test.js +0 -150
- package/dist/core/review/__tests__/comments.test.d.ts +0 -1
- package/dist/core/review/__tests__/comments.test.js +0 -116
- package/dist/core/review/__tests__/remap.test.d.ts +0 -1
- package/dist/core/review/__tests__/remap.test.js +0 -177
- package/dist/core/review/__tests__/stage-identity.test.d.ts +0 -1
- package/dist/core/review/__tests__/stage-identity.test.js +0 -150
- package/dist/core/runtime/__tests__/engine-route.test.d.ts +0 -1
- package/dist/core/runtime/__tests__/engine-route.test.js +0 -36
- package/dist/core/runtime/__tests__/install-id-cache-scoping.test.d.ts +0 -1
- package/dist/core/runtime/__tests__/install-id-cache-scoping.test.js +0 -45
- package/dist/core/runtime/__tests__/node-env.test.d.ts +0 -1
- package/dist/core/runtime/__tests__/node-env.test.js +0 -73
- package/dist/core/runtime/__tests__/spawn-env.test.d.ts +0 -1
- package/dist/core/runtime/__tests__/spawn-env.test.js +0 -259
- package/dist/core/substrate/__tests__/surface-match-command.test.d.ts +0 -1
- package/dist/core/substrate/__tests__/surface-match-command.test.js +0 -89
- package/dist/core/substrate/__tests__/surface-match-memory-read.test.d.ts +0 -1
- package/dist/core/substrate/__tests__/surface-match-memory-read.test.js +0 -28
- package/dist/core/substrate/__tests__/surface-match-pre-command.test.d.ts +0 -1
- package/dist/core/substrate/__tests__/surface-match-pre-command.test.js +0 -92
- package/dist/daemon/__tests__/autostart-storm.test.d.ts +0 -1
- package/dist/daemon/__tests__/autostart-storm.test.js +0 -128
- package/dist/daemon/__tests__/broker-ownership.test.d.ts +0 -1
- package/dist/daemon/__tests__/broker-ownership.test.js +0 -25
- package/dist/daemon/__tests__/daemon-ownership.test.d.ts +0 -1
- package/dist/daemon/__tests__/daemon-ownership.test.js +0 -27
- package/dist/daemon/__tests__/helpers/source-daemon.d.ts +0 -30
- package/dist/daemon/__tests__/helpers/source-daemon.js +0 -176
- package/dist/daemon/__tests__/integration/api-startup-readiness.test.d.ts +0 -1
- package/dist/daemon/__tests__/integration/api-startup-readiness.test.js +0 -83
- package/dist/daemon/__tests__/integration/migration-startup.test.d.ts +0 -1
- package/dist/daemon/__tests__/integration/migration-startup.test.js +0 -127
- package/dist/daemon/__tests__/node-deadline-lane.test.d.ts +0 -1
- package/dist/daemon/__tests__/node-deadline-lane.test.js +0 -77
- package/dist/daemon/__tests__/node-outcome-birth-invariants.test.d.ts +0 -1
- package/dist/daemon/__tests__/node-outcome-birth-invariants.test.js +0 -146
- package/dist/daemon/__tests__/node-outcome-delivery.test.d.ts +0 -1
- package/dist/daemon/__tests__/node-outcome-delivery.test.js +0 -116
- package/dist/daemon/__tests__/reconciler-signature.test.d.ts +0 -1
- package/dist/daemon/__tests__/reconciler-signature.test.js +0 -37
- package/dist/daemon/__tests__/subtree-filter-freshness.test.d.ts +0 -1
- package/dist/daemon/__tests__/subtree-filter-freshness.test.js +0 -63
- package/dist/daemon/__tests__/thaw-order.test.d.ts +0 -1
- package/dist/daemon/__tests__/thaw-order.test.js +0 -55
- package/dist/daemon/api/__tests__/bridge-heartbeat.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/bridge-heartbeat.test.js +0 -58
- package/dist/daemon/api/__tests__/broker-settle-park.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/broker-settle-park.test.js +0 -175
- package/dist/daemon/api/__tests__/canvas-snapshot-fields.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/canvas-snapshot-fields.test.js +0 -216
- package/dist/daemon/api/__tests__/error-seam.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/error-seam.test.js +0 -83
- package/dist/daemon/api/__tests__/model-config.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/model-config.test.js +0 -73
- package/dist/daemon/api/__tests__/node-create-description.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/node-create-description.test.js +0 -127
- package/dist/daemon/api/__tests__/node-model-validation.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/node-model-validation.test.js +0 -183
- package/dist/daemon/api/__tests__/nodes-activity-query.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/nodes-activity-query.test.js +0 -99
- package/dist/daemon/api/__tests__/profile-launch-gates.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/profile-launch-gates.test.js +0 -172
- package/dist/daemon/api/__tests__/profile-metadata-route.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/profile-metadata-route.test.js +0 -95
- package/dist/daemon/api/__tests__/reopen-delivery.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/reopen-delivery.test.js +0 -260
- package/dist/daemon/api/__tests__/seam/api-server.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/seam/api-server.test.js +0 -442
- package/dist/daemon/api/__tests__/seam/b10-attach-modelauth.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/seam/b10-attach-modelauth.test.js +0 -310
- package/dist/daemon/api/__tests__/seam/leaf-api-parity.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/seam/leaf-api-parity.test.js +0 -351
- package/dist/daemon/api/__tests__/seam/node-outcome-api.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/seam/node-outcome-api.test.js +0 -159
- package/dist/daemon/api/__tests__/seam/profile-delete.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/seam/profile-delete.test.js +0 -372
- package/dist/daemon/api/__tests__/submit-result.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/submit-result.test.js +0 -215
- package/dist/migrations/__tests__/activation-concurrency.test.d.ts +0 -1
- package/dist/migrations/__tests__/activation-concurrency.test.js +0 -146
- package/dist/migrations/__tests__/activation.test.d.ts +0 -1
- package/dist/migrations/__tests__/activation.test.js +0 -152
- package/dist/migrations/__tests__/deletion-and-root-declaration.test.d.ts +0 -1
- package/dist/migrations/__tests__/deletion-and-root-declaration.test.js +0 -149
- package/dist/pi-extensions/__tests__/canvas-bash-valve.test.d.ts +0 -1
- package/dist/pi-extensions/__tests__/canvas-bash-valve.test.js +0 -86
- package/dist/pi-extensions/__tests__/canvas-context-intro.test.d.ts +0 -1
- package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +0 -364
- package/dist/pi-extensions/__tests__/canvas-goal-capture-envelope.test.d.ts +0 -1
- package/dist/pi-extensions/__tests__/canvas-goal-capture-envelope.test.js +0 -106
- package/dist/pi-extensions/__tests__/canvas-recap.test.d.ts +0 -1
- package/dist/pi-extensions/__tests__/canvas-recap.test.js +0 -62
- package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.d.ts +0 -1
- package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +0 -432
- package/dist/pi-extensions/__tests__/canvas-stophook-context-nudge.test.d.ts +0 -1
- package/dist/pi-extensions/__tests__/canvas-stophook-context-nudge.test.js +0 -152
- package/dist/pi-extensions/__tests__/canvas-structured-output.test.d.ts +0 -1
- package/dist/pi-extensions/__tests__/canvas-structured-output.test.js +0 -88
- package/dist/pi-extensions/__tests__/canvas-tool-guide.test.d.ts +0 -1
- package/dist/pi-extensions/__tests__/canvas-tool-guide.test.js +0 -96
- package/dist/pi-extensions/__tests__/integration/canvas-bash-valve.test.d.ts +0 -1
- package/dist/pi-extensions/__tests__/integration/canvas-bash-valve.test.js +0 -133
- package/dist/pi-extensions/__tests__/pre-command-gate.test.d.ts +0 -1
- package/dist/pi-extensions/__tests__/pre-command-gate.test.js +0 -232
- package/dist/shared/__tests__/env-boundary.test.d.ts +0 -1
- package/dist/shared/__tests__/env-boundary.test.js +0 -95
- package/dist/shared/__tests__/generated-context-grammar.test.d.ts +0 -1
- package/dist/shared/__tests__/generated-context-grammar.test.js +0 -80
- package/docs/compat/hearth-crtr-v1.md +0 -179
- package/docs/compat/hearth-crtr-v2.md +0 -177
- package/docs/compat/hearth-crtr-v3.md +0 -176
- package/docs/compat/hearth-crtr-v4.md +0 -182
- package/docs/compat/hearth-crtr-v5.md +0 -169
|
@@ -1,1200 +0,0 @@
|
|
|
1
|
-
// Contract-seam tests for the external command-plugin seam (Phase 1).
|
|
2
|
-
// Run with: npm run test:integration
|
|
3
|
-
//
|
|
4
|
-
// All tests run against an ISOLATED home (HOME → a fresh temp dir, no ambient
|
|
5
|
-
// user plugins) and pass an explicit no-`.crouter` startDir, so discovery is
|
|
6
|
-
// deterministic and cannot pick up the developer's real machine state.
|
|
7
|
-
//
|
|
8
|
-
// Covers the spec's Tests items:
|
|
9
|
-
// 1. Registry composition — a fixture top-level branch + leaf composes into
|
|
10
|
-
// real BranchDef/LeafDef whose root/branch/leaf help carries the plugin's
|
|
11
|
-
// representations, schema, effects, and stable order.
|
|
12
|
-
// 2. Core collision — a fixture claiming a SUBTREE_NAMES name is skipped +
|
|
13
|
-
// recorded as a command_collision issue; plugin collisions keep both
|
|
14
|
-
// commands under origin-qualified names.
|
|
15
|
-
// 3. Scope/shadowing — a project copy shadows a user copy of the same plugin
|
|
16
|
-
// name; a disabled project copy suppresses the user copy.
|
|
17
|
-
// 4. Protocol integration (table-driven, one fixture executable) — request
|
|
18
|
-
// envelope contents, rendered success, --json mirror, stderr separation,
|
|
19
|
-
// recoverable error propagation, and every malformed case.
|
|
20
|
-
// 5. Lifecycle without restart — install/disable/edit/remove all take effect
|
|
21
|
-
// on the next discovery call (per-invocation, no cache).
|
|
22
|
-
// 6/7. Typed issues for path/exec-bit/schema/unknown-key violations and nested
|
|
23
|
-
// mount composition without executing the fixture binary.
|
|
24
|
-
import { test, describe, before, after, beforeEach, afterEach } from 'node:test';
|
|
25
|
-
import assert from 'node:assert/strict';
|
|
26
|
-
import { mkdtempSync, mkdirSync, writeFileSync, rmSync, chmodSync, existsSync, lstatSync, realpathSync } from 'node:fs';
|
|
27
|
-
import { readFileSync } from 'node:fs';
|
|
28
|
-
import { execFileSync } from 'node:child_process';
|
|
29
|
-
import { tmpdir } from 'node:os';
|
|
30
|
-
import { join, dirname } from 'node:path';
|
|
31
|
-
import { fileURLToPath } from 'node:url';
|
|
32
|
-
import { discoverCommandContributions, effectiveCommandPlugins, validatePluginCommands, buildExternalCommandSnapshot, } from '../../command-plugins/discovery.js';
|
|
33
|
-
import { composeExternalSubtrees, adaptPluginContributions } from '../../command-plugins/compose.js';
|
|
34
|
-
import { collectHelpAddenda } from '../../command-plugins/help-addenda.js';
|
|
35
|
-
import { resolveCommandRegistry } from '../../command-manifests/registry.js';
|
|
36
|
-
import { defineRoot } from '../../command.js';
|
|
37
|
-
import { renderRoot, renderBranch, renderLeafArgv } from '../../help.js';
|
|
38
|
-
import { renderResult } from '../../render.js';
|
|
39
|
-
import { CrtrError } from '../../errors.js';
|
|
40
|
-
import { resetScopeCache } from '../../scope.js';
|
|
41
|
-
import { readConfig, updateRawConfigAtomically, writeRawConfig } from '../../config.js';
|
|
42
|
-
import { closeScopedStores } from '../../scoped-state/db.js';
|
|
43
|
-
import { initializeFreshScopedStore } from '../../scoped-state/migrate.js';
|
|
44
|
-
import { createProfile } from '../../profiles/manifest.js';
|
|
45
|
-
import { listInstalledPluginsInRoot } from '../../resolver.js';
|
|
46
|
-
import { pluginShow } from '../../../commands/pkg/plugin-inspect.js';
|
|
47
|
-
import { pluginDisable, pluginEnable, pluginInstall, pluginUpdate } from '../../../commands/pkg/plugin-manage.js';
|
|
48
|
-
import { runCommandPluginChecks } from '../../../commands/sys/doctor.js';
|
|
49
|
-
// The set of reserved core names discovery must fail closed against. We don't
|
|
50
|
-
// import the real SUBTREE_NAMES (build-root.ts pulls the whole tree); a small
|
|
51
|
-
// explicit set is enough for the collision contract and keeps the test cheap.
|
|
52
|
-
const RESERVED = new Set(['push', 'node', 'canvas', 'sys', 'memory']);
|
|
53
|
-
// Fixture executable: reads one JSON request on stdin, writes one envelope.
|
|
54
|
-
// Behavior is selected by req.input.mode so one binary drives the whole table.
|
|
55
|
-
const FIXTURE_EXEC = `#!/usr/bin/env node
|
|
56
|
-
const fs = require('fs');
|
|
57
|
-
let data = '';
|
|
58
|
-
process.stdin.on('data', (c) => (data += c));
|
|
59
|
-
process.stdin.on('end', () => {
|
|
60
|
-
const req = JSON.parse(data);
|
|
61
|
-
const log = process.env.FIXTURE_REQUEST_LOG;
|
|
62
|
-
if (log) fs.writeFileSync(log, JSON.stringify(req));
|
|
63
|
-
const mode = (req.input && req.input.mode) || 'ok';
|
|
64
|
-
const env = (o, code) => { process.stdout.write(JSON.stringify(o)); process.exit(code); };
|
|
65
|
-
if (mode === 'invalid-json') { process.stdout.write('this is not json'); process.exit(0); }
|
|
66
|
-
if (mode === 'extra-stdout') { process.stdout.write(JSON.stringify({ protocolVersion: 1, ok: true, result: { app_id: 'x' } }) + '\\nEXTRA JUNK'); process.exit(0); }
|
|
67
|
-
if (mode === 'oversize') { process.stdout.write('x'.repeat(11 * 1024 * 1024)); process.exit(0); }
|
|
68
|
-
if (mode === 'signal') { process.kill(process.pid, 'SIGKILL'); return; }
|
|
69
|
-
if (mode === 'error') return env({ protocolVersion: 1, ok: false, error: { code: 'authentication_required', message: 'No home session is available.', field: 'session', next: 'Log in, then retry.' } }, 1);
|
|
70
|
-
if (mode === 'reserved-code') return env({ protocolVersion: 1, ok: false, error: { code: 'internal', message: 'boom' } }, 1);
|
|
71
|
-
if (mode === 'missing-field') return env({ protocolVersion: 1, ok: true, result: { status: 'running' } }, 0);
|
|
72
|
-
if (mode === 'exit-mismatch') return env({ protocolVersion: 1, ok: true, result: { app_id: req.input.appId, status: 'running' } }, 3);
|
|
73
|
-
if (mode === 'diag') { process.stderr.write('a diagnostic line on stderr\\n'); return env({ protocolVersion: 1, ok: true, result: { app_id: req.input.appId, status: 'running' } }, 0); }
|
|
74
|
-
return env({ protocolVersion: 1, ok: true, result: { app_id: req.input.appId, status: 'running' } }, 0);
|
|
75
|
-
});
|
|
76
|
-
`;
|
|
77
|
-
function commandsJson(topName = 'app') {
|
|
78
|
-
return {
|
|
79
|
-
schemaVersion: 1,
|
|
80
|
-
mounts: [
|
|
81
|
-
{
|
|
82
|
-
parent: [],
|
|
83
|
-
node: {
|
|
84
|
-
kind: 'branch',
|
|
85
|
-
name: topName,
|
|
86
|
-
description: 'application lifecycle and inspection',
|
|
87
|
-
whenToUse: 'you need to create, deploy, inspect, or remove an application',
|
|
88
|
-
rootEntry: {
|
|
89
|
-
concept: 'applications hosted by a crouter home',
|
|
90
|
-
description: 'application lifecycle and inspection',
|
|
91
|
-
whenToUse: 'you need to create, deploy, inspect, or remove an application',
|
|
92
|
-
},
|
|
93
|
-
summary: 'application lifecycle and inspection',
|
|
94
|
-
model: 'Applications are product resources owned by the selected home.',
|
|
95
|
-
children: [
|
|
96
|
-
{
|
|
97
|
-
kind: 'leaf',
|
|
98
|
-
name: 'show',
|
|
99
|
-
description: 'show one application',
|
|
100
|
-
whenToUse: 'inspect a single application by id',
|
|
101
|
-
tier: 'important',
|
|
102
|
-
summary: 'show one application details',
|
|
103
|
-
params: [
|
|
104
|
-
{ kind: 'positional', name: 'app-id', required: true, constraint: 'the application id' },
|
|
105
|
-
{ kind: 'flag', name: 'mode', type: 'string', required: false, constraint: 'fixture behavior selector' },
|
|
106
|
-
],
|
|
107
|
-
output: [
|
|
108
|
-
{ name: 'app_id', type: 'string', required: true, constraint: 'the echoed application id' },
|
|
109
|
-
{ name: 'status', type: 'string', required: false, constraint: 'current application status' },
|
|
110
|
-
],
|
|
111
|
-
outputKind: 'object',
|
|
112
|
-
effects: ['None. Read-only.'],
|
|
113
|
-
},
|
|
114
|
-
],
|
|
115
|
-
},
|
|
116
|
-
},
|
|
117
|
-
],
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
function humanCommandsJson(parent = ['human'], name = 'pr') {
|
|
121
|
-
return {
|
|
122
|
-
schemaVersion: 1,
|
|
123
|
-
helpAddenda: { human: 'Pull request review commands are provided by this plugin.' },
|
|
124
|
-
mounts: [{
|
|
125
|
-
parent,
|
|
126
|
-
node: {
|
|
127
|
-
kind: 'branch',
|
|
128
|
-
name,
|
|
129
|
-
description: 'pull request review',
|
|
130
|
-
whenToUse: 'a person needs to review a pull request',
|
|
131
|
-
summary: 'review a pull request with a person',
|
|
132
|
-
children: [{
|
|
133
|
-
kind: 'leaf',
|
|
134
|
-
name: 'review',
|
|
135
|
-
description: 'start pull request review',
|
|
136
|
-
whenToUse: 'the pull request is ready for review',
|
|
137
|
-
summary: 'start one pull request review',
|
|
138
|
-
params: [{ kind: 'flag', name: 'app-id', type: 'string', required: true, constraint: 'fixture pull request id' }],
|
|
139
|
-
output: [{ name: 'app_id', type: 'string', required: true, constraint: 'echoed fixture pull request id' }, { name: 'status', type: 'string', required: false, constraint: 'fixture status' }],
|
|
140
|
-
outputKind: 'object',
|
|
141
|
-
effects: ['None. Read-only.'],
|
|
142
|
-
}],
|
|
143
|
-
},
|
|
144
|
-
}],
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
function extensibleDemoCommandsJson(extensible = true) {
|
|
148
|
-
return {
|
|
149
|
-
schemaVersion: 1,
|
|
150
|
-
mounts: [{
|
|
151
|
-
parent: [],
|
|
152
|
-
node: {
|
|
153
|
-
kind: 'branch',
|
|
154
|
-
name: 'demo',
|
|
155
|
-
description: 'fixture extensible branch',
|
|
156
|
-
whenToUse: 'testing repository command contributions',
|
|
157
|
-
...(extensible ? { extensible: true } : {}),
|
|
158
|
-
rootEntry: { concept: 'fixture command contributions', description: 'fixture extensible branch', whenToUse: 'testing repository command contributions' },
|
|
159
|
-
summary: 'fixture extensible branch',
|
|
160
|
-
children: [{ kind: 'branch', name: 'built-in', description: 'plugin-owned branch', whenToUse: 'using the plugin-owned command', summary: 'plugin-owned branch', children: [] }],
|
|
161
|
-
},
|
|
162
|
-
}],
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
function extensionFragment(rootName = 'repo-branch') {
|
|
166
|
-
return {
|
|
167
|
-
schemaVersion: 1,
|
|
168
|
-
transport: { kind: 'exec', executable: 'scripts/extension.js' },
|
|
169
|
-
mounts: [
|
|
170
|
-
{ parent: [], node: { kind: 'branch', name: rootName, description: 'repository branch', whenToUse: 'using repository-defined commands', summary: 'repository branch', children: [] } },
|
|
171
|
-
{ parent: [rootName], node: { kind: 'leaf', name: 'run', description: 'run repository operation', whenToUse: 'testing extension execution', summary: 'run repository operation', params: [{ kind: 'flag', name: 'thing', type: 'string', required: true, constraint: 'fixture input' }], output: [{ name: 'value', type: 'string', required: true, constraint: 'echoed fixture input' }], outputKind: 'object', effects: ['None. Read-only.'] } },
|
|
172
|
-
],
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
const EXTENSION_EXEC = `#!/usr/bin/env node
|
|
176
|
-
const fs = require('fs');
|
|
177
|
-
let data = '';
|
|
178
|
-
process.stdin.on('data', (chunk) => data += chunk);
|
|
179
|
-
process.stdin.on('end', () => {
|
|
180
|
-
const request = JSON.parse(data);
|
|
181
|
-
if (process.env.EXTENSION_REQUEST_LOG) fs.writeFileSync(process.env.EXTENSION_REQUEST_LOG, JSON.stringify(request));
|
|
182
|
-
if (process.env.EXTENSION_SENTINEL) fs.writeFileSync(process.env.EXTENSION_SENTINEL, 'executed');
|
|
183
|
-
process.stdout.write(JSON.stringify({ protocolVersion: 1, ok: true, result: { value: request.input.thing } }));
|
|
184
|
-
});
|
|
185
|
-
`;
|
|
186
|
-
function passthroughCommandsJson(bin = 'capture') {
|
|
187
|
-
return {
|
|
188
|
-
schemaVersion: 1,
|
|
189
|
-
mounts: [{
|
|
190
|
-
parent: [],
|
|
191
|
-
node: {
|
|
192
|
-
kind: 'branch',
|
|
193
|
-
name: 'capture',
|
|
194
|
-
description: 'browser automation',
|
|
195
|
-
whenToUse: 'driving a browser through the Capture CLI',
|
|
196
|
-
rootEntry: {
|
|
197
|
-
concept: 'browser automation',
|
|
198
|
-
description: 'browser automation through Capture',
|
|
199
|
-
whenToUse: 'driving a browser through the Capture CLI',
|
|
200
|
-
},
|
|
201
|
-
summary: 'browser automation through Capture',
|
|
202
|
-
passthrough: { bin, installHint: 'Install @crouton-kit/capture globally.' },
|
|
203
|
-
children: [],
|
|
204
|
-
},
|
|
205
|
-
}],
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
/** Write a plugin into `scopeRoot/plugins/<name>/` with a command manifest +
|
|
209
|
-
* executable. `manifest` is the commands.json object (default fixture). */
|
|
210
|
-
function installPlugin(scopeRoot, name, opts = {}) {
|
|
211
|
-
const root = join(scopeRoot, 'plugins', name);
|
|
212
|
-
mkdirSync(join(root, '.crouter-plugin'), { recursive: true });
|
|
213
|
-
mkdirSync(join(root, 'bin'), { recursive: true });
|
|
214
|
-
const pointer = opts.commandsPointer ?? 'commands.json';
|
|
215
|
-
writeFileSync(join(root, '.crouter-plugin', 'plugin.json'), JSON.stringify({
|
|
216
|
-
name,
|
|
217
|
-
version: '0.1.0',
|
|
218
|
-
description: 'fixture',
|
|
219
|
-
commands: pointer,
|
|
220
|
-
transport: { kind: 'exec', ...(opts.executable === null ? {} : { executable: opts.executable ?? 'bin/cmd.js' }) },
|
|
221
|
-
}));
|
|
222
|
-
writeFileSync(join(root, 'commands.json'), JSON.stringify(opts.manifest ?? commandsJson()));
|
|
223
|
-
const execPath = join(root, 'bin', 'cmd.js');
|
|
224
|
-
writeFileSync(execPath, opts.exec ?? FIXTURE_EXEC);
|
|
225
|
-
chmodSync(execPath, opts.execBit === false ? 0o644 : 0o755);
|
|
226
|
-
const config = {
|
|
227
|
-
...(opts.enabled === false ? { enabled: false } : {}),
|
|
228
|
-
...(opts.sourceMarketplace !== undefined ? { source_marketplace: opts.sourceMarketplace } : {}),
|
|
229
|
-
};
|
|
230
|
-
if (Object.keys(config).length > 0) {
|
|
231
|
-
if (scopeRoot === userRoot) {
|
|
232
|
-
updateRawConfigAtomically('user', (raw) => ({ ...raw, plugins: { ...raw.plugins, [name]: config } }));
|
|
233
|
-
}
|
|
234
|
-
else {
|
|
235
|
-
writeFileSync(join(scopeRoot, 'config.json'), JSON.stringify({ plugins: { [name]: config } }));
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
return root;
|
|
239
|
-
}
|
|
240
|
-
// Isolated home + workspace
|
|
241
|
-
let home; // becomes HOME → user scope root = $HOME/.crouter
|
|
242
|
-
let userRoot;
|
|
243
|
-
let projectDir; // a workspace with its own .crouter (project scope)
|
|
244
|
-
let projectRoot;
|
|
245
|
-
let emptyStart; // a startDir with NO .crouter anywhere above it
|
|
246
|
-
let realHome;
|
|
247
|
-
let realProfile;
|
|
248
|
-
before(() => {
|
|
249
|
-
realHome = process.env['HOME'];
|
|
250
|
-
realProfile = process.env['CRTR_PROFILE_ID'];
|
|
251
|
-
delete process.env['CRTR_PROFILE_ID'];
|
|
252
|
-
});
|
|
253
|
-
after(() => {
|
|
254
|
-
if (realHome !== undefined)
|
|
255
|
-
process.env['HOME'] = realHome;
|
|
256
|
-
else
|
|
257
|
-
delete process.env['HOME'];
|
|
258
|
-
if (realProfile !== undefined)
|
|
259
|
-
process.env['CRTR_PROFILE_ID'] = realProfile;
|
|
260
|
-
});
|
|
261
|
-
// Every temp dir any test mints, so cleanup removes them ALL (an
|
|
262
|
-
// after(...[home, ...]) would only see the LAST test's set and leak the rest).
|
|
263
|
-
const tempDirs = [];
|
|
264
|
-
function mintDir(prefix) {
|
|
265
|
-
const d = realpathSync(mkdtempSync(join(tmpdir(), prefix)));
|
|
266
|
-
tempDirs.push(d);
|
|
267
|
-
return d;
|
|
268
|
-
}
|
|
269
|
-
beforeEach(() => {
|
|
270
|
-
home = mintDir('crtr-cmdplugin-home-');
|
|
271
|
-
process.env['HOME'] = home;
|
|
272
|
-
userRoot = join(home, '.crouter');
|
|
273
|
-
initializeFreshScopedStore({ kind: 'user', root: userRoot });
|
|
274
|
-
mkdirSync(join(userRoot, 'plugins'), { recursive: true });
|
|
275
|
-
projectDir = mintDir('crtr-cmdplugin-proj-');
|
|
276
|
-
projectRoot = join(projectDir, '.crouter');
|
|
277
|
-
mkdirSync(join(projectRoot, 'plugins'), { recursive: true });
|
|
278
|
-
emptyStart = mintDir('crtr-cmdplugin-empty-');
|
|
279
|
-
resetScopeCache();
|
|
280
|
-
});
|
|
281
|
-
after(() => {
|
|
282
|
-
closeScopedStores();
|
|
283
|
-
for (const d of tempDirs) {
|
|
284
|
-
try {
|
|
285
|
-
rmSync(d, { recursive: true, force: true });
|
|
286
|
-
}
|
|
287
|
-
catch { /* ignore */ }
|
|
288
|
-
}
|
|
289
|
-
resetScopeCache();
|
|
290
|
-
});
|
|
291
|
-
function installExtensionFixture(manifest = extensionFragment()) {
|
|
292
|
-
installPlugin(userRoot, 'extension-fixture', { manifest: extensibleDemoCommandsJson() });
|
|
293
|
-
const commandsDir = join(projectRoot, 'commands');
|
|
294
|
-
const scriptsDir = join(projectDir, 'scripts');
|
|
295
|
-
mkdirSync(commandsDir, { recursive: true });
|
|
296
|
-
mkdirSync(scriptsDir, { recursive: true });
|
|
297
|
-
const fragmentPath = join(commandsDir, 'demo.json');
|
|
298
|
-
const executable = join(scriptsDir, 'extension.js');
|
|
299
|
-
writeFileSync(fragmentPath, JSON.stringify(manifest));
|
|
300
|
-
writeFileSync(executable, EXTENSION_EXEC);
|
|
301
|
-
chmodSync(executable, 0o755);
|
|
302
|
-
return { fragmentPath, executable };
|
|
303
|
-
}
|
|
304
|
-
function extensionBranch(startDir = projectDir, name = 'demo') {
|
|
305
|
-
resetScopeCache();
|
|
306
|
-
const snapshot = buildExternalCommandSnapshot(RESERVED, startDir);
|
|
307
|
-
const branch = composeExternalSubtrees(snapshot).find((node) => node.name === name);
|
|
308
|
-
assert.ok(branch, `expected the extensible ${name} branch`);
|
|
309
|
-
return branch;
|
|
310
|
-
}
|
|
311
|
-
function leafOf(branch, name) {
|
|
312
|
-
const c = branch.children.find((x) => x.name === name);
|
|
313
|
-
assert.ok(c !== undefined && c.kind === 'leaf', `expected leaf ${name}`);
|
|
314
|
-
return c;
|
|
315
|
-
}
|
|
316
|
-
// 1. Registry composition
|
|
317
|
-
describe('registry composition', () => {
|
|
318
|
-
test('a fixture top-level branch composes with plugin-owned help, schema, effects, stable order', () => {
|
|
319
|
-
installPlugin(userRoot, 'deploy-tools');
|
|
320
|
-
resetScopeCache();
|
|
321
|
-
const snapshot = discoverCommandContributions(RESERVED, emptyStart);
|
|
322
|
-
// user scope is discovered from any startDir (it's not a project ancestor).
|
|
323
|
-
assert.equal(snapshot.issues.length, 0, JSON.stringify(snapshot.issues));
|
|
324
|
-
const registrySnapshot = adaptPluginContributions(snapshot.contributions);
|
|
325
|
-
const external = composeExternalSubtrees(registrySnapshot);
|
|
326
|
-
assert.equal(external.length, 1);
|
|
327
|
-
const app = external[0];
|
|
328
|
-
assert.equal(app.kind, 'branch');
|
|
329
|
-
assert.equal(app.name, 'app');
|
|
330
|
-
// Root help carries the plugin-owned rootEntry (mapped description→desc,
|
|
331
|
-
// whenToUse→useWhen), no core file knows what an app is.
|
|
332
|
-
const root = defineRoot({ tagline: 'test', globals: [], subtrees: external });
|
|
333
|
-
const rootOut = renderRoot(root.help);
|
|
334
|
-
assert.match(rootOut, /<command name="app">/);
|
|
335
|
-
assert.match(rootOut, /applications hosted by a crouter home/);
|
|
336
|
-
assert.match(rootOut, /use when you need to create, deploy, inspect, or remove an application/);
|
|
337
|
-
// important child promoted into root with its shortform desc.
|
|
338
|
-
assert.match(rootOut, /app show {2,}show one application/);
|
|
339
|
-
// Branch help lists the leaf via its own description/whenToUse.
|
|
340
|
-
const branchOut = renderBranch(app.help);
|
|
341
|
-
assert.match(branchOut, /<command name="app" description="application lifecycle and inspection">/);
|
|
342
|
-
assert.match(branchOut, /Applications are product resources owned by the selected home\./);
|
|
343
|
-
assert.match(branchOut, /name="show"[^>]*whenToUse="inspect a single application by id"/);
|
|
344
|
-
// Leaf help carries the full input/output schema + effects.
|
|
345
|
-
const leaf = leafOf(app, 'show');
|
|
346
|
-
const leafOut = renderLeafArgv(leaf.help);
|
|
347
|
-
assert.match(leafOut, /APP-ID/);
|
|
348
|
-
assert.match(leafOut, /--mode MODE/);
|
|
349
|
-
assert.match(leafOut, /app_id {2,}string\. the echoed application id/);
|
|
350
|
-
assert.match(leafOut, /None\. Read-only\./);
|
|
351
|
-
});
|
|
352
|
-
});
|
|
353
|
-
describe('extensible core mounts', () => {
|
|
354
|
-
test('a plugin mounts under human in real help and dispatch receives the full path', async () => {
|
|
355
|
-
installPlugin(userRoot, 'pr-review', { manifest: humanCommandsJson() });
|
|
356
|
-
resetScopeCache();
|
|
357
|
-
const { resolveRoot } = await import('../../../build-root.js');
|
|
358
|
-
const { runCli } = await import('../../command.js');
|
|
359
|
-
const root = await resolveRoot('human');
|
|
360
|
-
const chunks = [];
|
|
361
|
-
const realWrite = process.stdout.write.bind(process.stdout);
|
|
362
|
-
const realCwd = process.cwd();
|
|
363
|
-
const requestLog = join(emptyStart, 'human-mount-request.json');
|
|
364
|
-
process.env['FIXTURE_REQUEST_LOG'] = requestLog;
|
|
365
|
-
process.chdir(emptyStart);
|
|
366
|
-
process.stdout.write = ((chunk) => {
|
|
367
|
-
chunks.push(String(chunk));
|
|
368
|
-
return true;
|
|
369
|
-
});
|
|
370
|
-
try {
|
|
371
|
-
await runCli(root, ['node', 'crtr', 'human', '-h']);
|
|
372
|
-
await runCli(root, ['node', 'crtr', 'human', 'pr', 'review', '--app-id', '42', '--json']);
|
|
373
|
-
}
|
|
374
|
-
finally {
|
|
375
|
-
process.stdout.write = realWrite;
|
|
376
|
-
process.chdir(realCwd);
|
|
377
|
-
delete process.env['FIXTURE_REQUEST_LOG'];
|
|
378
|
-
}
|
|
379
|
-
assert.match(chunks.join(''), /name="pr"[^>]*plugin="pr-review"/);
|
|
380
|
-
assert.match(chunks.join(''), /<plugin-help plugin="pr-review">/);
|
|
381
|
-
assert.deepEqual(JSON.parse(readFileSync(requestLog, 'utf8')).command, ['human', 'pr', 'review']);
|
|
382
|
-
});
|
|
383
|
-
test('plugin installation accepts a human mount', async () => {
|
|
384
|
-
const source = join(mintDir('crtr-human-mount-source-'), 'fixture');
|
|
385
|
-
mkdirSync(join(source, '.crouter-plugin'), { recursive: true });
|
|
386
|
-
mkdirSync(join(source, 'bin'), { recursive: true });
|
|
387
|
-
writeFileSync(join(source, '.crouter-plugin', 'plugin.json'), JSON.stringify({ name: 'human-mount-install', version: '0.1.0', description: 'fixture', commands: 'commands.json', transport: { kind: 'exec', executable: 'bin/cmd.js' } }));
|
|
388
|
-
writeFileSync(join(source, 'commands.json'), JSON.stringify(humanCommandsJson()));
|
|
389
|
-
writeFileSync(join(source, 'bin', 'cmd.js'), FIXTURE_EXEC);
|
|
390
|
-
chmodSync(join(source, 'bin', 'cmd.js'), 0o755);
|
|
391
|
-
await pluginInstall.run({ installRef: source, scope: 'user' });
|
|
392
|
-
});
|
|
393
|
-
test('only explicitly extensible core branches accept mounts and core children win collisions', () => {
|
|
394
|
-
const node = listInstalledPluginsInRoot('user', userRoot);
|
|
395
|
-
installPlugin(userRoot, 'wrong-parent', { manifest: humanCommandsJson(['node']) });
|
|
396
|
-
installPlugin(userRoot, 'core-child', { manifest: humanCommandsJson(['human'], 'send') });
|
|
397
|
-
resetScopeCache();
|
|
398
|
-
const plugins = listInstalledPluginsInRoot('user', userRoot);
|
|
399
|
-
const options = { reserved: new Set(['human', 'node']), paths: new Set(['human', 'human send']), extensible: new Set(['human']) };
|
|
400
|
-
const wrongParent = validatePluginCommands(plugins.find((plugin) => plugin.name === 'wrong-parent'), options.reserved, options.paths, options.extensible);
|
|
401
|
-
const coreChild = validatePluginCommands(plugins.find((plugin) => plugin.name === 'core-child'), options.reserved, options.paths, options.extensible);
|
|
402
|
-
assert.equal(wrongParent.contributions.length, 0);
|
|
403
|
-
assert.match(wrongParent.issues[0]?.next ?? '', /extensible core branches: human/);
|
|
404
|
-
assert.equal(coreChild.contributions.length, 0);
|
|
405
|
-
assert.match(coreChild.issues[0]?.message ?? '', /conflicts with a child the extensible core branch already owns/);
|
|
406
|
-
assert.equal(node.length, 0);
|
|
407
|
-
});
|
|
408
|
-
});
|
|
409
|
-
// 2. Core collision
|
|
410
|
-
describe('core collision', () => {
|
|
411
|
-
test('a fixture claiming a core top-level name is skipped + recorded', () => {
|
|
412
|
-
installPlugin(userRoot, 'rogue', { manifest: commandsJson('push') });
|
|
413
|
-
resetScopeCache();
|
|
414
|
-
const candidates = discoverCommandContributions(new Set(), emptyStart);
|
|
415
|
-
const registrySnapshot = resolveCommandRegistry(adaptPluginContributions(candidates.contributions).contributions, RESERVED);
|
|
416
|
-
assert.equal(composeExternalSubtrees(registrySnapshot).length, 0, 'the colliding branch must not enter the tree');
|
|
417
|
-
const collision = registrySnapshot.issues.find((i) => i.code === 'command_collision');
|
|
418
|
-
assert.ok(collision, 'a command_collision issue must be recorded for doctor/show');
|
|
419
|
-
assert.equal(collision.path, 'push');
|
|
420
|
-
assert.equal(collision.contributor.name, 'rogue');
|
|
421
|
-
});
|
|
422
|
-
});
|
|
423
|
-
// 3. Scope / shadowing
|
|
424
|
-
describe('scope shadowing', () => {
|
|
425
|
-
test('a project copy shadows a user copy of the same plugin name', () => {
|
|
426
|
-
installPlugin(userRoot, 'deploy-tools');
|
|
427
|
-
installPlugin(projectRoot, 'deploy-tools');
|
|
428
|
-
resetScopeCache();
|
|
429
|
-
const effective = effectiveCommandPlugins(projectDir);
|
|
430
|
-
assert.equal(effective.length, 1);
|
|
431
|
-
assert.equal(effective[0].scope, 'project');
|
|
432
|
-
assert.equal(effective[0].root, join(projectRoot, 'plugins', 'deploy-tools'));
|
|
433
|
-
});
|
|
434
|
-
test('a disabled project copy suppresses the user copy (no resurfacing)', () => {
|
|
435
|
-
installPlugin(userRoot, 'deploy-tools');
|
|
436
|
-
installPlugin(projectRoot, 'deploy-tools', { enabled: false });
|
|
437
|
-
resetScopeCache();
|
|
438
|
-
// sanity: the project copy really is disabled at that root.
|
|
439
|
-
const projPlugins = listInstalledPluginsInRoot('project', projectRoot);
|
|
440
|
-
assert.equal(projPlugins.find((p) => p.name === 'deploy-tools').enabled, false);
|
|
441
|
-
const effective = effectiveCommandPlugins(projectDir);
|
|
442
|
-
assert.equal(effective.length, 0, 'the disabled higher-precedence copy must suppress the user copy');
|
|
443
|
-
});
|
|
444
|
-
});
|
|
445
|
-
// 4. Protocol integration (table-driven)
|
|
446
|
-
describe('protocol integration', () => {
|
|
447
|
-
function showLeaf() {
|
|
448
|
-
installPlugin(userRoot, 'deploy-tools');
|
|
449
|
-
resetScopeCache();
|
|
450
|
-
const snapshot = discoverCommandContributions(RESERVED, emptyStart);
|
|
451
|
-
const registrySnapshot = adaptPluginContributions(snapshot.contributions);
|
|
452
|
-
const app = composeExternalSubtrees(registrySnapshot)[0];
|
|
453
|
-
return leafOf(app, 'show');
|
|
454
|
-
}
|
|
455
|
-
test('request envelope carries command path, camelCase input, cwd, plugin context', async () => {
|
|
456
|
-
const leaf = showLeaf();
|
|
457
|
-
const log = join(emptyStart, 'req.json');
|
|
458
|
-
process.env['FIXTURE_REQUEST_LOG'] = log;
|
|
459
|
-
try {
|
|
460
|
-
await leaf.run({ appId: 'app_123', mode: 'ok' });
|
|
461
|
-
const req = JSON.parse(readFileSync(log, 'utf8'));
|
|
462
|
-
assert.equal(req.protocolVersion, 1);
|
|
463
|
-
assert.deepEqual(req.command, ['app', 'show']);
|
|
464
|
-
assert.equal(req.input.appId, 'app_123');
|
|
465
|
-
assert.equal(req.context.cwd, process.cwd());
|
|
466
|
-
assert.equal(req.context.plugin.name, 'deploy-tools');
|
|
467
|
-
assert.equal(req.context.plugin.scope, 'user');
|
|
468
|
-
assert.equal(req.context.plugin.version, '0.1.0');
|
|
469
|
-
assert.equal(req.context.plugin.root, join(userRoot, 'plugins', 'deploy-tools'));
|
|
470
|
-
}
|
|
471
|
-
finally {
|
|
472
|
-
delete process.env['FIXTURE_REQUEST_LOG'];
|
|
473
|
-
}
|
|
474
|
-
});
|
|
475
|
-
test('ok:true → result validated + rendered; --json mirrors the same object', async () => {
|
|
476
|
-
const leaf = showLeaf();
|
|
477
|
-
const result = await leaf.run({ appId: 'app_123', mode: 'ok' });
|
|
478
|
-
assert.deepEqual(result, { app_id: 'app_123', status: 'running' });
|
|
479
|
-
// Rendered through the existing generic renderer (no custom renderer).
|
|
480
|
-
const rendered = renderResult(result, leaf.help);
|
|
481
|
-
assert.match(rendered, /app_id/);
|
|
482
|
-
assert.match(rendered, /app_123/);
|
|
483
|
-
});
|
|
484
|
-
test('valid envelope + wrong exit code is honored (soft diagnostic, not a discard)', async () => {
|
|
485
|
-
const leaf = showLeaf();
|
|
486
|
-
const result = await leaf.run({ appId: 'app_123', mode: 'exit-mismatch' });
|
|
487
|
-
assert.deepEqual(result, { app_id: 'app_123', status: 'running' });
|
|
488
|
-
});
|
|
489
|
-
test('stderr diagnostics do not pollute the stdout envelope', async () => {
|
|
490
|
-
const leaf = showLeaf();
|
|
491
|
-
const result = await leaf.run({ appId: 'app_123', mode: 'diag' });
|
|
492
|
-
assert.deepEqual(result, { app_id: 'app_123', status: 'running' });
|
|
493
|
-
});
|
|
494
|
-
test('ok:false → structured CrtrError with the plugin code', async () => {
|
|
495
|
-
const leaf = showLeaf();
|
|
496
|
-
await assert.rejects(() => leaf.run({ appId: 'app_123', mode: 'error' }), (e) => e instanceof CrtrError && e.code === 'authentication_required' && (e.details?.['next'] === 'Log in, then retry.'));
|
|
497
|
-
});
|
|
498
|
-
const malformed = [
|
|
499
|
-
['invalid JSON', 'invalid-json'],
|
|
500
|
-
['extra stdout after the envelope', 'extra-stdout'],
|
|
501
|
-
['oversize stdout (>10 MiB)', 'oversize'],
|
|
502
|
-
['signal termination', 'signal'],
|
|
503
|
-
['missing declared output field', 'missing-field'],
|
|
504
|
-
['reserved error code', 'reserved-code'],
|
|
505
|
-
];
|
|
506
|
-
for (const [desc, mode] of malformed) {
|
|
507
|
-
test(`malformed: ${desc} → plugin_protocol_error`, async () => {
|
|
508
|
-
const leaf = showLeaf();
|
|
509
|
-
await assert.rejects(() => leaf.run({ appId: 'app_123', mode }), (e) => e instanceof CrtrError && e.code === 'plugin_protocol_error');
|
|
510
|
-
});
|
|
511
|
-
}
|
|
512
|
-
});
|
|
513
|
-
const CLI = join(dirname(fileURLToPath(import.meta.url)), '..', '..', '..', '..', 'dist', 'cli.js');
|
|
514
|
-
// 4b. True end-to-end CLI invocation (argv → parseArgv → adapter → renderer)
|
|
515
|
-
describe('end-to-end CLI invocation', () => {
|
|
516
|
-
// dist/cli.js is up 4 from src/core/__tests__/integration/. Requires a prior
|
|
517
|
-
// `npm run build` (the harness/CI builds before tests). Drives the WHOLE seam: the
|
|
518
|
-
// declared positional `app-id` must arrive as `appId` in the request, and
|
|
519
|
-
// the rendered + --json outputs come through the real dispatcher.
|
|
520
|
-
const runCrtr = (args) => {
|
|
521
|
-
installPlugin(userRoot, 'deploy-tools');
|
|
522
|
-
resetScopeCache();
|
|
523
|
-
return execFileSync(process.execPath, [CLI, ...args], {
|
|
524
|
-
cwd: emptyStart,
|
|
525
|
-
env: { ...process.env, HOME: home, CRTR_FRONT_DOOR: '' },
|
|
526
|
-
encoding: 'utf8',
|
|
527
|
-
});
|
|
528
|
-
};
|
|
529
|
-
test('crtr app show <id> renders the plugin result end to end', { timeout: 40000 }, () => {
|
|
530
|
-
const out = runCrtr(['app', 'show', 'app_123']);
|
|
531
|
-
assert.match(out, /app_123/);
|
|
532
|
-
assert.match(out, /running/);
|
|
533
|
-
});
|
|
534
|
-
test('--json mirrors the same result object', { timeout: 40000 }, () => {
|
|
535
|
-
const out = runCrtr(['app', 'show', 'app_123', '--json']);
|
|
536
|
-
const obj = JSON.parse(out);
|
|
537
|
-
assert.equal(obj.app_id, 'app_123');
|
|
538
|
-
assert.equal(obj.status, 'running');
|
|
539
|
-
});
|
|
540
|
-
});
|
|
541
|
-
// Passthrough paths resolve inside their plugin during discovery. Bare names are
|
|
542
|
-
// deliberately left for the invoking process's PATH.
|
|
543
|
-
describe('passthrough binary resolution', () => {
|
|
544
|
-
function runPassthrough(args, env = process.env) {
|
|
545
|
-
return execFileSync(process.execPath, [CLI, ...args], {
|
|
546
|
-
cwd: emptyStart,
|
|
547
|
-
env: { ...env, HOME: home, CRTR_FRONT_DOOR: '' },
|
|
548
|
-
encoding: 'utf8',
|
|
549
|
-
});
|
|
550
|
-
}
|
|
551
|
-
test('a plugin-relative bin runs the plugin program', () => {
|
|
552
|
-
const root = installPlugin(userRoot, 'passthrough-fixture', { manifest: passthroughCommandsJson('bin/passthrough.js'), executable: null });
|
|
553
|
-
const program = join(root, 'bin', 'passthrough.js');
|
|
554
|
-
writeFileSync(program, '#!/bin/sh\nprintf "plugin program: %s\\n" "$*"\n');
|
|
555
|
-
chmodSync(program, 0o755);
|
|
556
|
-
const validation = validatePluginCommands(listInstalledPluginsInRoot('user', userRoot).find((plugin) => plugin.name === 'passthrough-fixture'), RESERVED);
|
|
557
|
-
assert.equal(validation.issues.length, 0, JSON.stringify(validation.issues));
|
|
558
|
-
assert.equal(validation.contributions[0].node.passthrough?.bin, realpathSync(program));
|
|
559
|
-
assert.equal(runPassthrough(['capture', 'one', '--two']).trim(), 'plugin program: one --two');
|
|
560
|
-
});
|
|
561
|
-
test('a bare bin runs the program from PATH', () => {
|
|
562
|
-
installPlugin(userRoot, 'passthrough-fixture', { manifest: passthroughCommandsJson('capture-fixture'), executable: null });
|
|
563
|
-
const pathDir = mintDir('crtr-cmdplugin-path-');
|
|
564
|
-
const program = join(pathDir, 'capture-fixture');
|
|
565
|
-
writeFileSync(program, '#!/bin/sh\nprintf "PATH program: %s\\n" "$*"\n');
|
|
566
|
-
chmodSync(program, 0o755);
|
|
567
|
-
const validation = validatePluginCommands(listInstalledPluginsInRoot('user', userRoot).find((plugin) => plugin.name === 'passthrough-fixture'), RESERVED);
|
|
568
|
-
assert.equal(validation.issues.length, 0, JSON.stringify(validation.issues));
|
|
569
|
-
assert.equal(validation.contributions[0].node.passthrough?.bin, 'capture-fixture');
|
|
570
|
-
assert.equal(runPassthrough(['capture', 'three'], { ...process.env, PATH: `${pathDir}:${process.env['PATH'] ?? ''}` }).trim(), 'PATH program: three');
|
|
571
|
-
});
|
|
572
|
-
});
|
|
573
|
-
// Extensible plugin command branches — repository fragments attach to a marked
|
|
574
|
-
// top-level branch as one native forest and stay entirely inside the existing
|
|
575
|
-
// parser/help/exec contract.
|
|
576
|
-
describe('extensible plugin command branches', () => {
|
|
577
|
-
test('merges native help, executes with extension context, and mirrors JSON', async () => {
|
|
578
|
-
const { fragmentPath } = installExtensionFixture();
|
|
579
|
-
const branch = extensionBranch();
|
|
580
|
-
const help = renderBranch(branch.help);
|
|
581
|
-
assert.match(help, /<command name="demo"/);
|
|
582
|
-
assert.match(help, /<subcommand name="built-in"/);
|
|
583
|
-
assert.match(help, /<subcommand name="repo-branch"[^>]*subcommands="1"/);
|
|
584
|
-
assert.ok(help.indexOf('name="built-in"') < help.indexOf('name="repo-branch"'));
|
|
585
|
-
assert.equal((help.match(/<command name=/g) ?? []).length, 1);
|
|
586
|
-
const repoBranch = branch.children.find((child) => child.name === 'repo-branch');
|
|
587
|
-
assert.ok(repoBranch !== undefined && repoBranch.kind === 'branch');
|
|
588
|
-
const leaf = leafOf(repoBranch, 'run');
|
|
589
|
-
const leafHelp = renderLeafArgv(leaf.help);
|
|
590
|
-
assert.match(leafHelp, /^demo repo-branch run: run repository operation\./);
|
|
591
|
-
assert.match(leafHelp, /Input/);
|
|
592
|
-
assert.match(leafHelp, /Output \(fields carried in the rendered result\)/);
|
|
593
|
-
assert.match(leafHelp, /Effects/);
|
|
594
|
-
const requestLog = join(projectDir, 'extension-request.json');
|
|
595
|
-
process.env['EXTENSION_REQUEST_LOG'] = requestLog;
|
|
596
|
-
const priorCwd = process.cwd();
|
|
597
|
-
process.chdir(projectDir);
|
|
598
|
-
try {
|
|
599
|
-
assert.deepEqual(await leaf.run({ thing: 'x' }), { value: 'x' });
|
|
600
|
-
}
|
|
601
|
-
finally {
|
|
602
|
-
process.chdir(priorCwd);
|
|
603
|
-
delete process.env['EXTENSION_REQUEST_LOG'];
|
|
604
|
-
}
|
|
605
|
-
const request = JSON.parse(readFileSync(requestLog, 'utf8'));
|
|
606
|
-
assert.deepEqual(request.command, ['demo', 'repo-branch', 'run']);
|
|
607
|
-
assert.deepEqual(request.input, { thing: 'x' });
|
|
608
|
-
assert.deepEqual(request.context.extension, { branch: 'demo', root: projectDir });
|
|
609
|
-
assert.equal(request.context.plugin, undefined);
|
|
610
|
-
const root = defineRoot({ tagline: 'test', globals: [], subtrees: [branch] });
|
|
611
|
-
assert.match(renderRoot(root.help), /\[\+2 subcommands — `crtr demo -h`\]/);
|
|
612
|
-
assert.equal(existsSync(join(projectDir, 'EXECUTED')), false);
|
|
613
|
-
assert.ok(existsSync(fragmentPath));
|
|
614
|
-
});
|
|
615
|
-
test('uses a collision-qualified branch name for fragment discovery, doctor, and exec context', async () => {
|
|
616
|
-
installPlugin(userRoot, 'first', { manifest: extensibleDemoCommandsJson() });
|
|
617
|
-
installPlugin(userRoot, 'second', { manifest: extensibleDemoCommandsJson() });
|
|
618
|
-
const commandsDir = join(projectRoot, 'commands');
|
|
619
|
-
const scriptsDir = join(projectDir, 'scripts');
|
|
620
|
-
mkdirSync(commandsDir, { recursive: true });
|
|
621
|
-
mkdirSync(scriptsDir, { recursive: true });
|
|
622
|
-
writeFileSync(join(commandsDir, 'first:demo.json'), JSON.stringify(extensionFragment()));
|
|
623
|
-
writeFileSync(join(scriptsDir, 'extension.js'), EXTENSION_EXEC);
|
|
624
|
-
chmodSync(join(scriptsDir, 'extension.js'), 0o755);
|
|
625
|
-
const first = extensionBranch(projectDir, 'first:demo');
|
|
626
|
-
const second = extensionBranch(projectDir, 'second:demo');
|
|
627
|
-
assert.ok(first.children.some((child) => child.name === 'repo-branch'));
|
|
628
|
-
assert.ok(!second.children.some((child) => child.name === 'repo-branch'));
|
|
629
|
-
const repoBranch = first.children.find((child) => child.name === 'repo-branch');
|
|
630
|
-
assert.ok(repoBranch !== undefined && repoBranch.kind === 'branch');
|
|
631
|
-
const requestLog = join(projectDir, 'collision-extension-request.json');
|
|
632
|
-
process.env['EXTENSION_REQUEST_LOG'] = requestLog;
|
|
633
|
-
const priorCwd = process.cwd();
|
|
634
|
-
process.chdir(projectDir);
|
|
635
|
-
try {
|
|
636
|
-
assert.deepEqual(await leafOf(repoBranch, 'run').run({ thing: 'x' }), { value: 'x' });
|
|
637
|
-
const checks = await runCommandPluginChecks(['project']);
|
|
638
|
-
const extension = checks.find((check) => check.name === 'extension:first:demo');
|
|
639
|
-
assert.ok(extension, JSON.stringify(checks));
|
|
640
|
-
assert.equal(extension.status, 'pass');
|
|
641
|
-
}
|
|
642
|
-
finally {
|
|
643
|
-
process.chdir(priorCwd);
|
|
644
|
-
delete process.env['EXTENSION_REQUEST_LOG'];
|
|
645
|
-
}
|
|
646
|
-
const request = JSON.parse(readFileSync(requestLog, 'utf8'));
|
|
647
|
-
assert.deepEqual(request.command, ['first:demo', 'repo-branch', 'run']);
|
|
648
|
-
assert.deepEqual(request.context.extension, { branch: 'first:demo', root: projectDir });
|
|
649
|
-
assert.equal(request.context.plugin, undefined);
|
|
650
|
-
});
|
|
651
|
-
test('runs through the real CLI with native help and --json output', { timeout: 40000 }, () => {
|
|
652
|
-
installExtensionFixture();
|
|
653
|
-
const cli = join(dirname(fileURLToPath(import.meta.url)), '..', '..', '..', '..', 'dist', 'cli.js');
|
|
654
|
-
const run = (args) => execFileSync(process.execPath, [cli, ...args], {
|
|
655
|
-
cwd: projectDir,
|
|
656
|
-
env: { ...process.env, HOME: home, CRTR_FRONT_DOOR: '' },
|
|
657
|
-
encoding: 'utf8',
|
|
658
|
-
});
|
|
659
|
-
const branchHelp = run(['demo', '-h']);
|
|
660
|
-
assert.match(branchHelp, /<command name="demo"/);
|
|
661
|
-
assert.match(branchHelp, /<subcommand name="built-in"/);
|
|
662
|
-
assert.match(branchHelp, /<subcommand name="repo-branch"/);
|
|
663
|
-
assert.deepEqual(JSON.parse(run(['demo', 'repo-branch', 'run', '--thing', 'x', '--json'])), { value: 'x' });
|
|
664
|
-
});
|
|
665
|
-
test('discovers per invocation, scopes by cwd, and nearest root wins', () => {
|
|
666
|
-
const { fragmentPath } = installExtensionFixture();
|
|
667
|
-
assert.ok(renderBranch(extensionBranch().help).includes('repo-branch'));
|
|
668
|
-
writeFileSync(fragmentPath, JSON.stringify(extensionFragment('changed')));
|
|
669
|
-
assert.ok(renderBranch(extensionBranch().help).includes('name="changed"'));
|
|
670
|
-
rmSync(fragmentPath);
|
|
671
|
-
assert.ok(!renderBranch(extensionBranch().help).includes('repo-branch'));
|
|
672
|
-
writeFileSync(fragmentPath, JSON.stringify(extensionFragment('outer')));
|
|
673
|
-
const inner = join(projectDir, 'nested');
|
|
674
|
-
const innerScope = join(inner, '.crouter', 'commands');
|
|
675
|
-
mkdirSync(innerScope, { recursive: true });
|
|
676
|
-
mkdirSync(join(inner, 'scripts'), { recursive: true });
|
|
677
|
-
writeFileSync(join(inner, 'scripts', 'extension.js'), EXTENSION_EXEC);
|
|
678
|
-
chmodSync(join(inner, 'scripts', 'extension.js'), 0o755);
|
|
679
|
-
writeFileSync(join(innerScope, 'demo.json'), JSON.stringify(extensionFragment('inner')));
|
|
680
|
-
assert.ok(renderBranch(extensionBranch(inner).help).includes('name="inner"'));
|
|
681
|
-
assert.ok(!renderBranch(extensionBranch(inner).help).includes('name="outer"'));
|
|
682
|
-
assert.ok(!renderBranch(extensionBranch(emptyStart).help).includes('name="outer"'));
|
|
683
|
-
});
|
|
684
|
-
test('does not discover fragments from selected-profile projects outside the cwd chain', () => {
|
|
685
|
-
installPlugin(userRoot, 'extension-fixture', { manifest: extensibleDemoCommandsJson() });
|
|
686
|
-
const profileProject = mintDir('crtr-cmdplugin-profile-project-');
|
|
687
|
-
const fragmentDir = join(profileProject, '.crouter', 'commands');
|
|
688
|
-
const scriptDir = join(profileProject, 'scripts');
|
|
689
|
-
mkdirSync(fragmentDir, { recursive: true });
|
|
690
|
-
mkdirSync(scriptDir, { recursive: true });
|
|
691
|
-
writeFileSync(join(fragmentDir, 'demo.json'), JSON.stringify(extensionFragment()));
|
|
692
|
-
writeFileSync(join(scriptDir, 'extension.js'), EXTENSION_EXEC);
|
|
693
|
-
chmodSync(join(scriptDir, 'extension.js'), 0o755);
|
|
694
|
-
process.env['CRTR_PROFILE_ID'] = createProfile('extension-fragment-scope', [{ path: profileProject, memory: 'content' }]).profileId;
|
|
695
|
-
resetScopeCache();
|
|
696
|
-
assert.ok(!renderBranch(extensionBranch(emptyStart).help).includes('repo-branch'));
|
|
697
|
-
});
|
|
698
|
-
test('rejects absolute executable paths and identifies the offending fragment node', async () => {
|
|
699
|
-
const { fragmentPath, executable } = installExtensionFixture();
|
|
700
|
-
const fragment = extensionFragment();
|
|
701
|
-
fragment.transport.executable = executable;
|
|
702
|
-
writeFileSync(fragmentPath, JSON.stringify(fragment));
|
|
703
|
-
const help = renderBranch(extensionBranch().help);
|
|
704
|
-
assert.match(help, /<extension-issue/);
|
|
705
|
-
assert.ok(!help.includes('repo-branch'));
|
|
706
|
-
const priorCwd = process.cwd();
|
|
707
|
-
process.chdir(projectDir);
|
|
708
|
-
try {
|
|
709
|
-
const checks = await runCommandPluginChecks(['project']);
|
|
710
|
-
const check = checks.find((candidate) => candidate.name === 'extension:demo');
|
|
711
|
-
assert.ok(check, JSON.stringify(checks));
|
|
712
|
-
assert.equal(check.status, 'fail');
|
|
713
|
-
assert.match(check.message, new RegExp(`${fragmentPath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}:transport\\.executable`));
|
|
714
|
-
}
|
|
715
|
-
finally {
|
|
716
|
-
process.chdir(priorCwd);
|
|
717
|
-
}
|
|
718
|
-
});
|
|
719
|
-
test('rejects the complete fragment with scoped help notice and doctor remediation', async () => {
|
|
720
|
-
const { fragmentPath } = installExtensionFixture();
|
|
721
|
-
const bad = extensionFragment();
|
|
722
|
-
bad['unknown'] = true;
|
|
723
|
-
writeFileSync(fragmentPath, JSON.stringify(bad));
|
|
724
|
-
const help = renderBranch(extensionBranch().help);
|
|
725
|
-
assert.match(help, /name="built-in"/);
|
|
726
|
-
assert.ok(!help.includes('repo-branch'));
|
|
727
|
-
assert.match(help, new RegExp(`<extension-issue fragment="${fragmentPath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}"`));
|
|
728
|
-
assert.match(help, /unknown top-level keys/);
|
|
729
|
-
const sentinel = join(projectDir, 'extension-executed');
|
|
730
|
-
process.env['EXTENSION_SENTINEL'] = sentinel;
|
|
731
|
-
const priorCwd = process.cwd();
|
|
732
|
-
process.chdir(projectDir);
|
|
733
|
-
try {
|
|
734
|
-
const checks = await runCommandPluginChecks(['project']);
|
|
735
|
-
const check = checks.find((candidate) => candidate.name === 'extension:demo');
|
|
736
|
-
assert.ok(check, JSON.stringify(checks));
|
|
737
|
-
assert.equal(check.status, 'fail');
|
|
738
|
-
assert.match(check.message, /command_extension_invalid/);
|
|
739
|
-
assert.match(check.message, new RegExp(fragmentPath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')));
|
|
740
|
-
assert.match(check.remediation.description, /regenerate/i);
|
|
741
|
-
}
|
|
742
|
-
finally {
|
|
743
|
-
process.chdir(priorCwd);
|
|
744
|
-
delete process.env['EXTENSION_SENTINEL'];
|
|
745
|
-
}
|
|
746
|
-
assert.equal(existsSync(sentinel), false);
|
|
747
|
-
});
|
|
748
|
-
test('requires the marker, rejects passthrough/rootEntry/conflicts, and leaves unmarked passthrough inert', async () => {
|
|
749
|
-
const { fragmentPath } = installExtensionFixture();
|
|
750
|
-
writeFileSync(join(userRoot, 'plugins', 'extension-fixture', 'commands.json'), JSON.stringify(extensibleDemoCommandsJson(false)));
|
|
751
|
-
assert.ok(!renderBranch(extensionBranch().help).includes('repo-branch'));
|
|
752
|
-
const priorCwd = process.cwd();
|
|
753
|
-
process.chdir(projectDir);
|
|
754
|
-
try {
|
|
755
|
-
const checks = await runCommandPluginChecks(['project']);
|
|
756
|
-
const orphan = checks.find((candidate) => candidate.name === 'extension:demo');
|
|
757
|
-
assert.ok(orphan, JSON.stringify(checks));
|
|
758
|
-
assert.equal(orphan.status, 'fail');
|
|
759
|
-
assert.match(orphan.message, /no effective plugin branch is extensible/);
|
|
760
|
-
}
|
|
761
|
-
finally {
|
|
762
|
-
process.chdir(priorCwd);
|
|
763
|
-
}
|
|
764
|
-
writeFileSync(join(userRoot, 'plugins', 'extension-fixture', 'commands.json'), JSON.stringify(extensibleDemoCommandsJson()));
|
|
765
|
-
const variants = [
|
|
766
|
-
['passthrough', (fragment) => { fragment['mounts'][0]['node']['passthrough'] = { bin: 'x', installHint: 'x' }; }],
|
|
767
|
-
['rootEntry', (fragment) => { fragment['mounts'][0]['node']['rootEntry'] = { concept: 'x', description: 'x', whenToUse: 'x' }; }],
|
|
768
|
-
];
|
|
769
|
-
for (const [name, mutate] of variants) {
|
|
770
|
-
const fragment = extensionFragment();
|
|
771
|
-
mutate(fragment);
|
|
772
|
-
writeFileSync(fragmentPath, JSON.stringify(fragment));
|
|
773
|
-
const help = renderBranch(extensionBranch().help);
|
|
774
|
-
assert.match(help, /<extension-issue/);
|
|
775
|
-
assert.ok(!help.includes('repo-branch'), name);
|
|
776
|
-
}
|
|
777
|
-
writeFileSync(fragmentPath, JSON.stringify(extensionFragment('built-in')));
|
|
778
|
-
const conflictHelp = renderBranch(extensionBranch().help);
|
|
779
|
-
assert.match(conflictHelp, /<extension-issue/);
|
|
780
|
-
assert.match(conflictHelp, /conflicts with a child/);
|
|
781
|
-
installPlugin(userRoot, 'passthrough-fixture', { manifest: passthroughCommandsJson() });
|
|
782
|
-
writeFileSync(join(projectRoot, 'commands', 'capture.json'), JSON.stringify(extensionFragment()));
|
|
783
|
-
resetScopeCache();
|
|
784
|
-
const snapshot = buildExternalCommandSnapshot(RESERVED, projectDir);
|
|
785
|
-
const capture = composeExternalSubtrees(snapshot).find((branch) => branch.name === 'capture');
|
|
786
|
-
assert.ok(capture?.passthrough);
|
|
787
|
-
assert.equal(capture.children.length, 0);
|
|
788
|
-
});
|
|
789
|
-
test('install and update validate the marker but never inspect repository fragments', async () => {
|
|
790
|
-
const source = join(mintDir('crtr-extensible-source-'), 'fixture');
|
|
791
|
-
mkdirSync(join(source, '.crouter-plugin'), { recursive: true });
|
|
792
|
-
mkdirSync(join(source, 'bin'), { recursive: true });
|
|
793
|
-
const manifest = extensibleDemoCommandsJson();
|
|
794
|
-
manifest.mounts[0].node['name'] = 'install-demo';
|
|
795
|
-
const rootEntry = manifest.mounts[0].node['rootEntry'];
|
|
796
|
-
rootEntry['concept'] = 'install fixture';
|
|
797
|
-
writeFileSync(join(source, '.crouter-plugin', 'plugin.json'), JSON.stringify({ name: 'install-extension-fixture', version: '0.1.0', description: 'fixture', commands: 'commands.json', transport: { kind: 'exec', executable: 'bin/cmd.js' } }));
|
|
798
|
-
writeFileSync(join(source, 'commands.json'), JSON.stringify(manifest));
|
|
799
|
-
writeFileSync(join(source, 'bin', 'cmd.js'), EXTENSION_EXEC);
|
|
800
|
-
chmodSync(join(source, 'bin', 'cmd.js'), 0o755);
|
|
801
|
-
mkdirSync(join(projectRoot, 'commands'), { recursive: true });
|
|
802
|
-
writeFileSync(join(projectRoot, 'commands', 'install-demo.json'), JSON.stringify({ unknown: true }));
|
|
803
|
-
await pluginInstall.run({ installRef: source, scope: 'user' });
|
|
804
|
-
(manifest.mounts[0].node['children'][0]['extensible'] = true);
|
|
805
|
-
writeFileSync(join(source, 'commands.json'), JSON.stringify(manifest));
|
|
806
|
-
await assert.rejects(pluginUpdate.run({ name: 'install-extension-fixture' }), /extensible is valid only on a top-level branch mount/);
|
|
807
|
-
});
|
|
808
|
-
test('plugin inspection identifies extensible branches without executing the fragment executable', async () => {
|
|
809
|
-
const { executable } = installExtensionFixture();
|
|
810
|
-
const sentinel = join(projectDir, 'inspect-executed');
|
|
811
|
-
process.env['EXTENSION_SENTINEL'] = sentinel;
|
|
812
|
-
const priorCwd = process.cwd();
|
|
813
|
-
process.chdir(projectDir);
|
|
814
|
-
try {
|
|
815
|
-
const shown = await pluginShow.run({ name: 'extension-fixture' });
|
|
816
|
-
const commands = shown['commands'];
|
|
817
|
-
assert.deepEqual(commands.extensibleBranches, ['demo']);
|
|
818
|
-
}
|
|
819
|
-
finally {
|
|
820
|
-
process.chdir(priorCwd);
|
|
821
|
-
delete process.env['EXTENSION_SENTINEL'];
|
|
822
|
-
}
|
|
823
|
-
assert.equal(existsSync(sentinel), false);
|
|
824
|
-
assert.ok(existsSync(executable));
|
|
825
|
-
});
|
|
826
|
-
});
|
|
827
|
-
// 5. Lifecycle without restart (per-invocation discovery)
|
|
828
|
-
describe('lifecycle without restart', () => {
|
|
829
|
-
test('install → appears; disable → gone; edit → visible; remove → gone', () => {
|
|
830
|
-
const discover = () => {
|
|
831
|
-
resetScopeCache();
|
|
832
|
-
const snapshot = discoverCommandContributions(RESERVED, emptyStart);
|
|
833
|
-
return composeExternalSubtrees(adaptPluginContributions(snapshot.contributions));
|
|
834
|
-
};
|
|
835
|
-
// install
|
|
836
|
-
installPlugin(userRoot, 'deploy-tools');
|
|
837
|
-
assert.equal(discover().length, 1);
|
|
838
|
-
// disable (config edit only — no restart)
|
|
839
|
-
writeRawConfig('user', { plugins: { 'deploy-tools': { enabled: false } } });
|
|
840
|
-
assert.equal(discover().length, 0);
|
|
841
|
-
// re-enable + edit the declaration (rename the top-level command)
|
|
842
|
-
writeRawConfig('user', { plugins: { 'deploy-tools': { enabled: true } } });
|
|
843
|
-
writeFileSync(join(userRoot, 'plugins', 'deploy-tools', 'commands.json'), JSON.stringify(commandsJson('deploy')));
|
|
844
|
-
const afterEdit = discover();
|
|
845
|
-
assert.equal(afterEdit.length, 1);
|
|
846
|
-
assert.equal(afterEdit[0].name, 'deploy');
|
|
847
|
-
// remove
|
|
848
|
-
rmSync(join(userRoot, 'plugins', 'deploy-tools'), { recursive: true, force: true });
|
|
849
|
-
assert.equal(discover().length, 0);
|
|
850
|
-
});
|
|
851
|
-
});
|
|
852
|
-
// 6/7. Typed issues without executing the binary
|
|
853
|
-
describe('typed validation issues', () => {
|
|
854
|
-
function validate(manifest, extra = {}) {
|
|
855
|
-
installPlugin(userRoot, 'p', { manifest, ...extra });
|
|
856
|
-
resetScopeCache();
|
|
857
|
-
const plugins = listInstalledPluginsInRoot('user', userRoot);
|
|
858
|
-
const p = plugins.find((x) => x.name === 'p');
|
|
859
|
-
return validatePluginCommands(p, RESERVED);
|
|
860
|
-
}
|
|
861
|
-
test('unknown schemaVersion → command_schema_version, no contribution', () => {
|
|
862
|
-
const m = commandsJson();
|
|
863
|
-
m['schemaVersion'] = 2;
|
|
864
|
-
const v = validate(m);
|
|
865
|
-
assert.equal(v.contributions.length, 0);
|
|
866
|
-
assert.ok(v.issues.some((i) => i.code === 'command_schema_version'));
|
|
867
|
-
});
|
|
868
|
-
test('unknown top-level key → command_manifest_invalid', () => {
|
|
869
|
-
const m = commandsJson();
|
|
870
|
-
m['requires'] = { crtr: '>=1' };
|
|
871
|
-
const v = validate(m);
|
|
872
|
-
assert.ok(v.issues.some((i) => i.code === 'command_manifest_invalid'));
|
|
873
|
-
});
|
|
874
|
-
test('a child mount declared before its non-empty parent materializes into the nested branch', () => {
|
|
875
|
-
const m = commandsJson();
|
|
876
|
-
const topLevel = m.mounts[0];
|
|
877
|
-
const child = topLevel.node['children'][0];
|
|
878
|
-
topLevel.node['children'] = [{
|
|
879
|
-
kind: 'branch',
|
|
880
|
-
name: 'tools',
|
|
881
|
-
description: 'application tools',
|
|
882
|
-
whenToUse: 'inspect application tools',
|
|
883
|
-
summary: 'application tools',
|
|
884
|
-
children: [],
|
|
885
|
-
}];
|
|
886
|
-
m.mounts = [
|
|
887
|
-
{ parent: ['app', 'tools'], node: { ...child, name: 'status' } },
|
|
888
|
-
topLevel,
|
|
889
|
-
];
|
|
890
|
-
const v = validate(m);
|
|
891
|
-
assert.equal(v.issues.length, 0, JSON.stringify(v.issues));
|
|
892
|
-
assert.equal(v.contributions.length, 1);
|
|
893
|
-
const tools = (v.contributions[0].node.children.find((node) => node.name === 'tools'));
|
|
894
|
-
assert.equal(tools.kind, 'branch');
|
|
895
|
-
assert.deepEqual(tools.children.map((node) => node.name), ['status']);
|
|
896
|
-
});
|
|
897
|
-
test('non-executable file → command_not_executable', () => {
|
|
898
|
-
const v = validate(commandsJson(), { execBit: false });
|
|
899
|
-
assert.ok(v.issues.some((i) => i.code === 'command_not_executable'));
|
|
900
|
-
});
|
|
901
|
-
test('exec transport omits executable only for a passthrough-only manifest', () => {
|
|
902
|
-
const passthrough = validate(passthroughCommandsJson(), { executable: null });
|
|
903
|
-
assert.equal(passthrough.issues.length, 0, JSON.stringify(passthrough.issues));
|
|
904
|
-
assert.equal(passthrough.contributions.length, 1);
|
|
905
|
-
assert.equal(passthrough.contributions[0].node.passthrough?.bin, 'capture');
|
|
906
|
-
assert.equal(composeExternalSubtrees(adaptPluginContributions(passthrough.contributions))[0].passthrough?.bin, 'capture');
|
|
907
|
-
const nestedPassthrough = passthroughCommandsJson();
|
|
908
|
-
nestedPassthrough.mounts.push({
|
|
909
|
-
parent: ['capture'],
|
|
910
|
-
node: { kind: 'branch', name: 'child', description: 'nested child', whenToUse: 'testing invalid composition', summary: 'nested child', children: [] },
|
|
911
|
-
});
|
|
912
|
-
const rejectedNestedMount = validate(nestedPassthrough, { executable: null });
|
|
913
|
-
assert.ok(rejectedNestedMount.issues.some((issue) => issue.code === 'command_parent_invalid' && /passthrough branch/.test(issue.message)));
|
|
914
|
-
const executableLeaf = validate(commandsJson(), { executable: null });
|
|
915
|
-
assert.equal(executableLeaf.contributions.length, 0);
|
|
916
|
-
assert.ok(executableLeaf.issues.some((i) => i.path === 'transport.executable' && /requires executable/.test(i.message)));
|
|
917
|
-
});
|
|
918
|
-
test('executable escaping the plugin root → command_path_unsafe', () => {
|
|
919
|
-
const v = validate(commandsJson(), { executable: '../../../../bin/sh' });
|
|
920
|
-
assert.ok(v.issues.some((i) => i.code === 'command_path_unsafe'));
|
|
921
|
-
});
|
|
922
|
-
test('passthrough path escaping the plugin root → command_path_unsafe', () => {
|
|
923
|
-
const v = validate(passthroughCommandsJson('../../../../bin/sh'), { executable: null });
|
|
924
|
-
assert.ok(v.issues.some((i) => i.code === 'command_path_unsafe'));
|
|
925
|
-
});
|
|
926
|
-
test('non-executable passthrough path → command_not_executable', () => {
|
|
927
|
-
const v = validate(passthroughCommandsJson('bin/cmd.js'), { executable: null, execBit: false });
|
|
928
|
-
assert.ok(v.issues.some((i) => i.code === 'command_not_executable'));
|
|
929
|
-
});
|
|
930
|
-
test('a top-level leaf (no rootEntry) → command_node_invalid', () => {
|
|
931
|
-
const m = {
|
|
932
|
-
schemaVersion: 1,
|
|
933
|
-
mounts: [{ parent: [], node: { kind: 'leaf', name: 'x', description: 'd', whenToUse: 'w', summary: 's', params: [], output: [], outputKind: 'object', effects: ['None. Read-only.'] } }],
|
|
934
|
-
};
|
|
935
|
-
const v = validate(m);
|
|
936
|
-
assert.ok(v.issues.some((i) => i.code === 'command_node_invalid'));
|
|
937
|
-
assert.equal(v.contributions.length, 0);
|
|
938
|
-
});
|
|
939
|
-
test('a valid manifest yields a contribution and zero issues', () => {
|
|
940
|
-
const v = validate(commandsJson());
|
|
941
|
-
assert.equal(v.issues.length, 0);
|
|
942
|
-
assert.equal(v.contributions.length, 1);
|
|
943
|
-
assert.equal(v.contributions[0].node.name, 'app');
|
|
944
|
-
});
|
|
945
|
-
});
|
|
946
|
-
// Plugin help addenda — the append-only product-guidance seam. An addendum
|
|
947
|
-
// that quietly stops rendering is exactly the silent-absence class: pin that a
|
|
948
|
-
// valid entry survives validation and is collected attributed, and that the
|
|
949
|
-
// STRICT gates (install/bundle, which pass coreCommandPaths) reject a key
|
|
950
|
-
// naming no core command path while the tolerant compose path still mounts the
|
|
951
|
-
// plugin's tree. The help-render lookup receives the gate's exact inputs, so a
|
|
952
|
-
// map rejected at ingress renders nothing — render never disagrees with the
|
|
953
|
-
// install report.
|
|
954
|
-
describe('plugin help addenda', () => {
|
|
955
|
-
const gate = (paths) => ({
|
|
956
|
-
reservedCoreNames: RESERVED,
|
|
957
|
-
coreCommandPaths: () => Promise.resolve(new Set(paths)),
|
|
958
|
-
extensibleCoreBranches: () => Promise.resolve(new Set(['human'])),
|
|
959
|
-
});
|
|
960
|
-
test('a helpAddenda entry survives validation and is collected attributed to its plugin', async () => {
|
|
961
|
-
const m = commandsJson();
|
|
962
|
-
m['helpAddenda'] = { cron: 'Gate on the device: exit 75 parks the occurrence.' };
|
|
963
|
-
installPlugin(userRoot, 'northlight-fixture', { manifest: m });
|
|
964
|
-
resetScopeCache();
|
|
965
|
-
const p = listInstalledPluginsInRoot('user', userRoot).find((x) => x.name === 'northlight-fixture');
|
|
966
|
-
const v = validatePluginCommands(p, RESERVED);
|
|
967
|
-
assert.equal(v.issues.length, 0, JSON.stringify(v.issues));
|
|
968
|
-
assert.deepEqual(v.manifest?.helpAddenda, { cron: 'Gate on the device: exit 75 parks the occurrence.' });
|
|
969
|
-
// The help-render lookup: attributed, and empty for an unaddended path.
|
|
970
|
-
assert.deepEqual(await collectHelpAddenda('cron', gate(['cron', 'node']), emptyStart), [
|
|
971
|
-
{ plugin: 'northlight-fixture', text: 'Gate on the device: exit 75 parks the occurrence.' },
|
|
972
|
-
]);
|
|
973
|
-
assert.deepEqual(await collectHelpAddenda('node', gate(['cron', 'node']), emptyStart), []);
|
|
974
|
-
});
|
|
975
|
-
test('a key naming no core command path fails the strict gate and renders nothing, even beside a valid key', async () => {
|
|
976
|
-
const m = commandsJson();
|
|
977
|
-
m['helpAddenda'] = {
|
|
978
|
-
cron: 'a valid target beside the typo',
|
|
979
|
-
'cronn add': 'a typo that must fail at install, never silently at render',
|
|
980
|
-
};
|
|
981
|
-
installPlugin(userRoot, 'p', { manifest: m });
|
|
982
|
-
resetScopeCache();
|
|
983
|
-
const p = listInstalledPluginsInRoot('user', userRoot).find((x) => x.name === 'p');
|
|
984
|
-
// Strict (install/bundle/doctor): the typo is a typed issue, zero contributions.
|
|
985
|
-
const strict = validatePluginCommands(p, RESERVED, new Set(['cron', 'cron add']));
|
|
986
|
-
assert.ok(strict.issues.some((i) => i.code === 'command_help_addendum_invalid'), JSON.stringify(strict.issues));
|
|
987
|
-
assert.equal(strict.contributions.length, 0);
|
|
988
|
-
assert.equal(strict.manifest, undefined);
|
|
989
|
-
// Tolerant (runtime compose): an already-installed plugin's typo'd addendum
|
|
990
|
-
// must not drop its whole command tree.
|
|
991
|
-
const tolerant = validatePluginCommands(p, RESERVED);
|
|
992
|
-
assert.equal(tolerant.issues.length, 0, JSON.stringify(tolerant.issues));
|
|
993
|
-
assert.equal(tolerant.contributions.length, 1);
|
|
994
|
-
// The render lookup reproduces the GATE verdict, not the compose one: the
|
|
995
|
-
// rejected map contributes nothing — including its valid key — so render
|
|
996
|
-
// can never show what the install report said was rejected.
|
|
997
|
-
assert.deepEqual(await collectHelpAddenda('cron', gate(['cron', 'cron add']), emptyStart), []);
|
|
998
|
-
});
|
|
999
|
-
test('an installed addendum renders through the real help path as an attributed block', async () => {
|
|
1000
|
-
const m = commandsJson();
|
|
1001
|
-
m['helpAddenda'] = { cron: 'ADDENDUM RENDERED THROUGH THE REAL HELP PATH' };
|
|
1002
|
-
installPlugin(userRoot, 'northlight-fixture', { manifest: m });
|
|
1003
|
-
resetScopeCache();
|
|
1004
|
-
// Pin the durable wiring, not the lookup: runCli → renderNodeWithAddenda →
|
|
1005
|
-
// collectHelpAddenda → <plugin-help> serialization. This is the exact
|
|
1006
|
-
// silent-absence class — the dynamic import or the append could regress
|
|
1007
|
-
// with every lookup-level assertion still green.
|
|
1008
|
-
const { resolveRoot } = await import('../../../build-root.js');
|
|
1009
|
-
const { runCli } = await import('../../command.js');
|
|
1010
|
-
const root = await resolveRoot('cron');
|
|
1011
|
-
const chunks = [];
|
|
1012
|
-
const realWrite = process.stdout.write.bind(process.stdout);
|
|
1013
|
-
const realCwd = process.cwd();
|
|
1014
|
-
process.chdir(emptyStart); // startDir with no project scope — user scope is the fixture HOME
|
|
1015
|
-
process.stdout.write = ((chunk) => {
|
|
1016
|
-
chunks.push(String(chunk));
|
|
1017
|
-
return true;
|
|
1018
|
-
});
|
|
1019
|
-
try {
|
|
1020
|
-
await runCli(root, ['node', 'crtr', 'cron', '-h']);
|
|
1021
|
-
}
|
|
1022
|
-
finally {
|
|
1023
|
-
process.stdout.write = realWrite;
|
|
1024
|
-
process.chdir(realCwd);
|
|
1025
|
-
}
|
|
1026
|
-
const out = chunks.join('');
|
|
1027
|
-
assert.ok(out.includes('<plugin-help plugin="northlight-fixture">'), out.slice(-400));
|
|
1028
|
-
assert.ok(out.includes('ADDENDUM RENDERED THROUGH THE REAL HELP PATH'), out.slice(-400));
|
|
1029
|
-
});
|
|
1030
|
-
});
|
|
1031
|
-
// Lifecycle surfaces — the validator's verdict must reach the caller WITHOUT
|
|
1032
|
-
// executing the plugin binary, and a cross-plugin top-level collision must
|
|
1033
|
-
// preserve every claimant under its origin-qualified command name.
|
|
1034
|
-
describe('lifecycle surfaces report validation without executing the plugin', () => {
|
|
1035
|
-
// Records the fact it ran. No validation surface may ever spawn it.
|
|
1036
|
-
const SENTINEL_EXEC = `#!/usr/bin/env node
|
|
1037
|
-
const fs = require('fs');
|
|
1038
|
-
if (process.env.CMDPLUGIN_SENTINEL) fs.writeFileSync(process.env.CMDPLUGIN_SENTINEL, 'executed');
|
|
1039
|
-
process.stdout.write(JSON.stringify({ protocolVersion: 1, ok: true, result: { app_id: 'x', status: 'running' } }));
|
|
1040
|
-
`;
|
|
1041
|
-
let sentinel;
|
|
1042
|
-
let realCwd;
|
|
1043
|
-
beforeEach(() => {
|
|
1044
|
-
realCwd = process.cwd();
|
|
1045
|
-
sentinel = join(emptyStart, 'EXECUTED');
|
|
1046
|
-
process.env['CMDPLUGIN_SENTINEL'] = sentinel;
|
|
1047
|
-
process.chdir(emptyStart); // no .crouter ancestor → project scope is empty
|
|
1048
|
-
resetScopeCache();
|
|
1049
|
-
});
|
|
1050
|
-
afterEach(() => {
|
|
1051
|
-
process.chdir(realCwd);
|
|
1052
|
-
delete process.env['CMDPLUGIN_SENTINEL'];
|
|
1053
|
-
resetScopeCache();
|
|
1054
|
-
});
|
|
1055
|
-
function assertNotExecuted() {
|
|
1056
|
-
assert.equal(existsSync(sentinel), false, 'a validation surface must never spawn the plugin binary');
|
|
1057
|
-
}
|
|
1058
|
-
test('pkg plugin show passes the typed issue through and mounts nothing', async () => {
|
|
1059
|
-
const broken = commandsJson();
|
|
1060
|
-
broken['schemaVersion'] = 2;
|
|
1061
|
-
installPlugin(userRoot, 'p', { manifest: broken, exec: SENTINEL_EXEC });
|
|
1062
|
-
resetScopeCache();
|
|
1063
|
-
const out = await pluginShow.run({ name: 'p' });
|
|
1064
|
-
const commands = out['commands'];
|
|
1065
|
-
const issue = commands.issues.find((i) => i.code === 'command_schema_version');
|
|
1066
|
-
assert.ok(issue, `expected command_schema_version, got ${JSON.stringify(commands.issues.map((i) => i.code))}`);
|
|
1067
|
-
assert.ok(typeof issue.received === 'string' && typeof issue.expected === 'string' && typeof issue.next === 'string');
|
|
1068
|
-
assert.equal(commands.mounts.length, 0, 'a rejected manifest contributes no mounts');
|
|
1069
|
-
assertNotExecuted();
|
|
1070
|
-
});
|
|
1071
|
-
test('a cross-plugin top-level collision keeps both commands under their origin-qualified names', async () => {
|
|
1072
|
-
// Two plugins, each valid in isolation, both claiming `app`. One is direct;
|
|
1073
|
-
// the other records its marketplace as the command origin.
|
|
1074
|
-
installPlugin(userRoot, 'p-one', { exec: SENTINEL_EXEC });
|
|
1075
|
-
installPlugin(userRoot, 'p-two', { exec: SENTINEL_EXEC, sourceMarketplace: 'fixture-market' });
|
|
1076
|
-
resetScopeCache();
|
|
1077
|
-
const snapshot = discoverCommandContributions(new Set(['sys']), emptyStart);
|
|
1078
|
-
assert.deepEqual(snapshot.contributions.map((contribution) => contribution.node.name).sort(), ['fixture-market:app', 'p-one:app']);
|
|
1079
|
-
assert.deepEqual(snapshot.issues.filter((i) => i.code === 'command_collision').map((i) => i.plugin).sort(), ['p-one', 'p-two'], 'both claimants report their resolved mount');
|
|
1080
|
-
for (const [name, mount] of [['p-one', 'p-one:app'], ['p-two', 'fixture-market:app']]) {
|
|
1081
|
-
const out = await pluginShow.run({ name });
|
|
1082
|
-
const commands = out['commands'];
|
|
1083
|
-
assert.deepEqual(commands.mounts, [mount], `${name} lists its qualified command as an accepted mount`);
|
|
1084
|
-
const issue = commands.issues.find((i) => i.code === 'command_collision');
|
|
1085
|
-
assert.ok(issue, `${name} show must carry the command_collision issue`);
|
|
1086
|
-
assert.deepEqual(issue.received.split(', ').sort(), ['p-one', 'p-two'], 'the issue names both claimants');
|
|
1087
|
-
assert.match(issue.message, new RegExp(`mounted as "${mount}"`));
|
|
1088
|
-
assert.equal(issue.expected, 'an origin-qualified top-level command for each claimant');
|
|
1089
|
-
assert.equal(issue.next, `Invoke "${mount}" to use this plugin command.`);
|
|
1090
|
-
}
|
|
1091
|
-
assertNotExecuted();
|
|
1092
|
-
});
|
|
1093
|
-
test('a colliding exec plugin keeps its manifest path for help and execution', async () => {
|
|
1094
|
-
installPlugin(userRoot, 'p-one', { exec: FIXTURE_EXEC });
|
|
1095
|
-
installPlugin(userRoot, 'p-two', { exec: FIXTURE_EXEC, sourceMarketplace: 'fixture-market' });
|
|
1096
|
-
resetScopeCache();
|
|
1097
|
-
const snapshot = discoverCommandContributions(new Set(['sys']), emptyStart);
|
|
1098
|
-
const external = composeExternalSubtrees(adaptPluginContributions(snapshot.contributions));
|
|
1099
|
-
const mounted = external.find((branch) => branch.name === 'fixture-market:app');
|
|
1100
|
-
assert.ok(mounted, 'the marketplace-qualified plugin branch is mounted');
|
|
1101
|
-
assert.match(renderBranch(mounted.help), /<command name="fixture-market:app"/);
|
|
1102
|
-
const leaf = leafOf(mounted, 'show');
|
|
1103
|
-
const log = join(emptyStart, 'collision-request.json');
|
|
1104
|
-
process.env['FIXTURE_REQUEST_LOG'] = log;
|
|
1105
|
-
try {
|
|
1106
|
-
const result = await leaf.run({ appId: 'app_123', mode: 'ok' });
|
|
1107
|
-
assert.deepEqual(result, { app_id: 'app_123', status: 'running' });
|
|
1108
|
-
assert.deepEqual(JSON.parse(readFileSync(log, 'utf8')).command, ['app', 'show']);
|
|
1109
|
-
}
|
|
1110
|
-
finally {
|
|
1111
|
-
delete process.env['FIXTURE_REQUEST_LOG'];
|
|
1112
|
-
}
|
|
1113
|
-
});
|
|
1114
|
-
});
|
|
1115
|
-
// Memory-corpus gate across the plugin lifecycle — install, and enable of a
|
|
1116
|
-
// package installed while disabled, both converge the candidate's memory store
|
|
1117
|
-
// onto exact canonical identity BEFORE it can mount. A local-path install stays
|
|
1118
|
-
// a live link, so the caller's own directory is the corpus that gets rewritten;
|
|
1119
|
-
// a corpus that cannot converge writes nothing and changes no config. Update
|
|
1120
|
-
// runs the same gate through the same helper, so it needs no cases of its own.
|
|
1121
|
-
describe('memory corpus gate across the plugin lifecycle', () => {
|
|
1122
|
-
let realCwd;
|
|
1123
|
-
beforeEach(() => {
|
|
1124
|
-
realCwd = process.cwd();
|
|
1125
|
-
process.chdir(emptyStart); // no .crouter ancestor → the real repo is never a scope
|
|
1126
|
-
resetScopeCache();
|
|
1127
|
-
});
|
|
1128
|
-
afterEach(() => {
|
|
1129
|
-
process.chdir(realCwd);
|
|
1130
|
-
resetScopeCache();
|
|
1131
|
-
});
|
|
1132
|
-
function writeDoc(path, frontmatter, body) {
|
|
1133
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
1134
|
-
writeFileSync(path, `---\n${frontmatter}\nwhen-and-why-to-read: When the fixture runs, this knowledge should be read because it proves the gate.\n---\n\n${body}\n`);
|
|
1135
|
-
}
|
|
1136
|
-
function pluginSource(name) {
|
|
1137
|
-
const root = join(mintDir('crtr-plugin-src-'), name);
|
|
1138
|
-
mkdirSync(join(root, '.crouter-plugin'), { recursive: true });
|
|
1139
|
-
writeFileSync(join(root, '.crouter-plugin', 'plugin.json'), JSON.stringify({ name, version: '0.1.0', description: 'fixture' }));
|
|
1140
|
-
return root;
|
|
1141
|
-
}
|
|
1142
|
-
function userConfig() {
|
|
1143
|
-
return readConfig('user');
|
|
1144
|
-
}
|
|
1145
|
-
test('a local install migrates the caller-owned linked corpus in place and reports it', async () => {
|
|
1146
|
-
const source = pluginSource('memfix');
|
|
1147
|
-
writeDoc(join(source, 'memory', 'topics', 'INDEX.md'), 'kind: knowledge\nname: topics/INDEX', 'Topic overview.');
|
|
1148
|
-
writeDoc(join(source, 'memory', 'overview.md'), 'kind: knowledge', 'Depth lives in [[memfix/topics/INDEX]].');
|
|
1149
|
-
// Non-document files the substrate never loads as documents: the count
|
|
1150
|
-
// below must not include them even though lint YAML-checks them too.
|
|
1151
|
-
writeDoc(join(source, 'memory', 'SKILL.md'), 'kind: knowledge\nname: unrelated-skill', 'Skill body.');
|
|
1152
|
-
writeDoc(join(source, 'memory', 'MEMORY.md'), 'kind: knowledge', 'Index body.');
|
|
1153
|
-
resetScopeCache();
|
|
1154
|
-
const out = await pluginInstall.run({ installRef: source, scope: 'user' });
|
|
1155
|
-
const memory = out['memory'];
|
|
1156
|
-
assert.deepEqual(memory.migrated, ['overview.md', 'topics/INDEX.md'], 'both phases rewrote a document');
|
|
1157
|
-
assert.equal(memory.linkedSource, realpathSync(join(source, 'memory')), 'the report names the caller-owned directory it rewrote');
|
|
1158
|
-
assert.equal(memory.docs, 2);
|
|
1159
|
-
assert.equal(lstatSync(join(userRoot, 'plugins', 'memfix')).isSymbolicLink(), true, 'the install stays a live link');
|
|
1160
|
-
// The rewrite landed in the caller's source, not in a copy.
|
|
1161
|
-
assert.match(readFileSync(join(source, 'memory', 'overview.md'), 'utf8'), /\[\[memfix\/topics\]\]/);
|
|
1162
|
-
assert.doesNotMatch(readFileSync(join(source, 'memory', 'topics', 'INDEX.md'), 'utf8'), /^name:/m);
|
|
1163
|
-
assert.equal(userConfig().plugins['memfix']?.enabled, true);
|
|
1164
|
-
});
|
|
1165
|
-
test('a corpus that cannot converge blocks the install, writes nothing, and registers nothing', async () => {
|
|
1166
|
-
const source = pluginSource('blocked');
|
|
1167
|
-
writeDoc(join(source, 'memory', 'dup-a.md'), 'kind: knowledge\nname: dup', 'First claimant.');
|
|
1168
|
-
writeDoc(join(source, 'memory', 'dup-b.md'), 'kind: knowledge\nname: dup', 'Second claimant.');
|
|
1169
|
-
const before = ['dup-a.md', 'dup-b.md'].map((f) => readFileSync(join(source, 'memory', f), 'utf8'));
|
|
1170
|
-
resetScopeCache();
|
|
1171
|
-
await assert.rejects(pluginInstall.run({ installRef: source, scope: 'user' }), (error) => /cannot be migrated to exact canonical identity/.test(error.message) && /dup/.test(error.message));
|
|
1172
|
-
assert.equal(existsSync(join(userRoot, 'plugins', 'blocked')), false, 'a blocked candidate installs nothing');
|
|
1173
|
-
assert.equal(userConfig().plugins['blocked'], undefined, 'config is unchanged');
|
|
1174
|
-
assert.deepEqual(['dup-a.md', 'dup-b.md'].map((f) => readFileSync(join(source, 'memory', f), 'utf8')), before, 'a blocked plan writes nothing');
|
|
1175
|
-
});
|
|
1176
|
-
test('enable migrates a package installed while disabled before it flips config', async () => {
|
|
1177
|
-
const source = pluginSource('lifecycle');
|
|
1178
|
-
writeDoc(join(source, 'memory', 'ready.md'), 'kind: knowledge', 'Already canonical.');
|
|
1179
|
-
resetScopeCache();
|
|
1180
|
-
await pluginInstall.run({ installRef: source, scope: 'user' });
|
|
1181
|
-
resetScopeCache();
|
|
1182
|
-
await pluginDisable.run({ name: 'lifecycle' });
|
|
1183
|
-
resetScopeCache();
|
|
1184
|
-
// The package gains an old-format document while it sits disabled.
|
|
1185
|
-
writeDoc(join(source, 'memory', 'guide', 'INDEX.md'), 'kind: knowledge\nname: guide/INDEX', 'Guide.');
|
|
1186
|
-
const enabled = await pluginEnable.run({ name: 'lifecycle' });
|
|
1187
|
-
const memory = enabled['memory'];
|
|
1188
|
-
assert.deepEqual(memory.migrated, ['guide/INDEX.md']);
|
|
1189
|
-
assert.equal(memory.linkedSource, realpathSync(join(source, 'memory')));
|
|
1190
|
-
assert.doesNotMatch(readFileSync(join(source, 'memory', 'guide', 'INDEX.md'), 'utf8'), /^name:/m);
|
|
1191
|
-
assert.equal(userConfig().plugins['lifecycle']?.enabled, true);
|
|
1192
|
-
resetScopeCache();
|
|
1193
|
-
await pluginDisable.run({ name: 'lifecycle' });
|
|
1194
|
-
resetScopeCache();
|
|
1195
|
-
writeDoc(join(source, 'memory', 'dup-a.md'), 'kind: knowledge\nname: dup', 'First claimant.');
|
|
1196
|
-
writeDoc(join(source, 'memory', 'dup-b.md'), 'kind: knowledge\nname: dup', 'Second claimant.');
|
|
1197
|
-
await assert.rejects(pluginEnable.run({ name: 'lifecycle' }), /cannot be migrated to exact canonical identity/);
|
|
1198
|
-
assert.equal(userConfig().plugins['lifecycle']?.enabled, false, 'a refused corpus leaves the plugin disabled');
|
|
1199
|
-
});
|
|
1200
|
-
});
|