/** * THE DELIVERABLE FLOOR (crew#311) — "done" is re-derived from the artifact, never asserted. * * ## The defect * * A governed unit that produced NOTHING still passed its execution gate on the strength of a * prose reply. The engine's only universal floor is the SUBSTANCE floor * (wicked-core `actor.rs`, "phase produced no reviewable substance"): a governed * Creator/Neutral unit is rejected only when its output carries BOTH under 200 trimmed chars * of prose AND no worktree change. So ~200 characters of narration — "I'll read the design * spec, let me check the API types…" — clears it, with no file anywhere. Prose length stood in * for evidence. * * The engine has two real evidence instruments, and neither reaches a run of this shape: * * 1. `validator_pin` → the built-in EVIDENCE floor (`builtin_floors::EVIDENCE_FLOOR_PIN`, * criterion "the run left a change in its worktree (done is re-derived from the diff, never * asserted)"). It re-verifies a git DIFF, and is fail-closed on a run with no worktree — so * an UNBOUND run (`repoRef` omitted, `workdir: null`) can never satisfy it. Every crew * interactive seam launches unbound on purpose (wicked-core#293/#294), and their deliverable * is a FILE in a declared write root, invisible to a diff. * 2. `required_deliverables` → enforced by wicked-core as of FINDING-101, but only in the * WRAPPED-CLI runner (`execute_wrapped.rs`), only against the unit's own cwd, and any * absolute or `..`-escaping path is counted MISSING by construction. The ACP runner — the * path a real seat takes — never consults it. So for a run whose deliverable is an absolute * path under `extraWriteRoots`, declaring it there would fail every run on one runner and * check nothing on the other. That gap is wicked-core's to close * (wicked-core#297, items 1 and 3); once it is, this phase can retire in favour of the * engine field. Crew must not paper over it meanwhile by declaring something unverifiable. * * ## What this module does * * It gives crew the instrument it can honestly own: a deterministic TOOL phase, appended to a * PER-RUN copy of the workflow def (the exact mechanism `core/deliver.ts` proved for * `deliver: "pr"` — the shared def is never mutated, nothing lands in the overlay dir, the * catalog never grows a per-run entry), which asserts that the artifacts the launcher declared * EXIST, are non-empty, and were written by THIS run (crew#320 — existence alone re-derives * nothing at a path a prior run already populated). A Tool phase's failure surface is its exit * code: wicked-core's * `run_tool_cmd` maps a non-zero exit to `StepStatus::Failed`, which fails the unit and the run * through the unchanged completion path. No LLM, no worktree, no judgement about the content — * only "the phase promised this file; is it there". * * That is deliberately a FLOOR and not a review, in exactly the sense `builtin_floors` documents: * it proves an artifact exists. It says nothing about whether the artifact is correct, or even * related to the task. What it removes is the failure mode crew#311 recorded — a unit whose * `Write` was policy-denied, which therefore produced no file at all, reporting done. * * ## The report * * The script prints what was EXPECTED and what was FOUND before it exits, on both branches, so * the failure is legible from the unit output alone: which paths were declared, which exist * (with their size), and which are missing and why (absent / empty file / empty directory). * An operator reading a failed run must never have to guess what the phase was supposed to * produce. */ import type { PhaseDef, WorkflowDef } from './types.js'; /** The id of the appended floor phase — also the collision probe when a def already carries one. */ export declare const DELIVERABLE_FLOOR_PHASE_ID = "verify-deliverables"; /** The marker line the failing branch prints. Asserted by tests and greppable in a unit output. */ export declare const DELIVERABLE_FLOOR_FAILURE_MARKER = "[wicked-crew] DELIVERABLE FLOOR FAILED"; /** * Slack allowed on the freshness comparison, in milliseconds (crew#320). * * The launch timestamp comes from the daemon's `Date.now()` (millisecond resolution); the * artifact timestamp comes from the FILESYSTEM, and not every filesystem keeps milliseconds — * HFS+ and ext3 truncate mtime to whole seconds, and some SMB/NFS mounts are coarser still. A * file genuinely written 400 ms after a launch at `…:07.600Z` can therefore report an mtime of * `…:07.000Z` and read as older than the launch that produced it. * * One second absorbs that truncation without weakening the check this exists to make: the stale * artifact crew#320 describes is the PREVIOUS run's output, which predates this run's launch by * that run's whole remaining lifetime plus the turnaround before the next one — orders of * magnitude more than a timestamp-granularity rounding error. */ export declare const DELIVERABLE_FLOOR_MTIME_SLACK_MS = 1000; /** * The floor program, run as `node -e