Skip to content

feat(pass2): optional domain/range check on extracted edges - #82

Closed
SenolIsci wants to merge 1 commit into
mainfrom
feature/pass2-domain-range-check
Closed

SenolIsci wants to merge 1 commit into
mainfrom
feature/pass2-domain-range-check

Conversation

@SenolIsci

@SenolIsci SenolIsci commented Oct 4, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • New pass2.domain_range_policy (off | warn | strict, default warn), exposed as config.PASS2_DOMAIN_RANGE_POLICY; invalid values log a warning and fall back to warn. Intentionally not added to either mykg_config.yaml.
  • pass2.py: _ancestors, _domain_range_status (inheritance-aware, uses response nodes + prior_nodes), _apply_domain_range_policy run after _normalize_scalars on first attempt and retry.
    • warn/strict: reversed edges are swapped (INFO log)
    • warn: remaining violators are kept and tagged domain_range_violation: true. The tag reaches edge_metadata.json through the assembler unchanged.
    • strict: validate_extraction reports Domain/range violation: ... (which triggers the existing retry), and _partial_recover drops violators before the hallucinated-anchor pass.
  • Both new kwargs are optional, so existing call sites keep working.

Testing

  • pytest tests/test_pass2.py tests/test_extraction_edge_paths.py: 63 passed
  • E2E on _test_files2 with ollama-local, under warn and under strict: both runs finished and wrote knowledge_graph_validation.json. The LLM produced no reversed or violating edges (warn: 18 edges, strict: 24, 0 violators, 0 swaps). The scripted stub test test_extract_chunk_policies covers that path: off leaves edges unchanged, warn swaps and tags, strict retries and drops the violator.

🤖 Generated with Claude Code

Summary by Sourcery

Add optional domain/range policy enforcement to pass2 edge extraction.

New Features:

  • Add configurable domain/range validation for extracted edges with off, warn, and strict policies.
  • Handle reversed edges automatically and preserve or remove domain/range violators according to the selected policy.

Enhancements:

  • Make domain/range checks inheritance-aware and include node types carried over from prior extraction results.
  • Propagate warning annotations through assembled edge metadata and trigger existing retry and recovery flows for strict violations.

Tests:

  • Add coverage for policy behavior, inheritance, prior nodes, invalid configuration values, and strict recovery of violating edges.

Adds pass2.domain_range_policy (off|warn|strict, default warn; read but not
surfaced in the shipped YAML). Inheritance-aware endpoint-type check:
reversed edges are swapped under warn/strict; warn tags remaining violators
with domain_range_violation=true; strict reports them as validation errors
(triggering the existing retry) and _partial_recover drops them before the
hallucinated-anchor pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sourcery-ai

sourcery-ai Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

The PR adds an optional, inheritance-aware domain/range policy to pass2 extraction. Reversed edges are normalized, warn mode preserves and tags other violations for downstream metadata, and strict mode feeds violations into retry and recovery cleanup, with configuration validation and comprehensive unit-path coverage.

Sequence diagram for strict domain/range extraction

sequenceDiagram
    participant Extractor
    participant LLM
    participant Validator
    participant Recovery

    Extractor->>LLM: llm_complete_with_retry
    LLM-->>Extractor: extraction
    Extractor->>Extractor: _normalize_scalars
    Extractor->>Extractor: _apply_domain_range_policy
    Extractor->>Validator: validate_extraction
    Validator-->>Extractor: Domain/range violation
    Extractor->>LLM: retry with validation errors
    LLM-->>Extractor: extraction2
    Extractor->>Extractor: _apply_domain_range_policy
    Extractor->>Validator: validate_extraction
    Validator-->>Extractor: errors2
    Extractor->>Recovery: _partial_recover
    Recovery-->>Extractor: cleaned extraction
Loading

Flow diagram for pass2 domain/range policy handling

flowchart TD
    A["_extract_chunk"] --> B["_normalize_scalars"]
    B --> C["_apply_domain_range_policy"]
    C --> D{"Policy"}
    D -->|off| E["Edges unchanged"]
    D -->|warn| F["Swap reversed edges"]
    F --> G["Tag remaining violations"]
    D -->|strict| H["Swap reversed edges"]
    H --> I["validate_extraction"]
    I -->|violation| J["Retry extraction"]
    J --> K["_partial_recover"]
    K --> L["Drop violating edges and unanchored nodes"]
    G --> M["edge_metadata.json"]
    E --> N["Backfill extraction"]
    L --> N
Loading

File-Level Changes

Change Details Files
Added configurable domain/range validation policies with safe fallback behavior.
  • Introduced off, warn, and strict policy values with a default of warn.
  • Exposed configuration through PASS2_DOMAIN_RANGE_POLICY without modifying shipped YAML files.
  • Logged invalid configured or per-call policies and normalized them to warn.
src/mykg/config.py
src/mykg/pass2.py
Implemented inheritance-aware endpoint domain/range classification and policy application throughout extraction.
  • Resolved node types from prior nodes plus current response nodes, with current nodes taking precedence.
  • Recognized valid subclass endpoints, reversed edges, violations, and unknown cases.
  • Swapped reversed edges in warn and strict modes; tagged retained violations in warn mode.
  • Applied policy after scalar normalization on both initial and retry responses.
src/mykg/pass2.py
Integrated strict violations into validation, retry, and partial recovery flows.
  • Reported strict violations through validate_extraction to trigger the existing retry path.
  • Dropped strict-mode violating edges before hallucinated-anchor cleanup during partial recovery.
  • Preserved optional kwargs for existing callers.
src/mykg/pass2.py
Added focused coverage for policy behavior and extraction recovery.
  • Tested inheritance, cycle-safe ancestry, prior-node typing, reversed-edge swapping, warning tags, strict errors, off-mode behavior, and invalid-policy fallback.
  • Tested initial extraction, retry, strict edge removal, and anchor cleanup with a scripted adapter.
  • Added strict partial-recovery coverage for removing violating edges and their unanchored nodes.
tests/test_pass2.py
tests/test_extraction_edge_paths.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="src/mykg/pass2.py" line_range="125" />
<code_context>
+            )
+            edge["from"], edge["to"] = edge["to"], edge["from"]
+        elif status == "violation" and policy == "warn":
+            edge["domain_range_violation"] = True
+            log.warning(
+                "    %s — kept and tagged (policy=warn)",
</code_context>
<issue_to_address>
**issue (broader_impact):** The warning tag is copied only from the first occurrence of a deduplicated edge. When the same logical edge is extracted from multiple files and a later occurrence is tagged while the first occurrence is untagged, `deduplicate_edges` keeps the first copy and silently drops `domain_range_violation` from `edge_metadata.json`.

**Triggers:** When a logical edge is extracted in multiple files and its endpoint types are available only in a later occurrence, causing only that occurrence to be classified as a violation.

**Suggested fix:** When merging duplicate edges, explicitly OR `domain_range_violation` across all occurrences instead of relying on the first occurrence's copied fields.
</issue_to_address>

Sourcery assessment

Needs a human reviewer. 1 finding to address first, and the new default behavior can swap reversed edges, tag violations, or drop them under strict mode, so an incorrect domain/range inference could write wrong relationships to the extracted graph. Reverting stops future changes but does not undo already stored edges; they are bounded and can be repaired by re-running extraction.

Blocking findings: src/mykg/pass2.py:125


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread src/mykg/pass2.py
)
edge["from"], edge["to"] = edge["to"], edge["from"]
elif status == "violation" and policy == "warn":
edge["domain_range_violation"] = True

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (broader_impact): The warning tag is copied only from the first occurrence of a deduplicated edge. When the same logical edge is extracted from multiple files and a later occurrence is tagged while the first occurrence is untagged, deduplicate_edges keeps the first copy and silently drops domain_range_violation from edge_metadata.json.

Triggers: When a logical edge is extracted in multiple files and its endpoint types are available only in a later occurrence, causing only that occurrence to be classified as a violation.

Suggested fix: When merging duplicate edges, explicitly OR domain_range_violation across all occurrences instead of relying on the first occurrence's copied fields.

@codecov

codecov Bot commented Oct 4, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.75000% with 5 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/mykg/pass2.py 95.94% 3 Missing ⚠️
src/mykg/config.py 66.66% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@SenolIsci

Copy link
Copy Markdown
Owner Author

Abandoned: domain/range policy feature dropped.

@SenolIsci SenolIsci closed this Oct 4, 2026
@SenolIsci
SenolIsci deleted the feature/pass2-domain-range-check branch October 4, 2026 19:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant