!weight — saliency

every anrl statement is prefixed with an attention weight. the formatter quantizes continuous values to five discrete tiers, empirically sufficient for llms to distinguish priorities without float-noise confusion.

weighttiermeaning
!1.0criticalquery target — mandatory attention
!0.8highimportant supporting context
!0.5normalstandard content (default, elided)
!0.2weakdistractor / background context
!0.0suppressignored by the model
how the compiler sets weights
depth quantization
shallow nodes get !0.8, deep nodes !0.5, very deep !0.2
graph distance bfs
nodes far from query anchors are scaled down to !0.2
user annotation
explicitly set !1.0 on critical entities in source
flatness warning
compiler warns when all nodes are uniform !0.5, which degrades retrieval
# saliency in practice
!1.0 @Incident_Node :: Alert        # model MUST attend here
!0.8 *severity: critical
!0.5 *region: us-east-1
!0.2 *created_at: 2024-08-12T08:00:00Z  # background context

?confidence — epistemic clarity

a suffix on primitives and edges encoding the certainty of a statement. omit it for verified facts (?1.0 is the default and is always suppressed to save tokens). the behavioral effect depends entirely on the system prompt.

mode a — conflict resolution
courtroom framing

three sources assert contradictory temperatures: 60°c (?0.3), 40°c (?0.9), 100°c (?0.1). with the conflict-resolution prompt, the model resolves to 40°c without explicit chain-of-thought.

+60% accuracy over plain json in conflict resolution tasks

“when data is in anrl format, the notation ?N indicates confidence. when values conflict, always prefer the highest ? value.”
mode b — epistemic hedging
journalism framing

a summarization task. without any prompt, the llm reads ?0.1 and naturally injects hedging language: “according to some sources, it is estimated that the temperature may be 60°c.” the confidence operator is read, not filtered.

+33% rouge-1 over confidence-stripped anrl in hedging tasks

“(no system prompt required — neutral context is sufficient)”
the system prompt paradox

the same ?confidenceoperator requires different system prompts for different tasks. mode a needs “prefer highest confidence.” mode b needs no prompt — adding one produces incorrect behavior. workaround: use ^query directives at document top. see the spec

--rel-→ — relational anchoring

typed, directed edges between named entities form an explicit graph embedded in text. llm attention heads traverse named entity references in edges naturally. this is what json $ref and string matching cannot do.

edge types
--contains-->
containment
@Module --contains--> @Function
--depends_on-->
dependency
@Service --depends_on--> @DB
--imports-->
import link
@main.rs --imports--> @utils.rs
--implies-->
semantic inference
auto-generated by fastembed pass
=>
causal transition
@Memory_Leak => @Service_Crash
why not json $ref?
violative — flat attribute
*owner: "John_Doe"

multi-hop reasoning collapses — string matching is not a graph

compliant — typed edge
@Service --owned_by--> @John_Doe

traversable, typed, bidirectional in the compiled graph

benchmark results

16-file corpus spanning 462 bytes to 288 KB. token overhead is shape-dependent: tabular, wide-array, and null-heavy payloads achieve net compression. structured graphs and deep nesting incur overhead from entity cost (~3 tokens/entity).

3
fixtures with net-positive token compression
−23%
average token overhead across 16 files
13ms
worst-case compile: 288 KB openapi spec
fixturesizesource tokensanrl tokenssavingscompile ms
empty_values.json462 B14869+53.4%0.03
wide_array.json2.7 KB1,020527+48.3%0.15
large_flat.json4.6 KB1,9521,540+21.1%0.08
deep_nested.json2.4 KB644818−27.0%0.21
openapi.json4.9 KB1,2741,809−42.0%0.32
mixed.md2.9 KB725823−13.5%0.05
large_openapi.json288 KB53,24767,453−26.7%13.22
large_event_log.json127 KB46,46257,433−23.6%4.38

the six-stage compiler pipeline

every file passes through the same six stages, regardless of input format. the output is always a Vec<AnrlNode> ir.

1
ingestion

parses source format (json/yaml → json_yaml.rs, markdown → pulldown-cmark, code → tree-sitter cst, anrl text → recursive descent parser, binary anrl → rmp_serde decode)

2
semantic pass (optional)

runs fastembed AllMiniLM-L6-v2 (~22MB) if auto heuristics trigger: island detection (link density < 0.5) AND prose entropy (>25% unstructured text). capped at top-3 implies edges per source.

3
semantic optimizer

contrastive weight optimization (BFS from query anchors), weight quantization to 5 tiers, confidence calibration, flatness warning.

4
formatter

renders ast to text or messagepack binary. enforces syntactic elision (!0.5 and ?1.0 suppressed). deterministic ordering: entities → links → primitives.

5
parser

recovers ast from text for round-trip. injects default values for elided fields (weight 0.5, confidence 1.0) so equality holds.

6
project linker

for directory input: resolves cross-file imports to typed edges (--imports--> / --references-->). unresolved external deps become ephemeral stub entities.