diff --git a/CHANGELOG.d/2.6.0-land-first-ask-answer.md b/CHANGELOG.d/2.6.0-land-first-ask-answer.md new file mode 100644 index 000000000..7a3c0c80a --- /dev/null +++ b/CHANGELOG.d/2.6.0-land-first-ask-answer.md @@ -0,0 +1,5 @@ +# 2.6.0 Land the first Ask answer under the named seed next action + +Open Public post from the landed Demo Corp members and the first seeded +Ask answer sits under the Ask seed next action, ahead of the input. +Home list opens keep that answer after the input. diff --git a/CHANGELOG.md b/CHANGELOG.md index c4318d5ed..e4a3c9abe 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.6.0] - 2026-08-17 + +### Added + +- Opening Public post from the landed Demo Corp members now puts the + first Ask answer immediately under the named seed next action, ahead + of the chat input. Home list opens keep that answer after the input. + No TEPP theta is invented. No cutoff body is invented (ADR 0016). + ## [2.5.0] - 2026-08-17 ### Added diff --git a/CLAUDE.md b/CLAUDE.md index e3c68fe9b..2cc176764 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -59,6 +59,8 @@ landed Ada West related, the popup names the first related node as the next read. After that next action, the popup lands Priya Nair related nodes. After those related nodes land, the popup names Ask about this lineage as the next read. After that next action, the -popup lands Ask about this lineage. Changing the week first still +popup lands Ask about this lineage. After landed chat, the popup names +the first Ask. After that next action, the popup lands the first Ask +answer. Changing the week first still focuses the report period field. Mean θ stays on the period-report panel. diff --git a/frontend/package.json b/frontend/package.json index 511fd79db..1ddeeb39e 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "frontend", "private": true, - "version": "2.5.0", + "version": "2.6.0", "type": "module", "scripts": { "dev": "vite", diff --git a/frontend/src/App.test.tsx b/frontend/src/App.test.tsx index 784a047a6..53a8fab13 100644 --- a/frontend/src/App.test.tsx +++ b/frontend/src/App.test.tsx @@ -1521,6 +1521,19 @@ describe("App, authenticated", () => { expect( screen.getByText("The next commitment is Send Northridge Grid the revised quote, due 2026-01-12."), ).toBeInTheDocument(); + const homePopup = document.querySelector(".popup-panel"); + expect(homePopup).not.toBeNull(); + const homeAsk = within(homePopup as HTMLElement).getByRole("heading", { + name: "Ask about this lineage", + }); + const homeInput = within(homePopup as HTMLElement).getByPlaceholderText(/what happened/i); + const homeAnswer = within(homePopup as HTMLElement).getByText( + "The seeded follow-up after the site visit.", + ); + expect(homeAsk.compareDocumentPosition(homeInput) & Node.DOCUMENT_POSITION_FOLLOWING).not.toBe(0); + expect(homeInput.compareDocumentPosition(homeAnswer) & Node.DOCUMENT_POSITION_FOLLOWING).not.toBe( + 0, + ); expect(screen.getByRole("button", { name: /ask seeded question: what happened between these events/i })).toBeInTheDocument(); expect(screen.getByRole("button", { name: /ask seeded question: who is involved/i })).toBeInTheDocument(); expect(screen.getByRole("button", { name: /ask seeded question: what is the next commitment/i })).toBeInTheDocument(); @@ -2396,6 +2409,22 @@ describe("App, authenticated", () => { name: "Ask seeded question: What happened between these events?", }), ).toHaveAttribute("aria-current", "true"); + const firstAskAnswer = within(popup as HTMLElement).getByText( + "The seeded follow-up after the site visit.", + ); + const askInput = within(popup as HTMLElement).getByPlaceholderText(/what happened/i); + expect( + askSeed.compareDocumentPosition(firstAskAnswer) & Node.DOCUMENT_POSITION_FOLLOWING, + ).not.toBe(0); + expect( + firstAskAnswer.compareDocumentPosition(askInput) & Node.DOCUMENT_POSITION_FOLLOWING, + ).not.toBe(0); + expect( + firstAskAnswer.compareDocumentPosition(affiliate) & Node.DOCUMENT_POSITION_FOLLOWING, + ).not.toBe(0); + expect( + within(popup as HTMLElement).getAllByText("The seeded follow-up after the site visit."), + ).toHaveLength(1); await waitFor(() => expect(document.getElementById("post-ask")).toHaveFocus()); } finally { HTMLElement.prototype.scrollIntoView = originalScrollIntoView; @@ -2681,9 +2710,19 @@ describe("App, authenticated", () => { const askNext = screen.getByRole("status", { name: "Ask next action" }); expect(askNext.compareDocumentPosition(ask) & Node.DOCUMENT_POSITION_FOLLOWING).not.toBe(0); expect(ask.compareDocumentPosition(affiliate) & Node.DOCUMENT_POSITION_FOLLOWING).not.toBe(0); - expect(await screen.findByRole("status", { name: "Ask seed next action" })).toHaveTextContent( + const askSeed = await screen.findByRole("status", { name: "Ask seed next action" }); + expect(askSeed).toHaveTextContent( "What happened between these events? is the first Ask. Read that answer next.", ); + const firstAskAnswer = within(popup as HTMLElement).getByText( + "The seeded follow-up after the site visit.", + ); + expect( + askSeed.compareDocumentPosition(firstAskAnswer) & Node.DOCUMENT_POSITION_FOLLOWING, + ).not.toBe(0); + expect(firstAskAnswer.compareDocumentPosition(affiliate) & Node.DOCUMENT_POSITION_FOLLOWING).not.toBe( + 0, + ); await waitFor(() => expect(document.getElementById("post-ask")).toHaveFocus()); }); diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index c71270e89..4c53b73a3 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -219,6 +219,17 @@ function ChatPanel({ {firstAskNextAction(exchanges[0].question_text)}

) : null} + {nameFirstAsk && exchanges[0] ? ( +
+

{exchanges[0].question_text}

+

{exchanges[0].answer_text}

+ +
+ ) : null} {!seededOnly && (
)} {error &&

{error}

} - {exchanges.map((exchange) => ( + {exchanges + .filter( + (exchange) => + !(nameFirstAsk && exchange.question_text === exchanges[0]?.question_text), + ) + .map((exchange) => (

{exchange.question_text}

{exchange.answer_text}

diff --git a/lineageweave/__init__.py b/lineageweave/__init__.py index f452eceaa..f96875c7f 100644 --- a/lineageweave/__init__.py +++ b/lineageweave/__init__.py @@ -55,4 +55,4 @@ "sentence_excerpts", ] -__version__ = "2.5.0" +__version__ = "2.6.0" diff --git a/pyproject.toml b/pyproject.toml index cf5ffc76f..eb7cc5a39 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "lineageweave" -version = "2.5.0" +version = "2.6.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 c90a770a2..0fea7cd95 100644 --- a/uv.lock +++ b/uv.lock @@ -454,7 +454,7 @@ wheels = [ [[package]] name = "lineageweave" -version = "2.5.0" +version = "2.6.0" source = { virtual = "." } dependencies = [ { name = "certifi" },