import type { GoalSpec } from "./goal-parser.js"; import type { PersistentGuide } from "./agents-md-loader.js"; /** * v0.4 — 3-tier guardrails per `docs/plan/v0.4-autonomous-engine.md` §4.2. * * Input : 비용·시간·경로 화이트리스트 + immutable. 사이클 진입 전 평가. * Runtime: timeout · discard streak · 누적 비용 cap. 사이클 진행 중 평가. * Output : 외부 부수효과 금지 (메신저 직접 전송 등). 결과 통보는 morning-brief 경유. * * 본 모듈은 *순수 함수* — git 트랜잭션·spawn 호출 없음. goal-runner가 * 사이클 진행 흐름에서 결과를 평가해 행동에 옮긴다. */ export interface ResolvedPaths { /** 자율 실행이 만질 수 있는 경로. AGENTS.md.modifiable_paths ∩ goal.modifiable_paths_override. * override가 비어 있으면 AGENTS.md 기본값 그대로. */ modifiable: string[]; /** 절대 수정 금지 경로. AGENTS.md.immutable_paths + goal source_path 자체. */ immutable: string[]; } export interface InputGuardCheck { ok: boolean; reason?: string; } export interface CostTracker { total_usd: number; per_cycle_usd: Record; } export interface RuntimeGuardCheck { /** Continue the loop, or terminate? */ shouldContinue: boolean; /** Reason emitted when shouldContinue=false. */ reason?: string; /** True iff we just crossed the cost_cap_warning_pct threshold. */ costCapWarning: boolean; } export interface OutputGuardCheck { ok: boolean; violations: string[]; } /** Resolve final paths from GoalSpec + AGENTS.md. */ export declare function resolvePaths(goal: GoalSpec, guide: PersistentGuide): ResolvedPaths; /** * Pre-flight Input guard. Called once before the cycle loop starts. Catches * obvious "this goal is dead on arrival" cases. */ export declare function preflightInputGuard(goal: GoalSpec, guide: PersistentGuide, resolved: ResolvedPaths): InputGuardCheck; /** * Per-stage path guard: is the file the specialist intends to write * within the resolved modifiable set, and not in immutable? Goal-runner * calls this against each `_events.jsonl` event that records a file write, * post-hoc — we don't intercept the write itself (that's Claude Code's * scope). */ export declare function isPathAllowed(filepath: string, resolved: ResolvedPaths): boolean; export declare function newCostTracker(): CostTracker; export declare function recordCycleCost(tracker: CostTracker, cycle: number, costUsd: number): void; /** * Called between cycles. Decides whether to continue, terminate, or warn. */ export declare function runtimeGuard(goal: GoalSpec, guide: PersistentGuide, tracker: CostTracker, cycleIndex: number, consecutiveDiscards: number, elapsedHours: number): RuntimeGuardCheck; /** * Output guard — verifies that the cycle's recorded events do not contain * forbidden side-effects (messenger direct send, external mutating API, * non-whitelisted HTTP, etc.). * * We look at the spawn events' "agent ran X tool with Y target" trail — * goal-runner extracts target hosts/channels/etc. from events.jsonl entries * and passes them as a flat list of `effect descriptors`. Each descriptor is * a free-text string we compare against forbidden_side_effects (substring * match) and external_domain_whitelist (host comparison). */ export declare function outputGuard(guide: PersistentGuide, effectDescriptors: string[]): OutputGuardCheck; /** * Glob-ish match: supports `**` (any segments) and `*` (single segment). * Conservative — file ops touching a "broader" parent path are considered * to match. Used for both modifiable/immutable resolution and per-event * post-hoc verification. */ /** * Match `filepath` against `pattern` using a segment-based prefix model. * * Rules: * - `<...>` in either side is treated as a single-segment wildcard. * - `*` is a single-segment wildcard. * - `**` matches zero or more segments (rest-of-path). * - If the pattern's segments are a *prefix* of the filepath's segments * (with wildcards), the filepath matches (i.e. pattern declares a * directory; any file under it is in scope). * - The match is symmetric for intersection checks: if pattern is more * specific than filepath but they overlap, the function returns true. */ export declare function pathMatches(filepath: string, pattern: string): boolean;