Introduces a frozen Set<string> of directory basenames (node_modules, .git,
dist, build, .next, .sisyphus, .omx, .turbo, coverage, out, .cache,
.vscode-test, target, .local-ignore) that callers performing recursive
filesystem scans should skip.
This is shared infrastructure for upcoming fixes in rules-injector,
command-discovery, and claude-code-command-loader that currently descend
into node_modules and other junk directories, causing slow plugin init
and slow edit loops when the plugin is launched in-tree.
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.
Hoist shared ripgrep CLI resolution helpers (resolveGrepCli, resolveGrepCliWithAutoInstall, GrepBackend, DEFAULT_RG_THREADS, ResolvedCli) out of src/tools/grep/constants.ts into src/shared/ripgrep-cli.ts so they no longer straddle two sibling tool directories.
Before: src/tools/glob/constants.ts re-exported from src/tools/grep/constants.ts, violating the project's "tools should not import from sibling tools" rule enforced by .sisyphus/rules/modular-code-enforcement.md.
After: both src/tools/glob/ and src/tools/grep/ consume the shared helpers from src/shared/ripgrep-cli.ts. src/tools/grep/constants.ts keeps only the grep-specific UI-exposed constants.
Remove the dead plugin-dispose module and its dedicated test now that V1 plugin migration removed the last production call site. Clean the remaining bootstrap test mocks so src no longer references createPluginDispose.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Move the pending fallback, toast, and session-chain maps behind a shared controller initialized from the hook factory. This preserves the existing singleton semantics because exported helpers and hook instances still resolve the same lazily initialized controller while hook.ts stays under the 200-line limit.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
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.
Extract input preparation and image conversion handling into look-at-input-preparer.ts.
Extract prompt construction and multimodal session execution into look-at-prompt.ts and look-at-session-runner.ts while keeping createLookAt stable.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Convert the default export from the legacy callable Plugin to the V1 PluginModule shape (`{ id, server }`) documented by opencode's plugin SDK. This aligns oh-my-openagent with the canonical plugin entry format and removes plugin-format legacy debt.
Drop the module-level `let activePluginDispose` cleanup guard: opencode instantiates plugins in a scope-bound Layer per server and dynamic-imports fresh modules on reload, so module-level state is not preserved across reloads. Individual managers already register their own SIGINT/SIGTERM cleanup (skill-mcp-manager, background-agent process-cleanup), so the orphaned createPluginDispose call provided no runtime value.
Remove the non-standard `name` return field that opencode's Hooks interface does not include. The PluginModule's `id` now carries the plugin identity instead.
Drop the unused `lspManager` import that only fed the orphaned createPluginDispose.
Update src/index.test.ts and src/index.telemetry.test.ts to call `plugin.server(ctx)` instead of `plugin(ctx)`, and assert the V1 shape.
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>