diff --git a/CHANGELOG.d/2.3.0-focus-ask-after-priya-related.md b/CHANGELOG.d/2.3.0-focus-ask-after-priya-related.md new file mode 100644 index 000000000..bf2c4f350 --- /dev/null +++ b/CHANGELOG.d/2.3.0-focus-ask-after-priya-related.md @@ -0,0 +1,5 @@ +# 2.3.0 Focus Ask after Priya related + +Open Public post from the landed Demo Corp members and the Ask heading +takes focus after Priya Nair related nodes are current. Home list +opens do not. diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c9406593..d5268ae32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,15 @@ All notable changes to this project are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.3.0] - 2026-08-17 + +### Added + +- Opening Public post from the landed Demo Corp members now focuses + the Ask heading after Priya Nair related nodes are current. Home + list opens do not steal that focus. No TEPP theta is invented. No + cutoff body is invented (ADR 0016). + ## [2.2.0] - 2026-08-17 ### Added diff --git a/frontend/package.json b/frontend/package.json index c60b3e502..c69ccd443 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "frontend", "private": true, - "version": "2.2.0", + "version": "2.3.0", "type": "module", "scripts": { "dev": "vite", diff --git a/frontend/src/App.test.tsx b/frontend/src/App.test.tsx index 10c16e9e9..b5fb24455 100644 --- a/frontend/src/App.test.tsx +++ b/frontend/src/App.test.tsx @@ -1483,6 +1483,7 @@ describe("App, authenticated", () => { expect(screen.getAllByLabelText("A-100 lineage").length).toBeGreaterThanOrEqual(2); expect(screen.getAllByLabelText("Open post: Pricing renegotiation follow-up").length).toBeGreaterThanOrEqual(2); expect(document.getElementById("post-event-lineage")).not.toHaveFocus(); + expect(document.getElementById("post-ask")).not.toHaveFocus(); expect( screen.queryByRole("status", { name: "Event Lineage next action" }), ).not.toBeInTheDocument(); @@ -2308,7 +2309,6 @@ describe("App, authenticated", () => { expect( screen.getAllByRole("heading", { name: "Event Lineage" }).length, ).toBeGreaterThanOrEqual(2); - expect(document.getElementById("post-event-lineage")).toHaveFocus(); const popup = document.querySelector(".popup-panel"); expect(popup).not.toBeNull(); const currentNode = within(popup as HTMLElement).getByLabelText("Open post: Public post"); @@ -2379,6 +2379,7 @@ describe("App, authenticated", () => { expect(askNext.compareDocumentPosition(affiliate) & Node.DOCUMENT_POSITION_FOLLOWING).not.toBe( 0, ); + await waitFor(() => expect(document.getElementById("post-ask")).toHaveFocus()); } finally { HTMLElement.prototype.scrollIntoView = originalScrollIntoView; } @@ -2642,7 +2643,6 @@ describe("App, authenticated", () => { expect(screen.getByText("Constructive stance: 2")).toBeInTheDocument(); expect(screen.getAllByText(/Ada West/).length).toBeGreaterThan(0); expect(screen.getAllByLabelText("A-100 lineage").length).toBeGreaterThanOrEqual(2); - expect(document.getElementById("post-event-lineage")).toHaveFocus(); expect(screen.getByRole("status", { name: "Event Lineage next action" })).toHaveTextContent( "Public post is current in Event Lineage. Read Keyman and evaluation next.", ); @@ -2657,6 +2657,7 @@ describe("App, authenticated", () => { expect(await screen.findByRole("status", { name: "Ask next action" })).toHaveTextContent( "Related nodes for Priya Nair are current. Ask about this lineage next.", ); + await waitFor(() => expect(document.getElementById("post-ask")).toHaveFocus()); }); it("lets post_admin rebuild the period report", async () => { diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 0c32b3ef5..f2bc19098 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -684,6 +684,15 @@ function KeymanPanel({ }; }, [accessToken, landFirstRelated, related]); + useEffect(() => { + if (!landFirstRelated || !landedRelatedName || landedRelated === null) { + return; + } + const heading = document.getElementById("post-ask"); + heading?.focus(); + heading?.scrollIntoView?.({ block: "nearest" }); + }, [landFirstRelated, landedRelatedName, landedRelated]); + useEffect(() => { if (!focusPerson) return; const requestId = ++relatedRequest.current; diff --git a/lineageweave/__init__.py b/lineageweave/__init__.py index d6f62810d..7cc0d8636 100644 --- a/lineageweave/__init__.py +++ b/lineageweave/__init__.py @@ -55,4 +55,4 @@ "sentence_excerpts", ] -__version__ = "2.2.0" +__version__ = "2.3.0" diff --git a/pyproject.toml b/pyproject.toml index 07ad08f65..4ae85b35a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "lineageweave" -version = "2.2.0" +version = "2.3.0" description = "Reconstructs git-branch-style lineage DAGs from scattered short records using multi-channel score fusion and LLM adjudication." readme = "README.md" license = { text = "MIT" } diff --git a/uv.lock b/uv.lock index c75f5984b..517e10894 100644 --- a/uv.lock +++ b/uv.lock @@ -454,7 +454,7 @@ wheels = [ [[package]] name = "lineageweave" -version = "2.2.0" +version = "2.3.0" source = { virtual = "." } dependencies = [ { name = "certifi" },