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.
Validator finding #12 from the publish-debate-vortex hyperultradebate flagged that internal-only skill and command assets could leak into the npm payload once the dot asset roots are included.
Bun 1.3.x ignores a root .npmignore for directories listed in package.json#files, so the exclusion rules live in nested .npmignore files co-located with each published command and skill directory.
RED before nested ignores: bun test script/package-layout-exclusion.test.ts failed with expect(received).toEqual(expected), receiving .opencode/skills/__internal-fake-do-not-ship-test-artifact/SKILL.md, .agents/skills/__internal-fake-do-not-ship-test-artifact/SKILL.md, .opencode/command/__internal-fake-do-not-ship-test-artifact.md, and .agents/command/__internal-fake-do-not-ship-test-artifact.md instead of [].
GREEN after nested ignores: bun test script/package-layout-exclusion.test.ts reported 2 pass, 0 fail, 5 expect() calls.
This is the exclusion companion to script/package-layout.test.ts, the inclusion test arriving through the dev merge.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Add no-progress turn detector that inspects the most recent assistant
message: if finish is 'unknown', all token counts are zero, and there
is no meaningful content beyond step-start/step-finish markers, the
turn is classified as no-progress.
Integrate the check at all three idle/completion/error continuation
points in the event handler so the loop stops cleanly with a warning
toast instead of injecting another internal prompt.