Full Code of code-yeongyu/oh-my-openagent for AI

dev d2a49428b94d cached
1615 files
7.1 MB
1.9M tokens
4430 symbols
1 requests
Download .txt
Showing preview only (7,723K chars total). Download the full file or copy to clipboard to get everything.
Repository: code-yeongyu/oh-my-openagent
Branch: dev
Commit: d2a49428b94d
Files: 1615
Total size: 7.1 MB

Directory structure:
gitextract_lpvc9c4x/

├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.yml
│   │   ├── config.yml
│   │   ├── feature_request.yml
│   │   └── general.yml
│   ├── pull_request_template.md
│   └── workflows/
│       ├── ci.yml
│       ├── cla.yml
│       ├── lint-workflows.yml
│       ├── publish-platform.yml
│       ├── publish.yml
│       └── sisyphus-agent.yml
├── .gitignore
├── .opencode/
│   ├── background-tasks.json
│   ├── command/
│   │   ├── get-unpublished-changes.md
│   │   ├── omomomo.md
│   │   ├── publish.md
│   │   └── remove-deadcode.md
│   └── skills/
│       ├── github-triage/
│       │   ├── SKILL.md
│       │   └── scripts/
│       │       └── gh_fetch.py
│       ├── pre-publish-review/
│       │   └── SKILL.md
│       ├── work-with-pr/
│       │   └── SKILL.md
│       └── work-with-pr-workspace/
│           ├── evals/
│           │   └── evals.json
│           └── iteration-1/
│               ├── benchmark.json
│               ├── benchmark.md
│               ├── eval-1/
│               │   ├── eval_metadata.json
│               │   ├── with_skill/
│               │   │   ├── grading.json
│               │   │   ├── outputs/
│               │   │   │   ├── code-changes.md
│               │   │   │   ├── execution-plan.md
│               │   │   │   ├── pr-description.md
│               │   │   │   └── verification-strategy.md
│               │   │   └── timing.json
│               │   └── without_skill/
│               │       ├── grading.json
│               │       ├── outputs/
│               │       │   ├── code-changes.md
│               │       │   ├── execution-plan.md
│               │       │   ├── pr-description.md
│               │       │   └── verification-strategy.md
│               │       └── timing.json
│               ├── eval-2/
│               │   ├── eval_metadata.json
│               │   ├── with_skill/
│               │   │   ├── grading.json
│               │   │   ├── outputs/
│               │   │   │   ├── code-changes.md
│               │   │   │   ├── execution-plan.md
│               │   │   │   ├── pr-description.md
│               │   │   │   └── verification-strategy.md
│               │   │   └── timing.json
│               │   └── without_skill/
│               │       ├── grading.json
│               │       ├── outputs/
│               │       │   ├── code-changes.md
│               │       │   ├── execution-plan.md
│               │       │   ├── pr-description.md
│               │       │   └── verification-strategy.md
│               │       └── timing.json
│               ├── eval-3/
│               │   ├── eval_metadata.json
│               │   ├── with_skill/
│               │   │   ├── grading.json
│               │   │   ├── outputs/
│               │   │   │   ├── code-changes.md
│               │   │   │   ├── execution-plan.md
│               │   │   │   ├── pr-description.md
│               │   │   │   └── verification-strategy.md
│               │   │   └── timing.json
│               │   └── without_skill/
│               │       ├── grading.json
│               │       ├── outputs/
│               │       │   ├── code-changes.md
│               │       │   ├── execution-plan.md
│               │       │   ├── pr-description.md
│               │       │   └── verification-strategy.md
│               │       └── timing.json
│               ├── eval-4/
│               │   ├── eval_metadata.json
│               │   ├── with_skill/
│               │   │   ├── grading.json
│               │   │   ├── outputs/
│               │   │   │   ├── code-changes.md
│               │   │   │   ├── execution-plan.md
│               │   │   │   ├── pr-description.md
│               │   │   │   └── verification-strategy.md
│               │   │   └── timing.json
│               │   └── without_skill/
│               │       ├── grading.json
│               │       ├── outputs/
│               │       │   ├── code-changes.md
│               │       │   ├── execution-plan.md
│               │       │   ├── pr-description.md
│               │       │   └── verification-strategy.md
│               │       └── timing.json
│               ├── eval-5/
│               │   ├── eval_metadata.json
│               │   ├── with_skill/
│               │   │   ├── grading.json
│               │   │   ├── outputs/
│               │   │   │   ├── code-changes.md
│               │   │   │   ├── execution-plan.md
│               │   │   │   ├── pr-description.md
│               │   │   │   └── verification-strategy.md
│               │   │   └── timing.json
│               │   └── without_skill/
│               │       ├── grading.json
│               │       ├── outputs/
│               │       │   ├── code-changes.md
│               │       │   ├── execution-plan.md
│               │       │   ├── pr-description.md
│               │       │   └── verification-strategy.md
│               │       └── timing.json
│               └── review.html
├── AGENTS.md
├── CLA.md
├── CONTRIBUTING.md
├── FIX-BLOCKS.md
├── LICENSE.md
├── README.ja.md
├── README.ko.md
├── README.md
├── README.ru.md
├── README.zh-cn.md
├── assets/
│   └── oh-my-opencode.schema.json
├── bin/
│   ├── oh-my-opencode.js
│   ├── platform.d.ts
│   ├── platform.js
│   └── platform.test.ts
├── bun-test.d.ts
├── bunfig.toml
├── docs/
│   ├── guide/
│   │   ├── agent-model-matching.md
│   │   ├── installation.md
│   │   ├── orchestration.md
│   │   └── overview.md
│   ├── manifesto.md
│   ├── reference/
│   │   ├── cli.md
│   │   ├── configuration.md
│   │   └── features.md
│   └── troubleshooting/
│       └── ollama.md
├── package.json
├── packages/
│   ├── darwin-arm64/
│   │   ├── bin/
│   │   │   └── .gitkeep
│   │   └── package.json
│   ├── darwin-x64/
│   │   ├── bin/
│   │   │   └── .gitkeep
│   │   └── package.json
│   ├── darwin-x64-baseline/
│   │   └── package.json
│   ├── linux-arm64/
│   │   ├── bin/
│   │   │   └── .gitkeep
│   │   └── package.json
│   ├── linux-arm64-musl/
│   │   ├── bin/
│   │   │   └── .gitkeep
│   │   └── package.json
│   ├── linux-x64/
│   │   ├── bin/
│   │   │   └── .gitkeep
│   │   └── package.json
│   ├── linux-x64-baseline/
│   │   └── package.json
│   ├── linux-x64-musl/
│   │   ├── bin/
│   │   │   └── .gitkeep
│   │   └── package.json
│   ├── linux-x64-musl-baseline/
│   │   └── package.json
│   ├── windows-x64/
│   │   ├── bin/
│   │   │   └── .gitkeep
│   │   └── package.json
│   └── windows-x64-baseline/
│       └── package.json
├── postinstall.mjs
├── script/
│   ├── build-binaries.test.ts
│   ├── build-binaries.ts
│   ├── build-schema-document.ts
│   ├── build-schema.test.ts
│   ├── build-schema.ts
│   ├── generate-changelog.ts
│   └── publish.ts
├── signatures/
│   └── cla.json
├── src/
│   ├── AGENTS.md
│   ├── agents/
│   │   ├── AGENTS.md
│   │   ├── agent-builder.ts
│   │   ├── anti-duplication.test.ts
│   │   ├── atlas/
│   │   │   ├── agent.ts
│   │   │   ├── atlas-prompt.test.ts
│   │   │   ├── default.ts
│   │   │   ├── gemini.ts
│   │   │   ├── gpt.ts
│   │   │   ├── index.ts
│   │   │   ├── prompt-checkbox-enforcement.test.ts
│   │   │   └── prompt-section-builder.ts
│   │   ├── builtin-agents/
│   │   │   ├── agent-overrides.ts
│   │   │   ├── atlas-agent.ts
│   │   │   ├── available-skills.ts
│   │   │   ├── environment-context.ts
│   │   │   ├── general-agents.ts
│   │   │   ├── hephaestus-agent.ts
│   │   │   ├── model-resolution.ts
│   │   │   ├── resolve-file-uri.test.ts
│   │   │   ├── resolve-file-uri.ts
│   │   │   └── sisyphus-agent.ts
│   │   ├── builtin-agents.ts
│   │   ├── custom-agent-summaries.ts
│   │   ├── delegation-trust-prompt.test.ts
│   │   ├── dynamic-agent-prompt-builder.test.ts
│   │   ├── dynamic-agent-prompt-builder.ts
│   │   ├── env-context.test.ts
│   │   ├── env-context.ts
│   │   ├── explore.ts
│   │   ├── hephaestus/
│   │   │   ├── agent.test.ts
│   │   │   ├── agent.ts
│   │   │   ├── gpt-5-3-codex.ts
│   │   │   ├── gpt-5-4.ts
│   │   │   ├── gpt.ts
│   │   │   └── index.ts
│   │   ├── index.ts
│   │   ├── librarian.ts
│   │   ├── metis.ts
│   │   ├── momus.test.ts
│   │   ├── momus.ts
│   │   ├── multimodal-looker.ts
│   │   ├── oracle.ts
│   │   ├── prometheus/
│   │   │   ├── behavioral-summary.ts
│   │   │   ├── gemini.ts
│   │   │   ├── gpt.ts
│   │   │   ├── high-accuracy-mode.ts
│   │   │   ├── identity-constraints.ts
│   │   │   ├── index.ts
│   │   │   ├── interview-mode.ts
│   │   │   ├── plan-generation.ts
│   │   │   ├── plan-template.ts
│   │   │   └── system-prompt.ts
│   │   ├── prometheus-prompt.test.ts
│   │   ├── sisyphus/
│   │   │   ├── default.ts
│   │   │   ├── gemini.ts
│   │   │   ├── gpt-5-4.ts
│   │   │   └── index.ts
│   │   ├── sisyphus-junior/
│   │   │   ├── agent.ts
│   │   │   ├── default.ts
│   │   │   ├── gemini.ts
│   │   │   ├── gpt-5-3-codex.ts
│   │   │   ├── gpt-5-4.ts
│   │   │   ├── gpt.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── sisyphus.ts
│   │   ├── tool-restrictions.test.ts
│   │   ├── types.test.ts
│   │   ├── types.ts
│   │   └── utils.test.ts
│   ├── cli/
│   │   ├── AGENTS.md
│   │   ├── __snapshots__/
│   │   │   └── model-fallback.test.ts.snap
│   │   ├── cli-installer.test.ts
│   │   ├── cli-installer.ts
│   │   ├── cli-program.ts
│   │   ├── config-manager/
│   │   │   ├── AGENTS.md
│   │   │   ├── add-plugin-to-opencode-config.ts
│   │   │   ├── bun-install.test.ts
│   │   │   ├── bun-install.ts
│   │   │   ├── config-context.ts
│   │   │   ├── deep-merge-record.ts
│   │   │   ├── detect-current-config.ts
│   │   │   ├── ensure-config-directory-exists.ts
│   │   │   ├── format-error-with-suggestion.ts
│   │   │   ├── generate-omo-config.ts
│   │   │   ├── npm-dist-tags.ts
│   │   │   ├── opencode-binary.ts
│   │   │   ├── opencode-config-format.ts
│   │   │   ├── parse-opencode-config-file.ts
│   │   │   ├── plugin-detection.test.ts
│   │   │   ├── plugin-name-with-version.ts
│   │   │   ├── write-omo-config.test.ts
│   │   │   └── write-omo-config.ts
│   │   ├── config-manager.test.ts
│   │   ├── config-manager.ts
│   │   ├── doctor/
│   │   │   ├── checks/
│   │   │   │   ├── config.test.ts
│   │   │   │   ├── config.ts
│   │   │   │   ├── dependencies.test.ts
│   │   │   │   ├── dependencies.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── model-resolution-cache.ts
│   │   │   │   ├── model-resolution-config.ts
│   │   │   │   ├── model-resolution-details.ts
│   │   │   │   ├── model-resolution-effective-model.ts
│   │   │   │   ├── model-resolution-types.ts
│   │   │   │   ├── model-resolution-variant.ts
│   │   │   │   ├── model-resolution.test.ts
│   │   │   │   ├── model-resolution.ts
│   │   │   │   ├── system-binary.ts
│   │   │   │   ├── system-loaded-version.test.ts
│   │   │   │   ├── system-loaded-version.ts
│   │   │   │   ├── system-plugin.ts
│   │   │   │   ├── system.test.ts
│   │   │   │   ├── system.ts
│   │   │   │   ├── tools-gh.ts
│   │   │   │   ├── tools-lsp.ts
│   │   │   │   ├── tools-mcp.ts
│   │   │   │   └── tools.ts
│   │   │   ├── constants.ts
│   │   │   ├── format-default.test.ts
│   │   │   ├── format-default.ts
│   │   │   ├── format-shared.ts
│   │   │   ├── format-status.ts
│   │   │   ├── format-verbose.ts
│   │   │   ├── formatter.test.ts
│   │   │   ├── formatter.ts
│   │   │   ├── index.ts
│   │   │   ├── runner.test.ts
│   │   │   ├── runner.ts
│   │   │   └── types.ts
│   │   ├── fallback-chain-resolution.ts
│   │   ├── get-local-version/
│   │   │   ├── formatter.ts
│   │   │   ├── get-local-version.ts
│   │   │   ├── index.ts
│   │   │   └── types.ts
│   │   ├── index.test.ts
│   │   ├── index.ts
│   │   ├── install-validators.test.ts
│   │   ├── install-validators.ts
│   │   ├── install.test.ts
│   │   ├── install.ts
│   │   ├── mcp-oauth/
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   ├── login.test.ts
│   │   │   ├── login.ts
│   │   │   ├── logout.test.ts
│   │   │   ├── logout.ts
│   │   │   ├── status.test.ts
│   │   │   └── status.ts
│   │   ├── model-fallback-requirements.test.ts
│   │   ├── model-fallback-requirements.ts
│   │   ├── model-fallback-types.ts
│   │   ├── model-fallback.test.ts
│   │   ├── model-fallback.ts
│   │   ├── openai-only-model-catalog.test.ts
│   │   ├── openai-only-model-catalog.ts
│   │   ├── provider-availability.ts
│   │   ├── provider-model-id-transform.test.ts
│   │   ├── provider-model-id-transform.ts
│   │   ├── run/
│   │   │   ├── AGENTS.md
│   │   │   ├── agent-profile-colors.ts
│   │   │   ├── agent-resolver.ts
│   │   │   ├── completion-continuation.test.ts
│   │   │   ├── completion-verbose-logging.test.ts
│   │   │   ├── completion.test.ts
│   │   │   ├── completion.ts
│   │   │   ├── continuation-state-marker.test.ts
│   │   │   ├── continuation-state.ts
│   │   │   ├── display-chars.ts
│   │   │   ├── event-formatting.ts
│   │   │   ├── event-handlers.test.ts
│   │   │   ├── event-handlers.ts
│   │   │   ├── event-state.ts
│   │   │   ├── event-stream-processor.ts
│   │   │   ├── events.test.ts
│   │   │   ├── events.ts
│   │   │   ├── index.ts
│   │   │   ├── integration.test.ts
│   │   │   ├── json-output.test.ts
│   │   │   ├── json-output.ts
│   │   │   ├── message-part-delta.test.ts
│   │   │   ├── model-resolver.test.ts
│   │   │   ├── model-resolver.ts
│   │   │   ├── on-complete-hook.test.ts
│   │   │   ├── on-complete-hook.ts
│   │   │   ├── opencode-binary-resolver.test.ts
│   │   │   ├── opencode-binary-resolver.ts
│   │   │   ├── output-renderer.ts
│   │   │   ├── poll-for-completion.test.ts
│   │   │   ├── poll-for-completion.ts
│   │   │   ├── runner.test.ts
│   │   │   ├── runner.ts
│   │   │   ├── server-connection.test.ts
│   │   │   ├── server-connection.ts
│   │   │   ├── session-resolver.test.ts
│   │   │   ├── session-resolver.ts
│   │   │   ├── stdin-suppression.test.ts
│   │   │   ├── stdin-suppression.ts
│   │   │   ├── timestamp-output.test.ts
│   │   │   ├── timestamp-output.ts
│   │   │   ├── tool-input-preview.ts
│   │   │   └── types.ts
│   │   ├── tui-install-prompts.ts
│   │   ├── tui-installer.ts
│   │   └── types.ts
│   ├── config/
│   │   ├── AGENTS.md
│   │   ├── index.ts
│   │   ├── schema/
│   │   │   ├── agent-names.ts
│   │   │   ├── agent-overrides.ts
│   │   │   ├── babysitting.ts
│   │   │   ├── background-task-circuit-breaker.test.ts
│   │   │   ├── background-task.test.ts
│   │   │   ├── background-task.ts
│   │   │   ├── browser-automation.ts
│   │   │   ├── categories.ts
│   │   │   ├── claude-code.ts
│   │   │   ├── commands.ts
│   │   │   ├── comment-checker.ts
│   │   │   ├── dynamic-context-pruning.ts
│   │   │   ├── experimental.ts
│   │   │   ├── fallback-models.ts
│   │   │   ├── git-env-prefix.ts
│   │   │   ├── git-master.ts
│   │   │   ├── hooks.ts
│   │   │   ├── internal/
│   │   │   │   └── permission.ts
│   │   │   ├── notification.ts
│   │   │   ├── oh-my-opencode-config.ts
│   │   │   ├── openclaw.ts
│   │   │   ├── ralph-loop.ts
│   │   │   ├── runtime-fallback.ts
│   │   │   ├── sisyphus-agent.ts
│   │   │   ├── sisyphus.ts
│   │   │   ├── skills.ts
│   │   │   ├── start-work.ts
│   │   │   ├── tmux.ts
│   │   │   └── websearch.ts
│   │   ├── schema.test.ts
│   │   └── schema.ts
│   ├── create-hooks.ts
│   ├── create-managers.ts
│   ├── create-tools.ts
│   ├── features/
│   │   ├── AGENTS.md
│   │   ├── background-agent/
│   │   │   ├── AGENTS.md
│   │   │   ├── background-task-notification-template.ts
│   │   │   ├── cancel-task-cleanup.test.ts
│   │   │   ├── compaction-aware-message-resolver.test.ts
│   │   │   ├── compaction-aware-message-resolver.ts
│   │   │   ├── concurrency.test.ts
│   │   │   ├── concurrency.ts
│   │   │   ├── constants.ts
│   │   │   ├── default-message-staleness-timeout.test.ts
│   │   │   ├── default-stale-timeout.test.ts
│   │   │   ├── duration-formatter.ts
│   │   │   ├── error-classifier.test.ts
│   │   │   ├── error-classifier.ts
│   │   │   ├── fallback-retry-handler.test.ts
│   │   │   ├── fallback-retry-handler.ts
│   │   │   ├── index.ts
│   │   │   ├── loop-detector.test.ts
│   │   │   ├── loop-detector.ts
│   │   │   ├── manager-circuit-breaker.test.ts
│   │   │   ├── manager-session-permission.test.ts
│   │   │   ├── manager-shutdown-global-cleanup.test.ts
│   │   │   ├── manager.polling.test.ts
│   │   │   ├── manager.test.ts
│   │   │   ├── manager.ts
│   │   │   ├── opencode-client.ts
│   │   │   ├── process-cleanup.test.ts
│   │   │   ├── process-cleanup.ts
│   │   │   ├── remove-task-toast-tracking.ts
│   │   │   ├── session-idle-event-handler.test.ts
│   │   │   ├── session-idle-event-handler.ts
│   │   │   ├── session-status-classifier.test.ts
│   │   │   ├── session-status-classifier.ts
│   │   │   ├── spawner/
│   │   │   │   ├── parent-directory-resolver.test.ts
│   │   │   │   └── parent-directory-resolver.ts
│   │   │   ├── spawner.test.ts
│   │   │   ├── spawner.ts
│   │   │   ├── state.ts
│   │   │   ├── subagent-spawn-limits.test.ts
│   │   │   ├── subagent-spawn-limits.ts
│   │   │   ├── task-completion-cleanup.test.ts
│   │   │   ├── task-history-cleanup.test.ts
│   │   │   ├── task-history.test.ts
│   │   │   ├── task-history.ts
│   │   │   ├── task-poller.test.ts
│   │   │   ├── task-poller.ts
│   │   │   └── types.ts
│   │   ├── boulder-state/
│   │   │   ├── constants.ts
│   │   │   ├── index.ts
│   │   │   ├── storage.test.ts
│   │   │   ├── storage.ts
│   │   │   ├── top-level-task.test.ts
│   │   │   ├── top-level-task.ts
│   │   │   └── types.ts
│   │   ├── builtin-commands/
│   │   │   ├── commands.test.ts
│   │   │   ├── commands.ts
│   │   │   ├── index.ts
│   │   │   ├── templates/
│   │   │   │   ├── handoff.ts
│   │   │   │   ├── init-deep.ts
│   │   │   │   ├── ralph-loop.ts
│   │   │   │   ├── refactor.ts
│   │   │   │   ├── start-work.ts
│   │   │   │   ├── stop-continuation.test.ts
│   │   │   │   └── stop-continuation.ts
│   │   │   └── types.ts
│   │   ├── builtin-skills/
│   │   │   ├── agent-browser/
│   │   │   │   └── SKILL.md
│   │   │   ├── dev-browser/
│   │   │   │   ├── SKILL.md
│   │   │   │   └── references/
│   │   │   │       ├── installation.md
│   │   │   │       └── scraping.md
│   │   │   ├── frontend-ui-ux/
│   │   │   │   └── SKILL.md
│   │   │   ├── git-master/
│   │   │   │   └── SKILL.md
│   │   │   ├── index.ts
│   │   │   ├── skills/
│   │   │   │   ├── dev-browser.ts
│   │   │   │   ├── frontend-ui-ux.ts
│   │   │   │   ├── git-master-skill-metadata.ts
│   │   │   │   ├── git-master.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── playwright-cli.ts
│   │   │   │   └── playwright.ts
│   │   │   ├── skills.test.ts
│   │   │   ├── skills.ts
│   │   │   └── types.ts
│   │   ├── claude-code-agent-loader/
│   │   │   ├── claude-model-mapper.test.ts
│   │   │   ├── claude-model-mapper.ts
│   │   │   ├── index.ts
│   │   │   ├── loader.ts
│   │   │   └── types.ts
│   │   ├── claude-code-command-loader/
│   │   │   ├── index.ts
│   │   │   ├── loader.ts
│   │   │   └── types.ts
│   │   ├── claude-code-mcp-loader/
│   │   │   ├── env-expander.ts
│   │   │   ├── index.ts
│   │   │   ├── loader.test.ts
│   │   │   ├── loader.ts
│   │   │   ├── transformer.ts
│   │   │   └── types.ts
│   │   ├── claude-code-plugin-loader/
│   │   │   ├── agent-loader.ts
│   │   │   ├── command-loader.ts
│   │   │   ├── discovery.ts
│   │   │   ├── hook-loader.ts
│   │   │   ├── index.ts
│   │   │   ├── loader.ts
│   │   │   ├── mcp-server-loader.ts
│   │   │   ├── plugin-path-resolver.ts
│   │   │   ├── skill-loader.ts
│   │   │   └── types.ts
│   │   ├── claude-code-session-state/
│   │   │   ├── index.ts
│   │   │   ├── state.test.ts
│   │   │   └── state.ts
│   │   ├── claude-tasks/
│   │   │   ├── AGENTS.md
│   │   │   ├── session-storage.test.ts
│   │   │   ├── session-storage.ts
│   │   │   ├── storage.test.ts
│   │   │   ├── storage.ts
│   │   │   ├── types.test.ts
│   │   │   └── types.ts
│   │   ├── context-injector/
│   │   │   ├── collector.test.ts
│   │   │   ├── collector.ts
│   │   │   ├── index.ts
│   │   │   ├── injector.test.ts
│   │   │   ├── injector.ts
│   │   │   └── types.ts
│   │   ├── hook-message-injector/
│   │   │   ├── constants.ts
│   │   │   ├── index.ts
│   │   │   ├── injector.test.ts
│   │   │   ├── injector.ts
│   │   │   └── types.ts
│   │   ├── mcp-oauth/
│   │   │   ├── AGENTS.md
│   │   │   ├── callback-server.test.ts
│   │   │   ├── callback-server.ts
│   │   │   ├── dcr.test.ts
│   │   │   ├── dcr.ts
│   │   │   ├── discovery.test.ts
│   │   │   ├── discovery.ts
│   │   │   ├── oauth-authorization-flow.ts
│   │   │   ├── provider.test.ts
│   │   │   ├── provider.ts
│   │   │   ├── resource-indicator.test.ts
│   │   │   ├── resource-indicator.ts
│   │   │   ├── schema.test.ts
│   │   │   ├── schema.ts
│   │   │   ├── step-up.test.ts
│   │   │   ├── step-up.ts
│   │   │   ├── storage.test.ts
│   │   │   └── storage.ts
│   │   ├── opencode-skill-loader/
│   │   │   ├── AGENTS.md
│   │   │   ├── agents-skills-global.test.ts
│   │   │   ├── allowed-tools-parser.ts
│   │   │   ├── async-loader.test.ts
│   │   │   ├── async-loader.ts
│   │   │   ├── blocking.test.ts
│   │   │   ├── blocking.ts
│   │   │   ├── config-source-discovery.test.ts
│   │   │   ├── config-source-discovery.ts
│   │   │   ├── discover-worker.ts
│   │   │   ├── git-master-template-injection.test.ts
│   │   │   ├── git-master-template-injection.ts
│   │   │   ├── index.ts
│   │   │   ├── loaded-skill-from-path.ts
│   │   │   ├── loaded-skill-template-extractor.ts
│   │   │   ├── loader.test.ts
│   │   │   ├── loader.ts
│   │   │   ├── merger/
│   │   │   │   ├── builtin-skill-converter.ts
│   │   │   │   ├── config-skill-entry-loader.ts
│   │   │   │   ├── scope-priority.ts
│   │   │   │   ├── skill-definition-merger.ts
│   │   │   │   └── skills-config-normalizer.ts
│   │   │   ├── merger.test.ts
│   │   │   ├── merger.ts
│   │   │   ├── project-skill-tool-references.test.ts
│   │   │   ├── skill-content.test.ts
│   │   │   ├── skill-content.ts
│   │   │   ├── skill-deduplication.ts
│   │   │   ├── skill-definition-record.ts
│   │   │   ├── skill-directory-loader.ts
│   │   │   ├── skill-discovery.ts
│   │   │   ├── skill-mcp-config.ts
│   │   │   ├── skill-resolution-options.ts
│   │   │   ├── skill-template-resolver.ts
│   │   │   └── types.ts
│   │   ├── run-continuation-state/
│   │   │   ├── constants.ts
│   │   │   ├── index.ts
│   │   │   ├── storage.test.ts
│   │   │   ├── storage.ts
│   │   │   └── types.ts
│   │   ├── skill-mcp-manager/
│   │   │   ├── cleanup.ts
│   │   │   ├── connection-race.test.ts
│   │   │   ├── connection-type.ts
│   │   │   ├── connection.ts
│   │   │   ├── disconnect-cleanup.test.ts
│   │   │   ├── env-cleaner.test.ts
│   │   │   ├── env-cleaner.ts
│   │   │   ├── http-client.ts
│   │   │   ├── index.ts
│   │   │   ├── manager.test.ts
│   │   │   ├── manager.ts
│   │   │   ├── oauth-handler.ts
│   │   │   ├── stdio-client.ts
│   │   │   └── types.ts
│   │   ├── task-toast-manager/
│   │   │   ├── index.ts
│   │   │   ├── manager.test.ts
│   │   │   ├── manager.ts
│   │   │   └── types.ts
│   │   ├── tmux-subagent/
│   │   │   ├── AGENTS.md
│   │   │   ├── action-executor-core.ts
│   │   │   ├── action-executor.test.ts
│   │   │   ├── action-executor.ts
│   │   │   ├── cleanup.ts
│   │   │   ├── decision-engine.test.ts
│   │   │   ├── decision-engine.ts
│   │   │   ├── event-handlers.ts
│   │   │   ├── grid-planning.ts
│   │   │   ├── index.ts
│   │   │   ├── layout-config.test.ts
│   │   │   ├── manager.test.ts
│   │   │   ├── manager.ts
│   │   │   ├── oldest-agent-pane.ts
│   │   │   ├── pane-split-availability.ts
│   │   │   ├── pane-state-parser.test.ts
│   │   │   ├── pane-state-parser.ts
│   │   │   ├── pane-state-querier.test.ts
│   │   │   ├── pane-state-querier.ts
│   │   │   ├── polling-constants.ts
│   │   │   ├── polling-manager.test.ts
│   │   │   ├── polling-manager.ts
│   │   │   ├── polling.ts
│   │   │   ├── session-created-event.ts
│   │   │   ├── session-created-handler.ts
│   │   │   ├── session-deleted-handler.ts
│   │   │   ├── session-message-count.ts
│   │   │   ├── session-ready-waiter.ts
│   │   │   ├── session-status-parser.ts
│   │   │   ├── spawn-action-decider.ts
│   │   │   ├── spawn-target-finder.ts
│   │   │   ├── tmux-grid-constants.ts
│   │   │   ├── tracked-session-state.ts
│   │   │   ├── types.ts
│   │   │   └── zombie-pane.test.ts
│   │   └── tool-metadata-store/
│   │       ├── index.test.ts
│   │       ├── index.ts
│   │       └── store.ts
│   ├── hooks/
│   │   ├── AGENTS.md
│   │   ├── agent-usage-reminder/
│   │   │   ├── constants.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.ts
│   │   │   ├── storage.ts
│   │   │   └── types.ts
│   │   ├── anthropic-context-window-limit-recovery/
│   │   │   ├── AGENTS.md
│   │   │   ├── aggressive-truncation-strategy.ts
│   │   │   ├── client.ts
│   │   │   ├── deduplication-recovery.ts
│   │   │   ├── empty-content-recovery-sdk.test.ts
│   │   │   ├── empty-content-recovery-sdk.ts
│   │   │   ├── empty-content-recovery.ts
│   │   │   ├── executor.test.ts
│   │   │   ├── executor.ts
│   │   │   ├── index.ts
│   │   │   ├── message-builder.ts
│   │   │   ├── message-storage-directory.ts
│   │   │   ├── parser.test.ts
│   │   │   ├── parser.ts
│   │   │   ├── pruning-deduplication.test.ts
│   │   │   ├── pruning-deduplication.ts
│   │   │   ├── pruning-tool-output-truncation.ts
│   │   │   ├── pruning-types.ts
│   │   │   ├── recovery-deduplication.test.ts
│   │   │   ├── recovery-hook.test.ts
│   │   │   ├── recovery-hook.ts
│   │   │   ├── recovery-strategy.ts
│   │   │   ├── state.ts
│   │   │   ├── storage-paths.ts
│   │   │   ├── storage.test.ts
│   │   │   ├── storage.ts
│   │   │   ├── summarize-retry-strategy.test.ts
│   │   │   ├── summarize-retry-strategy.ts
│   │   │   ├── target-token-truncation.ts
│   │   │   ├── tool-part-types.ts
│   │   │   ├── tool-result-storage-sdk.ts
│   │   │   ├── tool-result-storage.ts
│   │   │   └── types.ts
│   │   ├── anthropic-effort/
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── atlas/
│   │   │   ├── AGENTS.md
│   │   │   ├── atlas-hook.ts
│   │   │   ├── boulder-continuation-injector.ts
│   │   │   ├── boulder-session-lineage.ts
│   │   │   ├── compaction-agent-filter.test.ts
│   │   │   ├── event-handler.ts
│   │   │   ├── final-wave-approval-gate-regression.test.ts
│   │   │   ├── final-wave-approval-gate.test.ts
│   │   │   ├── final-wave-approval-gate.ts
│   │   │   ├── final-wave-plan-state.ts
│   │   │   ├── hook-name.ts
│   │   │   ├── idle-event-lineage.test.ts
│   │   │   ├── idle-event.ts
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   ├── is-abort-error.ts
│   │   │   ├── recent-model-resolver.ts
│   │   │   ├── resolve-active-boulder-session.ts
│   │   │   ├── session-last-agent.sqlite.test.ts
│   │   │   ├── session-last-agent.ts
│   │   │   ├── sisyphus-path.ts
│   │   │   ├── subagent-session-id.test.ts
│   │   │   ├── subagent-session-id.ts
│   │   │   ├── system-reminder-templates.test.ts
│   │   │   ├── system-reminder-templates.ts
│   │   │   ├── tool-execute-after.ts
│   │   │   ├── tool-execute-before.ts
│   │   │   ├── tsconfig.json
│   │   │   ├── types.ts
│   │   │   ├── verification-reminders.test.ts
│   │   │   ├── verification-reminders.ts
│   │   │   └── write-edit-tool-policy.ts
│   │   ├── auto-slash-command/
│   │   │   ├── auto-slash-command-leak.test.ts
│   │   │   ├── constants.test.ts
│   │   │   ├── constants.ts
│   │   │   ├── detector.test.ts
│   │   │   ├── detector.ts
│   │   │   ├── executor-resolution.test.ts
│   │   │   ├── executor.test.ts
│   │   │   ├── executor.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   ├── processed-command-store.ts
│   │   │   └── types.ts
│   │   ├── auto-update-checker/
│   │   │   ├── cache.test.ts
│   │   │   ├── cache.ts
│   │   │   ├── checker/
│   │   │   │   ├── cached-version.ts
│   │   │   │   ├── check-for-update.ts
│   │   │   │   ├── config-paths.ts
│   │   │   │   ├── jsonc-strip.ts
│   │   │   │   ├── latest-version.ts
│   │   │   │   ├── local-dev-path.ts
│   │   │   │   ├── local-dev-version.ts
│   │   │   │   ├── package-json-locator.ts
│   │   │   │   ├── pinned-version-updater.test.ts
│   │   │   │   ├── pinned-version-updater.ts
│   │   │   │   ├── plugin-entry.test.ts
│   │   │   │   ├── plugin-entry.ts
│   │   │   │   ├── sync-package-json.test.ts
│   │   │   │   └── sync-package-json.ts
│   │   │   ├── checker.test.ts
│   │   │   ├── checker.ts
│   │   │   ├── constants.test.ts
│   │   │   ├── constants.ts
│   │   │   ├── hook/
│   │   │   │   ├── background-update-check.test.ts
│   │   │   │   ├── background-update-check.ts
│   │   │   │   ├── config-errors-toast.ts
│   │   │   │   ├── connected-providers-status.ts
│   │   │   │   ├── model-cache-warning.ts
│   │   │   │   ├── spinner-toast.ts
│   │   │   │   ├── startup-toasts.ts
│   │   │   │   ├── update-toasts.ts
│   │   │   │   └── workspace-resolution.test.ts
│   │   │   ├── hook.test.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   ├── types.ts
│   │   │   └── version-channel.ts
│   │   ├── background-notification/
│   │   │   ├── hook.ts
│   │   │   ├── index.ts
│   │   │   └── types.ts
│   │   ├── category-skill-reminder/
│   │   │   ├── formatter.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── claude-code-hooks/
│   │   │   ├── AGENTS.md
│   │   │   ├── claude-code-hooks-hook.ts
│   │   │   ├── config-loader.ts
│   │   │   ├── config.ts
│   │   │   ├── dispatch-hook.ts
│   │   │   ├── execute-http-hook.test.ts
│   │   │   ├── execute-http-hook.ts
│   │   │   ├── handlers/
│   │   │   │   ├── chat-message-handler.ts
│   │   │   │   ├── pre-compact-handler.ts
│   │   │   │   ├── session-event-handler.ts
│   │   │   │   ├── tool-execute-after-handler.test.ts
│   │   │   │   ├── tool-execute-after-handler.ts
│   │   │   │   └── tool-execute-before-handler.ts
│   │   │   ├── index.ts
│   │   │   ├── plugin-config.ts
│   │   │   ├── post-tool-use.ts
│   │   │   ├── pre-compact.ts
│   │   │   ├── pre-tool-use.ts
│   │   │   ├── session-hook-state.ts
│   │   │   ├── stop.test.ts
│   │   │   ├── stop.ts
│   │   │   ├── todo.ts
│   │   │   ├── tool-input-cache.ts
│   │   │   ├── transcript.test.ts
│   │   │   ├── transcript.ts
│   │   │   ├── types.ts
│   │   │   ├── user-prompt-submit.test.ts
│   │   │   └── user-prompt-submit.ts
│   │   ├── comment-checker/
│   │   │   ├── cli-runner.ts
│   │   │   ├── cli.test.ts
│   │   │   ├── cli.ts
│   │   │   ├── downloader.ts
│   │   │   ├── hook.apply-patch.test.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.ts
│   │   │   ├── pending-calls.test.ts
│   │   │   ├── pending-calls.ts
│   │   │   └── types.ts
│   │   ├── compaction-context-injector/
│   │   │   ├── compaction-context-prompt.ts
│   │   │   ├── constants.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   ├── recovery-prompt-config.ts
│   │   │   ├── recovery.test.ts
│   │   │   ├── recovery.ts
│   │   │   ├── session-id.ts
│   │   │   ├── session-prompt-config-resolver.test.ts
│   │   │   ├── session-prompt-config-resolver.ts
│   │   │   ├── tail-monitor.ts
│   │   │   ├── types.ts
│   │   │   └── validated-model.ts
│   │   ├── compaction-todo-preserver/
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── context-window-monitor.model-context-limits.test.ts
│   │   ├── context-window-monitor.test.ts
│   │   ├── context-window-monitor.ts
│   │   ├── delegate-task-retry/
│   │   │   ├── guidance.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   └── patterns.ts
│   │   ├── directory-agents-injector/
│   │   │   ├── constants.ts
│   │   │   ├── finder.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.ts
│   │   │   ├── injector.test.ts
│   │   │   ├── injector.ts
│   │   │   └── storage.ts
│   │   ├── directory-readme-injector/
│   │   │   ├── constants.ts
│   │   │   ├── finder.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.ts
│   │   │   ├── injector.test.ts
│   │   │   ├── injector.ts
│   │   │   └── storage.ts
│   │   ├── edit-error-recovery/
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── empty-task-response-detector.ts
│   │   ├── hashline-edit-diff-enhancer/
│   │   │   └── hook.ts
│   │   ├── hashline-read-enhancer/
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── index.ts
│   │   ├── interactive-bash-session/
│   │   │   ├── constants.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.ts
│   │   │   ├── interactive-bash-session-tracker.ts
│   │   │   ├── parser.ts
│   │   │   ├── state-manager.ts
│   │   │   ├── storage.ts
│   │   │   ├── tmux-command-parser.ts
│   │   │   └── types.ts
│   │   ├── json-error-recovery/
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── keyword-detector/
│   │   │   ├── AGENTS.md
│   │   │   ├── analyze/
│   │   │   │   ├── default.ts
│   │   │   │   └── index.ts
│   │   │   ├── constants.ts
│   │   │   ├── detector.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   ├── search/
│   │   │   │   ├── default.ts
│   │   │   │   └── index.ts
│   │   │   ├── types.ts
│   │   │   ├── ultrawork/
│   │   │   │   ├── default.ts
│   │   │   │   ├── gemini.ts
│   │   │   │   ├── gpt.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── planner.ts
│   │   │   │   └── source-detector.ts
│   │   │   └── ultrawork-runtime-variant.test.ts
│   │   ├── model-fallback/
│   │   │   ├── hook.test.ts
│   │   │   └── hook.ts
│   │   ├── no-hephaestus-non-gpt/
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── no-sisyphus-gpt/
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── non-interactive-env/
│   │   │   ├── constants.ts
│   │   │   ├── detector.ts
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   ├── non-interactive-env-hook.ts
│   │   │   └── types.ts
│   │   ├── openclaw.test.ts
│   │   ├── openclaw.ts
│   │   ├── preemptive-compaction.aws-bedrock.test.ts
│   │   ├── preemptive-compaction.context-limit-cache.test.ts
│   │   ├── preemptive-compaction.test.ts
│   │   ├── preemptive-compaction.ts
│   │   ├── prometheus-md-only/
│   │   │   ├── agent-matcher.ts
│   │   │   ├── agent-resolution.ts
│   │   │   ├── constants.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   └── path-policy.ts
│   │   ├── question-label-truncator/
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── ralph-loop/
│   │   │   ├── AGENTS.md
│   │   │   ├── command-arguments.ts
│   │   │   ├── completion-handler.ts
│   │   │   ├── completion-promise-detector.test.ts
│   │   │   ├── completion-promise-detector.ts
│   │   │   ├── constants.ts
│   │   │   ├── continuation-prompt-builder.ts
│   │   │   ├── continuation-prompt-injector.ts
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   ├── iteration-continuation.ts
│   │   │   ├── loop-session-recovery.ts
│   │   │   ├── loop-state-controller.ts
│   │   │   ├── message-storage-directory.ts
│   │   │   ├── pending-verification-handler.ts
│   │   │   ├── ralph-loop-event-handler.ts
│   │   │   ├── ralph-loop-hook.ts
│   │   │   ├── reset-strategy-race-condition.test.ts
│   │   │   ├── session-event-handler.ts
│   │   │   ├── session-reset-strategy.ts
│   │   │   ├── storage.ts
│   │   │   ├── types.ts
│   │   │   ├── ulw-loop-verification.test.ts
│   │   │   ├── verification-failure-handler.ts
│   │   │   └── with-timeout.ts
│   │   ├── read-image-resizer/
│   │   │   ├── hook.test.ts
│   │   │   ├── hook.ts
│   │   │   ├── image-dimensions.test.ts
│   │   │   ├── image-dimensions.ts
│   │   │   ├── image-resizer.test.ts
│   │   │   ├── image-resizer.ts
│   │   │   ├── index.ts
│   │   │   └── types.ts
│   │   ├── rules-injector/
│   │   │   ├── AGENTS.md
│   │   │   ├── cache.ts
│   │   │   ├── constants.ts
│   │   │   ├── finder.test.ts
│   │   │   ├── finder.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.ts
│   │   │   ├── injector.test.ts
│   │   │   ├── injector.ts
│   │   │   ├── matcher.ts
│   │   │   ├── output-path.test.ts
│   │   │   ├── output-path.ts
│   │   │   ├── parser.test.ts
│   │   │   ├── parser.ts
│   │   │   ├── project-root-finder.ts
│   │   │   ├── rule-distance.ts
│   │   │   ├── rule-file-finder.ts
│   │   │   ├── rule-file-scanner.ts
│   │   │   ├── storage.ts
│   │   │   └── types.ts
│   │   ├── runtime-fallback/
│   │   │   ├── agent-resolver.ts
│   │   │   ├── auto-retry.ts
│   │   │   ├── chat-message-handler.ts
│   │   │   ├── constants.ts
│   │   │   ├── dispose.test.ts
│   │   │   ├── error-classifier.test.ts
│   │   │   ├── error-classifier.ts
│   │   │   ├── event-handler.test.ts
│   │   │   ├── event-handler.ts
│   │   │   ├── fallback-bootstrap-model.ts
│   │   │   ├── fallback-models.test.ts
│   │   │   ├── fallback-models.ts
│   │   │   ├── fallback-retry-dispatcher.ts
│   │   │   ├── fallback-state.ts
│   │   │   ├── hook-dispose-cleanup.test.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   ├── last-user-retry-parts.ts
│   │   │   ├── message-update-handler.test.ts
│   │   │   ├── message-update-handler.ts
│   │   │   ├── retry-model-payload.ts
│   │   │   ├── session-messages.ts
│   │   │   ├── session-status-handler.test.ts
│   │   │   ├── session-status-handler.ts
│   │   │   ├── success-retry-key-cleanup.test.ts
│   │   │   ├── types.ts
│   │   │   └── visible-assistant-response.ts
│   │   ├── session-notification-content.test.ts
│   │   ├── session-notification-content.ts
│   │   ├── session-notification-formatting.ts
│   │   ├── session-notification-input-needed.test.ts
│   │   ├── session-notification-scheduler.ts
│   │   ├── session-notification-sender.test.ts
│   │   ├── session-notification-sender.ts
│   │   ├── session-notification-utils.ts
│   │   ├── session-notification.test.ts
│   │   ├── session-notification.ts
│   │   ├── session-recovery/
│   │   │   ├── AGENTS.md
│   │   │   ├── constants.ts
│   │   │   ├── detect-error-type.test.ts
│   │   │   ├── detect-error-type.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   ├── recover-empty-content-message-sdk.test.ts
│   │   │   ├── recover-empty-content-message-sdk.ts
│   │   │   ├── recover-thinking-block-order.ts
│   │   │   ├── recover-thinking-disabled-violation.ts
│   │   │   ├── recover-tool-result-missing.ts
│   │   │   ├── recover-unavailable-tool.ts
│   │   │   ├── resume.test.ts
│   │   │   ├── resume.ts
│   │   │   ├── storage/
│   │   │   │   ├── empty-messages.ts
│   │   │   │   ├── empty-text.ts
│   │   │   │   ├── message-dir.ts
│   │   │   │   ├── messages-reader.ts
│   │   │   │   ├── orphan-thinking-search.ts
│   │   │   │   ├── part-content.ts
│   │   │   │   ├── part-id.ts
│   │   │   │   ├── parts-reader.ts
│   │   │   │   ├── readers-from-sdk.test.ts
│   │   │   │   ├── text-part-injector.ts
│   │   │   │   ├── thinking-block-search.ts
│   │   │   │   ├── thinking-prepend.ts
│   │   │   │   └── thinking-strip.ts
│   │   │   ├── storage.ts
│   │   │   └── types.ts
│   │   ├── session-todo-status.ts
│   │   ├── shared/
│   │   │   └── compaction-model-resolver.ts
│   │   ├── sisyphus-junior-notepad/
│   │   │   ├── constants.ts
│   │   │   ├── hook.ts
│   │   │   └── index.ts
│   │   ├── start-work/
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   ├── parse-user-request.test.ts
│   │   │   ├── parse-user-request.ts
│   │   │   ├── start-work-hook.ts
│   │   │   ├── worktree-detector.test.ts
│   │   │   └── worktree-detector.ts
│   │   ├── stop-continuation-guard/
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── task-reminder/
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── task-resume-info/
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── tasks-todowrite-disabler/
│   │   │   ├── constants.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── think-mode/
│   │   │   ├── detector.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   ├── switcher.test.ts
│   │   │   ├── switcher.ts
│   │   │   └── types.ts
│   │   ├── thinking-block-validator/
│   │   │   ├── hook.ts
│   │   │   └── index.ts
│   │   ├── todo-continuation-enforcer/
│   │   │   ├── AGENTS.md
│   │   │   ├── abort-detection.ts
│   │   │   ├── compaction-guard.ts
│   │   │   ├── constants.ts
│   │   │   ├── continuation-injection.test.ts
│   │   │   ├── continuation-injection.ts
│   │   │   ├── countdown.ts
│   │   │   ├── dispose.test.ts
│   │   │   ├── handler.ts
│   │   │   ├── idle-event.ts
│   │   │   ├── index.ts
│   │   │   ├── message-directory.ts
│   │   │   ├── non-idle-events.ts
│   │   │   ├── pending-question-detection.test.ts
│   │   │   ├── pending-question-detection.ts
│   │   │   ├── resolve-message-info.ts
│   │   │   ├── session-state.regression.test.ts
│   │   │   ├── session-state.test.ts
│   │   │   ├── session-state.ts
│   │   │   ├── stagnation-detection.test.ts
│   │   │   ├── stagnation-detection.ts
│   │   │   ├── todo-continuation-enforcer.test.ts
│   │   │   ├── todo.ts
│   │   │   └── types.ts
│   │   ├── todo-description-override/
│   │   │   ├── description.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── tool-output-truncator.test.ts
│   │   ├── tool-output-truncator.ts
│   │   ├── unstable-agent-babysitter/
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   ├── task-message-analyzer.ts
│   │   │   └── unstable-agent-babysitter-hook.ts
│   │   └── write-existing-file-guard/
│   │       ├── hook.ts
│   │       ├── index.test.ts
│   │       └── index.ts
│   ├── index.compaction-model-agnostic.static.test.ts
│   ├── index.test.ts
│   ├── index.ts
│   ├── mcp/
│   │   ├── AGENTS.md
│   │   ├── context7.ts
│   │   ├── grep-app.ts
│   │   ├── index.test.ts
│   │   ├── index.ts
│   │   ├── types.ts
│   │   ├── websearch.test.ts
│   │   └── websearch.ts
│   ├── openclaw/
│   │   ├── __tests__/
│   │   │   ├── config.test.ts
│   │   │   ├── dispatcher.test.ts
│   │   │   └── tmux.test.ts
│   │   ├── config.ts
│   │   ├── daemon.ts
│   │   ├── dispatcher.ts
│   │   ├── index.ts
│   │   ├── reply-listener.ts
│   │   ├── session-registry.ts
│   │   ├── tmux.ts
│   │   └── types.ts
│   ├── plugin/
│   │   ├── AGENTS.md
│   │   ├── available-categories.ts
│   │   ├── chat-headers.test.ts
│   │   ├── chat-headers.ts
│   │   ├── chat-message.test.ts
│   │   ├── chat-message.ts
│   │   ├── chat-params.test.ts
│   │   ├── chat-params.ts
│   │   ├── event-compaction-agent.test.ts
│   │   ├── event.model-fallback.test.ts
│   │   ├── event.test.ts
│   │   ├── event.ts
│   │   ├── hooks/
│   │   │   ├── create-continuation-hooks.ts
│   │   │   ├── create-core-hooks.ts
│   │   │   ├── create-session-hooks.test.ts
│   │   │   ├── create-session-hooks.ts
│   │   │   ├── create-skill-hooks.ts
│   │   │   ├── create-tool-guard-hooks.ts
│   │   │   └── create-transform-hooks.ts
│   │   ├── messages-transform.ts
│   │   ├── normalize-tool-arg-schemas.test.ts
│   │   ├── normalize-tool-arg-schemas.ts
│   │   ├── recent-synthetic-idles.test.ts
│   │   ├── recent-synthetic-idles.ts
│   │   ├── session-agent-resolver.test.ts
│   │   ├── session-agent-resolver.ts
│   │   ├── session-status-normalizer.test.ts
│   │   ├── session-status-normalizer.ts
│   │   ├── skill-context.test.ts
│   │   ├── skill-context.ts
│   │   ├── system-transform.ts
│   │   ├── tool-execute-after.test.ts
│   │   ├── tool-execute-after.ts
│   │   ├── tool-execute-before-session-notification.test.ts
│   │   ├── tool-execute-before.test.ts
│   │   ├── tool-execute-before.ts
│   │   ├── tool-execute-before.ulw-loop.test.ts
│   │   ├── tool-registry.ts
│   │   ├── types.ts
│   │   ├── ultrawork-db-model-override.test.ts
│   │   ├── ultrawork-db-model-override.ts
│   │   ├── ultrawork-model-override.test.ts
│   │   ├── ultrawork-model-override.ts
│   │   ├── ultrawork-variant-availability.test.ts
│   │   ├── ultrawork-variant-availability.ts
│   │   └── unstable-agent-babysitter.ts
│   ├── plugin-config.test.ts
│   ├── plugin-config.ts
│   ├── plugin-dispose.test.ts
│   ├── plugin-dispose.ts
│   ├── plugin-handlers/
│   │   ├── AGENTS.md
│   │   ├── agent-config-handler.test.ts
│   │   ├── agent-config-handler.ts
│   │   ├── agent-key-remapper.test.ts
│   │   ├── agent-key-remapper.ts
│   │   ├── agent-override-protection.ts
│   │   ├── agent-priority-order.ts
│   │   ├── category-config-resolver.ts
│   │   ├── command-config-handler.ts
│   │   ├── config-handler-formatter.test.ts
│   │   ├── config-handler.test.ts
│   │   ├── config-handler.ts
│   │   ├── index.ts
│   │   ├── mcp-config-handler.test.ts
│   │   ├── mcp-config-handler.ts
│   │   ├── plan-model-inheritance.test.ts
│   │   ├── plan-model-inheritance.ts
│   │   ├── plugin-components-loader.ts
│   │   ├── prometheus-agent-config-builder.ts
│   │   ├── provider-config-handler.test.ts
│   │   ├── provider-config-handler.ts
│   │   ├── tool-config-handler.test.ts
│   │   └── tool-config-handler.ts
│   ├── plugin-interface.ts
│   ├── plugin-state.ts
│   ├── shared/
│   │   ├── AGENTS.md
│   │   ├── agent-config-integration.test.ts
│   │   ├── agent-display-names.test.ts
│   │   ├── agent-display-names.ts
│   │   ├── agent-tool-restrictions.ts
│   │   ├── agent-variant.test.ts
│   │   ├── agent-variant.ts
│   │   ├── binary-downloader.ts
│   │   ├── claude-config-dir.test.ts
│   │   ├── claude-config-dir.ts
│   │   ├── command-executor/
│   │   │   ├── embedded-commands.ts
│   │   │   ├── execute-command.ts
│   │   │   ├── execute-hook-command.ts
│   │   │   ├── home-directory.ts
│   │   │   ├── resolve-commands-in-text.ts
│   │   │   └── shell-path.ts
│   │   ├── command-executor.ts
│   │   ├── compaction-agent-config-checkpoint.ts
│   │   ├── config-errors.ts
│   │   ├── connected-providers-cache.test.ts
│   │   ├── connected-providers-cache.ts
│   │   ├── context-limit-resolver.test.ts
│   │   ├── context-limit-resolver.ts
│   │   ├── data-path.ts
│   │   ├── deep-merge.test.ts
│   │   ├── deep-merge.ts
│   │   ├── disabled-tools.ts
│   │   ├── dynamic-truncator.test.ts
│   │   ├── dynamic-truncator.ts
│   │   ├── external-plugin-detector.test.ts
│   │   ├── external-plugin-detector.ts
│   │   ├── fallback-chain-from-models.test.ts
│   │   ├── fallback-chain-from-models.ts
│   │   ├── fallback-model-availability.ts
│   │   ├── file-reference-resolver.ts
│   │   ├── file-utils.test.ts
│   │   ├── file-utils.ts
│   │   ├── first-message-variant.test.ts
│   │   ├── first-message-variant.ts
│   │   ├── frontmatter.test.ts
│   │   ├── frontmatter.ts
│   │   ├── git-worktree/
│   │   │   ├── collect-git-diff-stats.test.ts
│   │   │   ├── collect-git-diff-stats.ts
│   │   │   ├── format-file-changes.ts
│   │   │   ├── git-worktree.test.ts
│   │   │   ├── index.ts
│   │   │   ├── parse-diff-numstat.ts
│   │   │   ├── parse-status-porcelain-line.test.ts
│   │   │   ├── parse-status-porcelain-line.ts
│   │   │   ├── parse-status-porcelain.ts
│   │   │   └── types.ts
│   │   ├── hook-disabled.ts
│   │   ├── index.ts
│   │   ├── internal-initiator-marker.ts
│   │   ├── jsonc-parser.test.ts
│   │   ├── jsonc-parser.ts
│   │   ├── logger.ts
│   │   ├── merge-categories.test.ts
│   │   ├── merge-categories.ts
│   │   ├── migration/
│   │   │   ├── agent-category.ts
│   │   │   ├── agent-names.ts
│   │   │   ├── config-migration.ts
│   │   │   ├── hook-names.ts
│   │   │   └── model-versions.ts
│   │   ├── migration.test.ts
│   │   ├── migration.ts
│   │   ├── model-availability.test.ts
│   │   ├── model-availability.ts
│   │   ├── model-error-classifier.test.ts
│   │   ├── model-error-classifier.ts
│   │   ├── model-format-normalizer.test.ts
│   │   ├── model-format-normalizer.ts
│   │   ├── model-normalization.test.ts
│   │   ├── model-normalization.ts
│   │   ├── model-requirements.test.ts
│   │   ├── model-requirements.ts
│   │   ├── model-resolution-pipeline.test.ts
│   │   ├── model-resolution-pipeline.ts
│   │   ├── model-resolution-types.ts
│   │   ├── model-resolver.test.ts
│   │   ├── model-resolver.ts
│   │   ├── model-sanitizer.ts
│   │   ├── model-suggestion-retry.test.ts
│   │   ├── model-suggestion-retry.ts
│   │   ├── normalize-sdk-response.test.ts
│   │   ├── normalize-sdk-response.ts
│   │   ├── opencode-command-dirs.test.ts
│   │   ├── opencode-command-dirs.ts
│   │   ├── opencode-config-dir-types.ts
│   │   ├── opencode-config-dir.test.ts
│   │   ├── opencode-config-dir.ts
│   │   ├── opencode-http-api.test.ts
│   │   ├── opencode-http-api.ts
│   │   ├── opencode-message-dir.test.ts
│   │   ├── opencode-message-dir.ts
│   │   ├── opencode-server-auth.test.ts
│   │   ├── opencode-server-auth.ts
│   │   ├── opencode-storage-detection.test.ts
│   │   ├── opencode-storage-detection.ts
│   │   ├── opencode-storage-paths.ts
│   │   ├── opencode-version.test.ts
│   │   ├── opencode-version.ts
│   │   ├── pattern-matcher.test.ts
│   │   ├── pattern-matcher.ts
│   │   ├── permission-compat.test.ts
│   │   ├── permission-compat.ts
│   │   ├── plugin-command-discovery.test.ts
│   │   ├── plugin-command-discovery.ts
│   │   ├── plugin-identity.test.ts
│   │   ├── plugin-identity.ts
│   │   ├── port-utils.test.ts
│   │   ├── port-utils.ts
│   │   ├── prompt-timeout-context.ts
│   │   ├── prompt-tools.test.ts
│   │   ├── prompt-tools.ts
│   │   ├── provider-model-id-transform.ts
│   │   ├── question-denied-session-permission.ts
│   │   ├── record-type-guard.ts
│   │   ├── retry-status-utils.ts
│   │   ├── safe-create-hook.test.ts
│   │   ├── safe-create-hook.ts
│   │   ├── session-category-registry.ts
│   │   ├── session-cursor.test.ts
│   │   ├── session-cursor.ts
│   │   ├── session-directory-resolver.test.ts
│   │   ├── session-directory-resolver.ts
│   │   ├── session-injected-paths.ts
│   │   ├── session-model-state.test.ts
│   │   ├── session-model-state.ts
│   │   ├── session-tools-store.test.ts
│   │   ├── session-tools-store.ts
│   │   ├── session-utils.ts
│   │   ├── shell-env.test.ts
│   │   ├── shell-env.ts
│   │   ├── skill-path-resolver.test.ts
│   │   ├── skill-path-resolver.ts
│   │   ├── snake-case.ts
│   │   ├── spawn-with-windows-hide.ts
│   │   ├── system-directive.test.ts
│   │   ├── system-directive.ts
│   │   ├── tmux/
│   │   │   ├── constants.ts
│   │   │   ├── index.ts
│   │   │   ├── tmux-utils/
│   │   │   │   ├── environment.ts
│   │   │   │   ├── layout.test.ts
│   │   │   │   ├── layout.ts
│   │   │   │   ├── pane-close.ts
│   │   │   │   ├── pane-dimensions.ts
│   │   │   │   ├── pane-replace.ts
│   │   │   │   ├── pane-spawn.test.ts
│   │   │   │   ├── pane-spawn.ts
│   │   │   │   └── server-health.ts
│   │   │   ├── tmux-utils.test.ts
│   │   │   ├── tmux-utils.ts
│   │   │   └── types.ts
│   │   ├── tool-name.test.ts
│   │   ├── tool-name.ts
│   │   ├── truncate-description.test.ts
│   │   ├── truncate-description.ts
│   │   ├── vision-capable-models-cache.ts
│   │   └── zip-extractor.ts
│   └── tools/
│       ├── AGENTS.md
│       ├── ast-grep/
│       │   ├── cli-binary-path-resolution.ts
│       │   ├── cli.ts
│       │   ├── constants.ts
│       │   ├── downloader.ts
│       │   ├── environment-check.ts
│       │   ├── index.ts
│       │   ├── language-support.ts
│       │   ├── process-output-timeout.ts
│       │   ├── result-formatter.ts
│       │   ├── sg-cli-path.ts
│       │   ├── sg-compact-json-output.ts
│       │   ├── tools.ts
│       │   └── types.ts
│       ├── background-task/
│       │   ├── AGENTS.md
│       │   ├── clients.ts
│       │   ├── constants.ts
│       │   ├── create-background-cancel.ts
│       │   ├── create-background-output.blocking.test.ts
│       │   ├── create-background-output.metadata.test.ts
│       │   ├── create-background-output.ts
│       │   ├── create-background-task.metadata.test.ts
│       │   ├── create-background-task.test.ts
│       │   ├── create-background-task.ts
│       │   ├── delay.ts
│       │   ├── full-session-format.ts
│       │   ├── index.ts
│       │   ├── message-dir.ts
│       │   ├── session-messages.ts
│       │   ├── task-result-format.ts
│       │   ├── task-status-format.ts
│       │   ├── time-format.ts
│       │   ├── tools.test.ts
│       │   ├── tools.ts
│       │   ├── truncate-text.ts
│       │   └── types.ts
│       ├── call-omo-agent/
│       │   ├── AGENTS.md
│       │   ├── background-agent-executor.test.ts
│       │   ├── background-agent-executor.ts
│       │   ├── background-executor.test.ts
│       │   ├── background-executor.ts
│       │   ├── completion-poller.ts
│       │   ├── constants.ts
│       │   ├── index.ts
│       │   ├── message-dir.ts
│       │   ├── message-processor.ts
│       │   ├── message-storage-directory.ts
│       │   ├── reused-sync-session-delete-cleanup.test.ts
│       │   ├── session-creator.test.ts
│       │   ├── session-creator.ts
│       │   ├── subagent-session-creator.test.ts
│       │   ├── subagent-session-creator.ts
│       │   ├── sync-executor-leak.test.ts
│       │   ├── sync-executor.test.ts
│       │   ├── sync-executor.ts
│       │   ├── tool-context-with-metadata.ts
│       │   ├── tools.test.ts
│       │   ├── tools.ts
│       │   └── types.ts
│       ├── delegate-task/
│       │   ├── AGENTS.md
│       │   ├── available-models.ts
│       │   ├── background-continuation.test.ts
│       │   ├── background-continuation.ts
│       │   ├── background-task.test.ts
│       │   ├── background-task.ts
│       │   ├── cancel-unstable-agent-task.ts
│       │   ├── categories.ts
│       │   ├── category-resolver.test.ts
│       │   ├── category-resolver.ts
│       │   ├── constants.ts
│       │   ├── error-formatting.ts
│       │   ├── executor-types.ts
│       │   ├── executor.ts
│       │   ├── index.ts
│       │   ├── metadata-await.test.ts
│       │   ├── metadata-model-unification.test.ts
│       │   ├── model-selection.test.ts
│       │   ├── model-selection.ts
│       │   ├── model-string-parser.ts
│       │   ├── parent-context-resolver.ts
│       │   ├── prompt-builder.ts
│       │   ├── sisyphus-junior-agent.ts
│       │   ├── skill-resolver.ts
│       │   ├── subagent-resolver.test.ts
│       │   ├── subagent-resolver.ts
│       │   ├── sync-continuation-deps.ts
│       │   ├── sync-continuation.test.ts
│       │   ├── sync-continuation.ts
│       │   ├── sync-poll-timeout.test.ts
│       │   ├── sync-prompt-sender.test.ts
│       │   ├── sync-prompt-sender.ts
│       │   ├── sync-result-fetcher.test.ts
│       │   ├── sync-result-fetcher.ts
│       │   ├── sync-session-creator.test.ts
│       │   ├── sync-session-creator.ts
│       │   ├── sync-session-poller.test.ts
│       │   ├── sync-session-poller.ts
│       │   ├── sync-task-deps.ts
│       │   ├── sync-task.test.ts
│       │   ├── sync-task.ts
│       │   ├── time-formatter.ts
│       │   ├── timing.test.ts
│       │   ├── timing.ts
│       │   ├── token-limiter.test.ts
│       │   ├── token-limiter.ts
│       │   ├── tools.test.ts
│       │   ├── tools.ts
│       │   ├── types.ts
│       │   ├── unstable-agent-cleanup.test.ts
│       │   ├── unstable-agent-permission.test.ts
│       │   ├── unstable-agent-task.test.ts
│       │   ├── unstable-agent-task.ts
│       │   └── unstable-agent-timeout.test.ts
│       ├── glob/
│       │   ├── cli.test.ts
│       │   ├── cli.ts
│       │   ├── constants.ts
│       │   ├── index.ts
│       │   ├── result-formatter.ts
│       │   ├── tools.ts
│       │   └── types.ts
│       ├── grep/
│       │   ├── cli.ts
│       │   ├── constants.ts
│       │   ├── downloader.test.ts
│       │   ├── downloader.ts
│       │   ├── index.ts
│       │   ├── result-formatter.test.ts
│       │   ├── result-formatter.ts
│       │   ├── tools.ts
│       │   └── types.ts
│       ├── hashline-edit/
│       │   ├── AGENTS.md
│       │   ├── autocorrect-replacement-lines.ts
│       │   ├── constants.ts
│       │   ├── diff-utils.test.ts
│       │   ├── diff-utils.ts
│       │   ├── edit-deduplication.ts
│       │   ├── edit-operation-primitives.ts
│       │   ├── edit-operations.test.ts
│       │   ├── edit-operations.ts
│       │   ├── edit-ordering.ts
│       │   ├── edit-text-normalization.ts
│       │   ├── file-text-canonicalization.ts
│       │   ├── hash-computation.test.ts
│       │   ├── hash-computation.ts
│       │   ├── hashline-chunk-formatter.ts
│       │   ├── hashline-edit-diff.ts
│       │   ├── hashline-edit-executor.ts
│       │   ├── index.ts
│       │   ├── normalize-edits.test.ts
│       │   ├── normalize-edits.ts
│       │   ├── tool-description.ts
│       │   ├── tools.test.ts
│       │   ├── tools.ts
│       │   ├── types.ts
│       │   ├── validation.test.ts
│       │   └── validation.ts
│       ├── index.ts
│       ├── interactive-bash/
│       │   ├── constants.ts
│       │   ├── index.ts
│       │   ├── tmux-path-resolver.ts
│       │   └── tools.ts
│       ├── look-at/
│       │   ├── assistant-message-extractor.ts
│       │   ├── constants.ts
│       │   ├── image-converter.test.ts
│       │   ├── image-converter.ts
│       │   ├── index.ts
│       │   ├── look-at-arguments.ts
│       │   ├── mime-type-inference.test.ts
│       │   ├── mime-type-inference.ts
│       │   ├── multimodal-agent-metadata.test.ts
│       │   ├── multimodal-agent-metadata.ts
│       │   ├── multimodal-fallback-chain.test.ts
│       │   ├── multimodal-fallback-chain.ts
│       │   ├── session-poller.test.ts
│       │   ├── session-poller.ts
│       │   ├── tools.test.ts
│       │   ├── tools.ts
│       │   └── types.ts
│       ├── lsp/
│       │   ├── AGENTS.md
│       │   ├── client.test.ts
│       │   ├── client.ts
│       │   ├── config.test.ts
│       │   ├── config.ts
│       │   ├── constants.ts
│       │   ├── diagnostics-tool.ts
│       │   ├── directory-diagnostics.test.ts
│       │   ├── directory-diagnostics.ts
│       │   ├── find-references-tool.ts
│       │   ├── goto-definition-tool.ts
│       │   ├── index.ts
│       │   ├── language-config.ts
│       │   ├── language-mappings.ts
│       │   ├── lsp-client-connection.ts
│       │   ├── lsp-client-transport.ts
│       │   ├── lsp-client-wrapper.ts
│       │   ├── lsp-client.ts
│       │   ├── lsp-formatters.ts
│       │   ├── lsp-manager-process-cleanup.ts
│       │   ├── lsp-manager-temp-directory-cleanup.ts
│       │   ├── lsp-process.test.ts
│       │   ├── lsp-process.ts
│       │   ├── lsp-server.ts
│       │   ├── rename-tools.ts
│       │   ├── server-config-loader.test.ts
│       │   ├── server-config-loader.ts
│       │   ├── server-definitions.ts
│       │   ├── server-installation.ts
│       │   ├── server-path-bases.ts
│       │   ├── server-resolution.ts
│       │   ├── symbols-tool.ts
│       │   ├── tools.ts
│       │   ├── types.ts
│       │   ├── utils.test.ts
│       │   └── workspace-edit.ts
│       ├── session-manager/
│       │   ├── constants.ts
│       │   ├── index.ts
│       │   ├── session-formatter.ts
│       │   ├── storage.test.ts
│       │   ├── storage.ts
│       │   ├── tools.test.ts
│       │   ├── tools.ts
│       │   ├── types.ts
│       │   └── utils.test.ts
│       ├── shared/
│       │   └── semaphore.ts
│       ├── skill/
│       │   ├── constants.ts
│       │   ├── index.ts
│       │   ├── tools.test.ts
│       │   ├── tools.ts
│       │   └── types.ts
│       ├── skill-mcp/
│       │   ├── builtin-mcp-hint.test.ts
│       │   ├── constants.ts
│       │   ├── index.ts
│       │   ├── tools.test.ts
│       │   ├── tools.ts
│       │   └── types.ts
│       ├── slashcommand/
│       │   ├── command-discovery.test.ts
│       │   ├── command-discovery.ts
│       │   ├── command-output-formatter.test.ts
│       │   ├── command-output-formatter.ts
│       │   ├── execution-compatibility.test.ts
│       │   ├── index.test.ts
│       │   ├── index.ts
│       │   └── types.ts
│       └── task/
│           ├── index.ts
│           ├── task-create.test.ts
│           ├── task-create.ts
│           ├── task-get.test.ts
│           ├── task-get.ts
│           ├── task-list.test.ts
│           ├── task-list.ts
│           ├── task-update.test.ts
│           ├── task-update.ts
│           ├── todo-sync.test.ts
│           ├── todo-sync.ts
│           ├── types.test.ts
│           └── types.ts
├── test-setup.ts
├── tests/
│   └── hashline/
│       ├── headless.ts
│       ├── package.json
│       ├── test-edge-cases.ts
│       ├── test-edit-ops.ts
│       └── test-multi-model.ts
├── tsconfig.json
└── uvscripts/
    └── gh_fetch.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms

github: code-yeongyu
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
polar: # Replace with a single Polar username
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
thanks_dev: # Replace with a single thanks.dev username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.yml
================================================
name: Bug Report
description: Report a bug or unexpected behavior in oh-my-opencode
title: "[Bug]: "
labels: ["bug", "needs-triage"]
body:
  - type: markdown
    attributes:
      value: |
        **Please write your issue in English.** See our [Language Policy](https://github.com/code-yeongyu/oh-my-opencode/blob/dev/CONTRIBUTING.md#language-policy) for details.

  - type: checkboxes
    id: prerequisites
    attributes:
      label: Prerequisites
      description: Please confirm the following before submitting
      options:
        - label: I will write this issue in English (see our [Language Policy](https://github.com/code-yeongyu/oh-my-opencode/blob/dev/CONTRIBUTING.md#language-policy))
          required: true
        - label: I have searched existing issues to avoid duplicates
          required: true
        - label: I am using the latest version of oh-my-opencode
          required: true
        - label: I have read the [documentation](https://github.com/code-yeongyu/oh-my-opencode#readme) or asked an AI coding agent with this project's GitHub URL loaded and couldn't find the answer
          required: true

  - type: textarea
    id: description
    attributes:
      label: Bug Description
      description: A clear and concise description of what the bug is
      placeholder: Describe the bug in detail...
    validations:
      required: true

  - type: textarea
    id: reproduction
    attributes:
      label: Steps to Reproduce
      description: Steps to reproduce the behavior
      placeholder: |
        1. Configure oh-my-opencode with...
        2. Run command '...'
        3. See error...
    validations:
      required: true

  - type: textarea
    id: expected
    attributes:
      label: Expected Behavior
      description: What did you expect to happen?
      placeholder: Describe what should happen...
    validations:
      required: true

  - type: textarea
    id: actual
    attributes:
      label: Actual Behavior
      description: What actually happened?
      placeholder: Describe what actually happened...
    validations:
      required: true

  - type: textarea
    id: doctor
    attributes:
      label: Doctor Output
      description: |
        **Required:** Run `bunx oh-my-opencode doctor` and paste the full output below.
        This helps us diagnose your environment and configuration.
      placeholder: |
        Paste the output of: bunx oh-my-opencode doctor
        
        Example:
        ✓ OpenCode version: 1.0.150
        ✓ oh-my-opencode version: 1.2.3
        ✓ Plugin loaded successfully
        ...
      render: shell
    validations:
      required: true

  - type: textarea
    id: logs
    attributes:
      label: Error Logs
      description: If applicable, add any error messages or logs
      placeholder: Paste error logs here...
      render: shell

  - type: textarea
    id: config
    attributes:
      label: Configuration
      description: If relevant, share your oh-my-opencode configuration (remove sensitive data)
      placeholder: |
        {
          "agents": { ... },
          "disabled_hooks": [ ... ]
        }
      render: json

  - type: textarea
    id: context
    attributes:
      label: Additional Context
      description: Any other context about the problem
      placeholder: Add any other context, screenshots, or information...

  - type: dropdown
    id: os
    attributes:
      label: Operating System
      description: Which operating system are you using?
      options:
        - macOS
        - Linux
        - Windows
        - Other
    validations:
      required: true

  - type: input
    id: opencode-version
    attributes:
      label: OpenCode Version
      description: Run `opencode --version` to get your version
      placeholder: "1.0.150"
    validations:
      required: true


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
  - name: Discord Community
    url: https://discord.gg/PUwSMR9XNk
    about: Join our Discord server for real-time discussions and community support
  - name: Documentation
    url: https://github.com/code-yeongyu/oh-my-opencode#readme
    about: Read the comprehensive documentation and guides


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.yml
================================================
name: Feature Request
description: Suggest a new feature or enhancement for oh-my-opencode
title: "[Feature]: "
labels: ["enhancement", "needs-triage"]
body:
  - type: markdown
    attributes:
      value: |
        **Please write your issue in English.** See our [Language Policy](https://github.com/code-yeongyu/oh-my-opencode/blob/dev/CONTRIBUTING.md#language-policy) for details.

  - type: checkboxes
    id: prerequisites
    attributes:
      label: Prerequisites
      description: Please confirm the following before submitting
      options:
        - label: I will write this issue in English (see our [Language Policy](https://github.com/code-yeongyu/oh-my-opencode/blob/dev/CONTRIBUTING.md#language-policy))
          required: true
        - label: I have searched existing issues and discussions to avoid duplicates
          required: true
        - label: This feature request is specific to oh-my-opencode (not OpenCode core)
          required: true
        - label: I have read the [documentation](https://github.com/code-yeongyu/oh-my-opencode#readme) or asked an AI coding agent with this project's GitHub URL loaded and couldn't find the answer
          required: true

  - type: textarea
    id: problem
    attributes:
      label: Problem Description
      description: What problem does this feature solve? What's the use case?
      placeholder: |
        Describe the problem or limitation you're experiencing...
        Example: "As a user, I find it difficult to..."
    validations:
      required: true

  - type: textarea
    id: solution
    attributes:
      label: Proposed Solution
      description: Describe how you'd like this feature to work
      placeholder: |
        Describe your proposed solution in detail...
        Example: "Add a new hook that..."
    validations:
      required: true

  - type: textarea
    id: alternatives
    attributes:
      label: Alternatives Considered
      description: Have you considered any alternative solutions or workarounds?
      placeholder: |
        Describe any alternative solutions you've considered...
        Example: "I tried using X but it didn't work because..."

  - type: textarea
    id: doctor
    attributes:
      label: Doctor Output (Optional)
      description: |
        If relevant to your feature request, run `bunx oh-my-opencode doctor` and paste the output.
        This helps us understand your environment.
      placeholder: |
        Paste the output of: bunx oh-my-opencode doctor
        (Optional for feature requests)
      render: shell

  - type: textarea
    id: context
    attributes:
      label: Additional Context
      description: Any other context, mockups, or examples
      placeholder: |
        Add any other context, screenshots, code examples, or links...
        Examples from other tools/projects are helpful!

  - type: dropdown
    id: feature-type
    attributes:
      label: Feature Type
      description: What type of feature is this?
      options:
        - New Agent
        - New Hook
        - New Tool
        - New MCP Integration
        - Configuration Option
        - Documentation
        - Other
    validations:
      required: true

  - type: checkboxes
    id: contribution
    attributes:
      label: Contribution
      description: Are you willing to contribute to this feature?
      options:
        - label: I'm willing to submit a PR for this feature
        - label: I can help with testing
        - label: I can help with documentation


================================================
FILE: .github/ISSUE_TEMPLATE/general.yml
================================================
name: Question or Discussion
description: Ask a question or start a discussion about oh-my-opencode
title: "[Question]: "
labels: ["question", "needs-triage"]
body:
  - type: markdown
    attributes:
      value: |
        **Please write your issue in English.** See our [Language Policy](https://github.com/code-yeongyu/oh-my-opencode/blob/dev/CONTRIBUTING.md#language-policy) for details.

  - type: checkboxes
    id: prerequisites
    attributes:
      label: Prerequisites
      description: Please confirm the following before submitting
      options:
        - label: I will write this issue in English (see our [Language Policy](https://github.com/code-yeongyu/oh-my-opencode/blob/dev/CONTRIBUTING.md#language-policy))
          required: true
        - label: I have searched existing issues and discussions
          required: true
        - label: I have read the [documentation](https://github.com/code-yeongyu/oh-my-opencode#readme) or asked an AI coding agent with this project's GitHub URL loaded and couldn't find the answer
          required: true
        - label: This is a question (not a bug report or feature request)
          required: true

  - type: textarea
    id: question
    attributes:
      label: Question
      description: What would you like to know or discuss?
      placeholder: |
        Ask your question in detail...
        
        Examples:
        - How do I configure agent X to do Y?
        - What's the best practice for Z?
        - Why does feature A work differently than B?
    validations:
      required: true

  - type: textarea
    id: context
    attributes:
      label: Context
      description: Provide any relevant context or background
      placeholder: |
        What have you tried so far?
        What's your use case?
        Any relevant configuration or setup details?

  - type: textarea
    id: doctor
    attributes:
      label: Doctor Output (Optional)
      description: |
        If your question is about configuration or setup, run `bunx oh-my-opencode doctor` and paste the output.
      placeholder: |
        Paste the output of: bunx oh-my-opencode doctor
        (Optional for questions)
      render: shell

  - type: dropdown
    id: category
    attributes:
      label: Question Category
      description: What is your question about?
      options:
        - Configuration
        - Agent Usage
        - Hook Behavior
        - Tool Usage
        - Installation/Setup
        - Best Practices
        - Performance
        - Integration
        - Other
    validations:
      required: true

  - type: textarea
    id: additional
    attributes:
      label: Additional Information
      description: Any other information that might be helpful
      placeholder: Links, screenshots, examples, etc.


================================================
FILE: .github/pull_request_template.md
================================================
## Summary

<!-- Brief description of what this PR does. 1-3 bullet points. -->

- 

## Changes

<!-- What was changed and how. List specific modifications. -->

- 

## Screenshots

<!-- If applicable, add screenshots or GIFs showing before/after. Delete this section if not needed. -->

| Before | After |
|:---:|:---:|
|  |  |

## Testing

<!-- How to verify this PR works correctly. Delete if not applicable. -->

```bash
bun run typecheck
bun test
```

## Related Issues

<!-- Link related issues. Use "Closes #123" to auto-close on merge. -->

<!-- Closes # -->


================================================
FILE: .github/workflows/ci.yml
================================================
name: CI

on:
  push:
    branches: [master, dev]
  pull_request:
    branches: [master, dev]

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  # Block PRs targeting master branch
  block-master-pr:
    runs-on: ubuntu-latest
    if: github.event_name == 'pull_request'
    steps:
      - name: Check PR target branch
        run: |
          if [ "${{ github.base_ref }}" = "master" ]; then
            echo "::error::PRs to master branch are not allowed. Please target the 'dev' branch instead."
            echo ""
            echo "PULL REQUESTS TO MASTER ARE BLOCKED"
            echo ""
            echo "All PRs must target the 'dev' branch."
            echo "Please close this PR and create a new one targeting 'dev'."
            exit 1
          else
            echo "PR targets '${{ github.base_ref }}' branch - OK"
          fi

  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: oven-sh/setup-bun@v2
        with:
          bun-version: latest

      - name: Install dependencies
        run: bun install
        env:
          BUN_INSTALL_ALLOW_SCRIPTS: "@ast-grep/napi"

      - name: Run mock-heavy tests (isolated)
        run: |
          # These files use mock.module() which pollutes module cache
          # Run them in separate processes to prevent cross-file contamination
          bun test src/plugin-handlers
          bun test src/hooks/atlas
          bun test src/hooks/compaction-context-injector
          bun test src/features/tmux-subagent
          bun test src/cli/doctor/formatter.test.ts
          bun test src/cli/doctor/format-default.test.ts
          bun test src/tools/call-omo-agent/sync-executor.test.ts
          bun test src/tools/call-omo-agent/session-creator.test.ts
          bun test src/tools/session-manager
          bun test src/features/opencode-skill-loader/loader.test.ts
          bun test src/hooks/anthropic-context-window-limit-recovery/recovery-hook.test.ts
          bun test src/hooks/anthropic-context-window-limit-recovery/executor.test.ts

      - name: Run remaining tests
        run: |
          # Enumerate subdirectories/files explicitly to EXCLUDE mock-heavy files
          # that were already run in isolation above.
          # Excluded from src/cli: doctor/formatter.test.ts, doctor/format-default.test.ts
          # Excluded from src/tools: call-omo-agent/sync-executor.test.ts, call-omo-agent/session-creator.test.ts, session-manager (all)
          # Excluded from src/hooks/anthropic-context-window-limit-recovery: recovery-hook.test.ts, executor.test.ts
          bun test bin script src/config src/mcp src/index.test.ts \
            src/agents src/shared \
            src/cli/run src/cli/config-manager src/cli/mcp-oauth \
            src/cli/index.test.ts src/cli/install.test.ts src/cli/model-fallback.test.ts \
            src/cli/config-manager.test.ts \
            src/cli/doctor/runner.test.ts src/cli/doctor/checks \
            src/tools/ast-grep src/tools/background-task src/tools/delegate-task \
            src/tools/glob src/tools/grep src/tools/interactive-bash \
            src/tools/look-at src/tools/lsp \
            src/tools/skill src/tools/skill-mcp src/tools/slashcommand src/tools/task \
            src/tools/call-omo-agent/background-agent-executor.test.ts \
            src/tools/call-omo-agent/background-executor.test.ts \
            src/tools/call-omo-agent/subagent-session-creator.test.ts \
            src/hooks/anthropic-context-window-limit-recovery/empty-content-recovery-sdk.test.ts src/hooks/anthropic-context-window-limit-recovery/parser.test.ts src/hooks/anthropic-context-window-limit-recovery/pruning-deduplication.test.ts src/hooks/anthropic-context-window-limit-recovery/recovery-deduplication.test.ts src/hooks/anthropic-context-window-limit-recovery/storage.test.ts \
            src/hooks/claude-code-compatibility \
            src/hooks/context-injection \
            src/hooks/provider-toast \
            src/hooks/session-notification \
            src/hooks/sisyphus \
            src/hooks/todo-continuation-enforcer \
            src/features/background-agent \
            src/features/builtin-commands \
            src/features/builtin-skills \
            src/features/claude-code-session-state \
            src/features/hook-message-injector \
            src/features/opencode-skill-loader/config-source-discovery.test.ts \
            src/features/opencode-skill-loader/merger.test.ts \
            src/features/opencode-skill-loader/skill-content.test.ts \
            src/features/opencode-skill-loader/blocking.test.ts \
            src/features/opencode-skill-loader/async-loader.test.ts \
            src/features/skill-mcp-manager

  typecheck:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: oven-sh/setup-bun@v2
        with:
          bun-version: latest

      - name: Install dependencies
        run: bun install
        env:
          BUN_INSTALL_ALLOW_SCRIPTS: "@ast-grep/napi"

      - name: Type check
        run: bun run typecheck

  build:
    runs-on: ubuntu-latest
    needs: [test, typecheck]
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v4
        with:
          token: ${{ secrets.GITHUB_TOKEN }}

      - uses: oven-sh/setup-bun@v2
        with:
          bun-version: latest

      - name: Install dependencies
        run: bun install
        env:
          BUN_INSTALL_ALLOW_SCRIPTS: "@ast-grep/napi"

      - name: Build
        run: bun run build

      - name: Verify build output
        run: |
          test -f dist/index.js || (echo "ERROR: dist/index.js not found!" && exit 1)
          test -f dist/index.d.ts || (echo "ERROR: dist/index.d.ts not found!" && exit 1)

      - name: Auto-commit schema changes
        if: github.event_name == 'push' && github.ref == 'refs/heads/master'
        run: |
          if git diff --quiet assets/oh-my-opencode.schema.json; then
            echo "No schema changes to commit"
          else
            git config user.name "github-actions[bot]"
            git config user.email "github-actions[bot]@users.noreply.github.com"
            git add assets/oh-my-opencode.schema.json
            git commit -m "chore: auto-update schema.json"
            git push
          fi

  draft-release:
    runs-on: ubuntu-latest
    needs: [build]
    if: github.event_name == 'push' && github.ref == 'refs/heads/dev'
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - run: git fetch --force --tags

      - uses: oven-sh/setup-bun@v2
        with:
          bun-version: latest

      - name: Generate release notes
        id: notes
        run: |
          NOTES=$(bun run script/generate-changelog.ts)
          echo "notes<<EOF" >> $GITHUB_OUTPUT
          echo "$NOTES" >> $GITHUB_OUTPUT
          echo "EOF" >> $GITHUB_OUTPUT
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Create or update draft release
        run: |
          EXISTING_DRAFT=$(gh release list --json tagName,isDraft --jq '.[] | select(.isDraft == true and .tagName == "next") | .tagName')
          
          if [ -n "$EXISTING_DRAFT" ]; then
            echo "Updating existing draft release..."
            gh release edit next \
              --title "Upcoming Changes 🍿" \
              --notes-file - \
              --draft <<'EOF'
          ${{ steps.notes.outputs.notes }}
          EOF
          else
            echo "Creating new draft release..."
            gh release create next \
              --title "Upcoming Changes 🍿" \
              --notes-file - \
              --draft \
              --target ${{ github.sha }} <<'EOF'
          ${{ steps.notes.outputs.notes }}
          EOF
          fi
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}


================================================
FILE: .github/workflows/cla.yml
================================================
name: CLA Assistant

on:
  issue_comment:
    types: [created]
  pull_request_target:
    types: [opened, closed, synchronize]

permissions:
  actions: write
  contents: write
  pull-requests: write
  statuses: write

jobs:
  cla:
    runs-on: ubuntu-latest
    steps:
      - name: CLA Assistant
        if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target'
        uses: contributor-assistant/github-action@v2.6.1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          path-to-signatures: 'signatures/cla.json'
          path-to-document: 'https://github.com/code-yeongyu/oh-my-opencode/blob/master/CLA.md'
          branch: 'dev'
          allowlist: code-yeongyu,bot*,dependabot*,github-actions*,*[bot],sisyphus-dev-ai,web-flow
          custom-notsigned-prcomment: |
            Thank you for your contribution! Before we can merge this PR, we need you to sign our [Contributor License Agreement (CLA)](https://github.com/code-yeongyu/oh-my-opencode/blob/master/CLA.md).
            
            **To sign the CLA**, please comment on this PR with:
            ```
            I have read the CLA Document and I hereby sign the CLA
            ```
            
            This is a one-time requirement. Once signed, all your future contributions will be automatically accepted.
          custom-pr-sign-comment: 'I have read the CLA Document and I hereby sign the CLA'
          custom-allsigned-prcomment: |
            All contributors have signed the CLA. Thank you! ✅
          lock-pullrequest-aftermerge: false


================================================
FILE: .github/workflows/lint-workflows.yml
================================================
name: Lint Workflows

on:
  push:
    paths:
      - '.github/workflows/**'
  pull_request:
    paths:
      - '.github/workflows/**'

jobs:
  actionlint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5

      - name: Install actionlint
        run: |
          bash <(curl -sSL https://raw.githubusercontent.com/rhysd/actionlint/v1.7.10/scripts/download-actionlint.bash)

      - name: Run actionlint
        run: ./actionlint -color -shellcheck=""


================================================
FILE: .github/workflows/publish-platform.yml
================================================
name: publish-platform
run-name: "platform packages ${{ inputs.version }}"

on:
  workflow_call:
    inputs:
      version:
        required: true
        type: string
      dist_tag:
        required: false
        type: string
        default: ""
  workflow_dispatch:
    inputs:
      version:
        description: "Version to publish (e.g., 3.0.0-beta.12)"
        required: true
        type: string
      dist_tag:
        description: "npm dist tag (e.g., beta, latest)"
        required: false
        type: string
        default: ""

permissions:
  contents: read
  id-token: write

jobs:
  # =============================================================================
  # Job 1: Build binaries for all platforms
  # - Windows builds on windows-latest (avoid bun cross-compile segfault)
  # - All other platforms build on ubuntu-latest
  # - Uploads compressed artifacts for the publish job
  # =============================================================================
  build:
    runs-on: ${{ startsWith(matrix.platform, 'windows-') && 'windows-latest' || 'ubuntu-latest' }}
    defaults:
      run:
        shell: bash
    strategy:
      fail-fast: false
      max-parallel: 11
      matrix:
        platform: [darwin-arm64, darwin-x64, darwin-x64-baseline, linux-x64, linux-x64-baseline, linux-arm64, linux-x64-musl, linux-x64-musl-baseline, linux-arm64-musl, windows-x64, windows-x64-baseline]
    steps:
      - uses: actions/checkout@v4

      - uses: oven-sh/setup-bun@v2
        with:
          bun-version: latest

      - name: Install dependencies
        run: bun install
        env:
          BUN_INSTALL_ALLOW_SCRIPTS: "@ast-grep/napi"

      - name: Check if already published
        id: check
        run: |
          VERSION="${{ inputs.version }}"
          PLATFORM_KEY="${{ matrix.platform }}"
          PLATFORM_KEY="${PLATFORM_KEY//-/_}"
          
          # Check oh-my-opencode
          OC_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://registry.npmjs.org/oh-my-opencode-${{ matrix.platform }}/${VERSION}")
          # Check oh-my-openagent
          OA_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://registry.npmjs.org/oh-my-openagent-${{ matrix.platform }}/${VERSION}")
          
          echo "oh-my-opencode-${{ matrix.platform }}@${VERSION}: ${OC_STATUS}"
          echo "oh-my-openagent-${{ matrix.platform }}@${VERSION}: ${OA_STATUS}"
          
          if [ "$OC_STATUS" = "200" ]; then
            echo "skip_opencode=true" >> $GITHUB_OUTPUT
            echo "✓ oh-my-opencode-${{ matrix.platform }}@${VERSION} already published"
          else
            echo "skip_opencode=false" >> $GITHUB_OUTPUT
            echo "→ oh-my-opencode-${{ matrix.platform }}@${VERSION} needs publishing"
          fi
          
          if [ "$OA_STATUS" = "200" ]; then
            echo "skip_openagent=true" >> $GITHUB_OUTPUT
            echo "✓ oh-my-openagent-${{ matrix.platform }}@${VERSION} already published"
          else
            echo "skip_openagent=false" >> $GITHUB_OUTPUT
            echo "→ oh-my-openagent-${{ matrix.platform }}@${VERSION} needs publishing"
          fi
          
          # Skip build only if BOTH are already published
          if [ "$OC_STATUS" = "200" ] && [ "$OA_STATUS" = "200" ]; then
            echo "skip=true" >> $GITHUB_OUTPUT
          else
            echo "skip=false" >> $GITHUB_OUTPUT
          fi

      - name: Update version in package.json
        if: steps.check.outputs.skip != 'true'
        run: |
          VERSION="${{ inputs.version }}"
          cd packages/${{ matrix.platform }}
          jq --arg v "$VERSION" '.version = $v' package.json > tmp.json && mv tmp.json package.json

      - name: Set root package version
        if: steps.check.outputs.skip != 'true'
        run: |
          jq --arg v "${{ inputs.version }}" '.version = $v' package.json > tmp.json && mv tmp.json package.json

      - name: Pre-download baseline compile target
        if: steps.check.outputs.skip != 'true' && endsWith(matrix.platform, '-baseline')
        shell: bash
        run: |
          BUN_VERSION=$(bun --version)
          PLATFORM="${{ matrix.platform }}"
          PKG_NAME="bun-${PLATFORM}"
          CACHE_DIR=$(bun pm cache)
          CACHE_DEST="${CACHE_DIR}/${PKG_NAME}-v${BUN_VERSION}"
          
          if [[ -f "$CACHE_DEST" ]]; then
            echo "✓ Compile target already cached at ${CACHE_DEST}"
            exit 0
          fi
          
          echo "Pre-downloading ${PKG_NAME} v${BUN_VERSION} to ${CACHE_DEST}"
          TARBALL_URL="https://registry.npmjs.org/@oven/bun-${PLATFORM}/-/bun-${PLATFORM}-${BUN_VERSION}.tgz"
          echo "URL: ${TARBALL_URL}"
          
          mkdir -p "$(dirname "$CACHE_DEST")"
          TMP_DIR=$(mktemp -d)
          
          # Download and extract the bun binary from npm tarball
          curl -fsSL --retry 5 --retry-delay 5 "${TARBALL_URL}" | tar -xzf - -C "${TMP_DIR}"
          
          if [[ "$PLATFORM" == windows-* ]]; then
            BIN_NAME="bun.exe"
          else
            BIN_NAME="bun"
          fi
          
          # npm tarball has package/bin/bun structure
          if [[ -f "${TMP_DIR}/package/bin/${BIN_NAME}" ]]; then
            cp "${TMP_DIR}/package/bin/${BIN_NAME}" "${CACHE_DEST}"
          elif [[ -f "${TMP_DIR}/package/${BIN_NAME}" ]]; then
            cp "${TMP_DIR}/package/${BIN_NAME}" "${CACHE_DEST}"
          else
            echo "Could not find ${BIN_NAME} in tarball, listing contents:"
            find "${TMP_DIR}" -type f
            exit 1
          fi
          
          chmod +x "${CACHE_DEST}" 2>/dev/null || true
          echo "✓ Pre-downloaded to ${CACHE_DEST}"
          ls -lh "${CACHE_DEST}"

      - name: Build binary
        if: steps.check.outputs.skip != 'true'
        uses: nick-fields/retry@v3
        with:
          timeout_minutes: 5
          max_attempts: 5
          retry_wait_seconds: 10
          shell: bash
          command: |
            PLATFORM="${{ matrix.platform }}"
            case "$PLATFORM" in
              darwin-arm64) TARGET="bun-darwin-arm64" ;;
              darwin-x64) TARGET="bun-darwin-x64" ;;
              darwin-x64-baseline) TARGET="bun-darwin-x64-baseline" ;;
              linux-x64) TARGET="bun-linux-x64" ;;
              linux-x64-baseline) TARGET="bun-linux-x64-baseline" ;;
              linux-arm64) TARGET="bun-linux-arm64" ;;
              linux-x64-musl) TARGET="bun-linux-x64-musl" ;;
              linux-x64-musl-baseline) TARGET="bun-linux-x64-musl-baseline" ;;
              linux-arm64-musl) TARGET="bun-linux-arm64-musl" ;;
              windows-x64) TARGET="bun-windows-x64" ;;
              windows-x64-baseline) TARGET="bun-windows-x64-baseline" ;;
            esac
            
            if [[ "$PLATFORM" == windows-* ]]; then
              OUTPUT="packages/${PLATFORM}/bin/oh-my-opencode.exe"
            else
              OUTPUT="packages/${PLATFORM}/bin/oh-my-opencode"
            fi
            
            bun build src/cli/index.ts --compile --minify --target=$TARGET --outfile=$OUTPUT
            
            echo "Built binary:"
            ls -lh "$OUTPUT"

      - name: Compress binary
        if: steps.check.outputs.skip != 'true'
        run: |
          PLATFORM="${{ matrix.platform }}"
          cd packages/${PLATFORM}
          
          if [[ "$PLATFORM" == windows-* ]]; then
            # Windows: use 7z (pre-installed on windows-latest)
            7z a -tzip ../../binary-${PLATFORM}.zip bin/ package.json
          else
            # Unix: use tar.gz
            tar -czvf ../../binary-${PLATFORM}.tar.gz bin/ package.json
          fi
          
          cd ../..
          echo "Compressed artifact:"
          ls -lh binary-${PLATFORM}.*

      - name: Upload artifact
        if: steps.check.outputs.skip != 'true'
        uses: actions/upload-artifact@v4
        with:
          name: binary-${{ matrix.platform }}
          path: |
            binary-${{ matrix.platform }}.tar.gz
            binary-${{ matrix.platform }}.zip
          retention-days: 1
          if-no-files-found: error

  publish:
    needs: build
    if: always() && !cancelled()
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      max-parallel: 2
      matrix:
        platform: [darwin-arm64, darwin-x64, darwin-x64-baseline, linux-x64, linux-x64-baseline, linux-arm64, linux-x64-musl, linux-x64-musl-baseline, linux-arm64-musl, windows-x64, windows-x64-baseline]
    steps:
      - name: Check if already published
        id: check
        run: |
          VERSION="${{ inputs.version }}"
          
          OC_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://registry.npmjs.org/oh-my-opencode-${{ matrix.platform }}/${VERSION}")
          OA_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://registry.npmjs.org/oh-my-openagent-${{ matrix.platform }}/${VERSION}")
          
          if [ "$OC_STATUS" = "200" ]; then
            echo "skip_opencode=true" >> $GITHUB_OUTPUT
            echo "✓ oh-my-opencode-${{ matrix.platform }}@${VERSION} already published"
          else
            echo "skip_opencode=false" >> $GITHUB_OUTPUT
          fi
          
          if [ "$OA_STATUS" = "200" ]; then
            echo "skip_openagent=true" >> $GITHUB_OUTPUT
            echo "✓ oh-my-openagent-${{ matrix.platform }}@${VERSION} already published"
          else
            echo "skip_openagent=false" >> $GITHUB_OUTPUT
          fi
          
          # Need artifact if either package needs publishing
          if [ "$OC_STATUS" = "200" ] && [ "$OA_STATUS" = "200" ]; then
            echo "skip_all=true" >> $GITHUB_OUTPUT
          else
            echo "skip_all=false" >> $GITHUB_OUTPUT
          fi

      - name: Download artifact
        id: download
        if: steps.check.outputs.skip_all != 'true'
        continue-on-error: true
        uses: actions/download-artifact@v4
        with:
          name: binary-${{ matrix.platform }}
          path: .

      - name: Extract artifact
        if: steps.check.outputs.skip_all != 'true' && steps.download.outcome == 'success'
        run: |
          PLATFORM="${{ matrix.platform }}"
          mkdir -p packages/${PLATFORM}
          
          if [[ "$PLATFORM" == windows-* ]]; then
            unzip binary-${PLATFORM}.zip -d packages/${PLATFORM}/
          else
            tar -xzvf binary-${PLATFORM}.tar.gz -C packages/${PLATFORM}/
          fi
          
          echo "Extracted contents:"
          ls -la packages/${PLATFORM}/
          ls -la packages/${PLATFORM}/bin/

      - uses: actions/setup-node@v4
        if: steps.check.outputs.skip_all != 'true' && steps.download.outcome == 'success'
        with:
          node-version: "24"
          registry-url: "https://registry.npmjs.org"

      - name: Publish oh-my-opencode-${{ matrix.platform }}
        if: steps.check.outputs.skip_opencode != 'true' && steps.download.outcome == 'success'
        run: |
          cd packages/${{ matrix.platform }}
          
          TAG_ARG=""
          if [ -n "${{ inputs.dist_tag }}" ]; then
            TAG_ARG="--tag ${{ inputs.dist_tag }}"
          fi
          
          npm publish --access public --provenance $TAG_ARG
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
          NPM_CONFIG_PROVENANCE: true
        timeout-minutes: 15

      - name: Publish oh-my-openagent-${{ matrix.platform }}
        if: steps.check.outputs.skip_openagent != 'true' && steps.download.outcome == 'success'
        run: |
          cd packages/${{ matrix.platform }}
          
          # Rename package for oh-my-openagent
          jq --arg name "oh-my-openagent-${{ matrix.platform }}" \
             --arg desc "Platform-specific binary for oh-my-openagent (${{ matrix.platform }})" \
             '.name = $name | .description = $desc | .bin = {"oh-my-openagent": (.bin | to_entries | .[0].value)}' \
             package.json > tmp.json && mv tmp.json package.json
          
          TAG_ARG=""
          if [ -n "${{ inputs.dist_tag }}" ]; then
            TAG_ARG="--tag ${{ inputs.dist_tag }}"
          fi
          
          npm publish --access public --provenance $TAG_ARG
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
          NPM_CONFIG_PROVENANCE: true
        timeout-minutes: 15


================================================
FILE: .github/workflows/publish.yml
================================================
name: publish
run-name: "${{ format('release {0}', inputs.version || inputs.bump) }}"

on:
  workflow_dispatch:
    inputs:
      bump:
        description: "Bump major, minor, or patch"
        required: true
        type: choice
        default: patch
        options:
          - patch
          - minor
          - major
      version:
        description: "Override version (e.g., 3.0.0-beta.6). Takes precedence over bump."
        required: false
        type: string
      skip_platform:
        description: "Skip platform binary packages"
        required: false
        type: boolean
        default: false

concurrency: ${{ github.workflow }}-${{ github.ref }}

permissions:
  contents: write
  id-token: write
  actions: write

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: oven-sh/setup-bun@v2
        with:
          bun-version: latest

      - name: Install dependencies
        run: bun install
        env:
          BUN_INSTALL_ALLOW_SCRIPTS: "@ast-grep/napi"

      - name: Run mock-heavy tests (isolated)
        run: |
          # These files use mock.module() which pollutes module cache
          # Run them in separate processes to prevent cross-file contamination
          bun test src/plugin-handlers
          bun test src/hooks/atlas
          bun test src/hooks/compaction-context-injector
          bun test src/features/tmux-subagent
          bun test src/cli/doctor/formatter.test.ts
          bun test src/cli/doctor/format-default.test.ts
          bun test src/tools/call-omo-agent/sync-executor.test.ts
          bun test src/tools/call-omo-agent/session-creator.test.ts
          bun test src/features/opencode-skill-loader/loader.test.ts
          bun test src/hooks/anthropic-context-window-limit-recovery/recovery-hook.test.ts
          bun test src/hooks/anthropic-context-window-limit-recovery/executor.test.ts

      - name: Run remaining tests
        run: |
          # Enumerate subdirectories/files explicitly to EXCLUDE mock-heavy files
          # that were already run in isolation above.
          # Excluded from src/cli: doctor/formatter.test.ts, doctor/format-default.test.ts
          # Excluded from src/tools: call-omo-agent/sync-executor.test.ts, call-omo-agent/session-creator.test.ts
          # Excluded from src/hooks/anthropic-context-window-limit-recovery: recovery-hook.test.ts, executor.test.ts
          # Excluded from src/tools: call-omo-agent/sync-executor.test.ts, call-omo-agent/session-creator.test.ts
          bun test bin script src/config src/mcp src/index.test.ts \
            src/agents src/shared \
            src/cli/run src/cli/config-manager src/cli/mcp-oauth \
            src/cli/index.test.ts src/cli/install.test.ts src/cli/model-fallback.test.ts \
            src/cli/config-manager.test.ts \
            src/cli/doctor/runner.test.ts src/cli/doctor/checks \
            src/tools/ast-grep src/tools/background-task src/tools/delegate-task \
            src/tools/glob src/tools/grep src/tools/interactive-bash \
            src/tools/look-at src/tools/lsp src/tools/session-manager \
            src/tools/skill src/tools/skill-mcp src/tools/slashcommand src/tools/task \
            src/tools/call-omo-agent/background-agent-executor.test.ts \
            src/tools/call-omo-agent/background-executor.test.ts \
            src/tools/call-omo-agent/subagent-session-creator.test.ts \
            src/hooks/anthropic-context-window-limit-recovery/empty-content-recovery-sdk.test.ts src/hooks/anthropic-context-window-limit-recovery/parser.test.ts src/hooks/anthropic-context-window-limit-recovery/pruning-deduplication.test.ts src/hooks/anthropic-context-window-limit-recovery/recovery-deduplication.test.ts src/hooks/anthropic-context-window-limit-recovery/storage.test.ts \
            src/hooks/claude-code-compatibility \
            src/hooks/context-injection \
            src/hooks/provider-toast \
            src/hooks/session-notification \
            src/hooks/sisyphus \
            src/hooks/todo-continuation-enforcer \
            src/features/background-agent \
            src/features/builtin-commands \
            src/features/builtin-skills \
            src/features/claude-code-session-state \
            src/features/hook-message-injector \
            src/features/opencode-skill-loader/config-source-discovery.test.ts \
            src/features/opencode-skill-loader/merger.test.ts \
            src/features/opencode-skill-loader/skill-content.test.ts \
            src/features/opencode-skill-loader/blocking.test.ts \
            src/features/opencode-skill-loader/async-loader.test.ts \
            src/features/skill-mcp-manager

  typecheck:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: oven-sh/setup-bun@v2
        with:
          bun-version: latest

      - name: Install dependencies
        run: bun install
        env:
          BUN_INSTALL_ALLOW_SCRIPTS: "@ast-grep/napi"

      - name: Type check
        run: bun run typecheck

  publish-main:
    runs-on: ubuntu-latest
    needs: [test, typecheck]
    if: github.repository == 'code-yeongyu/oh-my-openagent'
    outputs:
      version: ${{ steps.version.outputs.version }}
      dist_tag: ${{ steps.version.outputs.dist_tag }}
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - run: git fetch --force --tags

      - uses: oven-sh/setup-bun@v2
        with:
          bun-version: latest

      - uses: actions/setup-node@v4
        with:
          node-version: "24"
          registry-url: "https://registry.npmjs.org"

      - name: Install dependencies
        run: bun install
        env:
          BUN_INSTALL_ALLOW_SCRIPTS: "@ast-grep/napi"

      - name: Calculate version
        id: version
        run: |
          VERSION="${{ inputs.version }}"
          if [ -z "$VERSION" ]; then
            PREV=$(curl -s https://registry.npmjs.org/oh-my-opencode/latest | jq -r '.version // "0.0.0"')
            BASE="${PREV%%-*}"
            IFS='.' read -r MAJOR MINOR PATCH <<< "$BASE"
            case "${{ inputs.bump }}" in
              major) VERSION="$((MAJOR+1)).0.0" ;;
              minor) VERSION="${MAJOR}.$((MINOR+1)).0" ;;
              *) VERSION="${MAJOR}.${MINOR}.$((PATCH+1))" ;;
            esac
          fi
          echo "version=$VERSION" >> $GITHUB_OUTPUT
          
          if [[ "$VERSION" == *"-"* ]]; then
            DIST_TAG=$(echo "$VERSION" | cut -d'-' -f2 | cut -d'.' -f1)
            echo "dist_tag=${DIST_TAG:-next}" >> $GITHUB_OUTPUT
          else
            echo "dist_tag=" >> $GITHUB_OUTPUT
          fi
          
          echo "Version: $VERSION"

      - name: Check if already published
        id: check
        run: |
          VERSION="${{ steps.version.outputs.version }}"
          STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://registry.npmjs.org/oh-my-opencode/${VERSION}")
          if [ "$STATUS" = "200" ]; then
            echo "skip=true" >> $GITHUB_OUTPUT
            echo "✓ oh-my-opencode@${VERSION} already published"
          else
            echo "skip=false" >> $GITHUB_OUTPUT
          fi

      - name: Update version
        if: steps.check.outputs.skip != 'true'
        run: |
          VERSION="${{ steps.version.outputs.version }}"
          jq --arg v "$VERSION" '.version = $v' package.json > tmp.json && mv tmp.json package.json
          
          for platform in darwin-arm64 darwin-x64 darwin-x64-baseline linux-x64 linux-x64-baseline linux-arm64 linux-x64-musl linux-x64-musl-baseline linux-arm64-musl windows-x64 windows-x64-baseline; do
            jq --arg v "$VERSION" '.version = $v' "packages/${platform}/package.json" > tmp.json
            mv tmp.json "packages/${platform}/package.json"
          done
          
          jq --arg v "$VERSION" '.optionalDependencies = (.optionalDependencies | to_entries | map(.value = $v) | from_entries)' package.json > tmp.json && mv tmp.json package.json

      - name: Build main package
        if: steps.check.outputs.skip != 'true'
        run: |
          bun build src/index.ts --outdir dist --target bun --format esm --external @ast-grep/napi
          bun build src/cli/index.ts --outdir dist/cli --target bun --format esm --external @ast-grep/napi
          bunx tsc --emitDeclarationOnly
          bun run build:schema

      - name: Publish oh-my-opencode
        if: steps.check.outputs.skip != 'true'
        run: |
          TAG_ARG=""
          if [ -n "${{ steps.version.outputs.dist_tag }}" ]; then
            TAG_ARG="--tag ${{ steps.version.outputs.dist_tag }}"
          fi
          npm publish --access public --provenance $TAG_ARG
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
          NPM_CONFIG_PROVENANCE: true

      - name: Check if oh-my-openagent already published
        id: check-openagent
        run: |
          VERSION="${{ steps.version.outputs.version }}"
          STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://registry.npmjs.org/oh-my-openagent/${VERSION}")
          if [ "$STATUS" = "200" ]; then
            echo "skip=true" >> $GITHUB_OUTPUT
            echo "✓ oh-my-openagent@${VERSION} already published"
          else
            echo "skip=false" >> $GITHUB_OUTPUT
          fi

      - name: Publish oh-my-openagent
        if: steps.check-openagent.outputs.skip != 'true'
        run: |
          VERSION="${{ steps.version.outputs.version }}"
          
          # Update package name, version, and optionalDependencies for oh-my-openagent
          jq --arg v "$VERSION" '
            .name = "oh-my-openagent" |
            .version = $v |
            .optionalDependencies = (
              .optionalDependencies | to_entries |
              map(.key = (.key | sub("^oh-my-opencode-"; "oh-my-openagent-")) | .value = $v) |
              from_entries
            )
          ' package.json > tmp.json && mv tmp.json package.json
          
          TAG_ARG=""
          if [ -n "${{ steps.version.outputs.dist_tag }}" ]; then
            TAG_ARG="--tag ${{ steps.version.outputs.dist_tag }}"
          fi
          npm publish --access public --provenance $TAG_ARG || echo "::warning::oh-my-openagent publish failed"
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
          NPM_CONFIG_PROVENANCE: true

      - name: Restore package.json
        if: steps.check-openagent.outputs.skip != 'true'
        run: |
          git checkout -- package.json

  trigger-platform:
    runs-on: ubuntu-latest
    needs: publish-main
    if: inputs.skip_platform != true
    steps:
      - name: Trigger platform publish workflow
        run: |
          gh workflow run publish-platform.yml \
            --repo ${{ github.repository }} \
            --ref ${{ github.ref }} \
            -f version=${{ needs.publish-main.outputs.version }} \
            -f dist_tag=${{ needs.publish-main.outputs.dist_tag }}
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  release:
    runs-on: ubuntu-latest
    needs: publish-main
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - run: git fetch --force --tags

      - uses: oven-sh/setup-bun@v2
        with:
          bun-version: latest

      - name: Install dependencies
        run: bun install
        env:
          BUN_INSTALL_ALLOW_SCRIPTS: "@ast-grep/napi"

      - name: Generate changelog
        run: |
          bun run script/generate-changelog.ts > /tmp/changelog.md
          cat /tmp/changelog.md
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Create GitHub release
        run: |
          VERSION="${{ needs.publish-main.outputs.version }}"
          gh release view "v${VERSION}" >/dev/null 2>&1 || \
            gh release create "v${VERSION}" --title "v${VERSION}" --notes-file /tmp/changelog.md
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Delete draft release
        run: gh release delete next --yes 2>/dev/null || true
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Merge to master
        continue-on-error: true
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"
          VERSION="${{ needs.publish-main.outputs.version }}"
          git stash --include-untracked || true
          git checkout master
          git reset --hard "v${VERSION}"
          git push -f origin master || echo "::warning::Failed to push to master"
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}


================================================
FILE: .github/workflows/sisyphus-agent.yml
================================================
name: Sisyphus Agent

on:
  workflow_dispatch:
    inputs:
      prompt:
        description: "Custom prompt"
        required: false
  # Only issue_comment works for fork PRs (secrets available)
  # pull_request_review/pull_request_review_comment do NOT get secrets for fork PRs
  issue_comment:
    types: [created]

jobs:
  agent:
    runs-on: ubuntu-latest
    # @sisyphus-dev-ai mention only (maintainers, exclude self)
    if: >-
      github.event_name == 'workflow_dispatch' ||
      (github.event_name == 'issue_comment' &&
       contains(github.event.comment.body || '', '@sisyphus-dev-ai') &&
       (github.event.comment.user.login || '') != 'sisyphus-dev-ai' &&
       contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association || ''))

    permissions:
      contents: read

    steps:
      # Checkout with sisyphus-dev-ai's PAT
      - uses: actions/checkout@v5
        with:
          token: ${{ secrets.GH_PAT }}
          fetch-depth: 0

      # Git config - commits as sisyphus-dev-ai
      - name: Configure Git as sisyphus-dev-ai
        run: |
          git config user.name "sisyphus-dev-ai"
          git config user.email "sisyphus-dev-ai@users.noreply.github.com"

      # gh CLI auth as sisyphus-dev-ai
      - name: Authenticate gh CLI as sisyphus-dev-ai
        run: |
          echo "${{ secrets.GH_PAT }}" | gh auth login --with-token
          gh auth status

      - name: Ensure tmux is available (Linux)
        if: runner.os == 'Linux'
        run: |
          set -euo pipefail
          if ! command -v tmux >/dev/null 2>&1; then
            sudo apt-get update
            sudo apt-get install -y --no-install-recommends tmux
          fi
          tmux -V

      - name: Setup Bun
        uses: oven-sh/setup-bun@v2
        with:
          bun-version: latest

      - name: Cache Bun dependencies
        uses: actions/cache@v4
        with:
          path: |
            ~/.bun/install/cache
            node_modules
          key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }}
          restore-keys: |
            ${{ runner.os }}-bun-

      # Build local oh-my-opencode
      - name: Build oh-my-opencode
        run: |
          bun install
          bun run build

      # Install OpenCode + configure local plugin + auth in single step
      - name: Setup OpenCode with oh-my-opencode
        env:
          OPENCODE_AUTH_JSON: ${{ secrets.OPENCODE_AUTH_JSON }}
          ANTHROPIC_BASE_URL: ${{ secrets.ANTHROPIC_BASE_URL }}
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        run: |
          export PATH="$HOME/.opencode/bin:$PATH"

          # Install OpenCode (skip if cached)
          if ! command -v opencode &>/dev/null; then
            echo "Installing OpenCode..."
            curl -fsSL https://opencode.ai/install -o /tmp/opencode-install.sh
            
            # Try default installer first, fallback to re-download if it fails
            if file /tmp/opencode-install.sh | grep -q "shell script\|text"; then
              if ! bash /tmp/opencode-install.sh 2>&1; then
                echo "Default installer failed, trying direct install..."
                bash <(curl -fsSL https://opencode.ai/install)
              fi
            else
              echo "Download corrupted, trying direct install..."
              bash <(curl -fsSL https://opencode.ai/install)
            fi
          fi
          opencode --version

          # Run local oh-my-opencode install (uses built dist)
          bun run dist/cli/index.js install --no-tui --claude=max20 --openai=no --gemini=no --copilot=no

          # Override plugin to use local file reference
          OPENCODE_JSON=~/.config/opencode/opencode.json
          REPO_PATH=$(pwd)
          jq --arg path "file://$REPO_PATH/src/index.ts" '
            .plugin = [.plugin[] | select(. != "oh-my-opencode")] + [$path]
          ' "$OPENCODE_JSON" > /tmp/oc.json && mv /tmp/oc.json "$OPENCODE_JSON"

          OPENCODE_JSON=~/.config/opencode/opencode.json
          jq --arg baseURL "$ANTHROPIC_BASE_URL" --arg apiKey "$ANTHROPIC_API_KEY" '
            .model = "anthropic/claude-opus-4-5" |
            .provider.anthropic = {
              "name": "Anthropic",
              "npm": "@ai-sdk/anthropic",
              "options": {
                "baseURL": $baseURL,
                "apiKey": $apiKey
              },
              "models": {
                "claude-opus-4-5": {
                  "id": "claude-opus-4-5-20251101",
                  "name": "Opus 4.5",
                  "limit": { "context": 190000, "output": 64000 },
                  "options": { "effort": "high" }
                },
                "claude-opus-4-5-high": {
                  "id": "claude-opus-4-5-20251101",
                  "name": "Opus 4.5 High",
                  "limit": { "context": 190000, "output": 128000 },
                  "options": { "effort": "high", "thinking": { "type": "enabled", "budgetTokens": 64000 } }
                },
                "claude-sonnet-4-6": {
                  "id": "claude-sonnet-4-6-20250929",
                  "name": "Sonnet 4.6",
                  "limit": { "context": 200000, "output": 64000 }
                },
                "claude-sonnet-4-6-high": {
                  "id": "claude-sonnet-4-6-20250929",
                  "name": "Sonnet 4.6 High",
                  "limit": { "context": 200000, "output": 128000 },
                  "options": { "thinking": { "type": "enabled", "budgetTokens": 64000 } }
                },
                "claude-haiku-4-5": {
                  "id": "claude-haiku-4-5-20251001",
                  "name": "Haiku 4.5",
                  "limit": { "context": 200000, "output": 64000 }
                }
              }
            } |
            .provider["zai-coding-plan"] = {
              "name": "Z.AI Coding Plan",
              "npm": "@ai-sdk/openai-compatible",
              "options": {
                "baseURL": "https://api.z.ai/api/paas/v4"
              },
              "models": {
                "glm-4.7": {
                  "id": "glm-4.7",
                  "name": "GLM 4.7",
                  "limit": { "context": 128000, "output": 16000 }
                },
                "glm-4.6v": {
                  "id": "glm-4.6v",
                  "name": "GLM 4.6 Vision",
                  "limit": { "context": 128000, "output": 16000 }
                }
              }
            } |
            .provider.openai = {
              "name": "OpenAI",
              "npm": "@ai-sdk/openai",
              "models": {
                "gpt-5.2": {
                  "id": "gpt-5.2",
                  "name": "GPT-5.2",
                  "limit": { "context": 128000, "output": 16000 }
                },
                "gpt-5.2-codex": {
                  "id": "gpt-5.2-codex",
                  "name": "GPT-5.2 Codex",
                  "limit": { "context": 128000, "output": 32000 }
                }
              }
            }
          ' "$OPENCODE_JSON" > /tmp/oc.json && mv /tmp/oc.json "$OPENCODE_JSON"

          OMO_JSON=~/.config/opencode/oh-my-opencode.json
          PROMPT_APPEND=$(cat << 'PROMPT_EOF'
          <ultrawork-mode>
          [CODE RED] Maximum precision required. Ultrathink before acting.

          YOU MUST LEVERAGE ALL AVAILABLE AGENTS TO THEIR FULLEST POTENTIAL.
          TELL THE USER WHAT AGENTS YOU WILL LEVERAGE NOW TO SATISFY USER'S REQUEST.

          ## AGENT UTILIZATION PRINCIPLES (by capability, not by name)
          - **Codebase Exploration**: Spawn exploration agents using BACKGROUND TASKS for file patterns, internal implementations, project structure
          - **Documentation & References**: Use librarian-type agents via BACKGROUND TASKS for API references, examples, external library docs
          - **Planning & Strategy**: For implementation tasks, spawn a dedicated planning agent for work breakdown (not needed for simple questions/investigations)
          - **High-IQ Reasoning**: Leverage specialized agents for architecture decisions, code review, strategic planning
          - **Frontend/UI Tasks**: Delegate to UI-specialized agents for design and implementation

          ## EXECUTION RULES
          - **TODO**: Track EVERY step. Mark complete IMMEDIATELY after each.
          - **PARALLEL**: Fire independent agent calls simultaneously via background_task - NEVER wait sequentially.
          - **BACKGROUND FIRST**: Use background_task for exploration/research agents (10+ concurrent if needed).
          - **VERIFY**: Re-read request after completion. Check ALL requirements met before reporting done.
          - **DELEGATE**: Don't do everything yourself - orchestrate specialized agents for their strengths.

          ## WORKFLOW
          1. Analyze the request and identify required capabilities
          2. Spawn exploration/librarian agents via background_task in PARALLEL (10+ if needed)
          3. Always Use Plan agent with gathered context to create detailed work breakdown
          4. Execute with continuous verification against original requirements

          ## TDD (if test infrastructure exists)

          1. Write spec (requirements)
          2. Write tests (failing)
          3. RED: tests fail
          4. Implement minimal code
          5. GREEN: tests pass
          6. Refactor if needed (must stay green)
          7. Next feature, repeat

          ## ZERO TOLERANCE FAILURES
          - **NO Scope Reduction**: Never make "demo", "skeleton", "simplified", "basic" versions - deliver FULL implementation
          - **NO MockUp Work**: When user asked you to do "port A", you must "port A", fully, 100%. No Extra feature, No reduced feature, no mock data, fully working 100% port.
          - **NO Partial Completion**: Never stop at 60-80% saying "you can extend this..." - finish 100%
          - **NO Assumed Shortcuts**: Never skip requirements you deem "optional" or "can be added later"
          - **NO Premature Stopping**: Never declare done until ALL TODOs are completed and verified
          - **NO TEST DELETION**: Never delete or skip failing tests to make the build pass. Fix the code, not the tests.

          THE USER ASKED FOR X. DELIVER EXACTLY X. NOT A SUBSET. NOT A DEMO. NOT A STARTING POINT.

          </ultrawork-mode>

          ---


          [analyze-mode]
          ANALYSIS MODE. Gather context before diving deep:

          CONTEXT GATHERING (parallel):
          - 1-2 explore agents (codebase patterns, implementations)
          - 1-2 librarian agents (if external library involved)
          - Direct tools: Grep, AST-grep, LSP for targeted searches

          IF COMPLEX (architecture, multi-system, debugging after 2+ failures):
          - Consult oracle for strategic guidance

          SYNTHESIZE findings before proceeding.

          ---

          ## GitHub Actions Environment

          You are `sisyphus-dev-ai` in GitHub Actions.

          ### CRITICAL: GitHub Comments = Your ONLY Output

          User CANNOT see console. Post everything via `gh issue comment` or `gh pr comment`.

          ### Comment Formatting (CRITICAL)

          **ALWAYS use heredoc syntax for comments containing code references, backticks, or multiline content:**

          ```bash
          gh issue comment <number> --body "$(cat <<'EOF'
          Your comment with `backticks` and code references preserved here.
          Multiple lines work perfectly.
          EOF
          )"
          ```

          **NEVER use direct quotes with backticks** (shell will interpret them as command substitution):
          ```bash
          # WRONG - backticks disappear:
          gh issue comment 123 --body "text with `code`"
          
          # CORRECT - backticks preserved:
          gh issue comment 123 --body "$(cat <<'EOF'
          text with `code`
          EOF
          )"
          ```

          ### GitHub Markdown Rules (MUST FOLLOW)

          **Code blocks MUST have EXACTLY 3 backticks and language identifier:**
          - CORRECT: ` ```bash ` ... ` ``` `
          - WRONG: ` ``` ` (no language), ` ```` ` (4 backticks), ` `` ` (2 backticks)
          
          **Every opening ` ``` ` MUST have a closing ` ``` ` on its own line:**
          ```
          ```bash
          code here
          ```
          ```
          
          **NO trailing backticks or spaces after closing ` ``` `**
          
          **For inline code, use SINGLE backticks:** `code` not ```code```
          
          **Lists inside code blocks break rendering - avoid them or use plain text**

          ### Rules
          - EVERY response = GitHub comment (use heredoc for proper escaping)
          - Code changes = PR (never push main/master)
          - Setup: bun install first
          - Acknowledge immediately, report when done

          ### Git Config
          - user.name: sisyphus-dev-ai
          - user.email: sisyphus-dev-ai@users.noreply.github.com
          PROMPT_EOF
          )
          jq --arg append "$PROMPT_APPEND" '.agents.Sisyphus.prompt_append = $append' "$OMO_JSON" > /tmp/omo.json && mv /tmp/omo.json "$OMO_JSON"

          # Add categories configuration for unspecified-low to use GLM 4.7
          jq '.categories["unspecified-low"] = { "model": "zai-coding-plan/glm-4.7" }' "$OMO_JSON" > /tmp/omo.json && mv /tmp/omo.json "$OMO_JSON"

          mkdir -p ~/.local/share/opencode
          echo "$OPENCODE_AUTH_JSON" > ~/.local/share/opencode/auth.json
          chmod 600 ~/.local/share/opencode/auth.json

          cat "$OPENCODE_JSON"

      # Collect context
      - name: Collect Context
        id: context
        env:
          GITHUB_TOKEN: ${{ secrets.GH_PAT }}
          EVENT_NAME: ${{ github.event_name }}
          ISSUE_NUMBER: ${{ github.event.issue.number }}
          COMMENT_BODY: ${{ github.event.comment.body }}
          COMMENT_AUTHOR: ${{ github.event.comment.user.login }}
          COMMENT_ID_VAL: ${{ github.event.comment.id }}
          REPO: ${{ github.repository }}
        run: |
          if [[ "$EVENT_NAME" == "issue_comment" ]]; then
            ISSUE_NUM="$ISSUE_NUMBER"
            AUTHOR="$COMMENT_AUTHOR"
            COMMENT_ID="$COMMENT_ID_VAL"

            # Check if PR or Issue and get title
            ISSUE_DATA=$(gh api "repos/$REPO/issues/${ISSUE_NUM}")
            TITLE=$(echo "$ISSUE_DATA" | jq -r '.title')
            if echo "$ISSUE_DATA" | jq -e '.pull_request' > /dev/null; then
              echo "type=pr" >> $GITHUB_OUTPUT
              echo "number=${ISSUE_NUM}" >> $GITHUB_OUTPUT
            else
              echo "type=issue" >> $GITHUB_OUTPUT
              echo "number=${ISSUE_NUM}" >> $GITHUB_OUTPUT
            fi
            echo "title=${TITLE}" >> $GITHUB_OUTPUT
          fi

          echo "comment<<EOF" >> $GITHUB_OUTPUT
          echo "$COMMENT_BODY" >> $GITHUB_OUTPUT
          echo "EOF" >> $GITHUB_OUTPUT
          echo "author=$AUTHOR" >> $GITHUB_OUTPUT
          echo "comment_id=$COMMENT_ID" >> $GITHUB_OUTPUT

      # Add :eyes: reaction (as sisyphus-dev-ai)
      - name: Add eyes reaction
        if: steps.context.outputs.comment_id != ''
        env:
          GITHUB_TOKEN: ${{ secrets.GH_PAT }}
        run: |
          gh api "/repos/${{ github.repository }}/issues/comments/${{ steps.context.outputs.comment_id }}/reactions" \
            -X POST -f content="eyes" || true

      - name: Add working label
        if: steps.context.outputs.number != ''
        env:
          GITHUB_TOKEN: ${{ secrets.GH_PAT }}
        run: |
          gh label create "sisyphus: working" \
            --repo "${{ github.repository }}" \
            --color "fcf2e1" \
            --description "Sisyphus is currently working on this" \
            --force || true
          
          if [[ "${{ steps.context.outputs.type }}" == "pr" ]]; then
            gh pr edit "${{ steps.context.outputs.number }}" \
              --repo "${{ github.repository }}" \
              --add-label "sisyphus: working" || true
          else
            gh issue edit "${{ steps.context.outputs.number }}" \
              --repo "${{ github.repository }}" \
              --add-label "sisyphus: working" || true
          fi

      - name: Run oh-my-opencode
        env:
          GITHUB_TOKEN: ${{ secrets.GH_PAT }}
          USER_COMMENT: ${{ steps.context.outputs.comment }}
          COMMENT_AUTHOR: ${{ steps.context.outputs.author }}
          CONTEXT_TYPE: ${{ steps.context.outputs.type }}
          CONTEXT_NUMBER: ${{ steps.context.outputs.number }}
          CONTEXT_TITLE: ${{ steps.context.outputs.title }}
          REPO_NAME: ${{ github.repository }}
          DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
        run: |
          export PATH="$HOME/.opencode/bin:$PATH"

          PROMPT=$(cat <<'PROMPT_EOF'
          [analyze-mode]
          ANALYSIS MODE. Gather context before diving deep:

          CONTEXT GATHERING (parallel):
          - 1-2 explore agents (codebase patterns, implementations)
          - 1-2 librarian agents (if external library involved)
          - Direct tools: Grep, AST-grep, LSP for targeted searches

          IF COMPLEX (architecture, multi-system, debugging after 2+ failures):
          - Consult oracle for strategic guidance

          SYNTHESIZE findings before proceeding.

          ---

          Your username is @sisyphus-dev-ai, mentioned by @AUTHOR_PLACEHOLDER in REPO_PLACEHOLDER.

          ## Context
          - Title: TITLE_PLACEHOLDER
          - Type: TYPE_PLACEHOLDER
          - Number: #NUMBER_PLACEHOLDER
          - Repository: REPO_PLACEHOLDER
          - Default Branch: BRANCH_PLACEHOLDER

          ## User's Request
          COMMENT_PLACEHOLDER

          ---

          ## CRITICAL: First Steps (MUST DO BEFORE ANYTHING ELSE)

          ### [CODE RED] MANDATORY CONTEXT READING - ZERO EXCEPTIONS

          **YOU MUST READ ALL CONTENT. NOT SOME. NOT MOST. ALL.**

          1. **READ FULL CONVERSATION** - Execute ALL commands below before ANY other action:
             - **Issues**: `gh issue view NUMBER_PLACEHOLDER --comments`
             - **PRs**: Use ALL THREE commands to get COMPLETE context:
               ```bash
               gh pr view NUMBER_PLACEHOLDER --comments
               gh api repos/REPO_PLACEHOLDER/pulls/NUMBER_PLACEHOLDER/comments
               gh api repos/REPO_PLACEHOLDER/pulls/NUMBER_PLACEHOLDER/reviews
               ```
             
             **WHAT TO EXTRACT FROM THE CONVERSATION:**
             - The ORIGINAL issue/PR description (first message) - this is often the TRUE requirement
             - ALL previous attempts and their outcomes
             - ALL decisions made and their reasoning
             - ALL feedback, criticism, and rejection reasons
             - ANY linked issues, PRs, or external references
             - The EXACT ask from the user who mentioned you
             
             **FAILURE TO READ EVERYTHING = GUARANTEED FAILURE**
             You WILL make wrong assumptions. You WILL repeat past mistakes. You WILL miss critical context.

          2. **CREATE TODOS IMMEDIATELY**: Right after reading, create your todo list using todo tools.
             - First todo: "Summarize issue/PR context and requirements"
             - Break down ALL work into atomic, verifiable steps
             - **GIT WORKFLOW (MANDATORY for implementation tasks)**: ALWAYS include these final todos:
               - "Create new branch from origin/BRANCH_PLACEHOLDER (NEVER push directly to BRANCH_PLACEHOLDER)"
               - "Commit changes"
               - "Create PR to BRANCH_PLACEHOLDER branch"
             - Plan everything BEFORE starting any work

          ---


          Plan everything using todo tools.
          Then investigate and satisfy the request. Only if user requested to you to work explicitly, then use plan agent to plan, todo obsessively then create a PR to `BRANCH_PLACEHOLDER` branch.
          When done, report the result to the issue/PR with `gh issue comment NUMBER_PLACEHOLDER` or `gh pr comment NUMBER_PLACEHOLDER`.
          PROMPT_EOF
          )

          PROMPT="${PROMPT//AUTHOR_PLACEHOLDER/$COMMENT_AUTHOR}"
          PROMPT="${PROMPT//REPO_PLACEHOLDER/$REPO_NAME}"
          PROMPT="${PROMPT//TYPE_PLACEHOLDER/$CONTEXT_TYPE}"
          PROMPT="${PROMPT//NUMBER_PLACEHOLDER/$CONTEXT_NUMBER}"
          PROMPT="${PROMPT//TITLE_PLACEHOLDER/$CONTEXT_TITLE}"
          PROMPT="${PROMPT//BRANCH_PLACEHOLDER/$DEFAULT_BRANCH}"
          PROMPT="${PROMPT//COMMENT_PLACEHOLDER/$USER_COMMENT}"

          stdbuf -oL -eL bun run dist/cli/index.js run "$PROMPT"

      # Push changes (as sisyphus-dev-ai)
      - name: Push changes
        if: always()
        env:
          GITHUB_TOKEN: ${{ secrets.GH_PAT }}
        run: |
          if [[ -n "$(git status --porcelain)" ]]; then
            git add -A
            git commit -m "chore: changes by sisyphus-dev-ai" || true
          fi

          BRANCH=$(git branch --show-current)
          if [[ "$BRANCH" != "main" && "$BRANCH" != "master" ]]; then
            git push origin "$BRANCH" || true
          fi

      - name: Update reaction and remove label
        if: always()
        env:
          GITHUB_TOKEN: ${{ secrets.GH_PAT }}
        run: |
          if [[ -n "${{ steps.context.outputs.comment_id }}" ]]; then
            REACTION_ID=$(gh api "/repos/${{ github.repository }}/issues/comments/${{ steps.context.outputs.comment_id }}/reactions" \
              --jq '.[] | select(.content == "eyes" and .user.login == "sisyphus-dev-ai") | .id' | head -1)
            if [[ -n "$REACTION_ID" ]]; then
              gh api -X DELETE "/repos/${{ github.repository }}/reactions/${REACTION_ID}" || true
            fi

            gh api "/repos/${{ github.repository }}/issues/comments/${{ steps.context.outputs.comment_id }}/reactions" \
              -X POST -f content="+1" || true
          fi

          if [[ -n "${{ steps.context.outputs.number }}" ]]; then
            if [[ "${{ steps.context.outputs.type }}" == "pr" ]]; then
              gh pr edit "${{ steps.context.outputs.number }}" \
                --repo "${{ github.repository }}" \
                --remove-label "sisyphus: working" || true
            else
              gh issue edit "${{ steps.context.outputs.number }}" \
                --repo "${{ github.repository }}" \
                --remove-label "sisyphus: working" || true
            fi
          fi


================================================
FILE: .gitignore
================================================
# Dependencies
.sisyphus/*
!.sisyphus/rules/
node_modules/

# Build output
dist/

# Platform binaries (built, not committed)
packages/*/bin/oh-my-opencode
packages/*/bin/oh-my-opencode.exe
packages/*/bin/*.map

# IDE
.idea/
.vscode/
*.swp
*.swo

# OS
.DS_Store
Thumbs.db

# Logs
*.log
npm-debug.log*

# Lock files (use bun.lockb instead)
package-lock.json
yarn.lock

# Environment
.env
.env.local
test-injection/
notepad.md
oauth-success.html
*.bun-build
.omx/


================================================
FILE: .opencode/background-tasks.json
================================================
[
  {
    "id": "bg_wzsdt60b",
    "sessionID": "ses_4f3e89f0dffeooeXNVx5QCifse",
    "parentSessionID": "ses_4f3e8d141ffeyfJ1taVVOdQTzx",
    "parentMessageID": "msg_b0c172ee1001w2B52VSZrP08PJ",
    "description": "Explore opencode in codebase",
    "agent": "explore",
    "status": "completed",
    "startedAt": "2025-12-11T06:26:57.395Z",
    "completedAt": "2025-12-11T06:27:36.778Z"
  },
  {
    "id": "bg_392b9c9b",
    "sessionID": "ses_4f38ebf4fffeJZBocIn3UVv7vE",
    "parentSessionID": "ses_4f38eefa0ffeKV0pVNnwT37P5L",
    "parentMessageID": "msg_b0c7110d2001TMBlPeEYIrByvs",
    "description": "Test explore agent",
    "agent": "explore",
    "status": "running",
    "startedAt": "2025-12-11T08:05:07.378Z",
    "progress": {
      "toolCalls": 0,
      "lastUpdate": "2025-12-11T08:05:07.378Z"
    }
  }
]

================================================
FILE: .opencode/command/get-unpublished-changes.md
================================================
---
description: Compare HEAD with the latest published npm version and list all unpublished changes
---

<command-instruction>
IMMEDIATELY output the analysis. NO questions. NO preamble.

## CRITICAL: DO NOT just copy commit messages!

For each commit, you MUST:
1. Read the actual diff to understand WHAT CHANGED
2. Describe the REAL change in plain language
3. Explain WHY it matters (if not obvious)

## Steps:
1. Run `git diff v{published-version}..HEAD` to see actual changes
2. Group by type (feat/fix/refactor/docs) with REAL descriptions
3. Note breaking changes if any
4. Recommend version bump (major/minor/patch)

## Output Format:
- feat: "Added X that does Y" (not just "add X feature")
- fix: "Fixed bug where X happened, now Y" (not just "fix X bug")
- refactor: "Changed X from A to B, now supports C" (not just "rename X")
</command-instruction>

<version-context>
<published-version>
!`npm view oh-my-opencode version 2>/dev/null || echo "not published"`
</published-version>
<local-version>
!`node -p "require('./package.json').version" 2>/dev/null || echo "unknown"`
</local-version>
<latest-tag>
!`git tag --sort=-v:refname | head -1 2>/dev/null || echo "no tags"`
</latest-tag>
</version-context>

<git-context>
<commits-since-release>
!`npm view oh-my-opencode version 2>/dev/null | xargs -I{} git log "v{}"..HEAD --oneline 2>/dev/null || echo "no commits since release"`
</commits-since-release>
<diff-stat>
!`npm view oh-my-opencode version 2>/dev/null | xargs -I{} git diff "v{}"..HEAD --stat 2>/dev/null || echo "no diff available"`
</diff-stat>
<files-changed-summary>
!`npm view oh-my-opencode version 2>/dev/null | xargs -I{} git diff "v{}"..HEAD --stat 2>/dev/null | tail -1 || echo ""`
</files-changed-summary>
</git-context>

<output-format>
## Unpublished Changes (v{published} → HEAD)

### feat
| Scope | What Changed |
|-------|--------------|
| X | Description of actual changes |

### fix
| Scope | What Changed |
|-------|--------------|
| X | Description of actual changes |

### refactor
| Scope | What Changed |
|-------|--------------|
| X | Description of actual changes |

### docs
| Scope | What Changed |
|-------|--------------|
| X | Description of actual changes |

### Breaking Changes
None or list

### Files Changed
{diff-stat}

### Suggested Version Bump
- **Recommendation**: patch|minor|major
- **Reason**: Reason for recommendation
</output-format>

<oracle-safety-review>
## Oracle Deployment Safety Review (Only when user explicitly requests)

**Trigger keywords**: "safe to deploy", "can I deploy", "is it safe", "review", "check", "oracle"

When user includes any of the above keywords in their request:

### 1. Pre-validation
```bash
bun run typecheck
bun test
```
- On failure → Report "❌ Cannot deploy" immediately without invoking Oracle

### 2. Oracle Invocation Prompt

Collect the following information and pass to Oracle:

```
## Deployment Safety Review Request

### Changes Summary
{Changes table analyzed above}

### Key diffs (organized by feature)
{Core code changes for each feat/fix/refactor - only key parts, not full diff}

### Validation Results
- Typecheck: ✅/❌
- Tests: {pass}/{total} (✅/❌)

### Review Items
1. **Regression Risk**: Are there changes that could affect existing functionality?
2. **Side Effects**: Are there areas where unexpected side effects could occur?
3. **Breaking Changes**: Are there changes that affect external users?
4. **Edge Cases**: Are there missed edge cases?
5. **Deployment Recommendation**: SAFE / CAUTION / UNSAFE

### Request
Please analyze the above changes deeply and provide your judgment on deployment safety.
If there are risks, explain with specific scenarios.
Suggest keywords to monitor after deployment if any.
```

### 3. Output Format After Oracle Response

## 🔍 Oracle Deployment Safety Review Result

### Verdict: ✅ SAFE / ⚠️ CAUTION / ❌ UNSAFE

### Risk Analysis
| Area | Risk Level | Description |
|------|------------|-------------|
| ... | 🟢/🟡/🔴 | ... |

### Recommendations
- ...

### Post-deployment Monitoring Keywords
- ...

### Conclusion
{Oracle's final judgment}
</oracle-safety-review>


================================================
FILE: .opencode/command/omomomo.md
================================================
---
description: Easter egg command - about oh-my-opencode
---

<command-instruction>
You found an easter egg! 🥚✨

Print the following message to the user EXACTLY as written (in a friendly, celebratory tone):

---

# 🎉 oMoMoMoMoMo···

**You found the easter egg!** 🥚✨

## What is Oh My OpenCode?

**Oh My OpenCode** is a powerful OpenCode plugin that transforms your AI agent into a full development team:

- 🤖 **Multi-Agent Orchestration**: Oracle (GPT-5.2), Librarian (Claude), Explore (Grok), Frontend Engineer (Gemini), and more
- 🔧 **LSP Tools**: Full IDE capabilities for your agents - hover, goto definition, find references, rename, code actions
- 🔍 **AST-Grep**: Structural code search and replace across 25 languages
- 📚 **Built-in MCPs**: Context7 for docs, Exa for web search, grep.app for GitHub code search
- 🔄 **Background Agents**: Run multiple agents in parallel like a real dev team
- 🎯 **Claude Code Compatibility**: Your existing Claude Code config just works

## Who Made This?

Created with ❤️ by **[code-yeongyu](https://github.com/code-yeongyu)**

🔗 **GitHub**: https://github.com/code-yeongyu/oh-my-opencode

---

*Enjoy coding on steroids!* 🚀

</command-instruction>


================================================
FILE: .opencode/command/publish.md
================================================
---
description: Publish oh-my-opencode to npm via GitHub Actions workflow
argument-hint: <patch|minor|major>
---

<command-instruction>
You are the release manager for oh-my-opencode. Execute the FULL publish workflow from start to finish.

## CRITICAL: ARGUMENT REQUIREMENT

**You MUST receive a version bump type from the user.** Valid options:
- `patch`: Bug fixes, backward-compatible (1.1.7 → 1.1.8)
- `minor`: New features, backward-compatible (1.1.7 → 1.2.0)
- `major`: Breaking changes (1.1.7 → 2.0.0)

**If the user did not provide a bump type argument, STOP IMMEDIATELY and ask:**
> "To proceed with deployment, please specify a version bump type: `patch`, `minor`, or `major`"

**DO NOT PROCEED without explicit user confirmation of bump type.**

---

## STEP 0: REGISTER TODO LIST (MANDATORY FIRST ACTION)

**Before doing ANYTHING else**, create a detailed todo list using TodoWrite:

```
[
  { "id": "confirm-bump", "content": "Confirm version bump type with user (patch/minor/major)", "status": "in_progress", "priority": "high" },
  { "id": "check-uncommitted", "content": "Check for uncommitted changes and commit if needed", "status": "pending", "priority": "high" },
  { "id": "sync-remote", "content": "Sync with remote (pull --rebase && push if unpushed commits)", "status": "pending", "priority": "high" },
  { "id": "run-workflow", "content": "Trigger GitHub Actions publish workflow", "status": "pending", "priority": "high" },
  { "id": "wait-workflow", "content": "Wait for workflow completion (poll every 30s)", "status": "pending", "priority": "high" },
  { "id": "verify-and-preview", "content": "Verify release created + preview auto-generated changelog & contributor thanks", "status": "pending", "priority": "high" },
  { "id": "draft-summary", "content": "Draft enhanced release summary (mandatory for minor/major, optional for patch — ask user)", "status": "pending", "priority": "high" },
  { "id": "apply-summary", "content": "Prepend enhanced summary to release (if user opted in)", "status": "pending", "priority": "high" },
  { "id": "verify-npm", "content": "Verify npm package published successfully", "status": "pending", "priority": "high" },
  { "id": "wait-platform-workflow", "content": "Wait for publish-platform workflow completion", "status": "pending", "priority": "high" },
  { "id": "verify-platform-binaries", "content": "Verify all 7 platform binary packages published", "status": "pending", "priority": "high" },
  { "id": "final-confirmation", "content": "Final confirmation to user with links", "status": "pending", "priority": "low" }
]
```

**Mark each todo as `in_progress` when starting, `completed` when done. ONE AT A TIME.**

---

## STEP 1: CONFIRM BUMP TYPE

If bump type provided as argument, confirm with user:
> "Version bump type: `{bump}`. Proceed? (y/n)"

Wait for user confirmation before proceeding.

---

## STEP 2: CHECK UNCOMMITTED CHANGES

Run: `git status --porcelain`

- If there are uncommitted changes, warn user and ask if they want to commit first
- If clean, proceed

---

## STEP 2.5: SYNC WITH REMOTE (MANDATORY)

Check if there are unpushed commits:
```bash
git log origin/master..HEAD --oneline
```

**If there are unpushed commits, you MUST sync before triggering workflow:**
```bash
git pull --rebase && git push
```

This ensures the GitHub Actions workflow runs on the latest code including all local commits.

---

## STEP 3: TRIGGER GITHUB ACTIONS WORKFLOW

Run the publish workflow:
```bash
gh workflow run publish -f bump={bump_type}
```

Wait 3 seconds, then get the run ID:
```bash
gh run list --workflow=publish --limit=1 --json databaseId,status --jq '.[0]'
```

---

## STEP 4: WAIT FOR WORKFLOW COMPLETION

Poll workflow status every 30 seconds until completion:
```bash
gh run view {run_id} --json status,conclusion --jq '{status: .status, conclusion: .conclusion}'
```

Status flow: `queued` → `in_progress` → `completed`

**IMPORTANT: Use polling loop, NOT sleep commands.**

If conclusion is `failure`, show error and stop:
```bash
gh run view {run_id} --log-failed
```

---

## STEP 5: VERIFY RELEASE & PREVIEW AUTO-GENERATED CONTENT

Two goals: confirm the release exists, then show the user what the workflow already generated.

```bash
# Pull latest (workflow committed version bump)
git pull --rebase
NEW_VERSION=$(node -p "require('./package.json').version")

# Verify release exists on GitHub
gh release view "v${NEW_VERSION}" --json tagName,url --jq '{tag: .tagName, url: .url}'
```

**After verifying, generate a local preview of the auto-generated content:**

```bash
bun run script/generate-changelog.ts
```

<agent-instruction>
After running the preview, present the output to the user and say:

> **The following content is ALREADY included in the release automatically:**
> - Commit changelog (grouped by feat/fix/refactor)
> - Contributor thank-you messages (for non-team contributors)
>
> You do NOT need to write any of this. It's handled.
>
> **For a patch release**, this is usually sufficient on its own. However, if there are notable bug fixes or changes worth highlighting, an enhanced summary can be added.
> **For a minor/major release**, an enhanced summary is **required** — I'll draft one in the next step.

Wait for the user to acknowledge before proceeding.
</agent-instruction>

---

## STEP 6: DRAFT ENHANCED RELEASE SUMMARY

<decision-gate>

| Release Type | Action |
|-------------|--------|
| **patch** | ASK the user: "Would you like me to draft an enhanced summary highlighting the key bug fixes / changes? Or is the auto-generated changelog sufficient?" If user declines → skip to Step 8. If user accepts → draft a concise bug-fix / change summary below. |
| **minor** | MANDATORY. Draft a concise feature summary. Do NOT proceed without one. |
| **major** | MANDATORY. Draft a full release narrative with migration notes if applicable. Do NOT proceed without one. |

</decision-gate>

### What You're Writing (and What You're NOT)

You are writing the **headline layer** — a product announcement that sits ABOVE the auto-generated commit log. Think "release blog post", not "git log".

<rules>
- NEVER duplicate commit messages. The auto-generated section already lists every commit.
- NEVER write generic filler like "Various bug fixes and improvements" or "Several enhancements".
- ALWAYS focus on USER IMPACT: what can users DO now that they couldn't before?
- ALWAYS group by THEME or CAPABILITY, not by commit type (feat/fix/refactor).
- ALWAYS use concrete language: "You can now do X" not "Added X feature".
</rules>

<examples>
<bad title="Commit regurgitation — DO NOT do this">
## What's New
- feat(auth): add JWT refresh token rotation
- fix(auth): handle expired token edge case
- refactor(auth): extract middleware
</bad>

<good title="User-impact narrative — DO this">
## 🔐 Smarter Authentication

Token refresh is now automatic and seamless. Sessions no longer expire mid-task — the system silently rotates credentials in the background. If you've been frustrated by random logouts, this release fixes that.
</good>

<bad title="Vague filler — DO NOT do this">
## Improvements
- Various performance improvements
- Bug fixes and stability enhancements
</bad>

<good title="Specific and measurable — DO this">
## ⚡ 3x Faster Rule Parsing

Rules are now cached by file modification time. If your project has 50+ rule files, you'll notice startup is noticeably faster — we measured a 3x improvement in our test suite.
</good>
</examples>

### Drafting Process

1. **Analyze** the commit list from Step 5's preview. Identify 2-5 themes that matter to users.
2. **Write** the summary to `/tmp/release-summary-v${NEW_VERSION}.md`.
3. **Present** the draft to the user for review and approval before applying.

```bash
# Write your draft here
cat > /tmp/release-summary-v${NEW_VERSION}.md << 'SUMMARY_EOF'
{your_enhanced_summary}
SUMMARY_EOF

cat /tmp/release-summary-v${NEW_VERSION}.md
```

<agent-instruction>
After drafting, ask the user:
> "Here's the release summary I drafted. This will appear AT THE TOP of the release notes, above the auto-generated commit changelog and contributor thanks. Want me to adjust anything before applying?"

Do NOT proceed to Step 7 without user confirmation.
</agent-instruction>

---

## STEP 7: APPLY ENHANCED SUMMARY TO RELEASE

**Skip this step ONLY if the user opted out of the enhanced summary in Step 6** — proceed directly to Step 8.

<architecture>
The final release note structure:

```
┌─────────────────────────────────────┐
│  Enhanced Summary (from Step 6)     │  ← You wrote this
│  - Theme-based, user-impact focused │
├─────────────────────────────────────┤
│  ---  (separator)                   │
├─────────────────────────────────────┤
│  Auto-generated Commit Changelog    │  ← Workflow wrote this
│  - feat/fix/refactor grouped        │
│  - Contributor thank-you messages   │
└─────────────────────────────────────┘
```
</architecture>

<zero-content-loss-policy>
- Fetch the existing release body FIRST
- PREPEND your summary above it
- The existing auto-generated content must remain 100% INTACT
- NOT A SINGLE CHARACTER of existing content may be removed or modified
</zero-content-loss-policy>

```bash
# 1. Fetch existing auto-generated body
EXISTING_BODY=$(gh release view "v${NEW_VERSION}" --json body --jq '.body')

# 2. Combine: enhanced summary on top, auto-generated below
{
  cat /tmp/release-summary-v${NEW_VERSION}.md
  echo ""
  echo "---"
  echo ""
  echo "$EXISTING_BODY"
} > /tmp/final-release-v${NEW_VERSION}.md

# 3. Update the release (additive only)
gh release edit "v${NEW_VERSION}" --notes-file /tmp/final-release-v${NEW_VERSION}.md

# 4. Confirm
echo "✅ Release v${NEW_VERSION} updated with enhanced summary."
gh release view "v${NEW_VERSION}" --json url --jq '.url'
```

---

## STEP 8: VERIFY NPM PUBLICATION

Poll npm registry until the new version appears:
```bash
npm view oh-my-opencode version
```

Compare with expected version. If not matching after 2 minutes, warn user about npm propagation delay.

---

## STEP 8.5: WAIT FOR PLATFORM WORKFLOW COMPLETION

The main publish workflow triggers a separate `publish-platform` workflow for platform-specific binaries.

1. Find the publish-platform workflow run triggered by the main workflow:
```bash
gh run list --workflow=publish-platform --limit=1 --json databaseId,status,conclusion --jq '.[0]'
```

2. Poll workflow status every 30 seconds until completion:
```bash
gh run view {platform_run_id} --json status,conclusion --jq '{status: .status, conclusion: .conclusion}'
```

**IMPORTANT: Use polling loop, NOT sleep commands.**

If conclusion is `failure`, show error logs:
```bash
gh run view {platform_run_id} --log-failed
```

---

## STEP 8.6: VERIFY PLATFORM BINARY PACKAGES

After publish-platform workflow completes, verify all 7 platform packages are published:

```bash
PLATFORMS="darwin-arm64 darwin-x64 linux-x64 linux-arm64 linux-x64-musl linux-arm64-musl windows-x64"
for PLATFORM in $PLATFORMS; do
  npm view "oh-my-opencode-${PLATFORM}" version
done
```

All 7 packages should show the same version as the main package (`${NEW_VERSION}`).

**Expected packages:**
| Package | Description |
|---------|-------------|
| `oh-my-opencode-darwin-arm64` | macOS Apple Silicon |
| `oh-my-opencode-darwin-x64` | macOS Intel |
| `oh-my-opencode-linux-x64` | Linux x64 (glibc) |
| `oh-my-opencode-linux-arm64` | Linux ARM64 (glibc) |
| `oh-my-opencode-linux-x64-musl` | Linux x64 (musl/Alpine) |
| `oh-my-opencode-linux-arm64-musl` | Linux ARM64 (musl/Alpine) |
| `oh-my-opencode-windows-x64` | Windows x64 |

If any platform package version doesn't match, warn the user and suggest checking the publish-platform workflow logs.

---

## STEP 9: FINAL CONFIRMATION

Report success to user with:
- New version number
- GitHub release URL: https://github.com/code-yeongyu/oh-my-opencode/releases/tag/v{version}
- npm package URL: https://www.npmjs.com/package/oh-my-opencode
- Platform packages status: List all 7 platform packages with their versions

---

## ERROR HANDLING

- **Workflow fails**: Show failed logs, suggest checking Actions tab
- **Release not found**: Wait and retry, may be propagation delay
- **npm not updated**: npm can take 1-5 minutes to propagate, inform user
- **Permission denied**: User may need to re-authenticate with `gh auth login`
- **Platform workflow fails**: Show logs from publish-platform workflow, check which platform failed
- **Platform package missing**: Some platforms may fail due to cross-compilation issues, suggest re-running publish-platform workflow manually

## LANGUAGE

Respond to user in English.

</command-instruction>

<current-context>
<published-version>
!`npm view oh-my-opencode version 2>/dev/null || echo "not published"`
</published-version>
<local-version>
!`node -p "require('./package.json').version" 2>/dev/null || echo "unknown"`
</local-version>
<git-status>
!`git status --porcelain`
</git-status>
<recent-commits>
!`npm view oh-my-opencode version 2>/dev/null | xargs -I{} git log "v{}"..HEAD --oneline 2>/dev/null | head -15 || echo "no commits"`
</recent-commits>
</current-context>


================================================
FILE: .opencode/command/remove-deadcode.md
================================================
---
description: Remove unused code from this project with ultrawork mode, LSP-verified safety, atomic commits
---

<command-instruction>

Dead code removal via massively parallel deep agents. You are the ORCHESTRATOR — you scan, verify, batch, then delegate ALL removals to parallel agents.

<rules>
- **LSP is law.** Verify with `LspFindReferences(includeDeclaration=false)` before ANY removal decision.
- **Never remove entry points.** `src/index.ts`, `src/cli/index.ts`, test files, config files, `packages/` — off-limits.
- **You do NOT remove code yourself.** You scan, verify, batch, then fire deep agents. They do the work.
</rules>

<false-positive-guards>
NEVER mark as dead:
- Symbols in `src/index.ts` or barrel `index.ts` re-exports
- Symbols referenced in test files (tests are valid consumers)
- Symbols with `@public` / `@api` JSDoc tags
- Hook factories (`createXXXHook`), tool factories (`createXXXTool`), agent definitions in `agentSources`
- Command templates, skill definitions, MCP configs
- Symbols in `package.json` exports
</false-positive-guards>

---

## PHASE 1: SCAN — Find Dead Code Candidates

Run ALL of these in parallel:

<parallel-scan>

**TypeScript strict mode (your primary scanner — run this FIRST):**
```bash
bunx tsc --noEmit --noUnusedLocals --noUnusedParameters 2>&1
```
This gives you the definitive list of unused locals, imports, parameters, and types with exact file:line locations.

**Explore agents (fire ALL simultaneously as background):**

```
task(subagent_type="explore", run_in_background=true, load_skills=[],
  description="Find orphaned files",
  prompt="Find files in src/ NOT imported by any other file. Check all import statements. EXCLUDE: index.ts, *.test.ts, entry points, .md, packages/. Return: file paths.")

task(subagent_type="explore", run_in_background=true, load_skills=[],
  description="Find unused exported symbols",
  prompt="Find exported functions/types/constants in src/ that are never imported by other files. Cross-reference: for each export, grep the symbol name across src/ — if it only appears in its own file, it's a candidate. EXCLUDE: src/index.ts exports, test files. Return: file path, line, symbol name, export type.")
```

</parallel-scan>

Collect all results into a master candidate list.

---

## PHASE 2: VERIFY — LSP Confirmation (Zero False Positives)

For EACH candidate from Phase 1:

```typescript
LspFindReferences(filePath, line, character, includeDeclaration=false)
// 0 references → CONFIRMED dead
// 1+ references → NOT dead, drop from list
```

Also apply the false-positive-guards above. Produce a confirmed list:

```
| # | File | Symbol | Type | Action |
|---|------|--------|------|--------|
| 1 | src/foo.ts:42 | unusedFunc | function | REMOVE |
| 2 | src/bar.ts:10 | OldType | type | REMOVE |
| 3 | src/baz.ts:7 | ctx | parameter | PREFIX _ |
```

**Action types:**
- `REMOVE` — delete the symbol/import/file entirely
- `PREFIX _` — unused function parameter required by signature → rename to `_paramName`

If ZERO confirmed: report "No dead code found" and STOP.

---

## PHASE 3: BATCH — Group by File for Conflict-Free Parallelism

<batching-rules>

**Goal: maximize parallel agents with ZERO git conflicts.**

1. Group confirmed dead code items by FILE PATH
2. All items in the SAME file go to the SAME batch (prevents two agents editing the same file)
3. If a dead FILE (entire file deletion) exists, it's its own batch
4. Target 5-15 batches. If fewer than 5 items total, use 1 batch per item.

**Example batching:**
```
Batch A: [src/hooks/foo/hook.ts — 3 unused imports]
Batch B: [src/features/bar/manager.ts — 2 unused constants, 1 dead function]
Batch C: [src/tools/baz/tool.ts — 1 unused param, src/tools/baz/types.ts — 1 unused type]
Batch D: [src/dead-file.ts — entire file deletion]
```

Files in the same directory CAN be batched together (they won't conflict as long as no two agents edit the same file). Maximize batch count for parallelism.

</batching-rules>

---

## PHASE 4: EXECUTE — Fire Parallel Deep Agents

For EACH batch, fire a deep agent:

```
task(
  category="deep",
  load_skills=["typescript-programmer", "git-master"],
  run_in_background=true,
  description="Remove dead code batch N: [brief description]",
  prompt="[see template below]"
)
```

<agent-prompt-template>

Every deep agent gets this prompt structure (fill in the specifics per batch):

```
## TASK: Remove dead code from [file list]

## DEAD CODE TO REMOVE

### [file path] line [N]
- Symbol: `[name]` — [type: unused import / unused constant / unused function / unused parameter / dead file]
- Action: [REMOVE entirely / REMOVE from import list / PREFIX with _]

### [file path] line [N]
- ...

## PROTOCOL

1. Read each file to understand exact syntax at the target lines
2. For each symbol, run LspFindReferences to RE-VERIFY it's still dead (another agent may have changed things)
3. Apply the change:
   - Unused import (only symbol in line): remove entire import line
   - Unused import (one of many): remove only that symbol from the import list
   - Unused constant/function/type: remove the declaration. Clean up trailing blank lines.
   - Unused parameter: prefix with `_` (do NOT remove — required by signature)
   - Dead file: delete with `rm`
4. After ALL edits in this batch, run: `bun run typecheck`
5. If typecheck fails: `git checkout -- [files]` and report failure
6. If typecheck passes: stage ONLY your files and commit:
   `git add [your-specific-files] && git commit -m "refactor: remove dead code from [brief file list]"`
7. Report what you removed and the commit hash

## CRITICAL
- Stage ONLY your batch's files (`git add [specific files]`). NEVER `git add -A` — other agents are working in parallel.
- If typecheck fails after your edits, REVERT all changes and report. Do not attempt to fix.
- Pre-existing test failures in other files are expected. Only typecheck matters for your batch.
```

</agent-prompt-template>

Fire ALL batches simultaneously. Wait for all to complete.

---

## PHASE 5: FINAL VERIFICATION

After ALL agents complete:

```bash
bun run typecheck   # must pass
bun test            # note any NEW failures vs pre-existing
bun run build       # must pass
```

Produce summary:

```markdown
## Dead Code Removal Complete

### Removed
| # | Symbol | File | Type | Commit | Agent |
|---|--------|------|------|--------|-------|
| 1 | unusedFunc | src/foo.ts | function | abc1234 | Batch A |

### Skipped (agent reported failure)
| # | Symbol | File | Reason |
|---|--------|------|--------|

### Verification
- Typecheck: PASS/FAIL
- Tests: X passing, Y failing (Z pre-existing)
- Build: PASS/FAIL
- Total removed: N symbols across M files
- Total commits: K atomic commits
- Parallel agents used: P
```

---

## SCOPE CONTROL

If `$ARGUMENTS` is provided, narrow the scan:
- File path → only that file
- Directory → only that directory
- Symbol name → only that symbol
- `all` or empty → full project scan (default)

## ABORT CONDITIONS

STOP and report if:
- More than 50 candidates found (ask user to narrow scope or confirm proceeding)
- Build breaks and cannot be fixed by reverting

</command-instruction>

<user-request>
$ARGUMENTS
</user-request>


================================================
FILE: .opencode/skills/github-triage/SKILL.md
================================================
---
name: github-triage
description: "Read-only GitHub triage for issues AND PRs. 1 item = 1 background task (category: quick). Analyzes all open items and writes evidence-backed reports to /tmp/{datetime}/. Every claim requires a GitHub permalink as proof. NEVER takes any action on GitHub - no comments, no merges, no closes, no labels. Reports only. Triggers: 'triage', 'triage issues', 'triage PRs', 'github triage'."
---

# GitHub Triage - Read-Only Analyzer

<role>
Read-only GitHub triage orchestrator. Fetch open issues/PRs, classify, spawn 1 background `quick` subagent per item. Each subagent analyzes and writes a report file. ZERO GitHub mutations.
</role>

## Architecture

**1 ISSUE/PR = 1 `task_create` = 1 `quick` SUBAGENT (background). NO EXCEPTIONS.**

| Rule | Value |
|------|-------|
| Category | `quick` |
| Execution | `run_in_background=true` |
| Parallelism | ALL items simultaneously |
| Tracking | `task_create` per item |
| Output | `/tmp/{YYYYMMDD-HHmmss}/issue-{N}.md` or `pr-{N}.md` |

---

## Zero-Action Policy (ABSOLUTE)

<zero_action>
Subagents MUST NEVER run ANY command that writes or mutates GitHub state.

**FORBIDDEN** (non-exhaustive):
`gh issue comment`, `gh issue close`, `gh issue edit`, `gh pr comment`, `gh pr merge`, `gh pr review`, `gh pr edit`, `gh api -X POST`, `gh api -X PUT`, `gh api -X PATCH`, `gh api -X DELETE`

**ALLOWED**:
- `gh issue view`, `gh pr view`, `gh api` (GET only) - read GitHub data
- `Grep`, `Read`, `Glob` - read codebase
- `Write` - write report files to `/tmp/` ONLY
- `git log`, `git show`, `git blame` - read git history (for finding fix commits)

**ANY GitHub mutation = CRITICAL violation.**
</zero_action>

---

## Evidence Rule (MANDATORY)

<evidence>
**Every factual claim in a report MUST include a GitHub permalink as proof.**

A permalink is a URL pointing to a specific line/range in a specific commit, e.g.:
`https://github.com/{owner}/{repo}/blob/{commit_sha}/{path}#L{start}-L{end}`

### How to generate permalinks

1. Find the relevant file and line(s) via Grep/Read.
2. Get the current commit SHA: `git rev-parse HEAD`
3. Construct: `https://github.com/{REPO}/blob/{SHA}/{filepath}#L{line}` (or `#L{start}-L{end}` for ranges)

### Rules

- **No permalink = no claim.** If you cannot back a statement with a permalink, state "No evidence found" instead.
- Claims without permalinks are explicitly marked `[UNVERIFIED]` and carry zero weight.
- Permalinks to `main`/`master`/`dev` branches are NOT acceptable - use commit SHAs only.
- For bug analysis: permalink to the problematic code. For fix verification: permalink to the fixing commit diff.
</evidence>

---

## Phase 0: Setup

```bash
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
REPORT_DIR="/tmp/$(date +%Y%m%d-%H%M%S)"
mkdir -p "$REPORT_DIR"
COMMIT_SHA=$(git rev-parse HEAD)
```

Pass `REPO`, `REPORT_DIR`, and `COMMIT_SHA` to every subagent.

---

## Phase 1: Fetch All Open Items

<fetch>
Paginate if 500 results returned.

```bash
ISSUES=$(gh issue list --repo $REPO --state open --limit 500 \
  --json number,title,state,createdAt,updatedAt,labels,author,body,comments)
ISSUE_LEN=$(echo "$ISSUES" | jq length)
if [ "$ISSUE_LEN" -eq 500 ]; then
  LAST_DATE=$(echo "$ISSUES" | jq -r '.[-1].createdAt')
  while true; do
    PAGE=$(gh issue list --repo $REPO --state open --limit 500 \
      --search "created:<$LAST_DATE" \
      --json number,title,state,createdAt,updatedAt,labels,author,body,comments)
    PAGE_LEN=$(echo "$PAGE" | jq length)
    [ "$PAGE_LEN" -eq 0 ] && break
    ISSUES=$(echo "[$ISSUES, $PAGE]" | jq -s 'add | unique_by(.number)')
    [ "$PAGE_LEN" -lt 500 ] && break
    LAST_DATE=$(echo "$PAGE" | jq -r '.[-1].createdAt')
  done
fi

PRS=$(gh pr list --repo $REPO --state open --limit 500 \
  --json number,title,state,createdAt,updatedAt,labels,author,body,headRefName,baseRefName,isDraft,mergeable,reviewDecision,statusCheckRollup)
PR_LEN=$(echo "$PRS" | jq length)
if [ "$PR_LEN" -eq 500 ]; then
  LAST_DATE=$(echo "$PRS" | jq -r '.[-1].createdAt')
  while true; do
    PAGE=$(gh pr list --repo $REPO --state open --limit 500 \
      --search "created:<$LAST_DATE" \
      --json number,title,state,createdAt,updatedAt,labels,author,body,headRefName,baseRefName,isDraft,mergeable,reviewDecision,statusCheckRollup)
    PAGE_LEN=$(echo "$PAGE" | jq length)
    [ "$PAGE_LEN" -eq 0 ] && break
    PRS=$(echo "[$PRS, $PAGE]" | jq -s 'add | unique_by(.number)')
    [ "$PAGE_LEN" -lt 500 ] && break
    LAST_DATE=$(echo "$PAGE" | jq -r '.[-1].createdAt')
  done
fi
```
</fetch>

---

## Phase 2: Classify

| Type | Detection |
|------|-----------|
| `ISSUE_QUESTION` | `[Question]`, `[Discussion]`, `?`, "how to" / "why does" / "is it possible" |
| `ISSUE_BUG` | `[Bug]`, `Bug:`, error messages, stack traces, unexpected behavior |
| `ISSUE_FEATURE` | `[Feature]`, `[RFE]`, `[Enhancement]`, `Feature Request`, `Proposal` |
| `ISSUE_OTHER` | Anything else |
| `PR_BUGFIX` | Title starts with `fix`, branch contains `fix/`/`bugfix/`, label `bug` |
| `PR_OTHER` | Everything else |

---

## Phase 3: Spawn Subagents (Individual Tool Calls)

**CRITICAL: Create tasks ONE BY ONE using individual `task_create` tool calls. NEVER batch or script.**

For each item, execute these steps sequentially:

### Step 3.1: Create Task Record
```typescript
task_create(
  subject="Triage: #{number} {title}",
  description="GitHub {issue|PR} triage analysis - {type}",
  metadata={"type": "{ISSUE_QUESTION|ISSUE_BUG|ISSUE_FEATURE|ISSUE_OTHER|PR_BUGFIX|PR_OTHER}", "number": {number}}
)
```

### Step 3.2: Spawn Analysis Subagent (Background)
```typescript
task(
  category="quick",
  run_in_background=true,
  load_skills=[],
  prompt=SUBAGENT_PROMPT
)
```

**ABSOLUTE RULES for Subagents:**
- **ONLY ANALYZE** - Never take action on GitHub (no comments, merges, closes)
- **READ-ONLY** - Use tools only for reading code/GitHub data
- **WRITE REPORT ONLY** - Output goes to `{REPORT_DIR}/{issue|pr}-{number}.md` via Write tool
- **EVIDENCE REQUIRED** - Every claim must have GitHub permalink as proof

```
For each item:
  1. task_create(subject="Triage: #{number} {title}")
  2. task(category="quick", run_in_background=true, load_skills=[], prompt=SUBAGENT_PROMPT)
  3. Store mapping: item_number -> { task_id, background_task_id }
```

---

## Subagent Prompts

### Common Preamble (include in ALL subagent prompts)

```
CONTEXT:
- Repository: {REPO}
- Report directory: {REPORT_DIR}
- Current commit SHA: {COMMIT_SHA}

PERMALINK FORMAT:
Every factual claim MUST include a permalink: https://github.com/{REPO}/blob/{COMMIT_SHA}/{filepath}#L{start}-L{end}
No permalink = no claim. Mark unverifiable claims as [UNVERIFIED].
To get current SHA if needed: git rev-parse HEAD

ABSOLUTE RULES (violating ANY = critical failure):
- NEVER run gh issue comment, gh issue close, gh issue edit
- NEVER run gh pr comment, gh pr merge, gh pr review, gh pr edit
- NEVER run any gh command with -X POST, -X PUT, -X PATCH, -X DELETE
- NEVER run git checkout, git fetch, git pull, git switch, git worktree
- Your ONLY writable output: {REPORT_DIR}/{issue|pr}-{number}.md via the Write tool
```


---

### ISSUE_QUESTION

```
You are analyzing issue #{number} for {REPO}.

ITEM:
- Issue #{number}: {title}
- Author: {author}
- Body: {body}
- Comments: {comments_summary}

TASK:
1. Understand the question.
2. Search the codebase (Grep, Read) for the answer.
3. For every finding, construct a permalink: https://github.com/{REPO}/blob/{COMMIT_SHA}/{path}#L{N}
4. Write report to {REPORT_DIR}/issue-{number}.md

REPORT FORMAT (write this as the file content):

# Issue #{number}: {title}
**Type:** Question | **Author:** {author} | **Created:** {createdAt}

## Question
[1-2 sentence summary]

## Findings
[Each finding with permalink proof. Example:]
- The config is parsed in [`src/config/loader.ts#L42-L58`](https://github.com/{REPO}/blob/{SHA}/src/config/loader.ts#L42-L58)

## Suggested Answer
[Draft answer with code references and permalinks]

## Confidence: [HIGH | MEDIUM | LOW]
[Reason. If LOW: what's missing]

## Recommended Action
[What maintainer should do]

---
REMEMBER: No permalink = no claim. Every code reference needs a permalink.
```

---

### ISSUE_BUG

```
You are analyzing bug report #{number} for {REPO}.

ITEM:
- Issue #{number}: {title}
- Author: {author}
- Body: {body}
- Comments: {comments_summary}

TASK:
1. Understand: expected behavior, actual behavior, reproduction steps.
2. Search the codebase for relevant code. Trace the logic.
3. Determine verdict: CONFIRMED_BUG, NOT_A_BUG, ALREADY_FIXED, or UNCLEAR.
4. For ALREADY_FIXED: find the fixing commit using git log/git blame. Include the commit SHA and what changed.
5. For every finding, construct a permalink.
6. Write report to {REPORT_DIR}/issue-{number}.md

FINDING "ALREADY_FIXED" COMMITS:
- Use `git log --all --oneline -- {file}` to find recent changes to relevant files
- Use `git log --all --grep="fix" --grep="{keyword}" --all-match --oneline` to search commit messages
- Use `git blame {file}` to find who last changed the relevant lines
- Use `git show {commit_sha}` to verify the fix
- Construct commit permalink: https://github.com/{REPO}/commit/{fix_commit_sha}

REPORT FORMAT (write this as the file content):

# Issue #{number}: {title}
**Type:** Bug Report | **Author:** {author} | **Created:** {createdAt}

## Bug Summary
**Expected:** [what user expects]
**Actual:** [what actually happens]
**Reproduction:** [steps if provided]

## Verdict: [CONFIRMED_BUG | NOT_A_BUG | ALREADY_FIXED | UNCLEAR]

## Analysis

### Evidence
[Each piece of evidence with permalink. No permalink = mark [UNVERIFIED]]

### Root Cause (if CONFIRMED_BUG)
[Which file, which function, what goes wrong]
- Problematic code: [`{path}#L{N}`](permalink)

### Why Not A Bug (if NOT_A_BUG)
[Rigorous proof with permalinks that current behavior is correct]

### Fix Details (if ALREADY_FIXED)
- **Fixed in commit:** [`{short_sha}`](https://github.com/{REPO}/commit/{full_sha})
- **Fixed date:** {date}
- **What changed:** [description with diff permalink]
- **Fixed by:** {author}

### Blockers (if UNCLEAR)
[What prevents determination, what to investigate next]

## Severity: [LOW | MEDIUM | HIGH | CRITICAL]

## Affected Files
[List with permalinks]

## Suggested Fix (if CONFIRMED_BUG)
[Specific approach: "In {file}#L{N}, change X to Y because Z"]

## Recommended Action
[What maintainer should do]

---
CRITICAL: Claims without permalinks are worthless. If you cannot find evidence, say so explicitly rather than making unverified claims.
```

---

### ISSUE_FEATURE

```
You are analyzing feature request #{number} for {REPO}.

ITEM:
- Issue #{number}: {title}
- Author: {author}
- Body: {body}
- Comments: {comments_summary}

TASK:
1. Understand the request.
2. Search codebase for existing (partial/full) implementations.
3. Assess feasibility.
4. Write report to {REPORT_DIR}/issue-{number}.md

REPORT FORMAT (write this as the file content):

# Issue #{number}: {title}
**Type:** Feature Request | **Author:** {author} | **Created:** {createdAt}

## Request Summary
[What the user wants]

## Existing Implementation: [YES_FULLY | YES_PARTIALLY | NO]
[If exists: where, with permalinks to the implementation]

## Feasibility: [EASY | MODERATE | HARD | ARCHITECTURAL_CHANGE]

## Relevant Files
[With permalinks]

## Implementation Notes
[Approach, pitfalls, dependencies]

## Recommended Action
[What maintainer should do]
```

---

### ISSUE_OTHER

```
You are analyzing issue #{number} for {REPO}.

ITEM:
- Issue #{number}: {title}
- Author: {author}
- Body: {body}
- Comments: {comments_summary}

TASK: Assess and write report to {REPORT_DIR}/issue-{number}.md

REPORT FORMAT (write this as the file content):

# Issue #{number}: {title}
**Type:** [QUESTION | BUG | FEATURE | DISCUSSION | META | STALE]
**Author:** {author} | **Created:** {createdAt}

## Summary
[1-2 sentences]

## Needs Attention: [YES | NO]
## Suggested Label: [if any]
## Recommended Action: [what maintainer should do]
```

---

### PR_BUGFIX

```
You are reviewing PR #{number} for {REPO}.

ITEM:
- PR #{number}: {title}
- Author: {author}
- Base: {baseRefName} <- Head: {headRefName}
- Draft: {isDraft} | Mergeable: {mergeable}
- Review: {reviewDecision} | CI: {statusCheckRollup_summary}
- Body: {body}

TASK:
1. Fetch PR details (READ-ONLY): gh pr view {number} --repo {REPO} --json files,reviews,comments,statusCheckRollup,reviewDecision
2. Read diff: gh api repos/{REPO}/pulls/{number}/files
3. Search codebase to verify fix correctness.
4. Write report to {REPORT_DIR}/pr-{number}.md

REPORT FORMAT (write this as the file content):

# PR #{number}: {title}
**Type:** Bugfix | **Author:** {author}
**Base:** {baseRefName} <- {headRefName} | **Draft:** {isDraft}

## Fix Summary
[What bug, how fixed - with permalinks to changed code]

## Code Review

### Correctness
[Is fix correct? Root cause addressed? Evidence with permalinks]

### Side Effects
[Risky changes, breaking changes - with permalinks if any]

### Code Quality
[Style, patterns, test coverage]

## Merge Readiness

| Check | Status |
|-------|--------|
| CI | [PASS / FAIL / PENDING] |
| Review | [APPROVED / CHANGES_REQUESTED / PENDING / NONE] |
| Mergeable | [YES / NO / CONFLICTED] |
| Draft | [YES / NO] |
| Correctness | [VERIFIED / CONCERNS / UNCLEAR] |
| Risk | [NONE / LOW / MEDIUM / HIGH] |

## Files Changed
[List with brief descriptions]

## Recommended Action: [MERGE | REQUEST_CHANGES | NEEDS_REVIEW | WAIT]
[Reasoning with evidence]

---
NEVER merge. NEVER comment. NEVER review. Write to file ONLY.
```

---

### PR_OTHER

```
You are reviewing PR #{number} for {REPO}.

ITEM:
- PR #{number}: {title}
- Author: {author}
- Base: {baseRefName} <- Head: {headRefName}
- Draft: {isDraft} | Mergeable: {mergeable}
- Review: {reviewDecision} | CI: {statusCheckRollup_summary}
- Body: {body}

TASK:
1. Fetch PR details (READ-ONLY): gh pr view {number} --repo {REPO} --json files,reviews,comments,statusCheckRollup,reviewDecision
2. Read diff: gh api repos/{REPO}/pulls/{number}/files
3. Write report to {REPORT_DIR}/pr-{number}.md

REPORT FORMAT (write this as the file content):

# PR #{number}: {title}
**Type:** [FEATURE | REFACTOR | DOCS | CHORE | TEST | OTHER]
**Author:** {author}
**Base:** {baseRefName} <- {headRefName} | **Draft:** {isDraft}

## Summary
[2-3 sentences with permalinks to key changes]

## Status

| Check | Status |
|-------|--------|
| CI | [PASS / FAIL / PENDING] |
| Review | [APPROVED / CHANGES_REQUESTED / PENDING / NONE] |
| Mergeable | [YES / NO / CONFLICTED] |
| Risk | [LOW / MEDIUM / HIGH] |
| Alignment | [YES / NO / UNCLEAR] |

## Files Changed
[Count and key files]

## Blockers
[If any]

## Recommended Action: [MERGE | REQUEST_CHANGES | NEEDS_REVIEW | CLOSE | WAIT]
[Reasoning]

---
NEVER merge. NEVER comment. NEVER review. Write to file ONLY.
```

---

## Phase 4: Collect & Update

Poll `background_output()` per task. As each completes:
1. Parse report.
2. `task_update(id=task_id, status="completed", description=REPORT_SUMMARY)`
3. Stream to user immediately.

---

## Phase 5: Final Summary

Write to `{REPORT_DIR}/SUMMARY.md` AND display to user:

```markdown
# GitHub Triage Report - {REPO}

**Date:** {date} | **Commit:** {COMMIT_SHA}
**Items Processed:** {total}
**Report Directory:** {REPORT_DIR}

## Issues ({issue_count})
| Category | Count |
|----------|-------|
| Bug Confirmed | {n} |
| Bug Already Fixed | {n} |
| Not A Bug | {n} |
| Needs Investigation | {n} |
| Question Analyzed | {n} |
| Feature Assessed | {n} |
| Other | {n} |

## PRs ({pr_count})
| Category | Count |
|----------|-------|
| Bugfix Reviewed | {n} |
| Other PR Reviewed | {n} |

## Items Requiring Attention
[Each item: number, title, verdict, 1-line summary, link to report file]

## Report Files
[All generated files with paths]
```

---

## Anti-Patterns

| Violation | Severity |
|-----------|----------|
| ANY GitHub mutation (comment/close/merge/review/label/edit) | **CRITICAL** |
| Claim without permalink | **CRITICAL** |
| Using category other than `quick` | CRITICAL |
| Batching multiple items into one task | CRITICAL |
| `run_in_background=false` | CRITICAL |
| `git checkout` on PR branch | CRITICAL |
| Guessing without codebase evidence | HIGH |
| Not writing report to `{REPORT_DIR}` | HIGH |
| Using branch name instead of commit SHA in permalink | HIGH |


================================================
FILE: .opencode/skills/github-triage/scripts/gh_fetch.py
================================================
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.11"
# dependencies = [
#     "typer>=0.12.0",
#     "rich>=13.0.0",
# ]
# ///
"""
GitHub Issues/PRs Fetcher with Exhaustive Pagination.

Fetches ALL issues and/or PRs from a GitHub repository using gh CLI.
Implements proper pagination to ensure no items are missed.

Usage:
    ./gh_fetch.py issues                    # Fetch all issues
    ./gh_fetch.py prs                       # Fetch all PRs
    ./gh_fetch.py all                       # Fetch both issues and PRs
    ./gh_fetch.py issues --hours 48         # Issues from last 48 hours
    ./gh_fetch.py prs --state open          # Only open PRs
    ./gh_fetch.py all --repo owner/repo     # Specify repository
"""

import asyncio
import json
from datetime import UTC, datetime, timedelta
from enum import Enum
from typing import Annotated

import typer
from rich.console import Console
from rich.panel import Panel
from rich.progress import Progress, TaskID
from rich.table import Table

app = typer.Typer(
    name="gh_fetch",
    help="Fetch GitHub issues/PRs with exhaustive pagination.",
    no_args_is_help=True,
)
console = Console()

BATCH_SIZE = 500  # Maximum allowed by GitHub API


class ItemState(str, Enum):
    ALL = "all"
    OPEN = "open"
    CLOSED = "closed"


class OutputFormat(str, Enum):
    JSON = "json"
    TABLE = "table"
    COUNT = "count"


async def run_gh_command(args: list[str]) -> tuple[str, str, int]:
    """Run gh CLI command asynchronously."""
    proc = await asyncio.create_subprocess_exec(
        "gh",
        *args,
        stdout=asyncio.subprocess.PIPE,
        stderr=asyncio.subprocess.PIPE,
    )
    stdout, stderr = await proc.communicate()
    return stdout.decode(), stderr.decode(), proc.returncode or 0


async def get_current_repo() -> str:
    """Get the current repository from gh CLI."""
    stdout, stderr, code = await run_gh_command(
        ["repo", "view", "--json", "nameWithOwner", "-q", ".nameWithOwner"]
    )
    if code != 0:
        console.print(f"[red]Error getting current repo: {stderr}[/red]")
        raise typer.Exit(1)
    return stdout.strip()


async def fetch_items_page(
    repo: str,
    item_type: str,  # "issue" or "pr"
    state: str,
    limit: int,
    search_filter: str = "",
) -> list[dict]:
    """Fetch a single page of issues or PRs."""
    cmd = [
        item_type,
        "list",
        "--repo",
        repo,
        "--state",
        state,
        "--limit",
        str(limit),
        "--json",
        "number,title,state,createdAt,updatedAt,labels,author,body",
    ]
    if search_filter:
        cmd.extend(["--search", search_filter])

    stdout, stderr, code = await run_gh_command(cmd)
    if code != 0:
        console.print(f"[red]Error fetching {item_type}s: {stderr}[/red]")
        return []

    try:
        return json.loads(stdout) if stdout.strip() else []
    except json.JSONDecodeError:
        console.print(f"[red]Error parsing {item_type} response[/red]")
        return []


async def fetch_all_items(
    repo: str,
    item_type: str,
    state: str,
    hours: int | None,
    progress: Progress,
    task_id: TaskID,
) -> list[dict]:
    """Fetch ALL items with exhaustive pagination."""
    all_items: list[dict] = []
    page = 1

    progress.update(task_id, description=f"[cyan]Fetching {item_type}s page {page}...")
    items = await fetch_items_page(repo, item_type, state, BATCH_SIZE)
    fetched_count = len(items)
    all_items.extend(items)

    console.print(f"[dim]Page {page}: fetched {fetched_count} {item_type}s[/dim]")

    while fetched_count == BATCH_SIZE:
        page += 1
        progress.update(
            task_id, description=f"[cyan]Fetching {item_type}s page {page}..."
        )

        last_created = all_items[-1].get("createdAt", "")
        if not last_created:
            break

        search_filter = f"created:<{last_created}"
        items = await fetch_items_page(
            repo, item_type, state, BATCH_SIZE, search_filter
        )
        fetched_count = len(items)

        if fetched_count == 0:
            break

        existing_numbers = {item["number"] for item in all_items}
        new_items = [item for item in items if item["number"] not in existing_numbers]
        all_items.extend(new_items)

        console.print(
            f"[dim]Page {page}: fetched {fetched_count}, added {len(new_items)} new (total: {len(all_items)})[/dim]"
        )

        if page > 20:
            console.print("[yellow]Safety limit reached (20 pages)[/yellow]")
            break

    if hours is not None:
        cutoff = datetime.now(UTC) - timedelta(hours=hours)
        cutoff_str = cutoff.isoformat()

        original_count = len(all_items)
        all_items = [
            item
            for item in all_items
            if item.get("createdAt", "") >= cutoff_str
            or item.get("updatedAt", "") >= cutoff_str
        ]
        filtered_count = original_count - len(all_items)
        if filtered_count > 0:
            console.print(
                f"[dim]Filtered out {filtered_count} items older than {hours} hours[/dim]"
            )

    return all_items


def display_table(items: list[dict], item_type: str) -> None:
    """Display items in a Rich table."""
    table = Table(title=f"{item_type.upper()}s ({len(items)} total)")
    table.add_column("#", style="cyan", width=6)
    table.add_column("Title", style="white", max_width=50)
    table.add_column("State", style="green", width=8)
    table.add_column("Author", style="yellow", width=15)
    table.add_column("Labels", style="magenta", max_width=30)
    table.add_column("Updated", style="dim", width=12)

    for item in items[:50]:
        labels = ", ".join(label.get("name", "") for label in item.get("labels", []))
        updated = item.get("updatedAt", "")[:10]
        author = item.get("author", {}).get("login", "unknown")

        table.add_row(
            str(item.get("number", "")),
            (item.get("title", "")[:47] + "...")
            if len(item.get("title", "")) > 50
            else item.get("title", ""),
            item.get("state", ""),
            author,
            (labels[:27] + "...") if len(labels) > 30 else labels,
            updated,
        )

    console.print(table)
    if len(items) > 50:
        console.print(f"[dim]... and {len(items) - 50} more items[/dim]")


@app.command()
def issues(
    repo: Annotated[
        str | None, typer.Option("--repo", "-r", help="Repository (owner/repo)")
    ] = None,
    state: Annotated[
        ItemState, typer.Option("--state", "-s", help="Issue state filter")
    ] = ItemState.ALL,
    hours: Annotated[
        int | None,
        typer.Option(
            "--hours", "-h", help="Only issues from last N hours (created or updated)"
        ),
    ] = None,
    output: Annotated[
        OutputFormat, typer.Option("--output", "-o", help="Output format")
    ] = OutputFormat.TABLE,
) -> None:
    """Fetch all issues with exhaustive pagination."""

    async def async_main() -> None:
        target_repo = repo or await get_current_repo()

        console.print(f"""
[cyan]Repository:[/cyan] {target_repo}
[cyan]State:[/cyan] {state.value}
[cyan]Time filter:[/cyan] {f"Last {hours} hours" if hours else "All time"}
""")

        with Progress(console=console) as progress:
            task: TaskID = progress.add_task("[cyan]Fetching issues...", total=None)
            items = await fetch_all_items(
                target_repo, "issue", state.value, hours, progress, task
            )
            progress.update(
                task, description="[green]Complete!", completed=100, total=100
            )

        console.print(
            Panel(f"[green]Found {len(items)} issues[/green]", border_style="green")
        )

        if output == OutputFormat.JSON:
            console.print(json.dumps(items, indent=2, ensure_ascii=False))
        elif output == OutputFormat.TABLE:
            display_table(items, "issue")
        else:
            console.print(f"Total issues: {len(items)}")

    asyncio.run(async_main())


@app.command()
def prs(
    repo: Annotated[
        str | None, typer.Option("--repo", "-r", help="Repository (owner/repo)")
    ] = None,
    state: Annotated[
        ItemState, typer.Option("--state", "-s", help="PR state filter")
    ] = ItemState.OPEN,
    hours: Annotated[
        int | None,
        typer.Option(
            "--hours", "-h", help="Only PRs from last N hours (created or updated)"
        ),
    ] = None,
    output: Annotated[
        OutputFormat, typer.Option("--output", "-o", help="Output format")
    ] = OutputFormat.TABLE,
) -> None:
    """Fetch all PRs with exhaustive pagination."""

    async def async_main() -> None:
        target_repo = repo or await get_current_repo()

        console.print(f"""
[cyan]Repository:[/cyan] {target_repo}
[cyan]State:[/cyan] {state.value}
[cyan]Time filter:[/cyan] {f"Last {hours} hours" if hours else "All time"}
""")

        with Progress(console=console) as progress:
            task: TaskID = progress.add_task("[cyan]Fetching PRs...", total=None)
            items = await fetch_all_items(
                target_repo, "pr", state.value, hours, progress, task
            )
            progress.update(
                task, description="[green]Complete!", completed=100, total=100
            )

        console.print(
            Panel(f"[green]Found {len(items)} PRs[/green]", border_style="green")
        )

        if output == OutputFormat.JSON:
            console.print(json.dumps(items, indent=2, ensure_ascii=False))
        elif output == OutputFormat.TABLE:
            display_table(items, "pr")
        else:
            console.print(f"Total PRs: {len(items)}")

    asyncio.run(async_main())


@app.command(name="all")
def fetch_all(
    repo: Annotated[
        str | None, typer.Option("--repo", "-r", help="Repository (owner/repo)")
    ] = None,
    state: Annotated[
        ItemState, typer.Option("--state", "-s", help="State filter")
    ] = ItemState.ALL,
    hours: Annotated[
        int | None,
        typer.Option(
            "--hours", "-h", help="Only items from last N hours (created or updated)"
        ),
    ] = None,
    output: Annotated[
        OutputFormat, typer.Option("--output", "-o", help="Output format")
    ] = OutputFormat.TABLE,
) -> None:
    """Fetch all issues AND PRs with exhaustive pagination."""

    async def async_main() -> None:
        target_repo = repo or await get_current_repo()

        console.print(f"""
[cyan]Repository:[/cyan] {target_repo}
[cyan]State:[/cyan] {state.value}
[cyan]Time filter:[/cyan] {f"Last {hours} hours" if hours else "All time"}
[cyan]Fetching:[/cyan] Issues AND PRs
""")

        with Progress(console=console) as progress:
            issues_task: TaskID = progress.add_task(
                "[cyan]Fetching issues...", total=None
            )
            prs_task: TaskID = progress.add_task("[cyan]Fetching PRs...", total=None)

            issues_items, prs_items = await asyncio.gather(
                fetch_all_items(
                    target_repo, "issue", state.value, hours, progress, issues_task
                ),
                fetch_all_items(
                    target_repo, "pr", state.value, hours, progress, prs_task
                ),
            )

            progress.update(
                issues_task,
                description="[green]Issues complete!",
                completed=100,
                total=100,
            )
            progress.update(
                prs_task, description="[green]PRs complete!", completed=100, total=100
            )

        console.print(
            Panel(
                f"[green]Found {len(issues_items)} issues and {len(prs_items)} PRs[/green]",
                border_style="green",
            )
        )

        if output == OutputFormat.JSON:
            result = {"issues": issues_items, "prs": prs_items}
            console.print(json.dumps(result, indent=2, ensure_ascii=False))
        elif output == OutputFormat.TABLE:
            display_table(issues_items, "issue")
            console.print("")
            display_table(prs_items, "pr")
        else:
            console.print(f"Total issues: {len(issues_items)}")
            console.print(f"Total PRs: {len(prs_items)}")

    asyncio.run(async_main())


if __name__ == "__main__":
    app()


================================================
FILE: .opencode/skills/pre-publish-review/SKILL.md
================================================
---
name: pre-publish-review
description: "Nuclear-grade 16-agent pre-publish release gate. Runs /get-unpublished-changes to detect all changes since last npm release, spawns up to 10 ultrabrain agents for deep per-change analysis, invokes /review-work (5 agents) for holistic review, and 1 oracle for overall release synthesis. Use before EVERY npm publish. Triggers: 'pre-publish review', 'review before publish', 'release review', 'pre-release review', 'ready to publish?', 'can I publish?', 'pre-publish', 'safe to publish', 'publishing review', 'pre-publish check'."
---

# Pre-Publish Review — 16-Agent Release Gate

Three-layer review before publishing to npm. Every layer covers a different angle — together they catch what no single reviewer could.

| Layer | Agents | Type | What They Check |
|-------|--------|------|-----------------|
| Per-Change Deep Dive | up to 10 | ultrabrain | Each logical change group individually — correctness, edge cases, pattern adherence |
| Holistic Review | 5 | review-work | Goal compliance, QA execution, code quality, security, context mining across full changeset |
| Release Synthesis | 1 | oracle | Overall release readiness, version bump, breaking changes, deployment risk |

---

## Phase 0: Detect Unpublished Changes

Run `/get-unpublished-changes` FIRST. This is the single source of truth for what changed.

```
skill(name="get-unpublished-changes")
```

This command automatically:
- Detects published npm version vs local version
- Lists all commits since last release
- Reads actual diffs (not just commit messages) to describe REAL changes
- Groups changes by type (feat/fix/refactor/docs) with scope
- Identifies breaking changes
- Recommends version bump (patch/minor/major)

**Save the full output** — it feeds directly into Phase 1 grouping and all agent prompts.

Then capture raw data needed by agent prompts:

```bash
# Extract versions (already in /get-unpublished-changes output)
PUBLISHED=$(npm view oh-my-opencode version 2>/dev/null || echo "not published")
LOCAL=$(node -p "require('./package.json').version" 2>/dev/null || echo "unknown")

# Raw data for agents (diffs, file lists)
COMMITS=$(git log "v${PUBLISHED}"..HEAD --oneline 2>/dev/null || echo "no commits")
COMMIT_COUNT=$(echo "$COMMITS" | wc -l | tr -d ' ')
DIFF_STAT=$(git diff "v${PUBLISHED}"..HEAD --stat 2>/dev/null || echo "no diff")
CHANGED_FILES=$(git diff --name-only "v${PUBLISHED}"..HEAD 2>/dev/null || echo "none")
FILE_COUNT=$(echo "$CHANGED_FILES" | wc -l | tr -d ' ')
```

If `PUBLISHED` is "not published", this is a first release — use the full git history instead.
---

## Phase 1: Parse Changes into Groups

Use the `/get-unpublished-changes` output as the starting point — it already groups by scope and type.

**Grouping strategy:**
1. Start from the `/get-unpublished-changes` analysis which already categorizes by feat/fix/refactor/docs with scope
2. Further split by **module/area** — changes touching the same module or feature area belong together
3. Target **up to 10 groups**. If fewer than 10 commits, each commit is its own group. If more than 10 logical areas, merge the smallest groups.
4. For each group, extract:
   - **Group name**: Short descriptive label (e.g., "agent-model-resolution", "hook-system-refactor")
   - **Commits**: List of commit hashes and messages
   - **Files**: Changed files in this group
   - **Diff**: The relevant portion of the full diff (`git diff v${PUBLISHED}..HEAD -- {group files}`)

---

## Phase 2: Spawn All Agents

Launch ALL agents in a single turn. Every agent uses `run_in_background=true`. No sequential launches.

### Layer 1: Ultrabrain Per-Change Analysis (up to 10)

For each change group, spawn one ultrabrain agent. Each gets only its portion of the diff — not the full changeset.

```
task(
  category="ultrabrain",
  run_in_background=true,
  load_skills=[],
  description="Deep analysis: {GROUP_NAME}",
  prompt="""
<review_type>PER-CHANGE DEEP ANALYSIS</review_type>
<change_group>{GROUP_NAME}</change_group>

<project>oh-my-opencode (npm package)</project>
<published_version>{PUBLISHED}</published_version>
<target_version>{LOCAL}</target_version>

<commits>
{GROUP_COMMITS — hash and message for each commit in this group}
</commits>

<changed_files>
{GROUP_FILES — files changed in this group}
</changed_files>

<diff>
{GROUP_DIFF — only the diff for this group's files}
</diff>

<file_contents>
{Read and include full content of each changed file in this group}
</file_contents>

You are reviewing a specific subset of changes heading into an npm release. Focus exclusively on THIS change group. Other groups are reviewed by parallel agents.

ANALYSIS CHECKLIST:

1. **Intent Clarity**: What is this change trying to do? Is the intent clear from the code and commit messages? If you have to guess, that's a finding.

2. **Correctness**: Trace through the logic for 3+ scenarios. Does the code actually do what it claims? Off-by-one errors, null handling, async edge cases, resource cleanup.

3. **Breaking Changes**: Does this change alter any public API, config format, CLI behavior, or hook contract? If yes, is it backward compatible? Would existing users be surprised?

4. **Pattern Adherence**: Does the new code follow the established patterns visible in the existing file contents? New patterns where old ones exist = finding.

5. **Edge Cases**: What inputs or conditions would break this? Empty arrays, undefined values, concurrent calls, very large inputs, missing config fields.

6. **Error Handling**: Are errors properly caught and propagated? No empty catch blocks? No swallowed promises?

7. **Type Safety**: Any `as any`, `@ts-ignore`, `@ts-expect-error`? Loose typing where strict is possible?

8. **Test Coverage**: Are the behavioral changes covered by tests? Are the tests meaningful or just coverage padding?

9. **Side Effects**: Could this change break something in a different module? Check imports and exports — who depends on what changed?

10. **Release Risk**: On a scale of SAFE / CAUTION / RISKY — how confident are you this change won't cause issues in production?

OUTPUT FORMAT:
<group_name>{GROUP_NAME}</group_name>
<verdict>PASS or FAIL</verdict>
<risk>SAFE / CAUTION / RISKY</risk>
<summary>2-3 sentence assessment of this change group</summary>
<has_breaking_changes>YES or NO</has_breaking_changes>
<breaking_change_details>If YES, describe what breaks and for whom</breaking_change_details>
<findings>
  For each finding:
  - [CRITICAL/MAJOR/MINOR] Category: Description
  - File: path (line range)
  - Evidence: specific code reference
  - Suggestion: how to fix
</findings>
<blocking_issues>Issues that MUST be fixed before publish. Empty if PASS.</blocking_issues>
""")
```

### Layer 2: Holistic Review via /review-work (5 agents)

Spawn a sub-agent that loads the `/review-work` skill. The review-work skill internally launches 5 parallel agents: Oracle (goal verification), unspecified-high (QA execution), Oracle (code quality), Oracle (security), unspecified-high (context mining). All 5 must pass for the review to pass.

```
task(
  category="unspecified-high",
  run_in_background=true,
  load_skills=["review-work"],
  description="Run /review-work on all unpublished changes",
  prompt="""
Run /review-work on the unpublished changes between v{PUBLISHED} and HEAD.

GOAL: Review all changes heading into npm publish of oh-my-opencode. These changes span {COMMIT_COUNT} commits across {FILE_COUNT} files.

CONSTRAINTS:
- This is a plugin published to npm — public API stability matters
- TypeScript strict mode, Bun runtime
- No `as any`, `@ts-ignore`, `@ts-expect-error`
- Factory pattern (createXXX) for tools, hooks, agents
- kebab-case files, barrel exports, no catch-all files

BACKGROUND: Pre-publish review of oh-my-opencode, an OpenCode plugin with 1268 TypeScript files, 160k LOC. Changes since v{PUBLISHED} are about to be published.

The diff base is: git diff v{PUBLISHED}..HEAD

Follow the /review-work skill flow exactly — launch all 5 review agents and collect results. Do NOT skip any of the 5 agents.
""")
```

### Layer 3: Oracle Release Synthesis (1 agent)

The oracle gets the full picture — all commits, full diff stat, and changed file list. It provides the final release readiness assessment.

```
task(
  subagent_type="oracle",
  run_in_background=true,
  load_skills=[],
  description="Oracle: overall release synthesis and version bump recommendation",
  prompt="""
<review_type>RELEASE SYNTHESIS — OVERALL ASSESSMENT</review_type>

<project>oh-my-opencode (npm package)</project>
<published_version>{PUBLISHED}</published_version>
<local_version>{LOCAL}</local_version>

<all_commits>
{ALL COMMITS since published version — hash, message, author, date}
</all_commits>

<diff_stat>
{DIFF_STAT — files changed, insertions, deletions}
</diff_stat>

<changed_files>
{CHANGED_FILES — full list of modified file paths}
</changed_files>

<full_diff>
{FULL_DIFF — the complete git diff between published version and HEAD}
</full_diff>

<file_contents>
{Read and include full content of KEY changed files — focus on public API surfaces, config schemas, agent definitions, hook registrations, tool registrations}
</file_contents>

You are the final gate before an npm publish. 10 ultrabrain agents are reviewing individual changes and 5 review-work agents are doing holistic review. Your job is the bird's-eye view that those focused reviews might miss.

SYNTHESIS CHECKLIST:

1. **Release Coherence**: Do these changes tell a coherent story? Or is this a grab-bag of unrelated changes that should be split into multiple releases?

2. **Version Bump**: Based on semver:
   - PATCH: Bug fixes only, no behavior changes
   - MINOR: New features, backward-compatible changes
   - MAJOR: Breaking changes to public API, config format, or behavior
   Recommend the correct bump with specific justification.

3. **Breaking Changes Audit**: Exhaustively list every change that could break existing users. Check:
   - Config schema changes (new required fields, removed fields, renamed fields)
   - Agent behavior changes (different prompts, different model routing)
   - Hook contract changes (new parameters, removed hooks, renamed hooks)
   - Tool interface changes (new required params, different return types)
   - CLI changes (new commands, changed flags, different output)
   - Skill format changes (SKILL.md schema changes)

4. **Migration Requirements**: If there are breaking changes, what migration steps do users need? Is there auto-migration in place?

5. **Dependency Changes**: New dependencies added? Dependencies removed? Version bumps? Any supply chain risk?

6. **Changelog Draft**: Write a draft changelog entry grouped by:
   - feat: New features
   - fix: Bug fixes
   - refactor: Internal changes (no user impact)
   - breaking: Breaking changes with migration instructions
   - docs: Documentation changes

7. **Deployment Risk Assessment**:
   - SAFE: Routine changes, well-tested, low risk
   - CAUTION: Significant changes but manageable risk
   - RISKY: Large surface area changes, insufficient testing, or breaking changes without migration
   - BLOCK: Critical issues found, do NOT publish

8. **Post-Publish Monitoring**: What should be monitored after publish? Error rates, specific features, user feedback channels.

OUTPUT FORMAT:
<verdict>SAFE / CAUTION / RISKY / BLOCK</verdict>
<recommended_version_bump>PATCH / MINOR / MAJOR</recommended_version_bump>
<version_bump_justification>Why this bump level</version_bump_justification>
<release_coherence>Assessment of whether changes belong in one release</release_coherence>
<breaking_changes>
  Exhaustive list, or "None" if none.
  For each:
  - What changed
  - Who is affected
  - Migration steps
</breaking_changes>
<changelog_draft>
  Ready-to-use changelog entry
</changelog_draft>
<deployment_risk>
  Overall risk assessment with specific concerns
</deployment_risk>
<monitoring_recommendations>
  What to watch after publish
</monitoring_recommendations>
<blocking_issues>Issues that MUST be fixed before publish. Empty if SAFE.</blocking_issues>
""")
```

---

## Phase 3: Collect Results

As agents complete (system notifications), collect via `background_output(task_id="...")`.

Track completion in a table:

| # | Agent | Type | Status | Verdict |
|---|-------|------|--------|---------|
| 1-10 | Ultrabrain: {group_name} | ultrabrain | pending | — |
| 11 | Review-Work Coordinator | unspecified-high | pending | — |
| 12 | Release Synthesis Oracle | oracle | pending | — |

Do NOT deliver the final report until ALL agents have completed.

---

## Phase 4: Final Verdict

<verdict_logic>

**BLOCK** if:
- Oracle verdict is BLOCK
- Any ultrabrain found CRITICAL blocking issues
- Review-work failed on any MAIN agent

**RISKY** if:
- Oracle verdict is RISKY
- Multiple ultrabrains returned CAUTION or FAIL
- Review-work passed but with significant findings

**CAUTION** if:
- Oracle verdict is CAUTION
- A few ultrabrains flagged minor issues
- Review-work passed cleanly

**SAFE** if:
- Oracle verdict is SAFE
- All ultrabrains passed
- Review-work passed

</verdict_logic>

Compile the final report:

```markdown
# Pre-Publish Review — oh-my-opencode

## Release: v{PUBLISHED} -> v{LOCAL}
**Commits:** {COMMIT_COUNT} | **Files Changed:** {FILE_COUNT} | **Agents:** {AGENT_COUNT}

---

## Overall Verdict: SAFE / CAUTION / RISKY / BLOCK

## Recommended Version Bump: PATCH / MINOR / MAJOR
{Justification from Oracle}

---

## Per-Change Analysis (Ultrabrains)

| # | Change Group | Verdict | Risk | Breaking? | Blocking Issues |
|---|-------------|---------|------|-----------|-----------------|
| 1 | {name} | PASS/FAIL | SAFE/CAUTION/RISKY | YES/NO | {count or "none"} |
| ... | ... | ... | ... | ... | ... |

### Blocking Issues from Per-Change Analysis
{Aggregated from all ultrabrains — deduplicated}

---

## Holistic Review (Review-Work)

| # | Review Area | Verdict | Confidence |
|---|------------|---------|------------|
| 1 | Goal & Constraint Verification | PASS/FAIL | HIGH/MED/LOW |
| 2 | QA Execution | PASS/FAIL | HIGH/MED/LOW |
| 3 | Code Quality | PASS/FAIL | HIGH/MED/LOW |
| 4 | Security | PASS/FAIL | Severity |
| 5 | Context Mining | PASS/FAIL | HIGH/MED/LOW |

### Blocking Issues from Holistic Review
{Aggregated from review-work}

---

## Release Synthesis (Oracle)

### Breaking Changes
{From Oracle — exhaustive list or "None"}

### Changelog Draft
{From Oracle — ready to use}

### Deployment Risk
{From Oracle — specific concerns}

### Post-Publish Monitoring
{From Oracle — what to watch}

---

## All Blocking Issues (Prioritized)
{Deduplicated, merged from all three layers, ordered by severity}

## Recommendations
{If BLOCK/RISKY: exactly what to fix, in priority order}
{If CAUTION: suggestions worth considering before publish}
{If SAFE: non-blocking improvements for future}
```

---

## Anti-Patterns

| Violation | Severity |
|-----------|----------|
| Publishing without waiting for all agents | **CRITICAL** |
| Spawning ultrabrains sequentially instead of in parallel | CRITICAL |
| Using `run_in_background=false` for any agent | CRITICAL |
| Skipping the Oracle synthesis | HIGH |
| Not reading file contents for Oracle (it cannot read files) | HIGH |
| Grouping all changes into 1-2 ultrabrains instead of distributing | HIGH |
| Delivering verdict before all agents complete | HIGH |
| Not including diff in ultrabrain prompts | MAJOR |


================================================
FILE: .opencode/skills/work-with-pr/SKILL.md
================================================
---
name: work-with-pr
description: "Full PR lifecycle: git worktree → implement → atomic commits → PR creation → verification loop (CI + review-work + Cubic approval) → merge. Keeps iterating until ALL gates pass and PR is merged. Worktree auto-cleanup after merge. Use whenever implementation work needs to land as a PR. Triggers: 'create a PR', 'implement and PR', 'work on this and make a PR', 'implement issue', 'land this as a PR', 'work-with-pr', 'PR workflow', 'implement end to end', even when user just says 'implement X' if the context implies PR delivery."
---

# Work With PR — Full PR Lifecycle

You are executing a complete PR lifecycle: from isolated worktree setup through implementation, PR creation, and an unbounded verification loop until the PR is merged. The loop has three gates — CI, review-work, and Cubic — and you keep fixing and pushing until all three pass simultaneously.

<architecture>

```
Phase 0: Setup         → Branch + worktree in sibling directory
Phase 1: Implement     → Do the work, atomic commits
Phase 2: PR Creation   → Push, create PR targeting dev
Phase 3: Verify Loop   → Unbounded iteration until ALL gates pass:
  ├─ Gate A: CI         → gh pr checks (bun test, typecheck, build)
  ├─ Gate B: review-work → 5-agent parallel review
  └─ Gate C: Cubic      → cubic-dev-ai[bot] "No issues found"
Phase 4: Merge         → Squash merge, worktree cleanup
```

</architecture>

---

## Phase 0: Setup

Create an isolated worktree so the user's main working directory stays clean. This matters because the user may have uncommitted work, and checking out a branch would destroy it.

<setup>

### 1. Resolve repository context

```bash
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
REPO_NAME=$(basename "$PWD")
BASE_BRANCH="dev"  # CI blocks PRs to master
```

### 2. Create branch

If user provides a branch name, use it. Otherwise, derive from the task:

```bash
# Auto-generate: feature/short-description or fix/short-description
BRANCH_NAME="feature/$(echo "$TASK_SUMMARY" | tr '[:upper:] ' '[:lower:]-' | head -c 50)"
git fetch origin "$BASE_BRANCH"
git branch "$BRANCH_NAME" "origin/$BASE_BRANCH"
```

### 3. Create worktree

Place worktrees as siblings to the repo — not inside it. This avoids git nested repo issues and keeps the working tree clean.

```bash
WORKTREE_PATH="../${REPO_NAME}-wt/${BRANCH_NAME}"
mkdir -p "$(dirname "$WORKTREE_PATH")"
git worktree add "$WORKTREE_PATH" "$BRANCH_NAME"
```

### 4. Set working context

All subsequent work happens inside the worktree. Install dependencies if needed:

```bash
cd "$WORKTREE_PATH"
# If bun project:
[ -f "bun.lock" ] && bun install
```

</setup>

---

## Phase 1: Implement

Do the actual implementation work inside the worktree. The agent using this skill does the work directly — no subagent delegation for the implementation itself.

**Scope discipline**: For bug fixes, stay minimal. Fix the bug, add a test for it, done. Do not refactor surrounding code, add config options, or "improve" things that aren't broken. The verification loop will catch regressions — trust the process.

<implementation>

### Commit strategy

Use the git-master skill's atomic commit principles. The reason for atomic commits: if CI fails on one change, you can isolate and fix it without unwinding everything.

```
3+ files changed  → 2+ commits minimum
5+ files changed  → 3+ commits minimum
10+ files changed → 5+ commits minimum
```

Each commit should pair implementation with its tests. Load `git-master` skill when committing:

```
task(category="quick", load_skills=["git-master"], prompt="Commit the changes atomically following git-master conventions. Repository is at {WORKTREE_PATH}.")
```

### Pre-push local validation

Before pushing, run the same checks CI will run. Catching failures locally saves a full CI round-trip (~3-5 min):

```bash
bun run typecheck
bun test
bun run build
```

Fix any failures before pushing. Each fix-commit cycle should be atomic.

</implementation>

---

## Phase 2: PR Creation

<pr_creation>

### Push and create PR

```bash
git push -u origin "$BRANCH_NAME"
```

Create the PR using the project's template structure:

```bash
gh pr create \
  --base "$BASE_BRANCH" \
  --head "$BRANCH_NAME" \
  --title "$PR_TITLE" \
  --body "$(cat <<'EOF'
## Summary
[1-3 sentences describing what this PR does and why]

## Changes
[Bullet list of key changes]

## Testing
- `bun run typecheck` ✅
- `bun test` ✅
- `bun run build` ✅

## Related Issues
[Link to issue if applicable]
EOF
)"
```

Capture the PR number:

```bash
PR_NUMBER=$(gh pr view --json number -q .number)
```

</pr_creation>

---

## Phase 3: Verification Loop

This is the core of the skill. Three gates must ALL pass for the PR to be ready. The loop has no iteration cap — keep going until done. Gate ordering is intentional: CI is cheapest/fastest, review-work is most thorough, Cubic is external and asynchronous.

<verify_loop>

```
while true:
  1. Wait for CI          → Gate A
  2. If CI fails          → read logs, fix, commit, push, continue
  3. Run review-work      → Gate B
  4. If review fails      → fix blocking issues, commit, push, continue
  5. Check Cubic          → Gate C
  6. If Cubic has issues   → fix issues, commit, push, continue
  7. All three pass       → break
```

### Gate A: CI Checks

CI is the fastest feedback loop. Wait for it to complete, then parse results.

```bash
# Wait for checks to start (GitHub needs a moment after push)
# Then watch for completion
gh pr checks "$PR_NUMBER" --watch --fail-fast
```

**On failure**: Get the failed run logs to understand what broke:

```bash
# Find the failed run
RUN_ID=$(gh run list --branch "$BRANCH_NAME" --status failure --json databaseId --jq '.[0].databaseId')

# Get failed job logs
gh run view "$RUN_ID" --log-failed
```

Read the logs, fix the issue, commit atomically, push, and re-enter the loop.

### Gate B: review-work

The review-work skill launches 5 parallel sub-agents (goal verification, QA, code quality, security, context mining). All 5 must pass.

Invoke review-work after CI passes — there's no point reviewing code that doesn't build:

```
task(
  category="unspecified-high",
  load_skills=["review-work"],
  run_in_background=false,
  description="Post-implementation review of PR changes",
  prompt="Review the implementation work on branch {BRANCH_NAME}. The worktree is at {WORKTREE_PATH}. Goal: {ORIGINAL_GOAL}. Constraints: {CONSTRAINTS}. Run command: bun run dev (or as appropriate)."
)
```

**On failure**: review-work reports blocking issues with specific files and line numbers. Fix each blocking issue, commit, push, and re-enter the loop from Gate A (since code changed, CI must re-run).

### Gate C: Cubic Approval

Cubic (`cubic-dev-ai[bot]`) is an automated review bot that comments on PRs. It does NOT use GitHub's APPROVED review state — instead it posts comments with issue counts and confidence scores.

**Approval signal**: The latest Cubic comment contains `**No issues found**` and confidence `**5/5**`.

**Issue signal**: The comment lists issues with file-level detail.

```bash
# Get the latest Cubic review
CUBIC_REVIEW=$(gh api "repos/${REPO}/pulls/${PR_NUMBER}/reviews" \
  --jq '[.[] | select(.user.login == "cubic-dev-ai[bot]")] | last | .body')

# Check if approved
if echo "$CUBIC_REVIEW" | grep -q "No issues found"; then
  echo "Cubic: APPROVED"
else
  echo "Cubic: ISSUES FOUND"
  echo "$CUBIC_REVIEW"
fi
```

**On issues**: Cubic's review body contains structured issue descriptions. Parse them, determine which are valid (some may be false positives), fix the valid ones, commit, push, re-enter from Gate A.

Cubic reviews are triggered automatically on PR updates. After pushing a fix, wait for the new review to appear before checking again. Use `gh api` polling with a conditional loop:

```bash
# Wait for new Cubic review after push
PUSH_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ)
while true; do
  LATEST_REVIEW_TIME=$(gh api "repos/${REPO}/pulls/${PR_NUMBER}/reviews" \
    --jq '[.[] | select(.user.login == "cubic-dev-ai[bot]")] | last | .submitted_at')
  if [[ "$LATEST_REVIEW_TIME" > "$PUSH_TIME" ]]; then
    break
  fi
  # Use gh api call itself as the delay mechanism — each call takes ~1-2s
  # For longer waits, use: timeout 30 gh pr checks "$PR_NUMBER" --watch 2>/dev/null || true
done
```

### Iteration discipline

Each iteration through the loop:
1. Fix ONLY the issues identified by the failing gate
2. Commit atomically (one logical fix per commit)
3. Push
4. Re-enter from Gate A (code changed → full re-verification)

Avoid the temptation to "improve" unrelated code during fix iterations. Scope creep in the fix loop makes debugging harder and can introduce new failures.

</verify_loop>

---

## Phase 4: Merge & Cleanup

Once all three gates pass:

<merge_cleanup>

### Merge the PR

```bash
# Squash merge to keep history clean
gh pr merge "$PR_NUMBER" --squash --delete-branch
```

### Clean up the worktree

The worktree served its purpose — remove it to avoid disk bloat:

```bash
cd "$ORIGINAL_DIR"  # Return to original working directory
git worktree remove "$WORKTREE_PATH"
# Prune any stale worktree references
git worktree prune
```

### Report completion

Summarize what happened:

```
## PR Merged ✅

- **PR**: #{PR_NUMBER} — {PR_TITLE}
- **Branch**: {BRANCH_NAME} → {BASE_BRANCH}
- **Iterations**: {N} verification loops
- **Gates passed**: CI ✅ | review-work ✅ | Cubic ✅
- **Worktree**: cleaned up
```

</merge_cleanup>

---

## Failure Recovery

<failure_recovery>

If you hit an unrecoverable error (e.g., merge conflict with base branch, infrastructure failure):

1. **Do NOT delete the worktree** — the user may want to inspect or continue manually
2. Report what happened, what was attempted, and where things stand
3. Include the worktree path so the user can resume

For merge conflicts:

```bash
cd "$WORKTREE_PATH"
git fetch origin "$BASE_BRANCH"
git rebase "origin/$BASE_BRANCH"
# Resolve conflicts, then continue the loop
```

</failure_recovery>

---

## Anti-Patterns

| Violation | Why it fails | Severity |
|-----------|-------------|----------|
| Working in main worktree instead of isolated worktree | Pollutes user's working directory, may destroy uncommitted work | CRITICAL |
| Pushing directly to dev/master | Bypasses review entirely | CRITICAL |
| Skipping CI gate after code changes | review-work and Cubic may pass on stale code | CRITICAL |
| Fixing unrelated code during verification loop | Scope creep causes new failures | HIGH |
| Deleting worktree on failure | User loses ability to inspect/resume | HIGH |
| Ignoring Cubic false positives without justification | Cubic issues should be evaluated, not blindly dismissed | MEDIUM |
| Giant single commits | Harder to isolate failures, violates git-master principles | MEDIUM |
| Not running local checks before push | Wastes CI time on obvious failures | MEDIUM |


================================================
FILE: .opencode/skills/work-with-pr-workspace/evals/evals.json
================================================
{
  "skill_name": "work-with-pr",
  "evals": [
    {
      "id": 1,
      "prompt": "I need to add a `max_background_agents` config option to oh-my-opencode that limits how many background agents can run simultaneously. It should be in the plugin config schema with a default of 5. Add validation and make sure the background manager respects it. Create a PR for this.",
      "expected_output": "Agent creates worktree, implements config option with schema validation, adds tests, creates PR, iterates through verification gates until merged",
      "files": [],
      "assertions": [
        {"id": "worktree-isolation", "text": "Plan uses git worktree in a sibling directory (not main working directory)"},
        {"id": "branch-from-dev", "text": "Branch is created from origin/dev (not master/main)"},
        {"id": "atomic-commits", "text": "Plan specifies multiple atomic commits for multi-file changes"},
        {"id": "local-validation", "text": "Runs bun run typecheck, bun test, and bun run build before pushing"},
        {"id": "pr-targets-dev", "text": "PR is created targeting dev branch (not master)"},
        {"id": "three-gates", "text": "Verification loop includes all 3 gates: CI, review-work, and Cubic"},
        {"id": "gate-ordering", "text": "Gates are checked in order: CI first, then review-work, then Cubic"},
        {"id": "cubic-check-method", "text": "Cubic check uses gh api to check cubic-dev-ai[bot] reviews for 'No issues found'"},
        {"id": "worktree-cleanup", "text": "Plan includes worktree cleanup after merge"},
        {"id": "real-file-references", "text": "Code changes reference actual files in the codebase (config schema, background manager)"}
      ]
    },
    {
      "id": 2,
      "prompt": "The atlas hook has a bug where it crashes when boulder.json is missing the worktree_path field. Fix it and land the fix as a PR. Make sure CI passes.",
      "expected_output": "Agent creates worktree for the fix branch, adds null check and test for missing worktree_path, creates PR, iterates verification loop",
      "files": [],
      "assertions": [
        {"id": "worktree-isolation", "text": "Plan uses git worktree in a sibling directory"},
        {"id": "minimal-fix", "text": "Fix is minimal — adds null check, doesn't refactor unrelated code"},
        {"id": "test-added", "text": "Test case added for the missing worktree_path scenario"},
        {"id": "three-gates", "text": "Verification loop includes all 3 gates: CI, review-work, Cubic"},
        {"id": "real-atlas-files", "text": "References actual atlas hook files in src/hooks/atlas/"},
        {"id": "fix-branch-naming", "text": "Branch name follows fix/ prefix convention"}
      ]
    },
    {
      "id": 3,
      "prompt": "Refactor src/tools/delegate-task/constants.ts to split DEFAULT_CATEGORIES and CATEGORY_MODEL_REQUIREMENTS into separate files. Keep backward compatibility with the barrel export. Make a PR.",
      "expected_output": "Agent creates worktree, splits file with atomic commits, ensures imports still work via barrel, creates PR, runs through all gates",
      "files": [],
      "assertions": [
        {"id": "worktree-isolation", "text": "Plan uses git worktree in a sibling directory"},
        {"id": "multiple-atomic-commits", "text": "Uses 2+ commits for the multi-file refactor"},
        {"id": "barrel-export", "text": "Maintains backward compatibility via barrel re-export in constants.ts or index.ts"},
        {"id": "three-gates", "text": "Verification loop includes all 3 gates"},
        {"id": "real-constants-file", "text": "References actual src/tools/delegate-task/constants.ts file and its exports"}
      ]
    },
    {
      "id": 4,
      "prompt": "implement issue #100 - we need to add a new built-in MCP for arxiv paper search. just the basic search endpoint, nothing fancy. pr it",
      "expected_output": "Agent creates worktree, implements arxiv MCP following existing MCP patterns (websearch, context7, grep_app), creates PR with proper template, verification loop runs",
      "files": [],
      "assertions": [
        {"id": "worktree-isolation", "text": "Plan uses git worktree in a sibling directory"},
        {"id": "follows-mcp-pattern", "text": "New MCP follows existing pattern from src/mcp/ (websearch, context7, grep_app)"},
        {"id": "three-gates", "text": "Verification loop includes all 3 gates"},
        {"id": "pr-targets-dev", "text": "PR targets dev branch"},
        {"id": "local-validation", "text": "Runs local checks before pushing"}
      ]
    },
    {
      "id": 5,
      "prompt": "The comment-checker hook is too aggressive - it's flagging legitimate comments that happen to contain 'Note:' as AI slop. Relax the regex pattern and add test cases for the false positives. Work on a separate branch and make a PR.",
      "expected_output": "Agent creates worktree, fixes regex, adds specific test cases for false positive scenarios, creates PR, all three gates pass",
      "files": [],
      "assertions": [
        {"id": "worktree-isolation", "text": "Plan uses git worktree in a sibling directory"},
        {"id": "real-comment-checker-files", "text": "References actual comment-checker hook files in the codebase"},
        {"id": "regression-tests", "text": "Adds test cases specifically for 'Note:' false positive scenarios"},
        {"id": "three-gates", "text": "Verification loop includes all 3 gates"},
        {"id": "minimal-change", "text": "Only modifies regex and adds tests — no unrelated changes"}
      ]
    }
  ]
}


================================================
FILE: .opencode/skills/work-with-pr-workspace/iteration-1/benchmark.json
================================================
{
  "skill_name": "work-with-pr",
  "iteration": 1,
  "summary": {
    "with_skill": {
      "pass_rate": 0.968,
      "mean_duration_seconds": 340.2,
      "stddev_duration_seconds": 169.3
    },
    "without_skill": {
      "pass_rate": 0.516,
      "mean_duration_seconds": 303.0,
      "stddev_duration_seconds": 77.8
    },
    "delta": {
      "pass_rate": 0.452,
      "mean_duration_seconds": 37.2,
      "stddev_duration_seconds": 91.5
    }
  },
  "evals": [
    {
      "eval_name": "happy-path-feature-config-option",
      "with_skill": {
        "pass_rate": 1.0,
        "passed": 10,
        "total": 10,
        "duration_seconds": 292,
        "failed_assertions": []
      },
      "without_skill": {
        "pass_rate": 0.4,
        "passed": 4,
        "total": 10,
        "duration_seconds": 365,
        "failed_assertions": [
          {"assertion": "Plan uses git worktree in a sibling directory", "reason": "Uses git checkout -b, no worktree isolation"},
          {"assertion": "Plan specifies multiple atomic commits for multi-file changes", "reason": "Steps listed sequentially but no atomic commit strategy mentioned"},
          {"assertion": "Verification loop includes all 3 gates: CI, review-work, and Cubic", "reason": "Only mentions CI pipeline in step 6. No review-work or Cubic."},
          {"assertion": "Gates are checked in order: CI first, then review-work, then Cubic", "reason": "No gate ordering - only CI mentioned"},
          {"assertion": "Cubic check uses gh api to check cubic-dev-ai[bot] reviews", "reason": "No mention of Cubic at all"},
          {"assertion": "Plan includes worktree cleanup after merge", "reason": "No worktree used, no cleanup needed"}
        ]
      }
    },
    {
      "eval_name": "bugfix-atlas-null-check",
      "with_skill": {
        "pass_rate": 1.0,
        "passed": 6,
        "total": 6,
        "duration_seconds": 506,
        "failed_assertions": []
      },
      "without_skill": {
        "pass_rate": 0.667,
        "passed": 4,
        "total": 6,
        "duration_seconds": 325,
        "failed_assertions": [
          {"assertion": "Plan uses git worktree in a sibling directory", "reason": "No worktree. Steps go directly to creating branch and modifying files."},
          {"assertion": "Verification loop includes all 3 gates", "reason": "Only mentions CI pipeline (step 5). No review-work or Cubic."}
        ]
      }
    },
    {
      "eval_name": "refactor-split-constants",
      "with_skill": {
        "pass_rate": 1.0,
        "passed": 5,
        "total": 5,
        "duration_seconds": 181,
        "failed_assertions": []
      },
      "without_skill": {
        "pass_rate": 0.4,
        "passed": 2,
        "total": 5,
        "duration_seconds": 229,
        "failed_assertions": [
          {"assertion": "Plan uses git worktree in a sibling directory", "reason": "git checkout -b only, no worktree"},
          {"assertion": "Uses 2+ commits for the multi-file refactor", "reason": "Single atomic commit: 'refactor: split delegate-task constants and category model requirements'"},
          {"assertion": "Verification loop includes all 3 gates", "reason": "Only mentions typecheck/test/build. No review-work or Cubic."}
        ]
      }
    },
    {
      "eval_name": "new-mcp-arxiv-casual",
      "with_skill": {
        "pass_rate": 1.0,
        "passed": 5,
        "total": 5,
        "duration_seconds": 152,
        "failed_assertions": []
      },
      "without_skill": {
        "pass_rate": 0.6,
        "passed": 3,
        "total": 5,
        "duration_seconds": 197,
        "failed_assertions": [
          {"assertion": "Verification loop includes all 3 gates", "reason": "Only mentions bun test/typecheck/build. No review-work or Cubic."}
        ]
      }
    },
    {
      "eval_name": "regex-fix-false-positive",
      "with_skill": {
        "pass_rate": 0.8,
        "passed": 4,
        "total": 5,
        "duration_seconds": 570,
        "failed_assertions": [
          {"assertion": "Only modifies regex and adds tests — no unrelated changes", "reason": "Also proposes config schema change (exclude_patterns) and Go binary update — goes beyond minimal fix"}
        ]
      },
      "without_skill": {
        "pass_rate": 0.6,
        "passed": 3,
        "total": 5,
        "duration_seconds": 399,
        "failed_assertions": [
          {"assertion": "Plan uses git worktree in a sibling directory", "reason": "git checkout -b, no worktree"},
          {"assertion": "Verification loop includes all 3 gates", "reason": "Only bun test and typecheck. No review-work or Cubic."}
        ]
      }
    }
  ],
  "analyst_observations": [
    "Three-gates assertion (CI + review-work + Cubic) is the strongest discriminator: 5/5 with-skill vs 0/5 without-skill. Without the skill, agents never know about Cubic or review-work gates.",
    "Worktree isolation is nearly as discriminating (5/5 vs 1/5). One without-skill run (eval-4) independently chose worktree, suggesting some agents already know worktree patterns, but the skill makes it consistent.",
    "The skill's only failure (eval-5 minimal-change) reveals a potential over-engineering tendency: the skill-guided agent proposed config schema changes and Go binary updates for what should have been a minimal regex fix. Consider adding explicit guidance for fix-type tasks to stay minimal.",
    "Duration tradeoff: with-skill is 12% slower on average (340s vs 303s), driven mainly by eval-2 (bugfix) and eval-5 (regex fix) where the skill's thorough verification planning adds overhead. For eval-1 and eval-3-4, with-skill was actually faster.",
    "Without-skill duration has lower variance (stddev 78s vs 169s), suggesting the skill introduces more variable execution paths depending on task complexity.",
    "Non-discriminating assertions: 'References actual files', 'PR targets dev', 'Runs local checks' — these pass regardless of skill. They validate baseline agent competence, not skill value. Consider removing or downweighting in future iterations.",
    "Atomic commits assertion discriminates moderately (2/2 with-skill tested vs 0/2 without-skill tested). Without the skill, agents default to single commits even for multi-file refactors."
  ]
}


================================================
FILE: .opencode/skills/work-with-pr-workspace/iteration-1/benchmark.md
================================================
# Benchmark: work-with-pr (Iteration 1)

## Summary

| Metric | With Skill | Without Skill | Delta |
|--------|-----------|---------------|-------|
| Pass Rate | 96.8% (30/31) | 51.6% (16/31) | +45.2% |
| Mean Duration | 340.2s | 303.0s | +37.2s |
| Duration Stddev | 169.3s | 77.8s | +91.5s |

## Per-Eval Breakdown

| Eval | With Skill | Without Skill | Delta |
|------|-----------|---------------|-------|
| happy-path-feature-config-option | 100% (10/10) | 40% (4/10) | +60% |
| bugfix-atlas-null-check | 100% (6/6) | 67% (4/6) | +33% |
| refactor-split-constants | 100% (5/5) | 40% (2/5) | +60% |
| new-mcp-arxiv-casual | 100% (5/5) | 60% (3/5) | +40% |
| regex-fix-false-positive | 80% (4/5) | 60% (3/5) | +20% |

## Key Discriminators

- **three-gates** (CI + review-work + Cubic): 5/5 vs 0/5 — strongest signal
- **worktree-isolation**: 5/5 vs 1/5
- **atomic-commits**: 2/2 vs 0/2
- **cubic-check-method**: 1/1 vs 0/1

## Non-Discriminating Assertions

- References actual files: passes in both conditions
- PR targets dev: passes in both conditions
- Runs local checks before pushing: passes in both conditions

## Only With-Skill Failure

- **eval-5 minimal-change**: Skill-guided agent proposed config schema changes and Go binary update for a minimal regex fix. The skill may encourage over-engineering in fix scenarios.

## Analyst Notes

- The skill adds most value for procedural knowledge (verification gates, worktree workflow) that agents cannot infer from codebase alone.
- Duration cost is modest (+12%) and acceptable given the +45% pass rate improvement.
- Consider adding explicit "fix-type tasks: stay minimal" guidance in iteration 2.


================================================
FILE: .opencode/skills/work-with-pr-workspace/iteration-1/eval-1/eval_metadata.json
================================================
{
  "eval_id": 1,
  "eval_name": "happy-path-feature-config-option",
  "prompt": "I need to add a `max_background_agents` config option to oh-my-opencode that limits how many background agents can run simultaneously. It should be in the plugin config schema with a default of 5. Add validation and make sure the background manager respects it. Create a PR for this.",
  "assertions": [
    {
      "id": "worktree-isolation",
      "text": "Plan uses git worktree in a sibling directory (not main working directory)",
      "type": "manual"
    },
    {
      "id": "branch-from-dev",
      "text": "Branch is created from origin/dev (not master/main)",
      "type": "manual"
    },
    {
      "id": "atomic-commits",
      "text": "Plan specifies multiple atomic commits for multi-file changes",
      "type": "manual"
    },
    {
      "id": "local-validation",
      "text": "Runs bun run typecheck, bun test, and bun run build before pushing",
      "type": "manual"
    },
    {
      "id": "pr-targets-dev",
      "text": "PR is created targeting dev branch (not master)",
      "type": "manual"
    },
    {
      "id": "three-gates",
      "text": "Verification loop includes all 3 gates: CI, review-work, and Cubic",
      "type": "manual"
    },
    {
      "id": "gate-ordering",
      "text": "Gates are checked in order: CI first, then review-work, then Cubic",
      "type": "manual"
    },
    {
      "id": "cubic-check-method",
      "text": "Cubic check uses gh api to check cubic-dev-ai[bot] reviews for 'No issues found'",
      "type": "manual"
    },
    {
      "id": "worktree-cleanup",
      "text": "Plan includes worktree cleanup after merge",
      "type": "manual"
    },
    {
      "id": "real-file-references",
      "text": "Code changes reference actual files in the codebase (config schema, background manager)",
      "type": "manual"
    }
  ]
}


================================================
FILE: .opencode/skills/work-with-pr-workspace/iteration-1/eval-1/with_skill/grading.json
================================================
{
  "run_id": "eval-1-with_skill",
  "expectations": [
    {"text": "Plan uses git worktree in a sibling directory", "passed": true, "evidence": "Uses ../omo-wt/feat-max-background-agents"},
    {"text": "Branch is created from origin/dev", "passed": true, "evidence": "git checkout dev && git pull origin dev, then branch"},
    {"text": "Plan specifies multiple atomic commits for multi-file changes", "passed": true, "evidence": "2 commits: schema+tests, then concurrency+manager"},
    {"text": "Runs bun run typecheck, bun test, and bun run build before pushing", "passed": true, "evidence": "Explicit pre-push section with all 3 commands"},
    {"text": "PR is created targeting dev branch", "passed": true, "evidence": "--base dev in gh pr create"},
    {"text": "Verification loop includes all 3 gates: CI, review-work, and Cubic", "passed": true, "evidence": "Gate A (CI), Gate B (review-work 5 agents), Gate C (Cubic)"},
    {"text": "Gates are checked in order: CI first, then review-work, then Cubic", "passed": true, "evidence": "Explicit ordering in verify loop pseudocode"},
    {"text": "Cubic check uses gh api to check cubic-dev-ai[bot] reviews", "passed": true, "evidence": "Mentions cubic-dev-ai[bot] and 'No issues found' signal"},
    {"text": "Plan includes worktree cleanup after merge", "passed": true, "evidence": "Phase 4: git worktree remove ../omo-wt/feat-max-background-agents"},
    {"text": "Code changes reference actual files in the codebase", "passed": true, "evidence": "References src/config/schema/background-task.ts, src/features/background-agent/concurrency.ts, manager.ts"}
  ]
}


================================================
FILE: .opencode/skills/work-with-pr-workspace/iteration-1/eval-1/with_skill/outputs/code-changes.md
================================================
# Code Changes: `max_background_agents` Config Option

## 1. `src/config/schema/background-task.ts` — Add schema field

```typescript
import { z } from "zod"

export const BackgroundTaskConfigSchema = z.object({
  defaultConcurrency: z.number().min(1).optional(),
  providerConcurrency: z.record(z.string(), z.number().min(0)).optional(),
  modelConcurrency: z.record(z.string(), z.number().min(0)).optional(),
  maxDepth: z.number().int().min(1).optional(),
  maxDescendants: z.number().int().min(1).optional(),
  /** Maximum number of background agents that can run simultaneously across all models/providers (default: 5, minimum: 1) */
  maxBackgroundAgents: z.number().int().min(1).optional(),
  /** Stale timeout in milliseconds - interrupt tasks with no activity for this duration (default: 180000 = 3 minutes, minimum: 60000 = 1 minute) */
  staleTimeoutMs: z.number().min(60000).optional(),
  /** Timeout for tasks that never received any progress update, falling back to startedAt (default: 1800000 = 30 minutes, minimum: 60000 = 1 minute) */
  messageStalenessTimeoutMs: z.number().min(60000).optional(),
  syncPollTimeoutMs: z.number().min(60000).optional(),
})

export type BackgroundTaskConfig = z.infer<typeof BackgroundTaskConfigSchema>
```

**Rationale:** Follows exact same pattern as `maxDepth` and `maxDescendants` — `z.number().int().min(1).optional()`. The field is optional; runtime default of 5 is applied in `ConcurrencyManager`. No barrel export changes needed since `src/config/schema.ts` already does `export * from "./schema/background-task"` and the type is inferred.

---

## 2. `src/config/schema/background-task.test.ts` — Add validation tests

Append after the existing `syncPollTimeoutMs` describe block (before the closing `})`):

```typescript
  describe("maxBackgroundAgents", () => {
    describe("#given valid maxBackgroundAgents (10)", () => {
      test("#when parsed #then returns correct value", () => {
        const result = BackgroundTaskConfigSchema.parse({ maxBackgroundAgents: 10 })

        expect(result.maxBackgroundAgents).toBe(10)
      })
    })

    describe("#given maxBackgroundAgents of 1 (minimum)", () => {
      test("#when parsed #then returns correct value", () => {
        const result = BackgroundTaskConfigSchema.parse({ maxBackgroundAgents: 1 })

        expect(result.maxBackgroundAgents).toBe(1)
      })
    })

    describe("#given maxBackgroundAgents below minimum (0)", () => {
      test("#when parsed #then throws ZodError", () => {
        let thrownError: unknown

        try {
          BackgroundTaskConfigSchema.parse({ maxBackgroundAgents: 0 })
        } catch (error) {
          thrownError = error
        }

        expect(thrownError).toBeInstanceOf(ZodError)
      })
    })

    describe("#given maxBackgroundAgents not provided", () => {
      test("#when parsed #then field is undefined", () => {
        const result = BackgroundTaskConfigSchema.parse({})

        expect(result.maxBackgroundAgents).toBeUndefined()
      })
    })

    describe('#given maxBackgroundAgents is non-integer (2.5)', () => {
      test("#when parsed #then throws ZodError", () => {
        let thrownError: unknown

        try {
          BackgroundTaskConfigSchema.parse({ maxBackgroundAgents: 2.5 })
        } catch (error) {
          thrownError = error
        }

        expect(thrownError).toBeInstanceOf(ZodError)
      })
    })
  })
```

**Rationale:** Follows exact test pattern from `maxDepth`, `maxDescendants`, and `syncPollTimeoutMs` tests. Uses `#given`/`#when`/`#then` nested describe style. Tests valid, minimum boundary, below minimum, not provided, and non-integer cases.

---

## 3. `src/features/background-agent/concurrency.ts` — Add global agent limit

```typescript
import type { BackgroundTaskConfig } from "../../config/schema"

const DEFAULT_MAX_BACKGROUND_AGENTS = 5

/**
 * Queue entry with settled-flag pattern to prevent double-resolution.
 *
 * The settled flag ensures that cancelWaiters() doesn't reject
 * an entry that was already resolved by release().
 */
interface QueueEntry {
  resolve: () => void
  rawReject: (error: Error) => void
  settled: boolean
}

export class ConcurrencyManager {
  private config?: BackgroundTaskConfig
  private counts: Map<string, number> = new Map()
  private queues: Map<string, QueueEntry[]> = new Map()
  private globalRunningCount = 0

  constructor(config?: BackgroundTaskConfig) {
    this.config = config
  }

  getMaxBackgroundAgents(): number {
    return this.config?.maxBackgroundAgents ?? DEFAULT_MAX_BACKGROUND_AGENTS
  }

  getGlobalRunningCount(): number {
    return this.globalRunningCount
  }

  canSpawnGlobally(): boolean {
    return this.globalRunningCount < this.getMaxBackgroundAgents()
  }

  acquireGlobal(): void {
    this.globalRunningCount++
  }

  releaseGlobal(): void {
    if (this.globalRunningCount > 0) {
      this.globalRunningCount--
    }
  }

  getConcurrencyLimit(model: string): number {
    // ... existing implementation unchanged ...
  }

  async acquire(model: string): Promise<void> {
    // ... existing implementation unchanged ...
  }

  release(model: string): void {
    // ... existing implementation unchanged ...
  }

  cancelWaiters(model: string): void {
    // ... existing implementation unchanged ...
  }

  clear(): void {
    for (const [model] of this.queues) {
      this.cancelWaiters(model)
    }
    this.counts.clear()
    this.queues.clear()
    this.globalRunningCount = 0
  }

  getCount(model: string): number {
    return this.counts.get(model) ?? 0
  }

  getQueueLength(model: string): number {
    return this.queues.get(model)?.length ?? 0
  }
}
```

**Key changes:**
- Add `DEFAULT_MAX_BACKGROUND_AGENTS = 5` constant
- Add `globalRunningCount` private field
- Add `getMaxBackgroundAgents()`, `getGlobalRunningCount()`, `canSpawnGlobally()`, `acquireGlobal()`, `releaseGlobal()` methods
- `clear()` resets `globalRunningCount` to 0
- All existing per-model methods remain unchanged

---

## 4. `src/features/background-agent/concurrency.test.ts` — Add global limit tests

Append new describe block:

```typescript
describe("ConcurrencyManager global background agent limit", () => {
  test("should default max background agents to 5 when no config", () => {
    // given
    const manager = new ConcurrencyManager()

    // when
    const max = manager.getMaxBackgroundAgents()

    // then
    expect(max).toBe(5)
  })

  test("should use configured maxBackgroundAgents", () => {
    // given
    const config: BackgroundTaskConfig = { maxBackgroundAgents: 10 }
    const manager = new ConcurrencyManager(config)

    // when
    const max = manager.getMaxBackgroundAgents()

    // then
    expect(max).toBe(10)
  })

  test("should allow spawning when under global limit", () => {
    // given
    const config: BackgroundTaskConfig = { maxBackgroundAgents: 2 }
    const manager = new ConcurrencyManager(config)

    // when
    manager.acquireGlobal()

    // then
    expect(manager.canSpawnGlobally()).toBe(true)
    expect(manager.getGlobalRunningCount()).toBe(1)
  })

  test("should block spawning when at global limit", () => {
    // given
    const config: BackgroundTaskConfig = { maxBackgroundAgents: 2 }
    const manager = new ConcurrencyManager(config)

    // when
    manager.acquireGlobal()
    manager.acquireGlobal()

    // then
    expect(manager.canSpawnGlobally()).toBe(false)
    expect(manager.getGlobalRunningCount()).toBe(2)
  })

  test("should allow spawning again after release", () => {
    // given
    const config: BackgroundTaskConfig = { maxBackgroundAgents: 1 }
    const manager = new ConcurrencyManager(config)
    manager.acquireGlobal()

    // when
    manager.releaseGlobal()

    // then
    expect(manager.canSpawnGlobally()).toBe(true)
    expect(manager.getGlobalRunningCount()).toBe(0)
  })

  test("should not go below zero on extra release", () => {
    // given
    const manager = new ConcurrencyManager()

    // when
    manager.releaseGlobal()

    // then
    expect(manager.getGlobalRunningCount()).toBe(0)
  })

  test("should reset global count on clear", () => {
    // given
    const config: BackgroundTaskConfig = { maxBackgroundAgents: 5 }
    const manager = new ConcurrencyManager(config)
    manager.acquireGlobal()
    manager.acquireGlobal()
    manager.acquireGlobal()

    // when
    manager.clear()

    // then
    expect(manager.getGlobalRunningCount()).toBe(0)
  })
})
```

---

## 5. `src/features/background-agent/manager.ts` — Enforce global limit

### In `launch()` method — add check before task creation (after `reserveSubagentSpawn`):

```typescript
  async launch(input: LaunchInput): Promise<BackgroundTask> {
    // ... existing logging ...

    if (!input.agent || input.agent.trim() === "") {
      throw new Error("Agent parameter is required")
    }

    // Check global background agent limit before spawn guard
    if (!this.concurrencyManager.canSpawnGlobally()) {
      const max = this.concurrencyManager.getMaxBackgroundAgents()
      const current = this.concurrencyManager.getGlobalRunningCount()
      throw new Error(
        `Background agent spawn blocked: ${current} agents running, max is ${max}. Wait for existing tasks to complete or increase background_task.maxBackgroundAgents.`
      )
    }

    const spawnReservation = await this.reserveSubagentSpawn(input.parentSessionID)

    try {
      // ... existing code ...

      // After task creation, before queueing:
      this.concurrencyManager.acquireGlobal()

      // ... rest of existing code ...
    } catch (error) {
      spawnReservation.rollback()
      throw error
    }
  }
```

### In `trackTask()` method — add global check:

```typescript
  async trackTask(input: { ... }): Promise<BackgroundTask> {
    const existingTask = this.tasks.get(input.taskId)
    if (existingTask) {
      // ... existing re-registration logic unchanged ...
      return existingTask
    }

    // Check global limit for new external tasks
    if (!this.concurrencyManager.canSpawnGlobally()) {
      const max = this.concurrencyManager.getMaxBackgroundAgents()
      const current = this.concurrencyManager.getGlobalRunningCount()
      throw new Error(
        `Background agent spawn blocked: ${current} agents running, max is ${max}. Wait for existing tasks to complete or increase background_task.maxBackgroundAgents.`
      )
    }

    // ... existing task creation ...
    this.concurrencyManager.acquireGlobal()

    // ... rest unchanged ...
  }
```

### In `tryCompleteTask()` — release global slot:

```typescript
  private async tryCompleteTask(task: BackgroundTask, source: string): Promise<boolean> {
    if (task.status !== "running") {
      // ... existing guard ...
      return false
    }

    task.status = "completed"
    task.completedAt = new Date()
    // ... existing history record ...

    removeTaskToastTracking(task.id)

    // Release per-model concurrency
    if (task.concurrencyKey) {
      this.concurrencyManager.release(task.concurrencyKey)
      task.concurrencyKey = undefined
    }

    // Release global slot
    this.concurrencyManager.releaseGlobal()

    // ... rest unchanged ...
  }
```

### In `cancelTask()` — release global slot:

```typescript
  async cancelTask(taskId: string, options?: { ... }): Promise<boolean> {
    // ... existing code up to concurrency release ...

    if (task.concurrencyKey) {
      this.concurrencyManager.release(task.concurrencyKey)
      task.concurrencyKey = undefined
    }

    // Release global slot (only for running tasks, pending never acquired)
    if (task.status !== "pending") {
      this.concurrencyManager.releaseGlobal()
    }

    // ... rest unchanged ...
  }
```

### In `handleEvent()` session.error handler — release global slot:

```typescript
    if (event.type === "session.error") {
      // ... existing error handling ...

      task.status = "error"
      // ...

      if (task.concurrencyKey) {
        this.concurrencyManager.release(task.concurrencyKey)
        task.concurrencyKey = undefined
      }

      // Release global slot
      this.concurrencyManager.releaseGlobal()

      // ... rest unchanged ...
    }
```

### In prompt error handler inside `startTask()` — release global slot:

```typescript
    promptWithModelSuggestionRetry(this.client, { ... }).catch((error) => {
      // ... existing error handling ...
      if (existingTask) {
        existingTask.status = "interrupt"
        // ...
        if (existingTask.concurrencyKey) {
          this.concurrencyManager.release(existingTask.concurrencyKey)
          existingTask.concurrencyKey = undefined
        }

        // Release global slot
        this.concurrencyManager.releaseGlobal()

        // ... rest unchanged ...
      }
    })
```

---

## Summary of Changes

| File | Lines Added | Lines Modified |
|------|-------------|----------------|
| `src/config/schema/background-task.ts` | 2 | 0 |
| `src/config/schema/background-task.test.ts` | ~50 | 0 |
| `src/features/background-agent/concurrency.ts` | ~25 | 1 (`clear()`) |
| `src/features/background-agent/concurrency.test.ts` | ~70 | 0 |
| `src/features/background-agent/manager.ts` | ~20 | 0 |

Total: ~167 lines added, 1 line modified across 5 files.


================================================
FILE: .opencode/skills/work-with-pr-workspace/iteration-1/eval-1/with_skill/outputs/execution-plan.md
================================================
# Execution Plan: `max_background_agents` Config Option

## Phase 0: Setup — Branch + Worktree

1. **Create branch** from `dev`:
   ```bash
   git checkout dev && git pull origin dev
   git checkout -b feat/max-background-agents
   ```

2. **Create worktree** in sibling directory:
   ```bash
   mkdir -p ../omo-wt
   git worktree add ../omo-wt/feat-max-background-agents feat/max-background-agents
   ```

3. **All subsequent work** happens in `../omo-wt/feat-max-background-agents/`, never in the main worktree.

---

## Phase 1: Implement — Atomic Commits

### Commit 1: Add `max_background_agents` to config schema

**Files changed:**
- `src/config/schema/background-task.ts` — Add `maxBackgroundAgents` field to `BackgroundTaskConfigSchema`
- `src/config/schema/background-task.test.ts` — Add validation tests for the new field

**What:**
- Add `maxBackgroundAgents: z.number().int().min(1).optional()` to `BackgroundTaskConfigSchema`
- Default value handled at runtime (5), not in schema (all schema fields are optional per convention)
- Add given/when/then tests: valid value, below minimum, not provided, non-number

### Commit 2: Enforce limit in BackgroundManager + ConcurrencyManager

**Files changed:**
- `src/features/background-agent/concurrency.ts` — Add global agent count tracking + `getGlobalRunningCount()` + `canSpawnGlobally()`
- `src/features/background-agent/concurrency.test.ts` — Tests for global limit enforcement
- `src/features/background-agent/manager.ts` — Check global limit before `launch()` and `trackTask()`

**What:**
- `ConcurrencyManager` already manages per-model concurrency. Add a separate global counter:
  - `private globalRunningCount: number = 0`
  - `private maxBackgroundAgents: number` (from config, default 5)
  - `acquireGlobal()` / `releaseGlobal()` methods
  - `getGlobalRunningCount()` for observability
- `BackgroundManager.launch()` checks `concurrencyManager.canSpawnGlobally()` before creating task
- `BackgroundManager.trackTask()` also checks global limit
- On task completion/cancellation/error, call `releaseGlobal()`
- Throw descriptive error when limit hit: `"Background agent spawn blocked: ${current} agents running, max is ${max}. Wait for existing tasks to complete or increase background_task.maxBackgroundAgents."`

### Local Validation

```bash
bun run typecheck
bun test src/config/schema/background-task.test.ts
bun test src/features/background-agent/concurrency.test.ts
bun run build
```

---

## Phase 2: PR Creation

1. **Push branch:**
   ```bash
   git push -u origin feat/max-background-agents
   ```

2. **Create PR** targeting `dev`:
   ```bash
   gh pr create \
     --base dev \
     --title "feat: add max_background_agents config to limit concurrent background agents" \
     --body-file /tmp/pull-request-max-background-agents-$(date +%s).md
   ```

---

## Phase 3: Verify Loop

### Gate A: CI
- Wait for `ci.yml` workflow to complete
- Check: `gh pr checks <PR_NUMBER> --watch`
- If fails: read logs, fix, push, re-check

### Gate B: review-work (5 agents)
- Run `/review-work` skill which launches 5 parallel background sub-agents:
  1. Oracle — goal/constraint verification
  2. Oracle — code quality
  3. Oracle — security
  4. Hephaestus — hands-on QA execution
  5. Hephaestus — context mining from GitHub/git
- All 5 must pass. If any fails, fix and re-push.

### Gate C: Cubic (cubic-dev-ai[bot])
- Wait for Cubic bot review on PR
- Must say "No issues found"
- If issues found: address feedback, push, re-check

### Loop
```
while (!allGatesPass) {
  if (CI fails) → fix → push → continue
  if (review-work fails) → fix → push → continue
  if (Cubic has issues) → fix → push → continue
}
```

---

## Phase 4: Merge + Cleanup

1. **Squash merge:**
   ```bash
   gh pr merge <PR_NUMBER> --squash --delete-branch
   ```

2. **Remove worktree:**
   ```bash
   git worktree remove ../omo-wt/feat-max-background-agents
   ```

---

## File Impact Summary

| File | Change Type |
|------|-------------|
| `src/config/schema/background-task.ts` | Modified — add schema field |
| `src/config/schema/background-task.test.ts` | Modified — add validation tests |
| `src/features/background-agent/concurrency.ts` | Modified — add global limit tracking |
| `src/features/background-agent/concurrency.test.ts` | Modified — add global limit tests |
| `src/features/background-agent/manager.ts` | Modified — enforce global limit in launch/trackTask |

5 files changed across 2 atomic commits. No new files created (follows existing patterns).


================================================
FILE: .opencode/skills/work-with-pr-workspace/iteration-1/eval-1/with_skill/outputs/pr-description.md
================================================
# PR Description

**Title:** `feat: add max_background_agents config to limit concurrent background agents`

**Base:** `dev`

---

## Summary

- Add `maxBackgroundAgents` field to `BackgroundTaskConfigSchema` (default: 5, min: 1) to cap total simultaneous background agents across all models/providers
- Enforce the global limit in `BackgroundManager.launch()` and `trackTask()` with descriptive error messages when the limit is hit
- Release global slots on task completion, cancellation, error, and interrupt to prevent slot leaks

## Motivation

The existing concurrency system in `ConcurrencyManager` limits agents **per model/provider** (e.g., 5 concurrent `anthropic/claude-opus-4-6` tasks). However, there is no **global** cap across all models. A user running tasks across multiple providers could spawn an unbounded number of background agents, exhausting system resources.

`max_background_agents` provides a single knob to limit total concurrent background agents regardless of which model they use.

## Config Usage

```jsonc
// .opencode/oh-my-opencode.jsonc
{
  "background_task": {
    "maxBackgroundAgents": 10  // default: 5, min: 1
  }
}
```

## Changes

| File | What |
|------|------|
| `src/config/schema/background-task.ts` | Add `maxBackgroundAgents` schema field |
| `src/config/schema/background-task.test.ts` | Validation tests (valid, boundary, invalid) |
| `src/features/background-agent/concurrency.ts` | Global counter + `canSpawnGlobally()` / `acquireGlobal()` / `releaseGlobal()` |
| `src/features/background-agent/concurrency.test.ts` | Global limit unit tests |
| `src/features/background-agent/manager.ts` | Enforce global limit in `launch()`, `trackTask()`; release in completion/cancel/error paths |

## Testing

- `bun test src/config/schema/background-task.test.ts` — schema validation
- `bun test src/features/background-agent/concurrency.test.ts` — global limit enforcement
- `bun run typecheck` — clean
- `bun run build` — clean


================================================
FILE: .opencode/skills/work-with-pr-workspace/iteration-1/eval-1/with_skill/outputs/verification-strategy.md
================================================
# Verification Strategy

## Pre-Push Local Validation

Before every push, run all three checks sequentially:

```bash
bun run typecheck && bun test && bun run build
```

Specific test files to watch:
```bash
bun test src/config/schema/background-task.test.ts
bun test src/features/background-agent/concurrency.test.ts
```

---

## Gate A: CI (`ci.yml`)

### What CI runs
1. **Tests (split):** mock-heavy tests run in isolation (separate `bun test` processes), rest in batch
2. **Typecheck:** `bun run typecheck` (tsc --noEmit)
3. **Build:** `bun run build` (ESM + declarations + schema)
4. **Schema auto-commit:** if generated schema changed, CI commits it

### How to monitor
```bash
gh pr checks <PR_NUMBER> --watch
```

### Common failure scenarios and fixes

| Failure | Likely Cause | Fix |
|---------|-------------|-----|
| Typecheck error | New field not matching existing type imports | Verify `BackgroundTaskConfig` type is auto-inferred from schema, no manual type updates needed |
| Test failure | Test assertion wrong or missing import | Fix test, re-push |
| Build failure | Import cycle or missing export | Check barrel exports in `src/config/schema.ts` (already re-exports via `export *`) |
| Schema auto-commit | Generated JSON schema changed | Pull the auto-commit, rebase if needed |

### Recovery
```bash
# Read CI logs
gh run view <RUN_ID> --log-failed

# Fix, commit, push
git add -A && git commit -m "fix: address CI failure" && git push
```

---

## Gate B: review-work (5 parallel agents)

### What it checks
Run `/review-work` which launches 5 background sub-agents:

| Agent | Role | What it checks for this PR |
|-------|------|---------------------------|
| Oracle (goal) | Goal/constraint verification | Does `maxBackgroundAgents` actually limit agents? Is default 5? Is min 1? |
| Oracle (quality) | Code quality | Follows existing patterns? No catch-all files? Under 200 LOC? given/when/then tests? |
| Oracle (security) | Security review | No injection vectors, no unsafe defaults, proper input validation via Zod |
| Hephaestus (QA) | Hands-on QA execution | Actually runs tests, checks typecheck, verifies build |
| Hephaestus (context) | Context mining | Checks git history, related issues, ensures no duplicate/conflicting PRs |

### Pass criteria
All 5 agents must pass. Any single failure blocks.

### Common failure scenarios and fixes

| Agent | Likely Issue | Fix |
|-------|-------------|-----|
| Oracle (goal) | Global limit not enforced in all exit paths (completion, cancel, error, interrupt) | Audit every status transition in `manager.ts` that should call `releaseGlobal()` |
| Oracle (quality) | Test style not matching given/when/then | Restructure tests with `#given`/`#when`/`#then` describe nesting |
| Oracle (quality) | File exceeds 200 LOC | `concurrency.ts` is 137 LOC + ~25 new = ~162 LOC, safe. `manager.ts` is already large but we're adding ~20 lines to existing methods, not creating new responsibility |
| Oracle (security) | Integer overflow or negative values | Zod `.int().min(1)` handles this at config parse time |
| Hephaestus (QA) | Test actually fails when run | Run tests locally first, fix before push |

### Recovery
```bash
# Review agent output
background_output(task_id="<review-work-task-id>")

# Fix identified issues
# ... edit files ...
git add -A && git commit -m "fix: address review-work feedback" && git push
```

---

## Gate C: Cubic (`cubic-dev-ai[bot]`)

### What it checks
Cubic is an automated code review bot that analyzes the PR diff. It must respond with "No issues found" for the gate to pass.

### Common failure scenarios and fixes

| Issue | Likely Cause | Fix |
|-------|-------------|-----|
| "Missing error handling" | `releaseGlobal()` not called in some error path | Add `releaseGlobal()` to the missed path |
| "Inconsistent naming" | Field name doesn't match convention | Use `maxBackgroundAgents` (camelCase in schema, `max_background_agents` in JSONC config) |
| "Missing documentation" | No JSDoc on new public methods | Add JSDoc comments to `canSpawnGlobally()`, `acquireGlobal()`, `releaseGlobal()`, `getMaxBackgroundAgents()` |
| "Test coverage gap" | Missing edge case test | Add the specific test case Cubic identifies |

### Recovery
```bash
# Read Cubic's review
gh api repos/code-yeongyu/oh-my-openagent/pulls/<PR_NUMBER>/reviews

# Address each comment
# ... edit files ...
git add -A && git commit -m "fix: address Cubic review feedback" && git push
```

---

## Verification Loop Pseudocode

```
iteration = 0
while true:
  iteration++
  log("Verification iteration ${iteration}")

  # Gate A: CI (cheapest, check first)
  push_and_wait_for_ci()
  if ci_failed:
    read_ci_logs()
    fix_and_commit()
    continue

  # Gate B: review-work (5 agents, more expensive)
  run_review_work()
  if any_agent_failed:
    read_agent_feedback()
    fix_and_commit()
    continue

  # Gate C: Cubic (external bot, wait for it)
  wait_for_cubic_review()
  if cubic_has_issues:
    read_cubic_comments()
    fix_and_commit()
    continue

  # All gates passed
  break

# Merge
gh pr merge <PR_NUMBER> --squash --delete-branch
```

No iteration cap. Loop continues until all three gates pass simultaneously in a single iteration.

---

## Risk Assessment

| Risk | Probability | Mitigation |
|------|------------|------------|
| Slot leak (global count never decremented) | Medium | Audit every exit path: `tryCompleteTask`, `cancelTask`, `handleEvent(session.error)`, `startTask` prompt error, `resume` prompt error |
| Race condition on global count | Low | `globalRunningCount` is synchronous (single-threaded JS), no async gap between check and increment in `launch()` |
| Breaking existing behavior | Low | Default is 5, same as existing per-model default. Users with <5 total agents see no change |
| `manager.ts` exceeding 200 LOC | Already exceeded | File is already ~1500 LOC (exempt due to being a core orchestration class with many methods). Our changes add ~20 lines to existing methods, not a new responsibility |


================================================
FILE: .opencode/skills/work-with-pr-workspace/iteration-1/eval-1/with_skill/timing.json
================================================
{"total_tokens": null, "duration_ms": 292000, "total_duration_seconds": 292}

================================================
FILE: .opencode/skills/work-with-pr-workspace/iteration-1/eval-1/without_skill/grading.json
================================================
{
  "run_id": "eval-1-without_skill",
  "expectations": [
    {"text": "Plan uses git worktr
Download .txt
gitextract_lpvc9c4x/

├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.yml
│   │   ├── config.yml
│   │   ├── feature_request.yml
│   │   └── general.yml
│   ├── pull_request_template.md
│   └── workflows/
│       ├── ci.yml
│       ├── cla.yml
│       ├── lint-workflows.yml
│       ├── publish-platform.yml
│       ├── publish.yml
│       └── sisyphus-agent.yml
├── .gitignore
├── .opencode/
│   ├── background-tasks.json
│   ├── command/
│   │   ├── get-unpublished-changes.md
│   │   ├── omomomo.md
│   │   ├── publish.md
│   │   └── remove-deadcode.md
│   └── skills/
│       ├── github-triage/
│       │   ├── SKILL.md
│       │   └── scripts/
│       │       └── gh_fetch.py
│       ├── pre-publish-review/
│       │   └── SKILL.md
│       ├── work-with-pr/
│       │   └── SKILL.md
│       └── work-with-pr-workspace/
│           ├── evals/
│           │   └── evals.json
│           └── iteration-1/
│               ├── benchmark.json
│               ├── benchmark.md
│               ├── eval-1/
│               │   ├── eval_metadata.json
│               │   ├── with_skill/
│               │   │   ├── grading.json
│               │   │   ├── outputs/
│               │   │   │   ├── code-changes.md
│               │   │   │   ├── execution-plan.md
│               │   │   │   ├── pr-description.md
│               │   │   │   └── verification-strategy.md
│               │   │   └── timing.json
│               │   └── without_skill/
│               │       ├── grading.json
│               │       ├── outputs/
│               │       │   ├── code-changes.md
│               │       │   ├── execution-plan.md
│               │       │   ├── pr-description.md
│               │       │   └── verification-strategy.md
│               │       └── timing.json
│               ├── eval-2/
│               │   ├── eval_metadata.json
│               │   ├── with_skill/
│               │   │   ├── grading.json
│               │   │   ├── outputs/
│               │   │   │   ├── code-changes.md
│               │   │   │   ├── execution-plan.md
│               │   │   │   ├── pr-description.md
│               │   │   │   └── verification-strategy.md
│               │   │   └── timing.json
│               │   └── without_skill/
│               │       ├── grading.json
│               │       ├── outputs/
│               │       │   ├── code-changes.md
│               │       │   ├── execution-plan.md
│               │       │   ├── pr-description.md
│               │       │   └── verification-strategy.md
│               │       └── timing.json
│               ├── eval-3/
│               │   ├── eval_metadata.json
│               │   ├── with_skill/
│               │   │   ├── grading.json
│               │   │   ├── outputs/
│               │   │   │   ├── code-changes.md
│               │   │   │   ├── execution-plan.md
│               │   │   │   ├── pr-description.md
│               │   │   │   └── verification-strategy.md
│               │   │   └── timing.json
│               │   └── without_skill/
│               │       ├── grading.json
│               │       ├── outputs/
│               │       │   ├── code-changes.md
│               │       │   ├── execution-plan.md
│               │       │   ├── pr-description.md
│               │       │   └── verification-strategy.md
│               │       └── timing.json
│               ├── eval-4/
│               │   ├── eval_metadata.json
│               │   ├── with_skill/
│               │   │   ├── grading.json
│               │   │   ├── outputs/
│               │   │   │   ├── code-changes.md
│               │   │   │   ├── execution-plan.md
│               │   │   │   ├── pr-description.md
│               │   │   │   └── verification-strategy.md
│               │   │   └── timing.json
│               │   └── without_skill/
│               │       ├── grading.json
│               │       ├── outputs/
│               │       │   ├── code-changes.md
│               │       │   ├── execution-plan.md
│               │       │   ├── pr-description.md
│               │       │   └── verification-strategy.md
│               │       └── timing.json
│               ├── eval-5/
│               │   ├── eval_metadata.json
│               │   ├── with_skill/
│               │   │   ├── grading.json
│               │   │   ├── outputs/
│               │   │   │   ├── code-changes.md
│               │   │   │   ├── execution-plan.md
│               │   │   │   ├── pr-description.md
│               │   │   │   └── verification-strategy.md
│               │   │   └── timing.json
│               │   └── without_skill/
│               │       ├── grading.json
│               │       ├── outputs/
│               │       │   ├── code-changes.md
│               │       │   ├── execution-plan.md
│               │       │   ├── pr-description.md
│               │       │   └── verification-strategy.md
│               │       └── timing.json
│               └── review.html
├── AGENTS.md
├── CLA.md
├── CONTRIBUTING.md
├── FIX-BLOCKS.md
├── LICENSE.md
├── README.ja.md
├── README.ko.md
├── README.md
├── README.ru.md
├── README.zh-cn.md
├── assets/
│   └── oh-my-opencode.schema.json
├── bin/
│   ├── oh-my-opencode.js
│   ├── platform.d.ts
│   ├── platform.js
│   └── platform.test.ts
├── bun-test.d.ts
├── bunfig.toml
├── docs/
│   ├── guide/
│   │   ├── agent-model-matching.md
│   │   ├── installation.md
│   │   ├── orchestration.md
│   │   └── overview.md
│   ├── manifesto.md
│   ├── reference/
│   │   ├── cli.md
│   │   ├── configuration.md
│   │   └── features.md
│   └── troubleshooting/
│       └── ollama.md
├── package.json
├── packages/
│   ├── darwin-arm64/
│   │   ├── bin/
│   │   │   └── .gitkeep
│   │   └── package.json
│   ├── darwin-x64/
│   │   ├── bin/
│   │   │   └── .gitkeep
│   │   └── package.json
│   ├── darwin-x64-baseline/
│   │   └── package.json
│   ├── linux-arm64/
│   │   ├── bin/
│   │   │   └── .gitkeep
│   │   └── package.json
│   ├── linux-arm64-musl/
│   │   ├── bin/
│   │   │   └── .gitkeep
│   │   └── package.json
│   ├── linux-x64/
│   │   ├── bin/
│   │   │   └── .gitkeep
│   │   └── package.json
│   ├── linux-x64-baseline/
│   │   └── package.json
│   ├── linux-x64-musl/
│   │   ├── bin/
│   │   │   └── .gitkeep
│   │   └── package.json
│   ├── linux-x64-musl-baseline/
│   │   └── package.json
│   ├── windows-x64/
│   │   ├── bin/
│   │   │   └── .gitkeep
│   │   └── package.json
│   └── windows-x64-baseline/
│       └── package.json
├── postinstall.mjs
├── script/
│   ├── build-binaries.test.ts
│   ├── build-binaries.ts
│   ├── build-schema-document.ts
│   ├── build-schema.test.ts
│   ├── build-schema.ts
│   ├── generate-changelog.ts
│   └── publish.ts
├── signatures/
│   └── cla.json
├── src/
│   ├── AGENTS.md
│   ├── agents/
│   │   ├── AGENTS.md
│   │   ├── agent-builder.ts
│   │   ├── anti-duplication.test.ts
│   │   ├── atlas/
│   │   │   ├── agent.ts
│   │   │   ├── atlas-prompt.test.ts
│   │   │   ├── default.ts
│   │   │   ├── gemini.ts
│   │   │   ├── gpt.ts
│   │   │   ├── index.ts
│   │   │   ├── prompt-checkbox-enforcement.test.ts
│   │   │   └── prompt-section-builder.ts
│   │   ├── builtin-agents/
│   │   │   ├── agent-overrides.ts
│   │   │   ├── atlas-agent.ts
│   │   │   ├── available-skills.ts
│   │   │   ├── environment-context.ts
│   │   │   ├── general-agents.ts
│   │   │   ├── hephaestus-agent.ts
│   │   │   ├── model-resolution.ts
│   │   │   ├── resolve-file-uri.test.ts
│   │   │   ├── resolve-file-uri.ts
│   │   │   └── sisyphus-agent.ts
│   │   ├── builtin-agents.ts
│   │   ├── custom-agent-summaries.ts
│   │   ├── delegation-trust-prompt.test.ts
│   │   ├── dynamic-agent-prompt-builder.test.ts
│   │   ├── dynamic-agent-prompt-builder.ts
│   │   ├── env-context.test.ts
│   │   ├── env-context.ts
│   │   ├── explore.ts
│   │   ├── hephaestus/
│   │   │   ├── agent.test.ts
│   │   │   ├── agent.ts
│   │   │   ├── gpt-5-3-codex.ts
│   │   │   ├── gpt-5-4.ts
│   │   │   ├── gpt.ts
│   │   │   └── index.ts
│   │   ├── index.ts
│   │   ├── librarian.ts
│   │   ├── metis.ts
│   │   ├── momus.test.ts
│   │   ├── momus.ts
│   │   ├── multimodal-looker.ts
│   │   ├── oracle.ts
│   │   ├── prometheus/
│   │   │   ├── behavioral-summary.ts
│   │   │   ├── gemini.ts
│   │   │   ├── gpt.ts
│   │   │   ├── high-accuracy-mode.ts
│   │   │   ├── identity-constraints.ts
│   │   │   ├── index.ts
│   │   │   ├── interview-mode.ts
│   │   │   ├── plan-generation.ts
│   │   │   ├── plan-template.ts
│   │   │   └── system-prompt.ts
│   │   ├── prometheus-prompt.test.ts
│   │   ├── sisyphus/
│   │   │   ├── default.ts
│   │   │   ├── gemini.ts
│   │   │   ├── gpt-5-4.ts
│   │   │   └── index.ts
│   │   ├── sisyphus-junior/
│   │   │   ├── agent.ts
│   │   │   ├── default.ts
│   │   │   ├── gemini.ts
│   │   │   ├── gpt-5-3-codex.ts
│   │   │   ├── gpt-5-4.ts
│   │   │   ├── gpt.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── sisyphus.ts
│   │   ├── tool-restrictions.test.ts
│   │   ├── types.test.ts
│   │   ├── types.ts
│   │   └── utils.test.ts
│   ├── cli/
│   │   ├── AGENTS.md
│   │   ├── __snapshots__/
│   │   │   └── model-fallback.test.ts.snap
│   │   ├── cli-installer.test.ts
│   │   ├── cli-installer.ts
│   │   ├── cli-program.ts
│   │   ├── config-manager/
│   │   │   ├── AGENTS.md
│   │   │   ├── add-plugin-to-opencode-config.ts
│   │   │   ├── bun-install.test.ts
│   │   │   ├── bun-install.ts
│   │   │   ├── config-context.ts
│   │   │   ├── deep-merge-record.ts
│   │   │   ├── detect-current-config.ts
│   │   │   ├── ensure-config-directory-exists.ts
│   │   │   ├── format-error-with-suggestion.ts
│   │   │   ├── generate-omo-config.ts
│   │   │   ├── npm-dist-tags.ts
│   │   │   ├── opencode-binary.ts
│   │   │   ├── opencode-config-format.ts
│   │   │   ├── parse-opencode-config-file.ts
│   │   │   ├── plugin-detection.test.ts
│   │   │   ├── plugin-name-with-version.ts
│   │   │   ├── write-omo-config.test.ts
│   │   │   └── write-omo-config.ts
│   │   ├── config-manager.test.ts
│   │   ├── config-manager.ts
│   │   ├── doctor/
│   │   │   ├── checks/
│   │   │   │   ├── config.test.ts
│   │   │   │   ├── config.ts
│   │   │   │   ├── dependencies.test.ts
│   │   │   │   ├── dependencies.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── model-resolution-cache.ts
│   │   │   │   ├── model-resolution-config.ts
│   │   │   │   ├── model-resolution-details.ts
│   │   │   │   ├── model-resolution-effective-model.ts
│   │   │   │   ├── model-resolution-types.ts
│   │   │   │   ├── model-resolution-variant.ts
│   │   │   │   ├── model-resolution.test.ts
│   │   │   │   ├── model-resolution.ts
│   │   │   │   ├── system-binary.ts
│   │   │   │   ├── system-loaded-version.test.ts
│   │   │   │   ├── system-loaded-version.ts
│   │   │   │   ├── system-plugin.ts
│   │   │   │   ├── system.test.ts
│   │   │   │   ├── system.ts
│   │   │   │   ├── tools-gh.ts
│   │   │   │   ├── tools-lsp.ts
│   │   │   │   ├── tools-mcp.ts
│   │   │   │   └── tools.ts
│   │   │   ├── constants.ts
│   │   │   ├── format-default.test.ts
│   │   │   ├── format-default.ts
│   │   │   ├── format-shared.ts
│   │   │   ├── format-status.ts
│   │   │   ├── format-verbose.ts
│   │   │   ├── formatter.test.ts
│   │   │   ├── formatter.ts
│   │   │   ├── index.ts
│   │   │   ├── runner.test.ts
│   │   │   ├── runner.ts
│   │   │   └── types.ts
│   │   ├── fallback-chain-resolution.ts
│   │   ├── get-local-version/
│   │   │   ├── formatter.ts
│   │   │   ├── get-local-version.ts
│   │   │   ├── index.ts
│   │   │   └── types.ts
│   │   ├── index.test.ts
│   │   ├── index.ts
│   │   ├── install-validators.test.ts
│   │   ├── install-validators.ts
│   │   ├── install.test.ts
│   │   ├── install.ts
│   │   ├── mcp-oauth/
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   ├── login.test.ts
│   │   │   ├── login.ts
│   │   │   ├── logout.test.ts
│   │   │   ├── logout.ts
│   │   │   ├── status.test.ts
│   │   │   └── status.ts
│   │   ├── model-fallback-requirements.test.ts
│   │   ├── model-fallback-requirements.ts
│   │   ├── model-fallback-types.ts
│   │   ├── model-fallback.test.ts
│   │   ├── model-fallback.ts
│   │   ├── openai-only-model-catalog.test.ts
│   │   ├── openai-only-model-catalog.ts
│   │   ├── provider-availability.ts
│   │   ├── provider-model-id-transform.test.ts
│   │   ├── provider-model-id-transform.ts
│   │   ├── run/
│   │   │   ├── AGENTS.md
│   │   │   ├── agent-profile-colors.ts
│   │   │   ├── agent-resolver.ts
│   │   │   ├── completion-continuation.test.ts
│   │   │   ├── completion-verbose-logging.test.ts
│   │   │   ├── completion.test.ts
│   │   │   ├── completion.ts
│   │   │   ├── continuation-state-marker.test.ts
│   │   │   ├── continuation-state.ts
│   │   │   ├── display-chars.ts
│   │   │   ├── event-formatting.ts
│   │   │   ├── event-handlers.test.ts
│   │   │   ├── event-handlers.ts
│   │   │   ├── event-state.ts
│   │   │   ├── event-stream-processor.ts
│   │   │   ├── events.test.ts
│   │   │   ├── events.ts
│   │   │   ├── index.ts
│   │   │   ├── integration.test.ts
│   │   │   ├── json-output.test.ts
│   │   │   ├── json-output.ts
│   │   │   ├── message-part-delta.test.ts
│   │   │   ├── model-resolver.test.ts
│   │   │   ├── model-resolver.ts
│   │   │   ├── on-complete-hook.test.ts
│   │   │   ├── on-complete-hook.ts
│   │   │   ├── opencode-binary-resolver.test.ts
│   │   │   ├── opencode-binary-resolver.ts
│   │   │   ├── output-renderer.ts
│   │   │   ├── poll-for-completion.test.ts
│   │   │   ├── poll-for-completion.ts
│   │   │   ├── runner.test.ts
│   │   │   ├── runner.ts
│   │   │   ├── server-connection.test.ts
│   │   │   ├── server-connection.ts
│   │   │   ├── session-resolver.test.ts
│   │   │   ├── session-resolver.ts
│   │   │   ├── stdin-suppression.test.ts
│   │   │   ├── stdin-suppression.ts
│   │   │   ├── timestamp-output.test.ts
│   │   │   ├── timestamp-output.ts
│   │   │   ├── tool-input-preview.ts
│   │   │   └── types.ts
│   │   ├── tui-install-prompts.ts
│   │   ├── tui-installer.ts
│   │   └── types.ts
│   ├── config/
│   │   ├── AGENTS.md
│   │   ├── index.ts
│   │   ├── schema/
│   │   │   ├── agent-names.ts
│   │   │   ├── agent-overrides.ts
│   │   │   ├── babysitting.ts
│   │   │   ├── background-task-circuit-breaker.test.ts
│   │   │   ├── background-task.test.ts
│   │   │   ├── background-task.ts
│   │   │   ├── browser-automation.ts
│   │   │   ├── categories.ts
│   │   │   ├── claude-code.ts
│   │   │   ├── commands.ts
│   │   │   ├── comment-checker.ts
│   │   │   ├── dynamic-context-pruning.ts
│   │   │   ├── experimental.ts
│   │   │   ├── fallback-models.ts
│   │   │   ├── git-env-prefix.ts
│   │   │   ├── git-master.ts
│   │   │   ├── hooks.ts
│   │   │   ├── internal/
│   │   │   │   └── permission.ts
│   │   │   ├── notification.ts
│   │   │   ├── oh-my-opencode-config.ts
│   │   │   ├── openclaw.ts
│   │   │   ├── ralph-loop.ts
│   │   │   ├── runtime-fallback.ts
│   │   │   ├── sisyphus-agent.ts
│   │   │   ├── sisyphus.ts
│   │   │   ├── skills.ts
│   │   │   ├── start-work.ts
│   │   │   ├── tmux.ts
│   │   │   └── websearch.ts
│   │   ├── schema.test.ts
│   │   └── schema.ts
│   ├── create-hooks.ts
│   ├── create-managers.ts
│   ├── create-tools.ts
│   ├── features/
│   │   ├── AGENTS.md
│   │   ├── background-agent/
│   │   │   ├── AGENTS.md
│   │   │   ├── background-task-notification-template.ts
│   │   │   ├── cancel-task-cleanup.test.ts
│   │   │   ├── compaction-aware-message-resolver.test.ts
│   │   │   ├── compaction-aware-message-resolver.ts
│   │   │   ├── concurrency.test.ts
│   │   │   ├── concurrency.ts
│   │   │   ├── constants.ts
│   │   │   ├── default-message-staleness-timeout.test.ts
│   │   │   ├── default-stale-timeout.test.ts
│   │   │   ├── duration-formatter.ts
│   │   │   ├── error-classifier.test.ts
│   │   │   ├── error-classifier.ts
│   │   │   ├── fallback-retry-handler.test.ts
│   │   │   ├── fallback-retry-handler.ts
│   │   │   ├── index.ts
│   │   │   ├── loop-detector.test.ts
│   │   │   ├── loop-detector.ts
│   │   │   ├── manager-circuit-breaker.test.ts
│   │   │   ├── manager-session-permission.test.ts
│   │   │   ├── manager-shutdown-global-cleanup.test.ts
│   │   │   ├── manager.polling.test.ts
│   │   │   ├── manager.test.ts
│   │   │   ├── manager.ts
│   │   │   ├── opencode-client.ts
│   │   │   ├── process-cleanup.test.ts
│   │   │   ├── process-cleanup.ts
│   │   │   ├── remove-task-toast-tracking.ts
│   │   │   ├── session-idle-event-handler.test.ts
│   │   │   ├── session-idle-event-handler.ts
│   │   │   ├── session-status-classifier.test.ts
│   │   │   ├── session-status-classifier.ts
│   │   │   ├── spawner/
│   │   │   │   ├── parent-directory-resolver.test.ts
│   │   │   │   └── parent-directory-resolver.ts
│   │   │   ├── spawner.test.ts
│   │   │   ├── spawner.ts
│   │   │   ├── state.ts
│   │   │   ├── subagent-spawn-limits.test.ts
│   │   │   ├── subagent-spawn-limits.ts
│   │   │   ├── task-completion-cleanup.test.ts
│   │   │   ├── task-history-cleanup.test.ts
│   │   │   ├── task-history.test.ts
│   │   │   ├── task-history.ts
│   │   │   ├── task-poller.test.ts
│   │   │   ├── task-poller.ts
│   │   │   └── types.ts
│   │   ├── boulder-state/
│   │   │   ├── constants.ts
│   │   │   ├── index.ts
│   │   │   ├── storage.test.ts
│   │   │   ├── storage.ts
│   │   │   ├── top-level-task.test.ts
│   │   │   ├── top-level-task.ts
│   │   │   └── types.ts
│   │   ├── builtin-commands/
│   │   │   ├── commands.test.ts
│   │   │   ├── commands.ts
│   │   │   ├── index.ts
│   │   │   ├── templates/
│   │   │   │   ├── handoff.ts
│   │   │   │   ├── init-deep.ts
│   │   │   │   ├── ralph-loop.ts
│   │   │   │   ├── refactor.ts
│   │   │   │   ├── start-work.ts
│   │   │   │   ├── stop-continuation.test.ts
│   │   │   │   └── stop-continuation.ts
│   │   │   └── types.ts
│   │   ├── builtin-skills/
│   │   │   ├── agent-browser/
│   │   │   │   └── SKILL.md
│   │   │   ├── dev-browser/
│   │   │   │   ├── SKILL.md
│   │   │   │   └── references/
│   │   │   │       ├── installation.md
│   │   │   │       └── scraping.md
│   │   │   ├── frontend-ui-ux/
│   │   │   │   └── SKILL.md
│   │   │   ├── git-master/
│   │   │   │   └── SKILL.md
│   │   │   ├── index.ts
│   │   │   ├── skills/
│   │   │   │   ├── dev-browser.ts
│   │   │   │   ├── frontend-ui-ux.ts
│   │   │   │   ├── git-master-skill-metadata.ts
│   │   │   │   ├── git-master.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── playwright-cli.ts
│   │   │   │   └── playwright.ts
│   │   │   ├── skills.test.ts
│   │   │   ├── skills.ts
│   │   │   └── types.ts
│   │   ├── claude-code-agent-loader/
│   │   │   ├── claude-model-mapper.test.ts
│   │   │   ├── claude-model-mapper.ts
│   │   │   ├── index.ts
│   │   │   ├── loader.ts
│   │   │   └── types.ts
│   │   ├── claude-code-command-loader/
│   │   │   ├── index.ts
│   │   │   ├── loader.ts
│   │   │   └── types.ts
│   │   ├── claude-code-mcp-loader/
│   │   │   ├── env-expander.ts
│   │   │   ├── index.ts
│   │   │   ├── loader.test.ts
│   │   │   ├── loader.ts
│   │   │   ├── transformer.ts
│   │   │   └── types.ts
│   │   ├── claude-code-plugin-loader/
│   │   │   ├── agent-loader.ts
│   │   │   ├── command-loader.ts
│   │   │   ├── discovery.ts
│   │   │   ├── hook-loader.ts
│   │   │   ├── index.ts
│   │   │   ├── loader.ts
│   │   │   ├── mcp-server-loader.ts
│   │   │   ├── plugin-path-resolver.ts
│   │   │   ├── skill-loader.ts
│   │   │   └── types.ts
│   │   ├── claude-code-session-state/
│   │   │   ├── index.ts
│   │   │   ├── state.test.ts
│   │   │   └── state.ts
│   │   ├── claude-tasks/
│   │   │   ├── AGENTS.md
│   │   │   ├── session-storage.test.ts
│   │   │   ├── session-storage.ts
│   │   │   ├── storage.test.ts
│   │   │   ├── storage.ts
│   │   │   ├── types.test.ts
│   │   │   └── types.ts
│   │   ├── context-injector/
│   │   │   ├── collector.test.ts
│   │   │   ├── collector.ts
│   │   │   ├── index.ts
│   │   │   ├── injector.test.ts
│   │   │   ├── injector.ts
│   │   │   └── types.ts
│   │   ├── hook-message-injector/
│   │   │   ├── constants.ts
│   │   │   ├── index.ts
│   │   │   ├── injector.test.ts
│   │   │   ├── injector.ts
│   │   │   └── types.ts
│   │   ├── mcp-oauth/
│   │   │   ├── AGENTS.md
│   │   │   ├── callback-server.test.ts
│   │   │   ├── callback-server.ts
│   │   │   ├── dcr.test.ts
│   │   │   ├── dcr.ts
│   │   │   ├── discovery.test.ts
│   │   │   ├── discovery.ts
│   │   │   ├── oauth-authorization-flow.ts
│   │   │   ├── provider.test.ts
│   │   │   ├── provider.ts
│   │   │   ├── resource-indicator.test.ts
│   │   │   ├── resource-indicator.ts
│   │   │   ├── schema.test.ts
│   │   │   ├── schema.ts
│   │   │   ├── step-up.test.ts
│   │   │   ├── step-up.ts
│   │   │   ├── storage.test.ts
│   │   │   └── storage.ts
│   │   ├── opencode-skill-loader/
│   │   │   ├── AGENTS.md
│   │   │   ├── agents-skills-global.test.ts
│   │   │   ├── allowed-tools-parser.ts
│   │   │   ├── async-loader.test.ts
│   │   │   ├── async-loader.ts
│   │   │   ├── blocking.test.ts
│   │   │   ├── blocking.ts
│   │   │   ├── config-source-discovery.test.ts
│   │   │   ├── config-source-discovery.ts
│   │   │   ├── discover-worker.ts
│   │   │   ├── git-master-template-injection.test.ts
│   │   │   ├── git-master-template-injection.ts
│   │   │   ├── index.ts
│   │   │   ├── loaded-skill-from-path.ts
│   │   │   ├── loaded-skill-template-extractor.ts
│   │   │   ├── loader.test.ts
│   │   │   ├── loader.ts
│   │   │   ├── merger/
│   │   │   │   ├── builtin-skill-converter.ts
│   │   │   │   ├── config-skill-entry-loader.ts
│   │   │   │   ├── scope-priority.ts
│   │   │   │   ├── skill-definition-merger.ts
│   │   │   │   └── skills-config-normalizer.ts
│   │   │   ├── merger.test.ts
│   │   │   ├── merger.ts
│   │   │   ├── project-skill-tool-references.test.ts
│   │   │   ├── skill-content.test.ts
│   │   │   ├── skill-content.ts
│   │   │   ├── skill-deduplication.ts
│   │   │   ├── skill-definition-record.ts
│   │   │   ├── skill-directory-loader.ts
│   │   │   ├── skill-discovery.ts
│   │   │   ├── skill-mcp-config.ts
│   │   │   ├── skill-resolution-options.ts
│   │   │   ├── skill-template-resolver.ts
│   │   │   └── types.ts
│   │   ├── run-continuation-state/
│   │   │   ├── constants.ts
│   │   │   ├── index.ts
│   │   │   ├── storage.test.ts
│   │   │   ├── storage.ts
│   │   │   └── types.ts
│   │   ├── skill-mcp-manager/
│   │   │   ├── cleanup.ts
│   │   │   ├── connection-race.test.ts
│   │   │   ├── connection-type.ts
│   │   │   ├── connection.ts
│   │   │   ├── disconnect-cleanup.test.ts
│   │   │   ├── env-cleaner.test.ts
│   │   │   ├── env-cleaner.ts
│   │   │   ├── http-client.ts
│   │   │   ├── index.ts
│   │   │   ├── manager.test.ts
│   │   │   ├── manager.ts
│   │   │   ├── oauth-handler.ts
│   │   │   ├── stdio-client.ts
│   │   │   └── types.ts
│   │   ├── task-toast-manager/
│   │   │   ├── index.ts
│   │   │   ├── manager.test.ts
│   │   │   ├── manager.ts
│   │   │   └── types.ts
│   │   ├── tmux-subagent/
│   │   │   ├── AGENTS.md
│   │   │   ├── action-executor-core.ts
│   │   │   ├── action-executor.test.ts
│   │   │   ├── action-executor.ts
│   │   │   ├── cleanup.ts
│   │   │   ├── decision-engine.test.ts
│   │   │   ├── decision-engine.ts
│   │   │   ├── event-handlers.ts
│   │   │   ├── grid-planning.ts
│   │   │   ├── index.ts
│   │   │   ├── layout-config.test.ts
│   │   │   ├── manager.test.ts
│   │   │   ├── manager.ts
│   │   │   ├── oldest-agent-pane.ts
│   │   │   ├── pane-split-availability.ts
│   │   │   ├── pane-state-parser.test.ts
│   │   │   ├── pane-state-parser.ts
│   │   │   ├── pane-state-querier.test.ts
│   │   │   ├── pane-state-querier.ts
│   │   │   ├── polling-constants.ts
│   │   │   ├── polling-manager.test.ts
│   │   │   ├── polling-manager.ts
│   │   │   ├── polling.ts
│   │   │   ├── session-created-event.ts
│   │   │   ├── session-created-handler.ts
│   │   │   ├── session-deleted-handler.ts
│   │   │   ├── session-message-count.ts
│   │   │   ├── session-ready-waiter.ts
│   │   │   ├── session-status-parser.ts
│   │   │   ├── spawn-action-decider.ts
│   │   │   ├── spawn-target-finder.ts
│   │   │   ├── tmux-grid-constants.ts
│   │   │   ├── tracked-session-state.ts
│   │   │   ├── types.ts
│   │   │   └── zombie-pane.test.ts
│   │   └── tool-metadata-store/
│   │       ├── index.test.ts
│   │       ├── index.ts
│   │       └── store.ts
│   ├── hooks/
│   │   ├── AGENTS.md
│   │   ├── agent-usage-reminder/
│   │   │   ├── constants.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.ts
│   │   │   ├── storage.ts
│   │   │   └── types.ts
│   │   ├── anthropic-context-window-limit-recovery/
│   │   │   ├── AGENTS.md
│   │   │   ├── aggressive-truncation-strategy.ts
│   │   │   ├── client.ts
│   │   │   ├── deduplication-recovery.ts
│   │   │   ├── empty-content-recovery-sdk.test.ts
│   │   │   ├── empty-content-recovery-sdk.ts
│   │   │   ├── empty-content-recovery.ts
│   │   │   ├── executor.test.ts
│   │   │   ├── executor.ts
│   │   │   ├── index.ts
│   │   │   ├── message-builder.ts
│   │   │   ├── message-storage-directory.ts
│   │   │   ├── parser.test.ts
│   │   │   ├── parser.ts
│   │   │   ├── pruning-deduplication.test.ts
│   │   │   ├── pruning-deduplication.ts
│   │   │   ├── pruning-tool-output-truncation.ts
│   │   │   ├── pruning-types.ts
│   │   │   ├── recovery-deduplication.test.ts
│   │   │   ├── recovery-hook.test.ts
│   │   │   ├── recovery-hook.ts
│   │   │   ├── recovery-strategy.ts
│   │   │   ├── state.ts
│   │   │   ├── storage-paths.ts
│   │   │   ├── storage.test.ts
│   │   │   ├── storage.ts
│   │   │   ├── summarize-retry-strategy.test.ts
│   │   │   ├── summarize-retry-strategy.ts
│   │   │   ├── target-token-truncation.ts
│   │   │   ├── tool-part-types.ts
│   │   │   ├── tool-result-storage-sdk.ts
│   │   │   ├── tool-result-storage.ts
│   │   │   └── types.ts
│   │   ├── anthropic-effort/
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── atlas/
│   │   │   ├── AGENTS.md
│   │   │   ├── atlas-hook.ts
│   │   │   ├── boulder-continuation-injector.ts
│   │   │   ├── boulder-session-lineage.ts
│   │   │   ├── compaction-agent-filter.test.ts
│   │   │   ├── event-handler.ts
│   │   │   ├── final-wave-approval-gate-regression.test.ts
│   │   │   ├── final-wave-approval-gate.test.ts
│   │   │   ├── final-wave-approval-gate.ts
│   │   │   ├── final-wave-plan-state.ts
│   │   │   ├── hook-name.ts
│   │   │   ├── idle-event-lineage.test.ts
│   │   │   ├── idle-event.ts
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   ├── is-abort-error.ts
│   │   │   ├── recent-model-resolver.ts
│   │   │   ├── resolve-active-boulder-session.ts
│   │   │   ├── session-last-agent.sqlite.test.ts
│   │   │   ├── session-last-agent.ts
│   │   │   ├── sisyphus-path.ts
│   │   │   ├── subagent-session-id.test.ts
│   │   │   ├── subagent-session-id.ts
│   │   │   ├── system-reminder-templates.test.ts
│   │   │   ├── system-reminder-templates.ts
│   │   │   ├── tool-execute-after.ts
│   │   │   ├── tool-execute-before.ts
│   │   │   ├── tsconfig.json
│   │   │   ├── types.ts
│   │   │   ├── verification-reminders.test.ts
│   │   │   ├── verification-reminders.ts
│   │   │   └── write-edit-tool-policy.ts
│   │   ├── auto-slash-command/
│   │   │   ├── auto-slash-command-leak.test.ts
│   │   │   ├── constants.test.ts
│   │   │   ├── constants.ts
│   │   │   ├── detector.test.ts
│   │   │   ├── detector.ts
│   │   │   ├── executor-resolution.test.ts
│   │   │   ├── executor.test.ts
│   │   │   ├── executor.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   ├── processed-command-store.ts
│   │   │   └── types.ts
│   │   ├── auto-update-checker/
│   │   │   ├── cache.test.ts
│   │   │   ├── cache.ts
│   │   │   ├── checker/
│   │   │   │   ├── cached-version.ts
│   │   │   │   ├── check-for-update.ts
│   │   │   │   ├── config-paths.ts
│   │   │   │   ├── jsonc-strip.ts
│   │   │   │   ├── latest-version.ts
│   │   │   │   ├── local-dev-path.ts
│   │   │   │   ├── local-dev-version.ts
│   │   │   │   ├── package-json-locator.ts
│   │   │   │   ├── pinned-version-updater.test.ts
│   │   │   │   ├── pinned-version-updater.ts
│   │   │   │   ├── plugin-entry.test.ts
│   │   │   │   ├── plugin-entry.ts
│   │   │   │   ├── sync-package-json.test.ts
│   │   │   │   └── sync-package-json.ts
│   │   │   ├── checker.test.ts
│   │   │   ├── checker.ts
│   │   │   ├── constants.test.ts
│   │   │   ├── constants.ts
│   │   │   ├── hook/
│   │   │   │   ├── background-update-check.test.ts
│   │   │   │   ├── background-update-check.ts
│   │   │   │   ├── config-errors-toast.ts
│   │   │   │   ├── connected-providers-status.ts
│   │   │   │   ├── model-cache-warning.ts
│   │   │   │   ├── spinner-toast.ts
│   │   │   │   ├── startup-toasts.ts
│   │   │   │   ├── update-toasts.ts
│   │   │   │   └── workspace-resolution.test.ts
│   │   │   ├── hook.test.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   ├── types.ts
│   │   │   └── version-channel.ts
│   │   ├── background-notification/
│   │   │   ├── hook.ts
│   │   │   ├── index.ts
│   │   │   └── types.ts
│   │   ├── category-skill-reminder/
│   │   │   ├── formatter.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── claude-code-hooks/
│   │   │   ├── AGENTS.md
│   │   │   ├── claude-code-hooks-hook.ts
│   │   │   ├── config-loader.ts
│   │   │   ├── config.ts
│   │   │   ├── dispatch-hook.ts
│   │   │   ├── execute-http-hook.test.ts
│   │   │   ├── execute-http-hook.ts
│   │   │   ├── handlers/
│   │   │   │   ├── chat-message-handler.ts
│   │   │   │   ├── pre-compact-handler.ts
│   │   │   │   ├── session-event-handler.ts
│   │   │   │   ├── tool-execute-after-handler.test.ts
│   │   │   │   ├── tool-execute-after-handler.ts
│   │   │   │   └── tool-execute-before-handler.ts
│   │   │   ├── index.ts
│   │   │   ├── plugin-config.ts
│   │   │   ├── post-tool-use.ts
│   │   │   ├── pre-compact.ts
│   │   │   ├── pre-tool-use.ts
│   │   │   ├── session-hook-state.ts
│   │   │   ├── stop.test.ts
│   │   │   ├── stop.ts
│   │   │   ├── todo.ts
│   │   │   ├── tool-input-cache.ts
│   │   │   ├── transcript.test.ts
│   │   │   ├── transcript.ts
│   │   │   ├── types.ts
│   │   │   ├── user-prompt-submit.test.ts
│   │   │   └── user-prompt-submit.ts
│   │   ├── comment-checker/
│   │   │   ├── cli-runner.ts
│   │   │   ├── cli.test.ts
│   │   │   ├── cli.ts
│   │   │   ├── downloader.ts
│   │   │   ├── hook.apply-patch.test.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.ts
│   │   │   ├── pending-calls.test.ts
│   │   │   ├── pending-calls.ts
│   │   │   └── types.ts
│   │   ├── compaction-context-injector/
│   │   │   ├── compaction-context-prompt.ts
│   │   │   ├── constants.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   ├── recovery-prompt-config.ts
│   │   │   ├── recovery.test.ts
│   │   │   ├── recovery.ts
│   │   │   ├── session-id.ts
│   │   │   ├── session-prompt-config-resolver.test.ts
│   │   │   ├── session-prompt-config-resolver.ts
│   │   │   ├── tail-monitor.ts
│   │   │   ├── types.ts
│   │   │   └── validated-model.ts
│   │   ├── compaction-todo-preserver/
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── context-window-monitor.model-context-limits.test.ts
│   │   ├── context-window-monitor.test.ts
│   │   ├── context-window-monitor.ts
│   │   ├── delegate-task-retry/
│   │   │   ├── guidance.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   └── patterns.ts
│   │   ├── directory-agents-injector/
│   │   │   ├── constants.ts
│   │   │   ├── finder.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.ts
│   │   │   ├── injector.test.ts
│   │   │   ├── injector.ts
│   │   │   └── storage.ts
│   │   ├── directory-readme-injector/
│   │   │   ├── constants.ts
│   │   │   ├── finder.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.ts
│   │   │   ├── injector.test.ts
│   │   │   ├── injector.ts
│   │   │   └── storage.ts
│   │   ├── edit-error-recovery/
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── empty-task-response-detector.ts
│   │   ├── hashline-edit-diff-enhancer/
│   │   │   └── hook.ts
│   │   ├── hashline-read-enhancer/
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── index.ts
│   │   ├── interactive-bash-session/
│   │   │   ├── constants.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.ts
│   │   │   ├── interactive-bash-session-tracker.ts
│   │   │   ├── parser.ts
│   │   │   ├── state-manager.ts
│   │   │   ├── storage.ts
│   │   │   ├── tmux-command-parser.ts
│   │   │   └── types.ts
│   │   ├── json-error-recovery/
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── keyword-detector/
│   │   │   ├── AGENTS.md
│   │   │   ├── analyze/
│   │   │   │   ├── default.ts
│   │   │   │   └── index.ts
│   │   │   ├── constants.ts
│   │   │   ├── detector.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   ├── search/
│   │   │   │   ├── default.ts
│   │   │   │   └── index.ts
│   │   │   ├── types.ts
│   │   │   ├── ultrawork/
│   │   │   │   ├── default.ts
│   │   │   │   ├── gemini.ts
│   │   │   │   ├── gpt.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── planner.ts
│   │   │   │   └── source-detector.ts
│   │   │   └── ultrawork-runtime-variant.test.ts
│   │   ├── model-fallback/
│   │   │   ├── hook.test.ts
│   │   │   └── hook.ts
│   │   ├── no-hephaestus-non-gpt/
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── no-sisyphus-gpt/
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── non-interactive-env/
│   │   │   ├── constants.ts
│   │   │   ├── detector.ts
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   ├── non-interactive-env-hook.ts
│   │   │   └── types.ts
│   │   ├── openclaw.test.ts
│   │   ├── openclaw.ts
│   │   ├── preemptive-compaction.aws-bedrock.test.ts
│   │   ├── preemptive-compaction.context-limit-cache.test.ts
│   │   ├── preemptive-compaction.test.ts
│   │   ├── preemptive-compaction.ts
│   │   ├── prometheus-md-only/
│   │   │   ├── agent-matcher.ts
│   │   │   ├── agent-resolution.ts
│   │   │   ├── constants.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   └── path-policy.ts
│   │   ├── question-label-truncator/
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── ralph-loop/
│   │   │   ├── AGENTS.md
│   │   │   ├── command-arguments.ts
│   │   │   ├── completion-handler.ts
│   │   │   ├── completion-promise-detector.test.ts
│   │   │   ├── completion-promise-detector.ts
│   │   │   ├── constants.ts
│   │   │   ├── continuation-prompt-builder.ts
│   │   │   ├── continuation-prompt-injector.ts
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   ├── iteration-continuation.ts
│   │   │   ├── loop-session-recovery.ts
│   │   │   ├── loop-state-controller.ts
│   │   │   ├── message-storage-directory.ts
│   │   │   ├── pending-verification-handler.ts
│   │   │   ├── ralph-loop-event-handler.ts
│   │   │   ├── ralph-loop-hook.ts
│   │   │   ├── reset-strategy-race-condition.test.ts
│   │   │   ├── session-event-handler.ts
│   │   │   ├── session-reset-strategy.ts
│   │   │   ├── storage.ts
│   │   │   ├── types.ts
│   │   │   ├── ulw-loop-verification.test.ts
│   │   │   ├── verification-failure-handler.ts
│   │   │   └── with-timeout.ts
│   │   ├── read-image-resizer/
│   │   │   ├── hook.test.ts
│   │   │   ├── hook.ts
│   │   │   ├── image-dimensions.test.ts
│   │   │   ├── image-dimensions.ts
│   │   │   ├── image-resizer.test.ts
│   │   │   ├── image-resizer.ts
│   │   │   ├── index.ts
│   │   │   └── types.ts
│   │   ├── rules-injector/
│   │   │   ├── AGENTS.md
│   │   │   ├── cache.ts
│   │   │   ├── constants.ts
│   │   │   ├── finder.test.ts
│   │   │   ├── finder.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.ts
│   │   │   ├── injector.test.ts
│   │   │   ├── injector.ts
│   │   │   ├── matcher.ts
│   │   │   ├── output-path.test.ts
│   │   │   ├── output-path.ts
│   │   │   ├── parser.test.ts
│   │   │   ├── parser.ts
│   │   │   ├── project-root-finder.ts
│   │   │   ├── rule-distance.ts
│   │   │   ├── rule-file-finder.ts
│   │   │   ├── rule-file-scanner.ts
│   │   │   ├── storage.ts
│   │   │   └── types.ts
│   │   ├── runtime-fallback/
│   │   │   ├── agent-resolver.ts
│   │   │   ├── auto-retry.ts
│   │   │   ├── chat-message-handler.ts
│   │   │   ├── constants.ts
│   │   │   ├── dispose.test.ts
│   │   │   ├── error-classifier.test.ts
│   │   │   ├── error-classifier.ts
│   │   │   ├── event-handler.test.ts
│   │   │   ├── event-handler.ts
│   │   │   ├── fallback-bootstrap-model.ts
│   │   │   ├── fallback-models.test.ts
│   │   │   ├── fallback-models.ts
│   │   │   ├── fallback-retry-dispatcher.ts
│   │   │   ├── fallback-state.ts
│   │   │   ├── hook-dispose-cleanup.test.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   ├── last-user-retry-parts.ts
│   │   │   ├── message-update-handler.test.ts
│   │   │   ├── message-update-handler.ts
│   │   │   ├── retry-model-payload.ts
│   │   │   ├── session-messages.ts
│   │   │   ├── session-status-handler.test.ts
│   │   │   ├── session-status-handler.ts
│   │   │   ├── success-retry-key-cleanup.test.ts
│   │   │   ├── types.ts
│   │   │   └── visible-assistant-response.ts
│   │   ├── session-notification-content.test.ts
│   │   ├── session-notification-content.ts
│   │   ├── session-notification-formatting.ts
│   │   ├── session-notification-input-needed.test.ts
│   │   ├── session-notification-scheduler.ts
│   │   ├── session-notification-sender.test.ts
│   │   ├── session-notification-sender.ts
│   │   ├── session-notification-utils.ts
│   │   ├── session-notification.test.ts
│   │   ├── session-notification.ts
│   │   ├── session-recovery/
│   │   │   ├── AGENTS.md
│   │   │   ├── constants.ts
│   │   │   ├── detect-error-type.test.ts
│   │   │   ├── detect-error-type.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   ├── recover-empty-content-message-sdk.test.ts
│   │   │   ├── recover-empty-content-message-sdk.ts
│   │   │   ├── recover-thinking-block-order.ts
│   │   │   ├── recover-thinking-disabled-violation.ts
│   │   │   ├── recover-tool-result-missing.ts
│   │   │   ├── recover-unavailable-tool.ts
│   │   │   ├── resume.test.ts
│   │   │   ├── resume.ts
│   │   │   ├── storage/
│   │   │   │   ├── empty-messages.ts
│   │   │   │   ├── empty-text.ts
│   │   │   │   ├── message-dir.ts
│   │   │   │   ├── messages-reader.ts
│   │   │   │   ├── orphan-thinking-search.ts
│   │   │   │   ├── part-content.ts
│   │   │   │   ├── part-id.ts
│   │   │   │   ├── parts-reader.ts
│   │   │   │   ├── readers-from-sdk.test.ts
│   │   │   │   ├── text-part-injector.ts
│   │   │   │   ├── thinking-block-search.ts
│   │   │   │   ├── thinking-prepend.ts
│   │   │   │   └── thinking-strip.ts
│   │   │   ├── storage.ts
│   │   │   └── types.ts
│   │   ├── session-todo-status.ts
│   │   ├── shared/
│   │   │   └── compaction-model-resolver.ts
│   │   ├── sisyphus-junior-notepad/
│   │   │   ├── constants.ts
│   │   │   ├── hook.ts
│   │   │   └── index.ts
│   │   ├── start-work/
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   ├── parse-user-request.test.ts
│   │   │   ├── parse-user-request.ts
│   │   │   ├── start-work-hook.ts
│   │   │   ├── worktree-detector.test.ts
│   │   │   └── worktree-detector.ts
│   │   ├── stop-continuation-guard/
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── task-reminder/
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── task-resume-info/
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── tasks-todowrite-disabler/
│   │   │   ├── constants.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── think-mode/
│   │   │   ├── detector.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   ├── switcher.test.ts
│   │   │   ├── switcher.ts
│   │   │   └── types.ts
│   │   ├── thinking-block-validator/
│   │   │   ├── hook.ts
│   │   │   └── index.ts
│   │   ├── todo-continuation-enforcer/
│   │   │   ├── AGENTS.md
│   │   │   ├── abort-detection.ts
│   │   │   ├── compaction-guard.ts
│   │   │   ├── constants.ts
│   │   │   ├── continuation-injection.test.ts
│   │   │   ├── continuation-injection.ts
│   │   │   ├── countdown.ts
│   │   │   ├── dispose.test.ts
│   │   │   ├── handler.ts
│   │   │   ├── idle-event.ts
│   │   │   ├── index.ts
│   │   │   ├── message-directory.ts
│   │   │   ├── non-idle-events.ts
│   │   │   ├── pending-question-detection.test.ts
│   │   │   ├── pending-question-detection.ts
│   │   │   ├── resolve-message-info.ts
│   │   │   ├── session-state.regression.test.ts
│   │   │   ├── session-state.test.ts
│   │   │   ├── session-state.ts
│   │   │   ├── stagnation-detection.test.ts
│   │   │   ├── stagnation-detection.ts
│   │   │   ├── todo-continuation-enforcer.test.ts
│   │   │   ├── todo.ts
│   │   │   └── types.ts
│   │   ├── todo-description-override/
│   │   │   ├── description.ts
│   │   │   ├── hook.ts
│   │   │   ├── index.test.ts
│   │   │   └── index.ts
│   │   ├── tool-output-truncator.test.ts
│   │   ├── tool-output-truncator.ts
│   │   ├── unstable-agent-babysitter/
│   │   │   ├── index.test.ts
│   │   │   ├── index.ts
│   │   │   ├── task-message-analyzer.ts
│   │   │   └── unstable-agent-babysitter-hook.ts
│   │   └── write-existing-file-guard/
│   │       ├── hook.ts
│   │       ├── index.test.ts
│   │       └── index.ts
│   ├── index.compaction-model-agnostic.static.test.ts
│   ├── index.test.ts
│   ├── index.ts
│   ├── mcp/
│   │   ├── AGENTS.md
│   │   ├── context7.ts
│   │   ├── grep-app.ts
│   │   ├── index.test.ts
│   │   ├── index.ts
│   │   ├── types.ts
│   │   ├── websearch.test.ts
│   │   └── websearch.ts
│   ├── openclaw/
│   │   ├── __tests__/
│   │   │   ├── config.test.ts
│   │   │   ├── dispatcher.test.ts
│   │   │   └── tmux.test.ts
│   │   ├── config.ts
│   │   ├── daemon.ts
│   │   ├── dispatcher.ts
│   │   ├── index.ts
│   │   ├── reply-listener.ts
│   │   ├── session-registry.ts
│   │   ├── tmux.ts
│   │   └── types.ts
│   ├── plugin/
│   │   ├── AGENTS.md
│   │   ├── available-categories.ts
│   │   ├── chat-headers.test.ts
│   │   ├── chat-headers.ts
│   │   ├── chat-message.test.ts
│   │   ├── chat-message.ts
│   │   ├── chat-params.test.ts
│   │   ├── chat-params.ts
│   │   ├── event-compaction-agent.test.ts
│   │   ├── event.model-fallback.test.ts
│   │   ├── event.test.ts
│   │   ├── event.ts
│   │   ├── hooks/
│   │   │   ├── create-continuation-hooks.ts
│   │   │   ├── create-core-hooks.ts
│   │   │   ├── create-session-hooks.test.ts
│   │   │   ├── create-session-hooks.ts
│   │   │   ├── create-skill-hooks.ts
│   │   │   ├── create-tool-guard-hooks.ts
│   │   │   └── create-transform-hooks.ts
│   │   ├── messages-transform.ts
│   │   ├── normalize-tool-arg-schemas.test.ts
│   │   ├── normalize-tool-arg-schemas.ts
│   │   ├── recent-synthetic-idles.test.ts
│   │   ├── recent-synthetic-idles.ts
│   │   ├── session-agent-resolver.test.ts
│   │   ├── session-agent-resolver.ts
│   │   ├── session-status-normalizer.test.ts
│   │   ├── session-status-normalizer.ts
│   │   ├── skill-context.test.ts
│   │   ├── skill-context.ts
│   │   ├── system-transform.ts
│   │   ├── tool-execute-after.test.ts
│   │   ├── tool-execute-after.ts
│   │   ├── tool-execute-before-session-notification.test.ts
│   │   ├── tool-execute-before.test.ts
│   │   ├── tool-execute-before.ts
│   │   ├── tool-execute-before.ulw-loop.test.ts
│   │   ├── tool-registry.ts
│   │   ├── types.ts
│   │   ├── ultrawork-db-model-override.test.ts
│   │   ├── ultrawork-db-model-override.ts
│   │   ├── ultrawork-model-override.test.ts
│   │   ├── ultrawork-model-override.ts
│   │   ├── ultrawork-variant-availability.test.ts
│   │   ├── ultrawork-variant-availability.ts
│   │   └── unstable-agent-babysitter.ts
│   ├── plugin-config.test.ts
│   ├── plugin-config.ts
│   ├── plugin-dispose.test.ts
│   ├── plugin-dispose.ts
│   ├── plugin-handlers/
│   │   ├── AGENTS.md
│   │   ├── agent-config-handler.test.ts
│   │   ├── agent-config-handler.ts
│   │   ├── agent-key-remapper.test.ts
│   │   ├── agent-key-remapper.ts
│   │   ├── agent-override-protection.ts
│   │   ├── agent-priority-order.ts
│   │   ├── category-config-resolver.ts
│   │   ├── command-config-handler.ts
│   │   ├── config-handler-formatter.test.ts
│   │   ├── config-handler.test.ts
│   │   ├── config-handler.ts
│   │   ├── index.ts
│   │   ├── mcp-config-handler.test.ts
│   │   ├── mcp-config-handler.ts
│   │   ├── plan-model-inheritance.test.ts
│   │   ├── plan-model-inheritance.ts
│   │   ├── plugin-components-loader.ts
│   │   ├── prometheus-agent-config-builder.ts
│   │   ├── provider-config-handler.test.ts
│   │   ├── provider-config-handler.ts
│   │   ├── tool-config-handler.test.ts
│   │   └── tool-config-handler.ts
│   ├── plugin-interface.ts
│   ├── plugin-state.ts
│   ├── shared/
│   │   ├── AGENTS.md
│   │   ├── agent-config-integration.test.ts
│   │   ├── agent-display-names.test.ts
│   │   ├── agent-display-names.ts
│   │   ├── agent-tool-restrictions.ts
│   │   ├── agent-variant.test.ts
│   │   ├── agent-variant.ts
│   │   ├── binary-downloader.ts
│   │   ├── claude-config-dir.test.ts
│   │   ├── claude-config-dir.ts
│   │   ├── command-executor/
│   │   │   ├── embedded-commands.ts
│   │   │   ├── execute-command.ts
│   │   │   ├── execute-hook-command.ts
│   │   │   ├── home-directory.ts
│   │   │   ├── resolve-commands-in-text.ts
│   │   │   └── shell-path.ts
│   │   ├── command-executor.ts
│   │   ├── compaction-agent-config-checkpoint.ts
│   │   ├── config-errors.ts
│   │   ├── connected-providers-cache.test.ts
│   │   ├── connected-providers-cache.ts
│   │   ├── context-limit-resolver.test.ts
│   │   ├── context-limit-resolver.ts
│   │   ├── data-path.ts
│   │   ├── deep-merge.test.ts
│   │   ├── deep-merge.ts
│   │   ├── disabled-tools.ts
│   │   ├── dynamic-truncator.test.ts
│   │   ├── dynamic-truncator.ts
│   │   ├── external-plugin-detector.test.ts
│   │   ├── external-plugin-detector.ts
│   │   ├── fallback-chain-from-models.test.ts
│   │   ├── fallback-chain-from-models.ts
│   │   ├── fallback-model-availability.ts
│   │   ├── file-reference-resolver.ts
│   │   ├── file-utils.test.ts
│   │   ├── file-utils.ts
│   │   ├── first-message-variant.test.ts
│   │   ├── first-message-variant.ts
│   │   ├── frontmatter.test.ts
│   │   ├── frontmatter.ts
│   │   ├── git-worktree/
│   │   │   ├── collect-git-diff-stats.test.ts
│   │   │   ├── collect-git-diff-stats.ts
│   │   │   ├── format-file-changes.ts
│   │   │   ├── git-worktree.test.ts
│   │   │   ├── index.ts
│   │   │   ├── parse-diff-numstat.ts
│   │   │   ├── parse-status-porcelain-line.test.ts
│   │   │   ├── parse-status-porcelain-line.ts
│   │   │   ├── parse-status-porcelain.ts
│   │   │   └── types.ts
│   │   ├── hook-disabled.ts
│   │   ├── index.ts
│   │   ├── internal-initiator-marker.ts
│   │   ├── jsonc-parser.test.ts
│   │   ├── jsonc-parser.ts
│   │   ├── logger.ts
│   │   ├── merge-categories.test.ts
│   │   ├── merge-categories.ts
│   │   ├── migration/
│   │   │   ├── agent-category.ts
│   │   │   ├── agent-names.ts
│   │   │   ├── config-migration.ts
│   │   │   ├── hook-names.ts
│   │   │   └── model-versions.ts
│   │   ├── migration.test.ts
│   │   ├── migration.ts
│   │   ├── model-availability.test.ts
│   │   ├── model-availability.ts
│   │   ├── model-error-classifier.test.ts
│   │   ├── model-error-classifier.ts
│   │   ├── model-format-normalizer.test.ts
│   │   ├── model-format-normalizer.ts
│   │   ├── model-normalization.test.ts
│   │   ├── model-normalization.ts
│   │   ├── model-requirements.test.ts
│   │   ├── model-requirements.ts
│   │   ├── model-resolution-pipeline.test.ts
│   │   ├── model-resolution-pipeline.ts
│   │   ├── model-resolution-types.ts
│   │   ├── model-resolver.test.ts
│   │   ├── model-resolver.ts
│   │   ├── model-sanitizer.ts
│   │   ├── model-suggestion-retry.test.ts
│   │   ├── model-suggestion-retry.ts
│   │   ├── normalize-sdk-response.test.ts
│   │   ├── normalize-sdk-response.ts
│   │   ├── opencode-command-dirs.test.ts
│   │   ├── opencode-command-dirs.ts
│   │   ├── opencode-config-dir-types.ts
│   │   ├── opencode-config-dir.test.ts
│   │   ├── opencode-config-dir.ts
│   │   ├── opencode-http-api.test.ts
│   │   ├── opencode-http-api.ts
│   │   ├── opencode-message-dir.test.ts
│   │   ├── opencode-message-dir.ts
│   │   ├── opencode-server-auth.test.ts
│   │   ├── opencode-server-auth.ts
│   │   ├── opencode-storage-detection.test.ts
│   │   ├── opencode-storage-detection.ts
│   │   ├── opencode-storage-paths.ts
│   │   ├── opencode-version.test.ts
│   │   ├── opencode-version.ts
│   │   ├── pattern-matcher.test.ts
│   │   ├── pattern-matcher.ts
│   │   ├── permission-compat.test.ts
│   │   ├── permission-compat.ts
│   │   ├── plugin-command-discovery.test.ts
│   │   ├── plugin-command-discovery.ts
│   │   ├── plugin-identity.test.ts
│   │   ├── plugin-identity.ts
│   │   ├── port-utils.test.ts
│   │   ├── port-utils.ts
│   │   ├── prompt-timeout-context.ts
│   │   ├── prompt-tools.test.ts
│   │   ├── prompt-tools.ts
│   │   ├── provider-model-id-transform.ts
│   │   ├── question-denied-session-permission.ts
│   │   ├── record-type-guard.ts
│   │   ├── retry-status-utils.ts
│   │   ├── safe-create-hook.test.ts
│   │   ├── safe-create-hook.ts
│   │   ├── session-category-registry.ts
│   │   ├── session-cursor.test.ts
│   │   ├── session-cursor.ts
│   │   ├── session-directory-resolver.test.ts
│   │   ├── session-directory-resolver.ts
│   │   ├── session-injected-paths.ts
│   │   ├── session-model-state.test.ts
│   │   ├── session-model-state.ts
│   │   ├── session-tools-store.test.ts
│   │   ├── session-tools-store.ts
│   │   ├── session-utils.ts
│   │   ├── shell-env.test.ts
│   │   ├── shell-env.ts
│   │   ├── skill-path-resolver.test.ts
│   │   ├── skill-path-resolver.ts
│   │   ├── snake-case.ts
│   │   ├── spawn-with-windows-hide.ts
│   │   ├── system-directive.test.ts
│   │   ├── system-directive.ts
│   │   ├── tmux/
│   │   │   ├── constants.ts
│   │   │   ├── index.ts
│   │   │   ├── tmux-utils/
│   │   │   │   ├── environment.ts
│   │   │   │   ├── layout.test.ts
│   │   │   │   ├── layout.ts
│   │   │   │   ├── pane-close.ts
│   │   │   │   ├── pane-dimensions.ts
│   │   │   │   ├── pane-replace.ts
│   │   │   │   ├── pane-spawn.test.ts
│   │   │   │   ├── pane-spawn.ts
│   │   │   │   └── server-health.ts
│   │   │   ├── tmux-utils.test.ts
│   │   │   ├── tmux-utils.ts
│   │   │   └── types.ts
│   │   ├── tool-name.test.ts
│   │   ├── tool-name.ts
│   │   ├── truncate-description.test.ts
│   │   ├── truncate-description.ts
│   │   ├── vision-capable-models-cache.ts
│   │   └── zip-extractor.ts
│   └── tools/
│       ├── AGENTS.md
│       ├── ast-grep/
│       │   ├── cli-binary-path-resolution.ts
│       │   ├── cli.ts
│       │   ├── constants.ts
│       │   ├── downloader.ts
│       │   ├── environment-check.ts
│       │   ├── index.ts
│       │   ├── language-support.ts
│       │   ├── process-output-timeout.ts
│       │   ├── result-formatter.ts
│       │   ├── sg-cli-path.ts
│       │   ├── sg-compact-json-output.ts
│       │   ├── tools.ts
│       │   └── types.ts
│       ├── background-task/
│       │   ├── AGENTS.md
│       │   ├── clients.ts
│       │   ├── constants.ts
│       │   ├── create-background-cancel.ts
│       │   ├── create-background-output.blocking.test.ts
│       │   ├── create-background-output.metadata.test.ts
│       │   ├── create-background-output.ts
│       │   ├── create-background-task.metadata.test.ts
│       │   ├── create-background-task.test.ts
│       │   ├── create-background-task.ts
│       │   ├── delay.ts
│       │   ├── full-session-format.ts
│       │   ├── index.ts
│       │   ├── message-dir.ts
│       │   ├── session-messages.ts
│       │   ├── task-result-format.ts
│       │   ├── task-status-format.ts
│       │   ├── time-format.ts
│       │   ├── tools.test.ts
│       │   ├── tools.ts
│       │   ├── truncate-text.ts
│       │   └── types.ts
│       ├── call-omo-agent/
│       │   ├── AGENTS.md
│       │   ├── background-agent-executor.test.ts
│       │   ├── background-agent-executor.ts
│       │   ├── background-executor.test.ts
│       │   ├── background-executor.ts
│       │   ├── completion-poller.ts
│       │   ├── constants.ts
│       │   ├── index.ts
│       │   ├── message-dir.ts
│       │   ├── message-processor.ts
│       │   ├── message-storage-directory.ts
│       │   ├── reused-sync-session-delete-cleanup.test.ts
│       │   ├── session-creator.test.ts
│       │   ├── session-creator.ts
│       │   ├── subagent-session-creator.test.ts
│       │   ├── subagent-session-creator.ts
│       │   ├── sync-executor-leak.test.ts
│       │   ├── sync-executor.test.ts
│       │   ├── sync-executor.ts
│       │   ├── tool-context-with-metadata.ts
│       │   ├── tools.test.ts
│       │   ├── tools.ts
│       │   └── types.ts
│       ├── delegate-task/
│       │   ├── AGENTS.md
│       │   ├── available-models.ts
│       │   ├── background-continuation.test.ts
│       │   ├── background-continuation.ts
│       │   ├── background-task.test.ts
│       │   ├── background-task.ts
│       │   ├── cancel-unstable-agent-task.ts
│       │   ├── categories.ts
│       │   ├── category-resolver.test.ts
│       │   ├── category-resolver.ts
│       │   ├── constants.ts
│       │   ├── error-formatting.ts
│       │   ├── executor-types.ts
│       │   ├── executor.ts
│       │   ├── index.ts
│       │   ├── metadata-await.test.ts
│       │   ├── metadata-model-unification.test.ts
│       │   ├── model-selection.test.ts
│       │   ├── model-selection.ts
│       │   ├── model-string-parser.ts
│       │   ├── parent-context-resolver.ts
│       │   ├── prompt-builder.ts
│       │   ├── sisyphus-junior-agent.ts
│       │   ├── skill-resolver.ts
│       │   ├── subagent-resolver.test.ts
│       │   ├── subagent-resolver.ts
│       │   ├── sync-continuation-deps.ts
│       │   ├── sync-continuation.test.ts
│       │   ├── sync-continuation.ts
│       │   ├── sync-poll-timeout.test.ts
│       │   ├── sync-prompt-sender.test.ts
│       │   ├── sync-prompt-sender.ts
│       │   ├── sync-result-fetcher.test.ts
│       │   ├── sync-result-fetcher.ts
│       │   ├── sync-session-creator.test.ts
│       │   ├── sync-session-creator.ts
│       │   ├── sync-session-poller.test.ts
│       │   ├── sync-session-poller.ts
│       │   ├── sync-task-deps.ts
│       │   ├── sync-task.test.ts
│       │   ├── sync-task.ts
│       │   ├── time-formatter.ts
│       │   ├── timing.test.ts
│       │   ├── timing.ts
│       │   ├── token-limiter.test.ts
│       │   ├── token-limiter.ts
│       │   ├── tools.test.ts
│       │   ├── tools.ts
│       │   ├── types.ts
│       │   ├── unstable-agent-cleanup.test.ts
│       │   ├── unstable-agent-permission.test.ts
│       │   ├── unstable-agent-task.test.ts
│       │   ├── unstable-agent-task.ts
│       │   └── unstable-agent-timeout.test.ts
│       ├── glob/
│       │   ├── cli.test.ts
│       │   ├── cli.ts
│       │   ├── constants.ts
│       │   ├── index.ts
│       │   ├── result-formatter.ts
│       │   ├── tools.ts
│       │   └── types.ts
│       ├── grep/
│       │   ├── cli.ts
│       │   ├── constants.ts
│       │   ├── downloader.test.ts
│       │   ├── downloader.ts
│       │   ├── index.ts
│       │   ├── result-formatter.test.ts
│       │   ├── result-formatter.ts
│       │   ├── tools.ts
│       │   └── types.ts
│       ├── hashline-edit/
│       │   ├── AGENTS.md
│       │   ├── autocorrect-replacement-lines.ts
│       │   ├── constants.ts
│       │   ├── diff-utils.test.ts
│       │   ├── diff-utils.ts
│       │   ├── edit-deduplication.ts
│       │   ├── edit-operation-primitives.ts
│       │   ├── edit-operations.test.ts
│       │   ├── edit-operations.ts
│       │   ├── edit-ordering.ts
│       │   ├── edit-text-normalization.ts
│       │   ├── file-text-canonicalization.ts
│       │   ├── hash-computation.test.ts
│       │   ├── hash-computation.ts
│       │   ├── hashline-chunk-formatter.ts
│       │   ├── hashline-edit-diff.ts
│       │   ├── hashline-edit-executor.ts
│       │   ├── index.ts
│       │   ├── normalize-edits.test.ts
│       │   ├── normalize-edits.ts
│       │   ├── tool-description.ts
│       │   ├── tools.test.ts
│       │   ├── tools.ts
│       │   ├── types.ts
│       │   ├── validation.test.ts
│       │   └── validation.ts
│       ├── index.ts
│       ├── interactive-bash/
│       │   ├── constants.ts
│       │   ├── index.ts
│       │   ├── tmux-path-resolver.ts
│       │   └── tools.ts
│       ├── look-at/
│       │   ├── assistant-message-extractor.ts
│       │   ├── constants.ts
│       │   ├── image-converter.test.ts
│       │   ├── image-converter.ts
│       │   ├── index.ts
│       │   ├── look-at-arguments.ts
│       │   ├── mime-type-inference.test.ts
│       │   ├── mime-type-inference.ts
│       │   ├── multimodal-agent-metadata.test.ts
│       │   ├── multimodal-agent-metadata.ts
│       │   ├── multimodal-fallback-chain.test.ts
│       │   ├── multimodal-fallback-chain.ts
│       │   ├── session-poller.test.ts
│       │   ├── session-poller.ts
│       │   ├── tools.test.ts
│       │   ├── tools.ts
│       │   └── types.ts
│       ├── lsp/
│       │   ├── AGENTS.md
│       │   ├── client.test.ts
│       │   ├── client.ts
│       │   ├── config.test.ts
│       │   ├── config.ts
│       │   ├── constants.ts
│       │   ├── diagnostics-tool.ts
│       │   ├── directory-diagnostics.test.ts
│       │   ├── directory-diagnostics.ts
│       │   ├── find-references-tool.ts
│       │   ├── goto-definition-tool.ts
│       │   ├── index.ts
│       │   ├── language-config.ts
│       │   ├── language-mappings.ts
│       │   ├── lsp-client-connection.ts
│       │   ├── lsp-client-transport.ts
│       │   ├── lsp-client-wrapper.ts
│       │   ├── lsp-client.ts
│       │   ├── lsp-formatters.ts
│       │   ├── lsp-manager-process-cleanup.ts
│       │   ├── lsp-manager-temp-directory-cleanup.ts
│       │   ├── lsp-process.test.ts
│       │   ├── lsp-process.ts
│       │   ├── lsp-server.ts
│       │   ├── rename-tools.ts
│       │   ├── server-config-loader.test.ts
│       │   ├── server-config-loader.ts
│       │   ├── server-definitions.ts
│       │   ├── server-installation.ts
│       │   ├── server-path-bases.ts
│       │   ├── server-resolution.ts
│       │   ├── symbols-tool.ts
│       │   ├── tools.ts
│       │   ├── types.ts
│       │   ├── utils.test.ts
│       │   └── workspace-edit.ts
│       ├── session-manager/
│       │   ├── constants.ts
│       │   ├── index.ts
│       │   ├── session-formatter.ts
│       │   ├── storage.test.ts
│       │   ├── storage.ts
│       │   ├── tools.test.ts
│       │   ├── tools.ts
│       │   ├── types.ts
│       │   └── utils.test.ts
│       ├── shared/
│       │   └── semaphore.ts
│       ├── skill/
│       │   ├── constants.ts
│       │   ├── index.ts
│       │   ├── tools.test.ts
│       │   ├── tools.ts
│       │   └── types.ts
│       ├── skill-mcp/
│       │   ├── builtin-mcp-hint.test.ts
│       │   ├── constants.ts
│       │   ├── index.ts
│       │   ├── tools.test.ts
│       │   ├── tools.ts
│       │   └── types.ts
│       ├── slashcommand/
│       │   ├── command-discovery.test.ts
│       │   ├── command-discovery.ts
│       │   ├── command-output-formatter.test.ts
│       │   ├── command-output-formatter.ts
│       │   ├── execution-compatibility.test.ts
│       │   ├── index.test.ts
│       │   ├── index.ts
│       │   └── types.ts
│       └── task/
│           ├── index.ts
│           ├── task-create.test.ts
│           ├── task-create.ts
│           ├── task-get.test.ts
│           ├── task-get.ts
│           ├── task-list.test.ts
│           ├── task-list.ts
│           ├── task-update.test.ts
│           ├── task-update.ts
│           ├── todo-sync.test.ts
│           ├── todo-sync.ts
│           ├── types.test.ts
│           └── types.ts
├── test-setup.ts
├── tests/
│   └── hashline/
│       ├── headless.ts
│       ├── package.json
│       ├── test-edge-cases.ts
│       ├── test-edit-ops.ts
│       └── test-multi-model.ts
├── tsconfig.json
└── uvscripts/
    └── gh_fetch.py
Download .txt
Showing preview only (452K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (4430 symbols across 1080 files)

FILE: .opencode/skills/github-triage/scripts/gh_fetch.py
  class ItemState (line 46) | class ItemState(str, Enum):
  class OutputFormat (line 52) | class OutputFormat(str, Enum):
  function run_gh_command (line 58) | async def run_gh_command(args: list[str]) -> tuple[str, str, int]:
  function get_current_repo (line 70) | async def get_current_repo() -> str:
  function fetch_items_page (line 81) | async def fetch_items_page(
  function fetch_all_items (line 116) | async def fetch_all_items(
  function display_table (line 186) | def display_table(items: list[dict], item_type: str) -> None:
  function issues (line 218) | def issues(
  function prs (line 270) | def prs(
  function fetch_all (line 322) | def fetch_all(

FILE: bin/oh-my-opencode.js
  function getLibcFamily (line 16) | function getLibcFamily() {
  function supportsAvx2 (line 30) | function supportsAvx2() {
  function getSignalExitCode (line 63) | function getSignalExitCode(signal) {
  function main (line 74) | function main() {

FILE: bin/platform.js
  function getPlatformPackage (line 10) | function getPlatformPackage({ platform, arch, libcFamily }) {
  function getPlatformPackageCandidates (line 30) | function getPlatformPackageCandidates({ platform, arch, libcFamily, pref...
  function getBaselinePlatformPackage (line 42) | function getBaselinePlatformPackage({ platform, arch, libcFamily }) {
  function getBinaryPath (line 79) | function getBinaryPath(pkg, platform) {

FILE: bun-test.d.ts
  type Matchers (line 10) | interface Matchers {

FILE: postinstall.mjs
  function getLibcFamily (line 12) | function getLibcFamily() {
  function main (line 25) | function main() {

FILE: script/build-binaries.test.ts
  constant EXPECTED_BASELINE_TARGETS (line 8) | const EXPECTED_BASELINE_TARGETS = [

FILE: script/build-binaries.ts
  type PlatformTarget (line 9) | interface PlatformTarget {
  constant PLATFORMS (line 16) | const PLATFORMS: PlatformTarget[] = [
  constant ENTRY_POINT (line 30) | const ENTRY_POINT = "src/cli/index.ts";
  function buildPlatform (line 32) | async function buildPlatform(platform: PlatformTarget): Promise<boolean> {
  function main (line 63) | async function main() {

FILE: script/build-schema-document.ts
  function createOhMyOpenCodeJsonSchema (line 4) | function createOhMyOpenCodeJsonSchema(): Record<string, unknown> {

FILE: script/build-schema.ts
  constant SCHEMA_OUTPUT_PATH (line 4) | const SCHEMA_OUTPUT_PATH = "assets/oh-my-opencode.schema.json"
  constant DIST_SCHEMA_OUTPUT_PATH (line 5) | const DIST_SCHEMA_OUTPUT_PATH = "dist/oh-my-opencode.schema.json"
  function main (line 7) | async function main() {

FILE: script/generate-changelog.ts
  constant TEAM (line 5) | const TEAM = ["actions-user", "github-actions[bot]", "code-yeongyu"]
  function getLatestReleasedTag (line 7) | async function getLatestReleasedTag(): Promise<string | null> {
  function generateChangelog (line 16) | async function generateChangelog(previousTag: string): Promise<string[]> {
  function getContributors (line 37) | async function getContributors(previousTag: string): Promise<string[]> {
  function main (line 73) | async function main() {

FILE: script/publish.ts
  constant PACKAGE_NAME (line 7) | const PACKAGE_NAME = "oh-my-opencode"
  constant PLATFORM_PACKAGES (line 13) | const PLATFORM_PACKAGES = [
  function fetchPreviousVersion (line 25) | async function fetchPreviousVersion(): Promise<string> {
  function bumpVersion (line 38) | function bumpVersion(version: string, type: "major" | "minor" | "patch")...
  function updatePackageVersion (line 52) | async function updatePackageVersion(pkgPath: string, newVersion: string)...
  function updateAllPackageVersions (line 59) | async function updateAllPackageVersions(newVersion: string): Promise<voi...
  function findPreviousTag (line 88) | async function findPreviousTag(currentVersion: string): Promise<string |...
  function generateChangelog (line 103) | async function generateChangelog(previous: string, currentVersion?: stri...
  function getContributors (line 137) | async function getContributors(previous: string): Promise<string[]> {
  function getDistTag (line 178) | function getDistTag(version: string): string | null {
  type PublishResult (line 185) | interface PublishResult {
  function checkPackageVersionExists (line 191) | async function checkPackageVersionExists(pkgName: string, version: strin...
  function publishPackage (line 200) | async function publishPackage(cwd: string, distTag: string | null, usePr...
  function publishAllPackages (line 249) | async function publishAllPackages(version: string): Promise<void> {
  function buildPackages (line 318) | async function buildPackages(): Promise<void> {
  function gitTagAndRelease (line 332) | async function gitTagAndRelease(newVersion: string, notes: string[]): Pr...
  function checkVersionExists (line 380) | async function checkVersionExists(version: string): Promise<boolean> {
  function main (line 389) | async function main() {

FILE: src/agents/agent-builder.ts
  type AgentSource (line 8) | type AgentSource = AgentFactory | AgentConfig
  function isFactory (line 10) | function isFactory(source: AgentSource): source is AgentFactory {
  function buildAgent (line 14) | function buildAgent(

FILE: src/agents/atlas/agent.ts
  constant MODE (line 32) | const MODE: AgentMode = "all"
  type AtlasPromptSource (line 34) | type AtlasPromptSource = "default" | "gpt" | "gemini"
  function getAtlasPromptSource (line 39) | function getAtlasPromptSource(model?: string): AtlasPromptSource {
  type OrchestratorContext (line 49) | interface OrchestratorContext {
  function getAtlasPrompt (line 59) | function getAtlasPrompt(model?: string): string {
  function buildDynamicOrchestratorPrompt (line 73) | function buildDynamicOrchestratorPrompt(ctx?: OrchestratorContext): stri...
  function createAtlasAgent (line 101) | function createAtlasAgent(ctx: OrchestratorContext): AgentConfig {

FILE: src/agents/atlas/default.ts
  constant ATLAS_SYSTEM_PROMPT (line 13) | const ATLAS_SYSTEM_PROMPT = `
  function getDefaultAtlasPrompt (line 452) | function getDefaultAtlasPrompt(): string {

FILE: src/agents/atlas/gemini.ts
  constant ATLAS_GEMINI_SYSTEM_PROMPT (line 13) | const ATLAS_GEMINI_SYSTEM_PROMPT = `
  function getGeminiAtlasPrompt (line 422) | function getGeminiAtlasPrompt(): string {

FILE: src/agents/atlas/gpt.ts
  constant ATLAS_GPT_SYSTEM_PROMPT (line 13) | const ATLAS_GPT_SYSTEM_PROMPT = `
  function getGptAtlasPrompt (line 425) | function getGptAtlasPrompt(): string {

FILE: src/agents/atlas/prompt-section-builder.ts
  function buildAgentSelectionSection (line 17) | function buildAgentSelectionSection(agents: AvailableAgent[]): string {
  function buildCategorySection (line 34) | function buildCategorySection(userCategories?: Record<string, CategoryCo...
  function buildSkillsSection (line 53) | function buildSkillsSection(skills: AvailableSkill[]): string {
  function buildDecisionMatrix (line 85) | function buildDecisionMatrix(agents: AvailableAgent[], userCategories?: ...

FILE: src/agents/builtin-agents.ts
  type AgentSource (line 31) | type AgentSource = AgentFactory | AgentConfig
  function createBuiltinAgents (line 62) | async function createBuiltinAgents(

FILE: src/agents/builtin-agents/agent-overrides.ts
  function applyCategoryOverride (line 13) | function applyCategoryOverride(
  function mergeAgentConfig (line 38) | function mergeAgentConfig(
  function applyOverrides (line 54) | function applyOverrides(

FILE: src/agents/builtin-agents/atlas-agent.ts
  function maybeCreateAtlasConfig (line 10) | function maybeCreateAtlasConfig(input: {

FILE: src/agents/builtin-agents/available-skills.ts
  function mapScopeToLocation (line 6) | function mapScopeToLocation(scope: SkillScope): AvailableSkill["location...
  function buildAvailableSkills (line 12) | function buildAvailableSkills(

FILE: src/agents/builtin-agents/environment-context.ts
  type ApplyEnvironmentContextOptions (line 4) | type ApplyEnvironmentContextOptions = {
  function applyEnvironmentContext (line 8) | function applyEnvironmentContext(

FILE: src/agents/builtin-agents/general-agents.ts
  function collectPendingBuiltinAgents (line 12) | function collectPendingBuiltinAgents(input: {

FILE: src/agents/builtin-agents/hephaestus-agent.ts
  function maybeCreateHephaestusConfig (line 11) | function maybeCreateHephaestusConfig(input: {

FILE: src/agents/builtin-agents/model-resolution.ts
  function applyModelResolution (line 4) | function applyModelResolution(input: {
  function getFirstFallbackModel (line 19) | function getFirstFallbackModel(requirement?: {

FILE: src/agents/builtin-agents/resolve-file-uri.ts
  function resolvePromptAppend (line 5) | function resolvePromptAppend(promptAppend: string, configDir?: string): ...

FILE: src/agents/builtin-agents/sisyphus-agent.ts
  function maybeCreateSisyphusConfig (line 11) | function maybeCreateSisyphusConfig(input: {

FILE: src/agents/custom-agent-summaries.ts
  type RegisteredAgentSummary (line 4) | type RegisteredAgentSummary = {
  function sanitizeMarkdownTableCell (line 9) | function sanitizeMarkdownTableCell(value: string): string {
  function isRecord (line 17) | function isRecord(value: unknown): value is Record<string, unknown> {
  function parseRegisteredAgentSummaries (line 21) | function parseRegisteredAgentSummaries(input: unknown): RegisteredAgentS...
  function buildCustomAgentMetadata (line 47) | function buildCustomAgentMetadata(agentName: string, description: string...

FILE: src/agents/dynamic-agent-prompt-builder.ts
  type AvailableAgent (line 3) | interface AvailableAgent {
  type AvailableTool (line 9) | interface AvailableTool {
  type AvailableSkill (line 14) | interface AvailableSkill {
  type AvailableCategory (line 20) | interface AvailableCategory {
  function categorizeTools (line 26) | function categorizeTools(toolNames: string[]): AvailableTool[] {
  function formatToolsForPrompt (line 44) | function formatToolsForPrompt(tools: AvailableTool[]): string {
  function buildKeyTriggersSection (line 66) | function buildKeyTriggersSection(agents: AvailableAgent[], _skills: Avai...
  function buildToolSelectionTable (line 79) | function buildToolSelectionTable(
  function buildExploreSection (line 110) | function buildExploreSection(agents: AvailableAgent[]): string {
  function buildLibrarianSection (line 130) | function buildLibrarianSection(agents: AvailableAgent[]): string {
  function buildDelegationTable (line 147) | function buildDelegationTable(agents: AvailableAgent[]): string {
  function buildCategorySkillsDelegationGuide (line 163) | function buildCategorySkillsDelegationGuide(categories: AvailableCategor...
  function buildOracleSection (line 282) | function buildOracleSection(agents: AvailableAgent[]): string {
  function buildHardBlocksSection (line 317) | function buildHardBlocksSection(): string {
  function buildAntiPatternsSection (line 332) | function buildAntiPatternsSection(): string {
  function buildToolCallFormatSection (line 349) | function buildToolCallFormatSection(): string {
  function buildNonClaudePlannerSection (line 366) | function buildNonClaudePlannerSection(model: string): string {
  function buildParallelDelegationSection (line 382) | function buildParallelDelegationSection(model: string, categories: Avail...
  function buildUltraworkSection (line 416) | function buildUltraworkSection(
  function buildAntiDuplicationSection (line 478) | function buildAntiDuplicationSection(): string {

FILE: src/agents/env-context.ts
  function createEnvContext (line 7) | function createEnvContext(): string {

FILE: src/agents/explore.ts
  constant MODE (line 5) | const MODE: AgentMode = "subagent"
  constant EXPLORE_PROMPT_METADATA (line 7) | const EXPLORE_PROMPT_METADATA: AgentPromptMetadata = {
  function createExploreAgent (line 27) | function createExploreAgent(model: string): AgentConfig {

FILE: src/agents/hephaestus/agent.ts
  constant MODE (line 16) | const MODE: AgentMode = "all";
  type HephaestusPromptSource (line 18) | type HephaestusPromptSource = "gpt-5-4" | "gpt-5-3-codex" | "gpt";
  function getHephaestusPromptSource (line 20) | function getHephaestusPromptSource(
  type HephaestusContext (line 32) | interface HephaestusContext {
  function getHephaestusPrompt (line 41) | function getHephaestusPrompt(
  function buildDynamicHephaestusPrompt (line 48) | function buildDynamicHephaestusPrompt(ctx?: HephaestusContext): string {
  function createHephaestusAgent (line 93) | function createHephaestusAgent(

FILE: src/agents/hephaestus/gpt-5-3-codex.ts
  constant MODE (line 24) | const MODE: AgentMode = "all";
  function buildTodoDisciplineSection (line 26) | function buildTodoDisciplineSection(useTaskSystem: boolean): string {
  function buildHephaestusPrompt (line 108) | function buildHephaestusPrompt(
  function createHephaestusAgent (line 507) | function createHephaestusAgent(

FILE: src/agents/hephaestus/gpt-5-4.ts
  function buildTodoDisciplineSection (line 22) | function buildTodoDisciplineSection(useTaskSystem: boolean): string {
  function buildHephaestusPrompt (line 68) | function buildHephaestusPrompt(

FILE: src/agents/hephaestus/gpt.ts
  function buildTodoDisciplineSection (line 22) | function buildTodoDisciplineSection(useTaskSystem: boolean): string {
  function buildHephaestusPrompt (line 64) | function buildHephaestusPrompt(

FILE: src/agents/librarian.ts
  constant MODE (line 5) | const MODE: AgentMode = "subagent"
  constant LIBRARIAN_PROMPT_METADATA (line 7) | const LIBRARIAN_PROMPT_METADATA: AgentPromptMetadata = {
  function createLibrarianAgent (line 24) | function createLibrarianAgent(model: string): AgentConfig {

FILE: src/agents/metis.ts
  constant MODE (line 6) | const MODE: AgentMode = "subagent"
  constant METIS_SYSTEM_PROMPT (line 22) | const METIS_SYSTEM_PROMPT = `# Metis - Pre-Planning Consultant
  function createMetisAgent (line 302) | function createMetisAgent(model: string): AgentConfig {

FILE: src/agents/momus.test.ts
  function escapeRegExp (line 4) | function escapeRegExp(value: string) {

FILE: src/agents/momus.ts
  constant MODE (line 6) | const MODE: AgentMode = "subagent";
  constant MOMUS_DEFAULT_PROMPT (line 25) | const MOMUS_DEFAULT_PROMPT = `You are a **practical** work plan reviewer...
  constant MOMUS_GPT_PROMPT (line 210) | const MOMUS_GPT_PROMPT = `<identity>
  function createMomusAgent (line 284) | function createMomusAgent(model: string): AgentConfig {

FILE: src/agents/multimodal-looker.ts
  constant MODE (line 5) | const MODE: AgentMode = "subagent"
  constant MULTIMODAL_LOOKER_PROMPT_METADATA (line 7) | const MULTIMODAL_LOOKER_PROMPT_METADATA: AgentPromptMetadata = {
  function createMultimodalLookerAgent (line 14) | function createMultimodalLookerAgent(model: string): AgentConfig {

FILE: src/agents/oracle.ts
  constant MODE (line 6) | const MODE: AgentMode = "subagent";
  constant ORACLE_PROMPT_METADATA (line 8) | const ORACLE_PROMPT_METADATA: AgentPromptMetadata = {
  constant ORACLE_DEFAULT_PROMPT (line 44) | const ORACLE_DEFAULT_PROMPT = `You are a strategic technical advisor wit...
  constant ORACLE_GPT_PROMPT (line 165) | const ORACLE_GPT_PROMPT = `You are a strategic technical advisor operati...
  function createOracleAgent (line 245) | function createOracleAgent(model: string): AgentConfig {

FILE: src/agents/prometheus/behavioral-summary.ts
  constant PROMETHEUS_BEHAVIORAL_SUMMARY (line 7) | const PROMETHEUS_BEHAVIORAL_SUMMARY = `## After Plan Completion: Cleanup...

FILE: src/agents/prometheus/gemini.ts
  constant PROMETHEUS_GEMINI_SYSTEM_PROMPT (line 14) | const PROMETHEUS_GEMINI_SYSTEM_PROMPT = `
  function getGeminiPrometheusPrompt (line 331) | function getGeminiPrometheusPrompt(): string {

FILE: src/agents/prometheus/gpt.ts
  constant PROMETHEUS_GPT_SYSTEM_PROMPT (line 13) | const PROMETHEUS_GPT_SYSTEM_PROMPT = `
  function getGptPrometheusPrompt (line 462) | function getGptPrometheusPrompt(): string {

FILE: src/agents/prometheus/high-accuracy-mode.ts
  constant PROMETHEUS_HIGH_ACCURACY_MODE (line 7) | const PROMETHEUS_HIGH_ACCURACY_MODE = `# PHASE 3: PLAN GENERATION

FILE: src/agents/prometheus/identity-constraints.ts
  constant PROMETHEUS_IDENTITY_CONSTRAINTS (line 8) | const PROMETHEUS_IDENTITY_CONSTRAINTS = `<system-reminder>

FILE: src/agents/prometheus/interview-mode.ts
  constant PROMETHEUS_INTERVIEW_MODE (line 10) | const PROMETHEUS_INTERVIEW_MODE = `# PHASE 1: INTERVIEW MODE (DEFAULT)

FILE: src/agents/prometheus/plan-generation.ts
  constant PROMETHEUS_PLAN_GENERATION (line 8) | const PROMETHEUS_PLAN_GENERATION = `# PHASE 2: PLAN GENERATION (Auto-Tra...

FILE: src/agents/prometheus/plan-template.ts
  constant PROMETHEUS_PLAN_TEMPLATE (line 8) | const PROMETHEUS_PLAN_TEMPLATE = `## Plan Structure

FILE: src/agents/prometheus/system-prompt.ts
  constant PROMETHEUS_SYSTEM_PROMPT (line 15) | const PROMETHEUS_SYSTEM_PROMPT = `${PROMETHEUS_IDENTITY_CONSTRAINTS}
  constant PROMETHEUS_PERMISSION (line 27) | const PROMETHEUS_PERMISSION = {
  type PrometheusPromptSource (line 34) | type PrometheusPromptSource = "default" | "gpt" | "gemini"
  function getPrometheusPromptSource (line 39) | function getPrometheusPromptSource(model?: string): PrometheusPromptSour...
  function getPrometheusPrompt (line 55) | function getPrometheusPrompt(model?: string): string {

FILE: src/agents/sisyphus-junior/agent.ts
  constant MODE (line 28) | const MODE: AgentMode = "subagent"
  constant BLOCKED_TOOLS (line 32) | const BLOCKED_TOOLS = ["task"]
  constant SISYPHUS_JUNIOR_DEFAULTS (line 34) | const SISYPHUS_JUNIOR_DEFAULTS = {
  type SisyphusJuniorPromptSource (line 39) | type SisyphusJuniorPromptSource = "default" | "gpt" | "gpt-5-4" | "gpt-5...
  function getSisyphusJuniorPromptSource (line 41) | function getSisyphusJuniorPromptSource(model?: string): SisyphusJuniorPr...
  function buildSisyphusJuniorPrompt (line 57) | function buildSisyphusJuniorPrompt(
  function createSisyphusJuniorAgentWithOverrides (line 79) | function createSisyphusJuniorAgentWithOverrides(

FILE: src/agents/sisyphus-junior/default.ts
  function buildDefaultSisyphusJuniorPrompt (line 13) | function buildDefaultSisyphusJuniorPrompt(
  function buildTodoDisciplineSection (line 48) | function buildTodoDisciplineSection(useTaskSystem: boolean): string {

FILE: src/agents/sisyphus-junior/gemini.ts
  function buildGeminiSisyphusJuniorPrompt (line 14) | function buildGeminiSisyphusJuniorPrompt(
  function buildGeminiTaskDisciplineSection (line 170) | function buildGeminiTaskDisciplineSection(useTaskSystem: boolean): string {

FILE: src/agents/sisyphus-junior/gpt-5-3-codex.ts
  function buildGpt53CodexSisyphusJuniorPrompt (line 12) | function buildGpt53CodexSisyphusJuniorPrompt(
  function buildGpt53CodexTaskDisciplineSection (line 134) | function buildGpt53CodexTaskDisciplineSection(useTaskSystem: boolean): s...

FILE: src/agents/sisyphus-junior/gpt-5-4.ts
  function buildGpt54SisyphusJuniorPrompt (line 15) | function buildGpt54SisyphusJuniorPrompt(
  function buildGpt54TaskDisciplineSection (line 140) | function buildGpt54TaskDisciplineSection(useTaskSystem: boolean): string {

FILE: src/agents/sisyphus-junior/gpt.ts
  function buildGptSisyphusJuniorPrompt (line 13) | function buildGptSisyphusJuniorPrompt(
  function buildGptTaskDisciplineSection (line 135) | function buildGptTaskDisciplineSection(useTaskSystem: boolean): string {

FILE: src/agents/sisyphus.ts
  constant MODE (line 15) | const MODE: AgentMode = "all";
  constant SISYPHUS_PROMPT_METADATA (line 16) | const SISYPHUS_PROMPT_METADATA: AgentPromptMetadata = {
  function buildDynamicSisyphusPrompt (line 44) | function buildDynamicSisyphusPrompt(
  function createSisyphusAgent (line 446) | function createSisyphusAgent(

FILE: src/agents/sisyphus/default.ts
  function buildTaskManagementSection (line 28) | function buildTaskManagementSection(useTaskSystem: boolean): string {
  function buildDefaultSisyphusPrompt (line 138) | function buildDefaultSisyphusPrompt(

FILE: src/agents/sisyphus/gemini.ts
  function buildGeminiToolMandate (line 16) | function buildGeminiToolMandate(): string {
  function buildGeminiToolGuide (line 42) | function buildGeminiToolGuide(): string {
  function buildGeminiToolCallExamples (line 97) | function buildGeminiToolCallExamples(): string {
  function buildGeminiDelegationOverride (line 172) | function buildGeminiDelegationOverride(): string {
  function buildGeminiVerificationOverride (line 189) | function buildGeminiVerificationOverride(): string {
  function buildGeminiIntentGateEnforcement (line 213) | function buildGeminiIntentGateEnforcement(): string {

FILE: src/agents/sisyphus/gpt-5-4.ts
  function buildGpt54TasksSection (line 45) | function buildGpt54TasksSection(useTaskSystem: boolean): string {
  function buildGpt54SisyphusPrompt (line 79) | function buildGpt54SisyphusPrompt(

FILE: src/agents/tool-restrictions.test.ts
  constant TEST_MODEL (line 9) | const TEST_MODEL = "anthropic/claude-sonnet-4-5"

FILE: src/agents/types.ts
  type AgentMode (line 9) | type AgentMode = "primary" | "subagent" | "all";
  type AgentFactory (line 15) | type AgentFactory = ((model: string) => AgentConfig) & {
  type AgentCategory (line 22) | type AgentCategory =
  type AgentCost (line 31) | type AgentCost = "FREE" | "CHEAP" | "EXPENSIVE";
  type DelegationTrigger (line 36) | interface DelegationTrigger {
  type AgentPromptMetadata (line 47) | interface AgentPromptMetadata {
  function extractModelName (line 73) | function extractModelName(model: string): string {
  function isGptModel (line 77) | function isGptModel(model: string): boolean {
  function isGpt5_4Model (line 82) | function isGpt5_4Model(model: string): boolean {
  function isGpt5_3CodexModel (line 87) | function isGpt5_3CodexModel(model: string): boolean {
  constant GEMINI_PROVIDERS (line 92) | const GEMINI_PROVIDERS = ["google/", "google-vertex/"];
  function isGeminiModel (line 94) | function isGeminiModel(model: string): boolean {
  type BuiltinAgentName (line 107) | type BuiltinAgentName =
  type OverridableAgentName (line 119) | type OverridableAgentName = "build" | BuiltinAgentName;
  type AgentName (line 121) | type AgentName = BuiltinAgentName;
  type AgentOverrideConfig (line 123) | type AgentOverrideConfig = Partial<AgentConfig> & {
  type AgentOverrides (line 129) | type AgentOverrides = Partial<

FILE: src/agents/utils.test.ts
  constant TEST_DEFAULT_MODEL (line 11) | const TEST_DEFAULT_MODEL = "anthropic/claude-opus-4-6"
  function buildAgents (line 686) | async function buildAgents(disableFlag?: boolean) {
  function buildAgents (line 745) | async function buildAgents(disableFlag?: boolean) {

FILE: src/cli/cli-installer.ts
  function runCliInstaller (line 25) | async function runCliInstaller(args: InstallArgs, version: string): Prom...

FILE: src/cli/cli-program.ts
  constant VERSION (line 13) | const VERSION = packageJson.version
  function runCli (line 188) | function runCli(): void {

FILE: src/cli/config-manager/add-plugin-to-opencode-config.ts
  function addPluginToOpenCodeConfig (line 11) | async function addPluginToOpenCodeConfig(currentVersion: string): Promis...

FILE: src/cli/config-manager/bun-install.test.ts
  type CreateProcOptions (line 13) | type CreateProcOptions = {
  function createProc (line 23) | function createProc(options: CreateProcOptions = {}): ReturnType<typeof ...

FILE: src/cli/config-manager/bun-install.ts
  constant BUN_INSTALL_TIMEOUT_SECONDS (line 7) | const BUN_INSTALL_TIMEOUT_SECONDS = 60
  constant BUN_INSTALL_TIMEOUT_MS (line 8) | const BUN_INSTALL_TIMEOUT_MS = BUN_INSTALL_TIMEOUT_SECONDS * 1000
  type BunInstallOutputMode (line 10) | type BunInstallOutputMode = "inherit" | "pipe"
  type RunBunInstallOptions (line 12) | interface RunBunInstallOptions {
  type BunInstallOutput (line 18) | interface BunInstallOutput {
  type ProcessOutputStream (line 26) | type ProcessOutputStream = ReturnType<typeof spawnWithWindowsHide>["stdo...
  type BunInstallResult (line 32) | interface BunInstallResult {
  function runBunInstall (line 38) | async function runBunInstall(): Promise<boolean> {
  function readProcessOutput (line 43) | function readProcessOutput(stream: ProcessOutputStream): Promise<string> {
  function logCapturedOutputOnFailure (line 51) | function logCapturedOutputOnFailure(outputMode: BunInstallOutputMode, ou...
  function runBunInstallWithDetails (line 68) | async function runBunInstallWithDetails(options?: RunBunInstallOptions):...

FILE: src/cli/config-manager/config-context.ts
  type ConfigContext (line 7) | interface ConfigContext {
  function initConfigContext (line 15) | function initConfigContext(binary: OpenCodeBinaryType, version: string |...
  function getConfigContext (line 20) | function getConfigContext(): ConfigContext {
  function resetConfigContext (line 28) | function resetConfigContext(): void {
  function getConfigDir (line 32) | function getConfigDir(): string {
  function getConfigJson (line 36) | function getConfigJson(): string {
  function getConfigJsonc (line 40) | function getConfigJsonc(): string {
  function getOmoConfigPath (line 44) | function getOmoConfigPath(): string {

FILE: src/cli/config-manager/deep-merge-record.ts
  function deepMergeRecord (line 1) | function deepMergeRecord<TTarget extends Record<string, unknown>>(

FILE: src/cli/config-manager/detect-current-config.ts
  function detectProvidersFromOmoConfig (line 8) | function detectProvidersFromOmoConfig(): {
  function isOurPlugin (line 58) | function isOurPlugin(plugin: string): boolean {
  function detectCurrentConfig (line 63) | function detectCurrentConfig(): DetectedConfig {

FILE: src/cli/config-manager/ensure-config-directory-exists.ts
  function ensureConfigDirectoryExists (line 4) | function ensureConfigDirectoryExists(): void {

FILE: src/cli/config-manager/format-error-with-suggestion.ts
  type NodeError (line 1) | interface NodeError extends Error {
  function isPermissionError (line 5) | function isPermissionError(err: unknown): boolean {
  function isFileNotFoundError (line 10) | function isFileNotFoundError(err: unknown): boolean {
  function formatErrorWithSuggestion (line 15) | function formatErrorWithSuggestion(err: unknown, context: string): string {

FILE: src/cli/config-manager/generate-omo-config.ts
  function generateOmoConfig (line 4) | function generateOmoConfig(installConfig: InstallConfig): Record<string,...

FILE: src/cli/config-manager/npm-dist-tags.ts
  type NpmDistTags (line 1) | interface NpmDistTags {
  constant NPM_FETCH_TIMEOUT_MS (line 8) | const NPM_FETCH_TIMEOUT_MS = 5000
  function fetchNpmDistTags (line 10) | async function fetchNpmDistTags(packageName: string): Promise<NpmDistTag...

FILE: src/cli/config-manager/opencode-binary.ts
  constant OPENCODE_BINARIES (line 5) | const OPENCODE_BINARIES = ["opencode", "opencode-desktop"] as const
  type OpenCodeBinaryResult (line 7) | interface OpenCodeBinaryResult {
  function findOpenCodeBinaryWithVersion (line 12) | async function findOpenCodeBinaryWithVersion(): Promise<OpenCodeBinaryRe...
  function isOpenCodeInstalled (line 33) | async function isOpenCodeInstalled(): Promise<boolean> {
  function getOpenCodeVersion (line 38) | async function getOpenCodeVersion(): Promise<string | null> {

FILE: src/cli/config-manager/opencode-config-format.ts
  type ConfigFormat (line 4) | type ConfigFormat = "json" | "jsonc" | "none"
  function detectConfigFormat (line 6) | function detectConfigFormat(): { format: ConfigFormat; path: string } {

FILE: src/cli/config-manager/parse-opencode-config-file.ts
  type ParseConfigResult (line 5) | interface ParseConfigResult {
  type OpenCodeConfig (line 10) | interface OpenCodeConfig {
  function isEmptyOrWhitespace (line 15) | function isEmptyOrWhitespace(content: string): boolean {
  function parseOpenCodeConfigFileWithError (line 19) | function parseOpenCodeConfigFileWithError(path: string): ParseConfigResu...

FILE: src/cli/config-manager/plugin-name-with-version.ts
  constant DEFAULT_PACKAGE_NAME (line 3) | const DEFAULT_PACKAGE_NAME = "oh-my-opencode"
  constant PRIORITIZED_TAGS (line 4) | const PRIORITIZED_TAGS = ["latest", "beta", "next"] as const
  function getFallbackEntry (line 6) | function getFallbackEntry(version: string, packageName: string): string {
  function getPluginNameWithVersion (line 15) | async function getPluginNameWithVersion(

FILE: src/cli/config-manager/write-omo-config.test.ts
  function getRecord (line 23) | function getRecord(value: unknown): Record<string, unknown> {

FILE: src/cli/config-manager/write-omo-config.ts
  function isEmptyOrWhitespace (line 10) | function isEmptyOrWhitespace(content: string): boolean {
  function writeOmoConfig (line 14) | function writeOmoConfig(installConfig: InstallConfig): ConfigMergeResult {

FILE: src/cli/doctor/checks/config.ts
  constant USER_CONFIG_BASE (line 12) | const USER_CONFIG_BASE = join(getOpenCodeConfigDir({ binary: "opencode" ...
  constant PROJECT_CONFIG_BASE (line 13) | const PROJECT_CONFIG_BASE = join(process.cwd(), ".opencode", PACKAGE_NAME)
  type ConfigValidationResult (line 15) | interface ConfigValidationResult {
  function findConfigPath (line 23) | function findConfigPath(): string | null {
  function validateConfig (line 33) | function validateConfig(): ConfigValidationResult {
  function collectModelResolutionIssues (line 66) | function collectModelResolutionIssues(config: OmoConfig): DoctorIssue[] {
  function checkConfig (line 120) | async function checkConfig(): Promise<CheckResult> {

FILE: src/cli/doctor/checks/dependencies.ts
  function checkBinaryExists (line 8) | async function checkBinaryExists(binary: string): Promise<{ exists: bool...
  function getBinaryVersion (line 20) | async function getBinaryVersion(binary: string): Promise<string | null> {
  function checkAstGrepCli (line 34) | async function checkAstGrepCli(): Promise<DependencyInfo> {
  function checkAstGrepNapi (line 61) | async function checkAstGrepNapi(): Promise<DependencyInfo> {
  function findCommentCheckerPackageBinary (line 106) | function findCommentCheckerPackageBinary(): string | null {
  function checkCommentChecker (line 119) | async function checkCommentChecker(): Promise<DependencyInfo> {

FILE: src/cli/doctor/checks/index.ts
  function getAllCheckDefinitions (line 12) | function getAllCheckDefinitions(): CheckDefinition[] {

FILE: src/cli/doctor/checks/model-resolution-cache.ts
  function getOpenCodeCacheDir (line 7) | function getOpenCodeCacheDir(): string {
  function loadAvailableModelsFromCache (line 13) | function loadAvailableModelsFromCache(): AvailableModelsInfo {

FILE: src/cli/doctor/checks/model-resolution-config.ts
  constant PACKAGE_NAME (line 6) | const PACKAGE_NAME = "oh-my-opencode"
  constant USER_CONFIG_BASE (line 7) | const USER_CONFIG_BASE = join(
  constant PROJECT_CONFIG_BASE (line 11) | const PROJECT_CONFIG_BASE = join(process.cwd(), ".opencode", PACKAGE_NAME)
  function loadOmoConfig (line 13) | function loadOmoConfig(): OmoConfig | null {

FILE: src/cli/doctor/checks/model-resolution-details.ts
  function buildModelResolutionDetails (line 7) | function buildModelResolutionDetails(options: {

FILE: src/cli/doctor/checks/model-resolution-effective-model.ts
  function formatProviderChain (line 3) | function formatProviderChain(providers: string[]): string {
  function getEffectiveModel (line 7) | function getEffectiveModel(requirement: ModelRequirement, userOverride?:...
  function buildEffectiveResolution (line 18) | function buildEffectiveResolution(requirement: ModelRequirement, userOve...

FILE: src/cli/doctor/checks/model-resolution-types.ts
  type AgentResolutionInfo (line 3) | interface AgentResolutionInfo {
  type CategoryResolutionInfo (line 12) | interface CategoryResolutionInfo {
  type ModelResolutionInfo (line 21) | interface ModelResolutionInfo {
  type OmoConfig (line 26) | interface OmoConfig {
  type AvailableModelsInfo (line 31) | interface AvailableModelsInfo {

FILE: src/cli/doctor/checks/model-resolution-variant.ts
  function formatModelWithVariant (line 4) | function formatModelWithVariant(model: string, variant?: string): string {
  function getAgentOverride (line 8) | function getAgentOverride(
  function getEffectiveVariant (line 21) | function getEffectiveVariant(
  function getCategoryEffectiveVariant (line 44) | function getCategoryEffectiveVariant(

FILE: src/cli/doctor/checks/model-resolution.ts
  function getModelResolutionInfo (line 10) | function getModelResolutionInfo(): ModelResolutionInfo {
  function getModelResolutionInfoWithOverrides (line 30) | function getModelResolutionInfoWithOverrides(config: OmoConfig): ModelRe...
  function checkModels (line 62) | async function checkModels(): Promise<CheckResult> {

FILE: src/cli/doctor/checks/system-binary.ts
  constant WINDOWS_EXECUTABLE_EXTS (line 8) | const WINDOWS_EXECUTABLE_EXTS = [".exe", ".cmd", ".bat", ".ps1"]
  type OpenCodeBinaryInfo (line 10) | interface OpenCodeBinaryInfo {
  function getDesktopAppPaths (line 15) | function getDesktopAppPaths(platform: NodeJS.Platform): string[] {
  function getBinaryLookupCommand (line 50) | function getBinaryLookupCommand(platform: NodeJS.Platform): "which" | "w...
  function parseBinaryPaths (line 54) | function parseBinaryPaths(output: string): string[] {
  function selectBinaryPath (line 61) | function selectBinaryPath(paths: string[], platform: NodeJS.Platform): s...
  function buildVersionCommand (line 76) | function buildVersionCommand(binaryPath: string, platform: NodeJS.Platfo...
  function findDesktopBinary (line 84) | function findDesktopBinary(
  function findOpenCodeBinary (line 97) | async function findOpenCodeBinary(): Promise<OpenCodeBinaryInfo | null> {
  function getOpenCodeVersion (line 108) | async function getOpenCodeVersion(
  function compareVersions (line 125) | function compareVersions(current: string, minimum: string): boolean {

FILE: src/cli/doctor/checks/system-loaded-version.test.ts
  function createTemporaryDirectory (line 17) | function createTemporaryDirectory(prefix: string): string {
  function writeJson (line 23) | function writeJson(filePath: string, value: Record<string, string | Reco...

FILE: src/cli/doctor/checks/system-loaded-version.ts
  type PackageJsonShape (line 10) | interface PackageJsonShape {
  type LoadedVersionInfo (line 15) | interface LoadedVersionInfo {
  function getPlatformDefaultCacheDir (line 23) | function getPlatformDefaultCacheDir(platform: NodeJS.Platform = process....
  function resolveOpenCodeCacheDir (line 29) | function resolveOpenCodeCacheDir(): string {
  function readPackageJson (line 39) | function readPackageJson(filePath: string): PackageJsonShape | null {
  function normalizeVersion (line 50) | function normalizeVersion(value: string | undefined): string | null {
  function getLoadedPluginVersion (line 56) | function getLoadedPluginVersion(): LoadedVersionInfo {
  function getLatestPluginVersion (line 91) | async function getLatestPluginVersion(currentVersion: string | null): Pr...
  function getSuggestedInstallTag (line 96) | function getSuggestedInstallTag(currentVersion: string | null): string {

FILE: src/cli/doctor/checks/system-plugin.ts
  type PluginInfo (line 5) | interface PluginInfo {
  type OpenCodeConfigShape (line 14) | interface OpenCodeConfigShape {
  function detectConfigPath (line 18) | function detectConfigPath(): string | null {
  function parsePluginVersion (line 25) | function parsePluginVersion(entry: string): string | null {
  function findPluginEntry (line 41) | function findPluginEntry(entries: string[]): { entry: string; isLocalDev...
  function getPluginInfo (line 60) | function getPluginInfo(): PluginInfo {

FILE: src/cli/doctor/checks/system.ts
  function isConfigValid (line 10) | function isConfigValid(configPath: string | null): boolean {
  function getResultStatus (line 22) | function getResultStatus(issues: DoctorIssue[]): CheckResult["status"] {
  function buildMessage (line 28) | function buildMessage(status: CheckResult["status"], issues: DoctorIssue...
  function gatherSystemInfo (line 34) | async function gatherSystemInfo(): Promise<SystemInfo> {
  function checkSystem (line 53) | async function checkSystem(): Promise<CheckResult> {

FILE: src/cli/doctor/checks/tools-gh.ts
  type GhCliInfo (line 3) | interface GhCliInfo {
  function checkBinaryExists (line 13) | async function checkBinaryExists(binary: string): Promise<{ exists: bool...
  function getGhVersion (line 22) | async function getGhVersion(): Promise<string | null> {
  function getGhAuthStatus (line 36) | async function getGhAuthStatus(): Promise<{
  function getGhCliInfo (line 83) | async function getGhCliInfo(): Promise<GhCliInfo> {

FILE: src/cli/doctor/checks/tools-lsp.ts
  function getInstalledLspServers (line 3) | function getInstalledLspServers(): Array<{ id: string; extensions: strin...

FILE: src/cli/doctor/checks/tools-mcp.ts
  constant BUILTIN_MCP_SERVERS (line 8) | const BUILTIN_MCP_SERVERS = ["context7", "grep_app"]
  type McpConfigShape (line 10) | interface McpConfigShape {
  function getMcpConfigPaths (line 14) | function getMcpConfigPaths(): string[] {
  function loadUserMcpConfig (line 22) | function loadUserMcpConfig(): Record<string, unknown> {
  function getBuiltinMcpInfo (line 42) | function getBuiltinMcpInfo(): McpServerInfo[] {
  function getUserMcpInfo (line 51) | function getUserMcpInfo(): McpServerInfo[] {

FILE: src/cli/doctor/checks/tools.ts
  function gatherToolsSummary (line 8) | async function gatherToolsSummary(): Promise<ToolsSummary> {
  function buildToolIssues (line 35) | function buildToolIssues(summary: ToolsSummary): DoctorIssue[] {
  function checkTools (line 88) | async function checkTools(): Promise<CheckResult> {

FILE: src/cli/doctor/constants.ts
  constant SYMBOLS (line 3) | const SYMBOLS = {
  constant STATUS_COLORS (line 13) | const STATUS_COLORS = {
  constant CHECK_IDS (line 20) | const CHECK_IDS = {
  constant CHECK_NAMES (line 27) | const CHECK_NAMES: Record<string, string> = {
  constant EXIT_CODES (line 34) | const EXIT_CODES = {
  constant MIN_OPENCODE_VERSION (line 39) | const MIN_OPENCODE_VERSION = "1.0.150"
  constant PACKAGE_NAME (line 41) | const PACKAGE_NAME = "oh-my-opencode"
  constant OPENCODE_BINARIES (line 43) | const OPENCODE_BINARIES = ["opencode", "opencode-desktop"] as const

FILE: src/cli/doctor/format-default.test.ts
  function createBaseResult (line 6) | function createBaseResult(): DoctorResult {

FILE: src/cli/doctor/format-default.ts
  function formatDefault (line 6) | function formatDefault(result: DoctorResult): string {

FILE: src/cli/doctor/format-shared.ts
  function formatStatusSymbol (line 5) | function formatStatusSymbol(status: CheckStatus): string {
  function formatStatusMark (line 19) | function formatStatusMark(available: boolean): string {
  function stripAnsi (line 23) | function stripAnsi(str: string): string {
  function formatHeader (line 29) | function formatHeader(): string {
  function formatIssue (line 33) | function formatIssue(issue: DoctorIssue, index: number): string {

FILE: src/cli/doctor/format-status.ts
  function formatStatus (line 5) | function formatStatus(result: DoctorResult): string {

FILE: src/cli/doctor/format-verbose.ts
  function formatVerbose (line 5) | function formatVerbose(result: DoctorResult): string {

FILE: src/cli/doctor/formatter.test.ts
  function createDoctorResult (line 5) | function createDoctorResult(): DoctorResult {
  function createDoctorResultWithIssues (line 45) | function createDoctorResultWithIssues(): DoctorResult {
  function createDoctorResultWithDetails (line 56) | function createDoctorResultWithDetails(): DoctorResult {

FILE: src/cli/doctor/formatter.ts
  function formatDoctorOutput (line 6) | function formatDoctorOutput(result: DoctorResult, mode: DoctorMode): str...
  function formatJsonOutput (line 17) | function formatJsonOutput(result: DoctorResult): string {

FILE: src/cli/doctor/index.ts
  function doctor (line 4) | async function doctor(options: DoctorOptions = { mode: "default" }): Pro...

FILE: src/cli/doctor/runner.test.ts
  function createSystemInfo (line 4) | function createSystemInfo(): SystemInfo {
  function createTools (line 17) | function createTools(): ToolsSummary {
  function createPassResult (line 29) | function createPassResult(name: string): CheckResult {
  function createDeferred (line 33) | function createDeferred(): {

FILE: src/cli/doctor/runner.ts
  function runCheck (line 6) | async function runCheck(check: CheckDefinition): Promise<CheckResult> {
  function calculateSummary (line 23) | function calculateSummary(results: CheckResult[], duration: number): Doc...
  function determineExitCode (line 34) | function determineExitCode(results: CheckResult[]): number {
  function runDoctor (line 38) | async function runDoctor(options: DoctorOptions): Promise<DoctorResult> {

FILE: src/cli/doctor/types.ts
  type DoctorMode (line 3) | type DoctorMode = "default" | "status" | "verbose"
  type DoctorOptions (line 5) | interface DoctorOptions {
  type DoctorIssue (line 10) | interface DoctorIssue {
  type CheckStatus (line 18) | type CheckStatus = "pass" | "fail" | "warn" | "skip"
  type CheckResult (line 20) | interface CheckResult {
  type CheckFunction (line 29) | type CheckFunction = () => Promise<CheckResult>
  type CheckDefinition (line 31) | interface CheckDefinition {
  type SystemInfo (line 38) | interface SystemInfo {
  type ToolsSummary (line 49) | interface ToolsSummary {
  type DoctorSummary (line 59) | interface DoctorSummary {
  type DoctorResult (line 68) | interface DoctorResult {
  type CheckCategory (line 78) | type CheckCategory =
  type OpenCodeInfo (line 86) | interface OpenCodeInfo {
  type PluginInfo (line 93) | interface PluginInfo {
  type ConfigInfo (line 101) | interface ConfigInfo {
  type AuthProviderId (line 109) | type AuthProviderId = "anthropic" | "openai" | "google"
  type AuthProviderInfo (line 111) | interface AuthProviderInfo {
  type DependencyInfo (line 119) | interface DependencyInfo {
  type McpServerInfo (line 128) | interface McpServerInfo {
  type VersionCheckInfo (line 136) | interface VersionCheckInfo {

FILE: src/cli/fallback-chain-resolution.ts
  function resolveModelFromChain (line 7) | function resolveModelFromChain(
  function getSisyphusFallbackChain (line 25) | function getSisyphusFallbackChain(): FallbackEntry[] {
  function isAnyFallbackEntryAvailable (line 29) | function isAnyFallbackEntryAvailable(
  function isRequiredModelAvailable (line 38) | function isRequiredModelAvailable(
  function isRequiredProviderAvailable (line 48) | function isRequiredProviderAvailable(

FILE: src/cli/get-local-version/formatter.ts
  constant SYMBOLS (line 4) | const SYMBOLS = {
  function formatVersionOutput (line 14) | function formatVersionOutput(info: VersionInfo): string {
  function formatJsonOutput (line 64) | function formatJsonOutput(info: VersionInfo): string {

FILE: src/cli/get-local-version/get-local-version.ts
  function getLocalVersion (line 12) | async function getLocalVersion(

FILE: src/cli/get-local-version/types.ts
  type VersionInfo (line 1) | interface VersionInfo {
  type GetLocalVersionOptions (line 11) | interface GetLocalVersionOptions {

FILE: src/cli/install-validators.test.ts
  function createArgs (line 6) | function createArgs(overrides: Partial<InstallArgs> = {}): InstallArgs {

FILE: src/cli/install-validators.ts
  constant SYMBOLS (line 10) | const SYMBOLS = {
  constant ANSI_COLOR_PATTERN (line 20) | const ANSI_COLOR_PATTERN = new RegExp("\u001b\\[[0-9;]*m", "g")
  function formatProvider (line 22) | function formatProvider(name: string, enabled: boolean, detail?: string)...
  function formatConfigSummary (line 29) | function formatConfigSummary(config: InstallConfig): string {
  function printHeader (line 56) | function printHeader(isUpdate: boolean): void {
  function printStep (line 63) | function printStep(step: number, total: number, message: string): void {
  function printSuccess (line 68) | function printSuccess(message: string): void {
  function printError (line 72) | function printError(message: string): void {
  function printInfo (line 76) | function printInfo(message: string): void {
  function printWarning (line 80) | function printWarning(message: string): void {
  function printBox (line 84) | function printBox(content: string, title?: string): void {
  function validateNonTuiArgs (line 115) | function validateNonTuiArgs(args: InstallArgs): { valid: boolean; errors...
  function argsToConfig (line 159) | function argsToConfig(args: InstallArgs): InstallConfig {
  function detectedToInitialValues (line 173) | function detectedToInitialValues(detected: DetectedConfig): {

FILE: src/cli/install.ts
  constant VERSION (line 6) | const VERSION = packageJson.version
  function install (line 8) | async function install(args: InstallArgs): Promise<number> {

FILE: src/cli/mcp-oauth/index.ts
  function createMcpOAuthCommand (line 6) | function createMcpOAuthCommand(): Command {

FILE: src/cli/mcp-oauth/login.test.ts
  method constructor (line 7) | constructor(public options: { serverUrl: string; clientId?: string; scop...
  method login (line 8) | async login() {

FILE: src/cli/mcp-oauth/login.ts
  type LoginOptions (line 3) | interface LoginOptions {
  function login (line 9) | async function login(serverName: string, options: LoginOptions): Promise...

FILE: src/cli/mcp-oauth/logout.ts
  type LogoutOptions (line 3) | interface LogoutOptions {
  function logout (line 7) | async function logout(serverName: string, options?: LogoutOptions): Prom...

FILE: src/cli/mcp-oauth/status.ts
  function status (line 3) | async function status(serverName: string | undefined): Promise<number> {

FILE: src/cli/model-fallback-requirements.ts
  constant CLI_AGENT_MODEL_REQUIREMENTS (line 7) | const CLI_AGENT_MODEL_REQUIREMENTS: Record<string, ModelRequirement> = A...
  constant CLI_CATEGORY_MODEL_REQUIREMENTS (line 9) | const CLI_CATEGORY_MODEL_REQUIREMENTS: Record<string, ModelRequirement> ...

FILE: src/cli/model-fallback-types.ts
  type ProviderAvailability (line 1) | interface ProviderAvailability {
  type AgentConfig (line 15) | interface AgentConfig {
  type CategoryConfig (line 20) | interface CategoryConfig {
  type GeneratedOmoConfig (line 25) | interface GeneratedOmoConfig {

FILE: src/cli/model-fallback.test.ts
  function createConfig (line 6) | function createConfig(overrides: Partial<InstallConfig> = {}): InstallCo...

FILE: src/cli/model-fallback.ts
  constant ZAI_MODEL (line 20) | const ZAI_MODEL = "zai-coding-plan/glm-4.7"
  constant ULTIMATE_FALLBACK (line 22) | const ULTIMATE_FALLBACK = "opencode/gpt-5-nano"
  constant SCHEMA_URL (line 23) | const SCHEMA_URL = "https://raw.githubusercontent.com/code-yeongyu/oh-my...
  function generateModelConfig (line 27) | function generateModelConfig(config: InstallConfig): GeneratedOmoConfig {
  function shouldShowChatGPTOnlyWarning (line 143) | function shouldShowChatGPTOnlyWarning(config: InstallConfig): boolean {

FILE: src/cli/openai-only-model-catalog.test.ts
  function createConfig (line 6) | function createConfig(overrides: Partial<InstallConfig> = {}): InstallCo...

FILE: src/cli/openai-only-model-catalog.ts
  constant OPENAI_ONLY_AGENT_OVERRIDES (line 3) | const OPENAI_ONLY_AGENT_OVERRIDES: Record<string, AgentConfig> = {
  constant OPENAI_ONLY_CATEGORY_OVERRIDES (line 8) | const OPENAI_ONLY_CATEGORY_OVERRIDES: Record<string, CategoryConfig> = {
  function isOpenAiOnlyAvailability (line 15) | function isOpenAiOnlyAvailability(availability: ProviderAvailability): b...
  function applyOpenAiOnlyModelCatalog (line 28) | function applyOpenAiOnlyModelCatalog(config: GeneratedOmoConfig): Genera...

FILE: src/cli/provider-availability.ts
  function toProviderAvailability (line 4) | function toProviderAvailability(config: InstallConfig): ProviderAvailabi...
  function isProviderAvailable (line 20) | function isProviderAvailable(provider: string, availability: ProviderAva...

FILE: src/cli/run/agent-profile-colors.ts
  type AgentProfile (line 4) | interface AgentProfile {
  function loadAgentProfileColors (line 9) | async function loadAgentProfileColors(

FILE: src/cli/run/agent-resolver.ts
  constant CORE_AGENT_ORDER (line 6) | const CORE_AGENT_ORDER = ["sisyphus", "hephaestus", "prometheus", "atlas...
  constant DEFAULT_AGENT (line 7) | const DEFAULT_AGENT = "sisyphus"
  type EnvVars (line 9) | type EnvVars = Record<string, string | undefined>
  type CoreAgentKey (line 10) | type CoreAgentKey = (typeof CORE_AGENT_ORDER)[number]
  type ResolvedAgent (line 12) | interface ResolvedAgent {

FILE: src/cli/run/completion-continuation.test.ts
  function createTempDir (line 19) | function createTempDir(): string {
  function createMockContext (line 25) | function createMockContext(directory: string): RunContext {
  function writeBoulderStateFile (line 40) | function writeBoulderStateFile(directory: string, activePlanPath: string...

FILE: src/cli/run/completion.ts
  function checkCompletionConditions (line 9) | async function checkCompletionConditions(ctx: RunContext): Promise<boole...
  function areContinuationHooksIdle (line 38) | function areContinuationHooksIdle(
  function areAllTodosComplete (line 55) | async function areAllTodosComplete(ctx: RunContext): Promise<boolean> {
  function areAllChildrenIdle (line 74) | async function areAllChildrenIdle(ctx: RunContext): Promise<boolean> {
  function fetchAllStatuses (line 79) | async function fetchAllStatuses(
  function areAllDescendantsIdle (line 88) | async function areAllDescendantsIdle(
  function logWaiting (line 119) | function logWaiting(ctx: RunContext, message: string): void {

FILE: src/cli/run/continuation-state-marker.test.ts
  function createTempDir (line 10) | function createTempDir(): string {

FILE: src/cli/run/continuation-state.ts
  type ContinuationState (line 9) | interface ContinuationState {
  function getContinuationState (line 18) | function getContinuationState(directory: string, sessionID: string): Con...
  function hasActiveBoulderContinuation (line 31) | function hasActiveBoulderContinuation(directory: string, sessionID: stri...
  function hasActiveRalphLoopContinuation (line 40) | function hasActiveRalphLoopContinuation(directory: string, sessionID: st...

FILE: src/cli/run/event-formatting.ts
  function serializeError (line 13) | function serializeError(error: unknown): string {
  function getSessionTag (line 58) | function getSessionTag(ctx: RunContext, payload: EventPayload): string {
  function logEventVerbose (line 72) | function logEventVerbose(ctx: RunContext, payload: EventPayload): void {

FILE: src/cli/run/event-handlers.ts
  function getSessionId (line 26) | function getSessionId(props?: { sessionID?: string; sessionId?: string }...
  function getInfoSessionId (line 30) | function getInfoSessionId(props?: {
  function getPartSessionId (line 36) | function getPartSessionId(props?: {
  function getPartMessageId (line 42) | function getPartMessageId(props?: {
  function getDeltaMessageId (line 48) | function getDeltaMessageId(props?: {
  function renderCompletionMetaLine (line 54) | function renderCompletionMetaLine(state: EventState, messageID: string):...
  function handleSessionIdle (line 67) | function handleSessionIdle(ctx: RunContext, payload: EventPayload, state...
  function handleSessionStatus (line 76) | function handleSessionStatus(ctx: RunContext, payload: EventPayload, sta...
  function handleSessionError (line 91) | function handleSessionError(ctx: RunContext, payload: EventPayload, stat...
  function handleMessagePartUpdated (line 102) | function handleMessagePartUpdated(ctx: RunContext, payload: EventPayload...
  function handleMessagePartDelta (line 163) | function handleMessagePartDelta(ctx: RunContext, payload: EventPayload, ...
  function handleToolPart (line 201) | function handleToolPart(
  function handleMessageUpdated (line 233) | function handleMessageUpdated(ctx: RunContext, payload: EventPayload, st...
  function handleToolExecute (line 278) | function handleToolExecute(ctx: RunContext, payload: EventPayload, state...
  function handleToolResult (line 297) | function handleToolResult(ctx: RunContext, payload: EventPayload, state:...
  function handleTuiToast (line 320) | function handleTuiToast(_ctx: RunContext, payload: EventPayload, state: ...
  function ensureThinkBlockOpen (line 336) | function ensureThinkBlockOpen(state: EventState): void {
  function closeThinkBlockIfNeeded (line 344) | function closeThinkBlockIfNeeded(state: EventState): void {

FILE: src/cli/run/event-state.ts
  type EventState (line 1) | interface EventState {
  function createEventState (line 50) | function createEventState(): EventState {

FILE: src/cli/run/event-stream-processor.ts
  function processEvents (line 17) | async function processEvents(

FILE: src/cli/run/integration.test.ts
  type MockWriteStream (line 40) | interface MockWriteStream {
  function createMockWriteStream (line 45) | function createMockWriteStream(): MockWriteStream {

FILE: src/cli/run/json-output.test.ts
  type MockWriteStream (line 5) | interface MockWriteStream {
  function createMockWriteStream (line 10) | function createMockWriteStream(): MockWriteStream {

FILE: src/cli/run/json-output.ts
  type JsonOutputManager (line 3) | interface JsonOutputManager {
  type JsonOutputManagerOptions (line 9) | interface JsonOutputManagerOptions {
  function createJsonOutputManager (line 14) | function createJsonOutputManager(

FILE: src/cli/run/message-part-delta.test.ts
  function stripAnsi (line 6) | function stripAnsi(str: string): string {

FILE: src/cli/run/model-resolver.ts
  function resolveRunModel (line 1) | function resolveRunModel(

FILE: src/cli/run/on-complete-hook.test.ts
  function createStream (line 7) | function createStream(text: string): ReadableStream<Uint8Array> | undefi...
  function createProc (line 21) | function createProc(exitCode: number, output?: { stdout?: string; stderr...

FILE: src/cli/run/on-complete-hook.ts
  function readOutput (line 4) | async function readOutput(
  function executeOnCompleteHook (line 23) | async function executeOnCompleteHook(options: {

FILE: src/cli/run/opencode-binary-resolver.ts
  constant OPENCODE_COMMANDS (line 4) | const OPENCODE_COMMANDS = ["opencode", "opencode-desktop"] as const
  constant WINDOWS_SUFFIXES (line 5) | const WINDOWS_SUFFIXES = ["", ".exe", ".cmd", ".bat", ".ps1"] as const
  function getCommandCandidates (line 7) | function getCommandCandidates(platform: NodeJS.Platform): string[] {
  function collectCandidateBinaryPaths (line 15) | function collectCandidateBinaryPaths(
  function canExecuteBinary (line 43) | async function canExecuteBinary(binaryPath: string): Promise<boolean> {
  function findWorkingOpencodeBinary (line 56) | async function findWorkingOpencodeBinary(
  function buildPathWithBinaryFirst (line 71) | function buildPathWithBinaryFirst(pathEnv: string | undefined, binaryPat...
  function withWorkingOpencodePath (line 79) | async function withWorkingOpencodePath<T>(

FILE: src/cli/run/output-renderer.ts
  function renderAgentHeader (line 3) | function renderAgentHeader(
  function openThinkBlock (line 31) | function openThinkBlock(): void {
  function closeThinkBlock (line 35) | function closeThinkBlock(): void {
  function writePaddedText (line 39) | function writePaddedText(
  function colorizeWithProfileColor (line 70) | function colorizeWithProfileColor(text: string, hexColor?: string): stri...
  function parseHexColor (line 80) | function parseHexColor(hexColor: string): [number, number, number] | null {

FILE: src/cli/run/poll-for-completion.test.ts
  function abortAfter (line 36) | function abortAfter(abortController: AbortController, delayMs: number): ...

FILE: src/cli/run/poll-for-completion.ts
  constant DEFAULT_POLL_INTERVAL_MS (line 7) | const DEFAULT_POLL_INTERVAL_MS = 500
  constant DEFAULT_REQUIRED_CONSECUTIVE (line 8) | const DEFAULT_REQUIRED_CONSECUTIVE = 1
  constant ERROR_GRACE_CYCLES (line 9) | const ERROR_GRACE_CYCLES = 3
  constant MIN_STABILIZATION_MS (line 10) | const MIN_STABILIZATION_MS = 1_000
  constant DEFAULT_EVENT_WATCHDOG_MS (line 11) | const DEFAULT_EVENT_WATCHDOG_MS = 30_000 // 30 seconds
  constant DEFAULT_SECONDARY_MEANINGFUL_WORK_TIMEOUT_MS (line 12) | const DEFAULT_SECONDARY_MEANINGFUL_WORK_TIMEOUT_MS = 60_000 // 60 seconds
  type PollOptions (line 14) | interface PollOptions {
  function pollForCompletion (line 22) | async function pollForCompletion(
  function getMainSessionStatus (line 200) | async function getMainSessionStatus(

FILE: src/cli/run/runner.ts
  constant EVENT_PROCESSOR_SHUTDOWN_TIMEOUT_MS (line 18) | const EVENT_PROCESSOR_SHUTDOWN_TIMEOUT_MS = 2_000
  function waitForEventProcessorShutdown (line 20) | async function waitForEventProcessorShutdown(
  function run (line 32) | async function run(options: RunOptions): Promise<number> {

FILE: src/cli/run/server-connection.ts
  function isPortStartFailure (line 7) | function isPortStartFailure(error: unknown, port: number): boolean {
  function isPortRangeExhausted (line 15) | function isPortRangeExhausted(error: unknown): boolean {
  function startServer (line 23) | async function startServer(options: { signal: AbortSignal, port: number ...
  function createServerConnection (line 33) | async function createServerConnection(options: {

FILE: src/cli/run/session-resolver.ts
  constant SESSION_CREATE_MAX_RETRIES (line 5) | const SESSION_CREATE_MAX_RETRIES = 3
  constant SESSION_CREATE_RETRY_DELAY_MS (line 6) | const SESSION_CREATE_RETRY_DELAY_MS = 1000
  function resolveSession (line 8) | async function resolveSession(options: {

FILE: src/cli/run/stdin-suppression.test.ts
  type FakeStdin (line 5) | type FakeStdin = EventEmitter & {
  function createFakeStdin (line 14) | function createFakeStdin(options: {

FILE: src/cli/run/stdin-suppression.ts
  type StdinLike (line 1) | type StdinLike = {
  function includesCtrlC (line 12) | function includesCtrlC(chunk: string | Uint8Array): boolean {
  function suppressRunInput (line 17) | function suppressRunInput(

FILE: src/cli/run/timestamp-output.test.ts
  type MockWriteStream (line 6) | interface MockWriteStream {
  function createMockWriteStream (line 15) | function createMockWriteStream(): MockWriteStream {

FILE: src/cli/run/timestamp-output.ts
  function formatTimestamp (line 1) | function formatTimestamp(date: Date): string {
  function createTimestampTransformer (line 8) | function createTimestampTransformer(now: () => Date = () => new Date()):...
  type WriteFn (line 33) | type WriteFn = NodeJS.WriteStream["write"]
  function createTimestampedStdoutController (line 35) | function createTimestampedStdoutController(stdout: NodeJS.WriteStream = ...

FILE: src/cli/run/tool-input-preview.ts
  type ToolHeader (line 1) | interface ToolHeader {
  function formatToolHeader (line 7) | function formatToolHeader(toolName: string, input: Record<string, unknow...
  function formatKeyValues (line 128) | function formatKeyValues(input: Record<string, unknown>, exclude: string...
  function str (line 140) | function str(value: unknown): string | undefined {

FILE: src/cli/run/types.ts
  type RunOptions (line 4) | interface RunOptions {
  type ServerConnection (line 18) | interface ServerConnection {
  type RunResult (line 23) | interface RunResult {
  type RunContext (line 31) | interface RunContext {
  type Todo (line 39) | interface Todo {
  type SessionStatus (line 46) | interface SessionStatus {
  type ChildSession (line 50) | interface ChildSession {
  type EventPayload (line 54) | interface EventPayload {
  type SessionIdleProps (line 59) | interface SessionIdleProps {
  type SessionStatusProps (line 64) | interface SessionStatusProps {
  type MessageUpdatedProps (line 70) | interface MessageUpdatedProps {
  type MessagePartUpdatedProps (line 83) | interface MessagePartUpdatedProps {
  type MessagePartDeltaProps (line 103) | interface MessagePartDeltaProps {
  type ToolExecuteProps (line 112) | interface ToolExecuteProps {
  type ToolResultProps (line 119) | interface ToolResultProps {
  type SessionErrorProps (line 126) | interface SessionErrorProps {
  type TuiToastShowProps (line 132) | interface TuiToastShowProps {

FILE: src/cli/tui-install-prompts.ts
  function selectOrCancel (line 10) | async function selectOrCancel<TValue extends Readonly<string | boolean |...
  function promptInstallConfig (line 29) | async function promptInstallConfig(detected: DetectedConfig): Promise<In...

FILE: src/cli/tui-installer.ts
  function runTuiInstaller (line 14) | async function runTuiInstaller(args: InstallArgs, version: string): Prom...

FILE: src/cli/types.ts
  type ClaudeSubscription (line 1) | type ClaudeSubscription = "no" | "yes" | "max20"
  type BooleanArg (line 2) | type BooleanArg = "no" | "yes"
  type InstallArgs (line 4) | interface InstallArgs {
  type InstallConfig (line 17) | interface InstallConfig {
  type ConfigMergeResult (line 29) | interface ConfigMergeResult {
  type DetectedConfig (line 35) | interface DetectedConfig {

FILE: src/config/schema/agent-names.ts
  type AgentName (line 43) | type AgentName = z.infer<typeof AgentNameSchema>
  type BuiltinSkillName (line 45) | type BuiltinSkillName = z.infer<typeof BuiltinSkillNameSchema>

FILE: src/config/schema/agent-overrides.ts
  type AgentOverrideConfig (line 77) | type AgentOverrideConfig = z.infer<typeof AgentOverrideConfigSchema>
  type AgentOverrides (line 78) | type AgentOverrides = z.infer<typeof AgentOverridesSchema>

FILE: src/config/schema/babysitting.ts
  type BabysittingConfig (line 7) | type BabysittingConfig = z.infer<typeof BabysittingConfigSchema>

FILE: src/config/schema/background-task.ts
  type BackgroundTaskConfig (line 25) | type BackgroundTaskConfig = z.infer<typeof BackgroundTaskConfigSchema>

FILE: src/config/schema/browser-automation.ts
  type BrowserAutomationProvider (line 21) | type BrowserAutomationProvider = z.infer<
  type BrowserAutomationConfig (line 24) | type BrowserAutomationConfig = z.infer<typeof BrowserAutomationConfigSch...

FILE: src/config/schema/categories.ts
  type CategoryConfig (line 43) | type CategoryConfig = z.infer<typeof CategoryConfigSchema>
  type CategoriesConfig (line 44) | type CategoriesConfig = z.infer<typeof CategoriesConfigSchema>
  type BuiltinCategoryName (line 45) | type BuiltinCategoryName = z.infer<typeof BuiltinCategoryNameSchema>

FILE: src/config/schema/claude-code.ts
  type ClaudeCodeConfig (line 13) | type ClaudeCodeConfig = z.infer<typeof ClaudeCodeConfigSchema>

FILE: src/config/schema/commands.ts
  type BuiltinCommandName (line 13) | type BuiltinCommandName = z.infer<typeof BuiltinCommandNameSchema>

FILE: src/config/schema/comment-checker.ts
  type CommentCheckerConfig (line 8) | type CommentCheckerConfig = z.infer<typeof CommentCheckerConfigSchema>

FILE: src/config/schema/dynamic-context-pruning.ts
  type DynamicContextPruningConfig (line 53) | type DynamicContextPruningConfig = z.infer<

FILE: src/config/schema/experimental.ts
  type ExperimentalConfig (line 26) | type ExperimentalConfig = z.infer<typeof ExperimentalConfigSchema>

FILE: src/config/schema/fallback-models.ts
  type FallbackModels (line 5) | type FallbackModels = z.infer<typeof FallbackModelsSchema>

FILE: src/config/schema/git-env-prefix.ts
  constant GIT_ENV_ASSIGNMENT_PATTERN (line 3) | const GIT_ENV_ASSIGNMENT_PATTERN =
  constant GIT_ENV_PREFIX_VALIDATION_MESSAGE (line 6) | const GIT_ENV_PREFIX_VALIDATION_MESSAGE =
  function isValidGitEnvPrefix (line 9) | function isValidGitEnvPrefix(value: string): boolean {
  function assertValidGitEnvPrefix (line 17) | function assertValidGitEnvPrefix(value: string): string {

FILE: src/config/schema/git-master.ts
  type GitMasterConfig (line 14) | type GitMasterConfig = z.infer<typeof GitMasterConfigSchema>

FILE: src/config/schema/hooks.ts
  type HookName (line 56) | type HookName = z.infer<typeof HookNameSchema>

FILE: src/config/schema/internal/permission.ts
  type PermissionValue (line 4) | type PermissionValue = z.infer<typeof PermissionValueSchema>
  type AgentPermission (line 20) | type AgentPermission = z.infer<typeof AgentPermissionSchema>

FILE: src/config/schema/notification.ts
  type NotificationConfig (line 8) | type NotificationConfig = z.infer<typeof NotificationConfigSchema>

FILE: src/config/schema/oh-my-opencode-config.ts
  type OhMyOpenCodeConfig (line 71) | type OhMyOpenCodeConfig = z.infer<typeof OhMyOpenCodeConfigSchema>

FILE: src/config/schema/openclaw.ts
  type OpenClawConfig (line 47) | type OpenClawConfig = z.infer<typeof OpenClawConfigSchema>
  type OpenClawGateway (line 48) | type OpenClawGateway = z.infer<typeof OpenClawGatewaySchema>
  type OpenClawHook (line 49) | type OpenClawHook = z.infer<typeof OpenClawHookSchema>
  type OpenClawReplyListenerConfig (line 50) | type OpenClawReplyListenerConfig = z.infer<typeof OpenClawReplyListenerC...

FILE: src/config/schema/ralph-loop.ts
  type RalphLoopConfig (line 13) | type RalphLoopConfig = z.infer<typeof RalphLoopConfigSchema>

FILE: src/config/schema/runtime-fallback.ts
  type RuntimeFallbackConfig (line 18) | type RuntimeFallbackConfig = z.infer<typeof RuntimeFallbackConfigSchema>

FILE: src/config/schema/sisyphus-agent.ts
  type SisyphusAgentConfig (line 10) | type SisyphusAgentConfig = z.infer<typeof SisyphusAgentConfigSchema>

FILE: src/config/schema/sisyphus.ts
  type SisyphusTasksConfig (line 16) | type SisyphusTasksConfig = z.infer<typeof SisyphusTasksConfigSchema>
  type SisyphusConfig (line 17) | type SisyphusConfig = z.infer<typeof SisyphusConfigSchema>

FILE: src/config/schema/skills.ts
  type SkillsConfig (line 38) | type SkillsConfig = z.infer<typeof SkillsConfigSchema>
  type SkillDefinition (line 39) | type SkillDefinition = z.infer<typeof SkillDefinitionSchema>

FILE: src/config/schema/start-work.ts
  type StartWorkConfig (line 8) | type StartWorkConfig = z.infer<typeof StartWorkConfigSchema>

FILE: src/config/schema/tmux.ts
  type TmuxConfig (line 19) | type TmuxConfig = z.infer<typeof TmuxConfigSchema>
  type TmuxLayout (line 20) | type TmuxLayout = z.infer<typeof TmuxLayoutSchema>

FILE: src/config/schema/websearch.ts
  type WebsearchProvider (line 14) | type WebsearchProvider = z.infer<typeof WebsearchProviderSchema>
  type WebsearchConfig (line 15) | type WebsearchConfig = z.infer<typeof WebsearchConfigSchema>

FILE: src/create-hooks.ts
  type CreatedHooks (line 12) | type CreatedHooks = ReturnType<typeof createHooks>
  type DisposableHook (line 14) | type DisposableHook = { dispose?: () => void } | null | undefined
  type DisposableCreatedHooks (line 16) | type DisposableCreatedHooks = {
  function disposeCreatedHooks (line 22) | function disposeCreatedHooks(hooks: DisposableCreatedHooks): void {
  function createHooks (line 28) | function createHooks(args: {

FILE: src/create-managers.ts
  type Managers (line 13) | type Managers = {
  function createManagers (line 20) | function createManagers(args: {

FILE: src/create-tools.ts
  type CreateToolsResult (line 12) | type CreateToolsResult = {
  function createTools (line 22) | async function createTools(args: {

FILE: src/features/background-agent/background-task-notification-template.ts
  type BackgroundTaskNotificationStatus (line 3) | type BackgroundTaskNotificationStatus = "COMPLETED" | "CANCELLED" | "INT...
  function buildBackgroundTaskNotificationText (line 5) | function buildBackgroundTaskNotificationText(input: {

FILE: src/features/background-agent/cancel-task-cleanup.test.ts
  function createBackgroundManager (line 14) | function createBackgroundManager(config?: { defaultConcurrency?: number ...
  function createMockTask (line 37) | function createMockTask(overrides: Partial<BackgroundTask> & { id: strin...
  function getTaskMap (line 58) | function getTaskMap(manager: BackgroundManager): Map<string, BackgroundT...
  function getPendingByParent (line 60) | function getPendingByParent(manager: BackgroundManager): Map<string, Set...
  function getQueuesByKey (line 62) | function getQueuesByKey(manager: BackgroundManager): Map<string, Array<{...
  function getConcurrencyManager (line 64) | function getConcurrencyManager(manager: BackgroundManager): ConcurrencyM...
  function getCompletionTimers (line 66) | function getCompletionTimers(manager: BackgroundManager): Map<string, Re...
  function processKeyForTest (line 68) | async function processKeyForTest(manager: BackgroundManager, key: string...
  function runScheduledCleanup (line 73) | function runScheduledCleanup(manager: BackgroundManager, taskId: string)...

FILE: src/features/background-agent/compaction-aware-message-resolver.ts
  type SessionMessage (line 6) | type SessionMessage = {
  function isCompactionAgent (line 20) | function isCompactionAgent(agent: string | undefined): boolean {
  function hasFullAgentAndModel (line 24) | function hasFullAgentAndModel(message: StoredMessage): boolean {
  function hasPartialAgentOrModel (line 31) | function hasPartialAgentOrModel(message: StoredMessage): boolean {
  function convertSessionMessageToStoredMessage (line 37) | function convertSessionMessageToStoredMessage(message: SessionMessage): ...
  function mergeStoredMessages (line 61) | function mergeStoredMessages(
  function resolvePromptContextFromSessionMessages (line 115) | function resolvePromptContextFromSessionMessages(
  function findNearestMessageExcludingCompaction (line 126) | function findNearestMessageExcludingCompaction(

FILE: src/features/background-agent/concurrency.ts
  type QueueEntry (line 9) | interface QueueEntry {
  class ConcurrencyManager (line 15) | class ConcurrencyManager {
    method constructor (line 20) | constructor(config?: BackgroundTaskConfig) {
    method getConcurrencyLimit (line 24) | getConcurrencyLimit(model: string): number {
    method acquire (line 41) | async acquire(model: string): Promise<void> {
    method release (line 71) | release(model: string): void {
    method cancelWaiters (line 99) | cancelWaiters(model: string): void {
    method clear (line 116) | clear(): void {
    method getCount (line 127) | getCount(model: string): number {
    method getQueueLength (line 134) | getQueueLength(model: string): number {

FILE: src/features/background-agent/constants.ts
  constant TASK_TTL_MS (line 4) | const TASK_TTL_MS = 30 * 60 * 1000
  constant TERMINAL_TASK_TTL_MS (line 5) | const TERMINAL_TASK_TTL_MS = 30 * 60 * 1000
  constant MIN_STABILITY_TIME_MS (line 6) | const MIN_STABILITY_TIME_MS = 10 * 1000
  constant DEFAULT_STALE_TIMEOUT_MS (line 7) | const DEFAULT_STALE_TIMEOUT_MS = 1_200_000
  constant DEFAULT_MESSAGE_STALENESS_TIMEOUT_MS (line 8) | const DEFAULT_MESSAGE_STALENESS_TIMEOUT_MS = 1_800_000
  constant DEFAULT_MAX_TOOL_CALLS (line 9) | const DEFAULT_MAX_TOOL_CALLS = 4000
  constant DEFAULT_CIRCUIT_BREAKER_CONSECUTIVE_THRESHOLD (line 10) | const DEFAULT_CIRCUIT_BREAKER_CONSECUTIVE_THRESHOLD = 20
  constant DEFAULT_CIRCUIT_BREAKER_ENABLED (line 11) | const DEFAULT_CIRCUIT_BREAKER_ENABLED = true
  constant MIN_RUNTIME_BEFORE_STALE_MS (line 12) | const MIN_RUNTIME_BEFORE_STALE_MS = 30_000
  constant MIN_IDLE_TIME_MS (line 13) | const MIN_IDLE_TIME_MS = 5000
  constant POLLING_INTERVAL_MS (line 14) | const POLLING_INTERVAL_MS = 3000
  constant TASK_CLEANUP_DELAY_MS (line 15) | const TASK_CLEANUP_DELAY_MS = 10 * 60 * 1000
  constant TMUX_CALLBACK_DELAY_MS (line 16) | const TMUX_CALLBACK_DELAY_MS = 200
  type ProcessCleanupEvent (line 18) | type ProcessCleanupEvent = NodeJS.Signals | "beforeExit" | "exit"
  type OpencodeClient (line 20) | type OpencodeClient = PluginInput["client"]
  type MessagePartInfo (line 22) | interface MessagePartInfo {
  type EventProperties (line 28) | interface EventProperties {
  type BackgroundEvent (line 34) | interface BackgroundEvent {
  type Todo (line 39) | interface Todo {
  type QueueItem (line 46) | interface QueueItem {
  type SubagentSessionCreatedEvent (line 51) | interface SubagentSessionCreatedEvent {
  type OnSubagentSessionCreated (line 57) | type OnSubagentSessionCreated = (event: SubagentSessionCreatedEvent) => ...

FILE: src/features/background-agent/default-message-staleness-timeout.test.ts
  function createRunningTask (line 8) | function createRunningTask(startedAt: Date): BackgroundTask {

FILE: src/features/background-agent/duration-formatter.ts
  function formatDuration (line 1) | function formatDuration(start: Date, end?: Date): string {

FILE: src/features/background-agent/error-classifier.ts
  function isRecord (line 1) | function isRecord(value: unknown): value is Record<string, unknown> {
  function isAbortedSessionError (line 5) | function isAbortedSessionError(error: unknown): boolean {
  function getErrorText (line 10) | function getErrorText(error: unknown): string {
  function extractErrorName (line 27) | function extractErrorName(error: unknown): string | undefined {
  function extractErrorMessage (line 33) | function extractErrorMessage(error: unknown): string | undefined {
  type EventPropertiesLike (line 67) | interface EventPropertiesLike {
  function getSessionErrorMessage (line 71) | function getSessionErrorMessage(properties: EventPropertiesLike): string...

FILE: src/features/background-agent/fallback-retry-handler.test.ts
  function createMockTask (line 25) | function createMockTask(overrides: Partial<BackgroundTask> = {}): Backgr...
  function createMockConcurrencyManager (line 45) | function createMockConcurrencyManager(): ConcurrencyManager {
  function createMockClient (line 54) | function createMockClient() {
  function createDefaultArgs (line 62) | function createDefaultArgs(taskOverrides: Partial<BackgroundTask> = {}) {

FILE: src/features/background-agent/fallback-retry-handler.ts
  function tryFallbackRetry (line 14) | function tryFallbackRetry(args: {

FILE: src/features/background-agent/loop-detector.test.ts
  function buildWindow (line 9) | function buildWindow(
  function buildWindowWithInputs (line 21) | function buildWindowWithInputs(

FILE: src/features/background-agent/loop-detector.ts
  type CircuitBreakerSettings (line 9) | interface CircuitBreakerSettings {
  type ToolLoopDetectionResult (line 15) | interface ToolLoopDetectionResult {
  function resolveCircuitBreakerSettings (line 21) | function resolveCircuitBreakerSettings(
  function recordToolCall (line 33) | function recordToolCall(
  function sortObject (line 56) | function sortObject(obj: unknown): unknown {
  function createToolCallSignature (line 69) | function createToolCallSignature(
  function detectRepetitiveToolUse (line 82) | function detectRepetitiveToolUse(

FILE: src/features/background-agent/manager-circuit-breaker.test.ts
  function createManager (line 8) | function createManager(config?: BackgroundTaskConfig): BackgroundManager {
  function getTaskMap (line 32) | function getTaskMap(manager: BackgroundManager): Map<string, BackgroundT...
  function flushAsyncWork (line 36) | async function flushAsyncWork() {

FILE: src/features/background-agent/manager-shutdown-global-cleanup.test.ts
  function createTask (line 9) | function createTask(overrides: Partial<BackgroundTask> & { id: string; s...
  function createBackgroundManager (line 22) | function createBackgroundManager(): BackgroundManager {

FILE: src/features/background-agent/manager.polling.test.ts
  function createManagerWithStatus (line 7) | function createManagerWithStatus(statusImpl: () => Promise<{ data: Recor...
  function createRunningTask (line 57) | function createRunningTask(sessionID: string): BackgroundTask {
  function injectTask (line 72) | function injectTask(manager: BackgroundManager, task: BackgroundTask): v...
  function createManagerWithClient (line 77) | function createManagerWithClient(clientOverrides: Record<string, unknown...

FILE: src/features/background-agent/manager.test.ts
  constant TASK_TTL_MS (line 12) | const TASK_TTL_MS = 30 * 60 * 1000
  class MockBackgroundManager (line 14) | class MockBackgroundManager {
    method addTask (line 19) | addTask(task: BackgroundTask): void {
    method getTask (line 23) | getTask(id: string): BackgroundTask | undefined {
    method findBySession (line 27) | findBySession(sessionID: string): BackgroundTask | undefined {
    method getTasksByParentSession (line 36) | getTasksByParentSession(sessionID: string): BackgroundTask[] {
    method getAllDescendantTasks (line 46) | getAllDescendantTasks(sessionID: string): BackgroundTask[] {
    method markForNotification (line 61) | markForNotification(task: BackgroundTask): void {
    method getPendingNotifications (line 67) | getPendingNotifications(sessionID: string): BackgroundTask[] {
    method clearNotificationsForTask (line 71) | private clearNotificationsForTask(taskId: string): void {
    method pruneStaleTasksAndNotifications (line 82) | pruneStaleTasksAndNotifications(): { prunedTasks: string[]; prunedNoti...
    method getTaskCount (line 119) | getTaskCount(): number {
    method getNotificationCount (line 123) | getNotificationCount(): number {
    method resume (line 131) | resume(input: ResumeInput): BackgroundTask {
  function createMockTask (line 159) | function createMockTask(overrides: Partial<BackgroundTask> & { id: strin...
  function createBackgroundManager (line 171) | function createBackgroundManager(): BackgroundManager {
  function getConcurrencyManager (line 182) | function getConcurrencyManager(manager: BackgroundManager): ConcurrencyM...
  function getTaskMap (line 186) | function getTaskMap(manager: BackgroundManager): Map<string, BackgroundT...
  function getPendingByParent (line 190) | function getPendingByParent(manager: BackgroundManager): Map<string, Set...
  function getPendingNotifications (line 194) | function getPendingNotifications(manager: BackgroundManager): Map<string...
  function getCompletionTimers (line 198) | function getCompletionTimers(manager: BackgroundManager): Map<string, Re...
  function getQueuesByKey (line 202) | function getQueuesByKey(
  function processKeyForTest (line 210) | async function processKeyForTest(manager: BackgroundManager, key: string...
  function pruneStaleTasksAndNotificationsForTest (line 214) | function pruneStaleTasksAndNotificationsForTest(manager: BackgroundManag...
  function tryCompleteTaskForTest (line 218) | async function tryCompleteTaskForTest(manager: BackgroundManager, task: ...
  function stubNotifyParentSession (line 223) | function stubNotifyParentSession(manager: BackgroundManager): void {
  function flushBackgroundNotifications (line 227) | async function flushBackgroundNotifications(): Promise<void> {
  function createToastRemoveTaskTracker (line 233) | function createToastRemoveTaskTracker(): { removeTaskCalls: string[]; re...
  function getCleanupSignals (line 250) | function getCleanupSignals(): Array<NodeJS.Signals | "beforeExit" | "exi...
  function getListenerCounts (line 258) | function getListenerCounts(signals: Array<NodeJS.Signals | "beforeExit" ...
  type CurrentMessage (line 812) | interface CurrentMessage {
  function buildNotificationPromptBody (line 1184) | function buildNotificationPromptBody(
  type PromptAsyncBody (line 1448) | type PromptAsyncBody = Record<string, unknown> & { noReply?: boolean }
  function createMockClient (line 1734) | function createMockClient() {
  function createMockClientWithSessionChain (line 1749) | function createMockClientWithSessionChain(
  function setCompletionTimer (line 4013) | function setCompletionTimer(manager: BackgroundManager, taskId: string):...

FILE: src/features/background-agent/manager.ts
  type OpencodeClient (line 71) | type OpencodeClient = PluginInput["client"]
  type MessagePartInfo (line 74) | interface MessagePartInfo {
  type EventProperties (line 82) | interface EventProperties {
  type Event (line 88) | interface Event {
  function resolveMessagePartInfo (line 93) | function resolveMessagePartInfo(properties: EventProperties | undefined)...
  type Todo (line 106) | interface Todo {
  type QueueItem (line 113) | interface QueueItem {
  type SubagentSessionCreatedEvent (line 118) | interface SubagentSessionCreatedEvent {
  type OnSubagentSessionCreated (line 124) | type OnSubagentSessionCreated = (event: SubagentSessionCreatedEvent) => ...
  constant MAX_TASK_REMOVAL_RESCHEDULES (line 126) | const MAX_TASK_REMOVAL_RESCHEDULES = 6
  class BackgroundManager (line 128) | class BackgroundManager {
    method constructor (line 158) | constructor(
    method assertCanSpawn (line 185) | async assertCanSpawn(parentSessionID: string): Promise<SubagentSpawnCo...
    method reserveSubagentSpawn (line 210) | async reserveSubagentSpawn(parentSessionID: string): Promise<{
    method registerRootDescendant (line 235) | private registerRootDescendant(rootSessionID: string): number {
    method unregisterRootDescendant (line 241) | private unregisterRootDescendant(rootSessionID: string): void {
    method markPreStartDescendantReservation (line 251) | private markPreStartDescendantReservation(task: BackgroundTask): void {
    method settlePreStartDescendantReservation (line 255) | private settlePreStartDescendantReservation(task: BackgroundTask): void {
    method rollbackPreStartDescendantReservation (line 259) | private rollbackPreStartDescendantReservation(task: BackgroundTask): v...
    method launch (line 271) | async launch(input: LaunchInput): Promise<BackgroundTask> {
    method processKey (line 359) | private async processKey(key: string): Promise<void> {
    method startTask (line 400) | private async startTask(item: QueueItem): Promise<void> {
    method getTask (line 566) | getTask(id: string): BackgroundTask | undefined {
    method getTasksByParentSession (line 570) | getTasksByParentSession(sessionID: string): BackgroundTask[] {
    method getAllDescendantTasks (line 580) | getAllDescendantTasks(sessionID: string): BackgroundTask[] {
    method findBySession (line 595) | findBySession(sessionID: string): BackgroundTask | undefined {
    method getConcurrencyKeyFromInput (line 604) | private getConcurrencyKeyFromInput(input: LaunchInput): string {
    method trackTask (line 615) | async trackTask(input: {
    method resume (line 702) | async resume(input: ResumeInput): Promise<BackgroundTask> {
    method checkSessionTodos (line 841) | private async checkSessionTodos(sessionID: string): Promise<boolean> {
    method handleEvent (line 858) | handleEvent(event: Event): void {
    method tryFallbackRetry (line 1120) | private tryFallbackRetry(
    method markForNotification (line 1142) | markForNotification(task: BackgroundTask): void {
    method getPendingNotifications (line 1148) | getPendingNotifications(sessionID: string): BackgroundTask[] {
    method clearNotifications (line 1152) | clearNotifications(sessionID: string): void {
    method queuePendingNotification (line 1156) | queuePendingNotification(sessionID: string | undefined, notification: ...
    method injectPendingNotificationsIntoChatMessage (line 1163) | injectPendingNotificationsIntoChatMessage(output: { parts: Array<{ typ...
    method validateSessionHasOutput (line 1186) | private async validateSessionHasOutput(sessionID: string): Promise<boo...
    method clearNotificationsForTask (line 1242) | private clearNotificationsForTask(taskId: string): void {
    method cleanupPendingByParent (line 1257) | private cleanupPendingByParent(task: BackgroundTask): void {
    method clearTaskHistoryWhenParentTasksGone (line 1268) | private clearTaskHistoryWhenParentTasksGone(parentSessionID: string | ...
    method scheduleTaskRemoval (line 1275) | private scheduleTaskRemoval(taskId: string, rescheduleCount = 0): void {
    method cancelTask (line 1313) | async cancelTask(
    method cancelPendingTask (line 1401) | cancelPendingTask(taskId: string): boolean {
    method startPolling (line 1411) | private startPolling(): void {
    method stopPolling (line 1420) | private stopPolling(): void {
    method registerProcessCleanup (line 1427) | private registerProcessCleanup(): void {
    method unregisterProcessCleanup (line 1431) | private unregisterProcessCleanup(): void {
    method getRunningTasks (line 1439) | getRunningTasks(): BackgroundTask[] {
    method getNonRunningTasks (line 1446) | getNonRunningTasks(): BackgroundTask[] {
    method tryCompleteTask (line 1454) | private async tryCompleteTask(task: BackgroundTask, source: string): P...
    method notifyParentSession (line 1501) | private async notifyParentSession(task: BackgroundTask): Promise<void> {
    method hasRunningTasks (line 1687) | private hasRunningTasks(): boolean {
    method pruneStaleTasksAndNotifications (line 1694) | private pruneStaleTasksAndNotifications(): void {
    method checkAndInterruptStaleTasks (line 1744) | private async checkAndInterruptStaleTasks(
    method pollRunningTasks (line 1757) | private async pollRunningTasks(): Promise<void> {
    method shutdown (line 1855) | async shutdown(): Promise<void> {
    method enqueueNotificationForParent (line 1923) | private enqueueNotificationForParent(

FILE: src/features/background-agent/opencode-client.ts
  type OpencodeClient (line 3) | type OpencodeClient = PluginInput["client"]

FILE: src/features/background-agent/process-cleanup.ts
  type ProcessCleanupEvent (line 3) | type ProcessCleanupEvent = NodeJS.Signals | "beforeExit" | "exit"
  function registerProcessSignal (line 5) | function registerProcessSignal(
  type CleanupTarget (line 21) | interface CleanupTarget {
  function registerManagerForCleanup (line 29) | function registerManagerForCleanup(manager: CleanupTarget): void {
  function unregisterManagerForCleanup (line 61) | function unregisterManagerForCleanup(manager: CleanupTarget): void {
  function _resetForTesting (line 74) | function _resetForTesting(): void {

FILE: src/features/background-agent/remove-task-toast-tracking.ts
  function removeTaskToastTracking (line 3) | function removeTaskToastTracking(taskId: string): void {

FILE: src/features/background-agent/session-idle-event-handler.test.ts
  function createRunningTask (line 7) | function createRunningTask(overrides: Partial<BackgroundTask> = {}): Bac...

FILE: src/features/background-agent/session-idle-event-handler.ts
  function getString (line 5) | function getString(obj: Record<string, unknown>, key: string): string | ...
  function handleSessionIdleBackgroundEvent (line 10) | function handleSessionIdleBackgroundEvent(args: {

FILE: src/features/background-agent/session-status-classifier.ts
  constant ACTIVE_SESSION_STATUSES (line 3) | const ACTIVE_SESSION_STATUSES = new Set(["busy", "retry", "running"])
  constant KNOWN_TERMINAL_STATUSES (line 4) | const KNOWN_TERMINAL_STATUSES = new Set(["idle", "interrupted"])
  function isActiveSessionStatus (line 6) | function isActiveSessionStatus(type: string): boolean {
  function isTerminalSessionStatus (line 18) | function isTerminalSessionStatus(type: string): boolean {

FILE: src/features/background-agent/spawner.ts
  type SpawnerContext (line 10) | interface SpawnerContext {
  function createTask (line 19) | function createTask(input: LaunchInput): BackgroundTask {
  function startTask (line 35) | async function startTask(
  function resumeTask (line 156) | async function resumeTask(

FILE: src/features/background-agent/spawner/parent-directory-resolver.ts
  function resolveParentDirectory (line 4) | async function resolveParentDirectory(options: {

FILE: src/features/background-agent/state.ts
  class TaskStateManager (line 5) | class TaskStateManager {
    method getTask (line 12) | getTask(id: string): BackgroundTask | undefined {
    method findBySession (line 15) | findBySession(sessionID: string): BackgroundTask | undefined {
    method getTasksByParentSession (line 23) | getTasksByParentSession(sessionID: string): BackgroundTask[] {
    method getAllDescendantTasks (line 33) | getAllDescendantTasks(sessionID: string): BackgroundTask[] {
    method getRunningTasks (line 48) | getRunningTasks(): BackgroundTask[] {
    method getNonRunningTasks (line 51) | getNonRunningTasks(): BackgroundTask[] {
    method hasRunningTasks (line 55) | hasRunningTasks(): boolean {
    method getConcurrencyKeyFromInput (line 62) | getConcurrencyKeyFromInput(input: LaunchInput): string {
    method getConcurrencyKeyFromTask (line 69) | getConcurrencyKeyFromTask(task: BackgroundTask): string {
    method addTask (line 76) | addTask(task: BackgroundTask): void {
    method removeTask (line 80) | removeTask(taskId: string): void {
    method trackPendingTask (line 88) | trackPendingTask(parentSessionID: string, taskId: string): void {
    method cleanupPendingByParent (line 94) | cleanupPendingByParent(task: BackgroundTask): void {
    method markForNotification (line 105) | markForNotification(task: BackgroundTask): void {
    method getPendingNotifications (line 111) | getPendingNotifications(sessionID: string): BackgroundTask[] {
    method clearNotifications (line 115) | clearNotifications(sessionID: string): void {
    method clearNotificationsForTask (line 119) | clearNotificationsForTask(taskId: string): void {
    method addToQueue (line 130) | addToQueue(key: string, item: QueueItem): void {
    method getQueue (line 136) | getQueue(key: string): QueueItem[] | undefined {
    method removeFromQueue (line 140) | removeFromQueue(key: string, taskId: string): boolean {
    method setCompletionTimer (line 154) | setCompletionTimer(taskId: string, timer: ReturnType<typeof setTimeout...
    method clearCompletionTimer (line 158) | clearCompletionTimer(taskId: string): void {
    method clearAllCompletionTimers (line 166) | clearAllCompletionTimers(): void {
    method clear (line 173) | clear(): void {
    method cancelPendingTask (line 182) | cancelPendingTask(taskId: string): boolean {

FILE: src/features/background-agent/subagent-spawn-limits.test.ts
  function createMockClient (line 5) | function createMockClient(sessionGet: OpencodeClient["session"]["get"]):...

FILE: src/features/background-agent/subagent-spawn-limits.ts
  constant DEFAULT_MAX_SUBAGENT_DEPTH (line 4) | const DEFAULT_MAX_SUBAGENT_DEPTH = 3
  constant DEFAULT_MAX_ROOT_SESSION_SPAWN_BUDGET (line 5) | const DEFAULT_MAX_ROOT_SESSION_SPAWN_BUDGET = 50
  type SubagentSpawnContext (line 7) | interface SubagentSpawnContext {
  function getMaxSubagentDepth (line 13) | function getMaxSubagentDepth(config?: BackgroundTaskConfig): number {
  function getMaxRootSessionSpawnBudget (line 17) | function getMaxRootSessionSpawnBudget(config?: BackgroundTaskConfig): nu...
  function resolveSubagentSpawnContext (line 21) | async function resolveSubagentSpawnContext(
  function createSubagentDepthLimitError (line 74) | function createSubagentDepthLimitError(input: {
  function createSubagentDescendantLimitError (line 86) | function createSubagentDescendantLimitError(input: {

FILE: src/features/background-agent/task-completion-cleanup.test.ts
  type PromptAsyncCall (line 8) | type PromptAsyncCall = {
  type FakeTimers (line 16) | type FakeTimers = {
  function createTask (line 32) | function createTask(overrides: Partial<BackgroundTask> & { id: string; p...
  function createManager (line 50) | function createManager(enableParentSessionNotifications: boolean): {
  function installFakeTimers (line 86) | function installFakeTimers(): FakeTimers {
  function getTasks (line 131) | function getTasks(manager: BackgroundManager): Map<string, BackgroundTas...
  function getPendingByParent (line 135) | function getPendingByParent(manager: BackgroundManager): Map<string, Set...
  function getCompletionTimers (line 139) | function getCompletionTimers(manager: BackgroundManager): Map<string, Re...
  function notifyParentSessionForTest (line 143) | async function notifyParentSessionForTest(manager: BackgroundManager, ta...
  function getRequiredTimer (line 148) | function getRequiredTimer(manager: BackgroundManager, taskID: string): R...

FILE: src/features/background-agent/task-history-cleanup.test.ts
  function createManager (line 15) | function createManager(): BackgroundManager {
  function createTask (line 38) | function createTask(overrides: Partial<BackgroundTask> & { id: string; p...
  function getTaskMap (line 54) | function getTaskMap(manager: BackgroundManager): Map<string, BackgroundT...
  function pruneStaleTasksAndNotificationsForTest (line 58) | function pruneStaleTasksAndNotificationsForTest(manager: BackgroundManag...

FILE: src/features/background-agent/task-history.ts
  constant MAX_ENTRIES_PER_PARENT (line 3) | const MAX_ENTRIES_PER_PARENT = 100
  type TaskHistoryEntry (line 5) | interface TaskHistoryEntry {
  class TaskHistory (line 16) | class TaskHistory {
    method record (line 19) | record(parentSessionID: string | undefined, entry: TaskHistoryEntry): ...
    method getByParentSession (line 47) | getByParentSession(parentSessionID: string): TaskHistoryEntry[] {
    method clearSession (line 53) | clearSession(parentSessionID: string): void {
    method clearAll (line 57) | clearAll(): void {
    method formatForCompaction (line 61) | formatForCompaction(parentSessionID: string): string | null {

FILE: src/features/background-agent/task-poller.test.ts
  function createRunningTask (line 18) | function createRunningTask(overrides: Partial<BackgroundTask> = {}): Bac...
  function createTerminalTask (line 473) | function createTerminalTask(overrides: Partial<BackgroundTask> = {}): Ba...

FILE: src/features/background-agent/task-poller.ts
  constant TERMINAL_TASK_STATUSES (line 18) | const TERMINAL_TASK_STATUSES = new Set<BackgroundTask["status"]>([
  function pruneStaleTasksAndNotifications (line 25) | function pruneStaleTasksAndNotifications(args: {
  type SessionStatusMap (line 91) | type SessionStatusMap = Record<string, { type: string }>
  function checkAndInterruptStaleTasks (line 93) | async function checkAndInterruptStaleTasks(args: {

FILE: src/features/background-agent/types.ts
  type BackgroundTaskStatus (line 4) | type BackgroundTaskStatus =
  type ToolCallWindow (line 12) | interface ToolCallWindow {
  type TaskProgress (line 18) | interface TaskProgress {
  type BackgroundTask (line 28) | interface BackgroundTask {
  type LaunchInput (line 70) | interface LaunchInput {
  type ResumeInput (line 89) | interface ResumeInput {

FILE: src/features/boulder-state/constants.ts
  constant BOULDER_DIR (line 5) | const BOULDER_DIR = ".sisyphus"
  constant BOULDER_FILE (line 6) | const BOULDER_FILE = "boulder.json"
  constant BOULDER_STATE_PATH (line 7) | const BOULDER_STATE_PATH = `${BOULDER_DIR}/${BOULDER_FILE}`
  constant NOTEPAD_DIR (line 9) | const NOTEPAD_DIR = "notepads"
  constant NOTEPAD_BASE_PATH (line 10) | const NOTEPAD_BASE_PATH = `${BOULDER_DIR}/${NOTEPAD_DIR}`
  constant PROMETHEUS_PLANS_DIR (line 13) | const PROMETHEUS_PLANS_DIR = ".sisyphus/plans"

FILE: src/features/boulder-state/storage.ts
  constant RESERVED_KEYS (line 12) | const RESERVED_KEYS = new Set(["__proto__", "prototype", "constructor"])
  function getBoulderFilePath (line 14) | function getBoulderFilePath(directory: string): string {
  function readBoulderState (line 18) | function readBoulderState(directory: string): BoulderState | null {
  function writeBoulderState (line 43) | function writeBoulderState(directory: string, state: BoulderState): bool...
  function appendSessionId (line 59) | function appendSessionId(directory: string, sessionId: string): BoulderS...
  function clearBoulderState (line 79) | function clearBoulderState(directory: string): boolean {
  function getTaskSessionState (line 93) | function getTaskSessionState(directory: string, taskKey: string): TaskSe...
  function upsertTaskSessionState (line 102) | function upsertTaskSessionState(
  function findPrometheusPlans (line 145) | function findPrometheusPlans(directory: string): string[] {
  function getPlanProgress (line 171) | function getPlanProgress(planPath: string): PlanProgress {
  function getPlanName (line 199) | function getPlanName(planPath: string): string {
  function createBoulderState (line 206) | function createBoulderState(

FILE: src/features/boulder-state/top-level-task.test.ts
  function writePlanFile (line 8) | function writePlanFile(fileName: string, content: string): string {

FILE: src/features/boulder-state/top-level-task.ts
  constant TODO_HEADING_PATTERN (line 5) | const TODO_HEADING_PATTERN = /^##\s+TODOs\b/i
  constant FINAL_VERIFICATION_HEADING_PATTERN (line 6) | const FINAL_VERIFICATION_HEADING_PATTERN = /^##\s+Final Verification Wav...
  constant SECOND_LEVEL_HEADING_PATTERN (line 7) | const SECOND_LEVEL_HEADING_PATTERN = /^##\s+/
  constant UNCHECKED_CHECKBOX_PATTERN (line 8) | const UNCHECKED_CHECKBOX_PATTERN = /^(\s*)[-*]\s*\[\s*\]\s*(.+)$/
  constant TODO_TASK_PATTERN (line 9) | const TODO_TASK_PATTERN = /^(\d+)\.\s+(.+)$/
  constant FINAL_WAVE_TASK_PATTERN (line 10) | const FINAL_WAVE_TASK_PATTERN = /^(F\d+)\.\s+(.+)$/i
  type PlanSection (line 12) | type PlanSection = "todo" | "final-wave" | "other"
  function buildTaskRef (line 14) | function buildTaskRef(
  function readCurrentTopLevelTask (line 35) | function readCurrentTopLevelTask(planPath: string): TopLevelTaskRef | nu...

FILE: src/features/boulder-state/types.ts
  type BoulderState (line 8) | interface BoulderState {
  type PlanProgress (line 25) | interface PlanProgress {
  type TaskSessionState (line 34) | interface TaskSessionState {
  type TopLevelTaskRef (line 51) | interface TopLevelTaskRef {

FILE: src/features/builtin-commands/commands.ts
  constant BUILTIN_COMMAND_DEFINITIONS (line 10) | const BUILTIN_COMMAND_DEFINITIONS: Record<BuiltinCommandName, Omit<Comma...
  function loadBuiltinCommands (line 99) | function loadBuiltinCommands(

FILE: src/features/builtin-commands/templates/handoff.ts
  constant HANDOFF_TEMPLATE (line 1) | const HANDOFF_TEMPLATE = `# Handoff Command

FILE: src/features/builtin-commands/templates/init-deep.ts
  constant INIT_DEEP_TEMPLATE (line 1) | const INIT_DEEP_TEMPLATE = `# /init-deep

FILE: src/features/builtin-commands/templates/ralph-loop.ts
  constant RALPH_LOOP_TEMPLATE (line 1) | const RALPH_LOOP_TEMPLATE = `You are starting a Ralph Loop - a self-refe...
  constant ULW_LOOP_TEMPLATE (line 31) | const ULW_LOOP_TEMPLATE = `You are starting an ULTRAWORK Loop - a self-r...
  constant CANCEL_RALPH_TEMPLATE (line 59) | const CANCEL_RALPH_TEMPLATE = `Cancel the currently active Ralph Loop.

FILE: src/features/builtin-commands/templates/refactor.ts
  constant REFACTOR_TEMPLATE (line 1) | const REFACTOR_TEMPLATE = `# Intelligent Refactor Command

FILE: src/features/builtin-commands/templates/start-work.ts
  constant START_WORK_TEMPLATE (line 1) | const START_WORK_TEMPLATE = `You are starting a Sisyphus work session.

FILE: src/features/builtin-commands/templates/stop-continuation.ts
  constant STOP_CONTINUATION_TEMPLATE (line 1) | const STOP_CONTINUATION_TEMPLATE = `Stop all continuation mechanisms for...

FILE: src/features/builtin-commands/types.ts
  type BuiltinCommandName (line 3) | type BuiltinCommandName = "init-deep" | "ralph-loop" | "cancel-ralph" | ...
  type BuiltinCommandConfig (line 5) | interface BuiltinCommandConfig {
  type BuiltinCommands (line 9) | type BuiltinCommands = Record<string, CommandDefinition>

FILE: src/features/builtin-skills/skills.ts
  type CreateBuiltinSkillsOptions (line 13) | interface CreateBuiltinSkillsOptions {
  function createBuiltinSkills (line 18) | function createBuiltinSkills(options: CreateBuiltinSkillsOptions = {}): ...

FILE: src/features/builtin-skills/skills/git-master-skill-metadata.ts
  constant GIT_MASTER_SKILL_NAME (line 1) | const GIT_MASTER_SKILL_NAME = "git-master"
  constant GIT_MASTER_SKILL_DESCRIPTION (line 3) | const GIT_MASTER_SKILL_DESCRIPTION =

FILE: src/features/builtin-skills/types.ts
  type BuiltinSkill (line 3) | interface BuiltinSkill {

FILE: src/features/claude-code-agent-loader/claude-model-mapper.ts
  constant ANTHROPIC_PREFIX (line 4) | const ANTHROPIC_PREFIX = "anthropic/"
  constant CLAUDE_CODE_ALIAS_MAP (line 6) | const CLAUDE_CODE_ALIAS_MAP = new Map<string, string>([
  function mapClaudeModelString (line 12) | function mapClaudeModelString(model: string | undefined): string | undef...
  function mapClaudeModelToOpenCode (line 43) | function mapClaudeModelToOpenCode(

FILE: src/features/claude-code-agent-loader/loader.ts
  function parseToolsConfig (line 9) | function parseToolsConfig(toolsStr?: string): Record<string, boolean> | ...
  function loadAgentsFromDir (line 22) | function loadAgentsFromDir(agentsDir: string, scope: AgentScope): Loaded...
  function loadUserAgents (line 76) | function loadUserAgents(): Record<string, ClaudeCodeAgentConfig> {
  function loadProjectAgents (line 87) | function loadProjectAgents(directory?: string): Record<string, ClaudeCod...

FILE: src/features/claude-code-agent-loader/types.ts
  type AgentScope (line 3) | type AgentScope = "user" | "project"
  type ClaudeCodeAgentConfig (line 5) | type ClaudeCodeAgentConfig = Omit<AgentConfig, "model"> & {
  type AgentFrontmatter (line 9) | interface AgentFrontmatter {
  type LoadedAgent (line 17) | interface LoadedAgent {

FILE: src/features/claude-code-command-loader/loader.ts
  function loadCommandsFromDir (line 10) | async function loadCommandsFromDir(
  function commandsToRecord (line 102) | function commandsToRecord(commands: LoadedCommand[]): Record<string, Com...
  function loadUserCommands (line 111) | async function loadUserCommands(): Promise<Record<string, CommandDefinit...
  function loadProjectCommands (line 117) | async function loadProjectCommands(directory?: string): Promise<Record<s...
  function loadOpencodeGlobalCommands (line 123) | async function loadOpencodeGlobalCommands(): Promise<Record<string, Comm...
  function loadOpencodeProjectCommands (line 130) | async function loadOpencodeProjectCommands(directory?: string): Promise<...
  function loadAllCommands (line 136) | async function loadAllCommands(directory?: string): Promise<Record<strin...

FILE: src/features/claude-code-command-loader/types.ts
  type CommandScope (line 1) | type CommandScope = "user" | "project" | "opencode" | "opencode-project"
  type HandoffDefinition (line 8) | interface HandoffDefinition {
  type CommandDefinition (line 19) | interface CommandDefinition {
  type CommandFrontmatter (line 31) | interface CommandFrontmatter {
  type LoadedCommand (line 41) | interface LoadedCommand {

FILE: src/features/claude-code-mcp-loader/env-expander.ts
  function expandEnvVars (line 1) | function expandEnvVars(value: string): string {
  function expandEnvVarsInObject (line 13) | function expandEnvVarsInObject<T>(obj: T): T {

FILE: src/features/claude-code-mcp-loader/loader.test.ts
  constant TEST_DIR (line 6) | const TEST_DIR = join(tmpdir(), "mcp-loader-test-" + Date.now())
  constant TEST_HOME (line 7) | const TEST_HOME = join(TEST_DIR, "home")

FILE: src/features/claude-code-mcp-loader/loader.ts
  type McpConfigPath (line 14) | interface McpConfigPath {
  function getMcpConfigPaths (line 19) | function getMcpConfigPaths(): McpConfigPath[] {
  function loadMcpConfigFile (line 31) | async function loadMcpConfigFile(
  function getSystemMcpServerNames (line 47) | function getSystemMcpServerNames(): Set<string> {
  function loadMcpConfigs (line 71) | async function loadMcpConfigs(
  function formatLoadedServersForToast (line 121) | function formatLoadedServersForToast(

FILE: src/features/claude-code-mcp-loader/transformer.ts
  function transformMcpServer (line 9) | function transformMcpServer(

FILE: src/features/claude-code-mcp-loader/types.ts
  type McpScope (line 1) | type McpScope = "user" | "project" | "local"
  type ClaudeCodeMcpServer (line 3) | interface ClaudeCodeMcpServer {
  type ClaudeCodeMcpConfig (line 17) | interface ClaudeCodeMcpConfig {
  type McpLocalConfig (line 21) | interface McpLocalConfig {
  type McpRemoteConfig (line 28) | interface McpRemoteConfig {
  type McpServerConfig (line 35) | type McpServerConfig = McpLocalConfig | McpRemoteConfig
  type LoadedMcpServer (line 37) | interface LoadedMcpServer {
  type McpLoadResult (line 43) | interface McpLoadResult {

FILE: src/features/claude-code-plugin-loader/agent-loader.ts
  function parseToolsConfig (line 10) | function parseToolsConfig(toolsStr?: string): Record<string, boolean> | ...
  function loadPluginAgents (line 27) | function loadPluginAgents(plugins: LoadedPlugin[]): Record<string, Claud...

FILE: src/features/claude-code-plugin-loader/command-loader.ts
  function loadPluginCommands (line 10) | function loadPluginCommands(plugins: LoadedPlugin[]): Record<string, Com...

FILE: src/features/claude-code-plugin-loader/discovery.ts
  function getPluginsBaseDir (line 18) | function getPluginsBaseDir(): string {
  function getInstalledPluginsPath (line 25) | function getInstalledPluginsPath(): string {
  function loadInstalledPlugins (line 29) | function loadInstalledPlugins(): InstalledPluginsDatabase | null {
  function getClaudeSettingsPath (line 44) | function getClaudeSettingsPath(): string {
  function loadClaudeSettings (line 51) | function loadClaudeSettings(): ClaudeSettings | null {
  function loadPluginManifest (line 66) | function loadPluginManifest(installPath: string): PluginManifest | null {
  function derivePluginNameFromKey (line 81) | function derivePluginNameFromKey(pluginKey: string): string {
  function isPluginEnabled (line 86) | function isPluginEnabled(
  function v3EntryToInstallation (line 100) | function v3EntryToInstallation(entry: InstalledPluginEntryV3): PluginIns...
  function isValidV3Entry (line 111) | function isValidV3Entry(entry: unknown): entry is InstalledPluginEntryV3 {
  function extractPluginEntries (line 121) | function extractPluginEntries(
  function discoverInstalledPlugins (line 138) | function discoverInstalledPlugins(options?: PluginLoaderOptions): Plugin...

FILE: src/features/claude-code-plugin-loader/hook-loader.ts
  function loadPluginHooksConfigs (line 6) | function loadPluginHooksConfigs(plugins: LoadedPlugin[]): HooksConfig[] {

FILE: src/features/claude-code-plugin-loader/loader.ts
  type PluginComponentsResult (line 20) | interface PluginComponentsResult {
  function loadAllPluginComponents (line 30) | async function loadAllPluginComponents(options?: PluginLoaderOptions): P...

FILE: src/features/claude-code-plugin-loader/mcp-server-loader.ts
  function loadPluginMcpServers (line 10) | async function loadPluginMcpServers(

FILE: src/features/claude-code-plugin-loader/plugin-path-resolver.ts
  constant CLAUDE_PLUGIN_ROOT_VAR (line 1) | const CLAUDE_PLUGIN_ROOT_VAR = "${CLAUDE_PLUGIN_ROOT}"
  function resolvePluginPath (line 3) | function resolvePluginPath(path: string, pluginRoot: string): string {
  function resolvePluginPaths (line 7) | function resolvePluginPaths<T>(obj: T, pluginRoot: string): T {

FILE: src/features/claude-code-plugin-loader/skill-loader.ts
  function loadPluginSkillsAsCommands (line 12) | function loadPluginSkillsAsCommands(

FILE: src/features/claude-code-plugin-loader/types.ts
  type PluginScope (line 8) | type PluginScope = "user" | "project" | "local" | "managed"
  type PluginInstallation (line 13) | interface PluginInstallation {
  type InstalledPluginsDatabaseV1 (line 27) | interface InstalledPluginsDatabaseV1 {
  type InstalledPluginsDatabaseV2 (line 36) | interface InstalledPluginsDatabaseV2 {
  type InstalledPluginEntryV3 (line 46) | interface InstalledPluginEntryV3 {
  type InstalledPluginsDatabase (line 65) | type InstalledPluginsDatabase =
  type PluginAuthor (line 73) | interface PluginAuthor {
  type PluginManifest (line 83) | interface PluginManifest {
  type HookEntry (line 106) | type HookEntry =
  type HookMatcher (line 112) | interface HookMatcher {
  type HooksConfig (line 117) | interface HooksConfig {
  type PluginMcpServer (line 137) | interface PluginMcpServer {
  type McpServersConfig (line 147) | interface McpServersConfig {
  type LspServerConfig (line 154) | interface LspServerConfig {
  type LspServersConfig (line 173) | interface LspServersConfig {
  type LoadedPlugin (line 180) | interface LoadedPlugin {
  type PluginLoadResult (line 200) | interface PluginLoadResult {
  type PluginLoadError (line 205) | interface PluginLoadError {
  type ClaudeSettings (line 214) | interface ClaudeSettings {
  type PluginLoaderOptions (line 223) | interface PluginLoaderOptions {

FILE: src/features/claude-code-session-state/state.ts
  function setMainSession (line 6) | function setMainSession(id: string | undefined) {
  function getMainSessionID (line 10) | function getMainSessionID(): string | undefined {
  function _resetForTesting (line 15) | function _resetForTesting(): void {
  function setSessionAgent (line 24) | function setSessionAgent(sessionID: string, agent: string): void {
  function updateSessionAgent (line 30) | function updateSessionAgent(sessionID: string, agent: string): void {
  function getSessionAgent (line 34) | function getSessionAgent(sessionID: string): string | undefined {
  function clearSessionAgent (line 38) | function clearSessionAgent(sessionID: string): void {

FILE: src/features/claude-tasks/session-storage.test.ts
  constant TEST_DIR (line 12) | const TEST_DIR = ".test-session-storage"
  constant TEST_DIR_ABS (line 13) | const TEST_DIR_ABS = join(process.cwd(), TEST_DIR)
  function makeConfig (line 15) | function makeConfig(storagePath: string): Partial<OhMyOpenCodeConfig> {

FILE: src/features/claude-tasks/session-storage.ts
  function getSessionTaskDir (line 6) | function getSessionTaskDir(
  function listSessionTaskFiles (line 13) | function listSessionTaskFiles(
  function listAllSessionDirs (line 24) | function listAllSessionDirs(
  type TaskLocation (line 35) | interface TaskLocation {
  function findTaskAcrossSessions (line 40) | function findTaskAcrossSessions(

FILE: src/features/claude-tasks/storage.test.ts
  constant TEST_DIR (line 18) | const TEST_DIR = ".test-claude-tasks"
  constant TEST_DIR_ABS (line 19) | const TEST_DIR_ABS = join(process.cwd(), TEST_DIR)

FILE: src/features/claude-tasks/storage.ts
  function getTaskDir (line 8) | function getTaskDir(config: Partial<OhMyOpenCodeConfig> = {}): string {
  function sanitizePathSegment (line 21) | function sanitizePathSegment(value: string): string {
  function resolveTaskListId (line 25) | function resolveTaskListId(config: Partial<OhMyOpenCodeConfig> = {}): st...
  function ensureDir (line 38) | function ensureDir(dirPath: string): void {
  function readJsonSafe (line 44) | function readJsonSafe<T>(filePath: string, schema: z.ZodType<T>): T | nu...
  function writeJsonAtomic (line 64) | function writeJsonAtomic(filePath: string, data: unknown): void {
  constant STALE_LOCK_THRESHOLD_MS (line 85) | const STALE_LOCK_THRESHOLD_MS = 30000
  function generateTaskId (line 87) | function generateTaskId(): string {
  function listTaskFiles (line 91) | function listTaskFiles(config: Partial<OhMyOpenCodeConfig> = {}): string...
  function acquireLock (line 99) | function acquireLock(dirPath: string): { acquired: boolean; release: () ...

FILE: src/features/claude-tasks/types.ts
  type TaskStatus (line 4) | type TaskStatus = z.infer<typeof TaskStatusSchema>
  type Task (line 20) | type Task = z.infer<typeof TaskSchema>

FILE: src/features/context-injector/collector.ts
  constant PRIORITY_ORDER (line 8) | const PRIORITY_ORDER: Record<ContextPriority, number> = {
  constant CONTEXT_SEPARATOR (line 15) | const CONTEXT_SEPARATOR = "\n\n---\n\n"
  class ContextCollector (line 19) | class ContextCollector {
    method register (line 22) | register(sessionID: string, options: RegisterContextOptions): void {
    method getPending (line 42) | getPending(sessionID: string): PendingContext {
    method consume (line 63) | consume(sessionID: string): PendingContext {
    method clear (line 69) | clear(sessionID: string): void {
    method hasPending (line 73) | hasPending(sessionID: string): boolean {
    method sortEntries (line 78) | private sortEntries(entries: ContextEntry[]): ContextEntry[] {

FILE: src/features/context-injector/injector.ts
  type OutputPart (line 6) | interface OutputPart {
  type InjectionResult (line 12) | interface InjectionResult {
  function injectPendingContext (line 17) | function injectPendingContext(
  type ChatMessageInput (line 41) | interface ChatMessageInput {
  type ChatMessageOutput (line 48) | interface ChatMessageOutput {
  function createContextInjectorHook (line 53) | function createContextInjectorHook(collector: ContextCollector) {
  type MessageWithParts (line 70) | interface MessageWithParts {
  type MessagesTransformHook (line 75) | type MessagesTransformHook = {
  function createContextInjectorMessagesTransformHook (line 82) | function createContextInjectorMessagesTransformHook(

FILE: src/features/context-injector/types.ts
  type ContextSourceType (line 5) | type ContextSourceType =
  type ContextPriority (line 16) | type ContextPriority = "critical" | "high" | "normal" | "low"
  type ContextEntry (line 21) | interface ContextEntry {
  type RegisterContextOptions (line 39) | interface RegisterContextOptions {
  type PendingContext (line 55) | interface PendingContext {
  type MessageContext (line 68) | interface MessageContext {
  type OutputParts (line 84) | interface OutputParts {
  type InjectionStrategy (line 91) | type InjectionStrategy = "prepend-parts" | "storage" | "auto"

FILE: src/features/hook-message-injector/injector.test.ts
  function createMockClient (line 26) | function createMockClient(messages: Array<{

FILE: src/features/hook-message-injector/injector.ts
  type StoredMessage (line 11) | interface StoredMessage {
  type OpencodeClient (line 17) | type OpencodeClient = PluginInput["client"]
  type SDKMessage (line 19) | interface SDKMessage {
  function convertSDKMessageToStoredMessage (line 37) | function convertSDKMessageToStoredMessage(msg: SDKMessage): StoredMessag...
  function findNearestMessageWithFieldsFromSDK (line 67) | async function findNearestMessageWithFieldsFromSDK(
  function findFirstMessageWithAgentFromSDK (line 100) | async function findFirstMessageWithAgentFromSDK(
  function findNearestMessageWithFields (line 133) | function findNearestMessageWithFields(messageDir: string): StoredMessage...
  function findFirstMessageWithAgent (line 184) | function findFirstMessageWithAgent(messageDir: string): string | null {
  function generateMessageId (line 212) | function generateMessageId(): string {
  function generatePartId (line 216) | function generatePartId(): string {
  function getOrCreateMessageDir (line 220) | function getOrCreateMessageDir(sessionID: string): string {
  function injectHookMessage (line 259) | function injectHookMessage(
  function resolveMessageContext (line 360) | async function resolveMessageContext(

FILE: src/features/hook-message-injector/types.ts
  type ToolPermission (line 1) | type ToolPermission = boolean | "allow" | "deny" | "ask"
  type MessageMeta (line 3) | interface MessageMeta {
  type OriginalMessageContext (line 24) | interface OriginalMessageContext {
  type TextPart (line 38) | interface TextPart {

FILE: src/features/mcp-oauth/callback-server.ts
  constant DEFAULT_PORT (line 3) | const DEFAULT_PORT = 19877
  constant TIMEOUT_MS (line 4) | const TIMEOUT_MS = 5 * 60 * 1000
  type OAuthCallbackResult (line 6) | type OAuthCallbackResult = {
  type CallbackServer (line 11) | type CallbackServer = {
  constant SUCCESS_HTML (line 17) | const SUCCESS_HTML = `<!DOCTYPE html>
  function findAvailablePort (line 37) | async function findAvailablePort(startPort: number = DEFAULT_PORT): Prom...
  function startCallbackServer (line 41) | async function startCallbackServer(startPort: number = DEFAULT_PORT): Pr...

FILE: src/features/mcp-oauth/dcr.test.ts
  function createStorage (line 9) | function createStorage(initial: ClientCredentials | null):

FILE: src/features/mcp-oauth/dcr.ts
  type ClientRegistrationRequest (line 1) | type ClientRegistrationRequest = {
  type ClientCredentials (line 9) | type ClientCredentials = {
  type ClientRegistrationStorage (line 14) | type ClientRegistrationStorage = {
  type DynamicClientRegistrationOptions (line 22) | type DynamicClientRegistrationOptions = {
  type DcrFetch (line 33) | type DcrFetch = (
  function getOrRegisterClient (line 38) | async function getOrRegisterClient(
  function parseRegistrationResponse (line 83) | function parseRegistrationResponse(data: unknown): ClientCredentials | n...
  function isRecord (line 96) | function isRecord(value: unknown): value is Record<string, unknown> {

FILE: src/features/mcp-oauth/discovery.ts
  type OAuthServerMetadata (line 1) | interface OAuthServerMetadata {
  function parseHttpsUrl (line 11) | function parseHttpsUrl(value: string, label: string): URL {
  function readStringField (line 19) | function readStringField(source: Record<string, unknown>, field: string)...
  function fetchMetadata (line 27) | async function fetchMetadata(url: string): Promise<{ ok: true; json: Rec...
  function fetchAuthorizationServerMetadata (line 39) | async function fetchAuthorizationServerMetadata(issuer: string, resource...
  function parseAuthorizationServers (line 74) | function parseAuthorizationServers(metadata: Record<string, unknown>): s...
  function discoverOAuthServerMetadata (line 80) | async function discoverOAuthServerMetadata(resource: string): Promise<OA...
  function resetDiscoveryCache (line 120) | function resetDiscoveryCache(): void {

FILE: src/features/mcp-oauth/oauth-authorization-flow.ts
  type OAuthCallbackResult (line 5) | type OAuthCallbackResult = {
  function generateCodeVerifier (line 10) | function generateCodeVerifier(): string {
  function generateCodeChallenge (line 14) | function generateCodeChallenge(verifier: string): string {
  function buildAuthorizationUrl (line 18) | function buildAuthorizationUrl(
  constant CALLBACK_TIMEOUT_MS (line 45) | const CALLBACK_TIMEOUT_MS = 5 * 60 * 1000
  function startCallbackServer (line 47) | function startCallbackServer(port: number): Promise<OAuthCallbackResult> {
  function openBrowser (line 95) | function openBrowser(url: string): void {
  function runAuthorizationCodeRedirect (line 120) | async function runAuthorizationCodeRedirect(options: {

FILE: src/features/mcp-oauth/provider.ts
  type McpOAuthProviderOptions (line 16) | type McpOAuthProviderOptions = {
  class McpOAuthProvider (line 22) | class McpOAuthProvider {
    method constructor (line 30) | constructor(options: McpOAuthProviderOptions) {
    method tokens (line 36) | tokens(): OAuthTokenData | null {
    method saveTokens (line 40) | saveTokens(tokenData: OAuthTokenData): boolean {
    method clientInformation (line 44) | clientInformation(): ClientCredentials | null {
    method redirectUrl (line 54) | redirectUrl(): string {
    method saveCodeVerifier (line 58) | saveCodeVerifier(verifier: string): void {
    method codeVerifier (line 62) | codeVerifier(): string | null {
    method redirectToAuthorization (line 66) | async redirectToAuthorization(metadata: OAuthServerMetadata): Promise<...
    method login (line 89) | async login(): Promise<OAuthTokenData> {

FILE: src/features/mcp-oauth/resource-indicator.ts
  function getResourceIndicator (line 1) | function getResourceIndicator(url: string): string {
  function addResourceToParams (line 14) | function addResourceToParams(params: URLSearchParams, resource: string):...

FILE: src/features/mcp-oauth/schema.ts
  type McpOauth (line 8) | type McpOauth = z.infer<typeof McpOauthSchema>

FILE: src/features/mcp-oauth/step-up.ts
  type StepUpInfo (line 1) | interface StepUpInfo {
  function parseWwwAuthenticate (line 7) | function parseWwwAuthenticate(header: string): StepUpInfo | null {
  function extractParam (line 48) | function extractParam(params: string, name: string): string | null {
  function mergeScopes (line 60) | function mergeScopes(existing: string[], required: string[]): string[] {
  function isStepUpRequired (line 68) | function isStepUpRequired(statusCode: number, headers: Record<string, st...

FILE: src/features/mcp-oauth/storage.ts
  type OAuthTokenData (line 5) | interface OAuthTokenData {
  type TokenStore (line 15) | type TokenStore = Record<string, OAuthTokenData>
  constant STORAGE_FILE_NAME (line 17) | const STORAGE_FILE_NAME = "mcp-oauth.json"
  function getMcpOauthStoragePath (line 19) | function getMcpOauthStoragePath(): string {
  function normalizeHost (line 23) | function normalizeHost(serverHost: string): string {
  function normalizeResource (line 52) | function normalizeResource(resource: string): string {
  function buildKey (line 56) | function buildKey(serverHost: string, resource: string): string {
  function readStore (line 62) | function readStore(): TokenStore | null {
  function writeStore (line 76) | function writeStore(store: TokenStore): boolean {
  function loadToken (line 93) | function loadToken(serverHost: string, resource: string): OAuthTokenData...
  function saveToken (line 101) | function saveToken(serverHost: string, resource: string, token: OAuthTok...
  function deleteToken (line 108) | function deleteToken(serverHost: string, resource: string): boolean {
  function listTokensByHost (line 134) | function listTokensByHost(serverHost: string): TokenStore {
  function listAllTokens (line 151) | function listAllTokens(): TokenStore {

FILE: src/features/opencode-skill-loader/agents-skills-global.test.ts
  constant TEST_DIR (line 6) | const TEST_DIR = join(tmpdir(), "agents-global-skills-test-" + Date.now())
  constant TEMP_HOME (line 7) | const TEMP_HOME = join(TEST_DIR, "home")

FILE: src/features/opencode-skill-loader/allowed-tools-parser.ts
  function parseAllowedTools (line 1) | function parseAllowedTools(allowedTools: string | string[] | undefined):...

FILE: src/features/opencode-skill-loader/async-loader.test.ts
  constant TEST_DIR (line 7) | const TEST_DIR = join(tmpdir(), "async-loader-test-" + Date.now())
  constant SKILLS_DIR (line 8) | const SKILLS_DIR = join(TEST_DIR, ".opencode", "skills")
  function createTestSkill (line 10) | function createTestSkill(name: string, content: string, mcpJson?: object...
  function createDirectSkill (line 21) | function createDirectSkill(name: string, content: string): string {

FILE: src/features/opencode-skill-loader/async-loader.ts
  function mapWithConcurrency (line 13) | async function mapWithConcurrency<T, R>(
  function parseSkillMcpConfigFromFrontmatter (line 34) | function parseSkillMcpConfigFromFrontmatter(content: string): SkillMcpCo...
  function loadMcpJsonFromDirAsync (line 49) | async function loadMcpJsonFromDirAsync(skillDir: string): Promise<SkillM...
  function loadSkillFromPathAsync (line 74) | async function loadSkillFromPathAsync(
  function parseAllowedTools (line 133) | function parseAllowedTools(allowedTools: string | string[] | undefined):...
  function discoverSkillsInDirAsync (line 145) | async function discoverSkillsInDirAsync(skillsDir: string): Promise<Load...

FILE: src/features/opencode-skill-loader/blocking.test.ts
  constant TEST_DIR (line 8) | const TEST_DIR = join(tmpdir(), `blocking-test-${Date.now()}`)

FILE: src/features/opencode-skill-loader/blocking.ts
  type WorkerInput (line 4) | interface WorkerInput {
  type WorkerOutputSuccess (line 9) | interface WorkerOutputSuccess {
  type WorkerOutputError (line 14) | interface WorkerOutputError {
  type WorkerOutput (line 19) | type WorkerOutput = WorkerOutputSuccess | WorkerOutputError
  constant TIMEOUT_MS (line 21) | const TIMEOUT_MS = 30000
  function discoverAllSkillsBlocking (line 23) | function discoverAllSkillsBlocking(dirs: string[], scopes: SkillScope[])...

FILE: src/features/opencode-skill-loader/config-source-discovery.test.ts
  constant TEST_DIR (line 8) | const TEST_DIR = join(tmpdir(), `config-source-discovery-test-${Date.now...
  function writeSkill (line 10) | function writeSkill(path: string, name: string, description: string): vo...

FILE: src/features/opencode-skill-loader/config-source-discovery.ts
  constant MAX_RECURSIVE_DEPTH (line 11) | const MAX_RECURSIVE_DEPTH = 10
  function isHttpUrl (line 13) | function isHttpUrl(path: string): boolean {
  function toAbsolutePath (line 17) | function toAbsolutePath(path: string, configDir: string): string {
  function isMarkdownPath (line 24) | function isMarkdownPath(path: string): boolean {
  function normalizePathForGlob (line 28) | function normalizePathForGlob(path: string): string {
  function filterByGlob (line 32) | function filterByGlob(skills: LoadedSkill[], sourceBaseDir: string, glob...
  function loadSourcePath (line 42) | async function loadSourcePath(options: {
  function discoverConfigSourceSkills (line 78) | async function discoverConfigSourceSkills(options: {

FILE: src/features/opencode-skill-loader/discover-worker.ts
  type WorkerInput (line 6) | interface WorkerInput {
  type WorkerOutputSuccess (line 11) | interface WorkerOutputSuccess {
  type WorkerOutputError (line 16) | interface WorkerOutputError {

FILE: src/features/opencode-skill-loader/git-master-template-injection.test.ts
  constant SAMPLE_TEMPLATE (line 6) | const SAMPLE_TEMPLATE = [

FILE: src/features/opencode-skill-loader/git-master-template-injection.ts
  constant BASH_CODE_BLOCK_PATTERN (line 3) | const BASH_CODE_BLOCK_PATTERN = /```bash\r?\n([\s\S]*?)```/g
  constant LEADING_GIT_COMMAND_PATTERN (line 4) | const LEADING_GIT_COMMAND_PATTERN = /^([ \t]*(?:[A-Za-z_][A-Za-z0-9_]*=[...
  constant INLINE_GIT_COMMAND_PATTERN (line 5) | const INLINE_GIT_COMMAND_PATTERN = /([;&|()][ \t]*)git(?=[ \t]|$)/g
  function injectGitMasterConfig (line 7) | function injectGitMasterConfig(template: string, config?: GitMasterConfi...
  function injectGitEnvPrefix (line 31) | function injectGitEnvPrefix(template: string, prefix: string): string {
  function prefixGitCommandsInBashCodeBlocks (line 67) | function prefixGitCommandsInBashCodeBlocks(template: string, prefix: str...
  function prefixGitCommandsInCodeBlock (line 73) | function prefixGitCommandsInCodeBlock(codeBlock: string, prefix: string)...
  function buildCommitFooterInjection (line 87) | function buildCommitFooterInjection(

FILE: src/features/opencode-skill-loader/loaded-skill-from-path.ts
  function loadSkillFromPath (line 11) | async function loadSkillFromPath(options: {
  function inferSkillNameFromFileName (line 71) | function inferSkillNameFromFileName(filePath: string): string {

FILE: src/features/opencode-skill-loader/loaded-skill-template-extractor.ts
  function extractSkillTemplate (line 5) | function extractSkillTemplate(skill: LoadedSkill): string {

FILE: src/features/opencode-skill-loader/loader.test.ts
  constant TEST_DIR (line 6) | const TEST_DIR = join(tmpdir(), "skill-loader-test-" + Date.now())
  constant SKILLS_DIR (line 7) | const SKILLS_DIR = join(TEST_DIR, ".opencode", "skills")
  function createTestSkill (line 9) | function createTestSkill(name: string, content: string, mcpJson?: object...

FILE: src/features/opencode-skill-loader/loader.ts
  function loadUserSkills (line 12) | async function loadUserSkills(): Promise<Record<string, CommandDefinitio...
  function loadProjectSkills (line 18) | async function loadProjectSkills(directory?: string): Promise<Record<str...
  function loadOpencodeGlobalSkills (line 24) | async function loadOpencodeGlobalSkills(): Promise<Record<string, Comman...
  function loadOpencodeProjectSkills (line 32) | async function loadOpencodeProjectSkills(directory?: string): Promise<Re...
  type DiscoverSkillsOptions (line 38) | interface DiscoverSkillsOptions {
  function discoverAllSkills (line 43) | async function discoverAllSkills(directory?: string): Promise<LoadedSkil...
  function discoverSkills (line 65) | async function discoverSkills(options: DiscoverSkillsOptions = {}): Prom...
  function getSkillByName (line 96) | async function getSkillByName(name: string, options: DiscoverSkillsOptio...
  function discoverUserClaudeSkills (line 101) | async function discoverUserClaudeSkills(): Promise<LoadedSkill[]> {
  function discoverProjectClaudeSkills (line 106) | async function discoverProjectClaudeSkills(directory?: string): Promise<...
  function discoverOpencodeGlobalSkills (line 111) | async function discoverOpencodeGlobalSkills(): Promise<LoadedSkill[]> {
  function discoverOpencodeProjectSkills (line 119) | async function discoverOpencodeProjectSkills(directory?: string): Promis...
  function discoverProjectAgentsSkills (line 124) | async function discoverProjectAgentsSkills(directory?: string): Promise<...
  function discoverGlobalAgentsSkills (line 129) | async function discoverGlobalAgentsSkills(): Promise<LoadedSkill[]> {

FILE: src/features/opencode-skill-loader/merger.test.ts
  function createLoadedSkill (line 7) | function createLoadedSkill(scope: SkillScope, name: string, description:...

FILE: src/features/opencode-skill-loader/merger.ts
  type MergeSkillsOptions (line 10) | interface MergeSkillsOptions {
  function mergeSkills (line 14) | function mergeSkills(

FILE: src/features/opencode-skill-loader/merger/builtin-skill-converter.ts
  function builtinToLoadedSkill (line 5) | function builtinToLoadedSkill(builtin: BuiltinSkill): LoadedSkill {

FILE: src/features/opencode-skill-loader/merger/config-skill-entry-loader.ts
  function resolveFilePath (line 12) | function resolveFilePath(from: string, configDir?: string): string {
  function loadSkillFromFile (line 31) | function loadSkillFromFile(filePath: string): { template: string; metada...
  function configEntryToLoadedSkill (line 42) | function configEntryToLoadedSkill(

FILE: src/features/opencode-skill-loader/merger/scope-priority.ts
  constant SCOPE_PRIORITY (line 3) | const SCOPE_PRIORITY: Record<SkillScope, number> = {

FILE: src/features/opencode-skill-loader/merger/skill-definition-merger.ts
  function mergeSkillDefinitions (line 5) | function mergeSkillDefinitions(base: LoadedSkill, patch: SkillDefinition...

FILE: src/features/opencode-skill-loader/merger/skills-config-normalizer.ts
  function normalizeSkillsConfig (line 3) | function normalizeSkillsConfig(config: SkillsConfig | undefined): {

FILE: src/features/opencode-skill-loader/project-skill-tool-references.test.ts
  constant PROJECT_ROOT (line 7) | const PROJECT_ROOT = fileURLToPath(new URL("../../..", import.meta.url))
  function readProjectSkill (line 9) | async function readProjectSkill(...segments: string[]) {

FILE: src/features/opencode-skill-loader/skill-deduplication.ts
  function deduplicateSkillsByName (line 3) | function deduplicateSkillsByName(skills: LoadedSkill[]): LoadedSkill[] {

FILE: src/features/opencode-skill-loader/skill-definition-record.ts
  function skillsToCommandDefinitionRecord (line 4) | function skillsToCommandDefinitionRecord(skills: LoadedSkill[]): Record<...

FILE: src/features/opencode-skill-loader/skill-directory-loader.ts
  function loadSkillsFromDir (line 7) | async function loadSkillsFromDir(options: {

FILE: src/features/opencode-skill-loader/skill-discovery.ts
  function clearSkillCache (line 8) | function clearSkillCache(): void {
  function getAllSkills (line 12) | async function getAllSkills(options?: SkillResolutionOptions): Promise<L...

FILE: src/features/opencode-skill-loader/skill-mcp-config.ts
  function parseSkillMcpConfigFromFrontmatter (line 6) | function parseSkillMcpConfigFromFrontmatter(content: string): SkillMcpCo...
  function loadMcpJsonFromDir (line 21) | async function loadMcpJsonFromDir(skillDir: string): Promise<SkillMcpCon...

FILE: src/features/opencode-skill-loader/skill-resolution-options.ts
  type SkillResolutionOptions (line 3) | interface SkillResolutionOptions {

FILE: src/features/opencode-skill-loader/skill-template-resolver.ts
  function resolveSkillContent (line 8) | function resolveSkillContent(skillName: string, options?: SkillResolutio...
  function resolveMultipleSkills (line 23) | function resolveMultipleSkills(
  function resolveSkillContentAsync (line 52) | async function resolveSkillContentAsync(
  function resolveMultipleSkillsAsync (line 69) | async function resolveMultipleSkillsAsync(

FILE: src/features/opencode-skill-loader/types.ts
  type SkillScope (line 4) | type SkillScope = "builtin" | "config" | "user" | "project" | "opencode"...
  type SkillMetadata (line 6) | interface SkillMetadata {
  type LazyContentLoader (line 20) | interface LazyContentLoader {
  type LoadedSkill (line 26) | interface LoadedSkill {

FILE: src/features/run-continuation-state/constants.ts
  constant CONTINUATION_MARKER_DIR (line 1) | const CONTINUATION_MARKER_DIR = ".sisyphus/run-continuation"

FILE: src/features/run-continuation-state/storage.test.ts
  function createTempDir (line 14) | function createTempDir(): string {

FILE: src/features/run-continuation-state/storage.ts
  function getMarkerPath (line 10) | function getMarkerPath(directory: string, sessionID: string): string {
  function readContinuationMarker (line 14) | function readContinuationMarker(
  function setContinuationMarkerSource (line 31) | function setContinuationMarkerSource(
  function clearContinuationMarker (line 59) | function clearContinuationMarker(directory: string, sessionID: string): ...
  function isContinuationMarkerActive (line 69) | function isContinuationMarkerActive(marker: ContinuationMarker | null): ...
  function getActiveContinuationMarkerReason (line 74) | function getActiveContinuationMarkerReason(marker: ContinuationMarker | ...

FILE: src/features/run-continuation-state/types.ts
  type ContinuationMarkerSource (line 1) | type ContinuationMarkerSource = "todo" | "stop"
  type ContinuationMarkerState (line 3) | type ContinuationMarkerState = "idle" | "active" | "stopped"
  type ContinuationMarkerSourceEntry (line 5) | interface ContinuationMarkerSourceEntry {
  type ContinuationMarker (line 11) | interface ContinuationMarker {

FILE: src/features/skill-mcp-manager/cleanup.ts
  function closeManagedClient (line 3) | async function closeManagedClient(managed: ManagedClient): Promise<void> {
  function registerProcessCleanup (line 17) | function registerProcessCleanup(state: SkillMcpManagerState): void {
  function unregisterProcessCleanup (line 49) | function unregisterProcessCleanup(state: SkillMcpManagerState): void {
  function startCleanupTimer (line 58) | function startCleanupTimer(state: SkillMcpManagerState): void {
  function stopCleanupTimer (line 68) | function stopCleanupTimer(state: SkillMcpManagerState): void {
  function cleanupIdleClients (line 74) | async function cleanupIdleClients(state: SkillMcpManagerState): Promise<...
  function disconnectSession (line 90) | async function disconnectSession(state: SkillMcpManagerState, sessionID:...
  function disconnectAll (line 128) | async function disconnectAll(state: SkillMcpManagerState): Promise<void> {
  function forceReconnect (line 146) | async function forceReconnect(state: SkillMcpManagerState, clientKey: st...

FILE: src/features/skill-mcp-manager/connection-race.test.ts
  type Deferred (line 5) | type Deferred<TValue> = {
  class MockClient (line 16) | class MockClient {
    method constructor (line 19) | constructor(
    method connect (line 26) | async connect(_transport: MockStdioClientTransport): Promise<void> {
  class MockStdioClientTransport (line 34) | class MockStdioClientTransport {
    method constructor (line 37) | constructor(_options: { command: string; args?: string[]; env?: Record...
  function createDeferred (line 53) | function createDeferred<TValue>(): Deferred<TValue> {
  function createState (line 72) | function createState(): SkillMcpManagerState {
  function createClientInfo (line 91) | function createClientInfo(sessionID: string): SkillMcpClientInfo {
  function createClientKey (line 99) | function createClientKey(info: SkillMcpClientInfo): string {

FILE: src/features/skill-mcp-manager/connection-type.ts
  function getConnectionType (line 8) | function getConnectionType(config: ClaudeCodeMcpServer): ConnectionType ...

FILE: src/features/skill-mcp-manager/connection.ts
  function removeClientIfCurrent (line 10) | function removeClientIfCurrent(state: SkillMcpManagerState, clientKey: s...
  function getOrCreateClient (line 17) | async function getOrCreateClient(params: {
  function getOrCreateClientWithRetryImpl (line 91) | async function getOrCreateClientWithRetryImpl(params: {
  function createClient (line 110) | async function createClient(params: {

FILE: src/features/skill-mcp-manager/disconnect-cleanup.test.ts
  function createState (line 19) | function createState(): SkillMcpManagerState {
  function createManagedClient (line 38) | function createManagedClient(skillName: string): ManagedClient {

FILE: src/features/skill-mcp-manager/env-cleaner.ts
  constant EXCLUDED_ENV_PATTERNS (line 3) | const EXCLUDED_ENV_PATTERNS: RegExp[] = [
  function createCleanMcpEnvironment (line 28) | function createCleanMcpEnvironment(

FILE: src/features/skill-mcp-manager/http-client.ts
  function redactUrl (line 7) | function redactUrl(urlStr: string): string {
  function createHttpClient (line 25) | async function createHttpClient(params: SkillMcpClientConnectionParams):...

FILE: src/features/skill-mcp-manager/manager.test.ts
  method constructor (line 13) | constructor(public url: URL, public options?: { requestInit?: RequestIni...
  method start (line 16) | async start() {
  method close (line 19) | async close() {
  method constructor (line 30) | constructor(public options: { serverUrl: string; clientId?: string; scop...
  method tokens (line 31) | tokens() {
  method login (line 34) | async login() {

FILE: src/features/skill-mcp-manager/manager.ts
  class SkillMcpManager (line 9) | class SkillMcpManager {
    method getClientKey (line 24) | private getClientKey(info: SkillMcpClientInfo): string {
    method getOrCreateClient (line 28) | async getOrCreateClient(info: SkillMcpClientInfo, config: ClaudeCodeMc...
    method disconnectSession (line 38) | async disconnectSession(sessionID: string): Promise<void> {
    method disconnectAll (line 42) | async disconnectAll(): Promise<void> {
    method listTools (line 46) | async listTools(info: SkillMcpClientInfo, context: SkillMcpServerConte...
    method listResources (line 52) | async listResources(info: SkillMcpClientInfo, context: SkillMcpServerC...
    method listPrompts (line 58) | async listPrompts(info: SkillMcpClientInfo, context: SkillMcpServerCon...
    method callTool (line 64) | async callTool(
    method readResource (line 76) | async readResource(info: SkillMcpClientInfo, context: SkillMcpServerCo...
    method getPrompt (line 83) | async getPrompt(
    method withOperationRetry (line 95) | private async withOperationRetry<T>(
    method getOrCreateClientWithRetry (line 137) | private async getOrCreateClientWithRetry(info: SkillMcpClientInfo, con...
    method getConnectedServers (line 147) | getConnectedServers(): string[] {
    method isConnected (line 151) | isConnected(info: SkillMcpClientInfo): boolean {

FILE: src/features/skill-mcp-manager/oauth-handler.ts
  function getOrCreateAuthProvider (line 6) | function getOrCreateAuthProvider(
  function isTokenExpired (line 23) | function isTokenExpired(tokenData: OAuthTokenData): boolean {
  function buildHttpRequestInit (line 28) | async function buildHttpRequestInit(
  function handleStepUpIfNeeded (line 60) | async function handleStepUpIfNeeded(params: {

FILE: src/features/skill-mcp-manager/stdio-client.ts
  function getStdioCommand (line 8) | function getStdioCommand(config: ClaudeCodeMcpServer, serverName: string...
  function createStdioClient (line 15) | async function createStdioClient(params: SkillMcpClientConnectionParams)...

FILE: src/features/skill-mcp-manager/types.ts
  type SkillMcpConfig (line 7) | type SkillMcpConfig = Record<string, ClaudeCodeMcpServer>
  type SkillMcpClientInfo (line 9) | interface SkillMcpClientInfo {
  type SkillMcpServerContext (line 15) | interface SkillMcpServerContext {
  type ConnectionType (line 25) | type ConnectionType = "stdio" | "http"
  type ManagedClientBase (line 27) | interface ManagedClientBase {
  type ManagedStdioClient (line 34) | interface ManagedStdioClient extends ManagedClientBase {
  type ManagedHttpClient (line 39) | interface ManagedHttpClient extends ManagedClientBase {
  type ManagedClient (line 44) | type ManagedClient = ManagedStdioClient | ManagedHttpClient
  type ProcessCleanupHandler (line 46) | interface ProcessCleanupHandler {
  type SkillMcpManagerState (line 51) | interface SkillMcpManagerState {
  type SkillMcpClientConnectionParams (line 65) | interface SkillMcpClientConnectionParams {

FILE: src/features/task-toast-manager/manager.test.ts
  type TaskToastManagerClass (line 5) | type TaskToastManagerClass = typeof import("./manager").TaskToastManager

FILE: src/features/task-toast-manager/manager.ts
  type OpencodeClient (line 5) | type OpencodeClient = PluginInput["client"]
  type ClientWithTui (line 7) | type ClientWithTui = {
  class TaskToastManager (line 13) | class TaskToastManager {
    method constructor (line 18) | constructor(client: OpencodeClient, concurrencyManager?: ConcurrencyMa...
    method setConcurrencyManager (line 23) | setConcurrencyManager(manager: ConcurrencyManager): void {
    method addTask (line 27) | addTask(task: {
    method updateTask (line 58) | updateTask(id: string, status: TaskStatus): void {
    method updateTaskModelBySession (line 68) | updateTaskModelBySession(sessionID: string, modelInfo: ModelFallbackIn...
    method removeTask (line 80) | removeTask(id: string): void {
    method getRunningTasks (line 87) | getRunningTasks(): TrackedTask[] {
    method getQueuedTasks (line 97) | getQueuedTasks(): TrackedTask[] {
    method formatDuration (line 106) | private formatDuration(startedAt: Date): string {
    method getConcurrencyInfo (line 115) | private getConcurrencyInfo(): string {
    method buildTaskListMessage (line 125) | private buildTaskListMessage(newTask: TrackedTask): string {
    method showTaskListToast (line 185) | private showTaskListToast(newTask: TrackedTask): void {
    method showCompletionToast (line 210) | showCompletionToast(task: { id: string; description: string; duration:...
  function getTaskToastManager (line 237) | function getTaskToastManager(): TaskToastManager | null {
  function initTaskToastManager (line 241) | function initTaskToastManager(
  function _resetTaskToastManagerForTesting (line 249) | function _resetTaskToastManagerForTesting(): void {

FILE: src/features/task-toast-manager/types.ts
  type TaskStatus (line 3) | type TaskStatus = "running" | "queued" | "completed" | "error"
  type ModelFallbackInfo (line 5) | interface ModelFallbackInfo {
  type TrackedTask (line 11) | interface TrackedTask {
  type TaskToastOptions (line 24) | interface TaskToastOptions {

FILE: src/features/tmux-subagent/action-executor-core.ts
  type ActionResult (line 5) | interface ActionResult {
  type ExecuteContext (line 11) | interface ExecuteContext {
  type ActionExecutorDeps (line 17) | interface ActionExecutorDeps {
  function enforceMainPane (line 25) | async function enforceMainPane(
  function executeActionWithDeps (line 38) | async function executeActionWithDeps(

FILE: src/features/tmux-subagent/action-executor.test.ts
  function createConfig (line 21) | function createConfig(overrides?: Partial<TmuxConfig>): TmuxConfig {
  function createWindowState (line 32) | function createWindowState(overrides?: Partial<WindowState>): WindowState {
  function createContext (line 50) | function createContext(overrides?: Partial<ExecuteContext>): ExecuteCont...

FILE: src/features/tmux-subagent/action-executor.ts
  type ExecuteActionsResult (line 20) | interface ExecuteActionsResult {
  type ExecuteContext (line 26) | interface ExecuteContext {
  function enforceMainPane (line 33) | async function enforceMainPane(
  function enforceLayoutAndMainPane (line 45) | async function enforceLayoutAndMainPane(ctx: ExecuteContext): Promise<vo...
  function executeAction (line 66) | async function executeAction(
  function executeActions (line 114) | async function executeActions(

FILE: src/features/tmux-subagent/cleanup.ts
  function cleanupTmuxSessions (line 7) | async function cleanupTmuxSessions(params: {

FILE: src/features/tmux-subagent/decision-engine.test.ts
  constant MIN_SPLIT_WIDTH (line 14) | const MIN_SPLIT_WIDTH = 2 * MIN_PANE_WIDTH + 1
  constant MIN_SPLIT_HEIGHT (line 15) | const MIN_SPLIT_HEIGHT = 2 * MIN_PANE_HEIGHT + 1

FILE: src/features/tmux-subagent/grid-planning.ts
  type GridCapacity (line 9) | interface GridCapacity {
  type GridSlot (line 15) | interface GridSlot {
  type GridPlan (line 20) | interface GridPlan {
  type CapacityOptions (line 27) | type CapacityOptions = CapacityConfig | number | undefined
  function resolveMinPaneWidth (line 29) | function resolveMinPaneWidth(options?: CapacityOptions): number {
  function resolveAgentAreaWidth (line 39) | function resolveAgentAreaWidth(windowWidth: number, options?: CapacityOp...
  function calculateCapacity (line 46) | function calculateCapacity(
  function computeGridPlan (line 78) | function computeGridPlan(
  function mapPaneToSlot (line 118) | function mapPaneToSlot(

FILE: src/features/tmux-subagent/layout-config.test.ts
  function createState (line 5) | function createState(

FILE: src/features/tmux-subagent/manager.test.ts
  type ExecuteActionsResult (line 8) | type ExecuteActionsResult = {
  function createMockContext (line 78) | function createMockContext(overrides?: {
  function createSessionCreatedEvent (line 107) | function createSessionCreatedEvent(
  function createWindowState (line 120) | function createWindowState(overrides?: Partial<WindowState>): WindowState {

FILE: src/features/tmux-subagent/manager.ts
  type OpencodeClient (line 17) | type OpencodeClient = PluginInput["client"]
  type SessionCreatedEvent (line 19) | interface SessionCreatedEvent {
  type DeferredSession (line 24) | interface DeferredSession {
  type TmuxUtilDeps (line 30) | interface TmuxUtilDeps {
  constant DEFERRED_SESSION_TTL_MS (line 40) | const DEFERRED_SESSION_TTL_MS = 5 * 60 * 1000
  constant MAX_DEFERRED_QUEUE_SIZE (line 41) | const MAX_DEFERRED_QUEUE_SIZE = 20
  constant MAX_CLOSE_RETRY_COUNT (line 42) | const MAX_CLOSE_RETRY_COUNT = 3
  class TmuxSessionManager (line 56) | class TmuxSessionManager {
    method constructor (line 71) | constructor(ctx: PluginInput, tmuxConfig: TmuxConfig, deps: TmuxUtilDe...
    method isEnabled (line 94) | private isEnabled(): boolean {
    method getCapacityConfig (line 98) | private getCapacityConfig(): CapacityConfig {
    method getSessionMappings (line 107) | private getSessionMappings(): SessionMapping[] {
    method removeTrackedSession (line 115) | private removeTrackedSession(sessionId: string): void {
    method markSessionClosePending (line 123) | private markSessionClosePending(sessionId: string): void {
    method queryWindowStateSafely (line 135) | private async queryWindowStateSafely(): Promise<WindowState | null> {
    method tryCloseTrackedSession (line 148) | private async tryCloseTrackedSession(tracked: TrackedSession): Promise...
    method retryPendingCloses (line 174) | private async retryPendingCloses(): Promise<void> {
    method enqueueDeferredSession (line 232) | private enqueueDeferredSession(sessionId: string, title: string): void {
    method removeDeferredSession (line 255) | private removeDeferredSession(sessionId: string): void {
    method startDeferredAttachLoop (line 267) | private startDeferredAttachLoop(): void {
    method stopDeferredAttachLoop (line 286) | private stopDeferredAttachLoop(): void {
    method tryAttachDeferredSession (line 295) | private async tryAttachDeferredSession(): Promise<void> {
    method waitForSessionReady (line 400) | private async waitForSessionReady(sessionId: string): Promise<boolean> {
    method onSessionCreated (line 430) | async onSessionCreated(event: SessionCreatedEvent): Promise<void> {
    method enqueueSpawn (line 590) | private async enqueueSpawn(run: () => Promise<void>): Promise<void> {
    method onSessionDeleted (line 602) | async onSessionDeleted(event: { sessionID: string }): Promise<void> {
    method closeSessionById (line 650) | private async closeSessionById(sessionId: string): Promise<void> {
    method createEventHandler (line 678) | createEventHandler(): (input: { event: { type: string; properties?: un...
    method cleanup (line 684) | async cleanup(): Promise<void> {

FILE: src/features/tmux-subagent/oldest-agent-pane.ts
  type SessionMapping (line 3) | interface SessionMapping {
  function findOldestAgentPane (line 9) | function findOldestAgentPane(

FILE: src/features/tmux-subagent/pane-split-availability.ts
  function getMinSplitWidth (line 10) | function getMinSplitWidth(minPaneWidth?: number): number {
  function getColumnCount (line 15) | function getColumnCount(paneCount: number): number {
  function getColumnWidth (line 20) | function getColumnWidth(agentAreaWidth: number, paneCount: number): numb...
  function isSplittableAtCount (line 26) | function isSplittableAtCount(
  function findMinimalEvictions (line 35) | function findMinimalEvictions(
  function canSplitPane (line 48) | function canSplitPane(
  function canSplitPaneAnyDirection (line 59) | function canSplitPaneAnyDirection(
  function getBestSplitDirection (line 66) | function getBestSplitDirection(

FILE: src/features/tmux-subagent/pane-state-parser.ts
  constant MANDATORY_PANE_FIELD_COUNT (line 3) | const MANDATORY_PANE_FIELD_COUNT = 8
  type ParsedPaneState (line 5) | type ParsedPaneState = {
  type ParsedPaneLine (line 11) | type ParsedPaneLine = {
  type MandatoryPaneFields (line 17) | type MandatoryPaneFields = [
  function parsePaneStateOutput (line 28) | function parsePaneStateOutput(stdout: string): ParsedPaneState | null {
  function parsePaneLine (line 52) | function parsePaneLine(line: string): ParsedPaneLine | null {
  function getMandatoryPaneFields (line 94) | function getMandatoryPaneFields(fields: string[]): MandatoryPaneFields |...
  function parseInteger (line 124) | function parseInteger(value: string): number | null {
  function parseActiveValue (line 131) | function parseActiveValue(value: string): boolean | null {

FILE: src/features/tmux-subagent/pane-state-querier.ts
  function queryWindowState (line 7) | async function queryWindowState(sourcePaneId: string): Promise<WindowSta...

FILE: src/features/tmux-subagent/polling-constants.ts
  constant SESSION_TIMEOUT_MS (line 1) | const SESSION_TIMEOUT_MS = 10 * 60 * 1000
  constant MIN_STABILITY_TIME_MS (line 5) | const MIN_STABILITY_TIME_MS = 10 * 1000
  constant STABLE_POLLS_REQUIRED (line 6) | const STABLE_POLLS_REQUIRED = 3

FILE: src/features/tmux-subagent/polling-manager.ts
  constant SESSION_TIMEOUT_MS (line 8) | const SESSION_TIMEOUT_MS = 10 * 60 * 1000
  constant MIN_STABILITY_TIME_MS (line 9) | const MIN_STABILITY_TIME_MS = 10 * 1000
  constant STABLE_POLLS_REQUIRED (line 10) | const STABLE_POLLS_REQUIRED = 3
  class TmuxPollingManager (line 12) | class TmuxPollingManager {
    method constructor (line 16) | constructor(
    method startPolling (line 22) | startPolling(): void {
    method stopPolling (line 32) | stopPolling(): void {
    method pollSessions (line 40) | private async pollSessions(): Promise<void> {

FILE: src/features/tmux-subagent/polling.ts
  type OpencodeClient (line 20) | type OpencodeClient = PluginInput["client"]
  type SessionPollingController (line 22) | interface SessionPollingController {
  function createSessionPollingController (line 30) | function createSessionPollingController(params: {

FILE: src/features/tmux-subagent/session-created-event.ts
  type UnknownRecord (line 1) | type UnknownRecord = Record<string, unknown>
  function isRecord (line 3) | function isRecord(value: unknown): value is UnknownRecord {
  function getNestedRecord (line 7) | function getNestedRecord(value: unknown, key: string): UnknownRecord | u...
  function getNestedString (line 13) | function getNestedString(value: unknown, key: string): string | undefined {
  type SessionCreatedEvent (line 19) | interface SessionCreatedEvent {
  function coerceSessionCreatedEvent (line 24) | function coerceSessionCreatedEvent(input: {

FILE: src/features/tmux-subagent/session-created-handler.ts
  type OpencodeClient (line 11) | type OpencodeClient = PluginInput["client"]
  type SessionCreatedHandlerDeps (line 13) | interface SessionCreatedHandlerDeps {
  function handleSessionCreated (line 28) | async function handleSessionCreated(

FILE: src/features/tmux-subagent/session-deleted-handler.ts
  type SessionDeletedHandlerDeps (line 8) | interface SessionDeletedHandlerDeps {
  function handleSessionDeleted (line 18) | async function handleSessionDeleted(

FILE: src/features/tmux-subagent/session-message-count.ts
  function getMessageCount (line 1) | function getMessageCount(data: unknown): number {

FILE: src/features/tmux-subagent/session-ready-waiter.ts
  type OpencodeClient (line 9) | type OpencodeClient = PluginInput["client"]
  function waitForSessionReady (line 11) | async function waitForSessionReady(params: {

FILE: src/features/tmux-subagent/session-status-parser.ts
  type SessionStatus (line 1) | type SessionStatus = { type: string }
  function parseSessionStatusMap (line 3) | function parseSessionStatusMap(data: unknown): Record<string, SessionSta...

FILE: src/features/tmux-subagent/spawn-action-decider.ts
  function getInitialSplitDirection (line 17) | function getInitialSplitDirection(layout?: string): "-h" | "-v" {
  function isStrictMainLayout (line 21) | function isStrictMainLayout(layout?: string): boolean {
  function decideSpawnActions (line 25) | function decideSpawnActions(
  function decideCloseAction (line 135) | function decideCloseAction(

FILE: src/features/tmux-subagent/spawn-target-finder.ts
  type SpawnTarget (line 6) | interface SpawnTarget {
  function isStrictMainVertical (line 11) | function isStrictMainVertical(config: CapacityConfig): boolean {
  function isStrictMainHorizontal (line 15) | function isStrictMainHorizontal(config: CapacityConfig): boolean {
  function isStrictMainLayout (line 19) | function isStrictMainLayout(config: CapacityConfig): boolean {
  function getInitialSplitDirection (line 23) | function getInitialSplitDirection(config: CapacityConfig): SplitDirection {
  function getStrictFollowupSplitDirection (line 27) | function getStrictFollowupSplitDirection(config: CapacityConfig): SplitD...
  function sortPanesForStrictLayout (line 31) | function sortPanesForStrictLayout(panes: TmuxPaneInfo[], config: Capacit...
  function buildOccupancy (line 38) | function buildOccupancy(
  function findFirstEmptySlot (line 51) | function findFirstEmptySlot(
  function findSplittableTarget (line 65) | function findSplittableTarget(
  function findSpawnTarget (line 141) | function findSpawnTarget(

FILE: src/features/tmux-subagent/tmux-grid-constants.ts
  constant MAIN_PANE_RATIO (line 4) | const MAIN_PANE_RATIO = 0.5
  constant DEFAULT_MAIN_PANE_SIZE (line 5) | const DEFAULT_MAIN_PANE_SIZE = MAIN_PANE_RATIO * 100
  constant MAX_COLS (line 6) | const MAX_COLS = 2
  constant MAX_ROWS (line 7) | const MAX_ROWS = 3
  constant MAX_GRID_SIZE (line 8) | const MAX_GRID_SIZE = 4
  constant DIVIDER_SIZE (line 9) | const DIVIDER_SIZE = 1
  constant MIN_SPLIT_WIDTH (line 11) | const MIN_SPLIT_WIDTH = 2 * MIN_PANE_WIDTH + DIVIDER_SIZE
  constant MIN_SPLIT_HEIGHT (line 12) | const MIN_SPLIT_HEIGHT = 2 * MIN_PANE_HEIGHT + DIVIDER_SIZE
  function clamp (line 14) | function clamp(value: number, min: number, max: number): number {
  function getMainPaneSizePercent (line 18) | function getMainPaneSizePercent(config?: CapacityConfig): number {
  function computeMainPaneWidth (line 22) | function computeMainPaneWidth(
  function computeAgentAreaWidth (line 46) | function computeAgentAreaWidth(

FILE: src/features/tmux-subagent/tracked-session-state.ts
  function createTrackedSession (line 3) | function createTrackedSession(params: {
  function markTrackedSessionClosePending (line 22) | function markTrackedSessionClosePending(tracked: TrackedSession): Tracke...

FILE: src/features/tmux-subagent/types.ts
  type TrackedSession (line 1) | interface TrackedSession {
  constant MIN_PANE_WIDTH (line 14) | const MIN_PANE_WIDTH = 52
  constant MIN_PANE_HEIGHT (line 15) | const MIN_PANE_HEIGHT = 11
  type TmuxPaneInfo (line 17) | interface TmuxPaneInfo {
  type WindowState (line 27) | interface WindowState {
  type SplitDirection (line 34) | type SplitDirection = "-h" | "-v"
  type PaneAction (line 36) | type PaneAction =
  type SpawnDecision (line 41) | interface SpawnDecision {
  type CapacityConfig (line 47) | interface CapacityConfig {

FILE: src/features/tmux-subagent/zombie-pane.test.ts
  function createConfig (line 54) | function createConfig(): TmuxConfig {
  function createContext (line 64) | function createContext() {
  function createTrackedSession (line 106) | function createTrackedSession(overrides?: Partial<TrackedSession>): Trac...
  function getTrackedSessions (line 119) | function getTrackedSessions(target: object): Map<string, TrackedSession> {
  function getRetryPendingCloses (line 128) | function getRetryPendingCloses(target: object): () => Promise<void> {
  function getCloseSessionById (line 137) | function getCloseSessionById(target: object): (sessionId: string) => Pro...
  function createManager (line 146) | function createManager(

FILE: src/features/tool-metadata-store/store.ts
  type PendingToolMetadata (line 19) | interface PendingToolMetadata {
  constant STALE_TIMEOUT_MS (line 26) | const STALE_TIMEOUT_MS = 15 * 60 * 1000
  function makeKey (line 28) | function makeKey(sessionID: string, callID: string): string {
  function cleanupStaleEntries (line 32) | function cleanupStaleEntries(): void {
  function storeToolMetadata (line 45) | function storeToolMetadata(
  function consumeToolMetadata (line 58) | function consumeToolMetadata(
  function getPendingStoreSize (line 75) | function getPendingStoreSize(): number {
  function clearPendingStore (line 82) | function clearPendingStore(): void {

FILE: src/hooks/agent-usage-reminder/constants.ts
  constant AGENT_USAGE_REMINDER_STORAGE (line 3) | const AGENT_USAGE_REMINDER_STORAGE = join(
  constant TARGET_TOOLS (line 9) | const TARGET_TOOLS = new Set([
  constant AGENT_TOOLS (line 22) | const AGENT_TOOLS = new Set([
  constant REMINDER_MESSAGE (line 28) | const REMINDER_MESSAGE = `

FILE: src/hooks/agent-usage-reminder/hook.ts
  type ToolExecuteInput (line 12) | interface ToolExecuteInput {
  type ToolExecuteOutput (line 18) | interface ToolExecuteOutput {
  type EventInput (line 24) | interface EventInput {
  constant ORCHESTRATOR_AGENTS (line 36) | const ORCHESTRATOR_AGENTS = new Set([
  function isOrchestratorAgent (line 44) | function isOrchestratorAgent(agentName: string): boolean {
  function createAgentUsageReminderHook (line 48) | function createAgentUsageReminderHook(_ctx: PluginInput) {

FILE: src/hooks/agent-usage-reminder/storage.ts
  function getStoragePath (line 12) | function getStoragePath(sessionID: string): string {
  function loadAgentUsageState (line 16) | function loadAgentUsageState(sessionID: string): AgentUsageState | null {
  function saveAgentUsageState (line 28) | function saveAgentUsageState(state: AgentUsageState): void {
  function clearAgentUsageState (line 37) | function clearAgentUsageState(sessionID: string): void {

FILE: src/hooks/agent-usage-reminder/types.ts
  type AgentUsageState (line 1) | interface AgentUsageState {

FILE: src/hooks/anthropic-context-window-limit-recovery/aggressive-truncation-strategy.ts
  function runAggressiveTruncationStrategy (line 10) | async function runAggressiveTruncationStrategy(params: {

FILE: src/hooks/anthropic-context-window-limit-recovery/client.ts
  type Client (line 3) | type Client = PluginInput["client"] & {

FILE: src/hooks/anthropic-context-window-limit-recovery/deduplication-recovery.ts
  type OpencodeClient (line 10) | type OpencodeClient = PluginInput["client"]
  function createPruningState (line 12) | function createPruningState(): PruningState {
  function isPromptTooLongError (line 22) | function isPromptTooLongError(parsed: ParsedTokenLimitError): boolean {
  function getDeduplicationPlan (line 26) | function getDeduplicationPlan(
  function attemptDeduplicationRecovery (line 45) | async function attemptDeduplicationRecovery(

FILE: src/hooks/anthropic-context-window-limit-recovery/empty-content-recovery-sdk.test.ts
  function createMockClient (line 14) | function createMockClient(messages: Array<{ info?: { id?: string }; part...

FILE: src/hooks/anthropic-context-window-limit-recovery/empty-content-recovery-sdk.ts
  type SDKPart (line 5) | interface SDKPart {
  type SDKMessage (line 11) | interface SDKMessage {
  constant IGNORE_TYPES (line 16) | const IGNORE_TYPES = new Set(["thinking", "redacted_thinking", "meta"])
  constant TOOL_TYPES (line 17) | const TOOL_TYPES = new Set(["tool", "tool_use", "tool_result"])
  function messageHasContentFromSDK (line 19) | function messageHasContentFromSDK(message: SDKMessage): boolean {
  function getSdkMessages (line 45) | function getSdkMessages(response: unknown): SDKMessage[] {
  function findEmptyMessagesFromSDK (line 54) | async function findEmptyMessagesFromSDK(client: Client, sessionID: strin...
  function findEmptyMessageByIndexFromSDK (line 74) | async function findEmptyMessageByIndexFromSDK(
  function fixEmptyMessagesWithSDK (line 112) | async function fixEmptyMessagesWithSDK(params: {

FILE: src/hooks/anthropic-context-window-limit-recovery/empty-content-recovery.ts
  function fixEmptyMessages (line 14) | async function fixEmptyMessages(params: {

FILE: src/hooks/anthropic-context-window-limit-recovery/executor.test.ts
  type TimerCallback (line 8) | type TimerCallback = (...args: any[]) => void
  type FakeTimeouts (line 10) | interface FakeTimeouts {
  constant TRUE_ORIGINAL_SET_TIMEOUT (line 17) | const TRUE_ORIGINAL_SET_TIMEOUT = globalThis.setTimeout
  constant TRUE_ORIGINAL_CLEAR_TIMEOUT (line 18) | const TRUE_ORIGINAL_CLEAR_TIMEOUT = globalThis.clearTimeout
  function createFakeTimeouts (line 20) | function createFakeTimeouts(): FakeTimeouts {

FILE: src/hooks/anthropic-context-window-limit-recovery/executor.ts
  function executeCompact (line 15) | async function executeCompact(

FILE: src/hooks/anthropic-context-window-limit-recovery/message-builder.ts
  constant PLACEHOLDER_TEXT (line 14) | const PLACEHOLDER_TEXT = "[user interrupted]"
  type OpencodeClient (line 16) | type OpencodeClient = PluginInput["client"]
  type SDKPart (line 18) | interface SDKPart {
  type SDKMessage (line 23) | interface SDKMessage {
  constant IGNORE_TYPES (line 28) | const IGNORE_TYPES = new Set(["thinking", "redacted_thinking", "meta"])
  constant TOOL_TYPES (line 29) | const TOOL_TYPES = new Set(["tool", "tool_use", "tool_result"])
  function messageHasContentFromSDK (line 31) | function messageHasContentFromSDK(message: SDKMessage): boolean {
  function findEmptyMessageIdsFromSDK (line 57) | async function findEmptyMessageIdsFromSDK(
  function sanitizeEmptyMessagesBeforeSummarize (line 82) | async function sanitizeEmptyMessagesBeforeSummarize(
  function formatBytes (line 145) | function formatBytes(bytes: number): string {
  function getLastAssistant (line 151) | async function getLastAssistant(

FILE: src/hooks/anthropic-context-window-limit-recovery/message-storage-directory.ts
  type OpencodeClient (line 8) | type OpencodeClient = PluginInput["client"]
  type SDKMessage (line 10) | interface SDKMessage {
  function getMessageIdsFromSDK (line 15) | async function getMessageIdsFromSDK(
  function getMessageIds (line 28) | function getMessageIds(sessionID: string): string[] {

FILE: src/hooks/anthropic-context-window-limit-recovery/parser.ts
  type AnthropicErrorData (line 3) | interface AnthropicErrorData {
  constant TOKEN_LIMIT_PATTERNS (line 12) | const TOKEN_LIMIT_PATTERNS = [
  constant TOKEN_LIMIT_KEYWORDS (line 20) | const TOKEN_LIMIT_KEYWORDS = [
  constant THINKING_BLOCK_ERROR_PATTERNS (line 33) | const THINKING_BLOCK_ERROR_PATTERNS = [
  function isThinkingBlockError (line 42) | function isThinkingBlockError(text: string): boolean {
  constant MESSAGE_INDEX_PATTERN (line 46) | const MESSAGE_INDEX_PATTERN = /messages\.(\d+)/
  function extractTokensFromMessage (line 48) | function extractTokensFromMessage(message: string): { current: number; m...
  function extractMessageIndex (line 60) | function extractMessageIndex(text: string): number | undefined {
  function isTokenLimitError (line 68) | function isTokenLimitError(text: string): boolean {
  function parseAnthropicTokenLimitError (line 76) | function parseAnthropicTokenLimitError(err: unknown): ParsedTokenLimitEr...
  function parseAnthropicTokenLimitErrorUnsafe (line 84) | function parseAnthropicTokenLimitErrorUnsafe(err: unknown): ParsedTokenL...

FILE: src/hooks/anthropic-context-window-limit-recovery/pruning-deduplication.ts
  type OpencodeClient (line 11) | type OpencodeClient = PluginInput["client"]
  type DeduplicationConfig (line 13) | interface DeduplicationConfig {
  type ToolPart (line 18) | interface ToolPart {
  type MessagePart (line 28) | interface MessagePart {
  function createToolSignature (line 33) | function createToolSignature(toolName: string, input: unknown): string {
  function sortObject (line 38) | function sortObject(obj: unknown): unknown {
  function readMessages (line 51) | function readMessages(sessionID: string): MessagePart[] {
  function readMessagesFromSDK (line 73) | async function readMessagesFromSDK(client: OpencodeClient, sessionID: st...
  function executeDeduplication (line 83) | async function executeDeduplication(
  function findToolOutput (line 177) | function findToolOutput(messages: MessagePart[], callID: string): string...

FILE: src/hooks/anthropic-context-window-limit-recovery/pruning-tool-output-truncation.ts
  type OpencodeClient (line 12) | type OpencodeClient = PluginInput["client"]
  type StoredToolPart (line 14) | interface StoredToolPart {
  type SDKToolPart (line 23) | interface SDKToolPart {
  type SDKMessage (line 31) | interface SDKMessage {
  function getPartStorage (line 36) | function getPartStorage(): string {
  function getMessageIds (line 40) | function getMessageIds(sessionID: string): string[] {
  function truncateToolOutputsByCallId (line 53) | async function truncateToolOutputsByCallId(
  function truncateToolOutputsByCallIdFromSDK (line 105) | async function truncateToolOutputsByCallIdFromSDK(

FILE: src/hooks/anthropic-context-window-limit-recovery/pruning-types.ts
  type ToolCallSignature (line 1) | interface ToolCallSignature {
  type FileOperation (line 8) | interface FileOperation {
  type ErroredToolCall (line 15) | interface ErroredToolCall {
  type PruningResult (line 22) | interface PruningResult {
  type PruningState (line 32) | interface PruningState {
  constant CHARS_PER_TOKEN (line 40) | const CHARS_PER_TOKEN = 4
  function estimateTokens (line 42) | function estimateTokens(text: string): number {

FILE: src/hooks/anthropic-context-window-limit-recovery/recovery-deduplication.test.ts
  function createImmediateTimeouts (line 16) | function createImmediateTimeouts(): () => void {

FILE: src/hooks/anthropic-context-window-limit-recovery/recovery-hook.test.ts
  function createMockContext (line 36) | function createMockContext(): PluginInput {
  function setupDelayedTimeoutMocks (line 50) | function setupDelayedTimeoutMocks(): {

FILE: src/hooks/anthropic-context-window-limit-recovery/recovery-hook.ts
  type AnthropicContextWindowLimitRecoveryOptions (line 10) | interface AnthropicContextWindowLimitRecoveryOptions {
  function createRecoveryState (line 15) | function createRecoveryState(): AutoCompactState {
  function createAnthropicContextWindowLimitRecoveryHook (line 27) | function createAnthropicContextWindowLimitRecoveryHook(

FILE: src/hooks/anthropic-context-window-limit-recovery/state.ts
  function getOrCreateRetryState (line 3) | function getOrCreateRetryState(
  function getOrCreateTruncateState (line 15) | function getOrCreateTruncateState(
  function clearSessionState (line 27) | function clearSessionState(
  function getEmptyContentAttempt (line 39) | function getEmptyContentAttempt(
  function incrementEmptyContentAttempt (line 46) | function incrementEmptyContentAttempt(

FILE: src/hooks/anthropic-context-window-limit-recovery/storage-paths.ts
  constant TRUNCATION_MESSAGE (line 5) | const TRUNCATION_MESSAGE =

FILE: src/hooks/anthropic-context-window-limit-recovery/summarize-retry-strategy.test.ts
  type TimeoutCall (line 6) | type TimeoutCall = {
  function createAutoCompactState (line 10) | function createAutoCompactState(): AutoCompactState {

FILE: src/hooks/anthropic-context-window-limit-recovery/summarize-retry-strategy.ts
  constant SUMMARIZE_RETRY_TOTAL_TIMEOUT_MS (line 11) | const SUMMARIZE_RETRY_TOTAL_TIMEOUT_MS = 120_000
  function runSummarizeRetryStrategy (line 12) | async function runSummarizeRetryStrategy(params: {

FILE: src/hooks/anthropic-context-window-limit-recovery/target-token-truncation.ts
  type OpencodeClient (line 8) | type OpencodeClient = PluginInput["client"]
  type SDKToolPart (line 10) | interface SDKToolPart {
  type SDKMessage (line 21) | interface SDKMessage {
  function calculateTargetBytesToRemove (line 26) | function calculateTargetBytesToRemove(
  function truncateUntilTargetTokens (line 38) | async function truncateUntilTargetTokens(

FILE: src/hooks/anthropic-context-window-limit-recovery/tool-part-types.ts
  type StoredToolPart (line 1) | interface StoredToolPart {
  type ToolResultInfo (line 23) | interface ToolResultInfo {
  type AggressiveTruncateResult (line 31) | interface AggressiveTruncateResult {

FILE: src/hooks/anthropic-context-window-limit-recovery/tool-result-storage-sdk.ts
  type OpencodeClient (line 8) | type OpencodeClient = PluginInput["client"]
  type SDKToolPart (line 10) | interface SDKToolPart {
  type SDKMessage (line 24) | interface SDKMessage {
  function findToolResultsBySizeFromSDK (line 29) | async function findToolResultsBySizeFromSDK(
  function truncateToolResultAsync (line 61) | async function truncateToolResultAsync(
  function countTruncatedResultsFromSDK (line 95) | async function countTruncatedResultsFromSDK(
  function getTotalToolOutputSizeFromSDK (line 117) | async function getTotalToolOutputSizeFromSDK(

FILE: src/hooks/anthropic-context-window-limit-recovery/tool-result-storage.ts
  function findToolResultsBySize (line 12) | function findToolResultsBySize(sessionID: string): ToolResultInfo[] {
  function findLargestToolResult (line 45) | function findLargestToolResult(sessionID: string): ToolResultInfo | null {
  function truncateToolResult (line 50) | function truncateToolResult(partPath: string): {
  function getTotalToolOutputSize (line 91) | function getTotalToolOutputSize(sessionID: string): number {
  function countTruncatedResults (line 96) | function countTruncatedResults(sessionID: string): number {

FILE: src/hooks/anthropic-context-window-limit-recovery/types.ts
  type ParsedTokenLimitError (line 1) | interface ParsedTokenLimitError {
  type RetryState (line 11) | interface RetryState {
  type TruncateState (line 17) | interface TruncateState {
  type AutoCompactState (line 22) | interface AutoCompactState {
  constant RETRY_CONFIG (line 31) | const RETRY_CONFIG = {
  constant TRUNCATE_CONFIG (line 38) | const TRUNCATE_CONFIG = {

FILE: src/hooks/anthropic-effort/hook.ts
  constant OPUS_4_6_PATTERN (line 3) | const OPUS_4_6_PATTERN = /claude-opus-4[-.]6/i
  function isClaudeProvider (line 5) | function isClaudeProvider(providerID: string, modelID: string): boolean {
  function isOpus46 (line 11) | function isOpus46(modelID: string): boolean {
  type ChatParamsInput (line 16) | interface ChatParamsInput {
  type ChatParamsOutput (line 24) | interface ChatParamsOutput {
  function createAnthropicEffortHook (line 31) | function createAnthropicEffortHook() {

FILE: src/hooks/anthropic-effort/index.test.ts
  type ChatParamsInput (line 4) | interface ChatParamsInput {
  type ChatParamsOutput (line 12) | interface ChatParamsOutput {
  function createMockParams (line 19) | function createMockParams(overrides: {

FILE: src/hooks/atlas/atlas-hook.ts
  function createAtlasHook (line 7) | function createAtlasHook(ctx: PluginInput, options?: AtlasHookOptions) {

FILE: src/hooks/atlas/boulder-continuation-injector.ts
  function injectBoulderContinuation (line 10) | async function injectBoulderContinuation(input: {

FILE: src/hooks/atlas/boulder-session-lineage.ts
  function isSessionInBoulderLineage (line 5) | async function isSessionInBoulderLineage(input: {

FILE: src/hooks/atlas/compaction-agent-filter.test.ts
  constant TEST_STORAGE_ROOT (line 12) | const TEST_STORAGE_ROOT = join(tmpdir(), `atlas-compaction-storage-${ran...
  constant TEST_MESSAGE_STORAGE (line 13) | const TEST_MESSAGE_STORAGE = join(TEST_STORAGE_ROOT, "message")
  constant TEST_PART_STORAGE (line 14) | const TEST_PART_STORAGE = join(TEST_STORAGE_ROOT, "part")
  function createMockPluginInput (line 38) | function createMockPluginInput() {
  function writeMessage (line 52) | function writeMessage(sessionID: string, fileName: string, agent: string...

FILE: src/hooks/atlas/event-handler.ts
  function createAtlasEventHandler (line 8) | function createAtlasEventHandler(input: {

FILE: src/hooks/atlas/final-wave-approval-gate-regression.test.ts
  constant TEST_STORAGE_ROOT (line 11) | const TEST_STORAGE_ROOT = join(tmpdir(), `atlas-final-wave-regression-st...
  constant TEST_MESSAGE_STORAGE (line 12) | const TEST_MESSAGE_STORAGE = join(TEST_STORAGE_ROOT, "message")
  constant TEST_PART_STORAGE (line 13) | const TEST_PART_STORAGE = join(TEST_STORAGE_ROOT, "part")
  type AtlasHookContext (line 35) | type AtlasHookContext = Parameters<typeof createAtlasHook>[0]
  function createMockPluginInput (line 40) | function createMockPluginInput(): AtlasHookContext {
  function setupMessageStorage (line 82) | function setupMessageStorage(sessionID: string): void {
  function writePlanState (line 97) | function writePlanState(sessionID: string, planName: string, planContent...

FILE: src/hooks/atlas/final-wave-approval-gate.test.ts
  constant TEST_STORAGE_ROOT (line 11) | const TEST_STORAGE_ROOT = join(tmpdir(), `atlas-final-wave-storage-${ran...
  constant TEST_MESSAGE_STORAGE (line 12) | const TEST_MESSAGE_STORAGE = join(TEST_STORAGE_ROOT, "message")
  constant TEST_PART_STORAGE (line 13) | const TEST_PART_STORAGE = join(TEST_STORAGE_ROOT, "part")
  type AtlasHookContext (line 35) | type AtlasHookContext = Parameters<typeof createAtlasHook>[0]
  type PromptMock (line 36) | type PromptMock = ReturnType<typeof mock>
  function createMockPluginInput (line 41) | function createMockPluginInput(): AtlasHookContext & { _promptMock: Prom...
  function setupMessageStorage (line 90) | function setupMessageStorage(sessionID: string): void {
  function cleanupMessageStorage (line 105) | function cleanupMessageStorage(sessionID: string): void {

FILE: src/hooks/atlas/final-wave-approval-gate.ts
  constant APPROVE_VERDICT_PATTERN (line 4) | const APPROVE_VERDICT_PATTERN = /\bVERDICT:\s*APPROVE\b/i
  function clearFinalWaveApprovalTracking (line 6) | function clearFinalWaveApprovalTracking(sessionState: SessionState): void {
  function shouldPauseForFinalWaveApproval (line 11) | function shouldPauseForFinalWaveApproval(input: {

FILE: src/hooks/atlas/final-wave-plan-state.ts
  constant TODO_HEADING_PATTERN (line 3) | const TODO_HEADING_PATTERN = /^##\s+TODOs\b/i
  constant FINAL_VERIFICATION_HEADING_PATTERN (line 4) | const FINAL_VERIFICATION_HEADING_PATTERN = /^##\s+Final Verification Wav...
  constant SECOND_LEVEL_HEADING_PATTERN (line 5) | const SECOND_LEVEL_HEADING_PATTERN = /^##\s+/
  constant UNCHECKED_CHECKBOX_PATTERN (line 6) | const UNCHECKED_CHECKBOX_PATTERN = /^\s*[-*]\s*\[\s*\]\s*(.+)$/
  constant TODO_TASK_PATTERN (line 7) | const TODO_TASK_PATTERN = /^\d+\./
  constant FINAL_WAVE_TASK_PATTERN (line 8) | const FINAL_WAVE_TASK_PATTERN = /^F\d+\./i
  type PlanSection (line 10) | type PlanSection = "todo" | "final-wave" | "other"
  type FinalWavePlanState (line 12) | type FinalWavePlanState = {
  function readFinalWavePlanState (line 17) | function readFinalWavePlanState(planPath: string): FinalWavePlanState | ...

FILE: src/hooks/atlas/hook-name.ts
  constant HOOK_NAME (line 1) | const HOOK_NAME = "atlas"

FILE: src/hooks/atlas/idle-event-lineage.test.ts
  function writeIncompleteBoulder (line 19) | function writeIncompleteBoulder(): void {
  function createHook (line 33) | function createHook(parentSessionIDs?: Record<string, string | undefined...

FILE: src/hooks/atlas/idle-event.ts
  constant CONTINUATION_COOLDOWN_MS (line 14) | const CONTINUATION_COOLDOWN_MS = 5000
  constant FAILURE_BACKOFF_MS (line 15) | const FAILURE_BACKOFF_MS = 5 * 60 * 1000
  constant MAX_CONSECUTIVE_PROMPT_FAILURES (line 16) | const MAX_CONSECUTIVE_PROMPT_FAILURES = 10
  constant RETRY_DELAY_MS (line 17) | const RETRY_DELAY_MS = CONTINUATION_COOLDOWN_MS + 1000
  function hasRunningBackgroundTasks (line 19) | function hasRunningBackgroundTasks(sessionID: string, options?: AtlasHoo...
  function injectContinuation (line 26) | async function injectContinuation(input: {
  function scheduleRetry (line 67) | function scheduleRetry(input: {
  function handleAtlasSessionIdle (line 106) | async function handleAtlasSessionIdle(input: {

FILE: src/hooks/atlas/index.test.ts
  constant TEST_STORAGE_ROOT (line 15) | const TEST_STORAGE_ROOT = join(tmpdir(), `atlas-message-storage-${random...
  constant TEST_MESSAGE_STORAGE (line 16) | const TEST_MESSAGE_STORAGE = join(TEST_STORAGE_ROOT, "message")
  constant TEST_PART_STORAGE (line 17) | const TEST_PART_STORAGE = join(TEST_STORAGE_ROOT, "part")
  function createMockPluginInput (line 45) | function createMockPluginInput(overrides?: {
  function setupMessageStorage (line 73) | function setupMessageStorage(sessionID: string, agent: string): void {
  function cleanupMessageStorage (line 85) | function cleanupMessageStorage(sessionID: string): void {
  function flushMicrotasks (line 1178) | async function flushMicrotasks(): Promise<void> {
  function firePendingTimers (line 2094) | async function firePendingTimers(): Promise<void> {

FILE: src/hooks/atlas/is-abort-error.ts
  function isAbortError (line 1) | function isAbortError(error: unknown): boolean {

FILE: src/hooks/atlas/recent-model-resolver.ts
  type PromptContext (line 9) | type PromptContext = {
  function resolveRecentPromptContextForSession (line 14) | async function resolveRecentPromptContextForSession(
  function resolveRecentModelForSession (line 60) | async function resolveRecentModelForSession(

FILE: src/hooks/atlas/resolve-active-boulder-session.ts
  function resolveActiveBoulderSession (line 7) | async function resolveActiveBoulderSession(input: {

FILE: src/hooks/atlas/session-last-agent.sqlite.test.ts
  function createMockClient (line 11) | function createMockClient(messages: Array<{ info?: { agent?: string } }>) {

FILE: src/hooks/atlas/session-last-agent.ts
  type SessionMessagesClient (line 6) | type SessionMessagesClient = {
  function isCompactionAgent (line 12) | function isCompactionAgent(agent: unknown): boolean {
  function getLastAgentFromMessageDir (line 16) | function getLastAgentFromMessageDir(messageDir: string): string | null {
  function getLastAgentFromSession (line 41) | async function getLastAgentFromSession(

FILE: src/hooks/atlas/sisyphus-path.ts
  function isSisyphusPath (line 6) | function isSisyphusPath(filePath: string): boolean {

FILE: src/hooks/atlas/subagent-session-id.ts
  function extractSessionIdFromOutput (line 6) | function extractSessionIdFromOutput(output: string): string | undefined {
  function validateSubagentSessionId (line 20) | async function validateSubagentSessionId(input: {

FILE: src/hooks/atlas/system-reminder-templates.ts
  constant DIRECT_WORK_REMINDER (line 3) | const DIRECT_WORK_REMINDER = `
  constant BOULDER_CONTINUATION_PROMPT (line 31) | const BOULDER_CONTINUATION_PROMPT = `${createSystemDirective(SystemDirec...
  constant VERIFICATION_REMINDER (line 42) | const VERIFICATION_REMINDER = `**THE SUBAGENT JUST CLAIMED THIS TASK IS ...
  constant VERIFICATION_REMINDER_GEMINI (line 106) | const VERIFICATION_REMINDER_GEMINI = `**THE SUBAGENT HAS FINISHED. THEIR...
  constant ORCHESTRATOR_DELEGATION_REQUIRED (line 165) | const ORCHESTRATOR_DELEGATION_REQUIRED = `
  constant SINGLE_TASK_DIRECTIVE (line 215) | const SINGLE_TASK_DIRECTIVE = `

FILE: src/hooks/atlas/tool-execute-after.ts
  function resolvePreferredSessionId (line 28) | function resolvePreferredSessionId(currentSessionId?: string, trackedSes...
  function resolveTaskContext (line 32) | function resolveTaskContext(
  function createToolExecuteAfterHandler (line 71) | function createToolExecuteAfterHandler(input: {

FILE: src/hooks/atlas/tool-execute-before.ts
  function createToolExecuteBeforeHandler (line 12) | function createToolExecuteBeforeHandler(input: {

FILE: src/hooks/atlas/types.ts
  type ModelInfo (line 5) | type ModelInfo = { providerID: string; modelID: string }
  type AtlasHookOptions (line 7) | interface AtlasHookOptions {
  type ToolExecuteAfterInput (line 16) | interface ToolExecuteAfterInput {
  type ToolExecuteAfterOutput (line 22) | interface ToolExecuteAfterOutput {
  type TrackedTopLevelTaskRef (line 28) | type TrackedTopLevelTaskRef = Pick<TopLevelTaskRef, "key" | "label" | "t...
  type PendingTaskRef (line 30) | type PendingTaskRef =
  type SessionState (line 35) | interface SessionState {

FILE: src/hooks/atlas/verification-reminders.ts
  function buildReuseHint (line 3) | function buildReuseHint(sessionId: string): string {
  function buildCompletionGate (line 12) | function buildCompletionGate(planName: string, sessionId: string): string {
  function buildVerificationReminder (line 41) | function buildVerificationReminder(sessionId: string): string {
  function buildOrchestratorReminder (line 56) | function buildOrchestratorReminder(
  function buildFinalWaveApprovalReminder (line 123) | function buildFinalWaveApprovalReminder(
  function buildStandaloneVerificationReminder (line 163) | function buildStandaloneVerificationReminder(sessionId: string): string {

FILE: src/hooks/atlas/write-edit-tool-policy.ts
  constant WRITE_EDIT_TOOLS (line 1) | const WRITE_EDIT_TOOLS = ["Write", "Edit", "write", "edit"]
  function isWriteOrEditToolName (line 3) | function isWriteOrEditToolName(toolName: string): boolean {

FILE: src/hooks/auto-slash-command/auto-slash-command-leak.test.ts
  function createChatInput (line 26) | function createChatInput(sessionID: string, messageID: string): AutoSlas...
  function createChatOutput (line 33) | function createChatOutput(text: string): AutoSlashCommandHookOutput {
  function createCommandInput (line 40) | function createCommandInput(sessionID: string, command: string): Command...
  function createCommandOutput (line 48) | function createCommandOutput(text: string): CommandExecuteBeforeOutput {

FILE: src/hooks/auto-slash-command/constants.ts
  constant HOOK_NAME (line 1) | const HOOK_NAME = "auto-slash-command" as const
  constant AUTO_SLASH_COMMAND_TAG_OPEN (line 3) | const AUTO_SLASH_COMMAND_TAG_OPEN = "<auto-slash-command>"
  constant AUTO_SLASH_COMMAND_TAG_CLOSE (line 4) | const AUTO_SLASH_COMMAND_TAG_CLOSE = "</auto-slash-command>"
  constant SLASH_COMMAND_PATTERN (line 6) | const SLASH_COMMAND_PATTERN = /^\/([a-zA-Z@][\w.:@/-]*)\s*(.*)/
  constant EXCLUDED_COMMANDS (line 8) | const EXCLUDED_COMMANDS = new Set([

FILE: src/hooks/auto-slash-command/detector.ts
  constant CODE_BLOCK_PATTERN (line 7) | const CODE_BLOCK_PATTERN = /```[\s\S]*?```/g
  function removeCodeBlocks (line 9) | function removeCodeBlocks(text: string): string {
  function parseSlashCommand (line 13) | function parseSlashCommand(text: string): ParsedSlashCommand | null {
  function isExcludedCommand (line 33) | function isExcludedCommand(command: string): boolean {
  function detectSlashCommand (line 37) | function detectSlashCommand(text: string): ParsedSlashCommand | null {
  function extractPromptText (line 58) | function extractPromptText(
  function findSlashCommandPartIndex (line 77) | function findSlashCommandPartIndex(

FILE: src/hooks/auto-slash-command/executor-resolution.test.ts
  function createRestrictedSkill (line 32) | function createRestrictedSkill(): LoadedSkill {

FILE: src/hooks/auto-slash-command/executor.test.ts
  constant ENV_KEYS (line 7) | const ENV_KEYS = [
  type EnvKey (line 14) | type EnvKey = (typeof ENV_KEYS)[number]
  type EnvSnapshot (line 15) | type EnvSnapshot = Record<EnvKey, string | undefined>
  function writePluginFixture (line 17) | function writePluginFixture(baseDir: string): void {

FILE: src/hooks/auto-slash-command/executor.ts
  type SkillCommandInfo (line 11) | interface SkillCommandInfo {
  type CommandInfo (line 20) | type CommandInfo = DiscoveredCommandInfo | SkillCommandInfo
  function skillToCommandInfo (line 22) | function skillToCommandInfo(skill: LoadedSkill): SkillCommandInfo {
  type ExecutorOptions (line 40) | interface ExecutorOptions {
  function discoverAllCommands (line 48) | async function discoverAllCommands(options?: ExecutorOptions): Promise<C...
  function findCommand (line 72) | async function findCommand(commandName: string, options?: ExecutorOption...
  function formatCommandTemplate (line 79) | async function formatCommandTemplate(cmd: CommandInfo, args: string): Pr...
  type ExecuteResult (line 127) | interface ExecuteResult {
  function executeSlashCommand (line 133) | async function executeSlashCommand(parsed: ParsedSlashCommand, options?:...

FILE: src/hooks/auto-slash-command/hook.ts
  constant COMMAND_EXECUTE_FALLBACK_DEDUP_TTL_MS (line 21) | const COMMAND_EXECUTE_FALLBACK_DEDUP_TTL_MS = 100
  function isRecord (line 23) | function isRecord(value: unknown): value is Record<string, unknown> {
  function getDeletedSessionID (line 27) | function getDeletedSessionID(properties: unknown): string | null {
  function getCommandExecutionEventID (line 40) | function getCommandExecutionEventID(input: CommandExecuteBeforeInput): s...
  type AutoSlashCommandHookOptions (line 67) | interface AutoSlashCommandHookOptions {
  function createAutoSlashCommandHook (line 73) | function createAutoSlashCommandHook(options?: AutoSlashCommandHookOption...

FILE: src/hooks/auto-slash-command/index.test.ts
  function createMockInput (line 20) | function createMockInput(sessionID: string, messageID?: string): AutoSla...
  function createMockOutput (line 29) | function createMockOutput(text: string): AutoSlashCommandHookOutput {
  function createCommandInput (line 259) | function createCommandInput(command: string, args: string = ""): Command...
  function createCommandOutput (line 267) | function createCommandOutput(text?: string): CommandExecuteBeforeOutput {
  function createTestSkill (line 335) | function createTestSkill(name: string, template: string): LoadedSkill {

FILE: src/hooks/auto-slash-command/processed-command-store.ts
  constant MAX_PROCESSED_ENTRY_COUNT (line 1) | const MAX_PROCESSED_ENTRY_COUNT = 10_000
  constant PROCESSED_COMMAND_TTL_MS (line 2) | const PROCESSED_COMMAND_TTL_MS = 30_000
  function pruneExpiredEntries (line 4) | function pruneExpiredEntries(entries: Map<string, number>, now: number):...
  function trimProcessedEntries (line 8) | function trimProcessedEntries(entries: Map<string, number>): Map<string,...
  function removeSessionEntries (line 20) | function removeSessionEntries(entries: Map<string, number>, sessionID: s...
  type ProcessedCommandStore (line 25) | interface ProcessedCommandStore {
  function createProcessedCommandStore (line 32) | function createProcessedCommandStore(): ProcessedCommandStore {

FILE: src/hooks/auto-slash-command/types.ts
  type AutoSlashCommandHookInput (line 1) | interface AutoSlashCommandHookInput {
  type AutoSlashCommandHookOutput (line 8) | interface AutoSlashCommandHookOutput {
  type ParsedSlashCommand (line 13) | interface ParsedSlashCommand {
  type AutoSlashCommandResult (line 19) | interface AutoSlashCommandResult {
  type CommandExecuteBeforeInput (line 25) | interface CommandExecuteBeforeInput {
  type CommandExecuteBeforeOutput (line 40) | interface CommandExecuteBeforeOutput {

FILE: src/hooks/auto-update-checker/cache.test.ts
  constant TEST_CACHE_DIR (line 5) | const TEST_CACHE_DIR = join(import.meta.dir, "__test-cache__")
  constant TEST_OPENCODE_CACHE_DIR (line 6) | const TEST_OPENCODE_CACHE_DIR = join(TEST_CACHE_DIR, "opencode")
  constant TEST_USER_CONFIG_DIR (line 7) | const TEST_USER_CONFIG_DIR = "/tmp/opencode-config"
  function resetTestCache (line 19) | function resetTestCache(): void {

FILE: src/hooks/auto-update-checker/cache.ts
  type BunLockfile (line 6) | interface BunLockfile {
  function stripTrailingCommas (line 15) | function stripTrailingCommas(json: string): string {
  function removeFromTextBunLock (line 19) | function removeFromTextBunLock(lockPath: string, packageName: string): b...
  function deleteBinaryBunLock (line 36) | function deleteBinaryBunLock(lockPath: string): boolean {
  function removeFromBunLock (line 46) | function removeFromBunLock(packageName: string): boolean {
  function invalidatePackage (line 62) | function invalidatePackage(packageName: string = PACKAGE_NAME): boolean {
  function invalidateCache (line 95) | function invalidateCache(): boolean {

FILE: src/hooks/auto-update-checker/checker/cached-version.ts
  function getCachedVersion (line 9) | function getCachedVersion(): string | null {

FILE: src/hooks/auto-update-checker/checker/check-for-update.ts
  function checkForUpdate (line 9) | async function checkForUpdate(directory: string): Promise<UpdateCheckRes...

FILE: src/hooks/auto-update-checker/checker/config-paths.ts
  function getConfigPaths (line 10) | function getConfigPaths(directory: string): string[] {

FILE: src/hooks/auto-update-checker/checker/jsonc-strip.ts
  function stripJsonComments (line 1) | function stripJsonComments(json: string): string {

FILE: src/hooks/auto-update-checker/checker/latest-version.ts
  function getLatestVersion (line 4) | async function getLatestVersion(channel: string = "latest"): Promise<str...

FILE: src/hooks/auto-update-checker/checker/local-dev-path.ts
  function isLocalDevMode (line 8) | function isLocalDevMode(directory: string): boolean {
  function getLocalDevPath (line 12) | function getLocalDevPath(directory: string): string | null {

FILE: src/hooks/auto-update-checker/checker/local-dev-version.ts
  function getLocalDevVersion (line 6) | function getLocalDevVersion(directory: string): string | null {

FILE: src/hooks/auto-update-checker/checker/package-json-locator.ts
  function findPackageJsonUp (line 6) | function findPackageJsonUp(startPath: string): string | null {

FILE: src/hooks/auto-update-checker/checker/pinned-version-updater.ts
  function replacePluginEntry (line 5) | function replacePluginEntry(configPath: string, oldEntry: string, newEnt...
  function updatePinnedVersion (line 54) | function updatePinnedVersion(configPath: string, oldEntry: string, newVe...
  function revertPinnedVersion (line 59) | function revertPinnedVersion(configPath: string, failedVersion: string, ...

FILE: src/hooks/auto-update-checker/checker/plugin-entry.ts
  type PluginEntryInfo (line 7) | interface PluginEntryInfo {
  constant EXACT_SEMVER_REGEX (line 14) | const EXACT_SEMVER_REGEX = /^\d+\.\d+\.\d+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]...
  function findPluginEntry (line 16) | function findPluginEntry(directory: string): PluginEntryInfo | null {

FILE: src/hooks/auto-update-checker/checker/sync-package-json.test.ts
  constant TEST_CACHE_DIR (line 6) | const TEST_CACHE_DIR = join(import.meta.dir, "__test-sync-cache__")
  function resetTestCache (line 25) | function resetTestCache(currentVersion = "3.10.0"): void {
  function cleanupTestCache (line 37) | function cleanupTestCache(): void {
  function readCachePackageJsonVersion (line 43) | function readCachePackageJsonVersion(): string | undefined {

FILE: src/hooks/auto-update-checker/checker/sync-package-json.ts
  type CachePackageJson (line 8) | interface CachePackageJson {
  type SyncResult (line 12) | interface SyncResult {
  constant EXACT_SEMVER_REGEX (line 18) | const EXACT_SEMVER_REGEX = /^\d+\.\d+\.\d+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]...
  function safeUnlink (line 20) | function safeUnlink(filePath: string): void {
  function getIntentVersion (line 28) | function getIntentVersion(pluginInfo: PluginEntryInfo): string {
  function syncCachePackageJsonToIntent (line 35) | function syncCachePackageJsonToIntent(pluginInfo: PluginEntryInfo): Sync...

FILE: src/hooks/auto-update-checker/constants.ts
  constant PACKAGE_NAME (line 6) | const PACKAGE_NAME = "oh-my-opencode"
  constant NPM_REGISTRY_URL (line 7) | const NPM_REGISTRY_URL = `https://registry.npmjs.org/-/package/${PACKAGE...
  constant NPM_FETCH_TIMEOUT (line 8) | const NPM_FETCH_TIMEOUT = 5000
  constant CACHE_DIR (line 10) | const CACHE_DIR = getOpenCodeCacheDir()
  constant VERSION_FILE (line 11) | const VERSION_FILE = path.join(CACHE_DIR, "version")
  function getWindowsAppdataDir (line 13) | function getWindowsAppdataDir(): string | null {
  constant USER_CONFIG_DIR (line 18) | const USER_CONFIG_DIR = getOpenCodeConfigDir({ binary: "opencode" })
  constant USER_OPENCODE_CONFIG (line 19) | const USER_OPENCODE_CONFIG = path.join(USER_CONFIG_DIR, "opencode.json")
  constant USER_OPENCODE_CONFIG_JSONC (line 20) | const USER_OPENCODE_CONFIG_JSONC = path.join(USER_CONFIG_DIR, "opencode....
  constant INSTALLED_PACKAGE_JSON (line 22) | const INSTALLED_PACKAGE_JSON = path.join(

FILE: src/hooks/auto-update-checker/hook.test.ts
  type HookFactory (line 43) | type HookFactory = typeof import("./hook").createAutoUpdateCheckerHook
  function importFreshHookFactory (line 45) | async function importFreshHookFactory(): Promise<HookFactory> {
  function createPluginInput (line 50) | function createPluginInput() {
  function flushScheduledWork (line 57) | async function flushScheduledWork(): Promise<void> {
  function runSessionCreatedEvent (line 65) | function runSessionCreatedEvent(

FILE: src/hooks/auto-update-checker/hook.ts
  function createAutoUpdateCheckerHook (line 11) | function createAutoUpdateCheckerHook(ctx: PluginInput, options: AutoUpda...

FILE: src/hooks/auto-update-checker/hook/background-update-check.test.ts
  type PluginEntry (line 4) | type PluginEntry = {
  type ToastMessageGetter (line 11) | type ToastMessageGetter = (isUpdate: boolean, version?: string) => string
  function createPluginEntry (line 13) | function createPluginEntry(overrides?: Partial<PluginEntry>): PluginEntry {

FILE: src/hooks/auto-update-checker/hook/background-update-check.ts
  function getPinnedVersionToastMessage (line 13) | function getPinnedVersionToastMessage(latestVersion: string): string {
  function resolveActiveInstallWorkspace (line 21) | function resolveActiveInstallWorkspace(): string {
  function runBunInstallSafe (line 44) | async function runBunInstallSafe(workspaceDir: string): Promise<boolean> {
  function runBackgroundUpdateCheck (line 58) | async function runBackgroundUpdateCheck(

FILE: src/hooks/auto-update-checker/hook/config-errors-toast.ts
  function showConfigErrorsIfAny (line 5) | async function showConfigErrorsIfAny(ctx: PluginInput): Promise<void> {

FILE: src/hooks/auto-update-checker/hook/connected-providers-status.ts
  constant CACHE_UPDATE_TIMEOUT_MS (line 6) | const CACHE_UPDATE_TIMEOUT_MS = 10000
  function updateAndShowConnectedProvidersCacheStatus (line 8) | async function updateAndShowConnectedProvidersCacheStatus(ctx: PluginInp...

FILE: src/hooks/auto-update-checker/hook/model-cache-warning.ts
  function showModelCacheWarningIfNeeded (line 5) | async function showModelCacheWarningIfNeeded(ctx: PluginInput): Promise<...

FILE: src/hooks/auto-update-checker/hook/spinner-toast.ts
  constant SISYPHUS_SPINNER (line 3) | const SISYPHUS_SPINNER = ["·", "•", "●", "○", "◌", "◦", " "]
  function showSpinnerToast (line 5) | async function showSpinnerToast(ctx: PluginInput, version: string, messa...

FILE: src/hooks/auto-update-checker/hook/startup-toasts.ts
  function showVersionToast (line 5) | async function showVersionToast(ctx: PluginInput, version: string | null...
  function showLocalDevToast (line 11) | async function showLocalDevToast(

FILE: src/hooks/auto-update-checker/hook/update-toasts.ts
  function showUpdateAvailableToast (line 4) | async function showUpdateAvailableToast(
  function showAutoUpdatedToast (line 22) | async function showAutoUpdatedToast(ctx: PluginInput, oldVersion: string...

FILE: src/hooks/auto-update-checker/hook/workspace-resolution.test.ts
  type PluginEntry (line 6) | type PluginEntry = {
  type ToastMessageGetter (line 13) | type ToastMessageGetter = (isUpdate: boolean, version?: string) => string
  function createPluginEntry (line 15) | function createPluginEntry(overrides?: Partial<PluginEntry>): PluginEntry {
  constant TEST_DIR (line 25) | const TEST_DIR = join(import.meta.dir, "__test-workspace-resolution__")
  constant TEST_CACHE_DIR (line 26) | const TEST_CACHE_DIR = join(TEST_DIR, "cache")
  constant TEST_CONFIG_DIR (line 27) | const TEST_CONFIG_DIR = join(TEST_DIR, "config")
  constant ORIGINAL_PACKAGE_NAME (line 78) | const ORIGINAL_PACKAGE_NAME = "oh-my-opencode"

FILE: src/hooks/auto-update-checker/types.ts
  type NpmDistTags (line 1) | interface NpmDistTags {
  type OpencodeConfig (line 6) | interface OpencodeConfig {
  type PackageJson (line 11) | interface PackageJson {
  type UpdateCheckResult (line 17) | interface UpdateCheckResult {
  type AutoUpdateCheckerOptions (line 25) | interface AutoUpdateCheckerOptions {

FILE: src/hooks/auto-update-checker/version-channel.ts
  function isPrereleaseVersion (line 1) | function isPrereleaseVersion(version: string): boolean {
  function isDistTag (line 5) | function isDistTag(version: string): boolean {
  function isPrereleaseOrDistTag (line 10) | function isPrereleaseOrDistTag(pinnedVersion: string | null): boolean {
  function extractChannel (line 15) | function extractChannel(version: string | null): string {

FILE: src/hooks/background-notification/hook.ts
  type Event (line 3) | interface Event {
  type EventInput (line 8) | interface EventInput {
  type ChatMessageInput (line 12) | interface ChatMessageInput {
  type ChatMessageOutput (line 16) | interface ChatMessageOutput {
  function createBackgroundNotificationHook (line 26) | function createBackgroundNotificationHook(manager: BackgroundManager) {

FILE: src/hooks/background-notification/types.ts
  type BackgroundNotificationHookConfig (line 3) | interface BackgroundNotificationHookConfig {

FILE: src/hooks/category-skill-reminder/formatter.ts
  function formatSkillNames (line 3) | function formatSkillNames(skills: AvailableSkill[], limit: number): stri...
  function buildReminderMessage (line 11) | function buildReminderMessage(availableSkills: AvailableSkill[]): string {

FILE: src/hooks/category-skill-reminder/hook.ts
  constant TARGET_AGENTS (line 12) | const TARGET_AGENTS = new Set([
  constant DELEGATABLE_WORK_TOOLS (line 22) | const DELEGATABLE_WORK_TOOLS = new Set([
  constant DELEGATION_TOOLS (line 34) | const DELEGATION_TOOLS = new Set([
  type ToolExecuteInput (line 39) | interface ToolExecuteInput {
  type ToolExecuteOutput (line 46) | interface ToolExecuteOutput {
  type SessionState (line 52) | interface SessionState {
  func
Condensed preview — 1615 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (7,915K chars).
[
  {
    "path": ".github/FUNDING.yml",
    "chars": 856,
    "preview": "# These are supported funding model platforms\n\ngithub: code-yeongyu\npatreon: # Replace with a single Patreon username\nop"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "chars": 3835,
    "preview": "name: Bug Report\ndescription: Report a bug or unexpected behavior in oh-my-opencode\ntitle: \"[Bug]: \"\nlabels: [\"bug\", \"ne"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 339,
    "preview": "blank_issues_enabled: false\ncontact_links:\n  - name: Discord Community\n    url: https://discord.gg/PUwSMR9XNk\n    about:"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yml",
    "chars": 3512,
    "preview": "name: Feature Request\ndescription: Suggest a new feature or enhancement for oh-my-opencode\ntitle: \"[Feature]: \"\nlabels: "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/general.yml",
    "chars": 2793,
    "preview": "name: Question or Discussion\ndescription: Ask a question or start a discussion about oh-my-opencode\ntitle: \"[Question]: "
  },
  {
    "path": ".github/pull_request_template.md",
    "chars": 567,
    "preview": "## Summary\n\n<!-- Brief description of what this PR does. 1-3 bullet points. -->\n\n- \n\n## Changes\n\n<!-- What was changed a"
  },
  {
    "path": ".github/workflows/ci.yml",
    "chars": 7956,
    "preview": "name: CI\n\non:\n  push:\n    branches: [master, dev]\n  pull_request:\n    branches: [master, dev]\n\nconcurrency:\n  group: ${{"
  },
  {
    "path": ".github/workflows/cla.yml",
    "chars": 1684,
    "preview": "name: CLA Assistant\n\non:\n  issue_comment:\n    types: [created]\n  pull_request_target:\n    types: [opened, closed, synchr"
  },
  {
    "path": ".github/workflows/lint-workflows.yml",
    "chars": 474,
    "preview": "name: Lint Workflows\n\non:\n  push:\n    paths:\n      - '.github/workflows/**'\n  pull_request:\n    paths:\n      - '.github/"
  },
  {
    "path": ".github/workflows/publish-platform.yml",
    "chars": 12401,
    "preview": "name: publish-platform\nrun-name: \"platform packages ${{ inputs.version }}\"\n\non:\n  workflow_call:\n    inputs:\n      versi"
  },
  {
    "path": ".github/workflows/publish.yml",
    "chars": 12689,
    "preview": "name: publish\nrun-name: \"${{ format('release {0}', inputs.version || inputs.bump) }}\"\n\non:\n  workflow_dispatch:\n    inpu"
  },
  {
    "path": ".github/workflows/sisyphus-agent.yml",
    "chars": 22545,
    "preview": "name: Sisyphus Agent\n\non:\n  workflow_dispatch:\n    inputs:\n      prompt:\n        description: \"Custom prompt\"\n        re"
  },
  {
    "path": ".gitignore",
    "chars": 461,
    "preview": "# Dependencies\n.sisyphus/*\n!.sisyphus/rules/\nnode_modules/\n\n# Build output\ndist/\n\n# Platform binaries (built, not commit"
  },
  {
    "path": ".opencode/background-tasks.json",
    "chars": 821,
    "preview": "[\n  {\n    \"id\": \"bg_wzsdt60b\",\n    \"sessionID\": \"ses_4f3e89f0dffeooeXNVx5QCifse\",\n    \"parentSessionID\": \"ses_4f3e8d141f"
  },
  {
    "path": ".opencode/command/get-unpublished-changes.md",
    "chars": 4130,
    "preview": "---\ndescription: Compare HEAD with the latest published npm version and list all unpublished changes\n---\n\n<command-instr"
  },
  {
    "path": ".opencode/command/omomomo.md",
    "chars": 1193,
    "preview": "---\ndescription: Easter egg command - about oh-my-opencode\n---\n\n<command-instruction>\nYou found an easter egg! 🥚✨\n\nPrint"
  },
  {
    "path": ".opencode/command/publish.md",
    "chars": 13156,
    "preview": "---\ndescription: Publish oh-my-opencode to npm via GitHub Actions workflow\nargument-hint: <patch|minor|major>\n---\n\n<comm"
  },
  {
    "path": ".opencode/command/remove-deadcode.md",
    "chars": 7213,
    "preview": "---\ndescription: Remove unused code from this project with ultrawork mode, LSP-verified safety, atomic commits\n---\n\n<com"
  },
  {
    "path": ".opencode/skills/github-triage/SKILL.md",
    "chars": 16397,
    "preview": "---\nname: github-triage\ndescription: \"Read-only GitHub triage for issues AND PRs. 1 item = 1 background task (category: "
  },
  {
    "path": ".opencode/skills/github-triage/scripts/gh_fetch.py",
    "chars": 12447,
    "preview": "#!/usr/bin/env -S uv run --script\n# /// script\n# requires-python = \">=3.11\"\n# dependencies = [\n#     \"typer>=0.12.0\",\n# "
  },
  {
    "path": ".opencode/skills/pre-publish-review/SKILL.md",
    "chars": 15464,
    "preview": "---\nname: pre-publish-review\ndescription: \"Nuclear-grade 16-agent pre-publish release gate. Runs /get-unpublished-change"
  },
  {
    "path": ".opencode/skills/work-with-pr/SKILL.md",
    "chars": 10929,
    "preview": "---\nname: work-with-pr\ndescription: \"Full PR lifecycle: git worktree → implement → atomic commits → PR creation → verifi"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/evals/evals.json",
    "chars": 5558,
    "preview": "{\n  \"skill_name\": \"work-with-pr\",\n  \"evals\": [\n    {\n      \"id\": 1,\n      \"prompt\": \"I need to add a `max_background_age"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/benchmark.json",
    "chars": 6275,
    "preview": "{\n  \"skill_name\": \"work-with-pr\",\n  \"iteration\": 1,\n  \"summary\": {\n    \"with_skill\": {\n      \"pass_rate\": 0.968,\n      \""
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/benchmark.md",
    "chars": 1660,
    "preview": "# Benchmark: work-with-pr (Iteration 1)\n\n## Summary\n\n| Metric | With Skill | Without Skill | Delta |\n|--------|---------"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-1/eval_metadata.json",
    "chars": 1886,
    "preview": "{\n  \"eval_id\": 1,\n  \"eval_name\": \"happy-path-feature-config-option\",\n  \"prompt\": \"I need to add a `max_background_agents"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-1/with_skill/grading.json",
    "chars": 1621,
    "preview": "{\n  \"run_id\": \"eval-1-with_skill\",\n  \"expectations\": [\n    {\"text\": \"Plan uses git worktree in a sibling directory\", \"pa"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-1/with_skill/outputs/code-changes.md",
    "chars": 13288,
    "preview": "# Code Changes: `max_background_agents` Config Option\n\n## 1. `src/config/schema/background-task.ts` — Add schema field\n\n"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-1/with_skill/outputs/execution-plan.md",
    "chars": 4521,
    "preview": "# Execution Plan: `max_background_agents` Config Option\n\n## Phase 0: Setup — Branch + Worktree\n\n1. **Create branch** fro"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-1/with_skill/outputs/pr-description.md",
    "chars": 1971,
    "preview": "# PR Description\n\n**Title:** `feat: add max_background_agents config to limit concurrent background agents`\n\n**Base:** `"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-1/with_skill/outputs/verification-strategy.md",
    "chars": 6032,
    "preview": "# Verification Strategy\n\n## Pre-Push Local Validation\n\nBefore every push, run all three checks sequentially:\n\n```bash\nbu"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-1/with_skill/timing.json",
    "chars": 76,
    "preview": "{\"total_tokens\": null, \"duration_ms\": 292000, \"total_duration_seconds\": 292}"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-1/without_skill/grading.json",
    "chars": 1555,
    "preview": "{\n  \"run_id\": \"eval-1-without_skill\",\n  \"expectations\": [\n    {\"text\": \"Plan uses git worktree in a sibling directory\", "
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-1/without_skill/outputs/code-changes.md",
    "chars": 18147,
    "preview": "# Code Changes: `max_background_agents` Config Option\n\n## 1. Schema Change\n\n**File:** `src/config/schema/background-task"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-1/without_skill/outputs/execution-plan.md",
    "chars": 4954,
    "preview": "# Execution Plan: Add `max_background_agents` Config Option\n\n## Overview\n\nAdd a `max_background_agents` config option to"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-1/without_skill/outputs/pr-description.md",
    "chars": 2311,
    "preview": "# PR Description\n\n**Title:** feat: add `maxBackgroundAgents` config to limit total simultaneous background agents\n\n**Bod"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-1/without_skill/outputs/verification-strategy.md",
    "chars": 4752,
    "preview": "# Verification Strategy\n\n## 1. Static Analysis\n\n### TypeScript Typecheck\n```bash\nbun run typecheck\n```\n- Verify no type "
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-1/without_skill/timing.json",
    "chars": 76,
    "preview": "{\"total_tokens\": null, \"duration_ms\": 365000, \"total_duration_seconds\": 365}"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-2/eval_metadata.json",
    "chars": 1073,
    "preview": "{\n  \"eval_id\": 2,\n  \"eval_name\": \"bugfix-atlas-null-check\",\n  \"prompt\": \"The atlas hook has a bug where it crashes when "
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-2/with_skill/grading.json",
    "chars": 937,
    "preview": "{\n  \"run_id\": \"eval-2-with_skill\",\n  \"expectations\": [\n    {\"text\": \"Plan uses git worktree in a sibling directory\", \"pa"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-2/with_skill/outputs/code-changes.md",
    "chars": 6684,
    "preview": "# Code Changes\n\n## File 1: `src/features/boulder-state/storage.ts`\n\n**Change**: Add `worktree_path` sanitization in `rea"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-2/with_skill/outputs/execution-plan.md",
    "chars": 2923,
    "preview": "# Execution Plan — Fix atlas hook crash on missing worktree_path\n\n## Phase 0: Setup\n\n1. **Create worktree from origin/de"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-2/with_skill/outputs/pr-description.md",
    "chars": 2298,
    "preview": "# PR Title\n\n```\nfix(atlas): prevent crash when boulder.json missing worktree_path\n```\n\n# PR Body\n\n## Summary\n\n- Fix runt"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-2/with_skill/outputs/verification-strategy.md",
    "chars": 3443,
    "preview": "# Verification Strategy\n\n## Gate A: CI (`gh pr checks --watch`)\n\n### What CI runs (from `ci.yml`)\n1. **Tests (split)**: "
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-2/with_skill/timing.json",
    "chars": 76,
    "preview": "{\"total_tokens\": null, \"duration_ms\": 506000, \"total_duration_seconds\": 506}"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-2/without_skill/grading.json",
    "chars": 1000,
    "preview": "{\n  \"run_id\": \"eval-2-without_skill\",\n  \"expectations\": [\n    {\"text\": \"Plan uses git worktree in a sibling directory\", "
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-2/without_skill/outputs/code-changes.md",
    "chars": 10324,
    "preview": "# Code Changes: Fix Atlas Hook Crash on Missing worktree_path\n\n## Change 1: Harden `readBoulderState()` validation\n\n**Fi"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-2/without_skill/outputs/execution-plan.md",
    "chars": 3479,
    "preview": "# Execution Plan: Fix Atlas Hook Crash on Missing worktree_path\n\n## Bug Analysis\n\n### Root Cause\n\n`readBoulderState()` i"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-2/without_skill/outputs/pr-description.md",
    "chars": 1464,
    "preview": "## Summary\n\n- Fix crash in atlas hook when `boulder.json` is missing `worktree_path` (or other required fields) by harde"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-2/without_skill/outputs/verification-strategy.md",
    "chars": 3443,
    "preview": "# Verification Strategy\n\n## 1. Unit Tests (Direct Verification)\n\n### boulder-state storage tests\n```bash\nbun test src/fe"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-2/without_skill/timing.json",
    "chars": 76,
    "preview": "{\"total_tokens\": null, \"duration_ms\": 325000, \"total_duration_seconds\": 325}"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-3/eval_metadata.json",
    "chars": 1005,
    "preview": "{\n  \"eval_id\": 3,\n  \"eval_name\": \"refactor-split-constants\",\n  \"prompt\": \"Refactor src/tools/delegate-task/constants.ts "
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-3/with_skill/grading.json",
    "chars": 866,
    "preview": "{\n  \"run_id\": \"eval-3-with_skill\",\n  \"expectations\": [\n    {\"text\": \"Plan uses git worktree in a sibling directory\", \"pa"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-3/with_skill/outputs/code-changes.md",
    "chars": 7648,
    "preview": "# Code Changes\n\n## New File: `src/tools/delegate-task/default-categories.ts`\n\n```typescript\nimport type { CategoryConfig"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-3/with_skill/outputs/execution-plan.md",
    "chars": 4402,
    "preview": "# Execution Plan: Split delegate-task/constants.ts\n\n## Phase 0: Setup\n\n```bash\ngit fetch origin dev\ngit worktree add ../"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-3/with_skill/outputs/pr-description.md",
    "chars": 1948,
    "preview": "# PR Title\n\n```\nrefactor(delegate-task): split constants.ts into focused modules\n```\n\n# PR Body\n\n## Summary\n\n- Split the"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-3/with_skill/outputs/verification-strategy.md",
    "chars": 2634,
    "preview": "# Verification Strategy\n\n## Gate A: CI (Blocking)\n\n```bash\ngh pr checks --watch\n```\n\n**Expected CI jobs** (from `ci.yml`"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-3/with_skill/timing.json",
    "chars": 76,
    "preview": "{\"total_tokens\": null, \"duration_ms\": 181000, \"total_duration_seconds\": 181}"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-3/without_skill/grading.json",
    "chars": 847,
    "preview": "{\n  \"run_id\": \"eval-3-without_skill\",\n  \"expectations\": [\n    {\"text\": \"Plan uses git worktree in a sibling directory\", "
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-3/without_skill/outputs/code-changes.md",
    "chars": 11015,
    "preview": "# Code Changes\n\n## 1. NEW: `src/tools/delegate-task/default-categories.ts`\n\n```typescript\nimport type { CategoryConfig }"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-3/without_skill/outputs/execution-plan.md",
    "chars": 5551,
    "preview": "# Execution Plan: Refactor constants.ts\n\n## Context\n\n`src/tools/delegate-task/constants.ts` is **654 lines** with 6 dist"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-3/without_skill/outputs/pr-description.md",
    "chars": 1970,
    "preview": "## Summary\n\n- Split `src/tools/delegate-task/constants.ts` (654 LOC, 6 responsibilities) into 5 focused modules: `defaul"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-3/without_skill/outputs/verification-strategy.md",
    "chars": 5122,
    "preview": "# Verification Strategy\n\n## 1. Type Safety\n\n### 1a. LSP diagnostics on all new files\n```\nlsp_diagnostics(\"src/tools/dele"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-3/without_skill/timing.json",
    "chars": 76,
    "preview": "{\"total_tokens\": null, \"duration_ms\": 229000, \"total_duration_seconds\": 229}"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-4/eval_metadata.json",
    "chars": 871,
    "preview": "{\n  \"eval_id\": 4,\n  \"eval_name\": \"new-mcp-arxiv-casual\",\n  \"prompt\": \"implement issue #100 - we need to add a new built-"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-4/with_skill/grading.json",
    "chars": 692,
    "preview": "{\n  \"run_id\": \"eval-4-with_skill\",\n  \"expectations\": [\n    {\"text\": \"Plan uses git worktree in a sibling directory\", \"pa"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-4/with_skill/outputs/code-changes.md",
    "chars": 3715,
    "preview": "# Code Changes: Issue #100 - Built-in arXiv MCP\n\n## 1. NEW FILE: `src/mcp/arxiv.ts`\n\n```typescript\nexport const arxiv = "
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-4/with_skill/outputs/execution-plan.md",
    "chars": 2800,
    "preview": "# Execution Plan: Issue #100 - Built-in arXiv MCP\n\n## Phase 0: Setup\n\n1. `git fetch origin dev`\n2. `git worktree add ../"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-4/with_skill/outputs/pr-description.md",
    "chars": 1010,
    "preview": "# PR: feat(mcp): add built-in arXiv paper search MCP\n\n## Title\n\n`feat(mcp): add built-in arXiv paper search MCP`\n\n## Bod"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-4/with_skill/outputs/verification-strategy.md",
    "chars": 2305,
    "preview": "# Verification Strategy: Issue #100 - arXiv MCP\n\n## Gate A: CI (`ci.yml`)\n\n### What runs\n- `bun test` (split: mock-heavy"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-4/with_skill/timing.json",
    "chars": 76,
    "preview": "{\"total_tokens\": null, \"duration_ms\": 152000, \"total_duration_seconds\": 152}"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-4/without_skill/grading.json",
    "chars": 722,
    "preview": "{\n  \"run_id\": \"eval-4-without_skill\",\n  \"expectations\": [\n    {\"text\": \"Plan uses git worktree in a sibling directory\", "
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-4/without_skill/outputs/code-changes.md",
    "chars": 7520,
    "preview": "# Code Changes: Built-in arXiv MCP\n\n## 1. NEW FILE: `src/mcp/arxiv.ts`\n\n```typescript\nexport const arxiv = {\n  type: \"re"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-4/without_skill/outputs/execution-plan.md",
    "chars": 3854,
    "preview": "# Execution Plan: Add Built-in arXiv MCP (Issue #100)\n\n## Pre-Implementation\n\n1. **Create worktree + branch**\n   ```bash"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-4/without_skill/outputs/pr-description.md",
    "chars": 885,
    "preview": "## Summary\n\n- Add `arxiv` as a 4th built-in remote MCP for arXiv paper search\n- Follows the `grep-app.ts` pattern: stati"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-4/without_skill/outputs/verification-strategy.md",
    "chars": 2925,
    "preview": "# Verification Strategy: arXiv MCP\n\n## 1. Type Safety\n\n```bash\nbun run typecheck\n```\n\nVerify:\n- `McpNameSchema` type uni"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-4/without_skill/timing.json",
    "chars": 76,
    "preview": "{\"total_tokens\": null, \"duration_ms\": 197000, \"total_duration_seconds\": 197}"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-5/eval_metadata.json",
    "chars": 1030,
    "preview": "{\n  \"eval_id\": 5,\n  \"eval_name\": \"regex-fix-false-positive\",\n  \"prompt\": \"The comment-checker hook is too aggressive - i"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-5/with_skill/grading.json",
    "chars": 886,
    "preview": "{\n  \"run_id\": \"eval-5-with_skill\",\n  \"expectations\": [\n    {\"text\": \"Plan uses git worktree in a sibling directory\", \"pa"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-5/with_skill/outputs/code-changes.md",
    "chars": 9569,
    "preview": "# Code Changes\n\n## File 1: `src/config/schema/comment-checker.ts`\n\n### Before\n```typescript\nimport { z } from \"zod\"\n\nexp"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-5/with_skill/outputs/execution-plan.md",
    "chars": 4210,
    "preview": "# Execution Plan: Relax comment-checker \"Note:\" false positives\n\n## Phase 0: Setup (Worktree + Branch)\n\n1. Create worktr"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-5/with_skill/outputs/pr-description.md",
    "chars": 2168,
    "preview": "# PR: fix(comment-checker): relax regex to stop flagging legitimate Note: comments\n\n**Title:** `fix(comment-checker): re"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-5/with_skill/outputs/verification-strategy.md",
    "chars": 3478,
    "preview": "# Verification Strategy\n\n## Gate A: CI (`ci.yml`)\n\n### Pre-push local validation\n```bash\nbun run typecheck              "
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-5/with_skill/timing.json",
    "chars": 76,
    "preview": "{\"total_tokens\": null, \"duration_ms\": 570000, \"total_duration_seconds\": 570}"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-5/without_skill/grading.json",
    "chars": 850,
    "preview": "{\n  \"run_id\": \"eval-5-without_skill\",\n  \"expectations\": [\n    {\"text\": \"Plan uses git worktree in a sibling directory\", "
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-5/without_skill/outputs/code-changes.md",
    "chars": 17420,
    "preview": "# Code Changes: comment-checker false positive fix\n\n## Change 1: Extend config schema\n\n**File: `src/config/schema/commen"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-5/without_skill/outputs/execution-plan.md",
    "chars": 5904,
    "preview": "# Execution Plan: Relax comment-checker hook false positives\n\n## Problem Analysis\n\nThe comment-checker hook delegates to"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-5/without_skill/outputs/pr-description.md",
    "chars": 2123,
    "preview": "## Summary\n\n- Add `allowed_comment_prefixes` config to `CommentCheckerConfigSchema` with sensible defaults (Note:, TODO:"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-5/without_skill/outputs/verification-strategy.md",
    "chars": 4603,
    "preview": "# Verification Strategy\n\n## 1. Unit Tests\n\n### New test file: `allowed-prefix-filter.test.ts`\nRun: `bun test src/hooks/c"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/eval-5/without_skill/timing.json",
    "chars": 76,
    "preview": "{\"total_tokens\": null, \"duration_ms\": 399000, \"total_duration_seconds\": 399}"
  },
  {
    "path": ".opencode/skills/work-with-pr-workspace/iteration-1/review.html",
    "chars": 338379,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"width=device-width, in"
  },
  {
    "path": "AGENTS.md",
    "chars": 8595,
    "preview": "# oh-my-opencode — O P E N C O D E Plugin\n\n**Generated:** 2026-03-06 | **Commit:** 7fe44024 | **Branch:** dev\n\n## OVERVI"
  },
  {
    "path": "CLA.md",
    "chars": 2783,
    "preview": "# Contributor License Agreement\n\nThank you for your interest in contributing to oh-my-opencode (\"Project\"), owned by Yeo"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 8974,
    "preview": "# Contributing to Oh My OpenCode\n\nFirst off, thanks for taking the time to contribute! This document provides guidelines"
  },
  {
    "path": "FIX-BLOCKS.md",
    "chars": 6417,
    "preview": "# Pre-Publish BLOCK Issues: Fix ALL Before Release\n\nTwo independent pre-publish reviews (Opus 4.6 + GPT-5.4) both conclu"
  },
  {
    "path": "LICENSE.md",
    "chars": 3973,
    "preview": "# License\n\nPortions of this software are licensed as follows:\n\n- All third party components incorporated into the oh-my-"
  },
  {
    "path": "README.ja.md",
    "chars": 16906,
    "preview": "> [!WARNING]\n> **一時的なお知らせ(今週): メンテナー対応遅延のお知らせ**\n>\n> コアメンテナーのQが負傷したため、今週は Issue/PR への返信とリリースが遅れる可能性があります。\n> ご理解とご支援に感謝します"
  },
  {
    "path": "README.ko.md",
    "chars": 16740,
    "preview": "> [!WARNING]\n> **임시 공지 (이번 주): 메인테이너 대응 지연 안내**\n>\n> 핵심 메인테이너 Q가 부상을 입어, 이번 주에는 이슈/PR 응답 및 릴리스가 지연될 수 있습니다.\n> 양해와 응원에 감사드"
  },
  {
    "path": "README.md",
    "chars": 22431,
    "preview": "> [!NOTE]\n>\n> [![Sisyphus Labs - Sisyphus is the agent that codes like your team.](./.github/assets/sisyphuslabs.png?v=2"
  },
  {
    "path": "README.ru.md",
    "chars": 23322,
    "preview": "> [!WARNING]\n> **Временное уведомление (на этой неделе): сниженная доступность мейнтейнера**\n>\n> Ключевой мейнтейнер Q п"
  },
  {
    "path": "README.zh-cn.md",
    "chars": 15373,
    "preview": "> [!WARNING]\n> **临时通知(本周):维护者响应延迟说明**\n>\n> 核心维护者 Q 因受伤,本周 issue/PR 回复和发布可能会延迟。\n> 感谢你的耐心与支持。\n\n> [!NOTE]\n>\n> [![Sisyphus La"
  },
  {
    "path": "assets/oh-my-opencode.schema.json",
    "chars": 101308,
    "preview": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"$id\": \"https://raw.githubusercontent.com/code-yeongyu/oh-my"
  },
  {
    "path": "bin/oh-my-opencode.js",
    "chars": 3477,
    "preview": "#!/usr/bin/env node\n// bin/oh-my-opencode.js\n// Wrapper script that detects platform and spawns the correct binary\n\nimpo"
  },
  {
    "path": "bin/platform.d.ts",
    "chars": 384,
    "preview": "export declare function getPlatformPackage(options: {\n  platform: string;\n  arch: string;\n  libcFamily?: string | null;\n"
  },
  {
    "path": "bin/platform.js",
    "chars": 2620,
    "preview": "// bin/platform.js\n// Shared platform detection module - used by wrapper and postinstall\n\n/**\n * Get the platform-specif"
  },
  {
    "path": "bin/platform.test.ts",
    "chars": 6723,
    "preview": "// bin/platform.test.ts\nimport { describe, expect, test } from \"bun:test\";\nimport { getBinaryPath, getPlatformPackage, g"
  },
  {
    "path": "bun-test.d.ts",
    "chars": 931,
    "preview": "declare module \"bun:test\" {\n  export function describe(name: string, fn: () => void): void\n  export function it(name: st"
  },
  {
    "path": "bunfig.toml",
    "chars": 37,
    "preview": "[test]\npreload = [\"./test-setup.ts\"]\n"
  },
  {
    "path": "docs/guide/agent-model-matching.md",
    "chars": 16838,
    "preview": "# Agent-Model Matching Guide\n\n> **For agents and users**: Why each agent needs a specific model — and how to customize w"
  },
  {
    "path": "docs/guide/installation.md",
    "chars": 23090,
    "preview": "# Installation\n\n## For Humans\n\nPaste this into your llm agent session:\n\n```\nInstall and configure oh-my-opencode by foll"
  },
  {
    "path": "docs/guide/orchestration.md",
    "chars": 19295,
    "preview": "# Orchestration System Guide\n\nOh My OpenCode's orchestration system transforms a simple AI agent into a coordinated deve"
  },
  {
    "path": "docs/guide/overview.md",
    "chars": 12916,
    "preview": "# What Is Oh My OpenCode?\n\nOh My OpenCode is a multi-model agent orchestration harness for OpenCode. It transforms a sin"
  },
  {
    "path": "docs/manifesto.md",
    "chars": 5980,
    "preview": "# Manifesto\n\nThe principles and philosophy behind Oh My OpenCode.\n\n---\n\n## Human Intervention is a Failure Signal\n\n**HUM"
  },
  {
    "path": "docs/reference/cli.md",
    "chars": 8470,
    "preview": "# CLI Reference\n\nComplete reference for the `oh-my-opencode` command-line interface.\n\n## Basic Usage\n\n```bash\n# Display "
  },
  {
    "path": "docs/reference/configuration.md",
    "chars": 29219,
    "preview": "# Configuration Reference\n\nComplete reference for `oh-my-opencode.jsonc` configuration. This document covers every avail"
  },
  {
    "path": "docs/reference/features.md",
    "chars": 51486,
    "preview": "# Oh-My-OpenCode Features Reference\n\n## Agents\n\nOh-My-OpenCode provides 11 specialized AI agents. Each has distinct expe"
  },
  {
    "path": "docs/troubleshooting/ollama.md",
    "chars": 3449,
    "preview": "# Ollama Troubleshooting\n\n## Streaming Issue: JSON Parse Error\n\n### Problem\n\nWhen using Ollama as a provider with oh-my-"
  },
  {
    "path": "package.json",
    "chars": 3091,
    "preview": "{\n  \"name\": \"oh-my-opencode\",\n  \"version\": \"3.11.0\",\n  \"description\": \"The Best AI Agent Harness - Batteries-Included Op"
  },
  {
    "path": "packages/darwin-arm64/bin/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "packages/darwin-arm64/package.json",
    "chars": 414,
    "preview": "{\n  \"name\": \"oh-my-opencode-darwin-arm64\",\n  \"version\": \"3.11.0\",\n  \"description\": \"Platform-specific binary for oh-my-o"
  },
  {
    "path": "packages/darwin-x64/bin/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "packages/darwin-x64/package.json",
    "chars": 408,
    "preview": "{\n  \"name\": \"oh-my-opencode-darwin-x64\",\n  \"version\": \"3.11.0\",\n  \"description\": \"Platform-specific binary for oh-my-ope"
  },
  {
    "path": "packages/darwin-x64-baseline/package.json",
    "chars": 435,
    "preview": "{\n  \"name\": \"oh-my-opencode-darwin-x64-baseline\",\n  \"version\": \"3.11.0\",\n  \"description\": \"Platform-specific binary for "
  },
  {
    "path": "packages/linux-arm64/bin/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "packages/linux-arm64/package.json",
    "chars": 440,
    "preview": "{\n  \"name\": \"oh-my-opencode-linux-arm64\",\n  \"version\": \"3.11.0\",\n  \"description\": \"Platform-specific binary for oh-my-op"
  },
  {
    "path": "packages/linux-arm64-musl/bin/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "packages/linux-arm64-musl/package.json",
    "chars": 449,
    "preview": "{\n  \"name\": \"oh-my-opencode-linux-arm64-musl\",\n  \"version\": \"3.11.0\",\n  \"description\": \"Platform-specific binary for oh-"
  },
  {
    "path": "packages/linux-x64/bin/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "packages/linux-x64/package.json",
    "chars": 434,
    "preview": "{\n  \"name\": \"oh-my-opencode-linux-x64\",\n  \"version\": \"3.11.0\",\n  \"description\": \"Platform-specific binary for oh-my-open"
  },
  {
    "path": "packages/linux-x64-baseline/package.json",
    "chars": 461,
    "preview": "{\n  \"name\": \"oh-my-opencode-linux-x64-baseline\",\n  \"version\": \"3.11.0\",\n  \"description\": \"Platform-specific binary for o"
  },
  {
    "path": "packages/linux-x64-musl/bin/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "packages/linux-x64-musl/package.json",
    "chars": 443,
    "preview": "{\n  \"name\": \"oh-my-opencode-linux-x64-musl\",\n  \"version\": \"3.11.0\",\n  \"description\": \"Platform-specific binary for oh-my"
  },
  {
    "path": "packages/linux-x64-musl-baseline/package.json",
    "chars": 470,
    "preview": "{\n  \"name\": \"oh-my-opencode-linux-x64-musl-baseline\",\n  \"version\": \"3.11.0\",\n  \"description\": \"Platform-specific binary "
  },
  {
    "path": "packages/windows-x64/bin/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "packages/windows-x64/package.json",
    "chars": 413,
    "preview": "{\n  \"name\": \"oh-my-opencode-windows-x64\",\n  \"version\": \"3.11.0\",\n  \"description\": \"Platform-specific binary for oh-my-op"
  },
  {
    "path": "packages/windows-x64-baseline/package.json",
    "chars": 440,
    "preview": "{\n  \"name\": \"oh-my-opencode-windows-x64-baseline\",\n  \"version\": \"3.11.0\",\n  \"description\": \"Platform-specific binary for"
  },
  {
    "path": "postinstall.mjs",
    "chars": 1406,
    "preview": "// postinstall.mjs\n// Runs after npm install to verify platform binary is available\n\nimport { createRequire } from \"node"
  },
  {
    "path": "script/build-binaries.test.ts",
    "chars": 2974,
    "preview": "// script/build-binaries.test.ts\n// Tests for platform binary build configuration\n\nimport { describe, expect, it } from "
  },
  {
    "path": "script/build-binaries.ts",
    "chars": 4012,
    "preview": "#!/usr/bin/env bun\n// script/build-binaries.ts\n// Build platform-specific binaries for CLI distribution\n\nimport { $ } fr"
  },
  {
    "path": "script/build-schema-document.ts",
    "chars": 600,
    "preview": "import * as z from \"zod\"\nimport { OhMyOpenCodeConfigSchema } from \"../src/config/schema\"\n\nexport function createOhMyOpen"
  },
  {
    "path": "script/build-schema.test.ts",
    "chars": 589,
    "preview": "import { describe, expect, test } from \"bun:test\"\nimport { createOhMyOpenCodeJsonSchema } from \"./build-schema-document\""
  },
  {
    "path": "script/build-schema.ts",
    "chars": 574,
    "preview": "#!/usr/bin/env bun\nimport { createOhMyOpenCodeJsonSchema } from \"./build-schema-document\"\n\nconst SCHEMA_OUTPUT_PATH = \"a"
  },
  {
    "path": "script/generate-changelog.ts",
    "chars": 2603,
    "preview": "#!/usr/bin/env bun\n\nimport { $ } from \"bun\"\n\nconst TEAM = [\"actions-user\", \"github-actions[bot]\", \"code-yeongyu\"]\n\nasync"
  },
  {
    "path": "script/publish.ts",
    "chars": 14690,
    "preview": "#!/usr/bin/env bun\n\nimport { $ } from \"bun\"\nimport { existsSync } from \"node:fs\"\nimport { join } from \"node:path\"\n\nconst"
  },
  {
    "path": "signatures/cla.json",
    "chars": 54893,
    "preview": "{\n  \"signedContributors\": [\n    {\n      \"name\": \"tsanva\",\n      \"id\": 54318170,\n      \"comment_id\": 3690638858,\n      \"c"
  },
  {
    "path": "src/AGENTS.md",
    "chars": 1888,
    "preview": "# src/ — Plugin Source\n\n**Generated:** 2026-03-06\n\n## OVERVIEW\n\nEntry point `index.ts` orchestrates 5-step initializatio"
  },
  {
    "path": "src/agents/AGENTS.md",
    "chars": 3438,
    "preview": "# src/agents/ — 11 Agent Definitions\n\n**Generated:** 2026-03-06\n\n## OVERVIEW\n\nAgent factories following `createXXXAgent("
  },
  {
    "path": "src/agents/agent-builder.ts",
    "chars": 1939,
    "preview": "import type { AgentConfig } from \"@opencode-ai/sdk\"\nimport type { AgentFactory } from \"./types\"\nimport type { Categories"
  },
  {
    "path": "src/agents/anti-duplication.test.ts",
    "chars": 3935,
    "preview": "/// <reference types=\"bun-types\" />\n\nimport { describe, it, expect } from \"bun:test\"\nimport { buildAntiDuplicationSectio"
  },
  {
    "path": "src/agents/atlas/agent.ts",
    "chars": 4647,
    "preview": "/**\n * Atlas - Master Orchestrator Agent\n *\n * Orchestrates work via task() to complete ALL tasks in a todo list until f"
  },
  {
    "path": "src/agents/atlas/atlas-prompt.test.ts",
    "chars": 5208,
    "preview": "import { describe, test, expect } from \"bun:test\"\nimport { ATLAS_SYSTEM_PROMPT } from \"./default\"\nimport { ATLAS_GPT_SYS"
  },
  {
    "path": "src/agents/atlas/default.ts",
    "chars": 14586,
    "preview": "/**\n * Default Atlas system prompt optimized for Claude series models.\n *\n * Key characteristics:\n * - Optimized for Cla"
  },
  {
    "path": "src/agents/atlas/gemini.ts",
    "chars": 15425,
    "preview": "/**\n * Gemini-optimized Atlas System Prompt\n *\n * Key differences from Claude/GPT variants:\n * - EXTREME delegation enfo"
  },
  {
    "path": "src/agents/atlas/gpt.ts",
    "chars": 16493,
    "preview": "/**\n * GPT-5.4 Optimized Atlas System Prompt\n *\n * Tuned for GPT-5.4 system prompt design principles:\n * - Prose-first o"
  },
  {
    "path": "src/agents/atlas/index.ts",
    "chars": 134,
    "preview": "export { createAtlasAgent, atlasPromptMetadata } from \"./agent\"\nexport type { AtlasPromptSource, OrchestratorContext } f"
  },
  {
    "path": "src/agents/atlas/prompt-checkbox-enforcement.test.ts",
    "chars": 4635,
    "preview": "import { describe, test, expect } from \"bun:test\"\nimport { ATLAS_SYSTEM_PROMPT } from \"./default\"\nimport { ATLAS_GPT_SYS"
  },
  {
    "path": "src/agents/atlas/prompt-section-builder.ts",
    "chars": 3820,
    "preview": "/**\n * Atlas Orchestrator - Shared Utilities\n *\n * Common functions for building dynamic prompt sections used by both\n *"
  },
  {
    "path": "src/agents/builtin-agents/agent-overrides.ts",
    "chars": 2905,
    "preview": "import type { AgentConfig } from \"@opencode-ai/sdk\"\nimport type { AgentOverrideConfig } from \"../types\"\nimport type { Ca"
  },
  {
    "path": "src/agents/builtin-agents/atlas-agent.ts",
    "chars": 2080,
    "preview": "import type { AgentConfig } from \"@opencode-ai/sdk\"\nimport type { AgentOverrides } from \"../types\"\nimport type { Categor"
  },
  {
    "path": "src/agents/builtin-agents/available-skills.ts",
    "chars": 1395,
    "preview": "import type { AvailableSkill } from \"../dynamic-agent-prompt-builder\"\nimport type { BrowserAutomationProvider } from \".."
  },
  {
    "path": "src/agents/builtin-agents/environment-context.ts",
    "chars": 498,
    "preview": "import type { AgentConfig } from \"@opencode-ai/sdk\"\nimport { createEnvContext } from \"../env-context\"\n\ntype ApplyEnviron"
  },
  {
    "path": "src/agents/builtin-agents/general-agents.ts",
    "chars": 3990,
    "preview": "import type { AgentConfig } from \"@opencode-ai/sdk\"\nimport type { BuiltinAgentName, AgentOverrides, AgentPromptMetadata "
  },
  {
    "path": "src/agents/builtin-agents/hephaestus-agent.ts",
    "chars": 3132,
    "preview": "import type { AgentConfig } from \"@opencode-ai/sdk\"\nimport type { AgentOverrides } from \"../types\"\nimport type { Categor"
  },
  {
    "path": "src/agents/builtin-agents/model-resolution.ts",
    "chars": 1189,
    "preview": "import { resolveModelPipeline } from \"../../shared\"\nimport { transformModelForProvider } from \"../../shared/provider-mod"
  },
  {
    "path": "src/agents/builtin-agents/resolve-file-uri.test.ts",
    "chars": 3456,
    "preview": "import { afterAll, beforeAll, describe, expect, mock, test } from \"bun:test\"\nimport { mkdirSync, rmSync, writeFileSync }"
  },
  {
    "path": "src/agents/builtin-agents/resolve-file-uri.ts",
    "chars": 949,
    "preview": "import { existsSync, readFileSync } from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { isAbsolute, resolve } from"
  },
  {
    "path": "src/agents/builtin-agents/sisyphus-agent.ts",
    "chars": 3003,
    "preview": "import type { AgentConfig } from \"@opencode-ai/sdk\"\nimport type { AgentOverrides } from \"../types\"\nimport type { Categor"
  },
  {
    "path": "src/agents/builtin-agents.ts",
    "chars": 7235,
    "preview": "import type { AgentConfig } from \"@opencode-ai/sdk\"\nimport type { BuiltinAgentName, AgentOverrides, AgentFactory, AgentP"
  },
  {
    "path": "src/agents/custom-agent-summaries.ts",
    "chars": 1754,
    "preview": "import type { AgentPromptMetadata } from \"./types\"\nimport { truncateDescription } from \"../shared/truncate-description\"\n"
  },
  {
    "path": "src/agents/delegation-trust-prompt.test.ts",
    "chars": 5111,
    "preview": "import { describe, expect, test } from \"bun:test\"\nimport { createSisyphusAgent } from \"./sisyphus\"\nimport { createHephae"
  },
  {
    "path": "src/agents/dynamic-agent-prompt-builder.test.ts",
    "chars": 9545,
    "preview": "/// <reference types=\"bun-types\" />\n\nimport { describe, it, expect } from \"bun:test\"\nimport {\n  buildCategorySkillsDeleg"
  },
  {
    "path": "src/agents/dynamic-agent-prompt-builder.ts",
    "chars": 19208,
    "preview": "import type { AgentPromptMetadata } from \"./types\"\n\nexport interface AvailableAgent {\n  name: string\n  description: stri"
  },
  {
    "path": "src/agents/env-context.test.ts",
    "chars": 1331,
    "preview": "/// <reference types=\"bun-types\" />\n\nimport { describe, test, expect } from \"bun:test\"\nimport { createEnvContext } from "
  },
  {
    "path": "src/agents/env-context.ts",
    "chars": 570,
    "preview": "/**\n * Creates OmO-specific environment context (timezone, locale).\n * Note: Working directory, platform, and date are a"
  },
  {
    "path": "src/agents/explore.ts",
    "chars": 3912,
    "preview": "import type { AgentConfig } from \"@opencode-ai/sdk\"\nimport type { AgentMode, AgentPromptMetadata } from \"./types\"\nimport"
  },
  {
    "path": "src/agents/hephaestus/agent.test.ts",
    "chars": 7076,
    "preview": "import { describe, expect, test } from \"bun:test\";\nimport {\n  getHephaestusPromptSource,\n  getHephaestusPrompt,\n  create"
  },
  {
    "path": "src/agents/hephaestus/agent.ts",
    "chars": 4240,
    "preview": "import type { AgentConfig } from \"@opencode-ai/sdk\";\nimport type { AgentMode, AgentPromptMetadata } from \"../types\";\nimp"
  },
  {
    "path": "src/agents/hephaestus/gpt-5-3-codex.ts",
    "chars": 22426,
    "preview": "/** GPT-5.3 Codex optimized Hephaestus prompt */\nimport type { AgentConfig } from \"@opencode-ai/sdk\";\nimport type { Agen"
  },
  {
    "path": "src/agents/hephaestus/gpt-5-4.ts",
    "chars": 18635,
    "preview": "/** GPT-5.4 optimized Hephaestus prompt */\n\nimport type {\n  AvailableAgent,\n  AvailableTool,\n  AvailableSkill,\n  Availab"
  },
  {
    "path": "src/agents/hephaestus/gpt.ts",
    "chars": 12202,
    "preview": "/** Generic GPT Hephaestus prompt — fallback for GPT models without a model-specific variant */\n\nimport type {\n  Availab"
  },
  {
    "path": "src/agents/hephaestus/index.ts",
    "chars": 207,
    "preview": "export {\n  createHephaestusAgent,\n  getHephaestusPrompt,\n  getHephaestusPromptSource,\n  hephaestusPromptMetadata,\n} from"
  },
  {
    "path": "src/agents/index.ts",
    "chars": 343,
    "preview": "export * from \"./types\"\nexport { createBuiltinAgents } from \"./builtin-agents\"\nexport type { AvailableAgent, AvailableCa"
  },
  {
    "path": "src/agents/librarian.ts",
    "chars": 11747,
    "preview": "import type { AgentConfig } from \"@opencode-ai/sdk\"\nimport type { AgentMode, AgentPromptMetadata } from \"./types\"\nimport"
  },
  {
    "path": "src/agents/metis.ts",
    "chars": 13011,
    "preview": "import type { AgentConfig } from \"@opencode-ai/sdk\"\nimport type { AgentMode, AgentPromptMetadata } from \"./types\"\nimport"
  },
  {
    "path": "src/agents/momus.test.ts",
    "chars": 2094,
    "preview": "import { describe, test, expect } from \"bun:test\"\nimport { MOMUS_SYSTEM_PROMPT } from \"./momus\"\n\nfunction escapeRegExp(v"
  },
  {
    "path": "src/agents/momus.ts",
    "chars": 14301,
    "preview": "import type { AgentConfig } from \"@opencode-ai/sdk\";\nimport type { AgentMode, AgentPromptMetadata } from \"./types\";\nimpo"
  },
  {
    "path": "src/agents/multimodal-looker.ts",
    "chars": 2280,
    "preview": "import type { AgentConfig } from \"@opencode-ai/sdk\"\nimport type { AgentMode, AgentPromptMetadata } from \"./types\"\nimport"
  },
  {
    "path": "src/agents/oracle.ts",
    "chars": 14679,
    "preview": "import type { AgentConfig } from \"@opencode-ai/sdk\";\nimport type { AgentMode, AgentPromptMetadata } from \"./types\";\nimpo"
  },
  {
    "path": "src/agents/prometheus/behavioral-summary.ts",
    "chars": 2823,
    "preview": "/**\n * Prometheus Behavioral Summary\n *\n * Summary of phases, cleanup procedures, and final constraints.\n */\n\nexport con"
  },
  {
    "path": "src/agents/prometheus/gemini.ts",
    "chars": 13617,
    "preview": "/**\n * Gemini-optimized Prometheus System Prompt\n *\n * Key differences from Claude/GPT variants:\n * - Forced thinking ch"
  },
  {
    "path": "src/agents/prometheus/gpt.ts",
    "chars": 19305,
    "preview": "/**\n * GPT-5.4 Optimized Prometheus System Prompt\n *\n * Tuned for GPT-5.4 system prompt design principles:\n * - XML-tagg"
  },
  {
    "path": "src/agents/prometheus/high-accuracy-mode.ts",
    "chars": 2461,
    "preview": "/**\n * Prometheus High Accuracy Mode\n *\n * Phase 3: Momus review loop for rigorous plan validation.\n */\n\nexport const PR"
  },
  {
    "path": "src/agents/prometheus/identity-constraints.ts",
    "chars": 11201,
    "preview": "/**\n * Prometheus Identity and Constraints\n *\n * Defines the core identity, absolute constraints, and turn termination r"
  },
  {
    "path": "src/agents/prometheus/index.ts",
    "chars": 172,
    "preview": "export {\n  PROMETHEUS_SYSTEM_PROMPT,\n  PROMETHEUS_PERMISSION,\n  getPrometheusPrompt,\n} from \"./system-prompt\"\nexport typ"
  },
  {
    "path": "src/agents/prometheus/interview-mode.ts",
    "chars": 18086,
    "preview": "/**\n * Prometheus Interview Mode\n *\n * Phase 1: Interview strategies for different intent types.\n * Includes intent clas"
  },
  {
    "path": "src/agents/prometheus/plan-generation.ts",
    "chars": 7090,
    "preview": "/**\n * Prometheus Plan Generation\n *\n * Phase 2: Plan generation triggers, Metis consultation,\n * gap classification, an"
  },
  {
    "path": "src/agents/prometheus/plan-template.ts",
    "chars": 13233,
    "preview": "/**\n * Prometheus Plan Template\n *\n * The markdown template structure for work plans generated by Prometheus.\n * Include"
  },
  {
    "path": "src/agents/prometheus/system-prompt.ts",
    "chars": 2286,
    "preview": "import { PROMETHEUS_IDENTITY_CONSTRAINTS } from \"./identity-constraints\"\nimport { PROMETHEUS_INTERVIEW_MODE } from \"./in"
  },
  {
    "path": "src/agents/prometheus-prompt.test.ts",
    "chars": 3403,
    "preview": "import { describe, test, expect } from \"bun:test\"\nimport { PROMETHEUS_SYSTEM_PROMPT } from \"./prometheus\"\nimport { PROME"
  },
  {
    "path": "src/agents/sisyphus/default.ts",
    "chars": 21967,
    "preview": "/**\n * Default/base Sisyphus prompt builder.\n * Used for Claude and other non-specialized models.\n */\n\nimport type {\n  A"
  }
]

// ... and 1415 more files (download for full content)

About this extraction

This page contains the full source code of the code-yeongyu/oh-my-openagent GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 1615 files (7.1 MB), approximately 1.9M tokens, and a symbol index with 4430 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!