feat(pre-push-safety-net): stop declared exclusion vetoing first-party answers (M1b 10.6)

vendor_semantics_unresolved was grouped with the graph integrity failures, so any
declared exclusion demoted every otherwise complete answer in the repository to
graph_incomplete. Every real repository excludes its dependencies, so this fired
on all of them, including on a complete first-party census with successful query
receipts.

Graph boundaries are now split by what they mean. An integrity failure says the
graph could not be read or is incomplete, so an answer drawn from it is demoted:
unparsed files, an empty or sharded graph, an incomplete or unavailable census,
an unresolved symlink, an unsupported frontend, unreadable source, an ambiguous
frontend path and unvalidated TypeScript property support all keep that behavior.
A declared exclusion is a deliberate scope choice. It stays physical, stays out of
targets and graphs, and stays reported in coverage, but it is not evidence that a
first-party answer is wrong.

Whether a particular answer needed the excluded semantics is carried by that
question's own unresolved call destinations, recorded per question in 10.5, rather
than assumed for every answer in the repository.

Controls exercise the real partition logic rather than an injected reason: a
vendored directory leaves the answer completed with the exclusion still reported,
an unresolved symlink still demotes, and the two together still demote.

1,365 tests passed, nine skipped. Rollout stays NO-GO.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01EmM1j46qgKMh3zqD1QMwEo
This commit is contained in:
Marius Ciepluch
2026-09-16 17:35:00 +02:00
co-authored by Claude Opus 5
parent b202aabd8b
commit c1cc332bc1
4 changed files with 105 additions and 21 deletions
+29 -20
View File
@@ -509,25 +509,11 @@ def _scan_repository_impl(
if unasked:
degradations.append({"stage": "model", "reason": "budget_exhausted", "regions_unasked": len(unasked)})
graph_gaps = tuple(
str(d["reason"])
for d in degradations
if d.get("reason")
in {
"files_unparsed",
"cpg_empty",
"partition_file_census_incomplete",
"partition_file_census_unavailable",
"cpg_sharded",
"cross_partition_semantics_unresolved",
"vendor_semantics_unresolved",
"symlink_context_unresolved",
"frontend_unsupported",
"source_unreadable",
"ambiguous_frontend_path",
"typescript_property_support_unvalidated",
}
)
graph_gaps = tuple(str(d["reason"]) for d in degradations if d.get("reason") in GRAPH_INTEGRITY_GAPS)
# A declared exclusion is a deliberate scope choice, not a failure to read the graph. It stays
# in coverage, and whether a particular answer needed the excluded semantics is carried by that
# question's own unresolved call destinations, not assumed for every answer in the repository.
declared_gaps = tuple(str(d["reason"]) for d in degradations if d.get("reason") in DECLARED_EXCLUSION_GAPS)
for question in scope.selected:
rid = question.identity.question_id
if rid not in outcomes:
@@ -542,7 +528,7 @@ def _scan_repository_impl(
outcomes[rid] = replace(outcomes[rid], status="unresolved", reason="change_context_incomplete")
if graph_gaps and outcomes[rid].status == "completed":
outcomes[rid] = replace(outcomes[rid], status="unresolved", reason="graph_incomplete")
scope = replace(scope, unresolved_boundaries=tuple(dict.fromkeys((*scope.unresolved_boundaries, *graph_gaps))))
scope = replace(scope, unresolved_boundaries=tuple(dict.fromkeys((*scope.unresolved_boundaries, *graph_gaps, *declared_gaps))))
ordered_outcomes = tuple(outcomes[q.identity.question_id] for q in scope.selected)
scanned = len(judged)
@@ -573,6 +559,29 @@ def _scan_repository_impl(
)
# Reading the graph failed or produced something incomplete. An answer drawn from it cannot be
# trusted, so a completed outcome is demoted.
GRAPH_INTEGRITY_GAPS = frozenset(
{
"files_unparsed",
"cpg_empty",
"partition_file_census_incomplete",
"partition_file_census_unavailable",
"cpg_sharded",
"cross_partition_semantics_unresolved",
"symlink_context_unresolved",
"frontend_unsupported",
"source_unreadable",
"ambiguous_frontend_path",
"typescript_property_support_unvalidated",
}
)
# Declared, intentional exclusions. The exclusion stays physical and stays reported; it is not
# evidence that any particular first-party answer is wrong. Treating it as one demoted every
# answer on every real repository, because every real repository excludes its dependencies.
DECLARED_EXCLUSION_GAPS = frozenset({"vendor_semantics_unresolved"})
def _identity(unit: str, region: ScanRegion, family: str) -> QuestionIdentity:
return QuestionIdentity(unit, region.language, region.path, region.function, family)