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([]);
},
);