Skip to content

Epistemic tiers and confidence

ZettelForge 2.8.0 records two different judgments on every memory note: an editorial tier and a numeric confidence value. The tier can decide whether a note enters synthesis. Confidence records your assessment of the note, but it does not remove the note from synthesis by itself.

Use these fields as policy inputs, not as proof that intelligence is true. The released model stores values that you assign; it does not validate the source or enforce the documented ranges.

Prerequisites: Read the Memory Manager API for note operations and the Configuration reference for the complete synthesis settings.

Two judgments answer two questions

Tier and confidence are intentionally separate:

Field Released default Question it answers
metadata.tier "B" on a plain Metadata object What editorial role does this source play?
metadata.confidence 1.0 How strongly do you assess this note?
metadata.stix_confidence -1 What integer confidence did a STIX-oriented integration supply? -1 means unset.

ZettelForge defines three editorial tiers in its default configuration:

Tier Meaning Useful decision rule
A Authoritative: high-confidence, verified sources Reserve it for evidence your process has validated.
B Operational: working knowledge with moderate confidence Use it for intelligence that supports analysis but still needs corroboration.
C Support: low-confidence, inferred, or speculative material Keep it available for investigation without treating it as established fact.

The letter does not calculate the number, and the number does not promote the letter. ZettelForge also does not convert metadata.confidence to metadata.stix_confidence. This separation lets you describe provenance and certainty without collapsing them into one score.

Ingestion assigns a starting tier, not trust

The model default and the direct ingestion path use different starting values. A standalone Metadata object starts at tier B. The NoteConstructor used by the ordinary MemoryManager.remember() path creates every note at tier A, regardless of source_type, domain, or text.

That A is an implementation default, not an automatic source assessment. Review the source and rewrite the note metadata when the default does not match your evidence policy. SQLite persists later changes to both tier and stix_confidence.

Tier and confidence validation is in progress

ZettelForge 2.8.0 declares tier as a string, confidence as a float, and stix_confidence as an integer without range constraints. The released model accepts values such as tier D, confidence 1.5, and STIX confidence 101. Validate allowed tiers and numeric bounds in your ingestion layer before you store a note.

Evolution applies one confidence cap

Calling increment_evolution() records a revision and sets confidence to the lower of its current value and 0.95. A note at 1.0 therefore moves to 0.95 after its first evolution. A second call increases evolution_count but leaves that confidence at 0.95; the method does not apply repeated decay.

The built-in review predicate returns true when either condition holds:

  • metadata.confidence is below 0.5.
  • metadata.evolution_count is greater than 5.

The boundaries are strict. Confidence 0.5 is not flagged by the confidence rule, and an evolution count of 5 is not flagged by the count rule.

This mechanism is a review signal, not a calibrated probability model. If your workflow needs cumulative decay, corroboration weights, or conflict-aware scoring, calculate that policy outside increment_evolution() and persist the result explicitly.

Synthesis filters by tier only

The synthesis generator retrieves notes, removes duplicate IDs, and then keeps notes whose metadata.tier appears in tier_filter. It does not compare metadata.confidence with the generator's confidence_threshold. A tier B note with confidence 0.1 still enters synthesis when B is allowed.

Observed ZettelForge 2.8.0 behavior is:

Call behavior Tiers admitted
Omit tier_filter in a direct MemoryManager.synthesize() call A, B, and C
Pass tier_filter=["A", "B"] A and B
Pass tier_filter=["A"] A
Pass an empty list A, B, and C

The last row follows from the generator treating an empty list like a missing value. Pass an explicit non-empty list when you want a restriction.

The configured synthesis default is not wired to direct calls

config.default.yaml and SynthesisConfig default to tiers A and B, but MemoryManager.synthesize() does not load that setting when tier_filter is omitted. The generator uses all three tiers instead. Pass the required filter at each direct call until config-to-runtime wiring is implemented.

The operational model

Treat the fields as a small policy vocabulary:

  1. Tier expresses the source's role in your editorial process.
  2. Confidence expresses your current assessment of the note.
  3. Evolution count tells you how often later notes revised it.
  4. Your calling application validates values and decides what requires review.
  5. Synthesis uses only the explicit tier allowlist.

This division keeps ZettelForge flexible, but it leaves enforcement with you. The useful habit is simple: assign deliberately, validate before storage, and pass synthesis policy explicitly.

This page describes the self-hosted ZettelForge model. ThreatRecall.ai is the separate hosted SaaS and is outside this page's scope.