diff --git a/docs/00_overview/DASHBOARD.md b/docs/00_overview/DASHBOARD.md index bb54dac1..003c99e9 100644 --- a/docs/00_overview/DASHBOARD.md +++ b/docs/00_overview/DASHBOARD.md @@ -7,7 +7,7 @@ _Top-level index across MVP1 → GA v1+ as of **2026-06-04**. Click a release na | Release | Theme | Progress | Status | |---|---|---|---| | [MVP1 / v0.1](MVP1_DASHBOARD.md) | The Loop | 94 / 94 scoped done | **Complete** | -| [MVP2 / v0.2](MVP2_DASHBOARD.md) | Three-Engine + Real Signals | 16 / 26 scoped done · 26 remaining | **In progress** | +| [MVP2 / v0.2](MVP2_DASHBOARD.md) | Three-Engine + Real Signals | 17 / 26 scoped done · 25 remaining | **In progress** | | MVP3 / v0.3 | Observable | — | **Not yet scoped** | | GA v1 / v1.0 | Production-ready | — | **Not yet scoped** | diff --git a/docs/00_overview/MVP2_DASHBOARD.md b/docs/00_overview/MVP2_DASHBOARD.md index 69f7704e..8dbbb6b8 100644 --- a/docs/00_overview/MVP2_DASHBOARD.md +++ b/docs/00_overview/MVP2_DASHBOARD.md @@ -21,20 +21,20 @@ Plan approved; run /impl-execute to ship | Metric | Value | |---|---| | Filed under MVP2 | **50** folders total (done + specced not-done + idea backlog + bugs) | -| Specced features done | **16 / 26** (62%) — of features *past the idea stage* (those with a spec); the idea backlog below is NOT in this denominator, so 100% ≠ release complete | -| Pending work | **32** items (every not-done feat/infra/chore/bug across all priorities) | +| Specced features done | **17 / 26** (65%) — of features *past the idea stage* (those with a spec); the idea backlog below is NOT in this denominator, so 100% ≠ release complete | +| Pending work | **31** items (every not-done feat/infra/chore/bug across all priorities) | | → P0 — do next | **0** unblocking / paying daily cost | | → P1 | **0** high-value, ready when P0 clears | -| → P2 (default) | 27 important to file, not blocking | +| → P2 (default) | 26 important to file, not blocking | | → Backlog | 5 captured for record, not planned | | Open bugs | 9 | -| Legacy "Path to MVP2" | 26 items — scoped-not-done + bugs + chore-ideas only (excludes feat/infra ideas) | +| Legacy "Path to MVP2" | 25 items — scoped-not-done + bugs + chore-ideas only (excludes feat/infra ideas) | | Backlog ideas | 6 idea-only feat/infra (not yet scoped into MVP2) | | In flight | 0 feature(s) actively shipping | ## Pipeline -### Done (18) +### Done (19) | Feature | Type | One-liner | Depends on | Status | |---|---|---|---|---| @@ -43,6 +43,7 @@ Plan approved; run /impl-execute to ship | [feat_overnight_autopilot](implemented_features/2026_05_31_feat_overnight_autopilot/feature_spec.md) | Feature | an operator can (a) discover the overnight path while creating a study because the wizard control is reframed as a labeled "🌙 Run overnight (compound automatically)" toggle with explicit copy about th | — | [PR #343](https://github.com/SoundMindsAI/relyloop/pull/343) merged 2026-05-31 | | [feat_overnight_final_solution](implemented_features/2026_06_04_feat_overnight_final_solution/feature_spec.md) | Feature | The wizard exposes a strategy choice alongside the existing depth: keep today's predictable `narrow` loop OR opt into `follow_suggestions`, which lets each chain link consume the parent digest's top * | — | [PR #440](https://github.com/SoundMindsAI/relyloop/pull/440) merged 2026-06-04 | | [feat_overnight_final_solution_phase2](implemented_features/2026_06_04_feat_overnight_final_solution_phase2/feature_spec.md) | Feature | When the chain that this study belongs to has terminated (`stop_reason` ≠ `in_flight`) and has at least 2 links, a top-of-page **Overnight result card** mounts above `LinkedEntitiesRow` and compresses | — | [PR #442](https://github.com/SoundMindsAI/relyloop/pull/442) merged 2026-06-04 | +| [feat_overnight_studies_summary_card](implemented_features/2026_06_04_feat_overnight_studies_summary_card/feature_spec.md) | Feature | A "ran while you were away" card surfaces at the top of `/studies` when at least one overnight chain has completed since the operator's last visit. | — | [PR #444](https://github.com/SoundMindsAI/relyloop/pull/444) merged 2026-06-04 | | [feat_studies_convergence_visibility](implemented_features/2026_06_02_feat_studies_convergence_visibility/feature_spec.md) | Feature | The studies list shows a completed-trial count and a convergence badge (`Converged` / `Still improving` / `Too few trials`) per study, reusing the shipped classifier. | — | [PR #421](https://github.com/SoundMindsAI/relyloop/pull/421) merged 2026-06-02 | | [feat_study_convergence_indicator](implemented_features/2026_06_01_feat_study_convergence_indicator/feature_spec.md) | Feature | Every completed study carries a plain-language **convergence verdict** — `converged` / `still_improving` / `too_few_trials` — backed by a best-metric-so-far curve. | — | [PR #352](https://github.com/SoundMindsAI/relyloop/pull/352) merged 2026-06-01 | | [feat_study_sub_warmup_guard](implemented_features/2026_05_29_feat_study_sub_warmup_guard/feature_spec.md) | Feature | A non-blocking inline warning appears under the `max_trials` input whenever the derived preset is `custom` AND `max_trials < STUDIES_TPE_WARMUP_FLOOR (= 50)`, naming Focused/Standard as one-click reme | — | [PR #316](https://github.com/SoundMindsAI/relyloop/pull/316) merged 2026-05-29 | @@ -61,22 +62,21 @@ Plan approved; run /impl-execute to ship _None._ -### Plan (12) +### Plan (11) | # | Priority | Feature | Type | One-liner | Depends on | Status | |---|---|---|---|---|---|---| | 1 | P2 | [feat_apply_path_normalizer_declaration](planned_features/02_mvp2/feat_apply_path_normalizer_declaration/feature_spec.md) | Feature | The winning normalizer ships as a **structured, language-agnostic manifest** in the config-repo PR — not just prose. | — | — | -| 2 | P2 | [feat_overnight_studies_summary_card](planned_features/02_mvp2/feat_overnight_studies_summary_card/feature_spec.md) | Feature | A "ran while you were away" card surfaces at the top of `/studies` when at least one overnight chain has completed since the operator's last visit. | — | [PR #343](https://github.com/SoundMindsAI/relyloop/pull/343) | -| 3 | P2 | [feat_query_normalization_tuning](planned_features/02_mvp2/feat_query_normalization_tuning/feature_spec.md) | Feature | A template that opts in by declaring `query_normalizer` as a Categorical param gets the Optuna loop deciding empirically — on the operator's judgment set — whether lowercasing, trimming, or contractio | — | — | -| 4 | P2 | [feat_query_normalizer_typed_pipeline](planned_features/02_mvp2/feat_query_normalizer_typed_pipeline/feature_spec.md) | Feature | A new typed search-space member `NormalizerPipelineParam` lets a template declare an **ordered list of normalization steps**; the Optuna loop samples over the powerset of declared steps and proposes t | — | — | -| 5 | P2 | [feat_ubi_llm_study_comparison](planned_features/02_mvp2/feat_ubi_llm_study_comparison/feature_spec.md) | Feature | A single dedicated route `/studies/compare?a={id}&b={id}` renders the two studies side-by-side with a per-panel diff column: a sentence-level digest-narrative diff, a best-trial parameter table with s | — | [PR #320](https://github.com/SoundMindsAI/relyloop/pull/320) | -| 6 | P2 | [chore_arq_pool_aclose_deprecation](planned_features/02_mvp2/chore_arq_pool_aclose_deprecation/feature_spec.md) | Chore | Both call sites use `await arq_pool.aclose()`; no `DeprecationWarning` on shutdown; a regression guard asserts the async-correct form on both paths so a future edit cannot silently reintroduce `close( | — | — | -| 7 | P2 | [chore_cluster_detail_rung_badge](planned_features/02_mvp2/chore_cluster_detail_rung_badge/feature_spec.md) | Chore | The cluster-detail page surfaces a `` for the cluster, scoped by a user-selected (or auto-seeded) query set + target. | — | [PR #320](https://github.com/SoundMindsAI/relyloop/pull/320) | -| 8 | P2 | [chore_demo_seeding_integration_tests_rewrite](planned_features/02_mvp2/chore_demo_seeding_integration_tests_rewrite/feature_spec.md) | Chore | The 9 skipped cases are rewritten to the async "POST + poll-until-terminal" shape, the timeout case is re-homed to the worker layer, a new `AC-Async` case asserts the `running → complete` polling tran | — | [PR #286](https://github.com/SoundMindsAI/relyloop/pull/286) | -| 9 | P2 | [chore_studies_post_arq_spy_fixture](planned_features/02_mvp2/chore_studies_post_arq_spy_fixture/feature_spec.md) | Chore | A reusable `arq_pool_spy` integration fixture that records every `enqueue_job(name, *args)` call, letting studies-POST tests positively assert `spy.calls == []` on rejection and `spy.calls == [("start | — | — | -| 10 | P2 | [chore_ubi_reader_search_after_pagination](planned_features/02_mvp2/chore_ubi_reader_search_after_pagination/feature_spec.md) | Chore | A new engine-neutral `SearchAdapter.scan_all` cursor-scan lets `UbiReader` iterate the **entire** matching event/query stream for a window (subject to a caller ceiling), folding each page into the agg | — | [PR #413](https://github.com/SoundMindsAI/relyloop/pull/413) | -| 11 | P2 | [bug_baseline_phase_test_isolation](planned_features/02_mvp2/bug_baseline_phase_test_isolation/feature_spec.md) | Bug | The three `TestComputeBaselineWaitS` cases pass standalone — `.venv/bin/python -m pytest backend/tests/unit/workers/test_orchestrator_baseline_phase.py -p no:randomly` is all-green with no reliance on | — | — | -| 12 | P2 | [bug_judgment_header_omits_click_bucket](planned_features/02_mvp2/bug_judgment_header_omits_click_bucket/feature_spec.md) | Bug | The header renders all three buckets (`llm`, `human`, `click`) so the displayed terms sum to the displayed total count, making the doc-comment claim ("the UI's source-breakdown card now renders all th | — | — | +| 2 | P2 | [feat_query_normalization_tuning](planned_features/02_mvp2/feat_query_normalization_tuning/feature_spec.md) | Feature | A template that opts in by declaring `query_normalizer` as a Categorical param gets the Optuna loop deciding empirically — on the operator's judgment set — whether lowercasing, trimming, or contractio | — | — | +| 3 | P2 | [feat_query_normalizer_typed_pipeline](planned_features/02_mvp2/feat_query_normalizer_typed_pipeline/feature_spec.md) | Feature | A new typed search-space member `NormalizerPipelineParam` lets a template declare an **ordered list of normalization steps**; the Optuna loop samples over the powerset of declared steps and proposes t | — | — | +| 4 | P2 | [feat_ubi_llm_study_comparison](planned_features/02_mvp2/feat_ubi_llm_study_comparison/feature_spec.md) | Feature | A single dedicated route `/studies/compare?a={id}&b={id}` renders the two studies side-by-side with a per-panel diff column: a sentence-level digest-narrative diff, a best-trial parameter table with s | — | [PR #320](https://github.com/SoundMindsAI/relyloop/pull/320) | +| 5 | P2 | [chore_arq_pool_aclose_deprecation](planned_features/02_mvp2/chore_arq_pool_aclose_deprecation/feature_spec.md) | Chore | Both call sites use `await arq_pool.aclose()`; no `DeprecationWarning` on shutdown; a regression guard asserts the async-correct form on both paths so a future edit cannot silently reintroduce `close( | — | — | +| 6 | P2 | [chore_cluster_detail_rung_badge](planned_features/02_mvp2/chore_cluster_detail_rung_badge/feature_spec.md) | Chore | The cluster-detail page surfaces a `` for the cluster, scoped by a user-selected (or auto-seeded) query set + target. | — | [PR #320](https://github.com/SoundMindsAI/relyloop/pull/320) | +| 7 | P2 | [chore_demo_seeding_integration_tests_rewrite](planned_features/02_mvp2/chore_demo_seeding_integration_tests_rewrite/feature_spec.md) | Chore | The 9 skipped cases are rewritten to the async "POST + poll-until-terminal" shape, the timeout case is re-homed to the worker layer, a new `AC-Async` case asserts the `running → complete` polling tran | — | [PR #286](https://github.com/SoundMindsAI/relyloop/pull/286) | +| 8 | P2 | [chore_studies_post_arq_spy_fixture](planned_features/02_mvp2/chore_studies_post_arq_spy_fixture/feature_spec.md) | Chore | A reusable `arq_pool_spy` integration fixture that records every `enqueue_job(name, *args)` call, letting studies-POST tests positively assert `spy.calls == []` on rejection and `spy.calls == [("start | — | — | +| 9 | P2 | [chore_ubi_reader_search_after_pagination](planned_features/02_mvp2/chore_ubi_reader_search_after_pagination/feature_spec.md) | Chore | A new engine-neutral `SearchAdapter.scan_all` cursor-scan lets `UbiReader` iterate the **entire** matching event/query stream for a window (subject to a caller ceiling), folding each page into the agg | — | [PR #413](https://github.com/SoundMindsAI/relyloop/pull/413) | +| 10 | P2 | [bug_baseline_phase_test_isolation](planned_features/02_mvp2/bug_baseline_phase_test_isolation/feature_spec.md) | Bug | The three `TestComputeBaselineWaitS` cases pass standalone — `.venv/bin/python -m pytest backend/tests/unit/workers/test_orchestrator_baseline_phase.py -p no:randomly` is all-green with no reliance on | — | — | +| 11 | P2 | [bug_judgment_header_omits_click_bucket](planned_features/02_mvp2/bug_judgment_header_omits_click_bucket/feature_spec.md) | Bug | The header renders all three buckets (`llm`, `human`, `click`) so the displayed terms sum to the displayed total count, making the doc-comment claim ("the UI's source-breakdown card now renders all th | — | — | ### Spec (0) @@ -130,8 +130,6 @@ graph LR class chore_ubi_reader_search_after_pagination plan; feat_apply_path_normalizer_declaration["apply path normalizer declaration"] class feat_apply_path_normalizer_declaration plan; - feat_overnight_studies_summary_card["overnight studies summary card"] - class feat_overnight_studies_summary_card plan; feat_query_normalization_tuning["query normalization tuning"] class feat_query_normalization_tuning plan; feat_query_normalizer_typed_pipeline["query normalizer typed pipeline"] @@ -170,6 +168,8 @@ graph LR class feat_overnight_final_solution done; feat_overnight_final_solution_phase2["overnight final solution phase2"] class feat_overnight_final_solution_phase2 done; + feat_overnight_studies_summary_card["overnight studies summary card"] + class feat_overnight_studies_summary_card done; feat_ubi_judgments --> infra_adapter_solr ``` diff --git a/docs/00_overview/dashboard.html b/docs/00_overview/dashboard.html index 8732f0f9..a76cba7c 100644 --- a/docs/00_overview/dashboard.html +++ b/docs/00_overview/dashboard.html @@ -392,7 +392,7 @@

Releases

Three-Engine + Real Signals
-
16 / 26 scoped done · 26 remaining
+
17 / 26 scoped done · 25 remaining
In progress
diff --git a/docs/00_overview/planned_features/02_mvp2/feat_overnight_studies_summary_card/feature_spec.md b/docs/00_overview/implemented_features/2026_06_04_feat_overnight_studies_summary_card/feature_spec.md similarity index 100% rename from docs/00_overview/planned_features/02_mvp2/feat_overnight_studies_summary_card/feature_spec.md rename to docs/00_overview/implemented_features/2026_06_04_feat_overnight_studies_summary_card/feature_spec.md diff --git a/docs/00_overview/planned_features/02_mvp2/feat_overnight_studies_summary_card/idea.md b/docs/00_overview/implemented_features/2026_06_04_feat_overnight_studies_summary_card/idea.md similarity index 100% rename from docs/00_overview/planned_features/02_mvp2/feat_overnight_studies_summary_card/idea.md rename to docs/00_overview/implemented_features/2026_06_04_feat_overnight_studies_summary_card/idea.md diff --git a/docs/00_overview/planned_features/02_mvp2/feat_overnight_studies_summary_card/implementation_plan.md b/docs/00_overview/implemented_features/2026_06_04_feat_overnight_studies_summary_card/implementation_plan.md similarity index 99% rename from docs/00_overview/planned_features/02_mvp2/feat_overnight_studies_summary_card/implementation_plan.md rename to docs/00_overview/implemented_features/2026_06_04_feat_overnight_studies_summary_card/implementation_plan.md index 625f2747..0e140694 100644 --- a/docs/00_overview/planned_features/02_mvp2/feat_overnight_studies_summary_card/implementation_plan.md +++ b/docs/00_overview/implemented_features/2026_06_04_feat_overnight_studies_summary_card/implementation_plan.md @@ -1,7 +1,7 @@ # Implementation Plan — Overnight "Ran While You Were Away" Summary Card **Date:** 2026-06-01 -**Status:** Draft +**Status:** Complete (PR #444, merged 2026-06-04) **Primary spec:** [`feature_spec.md`](feature_spec.md) **Policy source(s):** [`CLAUDE.md`](../../../../CLAUDE.md) (Absolute Rules, enum discipline), [`docs/01_architecture/api-conventions.md`](../../../01_architecture/api-conventions.md), [`docs/01_architecture/ui-architecture.md`](../../../01_architecture/ui-architecture.md) diff --git a/docs/00_overview/planned_features/02_mvp2/feat_overnight_studies_summary_card/pipeline_status.md b/docs/00_overview/implemented_features/2026_06_04_feat_overnight_studies_summary_card/pipeline_status.md similarity index 54% rename from docs/00_overview/planned_features/02_mvp2/feat_overnight_studies_summary_card/pipeline_status.md rename to docs/00_overview/implemented_features/2026_06_04_feat_overnight_studies_summary_card/pipeline_status.md index 2e39b120..0a5ae738 100644 --- a/docs/00_overview/planned_features/02_mvp2/feat_overnight_studies_summary_card/pipeline_status.md +++ b/docs/00_overview/implemented_features/2026_06_04_feat_overnight_studies_summary_card/pipeline_status.md @@ -1,5 +1,7 @@ # Pipeline Status — Overnight "Ran While You Were Away" Summary Card +**Release:** mvp2 + ## Idea - Status: Complete - File: idea.md @@ -21,4 +23,12 @@ - Phases covered: single-phase (this IS Phase 2 of feat_overnight_autopilot, delivered standalone) ## Implementation -- Status: Not started +- Status: Complete +- Date: 2026-06-04 +- PR: #444 (squash-merged `ba1e6d68`) +- CI: all 17 `pr.yml` checks green +- Stories completed: 7/7 (Epic 1: 1.1 repo helper + 1.2 endpoint; Epic 2: 2.1 hooks + 2.2 card + 2.3 glossary; Epic 3: 3.1 E2E + 3.2 docs) +- Tests: 11 backend integration + 9 contract + 12 vitest + 2 Playwright E2E (33 new); full UI suite 1115 vitest green +- Cross-model review: Epic 1 GPT-5.5 1 finding (rejected — `select_best_link` signature); Epic 2 GPT-5.5 2 findings (1 accepted — raw-enum fallback; 1 rejected — plan-compliant null gate); Gemini 4 findings (2 accepted — N+1 elimination + corrupt-localStorage guard; 2 rejected — SSR hydration false positives); final GPT-5.5 0 findings (clean) +- Deferred follow-ons filed: `99_backlog/chore_studies_chain_recent_indexes` (OQ-3), `99_backlog/chore_studies_chain_recent_keyset_pagination` (OQ-2) +- No migration (Alembic head stays `0022_solr_engine_auth_check`) diff --git a/docs/00_overview/mvp2_dashboard.html b/docs/00_overview/mvp2_dashboard.html index 1f222f6b..a562b6c6 100644 --- a/docs/00_overview/mvp2_dashboard.html +++ b/docs/00_overview/mvp2_dashboard.html @@ -397,13 +397,13 @@

MVP2 Progress

Specced features done
-
16 / 26
-
62% specced · 50 filed under MVP2
-
+
17 / 26
+
65% specced · 50 filed under MVP2
+
Pending work
-
32
+
31
every not-done feat/infra/chore/bug across all priorities
@@ -425,7 +425,7 @@

MVP2 Progress

P2 (default)
-
27
+
26
important to file, not blocking
@@ -435,7 +435,7 @@

MVP2 Progress

Legacy "Path to MVP2"
-
26
+
25
scoped not-done + bugs + chore-ideas only (excludes feat/infra ideas)
@@ -732,7 +732,7 @@

Spec 0

-

Plan 12

+

Plan 11

@@ -747,19 +747,6 @@

Plan 12

-
- -
- Feature - P2 - PR #343 -
-
A "ran while you were away" card surfaces at the top of `/studies` when at least one overnight chain has completed since the operator's last visit.
- - -
- -
@@ -897,7 +884,7 @@

Implementing 0

-

Done 18

+

Done 19

@@ -964,6 +951,19 @@

Done 18

+
+ +
+ Feature + + PR #444 merged 2026-06-04 +
+
A "ran while you were away" card surfaces at the top of `/studies` when at least one overnight chain has completed since the operator's last visit.
+ + +
+ +
@@ -1157,8 +1157,6 @@

Dependency graph (feat_ + infra_)

class chore_ubi_reader_search_after_pagination plan; feat_apply_path_normalizer_declaration["apply path normalizer declaration"] class feat_apply_path_normalizer_declaration plan; - feat_overnight_studies_summary_card["overnight studies summary card"] - class feat_overnight_studies_summary_card plan; feat_query_normalization_tuning["query normalization tuning"] class feat_query_normalization_tuning plan; feat_query_normalizer_typed_pipeline["query normalizer typed pipeline"] @@ -1197,6 +1195,8 @@

Dependency graph (feat_ + infra_)

class feat_overnight_final_solution done; feat_overnight_final_solution_phase2["overnight final solution phase2"] class feat_overnight_final_solution_phase2 done; + feat_overnight_studies_summary_card["overnight studies summary card"] + class feat_overnight_studies_summary_card done; feat_ubi_judgments --> infra_adapter_solr
diff --git a/state.md b/state.md index dad832bb..322fb6af 100644 --- a/state.md +++ b/state.md @@ -2,7 +2,7 @@ > Read this first. A one-page snapshot: current focus, the last few merges, what's in flight, what's queued, and where the project sits in the MVP1 → MVP2 → MVP3 → GA roadmap. **Historical feature-merge narrative + chained execution context lives in [`state_history.md`](state_history.md)** — new merge entries land there, not here (per `chore_state_md_size_compression`, 2026-05-29). Keep this file loadable in a single `Read` call. -**Last updated:** 2026-06-04 (`feat_overnight_final_solution_phase2` merged — PR #442, squash `0c4e0358`. Phase 2 of the overnight autopilot, **frontend-only**: a top-of-page `` on `/studies/{id}` that compresses the morning chain review into one glance — headline lift, convergence chip, explored-path tokens, best-config CTA, stop-reason phrase, digest-narrative excerpt — plus a read-only strategy line in ``. Mounts only on terminated ≥2-link chains. Extracted `CHAIN_STOP_REASON_PHRASE` + `formatSignedLift` into shared `ui/src/lib/` modules; 2 new glossary keys. No backend code, no migration (head stays `0022`). Cap 2 (index-page surface) delegated to sibling `feat_overnight_studies_summary_card`. Gemini 1 finding accepted; GPT-5.5 final 2 (1 accepted — AC-11 test strengthened; 1 deferred — FR-9 screenshot → `chore_overnight_result_card_screenshot`). 1102+ vitest green; all 17 `pr.yml` checks green. Next: pull from the MVP2 Idea/Plan backlog.) +**Last updated:** 2026-06-04 (`feat_overnight_studies_summary_card` merged — PR #444, squash `ba1e6d68`. The index-page surface for the overnight autopilot (Cap 2 delegated out of `feat_overnight_final_solution_phase2`): a dismissible **"Ran while you were away" card** above the `/studies` table that surfaces overnight follow-up chains completed since the operator's last visit. New read-only endpoint `GET /api/v1/studies/chains/recent` (repo helper `list_recent_completed_chains` reuses Phase 1 traversal + stop-reason derivation; inert pagination per OQ-2). Frontend `` self-contained via `useRecentChains` + `useStudiesVisited` (localStorage, +1ms dismissal nudge); reuses the shared `CHAIN_STOP_REASON_PHRASE` map; new `recent_chains_card` glossary key. No migration (head stays `0022`). 33 new tests (11 backend integration + 9 contract + 12 vitest + 2 E2E). Cross-model: Epic GPT-5.5 reviews 1 accepted/2 rejected; Gemini 2 accepted (N+1 elimination + corrupt-localStorage guard) / 2 rejected (SSR false positives); final GPT-5.5 0 findings. OQ-2 + OQ-3 deferrals filed in `99_backlog/`. All 17 `pr.yml` checks green. Next: pull from the MVP2 Idea/Plan backlog.) ## Where the roadmap sits @@ -16,8 +16,8 @@ MVP1 (v0.1) **shipped** — all six differentiators live (Bayesian/TPE optimizer ## Current branch / execution context -- **Branch:** `main` (PR #442 `feat_overnight_final_solution_phase2` just merged `0c4e0358`, 2026-06-04). All `pr.yml` checks green (smoke skipped — opt-in/off). -- **Active feature:** _None in flight._ `feat_overnight_final_solution_phase2` shipped 2026-06-04 (PR #442). Next: pull from the MVP2 Idea/Plan backlog (run `/pipeline status`). +- **Branch:** `main` (PR #444 `feat_overnight_studies_summary_card` just merged `ba1e6d68`, 2026-06-04). All 17 `pr.yml` checks green (smoke skipped — opt-in/off). +- **Active feature:** _None in flight._ `feat_overnight_studies_summary_card` shipped 2026-06-04 (PR #444). Next: pull from the MVP2 Idea/Plan backlog (run `/pipeline status`). - **Alembic head:** `0022_solr_engine_auth_check` (added by `infra_adapter_solr` Story A6 — extends `clusters.engine_type` + `clusters.auth_kind` CHECK constraints for Solr). - **Python:** 3.13. **Frontend stack:** Next 16 (App Router + Turbopack), React 19, Tailwind 4 (CSS-first), Vitest 4, ESLint 9 (flat), TypeScript 6, Playwright (chromium, single worker) for E2E. - **Coverage gates:** backend 80% (`fail_under` in pyproject), UI vitest + tsc + ESLint + Next build, plus a full-stack smoke E2E job. Live pass counts: see the latest `pr.yml` run (the historical per-feature counts moved to `state_history.md`). @@ -26,17 +26,17 @@ MVP1 (v0.1) **shipped** — all six differentiators live (Bayesian/TPE optimizer Detail + reasoning for each is in [`state_history.md`](state_history.md). +- **2026-06-04** — `feat_overnight_studies_summary_card` (PR #444, squash-merged `ba1e6d68`). **"Ran while you were away" card on /studies.** The index-page surface for the overnight autopilot — Cap 2 delegated out of `feat_overnight_final_solution_phase2` (which shipped the detail-page ``). A dismissible card above the `/studies` table surfaces overnight follow-up chains that completed since the operator's last visit. **Backend:** new read-only endpoint `GET /api/v1/studies/chains/recent` — repo helper `list_recent_completed_chains` reuses the Phase 1 `get_chain_for_study` traversal + `derive_chain_stop_reason` (no chain math re-derived); filters `parent_study_id IS NOT NULL` (length ≥ 2 implied) + terminal status + `completed_at IS NOT NULL` + optional `?since=` cutoff; scan-caps candidates at `limit * 5` then dedupes to one row per anchor; defensive in-flight + concurrent-delete skips; inert pagination (`next_cursor: null`, `has_more: false`, `X-Total-Count = len(data)`) per OQ-2; declared BEFORE `/studies/{study_id}` so the static `chains` segment isn't captured. `RecentChainSummary` + `RecentChainsResponse` schemas (10 + 3 fields). **Frontend:** `` self-contained — owns its data via `useRecentChains(since)` (TanStack, window-focus refetch only) + `useStudiesVisited()` (localStorage `relyloop.last_visited_studies_at`, `now − 7d` first-visit default, `dismiss(T)` writes `T + 1ms` exclusive nudge per FR-5). Early-returns `null` on pending/error/empty (best-effort discoverability). Per-row: anchor ``, chain length, "Best {metric}: {value}", "Lift: {±value}" via shared `formatSignedLift`, stop-reason via shared `CHAIN_STOP_REASON_PHRASE` (defensive `?? 'Chain stopped'` fallback). Null-metric branch (AC-11) drops the numeric line. TWO `` affordances (recent_chains_card + overnight_autopilot) per FR-6. New `recent_chains_card` glossary key. Mounted on `/studies/page.tsx` above the target-filter chip row. **No migration** (head stays `0022`). 33 new tests: 11 backend integration (repo dedup/since/in-flight/failed-tail/concurrent-delete + endpoint AC-1/5/11 + route-order regression) + 9 contract (response shape, enum literals, OpenAPI presence, X-Total-Count, 422 envelope) + 12 vitest (4 hook + 8 card) + 2 Playwright E2E (smoke-job opt-in). Cross-model: Epic 1 GPT-5.5 1 finding (rejected — `select_best_link` is signed `-> str | None`); Epic 2 GPT-5.5 2 (1 accepted — raw-enum fallback → `'Chain stopped'`; 1 rejected — plan gates null branch on `best_metric` only, matching the chain panel's `formatSignedLift` "—" convention); Gemini 4 (2 accepted — N+1 elimination via `seen_study_ids` set + corrupt-localStorage `Date.parse` guard; 2 rejected — SSR-hydration false positives, card renders null during pending + matches `use-local-storage-set.ts` convention); final GPT-5.5 0 findings. Tangential: OQ-2 (keyset pagination) + OQ-3 (Postgres indexes) deferrals filed in `99_backlog/`. CI tripped the OpenAPI-surface allowlist (`test_openapi_has_no_orphan_endpoints`) — fixed inline by registering the new route, exactly as plan §3.3 anticipated. All 17 `pr.yml` checks green. - **2026-06-04** — `feat_overnight_final_solution_phase2` (PR #442, squash-merged `0c4e0358`). **Morning summary card + read-only strategy line.** Phase 2 of the overnight autopilot, frontend-only. Adds `` above `` on `/studies/{id}` — mounts only when the chain has terminated (`stop_reason !== 'in_flight'`) AND has ≥ 2 links — compressing the rolled-up answer into one glance: headline lift (`formatSignedLift`, shared with the chain panel), winning-link convergence chip (`` reading `StudyDetail.convergence.verdict`), explored-path tokens (`narrow → swap to {name} → widen`, anchor dropped, legacy-narrow chains get a path-less card per D-7), best-config CTA (three-case render matrix per D-13), stop-reason phrase, and a `truncateNarrative`-clamped digest excerpt with a "View full digest →" link. Plus a read-only "Strategy: Refine same knobs / Try suggested follow-ups" line inside `` for any study whose `config.auto_followup_strategy` is set. 6 stories / 1 epic: (1) extract `CHAIN_STOP_REASON_PHRASE` + `formatSignedLift` into shared `ui/src/lib/` modules (FR-8) + 2 new glossary keys (`overnight_result`, `auto_followup_strategy_line` — landed early because `` is type-locked); (2) pure `pathTokenForLink` with `Record` exhaustiveness; (3) card shell + headline + path + best-config + stop-reason + narrative + `truncateNarrative` + `shouldShowOvernightResultCard` predicate, hook-order invariant per D-19, per-link `useTemplate` in `` child per D-11; (4) `` (parent-gates-mount per D-18) + `id="digest"` anchor on ``; (5) ``; (6) tutorial guide + ui-architecture doc + real-backend E2E spec. **No backend code, no migration** (consumes existing `/chain` + `/studies/{id}` + `/digest` + `/query-templates/{id}`; head stays `0022`). Cap 2 (index-page surface) delegated to sibling `feat_overnight_studies_summary_card` per D-4. Spec + plan each GPT-5.5 3-cycle converged (22 D-log entries). Cross-model: Gemini cycle-1 1 finding (accepted — StrategyLine `inline-flex` markup); GPT-5.5 final 2 findings (1 accepted+fixed — AC-11 tautology strengthened to assert the hook's `best_link_id` + `enabled` args; 1 deferred — FR-9 populated-stack screenshot, demo seed can't produce a `follow_suggestions` chain with winning digest+proposal, tracked as `chore_overnight_result_card_screenshot`). Tests: 15 vitest lib unit + 26 card component + 5 strategy-line + 3 glossary lock + 2 Playwright E2E; full suite 1102+ green. All 17 `pr.yml` checks green. - **2026-06-04** — `feat_overnight_final_solution` (PR #440, squash-merged `1e9522a0`). **Autonomous cross-knob overnight tuning.** Teaches the overnight autopilot to consume the parent digest's *executable* follow-ups (narrow / widen / **swap_template**) on each chain link instead of always running the hardcoded ±50% narrow on the same template — so a chain can branch knobs AND templates while you sleep. Opt-in via a new wizard **Strategy** toggle (`"narrow"` default = byte-identical legacy behavior; `"follow_suggestions"` = the new mode); the existing `test_auto_followup.py` passes unmodified (that's the backward-compat gate). 7 stories / 4 epics: (1.1) `StudyConfigSpec.auto_followup_strategy: str | None` + `_validate_auto_followup_strategy` via the `AUTO_FOLLOWUP_STRATEGY_INVALID` 422 envelope (str-not-Literal per D-13 so the canonical error-code unwrap works) + a `mode="before"` validator rejecting operator-submitted worker-managed keys (single-writer rule, D-14); (1.2) wizard Strategy `