Finalized dependency aware scope prop

This commit is contained in:
2026-05-03 14:45:56 +02:00
parent 58f53e18de
commit 256dd497a0
4 changed files with 84 additions and 3 deletions

View File

@@ -47,6 +47,14 @@ The current implementation exposes this through `RegistryService`:
The impact result includes changed fact keys, impacted items, reason chains,
maximum propagation depth, breadth, and whether the root scope was affected.
## Review Workflow
The change-review UI shows dependency impact alongside ordinary run diffs. Each
impacted item carries a freshness state, reason chain, propagation depth, and a
recommended action. Curators can accept recalculated candidate text by approving
the target run, keep prior approved claims by leaving the change unapproved, or
edit approved characteristics through the existing manual registry forms.
## Interactive Visualization
The accepted implementation framework for the interactive graph view is

View File

@@ -1619,6 +1619,11 @@ def analysis_run_diff_detail(
base_analysis_run_id,
target_analysis_run_id,
)
impact = service.analyze_dependency_impact(
repository_id,
base_analysis_run_id,
target_analysis_run_id,
)
except NotFoundError as exc:
raise HTTPException(status_code=404, detail=str(exc)) from exc
display_name = repository_display_name(diff.repository)
@@ -1639,6 +1644,13 @@ def analysis_run_diff_detail(
</form>
</div>
</section>
<section class="panel" style="margin-top:18px">
<div class="actions">
<h2 style="margin-right:auto">Dependency Impact</h2>
<a class="button secondary" href="/ui/repos/{repository_id}/dependency-graph?base_analysis_run_id={base_analysis_run_id}&target_analysis_run_id={target_analysis_run_id}">Open Graph</a>
</div>
{render_dependency_impact_summary(asdict(impact))}
</section>
<div class="grid" style="margin-top:18px">
<section class="panel">
<h2>Approved Registry Impact</h2>
@@ -2403,6 +2415,65 @@ def render_diff_section(section: dict) -> str:
return rendered or '<p class="muted">No differences.</p>'
def render_dependency_impact_summary(impact: dict) -> str:
impacts = impact.get("impacts", [])
metric_row = (
f'<span class="pill">{escape(str(impact.get("propagation_breadth", 0)))} impacted</span>'
f'<span class="pill">depth {escape(str(impact.get("max_depth", 0)))}</span>'
+ (
'<span class="pill">scope impacted</span>'
if impact.get("scope_impacted")
else '<span class="pill">scope current</span>'
)
)
changed_facts = impact.get("changed_fact_keys", [])
changed_fact_rows = "".join(
f'<li class="source">{escape(str(fact_key))}</li>'
for fact_key in changed_facts[:8]
)
changed_fact_note = (
f"<ul>{changed_fact_rows}</ul>"
if changed_fact_rows
else '<p class="muted">No changed facts reached approved characteristics.</p>'
)
rows = "\n".join(
f"""
<tr>
<td><span class="pill">{escape(str(item.get('item_kind', '')))}</span></td>
<td>{escape(str(item.get('name', '')))}</td>
<td><span class="pill">{escape(str(item.get('freshness_state', '')))}</span></td>
<td>{escape(str(item.get('recommended_action', '')))}</td>
<td>{escape(str(item.get('impact_depth', '')))}</td>
<td>{render_impact_reasons(item.get('reasons', []))}</td>
</tr>
"""
for item in impacts
)
table = (
f"""
<table>
<thead><tr><th>Kind</th><th>Name</th><th>Freshness</th><th>Action</th><th>Depth</th><th>Why</th></tr></thead>
<tbody>{rows}</tbody>
</table>
"""
if rows
else '<p class="muted">No approved downstream items were marked stale.</p>'
)
return f"""
<div class="actions">{metric_row}</div>
<h3>Changed Facts</h3>
{changed_fact_note}
<h3>Impacted Items</h3>
{table}
"""
def render_impact_reasons(reasons: list[str]) -> str:
if not reasons:
return '<span class="muted">No reason recorded.</span>'
return "<br>".join(escape(str(reason)) for reason in reasons[:3])
def render_diff_group(items: list[dict], title: str) -> str:
if not items:
return ""

View File

@@ -1691,6 +1691,8 @@ def test_ui_register_analyze_and_approve_loop(tmp_path):
)
assert diff_response.status_code == 200
assert "Change Review" in diff_response.text
assert "Dependency Impact" in diff_response.text
assert "Open Graph" in diff_response.text
assert "Approved Registry Impact" in diff_response.text
assert "Candidate Claims" in diff_response.text
assert "GET /ready" in diff_response.text

View File

@@ -4,7 +4,7 @@ type: workplan
title: "Dependency-Aware Scope Propagation"
domain: capabilities
repo: repo-scoping
status: active
status: done
owner: codex
topic_slug: foerster-capabilities
created: "2026-05-01"
@@ -80,7 +80,7 @@ Acceptance criteria:
```task
id: RREG-WP-0008-T03
status: in_progress
status: done
priority: high
state_hub_task_id: "29a85e0a-7203-484c-aa5d-94096ab695a9"
```
@@ -115,7 +115,7 @@ Acceptance criteria:
```task
id: RREG-WP-0008-T05
status: in_progress
status: done
priority: medium
state_hub_task_id: "02147d64-d339-40e2-b88d-406567bfa366"
```