generated from coulomb/repo-seed
Towards systematic evidence
This commit is contained in:
@@ -537,8 +537,9 @@ def repository_detail(
|
||||
<tbody>{run_rows or '<tr><td colspan="5" class="muted">No runs yet.</td></tr>'}</tbody>
|
||||
</table>
|
||||
</section>
|
||||
<section class="panel">
|
||||
<h2>Approved Ability Map</h2>
|
||||
<section class="stack">
|
||||
<div class="panel">
|
||||
<h2>Approved Characteristics</h2>
|
||||
{render_graph_counts(
|
||||
asdict(ability_map),
|
||||
facts_count=None,
|
||||
@@ -548,13 +549,19 @@ def repository_detail(
|
||||
),
|
||||
)}
|
||||
{render_approved_registry_actions(repository_id, asdict(ability_map))}
|
||||
</div>
|
||||
<div class="panel">
|
||||
<h2>Latest Candidate Graph</h2>
|
||||
{render_latest_candidate_counts(repository_id, latest_candidate, service)}
|
||||
</div>
|
||||
<div class="panel">
|
||||
<h2>Approved Characteristic Tree</h2>
|
||||
{render_ability_map(asdict(ability_map), repository_id)}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<section class="panel" style="margin-top:18px">
|
||||
<h2>Manual Registry Entry</h2>
|
||||
<h2>Manual Characteristic Tuning</h2>
|
||||
<div class="grid">
|
||||
<form class="stack" method="post" action="/ui/repos/{repository_id}/abilities">
|
||||
<h3>Add Ability</h3>
|
||||
@@ -583,12 +590,12 @@ def repository_detail(
|
||||
<button type="submit">Add Feature</button>
|
||||
</form>
|
||||
<form class="stack" method="post" action="/ui/repos/{repository_id}/evidence">
|
||||
<h3>Add Evidence</h3>
|
||||
<label>Capability ID <input name="capability_id" type="number" min="1" required></label>
|
||||
<label>Type <input name="type" required></label>
|
||||
<label>Reference <input name="reference" required></label>
|
||||
<h3>Add Capability Support</h3>
|
||||
<label>Supported capability ID <input name="capability_id" type="number" min="1" required></label>
|
||||
<label>Support type <input name="type" placeholder="fact, documentation, test, example, feature" required></label>
|
||||
<label>Reference <input name="reference" placeholder="Observed fact, file, or lower-level characteristic" required></label>
|
||||
<label>Strength <input name="strength" value="medium" required></label>
|
||||
<button type="submit">Add Evidence</button>
|
||||
<button type="submit">Add Support</button>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
@@ -1850,7 +1857,7 @@ def render_latest_candidate_counts(
|
||||
analysis_run_id, candidate_graph = latest_candidate
|
||||
facts_count = len(service.list_observed_facts(repository_id, analysis_run_id))
|
||||
return render_graph_counts(
|
||||
asdict(candidate_graph),
|
||||
active_candidate_graph(asdict(candidate_graph)),
|
||||
facts_count=facts_count,
|
||||
label_prefix="candidate",
|
||||
base_href=(
|
||||
@@ -1865,6 +1872,39 @@ def render_latest_candidate_counts(
|
||||
)
|
||||
|
||||
|
||||
def active_candidate_graph(graph: dict) -> dict:
|
||||
active_abilities = []
|
||||
for ability in graph.get("abilities", []):
|
||||
active_capabilities = []
|
||||
for capability in ability.get("capabilities", []):
|
||||
active_features = [
|
||||
feature
|
||||
for feature in capability.get("features", [])
|
||||
if feature.get("status", "candidate") != "rejected"
|
||||
]
|
||||
active_evidence = [
|
||||
evidence
|
||||
for evidence in capability.get("evidence", [])
|
||||
if evidence.get("status", "candidate") != "rejected"
|
||||
]
|
||||
capability_active = (
|
||||
capability.get("status", "candidate") != "rejected"
|
||||
and (active_features or active_evidence)
|
||||
)
|
||||
if capability_active:
|
||||
active_capability = {**capability}
|
||||
active_capability["features"] = active_features
|
||||
active_capability["evidence"] = active_evidence
|
||||
active_capabilities.append(active_capability)
|
||||
if ability.get("status", "candidate") != "rejected" and active_capabilities:
|
||||
active_ability = {**ability}
|
||||
active_ability["capabilities"] = active_capabilities
|
||||
active_abilities.append(active_ability)
|
||||
active_graph = {**graph}
|
||||
active_graph["abilities"] = active_abilities
|
||||
return active_graph
|
||||
|
||||
|
||||
def render_graph_counts(
|
||||
graph: dict,
|
||||
facts_count: int | None = None,
|
||||
@@ -2639,6 +2679,10 @@ def render_ability_map(ability_map: dict, repository_id: int) -> str:
|
||||
abilities = ability_map.get("abilities", [])
|
||||
if not abilities:
|
||||
return '<p class="muted">No approved entries yet.</p>'
|
||||
repository = ability_map["repository"]
|
||||
scope_description = repository.get("description") or (
|
||||
f"Scope root for the approved characteristics of {repository['name']}."
|
||||
)
|
||||
items = []
|
||||
for ability in abilities:
|
||||
capabilities = []
|
||||
@@ -2659,7 +2703,10 @@ def render_ability_map(ability_map: dict, repository_id: int) -> str:
|
||||
<span class="pill">{capability['confidence']:.2f} {escape(capability['confidence_label'])}</span>
|
||||
<p class="muted">{escape(capability['description'])}</p>
|
||||
{render_approved_capability_forms(capability, repository_id)}
|
||||
<ul>{features}{evidence}</ul>
|
||||
<h3>Features</h3>
|
||||
<ul>{features or '<li class="muted">No approved features.</li>'}</ul>
|
||||
<h3>Evidence supporting this capability</h3>
|
||||
<ul>{evidence or '<li class="muted">No support evidence yet.</li>'}</ul>
|
||||
</li>
|
||||
"""
|
||||
)
|
||||
@@ -2675,7 +2722,18 @@ def render_ability_map(ability_map: dict, repository_id: int) -> str:
|
||||
</li>
|
||||
"""
|
||||
)
|
||||
return f'<div class="tree"><ul>{"".join(items)}</ul></div>'
|
||||
return f"""
|
||||
<div class="tree">
|
||||
<ul>
|
||||
<li id="scope-{repository['id']}">
|
||||
<strong>{escape(repository['name'])}</strong>
|
||||
<span class="pill">scope</span>
|
||||
<p class="muted">{escape(scope_description)}</p>
|
||||
<ul>{"".join(items)}</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
"""
|
||||
|
||||
|
||||
def render_approved_ability_forms(ability: dict, repository_id: int) -> str:
|
||||
@@ -2739,18 +2797,18 @@ def render_approved_feature(feature: dict, repository_id: int) -> str:
|
||||
def render_approved_evidence(evidence: dict, repository_id: int) -> str:
|
||||
return f"""
|
||||
<li>
|
||||
{escape(evidence["type"])}
|
||||
<strong>{escape(evidence["type"])}</strong>
|
||||
<span class="pill">{escape(evidence["strength"])}</span>
|
||||
<span class="source">{escape(evidence["reference"])}</span>
|
||||
{render_sources(evidence.get("source_refs", []))}
|
||||
<form class="stack" method="post" action="/ui/repos/{repository_id}/evidence/{evidence['id']}/edit">
|
||||
<label>Type <input name="type" value="{escape(evidence['type'])}" required></label>
|
||||
<label>Support type <input name="type" value="{escape(evidence['type'])}" required></label>
|
||||
<label>Reference <input name="reference" value="{escape(evidence['reference'])}" required></label>
|
||||
<label>Strength <input name="strength" value="{escape(evidence['strength'])}" required></label>
|
||||
<button class="secondary" type="submit">Save Evidence</button>
|
||||
<button class="secondary" type="submit">Save Support</button>
|
||||
</form>
|
||||
<form method="post" action="/ui/repos/{repository_id}/evidence/{evidence['id']}/delete">
|
||||
<button class="secondary" type="submit">Delete Evidence</button>
|
||||
<button class="secondary" type="submit">Delete Support</button>
|
||||
</form>
|
||||
</li>
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user