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
19 changes: 19 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,25 @@ repos:
files: ^ui/src/.*\.(ts|tsx|js|jsx)$
pass_filenames: false

# ---------------------------------------------------------------------------
# MVP1 dashboard — regenerate when feature folders change so the committed
# dashboard always matches the folder state. Mirrors the impl-execute Step 8
# finalization workflow but runs on every commit instead of only at merge time.
#
# Standard pre-commit pattern: if the script modifies mvp1_dashboard.html,
# the hook reports "files were modified" and aborts the commit, forcing the
# contributor to `git add docs/00_overview/mvp1_dashboard.html && git commit`.
# Same UX as ruff-format / prettier when those reformat staged files.
# ---------------------------------------------------------------------------
- repo: local
hooks:
- id: mvp1-dashboard-regen
name: Regenerate MVP1 dashboard if feature folders changed
entry: python3 scripts/build_mvp1_dashboard.py
language: system
files: ^(docs/02_product/planned_features/|docs/00_overview/implemented_features/|scripts/build_mvp1_dashboard\.py$)
pass_filenames: false

# ---------------------------------------------------------------------------
# Secret scanning — gitleaks
# ---------------------------------------------------------------------------
Expand Down
8 changes: 7 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
.PHONY: help fmt lint typecheck test test-unit test-integration test-contract \
ui-lint ui-typecheck ui-test ui-build \
pre-commit pre-commit-install \
up down logs reset migrate migrate-create seed-clusters
up down logs reset migrate migrate-create seed-clusters \
dashboard

help: ## Show this help message
@echo ""
Expand Down Expand Up @@ -116,3 +117,8 @@ migrate-create: ## Create new migration: make migrate-create name=<slug> (runs
docker compose exec -T api alembic revision --autogenerate --rev-id "$${NEXT_REV}" -m "$(name)"
@echo ""
@echo "Run 'make fmt' to apply ruff formatting to the new revision file."

# ---------- MVP1 Dashboard ----------

dashboard: ## Regenerate docs/00_overview/mvp1_dashboard.html from feature folders
@python3 scripts/build_mvp1_dashboard.py
118 changes: 118 additions & 0 deletions docs/00_overview/MVP1_DASHBOARD.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# RelyLoop MVP1 Dashboard

_Reflects feature-folder state as of **2026-05-10** (latest mtime of any planned/implemented feature `.md` file). Regenerated by `make dashboard` and the `mvp1-dashboard-regen` pre-commit hook. For the rich local view (filter chips, type colors), open [`mvp1_dashboard.html`](mvp1_dashboard.html) in a browser._

## MVP1 Progress

| Metric | Value |
|---|---|
| Features done | **2 / 12** (17%) |
| Path to MVP1 | **14** items remaining (features + bugs + chores) |
| Open bugs | 2 |
| Open chores | 2 (idea-stage debt) |
| Backlog ideas | 2 idea-only feat/infra (not yet scoped into MVP1) |
| In flight | 1 feature(s) actively shipping |

## Pipeline

### Done (2)

| Feature | Type | One-liner | Depends on | Status |
|---|---|---|---|---|
| [infra_adapter_elastic](implemented_features/2026_05_10_infra_adapter_elastic/feature_spec.md) | Infra | A single `ElasticAdapter` implements the `SearchAdapter` Protocol and serves both Elasticsearch (8.11+ / 9.x) and OpenSearch (2.x / 3.x), distinguished by a `engine_type` column. | — | [PR #16](https://github.com/SoundMindsAI/relyloop/pull/16) merged 2026-05-10 |
| [infra_foundation](implemented_features/2026_05_09_infra_foundation/feature_spec.md) | Infra | A relevance engineer can `git clone`, `docker compose up`, see all subsystems healthy in <60s on a 16GB laptop, and have a CI pipeline that gates every PR on lint, type-check, test, and an 80% coverag | — | [PR #4](https://github.com/SoundMindsAI/relyloop/pull/4) merged 2026-05-09 |

### Implementing (1)

| Feature | Type | One-liner | Depends on | Status |
|---|---|---|---|---|
| [feat_study_lifecycle](../02_product/planned_features/feat_study_lifecycle/feature_spec.md) | Feature | A relevance engineer creates a study via API or chat, the orchestrator enqueues N parallel `run_trial` jobs, trials accumulate in real time on the study detail page, the orchestrator detects stop-cond | — | [PR #18](https://github.com/SoundMindsAI/relyloop/pull/18) merged 2026-05-10 |

### Plan (0)

_None._

### Spec (9)

| Feature | Type | One-liner | Depends on | Status |
|---|---|---|---|---|
| [feat_chat_agent](../02_product/planned_features/feat_chat_agent/feature_spec.md) | Feature | A chat surface at `/chat/{conversation_id}` streams OpenAI completions via SSE. | — | Draft |
| [feat_digest_proposal](../02_product/planned_features/feat_digest_proposal/feature_spec.md) | Feature | When a study transitions to `completed`, the digest worker generates: a narrative summary (LLM-authored), a parameter-importance map (computed by `optuna.importance`), and a recommended config. | `feat_study_lifecycle` `feat_llm_judgments` | Draft |
| [feat_github_pr_worker](../02_product/planned_features/feat_github_pr_worker/feature_spec.md) | Feature | `POST /api/v1/proposals/{id}/open_pr` enqueues a Git worker job that clones the configured repo, edits `*.params.json`, commits with a structured message, pushes a branch, opens a GitHub PR, attaches | `infra_foundation` `infra_adapter_elastic` `feat_digest_proposal` | Draft |
| [feat_github_webhook](../02_product/planned_features/feat_github_webhook/feature_spec.md) | Feature | GitHub posts to `POST /webhooks/github` with HMAC-SHA256 signature; the receiver verifies the signature, looks up the proposal by `pr_url`, updates `pr_state` and `pr_merged_at`. | `infra_foundation` `feat_github_pr_worker` | Draft |
| [feat_llm_judgments](../02_product/planned_features/feat_llm_judgments/feature_spec.md) | Feature | A relevance engineer selects a query set + cluster + target + rubric and the system runs the current template to fetch top-K hits per query, asks OpenAI to rate each (query, doc) on a 0–3 scale with r | `infra_foundation` `infra_adapter_elastic` `feat_study_lifecycle` | Draft |
| [feat_proposals_ui](../02_product/planned_features/feat_proposals_ui/feature_spec.md) | Feature | Two routes — `/proposals` (filterable list) and `/proposals/{id}` (config diff + metric delta + "Open PR" button + post-open PR-state mirror) — plug into the existing `feat_studies_ui` Next.js app. | `feat_studies_ui` `feat_digest_proposal` `feat_github_pr_worker` `feat_github_webhook` | Draft |
| [feat_studies_ui](../02_product/planned_features/feat_studies_ui/feature_spec.md) | Feature | A Next.js app provides 9 of the 11 MVP1 routes from [`ui-architecture.md` §"Routes (MVP1)"](../../../01_architecture/ui-architecture.md): dashboard, clusters list/detail, query sets list/detail, judgm | `infra_foundation` `feat_study_lifecycle` `feat_digest_proposal` `feat_llm_judgments` `infra_adapter_elastic` | Draft |
| [infra_optuna_eval](../02_product/planned_features/infra_optuna_eval/feature_spec.md) | Infra | Optuna RDB storage co-tenants with the application Postgres; TPE sampler + median pruner are the MVP1 defaults; pytrec_eval scores trials against judgment lists for nDCG@10, MAP, P@K, recall@K, MRR, a | — | Draft |
| [chore_tutorial_polish](../02_product/planned_features/chore_tutorial_polish/feature_spec.md) | Chore | The release tag `v0.1.0` is pushed with: a worked tutorial at `docs/08_guides/tutorial-first-study.md`, sample data (50-query set + pre-baked judgment list + sample ES index of ~1,000 docs), README po | — | Draft |

### Idea (6)

| Feature | Type | One-liner | Depends on | Status |
|---|---|---|---|---|
| [infra_ci_smoke_makeup](../02_product/planned_features/infra_ci_smoke_makeup/idea.md) | Infra | CI runs `make test-unit && make test-integration && make test-contract` against a service-container Postgres on `localhost:5432` — a synthetic environment that masks every real-world `make up` failure | — | Idea — captured during `infra_foundation` PR #4 first-run testing |
| [infra_frontend_stack_refresh](../02_product/planned_features/infra_frontend_stack_refresh/idea.md) | Infra | The frontend stack landed during `infra_foundation` is already 1–2 majors behind across the board. Specifically (locked → npm latest as of 2026-05-09): | — | Idea — surfaced during dependency audit on `feature/infra-foundation` |
| [chore_starlette_422_deprecation](../02_product/planned_features/chore_starlette_422_deprecation/idea.md) | Chore | Starlette has renamed `HTTP_422_UNPROCESSABLE_ENTITY` to `HTTP_422_UNPROCESSABLE_CONTENT`. Three call sites still use the old name: | — | Idea — captured during `infra_foundation` Story 5.1 test backfill |
| [chore_test_both_engines](../02_product/planned_features/chore_test_both_engines/idea.md) | Chore | `backend/tests/integration/test_clusters_api.py` only registers an **Elasticsearch** cluster in every test: | — | Idea (deferred from `infra_adapter_elastic` — refactor sweep, 2026-05-09) |
| [bug_capability_check_test_isolation](../02_product/planned_features/bug_capability_check_test_isolation/idea.md) | Bug | Idea (deferred from `infra_adapter_elastic` Story 5.1) | — | Idea (deferred from `infra_adapter_elastic` Story 5.1) |
| [bug_env_file_corrupted_during_session](../02_product/planned_features/bug_env_file_corrupted_during_session/idea.md) | Bug | The user's working `.env` (containing the OpenAI API key referenced by [`CLAUDE.md`](../../../CLAUDE.md) "Cross-model review policy") was renamed to `.env.old` during the agent's implementation sessio | — | Idea — captured during `infra_foundation` Story 4.4 implementation |

## Dependency graph

Scoped feat/infra/chore nodes only. Idea-stage debt is omitted.

```mermaid
graph LR
classDef done fill:#dcfce7,stroke:#14532d,color:#14532d;
classDef implement fill:#ffedd5,stroke:#9a3412,color:#9a3412;
classDef plan fill:#fef9c3,stroke:#854d0e,color:#854d0e;
classDef spec fill:#dbeafe,stroke:#1e40af,color:#1e40af;
classDef idea fill:#f1f5f9,stroke:#334155,color:#334155;
chore_tutorial_polish["tutorial polish"]
class chore_tutorial_polish spec;
feat_chat_agent["chat agent"]
class feat_chat_agent spec;
feat_digest_proposal["digest proposal"]
class feat_digest_proposal spec;
feat_github_pr_worker["github pr worker"]
class feat_github_pr_worker spec;
feat_github_webhook["github webhook"]
class feat_github_webhook spec;
feat_llm_judgments["llm judgments"]
class feat_llm_judgments spec;
feat_proposals_ui["proposals ui"]
class feat_proposals_ui spec;
feat_studies_ui["studies ui"]
class feat_studies_ui spec;
feat_study_lifecycle["study lifecycle"]
class feat_study_lifecycle implement;
infra_optuna_eval["optuna eval"]
class infra_optuna_eval spec;
infra_foundation["foundation"]
class infra_foundation done;
infra_adapter_elastic["adapter elastic"]
class infra_adapter_elastic done;
feat_study_lifecycle --> feat_digest_proposal
feat_llm_judgments --> feat_digest_proposal
infra_foundation --> feat_github_pr_worker
infra_adapter_elastic --> feat_github_pr_worker
feat_digest_proposal --> feat_github_pr_worker
infra_foundation --> feat_github_webhook
feat_github_pr_worker --> feat_github_webhook
infra_foundation --> feat_llm_judgments
infra_adapter_elastic --> feat_llm_judgments
feat_study_lifecycle --> feat_llm_judgments
feat_studies_ui --> feat_proposals_ui
feat_digest_proposal --> feat_proposals_ui
feat_github_pr_worker --> feat_proposals_ui
feat_github_webhook --> feat_proposals_ui
infra_foundation --> feat_studies_ui
feat_study_lifecycle --> feat_studies_ui
feat_digest_proposal --> feat_studies_ui
feat_llm_judgments --> feat_studies_ui
infra_adapter_elastic --> feat_studies_ui
```

---

Source of truth: feature folders under [`docs/02_product/planned_features/`](../02_product/planned_features/) and [`docs/00_overview/implemented_features/`](implemented_features/). See [`state.md`](../../state.md) for active-branch context and [`CLAUDE.md`](../../CLAUDE.md) for conventions.
Loading
Loading