Coevolution extension

This commit is contained in:
2026-04-29 01:19:59 +02:00
parent 88afdc09fd
commit 991c34ce52
17 changed files with 764 additions and 4 deletions

View File

@@ -877,6 +877,7 @@ def analysis_run_detail(
facts = service.list_observed_facts(repository_id, analysis_run_id)
chunks = service.list_content_chunks(repository_id, analysis_run_id)
decisions = service.list_review_decisions(repository_id, analysis_run_id)
expectation_gaps = service.list_expectation_gaps(repository_id, analysis_run_id)
fact_rows = "\n".join(
f"""
<tr>
@@ -941,10 +942,47 @@ def analysis_run_detail(
<h2>Content Chunks</h2>
{render_content_chunks(chunks)}
</section>
<section class="panel" style="margin-top:18px">
<h2>Expectation Gaps</h2>
<form class="stack" method="post" action="/ui/repos/{repository_id}/analysis-runs/{analysis_run_id}/expectation-gaps">
<div class="grid">
<label>Expected type <input name="expected_type" placeholder="capability, feature, fact, classification" required></label>
<label>Expected name <input name="expected_name" placeholder="Use OpenRouter Models" required></label>
<label>Source <input name="source" value="human" required></label>
<label>Notes <input name="notes" placeholder="What made you expect this?"></label>
</div>
<button type="submit">Record Gap</button>
</form>
{render_expectation_gaps(expectation_gaps)}
</section>
"""
return page(f"{repository.name} Run {analysis_run_id}", body)
@router.post("/ui/repos/{repository_id}/analysis-runs/{analysis_run_id}/expectation-gaps")
def create_expectation_gap_from_form(
repository_id: int,
analysis_run_id: int,
expected_type: str = Form(...),
expected_name: str = Form(...),
source: str = Form("human"),
notes: str = Form(""),
service: RegistryService = Depends(get_service),
) -> RedirectResponse:
service.record_expectation_gap(
repository_id,
analysis_run_id=analysis_run_id,
expected_type=expected_type,
expected_name=expected_name,
source=source,
notes=notes,
)
return RedirectResponse(
f"/ui/repos/{repository_id}/analysis-runs/{analysis_run_id}",
status_code=303,
)
@router.get("/ui/repos/{repository_id}/elements")
def repository_element_listing(
repository_id: int,
@@ -2028,6 +2066,29 @@ def render_review_decisions(decisions: list) -> str:
"""
def render_expectation_gaps(gaps: list) -> str:
if not gaps:
return '<p class="muted">No expectation gaps recorded for this run.</p>'
rows = "\n".join(
f"""
<tr>
<td><span class="pill">{escape(gap.expected_type)}</span></td>
<td>{escape(gap.expected_name)}</td>
<td>{escape(gap.source)}</td>
<td>{escape(gap.notes)}</td>
<td>{escape(gap.status)}</td>
</tr>
"""
for gap in gaps
)
return f"""
<table>
<thead><tr><th>Type</th><th>Name</th><th>Source</th><th>Notes</th><th>Status</th></tr></thead>
<tbody>{rows}</tbody>
</table>
"""
def render_content_chunks(chunks: list) -> str:
if not chunks:
return '<p class="muted">No content chunks extracted.</p>'