/** * Deterministic derivation (DES-decision-capture §4.4) — PURE: no I/O, no model, golden-tested. * * Words → exclusions → template → D·G·C·R → key → route. Auto is decided here and ONLY here, from * facts the model cannot set: a human actor, `auth=required`, typed words, a T1/T2 template that * passes D and G, a known project, no redaction, not an approval of a proposal, not a restatement * or a conflict. Model labels can add an offer, or turn an auto into a question (`same_as` → * `maybe-restated`); they can never promote and never swallow a rule silently (review N6). * * The rev-1 template table is not carried in the rev-2 spec text; the six templates below are its * reconstruction from §3/§4.4/§8 (T1 always and T2 never auto-eligible; T3 "X before Y" is the * spec's own offer example), recorded in the PR as an assumption. */ import type { DecisionModelLabels, DecisionRoute, DecisionTemplateId } from './types.js'; import type { SteeringType } from 'wicked-crew-api-types'; /** One in-force rule the derivation compares against (from `considerRules`). */ export interface InForceRule { id: string; statement: string; project?: string; } export interface DeriveInput { words: string; actorKind: 'human' | 'agent' | 'system'; authMode: 'off' | 'required'; wordsSource: 'typed' | 'operator-files' | 'cli-transcript'; projectId: string | null; /** The names the project goes by besides its id (its display name): words naming any of them * scope the rule to the project. */ projectNames?: ReadonlyArray; inForce: ReadonlyArray; /** OTHER projects' in-force rules: an operator-wide rule lands in them too, so a conflict there * takes a person's click (never auto). */ elsewhere?: ReadonlyArray; /** Prior records with the same key (the ledger index); absent = none. */ recurrence?: (key: string) => { count: number; first_at: number; projects: string[]; } | null; labels?: DecisionModelLabels; now?: number; } export interface Derivation { words: string; redacted: boolean; template: DecisionTemplateId | null; exclusions: string[]; dgc: { durable: boolean; general: boolean; checkable: boolean; }; recurrence: { count: number; first_at: number; projects: string[]; }; statement: string | null; polarity: 'do' | 'dont' | null; key: string | null; scope: 'project' | 'everywhere'; steering_type: SteeringType; route: DecisionRoute; /** The in-force rule a restated / maybe-restated decision names, or a conflict contradicts. */ rule_ref?: string; } /** Mask secrets and email addresses. Returns the stored copy and whether anything was masked. */ export declare function scrubWords(words: string): { words: string; redacted: boolean; }; /** The content words of a text: lowercase tokens that are not stopwords, ids, paths or versions. */ export declare function contentWords(text: string): string[]; export declare function exclusionsOf(words: string, hasOpener: boolean, contentCount: number): string[]; export declare function steeringTypeOf(text: string): SteeringType; export declare function keyOf(template: DecisionTemplateId, polarity: 'do' | 'dont', body: string): string; /** The key a stored rule's statement derives to, so a restatement is an exact key match. */ export declare function ruleKey(statement: string): { key: string; polarity: 'do' | 'dont'; subject: string; } | null; export declare function deriveDecision(input: DeriveInput): Derivation; /** Do the words name the project (its id, as a word; `-`/`_` read as spaces)? */ export declare function namesProject(words: string, projectId: string): boolean; //# sourceMappingURL=derive.d.ts.map