TypeAgent Studio: corpus capture + Impact Report regression verdict#2623
Open
TalZaccai wants to merge 28 commits into
Open
TypeAgent Studio: corpus capture + Impact Report regression verdict#2623TalZaccai wants to merge 28 commits into
TalZaccai wants to merge 28 commits into
Conversation
Whole-session capture from a dispatcher displayLog.json into per-agent CorpusEntry buckets, reusing the existing corpus model, storage, and Corpora tree. Documents the data source and its on-disk location (<instanceDir>/displayLog.json, live session), the pure transform plus service/extension wiring, the Gate C tie-in, delivery slices, and open questions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Incorporate design-review findings (verified against code): capture the ordered multi-action sequence rather than a single action; omit feedback when the latest rating is cleared; use a logical (utterance, agent) entry id; explicit agent allowlist; aggregate-per-agent append with dedupe-against-existing; preserve the raw source path in provenance; and make explicit displayLog import the Gate C critical path. Add a 'feedback as a label, not a funnel' decision: feedback stays a read-time federated source and reaches the shared corpus only via promotion, with the projector aligned to the logical id so labels merge onto captured entries. Note durable feedback storage as a follow-up. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Slice 1 of corpus capture: a pure function that turns display-log entries into per-agent CorpusEntry[]. Groups by requestId; takes the utterance from the user-request, the agent from the set-display-info source, and the ordered multi-action sequence from the action-bearing set-display-info entries (sorted by actionIndex, then seq, then log order). Feedback is latest-wins and omitted when the rating was cleared. Entries use a logical (utterance, agent) id and are deduped within the batch, latest wins. Reads a narrow CaptureLogEntry structural type so core keeps no dispatcher dependency. Covered by 14 unit tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Slice 2 of corpus capture. importDisplayLogs reads one or more displayLog.json files, runs the capture transform with an optional agent allowlist, and writes the results through importCaptureEntries, which buckets per agent, dedupes by logical id within the batch and against existing entries, and appends once per agent. Malformed or missing files are skipped. Preserve the raw source path via a new provenance.rawSourceUri (the transform sets it) so it survives append overwriting sourceUri with the captures-file path. Make append collision-safe: pick a unique capture filename when one with the same timestamp already exists, so same- millisecond appends no longer overwrite each other. Covered by 10 tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Wire displayLog import end-to-end: a new importCorpusFromLogs runtime method delegating to importDisplayLogs, exposed over the studio service channel (protocol + RPC handler + client facade), and a typeagent-studio.importCorpusFromLogs command. The command takes a file/folder picker (folders resolve to displayLog.json), an optional agent allowlist, imports into the captures corpus, refreshes the Corpora tree, and reports a captured/skipped summary. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Transform: only a structured TypeAgentAction object counts as a real action; string[] display actions (the dispatcher's "request", system's "config"/"agent") are ignored, and the request's agent is taken from the source of its structured-action entry. This stops attributing requests to framework pseudo-sources. Visibility: FileCorpusService.listAgents() enumerates agents that have any corpus content (in-repo, captures, or external), and the runtime unions these with loaded-sandbox agents so imported corpora appear in the Corpora tree without first loading the agent. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the listAgents() union so the Corpora tree lists only agents loaded in a sandbox, not every agent with content on disk. Imported captures still accumulate and surface once their agent is loaded. The structured-action capture fix is unaffected. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Bulk import now lands entries directly in corpus/<agent>.utterances.jsonl via append-then-promote, with no per-utterance staging step. importDisplayLogs gains a target option (captures default, in-repo for the import command); importCaptureEntries returns the written ids per agent so they can be promoted in one move. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ort-only staging Captures is no longer part of the federated list view or the Corpora tree. It remains a private, transient scratch area used only while an import promotes entries into the shared in-repo corpus (append-then-promote). Removes the import target option (always in-repo), drops captures from the tree source order, and updates federation docs. Tests inspect the staging area by reading files directly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…rows Make the shared in-repo corpus files safe to commit and share, and clarify the Corpora tree. - Promotion now writes a repo-relative sourceUri and strips the machine-local rawSourceUri from every entry, so the committed file stays portable and leaks no local paths. The absolute path is re-derived on read for opening the backing file. - Corpora tree renders file-backed sources as one row per backing file, titled by file name with the themed file icon and an inline open-file action. Feedback collapses to a single group. - An existing but empty in-repo file renders as an openable row instead of the seed action; the seed row is reworded to 'Create corpus file...'. - The tree refreshes when a corpus .utterances.jsonl file is saved in the editor, via a single save listener rather than a filesystem watcher. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…tire manual feedback UI Move the Replay corpus action from the Corpora titlebar to a per-agent inline action (rerun icon) alongside Open Impact Report (graph icon); the replayCorpus command now replays the clicked agent directly and keeps the quick-pick as a command-palette fallback. Impact Report now remembers the last run across close/reopen: the host persists each agent's last run in workspaceState (row-capped) and re-posts it on open as a restored result, and the webview shows "Restored from last run (<timestamp>) — Run for live results". Adds optional restored/runAt fields to the result message. Retire the manual Record feedback command and read-time Feedback tree group (a scaffold with no request/response/action context); core feedback plumbing and the recordFeedback RPC are kept for a future per-response-bubble path. Promote to in-repo storage now strips feedback along with local absolute source URIs. Docs (QUICKSTART, README, corpus-capture-design) updated to match. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…o the report The Impact Report status now always reads "Done — N row(s) · Xms." with a " · Last run: <timestamp>" suffix on every run, live or reopened, instead of the separate "Restored from last run — Run for live results" wording. The host always sends the run time; the restored flag is dropped from the protocol, host, and client. The lightweight Replay corpus action (agent row / quick-pick) now compares HEAD against the working tree — the same check the report runs by default — rather than a moot working-tree self-compare, and saves its result as the agent's last run so opening the Impact Report re-renders it. A new impactReportStore module holds the shared per-agent workspaceState last-run store used by both the report host and the Replay command. Docs (QUICKSTART 4.6, README replay section) updated to match. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Thread the resolved version selections through the run -> persist -> reopen path so reopening a closed Impact Report restores its branch/version dropdowns to the last run instead of falling back to defaults. The webview sends the resolved versions with the run message; the host echoes them on the result and persists them; on reopen the host seeds them from the durable store and posts them, and the client applies them and re-renders the version buttons. Also let a Replay launched from the Corpora view refresh an already-open Impact Report for that agent in place: the command looks up a per-agent refresher and posts the result to the live webview. A new external flag on the result message lets the client accept an outside push regardless of its own request-id sequence, without disturbing that sequence so later in-panel runs still dedupe. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
201 labelled player utterances (145 grammar-matching across playTrack, playFromCurrentTrackList, and selectDevice; 56 realistic non-matching intents). Every grammar-tagged entry resolves through the real player NFA grammar with expectedAction matching the resolver output exactly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the earlier hand-fabricated regression set with a genuine measurement instrument. The predicate is now structural (judges from the delta shape so it works with no feedback yet), and the benchmark deltas are produced by running the real grammar replay resolver over the committed player corpus against six hand-authored grammar variants, each materialized as a throwaway commit-tree commit. The resulting 25 deltas are blind-labelled and the predicate is measured against them (92% agreement), with guards proving the deltas regenerate exactly from the fixtures and that trivial always-one-verdict predicates fail the bar. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Surface the likelyBadChange regression verdict as the Impact Report's red/green judgment across three surfaces: a headline banner leading with the regression count, a per-row verdict pill beside the structural status cell, and a Verdict filter tier composing with the existing Status filter. Rows open regression-first sorted. The browser view model imports the real verdict predicate so the judgment stays authoritative; only the display reason string is re-derived. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add clickable column-header sorting (with a right-aligned direction chevron) and an utterance text filter to the replay compare table. The filter lives as a funnel icon in the Utterance column header that opens a live VS Code input box: each keystroke narrows the visible rows and recomputes the non-exclusive filter-chip counts. Sorting and the filter are both modeled in the browser-neutral view model and covered by tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Persist the most significant rows when a run exceeds the row cap: order regression-first before slicing so a reopened, capped report still surfaces every likely regression instead of an arbitrary prefix. - Dispose the utterance-filter input box with the report panel, and drop any prior box when a new one opens, so none lingers after the panel closes. - Reword two comments to describe behavior in plain language. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…lyRegression The regression predicate's feedback override is observation-scoped: a rating judges the action seen in one run, not the utterance in the abstract. The grammar resolver now attaches a rating to a replay side only when that side re-resolves to the exact action the rating was recorded against, so a stale thumbs-down for a now-different action no longer forces a red verdict. Rename likelyBadChange to likelyRegression across code and docs to match the Impact Report UI, and recover the blind human labels in the player regression benchmark (predicate agreement ~92%). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR completes an end-to-end “find a regression” workflow in TypeAgent Studio by (1) capturing portable corpora from interaction/display logs, (2) replaying two agent versions, and (3) presenting a regression verdict in the Impact Report driven by a benchmarked likelyRegression predicate.
Changes:
- Add corpus capture/import pipeline (
displayLog.json→*.utterances.jsonl) and update the Corpora tree to be file-backed (one row per backing file) with open-file + auto-refresh on save. - Introduce and benchmark a
likelyRegressionpredicate (delta-shape + observation-scoped feedback override) and wire it into replay/Impact Report presentation (banner + per-row Impact). - Add Impact Report UX controls (unified chips with live counts, sorting, utterance filter via host input box) plus durable “last run” persistence and live refresh of an open report.
Show a summary per file
| File | Description |
|---|---|
| ts/packages/typeagent-studio/src/webviewKit/protocol.ts | Extend host↔webview protocol (run provenance, runAt, utterance search, external refresh). |
| ts/packages/typeagent-studio/src/test/webviewProtocol.spec.ts | Update protocol parsing tests for echoed resolved versions. |
| ts/packages/typeagent-studio/src/test/replayViewModel.spec.ts | Expand Impact Report view-model tests (filters/search/sort/verdict banner). |
| ts/packages/typeagent-studio/src/test/feedbackInputPresentation.spec.ts | Remove tests for retired feedback input flow. |
| ts/packages/typeagent-studio/src/test/corpusTreePresentation.spec.ts | Update corpus tree presentation tests for file-backed grouping. |
| ts/packages/typeagent-studio/src/studioServiceClient.ts | Add RPC client method for corpus import from logs. |
| ts/packages/typeagent-studio/src/serviceRuntimeFacade.ts | Expose repo-root info via CorpusSource and add corpus import method. |
| ts/packages/typeagent-studio/src/impactReportView.ts | Add durable last-run restore, external live refresh, utterance-filter host input box. |
| ts/packages/typeagent-studio/src/impactReportStore.ts | New workspaceState store for per-agent last run (row-capped, regression-first). |
| ts/packages/typeagent-studio/src/feedbackInputPresentation.ts | Remove feedback input shaping module (command retired). |
| ts/packages/typeagent-studio/src/extension.ts | Add corpus-file open/import commands, corpus tree refresh-on-save, replay→persist + live report refresh. |
| ts/packages/typeagent-studio/src/corpusTreeProvider.ts | Render corpus file rows with resourceUri + resolve existing in-repo file on disk. |
| ts/packages/typeagent-studio/src/corpusTreePresentation.ts | Rework corpus grouping to file-backed sources; remove feedback badge handling. |
| ts/packages/typeagent-studio/README.md | Update docs for corpus tree + replay/Impact Report last-run behavior; remove feedback section. |
| ts/packages/typeagent-studio/package.json | Update contributed commands/menus/activation events for new corpus import/open commands. |
| ts/packages/typeagent-studio/media/impactReport.css | Add verdict/impact styling, sortable headers, utterance funnel icon, docked detail pane layout. |
| ts/packages/typeagent-core/test/regressionPredicateBenchmark.spec.ts | Add predicate benchmark spec with threshold + authenticity regen checks (when git available). |
| ts/packages/typeagent-core/test/regressionBenchmarkHarness.ts | Add harness to generate real deltas via variant grammar commits. |
| ts/packages/typeagent-core/test/predicate.spec.ts | Add unit tests for structural likelyRegression behavior + feedback overrides. |
| ts/packages/typeagent-core/test/grammarReplayResolver.spec.ts | Add tests enforcing observation-scoped feedback attachment rule. |
| ts/packages/typeagent-core/test/fixtures/regression-variants/v9-wrong-enrichment.agr | New grammar variant fixture for benchmark delta generation. |
| ts/packages/typeagent-core/test/fixtures/regression-variants/v6-over-broad-genre.agr | New grammar variant fixture for benchmark delta generation. |
| ts/packages/typeagent-core/test/fixtures/regression-variants/v5-gained-good.agr | New grammar variant fixture for benchmark delta generation. |
| ts/packages/typeagent-core/test/fixtures/regression-variants/v4-skip-to-previous.agr | New grammar variant fixture for benchmark delta generation. |
| ts/packages/typeagent-core/test/fixtures/regression-variants/v2-lost-track-number.agr | New grammar variant fixture for benchmark delta generation. |
| ts/packages/typeagent-core/test/fixtures/regression-variants/v1-lost-transport.agr | New grammar variant fixture for benchmark delta generation. |
| ts/packages/typeagent-core/test/corpus.spec.ts | Update corpus federation expectations; add tests for in-repo sourceUri stamping + feedback stripping on promote. |
| ts/packages/typeagent-core/test/captureTransform.spec.ts | Add unit tests for display log → corpus transform. |
| ts/packages/typeagent-core/test/captureImport.spec.ts | Add tests for display log import into in-repo corpus (dedupe/idempotency/allowlist). |
| ts/packages/typeagent-core/src/runtime/studioRuntimeCore.ts | Add runtime API types + implementation for importCorpusFromLogs. |
| ts/packages/typeagent-core/src/runtime/studioProtocol.ts | Extend studio RPC protocol with importCorpusFromLogs. |
| ts/packages/typeagent-core/src/replay/predicate.ts | New likelyRegression predicate implementation. |
| ts/packages/typeagent-core/src/replay/index.ts | Re-export predicate from replay package barrel. |
| ts/packages/typeagent-core/src/replay/grammarResolver.ts | Implement observation-scoped feedback attachment (only when action reproduced). |
| ts/packages/typeagent-core/src/corpus/types.ts | Add provenance.rawSourceUri; clarify captures as transient staging. |
| ts/packages/typeagent-core/src/corpus/index.ts | Export capture transform/import helpers. |
| ts/packages/typeagent-core/src/corpus/fileCorpusService.ts | Make captures staging private (not federated); sanitize in-repo storage; avoid capture filename collisions. |
| ts/packages/typeagent-core/src/corpus/captureTransform.ts | New pure transform: display-log entries → corpus entries. |
| ts/packages/typeagent-core/src/corpus/captureImport.ts | New import pipeline: read display logs → stage → promote into in-repo corpus. |
| ts/packages/studio-service/src/studioRpcHandlers.ts | Wire new importCorpusFromLogs RPC handler. |
| ts/docs/plans/vscode-devx/STATUS.md | Update plan status/capability matrix for Gate C closure work. |
| ts/docs/plans/vscode-devx/README.md | Rename predicate phrasing to “likely regression” in plan docs. |
| ts/docs/plans/vscode-devx/QUICKSTART.md | Update quickstart for corpus tree + replay/Impact Report behavior; remove feedback steps. |
| ts/docs/plans/vscode-devx/impact-report-multi-variant-design.md | Update terminology to “likely regression”. |
| ts/docs/plans/vscode-devx/DESIGN.md | Update Impact Report narrative to “likely regression”. |
| ts/docs/plans/vscode-devx/corpus-capture-design.md | Add corpus capture design doc detailing transform/import + feedback semantics. |
| ts/docs/plans/vscode-devx/05-implementation-plan.md | Update predicate decision wording. |
| ts/docs/plans/vscode-devx/04-mvp-slice.md | Update demo script + Gate C wording to “likely regression”. |
| ts/docs/plans/vscode-devx/03-features.md | Rename feature to “Likely-regression predicate”. |
| ts/docs/plans/vscode-devx/02-journeys.md | Update journey language to “likely regressions”. |
| ts/docs/plans/vscode-devx/01-inventory.md | Update inventory implications wording for regression/improvement. |
| ts/corpus/player.regression-benchmark.jsonl | Add committed blind-labelled benchmark delta set for predicate measurement. |
Review details
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 55/55 changed files
- Comments generated: 3
- Review effort level: Low
The regression-predicate benchmark now prints each row where the verdict disagrees with its blind human label, so a drop below the threshold points straight at the offending deltas instead of an opaque aggregate. STATUS.md and the benchmark header reframe the ~92% as detector agreement on a fixed benchmark of fixture-grammar deltas, not a regression rate of any real change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…dings Split displayLogToCorpusEntries and the Impact Report renderTable into focused helpers so both clear the cyclomatic/cognitive ratchet. Also address review findings: make the capture-file name reservation atomic via the exclusive wx flag (no TOCTOU race between concurrent appends), give compareActions a deterministic tie-break to log order, and correct the utteranceSearch protocol doc to say it is posted live per keystroke. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The benchmark harness materializes fixture grammar variants via git commit-tree, which fails on a runner with no configured git user (empty ident). Pass an explicit synthetic author/committer identity in the env so the commit succeeds regardless of runner config; only the resulting tree content is read back, so the identity and SHA are irrelevant. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
robgruen
previously approved these changes
Jul 8, 2026
Contributor
There was a problem hiding this comment.
Review details
Comments suppressed due to low confidence (1)
ts/docs/plans/vscode-devx/STATUS.md:62
- STATUS.md is internally inconsistent about Gate C: it claims the work “closes the headline "find a regression" gate”, but the Gate C row still says “Impact Report wiring ❌” and the next paragraph says “Critical path now: close Gate C”. Please reconcile these status statements so readers don’t get conflicting guidance.
| **C** | J4 Find a regression | Impact Report ≥ 80% red/green on hand-labelled `player` | P-3 | 🟡 **long pole** — engine L1–L4a ✅; corpus ✅; predicate + measurement ✅ (detector agrees with human labels at 92% on a fixture-delta benchmark); Impact Report wiring ❌ |
| **D** | J5 Debug a trace | Trace Viewer | P-3 | ❌ not started |
| **E** | J6 Observe live | Live Trace + status bar | P-5 | ❌ not started |
**Critical path now: close Gate C** — corpus capture (the agent-agnostic capture
path; `player` is just the anchor set the gate is scored on) → predicate tuning →
run the ≥ 80% validation. It is the only _tunable_ gate and §7's top risk.
- Files reviewed: 55/55 changed files
- Comments generated: 1
- Review effort level: Low
You're not authorized to push to this branch. Visit "About protected branches" for more information.
You're not authorized to push to this branch. Visit "About protected branches" for more information.
You're not authorized to push to this branch. Visit "About protected branches" for more information.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the "find a regression" workflow end-to-end: capture a real corpus from
interaction logs, replay two versions of an agent, and read a red/green Impact
Report that says whether anything regressed.
Critical changes
logs into portable in-repo
*.utterances.jsonlfiles; imports auto-promoteinto the shared corpus and show up in the Corpora tree. Replaces the manual
feedback-entry UI.
playeris just the first capture — it's the labelled setthe bar is scored on.
likelyRegression). Classifies each replayed row asregression / improvement / benign / neutral from the delta shape (works on a
fresh edit with no feedback). Feedback, when present, overrides the guess — but
only when the replayed side reproduces the exact action the rating was recorded
against, so a stale thumbs-down for a now-different action never drives the
verdict.
each row carries an Impact column, both driven by the same
likelyRegressioncall the benchmark measures — so UI and evidence can't diverge.
with live counts and select/deselect-all; clickable column-header sorting with
a direction chevron; and an utterance filter (funnel icon → live VS Code input
box).
the last run persists in workspace state and restores on reopen.
Supporting changes
report still surfaces every likely regression.
so a drop points at the offending deltas. The two current misses are semantic
(a band matched as a genre, a mangled genre param) — the predicate reasons
about delta shape, not param correctness, and those two are why the score is
92%, not a circular 100%.
binding.
Testing
Studio view-model suite (48) and core replay suites green — including the
predicate benchmark (~92% agreement over 25 fixture deltas, bar 80%), predicate
unit specs, resolver specs for the feedback-binding rule, and corpus
transform/import specs. Type-check clean (only pre-existing unrelated errors),
Prettier clean, VSIX builds and installs.
55 files changed (+5,513 / −748), 21 commits. Targets
maindirectly.