# WI-002 — Wall-clock harness mode + first real direct controller (Gate 2 entry)

Status: Built → Contract-verified (mock) → Measured with a LOCAL model (Qwen/Qwen3.8-27B via vLLM on this machine; no API keys) — see LEDGER

```text
work_item_id:        WI-002
question_id:         Q2
hypothesis_id:       H2
study_id:            S2 (competence qualification + Paused–Replay–Live on the minimal task)
current_project_belief:
    (a) The Gate 1 harness can stamp O, B, D, A faithfully when the controller consumes REAL
        wall time, without a concurrent publisher, because the synthetic environment is a pure
        function of task time (frames due during B->D can be rendered lazily at D and stamped
        with their due time). (b) A frontier VLM can click a white square on black under Paused
        (competence). (c) Under Live, success will fall as the window shrinks below the VLM's
        B->D, and the failures will be timing-labelled, not semantic.
exact_uncertainty_to_reduce:
    U4. Does lazy rendering reproduce the simulated-clock results under a real clock (oracle that
        sleeps its declared compute), within sleep jitter?
    U5. Competence: does the VLM click inside the target under Paused on >= 80% of 10
        calibration seeds (threshold predeclared here)?
    U6. P/R/L: on 10 held-out seeds x windows {1,2,4,8,16} s, what are Paused, Replay, Live
        success, and which labels do Live failures carry?
claim_or_decision_enabled_by_this_work:
    Whether a concurrent publisher is needed at all (U4); whether S2 can proceed on this task
    with this agent (U5); the first real Paused–Replay–Live row (U6).
intended intervention or measurement:
    timestamp_source=monotonic_ns; controller=vlm_direct (change-triggered single invocation,
    decoder-enforced JSON {action: click|wait, x, y} from a local OpenAI-compatible vLLM server
    serving Qwen/Qwen3.8-27B bf16; thinking off, temperature 0); windows swept; all else fixed.
    A second agent config (thinking on, low effort) is run only if budget/time permit, to test
    whether agent ORDERING changes between Paused and Live.
matched conditions:          Paused, Replay(Live), Live per (seed, window).
variables held fixed:        manifest (except response_window_ns per cell), seed per cell, model,
                             prompt v1, image scale, decoding config, action space v1, scorer v1.
primary outcome:             valid_at_receipt; per-trial labels; B->D distribution.
required trace fields:       §13 + invocation id, reported model, token usage per decision.
competing explanation ruled out:
    "Live failures are perception/semantic errors" — ruled out if Paused/Replay succeed on the
    same seed and Live failures carry timing labels with semantic_correct = true.
possible result patterns and their interpretations:
    U4 (a) wall-clock oracle matches closed form within jitter -> no publisher needed for
        synthetic envs; (b) mismatch -> lazy rendering is unfaithful; build a publisher.
    U5 (a) >= 80% -> proceed; (b) < 80% -> STOP; the task/agent pair cannot support a timing claim.
    U6 (a) Paused ~ Replay high, Live falls with window -> H2 supported on the minimal task;
        (b) Paused high but Replay low -> decoding variance / sequence effect; investigate
        before timing claims; (c) Live high at all windows -> the tested windows did not
        expose the problem; shrink them.
project_delta_expected_from_each_result:  as above.
project_decision_unlocked:   Gate 2 pass/fail for (revealed_target, vlm_direct).
generalist_reader_starting_point:
    "A real AI was asked to click a square; we timed it and let the square disappear."
one_sentence_reader_takeaway:
    The same AI, the same picture, the same click — it succeeds when the world waits and
    fails when the world does not, and the trace says exactly which it was.
reader_confusion_or_misconception_prevented:
    Replay is a re-run here (the model is stochastic), not a re-score; and the controller is
    invoked once per frame CHANGE, so "wait" decisions are real invocations that cost time.
positive acceptance test:    tests/test_wallclock.py (U4); mock-client tests for the controller.
negative contract test:      spec rejects unknown controller fields / wrong types / unitless;
                             decision_failed (API error) -> invalid trial, not an agent failure.
stop condition:              U4 mismatch; U5 < 80%; more than 10% invalid trials.
what this work does not establish:
    anything about physical delivery; anything about agents with history; generalization
    beyond one synthetic task.
what remains unknown afterward:
    whether relevant observations arrive during a real B->D (they do, trivially, for long
    B->D — the question is whether using them would change the action: Gate 4).
```

Amendment (2026-08-22, before any study data): windows changed from {0.5,1,2,4,8} s to
{1,2,4,8,16} s because the smoke test measured ~5.4 s per decision for Qwen3.8-27B (thinking off)
on this machine; the original grid would have left Live with no success region to cross.
