Skip to content

The deterministic core

Most of CiteNexus is the Python facade — ingest, retrieve, ask, evaluate, the config layer. This page is the part that is not Python: pure functions that exist in Python, Go and JavaScript alike, take the same input, and return the same output, because a shared set of conformance vectors fails the build otherwise.

Algorithm Python Go JavaScript Pinned by
Chunking chunk_text chunker.ChunkText chunkText conformance/cases/chunker.json
Faithfulness gate (v2) is_supported_v2, align gate.IsSupportedV2, gate.Align isSupportedV2, align conformance/cases/faithful_v2.json
Claim segmentation split_claims answer.SplitClaims splitClaims conformance/cases/segmentation.json
Conflict + near-duplicate detect_conflict, is_near_duplicate answer.DetectConflict, answer.IsNearDuplicate detectConflict, isNearDuplicate conformance/cases/conflict.json
Embedding-vector validation check_vector contracts.CheckVector checkVector conformance/cases/vector_validation.json

The tokenizer underneath them (14 scripts, one table) and RRF fusion are pinned the same way.

chunk_text splits text into bounded, overlapping, boundary-respecting chunks. Defaults are the same everywhere: max_tokens = 450, overlap = 60.

from citenexus.evidence.chunker import chunk_text
chunk_text("one two three four five", max_tokens=3, overlap=1)
# ['one\ntwo\nthree', 'three\nfour\nfive']

The only difference is call style: Python takes max_tokens / overlap as keyword-only arguments, Go and JavaScript take them positionally after the text. A max_tokens below 1 is an error in every port, and empty text yields an empty list rather than one empty chunk.

is_supported_v2 is the predicate that stands between a caller and a lie: the claim’s tokens must appear in the passage in order, preserving multiplicity, within a bounded interior gap, and every polarity marker inside the matched span must survive into the claim. See the faithfulness gate for why set containment was not enough.

from citenexus.answer.verify import (
is_supported_v2, align, MAX_SINGLE_GAP, MAX_TOTAL_GAP,
)
from citenexus.tokenize import tokenize_v2
is_supported_v2("notice period is 30 days", "The notice period is 30 days.")
# True
align(tokenize_v2("notice period is 30 days"),
tokenize_v2("The notice period is 30 days."))
# Alignment(start=1, end=5, total_gap=0, max_gap=0) — or None if it does not align
MAX_SINGLE_GAP, MAX_TOTAL_GAP # (4, 8)

align reports where the claim matched, in passage-token indices, and how much it had to skip. Go returns (Alignment, bool); Python returns Alignment | None; JavaScript returns Alignment | null — the same four numbers either way (start, end, total_gap/TotalGap/totalGap, max_gap/MaxGap/maxGap).

The frozen v1 predicate (is_supported / gate.IsSupported / isSupported) is still exported in every port so its vectors keep passing, but it is no longer what the answer path calls anywhere.

split_claims breaks an answer into atomic claims — the unit the gate verifies.

from citenexus.answer.segment import split_claims
split_claims("The notice period is 30 days. It may be extended.")
# ['The notice period is 30 days.', 'It may be extended.']

Everything that needs orchestration. Ingestion, retrieval, the config layer, the authority floor, evaluation, graph and wiki, deep-ask and the CiteNexus class itself live only in Python — the ports have no facade to hang them on. (Conflict detection is not on that list any more: ADR-0007 detection and near-duplicate collapse are deterministic set arithmetic, so they are native in all three, pinned by conformance/cases/conflict.json — see Conflicting sources.) Install has the per-port surface; Scope has the boundary and why it is drawn there.