feat(release): parse_release returns (ParsedRelease, ParseReport)
Wire the scoring foundations into the parser entry point. parse_release now returns a tuple — the structural ParsedRelease and a diagnostic ParseReport carrying confidence (0-100), road (EASY / SHITTY / PATH_OF_PAIN), the residual UNKNOWN tokens, and the list of critical fields that couldn't be filled. EASY is decided structurally (a group schema matched), independently of the score. SHITTY vs PATH_OF_PAIN is decided by score against the 60 cutoff from scoring.yaml. Malformed names (forbidden chars) emit a zero-confidence PoP report and short-circuit to parse_path=AI as before. ParsePath stays as-is (DIRECT / SANITIZED / AI) — it records *how* we tokenized, not how confident we are. The two dimensions are now properly separated. Call sites propagated: - alfred/application/filesystem/resolve_destination.py (4 occurrences) - alfred/agent/tools/filesystem.py - tests/domain/test_release.py - tests/domain/test_release_fixtures.py - tests/application/test_detect_media_type.py New tests/domain/release/test_parser_v2_scoring.py (22 cases) locks ParseReport validation, compute_score arithmetic, decide_road thresholding, the collector helpers, and the end-to-end tuple contract.
This commit is contained in:
@@ -42,9 +42,10 @@ def test_parse_matches_fixture(fixture: ReleaseFixture, tmp_path) -> None:
|
||||
# plausible filesystem paths. Catches typos / missing leading dirs early.
|
||||
fixture.materialize(tmp_path)
|
||||
|
||||
result = asdict(parse_release(fixture.release_name, _KB))
|
||||
parsed, _report = parse_release(fixture.release_name, _KB)
|
||||
result = asdict(parsed)
|
||||
# ``is_season_pack`` is a @property — asdict() does not include it.
|
||||
result["is_season_pack"] = parse_release(fixture.release_name, _KB).is_season_pack
|
||||
result["is_season_pack"] = parsed.is_season_pack
|
||||
|
||||
for field, expected in fixture.expected_parsed.items():
|
||||
assert field in result, (
|
||||
|
||||
Reference in New Issue
Block a user