docs← Back to article

Markdown for LLMs

Query types

The source Markdown for this article. Copy it into your assistant or download it as a text file.

Download this articlePlain text ↗
# Query types

One request shape, seven question kinds. The kind says what the engine
does with the facts: check a claim, compute a value, count days,
explain a gap, or list what the case requires. This chapter says when
to use each, what the answer carries, and which exist in Python.

```ts
export type AskRequest = {
  kind: 'truth' | 'focused_truth' | 'why_not' | 'collect' | 'calendar_op' | 'term' | 'positions';
  predicate?: string;
  args?: FactArg[];
  caseInput: CaseInput;
  queryId?: string;
  caseName?: string;
  extra?: Record<string, unknown>;
};
```

## truth — is the claim established

```ts
truth(predicate: Rel, args: FactArg[], caseInput: CaseInput): Promise<Answer>;
```

```python
def truth(self, predicate: str, args: list[Any], case_input: dict[str, Any]) -> Answer: ...
```

Use `truth` to check a complete claim: does the period end on 20
March. The answer carries `truthStatus` — one of `TRUE_ONLY`,
`FALSE_ONLY`, `BOTH`, `NEITHER` — with the proof of what fired. The
candidate date is yours; the engine only judges it.

```js
await fristen.truth('frist_ende', ['frist', '2026-03-20'], caseInput);
// COMPUTED, TRUE_ONLY
await fristen.truth('frist_ende', ['frist', '2026-03-21'], caseInput);
// COMPUTED, NEITHER — the wrong date is supported by nothing
```

## focused_truth — the same answer, sliced by the question

```ts
focusedTruth(predicate: Rel, args: FactArg[], caseInput: CaseInput): Promise<Answer>;
```

The same answer as `truth`, with the proof and the issues reduced to
the question's cone only. The answer is marked `focused_truth` and
carries a focus manifest instead of the full proof graph. It is not an
audit document: a sliced answer has no full `result` hash. Python does
not ship this kind; ask `truth` instead.

## why_not — what blocked the claim

```ts
whyNot(predicate: Rel, args: FactArg[], caseInput: CaseInput): Promise<Answer>;
```

```python
def why_not(self, predicate: str, args: list[Any], case_input: dict[str, Any]) -> Answer: ...
def whyNot(self, predicate: str, args: list[Any], case_input: dict[str, Any]) -> Answer: ...
```

Use `why_not` when `truth` answered `NEITHER` and the application must
ask the user for more. The answer carries `whyNot`: one blocker per
candidate rule, each with its applicability, a summary trigger, and
the state of every conjunct. Compare the premises with the facts you
supplied and the gap is named.

```js
const w = await fristen.whyNot('frist_ende', ['frist', '2026-03-20'], partial);
w.value.value.blockers;
// two blockers: TagesfristEnde waits on frist_ereignis and frist_dauer_tage,
// Verlegung193 waits on frist_ende_kalender
```

On the partial frist case — the duration fact removed — the report
holds exactly two blockers. Term errors of candidate rules, if any,
are reported next to them in `whyNotTermErrors`.

## collect — compute the value

```ts
collect(predicate: Rel, args: FactArg[] | { args: FactArg[]; free?: unknown }, caseInput: CaseInput): Promise<Answer>;
```

```python
def collect(self, predicate: str, args: Any, case_input: dict[str, Any]) -> Answer: ...
```

Use `collect` to compute rather than check: on which day does the
period end. The free position is named with `?name` in the argument
list, or passed explicitly as `free` with `args` as a dict. The answer
carries the bindings in `value`.

```js
const end = await fristen.collect('frist_ende', ['frist', '?end'], caseInput);
end.value[0].value; // '2026-03-20'
```

Choose `collect` when the application does not have a candidate, and
`truth` when it does — a form that asks "when does it end" collects,
a form that asks "does it end on this day" checks.

## deadline — count days on the calendar

```ts
  deadline(
    opArgs: { date: string; days?: number; unit?: 'business_day' | 'calendar_day'; afterTime?: string; policy?: unknown; suspensions?: Array<{ start: string; end: string }> },
    caseInput: CaseInput,
  ): Promise<Answer>;
```

```python
def deadline(self, op_args: dict[str, Any], case_input: dict[str, Any]) -> Answer: ...
```

Use `deadline` for the calendar operation itself: a start date plus a
number of days under a counting policy. The policy defaults to the
case's `deadlinePolicy`. Python sends the operation as
`{"op": "deadline", **op_args}`. The answer carries the computed date
in `value`.

## calc — evaluate a term

```ts
calc(term: unknown, caseInput: CaseInput): Promise<Answer>;
```

```python
def calc(self, term: Any, case_input: dict[str, Any]) -> Answer: ...
```

Use `calc` to evaluate a term — an amount, a comparison, an aggregate
over the case — without asking a predicate. The term travels in the
request and the answer carries its value. A term that needs the case's
counting policy reads `deadlinePolicy` from the context.

## positions — what the case requires

```ts
positions(caseInput: CaseInput): Promise<Answer>;
```

```python
def positions(self, case_input: dict[str, Any]) -> Answer: ...
```

Use `positions` to list the duties the facts give rise to and their
statuses, without naming a predicate. The answer carries them in
`positions` on the Python shape and in the value on the TypeScript
shape.

## unfold and questions — no case needed

```ts
unfold(predicate: Rel | string, options?: { lang?: string; depth?: number; quote?: number; fold?: boolean }): { tree: unknown; text: string };
questions(lang?: string): FormManifest;
```

Neither executes a rule. `unfold` returns the tree of producers of a
predicate over the package's world — every rule, its strength, the
provision it is anchored to, and the facts it needs — plus the text
the engine prints for it. `questions` returns the canon's inventory:
the questions that can be asked, the facts that can be supplied, their
parameters with types and widgets, and the author's labels. Both are
TypeScript-only; Python reads the inventory at author time instead, as
the Python chapter describes.

## Which kinds exist where

| Kind | TypeScript | Python |
|---|---|---|
| `truth` | `truth` | `truth` |
| `focused_truth` | `focusedTruth` | — |
| `why_not` | `whyNot` | `why_not` / `whyNot` |
| `collect` | `collect` | `collect` |
| `calendar_op` | `deadline` | `deadline` |
| `term` | `calc` | `calc` |
| `positions` | `positions` | `positions` |
| `unfold` | `unfold` | — |
| manifest | `questions` | — (author-time workaround) |

## Limits

- `collect` needs exactly one free position: `?name` inline or an
  explicit `free`.
- `deadline` without a policy — neither in the operation nor in the
  case — answers that the policy is missing; the engine never assumes
  how days are counted.
- `focused_truth` answers are slices: same verdict, reduced proof, no
  full result hash.