@webpresso/agent-kit 3.1.26 → 3.1.30

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.
Files changed (150) hide show
  1. package/catalog/AGENTS.md.tpl +7 -11
  2. package/catalog/agent/commands/verify.md +2 -2
  3. package/catalog/agent/rules/changeset-release.md +4 -2
  4. package/catalog/agent/rules/ci-cost-local-first.md +139 -0
  5. package/catalog/agent/rules/ci-test-perf.md +5 -1
  6. package/catalog/agent/rules/cmd-execution.md +9 -0
  7. package/catalog/agent/rules/pre-implementation.md +2 -1
  8. package/catalog/agent/rules/test-scan-perf.md +80 -0
  9. package/catalog/agent/rules/workflow-skills-routing.md +9 -4
  10. package/catalog/agent/skills/autopilot/SKILL.md +48 -11
  11. package/catalog/agent/skills/claude/SKILL.md +7 -0
  12. package/catalog/agent/skills/codex/SKILL.md +7 -0
  13. package/catalog/agent/skills/fix/SKILL.md +36 -8
  14. package/catalog/agent/skills/grok/SKILL.md +7 -0
  15. package/catalog/agent/skills/investigate/SKILL.md +12 -1
  16. package/catalog/agent/skills/pll/SKILL.md +53 -48
  17. package/catalog/agent/skills/team/SKILL.md +26 -9
  18. package/catalog/agent/skills/ultragoal/SKILL.md +147 -19
  19. package/catalog/agent/skills/verify/SKILL.md +89 -51
  20. package/dist/esm/audit/blueprint-lifecycle-sql.d.ts +8 -0
  21. package/dist/esm/audit/blueprint-lifecycle-sql.js +25 -1
  22. package/dist/esm/audit/blueprint-pr-coverage.js +68 -7
  23. package/dist/esm/audit/registry.d.ts +4 -4
  24. package/dist/esm/audit/registry.js +3 -0
  25. package/dist/esm/audit/roadmap-links.js +6 -0
  26. package/dist/esm/audit/test-scan-perf.d.ts +18 -0
  27. package/dist/esm/audit/test-scan-perf.js +275 -0
  28. package/dist/esm/blueprint/lifecycle/engine.d.ts +9 -0
  29. package/dist/esm/blueprint/lifecycle/engine.js +53 -6
  30. package/dist/esm/blueprint/lifecycle/review-provenance.d.ts +6 -0
  31. package/dist/esm/blueprint/lifecycle/review-provenance.js +93 -12
  32. package/dist/esm/blueprint/markdown/helpers.js +6 -2
  33. package/dist/esm/ci/act-replay.js +110 -7
  34. package/dist/esm/ci/act-runner.d.ts +4 -0
  35. package/dist/esm/ci/act-runner.js +85 -26
  36. package/dist/esm/ci/act-worktree-git.d.ts +11 -0
  37. package/dist/esm/ci/act-worktree-git.js +219 -0
  38. package/dist/esm/ci/native-session-memory-cache.d.ts +9 -1
  39. package/dist/esm/ci/native-session-memory-cache.js +9 -1
  40. package/dist/esm/ci/vitest-ci-shards.d.ts +6 -4
  41. package/dist/esm/ci/vitest-ci-shards.js +6 -4
  42. package/dist/esm/cli/auto-update/guard-tombstone.d.ts +25 -0
  43. package/dist/esm/cli/auto-update/guard-tombstone.js +67 -0
  44. package/dist/esm/cli/auto-update/installer.d.ts +4 -17
  45. package/dist/esm/cli/auto-update/installer.js +6 -57
  46. package/dist/esm/cli/auto-update/self-invocation.d.ts +37 -0
  47. package/dist/esm/cli/auto-update/self-invocation.js +62 -0
  48. package/dist/esm/cli/commands/audit.js +4 -0
  49. package/dist/esm/cli/commands/blueprint/mutations.js +35 -18
  50. package/dist/esm/cli/commands/blueprint/router.js +27 -2
  51. package/dist/esm/cli/commands/ci.d.ts +8 -1
  52. package/dist/esm/cli/commands/ci.js +80 -21
  53. package/dist/esm/cli/commands/dash/index.js +3 -3
  54. package/dist/esm/cli/commands/dash/keymap.js +1 -0
  55. package/dist/esm/cli/commands/dash/launch-preferences.d.ts +15 -0
  56. package/dist/esm/cli/commands/dash/launch-preferences.js +46 -17
  57. package/dist/esm/cli/commands/dash/plan-once-attention.d.ts +32 -0
  58. package/dist/esm/cli/commands/dash/plan-once-attention.js +50 -0
  59. package/dist/esm/cli/commands/dash/plan-once-label.d.ts +7 -0
  60. package/dist/esm/cli/commands/dash/plan-once-label.js +5 -0
  61. package/dist/esm/cli/commands/dash/plan-once-membership.d.ts +67 -0
  62. package/dist/esm/cli/commands/dash/plan-once-membership.js +151 -0
  63. package/dist/esm/cli/commands/dash/plan-once-merge.d.ts +143 -0
  64. package/dist/esm/cli/commands/dash/plan-once-merge.js +238 -0
  65. package/dist/esm/cli/commands/dash/plan-once-schema.d.ts +73 -0
  66. package/dist/esm/cli/commands/dash/plan-once-schema.js +119 -0
  67. package/dist/esm/cli/commands/dash/plan-once.d.ts +142 -0
  68. package/dist/esm/cli/commands/dash/plan-once.js +261 -0
  69. package/dist/esm/cli/commands/dash/tui/attention-hud.d.ts +9 -0
  70. package/dist/esm/cli/commands/dash/tui/attention-hud.js +9 -0
  71. package/dist/esm/cli/commands/dash/tui/chat-bridge.d.ts +41 -0
  72. package/dist/esm/cli/commands/dash/tui/chat-bridge.js +73 -0
  73. package/dist/esm/cli/commands/dash/tui/chat-mode.d.ts +47 -0
  74. package/dist/esm/cli/commands/dash/tui/chat-mode.js +98 -0
  75. package/dist/esm/cli/commands/dash/tui/frame.d.ts +3 -0
  76. package/dist/esm/cli/commands/dash/tui/frame.js +3 -1
  77. package/dist/esm/cli/commands/dash/tui/ipc-protocol.d.ts +87 -0
  78. package/dist/esm/cli/commands/dash/tui/ipc-protocol.js +128 -0
  79. package/dist/esm/cli/commands/dash/tui/native-host.d.ts +34 -0
  80. package/dist/esm/cli/commands/dash/tui/native-host.js +256 -0
  81. package/dist/esm/cli/commands/dash/tui/native-path.d.ts +11 -0
  82. package/dist/esm/cli/commands/dash/tui/native-path.js +41 -0
  83. package/dist/esm/cli/commands/dash/tui/palette.d.ts +1 -1
  84. package/dist/esm/cli/commands/dash/tui/palette.js +14 -0
  85. package/dist/esm/cli/commands/dash/tui/runtime.js +311 -4
  86. package/dist/esm/cli/commands/dash/tui/state.d.ts +41 -0
  87. package/dist/esm/cli/commands/dash/tui/state.js +257 -4
  88. package/dist/esm/cli/commands/format.js +0 -2
  89. package/dist/esm/cli/commands/init/config.d.ts +0 -1
  90. package/dist/esm/cli/commands/init/config.js +1 -4
  91. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/emitters/claude.d.ts +5 -6
  92. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/emitters/claude.js +6 -13
  93. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/ir.d.ts +0 -2
  94. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/ir.js +0 -2
  95. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/merge.d.ts +6 -3
  96. package/dist/esm/cli/commands/init/scaffolders/agent-hooks/merge.js +39 -26
  97. package/dist/esm/cli/commands/init/scaffolders/agent-kit-global/index.js +1 -1
  98. package/dist/esm/cli/commands/init/scaffolders/codex-mcp/index.js +61 -23
  99. package/dist/esm/cli/commands/logs.d.ts +15 -0
  100. package/dist/esm/cli/commands/logs.js +192 -3
  101. package/dist/esm/cli/commands/package-manager.js +2 -1
  102. package/dist/esm/cli/commands/quality-log-store.d.ts +1 -0
  103. package/dist/esm/cli/commands/quality-log-store.js +187 -51
  104. package/dist/esm/cli/commands/review.js +5 -8
  105. package/dist/esm/cli/commands/secrets.d.ts +1 -0
  106. package/dist/esm/cli/commands/secrets.js +4 -1
  107. package/dist/esm/cli/commands/self-install-guard.d.ts +14 -32
  108. package/dist/esm/cli/commands/self-install-guard.js +17 -63
  109. package/dist/esm/cli/direct-provider-launch.js +25 -1
  110. package/dist/esm/hooks/doctor.d.ts +15 -0
  111. package/dist/esm/hooks/doctor.js +56 -0
  112. package/dist/esm/hooks/guard-switch/index.js +8 -4
  113. package/dist/esm/hooks/post-tool/lint-after-edit.js +6 -4
  114. package/dist/esm/hooks/precompact/index.js +5 -3
  115. package/dist/esm/hooks/pretool-guard/validators/forbidden-commands.js +4 -4
  116. package/dist/esm/hooks/pretool-guard/validators/mcp-redirect.d.ts +0 -1
  117. package/dist/esm/hooks/pretool-guard/validators/mcp-redirect.js +8 -5
  118. package/dist/esm/hooks/pretool-guard/validators/worktree-discipline.d.ts +9 -7
  119. package/dist/esm/hooks/pretool-guard/validators/worktree-discipline.js +126 -14
  120. package/dist/esm/hooks/sessionstart/index.d.ts +10 -0
  121. package/dist/esm/hooks/sessionstart/index.js +61 -4
  122. package/dist/esm/hooks/shared/types.d.ts +11 -0
  123. package/dist/esm/hooks/shared/types.js +21 -0
  124. package/dist/esm/mcp/tools/_shared/audit-kinds.d.ts +1 -1
  125. package/dist/esm/mcp/tools/audit.d.ts +2 -1
  126. package/dist/esm/mcp/tools/audit.js +10 -0
  127. package/dist/esm/mcp/tools/audits.d.ts +1 -0
  128. package/dist/esm/mcp/tools/ci-act.js +9 -11
  129. package/dist/esm/paths/state-root.js +9 -0
  130. package/dist/esm/review/authority.js +17 -2
  131. package/dist/esm/review/availability.js +18 -5
  132. package/dist/esm/review/subject.d.ts +15 -0
  133. package/dist/esm/review/subject.js +105 -10
  134. package/dist/esm/runtime/executor.d.ts +1 -0
  135. package/dist/esm/runtime/executor.js +2 -1
  136. package/dist/esm/secret-gate/runner.d.ts +1 -0
  137. package/dist/esm/secret-gate/runner.js +4 -1
  138. package/dist/esm/session-memory/current-session.js +2 -0
  139. package/dist/esm/session-memory/native-runtime.js +5 -3
  140. package/dist/esm/session-memory/native-warm-markers.d.ts +18 -0
  141. package/dist/esm/session-memory/native-warm-markers.js +22 -0
  142. package/dist/esm/session-memory/sync/types.d.ts +4 -0
  143. package/dist/esm/session-memory/types.d.ts +3 -1
  144. package/dist/esm/session-memory/types.js +2 -0
  145. package/dist/esm/ultragoal/runtime.js +44 -2
  146. package/dist/esm/worktrees/current.d.ts +1 -0
  147. package/dist/esm/worktrees/current.js +1 -0
  148. package/dist/esm/worktrees/project-agent-surfaces.d.ts +1 -0
  149. package/dist/esm/worktrees/project-agent-surfaces.js +2 -1
  150. package/package.json +17 -14
@@ -0,0 +1,256 @@
1
+ // Domain host for the native Ratatui shell: maps AppViewModel ↔ IPC and keys → reduceTuiKey.
2
+ import { spawn } from "node:child_process";
3
+ import { emitDashE2eState } from "#cli/commands/dash/e2e-state.js";
4
+ import { buildRows } from "#cli/commands/dash/menu-state.js";
5
+ import { filterPaletteCommands, groupPaletteCommands } from "#cli/commands/dash/tui/palette.js";
6
+ import { reduceTuiKey } from "#cli/commands/dash/tui/state.js";
7
+ import { decodeIpcFrames, encodeIpcFrame, parseClientMessage, } from "#cli/commands/dash/tui/ipc-protocol.js";
8
+ import { sanitizeTuiText } from "#cli/commands/dash/tui/sanitize.js";
9
+ function hostAvailabilityNote(agentKey, availability) {
10
+ const row = availability.find((item) => item.id === agentKey);
11
+ if (!row || row.available)
12
+ return null;
13
+ return row.reason ?? "unavailable";
14
+ }
15
+ export function projectNativeViewModel(state, input) {
16
+ const rows = buildRows(state.agents, state.menu.expandedAgent);
17
+ const menuLines = rows.map((row) => {
18
+ const mark = row.key === state.menu.selectedKey ? "▸" : " ";
19
+ const note = row.kind === "agent" ? hostAvailabilityNote(row.agentKey, state.hostAvailability) : null;
20
+ const label = note ? `${row.label} · ${note}` : row.label;
21
+ return sanitizeTuiText(`${mark} ${label}`);
22
+ });
23
+ let overlayKind = state.overlay.kind;
24
+ let overlayLines = [];
25
+ if (state.overlay.kind === "palette") {
26
+ const matches = filterPaletteCommands(state.overlay.query);
27
+ const groups = groupPaletteCommands(matches);
28
+ overlayLines = [sanitizeTuiText(`query: ${state.overlay.query || "…"}`)];
29
+ for (const group of groups) {
30
+ overlayLines.push(sanitizeTuiText(`— ${group.category}`));
31
+ for (const [index, command] of group.commands.entries()) {
32
+ // Approximate global cursor: mark the selected match row.
33
+ const globalIndex = matches.indexOf(command);
34
+ const mark = globalIndex === state.overlay.cursor ? "▸" : " ";
35
+ overlayLines.push(sanitizeTuiText(`${mark} ${command.title} · ${command.keys}`));
36
+ void index;
37
+ }
38
+ }
39
+ if (matches.length === 0) {
40
+ overlayLines.push("(no matches)");
41
+ }
42
+ }
43
+ else if (state.overlay.kind === "help") {
44
+ overlayLines = [
45
+ "^p palette",
46
+ "^o mode",
47
+ "^s sessions",
48
+ "^x help",
49
+ "j/k move · h/l fold · g/G jump",
50
+ "q quit",
51
+ ];
52
+ }
53
+ else if (state.overlay.kind === "wizard") {
54
+ overlayLines = state.overlay.lines.map((line) => sanitizeTuiText(line));
55
+ }
56
+ else if (state.overlay.kind === "browser") {
57
+ overlayLines = state.overlay.lines.map((line) => sanitizeTuiText(line));
58
+ }
59
+ else if (state.overlay.kind === "lifecycle") {
60
+ overlayLines = [
61
+ sanitizeTuiText(`target ${state.overlay.target}`),
62
+ "d detach · s stop · f force-kill · a archive",
63
+ "Backspace delete · y confirm · Esc cancel",
64
+ ];
65
+ }
66
+ return {
67
+ repoLabel: sanitizeTuiText(input.repoLabel),
68
+ width: input.width,
69
+ height: input.height,
70
+ permissionMode: state.permissionMode,
71
+ hostAvailability: state.hostAvailability.map((h) => ({
72
+ id: h.id,
73
+ available: h.available,
74
+ ...(h.reason ? { reason: sanitizeTuiText(h.reason) } : {}),
75
+ })),
76
+ status: state.status ? sanitizeTuiText(state.status) : null,
77
+ warnings: state.warnings.map((w) => sanitizeTuiText(w)),
78
+ menuLines,
79
+ overlayKind,
80
+ overlayLines,
81
+ paletteQuery: state.overlay.kind === "palette" ? state.overlay.query : null,
82
+ };
83
+ }
84
+ export function clientMessageToParsedKey(message) {
85
+ switch (message.kind) {
86
+ case "char":
87
+ return message.value ? { kind: "char", value: message.value } : null;
88
+ case "up":
89
+ case "down":
90
+ case "left":
91
+ case "right":
92
+ case "enter":
93
+ case "escape":
94
+ case "tab":
95
+ case "backspace":
96
+ return { kind: message.kind };
97
+ case "ctrl":
98
+ return message.value ? { kind: "ctrl", value: message.value } : null;
99
+ default:
100
+ return null;
101
+ }
102
+ }
103
+ /**
104
+ * Drive pure TUI state from a native binary over length-prefixed JSON frames.
105
+ * State is owned by the caller (runtime) so launch/HUD/browser updates paint.
106
+ */
107
+ export async function runNativeTuiHost(input) {
108
+ const spawnFn = input.spawnImpl ?? spawn;
109
+ const child = spawnFn(input.binaryPath, [], {
110
+ stdio: ["pipe", "pipe", "inherit"],
111
+ });
112
+ if (!child.stdin || !child.stdout) {
113
+ throw new Error("native shell spawn did not provide stdio pipes");
114
+ }
115
+ let stdinBuf = Buffer.alloc(0);
116
+ let width = 80;
117
+ let height = 24;
118
+ const childStdin = child.stdin;
119
+ const childStdout = child.stdout;
120
+ const pushView = () => {
121
+ if (!childStdin.writable)
122
+ return;
123
+ const view = projectNativeViewModel(input.getState(), {
124
+ repoLabel: input.repoLabel,
125
+ width,
126
+ height,
127
+ });
128
+ childStdin.write(encodeIpcFrame({ type: "view", view }));
129
+ };
130
+ input.onBridge?.({ pushView });
131
+ childStdin.write(encodeIpcFrame({ type: "hello", schemaVersion: 1 }));
132
+ pushView();
133
+ /**
134
+ * Handshake hang detection: fail closed if the shell never greets.
135
+ * After ready, probe process liveness so a zombie/stuck native binary
136
+ * cannot pin the domain host forever (runtime falls back to pure-ANSI).
137
+ */
138
+ const HANDSHAKE_MS = 30_000;
139
+ const LIVENESS_MS = 5_000;
140
+ return await new Promise((resolve) => {
141
+ let settled = false;
142
+ let handshakeDone = false;
143
+ let handshakeTimer = setTimeout(() => {
144
+ if (handshakeDone || settled)
145
+ return;
146
+ input.handlers.onQuit();
147
+ child.kill("SIGTERM");
148
+ setTimeout(() => child.kill("SIGKILL"), 2_000);
149
+ finish(1);
150
+ }, HANDSHAKE_MS);
151
+ let livenessTimer;
152
+ const finish = (code) => {
153
+ if (settled)
154
+ return;
155
+ settled = true;
156
+ if (handshakeTimer)
157
+ clearTimeout(handshakeTimer);
158
+ if (livenessTimer)
159
+ clearInterval(livenessTimer);
160
+ resolve(code);
161
+ };
162
+ const armLiveness = () => {
163
+ if (livenessTimer)
164
+ return;
165
+ livenessTimer = setInterval(() => {
166
+ if (settled)
167
+ return;
168
+ // exitCode set when the process has already exited without us finishing.
169
+ if (child.exitCode !== null || child.signalCode !== null) {
170
+ finish(child.exitCode ?? 1);
171
+ return;
172
+ }
173
+ const pid = child.pid;
174
+ if (pid === undefined) {
175
+ finish(1);
176
+ return;
177
+ }
178
+ try {
179
+ process.kill(pid, 0);
180
+ }
181
+ catch {
182
+ finish(1);
183
+ }
184
+ }, LIVENESS_MS);
185
+ };
186
+ childStdout.on("data", (chunk) => {
187
+ stdinBuf = Buffer.concat([stdinBuf, chunk]);
188
+ let decoded;
189
+ try {
190
+ decoded = decodeIpcFrames(stdinBuf);
191
+ }
192
+ catch {
193
+ // Drop a corrupted frame prefix rather than crashing the domain host.
194
+ // Keep a bounded tail so a subsequent well-formed frame can resync.
195
+ stdinBuf = stdinBuf.length > 64 * 1024 ? stdinBuf.subarray(-4096) : Buffer.alloc(0);
196
+ return;
197
+ }
198
+ stdinBuf = Buffer.from(decoded.rest);
199
+ for (const raw of decoded.messages) {
200
+ let msg;
201
+ try {
202
+ msg = parseClientMessage(raw);
203
+ }
204
+ catch {
205
+ continue;
206
+ }
207
+ if (msg.type === "hello" || msg.type === "ready") {
208
+ handshakeDone = true;
209
+ if (handshakeTimer)
210
+ clearTimeout(handshakeTimer);
211
+ armLiveness();
212
+ pushView();
213
+ continue;
214
+ }
215
+ if (msg.type === "resize") {
216
+ width = msg.width;
217
+ height = msg.height;
218
+ pushView();
219
+ continue;
220
+ }
221
+ if (msg.type === "key") {
222
+ const key = clientMessageToParsedKey(msg);
223
+ if (!key)
224
+ continue;
225
+ const result = reduceTuiKey(input.getState(), key);
226
+ input.setState(result.state);
227
+ // Match pure-ANSI path: selection transitions ride the E2E channel so
228
+ // CI tmux harness can assert menu navigation without screen scrapes.
229
+ if (result.state.menu.selectedKey) {
230
+ emitDashE2eState({ kind: "selection", row: result.state.menu.selectedKey });
231
+ }
232
+ for (const effect of result.effects) {
233
+ void input.handlers.onEffect(effect);
234
+ if (effect.kind === "quit") {
235
+ input.handlers.onQuit();
236
+ child.kill("SIGTERM");
237
+ setTimeout(() => child.kill("SIGKILL"), 2_000);
238
+ finish(0);
239
+ return;
240
+ }
241
+ }
242
+ if (result.state.quit) {
243
+ input.handlers.onQuit();
244
+ child.kill("SIGTERM");
245
+ setTimeout(() => child.kill("SIGKILL"), 2_000);
246
+ finish(0);
247
+ return;
248
+ }
249
+ pushView();
250
+ }
251
+ }
252
+ });
253
+ child.on("exit", (code) => finish(code ?? 0));
254
+ child.on("error", () => finish(1));
255
+ });
256
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Env contract:
3
+ * - `WP_DASH_NATIVE=0|false|off` → force pure-ANSI
4
+ * - `WP_DASH_NATIVE=1|true|on` → prefer native when binary present
5
+ * - unset → prefer native when binary present (cutover default)
6
+ * - `WP_DASH_TUI_BIN` → absolute path override
7
+ * - `WP_DASH_FORCE_ANSI=1` → runtime force pure-ANSI even if a binary resolves
8
+ */
9
+ export declare function shouldPreferNativeDashTui(env?: NodeJS.ProcessEnv): boolean;
10
+ export declare function resolveNativeDashTuiBinary(env?: NodeJS.ProcessEnv, candidates?: readonly string[]): string | null;
11
+ export declare function defaultBinaryCandidates(cwd?: string): readonly string[];
@@ -0,0 +1,41 @@
1
+ // Resolve the optional native wp-dash-tui binary for the control-plane shell.
2
+ import { existsSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { findPackageAsset } from "#utils/package-assets.js";
5
+ /**
6
+ * Env contract:
7
+ * - `WP_DASH_NATIVE=0|false|off` → force pure-ANSI
8
+ * - `WP_DASH_NATIVE=1|true|on` → prefer native when binary present
9
+ * - unset → prefer native when binary present (cutover default)
10
+ * - `WP_DASH_TUI_BIN` → absolute path override
11
+ * - `WP_DASH_FORCE_ANSI=1` → runtime force pure-ANSI even if a binary resolves
12
+ */
13
+ export function shouldPreferNativeDashTui(env = process.env) {
14
+ const flag = env["WP_DASH_NATIVE"]?.trim().toLowerCase();
15
+ if (flag === "0" || flag === "false" || flag === "off" || flag === "no") {
16
+ return false;
17
+ }
18
+ return true;
19
+ }
20
+ export function resolveNativeDashTuiBinary(env = process.env, candidates = defaultBinaryCandidates()) {
21
+ const override = env["WP_DASH_TUI_BIN"]?.trim();
22
+ if (override && existsSync(override))
23
+ return override;
24
+ for (const candidate of candidates) {
25
+ if (existsSync(candidate))
26
+ return candidate;
27
+ }
28
+ return null;
29
+ }
30
+ export function defaultBinaryCandidates(cwd = process.cwd()) {
31
+ const fromPackage = [
32
+ findPackageAsset("native/dash-tui/target/release/wp-dash-tui", { cwd }),
33
+ findPackageAsset("native/dash-tui/target/debug/wp-dash-tui", { cwd }),
34
+ ].filter((path) => path !== null);
35
+ return [
36
+ join(cwd, "native/dash-tui/target/release/wp-dash-tui"),
37
+ join(cwd, "native/dash-tui/target/debug/wp-dash-tui"),
38
+ ...fromPackage,
39
+ join(cwd, "bin/wp-dash-tui"),
40
+ ];
41
+ }
@@ -1,4 +1,4 @@
1
- export type PaletteCommandId = "palette.open" | "host.new.claude" | "host.new.codex" | "host.new.grok" | "host.new.opencode" | "sessions.focus" | "wizard.open" | "blueprints.open" | "fleet.open" | "permission.toggle" | "help.open" | "app.quit";
1
+ export type PaletteCommandId = "palette.open" | "host.new.claude" | "host.new.codex" | "host.new.grok" | "host.new.opencode" | "sessions.focus" | "wizard.open" | "blueprints.open" | "fleet.open" | "merge.status" | "chat.mode.toggle" | "chat.mode.open" | "chat.mode.send" | "permission.toggle" | "help.open" | "app.quit";
2
2
  export type PaletteCategory = "Host" | "Session" | "Navigate" | "System";
3
3
  export type PaletteCommand = {
4
4
  readonly id: PaletteCommandId;
@@ -37,6 +37,20 @@ const STATIC_PALETTE_COMMANDS = [
37
37
  keys: "f",
38
38
  keywords: ["fleet", "watch", "status"],
39
39
  },
40
+ {
41
+ id: "merge.status",
42
+ title: "Plan-once merge status matrix",
43
+ category: "Navigate",
44
+ keys: "m",
45
+ keywords: ["merge", "plan-once", "multi-host", "rollup", "status", "matrix"],
46
+ },
47
+ {
48
+ id: "chat.mode.toggle",
49
+ title: "Toggle host-pane / integrated chat",
50
+ category: "Session",
51
+ keys: "c",
52
+ keywords: ["chat", "acp", "integrated", "host-pane", "mode", "pane"],
53
+ },
40
54
  {
41
55
  id: "permission.toggle",
42
56
  title: "Toggle permission mode (safe / always-approve)",