Skip to content

Consolidate bounded pane context with GetPaneContext - #884

Open
Kai Tao (vanzue) wants to merge 2 commits into
mainfrom
dev/vanzue/get-context
Open

Consolidate bounded pane context with GetPaneContext#884
Kai Tao (vanzue) wants to merge 2 commits into
mainfrom
dev/vanzue/get-context

Conversation

@vanzue

@vanzue Kai Tao (vanzue) commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements the consolidated, bounded context operation for #838, named GetPaneContext as agreed during implementation.

  • Append GetPaneContext to the existing COM protocol without changing earlier vtable slots; advertise protocol 2.3 and get_pane_context.
  • Add wtcli get-pane-context, with version/capability negotiation before calling the appended method and validation of targets and capture budgets.
  • Resolve the source pane once inside Terminal and return metadata plus bounded command output, or a bounded recent buffer tail when command marks are unavailable.
  • Route planner, manual /fix, and error-triggered Autofix context collection through WTA -> wtcli -> the existing COM server. No direct Rust COM client and no new COM server.
  • Preserve a logged, capability-gated legacy path for older servers. Ordinary request failures do not retry against another pane.
  • Bound capture at the buffer-reading stage, preserve Unicode, and report truncation accurately, including the newline-lookahead edge case.

The Autofix event-delivery and cross-tab routing fixes were isolated and already merged in #880. They are part of this branch's main baseline, not new fixes in this PR.

Debug benchmark results

Important: this is a same-build comparison of two context-collection paths, not an A/B comparison of two separately built branches.

Both paths ran against the same locally deployed x64 Debug package built from dev/vanzue/get-context, based on main commit db609f8061f81c2eb9a4bdaf3e0666392596bce4, with the feature changes applied:

  • Package: IntelligentTerminal_0.8.0.2_x64__rd9vj3e6a2mbr.
  • Build layout: src\cascadia\CascadiaPackage\bin\x64\Debug\AppX.
  • Both paths used the same packaged wtcli.exe and the same running Terminal/server. Deployed WTA and WindowsTerminal hashes matched the build outputs.
  • Legacy: the benchmark script reproduces the serial collector in main at the baseline commit above, using the old protocol operations. It does not execute a main-built WTA binary. Explicit Autofix retains the old initial active-pane call, followed by window/tab/pane enumeration and output capture. There is no artificially added unsupported-capability probe.
  • Consolidated: one wtcli get-pane-context process captures the context. Authentication and capability negotiation still happen within wtcli; one process does not mean only one raw COM call.
  • Each scenario used the same stable target pane for both paths, five warmup pairs and 40 recorded pairs, alternating execution order. Percentiles use nearest rank and exclude warmups.
  • The measured boundary is the sum of wtcli process startup through exit and stdout/stderr completion. It includes authentication, COM, and capture, but excludes PowerShell JSON processing, full prompt assembly, model inference, and network latency.
Output scenario Entry point wtcli processes, old -> new p50 old (ms) p50 new (ms) p50 reduction p95 old (ms) p95 new (ms)
Completed marked command Planner 2 -> 1 169.97 85.02 50.0% 189.52 93.52
Completed marked command Manual /fix 2 -> 1 166.69 86.80 47.9% 175.63 94.90
Completed marked command Explicit-source Autofix 6 -> 1 495.22 84.72 82.9% 531.50 106.81
Unmarked output, 20 lines Planner 3 -> 1 251.34 85.90 65.8% 269.90 105.12
Unmarked output, 20 lines Manual /fix 3 -> 1 251.44 84.91 66.2% 275.15 90.77
Unmarked output, 20 lines Explicit-source Autofix 8 -> 1 662.46 86.22 87.0% 686.38 103.97
Unmarked output, 8,000-line history Planner 3 -> 1 277.16 84.82 69.4% 296.40 105.08
Unmarked output, 8,000-line history Manual /fix 3 -> 1 277.20 84.21 69.6% 304.57 94.76
Unmarked output, 8,000-line history Explicit-source Autofix 9 -> 1 769.87 85.07 88.9% 803.46 93.45

In these measurements, median context-collection time decreased by 47.9%-88.9%, saving approximately 80-685 ms per collection. The new path's p50 stayed at approximately 84-87 ms.

Interpretation and limits

  • The main benefit is removing repeated wtcli process launches and serial queries, not parallelizing the original calls.
  • Explicit Autofix's legacy request count depends on how many tabs must be visited before finding the source pane. The three fixture panes occupied different positions in the same topology. The 6/8/9 request counts and the largest speedup are scenario-specific, not universal and not solely attributable to scrollback length.
  • Both paths read the same source pane and expected marker. Content/metadata stability was checked for each path across all samples. Bounded output was identical for the unmarked fixtures. Marked output was not byte-identical: the old capture returned one concatenated line, whereas the consolidated capture preserved 11 lines. Raw hashes and lengths record this difference rather than assuming identical payloads.
  • This does not establish the improvement to full user-perceived AI response time, nor a full main-build-versus-feature-build comparison.
  • Release measurements have not been run. Debug numbers must not be presented as Release results.

Reproduction and artifacts

The PR includes test\e2e\Measure-PaneContext.ps1, its shared helpers, 16 hermetic selftests, and usage documentation in test\e2e\README.md.

Example, with an already-running Dev package and a stable existing pane:

$env:ITE2E_PACKAGE = 'Dev'
.\test\e2e\Measure-PaneContext.ps1 `
    -Package Dev -Configuration Debug `
    -Mode ExplicitAutofix -TargetPaneId '<source-pane-guid>' `
    -Scenario marked-short -ExpectedMarks Marked `
    -ExpectedMarker '<known-output-marker>' `
    -OutDir test\e2e\artifacts\pane-context-benchmark\debug-marked

For Planner or ManualFix, focus the expected source pane first; the script does not change focus, send input, change settings, or start/stop Terminal. Each run exports samples.csv, requests.csv, metadata.json, and summary.json, including binary hashes, source provenance, and timing definitions.

Local measurements are retained under test\e2e\artifacts\pane-context-benchmark\, with the combined table in debug-comparison.csv. These ignored local artifacts are not committed or uploaded; the measured summary is reproduced above.

Coverage and validation

  • Full WTA unit suite after merging main at e90ab68c4: 2,082 passed, 1 ignored.
  • Fresh C++ protocol-parsing tests: 5 passed; bounded ControlCore buffer-tail test: 1 passed.
  • Benchmark hermetic selftests: 16 passed.
  • Debug package built and deployed; the live get_pane_context capability and metadata-only request succeeded.
  • All nine paired live benchmark scenarios completed, each with 40 recorded old/new pairs.
  • Added unit assertions that planner and both Autofix source-selection modes each make exactly one context request, and that ordinary failures never enter the legacy fallback.
  • Preserved the seven packaged PaneContext E2E cases: marked capture, unmarked fallback, explicit tab/split routing, missing/closed targets, metadata-only capture, Unicode/truncation bounds, and source resolution from focused agent panes.
  • The earlier pre-restoration PaneContext + ShellIntegration + AutofixParser run passed 17/17, with a separate AutofixPane run 12/12. These are historical results, not a fresh full E2E run of the latest merged tree.
  • Checklist mapping was rechecked using those historical results through both full and incremental report generators. After merging main at e90ab68c4, PaneContext uses C300-C306; Autofix routing uses C299. This preserves main's hook cases at C296-C298 and removes the merged-main C295 collision with Ctrl+wheel coverage.

Remaining validation

  • Run the related full live E2E suites again against this latest merged optimization build.
  • Record Release p50/p95 measurements.

Add GetPaneContext protocol support, shared planner and Autofix collection, bounded capture coverage, and reproducible same-build performance benchmarks.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 77616472-cc8d-4566-9050-60ab09248076
Copilot AI lite review requested due to automatic review settings September 7, 2026 09:13

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

wtcli get-pane-context currently fails silently on an invalid --target GUID (non-zero exit without an error message), which should be fixed for debuggability and script reliability.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR implements the consolidated, bounded pane-context operation for #838 by appending GetPaneContext to the existing Terminal Protocol COM interface (protocol 2.3), exposing it via wtcli get-pane-context, and routing WTA planner/manual-fix/autofix context collection through the single consolidated request with bounded capture and accurate truncation reporting.

Changes:

  • Add protocol 2.3 GetPaneContext end-to-end (IDL/COM server/TerminalPage/ControlCore) with bounded marked-command capture and bounded buffer-tail fallback.
  • Add wtcli get-pane-context with protocol/capability negotiation and max-lines/max-chars validation; add WTA channel support (get_pane_context) and migrate ACP prompt context collection to use it (with legacy fallback for unsupported servers).
  • Add E2E coverage for pane-context scenarios and a PowerShell benchmark harness + selftests + documentation + release checklist mapping.
File summaries
File Description
tools/wta/src/shell/wt_channel/cli_channel.rs Map get_pane_context to a single wtcli get-pane-context invocation with bounds validation.
tools/wta/src/shell/shell_manager.rs Add wt_get_pane_context helper routing through the WT channel.
tools/wta/src/protocol/acp/prompt_context.rs Switch planner/autofix context capture to consolidated pane-context request; retain capability-gated legacy fallback.
tools/wta/src/protocol/acp/prompt_builder.rs Remove direct shell manager field from ContextRequest and adapt tests/mocks to consolidated capture.
tools/wta/src/protocol/acp/mock_agent_tests.rs Update blocking/mock WT channel behavior to serve consolidated pane-context payload shape.
test/e2e/tools/PaneContextBenchmark.ps1 Add shared benchmark/statistics + UTF-16-surrogate-safe scalar counting and prompt truncation helpers.
test/e2e/tests/Feature.PaneContext.Tests.ps1 Add packaged E2E tests covering marked/unmarked capture, isolation, missing panes, metadata-only, Unicode/truncation, and agent-focus resolution.
test/e2e/selftests/PaneContextBenchmark.Unit.Tests.ps1 Add hermetic Pester selftests for benchmark math, Unicode handling, and request fidelity.
test/e2e/README.md Document the new pane-context benchmark workflow and add the new PaneContext feature suite to the table.
test/e2e/Measure-PaneContext.ps1 Add the benchmark driver script that validates stability and compares legacy vs consolidated collectors on the same deployed build.
src/tools/wtcli/main.cpp Add get-pane-context subcommand with negotiation and validation; call ITerminalProtocol::GetPaneContext.
src/host/proxy/ITerminalProtocol.idl Append COM GetPaneContext without reordering existing vtable slots (protocol 2.3).
src/cascadia/WindowsTerminal/TerminalProtocolComServer.h Declare COM server implementation of GetPaneContext.
src/cascadia/WindowsTerminal/TerminalProtocolComServer.cpp Advertise protocol 2.3 + capability; implement GetPaneContext routing to TerminalPage::GetProtocolPaneContext.
src/cascadia/ut_app/ProtocolParsingTests.cpp Add unit tests for bounded UTF-8/line handling in command and buffer-tail builders.
src/cascadia/UnitTests_Control/ControlCoreTests.cpp Add unit tests for ControlCore::ReadBufferTail behavior, bounds, and Unicode handling.
src/cascadia/TerminalProtocol/TerminalProtocol.idl Add PaneContext struct and GetPaneContext WinRT method to the Terminal Protocol surface.
src/cascadia/TerminalProtocol/ProtocolParsing.h Add bounded UTF-8-aware command and buffer-tail text builders used by pane-context capture.
src/cascadia/TerminalControl/TermControl.idl Add ReadBufferTail and ReadLastPromptBounded to the TermControl API.
src/cascadia/TerminalControl/TermControl.h Declare TermControl wrappers for new bounded read methods.
src/cascadia/TerminalControl/TermControl.cpp Implement TermControl wrappers delegating to ControlCore.
src/cascadia/TerminalControl/ControlCore.idl Add ReadBufferTail and ReadLastPromptBounded to ControlCore WinRT surface.
src/cascadia/TerminalControl/ControlCore.h Declare new bounded read APIs on ControlCore.
src/cascadia/TerminalControl/ControlCore.cpp Implement bounded buffer-tail reading and bounded mark-based last-prompt reading with Unicode-safe iteration.
src/cascadia/TerminalApp/TerminalPage.Protocol.cpp Implement GetProtocolPaneContext resolving explicit/effective source pane and performing bounded capture/fallback.
src/cascadia/TerminalApp/TerminalPage.idl Add GetProtocolPaneContext to TerminalPage IDL.
src/cascadia/TerminalApp/TerminalPage.h Add GetProtocolPaneContext declaration.
doc/release-check-list.md Add/reassign release checklist items C296–C303 for pane-context and routing coverage.
Review details
  • Files reviewed: 28/28 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/tools/wtcli/main.cpp
Comment on lines +603 to +613
GUID source{};
const auto hasExplicitSource = !paneContextTarget.empty();
if (hasExplicitSource)
{
source = GuidFromString(paneContextTarget);
if (InlineIsEqualGUID(source, GUID{}))
{
exitCode = 1;
return;
}
}
@github-actions

This comment has been minimized.

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
Copilot AI review requested due to automatic review settings September 7, 2026 09:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

It spans COM ABI changes, cross-process protocol negotiation, and UI-thread-adjacent context capture logic that merits final human validation.

Review details
  • Files reviewed: 28/28 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment on lines +266 to +279
const auto lastCommand = termControl.ReadLastPromptBounded(maxLines + 1, maxCharacters + 1);
if (!lastCommand.empty())
{
const auto bounded = ProtocolParsing::BuildBoundedCommand(
winrt::to_string(lastCommand),
maxLines,
maxCharacters);
result.Content = winrt::to_hstring(bounded.content);
result.OutputSource = L"last_command";
result.LineCount = bounded.lineCount;
result.Truncated = bounded.truncated;
result.HasMarks = true;
co_return result;
}
VERIFY_IS_TRUE(result.truncated);

const auto lines = BuildBoundedCommand("command\r\nfirst\r\nsecond\r\n", 2, 100);
VERIFY_ARE_EQUAL("command\nfirst", lines.content);
VERIFY_ARE_EQUAL(2, blankLineLookahead.lineCount);
VERIFY_IS_TRUE(blankLineLookahead.truncated);

const auto leadingBlankLines = BuildBoundedCommand("\n\ncommand\n", 10, 100);
VERIFY_IS_TRUE(blankLineLookahead.truncated);

const auto leadingBlankLines = BuildBoundedCommand("\n\ncommand\n", 10, 100);
VERIFY_ARE_EQUAL("\n\ncommand\n", leadingBlankLines.content);
void ProtocolParsingTests::BoundedBufferTailAppliesLineAndCharacterLimits()
{
const auto byLines = BuildBoundedBufferTail("first\r\nsecond\r\nthird\r\n", 2, 100);
VERIFY_ARE_EQUAL("second\nthird", byLines.content);
VERIFY_IS_TRUE(byLines.truncated);

const auto byCharacters = BuildBoundedBufferTail("one\r\ntwo\r\nthree\r\n", 3, 6);
VERIFY_ARE_EQUAL("\nthree", byCharacters.content);
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown

check-spelling-bot Report

⚠️ Dictionary not found

Problems were encountered retrieving check dictionaries (cspell:dart/src/dart.txt cspell:k8s/dict/k8s.txt cspell:svelte/dict/svelte.txt cspell:php/dict/php.txt cspell:cpp/src/compiler-gcc.txt cspell:cpp/src/stdlib-cerrno.txt cspell:r/src/r.txt cspell:monkeyc/src/monkeyc_keywords.txt cspell:redis/dict/redis.txt cspell:golang/dict/go.txt cspell:django/dict/django.txt cspell:java/src/java-terms.txt cspell:npm/dict/npm.txt cspell:python/src/additional_words.txt cspell:cpp/src/people.txt cspell:lua/dict/lua.txt cspell:elixir/dict/elixir.txt cspell:powershell/dict/powershell.txt cspell:cpp/src/ecosystem.txt cspell:shell/dict/shell-all-words.txt cspell:ruby/dict/ruby.txt cspell:cpp/src/stdlib-c.txt cspell:python/src/python/python.txt cspell:public-licenses/src/generated/public-licenses.txt cspell:swift/src/swift.txt cspell:haskell/dict/haskell.txt cspell:sql/src/sql.txt cspell:rust/dict/rust.txt cspell:docker/src/docker-words.txt cspell:fullstack/dict/fullstack.txt cspell:cpp/src/compiler-msvc.txt cspell:software-terms/dict/softwareTerms.txt cspell:cpp/src/compiler-clang-attributes.txt cspell:cpp/src/stdlib-cpp.txt cspell:gaming-terms/dict/gaming-terms.txt cspell:cpp/src/stdlib-cmath.txt cspell:css/dict/css.txt cspell:python/src/python/python-lib.txt cspell:node/dict/node.txt cspell:software-terms/dict/webServices.txt cspell:ada/dict/ada.txt cspell:dotnet/dict/dotnet.txt cspell:java/src/java.txt cspell:typescript/dict/typescript.txt cspell:public-licenses/src/additional-licenses.txt cspell:clojure/src/clojure.txt cspell:latex/dict/latex.txt cspell:scala/dict/scala.txt cspell:html/dict/html.txt cspell:python/src/common/extra.txt cspell:sql/src/tsql.txt cspell:cpp/src/lang-keywords.txt cspell:cpp/src/template-strings.txt cspell:cpp/src/lang-jargon.txt).

⚠️ For more information, see check-dictionary-not-found.

🔴 Please review

See the 📂 files view, the 📜action log, 👼 SARIF report, or 📝 job summary for details.

Unrecognized words (4)

ncommand
nfirst
nthird
nthree

These words are not needed and should be removed AHP aiu Backgrounder CANTCALLOUT Ccc cplusplus ctl Debian depl dotnet drv endptr EOFs evt frob frobnicate Fullwidth gitlab hdr idl IME inbox ININPUTSYNCCALL INJ intelligentterminal Ioctl KVM lbl lld lsb NODEFAULT NONINFRINGEMENT notif oss outdir Podcast pri prioritization rcv segfault SND sourced SWP Tbl testname transitioning Uninstalls unk unparseable unregisters Virt VMs webpage websites WINVER WSLENV xsi

To accept these unrecognized words as correct and remove the previously acknowledged and now absent words, you could run the following commands

... in a clone of the git@github.com:microsoft/intelligent-terminal.git repository
on the dev/vanzue/get-context branch (ℹ️ how do I use this?):

curl -s -S -L 'https://raw.githubusercontent.com/check-spelling/check-spelling/cfb6f7e75bbfc89c71eaa30366d0c166f1bd9c8c/apply.pl' |
perl - 'https://github.com/microsoft/intelligent-terminal/actions/runs/34105532582/attempts/1' &&
git commit -m 'Update check-spelling metadata'
Available 📚 dictionaries could cover words (expected and unrecognized) not in the 📘 dictionary

This includes both expected items (2103) from .github/actions/spelling/expect/alphabet.txt .github/actions/spelling/expect/expect.txt .github/actions/spelling/expect/web.txt and unrecognized words (4)

Dictionary Entries Covers Uniquely
cspell:csharp/csharp.txt 32 2 2
cspell:aws/aws.txt 232 2 2
cspell:fonts/fonts.txt 536 1 1

Consider adding to the extra_dictionaries array (in the .github/actions/spelling/config.json file):

    "cspell:csharp/csharp.txt",
    "cspell:aws/aws.txt",
    "cspell:fonts/fonts.txt",

To stop checking additional dictionaries, put (in the .github/actions/spelling/config.json file):

"check_extra_dictionaries": []

Pattern suggestions ✂️ (1)

You could add these patterns to .github/actions/spelling/patterns/71516d3bb5164939437b76ea6e830eac9ab39fbd.txt:

# Automatically suggested patterns

# hit-count: 1 file-count: 1
# container images
image: [-\w./:@]+

Alternatively, if a pattern suggestion doesn't make sense for this project, add a # to the beginning of the line in the candidates file with the pattern to stop suggesting it.

Warnings and Notices ⚠️ (2)

See the 📂 files view, the 📜action log, 👼 SARIF report, or 📝 job summary for details.

⚠️ Warnings and Notices Count
ℹ️ candidate-pattern 1
⚠️ check-dictionary-not-found 54

See ⚠️ Event descriptions for more information.

✏️ Contributor please read this

By default the command suggestion will generate a file named based on your commit. That's generally ok as long as you add the file to your commit. Someone can reorganize it later.

If the listed items are:

  • ... misspelled, then please correct them instead of using the command.
  • ... names, please add them to .github/actions/spelling/allow/names.txt.
  • ... APIs, you can add them to a file in .github/actions/spelling/allow/.
  • ... just things you're using, please add them to an appropriate file in .github/actions/spelling/expect/.
  • ... tokens you only need in one place and shouldn't generally be used, you can add an item in an appropriate file in .github/actions/spelling/patterns/.

See the README.md in each directory for more information.

🔬 You can test your commits without appending to a PR by creating a new branch with that extra change and pushing it to your fork. The check-spelling action will run in response to your push -- it doesn't require an open pull request. By using such a branch, you can limit the number of typos your peers see you make. 😉

If the flagged items are 🤯 false positives

If items relate to a ...

  • binary file (or some other file you wouldn't want to check at all).

    Please add a file path to the excludes.txt file matching the containing file.

    File paths are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your files.

    ^ refers to the file's path from the root of the repository, so ^README\.md$ would exclude README.md (on whichever branch you're using).

  • well-formed pattern.

    If you can write a pattern that would match it,
    try adding it to the patterns.txt file.

    Patterns are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your lines.

    Note that patterns can't match multiline strings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants