Implement Pruning of Filled Steps from Roadmap Unfilled
All checks were successful
Deploy Development / deploy (push) Successful in 41s
Test Suite / pytest-backend (push) Successful in 44s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 22s
Test Suite / k6 /health Baseline (push) Successful in 34s
Test Suite / playwright-tests (push) Successful in 1m13s

- Introduced `_prune_filled_from_roadmap_unfilled` function to remove steps with filled exercises from the unfilled roadmap, preventing outdated references.
- Updated `_run_roadmap_rematch_loop` to incorporate the new pruning logic, ensuring only relevant unfilled steps are retained during rematching.
- Added tests for the pruning function to validate its behavior with various step scenarios.
- Bumped version to 0.8.232 to reflect the new functionality and improvements.
This commit is contained in:
Lars 2026-06-12 08:27:39 +02:00
parent 63c99b0ec5
commit a4e73c830f
3 changed files with 42 additions and 2 deletions

View File

@ -1518,6 +1518,31 @@ def _merge_rematch_unfilled(
return kept return kept
def _prune_filled_from_roadmap_unfilled(
steps: Sequence[Mapping[str, Any]],
roadmap_unfilled: List[Tuple[int, StageSpecArtifact]],
) -> List[Tuple[int, StageSpecArtifact]]:
"""Entfernt Stufen mit Bibliotheks-Treffer — verhindert veraltete roadmap_unfilled-Hinweise."""
filled_majors: Set[int] = set()
for raw in steps:
if raw.get("exercise_id") is None:
continue
midx = raw.get("roadmap_major_step_index")
if midx is None:
continue
try:
filled_majors.add(int(midx))
except (TypeError, ValueError):
continue
if not filled_majors:
return roadmap_unfilled
return [
item
for item in roadmap_unfilled
if int(item[1].major_step_index) not in filled_majors
]
def _run_roadmap_rematch_loop( def _run_roadmap_rematch_loop(
cur, cur,
*, *,
@ -1683,6 +1708,7 @@ def _run_roadmap_rematch_loop(
current_stripped = prune_stripped_after_rematch(current_stripped, round_log) current_stripped = prune_stripped_after_rematch(current_stripped, round_log)
roadmap_unfilled = _merge_rematch_unfilled(roadmap_unfilled, rematch_new_unfilled) roadmap_unfilled = _merge_rematch_unfilled(roadmap_unfilled, rematch_new_unfilled)
roadmap_unfilled = _prune_filled_from_roadmap_unfilled(steps, roadmap_unfilled)
use_initial_off_topic = False use_initial_off_topic = False
off_topic_steps = detect_off_topic_steps( off_topic_steps = detect_off_topic_steps(
@ -1721,6 +1747,8 @@ def _run_roadmap_rematch_loop(
goal_query=goal_query, goal_query=goal_query,
) )
roadmap_unfilled = _prune_filled_from_roadmap_unfilled(steps, roadmap_unfilled)
return ( return (
steps, steps,
rematch_log, rematch_log,

View File

@ -223,3 +223,15 @@ def test_rematch_unfilled_leaves_placeholder_step():
assert slot1["roadmap_match_source"] == "unfilled" assert slot1["roadmap_match_source"] == "unfilled"
assert log[0]["action"] == "rematch_unfilled" assert log[0]["action"] == "rematch_unfilled"
assert len(unfilled) == 1 assert len(unfilled) == 1
def test_prune_filled_from_roadmap_unfilled():
from planning_exercise_path_builder import _prune_filled_from_roadmap_unfilled
spec = StageSpecArtifact(major_step_index=5, learning_goal="Zielgenauigkeit")
steps = [{"exercise_id": 99, "roadmap_major_step_index": 5}]
kept = _prune_filled_from_roadmap_unfilled(steps, [(4, spec)])
assert kept == []
unfilled_steps = [{"exercise_id": None, "roadmap_major_step_index": 5}]
kept2 = _prune_filled_from_roadmap_unfilled(unfilled_steps, [(4, spec)])
assert len(kept2) == 1

View File

@ -1,6 +1,6 @@
# Shinkan Jinkendo Version Information # Shinkan Jinkendo Version Information
APP_VERSION = "0.8.231" APP_VERSION = "0.8.232"
BUILD_DATE = "2026-05-22" BUILD_DATE = "2026-05-22"
DB_SCHEMA_VERSION = "20260607090" DB_SCHEMA_VERSION = "20260607090"
@ -38,7 +38,7 @@ MODULE_VERSIONS = {
"skill_profiles": "1.0.0", # Phase 3: gewichtetes Fähigkeiten-Profil + skill-discovery/suggestions "skill_profiles": "1.0.0", # Phase 3: gewichtetes Fähigkeiten-Profil + skill-discovery/suggestions
"methods": "0.1.0", "methods": "0.1.0",
"exercises": "2.37.1", # KI-Endpoints: feature_usage nach ai_calls consume "exercises": "2.37.1", # KI-Endpoints: feature_usage nach ai_calls consume
"planning_exercise_suggest": "0.23.6", # Gap-Angebote nach Rematch; LLM-QA auf finalem Pfad; Post-Match-Gate "planning_exercise_suggest": "0.23.7", # roadmap_unfilled nach Rematch-Treffer bereinigen
"training_units": "0.4.0", # POST .../publish-to-framework: Ablauf aus geplanter Einheit → Rahmen-Slot-Blueprint "training_units": "0.4.0", # POST .../publish-to-framework: Ablauf aus geplanter Einheit → Rahmen-Slot-Blueprint
"training_programs": "0.1.0", "training_programs": "0.1.0",
"planning": "0.15.0", # Vorlagen: Strukturvorschau, Bearbeiten inkl. Split-Sessions + Beschreibung "planning": "0.15.0", # Vorlagen: Strukturvorschau, Bearbeiten inkl. Split-Sessions + Beschreibung