@north-light/cli 0.3.530 → 0.3.531
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/clients/attach/session/connection.js +1 -1
- package/dist/clients/attach/session/reconnect.js +1 -1
- package/dist/clients/attach/viewer.js +3 -3
- package/dist/core/async-array.d.ts +7 -0
- package/dist/core/async-array.js +1 -0
- package/dist/core/audit.d.ts +1 -1
- package/dist/core/audit.js +2 -2
- package/dist/core/canvas/attention.d.ts +4 -4
- package/dist/core/canvas/attention.js +1 -1
- package/dist/core/canvas/boot.d.ts +4 -4
- package/dist/core/canvas/boot.js +1 -1
- package/dist/core/canvas/canvas.d.ts +59 -59
- package/dist/core/canvas/canvas.js +19 -19
- package/dist/core/canvas/context-strip.js +2 -2
- package/dist/core/canvas/crons.d.ts +27 -27
- package/dist/core/canvas/crons.js +11 -11
- package/dist/core/canvas/daemon-actions.d.ts +10 -10
- package/dist/core/canvas/daemon-actions.js +8 -8
- package/dist/core/canvas/daemon-owner.d.ts +3 -3
- package/dist/core/canvas/daemon-owner.js +2 -2
- package/dist/core/canvas/db.d.ts +19 -30
- package/dist/core/canvas/db.js +3 -2
- package/dist/core/canvas/deliveries.d.ts +16 -16
- package/dist/core/canvas/deliveries.js +24 -24
- package/dist/core/canvas/executions.d.ts +8 -8
- package/dist/core/canvas/executions.js +1 -1
- package/dist/core/canvas/focuses.d.ts +8 -8
- package/dist/core/canvas/focuses.js +1 -1
- package/dist/core/canvas/history.d.ts +3 -3
- package/dist/core/canvas/history.js +9 -9
- package/dist/core/canvas/install-id.d.ts +1 -1
- package/dist/core/canvas/install-id.js +1 -1
- package/dist/core/canvas/managed-worktree-sweep-candidates.d.ts +1 -1
- package/dist/core/canvas/managed-worktree-sweep-candidates.js +2 -2
- package/dist/core/canvas/memory-reads.d.ts +6 -6
- package/dist/core/canvas/memory-reads.js +1 -1
- package/dist/core/canvas/nav-model.d.ts +13 -13
- package/dist/core/canvas/nav-model.js +1 -1
- package/dist/core/canvas/node-agent-paths.d.ts +6 -6
- package/dist/core/canvas/node-agent-paths.js +1 -1
- package/dist/core/canvas/node-tokens.d.ts +7 -7
- package/dist/core/canvas/node-tokens.js +3 -3
- package/dist/core/canvas/outcome-actions.d.ts +5 -5
- package/dist/core/canvas/outcome-actions.js +3 -3
- package/dist/core/canvas/recovery.d.ts +26 -26
- package/dist/core/canvas/recovery.js +2 -2
- package/dist/core/canvas/render-source.d.ts +1 -1
- package/dist/core/canvas/render-source.js +1 -1
- package/dist/core/canvas/sessions.d.ts +10 -10
- package/dist/core/canvas/sessions.js +4 -4
- package/dist/core/canvas/source.js +1 -1
- package/dist/core/canvas/structured-requests.d.ts +15 -15
- package/dist/core/canvas/structured-requests.js +5 -5
- package/dist/core/canvas/tree.d.ts +9 -9
- package/dist/core/canvas/tree.js +5 -5
- package/dist/core/canvas/waits.d.ts +13 -13
- package/dist/core/canvas/waits.js +6 -6
- package/dist/core/canvas/worktrees.d.ts +15 -15
- package/dist/core/canvas/worktrees.js +1 -1
- package/dist/core/command-hooks/transport/exec-lifecycle.js +1 -1
- package/dist/core/conversation-store/file-store.d.ts +7 -7
- package/dist/core/conversation-store/file-store.js +9 -9
- package/dist/core/conversation-store/index.d.ts +16 -14
- package/dist/core/conversation-store/index.js +1 -1
- package/dist/core/conversation-store/listener.js +5 -5
- package/dist/core/conversation-store/patch.d.ts +3 -1
- package/dist/core/conversation-store/patch.js +1 -1
- package/dist/core/feed/feed.js +3 -3
- package/dist/core/feed/inbox.d.ts +2 -2
- package/dist/core/feed/inbox.js +1 -1
- package/dist/core/feed/messages.d.ts +11 -12
- package/dist/core/feed/messages.js +5 -5
- package/dist/core/feed/reports.d.ts +4 -4
- package/dist/core/feed/reports.js +2 -2
- package/dist/core/grants/cover.d.ts +1 -1
- package/dist/core/grants/cover.js +1 -1
- package/dist/core/grants/local.d.ts +1 -1
- package/dist/core/grants/local.js +1 -1
- package/dist/core/grants/mirror.d.ts +19 -19
- package/dist/core/grants/mirror.js +2 -2
- package/dist/core/grants/on-sync.d.ts +1 -1
- package/dist/core/grants/on-sync.js +1 -1
- package/dist/core/grants/remove.js +1 -1
- package/dist/core/grants/sync.js +1 -1
- package/dist/core/graph/access.d.ts +17 -17
- package/dist/core/graph/access.js +3 -3
- package/dist/core/graph/custom.d.ts +16 -16
- package/dist/core/graph/custom.js +9 -9
- package/dist/core/graph/deletion.d.ts +3 -7
- package/dist/core/graph/deletion.js +4 -4
- package/dist/core/graph/documents.d.ts +24 -27
- package/dist/core/graph/documents.js +7 -7
- package/dist/core/graph/edges.d.ts +13 -13
- package/dist/core/graph/edges.js +1 -1
- package/dist/core/graph/events.d.ts +7 -9
- package/dist/core/graph/events.js +8 -8
- package/dist/core/graph/exposures.d.ts +6 -6
- package/dist/core/graph/exposures.js +4 -4
- package/dist/core/graph/jobs.d.ts +6 -8
- package/dist/core/graph/jobs.js +2 -2
- package/dist/core/graph/kinds/action.js +1 -1
- package/dist/core/graph/kinds/custom.js +2 -2
- package/dist/core/graph/kinds/document.d.ts +1 -0
- package/dist/core/graph/kinds/document.js +4 -4
- package/dist/core/graph/kinds/dto.d.ts +2 -2
- package/dist/core/graph/kinds/dto.js +1 -1
- package/dist/core/graph/kinds/job.js +2 -2
- package/dist/core/graph/kinds/kind.d.ts +6 -8
- package/dist/core/graph/kinds/kind.js +1 -1
- package/dist/core/graph/kinds/node.js +5 -5
- package/dist/core/graph/kinds/owner.js +2 -2
- package/dist/core/graph/kinds/registry.d.ts +6 -9
- package/dist/core/graph/kinds/registry.js +1 -1
- package/dist/core/graph/names.d.ts +6 -6
- package/dist/core/graph/names.js +3 -3
- package/dist/core/graph/object-waits.d.ts +4 -7
- package/dist/core/graph/object-waits.js +1 -1
- package/dist/core/graph/objects.d.ts +14 -14
- package/dist/core/graph/objects.js +9 -9
- package/dist/core/graph/package-docs.d.ts +2 -7
- package/dist/core/graph/package-docs.js +5 -5
- package/dist/core/graph/package-kinds.d.ts +2 -5
- package/dist/core/graph/package-kinds.js +1 -1
- package/dist/core/graph/package-reconcile.d.ts +2 -5
- package/dist/core/graph/package-reconcile.js +1 -1
- package/dist/core/graph/reader.d.ts +18 -18
- package/dist/core/graph/reader.js +3 -3
- package/dist/core/graph/receivers.d.ts +4 -4
- package/dist/core/graph/receivers.js +5 -5
- package/dist/core/graph/repo-sync/exchange.d.ts +3 -7
- package/dist/core/graph/repo-sync/exchange.js +2 -2
- package/dist/core/graph/repo-sync/repos.d.ts +7 -5
- package/dist/core/graph/repo-sync/repos.js +3 -3
- package/dist/core/graph/repo-sync/sync.d.ts +3 -6
- package/dist/core/graph/repo-sync/sync.js +2 -2
- package/dist/core/graph/rules.d.ts +5 -5
- package/dist/core/graph/rules.js +3 -3
- package/dist/core/graph/spaces/app.js +1 -1
- package/dist/core/graph/spaces/index.d.ts +4 -5
- package/dist/core/graph/spaces/index.js +1 -1
- package/dist/core/graph/spaces/own-memory.d.ts +4 -4
- package/dist/core/graph/spaces/own-memory.js +1 -1
- package/dist/core/graph/spaces/person.js +3 -3
- package/dist/core/graph/spaces/repo.d.ts +1 -1
- package/dist/core/graph/spaces/repo.js +1 -1
- package/dist/core/graph/watches.d.ts +15 -15
- package/dist/core/graph/watches.js +10 -10
- package/dist/core/human/feedback-companion.d.ts +2 -2
- package/dist/core/human/feedback-companion.js +1 -1
- package/dist/core/human/feedback.d.ts +3 -3
- package/dist/core/human/feedback.js +1 -1
- package/dist/core/human/requests.d.ts +34 -33
- package/dist/core/human/requests.js +20 -20
- package/dist/core/human/scan.d.ts +2 -2
- package/dist/core/human/scan.js +1 -1
- package/dist/core/human/tickets.d.ts +9 -9
- package/dist/core/human/tickets.js +1 -1
- package/dist/core/llm/app-rungs.d.ts +1 -1
- package/dist/core/llm/app-rungs.js +1 -1
- package/dist/core/llm/run.js +1 -1
- package/dist/core/peer/directory.d.ts +1 -1
- package/dist/core/peer/directory.js +1 -1
- package/dist/core/peer/envelope.d.ts +3 -3
- package/dist/core/peer/envelope.js +1 -1
- package/dist/core/peer/home.d.ts +7 -7
- package/dist/core/peer/home.js +2 -2
- package/dist/core/peer/ingest.d.ts +6 -6
- package/dist/core/peer/ingest.js +1 -1
- package/dist/core/peer/outbox-store.d.ts +14 -14
- package/dist/core/peer/outbox-store.js +5 -5
- package/dist/core/peer/receiver.d.ts +2 -2
- package/dist/core/peer/receiver.js +1 -1
- package/dist/core/peer/stubs.d.ts +10 -10
- package/dist/core/peer/stubs.js +1 -1
- package/dist/core/providers/approval.d.ts +2 -2
- package/dist/core/providers/approval.js +2 -2
- package/dist/core/providers/audit.d.ts +3 -3
- package/dist/core/providers/audit.js +2 -2
- package/dist/core/providers/bundles.js +2 -2
- package/dist/core/providers/call.d.ts +2 -2
- package/dist/core/providers/call.js +1 -1
- package/dist/core/providers/files.d.ts +1 -1
- package/dist/core/providers/files.js +1 -1
- package/dist/core/providers/mint.js +1 -1
- package/dist/core/providers/receipts.d.ts +1 -1
- package/dist/core/providers/receipts.js +2 -2
- package/dist/core/review/birth.js +1 -1
- package/dist/core/review/comments.d.ts +19 -19
- package/dist/core/review/comments.js +5 -5
- package/dist/core/review/companion.d.ts +1 -1
- package/dist/core/review/companion.js +1 -1
- package/dist/core/review/document.d.ts +3 -3
- package/dist/core/review/document.js +2 -2
- package/dist/core/review/fork.js +2 -2
- package/dist/core/review/realize.js +1 -1
- package/dist/core/review/remap.d.ts +2 -2
- package/dist/core/review/remap.js +4 -4
- package/dist/core/review/stage.d.ts +1 -1
- package/dist/core/review/stage.js +1 -1
- package/dist/core/review/store.d.ts +21 -21
- package/dist/core/review/store.js +1 -1
- package/dist/core/runs/activity.d.ts +1 -1
- package/dist/core/runs/activity.js +5 -5
- package/dist/core/runs/confinement.d.ts +7 -7
- package/dist/core/runs/confinement.js +2 -2
- package/dist/core/runs/events.d.ts +12 -12
- package/dist/core/runs/events.js +4 -4
- package/dist/core/runs/operations.d.ts +11 -11
- package/dist/core/runs/operations.js +5 -5
- package/dist/core/runs/questions.d.ts +10 -10
- package/dist/core/runs/questions.js +3 -3
- package/dist/core/runtime/auth-reload.js +1 -1
- package/dist/core/runtime/bearings.d.ts +5 -5
- package/dist/core/runtime/bearings.js +6 -6
- package/dist/core/runtime/broker-inventory.js +1 -1
- package/dist/core/runtime/broker-request.js +1 -1
- package/dist/core/runtime/broker.js +1 -1
- package/dist/core/runtime/close.d.ts +3 -3
- package/dist/core/runtime/close.js +1 -1
- package/dist/core/runtime/deliver-live.js +1 -1
- package/dist/core/runtime/fleet.d.ts +2 -2
- package/dist/core/runtime/host.d.ts +3 -3
- package/dist/core/runtime/host.js +3 -3
- package/dist/core/runtime/kickoff.d.ts +12 -12
- package/dist/core/runtime/kickoff.js +17 -17
- package/dist/core/runtime/launch-target.d.ts +1 -1
- package/dist/core/runtime/launch-target.js +1 -1
- package/dist/core/runtime/ledger.d.ts +3 -3
- package/dist/core/runtime/ledger.js +3 -3
- package/dist/core/runtime/lifecycle.d.ts +1 -1
- package/dist/core/runtime/lifecycle.js +2 -2
- package/dist/core/runtime/memory-admission.js +1 -1
- package/dist/core/runtime/model-swap.d.ts +2 -2
- package/dist/core/runtime/model-swap.js +1 -1
- package/dist/core/runtime/node-read.d.ts +1 -1
- package/dist/core/runtime/node-read.js +2 -2
- package/dist/core/runtime/nodes.d.ts +6 -6
- package/dist/core/runtime/nodes.js +1 -1
- package/dist/core/runtime/outcome-document.d.ts +1 -1
- package/dist/core/runtime/outcome-document.js +1 -1
- package/dist/core/runtime/persona.d.ts +3 -3
- package/dist/core/runtime/persona.js +2 -2
- package/dist/core/runtime/placement.d.ts +11 -11
- package/dist/core/runtime/placement.js +1 -1
- package/dist/core/runtime/promote.d.ts +3 -3
- package/dist/core/runtime/promote.js +1 -1
- package/dist/core/runtime/recycle.js +1 -1
- package/dist/core/runtime/reopen.d.ts +5 -5
- package/dist/core/runtime/reopen.js +1 -1
- package/dist/core/runtime/reset.d.ts +4 -4
- package/dist/core/runtime/reset.js +1 -1
- package/dist/core/runtime/revive-all.d.ts +2 -2
- package/dist/core/runtime/revive-all.js +1 -1
- package/dist/core/runtime/revive.d.ts +4 -4
- package/dist/core/runtime/revive.js +2 -2
- package/dist/core/runtime/roadmap.d.ts +6 -6
- package/dist/core/runtime/roadmap.js +5 -5
- package/dist/core/runtime/session-branch.d.ts +1 -1
- package/dist/core/runtime/session-branch.js +1 -1
- package/dist/core/runtime/session-list-cache.js +1 -1
- package/dist/core/runtime/situational-live.js +1 -1
- package/dist/core/runtime/spawn.d.ts +2 -2
- package/dist/core/runtime/spawn.js +2 -2
- package/dist/core/runtime/stop-guard.d.ts +2 -2
- package/dist/core/runtime/stop-guard.js +3 -3
- package/dist/core/runtime/warm-pool.d.ts +2 -2
- package/dist/core/runtime/warm-pool.js +1 -1
- package/dist/core/spaces/mounts.d.ts +2 -2
- package/dist/core/spaces/mounts.js +1 -1
- package/dist/core/spaces/permissions.d.ts +1 -1
- package/dist/core/spaces/permissions.js +1 -1
- package/dist/core/spaces/process.d.ts +1 -1
- package/dist/core/spaces/process.js +1 -1
- package/dist/core/spaces/space.js +1 -1
- package/dist/core/spaces/stop.d.ts +3 -3
- package/dist/core/spaces/stop.js +2 -2
- package/dist/core/spaces/users.d.ts +6 -6
- package/dist/core/spaces/users.js +1 -1
- package/dist/core/storage/attachments.d.ts +2 -2
- package/dist/core/storage/attachments.js +1 -1
- package/dist/core/storage/shares.d.ts +2 -2
- package/dist/core/storage/shares.js +1 -1
- package/dist/core/storage/tables.d.ts +21 -21
- package/dist/core/storage/tables.js +3 -3
- package/dist/core/substrate/delivery/corpus.d.ts +5 -8
- package/dist/core/substrate/delivery/corpus.js +3 -3
- package/dist/core/substrate/delivery/deliver.d.ts +10 -15
- package/dist/core/substrate/delivery/deliver.js +3 -3
- package/dist/core/substrate/delivery/plan.d.ts +2 -12
- package/dist/core/substrate/delivery/plan.js +3 -3
- package/dist/core/substrate/delivery/render-boot.d.ts +4 -4
- package/dist/core/substrate/delivery/render-boot.js +18 -18
- package/dist/core/substrate/delivery/render-event.d.ts +7 -14
- package/dist/core/substrate/delivery/render-event.js +4 -4
- package/dist/core/substrate/subject.d.ts +2 -2
- package/dist/core/substrate/subject.js +1 -1
- package/dist/core/usage/ledger.d.ts +6 -6
- package/dist/core/usage/ledger.js +4 -4
- package/dist/core/worktree-close.js +4 -4
- package/dist/core/worktree-mutation-async.js +7 -7
- package/dist/core/worktree-quarantine.js +1 -1
- package/dist/core/worktree-sweep.d.ts +1 -1
- package/dist/core/worktree-sweep.js +6 -6
- package/dist/core/worktree.d.ts +5 -5
- package/dist/core/worktree.js +13 -13
- package/dist/daemon/analytics/compute.d.ts +2 -2
- package/dist/daemon/analytics/compute.js +1 -1
- package/dist/daemon/api/app-listener.d.ts +4 -4
- package/dist/daemon/api/app-listener.js +13 -13
- package/dist/daemon/api/bridge.js +5 -5
- package/dist/daemon/api/document-listener.js +6 -6
- package/dist/daemon/api/handlers/analytics.js +1 -1
- package/dist/daemon/api/handlers/attach.js +1 -1
- package/dist/daemon/api/handlers/bash-jobs.js +1 -1
- package/dist/daemon/api/handlers/bash.js +1 -1
- package/dist/daemon/api/handlers/broker-ops.d.ts +1 -1
- package/dist/daemon/api/handlers/broker-ops.js +1 -1
- package/dist/daemon/api/handlers/broker-recovery.d.ts +1 -1
- package/dist/daemon/api/handlers/broker-recovery.js +1 -1
- package/dist/daemon/api/handlers/broker-signals.d.ts +2 -2
- package/dist/daemon/api/handlers/broker-signals.js +2 -2
- package/dist/daemon/api/handlers/canvas.d.ts +1 -1
- package/dist/daemon/api/handlers/canvas.js +4 -4
- package/dist/daemon/api/handlers/chat-inventory.js +1 -1
- package/dist/daemon/api/handlers/crons.js +1 -1
- package/dist/daemon/api/handlers/custom-objects.d.ts +4 -4
- package/dist/daemon/api/handlers/custom-objects.js +3 -3
- package/dist/daemon/api/handlers/delivery-retry.js +1 -1
- package/dist/daemon/api/handlers/delivery.js +1 -1
- package/dist/daemon/api/handlers/docs.d.ts +4 -4
- package/dist/daemon/api/handlers/docs.js +1 -1
- package/dist/daemon/api/handlers/feedback-comments.js +3 -3
- package/dist/daemon/api/handlers/files.js +1 -1
- package/dist/daemon/api/handlers/focus.js +1 -1
- package/dist/daemon/api/handlers/health.js +3 -3
- package/dist/daemon/api/handlers/hook-exec.js +1 -1
- package/dist/daemon/api/handlers/human-requests.js +1 -1
- package/dist/daemon/api/handlers/inbox-page.d.ts +1 -1
- package/dist/daemon/api/handlers/inbox-page.js +1 -1
- package/dist/daemon/api/handlers/inbox.d.ts +1 -1
- package/dist/daemon/api/handlers/inbox.js +1 -1
- package/dist/daemon/api/handlers/llm.d.ts +1 -1
- package/dist/daemon/api/handlers/llm.js +3 -3
- package/dist/daemon/api/handlers/memory-reads.js +1 -1
- package/dist/daemon/api/handlers/memory.d.ts +5 -5
- package/dist/daemon/api/handlers/memory.js +5 -5
- package/dist/daemon/api/handlers/messages.js +2 -2
- package/dist/daemon/api/handlers/node-events.d.ts +2 -2
- package/dist/daemon/api/handlers/node-events.js +3 -3
- package/dist/daemon/api/handlers/node-outcomes.js +1 -1
- package/dist/daemon/api/handlers/node-records.js +2 -2
- package/dist/daemon/api/handlers/nodes.d.ts +1 -1
- package/dist/daemon/api/handlers/nodes.js +1 -1
- package/dist/daemon/api/handlers/objects.js +3 -3
- package/dist/daemon/api/handlers/package-docs.js +1 -1
- package/dist/daemon/api/handlers/plugin-app-token.d.ts +1 -1
- package/dist/daemon/api/handlers/plugin-app-token.js +1 -1
- package/dist/daemon/api/handlers/profiles.d.ts +3 -3
- package/dist/daemon/api/handlers/profiles.js +1 -1
- package/dist/daemon/api/handlers/providers.d.ts +1 -1
- package/dist/daemon/api/handlers/providers.js +1 -1
- package/dist/daemon/api/handlers/questions.js +1 -1
- package/dist/daemon/api/handlers/reports.d.ts +1 -1
- package/dist/daemon/api/handlers/reports.js +5 -5
- package/dist/daemon/api/handlers/review-comments.js +1 -1
- package/dist/daemon/api/handlers/reviews.js +1 -1
- package/dist/daemon/api/handlers/runs.js +1 -1
- package/dist/daemon/api/handlers/structured-requests.js +1 -1
- package/dist/daemon/api/handlers/subscriptions.js +1 -1
- package/dist/daemon/api/handlers/transfer.js +1 -1
- package/dist/daemon/api/map.d.ts +3 -3
- package/dist/daemon/api/map.js +1 -1
- package/dist/daemon/api/principal.d.ts +1 -1
- package/dist/daemon/api/principal.js +1 -1
- package/dist/daemon/api/reader.d.ts +5 -5
- package/dist/daemon/api/reader.js +1 -1
- package/dist/daemon/api/router.d.ts +5 -5
- package/dist/daemon/api/router.js +1 -1
- package/dist/daemon/api/server.js +1 -1
- package/dist/daemon/broker-signals/bus.d.ts +1 -1
- package/dist/daemon/broker-signals/bus.js +1 -1
- package/dist/daemon/companion-retire.js +1 -1
- package/dist/daemon/cron/armed-context.d.ts +2 -2
- package/dist/daemon/cron/armed-context.js +1 -1
- package/dist/daemon/cron/authority.d.ts +2 -2
- package/dist/daemon/cron/authority.js +1 -1
- package/dist/daemon/cron/disposition.js +1 -1
- package/dist/daemon/cron/ended.d.ts +1 -1
- package/dist/daemon/cron/ended.js +2 -2
- package/dist/daemon/cron/escalation.js +3 -3
- package/dist/daemon/cron/folders.d.ts +1 -1
- package/dist/daemon/cron/folders.js +1 -1
- package/dist/daemon/cron/held.d.ts +1 -1
- package/dist/daemon/cron/held.js +1 -1
- package/dist/daemon/cron/lease-recovery.d.ts +1 -1
- package/dist/daemon/cron/lease-recovery.js +1 -1
- package/dist/daemon/cron/passes.d.ts +2 -2
- package/dist/daemon/cron/passes.js +1 -1
- package/dist/daemon/cron/run-socket.d.ts +1 -1
- package/dist/daemon/cron/run-socket.js +1 -1
- package/dist/daemon/cron/settle.js +1 -1
- package/dist/daemon/cron/sinks.d.ts +1 -1
- package/dist/daemon/cron/sinks.js +2 -2
- package/dist/daemon/cron-run.d.ts +12 -3
- package/dist/daemon/cron-run.js +2 -2
- package/dist/daemon/crtrd.js +6 -6
- package/dist/daemon/delivery/run-delivery.js +1 -1
- package/dist/daemon/due-sources.d.ts +3 -3
- package/dist/daemon/due-sources.js +1 -1
- package/dist/daemon/due.d.ts +3 -3
- package/dist/daemon/due.js +7 -7
- package/dist/daemon/fleet.d.ts +2 -2
- package/dist/daemon/fleet.js +11 -11
- package/dist/daemon/human/finish.js +3 -3
- package/dist/daemon/human/settle.d.ts +1 -1
- package/dist/daemon/human/settle.js +1 -1
- package/dist/daemon/human/sweep.js +1 -1
- package/dist/daemon/joined-owner.d.ts +2 -2
- package/dist/daemon/joined-owner.js +1 -1
- package/dist/daemon/messaging/node-message.js +1 -1
- package/dist/daemon/park-activity.d.ts +2 -2
- package/dist/daemon/park-activity.js +1 -1
- package/dist/daemon/peer/authority.js +1 -1
- package/dist/daemon/peer/forward.d.ts +6 -6
- package/dist/daemon/peer/forward.js +1 -1
- package/dist/daemon/peer/handlers.js +1 -1
- package/dist/daemon/peer/ingress.d.ts +4 -4
- package/dist/daemon/peer/ingress.js +1 -1
- package/dist/daemon/peer/outbox.d.ts +2 -2
- package/dist/daemon/peer/outbox.js +1 -1
- package/dist/daemon/peer/relay-service.js +1 -1
- package/dist/daemon/plugin-objects/read-leaf.d.ts +2 -2
- package/dist/daemon/plugin-objects/read-leaf.js +2 -2
- package/dist/daemon/profile-delete.js +1 -1
- package/dist/daemon/readiness.d.ts +2 -2
- package/dist/daemon/readiness.js +1 -1
- package/dist/daemon/reconcilers/action-lane.d.ts +1 -1
- package/dist/daemon/reconcilers/action-lane.js +1 -1
- package/dist/daemon/reconcilers/bash-deadline.js +2 -2
- package/dist/daemon/reconcilers/broker-supervision.d.ts +1 -1
- package/dist/daemon/reconcilers/broker-supervision.js +4 -4
- package/dist/daemon/reconcilers/controller-death.d.ts +1 -1
- package/dist/daemon/reconcilers/controller-death.js +1 -1
- package/dist/daemon/reconcilers/cron-lane.d.ts +1 -1
- package/dist/daemon/reconcilers/cron-lane.js +1 -1
- package/dist/daemon/reconcilers/delivery-lane.d.ts +1 -1
- package/dist/daemon/reconcilers/delivery-lane.js +2 -2
- package/dist/daemon/reconcilers/fault-retry-backstop.d.ts +3 -3
- package/dist/daemon/reconcilers/fault-retry-backstop.js +1 -1
- package/dist/daemon/reconcilers/grove-instance-sweep.d.ts +2 -2
- package/dist/daemon/reconcilers/grove-instance-sweep.js +1 -1
- package/dist/daemon/reconcilers/live-obligation.d.ts +6 -6
- package/dist/daemon/reconcilers/live-obligation.js +1 -1
- package/dist/daemon/reconcilers/managed-worktree-sweep.js +1 -1
- package/dist/daemon/reconcilers/node-deadline.d.ts +1 -1
- package/dist/daemon/reconcilers/node-deadline.js +1 -1
- package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +1 -1
- package/dist/daemon/reconcilers/node-lifecycle/respawn-policy.d.ts +3 -3
- package/dist/daemon/reconcilers/node-lifecycle/respawn-policy.js +1 -1
- package/dist/daemon/reconcilers/node-lifecycle/terminating.js +1 -1
- package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -1
- package/dist/daemon/reconcilers/node-lifecycle/wants-execution.d.ts +1 -1
- package/dist/daemon/reconcilers/node-lifecycle/wants-execution.js +1 -1
- package/dist/daemon/reconcilers/pending-review-submit.d.ts +1 -1
- package/dist/daemon/reconcilers/pending-review-submit.js +1 -1
- package/dist/daemon/reconcilers/storage-due-work.js +1 -1
- package/dist/daemon/reconcilers/storage-maintenance.d.ts +1 -1
- package/dist/daemon/reconcilers/storage-maintenance.js +2 -2
- package/dist/daemon/reconcilers/structured-request-lane.d.ts +1 -1
- package/dist/daemon/reconcilers/structured-request-lane.js +1 -1
- package/dist/daemon/review/comment-notify.js +2 -2
- package/dist/daemon/review/companion.d.ts +3 -3
- package/dist/daemon/review/companion.js +1 -1
- package/dist/daemon/review/finish.js +1 -1
- package/dist/daemon/review/sweep.js +1 -1
- package/dist/daemon/run-notices.d.ts +4 -4
- package/dist/daemon/run-notices.js +1 -1
- package/dist/daemon/runs/append-section.d.ts +2 -2
- package/dist/daemon/runs/append-section.js +2 -2
- package/dist/daemon/runs/observer.d.ts +2 -2
- package/dist/daemon/runs/observer.js +2 -2
- package/dist/daemon/structured-requests/boot.d.ts +1 -1
- package/dist/daemon/structured-requests/boot.js +1 -1
- package/dist/daemon/structured-requests/effects.js +1 -1
- package/dist/daemon/structured-requests/sidecar.d.ts +1 -1
- package/dist/daemon/structured-requests/sidecar.js +1 -1
- package/dist/migrations/004-canvas-documents/apply.d.ts +3 -3
- package/dist/migrations/004-canvas-documents/apply.js +1 -1
- package/dist/migrations/004-canvas-documents/index.d.ts +2 -2
- package/dist/migrations/004-canvas-documents/index.js +2 -2
- package/dist/migrations/activation.js +2 -2
- package/docs/public-api.md +11 -0
- package/package.json +3 -2
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +12 -12
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
var Y=Object.defineProperty;var l=(e,s)=>Y(e,"name",{value:s,configurable:!0});import{heldAtOrAbove as $,hold as _,freezePreferences as F}from"../../graph/exposures.js";import{interpolateNodePaths as z}from"../../canvas/paths.js";import{buildSubPersonaMenu as B}from"./sub-persona-menu.js";import{rungAtLeast as k}from"../schema.js";import{loadCorpus as A}from"./corpus.js";import{listingPrefixes as H}from"./listings.js";import{bootPartitionOf as O,planDelivery as P}from"./plan.js";import{linkedDocs as q,renderEvent as S}from"./render-event.js";const E="Each %s below shows either its full content (indented beneath its name), a `# read when:` line telling you when to read the full document, or simply its name.",
|
|
2
|
-
`)}l(
|
|
1
|
+
var Y=Object.defineProperty;var l=(e,s)=>Y(e,"name",{value:s,configurable:!0});import{heldAtOrAbove as $,hold as _,freezePreferences as F}from"../../graph/exposures.js";import{interpolateNodePaths as z}from"../../canvas/paths.js";import{buildSubPersonaMenu as B}from"./sub-persona-menu.js";import{rungAtLeast as k}from"../schema.js";import{loadCorpus as A}from"./corpus.js";import{listingPrefixes as H}from"./listings.js";import{bootPartitionOf as O,planDelivery as P}from"./plan.js";import{linkedDocs as q,renderEvent as S}from"./render-event.js";import{mapAsync as J}from"../../async-array.js";const E="Each %s below shows either its full content (indented beneath its name), a `# read when:` line telling you when to read the full document, or simply its name.",Q="Preferences are how the user wants you to behave \u2014 standing directives and corrections. To read a preference, run `crtr canvas read <name>`. "+E.replace("%s","preference"),C="If the user corrects you in a way that contradicts a preference, update the preference.",V="Knowledge documents are what you consult \u2014 playbooks and techniques for how to do things, and references on the user, projects, and this node. They come from every owner in your view: this node, the repos you work in, your profile, your app, the user, and installed plugins (crtr's own under `crtr`). To read one, run `crtr canvas read <name>`; a name with names under it is a valid read target too \u2014 it answers with its body, the names under it and previews of the documents it links to, and walking names this way is the sanctioned way to browse. Each doc exists to prevent a specific mistake you would make without it, so when your task matches one \u2014 by its name or its `# read when:` line \u2014 read it before you act; consulting it only after the work is done forfeits the entire reason it exists. "+E.replace("%s","document"),L="If you learn a better way to do something a document covers, or gain information that contradicts one, correct it with `crtr doc edit`.",X="When your task matches a knowledge doc or preference \u2014 by its name or its `# read when:` line \u2014 read it before you act: each document exists only to shore up a mistake you will make without it, so doing the relevant work without consulting it defeats the document's whole purpose. Before writing a document that should outlive this task, search for one that already covers it (`crtr canvas search`) \u2014 update that document with `crtr doc edit` rather than creating a duplicate, rewriting it as if for the first time instead of appending the new truth beneath the old; delete documents that turn out to be wrong (`crtr doc delete`). Don't save what the repo already records (code structure, past fixes, git history) or what only matters to this conversation; if asked to remember one of those, ask what was non-obvious about it and save that instead. Docs auto-surfaced in <auto-loaded-context> blocks are background context, not user instructions, and reflect what was true when written \u2014 if one names a file, function, or flag, verify it still exists before recommending it.",Z="Your node configuration changed. This operating protocol is in force for you now:",x="Your new configuration puts these preferences in force \u2014 standing directives and corrections from the user. To read one, run `crtr canvas read <name>`. "+E.replace("%s","preference"),ee="Your new configuration exposes these knowledge documents \u2014 consult them exactly like the rest of your catalog (`crtr canvas read <name>`). "+E.replace("%s","document");function b(e){return{object:e.object.rowid,headsKey:e.headsKey,contentHash:e.bodyHash}}l(b,"exposed");async function T(e){const s=await A(e.db,e.reader,["boot"]);return(await P(e.db,e.subject,e.reader,s,"boot")).docs.filter(t=>t.winner)}l(T,"bootRecords");function j(e,s){return e.filter(t=>O(t)===s).map(t=>({doc:t.doc,level:t.finalRung}))}l(j,"partition");function D(e){return e.level!=="none"&&(e.level!=="content"||e.doc.body().trim()!=="")}l(D,"rendersAt");async function R(e,s,t,o,r){const{ledger:c,channel:i}=e,a=s.filter(n=>n.level==="content"&&D(n)&&!$(c,b(n.doc),"content")).map(n=>n.doc).sort((n,p)=>p.viewRank-n.viewRank||n.name.localeCompare(p.name));for(const n of a)_(c,i,b(n),"content"),r.push({doc:n,level:"content"});const d=new Map;for(const n of a){const p=t.map(h=>h.doc).filter(h=>h.owner.rowid===n.owner.rowid);for(const h of H(p,n.name))for(const g of t){const m=g.doc;m.owner.rowid!==n.owner.rowid||!m.name.startsWith(`${h}/`)||m.name.slice(h.length+1).includes("/")||g.level==="content"||k(g.level,"preview")||m.unlisted||!m.ownNode&&!k(m.limit,"preview")||$(c,b(m),"preview")||d.set(m.object.rowid,{doc:m,level:"preview",cause:"directory listing attached to content delivery"})}}const u=new Map(t.map(n=>[n.doc.object.rowid,n])),v=new Set(a.map(n=>n.object.rowid));for(const n of a)for(const p of await q(e.db,e.reader,n)){const h=p.object.rowid,g=u.get(h);d.has(h)||v.has(h)||g!==void 0&&k(g.level,"preview")||O({doc:p})===O({doc:n})&&(!p.ownNode&&!k(p.limit,"preview")||$(c,b(p),"preview")||d.set(h,{doc:g?.doc??p,level:"preview",cause:"link preview attached to content delivery"}))}const y=(await J(a,async n=>await S(e,"document-read",{doc:n}))).flatMap(({content:n,delivered:p})=>(r.push(...p),n===""?[]:[n])),w=s.filter(n=>n.level!=="content").map(n=>d.get(n.doc.object.rowid)??n),f=new Set(w.map(n=>n.doc.object.rowid));w.push(...[...d.values()].filter(n=>!f.has(n.doc.object.rowid)));for(const n of w)D(n)&&(_(c,i,b(n.doc),n.level),r.push({doc:n.doc,level:n.level,...n.cause===void 0?{}:{cause:n.cause}}));return{content:a,attachments:y,tree:te(w,o)}}l(R,"renderGrouped");function I(e){return{segment:e,own:null,dirs:new Map,leaves:new Map,hidden:0,renders:!1,count:0}}l(I,"newDir");const ne=l(e=>k(e,"name"),"visible");function M(e,s){let t=e.hidden;for(const o of e.dirs.values())t+=M(o,e.segment==="");return e.renders=e.own!==null||e.leaves.size>0||[...e.dirs.values()].some(o=>o.renders)||s||e.segment==="",e.count=e.renders?t:0,e.renders?0:t}l(M,"resolveDir");function G(e,s,t){const o=e.level==="preview"?e.doc.preview.trim():"";return o===""?`${t}${s}`:`${t}${s} # read when: ${o}`}l(G,"entryLine");function K(e,s,t){const o=[...[...e.dirs.values()].filter(r=>r.renders).map(r=>({name:r.segment,dir:r})),...[...e.leaves].map(([r,c])=>({name:r,leaf:c}))].sort((r,c)=>r.name.localeCompare(c.name));e.count>0&&o.push({name:"",more:e.count}),o.forEach((r,c)=>{const i=c===o.length-1,a=s+(i?"\u2514\u2500 ":"\u251C\u2500 ");if("more"in r)t.push(`${a}[+${r.more} more]`);else if(r.dir!==void 0){const d=`${r.dir.segment}/`;t.push(r.dir.own===null?`${a}${d}`:G(r.dir.own,d,a)),K(r.dir,s+(i?" ":"\u2502 "),t)}else t.push(G(r.leaf,r.name,a))})}l(K,"renderChildren");function te(e,s){if(e.length===0)return"";const t=I(""),o=l(i=>{let a=t;for(const d of i){let u=a.dirs.get(d);u===void 0&&a.dirs.set(d,u=I(d)),a=u}return a},"dirAt"),r=new Set(e.map(i=>i.doc.displayName));for(const i of e){const a=i.doc.displayName.split("/"),d=[...r].some(u=>u.startsWith(`${i.doc.displayName}/`));ne(i.level)?d?o(a).own=i:o(a.slice(0,-1)).leaves.set(a[a.length-1],i):o(d?a:a.slice(0,-1)).hidden+=1}M(t,!1);const c=[s];return K(t,"",c),c.join(`
|
|
2
|
+
`)}l(te,"buildTree");function N(e,s){const{reader:t}=e;return t.class==="node"?z(s,t.node.id,t.app.name):s}l(N,"interpolate");function W(e){return e.shipped}l(W,"isShipped");function U(e){const s=e.content.filter(W).map(o=>o.body().trim()).filter(o=>o!==""),t=e.content.filter(o=>!W(o)).map(o=>o.body().trim()===""?"":`<preference name="${o.displayName}">
|
|
3
3
|
${o.body().trim()}
|
|
4
|
-
</preference>`).filter(o=>o!=="");return{shipped:s,editable:t}}l(U,"preferenceParts");function
|
|
4
|
+
</preference>`).filter(o=>o!=="");return{shipped:s,editable:t}}l(U,"preferenceParts");async function pe(e){if(e.ledger.preferenceSnapshot!==null)return{content:e.ledger.preferenceSnapshot,delivered:[]};const s={...e,channel:"system"},t=[];let o=[],r=X;if(e.subject!==null){const i=j(await T(s),"preference"),a=await R(s,i,i,"preferences",t),{shipped:d,editable:u}=U(a),v=B(e.subject.kind);o=[...d,...a.attachments,...v===""?[]:[v]],(u.length>0||a.tree!=="")&&(r+=`
|
|
5
5
|
|
|
6
|
-
${
|
|
6
|
+
${Q}`,u.length>0&&(r+=`
|
|
7
7
|
|
|
8
8
|
${u.join(`
|
|
9
9
|
|
|
10
|
-
`)}`),
|
|
10
|
+
`)}`),a.tree!==""&&(r+=`
|
|
11
11
|
|
|
12
|
-
${
|
|
12
|
+
${a.tree}`),r+=`
|
|
13
13
|
|
|
14
|
-
${C}`)}const
|
|
14
|
+
${C}`)}const c=[...o,`<memory kind="preference">
|
|
15
15
|
${r}
|
|
16
16
|
</memory>`].join(`
|
|
17
17
|
|
|
18
|
-
`);return{content:F(e.ledger,N(e,
|
|
18
|
+
`);return{content:F(e.ledger,N(e,c)),delivered:t}}l(pe,"renderPreferences");async function he(e){const s=[],t=j(await T(e),"knowledge"),o=await R(e,t,t,"knowledge",s),r=[...o.content.map(i=>i.body().trim()),...o.attachments].filter(i=>i!=="");if(r.length===0&&o.tree==="")return{content:"",delivered:s};let c=V;return r.length>0&&(c+=`
|
|
19
19
|
|
|
20
20
|
${r.join(`
|
|
21
21
|
|
|
22
|
-
`)}`),o.tree!==""&&(
|
|
22
|
+
`)}`),o.tree!==""&&(c+=`
|
|
23
23
|
|
|
24
|
-
${o.tree}`),
|
|
24
|
+
${o.tree}`),c+=`
|
|
25
25
|
|
|
26
26
|
${L}`,{content:N(e,`<memory kind="knowledge">
|
|
27
|
-
${
|
|
28
|
-
</memory>`),delivered:s}}l(
|
|
27
|
+
${c}
|
|
28
|
+
</memory>`),delivered:s}}l(he,"renderKnowledge");async function me(e){const s=await A(e.db,e.reader,["workspace-open"]),t=(await P(e.db,e.subject,e.reader,s,"workspace-open")).docs.filter(c=>c.winner).map(c=>c.doc).sort((c,i)=>i.viewRank-c.viewRank||c.object.rowid-i.object.rowid),{content:o,delivered:r}=await S(e,"workspace-open",{},t);return{content:N(e,o),delivered:r}}l(me,"renderWorkspaceOpen");async function we(e){const{ledger:s}=e,t=[],o=await T(e),r=l(f=>f.filter(n=>D(n)&&!$(s,b(n.doc),n.level)),"fresh"),c=j(o,"preference"),i=await R(e,r(c),c,"preferences",t),{shipped:a,editable:d}=U(i),u=[];if((a.length>0||i.attachments.length>0)&&u.push(`${Z}
|
|
29
29
|
|
|
30
|
-
${[...
|
|
30
|
+
${[...a,...i.attachments].join(`
|
|
31
31
|
|
|
32
|
-
`)}`),d.length>0||i.tree!==""){let f=
|
|
32
|
+
`)}`),d.length>0||i.tree!==""){let f=x;d.length>0&&(f+=`
|
|
33
33
|
|
|
34
34
|
${d.join(`
|
|
35
35
|
|
|
@@ -39,16 +39,16 @@ ${i.tree}`),f+=`
|
|
|
39
39
|
|
|
40
40
|
${C}`,u.push(`<memory kind="preference">
|
|
41
41
|
${f}
|
|
42
|
-
</memory>`)}const v=j(o,"knowledge"),
|
|
42
|
+
</memory>`)}const v=j(o,"knowledge"),y=await R(e,r(v),v,"knowledge",t),w=[...y.content.map(f=>f.body().trim()),...y.attachments].filter(f=>f!=="");if(w.length>0||y.tree!==""){let f=ee;w.length>0&&(f+=`
|
|
43
43
|
|
|
44
44
|
${w.join(`
|
|
45
45
|
|
|
46
|
-
`)}`),
|
|
46
|
+
`)}`),y.tree!==""&&(f+=`
|
|
47
47
|
|
|
48
|
-
${
|
|
48
|
+
${y.tree}`),f+=`
|
|
49
49
|
|
|
50
50
|
${L}`,u.push(`<memory kind="knowledge">
|
|
51
51
|
${f}
|
|
52
52
|
</memory>`)}return{content:u.length===0?"":N(e,u.join(`
|
|
53
53
|
|
|
54
|
-
`)),delivered:t}}l(
|
|
54
|
+
`)),delivered:t}}l(we,"renderConfigDelta");export{we as renderConfigDelta,he as renderKnowledge,pe as renderPreferences,me as renderWorkspaceOpen};
|
|
@@ -1,17 +1,10 @@
|
|
|
1
|
-
/** Event rendering for the row-backed delivery engine: plan an activity, render
|
|
2
|
-
* each winner the ledger does not already hold, and for every content
|
|
3
|
-
* delivery attach its prefix listings and link previews and chain its `document-read` rules
|
|
4
|
-
* until nothing new is delivered. Every rendered document is held in the
|
|
5
|
-
* in-memory `ledger`; persisting it is the caller's. Envelope markup is the
|
|
6
|
-
* `<memory>` / `<memory-listing>` / `<auto-loaded-context>` shape that
|
|
7
|
-
* `pi-extensions/envelope-merge.ts` parses. */
|
|
8
|
-
import type { DatabaseSync } from 'node:sqlite';
|
|
9
1
|
import { type Channel, type Ledger } from '../../graph/exposures.js';
|
|
10
2
|
import type { Reader, RuleOn } from '../../graph/types.js';
|
|
11
3
|
import type { Rung } from '../schema.js';
|
|
12
4
|
import type { NodeConfigSubject } from '../subject-fields.js';
|
|
13
5
|
import { type DeliveryPayload } from './plan.js';
|
|
14
6
|
import type { DeliveryDoc } from './types.js';
|
|
7
|
+
import type { CanvasDb } from '../../canvas/db.js';
|
|
15
8
|
export type DeliveryCause = 'directory listing attached to content delivery' | 'link preview attached to content delivery' | 'memory-read companion of content delivery';
|
|
16
9
|
export interface DeliveredDoc {
|
|
17
10
|
doc: DeliveryDoc;
|
|
@@ -20,7 +13,7 @@ export interface DeliveredDoc {
|
|
|
20
13
|
cause?: DeliveryCause;
|
|
21
14
|
}
|
|
22
15
|
export interface RenderContext {
|
|
23
|
-
db:
|
|
16
|
+
db: CanvasDb;
|
|
24
17
|
reader: Reader;
|
|
25
18
|
subject: NodeConfigSubject | null;
|
|
26
19
|
ledger: Ledger;
|
|
@@ -33,22 +26,22 @@ export declare function wrapAutoLoaded(blocks: readonly string[]): string;
|
|
|
33
26
|
/** The live documents `doc`'s current revision links to that the reader may
|
|
34
27
|
* read, in link order, without `doc` itself. Remote and unresolved links have
|
|
35
28
|
* no `links-to` edge, so they never appear. */
|
|
36
|
-
export declare function linkedDocs(db:
|
|
29
|
+
export declare function linkedDocs(db: CanvasDb, reader: Reader, doc: DeliveryDoc): Promise<DeliveryDoc[]>;
|
|
37
30
|
/** Deliver one activity. `corpus` overrides the reader's own corpus for `on`
|
|
38
31
|
* (the file-read corpus also carries the rules of repos enclosing the file). */
|
|
39
|
-
export declare function renderEvent(ctx: RenderContext, on: RuleOn, payload: DeliveryPayload, corpus?: readonly DeliveryDoc[]): {
|
|
32
|
+
export declare function renderEvent(ctx: RenderContext, on: RuleOn, payload: DeliveryPayload, corpus?: readonly DeliveryDoc[]): Promise<{
|
|
40
33
|
content: string;
|
|
41
34
|
delivered: DeliveredDoc[];
|
|
42
|
-
}
|
|
35
|
+
}>;
|
|
43
36
|
/** What a document the node read on purpose brings with it: its own prefix
|
|
44
37
|
* listing unfiltered (`listing`), the documents it links to not yet held at
|
|
45
38
|
* preview (`linked`, held at preview now), enclosing listings and chained
|
|
46
39
|
* `document-read` deliveries (`attachments`, wrapped). With `ownAsBlock`
|
|
47
40
|
* (a caller that renders only `attachments`), the own set rides there as a
|
|
48
41
|
* block instead. The read document itself is held at content in `ledger`. */
|
|
49
|
-
export declare function renderExplicitRead(ctx: RenderContext, doc: DeliveryDoc, ownAsBlock?: boolean): {
|
|
42
|
+
export declare function renderExplicitRead(ctx: RenderContext, doc: DeliveryDoc, ownAsBlock?: boolean): Promise<{
|
|
50
43
|
attachments: string;
|
|
51
44
|
listing?: string[];
|
|
52
45
|
linked: DeliveryDoc[];
|
|
53
46
|
delivered: DeliveredDoc[];
|
|
54
|
-
}
|
|
47
|
+
}>;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var
|
|
1
|
+
var N=Object.defineProperty;var s=(e,n)=>N(e,"name",{value:n,configurable:!0});import{canRead as D}from"../../graph/access.js";import{heldAtOrAbove as b,hold as y,holdListing as E,listedAtOrAbove as O}from"../../graph/exposures.js";import{deliveryDocOf as H,listingCorpus as K,loadCorpus as g}from"./corpus.js";import{listingBlock as L,ownSetBlock as R,listingKey as C,listingLabel as x,listingPrefixes as P,renderListing as k}from"./listings.js";import{planDelivery as B}from"./plan.js";import{filterAsync as M,mapAsync as S}from"../../async-array.js";function v(e){return e.replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}s(v,"attr");function W(e,n){let t=`kind="${v(e.kind)}" name="${v(e.displayName)}"`;if(n==="content"){const i=e.body().trim();if(i!=="")return`<memory ${t}>
|
|
2
2
|
${i}
|
|
3
|
-
</memory>`}else n==="preview"&&e.preview.trim()!==""&&(t+=` readWhen="${
|
|
3
|
+
</memory>`}else n==="preview"&&e.preview.trim()!==""&&(t+=` readWhen="${v(e.preview.trim())}"`);return`<memory ${t} />`}s(W,"renderEnvelope");function j(e){return e.length===0?"":`<auto-loaded-context>
|
|
4
4
|
${e.join(`
|
|
5
5
|
`)}
|
|
6
|
-
</auto-loaded-context>`}s(j,"wrapAutoLoaded");function
|
|
6
|
+
</auto-loaded-context>`}s(j,"wrapAutoLoaded");async function I(e,n){let t=e.members.get(n.owner.rowid);return t===void 0&&(t=await K(e.ctx.db,e.ctx.reader,n.owner),e.members.set(n.owner.rowid,t)),t}s(I,"membersOf");async function _(e,n,t){const i=await e.prepare(`SELECT o.* FROM edges e JOIN objects o ON o.rowid = e.dst
|
|
7
7
|
WHERE e.type = 'links-to' AND e.src = ? AND o.type = 'document' AND o.deleted_at IS NULL AND o.rowid <> ?
|
|
8
|
-
ORDER BY e.written_as`).all(t.object.rowid,t.object.rowid)
|
|
8
|
+
ORDER BY e.written_as`).all(t.object.rowid,t.object.rowid);return await S(await M(i,async o=>await D(e,n,o)),async o=>await H(e,n,o))}s(_,"linkedDocs");function q(e,n){return n.owner.rowid===e.owner.rowid&&n.name.startsWith(`${e.name}/`)&&!n.name.slice(e.name.length+1).includes("/")}s(q,"underOwnPrefix");async function F(e,n){const{ledger:t,channel:i}=e.ctx,o=[],c=[];for(const r of await _(e.ctx.db,e.ctx.reader,n)){if(q(n,r)&&!r.unlisted)continue;const l={object:r.object.rowid,headsKey:r.headsKey,contentHash:r.bodyHash};if(b(t,l,"preview"))continue;y(t,i,l,"preview"),e.delivered.push({doc:r,level:"preview",cause:"link preview attached to content delivery"}),c.push(r);const a=r.preview.trim();o.push(a===""?`[[${r.displayName}]]`:`[[${r.displayName}]]: ${a}`)}return{lines:o,linked:c}}s(F,"linkPreviews");async function A(e,n,t){const{ledger:i,channel:o}=e.ctx,c=await I(e,n),r=[];let l,a=[];for(const m of P(c,n.name)){const p=m===n.name,f=C(n,m);if(!(p&&t)&&O(i,f,"preview"))continue;const{lines:d,previewed:u}=k(c,m,i,o,!(p&&t));for(const w of u)e.delivered.push({doc:w,level:"preview",cause:"directory listing attached to content delivery"});d.length!==0&&(E(i,o,f,"preview"),p?a=d:r.push(L(x(n,m),d)))}const h=await F(e,n);return t?a.length>0&&(l=a):a.length+h.lines.length>0&&r.unshift(R(x(n,n.name),a,h.lines)),e.chainCorpus??=await g(e.ctx.db,e.ctx.reader,["document-read"]),r.push(...await $(e,e.chainCorpus,"document-read",{doc:n},"memory-read companion of content delivery")),{blocks:r,...l===void 0?{}:{listing:l},linked:h.linked}}s(A,"attachments");async function $(e,n,t,i,o){const{db:c,reader:r,subject:l,ledger:a,channel:h}=e.ctx,m=await B(c,l,r,n,t,i),p=[];for(const f of m.docs){const d=f.finalRung;if(!f.winner||d==="none")continue;const{doc:u}=f,w={object:u.object.rowid,headsKey:u.headsKey,contentHash:u.bodyHash};b(a,w,d)||(y(a,h,w,d),e.delivered.push({doc:u,level:d,...o===void 0?{}:{cause:o}}),d==="content"&&p.push(...(await A(e,u,!1)).blocks),p.push(W(u,d)))}return p}s($,"renderPlan");async function V(e,n,t,i){i??=await g(e.db,e.reader,[n]);const o={ctx:e,delivered:[],members:new Map};return{content:j(await $(o,i,n,t)),delivered:o.delivered}}s(V,"renderEvent");async function X(e,n,t=!1){const i={ctx:e,delivered:[],members:new Map};y(e.ledger,e.channel,{object:n.object.rowid,headsKey:n.headsKey,contentHash:n.bodyHash},"content");const{blocks:o,listing:c,linked:r}=await A(i,n,!t);return{attachments:j(o),...c===void 0?{}:{listing:c},linked:r,delivered:i.delivered}}s(X,"renderExplicitRead");export{_ as linkedDocs,W as renderEnvelope,V as renderEvent,X as renderExplicitRead,j as wrapAutoLoaded};
|
|
@@ -6,8 +6,8 @@ export type { NodeConfigSubject } from './subject-fields.js';
|
|
|
6
6
|
* walking the `parent` chain (canvas-db rows) until a row with no parent (the
|
|
7
7
|
* root). The root is depth 0. Cycle-guarded (parents must not cycle, but never
|
|
8
8
|
* loop forever) — mirrors `rootOfSpine` in runtime/placement.ts. */
|
|
9
|
-
export declare function spineDepth(nodeId: string): number
|
|
9
|
+
export declare function spineDepth(nodeId: string): Promise<number>;
|
|
10
10
|
/** Assemble the node-config subject for `nodeId` from its `NodeMeta` + the
|
|
11
11
|
* derived fields. Returns `null` when the node has no canvas-db row (an
|
|
12
12
|
* unknown id). Pure aside from the canvas-db + profile-manifest reads. */
|
|
13
|
-
export declare function assembleNodeSubject(nodeId: string, repos?: readonly ObjectRow[]): NodeConfigSubject | null
|
|
13
|
+
export declare function assembleNodeSubject(nodeId: string, repos?: readonly ObjectRow[]): Promise<NodeConfigSubject | null>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var p=Object.defineProperty;var n=(r,o)=>p(r,"name",{value:o,configurable:!0});import{getNode as a,getRow as c}from"../canvas/index.js";import{openDb as s}from"../canvas/db.js";import{checkoutsForCwd as l}from"../graph/repo-sync/repos.js";import{liveLookups as f,viewRepos as m}from"../graph/reader.js";import{effectiveScopes as w,scopeForCwd as u,profileNameFor as d}from"./subject-fields.js";import{effectiveScopes as C,scopeForCwd as j,profileNameFor as D}from"./subject-fields.js";async function b(r){let o=r;const e=new Set;let t=0;for(;!e.has(o);){e.add(o);const i=await c(o);if(i===null||i.parent==null)break;o=i.parent,t++}return t}n(b,"spineDepth");async function h(r,o){const e=await s(),t=await m(r,o,async i=>await l(e,i),f(e));return[...t.repos,...t.projectRepos]}n(h,"eligibleRepos");async function R(r,o){const e=await a(r);return e===null?null:{kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,hasManager:(e.parent??null)!==null,cwd:e.cwd,scope:u(e.cwd),orchestration:{depth:await b(r)},profile:d(e.profile_id),scopes:w(e.scopes),repo:(o??await h(e.cwd,e.profile_id??null)).map(t=>t.name)}}n(R,"assembleNodeSubject");export{R as assembleNodeSubject,C as effectiveScopes,D as profileNameFor,j as scopeForCwd,b as spineDepth};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type CanvasDb } from '../canvas/db.js';
|
|
2
2
|
import type { SpendUsageDTO } from '../../api/dto/usage.js';
|
|
3
3
|
/** The person's own agent. Its grant carries the directory's default cap, but the
|
|
4
4
|
* cap bounds what an app spends of the person's subscription, never the person's
|
|
@@ -23,15 +23,15 @@ export interface UsageRecord {
|
|
|
23
23
|
usd_equivalent: number | null;
|
|
24
24
|
}
|
|
25
25
|
/** Add one completion's or receipt's usage to its grantee's month, inside the caller's write. */
|
|
26
|
-
export declare function addUsage(db:
|
|
26
|
+
export declare function addUsage(db: CanvasDb, record: UsageRecord, at?: Date): Promise<void>;
|
|
27
27
|
/** Record one model completion for `grantee`. */
|
|
28
28
|
export declare function recordModelUsage(grantee: string, payer: Payer, servedModel: string, usage: {
|
|
29
29
|
input: number;
|
|
30
30
|
output: number;
|
|
31
31
|
cacheRead: number;
|
|
32
|
-
}, usdEquivalent: number | null): void
|
|
32
|
+
}, usdEquivalent: number | null): Promise<void>;
|
|
33
33
|
/** The grantee's user-paid month-to-date model spend; provider receipts are not in it. */
|
|
34
|
-
export declare function monthSpend(grantee: string, month?: string): number
|
|
34
|
+
export declare function monthSpend(grantee: string, month?: string): Promise<number>;
|
|
35
35
|
/** Who a user-paid call bills, and the cap that bounds it (`null` = uncapped). */
|
|
36
36
|
export interface SpendTarget {
|
|
37
37
|
grantee: string;
|
|
@@ -42,8 +42,8 @@ export declare function effectiveCap(target: SpendTarget): number | null;
|
|
|
42
42
|
/** Refuse a user-paid call once the grantee's month spend reached its cap (SPD-2).
|
|
43
43
|
* The check runs before the call; one response may overshoot the cap (no
|
|
44
44
|
* reserve-then-settle), and the next call is refused. */
|
|
45
|
-
export declare function assertUnderCap(target: SpendTarget | undefined, at?: Date): void
|
|
45
|
+
export declare function assertUnderCap(target: SpendTarget | undefined, at?: Date): Promise<void>;
|
|
46
46
|
/** `usage.get` for one grantee and month. */
|
|
47
|
-
export declare function usageFor(grantee: string, spendCap: number | null, month?: string): SpendUsageDTO
|
|
47
|
+
export declare function usageFor(grantee: string, spendCap: number | null, month?: string): Promise<SpendUsageDTO>;
|
|
48
48
|
/** A `month` query value: `YYYY-MM` with a real month, years 1000-9999; absent means the current month. */
|
|
49
49
|
export declare function parseUsageMonth(value: string | null): string;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
var
|
|
1
|
+
var h=Object.defineProperty;var a=(e,t)=>h(e,"name",{value:t,configurable:!0});import{withCanvasWrite as q,openDb as d}from"../canvas/db.js";import{RunError as _}from"../runs/operations.js";const w="app:terminal";function r(e=new Date){return e.toISOString().slice(0,7)}a(r,"usageMonth");function l(e){const[t,n]=e.split("-").map(Number);return new Date(Date.UTC(t,n,1)).toISOString()}a(l,"resetAt");async function k(e,t,n=new Date){const u=r(n);await e.prepare(`INSERT INTO usage (grantee, month, payer, source, served_model, input_tokens, output_tokens, cached_tokens, usd_equivalent)
|
|
2
2
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
3
3
|
ON CONFLICT(grantee, month, payer, source, served_model) DO UPDATE SET
|
|
4
4
|
input_tokens = input_tokens + excluded.input_tokens,
|
|
5
5
|
output_tokens = output_tokens + excluded.output_tokens,
|
|
6
6
|
cached_tokens = cached_tokens + excluded.cached_tokens,
|
|
7
7
|
usd_equivalent = CASE WHEN usd_equivalent IS NULL AND excluded.usd_equivalent IS NULL THEN NULL
|
|
8
|
-
ELSE COALESCE(usd_equivalent, 0) + COALESCE(excluded.usd_equivalent, 0) END`).run(t.grantee,u,t.payer,t.source,t.served_model,t.input_tokens,t.output_tokens,t.cached_tokens,t.usd_equivalent),t.payer==="user"&&t.source==="model"&&t.usd_equivalent!==null&&t.usd_equivalent>0&&
|
|
9
|
-
ON CONFLICT(grantee, month) DO UPDATE SET usd_equivalent = usd_equivalent + excluded.usd_equivalent`).run(t.grantee,u,t.usd_equivalent)}
|
|
10
|
-
FROM usage WHERE grantee = ? AND month = ? ORDER BY served_model`).all(e,n),
|
|
8
|
+
ELSE COALESCE(usd_equivalent, 0) + COALESCE(excluded.usd_equivalent, 0) END`).run(t.grantee,u,t.payer,t.source,t.served_model,t.input_tokens,t.output_tokens,t.cached_tokens,t.usd_equivalent),t.payer==="user"&&t.source==="model"&&t.usd_equivalent!==null&&t.usd_equivalent>0&&await e.prepare(`INSERT INTO grantee_usage (grantee, month, usd_equivalent) VALUES (?, ?, ?)
|
|
9
|
+
ON CONFLICT(grantee, month) DO UPDATE SET usd_equivalent = usd_equivalent + excluded.usd_equivalent`).run(t.grantee,u,t.usd_equivalent)}a(k,"addUsage");async function g(e,t,n,u,s){await q(async p=>await k(p,{grantee:e,payer:t,source:"model",served_model:n,input_tokens:u.input,output_tokens:u.output,cached_tokens:u.cacheRead,usd_equivalent:s}))}a(g,"recordModelUsage");async function c(e,t=r()){return(await(await d()).prepare("SELECT usd_equivalent FROM grantee_usage WHERE grantee = ? AND month = ?").get(e,t))?.usd_equivalent??0}a(c,"monthSpend");function m(e){return e.grantee===w?null:e.spend_cap}a(m,"effectiveCap");async function x(e,t=new Date){if(!e)return;const n=m(e);if(n===null)return;const u=r(t),s=await c(e.grantee,u);if(!(s<n))throw new _(402,"cap_exhausted",`${e.grantee} reached its monthly usage limit`,void 0,{spend_cap:n,usd_equivalent:s,reset_at:l(u)})}a(x,"assertUnderCap");async function C(e,t,n=r()){const u=await(await d()).prepare(`SELECT payer, source, served_model, input_tokens, output_tokens, usd_equivalent
|
|
10
|
+
FROM usage WHERE grantee = ? AND month = ? ORDER BY served_model`).all(e,n),s=a(i=>u.filter(o=>o.payer===i&&o.source==="model").map(({served_model:o,input_tokens:E,output_tokens:v,usd_equivalent:f})=>({served_model:o,input_tokens:E,output_tokens:v,usd_equivalent:f})),"byModel"),p=u.filter(i=>i.payer==="app").reduce((i,o)=>i+(o.usd_equivalent??0),0);return{grantee:e,month:n,usd_equivalent:await c(e,n),by_model:s("user"),app_paid:{usd_equivalent:p,by_model:s("app")},spend_cap:m({grantee:e,spend_cap:t}),reset_at:l(n)}}a(C,"usageFor");function D(e){if(e===null)return r();if(!/^[1-9]\d{3}-(0[1-9]|1[0-2])$/.test(e))throw new _(400,"invalid_request","month must be YYYY-MM","month");return e}a(D,"parseUsageMonth");export{w as UNCAPPED_GRANTEE,k as addUsage,x as assertUnderCap,m as effectiveCap,c as monthSpend,D as parseUsageMonth,g as recordModelUsage,l as resetAt,C as usageFor,r as usageMonth};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
var P=Object.defineProperty;var c=(t,r)=>P(t,"name",{value:r,configurable:!0});import{existsSync as $,realpathSync as R}from"node:fs";import{resolve as q}from"node:path";import{getNode as v,recordDisposalGrant as B,recordLandIntent as M}from"./canvas/index.js";import{withExclusiveDirectoryLockAsync as O}from"./exclusive-lock.js";import{gitAsync as i}from"./git.js";import{proveBranchContained as x}from"./worktree-containment.js";import{concludeAbsentManagedWorktreeAsync as F}from"./worktree-mutation-async.js";import{parseStatusPorcelain as G,planLandIntoCheckout as I}from"./worktree-landing.js";import{WORKTREE_LOCK_WAIT_MS as T,checkoutPathForBranchInList as N,missingWorktreeRecoveryHint as j,persistClosedWorktreeState as A,samePath as K,worktreeLockPathForCommonDir as z,WorktreeError as h}from"./worktree.js";import{shellQuote as E}from"../shared/shell-quote.js";function
|
|
1
|
+
var P=Object.defineProperty;var c=(t,r)=>P(t,"name",{value:r,configurable:!0});import{existsSync as $,realpathSync as R}from"node:fs";import{resolve as q}from"node:path";import{getNode as v,recordDisposalGrant as B,recordLandIntent as M}from"./canvas/index.js";import{withExclusiveDirectoryLockAsync as O}from"./exclusive-lock.js";import{gitAsync as i}from"./git.js";import{proveBranchContained as x}from"./worktree-containment.js";import{concludeAbsentManagedWorktreeAsync as F}from"./worktree-mutation-async.js";import{parseStatusPorcelain as G,planLandIntoCheckout as I}from"./worktree-landing.js";import{WORKTREE_LOCK_WAIT_MS as T,checkoutPathForBranchInList as N,missingWorktreeRecoveryHint as j,persistClosedWorktreeState as A,samePath as K,worktreeLockPathForCommonDir as z,WorktreeError as h}from"./worktree.js";import{shellQuote as E}from"../shared/shell-quote.js";function w(t){return(t.stderr.trim()||t.stdout.trim()).trim()}c(w,"detailOf");async function u(t,r,e,o){const a=await i(r,t);if(a.status!==0)throw new h(e,`git ${r.join(" ")} failed`,o,w(a));return a.stdout.trim()}c(u,"runGit");async function H(t){const r=await u(t,["rev-parse","--git-common-dir"],"git_common_dir_failed","Inspect the repository git metadata, then retry.");return R(q(t,r))}c(H,"commonGitDir");async function Q(t,r){const e=`refs/heads/${r}`,o=await i(["show-ref","--verify","--quiet",e],t);if(o.status===1&&o.executionFailed!==!0)throw new h("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(o.status!==0){const a=o.processError===void 0?"":`
|
|
2
2
|
process error: ${o.processError}`;throw new h("base_branch_inspection_failed",`could not inspect local base branch '${r}' (git show-ref exited with status ${o.status})`,"Inspect the repository and its Git metadata, then retry.",`status: ${o.status}
|
|
3
3
|
stderr: ${o.stderr.trim()||"<empty>"}${a}`)}return u(t,["rev-parse","--verify",e],"base_branch_resolve_failed","Inspect the local base branch, then retry.")}c(Q,"resolveLandableBase");async function J(t){for(const r of["rebase-merge","rebase-apply"]){const e=await u(t,["rev-parse","--git-path",r],"git_path_failed","Inspect the worktree manually, then retry.");if($(e))return!0}return!1}c(J,"rebaseInProgress");async function L(t,r,e){const o=await i(["worktree","list","--porcelain"],t);if(o.status!==0)return!1;let a=null;for(const n of o.stdout.split(`
|
|
4
|
-
`))if(n.startsWith("worktree "))a=n.slice(9).trim();else if(a!==null&&K(a,r)&&n===`branch refs/heads/${e}`)return!0;return!1}c(L,"registeredWorktree");function D(t){return{worktree_removed:!1,worktree_remove_error:`cleanup pending: the caller checkout at ${t.path} remains intact. After its node exits, run \`git -C ${E(t.repo_root)} worktree remove ${E(t.path)}\` after confirming it is safe to delete.`,branch_deleted:!1,branch_delete_error:`cleanup pending: local branch ${t.branch} remains checked out at ${t.path}; delete it only after that checkout is removed and its landed commit is still contained in ${t.base_ref}.`}}c(D,"deferredCleanupResult");function U(t,r){const e=v(t)?.managed_worktree;e==null||e.state!=="open"||M(t,{at:new Date().toISOString(),blocked:r})}c(U,"recordBlockedLandIntent");async function W(t,r){const e=await i(["rev-parse","--verify","--quiet","refs/stash"],t);e.status===0&&e.stdout.trim()===r&&await i(["stash","drop"],t)}c(W,"dropStashIfStillTip");async function V(t,r,e,o){const a=await i(["status","--porcelain"],t);if(a.status!==0)return{ok:!1,detail:
|
|
5
|
-
`).map(_=>_.trim()).filter(_=>_!==""),k=I(G(a.stdout),f);if(k.kind==="refuse")return{ok:!1,detail:`untracked files in ${t} would be overwritten by the incoming commits: ${k.collisions.join(", ")}`};const
|
|
6
|
-
${s}`}}c(V,"landIntoBaseCheckout");async function S(t){const r=v(t);if(r===null)throw new h("unknown_node",`unknown node: ${t}`,"Run this from a live node, or pass a real node id once that command supports it.");const e=r?.managed_worktree?.state==="open"?r.managed_worktree:null;if(e===null)throw new h("no_managed_worktree",`node ${t} has no open managed worktree`,"Nothing to close for this node.");if(!$(e.path))throw new h("worktree_missing",`managed worktree path is missing: ${e.path}`,j(e));if(await J(e.path))throw new h("rebase_in_progress","this managed worktree is mid-rebase",`Resolve conflicts in ${e.path}, run \`git rebase --continue\` there, then rerun \`crtr node worktree close\`.`);if(await u(e.path,["status","--porcelain"],"status_failed","Inspect the worktree manually, then retry.")!=="")throw new h("dirty_worktree","managed worktree has uncommitted changes",`Commit the work in ${e.path}, then rerun \`crtr node worktree close\`.`);const a=await u(e.path,["rev-parse","--abbrev-ref","HEAD"],"branch_check_failed","Inspect the worktree manually, then retry."),n=await u(e.path,["rev-parse","HEAD"],"landed_sha_failed","Inspect the worktree checkout manually, then rerun `crtr node worktree close`.");if(a!==e.branch){if((await i(["show-ref","--verify","--quiet",`refs/heads/${e.branch}`],e.path)).status===0||a==="HEAD"||!await L(e.repo_root,e.path,a))throw new h("wrong_branch",`managed worktree is not on its recorded branch (expected ${e.branch}, found ${a==="HEAD"?"detached HEAD":a})`,`Inspect ${e.path}, then rerun \`crtr node worktree close\`.`);if(await x(e.path,e,n)===null)throw new h("branch_moved_unlanded",`managed worktree's recorded branch ${e.branch} no longer exists; its checkout is now on ${a} at ${n}, which carries content local base branch '${e.base_ref}' does not yet contain`,`Land or push ${a} through its own workflow before closing.`);const d=await H(e.path);if(!await L(e.repo_root,e.path,a)||await u(e.path,["rev-parse","--abbrev-ref","HEAD"],"branch_check_failed","Inspect the worktree manually, then retry.")!==a||await u(e.path,["rev-parse","HEAD"],"branch_check_failed","Inspect the worktree manually, then retry.")!==n)throw new h("wrong_branch",`managed worktree at ${e.path} changed while closing`,`Inspect ${e.path}, then rerun \`crtr node worktree close\`.`);return B(t,{observed_branch:a,observed_sha:n,common_dir:d,authorized:new Date().toISOString()}),A(t,e,"pending"),{node_id:t,branch:a,worktree_path:e.path,landed_sha:n,...D(e),branch_delete_error:`${a} is not a crtr-managed branch and will never be deleted automatically; it is preserved once the checkout above is removed.`}}if(await x(e.path,e,n)!==null)return A(t,e,"pending"),{node_id:t,branch:e.branch,worktree_path:e.path,landed_sha:n,...D(e)};let f;try{f=await Q(e.path,e.base_ref)}catch(s){if(!(s instanceof h)||s.code!=="missing_base_branch"||n!==e.base_sha)throw s;return A(t,e,"pending"),{node_id:t,branch:e.branch,worktree_path:e.path,landed_sha:e.base_sha,...D(e)}}const k=await i(["rebase",f],e.path);if(k.status!==0)throw new h("rebase_failed",`rebase onto local base branch '${e.base_ref}' did not complete`,`Resolve conflicts in ${e.path}, run \`git rebase --continue\` there, then rerun \`crtr node worktree close\`.`,
|
|
4
|
+
`))if(n.startsWith("worktree "))a=n.slice(9).trim();else if(a!==null&&K(a,r)&&n===`branch refs/heads/${e}`)return!0;return!1}c(L,"registeredWorktree");function D(t){return{worktree_removed:!1,worktree_remove_error:`cleanup pending: the caller checkout at ${t.path} remains intact. After its node exits, run \`git -C ${E(t.repo_root)} worktree remove ${E(t.path)}\` after confirming it is safe to delete.`,branch_deleted:!1,branch_delete_error:`cleanup pending: local branch ${t.branch} remains checked out at ${t.path}; delete it only after that checkout is removed and its landed commit is still contained in ${t.base_ref}.`}}c(D,"deferredCleanupResult");async function U(t,r){const e=(await v(t))?.managed_worktree;e==null||e.state!=="open"||await M(t,{at:new Date().toISOString(),blocked:r})}c(U,"recordBlockedLandIntent");async function W(t,r){const e=await i(["rev-parse","--verify","--quiet","refs/stash"],t);e.status===0&&e.stdout.trim()===r&&await i(["stash","drop"],t)}c(W,"dropStashIfStillTip");async function V(t,r,e,o){const a=await i(["status","--porcelain"],t);if(a.status!==0)return{ok:!1,detail:w(a)};const n=await i(["diff","--name-only",e,o],t);if(n.status!==0)return{ok:!1,detail:w(n)};const f=n.stdout.split(`
|
|
5
|
+
`).map(_=>_.trim()).filter(_=>_!==""),k=I(G(a.stdout),f);if(k.kind==="refuse")return{ok:!1,detail:`untracked files in ${t} would be overwritten by the incoming commits: ${k.collisions.join(", ")}`};const p=c(async()=>{const _=await i(["merge","--ff-only",o],t);return _.status===0?{ok:!0}:{ok:!1,detail:w(_)}},"merge");if(k.kind==="direct")return p();const b=await i(["rev-parse","--verify","--quiet","refs/stash"],t),g=b.status===0?b.stdout.trim():null,y=await i(["stash","push","--message",`crtr landing ${r}`],t);if(y.status!==0)return{ok:!1,detail:w(y)};const m=await i(["rev-parse","--verify","--quiet","refs/stash"],t),l=m.status===0?m.stdout.trim():null;if(l===null||l===g)return p();const s=`local changes from ${t} are retained in stash ${l}; recover them with \`git -C ${E(t)} stash apply ${l}\` and resolve any conflict.`,d=await p();return d.ok?(await i(["stash","apply",l],t)).status===0?(await W(t,l),{ok:!0}):(await i(["reset","--hard",o],t),{ok:!0,stash:`the shared base checkout was reset to landed commit ${o} because local changes conflicted with it. ${s}`}):(await i(["stash","apply",l],t)).status===0?(await W(t,l),d):{ok:!1,detail:`${d.detail}
|
|
6
|
+
${s}`}}c(V,"landIntoBaseCheckout");async function S(t){const r=await v(t);if(r===null)throw new h("unknown_node",`unknown node: ${t}`,"Run this from a live node, or pass a real node id once that command supports it.");const e=r?.managed_worktree?.state==="open"?r.managed_worktree:null;if(e===null)throw new h("no_managed_worktree",`node ${t} has no open managed worktree`,"Nothing to close for this node.");if(!$(e.path))throw new h("worktree_missing",`managed worktree path is missing: ${e.path}`,j(e));if(await J(e.path))throw new h("rebase_in_progress","this managed worktree is mid-rebase",`Resolve conflicts in ${e.path}, run \`git rebase --continue\` there, then rerun \`crtr node worktree close\`.`);if(await u(e.path,["status","--porcelain"],"status_failed","Inspect the worktree manually, then retry.")!=="")throw new h("dirty_worktree","managed worktree has uncommitted changes",`Commit the work in ${e.path}, then rerun \`crtr node worktree close\`.`);const a=await u(e.path,["rev-parse","--abbrev-ref","HEAD"],"branch_check_failed","Inspect the worktree manually, then retry."),n=await u(e.path,["rev-parse","HEAD"],"landed_sha_failed","Inspect the worktree checkout manually, then rerun `crtr node worktree close`.");if(a!==e.branch){if((await i(["show-ref","--verify","--quiet",`refs/heads/${e.branch}`],e.path)).status===0||a==="HEAD"||!await L(e.repo_root,e.path,a))throw new h("wrong_branch",`managed worktree is not on its recorded branch (expected ${e.branch}, found ${a==="HEAD"?"detached HEAD":a})`,`Inspect ${e.path}, then rerun \`crtr node worktree close\`.`);if(await x(e.path,e,n)===null)throw new h("branch_moved_unlanded",`managed worktree's recorded branch ${e.branch} no longer exists; its checkout is now on ${a} at ${n}, which carries content local base branch '${e.base_ref}' does not yet contain`,`Land or push ${a} through its own workflow before closing.`);const d=await H(e.path);if(!await L(e.repo_root,e.path,a)||await u(e.path,["rev-parse","--abbrev-ref","HEAD"],"branch_check_failed","Inspect the worktree manually, then retry.")!==a||await u(e.path,["rev-parse","HEAD"],"branch_check_failed","Inspect the worktree manually, then retry.")!==n)throw new h("wrong_branch",`managed worktree at ${e.path} changed while closing`,`Inspect ${e.path}, then rerun \`crtr node worktree close\`.`);return await B(t,{observed_branch:a,observed_sha:n,common_dir:d,authorized:new Date().toISOString()}),await A(t,e,"pending"),{node_id:t,branch:a,worktree_path:e.path,landed_sha:n,...D(e),branch_delete_error:`${a} is not a crtr-managed branch and will never be deleted automatically; it is preserved once the checkout above is removed.`}}if(await x(e.path,e,n)!==null)return await A(t,e,"pending"),{node_id:t,branch:e.branch,worktree_path:e.path,landed_sha:n,...D(e)};let f;try{f=await Q(e.path,e.base_ref)}catch(s){if(!(s instanceof h)||s.code!=="missing_base_branch"||n!==e.base_sha)throw s;return await A(t,e,"pending"),{node_id:t,branch:e.branch,worktree_path:e.path,landed_sha:e.base_sha,...D(e)}}const k=await i(["rebase",f],e.path);if(k.status!==0)throw new h("rebase_failed",`rebase onto local base branch '${e.base_ref}' did not complete`,`Resolve conflicts in ${e.path}, run \`git rebase --continue\` there, then rerun \`crtr node worktree close\`.`,w(k));const p=await u(e.path,["rev-parse","HEAD"],"landed_sha_failed","Inspect the worktree checkout manually, then rerun `crtr node worktree close`."),b=c(async(s,d,_)=>(await U(t,s),new h("land_base_failed",s,d,_)),"blocked"),g=await i(["merge-base","--is-ancestor",f,p],e.path);if(g.status!==0)throw await b(`rebased worktree is not a fast-forward of local base branch '${e.base_ref}'`,"Ask the user how to land this managed worktree.",w(g));const y=await u(e.path,["worktree","list","--porcelain"],"worktree_list_failed","Inspect the repository worktrees manually, then retry."),m=N(y,e.base_ref);let l;if(m!==null){const s=await i(["rev-parse","HEAD"],m);if(s.status!==0||s.stdout.trim()!==f)throw await b(`local base branch '${e.base_ref}' changed while this worktree was closing`,`Reconcile the base checkout at ${m}, then rerun \`crtr node worktree close\`.`,s.status!==0?w(s):`expected ${f}, found ${s.stdout.trim()}`);const d=await V(m,e.branch,f,p);if(!d.ok)throw await b(`could not fast-forward local base branch '${e.base_ref}' to this worktree`,`Local base branch '${e.base_ref}' is checked out at ${m} in a state that blocks a fast-forward.`,d.detail);l=d.stash}else{const s=await i(["update-ref",`refs/heads/${e.base_ref}`,p,f],e.path);if(s.status!==0)throw await b(`could not fast-forward local base branch '${e.base_ref}' to this worktree`,"Ask the user how to land this managed worktree.",w(s))}return await A(t,e,"pending"),{node_id:t,branch:e.branch,worktree_path:e.path,landed_sha:p,...D(e),...l===void 0?{}:{base_checkout_stash:l}}}c(S,"closeLocked");async function ie(t){const r=(await v(t))?.managed_worktree;if(r==null||r.state!=="open")return S(t);if(!$(r.path)){const n=await F(t);if(n!==null)return{node_id:t,branch:n.dropped.branch,worktree_path:n.dropped.worktree_path,landed_sha:n.landedSha,worktree_removed:!0,branch_deleted:n.dropped.branch_deleted,...n.dropped.branch_delete_error===void 0?{}:{branch_delete_error:n.dropped.branch_delete_error}}}const e=(await v(t))?.managed_worktree;if(e==null||e.state!=="open")return S(t);const o=$(e.path)?e.path:e.repo_root,a=await H(o);return O(z(a),()=>S(t),{timeoutMs:Math.min(T,25e3),timeoutError:c(()=>new h("worktree_lock_timeout",`timed out waiting to create a managed worktree in ${a}`,"Wait for the other managed-worktree operation to finish, then retry."),"timeoutError")})}c(ie,"closeManagedWorktreeAsync");export{ie as closeManagedWorktreeAsync};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
var P=Object.defineProperty;var o=(e,r)=>P(e,"name",{value:r,configurable:!0});import{existsSync as p,mkdirSync as H,readFileSync as R,realpathSync as O,rmSync as B,writeFileSync as q}from"node:fs";import{dirname as N,join as j,resolve as G}from"node:path";import{abandonWorktreeAndRepoint as I,getNode as
|
|
2
|
-
stderr: ${n.stderr.trim()||"<empty>"}`);return h(e,["rev-parse","--verify",a],"base_branch_resolve_failed","Inspect the local base branch, then retry.")}o($,"resolveLandableBase");function re(e,r){try{const a=j(r,"info","exclude");H(N(a),{recursive:!0});let n="";try{n=R(a,"utf8")}catch{}const t=[`/${x}/${z}`,`/${x}/${J}`];if(t.every(
|
|
3
|
-
`).map(l=>l.trim()).includes(
|
|
1
|
+
var P=Object.defineProperty;var o=(e,r)=>P(e,"name",{value:r,configurable:!0});import{existsSync as p,mkdirSync as H,readFileSync as R,realpathSync as O,rmSync as B,writeFileSync as q}from"node:fs";import{dirname as N,join as j,resolve as G}from"node:path";import{abandonWorktreeAndRepoint as I,getNode as m}from"./canvas/index.js";import{isPidAlive as K}from"./canvas/pid.js";import{CONFIG_FILE as z,CRTR_DIR_NAME as x,STATE_FILE as J}from"../types.js";import{withExclusiveDirectoryLockAsync as S}from"./exclusive-lock.js";import{gitAsync as i}from"./git.js";import{WORKTREE_LOCK_WAIT_MS as Q,checkoutPathForBranchInList as U,isManagedWorktreeBase as V,managedWorktreePath as X,persistClosedWorktreeState as _,worktreeLockPathForCommonDir as D,WorktreeError as c}from"./worktree.js";import{proveBranchContained as Y}from"./worktree-containment.js";import{refDeleteTransactionStdin as Z}from"./worktree-landing.js";import{deleteTrashAsync as ee,removeWorktreeCheckoutAsync as te}from"./worktree-remove.js";const E=Math.min(Q,25e3);function v(e){return(e.stderr.trim()||e.stdout.trim()).trim()}o(v,"detailOf");async function h(e,r,a,n){const t=await i(r,e);if(t.status!==0)throw new c(a,`git ${r.join(" ")} failed`,n,v(t));return t.stdout.trim()}o(h,"runGit");async function W(e){return O(G(e,await h(e,["rev-parse","--git-common-dir"],"git_common_dir_failed","Inspect the repository git metadata, then retry.")))}o(W,"commonGitDir");async function k(e,r){const a=await W(e);return S(D(a),r,{timeoutMs:E,timeoutError:o(()=>new c("worktree_lock_timeout",`timed out waiting to create a managed worktree in ${a}`,"Wait for the other managed-worktree operation to finish, then retry."),"timeoutError")})}o(k,"withRepositoryLock");async function $(e,r){const a=`refs/heads/${r}`,n=await i(["show-ref","--verify","--quiet",a],e);if(n.status===1&&n.executionFailed!==!0)throw new c("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)throw new c("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}
|
|
2
|
+
stderr: ${n.stderr.trim()||"<empty>"}`);return h(e,["rev-parse","--verify",a],"base_branch_resolve_failed","Inspect the local base branch, then retry.")}o($,"resolveLandableBase");function re(e,r){try{const a=j(r,"info","exclude");H(N(a),{recursive:!0});let n="";try{n=R(a,"utf8")}catch{}const t=[`/${x}/${z}`,`/${x}/${J}`];if(t.every(s=>n.split(`
|
|
3
|
+
`).map(l=>l.trim()).includes(s)))return;q(a,`${n}${n!==""&&!n.endsWith(`
|
|
4
4
|
`)?`
|
|
5
5
|
`:""}# crtr: exclude crtr's own untracked project-scope bookkeeping (auto-added at managed-worktree creation)
|
|
6
|
-
${t.filter(
|
|
7
|
-
`).map(l=>l.trim()).includes(
|
|
6
|
+
${t.filter(s=>!n.split(`
|
|
7
|
+
`).map(l=>l.trim()).includes(s)).join(`
|
|
8
8
|
`)}
|
|
9
|
-
`)}catch{}}o(re,"seedExclude");async function ye(e){await k(e.repo_root,async()=>{const r=await
|
|
10
|
-
`).some(n=>n.trim()===`branch refs/heads/${e.branch}`)){if((await
|
|
9
|
+
`)}catch{}}o(re,"seedExclude");async function ye(e){await k(e.repo_root,async()=>{const r=await i(["rev-parse","--verify",`refs/heads/${e.branch}`],e.repo_root);if(r.status!==0||r.stdout.trim()!==e.base_sha)return;const a=await i(["worktree","list","--porcelain"],e.repo_root);if(a.status===0){if(a.stdout.split(`
|
|
10
|
+
`).some(n=>n.trim()===`branch refs/heads/${e.branch}`)){if((await i(["worktree","remove","--force",e.path],e.repo_root)).status!==0)return}else if(p(e.path))try{B(e.path,{recursive:!0,force:!0})}catch{return}await i(["update-ref","-d",`refs/heads/${e.branch}`,e.base_sha],e.repo_root)}})}o(ye,"rollbackManagedWorktreeAsync");async function ge(e,r,a="main"){const n=await h(e,["rev-parse","--show-toplevel"],"not_git_repo","Pass --cwd <real repo> pointing inside a git repository.");if(V(n))throw new c("managed_worktree_base",`cwd ${n} is a managed worktree and cannot be used as a managed worktree base`,"Pass `--cwd` pointing at the repository\u2019s primary checkout and keep `--worktree` set to the desired existing local base branch, including the parent branch.");const t=await W(n);return S(D(t),async()=>{const s=await $(n,a),l=X(r),u=`crtr/${r}`;if(p(l))throw new c("worktree_path_exists",`managed worktree path already exists: ${l}`,"Remove the stale path or choose a fresh node id.");if((await i(["show-ref","--verify","--quiet",`refs/heads/${u}`],n)).status===0)throw new c("worktree_branch_exists",`managed worktree branch already exists: ${u}`,"Remove the stale branch or choose a fresh node id.");const b={state:"open",path:l,branch:u,repo_root:n,base_ref:a,base_sha:s,created:new Date().toISOString()};await h(n,["branch",u,s],"worktree_branch_create_failed","Inspect the git error, fix the repository/worktree state, then retry spawning with --worktree.");const f=await i(["worktree","add",l,u],n);if(f.status!==0)throw await i(["update-ref","-d",`refs/heads/${u}`,s],n),new c("worktree_add_failed","git worktree add failed","Inspect the git error, fix the repository/worktree state, then retry spawning with --worktree.",v(f));return re(n,t),b},{timeoutMs:E,timeoutError:o(()=>new c("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")})}o(ge,"createManagedWorktreeAsync");async function M(e){if(e.state!=="open"||!p(e.path))return null;const r=await i(["rev-parse","--abbrev-ref","HEAD"],e.path),a=await i(["status","--porcelain"],e.path),n=await i(["rev-parse","HEAD"],e.path);if(r.status!==0||r.stdout.trim()!==e.branch||a.status!==0||a.stdout.trim()!==""||n.status!==0)return null;const t=await i(["rev-parse","--git-path","rebase-merge"],e.path);return t.status!==0||p(t.stdout.trim())?null:n.stdout.trim()}o(M,"cleanTip");async function C(e,r){try{const a=await $(e.path,e.base_ref);return(await i(["merge-base","--is-ancestor",r,a],e.path)).status===0}catch(a){if(a instanceof c&&a.code==="missing_base_branch"&&r===e.base_sha)return!0;throw a}}o(C,"containedInLocalBase");function ae(e){return{node_id:"",branch:e.branch,worktree_path:e.path,worktree_removed:!1,worktree_remove_error:`cleanup pending: the caller checkout at ${e.path} remains intact.`,branch_deleted:!1,branch_delete_error:`cleanup pending: local branch ${e.branch} remains checked out at ${e.path}.`}}o(ae,"deferred");async function L(e){if(e.state!=="open"||p(e.path))return null;const r=`refs/heads/${e.branch}`,a=await i(["show-ref","--verify","--quiet",r],e.repo_root);if(a.status===1&&a.executionFailed!==!0)return{branchSha:null};if(a.status!==0)return null;const n=await i(["rev-parse","--verify",r],e.repo_root);if(n.status!==0)return null;const t=n.stdout.trim(),s=await i(["worktree","list","--porcelain"],e.repo_root);if(s.status!==0||U(s.stdout,e.branch)!==null)return null;const l=await Y(e.repo_root,e,t);return l===null?null:{branchSha:t,containment:l}}o(L,"proveAbsentPathManagedWorktree");async function ne(e,r,a){return p(r.path)?null:a.branchSha===null?(await _(e,r,"complete"),{node_id:e,branch:r.branch,worktree_path:r.path,worktree_removed:!0,branch_deleted:!0}):a.containment===void 0?null:(await _(e,r,"complete"),{node_id:e,branch:r.branch,worktree_path:r.path,worktree_removed:!0,branch_deleted:!1,branch_delete_error:`local branch ${r.branch} is delivered but retained because its checkout status can change outside crtr's repository lock.`})}o(ne,"autoDropAbsentPathManagedWorktreeLocked");async function oe(e){const r=(await m(e))?.managed_worktree;return r==null||r.state!=="open"||p(r.path)||await L(r)===null?null:k(r.repo_root,async()=>{const a=(await m(e))?.managed_worktree;if(a==null||a.state!=="open")return null;const n=await L(a);if(n===null)return null;const t=await ne(e,a,n);return t===null?null:{dropped:t,landedSha:n.branchSha??a.base_sha}})}o(oe,"concludeAbsentManagedWorktreeAsync");async function ve(e){const r=(await m(e))?.managed_worktree;if(r==null||r.state!=="open")return null;if(!p(r.path))return(await oe(e))?.dropped??null;const a=await M(r);return a===null||!await C(r,a)?null:k(r.path,async()=>{const n=(await m(e))?.managed_worktree;if(n==null||n.state!=="open")return null;const t=await M(n);return t===null||t!==a||!await C(n,t)?null:(await _(e,n,"pending"),{...ae(n),node_id:e})})}o(ve,"autoDropCleanManagedWorktreeAsync");async function T(e){for(const r of["rebase-merge","rebase-apply"]){const a=await i(["rev-parse","--git-path",r],e);if(a.status!==0||p(a.stdout.trim()))return!0}return!1}o(T,"rebaseInProgress");async function y(e,r,a,n,t,s=r.branch){await I(e,{cwd:r.repo_root,abandoned:{branch:s,tip_sha:a,at:n,by:t}})}o(y,"persistAbandoned");async function $e(e,r){const a=(await m(e))?.managed_worktree;if(a==null||a.state!=="open")throw new c("no_managed_worktree",`node ${e} has no open managed worktree`,"Nothing to abandon for this node.");const n=[];try{return await k(a.path,()=>ie(e,r,n))}finally{await ee(a.path,n[0])}}o($e,"abandonManagedWorktreeAsync");async function g(e,r){const{result:a,trash:n}=await te(e.repo_root,e.path);if(n!==void 0&&r.push(n),a.status!==0)throw new c("worktree_remove_failed",`git worktree remove ${e.path} failed`,"Inspect the worktree manually, then retry.",v(a))}o(g,"removeCheckout");async function ie(e,r,a){const n=await m(e),t=n?.managed_worktree;if(n===null||t===void 0||t===null||t.state!=="open")throw new c("no_managed_worktree",`node ${e} has no open managed worktree`,"Nothing to abandon for this node.");if(n.status==="active"||n.status==="idle"||K(n.pi_pid))throw new c("node_running",`node ${e} is still running`,"Abandon requires a stopped node with no live broker process. From the running owner, use `crtr node worktree close` to land locally, or make the checkout clean, push its current tip to origin, and rerun `crtr push final`.");if(!p(t.path))throw new c("worktree_missing",`managed worktree path is missing: ${t.path}`,"Inspect the branch and worktree registration, then retry.");const s=await h(t.path,["rev-parse","--abbrev-ref","HEAD"],"branch_check_failed","Inspect the worktree manually, then retry."),l=await i(["show-ref","--verify","--quiet",`refs/heads/${t.branch}`],t.path);if(s!==t.branch){if(l.status===0||s==="HEAD")throw new c("wrong_branch",`managed worktree is not on its recorded branch (expected ${t.branch}, found ${s==="HEAD"?"detached HEAD":s})`,`Inspect ${t.path}, then rerun \`crtr node worktree abandon\`.`);if(await T(t.path)||await h(t.path,["status","--porcelain"],"status_failed","Inspect the worktree manually, then retry.")!=="")throw new c("dirty_worktree","managed worktree has uncommitted changes",`Commit or stash them in ${t.path}, then rerun \`crtr node worktree abandon\`.`);const d=await h(t.path,["rev-parse","HEAD"],"abandon_tip_failed","Inspect the worktree manually, then retry.");await g(t,a);const w=new Date().toISOString();return await y(e,t,d,w,r,s),{node_id:e,branch:s,tip_sha:d,worktree_path:t.path,branch_deleted:!1}}const u=await h(t.path,["rev-parse","HEAD"],"abandon_tip_failed","Inspect the branch manually, then retry.");let b=null;try{const d=await $(t.path,t.base_ref);(await i(["merge-base","--is-ancestor",u,d],t.path)).status===0&&(b=d)}catch(d){if(!(d instanceof c)||d.code!=="missing_base_branch")throw d}const f=new Date().toISOString(),F=await h(t.path,["status","--porcelain"],"status_failed","Inspect the worktree manually, then retry.");if(b!==null&&u===t.base_sha){const d=await h(t.repo_root,["rev-parse",`${u}^{tree}`],"abandon_tree_failed","Inspect the branch manually, then retry."),w=await h(t.repo_root,["-c","user.name=crtr-abandon","-c","user.email=crtr-abandon@localhost","commit-tree",d,"-p",u,"-m","crtr-abandon","-m",`Crtr-Abandon: ${e} ${f}`],"abandon_commit_failed","Inspect the branch manually, then retry.");return await h(t.repo_root,["update-ref",`refs/heads/${t.branch}`,w,u],"abandon_marker_failed","The branch changed while abandon was starting; inspect the worktree, then retry."),await g(t,a),(await i(["update-ref","--stdin"],t.repo_root,Z(t.branch,w,`refs/heads/${t.base_ref}`,b))).status===0?(await _(e,t,"complete"),{node_id:e,branch:t.branch,tip_sha:w,worktree_path:t.path,branch_deleted:!0}):(await y(e,t,w,f,r),{node_id:e,branch:t.branch,tip_sha:w,worktree_path:t.path,branch_deleted:!1})}if(!await T(t.path)&&F==="")return await g(t,a),await y(e,t,u,f,r),{node_id:e,branch:t.branch,tip_sha:u,worktree_path:t.path,branch_deleted:!1};await h(t.path,["add","--all"],"abandon_stage_failed","Inspect the worktree manually, then retry."),await h(t.path,["-c","user.name=crtr-abandon","-c","user.email=crtr-abandon@localhost","commit","--allow-empty","-m","crtr-abandon","-m",`Crtr-Abandon: ${e} ${f}`],"abandon_commit_failed","Inspect the worktree manually, then retry.");const A=await h(t.path,["rev-parse","HEAD"],"abandon_tip_failed","Inspect the branch manually, then retry.");return await g(t,a),await y(e,t,A,f,r),{node_id:e,branch:t.branch,tip_sha:A,worktree_path:t.path,branch_deleted:!1}}o(ie,"abandonLocked");export{$e as abandonManagedWorktreeAsync,ve as autoDropCleanManagedWorktreeAsync,oe as concludeAbsentManagedWorktreeAsync,ge as createManagedWorktreeAsync,ye as rollbackManagedWorktreeAsync};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var s=Object.defineProperty;var o=(a,
|
|
1
|
+
var s=Object.defineProperty;var o=(a,e)=>s(a,"name",{value:e,configurable:!0});import{directorySizeBytes as r}from"./disk-usage.js";import{getNode as n,listNodes as i}from"./canvas/index.js";async function l(){const a=[];for(const e of await i()){const t=(await n(e.node_id))?.managed_worktree;t?.sweep?.quarantined===!0&&a.push({node_id:e.node_id,path:t.path,branch:t.branch,repo_root:t.repo_root,reason:t.sweep.reason,...t.sweep.detail===void 0?{}:{detail:t.sweep.detail},attempts:t.sweep.attempts,last_attempt:t.sweep.last_attempt})}return a.sort((e,t)=>e.last_attempt.localeCompare(t.last_attempt)),Promise.all(a.map(async e=>({...e,size_bytes:await r(e.path)})))}o(l,"listQuarantinedManagedWorktrees");export{l as listQuarantinedManagedWorktrees};
|
|
@@ -40,7 +40,7 @@ export interface ReconcileGuard {
|
|
|
40
40
|
* every destructive step re-asks, and a false answer stops the pass where it
|
|
41
41
|
* stands, leaving the record incomplete for a later pass to resume. The
|
|
42
42
|
* implementation must not spawn a subprocess: this runs inside crtrd. */
|
|
43
|
-
stillEligible: () => boolean
|
|
43
|
+
stillEligible: () => Promise<boolean>;
|
|
44
44
|
}
|
|
45
45
|
/** Dispose of one node's managed worktree, or explain why it must survive.
|
|
46
46
|
*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
var q=Object.defineProperty;var d=(e
|
|
2
|
-
`))if(
|
|
3
|
-
`))if(s.startsWith("worktree "))a=s.slice(9).trim();else if(a!==null&&s===`branch refs/heads/${r}`&&W(a,
|
|
4
|
-
${u.stdout}`).digest("hex");return{base:a,upstream:s?.sha??null,branch:n,checkout:o}}d(
|
|
5
|
-
`).map(p=>p.trim()).filter(p=>p!==""),o=G(j(n.stdout),u);if(o.kind==="refuse")return{ok:!1,detail:`untracked files in ${
|
|
6
|
-
${k}`}}d(
|
|
1
|
+
var q=Object.defineProperty;var d=(t,e)=>q(t,"name",{value:e,configurable:!0});import{createHash as z}from"node:crypto";import{existsSync as y,realpathSync as K}from"node:fs";import{resolve as N}from"node:path";import{completeCleanup as U,getNode as v,recordSweepAttempt as C}from"./canvas/index.js";import{withExclusiveDirectoryLockAsync as Q}from"./exclusive-lock.js";import{gitAsync as c}from"./git.js";import{proveBranchContained as A,upstreamTip as V}from"./worktree-containment.js";import{parseStatusPorcelain as j,planLandIntoCheckout as G,refDeleteTransactionStdin as I}from"./worktree-landing.js";import{shellQuote as J}from"../shared/shell-quote.js";import{deleteTrashAsync as X,removeWorktreeCheckoutAsync as R}from"./worktree-remove.js";import{WORKTREE_LOCK_WAIT_MS as Y,checkoutPathForBranchInList as B,samePath as W,worktreeLockPathForCommonDir as Z}from"./worktree.js";const E=[2,5,15,30,60],tt=E.length;function D(t){return t==null||t.state==="abandoned"?!1:t.state==="open"||t.cleanup!=="complete"}d(D,"isReconcilable");function vt(t,e){const r=t.sweep?.next_attempt;if(r===void 0)return!0;const a=Date.parse(r);return Number.isNaN(a)||a<=e}d(vt,"isDueForSweep");async function m(t,e){const r=await c(["rev-parse","--verify","--quiet",e],t);return r.status===0?r.stdout.trim():null}d(m,"revParseRef");function h(t){return(t.stderr.trim()||t.stdout.trim()).trim()}d(h,"detailOf");async function L(t){const e=await c(["rev-parse","--git-common-dir"],t);if(e.status!==0)return null;try{return K(N(t,e.stdout.trim()))}catch{return null}}d(L,"commonGitDirAsync");async function et(t){for(const e of["rebase-merge","rebase-apply"]){const r=await c(["rev-parse","--git-path",e],t);if(r.status!==0)return null;if(y(N(t,r.stdout.trim())))return!0}return!1}d(et,"isRebaseInProgressAsync");function at(t){for(const e of t.split(`
|
|
2
|
+
`))if(e.startsWith("worktree "))return e.slice(9).trim();return null}d(at,"mainWorktreePath");function rt(t,e,r){let a=null;for(const s of t.split(`
|
|
3
|
+
`))if(s.startsWith("worktree "))a=s.slice(9).trim();else if(a!==null&&s===`branch refs/heads/${r}`&&W(a,e))return a;return null}d(rt,"registeredCheckoutPath");async function st(t){const e=y(t.path),r=e?t.path:t.repo_root,a=await m(r,`refs/heads/${t.base_ref}`),s=await V(r,t.base_ref),n=await m(r,`refs/heads/${t.branch}`);if(!e)return{base:a,upstream:s?.sha??null,branch:n,checkout:"absent"};const i=await c(["rev-parse","HEAD"],t.path),u=await c(["status","--porcelain"],t.path),o=i.status!==0||u.status!==0?null:z("sha256").update(`${i.stdout.trim()}
|
|
4
|
+
${u.stdout}`).digest("hex");return{base:a,upstream:s?.sha??null,branch:n,checkout:o}}d(st,"observe");function nt(t,e){return t.checkout===null||e.checkout===null?!1:t.base===e.base&&t.upstream===e.upstream&&t.branch===e.branch&&t.checkout===e.checkout}d(nt,"sameObservation");async function it(t,e,r,a,s,n){if(r.status!=="refused"&&r.status!=="failed"||!await n.stillEligible())return;const i=(e.sweep?.attempts??0)+1,u=E[Math.min(i,E.length)-1]??E[0],o=(await v(t))?.managed_worktree;o==null||!D(o)||await C(t,{reason:r.reason,...r.detail===void 0?{}:{detail:r.detail},observed:a,attempts:i,lastAttemptAt:new Date(s).toISOString(),nextAttemptAt:new Date(s+u*6e4).toISOString(),quarantined:i>=tt})}d(it,"recordUnfinished");async function ot(t,e,r,a,s){const n=await c(["status","--porcelain"],t);if(n.status!==0)return{ok:!1,detail:h(n)};const i=await c(["diff","--name-only",r,a],t);if(i.status!==0)return{ok:!1,detail:h(i)};const u=i.stdout.split(`
|
|
5
|
+
`).map(p=>p.trim()).filter(p=>p!==""),o=G(j(n.stdout),u);if(o.kind==="refuse")return{ok:!1,detail:`untracked files in ${t} would be overwritten by the incoming commits: ${o.collisions.join(", ")}`};if(!await s.stillEligible())return{ok:!1,detail:"node is no longer terminal",ineligible:!0};const l=d(async()=>{const p=await c(["merge","--ff-only",a],t);return p.status===0?{ok:!0}:{ok:!1,detail:h(p)}},"merge");if(o.kind==="direct")return l();const b=await m(t,"refs/stash"),w=await c(["stash","push","--message",`crtr landing ${e}`],t);if(w.status!==0)return{ok:!1,detail:h(w)};const f=await m(t,"refs/stash");if(f===null||f===b)return l();const k=`local changes from ${t} are retained in stash ${f}; recover them with \`git -C ${J(t)} stash apply ${f}\` and resolve any conflict.`,_=await l();return _.ok?(await c(["stash","apply",f],t)).status===0?(await M(t,f),{ok:!0}):(await c(["reset","--hard",a],t),{ok:!0,stash:`the shared base checkout was reset to landed commit ${a} because local changes conflicted with it. ${k}`}):(await c(["stash","apply",f],t)).status===0?(await M(t,f),_):{ok:!1,detail:`${_.detail}
|
|
6
|
+
${k}`}}d(ot,"landIntoBaseCheckoutAsync");async function M(t,e){await m(t,"refs/stash")===e&&await c(["stash","drop"],t)}d(M,"dropStashIfStillTip");async function lt(t,e,r){const a=await m(t.path,`refs/heads/${t.base_ref}`);if(a===null)return{ok:!1,detail:`local base branch '${t.base_ref}' does not resolve`};if(!await r.stillEligible())return{ok:!1,detail:"node is no longer terminal",ineligible:!0};const s=await c(["rebase",a],t.path);if(s.status!==0)return await c(["rebase","--abort"],t.path),{ok:!1,detail:h(s)};const n=await m(t.path,"HEAD");if(n===null)return{ok:!1,detail:"could not read the rebased worktree tip"};if((await c(["merge-base","--is-ancestor",a,n],t.path)).status!==0)return{ok:!1,detail:`the rebased branch is not a fast-forward of '${t.base_ref}'`};const i=B(e,t.base_ref);if(i===null){if(!await r.stillEligible())return{ok:!1,detail:"node is no longer terminal",ineligible:!0};const l=await c(["update-ref",`refs/heads/${t.base_ref}`,n,a],t.path);return l.status===0?{ok:!0,landedSha:n}:{ok:!1,detail:h(l)}}const u=await c(["rev-parse","HEAD"],i);if(u.status!==0||u.stdout.trim()!==a)return{ok:!1,detail:`base checkout ${i} is not at ${a}`};const o=await ot(i,t.branch,a,n,r);return o.ok?{ok:!0,landedSha:n,...o.stash===void 0?{}:{stash:o.stash}}:o}d(lt,"finishBlockedLand");const $={status:"skipped",reason:"node_no_longer_terminal"};async function Et(t,e,r=Date.now()){const a=(await v(t))?.managed_worktree;if(!D(a)||a==null)return{status:"skipped",reason:"already_reconciled"};const s=y(a.path)?a.path:a.repo_root;if(!y(s))return await S(t,a,{status:"refused",reason:"repo_unavailable",detail:`neither the recorded checkout nor repository root exists, so ${a.branch} cannot be proved absent`},{base:null,upstream:null,branch:null,checkout:null},r,e);const n=await L(s);if(n===null)return await S(t,a,{status:"failed",reason:"git_dir_unreadable",detail:`could not resolve the git common dir from ${s}`},{base:null,upstream:null,branch:null,checkout:null},r,e);let i={base:null,upstream:null,branch:null,checkout:null},u;const o=[];try{u=await Q(Z(n),async()=>{if(!await e.stillEligible())return $;const l=(await v(t))?.managed_worktree;return!D(l)||l==null?{status:"skipped",reason:"already_reconciled"}:(i=await st(l),l.sweep!==void 0&&nt(l.sweep.observed,i)?{status:"refused",reason:l.sweep.reason,...l.sweep.detail===void 0?{}:{detail:l.sweep.detail},unchanged:!0}:y(l.path)?await ct(t,l,e,o):await ut(t,l,i,e))},{timeoutMs:Y,timeoutError:d(()=>new Error(`timed out waiting for the managed-worktree lock on ${n}`),"timeoutError")})}catch(l){u={status:"failed",reason:"lock_unavailable",detail:l instanceof Error?l.message:String(l)}}return await X(a.path,o[0]),await S(t,a,u,i,r,e)}d(Et,"reconcileManagedWorktree");async function S(t,e,r,a,s,n){return await it(t,e,r,a,s,n),r}d(S,"finish");async function x(t,e,r){if(!await r.stillEligible())return $;const a=(await v(t))?.managed_worktree;return a==null||a.path!==e.path||a.branch!==e.branch?{status:"skipped",reason:"record_changed"}:(await U(t),{status:"complete"})}d(x,"persistComplete");async function ut(t,e,r,a){const s=e.repo_root;if(r.branch===null){const o=await c(["show-ref","--verify","--quiet",`refs/heads/${e.branch}`],s);return o.status!==1?{status:"failed",reason:"branch_inspection_failed",detail:h(o)}:await x(t,e,a)}const n=await c(["worktree","list","--porcelain"],s);if(n.status!==0)return{status:"failed",reason:"worktree_list_failed",detail:h(n)};const i=B(n.stdout,e.branch);if(i!==null)return{status:"refused",reason:"branch_checked_out_elsewhere",detail:`${e.branch} is checked out at ${i}`};const u=await A(s,e,r.branch);return u===null?{status:"refused",reason:"unlanded_work",detail:`${e.branch} carries content no base or upstream ref contains; its checkout is already gone, so the branch is the only copy`}:F(t,e,s,r.branch,u,a)}d(ut,"concludeAbsentCheckout");async function ct(t,e,r,a){const s=await c(["worktree","list","--porcelain"],e.path);if(s.status!==0)return{status:"failed",reason:"worktree_list_failed",detail:h(s)};const n=e.disposal,i=n?.observed_branch??e.branch,u=rt(s.stdout,e.path,i);if(u===null)return{status:"refused",reason:"not_registered",detail:`${e.path} is not registered to refs/heads/${i}; crtr will not act on a path it cannot prove it owns`};const o=at(s.stdout);if(o===null||W(o,u)||!y(o))return{status:"refused",reason:"repo_unavailable",detail:`the repository's main checkout is unavailable, so ${e.path} cannot be removed from outside itself`};const l=await et(e.path);if(l===null)return{status:"failed",reason:"git_path_failed",detail:`could not inspect in-progress operations in ${e.path}`};if(l)return{status:"refused",reason:"rebase_in_progress",detail:`${e.path} is mid-rebase`};const b=await c(["rev-parse","--abbrev-ref","HEAD"],e.path);if(b.status!==0)return{status:"failed",reason:"branch_check_failed",detail:h(b)};if(b.stdout.trim()!==i)return{status:"refused",reason:"wrong_branch",detail:`expected ${i}, found ${b.stdout.trim()==="HEAD"?"detached HEAD":b.stdout.trim()}`};const w=await c(["status","--porcelain"],e.path);if(w.status!==0)return{status:"failed",reason:"status_failed",detail:h(w)};if(w.stdout.trim()!=="")return{status:"refused",reason:"dirty_worktree",detail:`${e.path} has uncommitted changes`};let f=await m(e.path,"HEAD");if(f===null)return{status:"failed",reason:"head_unreadable",detail:`could not read HEAD in ${e.path}`};if(n!==void 0){if(await L(e.path)!==n.common_dir||f!==n.observed_sha)return{status:"refused",reason:"disposal_authorization_stale",detail:`${e.path} changed since \`close\` authorized its disposal; rerun \`crtr node worktree close\` from that node to re-authorize, or ask the user with \`crtr human send\``};if(!await r.stillEligible())return $;const{result:H,trash:O}=await R(o,u);return O!==void 0&&a.push(O),H.status!==0?{status:"refused",reason:"worktree_remove_failed",detail:h(H)}:await x(t,e,r)}let k=await A(e.path,e,f),_;if(k===null&&e.land_intent!==void 0){const g=await lt(e,s.stdout,r);if(!g.ok)return g.ineligible===!0?$:{status:"refused",reason:"land_blocked",detail:g.detail};f=g.landedSha,_=g.stash,k=await A(e.path,e,f)}if(k===null)return{status:"refused",reason:"unlanded_work",detail:`${e.branch} carries commits its base does not contain, and this node never asked to land them`};if(!await r.stillEligible())return $;const{result:p,trash:P}=await R(o,u);if(P!==void 0&&a.push(P),p.status!==0)return{status:"refused",reason:"worktree_remove_failed",detail:h(p)};const T=await F(t,e,o,f,k,r);return T.status==="complete"&&_!==void 0?{status:"complete",stash:_}:T}d(ct,"reconcilePresentCheckout");async function F(t,e,r,a,s,n){if(!await n.stillEligible())return $;const i=I(e.branch,a,s.containingRef,s.containingSha),u=await c(["update-ref","--stdin"],r,i);return u.status!==0?{status:"refused",reason:"branch_delete_failed",detail:h(u)}:await x(t,e,n)}d(F,"deleteBranchAndComplete");export{vt as isDueForSweep,D as isReconcilable,Et as reconcileManagedWorktree};
|
package/dist/core/worktree.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export declare class WorktreeError extends Error {
|
|
|
13
13
|
export declare function managedWorktreesRoot(): string;
|
|
14
14
|
export declare function managedWorktreePath(nodeId: string): string;
|
|
15
15
|
export declare function hasOpenManagedWorktree(node: NodeMeta | null | undefined): boolean;
|
|
16
|
-
export declare function openManagedWorktreeForNode(nodeId: string): ManagedWorktree | null
|
|
16
|
+
export declare function openManagedWorktreeForNode(nodeId: string): Promise<ManagedWorktree | null>;
|
|
17
17
|
export declare function isManagedWorktreeBase(repoRoot: string): boolean;
|
|
18
18
|
/** Shared parse for a `git worktree list --porcelain` blob already in hand —
|
|
19
19
|
* callers that must not throw on a read failure (an absent-path proof that
|
|
@@ -67,8 +67,8 @@ export interface CloseManagedWorktreeResult {
|
|
|
67
67
|
* revive launch fresh instead. Both closing paths MUST go through this helper
|
|
68
68
|
* instead of hand-rolling the `updateNode` call, so neither can drift out of
|
|
69
69
|
* sync. */
|
|
70
|
-
export declare function persistClosedWorktreeState(nodeId: string, wt: ManagedWorktree, cleanup?: 'pending' | 'complete'): void
|
|
71
|
-
export declare function closeManagedWorktree(nodeId: string): CloseManagedWorktreeResult
|
|
70
|
+
export declare function persistClosedWorktreeState(nodeId: string, wt: ManagedWorktree, cleanup?: 'pending' | 'complete'): Promise<void>;
|
|
71
|
+
export declare function closeManagedWorktree(nodeId: string): Promise<CloseManagedWorktreeResult>;
|
|
72
72
|
export interface AbandonManagedWorktreeResult {
|
|
73
73
|
node_id: string;
|
|
74
74
|
branch: string;
|
|
@@ -114,7 +114,7 @@ export interface AutoDroppedWorktree {
|
|
|
114
114
|
* inside the owner broker, so it has the same destructive-cwd boundary as
|
|
115
115
|
* explicit close: removal and branch deletion are deferred until that owner
|
|
116
116
|
* has exited. */
|
|
117
|
-
export declare function autoDropCleanManagedWorktreeLocked(nodeId: string, wt: ManagedWorktree, proof: CleanEmptyProof): AutoDroppedWorktree | null
|
|
117
|
+
export declare function autoDropCleanManagedWorktreeLocked(nodeId: string, wt: ManagedWorktree, proof: CleanEmptyProof): Promise<AutoDroppedWorktree | null>;
|
|
118
118
|
export declare function branchIsPushedAtCurrentTip(wt: ManagedWorktree): Promise<boolean>;
|
|
119
|
-
export declare function autoDropCleanManagedWorktree(nodeId: string): AutoDroppedWorktree | null
|
|
119
|
+
export declare function autoDropCleanManagedWorktree(nodeId: string): Promise<AutoDroppedWorktree | null>;
|
|
120
120
|
export {};
|