compass-kb-validation 2.2.0__tar.gz → 2.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/PKG-INFO +1 -1
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/compass_kb_validation.egg-info/PKG-INFO +1 -1
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/discover_and_validate.py +44 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/__init__.py +1 -1
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/profiler.py +73 -1
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/report/__init__.py +7 -2
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_discover_cli.py +46 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_reporting.py +15 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/LICENSE +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/README.md +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/compass_kb_validation.egg-info/SOURCES.txt +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/compass_kb_validation.egg-info/dependency_links.txt +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/compass_kb_validation.egg-info/entry_points.txt +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/compass_kb_validation.egg-info/requires.txt +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/compass_kb_validation.egg-info/top_level.txt +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/__main__.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/ask.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/baseline.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/chunk_coherence.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/cli.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/config/__init__.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/config_lint.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/content_inspect.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/corpus.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/corpus_health.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/diagnostics.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/embedding_drift.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/eval_interop.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/init_wizard.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/live_dashboard.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/mcp_server.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/models/__init__.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/notifications.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/pipeline/__init__.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/provenance.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/providers/__init__.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/providers/embedding.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/providers/graph.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/providers/source.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/providers/storage.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/providers/vectorstore.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/remediation.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/report/_report_css.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/report/_report_js.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/report/analysis.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/report/export.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/report/shell.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/retrieval_analysis.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/trend_tracker.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/utils/__init__.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/validators/__init__.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/validators/api_upload.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/validators/base.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/validators/base_sparql.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/validators/cross_stage.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/validators/graphdb_metadata.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/validators/neptune_metadata.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/validators/redis_chunks.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/validators/registry.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/validators/retrieval_quality.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/validators/s3_storage.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/profile_kb.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/pyproject.toml +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/run_validation.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/setup.cfg +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_alt_adapters.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_analysis_report.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_api_upload.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_ask.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_baseline.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_benchmark.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_check_catalog.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_cli.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_config.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_config_lint.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_content_inspect.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_corpus.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_corpus_health.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_coverage.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_cross_stage.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_diagnostics.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_discovery_parallel.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_embedding_drift.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_eval_interop.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_gate.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_graph_transport.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_graph_validators.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_init_wizard.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_manifest.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_mcp.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_migration.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_models.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_neptune_bugfixes.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_neptune_bugfixes2.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_notifications.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_pipeline.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_profiler.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_providers.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_redis_chunks.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_registry.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_remediation.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_retrieval_assertions.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_retrieval_quality.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_run_cli.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_sources.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_storage_validator.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_trends.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_universal_concerns.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_utils.py +0 -0
- {compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_vectorstore_filters.py +0 -0
|
@@ -67,6 +67,12 @@ def parse_args(argv=None) -> argparse.Namespace:
|
|
|
67
67
|
help="Also fail unless the KB Hygiene score is >= PCT (0-100). Hygiene is "
|
|
68
68
|
"the share of advisory data-quality checks that passed - data-plane "
|
|
69
69
|
"cleanliness, separate from the READY integrity gate.")
|
|
70
|
+
p.add_argument("--suggest-config", nargs="?", const="-", metavar="PATH",
|
|
71
|
+
help="After the run, emit config refinements from what it observed "
|
|
72
|
+
"(document count, chunk-size distribution, checks that never applied). "
|
|
73
|
+
"Prints to stdout, or writes to PATH. Review before merging.")
|
|
74
|
+
p.add_argument("--no-tips", action="store_true",
|
|
75
|
+
help="Suppress the end-of-run tips about relevant unused flags.")
|
|
70
76
|
# --- config overrides (run scenarios without editing YAML; CLI wins over config) ---
|
|
71
77
|
p.add_argument("--readiness-threshold", type=float, metavar="FRAC",
|
|
72
78
|
help="Override corpus readiness cutoff (0-1). READY when pass-rate >= this.")
|
|
@@ -240,6 +246,32 @@ _AUTH_HINTS = ("403", "forbidden", "expired", "credential", "token", "signatured
|
|
|
240
246
|
"invalidclienttokenid", "accessdenied", "unauthor")
|
|
241
247
|
|
|
242
248
|
|
|
249
|
+
def _print_tips(args, hygiene: dict | None, saved_baseline: bool) -> None:
|
|
250
|
+
"""End-of-run hints about the most relevant unused flags.
|
|
251
|
+
|
|
252
|
+
Discoverability, not noise: at most three, only when the flag was NOT already used and
|
|
253
|
+
the run's own outcome makes it relevant. Suppress with --no-tips. This is why a partner
|
|
254
|
+
can run for weeks without finding --save-baseline / --unreachable-as / --suggest-config.
|
|
255
|
+
"""
|
|
256
|
+
tips: list[str] = []
|
|
257
|
+
if not saved_baseline:
|
|
258
|
+
tips.append("Save this run as a baseline to catch regressions next time: "
|
|
259
|
+
"--save-baseline baselines/{}.json".format(args.project or "kb"))
|
|
260
|
+
if hygiene and hygiene.get("score", 100) < 90 and args.quality_threshold is None:
|
|
261
|
+
tips.append("Gate CI on data-plane hygiene (not just integrity): "
|
|
262
|
+
"--quality-threshold {}".format(int(hygiene["score"])))
|
|
263
|
+
if not getattr(args, "include_retrieval", False):
|
|
264
|
+
tips.append("Add retrieval-quality checks (can a stored vector be found via KNN?): "
|
|
265
|
+
"--include-retrieval")
|
|
266
|
+
if not args.suggest_config:
|
|
267
|
+
tips.append("Refine your config from what this run observed: --suggest-config")
|
|
268
|
+
if not tips:
|
|
269
|
+
return
|
|
270
|
+
print("\n Tips (--no-tips to silence):")
|
|
271
|
+
for t in tips[:3]:
|
|
272
|
+
print(f" * {t}")
|
|
273
|
+
|
|
274
|
+
|
|
243
275
|
def _resolve_expected_documents(raw, project: str):
|
|
244
276
|
"""Resolve the configured expected_documents, supporting ``auto``.
|
|
245
277
|
|
|
@@ -502,6 +534,16 @@ def main(argv=None) -> int:
|
|
|
502
534
|
if args.output_format in ("junit", "all"):
|
|
503
535
|
print(f" JUnit report: {export_junit(results, base + '.xml')}")
|
|
504
536
|
|
|
537
|
+
if args.suggest_config:
|
|
538
|
+
from ingestion_validation.profiler import suggest_config_from_run
|
|
539
|
+
snippet = suggest_config_from_run(results, documents)
|
|
540
|
+
if args.suggest_config == "-":
|
|
541
|
+
print("\n" + snippet)
|
|
542
|
+
else:
|
|
543
|
+
from pathlib import Path as _P
|
|
544
|
+
_P(args.suggest_config).write_text(snippet, encoding="utf-8")
|
|
545
|
+
print(f" Config suggestions written: {args.suggest_config} (review before merging)")
|
|
546
|
+
|
|
505
547
|
# KB Hygiene: data-plane cleanliness (advisory checks), separate from the integrity
|
|
506
548
|
# gate. Printed for every run; gates the build only when --quality-threshold is set.
|
|
507
549
|
# Best-effort context - a failure to score it must not crash the gate decision.
|
|
@@ -539,6 +581,8 @@ def main(argv=None) -> int:
|
|
|
539
581
|
reason = f"{len(documents)} documents < s3.min_documents ({min_docs})"
|
|
540
582
|
failed_gate = True
|
|
541
583
|
code = EXIT_GATE_FAILED if (failed_gate or (regression and args.fail_on_regression)) else EXIT_OK
|
|
584
|
+
if not args.no_tips:
|
|
585
|
+
_print_tips(args, hygiene, saved_baseline=args.save_baseline is not None or bool(args.against))
|
|
542
586
|
print("=" * 60)
|
|
543
587
|
print(f" Results: {passed} passed, {failed} failed ({len(results)} total)")
|
|
544
588
|
print(f" Gate: {'FAILED' if failed_gate else 'PASSED'} - {reason}")
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/profiler.py
RENAMED
|
@@ -537,7 +537,79 @@ def apply_profile_to_settings(settings: Any, profiles: dict) -> list[str]:
|
|
|
537
537
|
return applied
|
|
538
538
|
|
|
539
539
|
|
|
540
|
+
def suggest_config_from_run(results: list, documents: list) -> str:
|
|
541
|
+
"""Suggest config refinements from what a validation RUN actually observed.
|
|
542
|
+
|
|
543
|
+
Complements ``emit_project_config`` (pre-run backend introspection) with the things
|
|
544
|
+
only a run reveals: the real document count, the observed chunk-size distribution, and
|
|
545
|
+
the checks that were NEUTRAL on every document - checks that never apply to this KB and
|
|
546
|
+
are pure noise (e.g. section_metadata when nothing carries sections). Returns a review-
|
|
547
|
+
and-merge snippet, never a file to apply blind - a wrong config key would be exactly the
|
|
548
|
+
silent-failure trap COMPASS exists to catch, so these are suggestions with the evidence.
|
|
549
|
+
"""
|
|
550
|
+
import statistics
|
|
551
|
+
|
|
552
|
+
n_docs = len(documents)
|
|
553
|
+
avg_chars: list[int] = []
|
|
554
|
+
# label -> [evaluated_count, neutral_count]; a check neutral everywhere never applies.
|
|
555
|
+
support: dict[str, list[int]] = {}
|
|
556
|
+
for item in results:
|
|
557
|
+
for st in getattr(item.get("result"), "steps", []) or []:
|
|
558
|
+
details = getattr(st, "details", {}) or {}
|
|
559
|
+
cv = details.get("chunk_view")
|
|
560
|
+
if isinstance(cv, dict) and cv.get("avg_chars"):
|
|
561
|
+
avg_chars.append(int(cv["avg_chars"]))
|
|
562
|
+
status = getattr(getattr(st, "status", None), "value", "")
|
|
563
|
+
if status == "SKIPPED":
|
|
564
|
+
continue # a step that did not run says nothing about applicability
|
|
565
|
+
for ch in getattr(st, "checks", []) or []:
|
|
566
|
+
lbl = ch.get("label", "")
|
|
567
|
+
if not lbl:
|
|
568
|
+
continue
|
|
569
|
+
rec = support.setdefault(lbl, [0, 0])
|
|
570
|
+
if ch.get("supported", True) is False:
|
|
571
|
+
rec[1] += 1
|
|
572
|
+
else:
|
|
573
|
+
rec[0] += 1
|
|
574
|
+
|
|
575
|
+
never_applies = sorted(lbl for lbl, (ev, neu) in support.items() if ev == 0 and neu > 0)
|
|
576
|
+
|
|
577
|
+
lines = [
|
|
578
|
+
"# --- compass discover --suggest-config -------------------------------------",
|
|
579
|
+
"# Refinements from THIS run's observations. Review each, then merge into your",
|
|
580
|
+
"# project YAML - nothing here is applied automatically.",
|
|
581
|
+
"",
|
|
582
|
+
"# Documents discovered this run. Pin it to alert on drift (or use 'auto' to",
|
|
583
|
+
"# baseline against the previous run automatically):",
|
|
584
|
+
"discovery:",
|
|
585
|
+
" extra:",
|
|
586
|
+
f" expected_documents: {n_docs}",
|
|
587
|
+
]
|
|
588
|
+
if avg_chars:
|
|
589
|
+
median_size = int(statistics.median(avg_chars))
|
|
590
|
+
lines += [
|
|
591
|
+
"",
|
|
592
|
+
f"# Observed chunk size: median {median_size} chars across {len(avg_chars)} document(s)",
|
|
593
|
+
f"# (range {min(avg_chars)}-{max(avg_chars)}). Set expected bounds if you gate on size:",
|
|
594
|
+
"# redis:",
|
|
595
|
+
f"# chunk_size: {median_size}",
|
|
596
|
+
]
|
|
597
|
+
if never_applies:
|
|
598
|
+
lines += [
|
|
599
|
+
"",
|
|
600
|
+
"# These checks were NOT APPLICABLE to any document this run (neutral every time) -",
|
|
601
|
+
"# the backend/data cannot answer them. Disabling removes them from the tally and",
|
|
602
|
+
"# the report noise. Verify each is genuinely irrelevant before disabling:",
|
|
603
|
+
]
|
|
604
|
+
for lbl in never_applies:
|
|
605
|
+
lines.append(f"# - {lbl}")
|
|
606
|
+
else:
|
|
607
|
+
lines += ["", "# Every check applied to at least one document - nothing to disable."]
|
|
608
|
+
return "\n".join(lines) + "\n"
|
|
609
|
+
|
|
610
|
+
|
|
540
611
|
__all__ = [
|
|
541
612
|
"profile_vectorstore", "profile_storage", "profile_graph", "profile_kb",
|
|
542
|
-
"apply_profile_to_settings", "suggest_config",
|
|
613
|
+
"apply_profile_to_settings", "suggest_config", "emit_project_config",
|
|
614
|
+
"suggest_config_from_run",
|
|
543
615
|
]
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/report/__init__.py
RENAMED
|
@@ -224,9 +224,14 @@ def _result_payload(name: str, r: PipelineResult) -> dict:
|
|
|
224
224
|
continue
|
|
225
225
|
order.append(s.step_name)
|
|
226
226
|
metrics = {k: v for k, v in s.details.items() if k not in ("screenshot", "chunk_view", "rdf_triples") and isinstance(v, (int, float, str))}
|
|
227
|
-
# Graph metadata steps export RDF triples for the knowledge-graph view
|
|
227
|
+
# Graph metadata steps export RDF triples for the knowledge-graph view, which
|
|
228
|
+
# renders ONLY predicate + value. The raw triples also carry `subject` and
|
|
229
|
+
# `predicate_uri` - both full IRIs, repeated on every triple - that nothing reads;
|
|
230
|
+
# they were ~83% of a graph-heavy report's payload. Keep only the rendered fields.
|
|
228
231
|
raw_triples = s.details.get("rdf_triples")
|
|
229
|
-
triples =
|
|
232
|
+
triples = ([{"predicate": t.get("predicate", ""), "value": t.get("value", "")}
|
|
233
|
+
for t in raw_triples[:_KG_TRIPLE_CAP]]
|
|
234
|
+
if isinstance(raw_triples, list) and raw_triples else None)
|
|
230
235
|
# Attach a remediation hint to each failed, evaluable check (advisory only).
|
|
231
236
|
checks_out = [
|
|
232
237
|
({**c, "hint": hint_for(c.get("label", ""))}
|
|
@@ -144,3 +144,49 @@ def test_quality_threshold_gates_on_hygiene():
|
|
|
144
144
|
assert not ok
|
|
145
145
|
# no threshold set -> hygiene never gates
|
|
146
146
|
assert not dav.gate_failed(10, 10, "READY", None, False, hygiene_score=10.0)[0]
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def _run_case(name, avg_chars, section_supported):
|
|
150
|
+
from ingestion_validation.models import PipelineResult, StepResult, StepStatus
|
|
151
|
+
r = PipelineResult(document_id=name, file_name=f"{name}.pdf")
|
|
152
|
+
checks = [{"label": "Chunks exist", "passed": True},
|
|
153
|
+
{"label": "Section metadata present", "passed": False, "supported": section_supported}]
|
|
154
|
+
r.add_step(StepResult("Redis Chunks", StepStatus.PASSED, "ok", checks=checks,
|
|
155
|
+
details={"chunk_view": {"count": 10, "total_chars": avg_chars * 10, "avg_chars": avg_chars}}))
|
|
156
|
+
r.finalize()
|
|
157
|
+
return {"name": name, "result": r}
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def test_suggest_config_from_run_reports_count_size_and_dead_checks():
|
|
161
|
+
from ingestion_validation.profiler import suggest_config_from_run
|
|
162
|
+
docs = [{"file_name": f"d{i}.pdf"} for i in range(12)]
|
|
163
|
+
# section metadata is neutral (unsupported) on every doc -> flagged as never-applicable
|
|
164
|
+
results = [_run_case(f"d{i}", 800 + i * 20, section_supported=False) for i in range(12)]
|
|
165
|
+
out = suggest_config_from_run(results, docs)
|
|
166
|
+
assert "expected_documents: 12" in out
|
|
167
|
+
assert "median 910 chars" in out # observed size distribution
|
|
168
|
+
assert "Section metadata present" in out # dead check surfaced for disabling
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def test_suggest_config_does_not_flag_a_check_that_applied_somewhere():
|
|
172
|
+
from ingestion_validation.profiler import suggest_config_from_run
|
|
173
|
+
docs = [{"file_name": "d0.pdf"}, {"file_name": "d1.pdf"}]
|
|
174
|
+
# section metadata is supported (applies) on d1 -> must NOT be suggested for disabling
|
|
175
|
+
results = [_run_case("d0", 900, section_supported=False),
|
|
176
|
+
_run_case("d1", 900, section_supported=True)]
|
|
177
|
+
out = suggest_config_from_run(results, docs)
|
|
178
|
+
assert "Section metadata present" not in out
|
|
179
|
+
assert "nothing to disable" in out
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def test_post_run_tips_are_contextual_and_suppressible(capsys):
|
|
183
|
+
class _A:
|
|
184
|
+
project = "wp-kb"; quality_threshold = None; include_retrieval = False; suggest_config = None
|
|
185
|
+
dav._print_tips(_A(), {"score": 56.1, "tier": "POOR"}, saved_baseline=False)
|
|
186
|
+
out = capsys.readouterr().out
|
|
187
|
+
assert "--save-baseline" in out and "--quality-threshold 56" in out and "--include-retrieval" in out
|
|
188
|
+
|
|
189
|
+
class _B:
|
|
190
|
+
project = "wp-kb"; quality_threshold = 80; include_retrieval = True; suggest_config = "-"
|
|
191
|
+
dav._print_tips(_B(), {"score": 98}, saved_baseline=True) # everything used, clean run
|
|
192
|
+
assert capsys.readouterr().out == "" # -> no tips
|
|
@@ -545,3 +545,18 @@ def test_hygiene_gauge_shows_score_and_worst_beside_the_verdict():
|
|
|
545
545
|
assert "KB Hygiene" in gauge and "POOR" in gauge
|
|
546
546
|
assert "worst:" in gauge and "Chunk Structure" in gauge
|
|
547
547
|
assert report_mod._hygiene_gauge(None) == "" # no advisory -> no gauge
|
|
548
|
+
|
|
549
|
+
|
|
550
|
+
def test_embedded_triples_keep_only_rendered_fields():
|
|
551
|
+
# The KG view renders predicate + value only; subject and predicate_uri (full IRIs,
|
|
552
|
+
# repeated per triple) were ~83% of a graph-heavy payload and are never read.
|
|
553
|
+
r = PipelineResult(document_id="d", file_name="d.pdf")
|
|
554
|
+
r.add_step(StepResult("Neptune Metadata", StepStatus.PASSED, "ok",
|
|
555
|
+
checks=[{"label": "Found", "passed": True}],
|
|
556
|
+
details={"rdf_triples": [
|
|
557
|
+
{"subject": "http://ns/doc/1", "predicate": "documentId",
|
|
558
|
+
"predicate_uri": "http://ns/documentId", "value": "DOC-1"}]}))
|
|
559
|
+
r.finalize()
|
|
560
|
+
triples = report_mod._result_payload("d.pdf", r)["steps"]["Neptune Metadata"]["triples"]
|
|
561
|
+
assert triples == [{"predicate": "documentId", "value": "DOC-1"}]
|
|
562
|
+
assert "subject" not in triples[0] and "predicate_uri" not in triples[0]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/__main__.py
RENAMED
|
File without changes
|
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/baseline.py
RENAMED
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/chunk_coherence.py
RENAMED
|
File without changes
|
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/config/__init__.py
RENAMED
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/config_lint.py
RENAMED
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/content_inspect.py
RENAMED
|
File without changes
|
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/corpus_health.py
RENAMED
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/diagnostics.py
RENAMED
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/embedding_drift.py
RENAMED
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/eval_interop.py
RENAMED
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/init_wizard.py
RENAMED
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/live_dashboard.py
RENAMED
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/mcp_server.py
RENAMED
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/models/__init__.py
RENAMED
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/notifications.py
RENAMED
|
File without changes
|
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/provenance.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/providers/graph.py
RENAMED
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/providers/source.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/remediation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/report/analysis.py
RENAMED
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/report/export.py
RENAMED
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/report/shell.py
RENAMED
|
File without changes
|
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/trend_tracker.py
RENAMED
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/utils/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/ingestion_validation/validators/base.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_discovery_parallel.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_retrieval_assertions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_universal_concerns.py
RENAMED
|
File without changes
|
|
File without changes
|
{compass_kb_validation-2.2.0 → compass_kb_validation-2.3.0}/tests/test_vectorstore_filters.py
RENAMED
|
File without changes
|