From 3af203775b20a773132cf28bbece08394e84ec77 Mon Sep 17 00:00:00 2001 From: SoundMindsAI Date: Tue, 12 May 2026 09:36:03 -0400 Subject: [PATCH] =?UTF-8?q?docs:=20finalize=20feat=5Fgithub=5Fwebhook=20(P?= =?UTF-8?q?R=20#56)=20=E2=80=94=20move=20to=20implemented=5Ffeatures?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move docs/02_product/planned_features/feat_github_webhook → docs/00_overview/implemented_features/2026_05_12_feat_github_webhook - implementation_plan.md Status header: Draft → Complete (PR #56, 9805f3e) - pipeline_status.md Implementation section: Not started → Complete with PR + CI cycle + GPT-5.5 adjudication summary - CLAUDE.md row 8: pending → Complete (PR #56, merged 2026-05-12) - state.md: flip current branch + remove from queued list; recent-changes entry updated to reflect merge SHA + CI iteration count - docs/00_overview/MVP1_DASHBOARD.md + mvp1_dashboard.html: regenerated by the mvp1-dashboard-regen pre-commit hook after the folder move Co-Authored-By: Claude Opus 4.7 (1M context) --- CLAUDE.md | 2 +- docs/00_overview/MVP1_DASHBOARD.md | 31 +++++---- .../feature_spec.md | 0 .../implementation_plan.md | 2 +- .../pipeline_status.md | 9 ++- docs/00_overview/mvp1_dashboard.html | 65 ++++++++++--------- state.md | 11 ++-- 7 files changed, 63 insertions(+), 57 deletions(-) rename docs/{02_product/planned_features/feat_github_webhook => 00_overview/implemented_features/2026_05_12_feat_github_webhook}/feature_spec.md (100%) rename docs/{02_product/planned_features/feat_github_webhook => 00_overview/implemented_features/2026_05_12_feat_github_webhook}/implementation_plan.md (99%) rename docs/{02_product/planned_features/feat_github_webhook => 00_overview/implemented_features/2026_05_12_feat_github_webhook}/pipeline_status.md (77%) diff --git a/CLAUDE.md b/CLAUDE.md index 9880fd42..6bc0dbca 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -426,7 +426,7 @@ If you slip and a stub leaks into a committed file, capture it as a `bug_` | 5 | [`feat_llm_judgments`](docs/00_overview/implemented_features/2026_05_11_feat_llm_judgments/) | **Complete (PR #35, merged 2026-05-11)** | | 6 | [`feat_digest_proposal`](docs/00_overview/implemented_features/2026_05_11_feat_digest_proposal/) | **Complete (PR #41, merged 2026-05-11)** | | 7 | [`feat_github_pr_worker`](docs/00_overview/implemented_features/2026_05_12_feat_github_pr_worker/) | **Complete (PR #45, merged 2026-05-12)** | -| 8 | [`feat_github_webhook`](docs/02_product/planned_features/feat_github_webhook/) | Implementation complete (all 10 stories), pending push + CI + merge on `feature/feat-github-webhook` | +| 8 | [`feat_github_webhook`](docs/00_overview/implemented_features/2026_05_12_feat_github_webhook/) | **Complete (PR #56, merged 2026-05-12)** | | 9 | [`feat_studies_ui`](docs/00_overview/implemented_features/2026_05_12_feat_studies_ui/) | **Complete (PR #50, pending merge)** | | 10 | [`feat_chat_agent`](docs/02_product/planned_features/feat_chat_agent/) | Spec approved, plan pending | | 11 | [`feat_proposals_ui`](docs/02_product/planned_features/feat_proposals_ui/) | Spec approved, plan pending | diff --git a/docs/00_overview/MVP1_DASHBOARD.md b/docs/00_overview/MVP1_DASHBOARD.md index b2fabc1d..287ab16b 100644 --- a/docs/00_overview/MVP1_DASHBOARD.md +++ b/docs/00_overview/MVP1_DASHBOARD.md @@ -4,22 +4,22 @@ _Reflects feature-folder state as of **2026-05-12** (latest mtime of any planned ## Next up -**[feat_github_webhook](../02_product/planned_features/feat_github_webhook/feature_spec.md)** — Feature, currently in **Plan** +**[feat_proposals_ui](../02_product/planned_features/feat_proposals_ui/feature_spec.md)** — Feature, currently in **Spec** -> 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`. +> 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. -Plan approved; run /impl-execute to ship +Spec exists; run /pipeline to generate the implementation plan + ship ```bash -/impl-execute docs/02_product/planned_features/feat_github_webhook/implementation_plan.md --all +/pipeline docs/02_product/planned_features/feat_proposals_ui --auto ``` ## MVP1 Progress | Metric | Value | |---|---| -| Features done | **9 / 13** (69%) | -| Path to MVP1 | **19** items remaining (features + bugs + chores) | +| Features done | **10 / 13** (77%) | +| Path to MVP1 | **18** items remaining (features + bugs + chores) | | Open bugs | 4 | | Open chores | 11 (idea-stage debt) | | Backlog ideas | 4 idea-only feat/infra (not yet scoped into MVP1) | @@ -27,12 +27,13 @@ Plan approved; run /impl-execute to ship ## Pipeline -### Done (9) +### Done (10) | Feature | Type | One-liner | Depends on | Status | |---|---|---|---|---| | [feat_digest_proposal](implemented_features/2026_05_11_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` | [PR #41](https://github.com/SoundMindsAI/relyloop/pull/41) merged 2026-05-11 | | [feat_github_pr_worker](implemented_features/2026_05_12_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_study_lifecycle` `feat_digest_proposal` | [PR #45](https://github.com/SoundMindsAI/relyloop/pull/45) merged 2026-05-12 | +| [feat_github_webhook](implemented_features/2026_05_12_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` `infra_adapter_elastic` `feat_github_pr_worker` | [PR #56](https://github.com/SoundMindsAI/relyloop/pull/56) merged 2026-05-12 | | [feat_llm_judgments](implemented_features/2026_05_11_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` | [PR #35](https://github.com/SoundMindsAI/relyloop/pull/35) merged 2026-05-11 | | [feat_studies_ui](implemented_features/2026_05_12_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` | [PR #50](https://github.com/SoundMindsAI/relyloop/pull/50) merged 2026-05-12 | | [feat_study_lifecycle](implemented_features/2026_05_10_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 | @@ -45,11 +46,9 @@ Plan approved; run /impl-execute to ship _None._ -### Plan (1) +### Plan (0) -| Feature | Type | One-liner | Depends on | Status | -|---|---|---|---|---| -| [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` `infra_adapter_elastic` `feat_github_pr_worker` | [PR #50](https://github.com/SoundMindsAI/relyloop/pull/50) | +_None._ ### Spec (3) @@ -98,8 +97,6 @@ graph LR class chore_tutorial_polish spec; feat_chat_agent["chat agent"] class feat_chat_agent spec; - feat_github_webhook["github webhook"] - class feat_github_webhook plan; feat_proposals_ui["proposals ui"] class feat_proposals_ui spec; infra_foundation["foundation"] @@ -116,6 +113,8 @@ graph LR class feat_llm_judgments done; feat_github_pr_worker["github pr worker"] class feat_github_pr_worker done; + feat_github_webhook["github webhook"] + class feat_github_webhook done; feat_studies_ui["studies ui"] class feat_studies_ui done; infra_frontend_stack_refresh["frontend stack refresh"] @@ -143,9 +142,6 @@ graph LR infra_foundation --> feat_chat_agent infra_frontend_stack_refresh --> feat_chat_agent infra_optuna_eval --> feat_chat_agent - infra_foundation --> feat_github_webhook - infra_adapter_elastic --> feat_github_webhook - feat_github_pr_worker --> feat_github_webhook feat_studies_ui --> feat_proposals_ui feat_digest_proposal --> feat_proposals_ui feat_github_pr_worker --> feat_proposals_ui @@ -159,6 +155,9 @@ graph LR infra_adapter_elastic --> feat_github_pr_worker feat_study_lifecycle --> feat_github_pr_worker feat_digest_proposal --> feat_github_pr_worker + infra_foundation --> feat_github_webhook + infra_adapter_elastic --> feat_github_webhook + feat_github_pr_worker --> feat_github_webhook infra_foundation --> feat_studies_ui feat_study_lifecycle --> feat_studies_ui feat_digest_proposal --> feat_studies_ui diff --git a/docs/02_product/planned_features/feat_github_webhook/feature_spec.md b/docs/00_overview/implemented_features/2026_05_12_feat_github_webhook/feature_spec.md similarity index 100% rename from docs/02_product/planned_features/feat_github_webhook/feature_spec.md rename to docs/00_overview/implemented_features/2026_05_12_feat_github_webhook/feature_spec.md diff --git a/docs/02_product/planned_features/feat_github_webhook/implementation_plan.md b/docs/00_overview/implemented_features/2026_05_12_feat_github_webhook/implementation_plan.md similarity index 99% rename from docs/02_product/planned_features/feat_github_webhook/implementation_plan.md rename to docs/00_overview/implemented_features/2026_05_12_feat_github_webhook/implementation_plan.md index a0b9cd91..f8db5f3a 100644 --- a/docs/02_product/planned_features/feat_github_webhook/implementation_plan.md +++ b/docs/00_overview/implemented_features/2026_05_12_feat_github_webhook/implementation_plan.md @@ -1,7 +1,7 @@ # Implementation Plan — feat_github_webhook **Date:** 2026-05-12 (Review & Patch cycle 2026-05-12 — see §11 patch log) -**Status:** Draft (cross-model reviewed) +**Status:** Complete (PR #56, merged 2026-05-12; squash commit `9805f3e`) **Primary spec:** [feature_spec.md](feature_spec.md) (Approved 2026-05-12 after Review & Patch cycle) **Policy sources:** - [`CLAUDE.md`](../../../../CLAUDE.md) — absolute rules, conventions, MVP1 stack diff --git a/docs/02_product/planned_features/feat_github_webhook/pipeline_status.md b/docs/00_overview/implemented_features/2026_05_12_feat_github_webhook/pipeline_status.md similarity index 77% rename from docs/02_product/planned_features/feat_github_webhook/pipeline_status.md rename to docs/00_overview/implemented_features/2026_05_12_feat_github_webhook/pipeline_status.md index 737c9185..60c62d0f 100644 --- a/docs/02_product/planned_features/feat_github_webhook/pipeline_status.md +++ b/docs/00_overview/implemented_features/2026_05_12_feat_github_webhook/pipeline_status.md @@ -30,4 +30,11 @@ - Next action: `/impl-execute docs/02_product/planned_features/feat_github_webhook/implementation_plan.md --all` (when MVP1 sequencing reaches this feature — `feat_studies_ui` PR #50 is the current blocker per `state.md`). ## Implementation -- Status: Not started +- Status: Complete +- Date: 2026-05-12 +- PR: [#56](https://github.com/SoundMindsAI/relyloop/pull/56) (squash commit `9805f3e`) +- Stories shipped: 10 of 10 (Epic 1: 5 / Epic 2: 1 / Epic 3: 1 / Epic 4: 3) +- CI: green on cycle 4 (`25737327542`) — backend lint + typecheck + tests + 80.18% coverage; frontend; docker buildx. +- Cross-model review: GPT-5.5 final review — 3 findings, 2 accepted + applied (non-dict JSON guard + merged-without-merged_at fallback), 1 rejected with cited counter-evidence (Settings validator + `_poll_cron_kwargs` fallback are both plan-mandated belt-and-suspenders). +- Gemini Code Assist: not installed on this repo (consistent with prior PRs #25/#23/#18/#16/#4). +- Tangential captured: [`bug_test_smoke_requires_env_vars`](../bug_test_smoke_requires_env_vars/idea.md). diff --git a/docs/00_overview/mvp1_dashboard.html b/docs/00_overview/mvp1_dashboard.html index 6f1d4058..ba622513 100644 --- a/docs/00_overview/mvp1_dashboard.html +++ b/docs/00_overview/mvp1_dashboard.html @@ -314,11 +314,11 @@

RelyLoop MVP1 Dashboard

-
Next up — Feature, currently in Plan
- -
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`.
-
Plan approved; run /impl-execute to ship
- /impl-execute docs/02_product/planned_features/feat_github_webhook/implementation_plan.md --all +
Next up — Feature, currently in Spec
+ +
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.
+
Spec exists; run /pipeline to generate the implementation plan + ship
+ /pipeline docs/02_product/planned_features/feat_proposals_ui --auto
@@ -328,13 +328,13 @@

MVP1 Progress

Features done
-
9 / 13
-
69% of scoped MVP1 features
-
+
10 / 13
+
77% of scoped MVP1 features
+
Path to MVP1
-
19
+
18
items left = features + bugs + chores
@@ -644,18 +644,7 @@

Spec 3

-

Plan 1

- -
- -
- Feature - PR #50 -
-
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`.
- -
depends on: infra_foundationinfra_adapter_elasticfeat_github_pr_worker
-
+

Plan 0

@@ -665,7 +654,7 @@

Implementing 0

-

Done 9

+

Done 10

@@ -691,6 +680,18 @@

Done 9

+
+ +
+ Feature + PR #56merged 2026-05-12 +
+
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`.
+ +
depends on: infra_foundationinfra_adapter_elasticfeat_github_pr_worker
+
+ +
@@ -791,8 +792,6 @@

Dependency graph (feat_ + infra_)

class chore_tutorial_polish spec; feat_chat_agent["chat agent"] class feat_chat_agent spec; - feat_github_webhook["github webhook"] - class feat_github_webhook plan; feat_proposals_ui["proposals ui"] class feat_proposals_ui spec; infra_foundation["foundation"] @@ -809,6 +808,8 @@

Dependency graph (feat_ + infra_)

class feat_llm_judgments done; feat_github_pr_worker["github pr worker"] class feat_github_pr_worker done; + feat_github_webhook["github webhook"] + class feat_github_webhook done; feat_studies_ui["studies ui"] class feat_studies_ui done; infra_frontend_stack_refresh["frontend stack refresh"] @@ -836,9 +837,6 @@

Dependency graph (feat_ + infra_)

infra_foundation --> feat_chat_agent infra_frontend_stack_refresh --> feat_chat_agent infra_optuna_eval --> feat_chat_agent - infra_foundation --> feat_github_webhook - infra_adapter_elastic --> feat_github_webhook - feat_github_pr_worker --> feat_github_webhook feat_studies_ui --> feat_proposals_ui feat_digest_proposal --> feat_proposals_ui feat_github_pr_worker --> feat_proposals_ui @@ -852,6 +850,9 @@

Dependency graph (feat_ + infra_)

infra_adapter_elastic --> feat_github_pr_worker feat_study_lifecycle --> feat_github_pr_worker feat_digest_proposal --> feat_github_pr_worker + infra_foundation --> feat_github_webhook + infra_adapter_elastic --> feat_github_webhook + feat_github_pr_worker --> feat_github_webhook infra_foundation --> feat_studies_ui feat_study_lifecycle --> feat_studies_ui feat_digest_proposal --> feat_studies_ui @@ -867,8 +868,6 @@

Dependency graph (feat_ + infra_)

class chore_tutorial_polish spec; feat_chat_agent["chat agent"] class feat_chat_agent spec; - feat_github_webhook["github webhook"] - class feat_github_webhook plan; feat_proposals_ui["proposals ui"] class feat_proposals_ui spec; infra_foundation["foundation"] @@ -885,6 +884,8 @@

Dependency graph (feat_ + infra_)

class feat_llm_judgments done; feat_github_pr_worker["github pr worker"] class feat_github_pr_worker done; + feat_github_webhook["github webhook"] + class feat_github_webhook done; feat_studies_ui["studies ui"] class feat_studies_ui done; infra_frontend_stack_refresh["frontend stack refresh"] @@ -912,9 +913,6 @@

Dependency graph (feat_ + infra_)

infra_foundation --> feat_chat_agent infra_frontend_stack_refresh --> feat_chat_agent infra_optuna_eval --> feat_chat_agent - infra_foundation --> feat_github_webhook - infra_adapter_elastic --> feat_github_webhook - feat_github_pr_worker --> feat_github_webhook feat_studies_ui --> feat_proposals_ui feat_digest_proposal --> feat_proposals_ui feat_github_pr_worker --> feat_proposals_ui @@ -928,6 +926,9 @@

Dependency graph (feat_ + infra_)

infra_adapter_elastic --> feat_github_pr_worker feat_study_lifecycle --> feat_github_pr_worker feat_digest_proposal --> feat_github_pr_worker + infra_foundation --> feat_github_webhook + infra_adapter_elastic --> feat_github_webhook + feat_github_pr_worker --> feat_github_webhook infra_foundation --> feat_studies_ui feat_study_lifecycle --> feat_studies_ui feat_digest_proposal --> feat_studies_ui diff --git a/state.md b/state.md index 1ad84506..bde86b55 100644 --- a/state.md +++ b/state.md @@ -2,13 +2,13 @@ > Read this first. Snapshots the active branch, what just shipped, what's in flight, what's queued, and where the project currently sits in the MVP1 → GA roadmap. Updated whenever a feature lands or a priority shifts. -**Last updated:** 2026-05-12 (after `feat_github_webhook` implementation complete; pending push + CI + merge on `feature/feat-github-webhook`) +**Last updated:** 2026-05-12 (after `feat_github_webhook` merged via PR #56, squash commit `9805f3e`) --- ## Current branch / execution context -- **Branch:** `feature/feat-github-webhook` — `POST /webhooks/github` receiver + 15-min polling reconciler cron + idempotent `register_webhook` Arq worker + extended `POST /api/v1/config-repos` to enqueue auto-registration. 10 stories across 4 epics shipped via `/impl-execute --all`. Pending push + CI + merge. +- **Branch:** `main` (post-merge); finalization docs land via `docs/finalize-github-webhook`. `feat_github_webhook` shipped end-to-end via PR #56. - **Active feature:** none in flight (post `feat_github_webhook`, next per the dashboard is `feat_chat_agent`). - **Alembic head:** `0006_proposals_pr_url_idx` (partial B-tree index on `proposals(pr_url) WHERE pr_url IS NOT NULL` for the webhook receiver's lookup). - **Python:** 3.13. @@ -17,7 +17,7 @@ ## Most recent meaningful changes (newest first) -- **2026-05-12 — `feat_github_webhook` implementation complete** on `feature/feat-github-webhook`. 10 stories across 4 epics shipped via `/impl-execute --all`. **One migration (`0006_proposals_pr_url_idx`).** Stories breakdown: +- **2026-05-12 — `feat_github_webhook` merged into `main`** as PR #56 (squash commit `9805f3e`). 10 stories across 4 epics shipped via `/impl-execute --all`. **One migration (`0006_proposals_pr_url_idx`).** GPT-5.5 final review converged in **1 cycle** (3 findings; 2 accepted + applied, 1 rejected with cited counter-evidence). CI iterated 4 cycles before green: initial push (structlog `event=` kwarg clash + migration head expectation + downgrade-target drift on digests + closed-unmerged config_repo isolation), cycle-2 fixes for the structlog rename + GPT-5.5 review fixes, cycle-3 fix for the unique `(owner, repo)` per test, cycle-4 fix for the second missed `0006 → 0006` migration assertion. Stories breakdown: - **Epic 1 (foundations, 5 stories):** Story 1.1 (migration `0006` + `Settings.relyloop_pr_poll_minutes` field bounded 1..1440); Story 1.2 (HMAC-SHA256 `verify_webhook_signature` + `parse_repository_full_name` short-form parser, pure-domain; deliberately separate from `validate_repo_url` so the URL regex isn't duplicated); Story 1.3 (`dispatch_event` pure-domain decision function — never emits `"unknown_pr"`, that's router-only); Story 1.4 (5 new proposal repo functions — `mark_proposal_pr_merged/closed/reopened`, `lookup_proposal_by_pr_url`, `list_pr_opened_proposals_for_reconcile`; 2 new config_repo repo functions — `set_webhook_registration_error`, `lookup_config_repo_by_owner_repo`); Story 1.5 (extracted `_github_post` + 4 inspection helpers from `workers/git_pr.py` to canonical `backend/app/git/github_client.py`; generalised to method-agnostic `github_request(client, method, url, *, json_body, token)`; hoisted `read_mounted_secret` from `git_pr._read_pat` to `backend/app/git/secrets.py`). - **Epic 2 (webhook receiver, 1 story):** Story 2.1 — `POST /webhooks/github` unprefixed router (CLAUDE.md Rule #6 carve-out). 9-step contract: raw body → repository.full_name parse → config_repo lookup → mounted secret read → HMAC verify → dispatch → proposal lookup → conditional mutation → structured `webhook_received` log. Single error code `INVALID_SIGNATURE` (403) covers both signature mismatch AND unknown repo (no enumeration leak). Router-only `"unknown_pr"` override on lookup miss. - **Epic 3 (polling reconciler, 1 story):** Story 3.1 — `reconcile_pr_state` cron job. Per-proposal flow: parse `pr_url` → `lookup_config_repo_by_owner_repo` → `read_mounted_secret(auth_ref)` → `GET pulls/{n}` via `github_request` → branch on `merged/state`. 401/403/404/5xx/RequestError-after-budget → WARN + skip. 429 → WARN + **break the proposal loop** for this tick (spec §10). `SUPPORTED_POLL_MINUTES` whitelist (18 values: divisors of 60 plus multiples of 60 that divide 1440) — Settings `@field_validator` rejects out-of-set at boot. @@ -228,9 +228,8 @@ **Source of truth:** [`docs/00_overview/MVP1_DASHBOARD.md`](docs/00_overview/MVP1_DASHBOARD.md) (regenerated by the `mvp1-dashboard-regen` pre-commit hook). Run `/pipeline status` for the live view. -1. **`feat_github_webhook`** — `/webhooks/github` (idempotent, signature-verified). Will mirror the per-repo `webhook_secret_ref` pattern that `feat_github_pr_worker` established for `auth_ref` (one HMAC secret per registered repo). -2. **`feat_chat_agent`** — streaming chat orchestrator. Will consume `POST /api/v1/proposals/{id}/open_pr` for the agent-tool "open this PR" path. Depends on `feat_studies_ui` for the chat surface UI. -3. **`feat_proposals_ui`** — `/proposals` review surface. Consumes the proposal CRUD endpoints `feat_digest_proposal` shipped + the `POST /proposals/{id}/open_pr` endpoint shipped by `feat_github_pr_worker`. Depends on `feat_studies_ui` shell + `feat_github_webhook` for PR-state mirroring. +1. **`feat_chat_agent`** — streaming chat orchestrator. Will consume `POST /api/v1/proposals/{id}/open_pr` for the agent-tool "open this PR" path. Depends on `feat_studies_ui` for the chat surface UI. +2. **`feat_proposals_ui`** — `/proposals` review surface. Consumes the proposal CRUD endpoints `feat_digest_proposal` shipped + the `POST /proposals/{id}/open_pr` endpoint shipped by `feat_github_pr_worker` + the `pr_state` updates shipped by `feat_github_webhook`. Depends on `feat_studies_ui` shell. 4. **`chore_tutorial_polish`** — sample data + walkthrough. Tutorial flow now has the `POST /judgment-lists/import` path it expects (FR-3b). 5. **`chore_studies_ui_shadcn_polish`** — migrate TopNav + CursorPaginator page-size to `` / `