Promote the four real-usage QA channels (HTTP call, tmux, Browser use, Computer use) into a dedicated top-level `# Manual-QA channels` section in both the Codex ultrawork directive and the ultragoal skill. Each channel ships with the concrete invocation (`curl -i`, `tmux new-session` + `send-keys` + `capture-pane`, Playwright / puppeteer / Chromium, OS-level GUI automation) and the artifact to capture. The Goal section now declares `TESTS ALONE NEVER PROVE DONE` and requires every criterion to build a fresh real-usage scenario and run it through one of the four channels every time. Auxiliary surfaces (CLI stdout / DB diff / parsed config dump) are explicitly demoted: they only satisfy genuinely CLI- or data-shaped criteria, never user-facing behavior.
Bootstrap criterion item 2 and execution step 4 used to repeat the same surface enumeration; they now collapse onto the new channel table (single source of truth, less drift). EXECUTE-AS-SCENARIO in the ultragoal skill follows the same compression. The previous CLEANUP (paired teardown + receipt) + leftover-state stop rule from the prior commit are preserved.
Regression tests in `components/ultrawork/hooks/ultrawork-hooks.test.mjs` pin: the `# Manual-QA channels` heading, all four channel labels (`HTTP call`, `tmux`, `Browser use`, `Computer use`), `TESTS ALONE NEVER PROVE DONE`, `every criterion needs its own real-usage scenario`, and `every time`. README + CHANGELOGs document the restructure and the new size (11,005 chars / 232 lines). All 11 ultrawork hook tests + 7 aggregate tests pass. Installed locally via `runCodexInstaller` into `~/.codex/plugins/cache/code-yeongyu-codex-plugins/omo/0.1.0/`; cache hooks emit the new directive end-to-end and the identifier-like `ulw_helper.ts` keyword-boundary check still suppresses.
Both the Codex ultrawork directive and the ultragoal skill now force the agent to actually invoke the real user-facing surface (HTTP via `curl -i`, terminal/TUI via `tmux new-session` + `send-keys` + `capture-pane`, GUI via computer-use / Playwright, CLI stdout, DB diff) instead of treating evidence as a free-form artifact list. A paired CLEANUP step requires teardown of every QA-spawned process, tmux session, browser context, container, bound port, temp file/dir, and QA-only env var, with a one-line cleanup receipt recorded next to the artifact path (ultrawork) or embedded in the `--evidence` string (ultragoal). Missing receipt keeps the criterion in_progress / records BLOCKED. New Stop rule: leftover state from QA means NOT done.
Regression tests in `components/ultrawork/hooks/ultrawork-hooks.test.mjs` pin SURFACE-AS-SCENARIO, the concrete `curl -i` / `tmux new-session` / `computer-use / Playwright` invocations, the paired CLEANUP block with cleanup receipt + `tmux kill-session`, and the leftover-state Stop rule so the mandates cannot be silently regressed. README and CHANGELOGs refreshed; stale 5,821-char claim replaced with measured 10,037 chars / 213 lines. All 9 ultrawork hook tests + 7 aggregate tests pass.
Spell out that omo_codex_daily_active now fires from two sources -
install_completed (CLI installer) and session_start (Codex plugin
SessionStart hook) - so readers understand DAU/WAU/MAU reflects real
Codex usage and not just install events. Opt-out env vars are unchanged.
- README.md (root + packages/omo-codex/): both reasons listed.
- docs/legal/privacy-policy.md: discloses session_start as a second
trigger for the same event, same opt-out posture.
- docs/reference/cli.md: telemetry section now describes both PostHog
streams (omo_daily_active vs omo_codex_daily_active) and both Codex
reasons.
- CHANGELOG.md: adds the plugin-runtime wiring under Unreleased.
Adds a new Codex plugin component `telemetry` that emits a single
omo_codex_daily_active event (reason: session_start) from every Codex
SessionStart hook, with the same UTC-day deduplication, hashed
installation identifier, and four-flag opt-out as the install-time
event. Previously omo-codex telemetry only fired on install_completed,
so DAU/WAU/MAU under-reported real Codex usage.
- New plugin component packages/omo-codex/plugin/components/telemetry/
mirrors the rules/comment-checker/lsp pattern: own src/, tsc build,
vitest tests, package.json (posthog-node dep), hooks/hooks.json.
- src/codex-hook.ts wraps createPluginPostHog().trackActive(..., "session_start")
with safeShutdown so Codex session startup never blocks on telemetry.
- Plugin root hooks.json + workspaces register the new component
alongside rules and ultrawork on SessionStart.
- Aggregate test expectations updated to include the telemetry directory.
- cross-package-equivalence.test.ts pins product-identity constants and
shouldDisablePostHog behavior to stay byte-equivalent between the CLI
installer (src/telemetry/) and the plugin runtime
(plugin/components/telemetry/src/), so the two PostHog sources never
drift on event name, distinct_id base, dedup file path, or opt-out
flags.
- PostHogActivityReason union in the CLI-side posthog.ts gains
"session_start" so future CLI paths can emit the same reason without
a type break.