@crouton-kit/crouter 0.3.83 → 0.3.84
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/__tests__/attach-keybindings.test.js +14 -1
- package/dist/clients/attach/__tests__/crtr-output-render.test.js +5 -4
- package/dist/clients/attach/attach-cmd.d.ts +1 -1
- package/dist/clients/attach/attach-cmd.js +491 -491
- package/dist/commands/human/prompts.js +12 -6
- package/dist/commands/human.js +4 -2
- package/dist/commands/node.js +2 -1
- package/dist/commands/sys/__tests__/setup-front-door.test.js +8 -21
- package/dist/commands/sys/setup-core.d.ts +5 -17
- package/dist/commands/sys/setup-core.js +12 -36
- package/dist/commands/sys/setup.js +6 -4
- package/dist/core/__tests__/boot.test.js +141 -6
- package/dist/core/__tests__/pid-identity-match.test.js +63 -1
- package/dist/core/__tests__/tmux-surface.test.js +180 -2
- package/dist/core/canvas/boot.d.ts +44 -0
- package/dist/core/canvas/boot.js +35 -2
- package/dist/core/canvas/canvas.d.ts +40 -0
- package/dist/core/canvas/canvas.js +65 -1
- package/dist/core/canvas/pid.d.ts +43 -0
- package/dist/core/canvas/pid.js +57 -11
- package/dist/core/keybindings/__tests__/inbox-affordance.test.d.ts +1 -0
- package/dist/core/keybindings/__tests__/inbox-affordance.test.js +38 -0
- package/dist/core/keybindings/__tests__/resolve.test.js +1 -0
- package/dist/core/keybindings/catalog.d.ts +2 -2
- package/dist/core/keybindings/catalog.js +1 -0
- package/dist/core/keybindings/inbox.d.ts +21 -0
- package/dist/core/keybindings/inbox.js +35 -0
- package/dist/core/keybindings/index.d.ts +1 -0
- package/dist/core/keybindings/index.js +1 -0
- package/dist/core/preview-registry.js +7 -6
- package/dist/core/runtime/spawn.js +2 -10
- package/dist/core/runtime/tmux-chrome.d.ts +1 -1
- package/dist/core/runtime/tmux-chrome.js +1 -1
- package/dist/core/runtime/tmux.d.ts +1 -0
- package/dist/core/runtime/tmux.js +55 -1
- package/dist/daemon/crtrd.js +29 -5
- package/package.json +2 -2
|
@@ -7,8 +7,8 @@ type BrowseAction = 'quit' | 'down' | 'up' | 'first' | 'last' | 'expand-or-child
|
|
|
7
7
|
type ProfileMenuAction = 'up' | 'down' | 'select' | 'accept-default' | 'abort' | `slot.${1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9}` | 'create' | 'search-existing' | 'use-root' | 'set-default' | 'add-directory' | 'unpin';
|
|
8
8
|
type SetupAction = 'cancel' | 'tab-next' | 'tab-previous' | 'open' | 'list-down' | 'list-up' | 'toggle' | 'details' | 'advance';
|
|
9
9
|
type SetupKeybindingAction = 'edit' | 'commit-edit' | 'cancel-edit' | 'unbind' | 'reset-row' | 'reset-all' | 'save' | 'discard' | 'page-up' | 'page-down' | 'filter' | 'filter-delete' | 'filter-clear';
|
|
10
|
-
export type BindingId = `crtr.tmux.menu.${TmuxMenuAction}` | `crtr.tmux.menu.issue.${'idea' | 'bug'}` | `crtr.tmux.node.${'next' | 'previous'}` | `crtr.tmux.view.${'next' | 'previous'}` | `crtr.attach.${'detach' | 'clear-or-detach' | 'graph.toggle' | 'model-ladder.next' | 'model-ladder.previous'}` | 'crtr.mode.cycle' | `crtr.graph.${GraphAction}` | `crtr.graph.confirm.${'accept' | 'cancel'}` | `crtr.view.host.${'force-quit' | 'editor.backspace'}` | `crtr.view.canvas.${'down' | 'up' | 'refresh' | 'quit'}` | `crtr.view.chat.${'submit' | 'contextual-cancel' | 'reconnect' | 'request-control' | 'release-control' | 'quit'}` | `crtr.view.git-pr.${'down' | 'up' | 'refresh' | 'quit'}` | `crtr.view.inbox.${InboxAction}` | `crtr.view.linkedin.${LinkedinAction}` | `crtr.view.prompt-review.${'down' | 'up' | 'compare-previous' | 'compare-next' | 'toggle-mode' | 'expand' | 'export' | 'refresh' | 'quit'}` | `crtr.view.settings.${'down' | 'up' | 'cell-previous' | 'cell-next' | 'refresh' | 'quit' | 'edit-or-submit' | 'cancel-edit'}` | `crtr.view.workspace-sidebar.${'down' | 'up' | 'open' | 'refresh' | 'quit'}` | `crtr.view-picker.${'down' | 'up' | 'run' | 'quit'}` | `crtr.browse.${BrowseAction}` | `crtr.browse.search.${'cancel' | 'commit' | 'delete' | 'quit'}` | `crtr.profile.menu.${ProfileMenuAction}` | `crtr.profile.search.${'up' | 'down' | 'pick' | 'back' | 'delete' | 'abort'}` | `crtr.setup.${SetupAction}` | `crtr.setup.confirm.${'accept' | 'back'}` | `crtr.setup.keybindings.${SetupKeybindingAction}`;
|
|
11
|
-
export declare const BINDING_CATALOG: readonly [BindingDefinition<"crtr.tmux.menu.open">, BindingDefinition<"crtr.tmux.menu.promote">, BindingDefinition<"crtr.tmux.menu.resume">, BindingDefinition<"crtr.tmux.menu.demote">, BindingDefinition<"crtr.tmux.menu.detach">, BindingDefinition<"crtr.tmux.menu.close-subtree">, BindingDefinition<"crtr.tmux.menu.context">, BindingDefinition<"crtr.tmux.menu.providers">, BindingDefinition<"crtr.tmux.menu.graph">, BindingDefinition<"crtr.tmux.menu.focus-manager">, BindingDefinition<"crtr.tmux.menu.issues">, BindingDefinition<"crtr.tmux.menu.issue.idea">, BindingDefinition<"crtr.tmux.menu.issue.bug">, BindingDefinition<"crtr.tmux.node.next">, BindingDefinition<"crtr.tmux.node.previous">, BindingDefinition<"crtr.tmux.view.next">, BindingDefinition<"crtr.tmux.view.previous">, BindingDefinition<"crtr.attach.detach">, BindingDefinition<"crtr.attach.clear-or-detach">, BindingDefinition<"crtr.attach.graph.toggle">, BindingDefinition<"crtr.attach.model-ladder.next">, BindingDefinition<"crtr.attach.model-ladder.previous">, BindingDefinition<"crtr.mode.cycle">, BindingDefinition<"crtr.graph.down">, BindingDefinition<"crtr.graph.up">, BindingDefinition<"crtr.graph.first">, BindingDefinition<"crtr.graph.last">, BindingDefinition<"crtr.graph.collapse-or-manager">, BindingDefinition<"crtr.graph.expand-or-child">, BindingDefinition<"crtr.graph.focus">, BindingDefinition<"crtr.graph.focus-manager">, BindingDefinition<"crtr.graph.close-subtree">, BindingDefinition<"crtr.graph.dismiss">, BindingDefinition<"crtr.graph.confirm.accept">, BindingDefinition<"crtr.graph.confirm.cancel">, BindingDefinition<"crtr.view.host.force-quit">, BindingDefinition<"crtr.view.host.editor.backspace">, BindingDefinition<BindingId>, BindingDefinition<BindingId>, BindingDefinition<BindingId>, BindingDefinition<BindingId>, BindingDefinition<"crtr.view.chat.submit">, BindingDefinition<"crtr.view.chat.contextual-cancel">, BindingDefinition<"crtr.view.chat.reconnect">, BindingDefinition<"crtr.view.chat.request-control">, BindingDefinition<"crtr.view.chat.release-control">, BindingDefinition<"crtr.view.chat.quit">, BindingDefinition<BindingId>, BindingDefinition<BindingId>, BindingDefinition<BindingId>, BindingDefinition<BindingId>, BindingDefinition<BindingId>, BindingDefinition<BindingId>, ...(BindingDefinition<BindingId> | BindingDefinition<"crtr.view.prompt-review.down"> | BindingDefinition<"crtr.view.prompt-review.up"> | BindingDefinition<"crtr.view.prompt-review.compare-previous"> | BindingDefinition<"crtr.view.prompt-review.compare-next"> | BindingDefinition<"crtr.view.prompt-review.toggle-mode"> | BindingDefinition<"crtr.view.prompt-review.expand"> | BindingDefinition<"crtr.view.prompt-review.export"> | BindingDefinition<"crtr.view.prompt-review.refresh"> | BindingDefinition<"crtr.view.prompt-review.quit"> | BindingDefinition<"crtr.view.settings.down"> | BindingDefinition<"crtr.view.settings.up"> | BindingDefinition<"crtr.view.settings.cell-previous"> | BindingDefinition<"crtr.view.settings.cell-next"> | BindingDefinition<"crtr.view.settings.refresh"> | BindingDefinition<"crtr.view.settings.quit"> | BindingDefinition<"crtr.view.settings.edit-or-submit"> | BindingDefinition<"crtr.view.settings.cancel-edit"> | BindingDefinition<"crtr.view.workspace-sidebar.down"> | BindingDefinition<"crtr.view.workspace-sidebar.up"> | BindingDefinition<"crtr.view.workspace-sidebar.open"> | BindingDefinition<"crtr.view.workspace-sidebar.refresh"> | BindingDefinition<"crtr.view.workspace-sidebar.quit"> | BindingDefinition<"crtr.view-picker.down"> | BindingDefinition<"crtr.view-picker.up"> | BindingDefinition<"crtr.view-picker.run"> | BindingDefinition<"crtr.view-picker.quit"> | BindingDefinition<"crtr.browse.quit"> | BindingDefinition<"crtr.browse.down"> | BindingDefinition<"crtr.browse.up"> | BindingDefinition<"crtr.browse.first"> | BindingDefinition<"crtr.browse.last"> | BindingDefinition<"crtr.browse.expand-or-child"> | BindingDefinition<"crtr.browse.collapse-or-parent"> | BindingDefinition<"crtr.browse.toggle-fold"> | BindingDefinition<"crtr.browse.tab-next"> | BindingDefinition<"crtr.browse.tab-previous"> | BindingDefinition<"crtr.browse.tab.2" | "crtr.browse.tab.1" | "crtr.browse.tab.3" | "crtr.browse.tab.4" | "crtr.browse.tab.5"> | BindingDefinition<"crtr.browse.close-subtree"> | BindingDefinition<"crtr.browse.confirm-close"> | BindingDefinition<"crtr.browse.sort"> | BindingDefinition<"crtr.browse.scope"> | BindingDefinition<"crtr.browse.residents"> | BindingDefinition<"crtr.browse.preview"> | BindingDefinition<"crtr.browse.search"> | BindingDefinition<"crtr.browse.revive-now"> | BindingDefinition<"crtr.browse.focus"> | BindingDefinition<"crtr.browse.search.cancel"> | BindingDefinition<"crtr.browse.search.commit"> | BindingDefinition<"crtr.browse.search.delete"> | BindingDefinition<"crtr.browse.search.quit"> | BindingDefinition<"crtr.profile.menu.up"> | BindingDefinition<"crtr.profile.menu.down"> | BindingDefinition<"crtr.profile.menu.select"> | BindingDefinition<"crtr.profile.menu.accept-default"> | BindingDefinition<"crtr.profile.menu.abort"> | BindingDefinition<"crtr.profile.menu.slot.2" | "crtr.profile.menu.slot.1" | "crtr.profile.menu.slot.3" | "crtr.profile.menu.slot.4" | "crtr.profile.menu.slot.5" | "crtr.profile.menu.slot.8" | "crtr.profile.menu.slot.6" | "crtr.profile.menu.slot.7" | "crtr.profile.menu.slot.9">)[], BindingDefinition<"crtr.profile.menu.create">, BindingDefinition<"crtr.profile.menu.search-existing">, BindingDefinition<"crtr.profile.menu.use-root">, BindingDefinition<"crtr.profile.menu.set-default">, BindingDefinition<"crtr.profile.menu.add-directory">, BindingDefinition<"crtr.profile.menu.unpin">, BindingDefinition<"crtr.profile.search.up">, BindingDefinition<"crtr.profile.search.down">, BindingDefinition<"crtr.profile.search.pick">, BindingDefinition<"crtr.profile.search.back">, BindingDefinition<"crtr.profile.search.delete">, BindingDefinition<"crtr.profile.search.abort">, BindingDefinition<"crtr.setup.cancel">, BindingDefinition<"crtr.setup.tab-next">, BindingDefinition<"crtr.setup.tab-previous">, BindingDefinition<"crtr.setup.open">, BindingDefinition<"crtr.setup.list-down">, BindingDefinition<"crtr.setup.list-up">, BindingDefinition<"crtr.setup.toggle">, BindingDefinition<"crtr.setup.details">, BindingDefinition<"crtr.setup.advance">, BindingDefinition<"crtr.setup.confirm.accept">, BindingDefinition<"crtr.setup.confirm.back">, BindingDefinition<"crtr.setup.keybindings.edit">, BindingDefinition<"crtr.setup.keybindings.commit-edit">, BindingDefinition<"crtr.setup.keybindings.cancel-edit">, BindingDefinition<"crtr.setup.keybindings.unbind">, BindingDefinition<"crtr.setup.keybindings.reset-row">, BindingDefinition<"crtr.setup.keybindings.reset-all">, BindingDefinition<"crtr.setup.keybindings.save">, BindingDefinition<"crtr.setup.keybindings.discard">, BindingDefinition<"crtr.setup.keybindings.page-up">, BindingDefinition<"crtr.setup.keybindings.page-down">, BindingDefinition<"crtr.setup.keybindings.filter">, BindingDefinition<"crtr.setup.keybindings.filter-delete">, BindingDefinition<"crtr.setup.keybindings.filter-clear">];
|
|
10
|
+
export type BindingId = `crtr.tmux.menu.${TmuxMenuAction}` | `crtr.tmux.menu.issue.${'idea' | 'bug'}` | `crtr.tmux.node.${'next' | 'previous'}` | `crtr.tmux.view.${'next' | 'previous'}` | 'crtr.tmux.inbox.toggle' | `crtr.attach.${'detach' | 'clear-or-detach' | 'graph.toggle' | 'model-ladder.next' | 'model-ladder.previous'}` | 'crtr.mode.cycle' | `crtr.graph.${GraphAction}` | `crtr.graph.confirm.${'accept' | 'cancel'}` | `crtr.view.host.${'force-quit' | 'editor.backspace'}` | `crtr.view.canvas.${'down' | 'up' | 'refresh' | 'quit'}` | `crtr.view.chat.${'submit' | 'contextual-cancel' | 'reconnect' | 'request-control' | 'release-control' | 'quit'}` | `crtr.view.git-pr.${'down' | 'up' | 'refresh' | 'quit'}` | `crtr.view.inbox.${InboxAction}` | `crtr.view.linkedin.${LinkedinAction}` | `crtr.view.prompt-review.${'down' | 'up' | 'compare-previous' | 'compare-next' | 'toggle-mode' | 'expand' | 'export' | 'refresh' | 'quit'}` | `crtr.view.settings.${'down' | 'up' | 'cell-previous' | 'cell-next' | 'refresh' | 'quit' | 'edit-or-submit' | 'cancel-edit'}` | `crtr.view.workspace-sidebar.${'down' | 'up' | 'open' | 'refresh' | 'quit'}` | `crtr.view-picker.${'down' | 'up' | 'run' | 'quit'}` | `crtr.browse.${BrowseAction}` | `crtr.browse.search.${'cancel' | 'commit' | 'delete' | 'quit'}` | `crtr.profile.menu.${ProfileMenuAction}` | `crtr.profile.search.${'up' | 'down' | 'pick' | 'back' | 'delete' | 'abort'}` | `crtr.setup.${SetupAction}` | `crtr.setup.confirm.${'accept' | 'back'}` | `crtr.setup.keybindings.${SetupKeybindingAction}`;
|
|
11
|
+
export declare const BINDING_CATALOG: readonly [BindingDefinition<"crtr.tmux.menu.open">, BindingDefinition<"crtr.tmux.menu.promote">, BindingDefinition<"crtr.tmux.menu.resume">, BindingDefinition<"crtr.tmux.menu.demote">, BindingDefinition<"crtr.tmux.menu.detach">, BindingDefinition<"crtr.tmux.menu.close-subtree">, BindingDefinition<"crtr.tmux.menu.context">, BindingDefinition<"crtr.tmux.menu.providers">, BindingDefinition<"crtr.tmux.menu.graph">, BindingDefinition<"crtr.tmux.menu.focus-manager">, BindingDefinition<"crtr.tmux.menu.issues">, BindingDefinition<"crtr.tmux.menu.issue.idea">, BindingDefinition<"crtr.tmux.menu.issue.bug">, BindingDefinition<"crtr.tmux.node.next">, BindingDefinition<"crtr.tmux.node.previous">, BindingDefinition<"crtr.tmux.inbox.toggle">, BindingDefinition<"crtr.tmux.view.next">, BindingDefinition<"crtr.tmux.view.previous">, BindingDefinition<"crtr.attach.detach">, BindingDefinition<"crtr.attach.clear-or-detach">, BindingDefinition<"crtr.attach.graph.toggle">, BindingDefinition<"crtr.attach.model-ladder.next">, BindingDefinition<"crtr.attach.model-ladder.previous">, BindingDefinition<"crtr.mode.cycle">, BindingDefinition<"crtr.graph.down">, BindingDefinition<"crtr.graph.up">, BindingDefinition<"crtr.graph.first">, BindingDefinition<"crtr.graph.last">, BindingDefinition<"crtr.graph.collapse-or-manager">, BindingDefinition<"crtr.graph.expand-or-child">, BindingDefinition<"crtr.graph.focus">, BindingDefinition<"crtr.graph.focus-manager">, BindingDefinition<"crtr.graph.close-subtree">, BindingDefinition<"crtr.graph.dismiss">, BindingDefinition<"crtr.graph.confirm.accept">, BindingDefinition<"crtr.graph.confirm.cancel">, BindingDefinition<"crtr.view.host.force-quit">, BindingDefinition<"crtr.view.host.editor.backspace">, BindingDefinition<BindingId>, BindingDefinition<BindingId>, BindingDefinition<BindingId>, BindingDefinition<BindingId>, BindingDefinition<"crtr.view.chat.submit">, BindingDefinition<"crtr.view.chat.contextual-cancel">, BindingDefinition<"crtr.view.chat.reconnect">, BindingDefinition<"crtr.view.chat.request-control">, BindingDefinition<"crtr.view.chat.release-control">, BindingDefinition<"crtr.view.chat.quit">, BindingDefinition<BindingId>, BindingDefinition<BindingId>, BindingDefinition<BindingId>, BindingDefinition<BindingId>, BindingDefinition<BindingId>, BindingDefinition<BindingId>, ...(BindingDefinition<BindingId> | BindingDefinition<"crtr.view.prompt-review.down"> | BindingDefinition<"crtr.view.prompt-review.up"> | BindingDefinition<"crtr.view.prompt-review.compare-previous"> | BindingDefinition<"crtr.view.prompt-review.compare-next"> | BindingDefinition<"crtr.view.prompt-review.toggle-mode"> | BindingDefinition<"crtr.view.prompt-review.expand"> | BindingDefinition<"crtr.view.prompt-review.export"> | BindingDefinition<"crtr.view.prompt-review.refresh"> | BindingDefinition<"crtr.view.prompt-review.quit"> | BindingDefinition<"crtr.view.settings.down"> | BindingDefinition<"crtr.view.settings.up"> | BindingDefinition<"crtr.view.settings.cell-previous"> | BindingDefinition<"crtr.view.settings.cell-next"> | BindingDefinition<"crtr.view.settings.refresh"> | BindingDefinition<"crtr.view.settings.quit"> | BindingDefinition<"crtr.view.settings.edit-or-submit"> | BindingDefinition<"crtr.view.settings.cancel-edit"> | BindingDefinition<"crtr.view.workspace-sidebar.down"> | BindingDefinition<"crtr.view.workspace-sidebar.up"> | BindingDefinition<"crtr.view.workspace-sidebar.open"> | BindingDefinition<"crtr.view.workspace-sidebar.refresh"> | BindingDefinition<"crtr.view.workspace-sidebar.quit"> | BindingDefinition<"crtr.view-picker.down"> | BindingDefinition<"crtr.view-picker.up"> | BindingDefinition<"crtr.view-picker.run"> | BindingDefinition<"crtr.view-picker.quit"> | BindingDefinition<"crtr.browse.quit"> | BindingDefinition<"crtr.browse.down"> | BindingDefinition<"crtr.browse.up"> | BindingDefinition<"crtr.browse.first"> | BindingDefinition<"crtr.browse.last"> | BindingDefinition<"crtr.browse.expand-or-child"> | BindingDefinition<"crtr.browse.collapse-or-parent"> | BindingDefinition<"crtr.browse.toggle-fold"> | BindingDefinition<"crtr.browse.tab-next"> | BindingDefinition<"crtr.browse.tab-previous"> | BindingDefinition<"crtr.browse.tab.2" | "crtr.browse.tab.1" | "crtr.browse.tab.3" | "crtr.browse.tab.4" | "crtr.browse.tab.5"> | BindingDefinition<"crtr.browse.close-subtree"> | BindingDefinition<"crtr.browse.confirm-close"> | BindingDefinition<"crtr.browse.sort"> | BindingDefinition<"crtr.browse.scope"> | BindingDefinition<"crtr.browse.residents"> | BindingDefinition<"crtr.browse.preview"> | BindingDefinition<"crtr.browse.search"> | BindingDefinition<"crtr.browse.revive-now"> | BindingDefinition<"crtr.browse.focus"> | BindingDefinition<"crtr.browse.search.cancel"> | BindingDefinition<"crtr.browse.search.commit"> | BindingDefinition<"crtr.browse.search.delete"> | BindingDefinition<"crtr.browse.search.quit"> | BindingDefinition<"crtr.profile.menu.up"> | BindingDefinition<"crtr.profile.menu.down"> | BindingDefinition<"crtr.profile.menu.select"> | BindingDefinition<"crtr.profile.menu.accept-default"> | BindingDefinition<"crtr.profile.menu.abort"> | BindingDefinition<"crtr.profile.menu.slot.2" | "crtr.profile.menu.slot.1" | "crtr.profile.menu.slot.3" | "crtr.profile.menu.slot.4" | "crtr.profile.menu.slot.5" | "crtr.profile.menu.slot.8" | "crtr.profile.menu.slot.6" | "crtr.profile.menu.slot.7" | "crtr.profile.menu.slot.9">)[], BindingDefinition<"crtr.profile.menu.create">, BindingDefinition<"crtr.profile.menu.search-existing">, BindingDefinition<"crtr.profile.menu.use-root">, BindingDefinition<"crtr.profile.menu.set-default">, BindingDefinition<"crtr.profile.menu.add-directory">, BindingDefinition<"crtr.profile.menu.unpin">, BindingDefinition<"crtr.profile.search.up">, BindingDefinition<"crtr.profile.search.down">, BindingDefinition<"crtr.profile.search.pick">, BindingDefinition<"crtr.profile.search.back">, BindingDefinition<"crtr.profile.search.delete">, BindingDefinition<"crtr.profile.search.abort">, BindingDefinition<"crtr.setup.cancel">, BindingDefinition<"crtr.setup.tab-next">, BindingDefinition<"crtr.setup.tab-previous">, BindingDefinition<"crtr.setup.open">, BindingDefinition<"crtr.setup.list-down">, BindingDefinition<"crtr.setup.list-up">, BindingDefinition<"crtr.setup.toggle">, BindingDefinition<"crtr.setup.details">, BindingDefinition<"crtr.setup.advance">, BindingDefinition<"crtr.setup.confirm.accept">, BindingDefinition<"crtr.setup.confirm.back">, BindingDefinition<"crtr.setup.keybindings.edit">, BindingDefinition<"crtr.setup.keybindings.commit-edit">, BindingDefinition<"crtr.setup.keybindings.cancel-edit">, BindingDefinition<"crtr.setup.keybindings.unbind">, BindingDefinition<"crtr.setup.keybindings.reset-row">, BindingDefinition<"crtr.setup.keybindings.reset-all">, BindingDefinition<"crtr.setup.keybindings.save">, BindingDefinition<"crtr.setup.keybindings.discard">, BindingDefinition<"crtr.setup.keybindings.page-up">, BindingDefinition<"crtr.setup.keybindings.page-down">, BindingDefinition<"crtr.setup.keybindings.filter">, BindingDefinition<"crtr.setup.keybindings.filter-delete">, BindingDefinition<"crtr.setup.keybindings.filter-clear">];
|
|
12
12
|
export declare const BINDING_IDS: ReadonlySet<string>;
|
|
13
13
|
export declare const SAFETY_REQUIREMENTS: readonly SafetyRequirement[];
|
|
14
14
|
export {};
|
|
@@ -40,6 +40,7 @@ export const BINDING_CATALOG = Object.freeze([
|
|
|
40
40
|
b('crtr.tmux.menu.issue.bug', 'Global tmux', 'Create bug', 'Create a bug issue.', ['b'], 'tmux-menu-selector', ['tmux.menu.issue']),
|
|
41
41
|
b('crtr.tmux.node.next', 'Global tmux', 'Next node', 'Focus the next canvas node.', ['alt+]'], 'host-global', ['tmux.root']),
|
|
42
42
|
b('crtr.tmux.node.previous', 'Global tmux', 'Previous node', 'Focus the previous canvas node.', ['alt+['], 'host-global', ['tmux.root']),
|
|
43
|
+
b('crtr.tmux.inbox.toggle', 'Global tmux', 'Toggle inbox', 'Open or close the human inbox popup.', ['alt+i'], 'host-global', ['tmux.root']),
|
|
43
44
|
b('crtr.tmux.view.next', 'Global tmux', 'Next view', 'Focus the next view.', ['alt+v > ]'], 'tmux-sequence', ['tmux.root']),
|
|
44
45
|
b('crtr.tmux.view.previous', 'Global tmux', 'Previous view', 'Focus the previous view.', ['alt+v > ['], 'tmux-sequence', ['tmux.root']),
|
|
45
46
|
b('crtr.attach.detach', 'Attach', 'Detach', 'Detach from the node.', ['ctrl+d'], 'host-global', ATTACH_CONTEXTS),
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { BindingId } from './catalog.js';
|
|
2
|
+
import type { BindingResolution } from './types.js';
|
|
3
|
+
/** The single source of truth for how every pending-interaction surface names
|
|
4
|
+
* the inbox shortcut. Resolves the live `crtr.tmux.inbox.toggle` gestures and
|
|
5
|
+
* returns the formatted label(s) — joined with ' / ' when multiple, matching
|
|
6
|
+
* crouter's `formatBinding` convention — or null when the binding is disabled.
|
|
7
|
+
* Bindings default to the user's resolved config so a bare call reflects
|
|
8
|
+
* current state; callers holding a live snapshot (e.g. the attach viewer) pass
|
|
9
|
+
* it so a `/reload` rebind is honored. */
|
|
10
|
+
export declare function inboxShortcut(bindings?: BindingResolution<BindingId>): string | null;
|
|
11
|
+
/** Closed-inbox footer affordance: "<shortcut> inbox", or the CLI fallback
|
|
12
|
+
* `hl inbox open` when the binding is disabled. */
|
|
13
|
+
export declare function inboxOpenHint(bindings?: BindingResolution<BindingId>): string;
|
|
14
|
+
/** Bare token naming the inbox affordance for a parenthetical — the resolved
|
|
15
|
+
* shortcut (e.g. `Alt+I`), or the backtick-quoted CLI form when disabled. Use
|
|
16
|
+
* where prose reads "the inbox popup (<hint>)". */
|
|
17
|
+
export declare function inboxPopupHint(bindings?: BindingResolution<BindingId>): string;
|
|
18
|
+
/** Imperative clause telling the human how to open the inbox — "press
|
|
19
|
+
* <shortcut> (or run `hl inbox open` at a terminal)", or just the CLI form
|
|
20
|
+
* when the binding is disabled. */
|
|
21
|
+
export declare function inboxOpenInstruction(bindings?: BindingResolution<BindingId>): string;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { formatGesture } from './match.js';
|
|
2
|
+
import { resolveUserKeybindings } from './resolve.js';
|
|
3
|
+
const INBOX_TOGGLE = 'crtr.tmux.inbox.toggle';
|
|
4
|
+
/** The single source of truth for how every pending-interaction surface names
|
|
5
|
+
* the inbox shortcut. Resolves the live `crtr.tmux.inbox.toggle` gestures and
|
|
6
|
+
* returns the formatted label(s) — joined with ' / ' when multiple, matching
|
|
7
|
+
* crouter's `formatBinding` convention — or null when the binding is disabled.
|
|
8
|
+
* Bindings default to the user's resolved config so a bare call reflects
|
|
9
|
+
* current state; callers holding a live snapshot (e.g. the attach viewer) pass
|
|
10
|
+
* it so a `/reload` rebind is honored. */
|
|
11
|
+
export function inboxShortcut(bindings = resolveUserKeybindings()) {
|
|
12
|
+
const gestures = bindings.gestures(INBOX_TOGGLE);
|
|
13
|
+
return gestures.length > 0 ? gestures.map(formatGesture).join(' / ') : null;
|
|
14
|
+
}
|
|
15
|
+
/** Closed-inbox footer affordance: "<shortcut> inbox", or the CLI fallback
|
|
16
|
+
* `hl inbox open` when the binding is disabled. */
|
|
17
|
+
export function inboxOpenHint(bindings) {
|
|
18
|
+
const shortcut = inboxShortcut(bindings);
|
|
19
|
+
return shortcut !== null ? `${shortcut} inbox` : 'hl inbox open';
|
|
20
|
+
}
|
|
21
|
+
/** Bare token naming the inbox affordance for a parenthetical — the resolved
|
|
22
|
+
* shortcut (e.g. `Alt+I`), or the backtick-quoted CLI form when disabled. Use
|
|
23
|
+
* where prose reads "the inbox popup (<hint>)". */
|
|
24
|
+
export function inboxPopupHint(bindings) {
|
|
25
|
+
return inboxShortcut(bindings) ?? '`hl inbox open`';
|
|
26
|
+
}
|
|
27
|
+
/** Imperative clause telling the human how to open the inbox — "press
|
|
28
|
+
* <shortcut> (or run `hl inbox open` at a terminal)", or just the CLI form
|
|
29
|
+
* when the binding is disabled. */
|
|
30
|
+
export function inboxOpenInstruction(bindings) {
|
|
31
|
+
const shortcut = inboxShortcut(bindings);
|
|
32
|
+
return shortcut !== null
|
|
33
|
+
? `press ${shortcut} (or run \`hl inbox open\` at a terminal)`
|
|
34
|
+
: 'run `hl inbox open` at a terminal';
|
|
35
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { BINDING_CATALOG, BINDING_IDS, SAFETY_REQUIREMENTS, type BindingId, } from './catalog.js';
|
|
2
2
|
export { GestureSyntaxError, KeybindingValidationError, normalizeGesture, normalizeSparseOverrides, normalizeStroke, resolveKeybindings, resolveUserKeybindings, } from './resolve.js';
|
|
3
3
|
export { canonicalTerminalStroke, formatBinding, formatGesture, formatStroke, matchesPiTuiInput, matchesTerminalInput, type PiTuiMatcher, type RawTerminalInput, } from './match.js';
|
|
4
|
+
export { inboxOpenHint, inboxOpenInstruction, inboxPopupHint, inboxShortcut, } from './inbox.js';
|
|
4
5
|
export { KeybindingConcurrentEditError, persistUserKeybindings, type PersistedKeybindings, type PersistKeybindingsOptions, } from './persistence.js';
|
|
5
6
|
export type { BindingDefinition, BindingInputKind, BindingResolution, BindingSafetyCapability, EffectiveBinding, KeybindingDiagnostic, KeybindingDiagnosticCode, SafetyRequirement, SparseKeybindingOverrides, } from './types.js';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { BINDING_CATALOG, BINDING_IDS, SAFETY_REQUIREMENTS, } from './catalog.js';
|
|
2
2
|
export { GestureSyntaxError, KeybindingValidationError, normalizeGesture, normalizeSparseOverrides, normalizeStroke, resolveKeybindings, resolveUserKeybindings, } from './resolve.js';
|
|
3
3
|
export { canonicalTerminalStroke, formatBinding, formatGesture, formatStroke, matchesPiTuiInput, matchesTerminalInput, } from './match.js';
|
|
4
|
+
export { inboxOpenHint, inboxOpenInstruction, inboxPopupHint, inboxShortcut, } from './inbox.js';
|
|
4
5
|
export { KeybindingConcurrentEditError, persistUserKeybindings, } from './persistence.js';
|
|
@@ -1085,11 +1085,12 @@ const ASK_TEASER_CHARS = 160;
|
|
|
1085
1085
|
/** `crtr human ask` (humanAsk.run, src/commands/human/prompts.ts) returns
|
|
1086
1086
|
* `{job_id, dir, follow_up}` — `job_id` is always short (a node id) so it
|
|
1087
1087
|
* always bullets; `dir`/`follow_up` cross the prose threshold depending on
|
|
1088
|
-
* path length, so the shape is recognized by `job_id` plus the
|
|
1089
|
-
*
|
|
1088
|
+
* path length, so the shape is recognized by `job_id` plus the stable road-sign
|
|
1089
|
+
* prefix `Queued for the human` (queuedFollowUp, prompts.ts — its inbox-
|
|
1090
|
+
* affordance tail resolves per call, the prefix never varies) appearing
|
|
1090
1091
|
* anywhere in the text — never by assuming dir/follow_up's bullet vs. prose
|
|
1091
|
-
* form. Arrival is
|
|
1092
|
-
*
|
|
1092
|
+
* form. Arrival is always just durable queue state, so the card collapses to
|
|
1093
|
+
* one posted line. The
|
|
1093
1094
|
* question text isn't in the output at all (only the bare-question invocation
|
|
1094
1095
|
* echoes it), so it's recovered from argv: the first non-flag token after
|
|
1095
1096
|
* `human ask`, skipping `--context-file`'s value — absent for a
|
|
@@ -1113,8 +1114,8 @@ function summarizeHumanAsk(text, tokens) {
|
|
|
1113
1114
|
}
|
|
1114
1115
|
/** `crtr human review` (humanReview.run, src/commands/human/prompts.ts)
|
|
1115
1116
|
* returns `{job_id, dir, output, follow_up}` — same recognition strategy as
|
|
1116
|
-
* summarizeHumanAsk (job_id bullet + the
|
|
1117
|
-
* road-sign,
|
|
1117
|
+
* summarizeHumanAsk (job_id bullet + the stable `Queued for the human`
|
|
1118
|
+
* road-sign prefix, which review shares with ask). The
|
|
1118
1119
|
* reviewed file isn't in the output either, so its basename is recovered
|
|
1119
1120
|
* from argv (the file positional, skipping `--output`'s value). Returns null
|
|
1120
1121
|
* when the road-sign is absent. */
|
|
@@ -24,7 +24,6 @@ import { appendSituationalContext } from './situational-context.js';
|
|
|
24
24
|
import { hasRoadmap, seedRoadmap } from './roadmap.js';
|
|
25
25
|
import { buildIdentityAssertion, buildWakeBearings } from './bearings.js';
|
|
26
26
|
import { installTmuxBindings } from './tmux-chrome.js';
|
|
27
|
-
import { installInboxBinding } from '@crouton-kit/humanloop';
|
|
28
27
|
import { getNode, fullName, recordPid } from '../canvas/index.js';
|
|
29
28
|
import { registerViewerFocus, openViewerWindow, waitForBrokerViewSocket, viewerSplitEnv, windowOfPane, currentTmux, inTmux, focusWindow, } from './placement.js';
|
|
30
29
|
import { transition } from './lifecycle.js';
|
|
@@ -98,19 +97,12 @@ export async function bootRoot(opts) {
|
|
|
98
97
|
// mandate (bare `crtr` has none — writeGoal no-ops on empty).
|
|
99
98
|
if (opts.prompt !== undefined)
|
|
100
99
|
writeGoal(meta.node_id, opts.prompt);
|
|
101
|
-
// Reconcile the crouter-owned tmux bindings on this server
|
|
100
|
+
// Reconcile the crouter-owned tmux bindings on this server, including the
|
|
101
|
+
// inbox-toggle key (crtr.tmux.inbox.toggle) folded into the same manifest sweep.
|
|
102
102
|
try {
|
|
103
103
|
installTmuxBindings();
|
|
104
104
|
}
|
|
105
105
|
catch { /* best-effort */ }
|
|
106
|
-
// Reconcile humanloop's collision-safe M-i inbox popup binding on the same
|
|
107
|
-
// server so the inbox is reachable from any window. Crouter calls humanloop's
|
|
108
|
-
// installer — it never authors or parses its own tmux command; the installer
|
|
109
|
-
// is idempotent and leaves any pre-existing M-i binding untouched.
|
|
110
|
-
try {
|
|
111
|
-
installInboxBinding();
|
|
112
|
-
}
|
|
113
|
-
catch { /* best-effort */ }
|
|
114
106
|
// This terminal becomes the root's attach VIEWER in the user's CURRENT session,
|
|
115
107
|
// so its window stays where the user already is. The node row carries NO
|
|
116
108
|
// presence — a broker node's pane/window/tmux_session stay NULL; the viewer
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { installTmuxBindings, sendKeysEnter, displayMessage, paneCurrentPath, type TmuxInstalledPair, type TmuxInstallDiagnostic, type TmuxInstallResult, } from './tmux.js';
|
|
1
|
+
export { installTmuxBindings, legacyInboxKeyFile, sendKeysEnter, displayMessage, paneCurrentPath, type TmuxInstalledPair, type TmuxInstallDiagnostic, type TmuxInstallResult, } from './tmux.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// tmux-chrome.ts — chrome seam (§2.1): stateless keybind/input verbs.
|
|
2
2
|
// The ONLY non-placement module allowed to import the tmux driver, per the
|
|
3
3
|
// §5.1 lint. Re-exports the server chrome callers need.
|
|
4
|
-
export { installTmuxBindings, sendKeysEnter, displayMessage, paneCurrentPath, } from './tmux.js';
|
|
4
|
+
export { installTmuxBindings, legacyInboxKeyFile, sendKeysEnter, displayMessage, paneCurrentPath, } from './tmux.js';
|
|
@@ -218,5 +218,6 @@ export interface TmuxInstallResult {
|
|
|
218
218
|
readonly installed: readonly TmuxInstalledPair[];
|
|
219
219
|
readonly diagnostics: readonly TmuxInstallDiagnostic[];
|
|
220
220
|
}
|
|
221
|
+
export declare function legacyInboxKeyFile(): string;
|
|
221
222
|
/** Reconcile the tmux server with one immutable crouter binding snapshot. */
|
|
222
223
|
export declare function installTmuxBindings(bindings?: BindingResolution<BindingId>): TmuxInstallResult;
|
|
@@ -8,9 +8,13 @@
|
|
|
8
8
|
// root) or switch-client + select-window (across roots). done/dead nodes close
|
|
9
9
|
// their window; reviving opens a fresh one.
|
|
10
10
|
import { spawnSync } from 'node:child_process';
|
|
11
|
+
import { readFileSync, rmSync } from 'node:fs';
|
|
12
|
+
import { homedir } from 'node:os';
|
|
13
|
+
import { join } from 'node:path';
|
|
11
14
|
import { resolveUserKeybindings, } from '../keybindings/index.js';
|
|
12
15
|
import { bundledPiCommandForShell } from './pi-cli.js';
|
|
13
16
|
import { surfaceTmuxStyleArgs } from './surface-bg.js';
|
|
17
|
+
import { inboxToggleTmuxCommand } from '@crouton-kit/humanloop';
|
|
14
18
|
// ---------------------------------------------------------------------------
|
|
15
19
|
// Shell quoting + tmux invocation
|
|
16
20
|
// ---------------------------------------------------------------------------
|
|
@@ -428,6 +432,7 @@ const MENU_ACTIONS = {
|
|
|
428
432
|
'crtr.tmux.menu.issue.bug': undefined,
|
|
429
433
|
'crtr.tmux.node.next': undefined,
|
|
430
434
|
'crtr.tmux.node.previous': undefined,
|
|
435
|
+
'crtr.tmux.inbox.toggle': undefined,
|
|
431
436
|
'crtr.tmux.view.next': undefined,
|
|
432
437
|
'crtr.tmux.view.previous': undefined,
|
|
433
438
|
};
|
|
@@ -546,12 +551,28 @@ function readManifest() {
|
|
|
546
551
|
return null;
|
|
547
552
|
}
|
|
548
553
|
}
|
|
554
|
+
// Crouter's own pre-manifest root bindings. When a machine had these installed
|
|
555
|
+
// before the ownership manifest existed, the first reconciliation adopts them
|
|
556
|
+
// into the manifest (unbinding the stale copy so it reinstalls cleanly) instead
|
|
557
|
+
// of reporting them foreign. Gated on a fresh manifest — once one exists these
|
|
558
|
+
// keys are already crouter-owned through it.
|
|
549
559
|
const LEGACY_ROOT_BINDINGS = [
|
|
550
560
|
{ key: 'M-c', markers: ['display-menu', 'promote to orchestrator', 'crtr canvas chord', 'new issue / todo'] },
|
|
551
561
|
{ key: 'M-]', markers: ['run-shell', 'crtr node cycle --dir next', "--pane '#{pane_id}'"] },
|
|
552
562
|
{ key: 'M-[', markers: ['run-shell', 'crtr node cycle --dir prev', "--pane '#{pane_id}'"] },
|
|
553
563
|
{ key: 'M-v', markers: ['switch-client', '-T crtr-view'] },
|
|
554
564
|
];
|
|
565
|
+
// The inbox toggle is a crouter-owned root binding, resolved from keybindings.json
|
|
566
|
+
// and installed through the manifest sweep like every sibling. Root bindings
|
|
567
|
+
// matching these markers that are NOT tracked in the manifest are hl-owned
|
|
568
|
+
// strays; reconciliation removes them (and the state file naming their key) so
|
|
569
|
+
// the manifest stays the sole owner of the inbox command.
|
|
570
|
+
const LEGACY_INBOX_MARKERS = ['run-shell', 'hl inbox toggle'];
|
|
571
|
+
const LEGACY_INBOX_DEFAULT_KEY = 'M-i';
|
|
572
|
+
export function legacyInboxKeyFile() {
|
|
573
|
+
const stateHome = process.env['XDG_STATE_HOME'] || join(homedir(), '.local', 'state');
|
|
574
|
+
return join(stateHome, 'humanloop', 'inbox-key');
|
|
575
|
+
}
|
|
555
576
|
function adoptLegacyBindings() {
|
|
556
577
|
for (const legacy of LEGACY_ROOT_BINDINGS) {
|
|
557
578
|
const existing = bindingAt(ROOT_TABLE, legacy.key);
|
|
@@ -560,10 +581,42 @@ function adoptLegacyBindings() {
|
|
|
560
581
|
}
|
|
561
582
|
}
|
|
562
583
|
}
|
|
584
|
+
// Enforce the manifest's sole ownership of the inbox command: any hl-owned
|
|
585
|
+
// inbox binding not tracked in the manifest is unbound, and the humanloop
|
|
586
|
+
// state file is discarded. Runs on every reconciliation regardless of whether
|
|
587
|
+
// a manifest already exists. Checks the default key plus the key the state
|
|
588
|
+
// file records (the file's value only locates a stray binding — it is never
|
|
589
|
+
// imported into crouter config). A key tracked in the manifest is crouter's
|
|
590
|
+
// own and left alone; a foreign non-hl binding never matches the markers and
|
|
591
|
+
// is preserved. Idempotent: with no file and no untracked hl binding, a no-op.
|
|
592
|
+
function removeLegacyInboxBindings(manifestPairs) {
|
|
593
|
+
const owned = new Set(manifestPairs.filter((pair) => pair.table === ROOT_TABLE).map((pair) => pair.key));
|
|
594
|
+
const keys = new Set([LEGACY_INBOX_DEFAULT_KEY]);
|
|
595
|
+
const file = legacyInboxKeyFile();
|
|
596
|
+
try {
|
|
597
|
+
const configured = readFileSync(file, 'utf8').trim();
|
|
598
|
+
if (configured !== '')
|
|
599
|
+
keys.add(configured);
|
|
600
|
+
}
|
|
601
|
+
catch { /* no state file: only the default key can hold a stale binding */ }
|
|
602
|
+
for (const key of keys) {
|
|
603
|
+
if (owned.has(key))
|
|
604
|
+
continue;
|
|
605
|
+
const existing = bindingAt(ROOT_TABLE, key);
|
|
606
|
+
if (existing !== null && LEGACY_INBOX_MARKERS.every((marker) => existing.includes(marker))) {
|
|
607
|
+
tmux(['unbind-key', '-T', ROOT_TABLE, key]);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
try {
|
|
611
|
+
rmSync(file, { force: true });
|
|
612
|
+
}
|
|
613
|
+
catch { /* best-effort */ }
|
|
614
|
+
}
|
|
563
615
|
function actionCommand(id) {
|
|
564
616
|
switch (id) {
|
|
565
617
|
case 'crtr.tmux.node.next': return ['run-shell', `crtr node cycle --dir next --pane '#{pane_id}' >/dev/null 2>&1`];
|
|
566
618
|
case 'crtr.tmux.node.previous': return ['run-shell', `crtr node cycle --dir prev --pane '#{pane_id}' >/dev/null 2>&1`];
|
|
619
|
+
case 'crtr.tmux.inbox.toggle': return inboxToggleTmuxCommand();
|
|
567
620
|
case 'crtr.tmux.view.next': return ['run-shell', `crtr surface view cycle --dir next --pane '#{pane_id}' >/dev/null 2>&1`];
|
|
568
621
|
case 'crtr.tmux.view.previous': return ['run-shell', `crtr surface view cycle --dir prev --pane '#{pane_id}' >/dev/null 2>&1`];
|
|
569
622
|
default: throw new Error(`no tmux command for ${id}`);
|
|
@@ -580,6 +633,7 @@ export function installTmuxBindings(bindings = resolveUserKeybindings()) {
|
|
|
580
633
|
}
|
|
581
634
|
if (!manifest.existed)
|
|
582
635
|
adoptLegacyBindings();
|
|
636
|
+
removeLegacyInboxBindings(manifest.pairs);
|
|
583
637
|
for (const pair of manifest.pairs) {
|
|
584
638
|
const result = tmux(['unbind-key', '-T', pair.table, pair.key]);
|
|
585
639
|
if (!result.ok && bindingAt(pair.table, pair.key) !== null) {
|
|
@@ -606,7 +660,7 @@ export function installTmuxBindings(bindings = resolveUserKeybindings()) {
|
|
|
606
660
|
for (const gesture of bindings.gestures('crtr.tmux.menu.open')) {
|
|
607
661
|
install(ROOT_TABLE, tmuxKey(gesture), menuCommand, 'crtr.tmux.menu.open', gesture);
|
|
608
662
|
}
|
|
609
|
-
for (const id of ['crtr.tmux.node.next', 'crtr.tmux.node.previous']) {
|
|
663
|
+
for (const id of ['crtr.tmux.node.next', 'crtr.tmux.node.previous', 'crtr.tmux.inbox.toggle']) {
|
|
610
664
|
for (const gesture of bindings.gestures(id))
|
|
611
665
|
install(ROOT_TABLE, tmuxKey(gesture), actionCommand(id), id, gesture);
|
|
612
666
|
}
|
package/dist/daemon/crtrd.js
CHANGED
|
@@ -56,7 +56,7 @@ import { dirname, join } from 'node:path';
|
|
|
56
56
|
import { homedir } from 'node:os';
|
|
57
57
|
import { spawnSync } from 'node:child_process';
|
|
58
58
|
import { crtrHome, nodeDir, jobDir } from '../core/canvas/paths.js';
|
|
59
|
-
import { listNodes, getRow, getNode, dueClockTriggers, consumeTrigger, advanceTrigger, listFocuses, closeFocusRow, pruneToLimit, subscribersOf, } from '../core/canvas/index.js';
|
|
59
|
+
import { listNodes, getRow, getNode, migrateLegacyPidIdentities, dueClockTriggers, consumeTrigger, advanceTrigger, listFocuses, closeFocusRow, pruneToLimit, subscribersOf, } from '../core/canvas/index.js';
|
|
60
60
|
import { fullName } from '../core/canvas/labels.js';
|
|
61
61
|
import { transition } from '../core/runtime/lifecycle.js';
|
|
62
62
|
import { isBusy, busySince } from '../core/runtime/busy.js';
|
|
@@ -65,7 +65,7 @@ import { fanDoctrineWake } from '../core/runtime/close.js';
|
|
|
65
65
|
import { logger } from '../core/log.js';
|
|
66
66
|
export { FAULT_QUIET_MS };
|
|
67
67
|
import { isPidAlive, isRecordedPidAlive, recordedPidLiveness } from '../core/canvas/pid.js';
|
|
68
|
-
import {
|
|
68
|
+
import { reconcileAndMigrateBoot } from '../core/canvas/boot.js';
|
|
69
69
|
import { listLivePanes, tearDownNode } from '../core/runtime/placement.js';
|
|
70
70
|
import { reviveNode } from '../core/runtime/revive.js';
|
|
71
71
|
import { isBrokerLive } from '../core/runtime/model-swap.js';
|
|
@@ -1614,9 +1614,33 @@ export function runDaemon(opts = {}) {
|
|
|
1614
1614
|
// "leave it, nothing to revive" and never calls reviveNode at all — a
|
|
1615
1615
|
// pid-reuse collision on the first post-boot tick would silently no-op
|
|
1616
1616
|
// forever with no revive attempt to even hit reviveNode's own reconcile call.
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1617
|
+
//
|
|
1618
|
+
// Ordering + gate live in reconcileAndMigrateBoot (canvas/boot.ts) so the
|
|
1619
|
+
// migration-gate regression tests exercise the real composition rather than a
|
|
1620
|
+
// test-side copy of these lines.
|
|
1621
|
+
const { reconcile, migrated } = reconcileAndMigrateBoot(migrateLegacyPidIdentities);
|
|
1622
|
+
if (reconcile.changed) {
|
|
1623
|
+
process.stderr.write(`[crtrd] boot change detected — cleared ${reconcile.cleared.length} stale pi_pid(s) recorded before this boot\n`);
|
|
1624
|
+
}
|
|
1625
|
+
// Then, once, complete the boot-scoped-identity format migration for any
|
|
1626
|
+
// broker that survived an in-place crouter upgrade and still carries a legacy
|
|
1627
|
+
// `lstart#ticks` baseline: re-record it as `<bootId>#<ticks>` if its pid still
|
|
1628
|
+
// names the same live process. `identitiesMatch` only TOLERATES legacy rows;
|
|
1629
|
+
// this is what actually closes the cross-boot ticks-collision exposure for
|
|
1630
|
+
// them, so the legacy compare lane then only engages for genuinely no-boot_id
|
|
1631
|
+
// hosts.
|
|
1632
|
+
//
|
|
1633
|
+
// GATED on PROVEN same-boot provenance: the sweep blesses a legacy row's pid
|
|
1634
|
+
// as a current-boot process (`<currentBootId>#<ticks>`) on a ticks match, so
|
|
1635
|
+
// it is correct ONLY when the recorded pid provably belongs to THIS boot. We
|
|
1636
|
+
// run it solely when reconciliation matched an exact kernel `boot_id` on both
|
|
1637
|
+
// sides (`sameBootProven`) — never on a first-ever/absent/malformed marker or
|
|
1638
|
+
// the wall-clock epoch fallback, where an equal-ticks collision with an
|
|
1639
|
+
// unrelated cross-boot process could otherwise baptize a stranger. (On a
|
|
1640
|
+
// detected boot change the prior-boot pids were just cleared, so there is
|
|
1641
|
+
// nothing left to migrate either.)
|
|
1642
|
+
if (migrated.length > 0) {
|
|
1643
|
+
process.stderr.write(`[crtrd] migrated ${migrated.length} legacy pi_pid identity baseline(s) to boot-scoped format\n`);
|
|
1620
1644
|
}
|
|
1621
1645
|
writePidfile();
|
|
1622
1646
|
log.info(`started (pid ${process.pid}, interval ${interval}ms)`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crouton-kit/crouter",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.84",
|
|
4
4
|
"description": "crtr — agent runtime with memory, plugins, and marketplaces",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
},
|
|
55
55
|
"license": "MIT",
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@crouton-kit/humanloop": "^0.3.
|
|
57
|
+
"@crouton-kit/humanloop": "^0.3.36",
|
|
58
58
|
"@earendil-works/pi-agent-core": "0.80.6",
|
|
59
59
|
"@earendil-works/pi-ai": "0.80.6",
|
|
60
60
|
"@earendil-works/pi-coding-agent": "0.80.6",
|