/** * design/125 D2 — **`runSpec`**:SpecContract 的 thin 装配器(形态定死 = `runTask` + Stop hook;裁决 * 议题#1:不组合 runGoal —— doneCheck 只在模型自报后跑不适合外部强制,且 mechanical goal 终态自己发射 * TaskOutcome,组合 = 同 taskSignature 双发射,违反 design/73 红线③)。 * * 装配五步(全部**组合而非覆盖**,codex-B1=fable-M4): * 1. preflight:frozenPaths 校验+字节快照;亲跑三值 oracle;requireRedStart(默认 true)⇒ 必须 red * (green→`spec.not_red`、error→`spec.oracle_error`,均 fail-loud);捕获 baseline 计数。 * 2. frozen deny policy 经 {@link combinePolicies} 合入部署基线(deny 短路不可被顶);绝不裸赋顶掉 * `taskSpec.toolPolicy`(TRAP #1)。 * 3. Hooks 多路复用:runSpec 的 stop gate 先跑(guard-restore → oracle 判)——red ⇒ block 短路(失败 * 尾部经 `delimitUntrusted` 围栏后置入:oracle 输出是模型可影响面);green ⇒ **链式调用**用户 stop * (不吞其否决权);error ⇒ block 一次并注明 oracle 基础设施故障,**连续 2 次 error 放弃把关**走终态 * 判定(防 oracle 自坏死循环)。其它 hook 槽原样透传。 * 4. 收口:终态亲跑 oracle = 最终判定;`emitTaskOutcome`(mechanical):`oracleHadRedRun` = 任一 * 「真跑过且判 red」的观察(preflight ∨ stop-gate ∨ 终态;error 永不置位)。durable pause * (suspended/needs_review)非终态,不发射(同 goal.ts 先例:无半事实、resume 不重复计数)。 * 5. objective 框架:spec 文本围栏置入 + frozenPaths 只读声明(框架 = 可信第一方,spec = DATA)。 * * 已知两代价(fable,写明):① stop cap=8 引擎硬常量 —— >8 次红反馈的超长修复需拆任务;② stop gate 只在 * 自然结束点咨询,maxTurns/timeout/abort 结束不咨询 —— 终态亲跑兜住**判定**但不兜**续命**(预算配比 * 参考 harness 实战:maxTurns=60 / 自限 6)。 * * runSpec **不接**的 harness 职责(fable-MIN1,显式留给使用方):JSONL 事件账本、不变量检查器、workcopy * 生命周期(调用方保证起点是干净树 —— preflight 红才有意义)、模型/Runner 装配、chaos 包装。frozen 写入 * 面:policy 只挡 Write/Edit 族 = belt;bash 写入由快照恢复兜(suspenders);危险 bash deny 仍是使用方纪律。 */ import type { Runner } from "../core/runner/runtask.js"; import type { TaskResult, TaskSpec } from "../core/types.js"; import type { TaskOutcome } from "../core/task-outcome.js"; import { type OracleBaseline, type OracleGateResult, type OracleVerdict, type SpecContract } from "../core/spec-contract.js"; export interface RunSpecOptions { /** Workcopy root — the containment root for frozenPaths, oracle cwd, and `spec.path` resolution. */ rootDir: string; /** Per-run base spec (model/tools/toolPolicy/hooks/limits/…). `objective` is owned by runSpec (the * spec framing); `toolPolicy` and `hooks` are COMPOSED with runSpec's, never replaced. */ taskSpec: Omit; } export interface RunSpecOracleReport { /** Terminal adjudication (the authoritative bit — the stop gate only advises mid-run). */ final: OracleVerdict; perGate: OracleGateResult[]; /** Preflight counts backing `minPass:"baseline"` (empty when no gate parses counts). */ baseline: OracleBaseline; } export interface RunSpecResult { result: TaskResult; oracle: RunSpecOracleReport; /** The emitted outcome fact. Undefined on a durable pause (suspended/needs_review — not a terminal). */ outcome?: TaskOutcome; /** How many frozen files were byte-restored after tampering (stop gates + terminal sweep). */ guardRestores: number; } /** * Run one task under a {@link SpecContract}. 🔴 CODE-tier input contract (fable-M3): `contract` must come * from the deployment author / a trusted code path — its oracle commands are executed verbatim. * * Throws coded errors on contract violations before any model turn runs: `spec.no_oracle`, * `spec.frozen_path_invalid`, `spec.frozen_missing`, `spec.spec_unreadable`, `spec.not_red`, * `spec.oracle_error`. */ export declare function runSpec(runner: Pick & Partial>, contract: SpecContract, opts: RunSpecOptions): Promise; //# sourceMappingURL=run-spec.d.ts.map