Credence.Assumptions (credence v0.7.1)

Copy Markdown

Safety switches — the promises Credence is allowed to make about your data.

A switch (an assumption) is a checkable promise about the text your code handles while it runs — names, chat messages, file contents — not about the characters in your .ex source files. Some rules only give the exact same answer as your original code when a particular promise holds; those rules declare the promise via assumptions/0 and run only while it is on.

The reframed invariant:

Credence never changes behaviour on any input your stated promises admit.

The two modes

  • :strict — you make no promises, so only rules that are correct for every possible input run. Bit-identical to your original code, guaranteed.
  • the helpful default — a small curated set of promises is on, which lets Credence also run the extra rules. Correct for the ~99% of real code whose running data is plain, single-piece text.

Setting switches

Pass assumptions: as one of three things (to Credence.fix/2, Credence.analyze/2, etc.), or set it project-wide via config :credence, assumptions: ...:

  • a small map naming only the switches you want to change — %{single_codepoint_graphemes: false}. It patches only the keys it names; every switch it does not mention falls through to the layer below.
  • :strict — a full reset that forces every switch off.
  • :default — a full reset that returns every switch to its built-in default (the mirror of :strict).

Three places, later wins

Credence folds three layers, later beating earlier: call options > config :credence > built-in defaults. A place that isn't set is skipped. Mechanically it starts from the full defaults map, then folds each later layer on top: :strict/:default overwrite all keys, a small map patches only its own keys (never expanded with defaults — that would let an unmentioned switch stomp the layer beneath it).

# project-wide: play it safe everywhere
config :credence, assumptions: :strict

# one trusted run re-enables just this switch, leaving the rest off
Credence.fix(code, assumptions: %{single_codepoint_graphemes: true})

Inspecting

Credence.Pattern.rule_status/1 lists every rule, the promises it needs, whether it is on now, and which needed promises are off. Credence.Pattern.enabled_rules/1 is the on-names from that list.

The switches

single_codepoint_graphemes (on by default)

Promises that every character (grapheme) in your running data is a single codepoint — a plain single-piece character. No decomposed accents (an "e" plus a separate combining accent mark), no ZWJ emoji (👨‍👩‍👧), no flag sequences (🇵🇱). This is about the text your program handles, not the characters in your source file. It is on by default because LLM-generated Phoenix apps overwhelmingly process exactly this kind of text; turn it off (or use :strict) if your code processes arbitrary Unicode.

proper_lists (on by default)

Promises that every list your running data builds or receives is a proper list — one whose final tail is [], so the tail of any cons cell is itself a list. It rules out improper lists such as [1 | 2], whose tail is a non-list value. This matters for rules that drop an is_list/1 guard on a cons-tail variable ([head | tail] when is_list(tail)): the guard is only redundant when tail cannot be a non-list, i.e. under this promise. It is on by default because improper lists are rare in application code; turn it off (or use :strict) if your code deliberately constructs improper lists.

Summary

Functions

The full registry: %{name => %{default:, summary:}}.

The built-in default settings: %{name => boolean}.

Whether name is a known switch.

The names of all known switches.

Validates a user-supplied settings map, raising ArgumentError if it names a switch that does not exist. Returns the map unchanged on success.

Types

name()

@type name() :: atom()

settings()

@type settings() :: %{required(name()) => boolean()}

Functions

all()

@spec all() :: %{required(name()) => %{default: boolean(), summary: String.t()}}

The full registry: %{name => %{default:, summary:}}.

defaults()

@spec defaults() :: settings()

The built-in default settings: %{name => boolean}.

known?(name)

@spec known?(term()) :: boolean()

Whether name is a known switch.

names()

@spec names() :: [name()]

The names of all known switches.

validate!(map)

@spec validate!(map()) :: map()

Validates a user-supplied settings map, raising ArgumentError if it names a switch that does not exist. Returns the map unchanged on success.