# 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; }; ``` ## truth — is the claim established ```ts truth(predicate: Rel, args: FactArg[], caseInput: CaseInput): Promise; ``` ```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; ``` 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; ``` ```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; ``` ```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; ``` ```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; ``` ```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; ``` ```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.