Skip to content

[Bug][LazyCodex] $omo:ulw-plan also triggers full Ultrawork mode, compounding planning and subagent stalls #124

Description

@ameforce

Summary

Invoking the planning-only Codex skill $omo:ulw-plan also activates the generic Ultrawork UserPromptSubmit hook. The hook searches the entire current prompt with /(?:ultrawork|ulw)/i, so the ulw inside the skill name causes a second, full <ultrawork-mode> directive to be injected.

The result is two overlapping contracts in one turn:

  • ulw-plan: planning consultant, stop at a decision-complete plan, never implement.
  • ultrawork: open a goal/notepad, create exhaustive update_plan state, fan out subagents, wait on dependent child barriers, verify, and continue until completion.

In the observed run, a bounded RCA-and-plan request remained active for about six hours with very little user-visible progress. Long Codex tool calls were a contributing trigger, but the deterministic LazyCodex routing collision caused a planning-only request to inherit the heavier execution workflow and its unbounded wait rules.

Environment

  • OS: Windows 11 Pro 10.0.26200 (build 26200)
  • Codex Desktop: 26.707.3748.0
  • Codex CLI: 0.142.4
  • Active plugin: omo@sisyphuslabs 4.16.2
  • Also verified against current LazyCodex main at bb8764ca1754148ca56478d433c42b91c550e0f4 (marketplace 4.16.3 sync)
  • Node.js used for the packaged-hook probe: 24.11.1

Repository Decision

This report belongs in code-yeongyu/lazycodex because the confirmed defect is in the Codex-specific Ultrawork UserPromptSubmit hook shipped by LazyCodex. Upstream Codex issues may explain individual long tool calls or child-result loss, but upstream Codex does not decide that $omo:ulw-plan should receive <ultrawork-mode>.

Related but not duplicate:

Reproduction

From plugins/omo/components/ultrawork in either the installed 4.16.2 payload or current 4.16.3 source:

printf '%s\n' '{"hook_event_name":"UserPromptSubmit","prompt":"$omo:ulw-plan RCA and improvement plan only"}' \
  | node dist/cli.js hook user-prompt-submit \
  | rg -o '<ultrawork-mode>'

Actual output:

<ultrawork-mode>

Control prompt without ulw returns zero bytes:

printf '%s\n' '{"hook_event_name":"UserPromptSubmit","prompt":"RCA and improvement plan only"}' \
  | node dist/cli.js hook user-prompt-submit \
  | wc -c
0

The same detector also injects Ultrawork for non-activation substrings such as refactor ulw_helper.ts. Current tests explicitly pin 하이ulw and ulw_helper.ts as positive triggers.

Expected

  • An explicit $omo:ulw-plan invocation should load the selected planning skill without also injecting the generic full Ultrawork execution contract.
  • Explicit skill routing should take precedence over substring keyword routing.
  • Identifiers such as ulw_helper.ts should not activate Ultrawork.
  • A user should be able to request planning only and reliably reach the approval/plan handoff stop condition.

Actual

  • $omo:ulw-plan deterministically receives <ultrawork-mode> in addition to the planning skill.
  • The two contracts add separate state, delegation, wait, and review requirements.
  • The planning request can become dominated by subagent barriers and continuation work instead of reaching the concise plan handoff.
  • In the observed run, continuation occurred after long waits and previously active child deliverables were not all available to the resumed parent, causing more discovery and orchestration.

Evidence

Deterministic source evidence

  • codex-hook.ts defines the unbounded substring detector and injects additional context when it matches.
  • isUltraworkPrompt is only the regex test.
  • codex-hook-trigger-policy.test.ts currently requires embedded ulw substrings to activate the hook and has no ulw-plan exclusion test.
  • ulw-plan/SKILL.md says to stop at sufficiency but also blocks dependent planning/final handoff until child lanes terminate or are recorded inconclusive.
  • ultrawork/SKILL.md adds a durable notepad and update_plan transition protocol; its child barrier adds further wait/respawn requirements.
  • In 4.16.3, full-workflow.md explicitly says elapsed time alone never justifies cancelling, replacing, or failing the high-accuracy reviewer.

Runtime evidence from the affected run

  • Planning-only request remained active for approximately six hours.
  • One small apply_patch execution reported 974.6 seconds wall time before yielding a running cell.
  • A later wait on another patch execution reported 375.7 seconds wall time.
  • A focused test invocation reported 249.7 seconds before yielding, while the same targeted tests later completed in 0.001 and 0.015 seconds. This refutes the target tests themselves as the main delay.
  • After continuation/interruption, only the root agent remained visible; final deliverables from several previously active child lanes were unavailable.
  • The packaged hook probe above reproduces on both installed 4.16.2 and current 4.16.3.

Root Cause

The confirmed LazyCodex root cause is prompt-routing collision:

  1. ULTRAWORK_CURRENT_PROMPT_PATTERN matches ulw anywhere, without token boundaries or exclusions for explicit ulw-* skill names.
  2. $omo:ulw-plan therefore activates both the selected planner and the generic Ultrawork hook.
  3. The injected full workflow compounds the planning skill's own delegation and wait rules.
  4. When Codex has a slow tool call or loses a child completion across continuation, the combined contracts lack a progress-aware bounded degradation path, so the workflow can keep waiting or re-orchestrating for hours.

Competing hypotheses were checked:

  • Upstream Codex tool/control-plane stalls are a real contributing trigger, supported by the related upstream reports, but they do not explain the deterministic extra LazyCodex directive.
  • Slow target tests were ruled out by direct millisecond test runtimes.

Proposed Fix

  1. Give explicit LazyCodex skill invocations precedence over the generic keyword detector. At minimum, $omo:ulw-plan, $omo:ulw-loop, and $omo:ulw-research should not implicitly activate full Ultrawork unless a separate explicit Ultrawork activation is also present.
  2. Replace arbitrary substring matching with an activation parser or a Unicode-aware standalone-token rule that excludes hyphenated skill names, identifiers, and filenames.
  3. Add a liveness backstop for combined planner/reviewer workflows: track last meaningful progress, persist child IDs/status/results before waiting, warn on staleness, and allow a lane to become durably inconclusive after a bounded recovery sequence.
  4. Reconcile continuation from the exact recorded phase instead of re-running completed research or respawning equivalent lanes.

Verification Plan

  • Hook unit tests must return no additional context for:
    • $omo:ulw-plan RCA and improvement plan only
    • [$omo:ulw-plan](...)
    • refactor ulw_helper.ts
    • 하이ulw
  • Existing intended activation forms such as ulw fix this and please ulw this change must still inject <ultrawork-mode>.
  • Add a precedence test where $omo:ulw-plan plus a separate explicit Ultrawork activation follows the documented intended behavior.
  • Run the packaged CLI smoke probe against the marketplace payload, not only source imports.
  • Add an integration fixture that invokes $omo:ulw-plan and verifies that the planner reaches its approval/plan stop condition without a second Ultrawork state machine.
  • Simulate a slow child/tool plus continuation and verify bounded, durable recovery without losing completed child evidence or re-running completed research.

This issue or PR was generated by LazyCodex.
Tag: lazycodex-generated

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions