/** * The WIRE that wraps core `runRepairLoop` onto the leader's single-agent path * (`sema-internal server/docs/LEADER-REPAIRLOOP-INTEGRATION.md` §3.3 + the authoritative §10 layer). It owns the three things the * `RepairOracle` closure (`repair-oracle.ts`) and the core engine CANNOT resolve themselves: * * 1. **The grader handle (R1, §10.1)** — the reused integration sandbox's writeFile/exec + `integBase`, bound by * the caller (`attachRepairLoopDeps` is handed the integration env). The closure grades there; the worker env * stays distinct so the §5.1 identity check (`graderEnv !== workerEnv`) is LIVE. * 2. **The worker diff source** — `pullWorkerDiff`, the same `pullDiff`/self-upload path the merge uses, so the * closure materializes the worker's LATEST committed `base..HEAD` diff every grade (§10.1; never a stale diff). * 3. **De-correlation model ids (§10.9 mechanics)** — the closure receives NO model ids (roles→models resolve * INSIDE `Runner.runTask`, AFTER the closure returns), so the WIRE resolves `generatorModelId` + * `verifierModelId` from `cfg.roles`/`cfg.models` and passes them to `mkRepairOracle.l3`. v1 ships L3 OFF * (`cfg.l3` unset) → L2 `trusted_hidden` is the sole clearer; `terminalForTier` caps every PASS at * `candidate_only`. * * §10.2 — for v1 SAFE-tier `candidate_only` we OMIT `immutableOraclePaths` (the bare `graderEnv !== workerEnv` * identity check suffices; the structural bash write-probe is vacuous across distinct sandboxes and matters only * for the mandate-OFF auto-accept path). `workerEnv` IS passed so the identity check runs. * * §10.7 — the surfaced `candidatePatch.patch` is worker-authored code reaching a human-read HTTP body / durable- * approval row, so it is DELIMITED (`delimitUntrusted(...)`); `reason` comes ONLY from the core-sanitized * `RepairResult.verification.findings[0]`, never the raw oracle trace. * * §10.8 — `attachRepairLoopDeps(deps, integEnv, cfg)` is the SINGLE wire-call helper so `wire.ts` gains one line * per integration-sandbox path instead of in-place edits to its dense provision spreads. Stage-2 calls it. * * Everything here is gated by the caller behind `LEADER_REPAIR_LOOP` (default OFF): when the dep is not attached * the leader's single-agent paths are byte-identical to today. */ import { type Runner, type TaskSpec, type ExecutionEnv, type ExecStep, type OracleTier, type RepairResult, type RepairBundle, type RepairTerminal } from "@sema-agent/core"; import { type WorkerDiff } from "./repair-oracle.js"; import type { GraderHandle } from "./grader-env-factory.js"; import type { LeaderDeps, ProvisionedWorker, SubtaskSpec } from "./leader.js"; import type { WorkerReport } from "./fanout.js"; /** The per-run inputs the leader's single-agent repair loop needs, resolved by the wire (§3.3). */ export interface RepairWireCfg { /** The CONCRETE core Runner that runs the solo worker's GENERATE/REPAIR turns. `runRepairLoop` requires the * real `Runner` (not the `RunnerLike` on `ProvisionedWorker`); the wire holds it (it builds the worker Runner). */ runner: Runner; /** The grader handle (R1: the reused integration sandbox) — writeFile/exec/repoDir/integBase bound by the wire. */ grader: GraderHandle; /** OPTIONAL solo worker execution env REF — passed as `runRepairLoop.workerEnv` so the §5.1 identity check is * LIVE. On the FACTORY lane (REMOTE_EXEC=e2b/k8s — the canary) the worker's RAW env is NOT surfaced (only * `fetchDiff`), so it is OMITTED: `runRepairLoop` then SKIPS the identity check (fires `onWarn` — fine). * Structural isolation is GUARANTEED regardless because the grader is a SEPARATE provisioned sandbox (a * distinct object / `sandboxId` from the worker by construction) — §10.2: the identity check is necessary-not- * sufficient; the real boundary is the separate sandbox. Present on the STATIC E2B lane (the leader owns the * worker env). When present it is forwarded; when absent runRepairLoop is called without `workerEnv`. */ workerEnv?: ExecutionEnv; /** Reap the dedicated grader sandbox the wire provisioned for THIS repair loop (called in a `finally` on every * path — the grader is a separate sandbox the leader owns, distinct from the worker + the integration sandbox). */ graderDestroy?: () => Promise; /** Pull the worker's LATEST committed `base..HEAD` diff from ITS env (the merge `pullDiff`/self-upload path). */ pullWorkerDiff: () => Promise; /** TRUSTED, spec-derived oracle steps run in the grader (`testCmd` [+ `measureCmd`]); NEVER worker-authored. */ oracleSteps: ExecStep[]; /** The tier assigned on a PASS — `trusted_hidden` when the steps run an oracleFiles-backed hidden oracle, * `property_harness_weak` for a compile-only gate, `none` if there is no usable oracle. */ passTier: OracleTier; /** council 2026-06-17 — the seeded hidden-oracle files (content), RE-INJECTED after each hermetic reset+apply so * the `clean -fdx` doesn't grade against a wiped/worker-substituted oracle. Empty for an inline-testCmd gate. */ oracleFiles?: Array<{ path: string; content: string; }>; /** fork1.2 — paths the candidate patch must not touch (the oracle/test paths); a touch → `needs_human_oracle`. */ oraclePaths?: string[]; /** In-loop attempt ceiling (LEADER_REPAIR_LOOP_ATTEMPTS, validated 2-3 by the wire). */ maxAttempts: number; /** K re-isolations to settle a flaky verdict (LEADER_ORACLE_FLAKY_K, default 2). */ flakyK?: number; /** Cost/time backstops forwarded to `runRepairLoop`. */ costCeilingMicroUsd?: number; totalTimeoutMs?: number; /** §10.5 resume threading: the restored `RepairBundle` from a resumed checkpoint (`repairBundleFromCheckpoint`), * re-seeded MONOTONICALLY. v1 makes the repair path mutually exclusive with resource-suspend (the wire drops * `resourceSpec` when `repairLoopActive`), so this is usually undefined; threaded for the future resume path. */ resumeBundle?: RepairBundle; /** §10.9 — the resolved generator+verifier model ids for the L3 de-correlation gate. v1 leaves L3 OFF (unset). */ l3?: { generatorModelId: string; verifierModelId: string; }; /** Per-attempt observability callback. */ /** S-136(core 7.6.0 D-8):键名随 core 从 `terminal` 改成 `repairTerminal` —— `terminal` 这个名字在 * `TaskResult` 上已经归**运行终局因由**所有,修复循环的判词与它同名会是两个不同东西共用一个名字 * (本仓 status/kind 同名词混淆病族)。 */ onAttempt?: (info: { attempt: number; repairTerminal?: RepairTerminal; oracleTier: OracleTier; passed: boolean; flaky: boolean; }) => void; log?: (event: string, x?: Record) => void; } /** A leader-mapped repair outcome: the report (carrying `repairTerminal` — §10.6) + the raw result + held candidate. */ export interface RepairWireOutcome { report: WorkerReport; result: RepairResult; candidatePatch?: { patch: string; tier: OracleTier; reason: string; gradedHash?: string; }; } /** * §3.3 — run the bounded single-agent self-repair loop over the solo worker and map the result to a `WorkerReport` * (with `repairTerminal` set — §10.6). Builds the `RepairOracle` closure (capturing the worker-diff source, the * grader handle, `integBase`, the trusted steps, the resolved model ids), then calls `runRepairLoop` with * `graderEnv` = the integration sandbox, `workerEnv` = the solo worker's env (so the identity check is LIVE), * OMITTING `immutableOraclePaths` (§10.2). Never throws — a thrown engine error maps to a `failed` report so the * leader's "never throws" contract holds. The held candidate (`candidate_only` etc.) is surfaced DELIMITED (§10.7). */ export declare function runRepairLoopForLeader(solo: ProvisionedWorker, implSpec: TaskSpec, cfg: RepairWireCfg): Promise; /** * §10.8 — the SINGLE wire-call helper. Attaches the `LeaderDeps.repairLoop` dep (the opt-in single-agent repair * loop) using the integration sandbox as the grader (R1). `wire.ts` calls this ONCE per integration-sandbox path * instead of editing its dense provision spreads. When `cfg` is absent (LEADER_REPAIR_LOOP off) it is a NO-OP → * `deps.repairLoop` stays unset → the leader's single-agent paths are byte-identical to today. * * The wire supplies a `resolve(solo, sub)` that, per solo worker, produces the concrete `RepairWireCfg` (the real * Runner + the worker env ref + the worker diff source bound to THAT worker). Kept as a callback so the grader * handle / steps / model ids the wire already holds are closed over once, and only the per-worker bindings are * resolved at call time. */ export declare function attachRepairLoopDeps(deps: LeaderDeps, resolve: ((solo: ProvisionedWorker, sub: SubtaskSpec) => Promise) | undefined): void; //# sourceMappingURL=repair-wire.d.ts.map