botinabox 1.4.2 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,6 +5,12 @@ A modular TypeScript framework for building multi-agent bots with LLM orchestrat
5
5
  ## Features
6
6
 
7
7
  - **Multi-agent orchestration** -- Define agents with different models, roles, and execution adapters. Task queue with priority scheduling, retry policies, and followup chains.
8
+ - **Two-tier agents** -- Deterministic adapter for tasks that don't need LLM reasoning (routing, validation, data fetching). API and CLI adapters for LLM-driven tasks.
9
+ - **Triage routing** -- Content-aware message routing with keyword/regex matching, priority rules, and LLM fallback for ambiguous messages. Ownership chain logging for every routing decision.
10
+ - **Loop detection and circuit breakers** -- Pattern-based loop detection (self-loops, ping-pong, blocked re-entry) plus circuit breakers with automatic human escalation when agents fail repeatedly.
11
+ - **Learning pipeline** -- Structured feedback capture with auto-promotion: 3+ similar feedback records become a playbook, playbooks used by 3+ agents become reusable skills. Two-axis scoring (accuracy + efficiency).
12
+ - **Governance gates** -- Independent QA, quality, and drift gates that validate agent output and report to the human operator. Gates run independently and cannot override each other.
13
+ - **Permission relay** -- Remote approval for unattended agents via messaging platforms (Slack, Discord, Telegram). Dual approval: local terminal and remote, first response wins.
8
14
  - **LLM provider abstraction** -- Swap between Anthropic, OpenAI, and Ollama with a unified interface. Model aliasing, purpose-based routing, and fallback chains.
9
15
  - **Channel adapters** -- Connect to Slack, Discord, and webhooks. Auto-discovery, session management, and notification queuing.
10
16
  - **Workflow engine** -- Define multi-step workflows with dependency resolution, parallel execution, and conditional branching.
@@ -15,8 +21,6 @@ A modular TypeScript framework for building multi-agent bots with LLM orchestrat
15
21
  - **Connectors** -- Generic `Connector<T>` interface for external service integrations. Ships with Google Gmail and Calendar implementations (OAuth2 and service account auth).
16
22
  - **Domain tables** -- `defineDomainTables()` and `defineDomainEntityContexts()` for standard multi-agent app schemas (org, project, client, invoice, repository, and more).
17
23
  - **Auto-update** -- `autoUpdate()` checks npm for newer versions and installs them at startup.
18
- - **Cursor persistence** -- `SecretStore.loadCursor()` / `saveCursor()` for persisting sync state across restarts.
19
- - **Utilities** -- `truncateAtWord()` for word-boundary text truncation, `parseClaudeStream()`, `buildProcessEnv()`, and more.
20
24
  - **Security** -- Input sanitization, field length enforcement, audit logging, and HMAC webhook verification.
21
25
 
22
26
  ## Install
@@ -128,10 +132,10 @@ hooks.register('run.completed', async (ctx) => {
128
132
  |
129
133
  +--------------------+--------------------+
130
134
  v v v
131
- +------------------+ +------------------+ +---------------+
132
- | CLI Adapter | | API Adapter | | Custom |
133
- | (subprocess) | | (LLM + tools) | | Adapters |
134
- +------------------+ +--------+----------+ +---------------+
135
+ +------------------+ +------------------+ +------------------+
136
+ | CLI Adapter | | API Adapter | | Deterministic |
137
+ | (subprocess) | | (LLM + tools) | | (no LLM) |
138
+ +------------------+ +--------+----------+ +------------------+
135
139
  |
136
140
  +--------------v-----------------------+
137
141
  | LLM Layer |
package/dist/index.d.ts CHANGED
@@ -848,14 +848,95 @@ declare class MessagePipeline {
848
848
  /**
849
849
  * Chat routing — maps channel/scope to agentId.
850
850
  * Story 4.2
851
+ *
852
+ * @deprecated Use TriageRouter for content-aware routing with keyword/regex
853
+ * matching and LLM fallback. This static channel→agent binding is kept for
854
+ * backward compatibility only. See `./triage-router.ts`.
851
855
  */
852
856
 
853
857
  /**
854
858
  * Build a map from channel identifier to agentId.
855
859
  * Each agent may have a config.channel or config.channels binding.
860
+ *
861
+ * @deprecated Use TriageRouter instead — it supports keyword, regex,
862
+ * and LLM-based routing with ownership chain logging.
856
863
  */
857
864
  declare function buildAgentBindings(agents: AgentConfig[]): Map<string, string>;
858
865
 
866
+ /**
867
+ * TriageRouter — content-based routing with deterministic-first resolution.
868
+ * Story 6.3
869
+ *
870
+ * Replaces the simple channel→agent binding with intelligent routing:
871
+ * 1. Keyword/regex rules evaluated first (deterministic, ~4ms)
872
+ * 2. LLM classification only for ambiguous messages (async, ~2-4s)
873
+ * 3. Ownership chain logged for every routing decision
874
+ *
875
+ * Key constraint: specialists return to triage, never to another specialist.
876
+ */
877
+
878
+ interface RoutingRule {
879
+ /** Target agent slug */
880
+ agentSlug: string;
881
+ /** Keywords that trigger this rule (case-insensitive) */
882
+ keywords?: string[];
883
+ /** Regex patterns that trigger this rule */
884
+ patterns?: string[];
885
+ /** Priority — lower number wins ties. Default: 50 */
886
+ priority?: number;
887
+ }
888
+ interface RoutingDecision {
889
+ timestamp: string;
890
+ source: string;
891
+ target: string;
892
+ reason: string;
893
+ method: 'deterministic' | 'llm';
894
+ messageId?: string;
895
+ channel?: string;
896
+ }
897
+ interface TriageRouterConfig {
898
+ /** Static routing rules evaluated deterministically */
899
+ rules: RoutingRule[];
900
+ /** Fallback agent if no rule matches and LLM is unavailable */
901
+ fallbackAgent?: string;
902
+ /** Whether to use LLM for ambiguous messages. Default: true */
903
+ llmFallback?: boolean;
904
+ /** Log decisions to the database. Default: true */
905
+ persist?: boolean;
906
+ }
907
+ declare class TriageRouter {
908
+ private db;
909
+ private hooks;
910
+ private readonly rules;
911
+ private readonly fallbackAgent?;
912
+ private readonly llmFallback;
913
+ private readonly persist;
914
+ private readonly compiledRules;
915
+ constructor(db: DataStore, hooks: HookBus, config: TriageRouterConfig);
916
+ /**
917
+ * Route an inbound message to the best agent.
918
+ * Returns the agent slug and the routing decision.
919
+ */
920
+ route(msg: InboundMessage): Promise<{
921
+ agentSlug: string | undefined;
922
+ decision: RoutingDecision;
923
+ }>;
924
+ /**
925
+ * Query the ownership chain for a given message or channel.
926
+ */
927
+ getDecisionHistory(filter?: {
928
+ channel?: string;
929
+ limit?: number;
930
+ }): Promise<RoutingDecision[]>;
931
+ /**
932
+ * LLM classification — emits a hook for external LLM integration.
933
+ * Returns agent slug + reason, or undefined if LLM is unavailable.
934
+ */
935
+ private classifyWithLLM;
936
+ private buildDecision;
937
+ private logDecision;
938
+ }
939
+
859
940
  /**
860
941
  * Chat policy helpers — allowlist and mention gate checks.
861
942
  * Story 4.2
@@ -1233,6 +1314,71 @@ declare function autoUpdate(packages?: string[], opts?: {
1233
1314
  quiet?: boolean;
1234
1315
  }): Promise<UpdateResult>;
1235
1316
 
1317
+ /**
1318
+ * CircuitBreaker — prevents runaway agent failures with automatic escalation.
1319
+ * Story 6.2
1320
+ *
1321
+ * States:
1322
+ * CLOSED → normal operation, failures counted
1323
+ * OPEN → tripped, all executions blocked, escalated to human
1324
+ * HALF_OPEN → probe mode, one execution allowed to test recovery
1325
+ *
1326
+ * Integrates with LoopDetector and RunManager via HookBus events.
1327
+ */
1328
+
1329
+ declare enum BreakerState {
1330
+ CLOSED = "closed",
1331
+ OPEN = "open",
1332
+ HALF_OPEN = "half_open"
1333
+ }
1334
+ interface CircuitBreakerConfig {
1335
+ /** Failures before tripping. Default: 3 */
1336
+ failureThreshold?: number;
1337
+ /** Milliseconds to wait before half-open probe. Default: 300_000 (5 min) */
1338
+ resetTimeoutMs?: number;
1339
+ /** Log events to the database. Default: true */
1340
+ persist?: boolean;
1341
+ }
1342
+ declare class CircuitBreaker {
1343
+ private db;
1344
+ private hooks;
1345
+ private readonly breakers;
1346
+ private readonly failureThreshold;
1347
+ private readonly resetTimeoutMs;
1348
+ private readonly persist;
1349
+ constructor(db: DataStore, hooks: HookBus, config?: CircuitBreakerConfig);
1350
+ /**
1351
+ * Check if an agent is allowed to execute.
1352
+ * Returns true if execution is allowed, false if circuit is open.
1353
+ */
1354
+ canExecute(agentId: string): boolean;
1355
+ /**
1356
+ * Record a successful execution. Resets the breaker to CLOSED.
1357
+ */
1358
+ recordSuccess(agentId: string): Promise<void>;
1359
+ /**
1360
+ * Record a failed execution. Increments failure count and may trip breaker.
1361
+ */
1362
+ recordFailure(agentId: string, reason?: string): Promise<void>;
1363
+ /**
1364
+ * Trip the breaker to OPEN state and escalate to human.
1365
+ */
1366
+ trip(agentId: string, reason: string): Promise<void>;
1367
+ /**
1368
+ * Manually reset a breaker (e.g. after human review).
1369
+ */
1370
+ reset(agentId: string): Promise<void>;
1371
+ /**
1372
+ * Get the current state of a breaker.
1373
+ */
1374
+ getState(agentId: string): BreakerState;
1375
+ /**
1376
+ * Get failure count for an agent.
1377
+ */
1378
+ getFailureCount(agentId: string): number;
1379
+ private logEvent;
1380
+ }
1381
+
1236
1382
  declare class RunManager {
1237
1383
  private db;
1238
1384
  private hooks;
@@ -1240,10 +1386,15 @@ declare class RunManager {
1240
1386
  private locks;
1241
1387
  private orphanTimer;
1242
1388
  private readonly staleThresholdMs;
1389
+ private circuitBreaker?;
1243
1390
  constructor(db: DataStore, hooks: HookBus, config?: {
1244
1391
  staleThresholdMs?: number;
1245
1392
  maxBackoffMs?: number;
1246
1393
  } | undefined);
1394
+ /**
1395
+ * Attach a CircuitBreaker to prevent retries on broken agents.
1396
+ */
1397
+ setCircuitBreaker(cb: CircuitBreaker): void;
1247
1398
  isLocked(agentId: string): boolean;
1248
1399
  startRun(agentId: string, taskId: string, adapter?: string): Promise<string>;
1249
1400
  finishRun(runId: string, result: {
@@ -1508,6 +1659,387 @@ declare class CliExecutionAdapter {
1508
1659
  }>;
1509
1660
  }
1510
1661
 
1662
+ /**
1663
+ * DeterministicAdapter — executes scripts without LLM calls.
1664
+ * Story 6.1
1665
+ *
1666
+ * For tasks that don't require reasoning: routing, validation,
1667
+ * data fetching, file transforms. Runs a user-specified command
1668
+ * (Python, Node, bash) as a subprocess with task context on stdin.
1669
+ */
1670
+ interface DeterministicConfig {
1671
+ command: string;
1672
+ args?: string[];
1673
+ env?: Record<string, string>;
1674
+ timeoutMs?: number;
1675
+ inputMode?: 'stdin' | 'arg';
1676
+ }
1677
+ declare class DeterministicAdapter {
1678
+ readonly type = "deterministic";
1679
+ execute(ctx: {
1680
+ agent: {
1681
+ id: string;
1682
+ cwd?: string;
1683
+ adapter_config?: string;
1684
+ };
1685
+ task: {
1686
+ title: string;
1687
+ description?: string;
1688
+ context?: string;
1689
+ };
1690
+ abortSignal?: AbortSignal;
1691
+ onLog?: (stream: string, chunk: string) => void;
1692
+ }): Promise<{
1693
+ output: string;
1694
+ exitCode: number;
1695
+ }>;
1696
+ }
1697
+
1698
+ /**
1699
+ * LoopDetector — pattern-based loop detection for agent routing.
1700
+ * Story 6.2
1701
+ *
1702
+ * Complements chain-guard's depth limit with active pattern detection:
1703
+ * - Self-loop: agent routes a task back to itself
1704
+ * - Ping-pong: two agents bounce tasks between each other (A→B→A→B)
1705
+ * - Blocked re-entry: a task re-enters the system after being blocked
1706
+ */
1707
+
1708
+ declare enum LoopType {
1709
+ SELF_LOOP = "self_loop",
1710
+ PING_PONG = "ping_pong",
1711
+ BLOCKED_REENTRY = "blocked_reentry"
1712
+ }
1713
+ interface LoopDetection {
1714
+ type: LoopType;
1715
+ agents: string[];
1716
+ taskId: string;
1717
+ chainOriginId?: string;
1718
+ message: string;
1719
+ }
1720
+ interface LoopDetectorConfig {
1721
+ /** Number of recent followup records to scan. Default: 10 */
1722
+ windowSize?: number;
1723
+ /** Minimum repetitions to confirm ping-pong. Default: 2 */
1724
+ pingPongThreshold?: number;
1725
+ }
1726
+ declare class LoopDetector {
1727
+ private db;
1728
+ private readonly windowSize;
1729
+ private readonly pingPongThreshold;
1730
+ constructor(db: DataStore, config?: LoopDetectorConfig);
1731
+ /**
1732
+ * Check for loops before creating a followup task.
1733
+ * Returns a LoopDetection if a loop pattern is found, undefined otherwise.
1734
+ */
1735
+ check(sourceAgentId: string, targetAgentId: string, taskId: string, chainOriginId?: string): Promise<LoopDetection | undefined>;
1736
+ /**
1737
+ * Check if an agent is routing to itself.
1738
+ */
1739
+ private checkSelfLoop;
1740
+ /**
1741
+ * Check if a previously blocked task is being re-entered.
1742
+ */
1743
+ private checkBlockedReentry;
1744
+ /**
1745
+ * Check for A→B→A→B ping-pong by scanning recent tasks in the chain.
1746
+ */
1747
+ private checkPingPong;
1748
+ }
1749
+
1750
+ /**
1751
+ * LearningPipeline — turns execution experience into durable knowledge.
1752
+ * Story 6.5
1753
+ *
1754
+ * Promotion ladder:
1755
+ * Execution → Feedback (structured capture)
1756
+ * → 3+ similar → Playbook (generalized rule)
1757
+ * → 3+ projects → Skill (executable behavior)
1758
+ * → Agent-Skill Matrix → Per-Agent Context
1759
+ *
1760
+ * Two-axis evaluation:
1761
+ * - Accuracy: was the output correct?
1762
+ * - Efficiency: how fast / how many tokens?
1763
+ */
1764
+
1765
+ interface FeedbackEntry {
1766
+ agentId: string;
1767
+ taskId?: string;
1768
+ issue: string;
1769
+ rootCause?: string;
1770
+ severity: 'low' | 'medium' | 'high' | 'critical';
1771
+ repeatable: boolean;
1772
+ accuracyScore?: number;
1773
+ efficiencyScore?: number;
1774
+ tags?: string[];
1775
+ }
1776
+ interface PlaybookEntry {
1777
+ pattern: string;
1778
+ rule: string;
1779
+ feedbackIds: string[];
1780
+ projectScoped: boolean;
1781
+ agentIds?: string[];
1782
+ }
1783
+ interface SkillEntry {
1784
+ name: string;
1785
+ slug: string;
1786
+ description?: string;
1787
+ behavior: string;
1788
+ sourcePlaybookIds: string[];
1789
+ category?: string;
1790
+ }
1791
+ interface LearningPipelineConfig {
1792
+ /** Feedback count threshold for playbook promotion. Default: 3 */
1793
+ playbookThreshold?: number;
1794
+ /** Project count threshold for skill promotion. Default: 3 */
1795
+ skillThreshold?: number;
1796
+ /** Auto-promote when thresholds are met. Default: false */
1797
+ autoPromote?: boolean;
1798
+ }
1799
+ declare class LearningPipeline {
1800
+ private db;
1801
+ private hooks;
1802
+ private readonly playbookThreshold;
1803
+ private readonly skillThreshold;
1804
+ private readonly autoPromote;
1805
+ constructor(db: DataStore, hooks: HookBus, config?: LearningPipelineConfig);
1806
+ /**
1807
+ * Capture a structured feedback record from an execution.
1808
+ */
1809
+ captureFeedback(entry: FeedbackEntry): Promise<string>;
1810
+ /**
1811
+ * Get all feedback records, optionally filtered.
1812
+ */
1813
+ listFeedback(filter?: {
1814
+ agentId?: string;
1815
+ severity?: string;
1816
+ repeatable?: boolean;
1817
+ }): Promise<Array<Record<string, unknown>>>;
1818
+ /**
1819
+ * Check if feedback records with similar issues should be promoted to a playbook.
1820
+ * Groups by issue text similarity (exact match for now).
1821
+ */
1822
+ checkPlaybookPromotion(issue: string): Promise<string | undefined>;
1823
+ /**
1824
+ * Manually create a playbook from a set of feedback records.
1825
+ */
1826
+ promoteToPlaybook(entry: PlaybookEntry): Promise<string>;
1827
+ /**
1828
+ * List playbooks, optionally filtered.
1829
+ */
1830
+ listPlaybooks(filter?: {
1831
+ projectScoped?: boolean;
1832
+ }): Promise<Array<Record<string, unknown>>>;
1833
+ /**
1834
+ * Check if a playbook should be promoted to a skill.
1835
+ * A playbook becomes a skill when it works across multiple projects
1836
+ * (indicated by being referenced by agents in different contexts).
1837
+ */
1838
+ checkSkillPromotion(playbookId: string): Promise<string | undefined>;
1839
+ /**
1840
+ * Manually promote a playbook to a reusable skill.
1841
+ */
1842
+ promoteToSkill(entry: SkillEntry): Promise<string>;
1843
+ /**
1844
+ * Assign a skill to an agent.
1845
+ */
1846
+ assignSkill(agentId: string, skillId: string): Promise<void>;
1847
+ /**
1848
+ * Get learning metrics for an agent.
1849
+ */
1850
+ getMetrics(agentId: string): Promise<{
1851
+ feedbackCount: number;
1852
+ avgAccuracy: number | null;
1853
+ avgEfficiency: number | null;
1854
+ playbookCount: number;
1855
+ skillCount: number;
1856
+ }>;
1857
+ }
1858
+
1859
+ /**
1860
+ * PermissionRelay — remote approval for unattended agent execution.
1861
+ * Story 6.6
1862
+ *
1863
+ * When an agent needs human approval but the operator is away:
1864
+ * 1. Post the approval prompt to a messaging platform (Slack, Discord, etc.)
1865
+ * 2. Poll for response (approve/deny)
1866
+ * 3. Relay the decision back to the agent
1867
+ *
1868
+ * Dual approval: local terminal + remote messaging. First response wins.
1869
+ * Race condition handled by atomic state transition.
1870
+ */
1871
+
1872
+ type ApprovalStatus = 'pending' | 'approved' | 'denied' | 'expired';
1873
+ interface PermissionPrompt {
1874
+ id: string;
1875
+ agentId: string;
1876
+ action: string;
1877
+ context?: string;
1878
+ requestedAt: string;
1879
+ expiresAt?: string;
1880
+ }
1881
+ interface ApprovalResponse {
1882
+ promptId: string;
1883
+ status: 'approved' | 'denied';
1884
+ respondedBy: string;
1885
+ respondedAt: string;
1886
+ comment?: string;
1887
+ }
1888
+ /**
1889
+ * Provider interface — implement for each messaging platform.
1890
+ */
1891
+ interface PermissionProvider {
1892
+ readonly id: string;
1893
+ /** Post an approval request, return a handle for polling. */
1894
+ sendPrompt(prompt: PermissionPrompt): Promise<string>;
1895
+ /** Check for a response. Returns undefined if still pending. */
1896
+ pollResponse(handle: string): Promise<ApprovalResponse | undefined>;
1897
+ /** Cancel a pending prompt (e.g. after local approval). */
1898
+ cancelPrompt(handle: string): Promise<void>;
1899
+ }
1900
+ interface PermissionRelayConfig {
1901
+ /** Registered providers (e.g. Slack, Discord adapters) */
1902
+ providers: PermissionProvider[];
1903
+ /** Poll interval in ms. Default: 5000 */
1904
+ pollIntervalMs?: number;
1905
+ /** Timeout for pending approvals in ms. Default: 300_000 (5 min) */
1906
+ timeoutMs?: number;
1907
+ }
1908
+ declare class PermissionRelay {
1909
+ private hooks;
1910
+ private readonly providers;
1911
+ private readonly pollIntervalMs;
1912
+ private readonly timeoutMs;
1913
+ private readonly pending;
1914
+ constructor(hooks: HookBus, config: PermissionRelayConfig);
1915
+ /**
1916
+ * Request approval from all configured providers.
1917
+ * Returns when the first provider responds (approve or deny).
1918
+ */
1919
+ requestApproval(prompt: PermissionPrompt): Promise<ApprovalResponse>;
1920
+ /**
1921
+ * Provide a local approval (from terminal).
1922
+ * Resolves the pending request and cancels remote providers.
1923
+ */
1924
+ approveLocally(promptId: string, approved: boolean): Promise<void>;
1925
+ /**
1926
+ * Get all pending approval requests.
1927
+ */
1928
+ getPending(): PermissionPrompt[];
1929
+ private cancelOtherProviders;
1930
+ }
1931
+
1932
+ /**
1933
+ * GovernanceGate — independent validation gates for agent output.
1934
+ * Story 6.7
1935
+ *
1936
+ * Key principle: gates report to the HUMAN, not to each other
1937
+ * or to a project manager agent. Structural independence prevents capture.
1938
+ *
1939
+ * Gate dimensions:
1940
+ * QA — data correctness (schema, row counts, format)
1941
+ * Quality — code quality (lint, coverage, patterns)
1942
+ * Drift — architectural drift (unintended dependencies, scope creep)
1943
+ */
1944
+
1945
+ type GateVerdict = 'pass' | 'fail' | 'warn';
1946
+ interface GateResult {
1947
+ gateId: string;
1948
+ verdict: GateVerdict;
1949
+ findings: GateFinding[];
1950
+ checkedAt: string;
1951
+ durationMs: number;
1952
+ }
1953
+ interface GateFinding {
1954
+ severity: 'info' | 'warning' | 'error' | 'critical';
1955
+ message: string;
1956
+ location?: string;
1957
+ suggestion?: string;
1958
+ }
1959
+ interface GateInput {
1960
+ agentId: string;
1961
+ taskId: string;
1962
+ output: string;
1963
+ metadata?: Record<string, unknown>;
1964
+ }
1965
+ /**
1966
+ * Base class for governance gates. Each gate checks a different dimension.
1967
+ * Gates are structurally independent — they report to the human operator,
1968
+ * not to each other or to any agent.
1969
+ */
1970
+ declare abstract class GovernanceGate {
1971
+ abstract readonly id: string;
1972
+ abstract readonly name: string;
1973
+ abstract readonly dimension: string;
1974
+ /**
1975
+ * Run the gate check on agent output.
1976
+ * Must return a verdict and any findings.
1977
+ */
1978
+ abstract check(input: GateInput): Promise<GateResult>;
1979
+ }
1980
+ /**
1981
+ * QA Gate — validates data correctness.
1982
+ * Checks: schema conformance, row counts, format validation.
1983
+ */
1984
+ declare class QAGate extends GovernanceGate {
1985
+ private validators;
1986
+ readonly id = "qa";
1987
+ readonly name = "Quality Assurance";
1988
+ readonly dimension = "data_correctness";
1989
+ constructor(validators?: Array<{
1990
+ name: string;
1991
+ validate: (output: string, metadata?: Record<string, unknown>) => GateFinding[];
1992
+ }>);
1993
+ check(input: GateInput): Promise<GateResult>;
1994
+ }
1995
+ /**
1996
+ * Quality Gate — validates code quality.
1997
+ * Checks: lint results, test coverage, review patterns.
1998
+ */
1999
+ declare class QualityGate extends GovernanceGate {
2000
+ private checks;
2001
+ readonly id = "quality";
2002
+ readonly name = "Code Quality";
2003
+ readonly dimension = "code_quality";
2004
+ constructor(checks?: Array<{
2005
+ name: string;
2006
+ check: (output: string, metadata?: Record<string, unknown>) => Promise<GateFinding[]>;
2007
+ }>);
2008
+ check(input: GateInput): Promise<GateResult>;
2009
+ }
2010
+ /**
2011
+ * Drift Gate — detects architectural drift.
2012
+ * Checks: unintended dependencies, scope creep, pattern violations.
2013
+ */
2014
+ declare class DriftGate extends GovernanceGate {
2015
+ private rules;
2016
+ readonly id = "drift";
2017
+ readonly name = "Architectural Drift";
2018
+ readonly dimension = "architecture";
2019
+ constructor(rules?: Array<{
2020
+ name: string;
2021
+ detect: (output: string, metadata?: Record<string, unknown>) => GateFinding[];
2022
+ }>);
2023
+ check(input: GateInput): Promise<GateResult>;
2024
+ }
2025
+ /**
2026
+ * GateRunner — orchestrates multiple independent gates on agent output.
2027
+ * Each gate runs independently. Results are reported to the human, not to agents.
2028
+ */
2029
+ declare class GateRunner {
2030
+ private gates;
2031
+ private hooks;
2032
+ constructor(gates: GovernanceGate[], hooks: HookBus);
2033
+ /**
2034
+ * Run all gates on the given input.
2035
+ * Gates run independently — one failure doesn't block others.
2036
+ */
2037
+ runAll(input: GateInput): Promise<{
2038
+ passed: boolean;
2039
+ results: GateResult[];
2040
+ }>;
2041
+ }
2042
+
1511
2043
  interface SecretInput {
1512
2044
  name: string;
1513
2045
  type?: string;
@@ -1596,4 +2128,4 @@ declare function isLoginRequired(stdout: string): boolean;
1596
2128
  /** Rewrite local image paths to prevent CLI auto-embedding as vision content. */
1597
2129
  declare function deactivateLocalImagePaths(prompt: string): string;
1598
2130
 
1599
- export { AGENT_STATUSES, type AgentConfig, type AgentDefinition, type AgentFilter, type AgentRecord, AgentRegistry, type AgentStatus, ApiExecutionAdapter, AuditEmitter, type AuditEvent, BackupManager, type BotConfig, type BudgetCheck, type BudgetConfig, BudgetController, CORE_MIGRATIONS, ChannelAdapter, ChannelRegistry, ChannelRegistryError, ChatMessage, ChatSessionManager, CliExecutionAdapter, type ColumnValidator, ColumnValidatorImpl, type ConfigLoadError, type ConfigLoadResult, ConnectorConfig, DEFAULTS, DEFAULT_CONFIG, type DataConfig, DataStore, DataStoreError, type DomainEntityContextOptions, type DomainSchemaOptions, EVENTS, type EntityColumnDef, type EntityConfig, type EntityContextDef, type EntityFileSpec, type EntitySource, type ExecutionAdapter, type Filter, HealthStatus, HookBus, type HookHandler, type HookOptions, type HookRegistration, InboundMessage, LLMProvider, MAX_CHAIN_DEPTH, MessagePipeline, type ModelConfig, ModelInfo, ModelRouter, NdjsonLogger, NotificationQueue, type PackageMigration, type PackageUpdate, type ParsedStream, type PkLookup, ProviderRegistry, type QueryOptions, RUN_STATUSES, type RelationDef, type RenderConfig, ResolvedModel, type RetryPolicy, type Row, type RunContext, RunManager, type RunResult, type RunStatus, type SanitizerOptions, type Schedule, type ScheduleDef, Scheduler, type SchemaError, type SecretInput, type SecretMeta, SecretStore, type SecurityConfig, type SeedItem, SessionKey, SessionManager, type SqliteAdapter, type StepRef, TASK_STATUSES, type TableDefinition, type TableInfoRow, type TaskDefinition, TaskQueue, type TaskRecord, type TaskStatus, TokenUsage, type Unsubscribe, UpdateChecker, type UpdateConfig, UpdateManager, type UpdateManifest, type UsageSummary, type User, type UserInput, UserRegistry, WakeupQueue, type WorkflowConfigEntry, type WorkflowDefinition$1 as WorkflowDefinition, WorkflowEngine, type WorkflowRunRecord, type WorkflowRunStatus, type WorkflowStep$1 as WorkflowStep, type WorkflowStepConfig, type WorkflowTrigger, _resetConfig, areDependenciesMet, autoUpdate, buildAgentBindings, buildChainOrigin, buildProcessEnv, checkAllowlist, checkChainDepth, checkMentionGate, chunkText, classifyUpdate, compareVersions, createConfigRevision, deactivateLocalImagePaths, defineCoreEntityContexts, defineCoreTables, defineDomainEntityContexts, defineDomainTables, detectCycle, discoverChannels, discoverProviders, formatText, getConfig, initConfig, interpolate, interpolateEnv, isLoginRequired, isMaxTurns, loadConfig, parseClaudeStream, parseVersion, runPackageMigrations, sanitize, topologicalSort, truncateAtWord, validateConfig };
2131
+ export { AGENT_STATUSES, type AgentConfig, type AgentDefinition, type AgentFilter, type AgentRecord, AgentRegistry, type AgentStatus, ApiExecutionAdapter, type ApprovalResponse, type ApprovalStatus, AuditEmitter, type AuditEvent, BackupManager, type BotConfig, BreakerState, type BudgetCheck, type BudgetConfig, BudgetController, CORE_MIGRATIONS, ChannelAdapter, ChannelRegistry, ChannelRegistryError, ChatMessage, ChatSessionManager, CircuitBreaker, type CircuitBreakerConfig, CliExecutionAdapter, type ColumnValidator, ColumnValidatorImpl, type ConfigLoadError, type ConfigLoadResult, ConnectorConfig, DEFAULTS, DEFAULT_CONFIG, type DataConfig, DataStore, DataStoreError, DeterministicAdapter, type DeterministicConfig, type DomainEntityContextOptions, type DomainSchemaOptions, DriftGate, EVENTS, type EntityColumnDef, type EntityConfig, type EntityContextDef, type EntityFileSpec, type EntitySource, type ExecutionAdapter, type FeedbackEntry, type Filter, type GateFinding, type GateInput, type GateResult, GateRunner, type GateVerdict, GovernanceGate, HealthStatus, HookBus, type HookHandler, type HookOptions, type HookRegistration, InboundMessage, LLMProvider, LearningPipeline, type LearningPipelineConfig, type LoopDetection, LoopDetector, type LoopDetectorConfig, LoopType, MAX_CHAIN_DEPTH, MessagePipeline, type ModelConfig, ModelInfo, ModelRouter, NdjsonLogger, NotificationQueue, type PackageMigration, type PackageUpdate, type ParsedStream, type PermissionPrompt, type PermissionProvider, PermissionRelay, type PermissionRelayConfig, type PkLookup, type PlaybookEntry, ProviderRegistry, QAGate, QualityGate, type QueryOptions, RUN_STATUSES, type RelationDef, type RenderConfig, ResolvedModel, type RetryPolicy, type RoutingDecision, type RoutingRule, type Row, type RunContext, RunManager, type RunResult, type RunStatus, type SanitizerOptions, type Schedule, type ScheduleDef, Scheduler, type SchemaError, type SecretInput, type SecretMeta, SecretStore, type SecurityConfig, type SeedItem, SessionKey, SessionManager, type SkillEntry, type SqliteAdapter, type StepRef, TASK_STATUSES, type TableDefinition, type TableInfoRow, type TaskDefinition, TaskQueue, type TaskRecord, type TaskStatus, TokenUsage, TriageRouter, type TriageRouterConfig, type Unsubscribe, UpdateChecker, type UpdateConfig, UpdateManager, type UpdateManifest, type UsageSummary, type User, type UserInput, UserRegistry, WakeupQueue, type WorkflowConfigEntry, type WorkflowDefinition$1 as WorkflowDefinition, WorkflowEngine, type WorkflowRunRecord, type WorkflowRunStatus, type WorkflowStep$1 as WorkflowStep, type WorkflowStepConfig, type WorkflowTrigger, _resetConfig, areDependenciesMet, autoUpdate, buildAgentBindings, buildChainOrigin, buildProcessEnv, checkAllowlist, checkChainDepth, checkMentionGate, chunkText, classifyUpdate, compareVersions, createConfigRevision, deactivateLocalImagePaths, defineCoreEntityContexts, defineCoreTables, defineDomainEntityContexts, defineDomainTables, detectCycle, discoverChannels, discoverProviders, formatText, getConfig, initConfig, interpolate, interpolateEnv, isLoginRequired, isMaxTurns, loadConfig, parseClaudeStream, parseVersion, runPackageMigrations, sanitize, topologicalSort, truncateAtWord, validateConfig };