/** * Sentient Loop Propose Tick — Single-pass Tier-2 proposal generator. * * Runs inside the daemon cron (every 2 hours) or standalone via * `cleo sentient propose run`. Orchestrates the three ingesters, * deduplicates candidates by fingerprint, applies the DB-enforced * rate limit, and writes accepted candidates as tasks with * `status='proposed'` and labels including `'sentient-tier2'`. * * Scoped IN: * - Ingest from brain.db, nexus.db, and .cleo/audit/gates.jsonl * - Transactional rate-limit check (BEGIN IMMEDIATE + COUNT + INSERT) * - Kill-switch re-check at each checkpoint (Round 2 audit §9) * - tier2Enabled guard (default false — owner opt-in) * - Auto-promotion scan: proposals exceeding weight threshold that pass * the classifyReadiness grill gate transition proposed→pending automatically * (E7-CLOSE-LOOPS T11499 AC1) * * Scoped OUT: * - LLM calls (NONE — all proposal titles are structured templates) * - Tier-3 sandbox/merge (blocked on T992+T993+T995) * * Title format enforcement: * All proposal titles MUST match `/^\[T2-(BRAIN|NEXUS|TEST)\]/`. * This is the prompt-injection defence from T1008 §3.6 — no freeform * LLM text can enter the task title column from the Tier-2 proposer. * * @task T1008 * @task T11499 E7-CLOSE-LOOPS — Tier-2 auto-promotion + cleo classify * @see ADR-054 — Sentient Loop Tier-2 */ /** * Regex that ALL proposal titles MUST match. * Enforces structured-template-only output (no freeform LLM text). */ export declare const PROPOSAL_TITLE_PATTERN: RegExp; /** * Label applied to every Tier-2 proposal task. * Used by the rate limiter to identify proposals. */ export declare const TIER2_LABEL = "sentient-tier2"; /** * Minimum proposal weight required for auto-promotion consideration. * * Proposals below this threshold remain in `proposed` status and require * manual `cleo sentient propose accept` to enter the Tier-1 run queue. * * The value 0.7 corresponds to the 70th-percentile weight signal (combined * brain citation density + nexus coupling score) surfaced by the ingesters. * * @task T11499 E7-CLOSE-LOOPS */ export declare const TIER2_AUTO_PROMOTE_WEIGHT_THRESHOLD: 0.7; /** * Maximum number of proposals auto-promoted in a single scan pass. * * Guards against bulk promotions flooding the Tier-1 run queue when a * BRAIN reconciler sweep suddenly raises many candidates above the threshold. * * @task T11499 E7-CLOSE-LOOPS */ export declare const TIER2_AUTO_PROMOTE_MAX_PER_PASS: 5; /** Discriminant for the propose-tick outcome. */ export type ProposalTickOutcomeKind = 'killed' | 'disabled' | 'rate-limited' | 'no-candidates' | 'wrote' | 'error'; /** Structured outcome of a single propose-tick pass. */ export interface ProposeTickOutcome { /** Discriminant describing how the tick ended. */ kind: ProposalTickOutcomeKind; /** Number of proposals written in this pass. */ written: number; /** Current daily proposal count at the end of the pass. */ count: number; /** Human-readable detail (one line). */ detail: string; } /** Options for {@link runProposeTick}. */ export interface ProposeTickOptions { /** Absolute path to the project root (contains `.cleo/`). */ projectRoot: string; /** Absolute path to sentient-state.json. */ statePath: string; /** * Override for the brain DB handle. Injected by tests to avoid * opening a real brain.db. When omitted the real getBrainNativeDb() is used. */ brainDb?: import('node:sqlite').DatabaseSync | null; /** * Override for the nexus DB handle. Injected by tests. * When omitted the real getNexusNativeDb() is used. */ nexusDb?: import('node:sqlite').DatabaseSync | null; /** * Override for the tasks DB handle (used by rate limiter + INSERT). * Injected by tests. When omitted the real getNativeTasksDb() is used. */ tasksDb?: import('node:sqlite').DatabaseSync | null; /** * Override the task ID allocator. Injected by tests. * When omitted the real allocateNextTaskId() is used. */ allocateTaskId?: () => Promise; } /** * Run a single Tier-2 propose pass. * * Steps: * 1. Check killSwitch → abort if true * 2. Check tier2Enabled → abort if false * 3. Run all three ingesters in parallel * 4. Check killSwitch again (post-ingest checkpoint) * 5. Merge + deduplicate candidates by fingerprint * 6. Validate title format (must match PROPOSAL_TITLE_PATTERN) * 7. Score + take top-N candidates (N = limit - countTodayProposals) * 8. Check killSwitch again (pre-write checkpoint) * 9. For each candidate: transactional INSERT into tasks.db * 10. Update tier2Stats in state * * @param options - Propose tick options (see {@link ProposeTickOptions}) * @returns Structured outcome describing how the pass ended. */ export declare function runProposeTick(options: ProposeTickOptions): Promise; /** * Safe wrapper for {@link runProposeTick} — swallows unexpected exceptions. * Used by the daemon cron handler. * * @param options - Propose tick options * @returns The propose tick outcome, or an error outcome if the tick threw. */ export declare function safeRunProposeTick(options: ProposeTickOptions): Promise; /** * Outcome of a single auto-promotion scan pass. * * @task T11499 E7-CLOSE-LOOPS */ export interface AutoPromoteOutcome { /** Number of proposals promoted to `pending` in this pass. */ promoted: number; /** Number of proposals inspected (above weight threshold). */ scanned: number; /** Number of proposals grilled (blocked by classifyReadiness). */ grilled: number; /** Human-readable summary. */ detail: string; } /** * Options for {@link runProposalAutoPromoteScan}. * * @task T11499 E7-CLOSE-LOOPS */ export interface AutoPromoteScanOptions { /** Absolute path to the project root (contains `.cleo/`). */ projectRoot: string; /** Absolute path to sentient-state.json. */ statePath: string; /** * Override for the tasks DB handle (used by SELECT + UPDATE). * When omitted, the real `getNativeTasksDb()` is used. */ tasksDb?: import('node:sqlite').DatabaseSync | null; /** * Weight threshold for auto-promotion candidacy. * Proposals whose stored `weight` is below this value are skipped. * Defaults to {@link TIER2_AUTO_PROMOTE_WEIGHT_THRESHOLD} (0.7). */ weightThreshold?: number; /** * Maximum proposals to promote per pass. * Defaults to {@link TIER2_AUTO_PROMOTE_MAX_PER_PASS} (5). */ maxPerPass?: number; } /** * Scan all `proposed` Tier-2 tasks and auto-promote those that: * 1. Have a proposal weight ≥ `weightThreshold` (default 0.7), AND * 2. Pass the {@link classifyReadiness} grill gate — i.e. verdict `'proceed'`. * * Promotes eligible tasks from `proposed` → `pending` so they enter the * Tier-1 run queue without requiring manual `cleo sentient propose accept`. * This closes the BRAIN learning loop (E7-CLOSE-LOOPS T11499 AC1). * * **Grill gate semantics**: `classifyReadiness` checks five triggers * (MISSING_AC, OWNER_DECISION_REQUIRED, IVTR_MAX_RETRIES, RELEASE_GATE, * AMBIGUOUS_SCOPE). A proposal that fires any trigger is left in `proposed` * status and counted in the `grilled` field so callers can surface it. * * **Kill-switch respected**: if the sentient kill-switch is active no * promotions are attempted and the function returns immediately. * * **Pure DB path**: no ingesters are invoked. The scan reads existing * `proposed` tasks directly from `tasks.db` via the junction query. * * @param options - Scan options (see {@link AutoPromoteScanOptions}). * @returns Structured outcome describing how many proposals were promoted. * * @task T11499 E7-CLOSE-LOOPS AC1 */ export declare function runProposalAutoPromoteScan(options: AutoPromoteScanOptions): Promise; /** * Safe wrapper for {@link runProposalAutoPromoteScan} — swallows unexpected exceptions. * * @param options - Scan options * @returns Structured outcome, or an error-annotated outcome if the scan threw. * @task T11499 E7-CLOSE-LOOPS AC1 */ export declare function safeRunProposalAutoPromoteScan(options: AutoPromoteScanOptions): Promise; //# sourceMappingURL=propose-tick.d.ts.map