@north-light/crouter 0.3.318 → 0.3.320
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 +6 -4
- package/runtime.lock.json +5 -5
- package/scripts/pack-minify.mjs +108 -0
- 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
package/dist/core/worktree.js
CHANGED
|
@@ -1,899 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
this.name = 'WorktreeError';
|
|
18
|
-
|
|
19
|
-
this.next = next;
|
|
20
|
-
this.detail = detail;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
function runGit(cwd, args, code, next) {
|
|
24
|
-
const res = gitSync(args, cwd);
|
|
25
|
-
if (res.status !== 0) {
|
|
26
|
-
const detail = (res.stderr.trim() || res.stdout.trim()).trim();
|
|
27
|
-
throw new WorktreeError(code, `git ${args.join(' ')} failed`, next, detail);
|
|
28
|
-
}
|
|
29
|
-
return res.stdout.trim();
|
|
30
|
-
}
|
|
31
|
-
export function managedWorktreesRoot() {
|
|
32
|
-
return `${crtrHome()}/worktrees`;
|
|
33
|
-
}
|
|
34
|
-
export function managedWorktreePath(nodeId) {
|
|
35
|
-
return `${managedWorktreesRoot()}/${nodeId}`;
|
|
36
|
-
}
|
|
37
|
-
export function hasOpenManagedWorktree(node) {
|
|
38
|
-
return node?.managed_worktree?.state === 'open';
|
|
39
|
-
}
|
|
40
|
-
export function openManagedWorktreeForNode(nodeId) {
|
|
41
|
-
const node = getNode(nodeId);
|
|
42
|
-
const wt = node?.managed_worktree;
|
|
43
|
-
return wt?.state === 'open' ? wt : null;
|
|
44
|
-
}
|
|
45
|
-
function repoRootFor(cwd) {
|
|
46
|
-
const result = gitSync(['rev-parse', '--show-toplevel'], cwd);
|
|
47
|
-
if (result.status !== 0) {
|
|
48
|
-
const detail = (result.stderr.trim() || result.stdout.trim()).trim();
|
|
49
|
-
throw new WorktreeError('not_git_repo', `cwd ${cwd} is not a git repository`, 'Pass --cwd <real repo> pointing inside a git repository.', detail);
|
|
50
|
-
}
|
|
51
|
-
return result.stdout.trim();
|
|
52
|
-
}
|
|
53
|
-
export function isManagedWorktreeBase(repoRoot) {
|
|
54
|
-
const path = relative(canonicalPath(managedWorktreesRoot()), canonicalPath(repoRoot));
|
|
55
|
-
return path !== '' && path !== '..' && !path.startsWith(`..${sep}`) && !isAbsolute(path);
|
|
56
|
-
}
|
|
57
|
-
function recordedBranchExists(cwd, branch) {
|
|
58
|
-
const ref = `refs/heads/${branch}`;
|
|
59
|
-
const exists = gitSync(['show-ref', '--verify', '--quiet', ref], cwd);
|
|
60
|
-
if (exists.status === 0)
|
|
61
|
-
return true;
|
|
62
|
-
if (exists.status === 1 && exists.executionFailed !== true)
|
|
63
|
-
return false;
|
|
64
|
-
const stderr = exists.stderr.trim() || '<empty>';
|
|
65
|
-
const execution = exists.processError === undefined ? '' : `\nprocess error: ${exists.processError}`;
|
|
66
|
-
throw new WorktreeError('recorded_branch_inspection_failed', `could not inspect recorded branch '${branch}' (git show-ref exited with status ${exists.status})`, 'Inspect the repository and its Git metadata, then retry.', `status: ${exists.status}\nstderr: ${stderr}${execution}`);
|
|
67
|
-
}
|
|
68
|
-
function resolveLandableBase(repoRoot, baseRef) {
|
|
69
|
-
const ref = `refs/heads/${baseRef}`;
|
|
70
|
-
// Verify the exact refs/heads name first: rev-parse alone accepts revision
|
|
71
|
-
// syntax, which could turn a SHA or a `^{commit}` suffix into a non-landable
|
|
72
|
-
// base even though no local branch by that exact name exists.
|
|
73
|
-
const exists = gitSync(['show-ref', '--verify', '--quiet', ref], repoRoot);
|
|
74
|
-
// `show-ref --verify --quiet` reserves exit 1 for an absent ref. gitSync
|
|
75
|
-
// preserves that numeric status for compatibility, but marks spawn failures,
|
|
76
|
-
// timeouts, and signal exits so they cannot masquerade as an absent branch.
|
|
77
|
-
if (exists.status === 1 && exists.executionFailed !== true) {
|
|
78
|
-
throw new WorktreeError('missing_base_branch', `managed worktree base '${baseRef}' does not name an existing local branch`, 'The base must be a local branch that landing can fast-forward — freshen your local branch from origin first (rebase-not-merge), then base on it.');
|
|
79
|
-
}
|
|
80
|
-
if (exists.status !== 0) {
|
|
81
|
-
const stderr = exists.stderr.trim() || '<empty>';
|
|
82
|
-
const execution = exists.processError === undefined ? '' : `\nprocess error: ${exists.processError}`;
|
|
83
|
-
throw new WorktreeError('base_branch_inspection_failed', `could not inspect local base branch '${baseRef}' (git show-ref exited with status ${exists.status})`, 'Inspect the repository and its Git metadata, then retry.', `status: ${exists.status}\nstderr: ${stderr}${execution}`);
|
|
84
|
-
}
|
|
85
|
-
return runGit(repoRoot, ['rev-parse', '--verify', ref], 'base_branch_resolve_failed', 'Inspect the local base branch, then retry.');
|
|
86
|
-
}
|
|
87
|
-
/** Path of the worktree where a local branch is currently checked out, or null
|
|
88
|
-
* if it is not checked out in any worktree. */
|
|
89
|
-
function checkoutPathForBranch(repoRoot, branch) {
|
|
90
|
-
const out = runGit(repoRoot, ['worktree', 'list', '--porcelain'], 'worktree_list_failed', 'Inspect the repository worktrees manually, then retry.');
|
|
91
|
-
return checkoutPathForBranchInList(out, branch);
|
|
92
|
-
}
|
|
93
|
-
/** Shared parse for a `git worktree list --porcelain` blob already in hand —
|
|
94
|
-
* callers that must not throw on a read failure (an absent-path proof that
|
|
95
|
-
* needs to fail closed rather than error) call `gitSync` themselves and pass
|
|
96
|
-
* the output here instead of going through `checkoutPathForBranch`. */
|
|
97
|
-
export function checkoutPathForBranchInList(porcelain, branch) {
|
|
98
|
-
let current = null;
|
|
99
|
-
for (const line of porcelain.split('\n')) {
|
|
100
|
-
if (line.startsWith('worktree '))
|
|
101
|
-
current = line.slice('worktree '.length).trim();
|
|
102
|
-
else if (line === `branch refs/heads/${branch}`)
|
|
103
|
-
return current;
|
|
104
|
-
}
|
|
105
|
-
return null;
|
|
106
|
-
}
|
|
107
|
-
/** Are these two spellings the same directory?
|
|
108
|
-
*
|
|
109
|
-
* Git canonicalizes every path it prints in `worktree list --porcelain`, while
|
|
110
|
-
* a recorded managed-worktree path preserves the spelling of `CRTR_HOME`. When
|
|
111
|
-
* the canvas home is reached through a symlink (macOS's `/var` → `/private/var`
|
|
112
|
-
* is the everyday case) the two forms name one directory but differ as
|
|
113
|
-
* strings, so a raw `===` reads a checkout crtr created as unowned. Resolution
|
|
114
|
-
* failures fall back to `resolve`, which is the pre-canonical comparison — no
|
|
115
|
-
* worse than the string compare it replaces. */
|
|
116
|
-
export function samePath(a, b) {
|
|
117
|
-
return a === b || canonicalPath(a) === canonicalPath(b);
|
|
118
|
-
}
|
|
119
|
-
function canonicalPath(path) {
|
|
120
|
-
try {
|
|
121
|
-
return realpathSync.native(path);
|
|
122
|
-
}
|
|
123
|
-
catch {
|
|
124
|
-
return resolve(path);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
export const WORKTREE_LOCK_WAIT_MS = 30_000;
|
|
128
|
-
/** The lock directory naming one repository's common Git dir. Every process
|
|
129
|
-
* that mutates a managed worktree — the synchronous commands here and the
|
|
130
|
-
* daemon's asynchronous sweep — derives its lock path through this function,
|
|
131
|
-
* so the two locking styles contend for the SAME name. */
|
|
132
|
-
export function worktreeLockPathForCommonDir(commonDir) {
|
|
133
|
-
const lockRoot = `${crtrHome()}/worktree-locks`;
|
|
134
|
-
mkdirSync(lockRoot, { recursive: true });
|
|
135
|
-
return `${lockRoot}/${createHash('sha256').update(commonDir).digest('hex')}`;
|
|
136
|
-
}
|
|
137
|
-
function commonGitDir(repoRoot) {
|
|
138
|
-
const commonDir = runGit(repoRoot, ['rev-parse', '--git-common-dir'], 'git_common_dir_failed', 'Inspect the repository git metadata, then retry.');
|
|
139
|
-
return realpathSync(resolve(repoRoot, commonDir));
|
|
140
|
-
}
|
|
141
|
-
/** Serialize worktree mutation for one repository across crtr processes. Git's
|
|
142
|
-
* own worktree metadata lock is intentionally short-lived and rejects a second
|
|
143
|
-
* add instead of waiting, so callers take this transaction lock first. */
|
|
144
|
-
function withRepositoryWorktreeLock(repoRoot, action) {
|
|
145
|
-
const commonDir = commonGitDir(repoRoot);
|
|
146
|
-
return withExclusiveDirectoryLock(worktreeLockPathForCommonDir(commonDir), action, {
|
|
147
|
-
timeoutMs: WORKTREE_LOCK_WAIT_MS,
|
|
148
|
-
timeoutError: () => new WorktreeError('worktree_lock_timeout', `timed out waiting to create a managed worktree in ${commonDir}`, 'Wait for the other managed-worktree operation to finish, then retry.'),
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
function registeredWorktree(repoRoot, path, branch) {
|
|
152
|
-
const list = gitSync(['worktree', 'list', '--porcelain'], repoRoot);
|
|
153
|
-
if (list.status !== 0)
|
|
154
|
-
return null;
|
|
155
|
-
let current = null;
|
|
156
|
-
for (const line of list.stdout.split('\n')) {
|
|
157
|
-
if (line.startsWith('worktree '))
|
|
158
|
-
current = line.slice('worktree '.length).trim();
|
|
159
|
-
else if (current !== null && samePath(current, path) && line === `branch refs/heads/${branch}`)
|
|
160
|
-
return true;
|
|
161
|
-
}
|
|
162
|
-
return false;
|
|
163
|
-
}
|
|
164
|
-
function proveBranchContained(cwd, baseRef, branchSha) {
|
|
165
|
-
const candidates = [];
|
|
166
|
-
const localBaseRef = `refs/heads/${baseRef}`;
|
|
167
|
-
const localBase = gitSync(['rev-parse', '--verify', '--quiet', localBaseRef], cwd);
|
|
168
|
-
if (localBase.status === 0)
|
|
169
|
-
candidates.push({ ref: localBaseRef, sha: localBase.stdout.trim() });
|
|
170
|
-
const upstream = gitSync(['rev-parse', '--symbolic-full-name', '--verify', `${baseRef}@{upstream}`], cwd);
|
|
171
|
-
const upstreamRef = upstream.status === 0 && upstream.stdout.trim().startsWith('refs/') ? upstream.stdout.trim() : `refs/remotes/origin/${baseRef}`;
|
|
172
|
-
const upstreamSha = gitSync(['rev-parse', '--verify', '--quiet', upstreamRef], cwd);
|
|
173
|
-
if (upstreamSha.status === 0)
|
|
174
|
-
candidates.push({ ref: upstreamRef, sha: upstreamSha.stdout.trim() });
|
|
175
|
-
if (candidates.length === 0)
|
|
176
|
-
return null;
|
|
177
|
-
for (const c of candidates) {
|
|
178
|
-
if (gitSync(['merge-base', '--is-ancestor', branchSha, c.sha], cwd).status === 0)
|
|
179
|
-
return { containingRef: c.ref, containingSha: c.sha };
|
|
180
|
-
}
|
|
181
|
-
for (const c of candidates) {
|
|
182
|
-
const cherry = gitSync(['cherry', c.sha, branchSha], cwd);
|
|
183
|
-
if (cherry.status !== 0)
|
|
184
|
-
continue;
|
|
185
|
-
const lines = cherry.stdout.split('\n').map((l) => l.trim()).filter((l) => l !== '');
|
|
186
|
-
if (lines.every((l) => l.startsWith('-')))
|
|
187
|
-
return { containingRef: c.ref, containingSha: c.sha };
|
|
188
|
-
}
|
|
189
|
-
for (const c of candidates) {
|
|
190
|
-
const candidateTree = gitSync(['rev-parse', '--verify', `${c.sha}^{tree}`], cwd);
|
|
191
|
-
if (candidateTree.status !== 0)
|
|
192
|
-
continue;
|
|
193
|
-
const merged = gitSync(['merge-tree', '--write-tree', c.sha, branchSha], cwd);
|
|
194
|
-
if (merged.status !== 0)
|
|
195
|
-
continue;
|
|
196
|
-
if (merged.stdout.split('\n')[0]?.trim() === candidateTree.stdout.trim())
|
|
197
|
-
return { containingRef: c.ref, containingSha: c.sha };
|
|
198
|
-
}
|
|
199
|
-
return null;
|
|
200
|
-
}
|
|
201
|
-
/** Undo a creation attempt, but only resources whose recorded path, branch,
|
|
202
|
-
* and original base still prove they belong to that attempt. */
|
|
203
|
-
function rollbackManagedWorktreeLocked(wt, pathWasAbsent) {
|
|
204
|
-
const branch = gitSync(['rev-parse', '--verify', `refs/heads/${wt.branch}`], wt.repo_root);
|
|
205
|
-
// A branch at the original base is the ownership proof for every destructive
|
|
206
|
-
// rollback step. If it was advanced or repurposed, preserve all resources.
|
|
207
|
-
if (branch.status !== 0 || branch.stdout.trim() !== wt.base_sha)
|
|
208
|
-
return;
|
|
209
|
-
const registration = registeredWorktree(wt.repo_root, wt.path, wt.branch);
|
|
210
|
-
// A failed registry read proves nothing. Preserve every resource rather than
|
|
211
|
-
// guessing that an uninspected checkout belongs to this failed attempt.
|
|
212
|
-
if (registration === null)
|
|
213
|
-
return;
|
|
214
|
-
if (registration) {
|
|
215
|
-
if (gitSync(['worktree', 'remove', '--force', wt.path], wt.repo_root).status !== 0)
|
|
216
|
-
return;
|
|
217
|
-
if (registeredWorktree(wt.repo_root, wt.path, wt.branch) !== false)
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
else if (pathWasAbsent && existsSync(wt.path)) {
|
|
221
|
-
// The caller observed this path absent while holding the repository lock;
|
|
222
|
-
// only its failed `worktree add` can have created it.
|
|
223
|
-
try {
|
|
224
|
-
rmSync(wt.path, { recursive: true, force: true });
|
|
225
|
-
}
|
|
226
|
-
catch {
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
// Compare-and-delete retains the ownership guard through the final mutation.
|
|
231
|
-
try {
|
|
232
|
-
gitSync(['update-ref', '-d', `refs/heads/${wt.branch}`, wt.base_sha], wt.repo_root);
|
|
233
|
-
}
|
|
234
|
-
catch { /* best-effort */ }
|
|
235
|
-
}
|
|
236
|
-
export function rollbackManagedWorktree(wt) {
|
|
237
|
-
withRepositoryWorktreeLock(wt.repo_root, () => rollbackManagedWorktreeLocked(wt, false));
|
|
238
|
-
}
|
|
239
|
-
// Every crtr process auto-initializes a project scope's
|
|
240
|
-
// `.crouter/config.json` (`ensureProjectScope` → `ensureScopeInitialized`)
|
|
241
|
-
// the first time it runs against a project root that has no ancestor
|
|
242
|
-
// `.crouter/` yet — which every fresh managed worktree checkout is, unless
|
|
243
|
-
// the repo itself already tracks `.crouter/memory/` (crouter's own repo does).
|
|
244
|
-
// That write is untracked crtr bookkeeping, not node work, so `git status`
|
|
245
|
-
// inside the worktree always shows `?? .crouter/config.json` and `close`'s
|
|
246
|
-
// dirty check refuses to land. `state.json` is the same category (written at
|
|
247
|
-
// project scope by explicit `pkg`/`canvas config` commands) — excluded
|
|
248
|
-
// defensively even though no automatic path writes it today.
|
|
249
|
-
//
|
|
250
|
-
// These two filenames, NOT the whole `.crouter/` directory, are the only
|
|
251
|
-
// patterns seeded below. `.git/info/exclude` only ever suppresses UNTRACKED
|
|
252
|
-
// paths from `git status` — it can never hide a modification to an
|
|
253
|
-
// already-tracked file — but crouter's own repo tracks `.crouter/memory/`,
|
|
254
|
-
// and a node can legitimately add a brand-new (untracked until committed)
|
|
255
|
-
// memory doc there. A blanket `.crouter/` exclude would silently hide that
|
|
256
|
-
// new doc from `git status` too, letting close/push-final land or auto-drop
|
|
257
|
-
// while it is quietly lost. Naming exactly `config.json`/`state.json` avoids
|
|
258
|
-
// that: nothing crtr writes automatically ever lands under `.crouter/memory/`.
|
|
259
|
-
const MANAGED_WORKTREE_EXCLUDE_MARKER = '# crtr: exclude crtr\'s own untracked project-scope bookkeeping (auto-added at managed-worktree creation)';
|
|
260
|
-
const MANAGED_WORKTREE_EXCLUDE_PATTERNS = [
|
|
261
|
-
`/${CRTR_DIR_NAME}/${CONFIG_FILE}`,
|
|
262
|
-
`/${CRTR_DIR_NAME}/${STATE_FILE}`,
|
|
263
|
-
];
|
|
264
|
-
/** Seed the repository's SHARED `.git/info/exclude` (one file per common git
|
|
265
|
-
* dir, not per worktree — `git rev-parse --git-path info/exclude` resolves
|
|
266
|
-
* there from every linked worktree, including the primary checkout) with
|
|
267
|
-
* crtr's own runtime bookkeeping patterns, idempotently. Leading `/` anchors
|
|
268
|
-
* each pattern to the toplevel of WHICHEVER worktree `git status` runs in,
|
|
269
|
-
* which is exactly where `ensureScopeInitialized` writes `.crouter/config.json`
|
|
270
|
-
* — the managed worktree's own root. Called once per managed-worktree
|
|
271
|
-
* creation, already inside `withRepositoryWorktreeLock`, so concurrent
|
|
272
|
-
* creators cannot race the append. */
|
|
273
|
-
function seedManagedWorktreeExclude(repoRoot) {
|
|
274
|
-
try {
|
|
275
|
-
const excludePath = join(commonGitDir(repoRoot), 'info', 'exclude');
|
|
276
|
-
mkdirSync(dirname(excludePath), { recursive: true });
|
|
277
|
-
let existing = '';
|
|
278
|
-
try {
|
|
279
|
-
existing = readFileSync(excludePath, 'utf8');
|
|
280
|
-
}
|
|
281
|
-
catch { /* first worktree this repo has ever had */ }
|
|
282
|
-
const present = new Set(existing.split('\n').map((l) => l.trim()));
|
|
283
|
-
const missing = MANAGED_WORKTREE_EXCLUDE_PATTERNS.filter((p) => !present.has(p));
|
|
284
|
-
if (missing.length === 0)
|
|
285
|
-
return;
|
|
286
|
-
const needsLeadingNewline = existing.length > 0 && !existing.endsWith('\n');
|
|
287
|
-
const block = (needsLeadingNewline ? '\n' : '') + MANAGED_WORKTREE_EXCLUDE_MARKER + '\n' + missing.join('\n') + '\n';
|
|
288
|
-
writeFileSync(excludePath, existing + block);
|
|
289
|
-
}
|
|
290
|
-
catch { /* best-effort; a failure here is cosmetic (one extra untracked bookkeeping line in git status) and must never fail worktree creation */ }
|
|
291
|
-
}
|
|
292
|
-
export function createManagedWorktree(cwd, nodeId, baseRef = 'main') {
|
|
293
|
-
const repoRoot = repoRootFor(cwd);
|
|
294
|
-
if (isManagedWorktreeBase(repoRoot)) {
|
|
295
|
-
throw new WorktreeError('managed_worktree_base', `cwd ${repoRoot} is a managed worktree and cannot be used as a managed worktree base`, 'Pass --cwd <real repo> pointing at the repository’s primary checkout.');
|
|
296
|
-
}
|
|
297
|
-
return withRepositoryWorktreeLock(repoRoot, () => {
|
|
298
|
-
const baseSha = resolveLandableBase(repoRoot, baseRef);
|
|
299
|
-
const path = managedWorktreePath(nodeId);
|
|
300
|
-
const branch = `crtr/${nodeId}`;
|
|
301
|
-
if (existsSync(path)) {
|
|
302
|
-
throw new WorktreeError('worktree_path_exists', `managed worktree path already exists: ${path}`, 'Remove the stale path or choose a fresh node id.');
|
|
303
|
-
}
|
|
304
|
-
if (gitSync(['show-ref', '--verify', '--quiet', `refs/heads/${branch}`], repoRoot).status === 0) {
|
|
305
|
-
throw new WorktreeError('worktree_branch_exists', `managed worktree branch already exists: ${branch}`, 'Remove the stale branch or choose a fresh node id.');
|
|
306
|
-
}
|
|
307
|
-
const wt = {
|
|
308
|
-
state: 'open', path, branch, repo_root: repoRoot, base_ref: baseRef, base_sha: baseSha, created: new Date().toISOString(),
|
|
309
|
-
};
|
|
310
|
-
runGit(repoRoot, ['branch', branch, baseSha], 'worktree_branch_create_failed', 'Inspect the git error, fix the repository/worktree state, then retry spawning with --worktree.');
|
|
311
|
-
try {
|
|
312
|
-
runGit(repoRoot, ['worktree', 'add', path, branch], 'worktree_add_failed', 'Inspect the git error, fix the repository/worktree state, then retry spawning with --worktree.');
|
|
313
|
-
seedManagedWorktreeExclude(repoRoot);
|
|
314
|
-
return wt;
|
|
315
|
-
}
|
|
316
|
-
catch (err) {
|
|
317
|
-
rollbackManagedWorktreeLocked(wt, true);
|
|
318
|
-
throw err;
|
|
319
|
-
}
|
|
320
|
-
});
|
|
321
|
-
}
|
|
322
|
-
function statusPorcelain(cwd) {
|
|
323
|
-
return runGit(cwd, ['status', '--porcelain'], 'status_failed', 'Inspect the worktree manually, then retry.');
|
|
324
|
-
}
|
|
325
|
-
function currentBranch(cwd) {
|
|
326
|
-
return runGit(cwd, ['rev-parse', '--abbrev-ref', 'HEAD'], 'branch_check_failed', 'Inspect the worktree manually, then retry.');
|
|
327
|
-
}
|
|
328
|
-
function gitPath(cwd, logicalPath) {
|
|
329
|
-
return runGit(cwd, ['rev-parse', '--git-path', logicalPath], 'git_path_failed', 'Inspect the worktree manually, then retry.');
|
|
330
|
-
}
|
|
331
|
-
export function isRebaseInProgress(cwd) {
|
|
332
|
-
return existsSync(gitPath(cwd, 'rebase-merge')) || existsSync(gitPath(cwd, 'rebase-apply'));
|
|
333
|
-
}
|
|
334
|
-
/** The ONE authoritative closed-worktree state transition, shared by every
|
|
335
|
-
* closing path (explicit `closeManagedWorktreeLocked` land, the clean
|
|
336
|
-
* `autoDropCleanManagedWorktreeLocked` push-final drop, and the daemon sweep's
|
|
337
|
-
* `reconcileManagedWorktree`): persist
|
|
338
|
-
* `managed_worktree.state: 'closed'`, name its cleanup state, and repoint the
|
|
339
|
-
* node's launch `cwd` to the durable base checkout. The caller broker stays
|
|
340
|
-
* alive and is Pi's sole transcript writer, so its session header cannot be
|
|
341
|
-
* safely rewritten here; clear the session coordinates and let the later
|
|
342
|
-
* revive launch fresh instead. Both closing paths MUST go through this helper
|
|
343
|
-
* instead of hand-rolling the `updateNode` call, so neither can drift out of
|
|
344
|
-
* sync. */
|
|
345
|
-
export function persistClosedWorktreeState(nodeId, wt, cleanup = 'pending') {
|
|
346
|
-
const node = getNode(nodeId);
|
|
347
|
-
closeWorktreeAndRepoint(nodeId, {
|
|
348
|
-
cwd: wt.repo_root,
|
|
349
|
-
cleanup,
|
|
350
|
-
closedAt: new Date().toISOString(),
|
|
351
|
-
unbindSession: node?.pi_session_id != null || node?.pi_session_file != null,
|
|
352
|
-
});
|
|
353
|
-
}
|
|
354
|
-
/** Record that this node ASKED to land and was blocked, so the daemon sweep may
|
|
355
|
-
* later retry exactly that land once the base checkout stops blocking it. The
|
|
356
|
-
* sweep never lands commits for a node that did not get this far: a node that
|
|
357
|
-
* crashed mid-work and never called close has its worktree preserved for a
|
|
358
|
-
* human instead. Recording a fresh intent also clears any prior refusal state,
|
|
359
|
-
* so the sweep re-examines promptly rather than honoring an old backoff. */
|
|
360
|
-
function recordBlockedLandIntent(nodeId, blocked) {
|
|
361
|
-
const current = getNode(nodeId)?.managed_worktree;
|
|
362
|
-
if (current == null || current.state !== 'open')
|
|
363
|
-
return;
|
|
364
|
-
recordLandIntent(nodeId, { at: new Date().toISOString(), blocked });
|
|
365
|
-
}
|
|
366
|
-
/** Fast-forward a base branch that is CHECKED OUT somewhere, landing underneath
|
|
367
|
-
* whatever local changes that checkout holds.
|
|
368
|
-
*
|
|
369
|
-
* The base checkout is shared by every other node using this repository, and
|
|
370
|
-
* its local changes usually have nothing to do with the child that is closing.
|
|
371
|
-
* Disjoint changes ride along untouched; overlapping ones are stashed, the
|
|
372
|
-
* fast-forward runs underneath them, and they are re-applied. The re-apply is
|
|
373
|
-
* `stash apply`, never `stash pop`, so a conflict cannot consume the stash and
|
|
374
|
-
* lose the work: on conflict the checkout is reset to the landed commit and the
|
|
375
|
-
* stash is deliberately KEPT for a person to apply. Either way this never
|
|
376
|
-
* leaves conflict markers behind in a checkout other nodes are using. */
|
|
377
|
-
function landIntoBaseCheckout(baseCheckout, branch, baseSha, landedSha) {
|
|
378
|
-
const status = gitSync(['status', '--porcelain'], baseCheckout);
|
|
379
|
-
if (status.status !== 0)
|
|
380
|
-
return { ok: false, detail: (status.stderr.trim() || status.stdout.trim()).trim() };
|
|
381
|
-
const diff = gitSync(['diff', '--name-only', baseSha, landedSha], baseCheckout);
|
|
382
|
-
if (diff.status !== 0)
|
|
383
|
-
return { ok: false, detail: (diff.stderr.trim() || diff.stdout.trim()).trim() };
|
|
384
|
-
const incoming = diff.stdout.split('\n').map((l) => l.trim()).filter((l) => l !== '');
|
|
385
|
-
const plan = planLandIntoCheckout(parseStatusPorcelain(status.stdout), incoming);
|
|
386
|
-
if (plan.kind === 'refuse') {
|
|
387
|
-
return { ok: false, detail: `untracked files in ${baseCheckout} would be overwritten by the incoming commits: ${plan.collisions.join(', ')}` };
|
|
388
|
-
}
|
|
389
|
-
const merge = () => {
|
|
390
|
-
const res = gitSync(['merge', '--ff-only', landedSha], baseCheckout);
|
|
391
|
-
return res.status === 0 ? { ok: true } : { ok: false, detail: (res.stderr.trim() || res.stdout.trim()).trim() };
|
|
392
|
-
};
|
|
393
|
-
if (plan.kind === 'direct')
|
|
394
|
-
return merge();
|
|
395
|
-
// Identify the stash by the exact commit this push created. `refs/stash` can
|
|
396
|
-
// already name an UNRELATED stash the user made earlier, and a push that
|
|
397
|
-
// saved nothing leaves it untouched — applying or dropping that one would
|
|
398
|
-
// destroy work this code never owned.
|
|
399
|
-
const before = gitSync(['rev-parse', '--verify', '--quiet', 'refs/stash'], baseCheckout);
|
|
400
|
-
const beforeSha = before.status === 0 ? before.stdout.trim() : null;
|
|
401
|
-
const push = gitSync(['stash', 'push', '--message', `crtr landing ${branch}`], baseCheckout);
|
|
402
|
-
if (push.status !== 0)
|
|
403
|
-
return { ok: false, detail: (push.stderr.trim() || push.stdout.trim()).trim() };
|
|
404
|
-
const after = gitSync(['rev-parse', '--verify', '--quiet', 'refs/stash'], baseCheckout);
|
|
405
|
-
const stashSha = after.status === 0 ? after.stdout.trim() : null;
|
|
406
|
-
if (stashSha === null || stashSha === beforeSha)
|
|
407
|
-
return merge(); // nothing was saved
|
|
408
|
-
const recovery = `local changes from ${baseCheckout} are retained in stash ${stashSha}; recover them with \`git -C ${shellQuote(baseCheckout)} stash apply ${stashSha}\` and resolve any conflict.`;
|
|
409
|
-
const landed = merge();
|
|
410
|
-
if (!landed.ok) {
|
|
411
|
-
// The failed merge left the tree exactly as the stash found it, so this
|
|
412
|
-
// re-apply is clean; restore before surfacing the refusal.
|
|
413
|
-
if (gitSync(['stash', 'apply', stashSha], baseCheckout).status === 0) {
|
|
414
|
-
dropStashIfStillTip(baseCheckout, stashSha);
|
|
415
|
-
return landed;
|
|
416
|
-
}
|
|
417
|
-
return { ok: false, detail: `${landed.detail}\n${recovery}` };
|
|
418
|
-
}
|
|
419
|
-
if (gitSync(['stash', 'apply', stashSha], baseCheckout).status === 0) {
|
|
420
|
-
dropStashIfStillTip(baseCheckout, stashSha);
|
|
421
|
-
return { ok: true };
|
|
422
|
-
}
|
|
423
|
-
gitSync(['reset', '--hard', landedSha], baseCheckout);
|
|
424
|
-
return {
|
|
425
|
-
ok: true,
|
|
426
|
-
stash: `the shared base checkout was reset to landed commit ${landedSha} because local changes conflicted with it. ${recovery}`,
|
|
427
|
-
};
|
|
428
|
-
}
|
|
429
|
-
/** Drop a stash entry only while it is still the tip `stash@{0}` names, so a
|
|
430
|
-
* stash someone else pushed in between is never dropped instead. */
|
|
431
|
-
function dropStashIfStillTip(cwd, stashSha) {
|
|
432
|
-
const tip = gitSync(['rev-parse', '--verify', '--quiet', 'refs/stash'], cwd);
|
|
433
|
-
if (tip.status === 0 && tip.stdout.trim() === stashSha)
|
|
434
|
-
gitSync(['stash', 'drop'], cwd);
|
|
435
|
-
}
|
|
436
|
-
function deferredCleanupResult(wt) {
|
|
437
|
-
const remove = `git -C ${shellQuote(wt.repo_root)} worktree remove ${shellQuote(wt.path)}`;
|
|
438
|
-
return {
|
|
439
|
-
worktree_removed: false,
|
|
440
|
-
worktree_remove_error: `cleanup pending: the caller checkout at ${wt.path} remains intact. After its node exits, run \`${remove}\` after confirming it is safe to delete.`,
|
|
441
|
-
branch_deleted: false,
|
|
442
|
-
branch_delete_error: `cleanup pending: local branch ${wt.branch} remains checked out at ${wt.path}; delete it only after that checkout is removed and its landed commit is still contained in ${wt.base_ref}.`,
|
|
443
|
-
};
|
|
444
|
-
}
|
|
445
|
-
/** The disposal path for `close` when the recorded `crtr/*` branch is gone:
|
|
446
|
-
* ordinary PR work moved this checkout onto a real branch. This never lands
|
|
447
|
-
* or rebases that branch — it belongs to a workflow crouter does not own —
|
|
448
|
-
* and never deletes it. It only AUTHORIZES the daemon sweep to remove the
|
|
449
|
-
* checkout later, once this node's own broker has exited, and only after
|
|
450
|
-
* proving the branch's content is already delivered. Runs after the caller
|
|
451
|
-
* already proved the checkout clean and not mid-rebase. */
|
|
452
|
-
function closeBranchMovedWorktree(nodeId, wt, actualBranch) {
|
|
453
|
-
if (registeredWorktree(wt.repo_root, wt.path, actualBranch) !== true) {
|
|
454
|
-
throw new WorktreeError('wrong_branch', `managed worktree's recorded branch ${wt.branch} no longer exists, and its checkout at ${wt.path} is not registered to ${actualBranch} either`, `Inspect ${wt.path} and its git worktree registration, then ask the user with \`crtr human send\` if you are unsure how to proceed.`);
|
|
455
|
-
}
|
|
456
|
-
const actualSha = runGit(wt.path, ['rev-parse', 'HEAD'], 'branch_check_failed', 'Inspect the worktree manually, then retry.');
|
|
457
|
-
const proof = proveBranchContained(wt.path, wt.base_ref, actualSha);
|
|
458
|
-
if (proof === null) {
|
|
459
|
-
throw new WorktreeError('branch_moved_unlanded', `managed worktree's recorded branch ${wt.branch} no longer exists; its checkout is now on ${actualBranch} at ${actualSha}, which carries content local base branch '${wt.base_ref}' does not yet contain`, `Land or push ${actualBranch} through its own workflow (merge its PR, or fast-forward '${wt.base_ref}' to include it) before closing, or ask the user with \`crtr human send\` if you are unsure how ${actualBranch} should be delivered.`);
|
|
460
|
-
}
|
|
461
|
-
const commonDir = commonGitDir(wt.repo_root);
|
|
462
|
-
// Recheck identity immediately before writing the authorization: nothing
|
|
463
|
-
// about the checkout may have moved between the proof above and this write.
|
|
464
|
-
const stillRegistered = registeredWorktree(wt.repo_root, wt.path, actualBranch) === true;
|
|
465
|
-
const stillOnBranch = currentBranch(wt.path) === actualBranch;
|
|
466
|
-
const stillAtSha = runGit(wt.path, ['rev-parse', 'HEAD'], 'branch_check_failed', 'Inspect the worktree manually, then retry.') === actualSha;
|
|
467
|
-
if (!stillRegistered || !stillOnBranch || !stillAtSha) {
|
|
468
|
-
throw new WorktreeError('wrong_branch', `managed worktree at ${wt.path} changed while closing`, `Inspect ${wt.path}, then rerun \`crtr node worktree close\`.`);
|
|
469
|
-
}
|
|
470
|
-
const disposal = { observed_branch: actualBranch, observed_sha: actualSha, common_dir: commonDir, authorized: new Date().toISOString() };
|
|
471
|
-
persistClosedWorktreeState(nodeId, { ...wt, disposal }, 'pending');
|
|
472
|
-
const remove = `git -C ${shellQuote(wt.repo_root)} worktree remove ${shellQuote(wt.path)}`;
|
|
473
|
-
return {
|
|
474
|
-
node_id: nodeId,
|
|
475
|
-
branch: actualBranch,
|
|
476
|
-
worktree_path: wt.path,
|
|
477
|
-
// Nothing was rebased or fast-forwarded here: `${actualBranch}`'s content
|
|
478
|
-
// was already proven contained in `${proof.containingRef}` at `${proof.containingSha}`.
|
|
479
|
-
landed_sha: actualSha,
|
|
480
|
-
worktree_removed: false,
|
|
481
|
-
worktree_remove_error: `cleanup pending: the caller checkout at ${wt.path} remains intact. After its node exits, run \`${remove}\` after confirming it is safe to delete.`,
|
|
482
|
-
branch_deleted: false,
|
|
483
|
-
branch_delete_error: `${actualBranch} is not a crtr-managed branch and will never be deleted automatically; it is preserved once the checkout above is removed.`,
|
|
484
|
-
};
|
|
485
|
-
}
|
|
486
|
-
/** Word the `no_managed_worktree` refusal from the record's ACTUAL state
|
|
487
|
-
* rather than a blanket "no worktree". A `closed`/`cleanup: pending` record
|
|
488
|
-
* still has its checkout on disk, scheduled for the daemon sweep to finish —
|
|
489
|
-
* that is not lost ownership, and three separate reports (#849, #862, #872)
|
|
490
|
-
* were misdiagnosed because the old wording read as if it were. */
|
|
491
|
-
function noManagedWorktreeMessage(nodeId, verb) {
|
|
492
|
-
const wt = getNode(nodeId)?.managed_worktree;
|
|
493
|
-
if (wt == null)
|
|
494
|
-
return { message: `node ${nodeId} has no managed worktree`, next: `Nothing to ${verb} for this node.` };
|
|
495
|
-
if (wt.state === 'abandoned') {
|
|
496
|
-
const branch = wt.abandoned?.branch ?? wt.branch;
|
|
497
|
-
return { message: `node ${nodeId}'s managed worktree was already abandoned`, next: `Nothing to ${verb} for this node; its work was retained on branch ${branch}.` };
|
|
498
|
-
}
|
|
499
|
-
if (wt.state === 'closed') {
|
|
500
|
-
return wt.cleanup === 'complete'
|
|
501
|
-
? { message: `node ${nodeId}'s managed worktree is already closed and its cleanup is complete`, next: `Nothing to ${verb} for this node.` }
|
|
502
|
-
: { message: `node ${nodeId}'s managed worktree is already closed; this is not lost ownership — its checkout at ${wt.path} is scheduled for automatic cleanup once that is safe`, next: `Nothing to ${verb} for this node. The daemon sweep finishes removing ${wt.path} on its own; inspect it directly only if it still needs manual attention.` };
|
|
503
|
-
}
|
|
504
|
-
return { message: `node ${nodeId} has no open managed worktree`, next: `Nothing to ${verb} for this node.` };
|
|
505
|
-
}
|
|
506
|
-
function closeManagedWorktreeLocked(nodeId) {
|
|
507
|
-
const node = getNode(nodeId);
|
|
508
|
-
if (node === null) {
|
|
509
|
-
throw new WorktreeError('unknown_node', `unknown node: ${nodeId}`, 'Run this from a live node, or pass a real node id once that command supports it.');
|
|
510
|
-
}
|
|
511
|
-
const wt = openManagedWorktreeForNode(nodeId);
|
|
512
|
-
if (wt === null) {
|
|
513
|
-
const { message, next } = noManagedWorktreeMessage(nodeId, 'close');
|
|
514
|
-
throw new WorktreeError('no_managed_worktree', message, next);
|
|
515
|
-
}
|
|
516
|
-
if (!existsSync(wt.path)) {
|
|
517
|
-
const proof = proveAbsentPathManagedWorktree(wt);
|
|
518
|
-
if (proof === null) {
|
|
519
|
-
throw new WorktreeError('worktree_missing', `managed worktree path is missing: ${wt.path}`, missingWorktreeRecoveryHint(wt));
|
|
520
|
-
}
|
|
521
|
-
const dropped = autoDropAbsentPathManagedWorktreeLocked(nodeId, wt, proof);
|
|
522
|
-
if (dropped === null) {
|
|
523
|
-
throw new WorktreeError('worktree_missing', `managed worktree path is missing: ${wt.path}`, missingWorktreeRecoveryHint(wt));
|
|
524
|
-
}
|
|
525
|
-
return {
|
|
526
|
-
node_id: nodeId,
|
|
527
|
-
branch: wt.branch,
|
|
528
|
-
worktree_path: wt.path,
|
|
529
|
-
// No local fast-forward happened in this recovery path. When the branch
|
|
530
|
-
// still exists, this is its remotely/local-base-delivered tip; when it
|
|
531
|
-
// was already deleted, the recorded creation base is the only durable
|
|
532
|
-
// SHA left to report through the established close result contract.
|
|
533
|
-
landed_sha: proof.branchSha ?? wt.base_sha,
|
|
534
|
-
worktree_removed: true,
|
|
535
|
-
branch_deleted: true,
|
|
536
|
-
};
|
|
537
|
-
}
|
|
538
|
-
if (isRebaseInProgress(wt.path)) {
|
|
539
|
-
throw new WorktreeError('rebase_in_progress', 'this managed worktree is mid-rebase', `Resolve conflicts in ${wt.path}, run \`git rebase --continue\` there, then rerun \`crtr node worktree close\`.`);
|
|
540
|
-
}
|
|
541
|
-
const dirty = statusPorcelain(wt.path);
|
|
542
|
-
if (dirty !== '') {
|
|
543
|
-
throw new WorktreeError('dirty_worktree', 'managed worktree has uncommitted changes', `Commit the work in ${wt.path} (or ask the user with \`crtr human send\` if you do not know whether to keep it), then rerun \`crtr node worktree close\`.`);
|
|
544
|
-
}
|
|
545
|
-
const branch = currentBranch(wt.path);
|
|
546
|
-
if (branch !== wt.branch) {
|
|
547
|
-
const found = branch === 'HEAD' ? 'detached HEAD' : branch;
|
|
548
|
-
const recordedRefExists = recordedBranchExists(wt.path, wt.branch);
|
|
549
|
-
if (recordedRefExists || branch === 'HEAD') {
|
|
550
|
-
throw new WorktreeError('wrong_branch', `managed worktree is not on its recorded branch (expected ${wt.branch}, found ${found})`, recordedRefExists
|
|
551
|
-
? `Check out ${wt.branch} in ${wt.path} before closing, or ask the user with \`crtr human send\` if you are unsure why it changed, then rerun \`crtr node worktree close\`.`
|
|
552
|
-
: `The recorded branch ${wt.branch} no longer exists, and ${wt.path} is in detached HEAD, so there is no branch to preserve. Check out or create a branch there before closing, or ask the user with \`crtr human send\` if you are unsure how to proceed.`);
|
|
553
|
-
}
|
|
554
|
-
// The recorded crtr/* branch is gone: ordinary PR work moved this checkout
|
|
555
|
-
// onto a real branch. The checkout is already proven clean and not
|
|
556
|
-
// mid-rebase (both checked above), so disposal may proceed.
|
|
557
|
-
return closeBranchMovedWorktree(nodeId, wt, branch);
|
|
558
|
-
}
|
|
559
|
-
let baseSha;
|
|
560
|
-
try {
|
|
561
|
-
// `repo_root` is the checkout that created this child, and it can vanish
|
|
562
|
-
// when that parent finishes first. The live managed checkout still names
|
|
563
|
-
// the shared repository and is the authority for every close operation.
|
|
564
|
-
baseSha = resolveLandableBase(wt.path, wt.base_ref);
|
|
565
|
-
}
|
|
566
|
-
catch (error) {
|
|
567
|
-
// A deleted parent base cannot receive a fast-forward. A clean child at
|
|
568
|
-
// its recorded creation SHA has nothing to land, however, so conclude its
|
|
569
|
-
// deferred cleanup without guessing where work should go.
|
|
570
|
-
const head = runGit(wt.path, ['rev-parse', 'HEAD'], 'landed_sha_failed', 'Inspect the worktree checkout manually, then rerun `crtr node worktree close`.');
|
|
571
|
-
if (!(error instanceof WorktreeError) || error.code !== 'missing_base_branch' || head !== wt.base_sha)
|
|
572
|
-
throw error;
|
|
573
|
-
persistClosedWorktreeState(nodeId, wt, 'pending');
|
|
574
|
-
return {
|
|
575
|
-
node_id: nodeId,
|
|
576
|
-
branch: wt.branch,
|
|
577
|
-
worktree_path: wt.path,
|
|
578
|
-
landed_sha: wt.base_sha,
|
|
579
|
-
...deferredCleanupResult(wt),
|
|
580
|
-
};
|
|
581
|
-
}
|
|
582
|
-
const rebase = gitSync(['rebase', baseSha], wt.path);
|
|
583
|
-
if (rebase.status !== 0) {
|
|
584
|
-
const detail = (rebase.stderr.trim() || rebase.stdout.trim()).trim();
|
|
585
|
-
throw new WorktreeError('rebase_failed', `rebase onto local base branch '${wt.base_ref}' did not complete`, `Resolve conflicts in ${wt.path}, run \`git rebase --continue\` there, then rerun \`crtr node worktree close\`. If the blocker is not mechanical, ask the user with \`crtr human send\`.`, detail);
|
|
586
|
-
}
|
|
587
|
-
const landedSha = runGit(wt.path, ['rev-parse', 'HEAD'], 'landed_sha_failed', 'Inspect the worktree checkout manually, then rerun `crtr node worktree close`.');
|
|
588
|
-
// Fast-forward the local base branch to the worktree tip rebased onto the
|
|
589
|
-
// captured baseSha — landing is purely local, nothing is ever pushed to
|
|
590
|
-
// origin. Both landing paths require the base to still be exactly at that
|
|
591
|
-
// captured tip, so neither can overwrite a concurrent base change.
|
|
592
|
-
// Every refusal below leaves a rebased, landable branch that this node ASKED
|
|
593
|
-
// to land. Recording that blocked intent is what later authorizes the daemon
|
|
594
|
-
// sweep to finish exactly this land once the blocker clears.
|
|
595
|
-
const blocked = (message, next, detail) => {
|
|
596
|
-
recordBlockedLandIntent(nodeId, message);
|
|
597
|
-
return new WorktreeError('land_base_failed', message, next, detail);
|
|
598
|
-
};
|
|
599
|
-
const fastForward = gitSync(['merge-base', '--is-ancestor', baseSha, landedSha], wt.path);
|
|
600
|
-
if (fastForward.status !== 0) {
|
|
601
|
-
throw blocked(`rebased worktree is not a fast-forward of local base branch '${wt.base_ref}'`, 'Ask the user with `crtr human send` how to land this managed worktree.', (fastForward.stderr.trim() || fastForward.stdout.trim()).trim());
|
|
602
|
-
}
|
|
603
|
-
const baseCheckout = checkoutPathForBranch(wt.path, wt.base_ref);
|
|
604
|
-
if (baseCheckout !== null) {
|
|
605
|
-
const checkoutHead = gitSync(['rev-parse', 'HEAD'], baseCheckout);
|
|
606
|
-
const actualHead = checkoutHead.stdout.trim();
|
|
607
|
-
if (checkoutHead.status !== 0 || actualHead !== baseSha) {
|
|
608
|
-
const detail = checkoutHead.status !== 0
|
|
609
|
-
? (checkoutHead.stderr.trim() || actualHead).trim()
|
|
610
|
-
: `expected ${baseSha}, found ${actualHead}`;
|
|
611
|
-
throw blocked(`local base branch '${wt.base_ref}' changed while this worktree was closing`, `Reconcile the base checkout at ${baseCheckout}, then rerun \`crtr node worktree close\`. If you are unsure, ask the user with \`crtr human send\`.`, detail);
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
let stashNote;
|
|
615
|
-
if (baseCheckout !== null) {
|
|
616
|
-
const landed = landIntoBaseCheckout(baseCheckout, wt.branch, baseSha, landedSha);
|
|
617
|
-
if (!landed.ok) {
|
|
618
|
-
throw blocked(`could not fast-forward local base branch '${wt.base_ref}' to this worktree`, `Local base branch '${wt.base_ref}' is checked out at ${baseCheckout} in a state that blocks a fast-forward. Reconcile it there, then rerun \`crtr node worktree close\`. If you are unsure, ask the user with \`crtr human send\`.`, landed.detail);
|
|
619
|
-
}
|
|
620
|
-
stashNote = landed.stash;
|
|
621
|
-
}
|
|
622
|
-
else {
|
|
623
|
-
const land = gitSync(['update-ref', `refs/heads/${wt.base_ref}`, landedSha, baseSha], wt.path);
|
|
624
|
-
if (land.status !== 0) {
|
|
625
|
-
throw blocked(`could not fast-forward local base branch '${wt.base_ref}' to this worktree`, 'Ask the user with `crtr human send` how to land this managed worktree.', (land.stderr.trim() || land.stdout.trim()).trim());
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
// The caller broker still runs from wt.path after this API response. Do not
|
|
629
|
-
// invoke `git worktree remove`: it recursively deletes the caller's cwd and
|
|
630
|
-
// a timeout can kill Git between individual unlink operations. Keep the
|
|
631
|
-
// checkout and its checked-out branch intact in the named pending-cleanup
|
|
632
|
-
// state; the successful land is still the point of no return for this node.
|
|
633
|
-
persistClosedWorktreeState(nodeId, wt, 'pending');
|
|
634
|
-
return {
|
|
635
|
-
node_id: nodeId,
|
|
636
|
-
branch: wt.branch,
|
|
637
|
-
worktree_path: wt.path,
|
|
638
|
-
landed_sha: landedSha,
|
|
639
|
-
...deferredCleanupResult(wt),
|
|
640
|
-
...(stashNote === undefined ? {} : { base_checkout_stash: stashNote }),
|
|
641
|
-
};
|
|
642
|
-
}
|
|
643
|
-
export function closeManagedWorktree(nodeId) {
|
|
644
|
-
const wt = openManagedWorktreeForNode(nodeId);
|
|
645
|
-
// Preserve the existing precise unknown/no-open-worktree errors without a
|
|
646
|
-
// repository to lock; every state-mutating close path runs under the lock.
|
|
647
|
-
if (wt === null)
|
|
648
|
-
return closeManagedWorktreeLocked(nodeId);
|
|
649
|
-
// An absent checkout has no live Git directory; its separate recovery proof
|
|
650
|
-
// still relies on the recorded repository path. Every live close locks from
|
|
651
|
-
// the child checkout instead of the parent that created it.
|
|
652
|
-
return withRepositoryWorktreeLock(existsSync(wt.path) ? wt.path : wt.repo_root, () => closeManagedWorktreeLocked(nodeId));
|
|
653
|
-
}
|
|
654
|
-
// Push-final auto-drop of a clean, zero-commit managed worktree
|
|
655
|
-
/** Delete a source branch only while the ref that proved it already delivered
|
|
656
|
-
* is still at the exact inspected SHA. `containingRef` can be the recorded
|
|
657
|
-
* local base or that base's remote-tracking upstream. */
|
|
658
|
-
function bestEffortDeleteBranchWithContainmentProof(wt, branchSha, containingRef, containingSha) {
|
|
659
|
-
const stdin = refDeleteTransactionStdin(wt.branch, branchSha, containingRef, containingSha);
|
|
660
|
-
const transaction = gitSync(['update-ref', '--stdin'], wt.repo_root, stdin);
|
|
661
|
-
const branchDeleted = transaction.status === 0;
|
|
662
|
-
if (branchDeleted)
|
|
663
|
-
return { branchDeleted };
|
|
664
|
-
const detail = (transaction.stderr.trim() || transaction.stdout.trim()).trim();
|
|
665
|
-
return {
|
|
666
|
-
branchDeleted,
|
|
667
|
-
branchDeleteError: `local branch ${wt.branch} could not be deleted automatically (${detail}); run \`git -C ${shellQuote(wt.repo_root)} branch -D ${shellQuote(wt.branch)}\` after confirming it is merged.`,
|
|
668
|
-
};
|
|
669
|
-
}
|
|
670
|
-
/** A missing checkout can still be concluded, but only from refs: either the
|
|
671
|
-
* recorded local branch is already gone, or its tip is contained in the
|
|
672
|
-
* recorded base or that base's upstream. Filesystem absence alone proves
|
|
673
|
-
* nothing about commits. */
|
|
674
|
-
function proveAbsentPathManagedWorktree(wt) {
|
|
675
|
-
if (wt.state !== 'open' || existsSync(wt.path))
|
|
676
|
-
return null;
|
|
677
|
-
const branchRef = `refs/heads/${wt.branch}`;
|
|
678
|
-
const branchExists = gitSync(['show-ref', '--verify', '--quiet', branchRef], wt.repo_root);
|
|
679
|
-
if (branchExists.status === 1)
|
|
680
|
-
return { branchSha: null };
|
|
681
|
-
if (branchExists.status !== 0)
|
|
682
|
-
return null;
|
|
683
|
-
const branch = gitSync(['rev-parse', '--verify', branchRef], wt.repo_root);
|
|
684
|
-
if (branch.status !== 0)
|
|
685
|
-
return null;
|
|
686
|
-
const branchSha = branch.stdout.trim();
|
|
687
|
-
// The recorded path being absent does NOT mean the branch has no live
|
|
688
|
-
// checkout: `git worktree move` (or a remove-then-re-add elsewhere) can
|
|
689
|
-
// relocate it to a different path while leaving `wt.path` gone. Deleting a
|
|
690
|
-
// branch that is still checked out somewhere else would bypass Git's own
|
|
691
|
-
// checked-out-branch protection and can abandon uncommitted work at that
|
|
692
|
-
// other path. Fail closed on any ambiguity from the inspection itself.
|
|
693
|
-
const worktreeList = gitSync(['worktree', 'list', '--porcelain'], wt.repo_root);
|
|
694
|
-
if (worktreeList.status !== 0)
|
|
695
|
-
return null;
|
|
696
|
-
if (checkoutPathForBranchInList(worktreeList.stdout, wt.branch) !== null)
|
|
697
|
-
return null;
|
|
698
|
-
const candidates = [];
|
|
699
|
-
const localBaseRef = `refs/heads/${wt.base_ref}`;
|
|
700
|
-
const localBaseExists = gitSync(['show-ref', '--verify', '--quiet', localBaseRef], wt.repo_root);
|
|
701
|
-
if (localBaseExists.status === 0) {
|
|
702
|
-
const localBase = gitSync(['rev-parse', '--verify', localBaseRef], wt.repo_root);
|
|
703
|
-
if (localBase.status !== 0)
|
|
704
|
-
return null;
|
|
705
|
-
candidates.push({ ref: localBaseRef, sha: localBase.stdout.trim() });
|
|
706
|
-
}
|
|
707
|
-
else if (localBaseExists.status !== 1) {
|
|
708
|
-
return null;
|
|
709
|
-
}
|
|
710
|
-
const upstream = gitSync(['rev-parse', '--symbolic-full-name', '--verify', `${wt.base_ref}@{upstream}`], wt.repo_root);
|
|
711
|
-
if (upstream.status === 0) {
|
|
712
|
-
const ref = upstream.stdout.trim();
|
|
713
|
-
const sha = gitSync(['rev-parse', '--verify', ref], wt.repo_root);
|
|
714
|
-
if (ref.startsWith('refs/') && sha.status === 0)
|
|
715
|
-
candidates.push({ ref, sha: sha.stdout.trim() });
|
|
716
|
-
}
|
|
717
|
-
else {
|
|
718
|
-
// Managed bases normally track origin. Retained records from before that
|
|
719
|
-
// configuration existed can still prove delivery through origin/<base>.
|
|
720
|
-
const ref = `refs/remotes/origin/${wt.base_ref}`;
|
|
721
|
-
const exists = gitSync(['show-ref', '--verify', '--quiet', ref], wt.repo_root);
|
|
722
|
-
if (exists.status === 0) {
|
|
723
|
-
const sha = gitSync(['rev-parse', '--verify', ref], wt.repo_root);
|
|
724
|
-
if (sha.status === 0)
|
|
725
|
-
candidates.push({ ref, sha: sha.stdout.trim() });
|
|
726
|
-
}
|
|
727
|
-
else if (exists.status !== 1) {
|
|
728
|
-
return null;
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
for (const candidate of candidates) {
|
|
732
|
-
if (gitSync(['merge-base', '--is-ancestor', branchSha, candidate.sha], wt.repo_root).status === 0) {
|
|
733
|
-
return { branchSha, containingRef: candidate.ref, containingSha: candidate.sha };
|
|
734
|
-
}
|
|
735
|
-
}
|
|
736
|
-
return null;
|
|
737
|
-
}
|
|
738
|
-
/** Recovery guidance for a vanished checkout whose refs do not prove that its
|
|
739
|
-
* work is delivered. This deliberately never recommends `worktree close`:
|
|
740
|
-
* that command cannot operate on the absent checkout. */
|
|
741
|
-
export function missingWorktreeRecoveryHint(wt) {
|
|
742
|
-
return `The recorded checkout path is gone, but crtr cannot prove ${wt.branch} is already delivered. Push or land ${wt.branch}, then rerun \`crtr push final\`; if you cannot establish what happened to the branch, ask the user with \`crtr human send\`.`;
|
|
743
|
-
}
|
|
744
|
-
/** Fix B's shared "nothing to land" test — the SAME clean-worktree definition
|
|
745
|
-
* `close`'s own dirty check now naturally satisfies once `.git/info/exclude`
|
|
746
|
-
* hides crtr's own `.crouter/config.json`/`state.json` bookkeeping (Fix A),
|
|
747
|
-
* plus one more requirement close doesn't need: the branch tip must already
|
|
748
|
-
* be a git-ancestor of (or equal to) the CURRENT tip of its recorded base
|
|
749
|
-
* branch — i.e. landing it would be a pure no-op. Any ambiguity (missing
|
|
750
|
-
* path, mid-rebase, wrong branch, an unresolvable base, or a real ancestry
|
|
751
|
-
* divergence) returns null. A missing base is the one exception: equality
|
|
752
|
-
* between the live HEAD and recorded creation SHA proves no work was added.
|
|
753
|
-
* This function only ever proves a no-op land from live Git state, never on
|
|
754
|
-
* a heuristic guess, so real unlanded work always falls through to the explicit-close guard. The locked
|
|
755
|
-
* path re-checks this predicate before recording deferred cleanup; production
|
|
756
|
-
* code must always go through `autoDropCleanManagedWorktree`. */
|
|
757
|
-
export function proveCleanEmptyManagedWorktree(wt) {
|
|
758
|
-
if (wt.state !== 'open')
|
|
759
|
-
return null;
|
|
760
|
-
if (!existsSync(wt.path))
|
|
761
|
-
return null;
|
|
762
|
-
if (isRebaseInProgress(wt.path))
|
|
763
|
-
return null;
|
|
764
|
-
const branch = gitSync(['rev-parse', '--abbrev-ref', 'HEAD'], wt.path);
|
|
765
|
-
if (branch.status !== 0 || branch.stdout.trim() !== wt.branch)
|
|
766
|
-
return null;
|
|
767
|
-
const status = gitSync(['status', '--porcelain'], wt.path);
|
|
768
|
-
if (status.status !== 0 || status.stdout.trim() !== '')
|
|
769
|
-
return null;
|
|
770
|
-
const head = gitSync(['rev-parse', 'HEAD'], wt.path);
|
|
771
|
-
if (head.status !== 0)
|
|
772
|
-
return null;
|
|
773
|
-
const branchSha = head.stdout.trim();
|
|
774
|
-
let baseSha;
|
|
775
|
-
try {
|
|
776
|
-
baseSha = resolveLandableBase(wt.path, wt.base_ref);
|
|
777
|
-
}
|
|
778
|
-
catch (error) {
|
|
779
|
-
// A parent-first close can remove the recorded base branch. Equality with
|
|
780
|
-
// the durable creation SHA proves this clean child never added work.
|
|
781
|
-
if (error instanceof WorktreeError && error.code === 'missing_base_branch' && branchSha === wt.base_sha) {
|
|
782
|
-
return { branchSha, baseSha: wt.base_sha };
|
|
783
|
-
}
|
|
784
|
-
throw error;
|
|
785
|
-
}
|
|
786
|
-
const ancestor = gitSync(['merge-base', '--is-ancestor', branchSha, baseSha], wt.path);
|
|
787
|
-
if (ancestor.status !== 0)
|
|
788
|
-
return null;
|
|
789
|
-
return { branchSha, baseSha };
|
|
790
|
-
}
|
|
791
|
-
/** Conclude an absent-path record only after `proveAbsentPathManagedWorktree`
|
|
792
|
-
* has established the same no-unlanded-work property required by auto-drop.
|
|
793
|
-
* There is no checkout left to remove; persistClosedWorktreeState records the
|
|
794
|
-
* completed cleanup and repoints cwd to the durable base checkout. */
|
|
795
|
-
function autoDropAbsentPathManagedWorktreeLocked(nodeId, wt, proof) {
|
|
796
|
-
if (existsSync(wt.path))
|
|
797
|
-
return null;
|
|
798
|
-
if (proof.branchSha === null) {
|
|
799
|
-
persistClosedWorktreeState(nodeId, wt, 'complete');
|
|
800
|
-
return { node_id: nodeId, branch: wt.branch, worktree_path: wt.path, worktree_removed: true, branch_deleted: true };
|
|
801
|
-
}
|
|
802
|
-
if (proof.containingRef === undefined || proof.containingSha === undefined)
|
|
803
|
-
return null;
|
|
804
|
-
const { branchDeleted } = bestEffortDeleteBranchWithContainmentProof(wt, proof.branchSha, proof.containingRef, proof.containingSha);
|
|
805
|
-
if (!branchDeleted)
|
|
806
|
-
return null;
|
|
807
|
-
persistClosedWorktreeState(nodeId, wt, 'complete');
|
|
808
|
-
return { node_id: nodeId, branch: wt.branch, worktree_path: wt.path, worktree_removed: true, branch_deleted: true };
|
|
809
|
-
}
|
|
810
|
-
/** Re-check a clean auto-drop before closing its record. `push final` runs
|
|
811
|
-
* inside the owner broker, so it has the same destructive-cwd boundary as
|
|
812
|
-
* explicit close: removal and branch deletion are deferred until that owner
|
|
813
|
-
* has exited. */
|
|
814
|
-
export function autoDropCleanManagedWorktreeLocked(nodeId, wt, proof) {
|
|
815
|
-
const current = proveCleanEmptyManagedWorktree(wt);
|
|
816
|
-
if (current === null || current.branchSha !== proof.branchSha)
|
|
817
|
-
return null;
|
|
818
|
-
// The owner is still running in this checkout while it publishes final.
|
|
819
|
-
// Preserve its files and checked-out branch; physical cleanup is explicitly
|
|
820
|
-
// recorded as pending rather than racing Git's recursive removal.
|
|
821
|
-
persistClosedWorktreeState(nodeId, wt, 'pending');
|
|
822
|
-
return {
|
|
823
|
-
node_id: nodeId,
|
|
824
|
-
branch: wt.branch,
|
|
825
|
-
worktree_path: wt.path,
|
|
826
|
-
...deferredCleanupResult(wt),
|
|
827
|
-
};
|
|
828
|
-
}
|
|
829
|
-
/** `push final`'s escape hatch: a managed worktree that has
|
|
830
|
-
* nothing to land is auto-dropped instead of blocking on an explicit
|
|
831
|
-
* `node worktree close` — one the caller may have been told NOT to run
|
|
832
|
-
* because a manager already landed the same change another way, or
|
|
833
|
-
* that never had anything to close in the first place (a read-only
|
|
834
|
-
* review node). Returns null and changes nothing when the worktree is not
|
|
835
|
-
* PROVABLY empty-and-clean by `proveCleanEmptyManagedWorktree`, OR when a
|
|
836
|
-
* concurrent mutation invalidates that proof before the record is closed
|
|
837
|
-
* (see `autoDropCleanManagedWorktreeLocked`); the caller's existing
|
|
838
|
-
* `open_managed_worktree` guard then still applies unchanged — real
|
|
839
|
-
* commits, real uncommitted changes, and a lost race all require the
|
|
840
|
-
* explicit path. */
|
|
841
|
-
function cleanCurrentCheckoutTip(wt) {
|
|
842
|
-
if (wt.state !== 'open' || !existsSync(wt.path) || isRebaseInProgress(wt.path))
|
|
843
|
-
return null;
|
|
844
|
-
const status = gitSync(['status', '--porcelain'], wt.path);
|
|
845
|
-
if (status.status !== 0 || status.stdout.trim() !== '')
|
|
846
|
-
return null;
|
|
847
|
-
const head = gitSync(['rev-parse', 'HEAD'], wt.path);
|
|
848
|
-
return head.status === 0 ? head.stdout.trim() : null;
|
|
849
|
-
}
|
|
850
|
-
export async function branchIsPushedAtCurrentTip(wt) {
|
|
851
|
-
const initialTip = cleanCurrentCheckoutTip(wt);
|
|
852
|
-
if (initialTip === null)
|
|
853
|
-
return false;
|
|
854
|
-
// A cached origin branch can be stale in either direction. Query origin's
|
|
855
|
-
// heads directly and require exact-tip equality: a remote that has an older
|
|
856
|
-
// commit would still leave newer local work stranded at finalization. The
|
|
857
|
-
// branch name is deliberately irrelevant because PR workflows publish this
|
|
858
|
-
// managed checkout's tip under a human-readable branch name.
|
|
859
|
-
// This runs asynchronously with a bounded, non-interactive Git invocation so
|
|
860
|
-
// an unreachable remote never stalls crtrd's event loop.
|
|
861
|
-
const ssh = process.env['GIT_SSH_COMMAND'] ?? process.env['GIT_SSH'] ?? 'ssh';
|
|
862
|
-
const remote = await gitAsync(['ls-remote', '--exit-code', '--heads', 'origin'], wt.path, undefined, { timeoutMs: 10_000, env: { ...process.env, GIT_TERMINAL_PROMPT: '0', GIT_SSH_COMMAND: `${ssh} -o BatchMode=yes` } });
|
|
863
|
-
if (remote.status !== 0)
|
|
864
|
-
return false;
|
|
865
|
-
const remotelyPushed = remote.stdout.split('\n').some((line) => {
|
|
866
|
-
const [sha, ref] = line.split('\t', 2);
|
|
867
|
-
return sha === initialTip && ref?.startsWith('refs/heads/') === true;
|
|
868
|
-
});
|
|
869
|
-
if (!remotelyPushed)
|
|
870
|
-
return false;
|
|
871
|
-
// The remote proof is useful only if the local checkout is still the exact
|
|
872
|
-
// clean tip it inspected when finalization begins.
|
|
873
|
-
return cleanCurrentCheckoutTip(wt) === initialTip;
|
|
874
|
-
}
|
|
875
|
-
export function autoDropCleanManagedWorktree(nodeId) {
|
|
876
|
-
const wt = openManagedWorktreeForNode(nodeId);
|
|
877
|
-
if (wt === null)
|
|
878
|
-
return null;
|
|
879
|
-
// A negative read-only preflight must fail before waiting on the repository
|
|
880
|
-
// mutation lock: real unlanded work should reach push-final's guard promptly.
|
|
881
|
-
const pathAbsent = !existsSync(wt.path);
|
|
882
|
-
if (pathAbsent ? proveAbsentPathManagedWorktree(wt) === null : proveCleanEmptyManagedWorktree(wt) === null)
|
|
883
|
-
return null;
|
|
884
|
-
return withRepositoryWorktreeLock(pathAbsent ? wt.repo_root : wt.path, () => {
|
|
885
|
-
// Re-fetch inside the lock: state may have changed since the caller's
|
|
886
|
-
// hasOpenManagedWorktree check ran outside it.
|
|
887
|
-
const locked = openManagedWorktreeForNode(nodeId);
|
|
888
|
-
if (locked === null)
|
|
889
|
-
return null;
|
|
890
|
-
// Re-prove the matching predicate under the lock before changing state.
|
|
891
|
-
// A path that reappeared follows the ordinary checkout path.
|
|
892
|
-
if (!existsSync(locked.path)) {
|
|
893
|
-
const proof = proveAbsentPathManagedWorktree(locked);
|
|
894
|
-
return proof === null ? null : autoDropAbsentPathManagedWorktreeLocked(nodeId, locked, proof);
|
|
895
|
-
}
|
|
896
|
-
const proof = proveCleanEmptyManagedWorktree(locked);
|
|
897
|
-
return proof === null ? null : autoDropCleanManagedWorktreeLocked(nodeId, locked, proof);
|
|
898
|
-
});
|
|
899
|
-
}
|
|
1
|
+
var J=Object.defineProperty;var a=(e,r)=>J(e,"name",{value:r,configurable:!0});import{existsSync as _,mkdirSync as H,readFileSync as V,realpathSync as N,rmSync as Y,writeFileSync as Z}from"node:fs";import{createHash as ee}from"node:crypto";import{dirname as te,isAbsolute as re,join as ne,relative as oe,resolve as C,sep as se}from"node:path";import{gitAsync as ae,gitSync as i}from"./git.js";import{crtrHome as O}from"./canvas/paths.js";import{closeWorktreeAndRepoint as ie,getNode as v,recordLandIntent as ce}from"./canvas/index.js";import{CONFIG_FILE as he,CRTR_DIR_NAME as F,STATE_FILE as ue}from"../types.js";import{withExclusiveDirectoryLock as le}from"./exclusive-lock.js";import{parseStatusPorcelain as de,planLandIntoCheckout as fe,refDeleteTransactionStdin as pe}from"./worktree-landing.js";import{shellQuote as w}from"../shared/shell-quote.js";class f extends Error{static{a(this,"WorktreeError")}code;next;detail;constructor(r,t,n,o){super(t),this.name="WorktreeError",this.code=r,this.next=n,this.detail=o}}function k(e,r,t,n){const o=i(r,e);if(o.status!==0){const s=(o.stderr.trim()||o.stdout.trim()).trim();throw new f(t,`git ${r.join(" ")} failed`,n,s)}return o.stdout.trim()}a(k,"runGit");function I(){return`${O()}/worktrees`}a(I,"managedWorktreesRoot");function me(e){return`${I()}/${e}`}a(me,"managedWorktreePath");function Ke(e){return e?.managed_worktree?.state==="open"}a(Ke,"hasOpenManagedWorktree");function x(e){const t=v(e)?.managed_worktree;return t?.state==="open"?t:null}a(x,"openManagedWorktreeForNode");function be(e){const r=i(["rev-parse","--show-toplevel"],e);if(r.status!==0){const t=(r.stderr.trim()||r.stdout.trim()).trim();throw new f("not_git_repo",`cwd ${e} is not a git repository`,"Pass --cwd <real repo> pointing inside a git repository.",t)}return r.stdout.trim()}a(be,"repoRootFor");function _e(e){const r=oe(S(I()),S(e));return r!==""&&r!==".."&&!r.startsWith(`..${se}`)&&!re(r)}a(_e,"isManagedWorktreeBase");function ke(e,r){const t=`refs/heads/${r}`,n=i(["show-ref","--verify","--quiet",t],e);if(n.status===0)return!0;if(n.status===1&&n.executionFailed!==!0)return!1;const o=n.stderr.trim()||"<empty>",s=n.processError===void 0?"":`
|
|
2
|
+
process error: ${n.processError}`;throw new f("recorded_branch_inspection_failed",`could not inspect recorded branch '${r}' (git show-ref exited with status ${n.status})`,"Inspect the repository and its Git metadata, then retry.",`status: ${n.status}
|
|
3
|
+
stderr: ${o}${s}`)}a(ke,"recordedBranchExists");function A(e,r){const t=`refs/heads/${r}`,n=i(["show-ref","--verify","--quiet",t],e);if(n.status===1&&n.executionFailed!==!0)throw new f("missing_base_branch",`managed worktree base '${r}' does not name an existing local branch`,"The base must be a local branch that landing can fast-forward \u2014 freshen your local branch from origin first (rebase-not-merge), then base on it.");if(n.status!==0){const o=n.stderr.trim()||"<empty>",s=n.processError===void 0?"":`
|
|
4
|
+
process error: ${n.processError}`;throw new f("base_branch_inspection_failed",`could not inspect local base branch '${r}' (git show-ref exited with status ${n.status})`,"Inspect the repository and its Git metadata, then retry.",`status: ${n.status}
|
|
5
|
+
stderr: ${o}${s}`)}return k(e,["rev-parse","--verify",t],"base_branch_resolve_failed","Inspect the local base branch, then retry.")}a(A,"resolveLandableBase");function ge(e,r){const t=k(e,["worktree","list","--porcelain"],"worktree_list_failed","Inspect the repository worktrees manually, then retry.");return q(t,r)}a(ge,"checkoutPathForBranch");function q(e,r){let t=null;for(const n of e.split(`
|
|
6
|
+
`))if(n.startsWith("worktree "))t=n.slice(9).trim();else if(n===`branch refs/heads/${r}`)return t;return null}a(q,"checkoutPathForBranchInList");function we(e,r){return e===r||S(e)===S(r)}a(we,"samePath");function S(e){try{return N.native(e)}catch{return C(e)}}a(S,"canonicalPath");const $e=3e4;function ye(e){const r=`${O()}/worktree-locks`;return H(r,{recursive:!0}),`${r}/${ee("sha256").update(e).digest("hex")}`}a(ye,"worktreeLockPathForCommonDir");function R(e){const r=k(e,["rev-parse","--git-common-dir"],"git_common_dir_failed","Inspect the repository git metadata, then retry.");return N(C(e,r))}a(R,"commonGitDir");function E(e,r){const t=R(e);return le(ye(t),r,{timeoutMs:$e,timeoutError:a(()=>new f("worktree_lock_timeout",`timed out waiting to create a managed worktree in ${t}`,"Wait for the other managed-worktree operation to finish, then retry."),"timeoutError")})}a(E,"withRepositoryWorktreeLock");function D(e,r,t){const n=i(["worktree","list","--porcelain"],e);if(n.status!==0)return null;let o=null;for(const s of n.stdout.split(`
|
|
7
|
+
`))if(s.startsWith("worktree "))o=s.slice(9).trim();else if(o!==null&&we(o,r)&&s===`branch refs/heads/${t}`)return!0;return!1}a(D,"registeredWorktree");function ve(e,r,t){const n=[],o=`refs/heads/${r}`,s=i(["rev-parse","--verify","--quiet",o],e);s.status===0&&n.push({ref:o,sha:s.stdout.trim()});const u=i(["rev-parse","--symbolic-full-name","--verify",`${r}@{upstream}`],e),h=u.status===0&&u.stdout.trim().startsWith("refs/")?u.stdout.trim():`refs/remotes/origin/${r}`,m=i(["rev-parse","--verify","--quiet",h],e);if(m.status===0&&n.push({ref:h,sha:m.stdout.trim()}),n.length===0)return null;for(const d of n)if(i(["merge-base","--is-ancestor",t,d.sha],e).status===0)return{containingRef:d.ref,containingSha:d.sha};for(const d of n){const l=i(["cherry",d.sha,t],e);if(l.status!==0)continue;if(l.stdout.split(`
|
|
8
|
+
`).map(c=>c.trim()).filter(c=>c!=="").every(c=>c.startsWith("-")))return{containingRef:d.ref,containingSha:d.sha}}for(const d of n){const l=i(["rev-parse","--verify",`${d.sha}^{tree}`],e);if(l.status!==0)continue;const b=i(["merge-tree","--write-tree",d.sha,t],e);if(b.status===0&&b.stdout.split(`
|
|
9
|
+
`)[0]?.trim()===l.stdout.trim())return{containingRef:d.ref,containingSha:d.sha}}return null}a(ve,"proveBranchContained");function G(e,r){const t=i(["rev-parse","--verify",`refs/heads/${e.branch}`],e.repo_root);if(t.status!==0||t.stdout.trim()!==e.base_sha)return;const n=D(e.repo_root,e.path,e.branch);if(n!==null){if(n){if(i(["worktree","remove","--force",e.path],e.repo_root).status!==0||D(e.repo_root,e.path,e.branch)!==!1)return}else if(r&&_(e.path))try{Y(e.path,{recursive:!0,force:!0})}catch{return}try{i(["update-ref","-d",`refs/heads/${e.branch}`,e.base_sha],e.repo_root)}catch{}}}a(G,"rollbackManagedWorktreeLocked");function Ue(e){E(e.repo_root,()=>G(e,!1))}a(Ue,"rollbackManagedWorktree");const xe="# crtr: exclude crtr's own untracked project-scope bookkeeping (auto-added at managed-worktree creation)",Se=[`/${F}/${he}`,`/${F}/${ue}`];function Ee(e){try{const r=ne(R(e),"info","exclude");H(te(r),{recursive:!0});let t="";try{t=V(r,"utf8")}catch{}const n=new Set(t.split(`
|
|
10
|
+
`).map(h=>h.trim())),o=Se.filter(h=>!n.has(h));if(o.length===0)return;const u=(t.length>0&&!t.endsWith(`
|
|
11
|
+
`)?`
|
|
12
|
+
`:"")+xe+`
|
|
13
|
+
`+o.join(`
|
|
14
|
+
`)+`
|
|
15
|
+
`;Z(r,t+u)}catch{}}a(Ee,"seedManagedWorktreeExclude");function Xe(e,r,t="main"){const n=be(e);if(_e(n))throw new f("managed_worktree_base",`cwd ${n} is a managed worktree and cannot be used as a managed worktree base`,"Pass --cwd <real repo> pointing at the repository\u2019s primary checkout.");return E(n,()=>{const o=A(n,t),s=me(r),u=`crtr/${r}`;if(_(s))throw new f("worktree_path_exists",`managed worktree path already exists: ${s}`,"Remove the stale path or choose a fresh node id.");if(i(["show-ref","--verify","--quiet",`refs/heads/${u}`],n).status===0)throw new f("worktree_branch_exists",`managed worktree branch already exists: ${u}`,"Remove the stale branch or choose a fresh node id.");const h={state:"open",path:s,branch:u,repo_root:n,base_ref:t,base_sha:o,created:new Date().toISOString()};k(n,["branch",u,o],"worktree_branch_create_failed","Inspect the git error, fix the repository/worktree state, then retry spawning with --worktree.");try{return k(n,["worktree","add",s,u],"worktree_add_failed","Inspect the git error, fix the repository/worktree state, then retry spawning with --worktree."),Ee(n),h}catch(m){throw G(h,!0),m}})}a(Xe,"createManagedWorktree");function De(e){return k(e,["status","--porcelain"],"status_failed","Inspect the worktree manually, then retry.")}a(De,"statusPorcelain");function B(e){return k(e,["rev-parse","--abbrev-ref","HEAD"],"branch_check_failed","Inspect the worktree manually, then retry.")}a(B,"currentBranch");function j(e,r){return k(e,["rev-parse","--git-path",r],"git_path_failed","Inspect the worktree manually, then retry.")}a(j,"gitPath");function M(e){return _(j(e,"rebase-merge"))||_(j(e,"rebase-apply"))}a(M,"isRebaseInProgress");function y(e,r,t="pending"){const n=v(e);ie(e,{cwd:r.repo_root,cleanup:t,closedAt:new Date().toISOString(),unbindSession:n?.pi_session_id!=null||n?.pi_session_file!=null})}a(y,"persistClosedWorktreeState");function We(e,r){const t=v(e)?.managed_worktree;t==null||t.state!=="open"||ce(e,{at:new Date().toISOString(),blocked:r})}a(We,"recordBlockedLandIntent");function Ae(e,r,t,n){const o=i(["status","--porcelain"],e);if(o.status!==0)return{ok:!1,detail:(o.stderr.trim()||o.stdout.trim()).trim()};const s=i(["diff","--name-only",t,n],e);if(s.status!==0)return{ok:!1,detail:(s.stderr.trim()||s.stdout.trim()).trim()};const u=s.stdout.split(`
|
|
16
|
+
`).map(g=>g.trim()).filter(g=>g!==""),h=fe(de(o.stdout),u);if(h.kind==="refuse")return{ok:!1,detail:`untracked files in ${e} would be overwritten by the incoming commits: ${h.collisions.join(", ")}`};const m=a(()=>{const g=i(["merge","--ff-only",n],e);return g.status===0?{ok:!0}:{ok:!1,detail:(g.stderr.trim()||g.stdout.trim()).trim()}},"merge");if(h.kind==="direct")return m();const d=i(["rev-parse","--verify","--quiet","refs/stash"],e),l=d.status===0?d.stdout.trim():null,b=i(["stash","push","--message",`crtr landing ${r}`],e);if(b.status!==0)return{ok:!1,detail:(b.stderr.trim()||b.stdout.trim()).trim()};const c=i(["rev-parse","--verify","--quiet","refs/stash"],e),p=c.status===0?c.stdout.trim():null;if(p===null||p===l)return m();const $=`local changes from ${e} are retained in stash ${p}; recover them with \`git -C ${w(e)} stash apply ${p}\` and resolve any conflict.`,W=m();return W.ok?i(["stash","apply",p],e).status===0?(K(e,p),{ok:!0}):(i(["reset","--hard",n],e),{ok:!0,stash:`the shared base checkout was reset to landed commit ${n} because local changes conflicted with it. ${$}`}):i(["stash","apply",p],e).status===0?(K(e,p),W):{ok:!1,detail:`${W.detail}
|
|
17
|
+
${$}`}}a(Ae,"landIntoBaseCheckout");function K(e,r){const t=i(["rev-parse","--verify","--quiet","refs/stash"],e);t.status===0&&t.stdout.trim()===r&&i(["stash","drop"],e)}a(K,"dropStashIfStillTip");function T(e){const r=`git -C ${w(e.repo_root)} worktree remove ${w(e.path)}`;return{worktree_removed:!1,worktree_remove_error:`cleanup pending: the caller checkout at ${e.path} remains intact. After its node exits, run \`${r}\` after confirming it is safe to delete.`,branch_deleted:!1,branch_delete_error:`cleanup pending: local branch ${e.branch} remains checked out at ${e.path}; delete it only after that checkout is removed and its landed commit is still contained in ${e.base_ref}.`}}a(T,"deferredCleanupResult");function Re(e,r,t){if(D(r.repo_root,r.path,t)!==!0)throw new f("wrong_branch",`managed worktree's recorded branch ${r.branch} no longer exists, and its checkout at ${r.path} is not registered to ${t} either`,`Inspect ${r.path} and its git worktree registration, then ask the user with \`crtr human send\` if you are unsure how to proceed.`);const n=k(r.path,["rev-parse","HEAD"],"branch_check_failed","Inspect the worktree manually, then retry.");if(ve(r.path,r.base_ref,n)===null)throw new f("branch_moved_unlanded",`managed worktree's recorded branch ${r.branch} no longer exists; its checkout is now on ${t} at ${n}, which carries content local base branch '${r.base_ref}' does not yet contain`,`Land or push ${t} through its own workflow (merge its PR, or fast-forward '${r.base_ref}' to include it) before closing, or ask the user with \`crtr human send\` if you are unsure how ${t} should be delivered.`);const s=R(r.repo_root),u=D(r.repo_root,r.path,t)===!0,h=B(r.path)===t,m=k(r.path,["rev-parse","HEAD"],"branch_check_failed","Inspect the worktree manually, then retry.")===n;if(!u||!h||!m)throw new f("wrong_branch",`managed worktree at ${r.path} changed while closing`,`Inspect ${r.path}, then rerun \`crtr node worktree close\`.`);const d={observed_branch:t,observed_sha:n,common_dir:s,authorized:new Date().toISOString()};y(e,{...r,disposal:d},"pending");const l=`git -C ${w(r.repo_root)} worktree remove ${w(r.path)}`;return{node_id:e,branch:t,worktree_path:r.path,landed_sha:n,worktree_removed:!1,worktree_remove_error:`cleanup pending: the caller checkout at ${r.path} remains intact. After its node exits, run \`${l}\` after confirming it is safe to delete.`,branch_deleted:!1,branch_delete_error:`${t} is not a crtr-managed branch and will never be deleted automatically; it is preserved once the checkout above is removed.`}}a(Re,"closeBranchMovedWorktree");function Me(e,r){const t=v(e)?.managed_worktree;if(t==null)return{message:`node ${e} has no managed worktree`,next:`Nothing to ${r} for this node.`};if(t.state==="abandoned"){const n=t.abandoned?.branch??t.branch;return{message:`node ${e}'s managed worktree was already abandoned`,next:`Nothing to ${r} for this node; its work was retained on branch ${n}.`}}return t.state==="closed"?t.cleanup==="complete"?{message:`node ${e}'s managed worktree is already closed and its cleanup is complete`,next:`Nothing to ${r} for this node.`}:{message:`node ${e}'s managed worktree is already closed; this is not lost ownership \u2014 its checkout at ${t.path} is scheduled for automatic cleanup once that is safe`,next:`Nothing to ${r} for this node. The daemon sweep finishes removing ${t.path} on its own; inspect it directly only if it still needs manual attention.`}:{message:`node ${e} has no open managed worktree`,next:`Nothing to ${r} for this node.`}}a(Me,"noManagedWorktreeMessage");function U(e){if(v(e)===null)throw new f("unknown_node",`unknown node: ${e}`,"Run this from a live node, or pass a real node id once that command supports it.");const t=x(e);if(t===null){const{message:c,next:p}=Me(e,"close");throw new f("no_managed_worktree",c,p)}if(!_(t.path)){const c=P(t);if(c===null)throw new f("worktree_missing",`managed worktree path is missing: ${t.path}`,X(t));if(z(e,t,c)===null)throw new f("worktree_missing",`managed worktree path is missing: ${t.path}`,X(t));return{node_id:e,branch:t.branch,worktree_path:t.path,landed_sha:c.branchSha??t.base_sha,worktree_removed:!0,branch_deleted:!0}}if(M(t.path))throw new f("rebase_in_progress","this managed worktree is mid-rebase",`Resolve conflicts in ${t.path}, run \`git rebase --continue\` there, then rerun \`crtr node worktree close\`.`);if(De(t.path)!=="")throw new f("dirty_worktree","managed worktree has uncommitted changes",`Commit the work in ${t.path} (or ask the user with \`crtr human send\` if you do not know whether to keep it), then rerun \`crtr node worktree close\`.`);const o=B(t.path);if(o!==t.branch){const c=o==="HEAD"?"detached HEAD":o,p=ke(t.path,t.branch);if(p||o==="HEAD")throw new f("wrong_branch",`managed worktree is not on its recorded branch (expected ${t.branch}, found ${c})`,p?`Check out ${t.branch} in ${t.path} before closing, or ask the user with \`crtr human send\` if you are unsure why it changed, then rerun \`crtr node worktree close\`.`:`The recorded branch ${t.branch} no longer exists, and ${t.path} is in detached HEAD, so there is no branch to preserve. Check out or create a branch there before closing, or ask the user with \`crtr human send\` if you are unsure how to proceed.`);return Re(e,t,o)}let s;try{s=A(t.path,t.base_ref)}catch(c){const p=k(t.path,["rev-parse","HEAD"],"landed_sha_failed","Inspect the worktree checkout manually, then rerun `crtr node worktree close`.");if(!(c instanceof f)||c.code!=="missing_base_branch"||p!==t.base_sha)throw c;return y(e,t,"pending"),{node_id:e,branch:t.branch,worktree_path:t.path,landed_sha:t.base_sha,...T(t)}}const u=i(["rebase",s],t.path);if(u.status!==0){const c=(u.stderr.trim()||u.stdout.trim()).trim();throw new f("rebase_failed",`rebase onto local base branch '${t.base_ref}' did not complete`,`Resolve conflicts in ${t.path}, run \`git rebase --continue\` there, then rerun \`crtr node worktree close\`. If the blocker is not mechanical, ask the user with \`crtr human send\`.`,c)}const h=k(t.path,["rev-parse","HEAD"],"landed_sha_failed","Inspect the worktree checkout manually, then rerun `crtr node worktree close`."),m=a((c,p,$)=>(We(e,c),new f("land_base_failed",c,p,$)),"blocked"),d=i(["merge-base","--is-ancestor",s,h],t.path);if(d.status!==0)throw m(`rebased worktree is not a fast-forward of local base branch '${t.base_ref}'`,"Ask the user with `crtr human send` how to land this managed worktree.",(d.stderr.trim()||d.stdout.trim()).trim());const l=ge(t.path,t.base_ref);if(l!==null){const c=i(["rev-parse","HEAD"],l),p=c.stdout.trim();if(c.status!==0||p!==s){const $=c.status!==0?(c.stderr.trim()||p).trim():`expected ${s}, found ${p}`;throw m(`local base branch '${t.base_ref}' changed while this worktree was closing`,`Reconcile the base checkout at ${l}, then rerun \`crtr node worktree close\`. If you are unsure, ask the user with \`crtr human send\`.`,$)}}let b;if(l!==null){const c=Ae(l,t.branch,s,h);if(!c.ok)throw m(`could not fast-forward local base branch '${t.base_ref}' to this worktree`,`Local base branch '${t.base_ref}' is checked out at ${l} in a state that blocks a fast-forward. Reconcile it there, then rerun \`crtr node worktree close\`. If you are unsure, ask the user with \`crtr human send\`.`,c.detail);b=c.stash}else{const c=i(["update-ref",`refs/heads/${t.base_ref}`,h,s],t.path);if(c.status!==0)throw m(`could not fast-forward local base branch '${t.base_ref}' to this worktree`,"Ask the user with `crtr human send` how to land this managed worktree.",(c.stderr.trim()||c.stdout.trim()).trim())}return y(e,t,"pending"),{node_id:e,branch:t.branch,worktree_path:t.path,landed_sha:h,...T(t),...b===void 0?{}:{base_checkout_stash:b}}}a(U,"closeManagedWorktreeLocked");function ze(e){const r=x(e);return r===null?U(e):E(_(r.path)?r.path:r.repo_root,()=>U(e))}a(ze,"closeManagedWorktree");function Te(e,r,t,n){const o=pe(e.branch,r,t,n),s=i(["update-ref","--stdin"],e.repo_root,o),u=s.status===0;if(u)return{branchDeleted:u};const h=(s.stderr.trim()||s.stdout.trim()).trim();return{branchDeleted:u,branchDeleteError:`local branch ${e.branch} could not be deleted automatically (${h}); run \`git -C ${w(e.repo_root)} branch -D ${w(e.branch)}\` after confirming it is merged.`}}a(Te,"bestEffortDeleteBranchWithContainmentProof");function P(e){if(e.state!=="open"||_(e.path))return null;const r=`refs/heads/${e.branch}`,t=i(["show-ref","--verify","--quiet",r],e.repo_root);if(t.status===1)return{branchSha:null};if(t.status!==0)return null;const n=i(["rev-parse","--verify",r],e.repo_root);if(n.status!==0)return null;const o=n.stdout.trim(),s=i(["worktree","list","--porcelain"],e.repo_root);if(s.status!==0||q(s.stdout,e.branch)!==null)return null;const u=[],h=`refs/heads/${e.base_ref}`,m=i(["show-ref","--verify","--quiet",h],e.repo_root);if(m.status===0){const l=i(["rev-parse","--verify",h],e.repo_root);if(l.status!==0)return null;u.push({ref:h,sha:l.stdout.trim()})}else if(m.status!==1)return null;const d=i(["rev-parse","--symbolic-full-name","--verify",`${e.base_ref}@{upstream}`],e.repo_root);if(d.status===0){const l=d.stdout.trim(),b=i(["rev-parse","--verify",l],e.repo_root);l.startsWith("refs/")&&b.status===0&&u.push({ref:l,sha:b.stdout.trim()})}else{const l=`refs/remotes/origin/${e.base_ref}`,b=i(["show-ref","--verify","--quiet",l],e.repo_root);if(b.status===0){const c=i(["rev-parse","--verify",l],e.repo_root);c.status===0&&u.push({ref:l,sha:c.stdout.trim()})}else if(b.status!==1)return null}for(const l of u)if(i(["merge-base","--is-ancestor",o,l.sha],e.repo_root).status===0)return{branchSha:o,containingRef:l.ref,containingSha:l.sha};return null}a(P,"proveAbsentPathManagedWorktree");function X(e){return`The recorded checkout path is gone, but crtr cannot prove ${e.branch} is already delivered. Push or land ${e.branch}, then rerun \`crtr push final\`; if you cannot establish what happened to the branch, ask the user with \`crtr human send\`.`}a(X,"missingWorktreeRecoveryHint");function L(e){if(e.state!=="open"||!_(e.path)||M(e.path))return null;const r=i(["rev-parse","--abbrev-ref","HEAD"],e.path);if(r.status!==0||r.stdout.trim()!==e.branch)return null;const t=i(["status","--porcelain"],e.path);if(t.status!==0||t.stdout.trim()!=="")return null;const n=i(["rev-parse","HEAD"],e.path);if(n.status!==0)return null;const o=n.stdout.trim();let s;try{s=A(e.path,e.base_ref)}catch(h){if(h instanceof f&&h.code==="missing_base_branch"&&o===e.base_sha)return{branchSha:o,baseSha:e.base_sha};throw h}return i(["merge-base","--is-ancestor",o,s],e.path).status!==0?null:{branchSha:o,baseSha:s}}a(L,"proveCleanEmptyManagedWorktree");function z(e,r,t){if(_(r.path))return null;if(t.branchSha===null)return y(e,r,"complete"),{node_id:e,branch:r.branch,worktree_path:r.path,worktree_removed:!0,branch_deleted:!0};if(t.containingRef===void 0||t.containingSha===void 0)return null;const{branchDeleted:n}=Te(r,t.branchSha,t.containingRef,t.containingSha);return n?(y(e,r,"complete"),{node_id:e,branch:r.branch,worktree_path:r.path,worktree_removed:!0,branch_deleted:!0}):null}a(z,"autoDropAbsentPathManagedWorktreeLocked");function Pe(e,r,t){const n=L(r);return n===null||n.branchSha!==t.branchSha?null:(y(e,r,"pending"),{node_id:e,branch:r.branch,worktree_path:r.path,...T(r)})}a(Pe,"autoDropCleanManagedWorktreeLocked");function Q(e){if(e.state!=="open"||!_(e.path)||M(e.path))return null;const r=i(["status","--porcelain"],e.path);if(r.status!==0||r.stdout.trim()!=="")return null;const t=i(["rev-parse","HEAD"],e.path);return t.status===0?t.stdout.trim():null}a(Q,"cleanCurrentCheckoutTip");async function Qe(e){const r=Q(e);if(r===null)return!1;const t=process.env.GIT_SSH_COMMAND??process.env.GIT_SSH??"ssh",n=await ae(["ls-remote","--exit-code","--heads","origin"],e.path,void 0,{timeoutMs:1e4,env:{...process.env,GIT_TERMINAL_PROMPT:"0",GIT_SSH_COMMAND:`${t} -o BatchMode=yes`}});return n.status!==0||!n.stdout.split(`
|
|
18
|
+
`).some(s=>{const[u,h]=s.split(" ",2);return u===r&&h?.startsWith("refs/heads/")===!0})?!1:Q(e)===r}a(Qe,"branchIsPushedAtCurrentTip");function Je(e){const r=x(e);if(r===null)return null;const t=!_(r.path);return(t?P(r)===null:L(r)===null)?null:E(t?r.repo_root:r.path,()=>{const n=x(e);if(n===null)return null;if(!_(n.path)){const s=P(n);return s===null?null:z(e,n,s)}const o=L(n);return o===null?null:Pe(e,n,o)})}a(Je,"autoDropCleanManagedWorktree");export{$e as WORKTREE_LOCK_WAIT_MS,f as WorktreeError,Je as autoDropCleanManagedWorktree,Pe as autoDropCleanManagedWorktreeLocked,Qe as branchIsPushedAtCurrentTip,q as checkoutPathForBranchInList,ze as closeManagedWorktree,Xe as createManagedWorktree,Ke as hasOpenManagedWorktree,_e as isManagedWorktreeBase,M as isRebaseInProgress,me as managedWorktreePath,I as managedWorktreesRoot,X as missingWorktreeRecoveryHint,x as openManagedWorktreeForNode,y as persistClosedWorktreeState,L as proveCleanEmptyManagedWorktree,Ue as rollbackManagedWorktree,we as samePath,ye as worktreeLockPathForCommonDir};
|