diff --git a/docs/00_overview/DASHBOARD.md b/docs/00_overview/DASHBOARD.md index f589de86..247bee12 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-03**. 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 | 13 / 24 scoped done · 25 remaining | **In progress** | +| [MVP2 / v0.2](MVP2_DASHBOARD.md) | Three-Engine + Real Signals | 14 / 24 scoped done · 24 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 82814c99..41796377 100644 --- a/docs/00_overview/MVP2_DASHBOARD.md +++ b/docs/00_overview/MVP2_DASHBOARD.md @@ -20,21 +20,21 @@ Plan approved; run /impl-execute to ship | Metric | Value | |---|---| -| Filed under MVP2 | **44** folders total (done + specced not-done + idea backlog + bugs) | -| Specced features done | **13 / 24** (54%) — 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 | **29** items (every not-done feat/infra/chore/bug across all priorities) | +| Filed under MVP2 | **43** folders total (done + specced not-done + idea backlog + bugs) | +| Specced features done | **14 / 24** (58%) — 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 | **27** 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) | 25 important to file, not blocking | +| → P2 (default) | 23 important to file, not blocking | | → Backlog | 4 captured for record, not planned | | Open bugs | 9 | -| Legacy "Path to MVP2" | 25 items — scoped-not-done + bugs + chore-ideas only (excludes feat/infra ideas) | -| Backlog ideas | 4 idea-only feat/infra (not yet scoped into MVP2) | +| Legacy "Path to MVP2" | 24 items — scoped-not-done + bugs + chore-ideas only (excludes feat/infra ideas) | +| Backlog ideas | 3 idea-only feat/infra (not yet scoped into MVP2) | | In flight | 0 feature(s) actively shipping | ## Pipeline -### Done (15) +### Done (16) | Feature | Type | One-liner | Depends on | Status | |---|---|---|---|---| @@ -46,6 +46,7 @@ Plan approved; run /impl-execute to ship | [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 | | [feat_ubi_judgments](implemented_features/2026_05_29_feat_ubi_judgments/feature_spec.md) | Feature | Operators with the OpenSearch / ES UBI plugin installed (today; Solr's first-party `solr.UBIComponent` lights up with the sibling `infra_adapter_solr` MVP2 release) can derive judgments from real clic | — | [PR #317](https://github.com/SoundMindsAI/relyloop/pull/317) merged 2026-05-29 | | [infra_adapter_solr](implemented_features/2026_05_31_infra_adapter_solr/feature_spec.md) | Infra | A single `SolrAdapter` implements the `SearchAdapter` Protocol against Apache Solr 9.x and 10.x (both SolrCloud and standalone), pivoting on a capability probe at construction time. | `feat_ubi_judgments` | [PR #336](https://github.com/SoundMindsAI/relyloop/pull/336) merged 2026-05-31 | +| [infra_generated_artifact_freshness_gate](implemented_features/2026_06_03_infra_generated_artifact_freshness_gate/feature_spec.md) | Infra | CI fails a PR whose committed `types.ts` does not match what the live OpenAPI schema would produce, and whose `ui/public/docs/*` copies do not match their `docs/08_guides/*` sources. | — | [PR #433](https://github.com/SoundMindsAI/relyloop/pull/433) merged 2026-06-03 | | [infra_smoke_reseed_runtime_budget](implemented_features/2026_06_02_infra_smoke_reseed_runtime_budget/feature_spec.md) | Infra | The CI smoke job's Playwright run excludes `demo-ubi.spec.ts` via the existing `testIgnore` precedent in [`ui/playwright.config.ts:47-65`](../../../ui/playwright.config.ts#L47-L65), so the reseed-boun | — | [PR #424](https://github.com/SoundMindsAI/relyloop/pull/424) merged 2026-06-02 | | [infra_solr_ci_readiness](implemented_features/2026_06_01_infra_solr_ci_readiness/feature_spec.md) | Infra | Post-2026-05-31, no full `pr.yml` run can go green on any branch. | — | [PR #367](https://github.com/SoundMindsAI/relyloop/pull/367) merged 2026-06-01 | | [infra_solr_smoke_stability](implemented_features/2026_06_02_infra_solr_smoke_stability/feature_spec.md) | Infra | The `pr.yml` `smoke (operator-path tutorial flow)` job is red on every branch. | — | [PR #383](https://github.com/SoundMindsAI/relyloop/pull/383) merged 2026-06-01 | @@ -58,7 +59,7 @@ Plan approved; run /impl-execute to ship _None._ -### Plan (13) +### Plan (12) | # | Priority | Feature | Type | One-liner | Depends on | Status | |---|---|---|---|---|---|---| @@ -67,39 +68,37 @@ _None._ | 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 | [infra_generated_artifact_freshness_gate](planned_features/02_mvp2/infra_generated_artifact_freshness_gate/feature_spec.md) | Infra | CI fails a PR whose committed `types.ts` does not match what the live OpenAPI schema would produce, and whose `ui/public/docs/*` copies do not match their `docs/08_guides/*` sources. | — | — | -| 7 | 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( | — | — | -| 8 | 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) | -| 9 | 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) | -| 10 | 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 | — | — | -| 11 | 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) | -| 12 | 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 | — | — | -| 13 | 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 | — | — | +| 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 | — | — | ### Spec (0) _None._ -### Idea (16) +### Idea (15) | # | Priority | Feature | Type | One-liner | Depends on | Status | |---|---|---|---|---|---|---| -| 1 | P2 | [infra_openapi_types_freshness_gate](planned_features/02_mvp2/infra_openapi_types_freshness_gate/idea.md) | Infra | Idea — Phase 2 of [`infra_generated_artifact_freshness_gate`](../infra_generated_artifact_freshness_gate/feature_spec.md), extracted to its own folder | — | Idea — Phase 2 of [`infra_generated_artifact_freshness_gate`](../infra_generated_artifact_freshness_gate/feature_spec.md), extracted to its own folder | -| 2 | P2 | [infra_smoke_fork_pr_secret_skip](planned_features/02_mvp2/infra_smoke_fork_pr_secret_skip/idea.md) | Infra | `.github/workflows/pr.yml` triggers on `pull_request:` ([pr.yml:43](../.github/workflows/pr.yml)) — **not** `pull_request_target`. GitHub deliberately withholds repository secrets from workflows trigg | — | Idea — tangential discovery while merging PR #387 (`chore_arq_pool_aclose_deprecation`) | -| 3 | P2 | [chore_demo_reseed_partial_completion_fast_test](planned_features/02_mvp2/chore_demo_reseed_partial_completion_fast_test/idea.md) | Chore | `infra_solr_ci_readiness` made the demo reseed engine-tolerant: when an engine is unreachable, its scenario is skipped, the reseed completes with `status="complete"` and a non-empty `scenarios_skipped | — | Idea — tangential discovery during `infra_solr_ci_readiness` Story 1.2 implementation | -| 4 | P2 | [chore_pr_yml_parallelize_backend_job](planned_features/02_mvp2/chore_pr_yml_parallelize_backend_job/idea.md) | Chore | `.github/workflows/pr.yml` has a job named `backend (lint + typecheck + tests + coverage)` that runs four sequential things in one job: ruff/lint, mypy, the full pytest matrix (unit + integration + co | — | Idea — captured during PR #426 CI watch | -| 5 | P2 | [chore_solr_post_pipeline_followups](planned_features/02_mvp2/chore_solr_post_pipeline_followups/idea.md) | Chore | The 13-story `infra_adapter_solr` execution surfaced several follow-on items that fit neither the original spec nor any sister feature folder. None block the MVP2 Solr release — they're operator-exper | — | Idea — tangential observations from `infra_adapter_solr` end-to-end | -| 6 | P2 | [chore_ubi_hybrid_template_render](planned_features/02_mvp2/chore_ubi_hybrid_template_render/idea.md) | Chore | Idea — contract decision deferred (NOT a worker bug) | — | Idea — contract decision deferred (NOT a worker bug) | -| 7 | P2 | [bug_e2e_teardown_chain_node_delete_500](planned_features/02_mvp2/bug_e2e_teardown_chain_node_delete_500/idea.md) | Bug | The E2E global-teardown deletes seeded rows in a fixed order (per `chore_e2e_test_rows_isolation` Story 1.2 cleanup registration). For auto-followup **chains**, the seeded nodes are `queued` studies c | — | Idea — tangential discovery during `feat_overnight_autopilot` (Story 4.2 E2E, PR forthcoming) | -| 8 | P2 | [bug_relyloop_spec_ubi_section_drift](planned_features/02_mvp2/bug_relyloop_spec_ubi_section_drift/idea.md) | Bug | [`docs/00_overview/relyloop-spec.md`](relyloop-spec.md) §"Click-derived judgments — OpenSearch UBI as the engine-neutral primary path" (line ~706) carries two staleness bugs from the 2026-05-27 releas | — | Idea — captured during `feat_ubi_judgments` preflight (2026-05-29) | -| 9 | P2 | [bug_reseed_failure_blocks_retry_arq_singleton_dedup](planned_features/02_mvp2/bug_reseed_failure_blocks_retry_arq_singleton_dedup/idea.md) | Bug | `run_demo_reseed` is enqueued with a fixed Arq job id `demo_reseed:singleton` (the singleton concurrency guard). When a run reaches a terminal state, Arq stores its **result** under `arq:result:demo_r | — | Idea — tangential discovery while verifying `fix(demo): add Solr (8983) to the reseed engine host-URL mapping` (branch `feat_demo_reseed_solr_and_steplog`) | -| 10 | P2 | [bug_seed_meaningful_demos_silent_bulk_errors](planned_features/02_mvp2/bug_seed_meaningful_demos_silent_bulk_errors/idea.md) | Bug | [`scripts/seed_meaningful_demos.py:917-935`](../../scripts/seed_meaningful_demos.py#L917-L935) bulk-indexes 1000 Amazon ESCI products into a dedicated index per demo scenario: | — | Idea — captured during `bug_smoke_seed_es_unavailable_shards_race` Phase 2.5 tangential sweep | -| 11 | P2 | [bug_studies_detail_vitest_intermittent_timeout](planned_features/02_mvp2/bug_studies_detail_vitest_intermittent_timeout/idea.md) | Bug | Under the full `pnpm test` run (`vitest run`, default worker pool), the Study-detail-page render test sometimes blocks past the 5 s `testTimeout` default — but the test itself is data-driven from mock | — | Idea — captured during `chore_template_library_expansion` post-impl tangential sweep | -| 12 | P2 | [bug_webhook_concurrent_merge_race_timing_sensitive](planned_features/02_mvp2/bug_webhook_concurrent_merge_race_timing_sensitive/idea.md) | Bug | Idea — surfaced during `bug_demo_clusters_unreachable_in_healthz` PR #236 CI. | — | Idea — surfaced during `bug_demo_clusters_unreachable_in_healthz` PR #236 CI. | -| 13 | Backlog | [feat_fts_rank_ordering](planned_features/02_mvp2/feat_fts_rank_ordering/idea.md) | Feature | `feat_data_table_primitive` shipped filter-only FTS — `?q=foo` matches rows where `search_vector @@ plainto_tsquery('english', 'foo')` is true but orders results by `created_at DESC, id DESC` (the def | — | Idea — deferred from `feat_data_table_primitive` (MVP1) per spec §16. | -| 14 | Backlog | [infra_arq_subprocess_test](planned_features/02_mvp2/infra_arq_subprocess_test/idea.md) | Infra | Idea (deferred from `feat_study_lifecycle` Phase 2 / PR #25 final GPT-5.5 review). Still applicable as of 2026-05-14: the three in-process tests cited below still cover the resume contract correctly; | — | Idea (deferred from `feat_study_lifecycle` Phase 2 / PR #25 final GPT-5.5 review). Still applicable as of 2026-05-14: the three in-process tests cited below still cover the resume contract correctly; a subprocess test would add a narrow Arq-version-regression guard. | -| 15 | Backlog | [chore_auto_followup_parent_advisory_lock](planned_features/02_mvp2/chore_auto_followup_parent_advisory_lock/idea.md) | Chore | The shipped `feat_auto_followup_studies` worker uses a two-layer idempotency scheme: | — | Idea — captured as a standalone file to resolve broken cross-references in `feat_auto_followup_studies` D-11 + plan F2 + `bug_auto_followup_completed_parent_stop_chain_race/idea.md`. The slug was coined 2026-05-24 in D-11 but only existed as descriptive prose across other documents until now. | -| 16 | Backlog | [bug_chat_long_conversation_truncation](planned_features/02_mvp2/bug_chat_long_conversation_truncation/idea.md) | Bug | [`backend/app/services/agent_chat.send_user_message`](../../backend/app/services/agent_chat.py) defensively caps the OpenAI history at the most recent `HISTORY_MAX_MESSAGES = 100` messages… | — | Held for MVP2 (decided 2026-05-13). Folder renamed with `_mvp2` suffix to make the deferral visible at-a-glance in `ls docs/00_overview/planned_features/`. Resume work when MVP2 starts — no technical dependency on MVP2 infra (audit_log is N/A; Langfuse is convenience only); the deferral is scope discipline + zero current impact (latent bug, no operator has hit the 100-message cap). | +| 1 | P2 | [infra_smoke_fork_pr_secret_skip](planned_features/02_mvp2/infra_smoke_fork_pr_secret_skip/idea.md) | Infra | `.github/workflows/pr.yml` triggers on `pull_request:` ([pr.yml:43](../.github/workflows/pr.yml)) — **not** `pull_request_target`. GitHub deliberately withholds repository secrets from workflows trigg | — | Idea — tangential discovery while merging PR #387 (`chore_arq_pool_aclose_deprecation`) | +| 2 | P2 | [chore_demo_reseed_partial_completion_fast_test](planned_features/02_mvp2/chore_demo_reseed_partial_completion_fast_test/idea.md) | Chore | `infra_solr_ci_readiness` made the demo reseed engine-tolerant: when an engine is unreachable, its scenario is skipped, the reseed completes with `status="complete"` and a non-empty `scenarios_skipped | — | Idea — tangential discovery during `infra_solr_ci_readiness` Story 1.2 implementation | +| 3 | P2 | [chore_pr_yml_parallelize_backend_job](planned_features/02_mvp2/chore_pr_yml_parallelize_backend_job/idea.md) | Chore | `.github/workflows/pr.yml` has a job named `backend (lint + typecheck + tests + coverage)` that runs four sequential things in one job: ruff/lint, mypy, the full pytest matrix (unit + integration + co | — | Idea — captured during PR #426 CI watch | +| 4 | P2 | [chore_solr_post_pipeline_followups](planned_features/02_mvp2/chore_solr_post_pipeline_followups/idea.md) | Chore | The 13-story `infra_adapter_solr` execution surfaced several follow-on items that fit neither the original spec nor any sister feature folder. None block the MVP2 Solr release — they're operator-exper | — | Idea — tangential observations from `infra_adapter_solr` end-to-end | +| 5 | P2 | [chore_ubi_hybrid_template_render](planned_features/02_mvp2/chore_ubi_hybrid_template_render/idea.md) | Chore | Idea — contract decision deferred (NOT a worker bug) | — | Idea — contract decision deferred (NOT a worker bug) | +| 6 | P2 | [bug_e2e_teardown_chain_node_delete_500](planned_features/02_mvp2/bug_e2e_teardown_chain_node_delete_500/idea.md) | Bug | The E2E global-teardown deletes seeded rows in a fixed order (per `chore_e2e_test_rows_isolation` Story 1.2 cleanup registration). For auto-followup **chains**, the seeded nodes are `queued` studies c | — | Idea — tangential discovery during `feat_overnight_autopilot` (Story 4.2 E2E, PR forthcoming) | +| 7 | P2 | [bug_relyloop_spec_ubi_section_drift](planned_features/02_mvp2/bug_relyloop_spec_ubi_section_drift/idea.md) | Bug | [`docs/00_overview/relyloop-spec.md`](relyloop-spec.md) §"Click-derived judgments — OpenSearch UBI as the engine-neutral primary path" (line ~706) carries two staleness bugs from the 2026-05-27 releas | — | Idea — captured during `feat_ubi_judgments` preflight (2026-05-29) | +| 8 | P2 | [bug_reseed_failure_blocks_retry_arq_singleton_dedup](planned_features/02_mvp2/bug_reseed_failure_blocks_retry_arq_singleton_dedup/idea.md) | Bug | `run_demo_reseed` is enqueued with a fixed Arq job id `demo_reseed:singleton` (the singleton concurrency guard). When a run reaches a terminal state, Arq stores its **result** under `arq:result:demo_r | — | Idea — tangential discovery while verifying `fix(demo): add Solr (8983) to the reseed engine host-URL mapping` (branch `feat_demo_reseed_solr_and_steplog`) | +| 9 | P2 | [bug_seed_meaningful_demos_silent_bulk_errors](planned_features/02_mvp2/bug_seed_meaningful_demos_silent_bulk_errors/idea.md) | Bug | [`scripts/seed_meaningful_demos.py:917-935`](../../scripts/seed_meaningful_demos.py#L917-L935) bulk-indexes 1000 Amazon ESCI products into a dedicated index per demo scenario: | — | Idea — captured during `bug_smoke_seed_es_unavailable_shards_race` Phase 2.5 tangential sweep | +| 10 | P2 | [bug_studies_detail_vitest_intermittent_timeout](planned_features/02_mvp2/bug_studies_detail_vitest_intermittent_timeout/idea.md) | Bug | Under the full `pnpm test` run (`vitest run`, default worker pool), the Study-detail-page render test sometimes blocks past the 5 s `testTimeout` default — but the test itself is data-driven from mock | — | Idea — captured during `chore_template_library_expansion` post-impl tangential sweep | +| 11 | P2 | [bug_webhook_concurrent_merge_race_timing_sensitive](planned_features/02_mvp2/bug_webhook_concurrent_merge_race_timing_sensitive/idea.md) | Bug | Idea — surfaced during `bug_demo_clusters_unreachable_in_healthz` PR #236 CI. | — | Idea — surfaced during `bug_demo_clusters_unreachable_in_healthz` PR #236 CI. | +| 12 | Backlog | [feat_fts_rank_ordering](planned_features/02_mvp2/feat_fts_rank_ordering/idea.md) | Feature | `feat_data_table_primitive` shipped filter-only FTS — `?q=foo` matches rows where `search_vector @@ plainto_tsquery('english', 'foo')` is true but orders results by `created_at DESC, id DESC` (the def | — | Idea — deferred from `feat_data_table_primitive` (MVP1) per spec §16. | +| 13 | Backlog | [infra_arq_subprocess_test](planned_features/02_mvp2/infra_arq_subprocess_test/idea.md) | Infra | Idea (deferred from `feat_study_lifecycle` Phase 2 / PR #25 final GPT-5.5 review). Still applicable as of 2026-05-14: the three in-process tests cited below still cover the resume contract correctly; | — | Idea (deferred from `feat_study_lifecycle` Phase 2 / PR #25 final GPT-5.5 review). Still applicable as of 2026-05-14: the three in-process tests cited below still cover the resume contract correctly; a subprocess test would add a narrow Arq-version-regression guard. | +| 14 | Backlog | [chore_auto_followup_parent_advisory_lock](planned_features/02_mvp2/chore_auto_followup_parent_advisory_lock/idea.md) | Chore | The shipped `feat_auto_followup_studies` worker uses a two-layer idempotency scheme: | — | Idea — captured as a standalone file to resolve broken cross-references in `feat_auto_followup_studies` D-11 + plan F2 + `bug_auto_followup_completed_parent_stop_chain_race/idea.md`. The slug was coined 2026-05-24 in D-11 but only existed as descriptive prose across other documents until now. | +| 15 | Backlog | [bug_chat_long_conversation_truncation](planned_features/02_mvp2/bug_chat_long_conversation_truncation/idea.md) | Bug | [`backend/app/services/agent_chat.send_user_message`](../../backend/app/services/agent_chat.py) defensively caps the OpenAI history at the most recent `HISTORY_MAX_MESSAGES = 100` messages… | — | Held for MVP2 (decided 2026-05-13). Folder renamed with `_mvp2` suffix to make the deferral visible at-a-glance in `ls docs/00_overview/planned_features/`. Resume work when MVP2 starts — no technical dependency on MVP2 infra (audit_log is N/A; Langfuse is convenience only); the deferral is scope discipline + zero current impact (latent bug, no operator has hit the 100-message cap). | ## Dependency graph @@ -132,8 +131,6 @@ graph LR class feat_query_normalizer_typed_pipeline plan; feat_ubi_llm_study_comparison["ubi llm study comparison"] class feat_ubi_llm_study_comparison plan; - infra_generated_artifact_freshness_gate["generated artifact freshness gate"] - class infra_generated_artifact_freshness_gate plan; feat_contextual_help_mvp2["contextual help mvp2"] class feat_contextual_help_mvp2 done; feat_study_sub_warmup_guard["study sub warmup guard"] @@ -160,6 +157,8 @@ graph LR class infra_smoke_reseed_runtime_budget done; infra_solr_smoke_stability["solr smoke stability"] class infra_solr_smoke_stability done; + infra_generated_artifact_freshness_gate["generated artifact freshness gate"] + class infra_generated_artifact_freshness_gate done; feat_ubi_judgments --> infra_adapter_solr ``` diff --git a/docs/00_overview/dashboard.html b/docs/00_overview/dashboard.html index 5219f5e9..6c2138f8 100644 --- a/docs/00_overview/dashboard.html +++ b/docs/00_overview/dashboard.html @@ -392,7 +392,7 @@

Releases

Three-Engine + Real Signals
-
13 / 24 scoped done · 25 remaining
+
14 / 24 scoped done · 24 remaining
In progress
diff --git a/docs/00_overview/planned_features/02_mvp2/infra_generated_artifact_freshness_gate/feature_spec.md b/docs/00_overview/implemented_features/2026_06_03_infra_generated_artifact_freshness_gate/feature_spec.md similarity index 100% rename from docs/00_overview/planned_features/02_mvp2/infra_generated_artifact_freshness_gate/feature_spec.md rename to docs/00_overview/implemented_features/2026_06_03_infra_generated_artifact_freshness_gate/feature_spec.md diff --git a/docs/00_overview/planned_features/02_mvp2/infra_generated_artifact_freshness_gate/idea.md b/docs/00_overview/implemented_features/2026_06_03_infra_generated_artifact_freshness_gate/idea.md similarity index 100% rename from docs/00_overview/planned_features/02_mvp2/infra_generated_artifact_freshness_gate/idea.md rename to docs/00_overview/implemented_features/2026_06_03_infra_generated_artifact_freshness_gate/idea.md diff --git a/docs/00_overview/planned_features/02_mvp2/infra_generated_artifact_freshness_gate/implementation_plan.md b/docs/00_overview/implemented_features/2026_06_03_infra_generated_artifact_freshness_gate/implementation_plan.md similarity index 99% rename from docs/00_overview/planned_features/02_mvp2/infra_generated_artifact_freshness_gate/implementation_plan.md rename to docs/00_overview/implemented_features/2026_06_03_infra_generated_artifact_freshness_gate/implementation_plan.md index 3e668168..0643dade 100644 --- a/docs/00_overview/planned_features/02_mvp2/infra_generated_artifact_freshness_gate/implementation_plan.md +++ b/docs/00_overview/implemented_features/2026_06_03_infra_generated_artifact_freshness_gate/implementation_plan.md @@ -1,7 +1,7 @@ # Implementation Plan — CI gate for generated-artifact freshness (`types.ts` + `ui/public/docs`) **Date:** 2026-06-01 -**Status:** Draft +**Status:** Complete (PR #433, merged 2026-06-03 — squash `c5c36c65`) **Primary spec:** [`feature_spec.md`](feature_spec.md) **Policy source(s):** CLAUDE.md (Absolute Rules #2 secrets-via-files, #7 conventional commits + DCO; "Common Pitfalls" hermetic-CI + local-stub hygiene); `scripts/gen_license_inventory.py --check` + the `license-inventory` job in [`.github/workflows/pr.yml`](../../../../../.github/workflows/pr.yml); [`.github/workflows/secrets-defense.yml`](../../../../../.github/workflows/secrets-defense.yml) (own-workflow-to-escape-`paths-ignore` precedent) diff --git a/docs/00_overview/planned_features/02_mvp2/infra_generated_artifact_freshness_gate/pipeline_status.md b/docs/00_overview/implemented_features/2026_06_03_infra_generated_artifact_freshness_gate/pipeline_status.md similarity index 55% rename from docs/00_overview/planned_features/02_mvp2/infra_generated_artifact_freshness_gate/pipeline_status.md rename to docs/00_overview/implemented_features/2026_06_03_infra_generated_artifact_freshness_gate/pipeline_status.md index a829b090..326ba856 100644 --- a/docs/00_overview/planned_features/02_mvp2/infra_generated_artifact_freshness_gate/pipeline_status.md +++ b/docs/00_overview/implemented_features/2026_06_03_infra_generated_artifact_freshness_gate/pipeline_status.md @@ -1,5 +1,7 @@ # Pipeline Status — CI gate for generated-artifact freshness +**Release:** mvp2 + ## Idea - Status: Complete - File: idea.md @@ -20,4 +22,11 @@ - Phases covered: Phase 1 + Phase 2 (both) ## Implementation -- Status: Not started +- Status: Complete +- Date: 2026-06-03 +- PR: #433 (squash-merged `c5c36c65`) +- CI: all 17 checks green (smoke skipped — operator-controlled, OFF by default) +- Stories completed: 6 / 6 (Epic 1: 1.1, 1.2; Epic 2: 2.1, 2.2, 2.3, 2.4) — both phases shipped together +- Tests: 48 new cases (10 backend unit + 17 vitest + 21 shell-guard self-test) +- Cross-model review: Epic 1 GPT-5.5 phase gate (1 accepted, 2 rejected w/ counter-evidence); Epic 2 GPT-5.5 phase gate (5 rejected); Gemini Code Assist (3 accepted — atexit cleanup, atomic-write try/finally, Windows shell flag); final GPT-5.5 review clean (0 findings) +- Note: the standalone Phase-2 record `infra_openapi_types_freshness_gate/` was retired at finalization since both phases shipped in this PR. diff --git a/docs/00_overview/mvp2_dashboard.html b/docs/00_overview/mvp2_dashboard.html index e9ddfb51..7327a67a 100644 --- a/docs/00_overview/mvp2_dashboard.html +++ b/docs/00_overview/mvp2_dashboard.html @@ -397,13 +397,13 @@

MVP2 Progress

Specced features done
-
13 / 24
-
54% specced · 44 filed under MVP2
-
+
14 / 24
+
58% specced · 43 filed under MVP2
+
Pending work
-
29
+
27
every not-done feat/infra/chore/bug across all priorities
@@ -425,7 +425,7 @@

MVP2 Progress

P2 (default)
-
25
+
23
important to file, not blocking
@@ -435,14 +435,14 @@

MVP2 Progress

Legacy "Path to MVP2"
-
25
+
24
scoped not-done + bugs + chore-ideas only (excludes feat/infra ideas)
Backlog ideas: - 4 idea-only feat/infra folders (not yet scoped into MVP2) + 3 idea-only feat/infra folders (not yet scoped into MVP2) In flight: @@ -463,20 +463,7 @@

Pipeline

-

Idea 16

- -
- -
- Infra - P2 - -
-
Idea — Phase 2 of [`infra_generated_artifact_freshness_gate`](../infra_generated_artifact_freshness_gate/feature_spec.md), extracted to its own folder
- - -
- +

Idea 15

@@ -680,7 +667,7 @@

Spec 0

-

Plan 13

+

Plan 12

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

Plan 13

-
- -
- Infra - P2 - -
-
CI fails a PR whose committed `types.ts` does not match what the live OpenAPI schema would produce, and whose `ui/public/docs/*` copies do not match their `docs/08_guides/*` sources.
- - -
- -
@@ -858,7 +832,7 @@

Implementing 0

-

Done 15

+

Done 16

@@ -964,6 +938,19 @@

Done 15

+
+ +
+ Infra + + PR #433 merged 2026-06-03 +
+
CI fails a PR whose committed `types.ts` does not match what the live OpenAPI schema would produce, and whose `ui/public/docs/*` copies do not match their `docs/08_guides/*` sources.
+ + +
+ +
@@ -1087,8 +1074,6 @@

Dependency graph (feat_ + infra_)

class feat_query_normalizer_typed_pipeline plan; feat_ubi_llm_study_comparison["ubi llm study comparison"] class feat_ubi_llm_study_comparison plan; - infra_generated_artifact_freshness_gate["generated artifact freshness gate"] - class infra_generated_artifact_freshness_gate plan; feat_contextual_help_mvp2["contextual help mvp2"] class feat_contextual_help_mvp2 done; feat_study_sub_warmup_guard["study sub warmup guard"] @@ -1115,6 +1100,8 @@

Dependency graph (feat_ + infra_)

class infra_smoke_reseed_runtime_budget done; infra_solr_smoke_stability["solr smoke stability"] class infra_solr_smoke_stability done; + infra_generated_artifact_freshness_gate["generated artifact freshness gate"] + class infra_generated_artifact_freshness_gate done; feat_ubi_judgments --> infra_adapter_solr
diff --git a/docs/00_overview/planned_features/02_mvp2/infra_openapi_types_freshness_gate/idea.md b/docs/00_overview/planned_features/02_mvp2/infra_openapi_types_freshness_gate/idea.md deleted file mode 100644 index 9f3035b0..00000000 --- a/docs/00_overview/planned_features/02_mvp2/infra_openapi_types_freshness_gate/idea.md +++ /dev/null @@ -1,40 +0,0 @@ -# infra_openapi_types_freshness_gate — offline OpenAPI export + `types.ts` freshness gate - -**Date:** 2026-06-01 -**Status:** Idea — Phase 2 of [`infra_generated_artifact_freshness_gate`](../infra_generated_artifact_freshness_gate/feature_spec.md), extracted to its own folder -**Type:** `infra_` -**Priority:** P2 (same as parent) - -## Origin - -Defined as Phase 2 in [`infra_generated_artifact_freshness_gate/feature_spec.md`](../infra_generated_artifact_freshness_gate/feature_spec.md) §3 "Phase boundaries". Phase 1 (the `copy-docs` freshness gate — FR-1, FR-3, FR-9) ships first because it is pure-filesystem and zero-infra. This work carries the OpenAPI-export + `types.ts` half, which has a real import-cleanliness investigation and a banner-determinism fix. - -> The parent's [`implementation_plan.md`](../infra_generated_artifact_freshness_gate/implementation_plan.md) covers both phases (Epic 1 = Phase 1, Epic 2 = Phase 2). This standalone folder is the discoverable idea-stage record of the Phase 2 half if Phase 1 ships alone; if both phases ship in one pass, this folder is retired at finalization. - -## Deferred functional requirements (from the spec) - -- **FR-2** — `types.ts` freshness gate: regenerate `ui/src/lib/types.ts` from the committed `ui/openapi.json` snapshot using the locked absolute-path source form (`OPENAPI_URL="$PWD/ui/openapi.json" pnpm --dir ui types:gen`), fail on `git status --porcelain` drift. -- **FR-4** — offline, deterministic OpenAPI export: a backend entrypoint that emits the canonical schema with **no** running server / live DB / ES / OpenSearch. Requires an **import-graph spike** (the parent spec's main open question) to prove no live clients are constructed at schema-build time and to pick path (a) `*_FILE` dummy stand-ins vs path (b) `get_openapi()` from a side-effect-clean route table. Canonical serialization locked: `json.dumps(schema, sort_keys=True, separators=(",",":"), ensure_ascii=False)` + trailing newline + atomic write + clean stdout. -- **FR-5** — banner determinism + stance reconciliation in `gen-types.mjs`: make the banner source-invariant (no interpolated `OPENAPI_URL`), drop the false "CI does NOT regenerate" line, and switch the invocation from `npx` to the lockfile-pinned `openapi-typescript` binary. -- **FR-6** — determinism verification (also applies to Phase 1, but the `types.ts`/snapshot determinism is the harder half). -- **FR-7** — `ui/openapi.json` snapshot freshness gate (needs the backend `uv` toolchain). -- **FR-8** (Phase 2 half) — the canonical chained local-fix command spanning exporter + `types:gen`. - -Acceptance criteria: AC-4, AC-5, AC-6, AC-7, AC-8, AC-9 (types/snapshot half), AC-10. - -## Why deferred - -Phase 1 is zero-dependency and immediately catches the recurring guide-sync drift. Phase 2 requires: -1. The import-graph spike (does the schema builder import cleanly without triggering `backend/app/main.py:195`'s module-level `get_settings()`, and is route-table assembly side-effect-free?). -2. The `gen-types.mjs` banner-determinism + `npx`→pinned-binary edits. -3. Committing a new `ui/openapi.json` snapshot artifact. - -These are larger surface + carry the only real open question in the spec. - -## Dependencies on Phase 1 - -Soft. Phase 2 reuses Phase 1's gate-step pattern (regenerate + `git status --porcelain` + canonical fix-command text + the `scripts/` guard + negative-test harness). Phase 2 can ship independently but is cheaper after Phase 1 establishes the pattern. - -## Open question carried forward - -- **FR-4 import path (a) vs (b)** — resolve in the Phase 2 plan's first story (the spike). Recommended default: try path (b) `get_openapi()` against a side-effect-clean router assembly; fall back to path (a) `*_FILE` dummy stand-ins. See spec §19. diff --git a/website/docs/roadmap.md b/website/docs/roadmap.md index c7b6b18b..dca3d196 100644 --- a/website/docs/roadmap.md +++ b/website/docs/roadmap.md @@ -182,18 +182,17 @@ - 🟡 [Query Normalizer Typed Pipeline](https://github.com/SoundMindsAI/relyloop/tree/main/docs/00_overview/planned_features/02_mvp2/feat_query_normalizer_typed_pipeline) - 🟡 [UBI LLM Study Comparison](https://github.com/SoundMindsAI/relyloop/tree/main/docs/00_overview/planned_features/02_mvp2/feat_ubi_llm_study_comparison) -??? note "Infrastructure & tooling (8)" +??? note "Infrastructure & tooling (7)" - ✅ [Adapter Solr](https://github.com/SoundMindsAI/relyloop/tree/main/docs/00_overview/implemented_features/2026_05_31_infra_adapter_solr) · [#336](https://github.com/SoundMindsAI/relyloop/pull/336) + - ✅ [Generated Artifact Freshness Gate](https://github.com/SoundMindsAI/relyloop/tree/main/docs/00_overview/implemented_features/2026_06_03_infra_generated_artifact_freshness_gate) · [#433](https://github.com/SoundMindsAI/relyloop/pull/433) - ✅ [Smoke Reseed Runtime Budget](https://github.com/SoundMindsAI/relyloop/tree/main/docs/00_overview/implemented_features/2026_06_02_infra_smoke_reseed_runtime_budget) · [#424](https://github.com/SoundMindsAI/relyloop/pull/424) - ✅ [Solr CI Readiness](https://github.com/SoundMindsAI/relyloop/tree/main/docs/00_overview/implemented_features/2026_06_01_infra_solr_ci_readiness) · [#367](https://github.com/SoundMindsAI/relyloop/pull/367) - ✅ [Solr Smoke Stability](https://github.com/SoundMindsAI/relyloop/tree/main/docs/00_overview/implemented_features/2026_06_02_infra_solr_smoke_stability) · [#383](https://github.com/SoundMindsAI/relyloop/pull/383) - 🟡 [Arq Subprocess Test](https://github.com/SoundMindsAI/relyloop/tree/main/docs/00_overview/planned_features/02_mvp2/infra_arq_subprocess_test) - - 🟡 [Generated Artifact Freshness Gate](https://github.com/SoundMindsAI/relyloop/tree/main/docs/00_overview/planned_features/02_mvp2/infra_generated_artifact_freshness_gate) - - 🟡 [Openapi Types Freshness Gate](https://github.com/SoundMindsAI/relyloop/tree/main/docs/00_overview/planned_features/02_mvp2/infra_openapi_types_freshness_gate) - 🟡 [Smoke Fork PR Secret Skip](https://github.com/SoundMindsAI/relyloop/tree/main/docs/00_overview/planned_features/02_mvp2/infra_smoke_fork_pr_secret_skip) -??? note "Maintenance & fixes (22)" +??? note "Maintenance & fixes (23)" - ✅ [Backend Suite Nondeterministic Caplog Isolation](https://github.com/SoundMindsAI/relyloop/tree/main/docs/00_overview/implemented_features/2026_06_01_bug_backend_suite_nondeterministic_caplog_isolation) · [#364](https://github.com/SoundMindsAI/relyloop/pull/364) - ✅ [Contract Allowlists Outdated After Mvp2 Features](https://github.com/SoundMindsAI/relyloop/tree/main/docs/00_overview/implemented_features/2026_06_01_bug_contract_allowlists_outdated_after_mvp2_features) · [#364](https://github.com/SoundMindsAI/relyloop/pull/364) @@ -208,6 +207,7 @@ - 🟡 [Demo Seeding Integration Tests Rewrite](https://github.com/SoundMindsAI/relyloop/tree/main/docs/00_overview/planned_features/02_mvp2/chore_demo_seeding_integration_tests_rewrite) - 🟡 [E2E Teardown Chain Node Delete 500](https://github.com/SoundMindsAI/relyloop/tree/main/docs/00_overview/planned_features/02_mvp2/bug_e2e_teardown_chain_node_delete_500) - 🟡 [Judgment Header Omits Click Bucket](https://github.com/SoundMindsAI/relyloop/tree/main/docs/00_overview/planned_features/02_mvp2/bug_judgment_header_omits_click_bucket) + - 🟡 [PR Yml Parallelize Backend Job](https://github.com/SoundMindsAI/relyloop/tree/main/docs/00_overview/planned_features/02_mvp2/chore_pr_yml_parallelize_backend_job) - 🟡 [Relyloop Spec UBI Section Drift](https://github.com/SoundMindsAI/relyloop/tree/main/docs/00_overview/planned_features/02_mvp2/bug_relyloop_spec_ubi_section_drift) - 🟡 [Reseed Failure Blocks Retry Arq Singleton Dedup](https://github.com/SoundMindsAI/relyloop/tree/main/docs/00_overview/planned_features/02_mvp2/bug_reseed_failure_blocks_retry_arq_singleton_dedup) - 🟡 [Seed Meaningful Demos Silent Bulk Errors](https://github.com/SoundMindsAI/relyloop/tree/main/docs/00_overview/planned_features/02_mvp2/bug_seed_meaningful_demos_silent_bulk_errors)