/** * #502 review rounds 3–4: paths that don't exist yet can't be denied by an * OS sandbox (deny lists drop missing paths), so a role can PLANT one that * the operator's own processes then obey. * * Two checks, each quarantining — moving, never deleting — what it finds to * `/quarantine///` (roles can neither read nor * write the operator dir, so they can't move a plant back or edit the * manifest), with an audit event and a question in the operator's inbox that * spells out the exact `mv` to undo it: * * 1. INDEPENDENT OF ANY RUN: `~/.claude/.config.json` (Claude Code * prefers this legacy global config over `~/.claude.json` whenever it * exists) and every other `.claude*.json` beside `~/.claude.json` or in * `~/.claude` that was not there at monomind's first look (recorded once * in the operator dir: some machines' Claude Code still writes a live * legacy config, which must not be moved); and an untracked `.mcp.json` in an org * work tree (`.monomind/orgs//work*`, `worktree*`) or a role cwd that * is a git work tree. Runs at every org start, every `org run` / `org * serve` tick, every session start and end, and every `doctor` run. An * operator who really uses a legacy config file allows it once by * creating `/allow-claude-legacy-config`. * 2. BASELINE: every other operator-protected path that was missing when a * role session started (`plantCandidates`). The baseline is stored in the * operator dir, so a crash or kill of `org run` does not make a plant look * pre-existing on the next start; it is never reset by a fresh start, only * by the operator: `monomind org sign` drops the paths that exist at that * point (the operator approving them). * * The SDK sandbox's own 0-byte mount-point stubs (sandbox-stubs.ts) — and a * directory holding only such stubs — are not a plant and are left alone. */ export declare const ALLOW_LEGACY_CONFIG = "allow-claude-legacy-config"; export interface WatchCtx { home: string; env: NodeJS.ProcessEnv; orgRoot?: string; cwd: string; allowWrite?: string[]; } /** A 0-byte file, or a directory holding only such files: a sandbox stub. */ export declare function isStubOnly(p: string): boolean; export declare const exists: (p: string) => boolean; /** Every path a role must not be able to plant, for this role's context. */ export declare function plantCandidates(ctx: WatchCtx): string[]; /** Existing, non-stub global-config candidates other than the current one. */ export declare function claudeConfigCandidates(home: string, env: NodeJS.ProcessEnv): string[]; export declare function readConfigRecord(operatorDir: string): Record | undefined; export declare function writeConfigRecord(operatorDir: string, rec: Record): void; /** 1a. Claude Code global-config files other than the operator's current * `~/.claude.json` — `~/.claude/.config.json` above all — that were not * there when monomind first looked. That first look is recorded once in * the operator dir (a live legacy config the operator already had is * trusted; Claude Code 2.1 still writes one on some machines) and never * reset by an org start; anything appearing after it is a plant. */ export declare function strayClaudeConfigs(home: string, env: NodeJS.ProcessEnv, operatorDir?: string, opts?: { readOnly?: boolean; onFirstLook?: (msg: string, trusted: string[]) => void; }): string[]; /** 1b. A `.mcp.json` in an org work tree or a role cwd that is a git work * tree, which the operator's session there would load: untracked, or — * a role can commit one on its branch — different from the main * checkout's `HEAD:.mcp.json` (or present where the main checkout has * none). The main checkout itself is only checked for untracked. */ export declare function worktreeMcpPlants(orgRoot: string | undefined, cwds?: string[]): string[]; /** @deprecated name kept for callers of round 4: see worktreeMcpPlants. */ export declare const untrackedWorktreeMcp: typeof worktreeMcpPlants; export interface PlantFinding { path: string; quarantined?: string; error?: string; } /** Move each path into the operator dir's quarantine, never deleting it: * rename, or copy then remove across filesystems, plus a manifest. */ export declare function quarantine(paths: string[], root: string, operatorDir?: string, now?: Date): PlantFinding[]; /** The operator-facing text, built from the in-memory findings. */ export declare function quarantineMessage(org: string | undefined, findings: PlantFinding[]): string; export declare function readBaseline(root: string, operatorDir: string): Set; export declare function writeBaseline(root: string, operatorDir: string, missing: Set): void; /** One project's watch. The baseline lives in the operator dir; the watch * also remembers the home and cwds its sessions used, for check 1. */ export declare class PlantWatch { private orgRoot; readonly org: string; notify: (findings: PlantFinding[]) => void | Promise; private operatorDir; private home; private env; private cwds; /** Told what the one-time first look at the Claude configs trusted. */ onFirstLook?: (msg: string, trusted: string[]) => void; constructor(orgRoot: string, org: string, notify: (findings: PlantFinding[]) => void | Promise, operatorDir?: string); /** Record what is missing now for this role's context — merged into the * persisted baseline, never replacing it. */ add(ctx: WatchCtx): void; /** What to quarantine now: both checks. */ planted(): string[]; check(): Promise; } /** The watch for one org, created on first use and kept for the process; * the latest caller's `notify` is the one used. */ export declare function plantWatchFor(orgRoot: string, org: string, notify: (findings: PlantFinding[]) => void | Promise, operatorDir?: string): PlantWatch; /** The `org run` / `org serve` tick: check every watch. */ export declare function sweepPlantWatches(): Promise; type Notifier = { bus?: { emit(e: Record): void; }; askHuman?: (role: string, question: string, blocking?: boolean) => Promise; def?: { roles: Array<{ id: string; reports_to?: string | null; }>; }; }; /** The first-look notice as an audit event on the run's bus. */ export declare function firstLookAudit(n: () => Notifier): (msg: string, trusted: string[]) => void; /** An audit event, a warning and a (non-blocking) question in the inbox. */ export declare function plantNotifier(org: string, n: () => Notifier): (findings: PlantFinding[]) => Promise; /** Around one role session (session.ts): check, record, and return the * check to run when it ends. */ export declare function beginPlantWatch(opts: { org: string; orgRoot?: string; cwd: string; role: { policy?: { sandbox?: { allowWrite?: string[]; }; }; }; bus: { emit(e: Record): void; }; askHuman?: (role: string, question: string, blocking?: boolean) => Promise; def?: { roles: Array<{ id: string; reports_to?: string | null; }>; }; home?: string; env?: NodeJS.ProcessEnv; }): Promise<() => Promise>; export {}; //# sourceMappingURL=planted-paths.d.ts.map