Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
bf2478a
feat: name Weekly VOC and focus Event Lineage (v2.13.0)
seonghobae Aug 19, 2026
2ee8378
fix: reject impossible Weekly VOC dates
seonghobae Aug 20, 2026
8c153a5
feat: open Calendar commitments onto Event Lineage (v2.14.0)
seonghobae Aug 19, 2026
da4978d
fix: stop auto-drilled Keyman panel from stealing Event Lineage focus
seonghobae Aug 20, 2026
b7ade01
fix: keep Calendar scroll with Event Lineage
seonghobae Aug 20, 2026
e5d3f60
feat: open Customer master related posts onto Event Lineage (v2.15.0)
seonghobae Aug 19, 2026
c4987c3
test: keep customer master router specific
seonghobae Aug 20, 2026
78babdd
feat: open Ask Agent cited posts onto Event Lineage (v2.16.0)
seonghobae Aug 19, 2026
a117ba7
chore: restack Ask Agent PR without rewriting its head
seonghobae Aug 20, 2026
0910eb8
test(red): reproduce stale Ask Agent citations
seonghobae Aug 20, 2026
7d73439
chore: remove self-modifying repair workflow
seonghobae Aug 20, 2026
432ac25
test(ui): reproduce superseded Ask evidence
seonghobae Aug 20, 2026
f30c30a
fix(ui): clear superseded Ask evidence normally
seonghobae Aug 20, 2026
29a6a74
chore: restack Ask Agent on current Customer Master head
seonghobae Aug 20, 2026
985c6ed
chore: restack Ask Agent on current Customer Master head
seonghobae Aug 20, 2026
350b970
chore: restack Ask Agent on current Customer Master
seonghobae Aug 20, 2026
44da864
chore: restack Ask Agent on current Customer Master
seonghobae Aug 20, 2026
7ab8de0
chore: reconcile remote Ask Agent restack
seonghobae Aug 20, 2026
25a653d
chore: restack Ask Agent on final Customer Master
seonghobae Aug 20, 2026
4f68b64
chore: restack Ask Agent on final Customer Master
seonghobae Aug 20, 2026
a239f6b
chore: restack Ask Agent on final Customer Master
seonghobae Aug 20, 2026
3657f8b
Merge remote-tracking branch 'origin/feat/customer-master-open-focus-…
seonghobae Aug 20, 2026
358b694
Merge commit '55934e2d1b33421f4a5d3c9c164ed07c5a747e82' of https://gi…
seonghobae Aug 20, 2026
fb92785
fix: avoid ask-agent ADR number collision
seonghobae Aug 20, 2026
b47d1fc
fix: align embedded image accessibility assertion
seonghobae Aug 20, 2026
f3d2438
Merge remote-tracking branch 'origin/feat/customer-master-open-focus-…
seonghobae Aug 20, 2026
2800b87
Merge remote-tracking branch 'origin/feat/customer-master-open-focus-…
seonghobae Aug 20, 2026
af6384c
Merge remote-tracking branch 'origin/feat/customer-master-open-focus-…
seonghobae Aug 20, 2026
de1659d
Merge current customer lineage base into Ask Agent lineage
seonghobae Aug 20, 2026
9238375
chore: sync lock metadata with release version
seonghobae Aug 20, 2026
ae79af8
merge: propagate current customer lineage base
seonghobae Aug 20, 2026
4f0a170
merge: propagate corrected Weekly VOC lineage base
seonghobae Aug 20, 2026
5df58a7
merge: propagate current protected board base
seonghobae Aug 20, 2026
f70a659
merge: propagate current board branch head
seonghobae Aug 20, 2026
d670acd
merge: propagate current semantic-source parent
seonghobae Aug 20, 2026
ef7189e
Merge remote-tracking branch 'origin/feat/customer-master-open-focus-…
seonghobae Aug 20, 2026
9ffe3b6
Merge remote-tracking branch 'origin/feat/customer-master-open-focus-…
seonghobae Aug 20, 2026
6e18cf4
Merge remote-tracking branch 'origin/feat/customer-master-open-focus-…
seonghobae Aug 21, 2026
457e7e1
Merge remote-tracking branch 'origin/feat/customer-master-open-focus-…
seonghobae Aug 21, 2026
5bd176c
Merge remote-tracking branch 'origin/feat/customer-master-open-focus-…
seonghobae Aug 21, 2026
349d559
Merge remote-tracking branch 'origin/feat/customer-master-open-focus-…
seonghobae Aug 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ Opening a Calendar commitment uses the same focus path (ADR 0094). Do not
invent a week, a theta, a cutoff body, or a CalDAV event.
Opening a Customer master related post uses the same focus path (ADR 0095).
Do not invent a week, a theta, a cutoff body, a CalDAV event, or a customer.
Opening an Ask Agent cited post uses the same focus path (ADR 0096). Do not
invent a cited post.


## Tests
Expand Down
3 changes: 2 additions & 1 deletion ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,8 @@ rebuild), the post list with a named Weekly VOC ISO-8601 week filter
(ADR 0092; opening that filtered post focuses Event Lineage, ADR 0093),
Calendar commitments use the same Event Lineage focus path (ADR 0094),
Customer master related posts use the same Event Lineage focus path
(ADR 0095), and the full detail popup includes Korean
(ADR 0095). Ask Agent cited posts use the same Event Lineage focus path
(ADR 0096), and the full detail popup includes Korean
summary/key-events/R&R, VOC evidence excerpts, an Event Lineage panel
(direct vs. indirect links; a link opens that post), the Keyman
affiliate tree (resolved ancestors plus unresolved org roots), Keyman +
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.d/2.16.0-ask-agent-open-event-lineage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# 2.16.0 Opening an Ask Agent cited post focuses Event Lineage

Ask Agent names authorized cited posts as current after an answer and to
open one to read Event Lineage. That open focuses the popup Event Lineage
heading. Home-list opens do not. No TEPP theta is invented.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ 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.16.0] - 2026-08-19

### Added

- Opening an Ask Agent cited post now focuses Event Lineage and names Keyman
and evaluation as the next read. After an authorized answer, Ask Agent
names cited posts as current before that open. Home-list opens do not add
that focus or copy. No TEPP theta is invented. No cited post is invented
(ADR 0096 / ADR 0039 / ADR 0016).

## [2.15.0] - 2026-08-19

### Added
Expand Down
7 changes: 7 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,10 @@ Open Customer master. Authorized customer entities are current. Open a
related post: Event Lineage takes focus and names Keyman and evaluation
next (ADR 0095). A home-list open does not. Do not invent a theta or a
customer.

## Ask Agent open (v2.16.0)

Open Ask Agent. After an authorized answer, cited posts are current. Open
a cited post: Event Lineage takes focus and names Keyman and evaluation
next (ADR 0096). A home-list open does not. Do not invent a theta or a
cited post.
36 changes: 36 additions & 0 deletions docs/adr/0096-ask-agent-open-focuses-event-lineage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# ADR 0096: Opening an Ask Agent cited post focuses Event Lineage

- Status: Accepted
- Date: 2026-08-19

## Context

Board Weekly VOC, Calendar, and Customer master opens already focus Event
Lineage (ADR 0093 / ADR 0094 / ADR 0095). Ask Agent is the remaining buyer
GNB destination that opens an authorized cited post. That open was a
home-list open: the popup body appeared and Event Lineage did not take
focus.

## Decision

Opening a cited post on Ask Agent is a `fromAskAgent` open. That open
reuses the Event Lineage focus path used by report-member, Weekly VOC,
Calendar, and Customer master opens:

- After an authorized answer, Ask Agent names the next action: cited posts
are current; open a cited post to read Event Lineage.
- The popup Event Lineage heading takes focus.
- The popup names the opened post as current in Event Lineage and tells
the buyer to read Keyman and evaluation next.

A Board home-list open does not focus Event Lineage and does not add that
copy. A `?post=` deep link is still a home-list open.

No TEPP theta is invented. No cutoff body is invented (ADR 0016). Ask Agent
does not invent a cited post (ADR 0039).

## Consequences

- Ask Agent, Customer master, Calendar, Weekly VOC, and report-member
opens share one focus contract.
- Closing the popup clears the Ask Agent open flag.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# ADR 0096: Preserve authorized internal evidence for relation verification
# ADR 0097: Preserve authorized internal evidence for relation verification

- Status: Accepted
- Date: 2026-08-18
Expand Down
2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "frontend",
"private": true,
"version": "2.15.0",
"version": "2.16.0",
"type": "module",
"scripts": {
"dev": "vite",
Expand Down
107 changes: 106 additions & 1 deletion frontend/src/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ describe("App, authenticated", () => {
pendingTeppRun?: boolean;
pluralAffiliations?: boolean;
deferMe?: boolean;
deferSecondAsk?: boolean;
meFailed?: boolean;
postBody?: string;
manyCustomerHints?: number;
Expand Down Expand Up @@ -122,6 +123,7 @@ describe("App, authenticated", () => {
contentAfterSummary?: boolean;
}): ReturnType<typeof vi.fn> & {
releaseMe: () => void;
releaseSecondAsk: () => void;
releaseGroupRelated: () => void;
releaseDemoRelated: () => void;
} {
Expand Down Expand Up @@ -156,6 +158,13 @@ describe("App, authenticated", () => {
releaseMe = resolve;
})
: Promise.resolve();
let releaseSecondAsk = () => {};
const secondAskReady = options?.deferSecondAsk
? new Promise<void>((resolve) => {
releaseSecondAsk = resolve;
})
: Promise.resolve();
let askRequestCount = 0;
let releaseGroupRelated = () => {};
let releaseDemoRelated = () => {};
const groupRelatedReady = options?.deferCustomerRelated
Expand Down Expand Up @@ -248,6 +257,9 @@ describe("App, authenticated", () => {
if (url.endsWith("/api/posts/post-1/activity") && method === "GET") {
return Promise.resolve(jsonResponse({ events }));
}
if (url.endsWith("/api/posts/post-2/activity") && method === "GET") {
return Promise.resolve(jsonResponse({ events: [] }));
}
if (url.endsWith("/api/posts/post-1/derive-commitment") && method === "POST") {
if (options?.chatUnavailable) {
return Promise.resolve(
Expand Down Expand Up @@ -1278,6 +1290,17 @@ describe("App, authenticated", () => {
}),
);
}
if (url.endsWith("/api/posts/post-2/summary")) {
return Promise.resolve(
jsonResponse({
post_id: "post-2",
korean_summary: "연결된 글입니다.",
key_events: [],
roles_and_responsibilities: [],
project_mentions: [],
}),
);
}
if (url.endsWith("/api/posts/post-1/keymen")) {
return Promise.resolve(
jsonResponse({
Expand Down Expand Up @@ -1588,6 +1611,15 @@ describe("App, authenticated", () => {
}),
);
}
if (url.endsWith("/api/posts/post-2/lineage")) {
return Promise.resolve(
jsonResponse({
post_id: "post-2",
direct: [{ post_id: "post-1", post_title: "Public post" }],
indirect: [],
}),
);
}
if (url.endsWith("/api/posts/post-1/chat") && method === "GET") {
return Promise.resolve(
jsonResponse({
Expand Down Expand Up @@ -1638,7 +1670,13 @@ describe("App, authenticated", () => {
);
}
if (url.endsWith("/api/ask") && method === "POST") {
return Promise.resolve(
askRequestCount += 1;
const ready =
options?.deferSecondAsk && askRequestCount === 2
? secondAskReady
: Promise.resolve();
return ready.then(() =>
Promise.resolve(
jsonResponse({
answer_text: "The cited project is supported by the stored semantic evidence.",
cited_post_ids: ["post-2"],
Expand All @@ -1654,6 +1692,7 @@ describe("App, authenticated", () => {
],
source_post_ids: ["post-1", "post-2"],
}),
),
);
}
if (url.endsWith("/api/customer-master") && method === "GET") {
Expand Down Expand Up @@ -1751,6 +1790,7 @@ describe("App, authenticated", () => {
vi.stubGlobal("fetch", fetchMock);
return Object.assign(fetchMock, {
releaseMe,
releaseSecondAsk,
releaseGroupRelated,
releaseDemoRelated,
});
Expand All @@ -1770,6 +1810,42 @@ describe("App, authenticated", () => {
expect(screen.queryByText(/ontology_iri|contextual_orchestrator/i)).not.toBeInTheDocument();
});

it("hides previous Ask evidence while a new answer is pending", async () => {
const fetchMock = stubBackend({ deferSecondAsk: true });
render(<App />);

await userEvent.click(await screen.findByRole("button", { name: "Ask Agent" }));
const ask = await screen.findByRole("region", { name: "Ask Agent" });
const question = within(ask).getByRole("textbox", { name: "Ask a question" });
await userEvent.type(question, "Which project?");
await userEvent.click(within(ask).getByRole("button", { name: "Ask" }));
expect(
await within(ask).findByText(
"The cited project is supported by the stored semantic evidence.",
),
).toBeInTheDocument();
expect(within(ask).getByLabelText("Next action")).toBeInTheDocument();

await userEvent.clear(question);
await userEvent.type(question, "Which person?");
await userEvent.click(within(ask).getByRole("button", { name: "Ask" }));

expect(within(ask).getByRole("button", { name: "Asking..." })).toBeDisabled();
expect(
within(ask).queryByText(
"The cited project is supported by the stored semantic evidence.",
),
).not.toBeInTheDocument();
expect(within(ask).queryByLabelText("Next action")).not.toBeInTheDocument();

fetchMock.releaseSecondAsk();
expect(
await within(ask).findByText(
"The cited project is supported by the stored semantic evidence.",
),
).toBeInTheDocument();
});

it("labels the Customer Master entity level and Keymen side, never the raw lookup code", async () => {
// Live UI finding (2026-08-19): read_customer_master() skipped the
// common_lookup_value join both endpoints elsewhere already use,
Expand Down Expand Up @@ -2138,6 +2214,35 @@ describe("App, authenticated", () => {
).toBeInTheDocument();
});

it("opening an Ask Agent cited post focuses Event Lineage; a home list open does not", async () => {
stubBackend();
render(<App />);

await userEvent.click(await screen.findByRole("button", { name: "Ask Agent" }));
const ask = await screen.findByRole("region", { name: "Ask Agent" });
await userEvent.type(within(ask).getByRole("textbox", { name: "Ask a question" }), "Which project?");
await userEvent.click(within(ask).getByRole("button", { name: "Ask" }));
expect(await within(ask).findByLabelText("Next action")).toHaveTextContent(
"Authorized cited posts are current. Open a cited post to read Event Lineage.",
);
await userEvent.click(within(ask).getByRole("button", { name: "Open cited post: Linked post" }));

await waitFor(() =>
expect(screen.getByText("The evidence panel should show exactly this text.")).toBeInTheDocument(),
);
expect(document.getElementById("post-event-lineage")).toHaveFocus();
expect(screen.getByRole("status", { name: "Event Lineage next action" })).toHaveTextContent(
"Linked post is current in Event Lineage. Read Keyman and evaluation next.",
);

await userEvent.click(screen.getByRole("button", { name: "Close" }));
const boardAfterAsk = screen.getByRole("region", { name: "Board" });
await userEvent.click(within(boardAfterAsk).getByRole("button", { name: "View post: Public post" }));
await waitFor(() => expect(screen.getByText("The full body text.")).toBeInTheDocument());
expect(document.getElementById("post-event-lineage")).not.toHaveFocus();
expect(screen.queryByRole("status", { name: "Event Lineage next action" })).not.toBeInTheDocument();
});

it("renders the A-100 fork as a git-style DAG, not a flat edge list", async () => {
stubBackend();
render(<App showLabPanels />);
Expand Down
Loading
Loading