# Contract Log: 2026-06-12-172600-95pv

## Dispatch Contract

Thread: THR-95, Funnel pre-load: place Notion key + install imsg (Dorian) - STOP before load

Worker/session reference: agent:worker:subagent:534bbc3c-71f2-4568-9b7d-abc5a19fa809

Substrate and executor: OpenClaw worker session, executor `worker`, model `openai/gpt-5.4-mini`.

Scope summary: Execute the Orchestrator-authorized preview pass only: verify `imsg` 0.11.1 schema compatibility by read-only evidence, confirm the actual funnel runtime reads `NOTION_API_KEY`, produce a full unified diff preview for the plist flag fix, and stop before applying or loading anything.

Expected completion criteria: Worker posts preview completion or blockage evidence to the Notion thread with runtime var proof, `imsg` compatibility finding, `--after-rowid` occurrence count, `--since-rowid` exclusivity/no +1 conclusion, full unified diff preview, explicit confirmation that no live watch/load/grant/edit/canonical update/secret exposure occurred, and sets Execution Status to `Needs Review` on success or `Blocked` on failure.

## Completion Contract

Done:

- Completed the preview-only THR-95 pass and appended progress and completion to the Notion thread dialogue log.
- Updated the thread `Execution Status` to `Needs Review`.
- Kept everything read-only except the Notion log/status update: no live `imsg watch`, no `launchctl load/bootstrap/start`, no FDA or Contacts grant attempt, no contacts-helper run, no live plist edit, and no secret value was echoed or logged.

Findings:

- `imsg` 0.11.1 compatibility is acceptable by field mapping, with one explicit inference: docs/README show `watch --json` emits message objects containing `id`, `chat_id`, `chat_identifier`, `chat_guid`, `guid`, `sender`, `is_from_me`, `text`, `created_at`, `attachments`, and `reactions`. Funnel expects `guid`, `rowid`, `created_at`, sender/contact key, `service`, `body`, `is_from_me`, and tapback metadata. This appears operationally compatible via `id` as cursor anchor, `guid` as identity anchor, and `reactions` for tapbacks; `service` relies on runtime enrichment rather than a raw 1:1 watch field.
- Runtime var proof: Stage 5 routes through `funnel-runtime notion-write` in `/Users/openclaw/Documents/OpenClaw/Projects/funnel/funnel.lobster:145`, and live OpenClaw config binds the Notion skill API key to `${NOTION_API_KEY}` in `/Users/openclaw/.openclaw/openclaw.json:387`.
- Plist check: `/Users/openclaw/Documents/OpenClaw/Projects/funnel/funnel-launchd.plist:85` contains `--after-rowid` exactly once. `imsg watch --help` exposes `--since-rowid <value>` with help text `start watching after this rowid`, so cursor `171497` does not need `+1`.
- No additional 0.11.1-only plist changes surfaced in the read-only pass. The only required preview change is the rowid flag rename.

Diff preview:

```diff
--- /Users/openclaw/Documents/OpenClaw/Projects/funnel/funnel-launchd.plist
+++ /Users/openclaw/Documents/OpenClaw/Projects/funnel/funnel-launchd.plist
@@ -82,7 +82,7 @@
 fi

 echo "starting imsg watch --json from ROWID ${last_rowid}" >&2
-exec /usr/bin/env imsg watch --json --after-rowid "$last_rowid" >> "$FUNNEL_QUEUE_PATH"
+exec /usr/bin/env imsg watch --json --since-rowid "$last_rowid" >> "$FUNNEL_QUEUE_PATH"
     </string>
   </array>
```

Parent review:

- Re-verified status is `Needs Review`.
- Re-verified installed `imsg` help exposes `--since-rowid <value>` and not `--after-rowid`.
- Re-verified the live plist still has exactly one `--after-rowid` occurrence and remains unmodified.
- Re-verified Stage 5 routes through `funnel-runtime notion-write` and OpenClaw config binds the Notion skill key to `${NOTION_API_KEY}` without exposing the credential value.
- Re-verified read-only schema evidence supports compatibility with one explicit inference around `service` enrichment.
- ACK is still required before applying the plist patch or proceeding to any load/grant phase.
