Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions CHANGELOG.d/0.99.0-analysis-run-comparison-strip-landing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# 0.99.0 Land the comparison strip on the opened Demo Corp row

Open period report 2026-W02 when already on that week. The grouping
comparison strip lands on Demo Corp. Mean θ stays on the report panel.
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).

## [0.99.0] - 2026-08-17

### Added

- Opening **Open period report 2026-W02** when the operator is already
on that week lands the grouping comparison strip on Demo Corp. The
Demo Corp chip is current and focused. Changing the week still
focuses the report period field. Mean θ stays on the report panel.
No TEPP theta is invented.

## [0.98.1] - 2026-08-17

### Fixed
Expand Down
8 changes: 5 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ envelope is Failed. Failed TEPP is terminal — request a new run,
then start. Do not invent a theta. Hover the Result prefix to read
the parent-choice digest.
After `make seed`, open **Period report · Succeeded · Demo Corp**,
then **Open period report 2026-W02**. The report period field is
focused. Report grouping is Corporate entity and Demo Corp is current.
Mean θ stays on the period-report panel.
then **Open period report 2026-W02**. The home week is already
2026-W02, so the grouping comparison strip lands on Demo Corp. Report
grouping is Corporate entity and Demo Corp is current. Changing the
week first still focuses the report period field. Mean θ stays on the
period-report panel.
5 changes: 3 additions & 2 deletions docs/adr/0024-seed-period-report-analysis-run.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,9 @@ After `make seed`, Demo Analyst opens Analysis runs and sees
rows. Opening it shows the cutoff posts and **Open period report
2026-W02** (the week stored on `scope_key`). That click also switches
Report grouping to Corporate entity and marks the Demo Corp grouping
current, using the persisted scope grouping key. Mean θ remains on
the period-report panel. Re-seed is idempotent on
current, using the persisted scope grouping key. When the operator is
already on that week, the comparison strip lands on Demo Corp. Mean θ
remains on the period-report panel. Re-seed is idempotent on
`demo-report-seed-2026-w02`.

## References — APA 7th
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": "0.98.1",
"version": "0.99.0",
"type": "module",
"scripts": {
"dev": "vite",
Expand Down
32 changes: 32 additions & 0 deletions frontend/src/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2190,6 +2190,38 @@ describe("App, authenticated", () => {
expect(screen.queryByText(/corp-1: mean θ/)).not.toBeInTheDocument();
});

it("lands the comparison strip on Demo Corp when already on that week", async () => {
stubBackend({ succeededReportRun: true });
const scrollIntoView = vi.fn();
const originalScrollIntoView = HTMLElement.prototype.scrollIntoView;
HTMLElement.prototype.scrollIntoView = scrollIntoView;
try {
render(<App />);

const periodInput = await screen.findByLabelText("Report period");
expect(periodInput).toHaveValue("2026-W02");
expect(screen.getByLabelText("Report grouping")).toHaveValue("process_unit");

await userEvent.click(
await screen.findByRole("button", {
name: "Open analysis run: Period report · Succeeded · Demo Corp",
}),
);
await userEvent.click(screen.getByRole("button", { name: "Open period report 2026-W02" }));

expect(periodInput).toHaveValue("2026-W02");
expect(screen.getByLabelText("Report grouping")).toHaveValue("corporate_entity");
const demoChip = screen.getByRole("button", { name: "Compare corporate_entity: Demo Corp" });
expect(demoChip).toHaveAttribute("aria-current", "true");
expect(demoChip).toHaveFocus();
expect(scrollIntoView).toHaveBeenCalled();
expect(periodInput).not.toHaveFocus();
expect(await screen.findByText(/Demo Corp: mean θ 0\.42/)).toBeInTheDocument();
} finally {
HTMLElement.prototype.scrollIntoView = originalScrollIntoView;
}
});

it("does not tell a failed period report to connect the measurement service", async () => {
stubBackend({ failedReportRun: true });
render(<App />);
Expand Down
39 changes: 37 additions & 2 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1742,10 +1742,12 @@ function analysisRunPostOpenOptions(run: AnalysisRun, postId: string): SelectPos

function AnalysisRunsPanel({
accessToken,
currentReportPeriod,
onSelectPost,
onSelectReportPeriod,
}: {
accessToken: string;
currentReportPeriod?: string;
onSelectPost: (postId: string, options?: SelectPostOptions) => void;
onSelectReportPeriod?: (
periodCode: string,
Expand Down Expand Up @@ -1930,13 +1932,16 @@ function AnalysisRunsPanel({
onClick={() => {
const periodCode = analysisRunReportPeriod(selected);
if (periodCode) {
const alreadyOnWeek = currentReportPeriod === periodCode;
onSelectReportPeriod(
periodCode,
analysisRunReportGrouping(selected) ?? undefined,
analysisRunReportGroupingKey(selected),
selected.scope_entity_name,
);
document.getElementById("report-period")?.focus();
if (!alreadyOnWeek) {
document.getElementById("report-period")?.focus();
}
}
}}
>
Expand Down Expand Up @@ -2098,6 +2103,7 @@ function ReportsPanel({
openedGroupingKey,
openedGroupingLabel,
onOpenGrouping,
landOnComparison,
}: {
accessToken: string;
canRebuild: boolean;
Expand All @@ -2109,12 +2115,14 @@ function ReportsPanel({
openedGroupingKey?: string | null;
openedGroupingLabel?: string | null;
onOpenGrouping?: (groupingKey: string, groupingLabel: string) => void;
landOnComparison?: boolean;
}) {
const [payload, setPayload] = useState<PeriodReports | null>(null);
const [index, setIndex] = useState<PeriodReportIndex | null>(null);
const [comparison, setComparison] = useState<PeriodComparison | null>(null);
const [error, setError] = useState<string | null>(null);
const [rebuilding, setRebuilding] = useState(false);
const openedComparisonRef = useRef<HTMLButtonElement | null>(null);

const groupingLabels: Record<string, string> = {
process_unit: "Process unit",
Expand Down Expand Up @@ -2147,6 +2155,18 @@ function ReportsPanel({
.catch((err) => setError(String(err)));
}, [accessToken, grouping, period]);

useEffect(() => {
if (!landOnComparison) {
return;
}
const current = openedComparisonRef.current;
if (!current) {
return;
}
current.scrollIntoView({ block: "nearest" });
current.focus();
}, [landOnComparison, grouping, openedGroupingKey, openedGroupingLabel, comparison]);

async function handleRebuild() {
setRebuilding(true);
setError(null);
Expand Down Expand Up @@ -2202,6 +2222,11 @@ function ReportsPanel({
<li key={`${row.grouping_kind}:${row.grouping_key}`} className="ticket-list-item">
<button
className="post-list-item"
ref={
groupingIsOpened(row.grouping_kind, row.grouping_key, row.grouping_label)
? openedComparisonRef
: undefined
}
aria-label={`Compare ${row.grouping_kind}: ${row.grouping_label}`}
aria-current={
groupingIsOpened(row.grouping_kind, row.grouping_key, row.grouping_label)
Expand Down Expand Up @@ -2341,13 +2366,15 @@ function PostList({ accessToken }: { accessToken: string }) {
const [reportGrouping, setReportGrouping] = useState("process_unit");
const [openedGroupingKey, setOpenedGroupingKey] = useState<string | null>(null);
const [openedGroupingLabel, setOpenedGroupingLabel] = useState<string | null>(null);
const [landOnComparison, setLandOnComparison] = useState(false);

function openReportFromAnalysisRun(
periodCode: string,
groupingKind?: string,
groupingKey?: string,
groupingLabel?: string,
) {
setLandOnComparison(reportPeriod === periodCode);
setReportPeriod(periodCode);
if (groupingKind) {
setReportGrouping(groupingKind);
Expand All @@ -2360,6 +2387,12 @@ function PostList({ accessToken }: { accessToken: string }) {
setReportGrouping(groupingKind);
setOpenedGroupingKey(null);
setOpenedGroupingLabel(null);
setLandOnComparison(false);
}

function selectReportPeriod(periodCode: string) {
setReportPeriod(periodCode);
setLandOnComparison(false);
}

function openComparedGrouping(groupingKey: string, groupingLabel: string) {
Expand Down Expand Up @@ -2409,6 +2442,7 @@ function PostList({ accessToken }: { accessToken: string }) {
<CalendarPanel accessToken={accessToken} onSelectPost={selectPost} />
<AnalysisRunsPanel
accessToken={accessToken}
currentReportPeriod={reportPeriod}
onSelectPost={selectPost}
onSelectReportPeriod={openReportFromAnalysisRun}
/>
Expand All @@ -2417,12 +2451,13 @@ function PostList({ accessToken }: { accessToken: string }) {
canRebuild={canRebuild}
onSelectPost={selectPost}
period={reportPeriod}
onSelectPeriod={setReportPeriod}
onSelectPeriod={selectReportPeriod}
grouping={reportGrouping}
onSelectGrouping={selectReportGrouping}
openedGroupingKey={openedGroupingKey}
openedGroupingLabel={openedGroupingLabel}
onOpenGrouping={openComparedGrouping}
landOnComparison={landOnComparison}
/>
<section className="popup-section lineage-home">
<div className="lineage-home-header">
Expand Down
2 changes: 1 addition & 1 deletion lineageweave/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,4 @@
"sentence_excerpts",
]

__version__ = "0.98.1"
__version__ = "0.99.0"
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "lineageweave"
version = "0.98.1"
version = "0.99.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" }
Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.