Skip to content

Commit 71516d3

Browse files
committed
Merge latest main into GetPaneContext optimization
Preserve consolidated context dispatch alongside upstream hook listener changes and reconcile release checklist IDs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 77616472-cc8d-4566-9050-60ab09248076
2 parents bc384b9 + e90ab68 commit 71516d3

14 files changed

Lines changed: 2130 additions & 475 deletions

File tree

doc/release-check-list.md

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -234,14 +234,14 @@ Net effect: UT shrinks the manual matrix to "did the wiring and UI connect", not
234234

235235
### Shell integration and detection
236236

237-
- [ ] `C296` `[new]` `[E2E]` **Detected Autofix clicks remain isolated between tabs:** With errors detected in two tabs, clicking one tab's diagnostics button submits exactly one prompt for that tab and preserves the other tab's pending opt-in. _(E2E: `Feature.AutofixRouting`.)_
238-
- [ ] `C297` `[new]` `[E2E]` **Pane context captures the completed marked command:** A single context request returns the source pane metadata together with the completed command and its error output. _(#838; E2E: `Feature.PaneContext`.)_
239-
- [ ] `C298` `[new]` `[E2E]` **Pane context falls back to the newest unmarked output:** Shells without command marks return a bounded recent buffer tail with an explicit fallback reason. _(#838; E2E: `Feature.PaneContext`.)_
240-
- [ ] `C299` `[new]` `[E2E]` **Explicit pane context stays isolated from the focused tab and split:** Explicit context requests read the requested pane even while a different tab or split is focused. _(#838; E2E: `Feature.PaneContext`.)_
241-
- [ ] `C300` `[new]` `[E2E]` **Missing and closed pane context fails without active-pane fallback:** Stale or unknown pane IDs fail instead of leaking another pane's context. _(#838; E2E: `Feature.PaneContext`.)_
242-
- [ ] `C301` `[new]` `[E2E]` **Pane context metadata-only requests omit terminal content:** A zero line or character budget returns only pane metadata. _(#838; E2E: `Feature.PaneContext`.)_
243-
- [ ] `C302` `[new]` `[E2E]` **Pane context bounds preserve Unicode and truthful truncation:** Marked-command and buffer-tail captures honor their limits without splitting Unicode characters or hiding truncation. _(#838; E2E: `Feature.PaneContext`.)_
244-
- [ ] `C303` `[new]` `[E2E]` **Focused agent pane context resolves to its source terminal:** Default context requests use the agent pane's source shell, while explicit agent-pane requests fail. _(#838; E2E: `Feature.PaneContext`.)_
237+
- [ ] `C299` `[new]` `[E2E]` **Detected Autofix clicks remain isolated between tabs:** With errors detected in two tabs, clicking one tab's diagnostics button submits exactly one prompt for that tab and preserves the other tab's pending opt-in. _(E2E: `Feature.AutofixRouting`.)_
238+
- [ ] `C300` `[new]` `[E2E]` **Pane context captures the completed marked command:** A single context request returns the source pane metadata together with the completed command and its error output. _(#838; E2E: `Feature.PaneContext`.)_
239+
- [ ] `C301` `[new]` `[E2E]` **Pane context falls back to the newest unmarked output:** Shells without command marks return a bounded recent buffer tail with an explicit fallback reason. _(#838; E2E: `Feature.PaneContext`.)_
240+
- [ ] `C302` `[new]` `[E2E]` **Explicit pane context stays isolated from the focused tab and split:** Explicit context requests read the requested pane even while a different tab or split is focused. _(#838; E2E: `Feature.PaneContext`.)_
241+
- [ ] `C303` `[new]` `[E2E]` **Missing and closed pane context fails without active-pane fallback:** Stale or unknown pane IDs fail instead of leaking another pane's context. _(#838; E2E: `Feature.PaneContext`.)_
242+
- [ ] `C304` `[new]` `[E2E]` **Pane context metadata-only requests omit terminal content:** A zero line or character budget returns only pane metadata. _(#838; E2E: `Feature.PaneContext`.)_
243+
- [ ] `C305` `[new]` `[E2E]` **Pane context bounds preserve Unicode and truthful truncation:** Marked-command and buffer-tail captures honor their limits without splitting Unicode characters or hiding truncation. _(#838; E2E: `Feature.PaneContext`.)_
244+
- [ ] `C306` `[new]` `[E2E]` **Focused agent pane context resolves to its source terminal:** Default context requests use the agent pane's source shell, while explicit agent-pane requests fail. _(#838; E2E: `Feature.PaneContext`.)_
245245

246246
- [ ] `C087` `[E2E]` **PowerShell shell integration installed:** Supported PowerShell profiles emit command-finished events, including non-zero marks for PowerShell-level failures on Windows PowerShell 5.1.
247247
- [ ] `C219` `[new]` `[E2E]` **Bash / WSL shell integration installed:** Supported bash and WSL-bash profiles emit command-finished events, and the injected `PROMPT_COMMAND` is safe under `set -u` (no errors in strict-mode shells). _(#340.)_
@@ -402,6 +402,9 @@ Net effect: UT shrinks the manual matrix to "did the wiring and UI connect", not
402402
- [ ] `C270` `[new]` `[E2E]` **Legacy hook bundle still delivers after an upgrade:** Hooks installed by a pre-#571 Terminal keep reaching a post-#571 Terminal, because `wtcli send-event` and the `agent_event` envelope stayed compatible. _(#571; the installed bundle is a copy in the CLI's plugin cache that an upgrade never rewrites, and the auto-refresh can fail while a CLI process holds the plugin directory open.)_
403403
- [ ] `C271` `[new]` `[E2E]` **Legacy hook bundle degrades quietly without Terminal:** With `WT_COM_CLSID` unset — the state an uninstall leaves — a stale pre-#571 hook exits 0, prints nothing, and publishes nothing. _(#571.)_
404404
- [ ] `C278` `[new]` `[E2E]` **Legacy hook bundle without WT_SESSION stays unattributed:** A legacy PowerShell hook whose process never inherited `WT_SESSION` still publishes, but with an empty `pane_id` instead of the focused pane's — so it cannot evict the focused pane's real session or misdirect Enter in the session list. _(#657; `wtcli send-event` no longer falls back to `GetActivePane()`.)_
405+
- [ ] `C296` `[new]` `[UT✓]` `[E2E]` **One hook broadcast applies once per helper fan-out:** One `wtcli agent-hook` invocation reaches master and every connected helper over the COM broadcast; master applies its own copy exactly once, while helpers update only their local pane bindings and never forward the hook over their named pipes. _(#761; UT: `master_com_agent_event_routes_directly_into_the_registry` + `helper_agent_event_updates_local_binding_without_forwarding`; E2E adds the real multi-process fan-out those unit tests cannot span.)_
406+
- [ ] `C297` `[new]` `[UT✓]` `[E2E]` **Terminal hook for an unknown session creates no row:** An `agent.session.end` for a session WTA never saw start leaves no session row, so no permanently unprunable `Ended` entry titled after the cwd basename appears in the picker. _(#761; UT: `terminal_agent_event_for_unknown_session_does_not_fabricate_a_row`.)_
407+
- [ ] `C298` `[new]` `[UT✓]` `[E2E]` **Agent error for an unknown session still records the failure:** `agent.error` reports a live but failing session, so it must keep creating the row its pane-keyed reducer needs — excluding it with the terminal events would silently drop a first-observed connection failure. _(#761; UT: `agent_error_for_unknown_session_still_records_the_failure`.)_
405408
- [ ] `C172` `[E2E]` **Hook remove works:** Removing a hook disables future session tracking for that CLI.
406409
- [ ] `C173` `[UT✓]` `[E2E]` **Partial or disabled hooks are repaired:** Reconciliation routes incomplete hook state through the install path and reports a failure if the agent CLI cannot repair it. _(UT: `install_action_installs_any_partial_bridge`.)_
407410
- [x] `C174` `[UT✓]` `[E2E]` **Hook auto-upgrade works:** Reconciliation updates an installed stale hook when its bundle version or registration path changes. _(UT: `install_action_upgrades_a_complete_but_outdated_bridge` + registration-path tests.)_

src/tools/wtcli/main.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,11 +1128,13 @@ int wmain(int argc, wchar_t** argv)
11281128
// ── listen ──
11291129
std::string listenTarget;
11301130
std::string listenEventFilter;
1131+
std::string listenReadyToken;
11311132
DWORD listenParentPid = 0;
11321133
auto* listenCmd = app.add_subcommand("listen", "Stream real-time events from Windows Terminal");
11331134
listenCmd->add_option("-t,--target", listenTarget, "Filter by session ID (GUID)");
11341135
listenCmd->add_option("--event", listenEventFilter, "Filter by event type (supports trailing wildcard, e.g. agent.*)");
11351136
listenCmd->add_option("--parent-pid", listenParentPid, "Exit when the specified parent process exits");
1137+
listenCmd->add_option("--ready-token", listenReadyToken, "Emit an internal JSON readiness marker after Subscribe succeeds");
11361138
listenCmd->callback([&]() {
11371139
wil::unique_handle parentProcess;
11381140
if (listenParentPid != 0)
@@ -1187,6 +1189,16 @@ int wmain(int argc, wchar_t** argv)
11871189
exitCode = 1;
11881190
return;
11891191
}
1192+
if (!listenReadyToken.empty())
1193+
{
1194+
Json::Value ready{ Json::objectValue };
1195+
ready["_wtcli"] = "listener_ready";
1196+
ready["token"] = listenReadyToken;
1197+
Json::StreamWriterBuilder writer;
1198+
writer["indentation"] = "";
1199+
printf("%s\n", Json::writeString(writer, ready).c_str());
1200+
fflush(stdout);
1201+
}
11901202

11911203
DWORD waitResult = WAIT_OBJECT_0;
11921204
if (parentProcess)

test/e2e/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ authenticated ACP agents. Current status (run on the Store package):
4646
| `Feature.AgentProposalFocus.Tests.ps1` | PR #533: Insert returns real window keyboard focus to the target shell pane | 1 |
4747
| `Feature.AgentMatrix.Tests.ps1` | §2 non-Copilot built-in agents (Claude/Codex/Gemini) connect+chat through the ACP adapter — ONE consolidated case (Copilot is the in-depth suite); skips when none installed+authed | 1 |
4848
| `Feature.HookTrace.Tests.ps1` | C190 + PR #571 C267-C269, C272: every shipped bundle's guarded command still delivers, `tool_input` survives only for interactive prompts, shells outside Terminal are ignored, and the broadcast envelope stays inside its budget | 5 |
49+
| `Feature.SessionHookRouting.Tests.ps1` | PR #761: master consumes one `wtcli agent-hook` COM broadcast directly while multiple helpers update only local pane bindings, a terminal hook for an unseen session fabricates no row, and `agent.error` still records the failure | 3 |
4950
| `Feature.HookBridgeCli.Tests.ps1` | PR #571 C274, C265, C266: a real agent CLI fires the bundled `hooks.json` command through its own shell, and neither an unreachable protocol server nor an uninstalled Terminal blocks the CLI; skips when the CLI isn't installed+authed | 3 (environment-gated) |
5051
| `Feature.LegacyHookBundle.Tests.ps1` | PR #571 C270-C271: a pre-#571 PowerShell hook bundle still delivers against a post-#571 Terminal, and degrades quietly when `WT_COM_CLSID` is unset | 2 |
5152
| `Feature.OpenCodeHookBridge.Tests.ps1` | PR #571 C273: OpenCode's JS plugin spawns `wtcli` through an argv array with no shell, so it resolves the bridge via `WTCLI_PATH` rather than the `PATH` alias | 1 (environment-gated) |

0 commit comments

Comments
 (0)