Tighten resolve-metadata-model runtime guards, tidy tool-argument-preparation
subagent-type override logging, and trim a redundant literal in the
metadata-model-unification test. Behavior preserved (328 tests pass).
Strip obvious comments, over-defensive guards, and dead branches across
the five delegate-task executor files while preserving all metadata
propagation behavior added in prior commits. Regression tests remain
green (328 pass / 0 fail).
The execute field with { task_id, task_dir } was defined but never referenced anywhere in the codebase. Removing dead code simplifies the type surface and prevents accidental future misuse.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Behavior-preserving cleanup of AI-generated code smells in 5 files authored/moved by this PR:
- src/hooks/model-fallback/fallback-state-controller.ts (-47/+47 net reorganization, redundant defensiveness removed)
- src/shared/model-string-parser.ts (-4 LOC obvious-comment cleanup)
- src/shared/ripgrep-cli.ts (-13 LOC obvious comments + redundant defensive checks)
- src/tools/delegate-task/tool-description.ts (-6 LOC)
- src/tools/look-at/look-at-input-preparer.ts (-6 LOC)
Targets: obvious comments that restate code, over-defensive null checks on guaranteed values, redundant existence checks. No public API signatures changed, no type hints removed, no new abstractions introduced. Full test suite still passes.
Extract the tool description/category metadata into tool-description.ts and move argument normalization plus validation into tool-argument-preparation.ts. This keeps createDelegateTask focused on orchestration while preserving behavior and bringing tools.ts under the module LOC rule.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Move parseModelString into src/shared so callers can depend on a neutral module instead of reaching into delegate-task internals.
Cross-tool coupling violates module boundaries, and this keeps call-omo-agent plus runtime-fallback from importing through a sibling tool.
Match opencode core 'task' tool behavior for metadata consistency:
1. Model fallback: When categoryModel/task.model/resumeModel is undefined,
fall back to parentContext.model so subagent metadata always includes
model info. Thread parentContext into executeSyncContinuation for parity.
2. Task ID consistency: unstable-agent-task was missing taskId and
backgroundTaskId in metadata. background_output used inconsistent
snake_case 'task_id' vs camelCase 'taskId' elsewhere. Standardize on
camelCase: taskId = sessionID (resume id), backgroundTaskId = bg task id.
Update text output blocks to use buildTaskMetadataBlock helper.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Add helper that picks primary model with fallback to a secondary model
(e.g., categoryModel → parentContext.model). Enforces consistent
{providerID, modelID} shape.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Updates the canonical Anthropic Opus model in every fallback chain
(sisyphus, oracle, prometheus, metis, momus, visual-engineering,
ultrabrain, deep, artistry, unspecified-high), the unspecified-high
category default, the think-mode HIGH_VARIANT_MAP, the Claude Code
alias map, the claude-thinking legacy alias, the context-limit GA
regex, and event.ts fallback strings.
Widens supportsCachedAnthropicLimit to accept both claude-*-4-6 and
claude-*-4-7 so the 1M context cache still applies across the bump.
Regenerates the bundled model-capabilities snapshot from models.dev
and the model-fallback snapshot to match the new source output.
- #3354: Coerce data.name to String in loadSkillFromPath/loadSkillFromPathAsync
to prevent crash when YAML parses numeric skill names (e.g., name: 12306)
- #3416: Add required run_in_background parameter to all task() examples in
ultrawork prompts (default, gpt, gemini, planner) to match tool schema
- #3379/#3417/#3418/#3337/#3335: Strip ZWSP (U+200B) before agent name
comparisons in agent-tool-restrictions, sync-prompt-sender, tool-execute-after,
tool-execute-before, oracle-verification-detector, call-omo-agent,
recovery-prompt-config, and agent-variant to prevent ZWSP-prefixed display
names from breaking exact-match lookups
setSessionFallbackChain stored the fallback chain but the sync path
never consumed it when sendSyncPrompt returned an error. Added a
retry loop that iterates getNextFallback() until the prompt succeeds
or the chain is exhausted, preserving the finally-block cleanup.
🤖 Generated with OhMyOpenCode assistance
https://github.com/code-yeongyu/oh-my-opencode
The sync poller returned 'Task aborted' immediately when the abort
signal fired, even when a terminal assistant message had already
arrived during the previous wait. Now attempts one final fetch and
returns the completion result if available before emitting the
abort message.
🤖 Generated with OhMyOpenCode assistance
https://github.com/code-yeongyu/oh-my-opencode
Anthropic API accepts claude-opus-4.6 (dot format) but not
claude-opus-4-6 (dash format). Added anthropic case to
transformModelForProvider to normalize dash-format model IDs before
they reach the provider. Updated model config snapshots and test
expectations to match the new dot-format output.
🤖 Generated with OhMyOpenCode assistance
https://github.com/code-yeongyu/oh-my-opencode
- Replace getAgentRuntimeName with getAgentDisplayName for consistency
- Add stripAgentListSortPrefix helper to normalize agent names
- Strip sort prefixes in subagent-resolver and sync-executor
- Backfill canonical names for core agents when builtin configs omit name
- Update tests to match new behavior
Update various modules to use centralized constants from plugin-identity:
- get-local-version/formatter: Use PUBLISHED_PACKAGE_NAME
- run/session-resolver: Use PUBLISHED_PACKAGE_NAME
- background-agent/task-poller: Use PUBLISHED_PACKAGE_NAME
- mcp-oauth/provider: Use PUBLISHED_PACKAGE_NAME
- auto-update-checker/constants: Use ACCEPTED_PACKAGE_NAMES
- comment-checker/downloader: Use PUBLISHED_PACKAGE_NAME
- legacy-plugin-toast/hook: Use PLUGIN_NAME
- shared/data-path: Use CACHE_DIR_NAME
- shared/external-plugin-detector: Use ACCEPTED_PACKAGE_NAMES
- shared/logger: Use LOG_FILENAME
- tools/ast-grep/downloader: Use PUBLISHED_PACKAGE_NAME
- tools/call-omo-agent/tools: Use PUBLISHED_PACKAGE_NAME
- tools/delegate-task/category-resolver: Use PUBLISHED_PACKAGE_NAME
- tools/grep/constants: Use PUBLISHED_PACKAGE_NAME
- tools/grep/downloader: Use PUBLISHED_PACKAGE_NAME
- tools/lsp/lsp-client-wrapper: Use PUBLISHED_PACKAGE_NAME
🤖 Generated with assistance of OhMyOpenCode
The depth limit (default maxDepth=3) was being silently bypassed when
sync-task.ts could not reach the manager's spawn enforcement methods --
the fallback hardcoded childDepth: 1, allowing infinite recursion of
delegate_task calls in degraded environments.
This was hard to catch because:
1. The fallback path took the dangerous default silently (no log).
2. There were no end-to-end smoke tests asserting that the depth value
coming back from reserveSubagentSpawn is actually used.
3. The unit tests for resolveSubagentSpawnContext only covered error
cases, not the actual depth calculation.
Changes:
- sync-task.ts: split the spawnContext fallback into an explicit if/else
with a WARNING log when the manager is missing enforcement methods.
This makes the dangerous path observable in logs.
- subagent-spawn-limits.test.ts: add depth calculation regression tests
(root, depth-1, depth-2, depth at max, parent cycle detection).
- sync-task.test.ts: add two regression smoke tests:
1. depth limit error from reserveSubagentSpawn must be propagated and
must NOT create the session.
2. spawnDepth recorded in metadata must equal what reserveSubagentSpawn
returns -- guards against silent fallback to childDepth: 1.
15 new spawn-limits tests + 2 new sync-task tests pass.
Full suite: 5105 pass, 0 fail.
prompt-builder.ts now includes project-level skills from
.opencode/skills/ when building delegated session prompts.
5007 tests pass, tsc clean.
Closes#2687
model-selection.ts now separates model selection from variant/reasoning
tier, so agent model overrides don't lock the variant.
34 tests pass, 5009 total, tsc clean.
Closes#3163
Added await for session ready state before sending prompt in
background-agent/manager.ts. Also improved image resizer error handling.
132 tests pass, tsc clean.
Closes#2932
When users configure agents.sisyphus-junior.model, category sessions
should use that model without falling back to hardcoded
AGENT_MODEL_REQUIREMENTS. Two leaks existed:
1. Launch-time: category-resolver.ts did not check overrideModel when
deciding whether to use the hardcoded fallbackChain. Fixed by adding
overrideModel to the suppression condition.
2. Runtime retry: model-fallback hook.ts treated undefined fallbackChain
(from setSessionFallbackChain(id, undefined)) as 'no override' and
fell through to AGENT_MODEL_REQUIREMENTS on session.error/status
retry. Fixed by storing explicit empty array and checking .has()
instead of truthiness.
Tests added:
- hook.test.ts: explicit empty session fallback suppresses agent chain
- event.model-fallback-2941.test.ts: session.error does not arm retry
- category-resolver.test.ts: overrideModel suppresses fallbackChain
- tools.test.ts: sisyphusJuniorModel override assertion