Cohomology Classification

JuGeo uses the language of Čech cohomology on the semantic site \((\mathcal{C}, J)\) to classify descent failures. Given a covering family \(\mathcal{U} = \{U_i \to U\}_{i \in I}\) and the judgment sheaf \(\mathcal{F}\), the Čech complex is:

The Čech Complex
\[ 0 \;\to\; \mathcal{F}(U) \;\to\; \prod_i \mathcal{F}(U_i) \;\xrightarrow{\delta^0}\; \prod_{i < j} \mathcal{F}(U_{ij}) \;\xrightarrow{\delta^1}\; \prod_{i < j < k} \mathcal{F}(U_{ijk}) \;\to\; \cdots \]

The cohomology groups \(\check{H}^n(\mathcal{U}, \mathcal{F})\) measure qualitatively different kinds of failure. JuGeo computes an approximation of these groups and assigns one of four obstruction degrees to each descent failure. Each degree corresponds to a distinct structural problem that requires a different remediation strategy.

H⁰

Missing Local Section

At least one element \(U_i\) of the cover has no valid local section. The property does not hold locally at some piece of the code. This is the most common and most directly fixable obstruction — repair or annotate the implementation at \(U_i\).

Compatibility Failure

All local sections exist, but they disagree on at least one intersection \(U_i \times_U U_j\). The 1-cochain of mismatches is a cocycle but not a coboundary — a genuine global obstruction. Requires interface reconciliation between two components.

Higher Coherence Failure

Local sections and pairwise compatibilities both exist, but triple intersections \(U_{ijk}\) fail to cohere. Arises from three-way interface conflicts; rare in practice but common in heavily parametric code (typeclass hierarchies, multiple inheritance chains).

H∞

Undecidable Obstruction

The compatibility condition reduces to an undecidable problem (e.g., general program equivalence or the halting problem). JuGeo cannot compute the cohomology group and classifies the obstruction as H∞. Only FORMAL_PROOF evidence or manual annotation can resolve it.

💡

Practical frequency. In the JuGeo evaluation benchmark H⁰ obstructions account for approximately 72% of failures, H¹ for 24%, H² for 3%, and H∞ for 1%. The overwhelmingly common case is a missing local section — a function that simply does not satisfy the required property. Most automated repair can therefore focus on H⁰ cases.

Obstruction Class Fields

Every obstruction is represented as an ObstructionClass dataclass. The fields encode both the mathematical data (which degree, which cochain) and the engineering data (source locations, repair hints, backpressure score) needed to present actionable diagnostics to the developer.

FieldTypeDescription
degree ObstructionDegree H0, H1, H2, or HINF. Determines which repair strategies apply.
coordinate Coordinate The object \(U\) where descent was attempted (e.g., a module or class).
cover list[Coordinate] The covering family \(\{U_i\}\) used for the descent attempt.
failing_indices list[int] | list[tuple[int,int]] Indices into cover of the failing local sections (H0) or pairs (H1/H2).
cochain Cochain The raw Čech cochain data: maps each failing index to a mismatch formula.
is_cocycle bool Whether \(\delta c = 0\) holds. True indicates a genuine cohomological obstruction; false means it may be resolvable by cover refinement.
representative Formula | None A canonical representative formula for the obstruction class, if computable.
repair_hints list[RepairHint] Ordered list of suggested code changes to resolve the obstruction, with source locations.
backpressure_score float Estimated propagation severity through the site, in [0.0, 1.0]. Higher means more downstream judgments are affected.
evidence_gaps list[EvidenceGap] Evidence channels that could supply a section but have not been queried yet.

Constructing and inspecting an obstruction manually:

python
from jugeo.geometry.descent import (
    CohomologyClass,
    DescentObstruction,
    OverlapCondition,
    OverlapStatus,
    RepairFrontier,
)

obs = DescentObstruction(
    coordinate="mymod.payments",
    violated_overlaps=(
        OverlapCondition(
            left_coordinate="mymod.payments.validate",
            right_coordinate="mymod.payments.charge",
            overlap_coordinate="mymod.payments.validate∩mymod.payments.charge",
            status=OverlapStatus.VIOLATED,
        ),
    ),
    repair_frontier=RepairFrontier(
        missing_evidence=("spec:payments-charge",),
        weakened_claims=("align validate/charge currency assumptions",),
    ),
    cohomology_class=CohomologyClass(
        cocycle_data={"validate∩charge": {"currency": {"left": "USD", "right": "EUR"}}}
    ),
)

print(obs.violation_count)
print(obs.violated_pairs())
print(obs.cohomology_class.cocycle_data)

Repair Frontiers

A repair frontier is the minimal set of code locations that, if modified, would eliminate a given obstruction. JuGeo computes repair frontiers by working backward from the obstruction through the antecedent DAG of judgments — finding the earliest points where an intervention would propagate forward and resolve the mismatch.

Repair Frontier — Formal Definition
\[ \mathrm{Frontier}([c]) \;=\; \bigl\{\, U_i \in \mathcal{U} \;\bigm|\; \exists\;\text{repair at } U_i \text{ making } \delta c\big|_{U_i} = 0 \,\bigr\} \]

For H⁰ obstructions:

For H¹ obstructions:

For H² obstructions:

Computing the frontier programmatically:

python
from jugeo.geometry.descent import RepairFrontier

frontier = RepairFrontier(
    missing_evidence=("runtime trace:payments.validate",),
    weakened_claims=("weaken charge() postcondition on accepted currencies",),
    suggested_refinements=("split payments cover into auth/charge",),
    estimated_cost=2.5,
)

print(frontier.total_items())
for category, item in frontier.prioritized_items():
    print(category, item)

Backpressure System

An obstruction at a low-level utility function does not exist in isolation — every function that depends on that utility inherits an unresolved antecedent obligation. JuGeo's backpressure system quantifies this propagation by assigning a score \(\beta \in [0, 1]\) to each obstruction that measures how broadly its effects cascade through the semantic site.

Backpressure Propagation
\[ \beta(V,\, [c]) \;=\; \sum_{U \xrightarrow{f} V} w(f) \cdot \beta(U,\, [c]) \]

Edge weights \(w(f)\) depend on the morphism kind: direct call edges carry weight 1.0, import/module edges 0.5, and containment edges 0.8. Scores are normalised to \([0, 1]\) across the full obstruction report and displayed in the jugeo prove CLI output.

JuGeo recognises five canonical backpressure families, each suggesting a different response:

ISOLATED
Score 0.0 – 0.1

Obstruction affects only one or two direct callers. Fix at leisure; low urgency.

LOCAL
Score 0.1 – 0.3

Affects a small local cluster. Fix before merging the affected module.

MODERATE
Score 0.3 – 0.6

Propagates across subsystem boundaries. Include in the current sprint.

HIGH
Score 0.6 – 0.85

Blocks a large fraction of the module graph. Fix immediately to unblock other work.

CRITICAL
Score 0.85 – 1.0

Obstructs a foundational utility used pervasively. All dependent judgments are partial until resolved.

⚠️

Fix high-pressure obstructions first. When multiple obstructions exist, repair the ones with the highest backpressure score first. Fixing a single CRITICAL obstruction (e.g., in a widely-called utility) can eliminate dozens of downstream partial judgments in one stroke.

Python Examples

Querying the obstruction report for a module:

python
from jugeo.geometry.covers import Cover
from jugeo.geometry.descent import DescentEngine
from jugeo.geometry.site import Coordinate, CoordinateKind

cover = Cover(
    target=Coordinate("payments", kind=CoordinateKind.MODULE),
    patches=(
        Coordinate(("payments", "validate"), kind=CoordinateKind.FUNCTION),
        Coordinate(("payments", "charge"), kind=CoordinateKind.FUNCTION),
    ),
    overlaps=(("payments/validate", "payments/charge"),),
)

sections = {
    "payments/validate": {"currency": "USD", "status": "ok"},
    "payments/charge": {"currency": "EUR", "status": "ok"},
}

result = DescentEngine().run(cover, sections).to_descent_result()
obstruction = result.unwrap_obstruction()

print(obstruction.violation_count)
print(obstruction.violated_pairs())
print(obstruction.cohomology_class.cocycle_data)

Attempting automatic repair:

python
import subprocess

        completed = subprocess.run(
            ["python3", "-m", "jugeo", "--format", "json", "repair", "payments.py"],
    check=True,
    capture_output=True,
    text=True,
)

print(completed.stdout)

Inspecting the Čech cochain directly:

python
cohomology = obstruction.cohomology_class

print(cohomology.dimension)
print(cohomology.rank)
print(cohomology.is_trivial())
print(cohomology.cocycle_data)