From c0a044fa0b1ae33a3b072714e1514672f99c06b9 Mon Sep 17 00:00:00 2001 From: tegwick Date: Tue, 28 Apr 2026 01:24:37 +0200 Subject: [PATCH] Explore after registration as default --- src/repo_registry/web_ui/views.py | 21 +++++++++ tests/test_web_api.py | 43 +++++++++++++++++++ ...P-0003-automatic-repository-exploration.md | 25 ++++++++++- 3 files changed, 87 insertions(+), 2 deletions(-) diff --git a/src/repo_registry/web_ui/views.py b/src/repo_registry/web_ui/views.py index 0776007..1e381e8 100644 --- a/src/repo_registry/web_ui/views.py +++ b/src/repo_registry/web_ui/views.py @@ -101,6 +101,15 @@ def page(title: str, body: str) -> HTMLResponse: font: inherit; }} label {{ display: grid; gap: 5px; color: var(--muted); font-size: 12px; font-weight: 600; }} + label.checkbox {{ + display: flex; + gap: 8px; + align-items: center; + color: var(--text); + font-size: 13px; + font-weight: 500; + }} + label.checkbox input {{ width: auto; }} button, .button {{ display: inline-flex; align-items: center; @@ -203,6 +212,7 @@ def render_repository_index( +
Registering repository... @@ -414,6 +424,7 @@ def create_repository_from_form( branch: str = Form("main"), access_username: str = Form(""), access_password: str = Form(""), + explore_after_registration: str | None = Form(None), service: RegistryService = Depends(get_service), ): try: @@ -429,6 +440,16 @@ def create_repository_from_form( error_message=str(exc), status_code=400, ) + if explore_after_registration: + summary = service.analyze_repository( + repository.id, + access_username=access_username or None, + access_password=access_password or None, + ) + return RedirectResponse( + f"/ui/repos/{repository.id}/analysis-runs/{summary.analysis_run.id}", + status_code=303, + ) return RedirectResponse(f"/ui/repos/{repository.id}", status_code=303) diff --git a/tests/test_web_api.py b/tests/test_web_api.py index 322220f..a2f276e 100644 --- a/tests/test_web_api.py +++ b/tests/test_web_api.py @@ -1075,6 +1075,7 @@ def test_ui_register_analyze_and_approve_loop(tmp_path): assert "Register Repository" in index_response.text assert "Registering repository..." in index_response.text assert "Password or access token" in index_response.text + assert "Explore after registration" in index_response.text create_response = client.post( "/ui/repos", @@ -1083,6 +1084,7 @@ def test_ui_register_analyze_and_approve_loop(tmp_path): "branch": "main", "access_username": "", "access_password": "", + "explore_after_registration": "", }, follow_redirects=False, ) @@ -1210,6 +1212,47 @@ def test_ui_register_analyze_and_approve_loop(tmp_path): app.dependency_overrides.clear() +def test_ui_register_and_explore_lands_on_analysis_result(tmp_path): + source = tmp_path / "explore-repo" + source.mkdir() + (source / "README.md").write_text("# Explore Repo\n", encoding="utf-8") + (source / "pyproject.toml").write_text( + "[project]\nname = \"explore-repo\"\ndescription = \"Explorable repo.\"\n", + encoding="utf-8", + ) + + def override_settings(): + return Settings( + database_path=str(tmp_path / "ui-explore.sqlite3"), + checkout_root=str(tmp_path / "ui-explore-checkouts"), + ) + + app.dependency_overrides[get_settings] = override_settings + client = TestClient(app) + try: + response = client.post( + "/ui/repos", + data={ + "url": str(source), + "branch": "main", + "access_username": "", + "access_password": "", + "explore_after_registration": "1", + }, + follow_redirects=False, + ) + + assert response.status_code == 303 + assert response.headers["location"].endswith("/analysis-runs/1") + + result = client.get(response.headers["location"]) + assert result.status_code == 200 + assert "Candidate Graph" in result.text + assert "Observed Facts" in result.text + finally: + app.dependency_overrides.clear() + + def test_ui_registration_failure_returns_feedback(tmp_path): def override_settings(): return Settings( diff --git a/workplans/RREG-WP-0003-automatic-repository-exploration.md b/workplans/RREG-WP-0003-automatic-repository-exploration.md index 80b4429..b35bd06 100644 --- a/workplans/RREG-WP-0003-automatic-repository-exploration.md +++ b/workplans/RREG-WP-0003-automatic-repository-exploration.md @@ -27,7 +27,7 @@ configured trusted automation mode. ```task id: RREG-WP-0003-T01 -status: in_progress +status: done priority: high state_hub_task_id: "ab718ce7-d38f-4080-9385-99be1bf80475" ``` @@ -58,7 +58,28 @@ coordination should be visible as source-linked claims. Acceptance: a self-analysis run produces non-trivial, source-linked candidate abilities and capabilities that a curator would recognize as the repo's real -purpose. +purpose. A one-to-one correspondence of observed fact to generated feature is a +quality smell: features should describe user-visible or operational behavior, with +facts as drilldown evidence, not mirror individual scanner facts. + +## P0: Abstraction Strategy And LLM Boundary + +```task +id: RREG-WP-0003-T06 +status: todo +priority: high +state_hub_task_id: "51890aff-511d-4635-85c4-fe4db0b7dd01" +``` + +Document and test how the registry should climb from deterministic observed facts +to useful ability/capability/feature abstractions. Explicitly compare what can be +done deterministically against what likely needs LLM assistance. Preserve the trust +boundary: deterministic scanners establish facts; abstraction may propose claims; +review or trusted automation decides approved registry truth. + +Acceptance: `docs/` contains an abstraction strategy note with examples from the +three trial repos, and candidate generation has at least one regression guard +against feature granularity collapsing into one feature per observed fact. ## P1: Guided Review To Populated Registry