From 6dd1b3a6bea4d79cc404c9be5bb6af96d7d7e835 Mon Sep 17 00:00:00 2001 From: Maggie Appleton <5599295+MaggieAppleton@users.noreply.github.com> Date: Fri, 2 Oct 2026 22:43:00 +0100 Subject: [PATCH 1/3] Hide inline Jev chat pills and retain popover actions --- .../src/conversation-plan/markers.test.tsx | 18 ++- apps/web/src/conversation-plan/markers.tsx | 61 ++++----- docs/jev-issues/JEV-007.md | 59 +++++++++ docs/jev-issues/README.md | 18 +++ e2e/conversation-plan-stress.e2e.ts | 11 +- e2e/conversation-plan-ui.e2e.ts | 23 +++- e2e/source/analysis-host-linked.native.ts | 124 ++++++++++++++++++ e2e/source/analysis-host-native.ts | 6 +- e2e/source/analysis-host.fixture.ts | 39 +++++- e2e/source/analysis-host.native.ts | 13 +- e2e/source/playwright.config.ts | 1 + .../exceptions/dynamic-web.json | 2 +- 12 files changed, 314 insertions(+), 61 deletions(-) create mode 100644 docs/jev-issues/JEV-007.md create mode 100644 docs/jev-issues/README.md create mode 100644 e2e/source/analysis-host-linked.native.ts diff --git a/apps/web/src/conversation-plan/markers.test.tsx b/apps/web/src/conversation-plan/markers.test.tsx index 2744e34d..d02752dd 100644 --- a/apps/web/src/conversation-plan/markers.test.tsx +++ b/apps/web/src/conversation-plan/markers.test.tsx @@ -180,12 +180,18 @@ test("unlinked analysis remains accessible without a status label", () => { expect(html).not.toContain('class="block size-1.5 rounded-full'); }); -test("message markers render at most three accepted card links", () => { - let html = markup(state(4, "applied")); +test("linked and reviewable messages have no inline Jev controls", () => { + let current = state(4, "applied"); + current.analysis[0]!.outcomes = [{ + start: 0, + end: 1, + status: "review", + gate: "target needs review", + eventIds: [], + }]; + let html = markup(current); - expect(html.match(/data-card-link=/g)).toHaveLength(3); - expect(html).toContain('data-card-link="link-1"'); - expect(html).toContain('data-card-link="link-3"'); - expect(html).not.toContain('data-card-link="link-4"'); + expect(html).not.toContain("data-card-link="); + expect(html).not.toContain("Review 1 excerpt"); expect(html).toContain('aria-label="Analysis for message: applied"'); }); diff --git a/apps/web/src/conversation-plan/markers.tsx b/apps/web/src/conversation-plan/markers.tsx index 3666b201..0059d4fd 100644 --- a/apps/web/src/conversation-plan/markers.tsx +++ b/apps/web/src/conversation-plan/markers.tsx @@ -59,12 +59,6 @@ export function MessageMarkers( ?? (links.length > 0 ? "applied" : jobsOnly ? "Planner jobs" : "unlinked"); let hasDiagnostics = !!analysis || links.length > 0 || jobs.length > 0; let visible = pinned && hasDiagnostics; - let reviewableCount = analysis && ["applied", "unlinked"].includes(analysis.status) - ? analysis.outcomes?.filter(outcome => - ["review", "ignored"].includes(outcome.status) - && !links.some(link => link.source.start === outcome.start && link.source.end === outcome.end) - ).length ?? 0 - : 0; let requestPanelFocus = () => setFocusPanelRequest(request => request + 1); let closeAnalysis = (returnFocus = false) => { setFocusPanelRequest(0); @@ -222,35 +216,7 @@ export function MessageMarkers( if (state && links.length === 0 && !analysis && jobs.length === 0) return null; return ( -
- {links.slice(0, 3).map(link => ( - - ))} - {reviewableCount > 0 && ( - - )} +
{hasDiagnostics && (
+ {links.length > 0 && ( +
+ {links.slice(0, 3).map(link => ( + + ))} +
+ )} (await wireState(page))?.analysis.find(item => item.messageId === unlinkedMessage)?.status diff --git a/e2e/source/analysis-host-linked.native.ts b/e2e/source/analysis-host-linked.native.ts new file mode 100644 index 00000000..a2ec9d42 --- /dev/null +++ b/e2e/source/analysis-host-linked.native.ts @@ -0,0 +1,124 @@ +import { expect, test } from "@playwright/test"; +import type { Page, TestInfo } from "@playwright/test"; +import { analysis, load, message, prepareAnalysisHost } from "./analysis-host-native"; + +test.beforeAll(prepareAnalysisHost); + +async function capture(page: Page, testInfo: TestInfo, name: string) { + await page.addStyleTag({ + content: ` + #host-outside { display: none; } + .analysis-host-chat { height: calc(100vh - 48px); } + .analysis-host-chat [data-chat-message-id^="host-background-"] { display: none; } + `, + }); + await page.evaluate(() => { + let scroller = document.querySelector( + ".analysis-host-chat > [data-focus-boundary]", + )!; + let target = document.querySelector( + '[data-chat-message-id="host-review"]', + )!; + scroller.scrollTop += target.getBoundingClientRect().top + - scroller.getBoundingClientRect().top - 16; + (document.activeElement as HTMLElement | null)?.blur(); + }); + await page.screenshot({ path: testInfo.outputPath(name) }); +} + +test( + "linked sources stay out of the transcript and remain keyboard navigable", + async ({ page }, testInfo) => { + await page.setViewportSize({ width: 893, height: 850 }); + let errors = await load(page); + await page.evaluate(() => window.analysisHostFixture.linked(true)); + let anchor = message(page, "host-review"); + await anchor.scrollIntoViewIfNeeded(); + let diagnosticsButton = anchor.getByRole("button", { name: /^Analysis for message:/ }); + await diagnosticsButton.press("Enter"); + let panel = analysis(page, "host-review"); + await expect(panel).toBeVisible(); + await expect(panel.getByRole("group", { name: "Linked decisions", exact: true })) + .toBeVisible(); + let cardLinks = panel.locator("[data-card-link]"); + await expect(cardLinks).toHaveCount(3); + await expect(cardLinks.nth(0)).toHaveText("Question"); + await expect(cardLinks.nth(1)).toHaveText("Proposal"); + await expect(cardLinks.nth(2)).toHaveText("Reason"); + await expect(panel.getByRole("button", { name: /^Constraint:/ })).toHaveCount(0); + await expect(panel.getByRole("button", { name: "Add another excerpt", exact: true })) + .toBeVisible(); + await page.keyboard.press("Escape"); + await expect(anchor.getByRole("button", { name: "Review 1 excerpt", exact: true })) + .toHaveCount(0); + await expect(anchor.locator("[data-card-link]")).toHaveCount(0); + await diagnosticsButton.press("Enter"); + + let proposal = panel.getByRole("button", { name: /^Proposal: show card for/ }); + await proposal.focus(); + await expect(proposal).toBeFocused(); + await page.keyboard.press("Enter"); + await expect(panel).toHaveCount(0); + expect(await page.evaluate(() => window.analysisHostFixture.cards)).toEqual(["host-thread"]); + + await anchor.scrollIntoViewIfNeeded(); + await capture(page, testInfo, "transcript-desktop-893x850.png"); + expect(errors).toEqual([]); + }, +); + +test( + "compact transcript stays clean and read-only diagnostics cannot correct or retry", + async ({ page }, testInfo) => { + await page.setViewportSize({ width: 390, height: 844 }); + let errors = await load(page, "readonly"); + await page.evaluate(() => window.analysisHostFixture.linked(true)); + let anchor = message(page, "host-review"); + await anchor.scrollIntoViewIfNeeded(); + await anchor.getByRole("button", { name: /^Analysis for message:/ }).press("Enter"); + let panel = analysis(page, "host-review"); + await expect(panel).toBeVisible(); + await expect(panel.getByRole("group", { name: "Linked decisions", exact: true })) + .toBeVisible(); + await expect(panel.getByRole("button", { name: "Add another excerpt", exact: true })) + .toBeDisabled(); + await expect(panel.getByRole("button", { name: "Add excerpt", exact: true })).toHaveCount(0); + await page.keyboard.press("Escape"); + await expect(anchor.getByRole("button", { name: "Review 1 excerpt", exact: true })) + .toHaveCount(0); + await expect(anchor.locator("[data-card-link]")).toHaveCount(0); + + let retry = message(page, "host-retry"); + await retry.getByRole("button", { name: /^Analysis for message:/ }).press("Enter"); + await expect( + analysis(page, "host-retry").getByRole("button", { + name: "Retry analysis", + exact: true, + }), + ).toHaveCount(0); + await page.keyboard.press("Escape"); + + let jobs = message(page, "host-jobs"); + await jobs.getByRole("button", { name: /^Analysis for message:/ }).press("Enter"); + await expect( + analysis(page, "host-jobs").getByRole("button", { + name: "Retry refine job", + exact: true, + }), + ).toHaveCount(0); + await page.keyboard.press("Escape"); + + await anchor.getByRole("button", { name: /^Analysis for message:/ }).press("Enter"); + let linkedPanel = analysis(page, "host-review"); + let questionLink = linkedPanel.getByRole("button", { name: /^Question: show card for/ }); + await questionLink.focus(); + await expect(questionLink).toBeFocused(); + await page.keyboard.press("Enter"); + await expect(linkedPanel).toHaveCount(0); + expect(await page.evaluate(() => window.analysisHostFixture.cards)).toEqual(["host-thread"]); + + await anchor.scrollIntoViewIfNeeded(); + await capture(page, testInfo, "transcript-compact-390x844.png"); + expect(errors).toEqual([]); + }, +); diff --git a/e2e/source/analysis-host-native.ts b/e2e/source/analysis-host-native.ts index 850e7eef..48428a94 100644 --- a/e2e/source/analysis-host-native.ts +++ b/e2e/source/analysis-host-native.ts @@ -82,9 +82,11 @@ export async function inspect(page: Page, id: string) { export async function openCorrection(page: Page) { let anchor = message(page, "host-review"); await anchor.scrollIntoViewIfNeeded(); - await anchor.getByRole("button", { name: "Review 1 excerpt", exact: true }).click(); + await anchor.getByRole("button", { name: /^Analysis for message:/ }).press("Enter"); let panel = analysis(page, "host-review"); - await expect(panel.getByRole("button", { name: "Add to card", exact: true })).toBeFocused(); + let correction = panel.getByRole("button", { name: "Add to card", exact: true }); + await correction.focus(); + await expect(correction).toBeFocused(); await panel.getByRole("button", { name: "Add to card", exact: true }).click(); await expect(panel.getByRole("combobox", { name: "Contribution type", exact: true })) .toBeFocused(); diff --git a/e2e/source/analysis-host.fixture.ts b/e2e/source/analysis-host.fixture.ts index edc59738..65a08425 100644 --- a/e2e/source/analysis-host.fixture.ts +++ b/e2e/source/analysis-host.fixture.ts @@ -14,6 +14,7 @@ declare global { version(version: number): void; editable(enabled: boolean): void; diagnostics(enabled: boolean): void; + linked(enabled: boolean): void; corrections: ExcerptCorrectionAction[]; analyses: Array<{ messageId: string; actionId: string }>; jobs: string[]; @@ -34,6 +35,38 @@ let analysisHostThread: ConversationPlan.Thread = { contributions: [{ id: "host-option", kind: "option", text: "S3", authoring: "quoted", sources: [], actor: { kind: "classifier" } }], stances: [], stanceHistory: [], decisionHistory: [], candidates: [], }; +let analysisHostLinkedThread: ConversationPlan.Thread = { + ...analysisHostThread, + questionSources: [{ + messageId: "host-review", author: { kind: "member", handle: "ana" }, + quote: "Prefix", start: 0, end: 6, role: "question", + }], + contributions: [ + { + ...analysisHostThread.contributions[0]!, + sources: [{ + messageId: "host-review", author: { kind: "member", handle: "ana" }, + quote: "S3", start: 8, end: 10, role: "option", + }], + }, + { + id: "host-reason", kind: "reason", text: "needs", authoring: "quoted", + sources: [{ + messageId: "host-review", author: { kind: "member", handle: "ana" }, + quote: "needs", start: 11, end: 16, role: "reason", + }], + actor: { kind: "classifier" }, + }, + { + id: "host-constraint", kind: "constraint", text: "encryption", authoring: "quoted", + sources: [{ + messageId: "host-review", author: { kind: "member", handle: "ana" }, + quote: "encryption", start: 17, end: 27, role: "constraint", + }], + actor: { kind: "classifier" }, + }, + ], +}; let analysisHostRecord: ConversationPlan.AnalysisRecord = { messageId: "host-review", questionSetVersion: "fixture-v1", modelVersion: "fixture-m1", status: "unlinked", passes: [], eventIds: [], outcomes: [{ @@ -74,15 +107,17 @@ function AnalysisHost({ mode }: { mode: "editable" | "readonly" }) { let [version, setVersion] = useState(7); let [diagnostics, setDiagnostics] = useState(true); window.analysisHostFixture.diagnostics = setDiagnostics; + let [linked, setLinked] = useState(false); window.analysisHostFixture.editable = setEditable; window.analysisHostFixture.version = setVersion; + window.analysisHostFixture.linked = setLinked; window.analysisHostFixture.append = () => setEntries(current => [...current, { id: \`appended-\${current.length}\`, author: { kind: "member", handle: "ana" }, text: "A new message while the analysis remains pinned.", ts: current.length + 1, }]); let state: ConversationPlan.State = { schemaVersion: 1, revision: 9, events: [], queue: [], - threads: [{ ...analysisHostThread, version }], + threads: [{ ...(linked ? analysisHostLinkedThread : analysisHostThread), version }], analysis: diagnostics ? [analysisHostRecord, { messageId: "host-retry", questionSetVersion: "fixture-v1", modelVersion: "fixture-m1", status: "failed", passes: [], eventIds: [], error: "Controlled analysis failure.", @@ -127,6 +162,6 @@ window.analysisHostFixture = { analysisHostPending.delete(kind); if (accepted) pending.resolve(); else pending.reject(new Error("Controlled held acknowledgement rejection")); }, - append() {}, version() {}, editable() {}, diagnostics() {}, + append() {}, version() {}, editable() {}, diagnostics() {}, linked() {}, }; `; diff --git a/e2e/source/analysis-host.native.ts b/e2e/source/analysis-host.native.ts index 8fc04e0a..b426085b 100644 --- a/e2e/source/analysis-host.native.ts +++ b/e2e/source/analysis-host.native.ts @@ -121,11 +121,16 @@ test("native selection refuses whole-message pinning and interactive controls re await page.waitForTimeout(180); await expect(analysis(page, "host-review")).toHaveCount(0); await page.evaluate(() => window.getSelection()!.removeAllRanges()); - await anchor.getByRole("button", { name: "Review 1 excerpt", exact: true }).click(); + await expect(anchor.getByRole("button", { name: "Review 1 excerpt", exact: true })) + .toHaveCount(0); + await anchor.getByRole("button", { name: /^Analysis for message:/ }).press("Enter"); await expect(analysis(page, "host-review")).toBeVisible(); - await expect( - analysis(page, "host-review").getByRole("button", { name: "Add to card", exact: true }), - ).toBeFocused(); + let correction = analysis(page, "host-review").getByRole("button", { + name: "Add to card", + exact: true, + }); + await correction.focus(); + await expect(correction).toBeFocused(); expect(errors).toEqual([]); }); diff --git a/e2e/source/playwright.config.ts b/e2e/source/playwright.config.ts index 8c425901..48bda0f2 100644 --- a/e2e/source/playwright.config.ts +++ b/e2e/source/playwright.config.ts @@ -15,6 +15,7 @@ export default defineConfig({ "conversation-announcements.native.ts", "analysis-host.native.ts", "diagnostic-controls.native.ts", + "analysis-host-linked.native.ts", "analysis-host-retries.native.ts", "decision-reader.native.ts", "collapse-deletion.native.ts", diff --git a/scripts/design-contract/exceptions/dynamic-web.json b/scripts/design-contract/exceptions/dynamic-web.json index 0c76ba41..a1fa9df6 100644 --- a/scripts/design-contract/exceptions/dynamic-web.json +++ b/scripts/design-contract/exceptions/dynamic-web.json @@ -333,6 +333,6 @@ 1 ] ], - "sourceHash": "f3695d501f5aedc2cc46c76134aa402e1608fa9b7b5f233adae9c855ab137516" + "sourceHash": "462f224addb47a1a0945bf8c49b49fb35f70fac66e92b81a8ed544a6c4b49ea0" } ] From 313fc6cf115818772087f6c8c3a612b5c35f481a Mon Sep 17 00:00:00 2001 From: Maggie Appleton <5599295+MaggieAppleton@users.noreply.github.com> Date: Fri, 2 Oct 2026 22:44:13 +0100 Subject: [PATCH 2/3] Record JEV007 PR and verified UI evidence --- docs/jev-issues/JEV-007.md | 7 ++++--- docs/jev-issues/README.md | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/jev-issues/JEV-007.md b/docs/jev-issues/JEV-007.md index adea6504..0355148c 100644 --- a/docs/jev-issues/JEV-007.md +++ b/docs/jev-issues/JEV-007.md @@ -1,6 +1,6 @@ # JEV-007 — Remove inline Jev pills from chat messages -Status: Verified; preparing PR. PR: Pending. Reported as “Issue 6”; stable ID: JEV-007. +Status: Ready for Maggie’s review. PR: [#245](https://github.com/githubnext/chopin/pull/245). Reported as “Issue 6”; stable ID: JEV-007. Maggie requested removal of the visible Jev labels beneath each chat message. The current transcript is the reference; the approved end state has message text @@ -31,7 +31,7 @@ both behavior changes. The width change in PR #244 is independent. read-only behavior, compact/desktop layout, and compatibility with PR #243. - [x] Reviewer checks the final diff. Run formatting, types, repository CI and relevant browser/unit checks; repair findings before handoff. -- [ ] Orchestrator owns this record/index and fix PR publication with a verified +- [x] Orchestrator owns this record/index and fix PR publication with a verified real UI image; no merge or direct prototype push. Use disposable fixtures. Preserve the live prototype at port 8787 and its document; @@ -55,5 +55,6 @@ PR URL and image evidence will be recorded here. A real-component desktop/compact image was captured and visually inspected from that disposable combination. It explicitly labels the code buttons as PR #243's -change. Published image verification and PR URL will be recorded after upload. +change. The image is embedded in PR #245; the published inline image returned HTTP 200 +with `image/png`, and the description contains no unresolved local image reference. The live prototype/document and prototype branch remain unchanged. diff --git a/docs/jev-issues/README.md b/docs/jev-issues/README.md index fec6c42a..3e0268c0 100644 --- a/docs/jev-issues/README.md +++ b/docs/jev-issues/README.md @@ -11,7 +11,7 @@ remains draft. One issue per fix PR; no automatic merges or direct prototype pus | [JEV-004](https://github.com/githubnext/chopin/blob/maggie/jev-001-decision-anchors/docs/jev-issues/JEV-004.md) | Baseline CI conversation-capacity timeouts | Queued | Pending | | [JEV-005](https://github.com/githubnext/chopin/blob/maggie/jev-005-click-debug-popovers/docs/jev-issues/JEV-005.md) | Click-only Jev debug popovers with code-icon buttons | Ready for Maggie’s review | [#243](https://github.com/githubnext/chopin/pull/243) | | [JEV-006](https://github.com/githubnext/chopin/blob/maggie/jev-006-wider-chat/docs/jev-issues/JEV-006.md) | Default chat pane 60px wider | Ready for Maggie’s review | [#244](https://github.com/githubnext/chopin/pull/244) | -| [JEV-007](JEV-007.md) | Remove inline Jev chat pills | Verified; preparing PR | Pending | +| [JEV-007](JEV-007.md) | Remove inline Jev chat pills | Ready for Maggie’s review | [#245](https://github.com/githubnext/chopin/pull/245) | Evidence: [live browser pass](../jev-live-browser-test.md), [UI reconciliation](../jev-ui-reconciliation.md). Baseline: From b4954406da35f1c875ec1158405e7df324a0a5b5 Mon Sep 17 00:00:00 2001 From: Maggie Appleton <5599295+MaggieAppleton@users.noreply.github.com> Date: Sat, 3 Oct 2026 05:47:21 +0100 Subject: [PATCH 3/3] Remove planning artifacts and streamline regression coverage --- .../src/conversation-plan/markers.test.tsx | 16 ----- docs/jev-issues/JEV-007.md | 60 ------------------- docs/jev-issues/README.md | 18 ------ e2e/source/analysis-host-linked.native.ts | 41 ++----------- 4 files changed, 4 insertions(+), 131 deletions(-) delete mode 100644 docs/jev-issues/JEV-007.md delete mode 100644 docs/jev-issues/README.md diff --git a/apps/web/src/conversation-plan/markers.test.tsx b/apps/web/src/conversation-plan/markers.test.tsx index d02752dd..1e82787c 100644 --- a/apps/web/src/conversation-plan/markers.test.tsx +++ b/apps/web/src/conversation-plan/markers.test.tsx @@ -179,19 +179,3 @@ test("unlinked analysis remains accessible without a status label", () => { expect(html).not.toContain("Unlinked"); expect(html).not.toContain('class="block size-1.5 rounded-full'); }); - -test("linked and reviewable messages have no inline Jev controls", () => { - let current = state(4, "applied"); - current.analysis[0]!.outcomes = [{ - start: 0, - end: 1, - status: "review", - gate: "target needs review", - eventIds: [], - }]; - let html = markup(current); - - expect(html).not.toContain("data-card-link="); - expect(html).not.toContain("Review 1 excerpt"); - expect(html).toContain('aria-label="Analysis for message: applied"'); -}); diff --git a/docs/jev-issues/JEV-007.md b/docs/jev-issues/JEV-007.md deleted file mode 100644 index 0355148c..00000000 --- a/docs/jev-issues/JEV-007.md +++ /dev/null @@ -1,60 +0,0 @@ -# JEV-007 — Remove inline Jev pills from chat messages - -Status: Ready for Maggie’s review. PR: [#245](https://github.com/githubnext/chopin/pull/245). Reported as “Issue 6”; stable ID: JEV-007. - -Maggie requested removal of the visible Jev labels beneath each chat message. -The current transcript is the reference; the approved end state has message text -without Question/Proposal/Reason/Support/etc. pills or the Review-excerpts pill. -Specs and routine choices are preapproved. - -## Design and scope - -Remove the inline card-link and Review-excerpts buttons from -`apps/web/src/conversation-plan/markers.tsx`. Keep analysis/evidence classification, -source metadata, retries, permission checks and card navigation. Move the existing -card-link controls into the analysis popover; excerpt correction already lives -there. Dropping the controls entirely was considered, but would lose navigation. -Remove unused summary-count code. Avoid new renderers or data changes. - -This fix is based on `origin/Maggie/jev-chat-product` and targets that prototype, -which remains unchanged. PR #243 separately adds click-only code icons. Verify -compatibility with that change in a disposable combined fixture; do not merge or -copy its commits into this fix PR. Any overlapping-file integration must preserve -both behavior changes. The width change in PR #244 is independent. - -## Small implementation plan - -- [x] Implementer owns markers/popover placement, relevant existing unit/native/app - test updates, and exact existing design-contract hash renewal if required. -- [x] Independent tester verifies linked/reviewable messages have no visible pills, - card navigation and excerpt Review still work inside diagnostics, keyboard and - read-only behavior, compact/desktop layout, and compatibility with PR #243. -- [x] Reviewer checks the final diff. Run formatting, types, repository CI and - relevant browser/unit checks; repair findings before handoff. -- [x] Orchestrator owns this record/index and fix PR publication with a verified - real UI image; no merge or direct prototype push. - -Use disposable fixtures. Preserve the live prototype at port 8787 and its document; -never read or publish .env contents, credentials or API keys. Final verification, -PR URL and image evidence will be recorded here. - -## Verification - -- Markers unit tests: 7/7. -- Actual Transcript native browser tests: 11/11; independent tester repeated all - 11 and TypeScript checks after the final fixture isolation. -- Affected application checks: 2/2, covering card navigation and writer/read-only - excerpt correction against disposable PostgreSQL and an isolated app. -- Disposable combination with PR #243: 5/5. Code-icon activation, quiet hover, - geometry, reset/restore, linked-card keyboard navigation, excerpt correction, - analysis retry, and compact read-only behavior pass together. -- `bun run fix`, `bun run types`, `bun run ci`, and `git diff --check` pass. - Existing lint warnings remain unchanged. The exact existing markers design - exception hash was renewed; the exception scope was not expanded. -- Independent production review: approved, no actionable findings. - -A real-component desktop/compact image was captured and visually inspected from -that disposable combination. It explicitly labels the code buttons as PR #243's -change. The image is embedded in PR #245; the published inline image returned HTTP 200 -with `image/png`, and the description contains no unresolved local image reference. -The live prototype/document and prototype branch remain unchanged. diff --git a/docs/jev-issues/README.md b/docs/jev-issues/README.md deleted file mode 100644 index 3e0268c0..00000000 --- a/docs/jev-issues/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# Jev issue queue - -Fix PRs target `Maggie/jev-chat-product`; [prototype PR #241](https://github.com/githubnext/chopin/pull/241) -remains draft. One issue per fix PR; no automatic merges or direct prototype pushes. - -| ID | Problem | Status | PR | -| ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | ---------------------------------------------------------------- | ----------------------------------------------------- | -| [JEV-001](https://github.com/githubnext/chopin/blob/maggie/jev-001-decision-anchors/docs/jev-issues/JEV-001.md) | Incorrect decision anchors and overlapping markers | Ready for Maggie’s review | [#242](https://github.com/githubnext/chopin/pull/242) | -| [JEV-002](https://github.com/githubnext/chopin/blob/maggie/jev-001-decision-anchors/docs/jev-issues/JEV-002.md) | Stale rationale after changing a choice | Queued | Pending | -| [JEV-003](https://github.com/githubnext/chopin/blob/maggie/jev-001-decision-anchors/docs/jev-issues/JEV-003.md) | Useful questions/preferences unapplied; incomplete review recovery | Queued; determine separate recovery scopes before implementation | Pending | -| [JEV-004](https://github.com/githubnext/chopin/blob/maggie/jev-001-decision-anchors/docs/jev-issues/JEV-004.md) | Baseline CI conversation-capacity timeouts | Queued | Pending | -| [JEV-005](https://github.com/githubnext/chopin/blob/maggie/jev-005-click-debug-popovers/docs/jev-issues/JEV-005.md) | Click-only Jev debug popovers with code-icon buttons | Ready for Maggie’s review | [#243](https://github.com/githubnext/chopin/pull/243) | -| [JEV-006](https://github.com/githubnext/chopin/blob/maggie/jev-006-wider-chat/docs/jev-issues/JEV-006.md) | Default chat pane 60px wider | Ready for Maggie’s review | [#244](https://github.com/githubnext/chopin/pull/244) | -| [JEV-007](JEV-007.md) | Remove inline Jev chat pills | Ready for Maggie’s review | [#245](https://github.com/githubnext/chopin/pull/245) | - -Evidence: [live browser pass](../jev-live-browser-test.md), -[UI reconciliation](../jev-ui-reconciliation.md). Baseline: -`27eb3724a6e7ba3020552e7a1fa17f234811941b`. Notes first recorded 2 October 2026. diff --git a/e2e/source/analysis-host-linked.native.ts b/e2e/source/analysis-host-linked.native.ts index a2ec9d42..704bd64c 100644 --- a/e2e/source/analysis-host-linked.native.ts +++ b/e2e/source/analysis-host-linked.native.ts @@ -1,34 +1,11 @@ import { expect, test } from "@playwright/test"; -import type { Page, TestInfo } from "@playwright/test"; import { analysis, load, message, prepareAnalysisHost } from "./analysis-host-native"; test.beforeAll(prepareAnalysisHost); -async function capture(page: Page, testInfo: TestInfo, name: string) { - await page.addStyleTag({ - content: ` - #host-outside { display: none; } - .analysis-host-chat { height: calc(100vh - 48px); } - .analysis-host-chat [data-chat-message-id^="host-background-"] { display: none; } - `, - }); - await page.evaluate(() => { - let scroller = document.querySelector( - ".analysis-host-chat > [data-focus-boundary]", - )!; - let target = document.querySelector( - '[data-chat-message-id="host-review"]', - )!; - scroller.scrollTop += target.getBoundingClientRect().top - - scroller.getBoundingClientRect().top - 16; - (document.activeElement as HTMLElement | null)?.blur(); - }); - await page.screenshot({ path: testInfo.outputPath(name) }); -} - test( - "linked sources stay out of the transcript and remain keyboard navigable", - async ({ page }, testInfo) => { + "linked sources remain keyboard navigable from diagnostics", + async ({ page }) => { await page.setViewportSize({ width: 893, height: 850 }); let errors = await load(page); await page.evaluate(() => window.analysisHostFixture.linked(true)); @@ -49,9 +26,6 @@ test( await expect(panel.getByRole("button", { name: "Add another excerpt", exact: true })) .toBeVisible(); await page.keyboard.press("Escape"); - await expect(anchor.getByRole("button", { name: "Review 1 excerpt", exact: true })) - .toHaveCount(0); - await expect(anchor.locator("[data-card-link]")).toHaveCount(0); await diagnosticsButton.press("Enter"); let proposal = panel.getByRole("button", { name: /^Proposal: show card for/ }); @@ -61,15 +35,13 @@ test( await expect(panel).toHaveCount(0); expect(await page.evaluate(() => window.analysisHostFixture.cards)).toEqual(["host-thread"]); - await anchor.scrollIntoViewIfNeeded(); - await capture(page, testInfo, "transcript-desktop-893x850.png"); expect(errors).toEqual([]); }, ); test( - "compact transcript stays clean and read-only diagnostics cannot correct or retry", - async ({ page }, testInfo) => { + "read-only diagnostics allow navigation but prevent correction and retries", + async ({ page }) => { await page.setViewportSize({ width: 390, height: 844 }); let errors = await load(page, "readonly"); await page.evaluate(() => window.analysisHostFixture.linked(true)); @@ -84,9 +56,6 @@ test( .toBeDisabled(); await expect(panel.getByRole("button", { name: "Add excerpt", exact: true })).toHaveCount(0); await page.keyboard.press("Escape"); - await expect(anchor.getByRole("button", { name: "Review 1 excerpt", exact: true })) - .toHaveCount(0); - await expect(anchor.locator("[data-card-link]")).toHaveCount(0); let retry = message(page, "host-retry"); await retry.getByRole("button", { name: /^Analysis for message:/ }).press("Enter"); @@ -117,8 +86,6 @@ test( await expect(linkedPanel).toHaveCount(0); expect(await page.evaluate(() => window.analysisHostFixture.cards)).toEqual(["host-thread"]); - await anchor.scrollIntoViewIfNeeded(); - await capture(page, testInfo, "transcript-compact-390x844.png"); expect(errors).toEqual([]); }, );