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
35 changes: 18 additions & 17 deletions docs/00_overview/MVP2_DASHBOARD.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Plan approved; run /impl-execute to ship
| Open bugs | 7 |
| Legacy "Path to MVP2" | 17 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 |
| In flight | 1 feature(s) actively shipping |

## Pipeline

Expand Down Expand Up @@ -66,9 +66,11 @@ Plan approved; run /impl-execute to ship
| [bug_backend_suite_nondeterministic_caplog_isolation](implemented_features/2026_06_01_bug_backend_suite_nondeterministic_caplog_isolation/idea.md) | Bug | Many backend unit tests assert on captured log records (`caplog` / a structlog capture fixture) and fail with empty-capture shapes (`assert []`, `assert 'x' in []`) when run in the full randomized sui | — | [PR #364](https://github.com/SoundMindsAI/relyloop/pull/364) merged 2026-06-01 |
| [bug_contract_allowlists_outdated_after_mvp2_features](implemented_features/2026_06_01_bug_contract_allowlists_outdated_after_mvp2_features/idea.md) | Bug | Three separate contract-test allowlists were not updated as features shipped through MVP2. Each is a "hand-maintained canonical list of valid values" that drifts when a feature adds new entries to the | — | [PR #364](https://github.com/SoundMindsAI/relyloop/pull/364) merged 2026-06-01 |

### Implementing (0)
### Implementing (1)

_None._
| # | Priority | Feature | Type | One-liner | Depends on | Status |
|---|---|---|---|---|---|---|
| 1 | P2 | [bug_cluster_url_ssrf_hostname_bypass](planned_features/02_mvp2/bug_cluster_url_ssrf_hostname_bypass/feature_spec.md) | Bug | When private clusters are disallowed (`RELYLOOP_ALLOW_PRIVATE_CLUSTERS=False`), a `base_url` whose host **resolves** to a private / loopback / link-local / reserved / multicast / unspecified / carrier | — | [PR #510](https://github.com/SoundMindsAI/relyloop/pull/510) |

### Plan (3)

Expand All @@ -82,27 +84,26 @@ _None._

_None._

### Idea (17)
### Idea (16)

| # | Priority | Feature | Type | One-liner | Depends on | Status |
|---|---|---|---|---|---|---|
| 1 | P2 | [chore_agent_confirmation_tool_name_word_boundary](planned_features/02_mvp2/chore_agent_confirmation_tool_name_word_boundary/idea.md) | Chore | The confirmation gate for the 8 mutating agent tools (`create_study`, `cancel_study`, `open_pr`, `create_proposal_*`, judgment generation, CSV import) is a two-condition heuristic: the last assistant | — | Idea — surfaced during a codebase-wide security review (branch `claude/codebase-security-review-6njwio`) |
| 2 | P2 | [chore_overnight_result_card_screenshot](planned_features/02_mvp2/chore_overnight_result_card_screenshot/idea.md) | Chore | The `docs/08_guides/tutorial-first-study.md` Step 12 sub-section *"In the morning — read the overnight result card"* (verified at [tutorial-first-study.md:510](../docs/08_guides/tutorial-first-study.m | — | Idea — deferred FR-9 deliverable from PR #442 |
| 3 | 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 |
| 4 | P2 | [chore_test_router_conditional_mount](planned_features/02_mvp2/chore_test_router_conditional_mount/idea.md) | Chore | The `_test` router exposes data-mutating endpoints used only for deterministic E2E (seed a completed study, demo reseed, hard-delete studies/judgment-lists/proposals). Today it is registered **uncondi | — | Idea — surfaced during a codebase-wide security review (branch `claude/codebase-security-review-6njwio`) |
| 5 | P2 | [bug_cluster_url_ssrf_hostname_bypass](planned_features/02_mvp2/bug_cluster_url_ssrf_hostname_bypass/idea.md) | Bug | The cluster registration `base_url` validator is intended to stop SSRF into internal/cloud-metadata endpoints (it cites "spec §10 Threat 3"), but the guard only fires when the host parses as a **liter | — | Idea — surfaced during a codebase-wide security review (branch `claude/codebase-security-review-6njwio`) |
| 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_request_id_header_unvalidated_log_injection](planned_features/02_mvp2/bug_request_id_header_unvalidated_log_injection/idea.md) | Bug | `RequestIDMiddleware` adopts a client-supplied `X-Request-ID` header verbatim with no validation of length or character set: | — | Idea — surfaced during a codebase-wide security review (branch `claude/codebase-security-review-6njwio`) |
| 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_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 |
| 10 | 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. |
| 11 | 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. |
| 12 | Backlog | [infra_pr_yml_split_backend_test_lanes](planned_features/02_mvp2/infra_pr_yml_split_backend_test_lanes/idea.md) | Infra | The heavy `backend (tests + coverage)` job in `.github/workflows/pr.yml` runs the full `pytest backend/tests/` matrix (unit + integration + contract) serially in one job with `--cov` gating at `fail_u | — | Idea — **deferred (defer-until-binding-constraint)**. Carved out of `chore_pr_yml_parallelize_backend_job` (now in `implemented_features/2026_06_05_*`; see "Relationship to other work" below for the link) at its 2026-06-05 descope. Pick up only when the integration layer becomes the binding CI constraint after other critical-path work lands. |
| 13 | Backlog | [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`) |
| 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 | [chore_e2e_overnight_strategy_radix_select_timing](planned_features/02_mvp2/chore_e2e_overnight_strategy_radix_select_timing/idea.md) | Chore | The Story 3.2 E2E spec walks the create-study wizard to Step 5, clicks the depth `<Select>` ("2 follow-ups"), and asserts the new Strategy `<Select>` becomes visible. In chromium against `pnpm dev`, t | — | Idea — tangential follow-up captured during `feat_overnight_final_solution` Story 3.2 implementation |
| 16 | Backlog | [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) |
| 17 | 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). |
| 5 | 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) |
| 6 | P2 | [bug_request_id_header_unvalidated_log_injection](planned_features/02_mvp2/bug_request_id_header_unvalidated_log_injection/idea.md) | Bug | `RequestIDMiddleware` adopts a client-supplied `X-Request-ID` header verbatim with no validation of length or character set: | — | Idea — surfaced during a codebase-wide security review (branch `claude/codebase-security-review-6njwio`) |
| 7 | 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`) |
| 8 | 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 |
| 9 | 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. |
| 10 | 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. |
| 11 | Backlog | [infra_pr_yml_split_backend_test_lanes](planned_features/02_mvp2/infra_pr_yml_split_backend_test_lanes/idea.md) | Infra | The heavy `backend (tests + coverage)` job in `.github/workflows/pr.yml` runs the full `pytest backend/tests/` matrix (unit + integration + contract) serially in one job with `--cov` gating at `fail_u | — | Idea — **deferred (defer-until-binding-constraint)**. Carved out of `chore_pr_yml_parallelize_backend_job` (now in `implemented_features/2026_06_05_*`; see "Relationship to other work" below for the link) at its 2026-06-05 descope. Pick up only when the integration layer becomes the binding CI constraint after other critical-path work lands. |
| 12 | Backlog | [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`) |
| 13 | 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. |
| 14 | Backlog | [chore_e2e_overnight_strategy_radix_select_timing](planned_features/02_mvp2/chore_e2e_overnight_strategy_radix_select_timing/idea.md) | Chore | The Story 3.2 E2E spec walks the create-study wizard to Step 5, clicks the depth `<Select>` ("2 follow-ups"), and asserts the new Strategy `<Select>` becomes visible. In chromium against `pnpm dev`, t | — | Idea — tangential follow-up captured during `feat_overnight_final_solution` Story 3.2 implementation |
| 15 | Backlog | [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) |
| 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). |

## Dependency graph

Expand Down
31 changes: 15 additions & 16 deletions docs/00_overview/mvp2_dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ <h2>MVP2 Progress</h2>
</span>
<span>
<strong>In flight:</strong>
0 feature(s) actively shipping
1 feature(s) actively shipping
</span>
</div>
</section>
Expand All @@ -463,7 +463,7 @@ <h2>Pipeline</h2>
</div>
<div class="kanban">
<div class="col idea">
<h3>Idea <span class="count">17</span></h3>
<h3>Idea <span class="count">16</span></h3>

<div class="card chore" data-prefix="chore" data-priority="P2">
<div class="name"><a href="../../docs/00_overview/planned_features/02_mvp2/chore_agent_confirmation_tool_name_word_boundary">Agent Confirmation Tool Name Word Boundary</a></div>
Expand Down Expand Up @@ -517,19 +517,6 @@ <h3>Idea <span class="count">17</span></h3>
</div>


<div class="card bug" data-prefix="bug" data-priority="P2">
<div class="name"><a href="../../docs/00_overview/planned_features/02_mvp2/bug_cluster_url_ssrf_hostname_bypass">Cluster Url Ssrf Hostname Bypass</a></div>
<div class="meta">
<span class="badge bug">Bug</span>
<span class="badge priority" data-priority="P2">P2</span>

</div>
<div class="one-liner">The cluster registration `base_url` validator is intended to stop SSRF into internal/cloud-metadata endpoints (it cites &quot;spec §10 Threat 3&quot;), but the guard only fires when the host parses as a **liter</div>


</div>


<div class="card bug" data-prefix="bug" data-priority="P2">
<div class="name"><a href="../../docs/00_overview/planned_features/02_mvp2/bug_e2e_teardown_chain_node_delete_500">E2E Teardown Chain Node Delete 500</a></div>
<div class="meta">
Expand Down Expand Up @@ -736,7 +723,19 @@ <h3>Plan <span class="count">3</span></h3>
</div>

<div class="col implement">
<h3>Implementing <span class="count">0</span></h3>
<h3>Implementing <span class="count">1</span></h3>

<div class="card bug" data-prefix="bug" data-priority="P2">
<div class="name"><a href="../../docs/00_overview/planned_features/02_mvp2/bug_cluster_url_ssrf_hostname_bypass/feature_spec.md">Cluster Url Ssrf Hostname Bypass</a></div>
<div class="meta">
<span class="badge bug">Bug</span>
<span class="badge priority" data-priority="P2">P2</span>
<a class="pr" href="https://github.com/SoundMindsAI/relyloop/pull/510">PR #510</a>
</div>
<div class="one-liner">When private clusters are disallowed (`RELYLOOP_ALLOW_PRIVATE_CLUSTERS=False`), a `base_url` whose host **resolves** to a private / loopback / link-local / reserved / multicast / unspecified / carrier</div>
<div class="deferred">deferred: Phase 2</div>

</div>

</div>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Implementation Plan — Cluster base_url SSRF guard (hostname-aware)

**Date:** 2026-06-09
**Status:** Ready for Execution
**Status:** Complete — Phase 1 (PR #510, squash-merged `3cb28c7`, 2026-06-09; Phase 2 deferred → phase2_idea.md)
**Primary spec:** [`feature_spec.md`](feature_spec.md)
**Policy source(s):** CLAUDE.md Absolute Rules #4 (engine-adapter boundary), #10 (never log secrets); `docs/01_architecture/cluster-lifecycle.md`

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Pipeline Status — Cluster base_url SSRF guard (hostname-aware)

**Release:** mvp2

## Idea
- Status: Complete
- File: idea.md
Expand All @@ -20,4 +22,8 @@
- Phases covered: Phase 1 (Phase 2 connect-time IP pinning deferred → phase2_idea.md)

## Implementation
- Status: Not started
- Status: Complete — Phase 1 (PR #510, squash-merged `3cb28c7`, 2026-06-09)
- CI: all `pr.yml` jobs green (smoke skipped — opt-in/off)
- Stories: 3/3 complete (classifier / orchestrator+wiring / docs)
- Review: Opus self-review (GPT-5.5 unreachable) + Gemini Code Assist 2 Medium findings accepted (bounded DNS timeout, malformed-port 422)
- **Folder retained in `planned_features/` — Phase 2 (connect-time IP pinning, `phase2_idea.md`) is still pending**, so it is NOT moved to `implemented_features/` per the impl-execute deferred-phase rule.
Loading