cadrumo.adapters.outbound.llm.supply_nature_proposal module

Proposing whether an invoice supplies goods or services, for a person to confirm.

The last resort on an axis that prefers evidence. Three routes settle the nature of a supply before this one is reached: an explicit printed statement, a printed statutory citation, and the articles the declared IVA category itself rests on. Each decides by law. What remains is a cross-border document that states none of them, and the governing record calls that population assisted, not automated on purpose.

This proposes to a person; it never decides. The sanctioned channel is suggest, review, apply: the proposal is shown beside the question the operator is already being asked, and the value that reaches the deterministic classifier is the one they state at confirm. Nothing here persists, nothing here is consulted by the classifier, and a proposal nobody confirms has no effect whatsoever – which is what keeps the classifier’s inputs facts rather than model output.

Why this is not the prose rule table the domain forbids. The supply-nature authority refuses a table mapping line descriptions to natures, because such a table answers confidently on the population it was written against and wrongly everywhere else with nothing downstream able to tell. That refusal governs anything that DECIDES. A proposal a human must accept is a different object: it is read by someone holding the document, and it is discarded by them at no cost. The distinction is the whole reason the apply arm is the operator’s own typed answer rather than a write from here.

Closed vocabulary, and an escape hatch that is not a domain member. The model chooses from the two natures or declines. Declining is spelled with a token that exists only in this reply shape – UNDETERMINED_SUPPLY_NATURE – and never as a SupplyNature member: the domain enum has two members and no “unknown” precisely because a stored “we could not tell” is indistinguishable from a fact at every later reader. A proposal that declines carries None.

The prompt and the parser are separable on purpose. Both are pure functions over strings, so the instruction the model receives and the containment applied to its reply are each assertable without dispatching a request – and the enumerated allow-list can be proved to come from the enum rather than from a template literal.

See also

derive_supply_nature_from_citation()

The printed-citation route, which decides by law and outranks this.

supply_nature_implied_by_category()

The category route, which also decides by law and outranks this.

domain.iva.supply_nature_is_required

The laziness rule that bounds the population reaching this at all.

SUPPLY_NATURE_PROMPT_ID: Final[str]

Names this instruction in the client’s prompt registry and every stamp.

UNDETERMINED_SUPPLY_NATURE: Final[str]

The reply token a model uses to decline, spelled once.

Deliberately NOT a SupplyNature member. That enum carries two natures and no “unknown” because a stored “we could not tell” reads as a fact to everything downstream; this token lives in the reply shape only, and a declining proposal carries None on the far side of the parser.

class SupplyNatureProposal(**data)[source]

Bases: BaseModel

One model’s proposal about an invoice, before any person has seen it.

Variables:
  • nature – The proposed nature, or None when the model declined or its reply did not survive containment. None is an ordinary outcome rather than a failure: the operator is asked either way, and a proposal is only ever a starting point for their answer.

  • declined – Whether the model explicitly declined, as distinct from having its reply refused. Both leave nature empty and neither reaches the classifier, but only one of them says something about the document rather than about the reply.

  • note – The model’s own short reason, kept verbatim for the operator and never parsed. Empty when nothing usable arrived.

Parameters:

data (Any)

nature: SupplyNature | None
declined: bool
note: str
permitted_supply_natures()[source]

Return every nature a model may choose, in declaration order.

Derived from SupplyNature itself rather than from a list held here, so the vocabulary offered to the model, the vocabulary the parser accepts and the vocabulary the allow-list enforces cannot disagree.

Return type:

tuple[SupplyNature, ...]

build_supply_nature_prompt(descriptions)[source]

Build the instruction the model receives for one invoice’s lines.

Written for the smallest capable model: one task, an explicit closed vocabulary, a stated escape hatch so the model never has to force a fit, and one literal reply shape.

Parameters:

descriptions (Sequence[str]) – The invoice’s line descriptions, as printed. Blank entries are dropped; the list is truncated and each entry bounded, because free issuer prose is the natural carrier for an injected instruction.

Return type:

str

Returns:

The full instruction, or an empty string when no description survives. Empty rather than a prompt over nothing: asking a model to judge an invoice whose lines it cannot see invites it to invent one, and a caller that receives no instruction makes no request.

parse_supply_nature_response(text)[source]

Turn one model reply into a proposal, refusing anything outside the vocabulary.

The containment boundary. Whatever the model emitted – or whatever an injected line description steered it into emitting – only one of the two declared natures may pass, and everything else yields an empty proposal.

Refusing yields an empty proposal rather than raising, and that is the right shape here rather than leniency: this proposal is advisory, the operator is asked either way, and an exception would turn a model’s bad reply into a failure of the confirm the operator was doing.

Parameters:

text (str) – The model’s reply, in whatever wrapping it arrived.

Return type:

SupplyNatureProposal

Returns:

The proposal. nature is populated only for an exact match against permitted_supply_natures(); a declared decline sets declined.

class SupplyNatureProposer(*, model=None, provider=None, client=None, settings=None)[source]

Bases: object

Ask a model for one proposal, for a person to accept or discard.

Binds to LLMClient and nothing lower, so which engine answers is configuration rather than a fact this class holds.

The model comes from the role, never the general default. Left to itself the client would answer on the configured frontier model for a task that is choosing between two words. The role resolves through select_model_for_role() against SUPPLY_NATURE_PROPOSAL, which names the WEAKEST catalogued candidate clearing the capability, licence and headroom bars – and that role clears wherever the column-role mapper does, because it is the same selection job over a smaller vocabulary.

Parameters:
  • model (str | None) – Optional runtime id, honoured over the role resolution.

  • provider (LLMProvider | None) – Optional provider override. None pairs a role-resolved model with LOCAL, since a role-resolved id is an on-host runtime id.

  • client (LLMClient | None) – Injected client; default-constructed otherwise.

  • settings (Settings | None) – Injected settings; defaults to load_settings().

property decided_by: str

Provenance stamp naming the transport and model a proposal was reached with.

propose(descriptions)[source]

Propose a nature from descriptions, or return an empty proposal.

Makes NO request when the instruction would be empty, which is the no-usable-description case: a model asked about lines it cannot see invents one, and there is nothing here worth spending a call on.

Parameters:

descriptions (Sequence[str]) – The invoice’s line descriptions, as printed.

Return type:

SupplyNatureProposal

Returns:

The proposal. Empty whenever nothing was asked, the model declined, or its reply did not survive containment – all of which leave the operator asked exactly as they were.