generated from coulomb/repo-seed
Orientation labels for support/evidence
This commit is contained in:
@@ -2232,6 +2232,7 @@ def filter_element_rows(
|
|||||||
str(row.get("target_id", "")),
|
str(row.get("target_id", "")),
|
||||||
str(row.get("reference_kind", "")),
|
str(row.get("reference_kind", "")),
|
||||||
str(row.get("reference_id", "")),
|
str(row.get("reference_id", "")),
|
||||||
|
support_orientation_label(row),
|
||||||
source_refs_text(row["source_refs"]),
|
source_refs_text(row["source_refs"]),
|
||||||
]
|
]
|
||||||
).lower()
|
).lower()
|
||||||
@@ -2291,11 +2292,45 @@ def render_element_source_detail(row: dict) -> str:
|
|||||||
return (
|
return (
|
||||||
f'<p><span class="pill">supports {target}{f" #{target_id}" if target_id else ""}</span>'
|
f'<p><span class="pill">supports {target}{f" #{target_id}" if target_id else ""}</span>'
|
||||||
f' <span class="pill">references {reference_kind}{f" #{reference_id}" if reference_id else ""}</span></p>'
|
f' <span class="pill">references {reference_kind}{f" #{reference_id}" if reference_id else ""}</span></p>'
|
||||||
|
f'<p>{render_support_orientation(row)}</p>'
|
||||||
f'{render_sources(row["source_refs"])}'
|
f'{render_sources(row["source_refs"])}'
|
||||||
)
|
)
|
||||||
return render_sources(row["source_refs"])
|
return render_sources(row["source_refs"])
|
||||||
|
|
||||||
|
|
||||||
|
def support_orientation_label(row: dict) -> str:
|
||||||
|
if row.get("item_kind") != "evidence":
|
||||||
|
return ""
|
||||||
|
target_kind = str(row.get("target_kind") or "capability")
|
||||||
|
reference_kind = str(row.get("reference_kind") or "source")
|
||||||
|
levels = {
|
||||||
|
"scope": 0,
|
||||||
|
"ability": 1,
|
||||||
|
"capability": 2,
|
||||||
|
"feature": 3,
|
||||||
|
"fact": 4,
|
||||||
|
"source": 4,
|
||||||
|
"content": 4,
|
||||||
|
"chunk": 4,
|
||||||
|
}
|
||||||
|
target_level = levels.get(target_kind)
|
||||||
|
reference_level = levels.get(reference_kind)
|
||||||
|
if target_level is None or reference_level is None:
|
||||||
|
return "unclassified support"
|
||||||
|
if reference_level > target_level:
|
||||||
|
return "downward support"
|
||||||
|
if reference_level == target_level:
|
||||||
|
return "same-level support review"
|
||||||
|
return "upward support review"
|
||||||
|
|
||||||
|
|
||||||
|
def render_support_orientation(row: dict) -> str:
|
||||||
|
label = support_orientation_label(row)
|
||||||
|
if not label:
|
||||||
|
return ""
|
||||||
|
return f'<span class="pill">{escape(label)}</span>'
|
||||||
|
|
||||||
|
|
||||||
def render_element_actions(
|
def render_element_actions(
|
||||||
row: dict,
|
row: dict,
|
||||||
repository_id: int,
|
repository_id: int,
|
||||||
@@ -3020,6 +3055,7 @@ def render_approved_evidence(evidence: dict, repository_id: int) -> str:
|
|||||||
<span class="pill">{escape(evidence["strength"])}</span>
|
<span class="pill">{escape(evidence["strength"])}</span>
|
||||||
<span class="pill">supports {target_kind}{f' #{target_id}' if target_id else ''}</span>
|
<span class="pill">supports {target_kind}{f' #{target_id}' if target_id else ''}</span>
|
||||||
<span class="pill">references {reference_kind}{f' #{reference_id}' if reference_id else ''}</span>
|
<span class="pill">references {reference_kind}{f' #{reference_id}' if reference_id else ''}</span>
|
||||||
|
{render_support_orientation(evidence | {"item_kind": "evidence"})}
|
||||||
<span class="source">{escape(evidence["reference"])}</span>
|
<span class="source">{escape(evidence["reference"])}</span>
|
||||||
{render_sources(evidence.get("source_refs", []))}
|
{render_sources(evidence.get("source_refs", []))}
|
||||||
<form class="stack" method="post" action="/ui/repos/{repository_id}/evidence/{evidence['id']}/edit">
|
<form class="stack" method="post" action="/ui/repos/{repository_id}/evidence/{evidence['id']}/edit">
|
||||||
|
|||||||
@@ -1722,6 +1722,7 @@ def test_ui_manual_registry_entry_loop(tmp_path):
|
|||||||
assert "README.md" in detail_response.text
|
assert "README.md" in detail_response.text
|
||||||
assert "supports capability" in detail_response.text
|
assert "supports capability" in detail_response.text
|
||||||
assert "references source" in detail_response.text
|
assert "references source" in detail_response.text
|
||||||
|
assert "downward support" in detail_response.text
|
||||||
assert "ID " in detail_response.text
|
assert "ID " in detail_response.text
|
||||||
assert "Save Ability" in detail_response.text
|
assert "Save Ability" in detail_response.text
|
||||||
|
|
||||||
@@ -1786,6 +1787,7 @@ def test_ui_manual_registry_entry_loop(tmp_path):
|
|||||||
assert "Edited Manual API" in detail_response.text
|
assert "Edited Manual API" in detail_response.text
|
||||||
assert "tests/test_manual.py" in detail_response.text
|
assert "tests/test_manual.py" in detail_response.text
|
||||||
assert f"references feature #{feature_id}" in detail_response.text
|
assert f"references feature #{feature_id}" in detail_response.text
|
||||||
|
assert "downward support" in detail_response.text
|
||||||
|
|
||||||
delete_feature_response = client.post(
|
delete_feature_response = client.post(
|
||||||
f"{repository_path}/features/{feature_id}/delete",
|
f"{repository_path}/features/{feature_id}/delete",
|
||||||
|
|||||||
@@ -247,3 +247,8 @@ from the UI and service layer. Accepting support promotes the parent ability and
|
|||||||
capability context as needed, records a review decision, marks the candidate
|
capability context as needed, records a review decision, marks the candidate
|
||||||
support approved, and maps capability support targets to the approved capability
|
support approved, and maps capability support targets to the approved capability
|
||||||
ID.
|
ID.
|
||||||
|
|
||||||
|
Implementation note 2026-04-29: support rows now show an orientation label based
|
||||||
|
on target/reference abstraction levels. Downward support is normal, same-level
|
||||||
|
support is marked for review, and upward support is marked for review because it
|
||||||
|
usually indicates an abstraction or organization problem.
|
||||||
|
|||||||
Reference in New Issue
Block a user