Browse Source

Codemap update

Alvin Unreal 3 months ago
parent
commit
51dad9e8e5

+ 199 - 0
.slim/codemap.json

@@ -0,0 +1,199 @@
+{
+  "metadata": {
+    "version": "1.0.0",
+    "last_run": "2026-04-20T21:09:45.113Z",
+    "root": "/Users/alvin/repos/oh-my-opencode-slim",
+    "include_patterns": [
+      "src/**/*.ts",
+      "src/**/*.d.ts",
+      "scripts/**/*.ts",
+      "package.json",
+      "tsconfig.json",
+      "biome.json",
+      "README.md",
+      "AGENTS.md"
+    ],
+    "exclude_patterns": [
+      "opencode/**",
+      "docs/**",
+      "dist/**",
+      "node_modules/**",
+      ".git/**",
+      "**/*.test.ts",
+      "**/*.spec.ts",
+      "**/test/**",
+      "**/*.snap"
+    ],
+    "exceptions": []
+  },
+  "file_hashes": {
+    "AGENTS.md": "a23a101768d4acb25542d54ab9243dd8",
+    "README.md": "60cc9be49a1495bc0a34a6463d610436",
+    "biome.json": "f708d9fb1676b9eb7159e317522ef6c9",
+    "package.json": "8345cbd15291d8f4874325ebdb8baab9",
+    "scripts/generate-schema.ts": "007f340e39adf6c3fd76feda72b71df1",
+    "scripts/verify-opencode-host-smoke.ts": "a87fdb08b123501edf81618a49bc421d",
+    "scripts/verify-release-artifact.ts": "83259be1926459412809013ce16e6fbb",
+    "src/agents/council-master.ts": "f013987f32d30178efb3bfa3030b3ce8",
+    "src/agents/council.ts": "afa3ed4c40b2f91bdc907b850a7e68d3",
+    "src/agents/councillor.ts": "e12284c5f632ba071e97924608375f9c",
+    "src/agents/designer.ts": "6b5786ea6de1fb41b367103824762c9d",
+    "src/agents/explorer.ts": "3213b5fd3c335be5fcc5f2ce3cafde95",
+    "src/agents/fixer.ts": "663d386c6597febc62344a554f90ded8",
+    "src/agents/index.ts": "6a3a02833a57119cb59393624b07b365",
+    "src/agents/librarian.ts": "6959db9e4917acaa14b9beefe465d0c9",
+    "src/agents/observer.ts": "e957caf6f289675bbbd47d795d4ff0bd",
+    "src/agents/oracle.ts": "93d69d90e29898dd6c760ada395e5730",
+    "src/agents/orchestrator.ts": "99daeea34b019990b7e3d86f8ad6454a",
+    "src/background/background-manager.ts": "03e5bf857bbb41210a354a6526caa2b3",
+    "src/background/index.ts": "af7f2545c2f37a547c3edfe18f856b95",
+    "src/background/multiplexer-session-manager.ts": "e06903121bfdbb5237a094422f49fbe9",
+    "src/background/subagent-depth.ts": "ea2d2a5949d50fa8b63307ca220a9f4c",
+    "src/cli/config-io.ts": "e9048becbe09e618f07853ea9050b840",
+    "src/cli/config-manager.ts": "7f2960f55aaebab21d822c586c2b12eb",
+    "src/cli/custom-skills.ts": "da74e53dfd5f570e97a99ea4fd1d0440",
+    "src/cli/index.ts": "759900abd74812e03982e7b42c6774ec",
+    "src/cli/install.ts": "3b9db79a1eaf21605ace124f356c6c8f",
+    "src/cli/model-key-normalization.ts": "7f988cc8109c95382b9ece9730e2a7a5",
+    "src/cli/paths.ts": "77054651c36e730aa3b32682fd26fe70",
+    "src/cli/providers.ts": "12ee3947cd27554e90d34760a3952b6a",
+    "src/cli/skills.ts": "4b3a3aec7ff891608c56d242a0f517f6",
+    "src/cli/system.ts": "b5464d7661ab1c8e196159641ee3bbed",
+    "src/cli/types.ts": "6b3468226ad733b8c4a601677a98a11e",
+    "src/config/agent-mcps.ts": "7e94663fd4a9a827615da53b320dd774",
+    "src/config/constants.ts": "77e199c035c2ee76d6cfa1680c245c67",
+    "src/config/council-schema.ts": "a97d9742d1ef8a68ab5d73a2411a3fed",
+    "src/config/index.ts": "713c6bc1ca211a4746ec8cebcfc94b6e",
+    "src/config/loader.ts": "8419310b841733920d03b99d6204387e",
+    "src/config/schema.ts": "f482c6dc189581037912698db88d62ab",
+    "src/config/utils.ts": "bc3af4a86874329f638a374ac7c00701",
+    "src/council/council-manager.ts": "40603ed65f34d7fd29d2e18e1d5fe97a",
+    "src/council/index.ts": "24cab5b06b4bfd91d2496692650eb18a",
+    "src/hooks/apply-patch/codec.ts": "fce9edab08aab27b5c09bdb46c201203",
+    "src/hooks/apply-patch/errors.ts": "fd2c9d9d185494f2f8b22862bd14700b",
+    "src/hooks/apply-patch/execution-context.ts": "b44fb8ae4c672ab7c0b18fb1aa1915a0",
+    "src/hooks/apply-patch/index.ts": "835302f13810b8cb88d92367d3fc034e",
+    "src/hooks/apply-patch/matching.ts": "2ea9569179cf01c0c010f257cd9278d3",
+    "src/hooks/apply-patch/operations.ts": "2ea0bbef64fcb6bd07a8adf35a490aeb",
+    "src/hooks/apply-patch/patch.ts": "65f24cc7d01d80eeda3016469d8e32ed",
+    "src/hooks/apply-patch/prepared-changes.ts": "bf504dea1fc8723f593093a6c8d9a829",
+    "src/hooks/apply-patch/resolution.ts": "45305823564edf4c9cdf972f5b03859a",
+    "src/hooks/apply-patch/rewrite.ts": "2ba1d58233a4093bf0d5ffde0ad8ff75",
+    "src/hooks/apply-patch/test-helpers.ts": "27b74cc1c0dec6c9dfdbbea4a9724468",
+    "src/hooks/apply-patch/types.ts": "bff517a2050313703b3e8c4af35617d0",
+    "src/hooks/auto-update-checker/cache.ts": "306b85a4beef7fd9959ecdfc655f8c3c",
+    "src/hooks/auto-update-checker/checker.ts": "18a6a25b534a3be31d57b2f5a401f235",
+    "src/hooks/auto-update-checker/constants.ts": "c46dcf24c3184965314f008ede59b7c7",
+    "src/hooks/auto-update-checker/index.ts": "3df09b0bec208c0c962c8f2bd0dab177",
+    "src/hooks/auto-update-checker/types.ts": "b53cb3c5c541d65da160d83451433499",
+    "src/hooks/chat-headers.ts": "2586390fd72f4e19da4d06a6e770aa8f",
+    "src/hooks/delegate-task-retry/guidance.ts": "a121a7fc081422351f4d5b2044aa6024",
+    "src/hooks/delegate-task-retry/hook.ts": "709bd483063a2090fff5b1048861b5c1",
+    "src/hooks/delegate-task-retry/index.ts": "7b78edb6f10cfee10b2c117ca2287378",
+    "src/hooks/delegate-task-retry/patterns.ts": "5e4919da29af630e4e2ec37df0b58025",
+    "src/hooks/filter-available-skills/index.ts": "4cac7bea2a22f57d602de1df22203baa",
+    "src/hooks/foreground-fallback/index.ts": "154b2a954447c70e2bccc68b58262d62",
+    "src/hooks/image-hook.ts": "94e07e33eac132eeb339d4b51f7dfca8",
+    "src/hooks/index.ts": "569c94462498575319218d2b9ac62895",
+    "src/hooks/json-error-recovery/hook.ts": "55f1268777de23ed5546c8f2f0a5b424",
+    "src/hooks/json-error-recovery/index.ts": "c54900170ea905776e973e30b5dd95f4",
+    "src/hooks/phase-reminder/index.ts": "55c78ab86f3b26a071c8e2f639831b8b",
+    "src/hooks/post-file-tool-nudge/index.ts": "7a23d01b3396c4018015e0e90629c45d",
+    "src/hooks/todo-continuation/index.ts": "4bc29a79ce7d85acc120c87a02cd09d2",
+    "src/hooks/todo-continuation/todo-hygiene.ts": "64009dcc4d7b88cc031cb0467ccb0387",
+    "src/index.ts": "f23fb25218b3f510051456e00d4646b5",
+    "src/interview/dashboard.ts": "dbe6703d036ff16952c98f5cc0066e5c",
+    "src/interview/document.ts": "c8c35c9042fdef497925c89ce1dba1b4",
+    "src/interview/helpers.ts": "b95a7e299bb4ab38ab66a272b3ba3612",
+    "src/interview/index.ts": "ab5c9a50b6c08826cfd53233cac75f38",
+    "src/interview/manager.ts": "62c337961c1e5638c3531c33a097c247",
+    "src/interview/parser.ts": "f555be74e939ac8a0e9eaf8fe2b38e11",
+    "src/interview/prompts.ts": "ff6e3cd2e95c407662b143af8db615fc",
+    "src/interview/server.ts": "486e31b94f0353a838a017510931bc50",
+    "src/interview/service.ts": "46f17024044edbcc2a2b8c8f5879f1d4",
+    "src/interview/types.ts": "2614f59dcf6fbbf1d7285644f98149a6",
+    "src/interview/ui.ts": "5f03d5500ed3bd9e5e0fd7449353dc20",
+    "src/mcp/context7.ts": "4e02e8ef204b6eb7e99a3209078428b5",
+    "src/mcp/grep-app.ts": "f76cb0ffb3484b16d55f27729e80e864",
+    "src/mcp/index.ts": "92464b907264ebd630e12a42ae6eee67",
+    "src/mcp/types.ts": "a67078f79aa8b99c41fb5be5d9fa9319",
+    "src/mcp/websearch.ts": "7c507eff1d6f9c01d3ccb928ea648ca7",
+    "src/multiplexer/factory.ts": "5ca22092bbe54953c620aed005485398",
+    "src/multiplexer/index.ts": "7117f0624caae306854253b90852e0b9",
+    "src/multiplexer/tmux/index.ts": "7873a9b809fa16f3266d16bc2d8f702c",
+    "src/multiplexer/types.ts": "09477cd693fa449950d53b0a856e3561",
+    "src/multiplexer/zellij/index.ts": "16b9534fafc904e84faaf862d3a67d37",
+    "src/skills/codemap/README.md": "fbb3e9fd31ae685b87e630df96c3c60a",
+    "src/skills/simplify/README.md": "2786c6e4e6b9f972193353b49741c8e3",
+    "src/tools/ast-grep/cli.ts": "94eea47198f97a4169f009e5249c3f7f",
+    "src/tools/ast-grep/constants.ts": "ef016f4d4c5a6861fed9c28e968cad07",
+    "src/tools/ast-grep/downloader.ts": "eda4a6bc69a3290a2e54f4d46c639bc1",
+    "src/tools/ast-grep/index.ts": "a2e6261cdd8f4ddfd5d89dcd5ad175eb",
+    "src/tools/ast-grep/tools.ts": "3f7c2c65cffd5273b0cd6c849800176d",
+    "src/tools/ast-grep/types.ts": "34ad28b5b1e9617b584f082dba9a427c",
+    "src/tools/ast-grep/utils.ts": "1dd3b2133c4b8c847a26eea0423bc0b2",
+    "src/tools/background.ts": "1b979e158a1ca515fae2755729d449aa",
+    "src/tools/council.ts": "4edec9c98d6e6d4082e5ee4eba0aa9c7",
+    "src/tools/index.ts": "f31e1c25b9af8375dba09a4b16766566",
+    "src/tools/lsp/client.ts": "c8821a8c2cc21c51c26ffb50759e7411",
+    "src/tools/lsp/config-store.ts": "e10072482fbb91b9214fa3bf333aa033",
+    "src/tools/lsp/config.ts": "13aeb4cab14b73db792f6411cc775f8a",
+    "src/tools/lsp/constants.ts": "06f4618b3937e6aaa6ec4076c2e9ed51",
+    "src/tools/lsp/index.ts": "913a5e5cb7f366a05e618905e65b4900",
+    "src/tools/lsp/tools.ts": "023d712c7a06ab9e43851826114309a0",
+    "src/tools/lsp/types.ts": "e11904f9c738f10670abbfbaa185004d",
+    "src/tools/lsp/utils.ts": "c64858938255ab3c964195106af9bff9",
+    "src/tools/smartfetch/binary.ts": "a65d816f46ebef11c39bda1764f82bb7",
+    "src/tools/smartfetch/cache.ts": "9a4e272b897b6914f0925919357bfce1",
+    "src/tools/smartfetch/constants.ts": "1ba20e00a4d3f4717eba62f381f9cd4c",
+    "src/tools/smartfetch/index.ts": "5bbf7898199c2764351dac4bc0b28b84",
+    "src/tools/smartfetch/network.ts": "307d17ba103ad69727c362aafa1a41ee",
+    "src/tools/smartfetch/secondary-model.ts": "83b6d543783bb05ded285da19871f2a4",
+    "src/tools/smartfetch/tool.ts": "03e91727dc3d408bdb7f751ac647c0de",
+    "src/tools/smartfetch/types.ts": "2576efe959365f34b7160c409fb54d26",
+    "src/tools/smartfetch/utils.ts": "ab169376765be6079f24f55862d9a90b",
+    "src/utils/agent-variant.ts": "d1d7492fd659516534845335e9bcd87a",
+    "src/utils/compat.ts": "806de91aefa1d164b004c6ca465d8700",
+    "src/utils/env.ts": "b76fbfea11c340337f6bdd8a9c87bb69",
+    "src/utils/index.ts": "cc35eee0a38f8dd094af5e3b26757804",
+    "src/utils/internal-initiator.ts": "64f4189f18ade892f92c0b30188dcd30",
+    "src/utils/logger.ts": "a73dd89ea1e97870b93d3387be122baf",
+    "src/utils/polling.ts": "b1d9c52df1fae7391234d0f5476d53b5",
+    "src/utils/session.ts": "a6d5dfb749b70bb3b96fee2d0428e1f9",
+    "src/utils/zip-extractor.ts": "11e6d1913e049f46099bb61d4a77e62b",
+    "tsconfig.json": "1d2bb6e93a43366843785a156c8e538a"
+  },
+  "folder_hashes": {
+    ".": "fe9dff93976b069d3333b562d3b87e0b",
+    "scripts": "7ebdcbc44fd1e155c3ef2cc3baecb925",
+    "src": "b3f31c80cf6fc23f609ebd934a5b9662",
+    "src/agents": "b3d9f47d074a62136012bc593054fd10",
+    "src/background": "10d8da779e14ca2191ecad616eb202f3",
+    "src/cli": "b2ffa3472c3b00b2f78d81a02913633c",
+    "src/config": "6dace0dbca5ca35c432ae47c243dd0f2",
+    "src/council": "446f3c30a7c879e8e22383929fdf1c87",
+    "src/hooks": "815f9b023ad0562f55a71e8cd15b656d",
+    "src/hooks/apply-patch": "d3bd03747a4c2ecd199fb68706d4c8d2",
+    "src/hooks/auto-update-checker": "c407065b8052ab293b8c78e643a19297",
+    "src/hooks/delegate-task-retry": "2624117607d8404122e82836c4c74114",
+    "src/hooks/filter-available-skills": "42214100c13e02e3b197f1e7cb1b586a",
+    "src/hooks/foreground-fallback": "7d31d4b918d1e1e1b674dece98e10c4d",
+    "src/hooks/json-error-recovery": "c8a245f5f48918279aa3d7724a573c75",
+    "src/hooks/phase-reminder": "80f01bd7edd895fcd3950a44b21a4d3a",
+    "src/hooks/post-file-tool-nudge": "e01c0aa6e649ec049c068d6a1b2006f9",
+    "src/hooks/todo-continuation": "b2a921fee7ba60ec8fc6cb055611907d",
+    "src/interview": "9284e82da3ddb9c5f140028c0c8c03ee",
+    "src/mcp": "5f5fc5fbb54bf9944063483cee8be88f",
+    "src/multiplexer": "14d687861c06ee71e303f57fb5ecc8bd",
+    "src/multiplexer/tmux": "796d0d51b317bdb05c54dcf257fb5597",
+    "src/multiplexer/zellij": "35ab5e99b43ac4da5a085d1e331da37b",
+    "src/skills": "c93b75814e75bc85966fba4513b81b24",
+    "src/skills/codemap": "1e82ef833612703b786daceb091f2422",
+    "src/skills/simplify": "9c745d8113135e3103af5f1a49d67dfe",
+    "src/tools": "2383d46a3f3878c98702e0470aca0ebb",
+    "src/tools/ast-grep": "2d4ad34fd02c6d068766dd38e826f2a8",
+    "src/tools/lsp": "952fb176aeb025f24ad127b8ca43e3eb",
+    "src/tools/smartfetch": "2b137fd3f65e105b005650b862b14fd7",
+    "src/utils": "7280f2365b7cbed95d7553dfb79dd238"
+  }
+}

+ 11 - 0
AGENTS.md

@@ -250,3 +250,14 @@ OpenCode has a built-in `/review` command that automatically performs comprehens
 - Council manager (multi-LLM orchestration) is in `src/council/`
 - Tmux utilities are in `src/utils/tmux.ts`
 - 468 tests across 35 files — run `bun test` to verify
+
+## Repository Map
+
+A full codemap is available at `codemap.md` in the project root.
+
+Before working on any task, read `codemap.md` to understand:
+- Project architecture and entry points
+- Directory responsibilities and design patterns
+- Data flow and integration points between modules
+
+For deep work on a specific folder, also read that folder's `codemap.md`.

+ 101 - 198
codemap.md

@@ -2,209 +2,112 @@
 
 ## Project Responsibility
 
-**oh-my-opencode-slim** is a lightweight agent orchestration plugin for OpenCode - a slimmed-down fork of oh-my-opencode. It provides a multi-agent system that enables specialized AI agents to work together under an orchestrator to optimize coding tasks for quality, speed, cost, and reliability.
-
-The plugin integrates with OpenCode to provide:
-- **Multi-agent orchestration** with specialized roles (Orchestrator, Explorer, Librarian, Oracle, Designer, Fixer)
-- **Background task management** for long-running async operations
-- **MCP (Model Context Protocol) integration** for external tools and services
-- **LSP (Language Server Protocol) tools** for code intelligence
-- **Code search capabilities** via grep and AST-grep
-- **Tmux integration** for visual task tracking
-- **Configuration system** with agent overrides and skill management
-- **CLI installer** for interactive setup and configuration
+`oh-my-opencode-slim` is an OpenCode plugin that adds a specialist-agent operating model on top of the host runtime. Its core job is to:
 
-## System Entry Points
-
-| File | Purpose | Key Exports |
-|------|---------|-------------|
-| `package.json` | Project manifest, dependencies, and build scripts | `oh-my-opencode-slim` CLI, `dist/index.js` main entry |
-| `src/index.ts` | Main plugin entry point | `OhMyOpenCodeLite` plugin, agent configs, tools, MCPs |
-| `src/cli/index.ts` | CLI installer entry point | `install` command, configuration management |
-| `tsconfig.json` | TypeScript compiler configuration | Build settings, type checking, declaration generation |
-
-### Build Artifacts
+- define orchestrator and specialist agents,
+- load layered plugin configuration and per-agent permissions,
+- expose additional tools and MCP integrations,
+- manage delegated/background work and terminal multiplexer visualization,
+- inject workflow-enforcement hooks,
+- ship install-time skills and a bootstrap CLI.
 
-- `dist/index.js` - Main plugin bundle (ESM)
-- `dist/index.d.ts` - TypeScript declarations
-- `dist/cli/index.js` - CLI bundle
-- `dist/cli/index.d.ts` - CLI TypeScript declarations
+This codemap intentionally covers the plugin repository itself and excludes the nested `opencode/` upstream checkout.
 
-### Published Files
+## System Entry Points
 
-- `dist/` - Built JavaScript and declarations
-- `src/skills/` - Skill definitions (included in npm package)
-- `README.md` - Documentation
-- `LICENSE` - MIT license
+| Path | Role |
+|---|---|
+| `package.json` | Package manifest, dependency graph, release scripts, published file list. |
+| `src/index.ts` | Main plugin bootstrap: wires agents, tools, MCPs, hooks, background managers, interview manager, and config merge behavior. |
+| `src/cli/index.ts` | CLI entrypoint for installation/bootstrap workflows. |
+| `src/config/schema.ts` | Source-of-truth runtime config schema used by validation and schema generation. |
+| `scripts/generate-schema.ts` | Generates `oh-my-opencode-slim.schema.json` from the Zod config schema. |
 
 ## Repository Directory Map
 
 | Directory | Responsibility Summary | Detailed Map |
-|-----------|------------------------|--------------|
-| `src/` | Main plugin entrypoint plus all feature modules that compose agents, tools, hooks, background managers, and utils. | [View Map](src/codemap.md) |
-| `src/agents/` | Defines specialist agents and the orchestrator, with factories and override/permission helpers. | [View Map](src/agents/codemap.md) |
-| `src/background/` | Background task/session managers and tmux pane orchestration for off-thread agent runs. | [View Map](src/background/codemap.md) |
-| `src/cli/` | Installer CLI flow, config edits, provider setup, and skill installation helpers. | [View Map](src/cli/codemap.md) |
-| `src/config/` | Plugin configuration schemas, defaults, loaders, and MCP/agent override helpers. | [View Map](src/config/codemap.md) |
-| `src/hooks/` | Lifecycle hooks for message transforms, error recovery, and rate-limit fallbacks. | [View Map](src/hooks/codemap.md) |
-| `src/hooks/auto-update-checker/` | Startup update check hook with cache invalidation and optional auto-install. | [View Map](src/hooks/auto-update-checker/codemap.md) |
-| `src/hooks/phase-reminder/` | Orchestrator message transform hook that injects phase reminders. | [View Map](src/hooks/phase-reminder/codemap.md) |
-| `src/hooks/post-file-tool-nudge/` | Read/Write tool after-hook that queues ephemeral delegation nudges. | [View Map](src/hooks/post-file-tool-nudge/codemap.md) |
-| `src/hooks/delegate-task-retry/` | Error detection and retry guidance with pattern matching and assistance. | [View Map](src/hooks/delegate-task-retry/codemap.md) |
-| `src/hooks/foreground-fallback/` | Rate-limit fallback manager for interactive sessions. | [View Map](src/hooks/foreground-fallback/codemap.md) |
-| `src/hooks/json-error-recovery/` | JSON parse error detection and recovery helpers. | [View Map](src/hooks/json-error-recovery/codemap.md) |
-| `src/mcp/` | Built-in MCP registry and config types for remote connectors. | [View Map](src/mcp/codemap.md) |
-| `src/tools/` | Tool registry plus LSP, AST-grep, and background task implementations. | [View Map](src/tools/codemap.md) |
-| `src/tools/ast-grep/` | AST-grep CLI discovery, execution, and tool definitions. | [View Map](src/tools/ast-grep/codemap.md) |
-| `src/tools/lsp/` | LSP client stack and tool surface for definitions, diagnostics, and rename. | [View Map](src/tools/lsp/codemap.md) |
-| `src/utils/` | Shared helpers for tmux, environment variables, internal initiation, and config. | [View Map](src/utils/codemap.md) |
-
-## Architecture Overview
-
-### Plugin Initialization Flow
-
-```
-OpenCode loads plugin
-    ↓
-src/index.ts: OhMyOpenCodeLite(ctx)
-    ↓
-Load plugin config (src/config)
-    ↓
-Initialize agent configs (src/agents)
-    ↓
-Initialize background manager (src/background)
-    ↓
-Initialize MCPs (src/mcp)
-    ↓
-Initialize hooks (src/hooks)
-    ↓
-Register tools (src/tools)
-    ↓
-Return plugin object with:
-    - agent: Agent configurations
-    - tool: Tool implementations
-    - mcp: MCP configurations
-    - config: Config merger
-    - event: Event handlers
-    - hooks: Message transforms
-```
-
-### Key Integrations
-
-1. **Agent System** (`src/agents/`)
-   - Orchestrator delegates to specialized subagents
-   - Each agent has specific tools, permissions, and temperature settings
-   - MCP tools configured per agent based on role
-
-2. **Background Tasks** (`src/background/`)
-   - Fire-and-forget task execution
-   - Session lifecycle management
-   - Optional tmux pane integration for visual tracking
-
-3. **Configuration** (`src/config/`)
-   - User, project, and preset config layers
-   - Agent overrides and custom prompts
-   - MCP availability and permissions
-
-4. **Tools** (`src/tools/`)
-   - Code search (grep, AST-grep)
-   - LSP integration (diagnostics, references, rename)
-   - Background task orchestration
-
-5. **MCP Integration** (`src/mcp/`)
-   - Built-in remote MCPs (websearch, context7, grep.app)
-   - Type-safe configuration
-   - Disabled MCP filtering
-
-6. **Hooks** (`src/hooks/`)
-   - Auto-update checking
-   - `apply_patch` stale-patch rescue with strict parsing, bounded LCS fallback, stateful same-path helper updates, and safe canonical rewrites only inside root/worktree
-   - Phase reminders for workflow compliance
-   - Post-read nudges for delegation
-
-## Development Workflow
-
-```bash
-# Build the project
-bun run build
-
-# Type checking
-bun run typecheck
-
-# Run tests
-bun test
-
-# Linting
-bun run lint
-
-# Format code
-bun run format
-
-# Run all checks (lint + format + organize imports)
-bun run check
-
-# CI mode checks (no auto-fix)
-bun run check:ci
-
-# Build and run with OpenCode
-bun run dev
-```
-
-## Key Dependencies
-
-| Dependency | Purpose |
-|------------|---------|
-| `@opencode-ai/plugin` | OpenCode plugin SDK |
-| `@opencode-ai/sdk` | OpenCode AI SDK |
-| `@modelcontextprotocol/sdk` | MCP protocol implementation |
-| `@ast-grep/cli` | AST-aware code search |
-| `vscode-jsonrpc` | JSON-RPC protocol |
-| `vscode-languageserver-protocol` | LSP protocol |
-| `zod` | Runtime validation |
-
-## Extension Points
-
-### Adding New Agents
-
-1. Create agent definition in `src/agents/`
-2. Add to agent factory registry
-3. Configure default model in `src/config/constants.ts`
-4. Add MCP configuration in `src/config/agent-mcps.ts`
-5. Add skill permissions in `src/cli/skills/`
-
-### Adding New Tools
-
-1. Implement tool in `src/tools/`
-2. Export from `src/tools/index.ts`
-3. Register in main plugin (`src/index.ts`)
-4. Configure agent permissions
-
-### Adding New MCPs
-
-1. Define MCP config in `src/mcp/`
-2. Add to `createBuiltinMcps` registry
-3. Configure agent access in `src/config/agent-mcps.ts`
-
-### Adding New Hooks
-
-1. Implement hook in `src/hooks/`
-2. Export factory function from `src/hooks/index.ts`
-3. Register in main plugin (`src/index.ts`)
-
-## Configuration Structure
-
-```typescript
-interface PluginConfig {
-  agents?: {
-    [agentName: string]: AgentOverrideConfig;
-  };
-  tmux?: TmuxConfig;
-  disabled_mcps?: McpName[];
-  background?: BackgroundTaskConfig;
-  presets?: Record<string, Partial<PluginConfig>>;
-}
-```
-
-## License
-
-MIT License - See [LICENSE](LICENSE) for details.
+|---|---|---|
+| `src/` | Main application surface that composes plugin bootstrap, runtime modules, and installer-facing code. | [View Map](src/codemap.md) |
+| `src/agents/` | Agent factory layer for orchestrator, specialists, council agents, and config/permission shaping. | [View Map](src/agents/codemap.md) |
+| `src/background/` | Async task lifecycle management plus session-to-pane coordination for delegated work. | [View Map](src/background/codemap.md) |
+| `src/cli/` | Installer, config editing, provider preset generation, and built-in skill installation. | [View Map](src/cli/codemap.md) |
+| `src/config/` | Configuration schema, defaults, loaders, constant tables, and agent/MCP policy helpers. | [View Map](src/config/codemap.md) |
+| `src/council/` | Multi-model council orchestration and synthesis fallback flow. | [View Map](src/council/codemap.md) |
+| `src/hooks/` | Aggregated runtime hook surface for prompt transforms, recovery logic, nudges, and lifecycle policies. | [View Map](src/hooks/codemap.md) |
+| `src/hooks/apply-patch/` | Structured `apply_patch` parsing, matching, recovery, and rewrite pipeline. | [View Map](src/hooks/apply-patch/codemap.md) |
+| `src/hooks/auto-update-checker/` | Startup update detection, cache handling, and optional install prompt flow. | [View Map](src/hooks/auto-update-checker/codemap.md) |
+| `src/hooks/delegate-task-retry/` | Post-tool retry guidance for failed delegation attempts. | [View Map](src/hooks/delegate-task-retry/codemap.md) |
+| `src/hooks/filter-available-skills/` | Skill-visibility filtering based on agent permission policy. | [View Map](src/hooks/filter-available-skills/codemap.md) |
+| `src/hooks/foreground-fallback/` | Interactive-session fallback control path for rate-limit or degraded foreground execution. | [View Map](src/hooks/foreground-fallback/codemap.md) |
+| `src/hooks/json-error-recovery/` | JSON/tool-output recovery helpers for malformed model responses. | [View Map](src/hooks/json-error-recovery/codemap.md) |
+| `src/hooks/phase-reminder/` | Message-transform reminder enforcing orchestrator workflow phases. | [View Map](src/hooks/phase-reminder/codemap.md) |
+| `src/hooks/post-file-tool-nudge/` | Post-read/write reminder path that nudges delegation-aware next steps. | [View Map](src/hooks/post-file-tool-nudge/codemap.md) |
+| `src/hooks/todo-continuation/` | Auto-continue behavior for outstanding todo execution. | [View Map](src/hooks/todo-continuation/codemap.md) |
+| `src/interview/` | `/interview` feature: prompt/state orchestration, persistence, local UI, and dashboard mode. | [View Map](src/interview/codemap.md) |
+| `src/mcp/` | Built-in MCP registry and per-provider MCP definitions. | [View Map](src/mcp/codemap.md) |
+| `src/multiplexer/` | Terminal multiplexer abstraction layer with backend selection and health helpers. | [View Map](src/multiplexer/codemap.md) |
+| `src/multiplexer/tmux/` | tmux backend implementation for pane lifecycle and layout management. | [View Map](src/multiplexer/tmux/codemap.md) |
+| `src/multiplexer/zellij/` | zellij backend implementation for tab/pane lifecycle. | [View Map](src/multiplexer/zellij/codemap.md) |
+| `src/skills/` | Bundled install-time OpenCode skills shipped as static payloads. | [View Map](src/skills/codemap.md) |
+| `src/skills/codemap/` | Repository-mapping skill package and codemap state-management script. | [View Map](src/skills/codemap/codemap.md) |
+| `src/skills/simplify/` | Behavior-preserving simplification skill package. | [View Map](src/skills/simplify/codemap.md) |
+| `src/tools/` | Tool export surface and orchestration helpers for AST-grep, LSP, smartfetch, council, and background tools. | [View Map](src/tools/codemap.md) |
+| `src/tools/ast-grep/` | AST-grep binary management and AST-aware search/replace tool flow. | [View Map](src/tools/ast-grep/codemap.md) |
+| `src/tools/lsp/` | LSP client pool, transport, formatting, and workspace-edit application. | [View Map](src/tools/lsp/codemap.md) |
+| `src/tools/smartfetch/` | Fetch/extract/cache pipeline for web content and secondary-model summarization. | [View Map](src/tools/smartfetch/codemap.md) |
+| `src/utils/` | Cross-cutting helpers for logging, sessions, compatibility, zip extraction, and runtime metadata. | [View Map](src/utils/codemap.md) |
+| `scripts/` | Build/release validation and generated-artifact maintenance scripts. | [View Map](scripts/codemap.md) |
+
+## Runtime Control Flow
+
+1. **Plugin startup**
+   - OpenCode loads `src/index.ts`.
+   - Config is loaded and normalized through `src/config/`.
+   - Agent definitions are produced by `src/agents/`.
+   - Tool factories from `src/tools/` and MCP definitions from `src/mcp/` are registered.
+   - Hooks from `src/hooks/` are attached.
+   - Background execution, multiplexer support, and interview support are initialized.
+
+2. **Interactive request handling**
+   - The orchestrator prompt drives routing decisions.
+   - Tool calls resolve through `src/tools/` or built-in OpenCode tools.
+   - Hooks can transform prompts/messages or repair tool failures before/after execution.
+
+3. **Delegated/background execution**
+   - `src/background/` creates child sessions and tracks task state.
+   - `src/multiplexer/` optionally mirrors those sessions into tmux/zellij panes.
+   - Results flow back into the parent session through notifications/output polling.
+
+4. **Install/release path**
+   - `src/cli/` configures host OpenCode instances.
+   - `src/skills/` is copied into the user skill directory.
+   - `scripts/` validates generated schema, package completeness, and host-load behavior.
+
+## Key Cross-Module Integration Points
+
+- `src/index.ts` is the central composition root for nearly every runtime subsystem.
+- `src/config/` feeds `src/agents/`, `src/tools/lsp/`, `src/background/`, and MCP registration.
+- `src/cli/skills.ts` and `src/cli/custom-skills.ts` bridge install-time skill packaging with runtime permission policy.
+- `src/background/` depends on `src/multiplexer/` and cooperates with session formatting helpers in `src/utils/`.
+- `src/tools/council.ts` delegates into `src/council/`.
+- `src/hooks/filter-available-skills/` and agent permission logic rely on shared skill names from the CLI/config layer.
+- `src/interview/` hooks into plugin command/event surfaces exposed by `src/index.ts`.
+
+## Root Assets
+
+- `README.md`: user-facing product overview, install docs, and agent descriptions.
+- `AGENTS.md`: agent operating conventions for this repository.
+- `biome.json`: formatting/lint policy.
+- `tsconfig.json`: TypeScript compiler settings.
+- `.slim/codemap.json`: codemap change-detection state for this repository.
+
+## Recommended Reading Order
+
+1. `codemap.md`
+2. `src/codemap.md`
+3. One of:
+   - `src/agents/codemap.md`
+   - `src/background/codemap.md`
+   - `src/tools/codemap.md`
+   - `src/hooks/codemap.md`
+4. Relevant subsystem sub-map for the task at hand

+ 43 - 0
scripts/codemap.md

@@ -0,0 +1,43 @@
+# scripts/
+
+## Responsibility
+
+- Maintain repository-level build, packaging, and release validation automation.
+- Generate derived artifacts from source-of-truth types/schemas and verify that published outputs remain host-safe.
+- Provide pre- and post-packaging checks that prevent leaking local paths and validate plugin installability in external
+  OpenCode runtimes.
+
+## Design
+
+- `generate-schema.ts`
+  - Imports `PluginConfigSchema` from `src/config/schema.ts` and emits canonical JSON Schema via `z.toJSONSchema`.
+  - Writes `oh-my-opencode-slim.schema.json` with explicit `$schema`, `title`, and plugin description.
+- `verify-release-artifact.ts`
+  - Uses `spawnSync` + `npm pack --json --ignore-scripts`.
+  - Scans `dist/**/*` for leaked machine paths (`/Users/*`, `/home/*`).
+  - Validates required package payload keys (`package.json`, `dist/index.js`, `README.md`, `LICENSE`,
+    `src/skills/codemap/SKILL.md`, `src/skills/simplify/SKILL.md`, etc.).
+  - Performs clean install smoke by importing the installed `dist/index.js` default export in a temp project.
+- `verify-opencode-host-smoke.ts`
+  - Builds temporary OpenCode environment (bin from `bun add opencode-ai`), mounts the plugin tarball,
+    launches `opencode serve`, and probes `http://127.0.0.1:<port>/global/health`.
+  - Captures logs and fails on `failed to load plugin` and `cannot find module` patterns.
+- All scripts are executable boundary files (`#!/usr/bin/env bun` / Node), with explicit temp-dir lifecycle management
+  and defensive cleanup via `rmSync(..., { force: true, recursive: true })`.
+
+## Flow
+
+- `bun run build` invokes `scripts/generate-schema.ts` through `package.json#generate-schema` after type declaration generation.
+- `bun run verify:release` runs `verify-release-artifact.ts`: sanitize dist -> pack artifact -> validate files -> install/import check.
+- `bun run verify:host-smoke` runs `verify-opencode-host-smoke.ts`: pack tarball -> boot isolated host -> wait for health -> verify no plugin-load errors.
+- Both verification scripts are non-interactive and designed for CI/CD pre-publish gates.
+
+## Integration
+
+- Bound to `package.json` scripts for local dev and release pipelines.
+- Release verification depends on build outputs from `bun run build:plugin` and `bun run build:cli` because it expects
+  `dist/index.js`, `dist/cli/index.js`, and generated schema.
+- Package integrity expectations are mirrored by tests and release scripts that assert packaged skill metadata and
+  runtime files are present.
+- Smoke checks instantiate the same plugin entrypoint (`dist/index.js`) that `src/index.ts` exports,
+  catching runtime breakage before publishing.

+ 29 - 0
src/council/codemap.md

@@ -0,0 +1,29 @@
+# src/council/
+
+## Responsibility
+
+- Orchestrate multi-agent council sessions by running configured councillors and synthesizing outputs with a master model.
+- Provide a configurable, defensive decision path for model-based consensus, including depth guarding and graceful degradation when partial failures occur.
+
+## Design
+
+- `src/council/index.ts` is a barrel export; implementation is in `council-manager.ts`.
+- `CouncilManager` is injected with `PluginInput`, optional `PluginConfig`, optional `SubagentDepthTracker`, and multiplexer settings.
+- Presets and schema are defined in `config/council-schema.ts` (`default_preset`, councillor/master timeout, retry rules, execution mode).
+- Uses shared formatting/parsing helpers from `utils/session.ts` so councillor/master prompting stays consistent with other session tools.
+
+## Flow
+
+- `runCouncil(prompt, presetName, parentSessionId)`:
+  - Validate depth limit and resolve preset.
+  - Abort early for missing config, unknown preset, or empty councillor set.
+  - Send a lightweight start notification into the parent session.
+  - Run councillors in configured mode (`parallel`/`serial`) with per-councillor timeout and retries.
+  - Aggregate completed responses; if none succeed, return failure.
+  - Run master synthesis on success; if master fails, fallback to a single completed councillor response with context.
+
+## Integration
+
+- Used by `createCouncilTool` in the tools layer for explicit user-triggered council sessions.
+- Depends on `SubagentDepthTracker` to prevent runaway nested delegation.
+- Reuses the same OpenCode session API contract (`client.session`) as background tasks and other agent orchestration modules.

+ 25 - 74
src/hooks/apply-patch/codemap.md

@@ -1,82 +1,33 @@
-# apply-patch codemap
+# apply-patch
 
-## Hook responsibility
+## Responsibility
 
-`src/hooks/apply-patch/` intercepts only the `apply_patch` tool before OpenCode executes it and, when it detects a stale but recoverable patch, rewrites only the canonical old lines so the native runtime can apply it without inventing new changes. If any patch path falls outside `root`/`worktree`, the hook blocks `apply_patch` before native execution.
+Provide a resilient preprocessor for `tool.execute.before` on `apply_patch` that rewrites recoverable stale hunks, validates workspace boundaries, and blocks unsafe patches before they reach OpenCode’s native patch executor.
 
-## Flow
-
-1. `index.ts` keeps the hook always active and calls `rewritePatchText(...)`.
-2. `operations.ts` remains a thin internal barrel over the concrete modules.
-3. `codec.ts` parses the `*** Begin Patch` / `*** End Patch` format and can serialize it again.
-4. `resolution.ts` resolves each chunk against the real file and canonicalizes safe tolerant matches.
-5. `matching.ts` implements exact matching and tolerant rescue paths (unicode, trim, prefix/suffix, and a bounded conservative LCS).
-6. `patch.ts` remains a compatibility shim; internal code imports the concrete modules.
-
-## Modules
-
-### `types.ts`
-- Shared patch-domain types.
-- Separates public contracts (`PatchChunk`, `PreparedChange`, etc.) from the logic.
-
-### `codec.ts`
-- `normalizeUnicode()` and `stripHeredoc()`.
-- `parsePatch()` converts text into hunks, and `parsePatchStrict()` provides the strict validation used by rewrite/prepare.
-- `formatPatch()` rebuilds the patch by reusing the lines from `new_lines` byte-for-byte; if an insertion is re-anchored, it also adds the required intact anchor line.
-
-### `matching.ts`
-- Exact/unicode/trim comparators.
-- `seek()` / `seekMatch()` and `list()` search for sequences.
-- `prefix()` / `suffix()` provide edge-based rescue.
-- `rescueByPrefixSuffix()` and `rescueByLcs()` recover stale chunks deterministically.
+## Design
 
-### `resolution.ts`
-- `readFileLines()` reads the file as logical lines; `deriveNewContent()` rebuilds it while preserving the detected physical EOL (`LF` or `CRLF`).
-- `resolveChunkStart()` uses `change_context` as the initial anchor.
-- `locateChunk()` chooses between exact match, canonicalized tolerant match, edge rescue, or LCS rescue.
-- `resolveUpdateChunks()` detects overlaps, prepares ordered hits, and handles the special anchored-insertion path for chunks without `old_lines`, including safe EOF canonicalization when the anchor only resolved through tolerant matching.
-- `deriveNewContent()` / `deriveNewContentFromText()` and `applyHits()` produce the final content while preserving `LF`/`CRLF` and the physical final-newline state in updates.
+- Entry point is `createApplyPatchHook` in `index.ts`, bound to `tool.execute.before`.
+- `rewritePatch` (`operations.ts`) is the main pipeline used by the hook and is backed by:
+  - `parseValidatedPatch` / `createPatchExecutionContext` (`execution-context.ts`) for patch parsing and path/state validation.
+  - `parsePatch` / `parsePatchStrict` / `formatPatch` (`codec.ts`) for patch AST conversion and serialization.
+  - `resolveChunkStart`, `locateChunk`, `resolveUpdateChunks`, `applyHits` (`resolution.ts`) for context matching.
+  - `resolveBy...` helpers in `matching.ts` (`seek`, `seekMatch`, `list`, `rescueByPrefixSuffix`, `rescueByLcs`) for tolerant matching.
+- `types.ts` defines domain contracts used across modules (`PatchChunk`, `PatchHunk`, `ResolvedChunk`, `ApplyPatchErrorKind`, etc.).
+- Error semantics are centralized in `errors.ts` (`ApplyPatchError`, `createApplyPatchBlockedError`, `createApplyPatchVerificationError`, `isApplyPatchError`) and surfaced in hook logging and thrown errors.
+- No additional runtime configuration is exposed; behavior is controlled by constant `APPLY_PATCH_RESCUE_OPTIONS` (`prefixSuffix` + `lcsRescue`).
 
-### `execution-context.ts`
-- `parseValidatedPatch()` centralizes upfront validation.
-- Owns the path guard, realpath/stat caches, and the staged file-state machine.
-- `createPatchExecutionContext()` is the shared entry point for rewrite/prepare.
-
-### `rewrite.ts`
-- `rewritePatchText()` rewrites update chunks when rescue or safe canonicalization happened.
-- It performs a global pre-scan of `add`/`delete`/`update`/`move` before rewriting anything.
-- `rewritePatch()` validates `Delete File` with the same staged state machine as `preparePatchChanges()`; this makes it fail if the file no longer exists in the prepared context (real missing file, double delete, or delete after a previous move/delete) before delegating to the native runtime.
-- `rewritePatch()` also detects when an `Update File` is no longer self-contained because it consumes staged state from an earlier hunk (for example `add -> update`, `move -> update`, or `update -> update`) and collapses that chain into a canonical form that is safe for the native runtime.
-- It keeps the merge/minimize/collapse helpers used for dependent update groups.
-
-### `prepared-changes.ts`
-- `preparePatchChanges()` converts hunks into filesystem changes while accumulating state per path to support multiple sequential `Update File` hunks on the same file.
-- `applyPreparedChanges()` is documented as an internal best-effort rollback helper that consumes the output of `preparePatchChanges()`, not as a universal transactional engine; it also revalidates the basic shape of the legacy array (types/text/normalized absolute paths) and filesystem invariants before touching disk.
-
-### `operations.ts`
-- Thin internal facade/barrel that preserves existing imports for the hook, tests, and compatibility shim.
-
-### `patch.ts`
-- Thin facade/barrel.
-- Re-exports only the stable public API used by the hook and the tests.
-
-## Invariants
+## Flow
 
-- The hook remains always active and has no public config.
-- Content provided through `new_lines` is neither normalized nor rewritten; it is only reused byte-for-byte, except for the intact anchor line that may be added for re-anchored insertions.
-- Updates preserve the detected physical `EOL` and whether the original file ended with a newline.
-- If a path falls outside `root`/`worktree`, the hook blocks `apply_patch` before native execution.
-- No new limits, flags, or runtime settings are introduced.
-- The scope of this rescue remains limited to `apply_patch`; it does not rewrite `edit` or `write`.
-- Errors remain descriptive and keep the `apply_patch verification failed` prefix where it already existed.
-- Normal rewriting remains limited to `update` chunks; only dependent chains between hunks may collapse a previous `add` into the equivalent final state to make the patch self-contained again.
-- If an exact resolution depends on the staged result of earlier hunks, the patch is no longer considered "intact" and is collapsed into a self-contained form before handoff to native.
-- `Delete File` shares the same staged semantics in both rewrite and prepare; an already invalid delete must not reach native.
-- Resolved chunks cannot overlap.
+1. `createApplyPatchHook` filters only `input.tool === 'apply_patch'`.
+2. It requires `output.args.patchText` to be a string.
+3. It resolves `root` and `worktree` from `input.directory` / `ctx.directory` / `ctx.worktree`.
+4. It calls `rewritePatch(root, patchText, options, worktree)`.
+5. On `result.changed`, it replaces `output.args.patchText` with canonicalized patch text.
+6. On failure, it normalizes to `ApplyPatchError`, logs `blocked | validation | verification | internal`, and rethrows so native execution is prevented.
 
-## Quick maintenance guide
+## Integration
 
-- Parsing or rendering issue for patches? → `codec.ts`
-- Issue locating stale lines? → `matching.ts` and `resolution.ts`
-- Issue writing files or moving paths? → `prepared-changes.ts`
-- Need to know what the real hook consumes? → `index.ts` and `patch.ts`
+- Consumed by `src/index.ts` through `createApplyPatchHook`.
+- Acts before native tool execution via OpenCode hook point `tool.execute.before`.
+- Downstream dependencies include `ctx.client` indirectly only for context, and `utils/logger` for structured hook telemetry.
+- Uses `Patch` parser/resolver modules to keep `new_lines` byte-preserving while only mutating stale anchors and chunk context.

+ 26 - 15
src/hooks/auto-update-checker/codemap.md

@@ -2,27 +2,38 @@
 
 ## Responsibility
 
-- Provides an OpenCode hook that reacts to `session.created`, ensures the hook only runs once per startup, and surfaces update information to the user via TUI toasts and logs.
-- Detects local development builds, cached installs, and running plugins pinned to specific versions so the hook can decide whether to notify, auto-update, or skip work.
+- Provide a startup hook that detects plugin update availability for `oh-my-opencode-slim`, reports status through TUI toasts, and optionally performs a cache-safe `bun install` refresh.
+- Handle local dev mode and pinned plugin versions distinctly (`file://`, pinned tags, and `latest` channel semantics).
 
 ## Design
 
-- `index.ts` orchestrates the hook lifecycle: it filters session events, defers the heavy work via `setTimeout`, and delegates version discovery and updates to helper functions while respecting the user’s `autoUpdate` and `showStartupToast` preferences.
-- `checker.ts` encapsulates environment-aware utilities (config path discovery, local dev detection, NPM registry fetching, and pinned-version mutation) plus memoized cache lookups so the hook can derive current, cached, and latest versions without duplicating logic.
-- `cache.ts` is responsible for invalidating cached installs (`node_modules`, `package.json`, `bun.lock`) before a fresh `bun install`, keeping the cached package state consistent with the server-provided latest version.
-- Shared `constants.ts` standardizes paths (cache directory, config locations, package name, registry URL) and fetch timeouts so the rest of the hook is configuration-free.
+- `createAutoUpdateCheckerHook(ctx, options)` in `index.ts` registers an `event` handler for `session.created` and guards one-time startup execution (`hasChecked`).
+- `runBackgroundUpdateCheck` performs version resolution and branches into:
+  - local-dev no-op path,
+  - pinned plugin notification,
+  - manual notification when `autoUpdate=false`,
+  - or auto-update execution path.
+- `checker.ts` is the core discovery layer and exports:
+  - `findPluginEntry`, `extractChannel`, `getCachedVersion`, `getLocalDevVersion`, `getLatestVersion`, `updatePinnedVersion`.
+- `cache.ts` owns cache preparation with `resolveInstallContext` and `preparePackageUpdate`.
+- `constants.ts` centralizes install and config-path constants (`CACHE_DIR`, `PACKAGE_NAME`, `NPM_REGISTRY_URL`, `NPM_FETCH_TIMEOUT`, config path aliases).
+- `types.ts` declares `AutoUpdateCheckerOptions`, `PluginEntryInfo`, config/package typed envelopes.
 
 ## Flow
 
-- On the first `session.created` event without a parent session, `createAutoUpdateCheckerHook` schedules `runBackgroundUpdateCheck` while immediately showing an initial toast (unless disabled) and short-circuiting for local dev builds.
-- `runBackgroundUpdateCheck` resolves the current plugin entry and cached version, determines the update channel via `extractChannel`, retrieves the latest dist-tag from `getLatestVersion`, and compares versions.
-- When an update is available, the hook either notifies the user or, if `autoUpdate` is on, updates the pinned entry in the OpenCode config (`updatePinnedVersion`), invalidates the cached package, and runs `bun install` safely (`runBunInstallSafe`) with a 60-second timeout before showing success/error toasts.
-- `checker.ts` supports the above flow with helpers (`getLocalDevVersion`, `findPluginEntry`, `getCachedVersion`, `extractChannel`, etc.) that read configs (`.opencode/*.jsonc`, global config paths) via `stripJsonComments` and `fs` operations.
-- `cache.ts` runs before reinstall to remove lingering plugin directories, dependency entries, and JSON-formatted `bun.lock` references, ensuring `runBunInstallSafe` operates on a clean slate.
+1. On first eligible `session.created` (root/no parent), schedule asynchronous update check.
+2. If local development plugin is detected (`getLocalDevVersion`), emit info toast and return.
+3. Resolve current version from `getCachedVersion` + plugin entry in config (`findPluginEntry`).
+4. Fetch channel metadata (`extractChannel` + `getLatestVersion`).
+5. If update is needed:
+   - pinned entry ⇒ notify only,
+   - unpinned and `autoUpdate=false` ⇒ notify only,
+   - unpinned and auto-update enabled ⇒ call `preparePackageUpdate`, then `runBunInstallSafe`.
+6. Surface success/failure via `ctx.client.tui.showToast` and `utils/logger`.
 
 ## Integration
 
-- Hooks into the OpenCode plugin lifecycle via `ctx.client.tui.showToast` and the `session.created` event, leveraging `PluginInput` to know the working directory and show UI feedback.
-- Reads OpenCode configuration files exposed by `../../cli/config-manager` to locate plugin entries, pinned versions, and local `file://` installs, so it stays aligned with the same config sources that enable plugin loading.
-- Uses shared `../../utils/logger` for tracing background operations and errors while talking to platform APIs (`fetch`, `Bun.spawn`, `fs`) to inspect, mutate, and reinstall the `oh-my-opencode-slim` package stored under `CACHE_DIR`.
-- Exposes `AutoUpdateCheckerOptions` for consumers (via `index.ts`) to opt out of toasts or automatic installs while still reusing the same checker/cache helpers.
+- Wired through `src/hooks/index.ts` and plugin initialization (`src/index.ts`) as an `event` hook.
+- Consumes `PluginInput.client.tui.showToast`, `PluginInput.directory`, `ctx.client` context, and reads config paths through `cli/config-manager` (`stripJsonComments`, `getOpenCodeConfigPaths`).
+- Runtime interactions use `crossSpawn` for `bun install`, Node `fs/path`, and `fetch` against `NPM_REGISTRY_URL`.
+- Export surface includes `getAutoUpdateInstallDir` and `AutoUpdateCheckerOptions` for testability and host-side overrides.

+ 18 - 10
src/hooks/codemap.md

@@ -4,25 +4,33 @@ This directory exposes the public hook entry points that feature code imports to
 
 ## Responsibility
 
-Acts as a single entry point that re-exports the factory functions and types for every hook implementation underneath `src/hooks/`, so other modules can import from a flat namespace without needing to know subpaths.
+Acts as the central export surface for all runtime hooks in `src/hooks/*`, so callers can register feature behavior from one namespace (`src/hooks/index.ts`) without depending on subfolder internals.
 
 ## Design
 
-- **Aggregator/re-export pattern**: `index.ts` consolidates all hook factories and types for the entire hooks subsystem.
-- **Factory-based design**: Each hook is a factory function that returns a hook object with specific hook points (e.g., `'tool.execute.after'`, `'experimental.chat.messages.transform'`, `'chat.headers'`).
-- **Modular architecture**: Each hook lives in its own subdirectory with internal components (hook implementation, patterns, guidance, etc.).
-- **Event-driven hooks**: Hooks respond to OpenCode plugin events and modify output before it reaches the LLM or UI.
+- **Aggregator/re-export pattern**: `src/hooks/index.ts` re-exports hook factories, classes, and types from submodules.
+- **Factory architecture**: Every feature module exports a `create*Hook` factory and returns an object implementing one or more OpenCode lifecycle surfaces (`tool.execute.before`, `tool.execute.after`, message/system transforms, `event`, command handlers).
+- **Submodule boundary**: Each behavior class/function set is isolated in a folder (`auto-update-checker/`, `foreground-fallback/`, etc.) with a local `index.ts` shim.
+- **Typed hook contracts**: The exported signatures use concrete OpenCode plugin types where available (`PluginInput`) and strict internal helper shapes for internal state.
 
 ## Flow
 
-1. **Import**: Feature modules import factories from `src/hooks/index.ts` (e.g., `createPhaseReminderHook`, `createJsonErrorRecoveryHook`).
-2. **Configure**: Call factory with any required context (e.g., `PluginInput` for client access).
-3. **Register**: Hook objects are registered with OpenCode's plugin system via the feature layer.
-4. **Execute**: At runtime, OpenCode invokes hook functions at specific points (tool execution, message transformation, event handling).
-5. **Modify**: Hooks inspect input/output and apply side-effects (inject text, modify headers, append guidance).
+1. Consumers import from `src/hooks/index.ts` (e.g. `createTodoContinuationHook`, `createPhaseReminderHook`).
+2. Plugin initialization in `src/index.ts` invokes hook factories with `PluginInput` and optional config.
+3. OpenCode dispatches lifecycle callbacks at tool, message, system, event, and command surfaces.
+4. Each implementation mutates the provided payload (e.g., `output.output`, `output.messages`, `output.system`) or triggers client APIs.
+5. Hook handlers produce side effects like retries, prompts, reminders, and metadata updates.
 
 ## Integration
 
+- `createAutoUpdateCheckerHook`: lifecycle `event` (`session.created`) and startup `ctx.client.tui` notifications.
+- `createApplyPatchHook`: `tool.execute.before` pre-processing for `apply_patch` arguments.
+- `createDelegateTaskRetryHook`, `createJsonErrorRecoveryHook`, `createPostFileToolNudgeHook`, `createFilterAvailableSkillsHook`: primarily `tool.execute.after` / message-transform surfaces.
+- `createPhaseReminderHook`, todo-continuation message system handlers: `experimental.chat.messages.transform` / `experimental.chat.system.transform`.
+- `ForegroundFallbackManager`: wired to the global event stream for foreground fallback on rate-limit conditions.
+- `createChatHeadersHook`, `processImageAttachments`: transport/attachments/header-level integrations.
+- All submodules are consumed through `src/index.ts`, which also wires `auto-continue` command integration from `todo-continuation`.
+
 ### Hook Points
 
 | Hook Point | Purpose | Hooks |

+ 33 - 0
src/hooks/delegate-task-retry/codemap.md

@@ -0,0 +1,33 @@
+# src/hooks/delegate-task-retry/
+
+## Responsibility
+
+- Detect delegate tool argument failures after execution and append structured, actionable retry guidance directly into string outputs so the model can recover in-place.
+
+## Design
+
+- `patterns.ts` defines the declarative error contract:
+  - `DelegateTaskErrorPattern` (`pattern`, `errorType`, `fixHint`)
+  - `DELEGATE_TASK_ERROR_PATTERNS`
+  - `detectDelegateTaskError(output: string): DetectedError | null`
+- `guidance.ts` implements `buildRetryGuidance(errorInfo)` and `extractAvailableList` to render fix text with optional `Available:` details from tool output.
+- `hook.ts` implements `createDelegateTaskRetryHook`:
+  - targets only `task` and `background_task`.
+  - only mutates when `output.output` is string.
+  - detects errors via `detectDelegateTaskError` and appends guidance once.
+- `index.ts` is a strict re-export boundary.
+
+## Flow
+
+1. At `tool.execute.after`, confirm tool is `task` or `background_task`.
+2. Verify output payload type is string.
+3. Quick-scan for generic error indicators (`[ERROR]`, `Invalid arguments`, `is not allowed...`).
+4. Match each configured `DELEGATE_TASK_ERROR_PATTERNS` substring in output.
+5. Resolve `DetectedError` and append `\n` + `buildRetryGuidance(...)`.
+
+## Integration
+
+- Registered via `src/hooks/index.ts` as a `tool.execute.after` hook for tool-call outputs.
+- No dependencies on scheduling/backends (`task` execution itself is delegated to OpenCode core), limiting blast radius.
+- Input/output compatibility is limited to OpenCode hook payload shape (`{ tool, output }`) and string-based error diagnostics.
+- Primarily consumed by `src/index.ts` where delegation robustness is needed for orchestrator tool usage.

+ 32 - 0
src/hooks/filter-available-skills/codemap.md

@@ -0,0 +1,32 @@
+# src/hooks/filter-available-skills/
+
+## Responsibility
+
+- Filter `<available_skills>` payload fragments in outgoing messages so they only include skills permitted for the active agent.
+
+## Design
+
+- Factory `createFilterAvailableSkillsHook(_ctx, config)` is defined in `index.ts` and implements `experimental.chat.messages.transform`.
+- `getCurrentAgent(messages)` scans backward for the latest user message and defaults to `orchestrator`.
+- `filterAvailableSkillsText(text, permissionRules)` is the pure transformation function used per message part.
+- Permissions flow:
+  - `getAgentOverride(config, agentName)` from `cli/config` resolves override arrays.
+  - `getSkillPermissionsForAgent` from `cli/skills` resolves canonical rules (`allow`, `ask`, `deny` wildcard).
+  - `isSkillAllowed` checks exact skill rule first, then `'*'` wildcard fallback.
+- `<available_skills>...</available_skills>` and nested `<skill>...</skill>` blocks are matched with regex extraction.
+
+## Flow
+
+1. In transform output, determine `agentName` via `getCurrentAgent`.
+2. Load `permissionRules = getSkillPermissionsForAgent(agentName, configuredSkills)`.
+3. For each `text` part containing `<available_skills>`, run regex replacement:
+   - parse `<skill>` entries,
+   - keep only allowed names,
+   - fallback to `<available_skills>\nNo skills available.\n</available_skills>` when none match.
+4. Write transformed `part.text` back to `output.messages` in place.
+
+## Integration
+
+- Hook is wired in `src/hooks/index.ts` and consumed by plugin hook registration.
+- Executed in the message path prior to model call, so users do not see changed prompt text in UI, but the model receives constrained capabilities.
+- Depends on `cli/skills` and `config` modules, and `PluginInput` only for registration compatibility.

+ 30 - 0
src/hooks/foreground-fallback/codemap.md

@@ -0,0 +1,30 @@
+# src/hooks/foreground-fallback/
+
+## Responsibility
+
+- Keep foreground (interactive) sessions alive when rate limiting is detected by switching the same session to the next model in a configured fallback chain and re-prompting asynchronously.
+
+## Design
+
+- `index.ts` exports `ForegroundFallbackManager` and `isRateLimitError`.
+- `ForegroundFallbackManager` tracks per-session state in maps:
+  - `sessionModel`, `sessionAgent`, `sessionTried`, `lastTrigger`, `inProgress`.
+- `isRateLimitError(error)` performs regex checks over `{ message, data.statusCode, data.message, data.responseBody }`.
+- `handleEvent` is the event dispatcher for `message.updated`, `session.error`, `session.status`, `subagent.session.created`, `session.deleted`.
+- `resolveChain(agentName, currentModel)` defines deterministic chain choice (agent-specific > inferred from current model > flattened fallback).
+- `tryFallback` performs dedupe (`DEDUP_WINDOW_MS`), aborts stale attempts, selects next untried model, fetches last user message, calls `session.abort()`, then `session.promptAsync()` with same user parts and new model.
+
+## Flow
+
+1. Every relevant event arrives at `handleEvent`.
+2. On suspected rate-limit signal, `handleEvent` calls `tryFallback(sessionID)`.
+3. `tryFallback` skips if in-progress, duplicate within 5s, or no candidate chain.
+4. It resolves the active chain, marks attempted models (`sessionTried`), parses `provider/model` with `parseModel`, and fetches last user message via `client.session.messages`.
+5. If a user message exists, it aborts current turn with `session.abort`, then re-issues using `promptAsync` with parsed model.
+6. Success updates `sessionModel`; `session.deleted` path clears all per-session maps.
+
+## Integration
+
+- Integrated through `src/index.ts` into global plugin event stream.
+- Consumes `PluginInput['client']` session APIs and reads fallback chain configuration from plugin startup composition.
+- Works in parallel to background fallback logic in task manager without altering core session scheduling.

+ 30 - 0
src/hooks/json-error-recovery/codemap.md

@@ -0,0 +1,30 @@
+# src/hooks/json-error-recovery/
+
+## Responsibility
+
+- Detect likely JSON syntax/parse failures in tool outputs and append a strong, non-redundant recovery prompt so the model replays corrected JSON on retry.
+
+## Design
+
+- `hook.ts` contains the implementation with exported constants:
+  - `JSON_ERROR_TOOL_EXCLUDE_LIST`
+  - `JSON_ERROR_PATTERNS`
+  - `JSON_ERROR_REMINDER`
+- `createJsonErrorRecoveryHook(_ctx)` returns a `tool.execute.after` handler that appends reminder text when parsing failed.
+- `JSON_ERROR_REMINDER_MARKER` prevents recursive duplicate injection.
+- Exclusion is by lowercase tool name (`bash`, `read`, `glob`, web tools) through a `Set`.
+- Matching uses regex literals in `JSON_ERROR_PATTERNS` and short-circuits for non-string output.
+- `index.ts` only re-exports hook/constant surface.
+
+## Flow
+
+1. In `tool.execute.after`, normalize `input.tool` to lowercase and skip excluded tools.
+2. Skip when `output.output` is not a string.
+3. Skip if output already contains `JSON_ERROR_REMINDER_MARKER`.
+4. Evaluate all `JSON_ERROR_PATTERNS`; on match, append `\n${JSON_ERROR_REMINDER}` to `output.output`.
+
+## Integration
+
+- Exported from `src/hooks/index.ts` and attached to tool output lifecycle at plugin registration.
+- Only consumes hook payload contracts (`ToolExecuteAfterInput`, `ToolExecuteAfterOutput`) and standard string checks, making it generic across tools.
+- No direct dependency on tool internals; integrates by observing tool-call results before they are surfaced to the model.

+ 17 - 6
src/hooks/phase-reminder/codemap.md

@@ -1,19 +1,30 @@
 # src/hooks/phase-reminder/
 
-<!-- Explorer: Fill in this section with architectural understanding -->
-
 ## Responsibility
 
-Keep the orchestrator agent’s working memory on track by injecting a terse phase reminder directly into the payload sent to the API. Because the reminder lives in `experimental.chat.messages.transform`, it doesn’t surface in the UI until the next response is generated, yet it keeps the delegate→plan→execute→verify workflow in scope for every user turn.
+Keep orchestrator guidance aligned over long turns by prepending a phase reminder to the latest user message text before the next LLM request.
 
 ## Design
 
-Exports a single factory (`createPhaseReminderHook`) that supplies an `experimental.chat.messages.transform` handler. The hook stores the reminder template in `PHASE_REMINDER`, scopes mutation to the orchestrator (or default session) only, and rewrites the first text part of the last user message by prefixing it with the reminder plus a divider. Encapsulating this in a synchronous factory keeps the hook pluggable and compatible with the global hook registry.
+- `PHASE_REMINDER` constant is composed from `PHASE_REMINDER_TEXT` (`config/constants.ts`).
+- `createPhaseReminderHook()` returns a single `experimental.chat.messages.transform` handler.
+- Message filtering is role/agent-aware:
+  - locates the latest `'user'` role in `output.messages`,
+  - only mutates if no explicit agent or `agent === 'orchestrator'`,
+  - no-op for internal control messages containing `SLIM_INTERNAL_INITIATOR_MARKER`.
+- Mutation target is the first `text` part in that message; replacement is an in-place prefix.
+- Uses `SLIM_INTERNAL_INITIATOR_MARKER` from `../../utils` to avoid feedback loops.
 
 ## Flow
 
-When the hook fires, it inspects the outgoing messages array, walks backward to locate the last `'user'` role entry, and short-circuits if none exists. If the user message belongs to another agent, it skips mutation. Otherwise it finds the first text part, prepends the reminder block (and a separator) to the existing text, and leaves the rest of the payload untouched. Since it modifies `output.messages` just before the API call, downstream components (like UI) never see the reminder; it only influences the assistant’s reasoning in the next turn.
+1. On transform, scan backward through `messages` for last `info.role === 'user'`.
+2. If agent is non-orchestrator, return.
+3. Locate first part where `type === 'text'`.
+4. If marker exists, return.
+5. Prefix `part.text` with `PHASE_REMINDER + '\n\n---\n\n'`.
 
 ## Integration
 
-Registered through the shared hook registry, this module hooks the `experimental.chat.messages.transform` lifecycle event that runs right before OpenAI invocation. It only touches the orchestrator session’s outgoing message list, so its effect is indirect: the reminder guides every assistant response that follows the user turn, but no other module needs to call it explicitly.
+- Registered through `src/hooks/index.ts` and plugin-level hook wiring in `src/index.ts`.
+- Consumes `experimental.chat.messages.transform` and mutates the outgoing `messages` payload only.
+- Does not depend on stateful services; no network or client APIs are required.

+ 17 - 7
src/hooks/post-file-tool-nudge/codemap.md

@@ -1,19 +1,29 @@
 # src/hooks/post-file-tool-nudge/
 
-<!-- Explorer: Fill in this section with architectural understanding -->
-
 ## Responsibility
 
-Provide a lightweight safety net that reminds the orchestrator to stay in the delegation workflow whenever it reads or writes project files. Read/Write tool results are treated as evidence only; the hook now queues a one-shot reminder for the next system prompt instead of modifying the persisted tool output.
+Detect recent file interaction (`Read`/`Write`) and queue a one-shot workflow reminder that is injected on the next system prompt transform without mutating tool execution output.
 
 ## Design
 
-Exports a single factory (`createPostFileToolNudgeHook`) that returns handlers for `tool.execute.after`, `experimental.chat.system.transform`, and session lifecycle events. The tool hook records pending session IDs for Read/Write tools, while the system transform consumes each pending ID once and appends the existing workflow reminder only when the caller allows injection for that session. The event handler clears stale pending IDs when sessions are deleted. This preserves the delegation behavior without contaminating persisted tool output.
+- Factory `createPostFileToolNudgeHook(options?)` emits three handlers:
+  - `tool.execute.after`
+  - `experimental.chat.system.transform`
+  - `event`
+- A per-instance in-memory `pendingSessionIds: Set<string>` tracks sessions that recently ran file tools.
+- `FILE_TOOLS` is the canonical set `{ 'Read', 'read', 'Write', 'write' }`.
+- Injection is optional per session via `options.shouldInject?: (sessionID) => boolean`.
+- Cleanup path handles both `session.deleted` payload shapes (`properties.sessionID` and `properties.info.id`).
 
 ## Flow
-
-The hook is instantiated once and registered with the hook system. When a Read or Write tool completes, `tool.execute.after` verifies the tool name and session ID, then stores the session ID in an in-memory pending set. On the next `experimental.chat.system.transform` call for that session, the hook deletes the pending marker and appends the workflow reminder to the outgoing system prompt. Multiple Read/Write calls before the next model turn collapse into one reminder, non-orchestrator sessions can be consumed without injection, and deleted sessions are removed from the pending set.
+1. `tool.execute.after`: if tool is file tool and has `sessionID`, add it to `pendingSessionIds`.
+2. `experimental.chat.system.transform`: if session has pending marker, remove it and append `POST_FILE_TOOL_NUDGE` (`PHASE_REMINDER_TEXT`) to `output.system`.
+3. Optional `shouldInject` gate can consume without injecting.
+4. Additional `Read`/`Write` events before the same transform collapse to one reminder due to set semantics.
+5. `session.deleted` event removes stale session IDs from the set.
 
 ## Integration
 
-Plugged into the global hook registry, this module intercepts every tool response via the `tool.execute.after` lifecycle event, participates in system prompt transformation via `experimental.chat.system.transform`, and listens to session deletion events for cleanup. It intentionally does not mutate `output.output`, so file contents remain clean for persistence, replay, and compaction while the orchestrator still receives the intended delegation reminder.
+- Registered via `src/hooks/index.ts` and activated in plugin lifecycle registration.
+- Mutates `output.system` only, ensuring persisted file tool outputs remain untouched.
+- Consumed by orchestrator session flows that need anti-pattern mitigation (`inspect/edit` loops).

+ 58 - 0
src/hooks/todo-continuation/codemap.md

@@ -0,0 +1,58 @@
+# src/hooks/todo-continuation/
+
+## Responsibility
+
+Automatically continue orchestrator work when open todos remain, while enforcing
+multiple safeguards (question suppression, cooldown, explicit abort handling) to
+avoid runaway automation.
+
+## Design
+
+- `createTodoContinuationHook(ctx, config?)` in `index.ts` is the public
+  factory and returns the complete hook contract: command, tool, message,
+  system-transform, and event handlers.
+- Internal state is tracked by `ContinuationState` (per-session timers, session
+  tracking, suppression windows, request signatures, and auto-injection flags).
+- `todo-hygiene.ts` is extracted as a dedicated reminder state machine with
+  reasons: `general`, `delegation_resume`, `final_active` and exposes:
+  `createTodoHygiene`, `handleRequestStart`, `handleToolExecuteAfter`,
+  `handleChatSystemTransform`, and `handleEvent`.
+- Message analysis is implemented in `handleMessagesTransform` with helpers like
+  `getLastExternalUserMessage`, `isExternalUserMessage`, and `inferSessionID`,
+  and ignores internal markers via `SLIM_INTERNAL_INITIATOR_MARKER`.
+- Continuation prompt string uses `CONTINUATION_PROMPT`; reminder strings come
+  from `TODO_HYGIENE_REMINDER`, `TODO_DELEGATION_RESUME_REMINDER`,
+  `TODO_FINAL_ACTIVE_REMINDER`.
+
+## Flow
+
+### Auto-continuation
+
+1. `handleMessagesTransform` identifies the latest external user message and
+   request boundary signature, then calls `hygiene.handleRequestStart`.
+2. `handleCommandExecuteBefore` processes `command === 'auto_continue'` and
+   toggles auto-continuation with `enabled` on/off.
+3. `handleToolExecuteAfter` records request context and may queue a continuation
+   prompt using `ctx.client.session.prompt`.
+4. `handleChatSystemTransform` injects only one continuation reminder per request
+   round when guards pass.
+5. `handleEvent` and `handleChatMessage` update session registries and clear stale
+   state on `session.deleted` / new boundaries.
+
+### Todo hygiene
+
+1. `createTodoHygiene.handleToolExecuteAfter` observes post-tool activity to
+   arm reminders based on todo state transitions.
+2. `createTodoHygiene.handleChatSystemTransform` injects one reminder into
+   `output.system` if open todos remain and session is still injectable.
+3. Reminder priorities resolve deterministically, with `final_active` overriding
+   other reasons.
+4. Session deletion clears pending states through `clear()`/`clearCycle()`.
+
+## Integration
+
+- Imported from `src/hooks/index.ts` and wired in `src/index.ts`.
+- Relies on OpenCode APIs on `ctx.client.session` (`todo`, `messages`, `prompt`).
+- Uses utility helpers from `../../utils` (`log`, `createInternalAgentTextPart`,
+  `SLIM_INTERNAL_INITIATOR_MARKER`) and config via hook options
+  (`maxContinuations`, `cooldownMs`, `autoEnable`, `autoEnableThreshold`).

+ 64 - 0
src/interview/codemap.md

@@ -0,0 +1,64 @@
+# src/interview/
+
+## Responsibility
+
+- Implement the `/interview` command feature end-to-end: parsing user invocation, building assistant prompts, tracking interview state, persisting markdown artifacts, and serving a local web UI.
+- Coordinate two execution modes: per-session self-hosted interview server (default) and shared dashboard mode for multi-process concurrency.
+- Keep interview lifecycle state synchronized between local markdown files, in-memory records, and dashboard caches for resumable/spec-recovery flows.
+
+## Design
+
+- `manager.ts` is the interview composition root and exposes a narrow adapter contract:
+  - `registerCommand`
+  - `handleCommandExecuteBefore`
+  - `handleEvent`
+- `manager.ts` decides runtime mode and wires a `createInterviewService(ctx, interviewConfig)` instance with one of:
+  - `createInterviewServer` (private per-process server), or
+  - dashboard orchestration via `tryBecomeDashboard`, `probeDashboard`, `readDashboardAuthFile`, and periodic dashboard fallback polling.
+- `service.ts` owns interview domain state and business rules:
+  - `interviewsById`, `activeInterviewIds`, `sessionBusy`
+  - `handleCommandExecuteBefore` for `/interview` handling
+  - `submitAnswers` and `handleNudgeAction` to inject internal prompts via `session.promptAsync`
+  - `getInterviewState`, `listInterviewFiles`, and `listInterviews`.
+- `document.ts` handles filesystem layout and transformation primitives: `createInterviewFilePath`, `resolveExistingInterviewPath`, `ensureInterviewFile`, `rewriteInterviewDocument`, `appendInterviewAnswers`, `readInterviewDocument`.
+- `parser.ts` validates structured agent output from `<interview_state>` blocks using `parseAssistantState` and `findLatestAssistantState` with `zod` schemas from `types.ts`.
+- `server.ts` exposes HTTP endpoints for dashboard and interview UI with typed handlers in `helpers.ts`.
+- `ui.ts` renders HTML views (`renderDashboardPage`, `renderInterviewPage`) for `/` and `/interview/{id}`.
+- `dashboard.ts` implements shared interview registry/auth and recovery mechanics (`createDashboardServer`, token auth, file rescan/rebuild, pending answers/nudges).
+- `prompts.ts` provides structured prompts for kickoff/resume/answer flows.
+- `types.ts` defines transport and domain contracts (`InterviewRecord`, `InterviewState`, `InterviewStateEntry`, schemas `RawInterviewStateSchema` / `RawQuestionSchema`).
+
+## Flow
+
+- `src/index.ts` initializes interview support via `createInterviewManager(ctx, config)`.
+- `manager.ts` computes effective port and dashboard flag (`interview.dashboard` / `interview.port > 0`) and selects mode:
+  - **Per-session**: instantiate `createInterviewService` + `createInterviewServer` on port `0`.
+  - **Dashboard**: attempt leadership with `tryBecomeDashboard`.
+- In dashboard leader mode:
+  - push state changes through local callback `setStatePushCallback`
+  - register created interviews and sessions into dashboard cache
+  - expose auth + scan discovery + file rehydration.
+- In dashboard client mode:
+  - resolve dashboard base URL and token
+  - register current process as session with `/api/register`
+  - deliver state via `pushStateViaHttp` / `/api/interviews/{id}/state`
+  - periodically poll `/api/interviews/{id}/pending` and `/api/interviews/{id}/nudge`.
+- `service.handleCommandExecuteBefore`:
+  - if no idea and no active interview -> ask for one
+  - if idea matches file slug -> `resumeInterview`
+  - else -> `createInterview` and inject kickoff/resume prompts.
+- `service.syncInterview` loads session messages, extracts latest valid assistant state, rewrites interview markdown, computes `InterviewState.mode`, and invokes state callbacks.
+- `handleEvent` listens for `session.status`/`session.deleted` to update busy flags, consume pending UI actions, refresh state, and mark interviews abandoned on session delete.
+- `server.ts` route flow:
+  - `/` and `/api/interviews` render list state
+  - `/interview/:id` renders interview UI
+  - `/api/interviews/:id/state` returns JSON state
+  - POST `/api/interviews/:id/answers` validates payload and forwards to `submitAnswers`
+  - POST `/api/interviews/:id/nudge` forwards action to `handleNudgeAction`.
+
+## Integration
+
+- Consumed by plugin bootstrap in `src/index.ts`; command pre-hook and event dispatch invoke the manager methods returned by `createInterviewManager`.
+- Integrated with OpenCode session API via `PluginInput.client.session` for message reads/prompt injection.
+- Exposed to users through local HTTP UI endpoints from whichever active server instance is running.
+- Used by tests in `interview/*.test.ts` for command mode transitions, server behavior, parsing, and command registration.

+ 0 - 2
src/mcp/codemap.md

@@ -1,7 +1,5 @@
 # src/mcp/
 
-<!-- Explorer: Fill in this section with architectural understanding -->
-
 ## Responsibility
 
 - Define and expose the built-in MCP endpoints (websearch, context7, grep.app) alongside the shared type aliases so the application can treat remote and local MCPs uniformly (`src/mcp/index.ts`, `src/mcp/types.ts`).

+ 34 - 0
src/multiplexer/codemap.md

@@ -0,0 +1,34 @@
+# src/multiplexer/
+
+## Responsibility
+
+- Abstract terminal multiplexer integration behind a unified interface for background session visualization.
+- Select the correct implementation based on configuration (`tmux`, `zellij`, `auto`, `none`) and runtime environment.
+- Expose shared utilities required by task orchestration and health-gating logic.
+
+## Design
+
+- `types.ts` is the boundary contract:
+  - `Multiplexer` (`spawnPane`, `closePane`, `applyLayout`, `isAvailable`, `isInsideSession`).
+  - `PaneResult` and `MultiplexerFactory`.
+  - `isServerRunning(serverUrl, timeoutMs, maxAttempts)` for shared health checks.
+- `factory.ts` implements mode selection and instance creation in `getMultiplexer`:
+  - direct construction for explicit `tmux`/`zellij`
+  - environment-based fallback in `auto` (`TMUX` vs `ZELLIJ`, else disabled)
+  - no caching: each call creates a fresh object to capture live environment (`TMUX_PANE` / `ZELLIJ`).
+- `index.ts` re-exports factories and contracts and both concrete implementations.
+- `startAvailabilityCheck` is a fire-and-forget availability preflight by calling `multiplexer.isAvailable()` asynchronously.
+- `getAutoMultiplexerType` is a pure helper used by tests/diagnostics to determine current effective backend.
+
+## Flow
+
+- `src/index.ts` computes `multiplexerConfig`, creates a one-shot probe instance in init, and starts `startAvailabilityCheck` for telemetry/log warming.
+- Consumers request concrete objects via `getMultiplexer(config)` and must handle `null` when disabled.
+- `MultiplexerSessionManager` consumes `spawnPane`, `closePane`, and `isServerRunning` in a unified lifecycle.
+- Concrete implementations apply their own platform-specific pane semantics while sharing the same abstractions.
+
+## Integration
+
+- Used by `background/background-manager.ts` for feature-gating background pane support and by `background/multiplexer-session-manager.ts` for session lifecycle hooks.
+- Implementations live in `src/multiplexer/tmux` and `src/multiplexer/zellij`; callers must pass `(sessionId, description, serverUrl, directory)`.
+- Unit tests in `src/multiplexer/factory.test.ts` validate mode selection, `none` behavior, and `auto` environment precedence.

+ 40 - 0
src/multiplexer/tmux/codemap.md

@@ -0,0 +1,40 @@
+# src/multiplexer/tmux/
+
+## Responsibility
+
+- Provide tmux-specific pane orchestration for attaching OpenCode child sessions to a split pane beside the current pane.
+- Handle lifecycle of spawned panes (create, rename, layout rebalancing, graceful close).
+- Resolve and cache tmux executable location for repeated operations.
+
+## Design
+
+- `TmuxMultiplexer` in `index.ts` implements `Multiplexer`.
+- `findBinary` uses platform command (`which` or `where`) and validates the binary via `-V`.
+- `isAvailable` caches `binaryPath` and `hasChecked` to avoid repeated lookups.
+- `targetPane` captures `process.env.TMUX_PANE` and is reused as `targetArgs()` for scoped tmux actions.
+- Command execution is performed with `crossSpawn` to support both Bun and Node process interfaces.
+- `quoteShellArg` provides shell-safe quoting used for directory/URL/session injection in `opencode` commands.
+
+## Flow
+
+- `spawnPane(sessionId, description, serverUrl, directory)`:
+  - ensure binary through `getBinary()`
+  - build command: `opencode attach <url> --session <sessionId> --dir <directory>`
+  - execute `tmux split-window -h -d -P -F '#{pane_id}' ...` with optional `-t <TMUX_PANE>`
+  - on success:
+    - rename pane with `select-pane -T` using first 30 chars of `description`
+    - call `applyLayout(storedLayout, storedMainPaneSize)`.
+- `applyLayout(layout, mainPaneSize)`:
+  - `select-layout` on current target
+  - for `main-*` layouts, update `main-pane-height|width` and re-select layout for deterministic size.
+- `closePane(paneId)`:
+  - `send-keys -t <pane> C-c`
+  - wait 250ms
+  - `kill-pane -t <pane>`
+  - on success, re-run `applyLayout` to rebalance panes.
+
+## Integration
+
+- Selected when `multiplexerConfig.type === 'tmux'` or auto mode resolves to tmux (`process.env.TMUX`).
+- Consumed by `MultiplexerSessionManager` in `background/multiplexer-session-manager.ts` for `session.created` spawn and completion cleanup.
+- Uses `ctx.directory` as working directory, OpenCode API URL as `serverUrl`, and session id as `opencode attach --session` target.

+ 44 - 0
src/multiplexer/zellij/codemap.md

@@ -0,0 +1,44 @@
+# src/multiplexer/zellij/
+
+## Responsibility
+
+- Implement zellij-backed pane orchestration for background/sub-agent tasks as an alternative to tmux.
+- Maintain a dedicated `opencode-agents` tab and route all spawned attach sessions into it.
+- Keep process cleanup and first-run reuse behavior to avoid repeated pane inflation.
+
+## Design
+
+- `ZellijMultiplexer` in `index.ts` implements `Multiplexer`.
+- `findBinary` is a simple `which/where zellij` probe with cached path.
+- `isInsideSession` checks `process.env.ZELLIJ`; `isAvailable` uses cached `binaryPath`.
+- First creation path builds/repurposes one dedicated tab (`opencode-agents`) via `ensureAgentTab` and tracks:
+  - `agentTabId`
+  - `firstPaneId`
+  - `firstPaneUsed`
+- Command composition is done by helper builders:
+  - `buildOpencodeAttachCommand`
+  - `buildShellLaunchCommand`
+- Layout is intentionally a no-op because zellij does not expose equivalent layout APIs used by this codebase.
+
+## Flow
+
+- `spawnPane(sessionId, description, serverUrl, directory)`:
+  - resolve zellij binary and call `ensureAgentTab`
+  - if first pane in the agent tab is free, execute attach command in-place via `runInPane`:
+    - `focus-pane --pane-id`
+    - `rename-pane`
+    - `write-chars` launch command + newline
+  - otherwise create a new pane via `new-pane --name <desc> --close-on-exit -- sh -lc <opencode attach ...>`.
+  - when called from user tab, temporarily switch to `agentTabId` and back to keep user context.
+  - return `{ success, paneId }` where pane ids are validated as `terminal_*`.
+- `closePane(paneId)`:
+  - `action write --pane-id <id> \u0003` (graceful SIGINT equivalent)
+  - wait 250ms
+  - `action close-pane --pane-id <id>`; treats exit codes `0` and `1` as successful closure.
+- `applyLayout` is intentionally no-op and retained for interface compatibility.
+
+## Integration
+
+- Selected by `getMultiplexer` in explicit `zellij` mode or env-driven `auto` when `process.env.ZELLIJ` is present.
+- Consumed by `MultiplexerSessionManager` as the pane backend in zellij environments.
+- UI attach command semantics are identical to tmux in argument shape: `opencode attach <url> --session <sessionId> --dir <directory>`, so background tasks remain config-agnostic across backends.

+ 40 - 0
src/skills/codemap.md

@@ -0,0 +1,40 @@
+# src/skills/
+
+## Responsibility
+
+- Own metadata-driven OpenCode custom skills shipped with this package.
+- Maintain the skill contract artifacts (`SKILL.md`, `README.md`, per-skill helper files) that are copied into
+  `${configDir}/skills` at install time.
+- Preserve a canonical registry boundary: runtime code consumes skill definitions as data, not as executable
+  plugin dependencies.
+
+## Design
+
+- `CUSTOM_SKILLS` in `src/cli/custom-skills.ts` is the authoritative skill manifest for bundled
+  skills; each entry maps folder name + `sourcePath` to an install-time consumer.
+- `install.ts` runs `installCustomSkill()` which recursively copies `src/skills/codemap` and
+  `src/skills/simplify` into the OpenCode skills directory.
+- This directory is partitioned by skill:
+  - `src/skills/codemap/` (command-style repository mapping skill)
+  - `src/skills/simplify/` (readability/refactor guidance skill)
+- Files are considered static runtime payload. No plugin TS module in `src/` imports these files directly; they
+  are loaded by OpenCode via filesystem installation.
+
+## Flow
+
+- `bun run install` delegates to `src/cli/install.ts`, where `installCustomSkills` gates copying of
+  each `CUSTOM_SKILLS` entry.
+- `installCustomSkill()` computes `packageRoot`, validates `sourcePath`, then performs a recursive
+  directory copy via `copyDirRecursive()`.
+- During plugin release, the `files` whitelist in `package.json` must include `src/skills` so
+  `src/skills/**` survive `npm pack`.
+- OpenCode plugin startup discovers these installed folders and reads each `SKILL.md` as a prompt-level contract.
+
+## Integration
+
+- `src/cli/custom-skills.ts`: source-of-truth registry consumed by installer and permission helpers.
+- `src/cli/skills.ts:getSkillPermissionsForAgent()` auto-populates permission rules for
+  `codemap` and `simplify` when agent policy is derived from built-in recommendations.
+- `verify-release-artifact.ts` enforces artifact completeness by asserting `src/skills/simplify/SKILL.md`
+  and `src/skills/codemap/SKILL.md` are present in the tarball.
+- `package.json` scripts (`verify:release`, `build`) rely on these assets to ensure install-time skill availability.

+ 36 - 0
src/skills/codemap/codemap.md

@@ -0,0 +1,36 @@
+# src/skills/codemap/
+
+## Responsibility
+
+- Provide a command-style skill package that standardizes repository mapping workflows for unfamiliar codebases.
+- Define the task contract used by Orchestrator/fixer agents via `SKILL.md` and operational guidance via `README.md`.
+- Generate and evolve change-aware codemap state artifacts (`.slim/codemap.json`) and scaffold placeholders (`codemap.md`).
+
+## Design
+
+- Contract layer: `SKILL.md` (machine prompt contract) + `README.md` (human-facing operation notes).
+- Execution layer: `scripts/codemap.mjs` exports deterministic helper functions:
+  - `parseArgs(argv)`
+  - `cmdInit`, `cmdChanges`, `cmdUpdate`
+  - `selectFiles`, `computeFileHash`, `computeFolderHash`, `createEmptyCodemap`
+  - `loadState`, `saveState`, `migrateLegacyState`
+- Persistence model: JSON state at `.slim/codemap.json` with `metadata`, `file_hashes`, and `folder_hashes`.
+- Testing layer: `scripts/codemap.test.ts` validates pattern matching, hash determinism, and migration behavior.
+- The script intentionally avoids network and mutates only filesystem-local state and codemap templates.
+
+## Flow
+
+- Entry point `main(argv)` parses command and arguments (`init|changes|update`, `--root`, `--include`, `--exclude`, `--exception`) and dispatches via strict branches.
+- `cmdInit()` computes include/exclude candidate sets using `selectFiles()` and writes:
+  1) `.slim/codemap.json` via `saveState()`
+  2) one `codemap.md` per discovered folder via `createEmptyCodemap()`.
+- `cmdChanges()` reloads state (`loadState()` + `migrateLegacyState()`), recomputes current hashes, emits added/removed/modified diffs and affected folder list, and exits non-zero if state is absent.
+- `cmdUpdate()` recomputes full state from existing metadata and persists it, used after targeted fixers finish updates.
+- `codemap` skill invocation path in SKILL workflow is explicit: Step 1 checks `.slim/codemap.json` or `.slim/cartography.json`, then Step 2/3 selects init or incremental path.
+
+## Integration
+
+- Installed under OpenCode through `src/cli/custom-skills.ts` as `name: 'codemap'`, `sourcePath: 'src/skills/codemap'`.
+- `src/cli/install.ts` copies this directory into the user skill directory; OpenCode executes `scripts/codemap.mjs` from that context.
+- `src/hooks/filter-available-skills/index.ts` applies agent-level skill gating via names from `getSkillPermissionsForAgent()`.
+- `scripts/verify-release-artifact.ts` includes codemap skill metadata and runtime checks as required packaged files.

+ 36 - 0
src/skills/simplify/codemap.md

@@ -0,0 +1,36 @@
+# src/skills/simplify/
+
+## Responsibility
+
+- Provide a behavior-preserving refactoring skill contract that constrains code cleanup to clarity-focused,
+  low-risk changes.
+- Define explicit quality gates (understand-before-edit, behavior parity, incremental simplification, rollback-friendly diffs)
+  for any simplification task.
+- Ship only metadata; no local runtime state machine is kept in this directory.
+
+## Design
+
+- Contract layer: `SKILL.md` is the executable prompt specification with explicit phases:
+  - pre-change understanding
+  - simplification candidate selection
+  - incremental transformation and verification
+  - final review checklist.
+- Documentation layer: `README.md` explains intent, source provenance, and plugin install behavior.
+- Policy model is declarative (`description`, allowed usage, checklist) consumed by the OpenCode skill executor,
+  without helper scripts or plugin code dependencies.
+
+## Flow
+
+- Agent discovery resolves `src/skills/simplify` as a custom skill entrypoint, then reads `SKILL.md` at runtime.
+- Runtime behavior is gated by `src/cli/custom-skills.ts` (`allowedAgents: ['oracle']`) and by skill permissions
+  computed in `getSkillPermissionsForAgent()`.
+- In practice the workflow is read-only and context-driven: simplify instructions require understanding of callers,
+  edge cases, and tests before mutation, then apply local, scoped refactors with validation.
+- Consumers (Fixer/Oracle/Reviewer tasks) rely on this contract as operational constraints, not as executable TypeScript.
+
+## Integration
+
+- Installed by plugin installer (`installCustomSkills`) using `src/cli/install.ts` via `installCustomSkill()`.
+- Permission surface is enforced by hook layer in `src/hooks/filter-available-skills/index.ts` (`permissionRules`).
+- Release integrity: `scripts/verify-release-artifact.ts` checks for `src/skills/simplify/SKILL.md` in package tarballs.
+- Operationally paired with codemap/fixer flows in `src/index.ts` orchestrations for post-feature readability hardening.

+ 89 - 289
src/tools/codemap.md

@@ -1,300 +1,100 @@
-# src/tools/ Codemap
-
 ## Responsibility
 
-The `src/tools/` directory provides the core tool implementations for the oh-my-opencode-slim plugin. It exposes three main categories of tools:
-
-1. **AST-grep** - AST-aware structural code search and replacement across 25+ languages
-2. **LSP** - Language Server Protocol integration for code intelligence (definition, references, diagnostics, rename)
-3. **Background Tasks** - Fire-and-forget agent task management with automatic notification
-
-These tools are consumed by the OpenCode plugin system and exposed to AI agents for code navigation, analysis, and modification tasks.
-
----
+- Expose plugin tool definitions for code intelligence and workflow tooling from
+  `src/tools/index.ts`.
+- Publish and compose three primary operational domains:
+  - AST pattern search/replace via `ast-grep/`.
+  - Language server tooling via `lsp/`.
+  - URL fetch/transform with optional secondary model via `smartfetch/`.
+- Provide runtime factories for orchestration helpers:
+  - `createBackgroundTools` (`background.ts`) and `createCouncilTool` (`council.ts`).
+- Expose runtime entry contracts (`lspManager`, `setUserLspConfig`, utility
+  constants/types) for plugin bootstrap and config hooks.
 
 ## Design
 
-### Architecture Overview
-
-```
-src/tools/
-├── index.ts              # Central export point
-├── background.ts         # Background task tools (3 tools)
-├── ast-grep/
-│   ├── cli.ts            # CLI execution, path resolution, binary download
-│   ├── index.ts          # Module re-exports
-│   ├── types.ts          # TypeScript interfaces (CliLanguage, CliMatch, SgResult)
-│   ├── utils.ts          # Output formatting (formatSearchResult, formatReplaceResult)
-│   ├── constants.ts      # CLI path resolution, safety limits
-│   └── downloader.ts     # Binary auto-download for missing ast-grep
-└── lsp/
-    ├── client.ts         # LSP client & connection pooling (LSPServerManager singleton)
-    ├── config.ts         # Server discovery & language mapping
-    ├── constants.ts      # Built-in server configs (45+ servers), extensions, install hints
-    ├── index.ts          # Module re-exports
-    ├── types.ts          # LSP type re-exports (Diagnostic, Location, WorkspaceEdit, etc.)
-    ├── utils.ts          # Formatters & workspace edit application
-    ├── config-store.ts   # User LSP config runtime storage
-    └── tools.ts          # 4 tool definitions
-```
-
-### Key Patterns
-
-#### 1. Tool Definition Pattern
-All tools follow the OpenCode plugin tool schema:
-```typescript
-export const toolName: ToolDefinition = tool({
-  description: string,
-  args: { /* Zod schema */ },
-  execute: async (args, context) => { /* implementation */ }
-});
-```
-
-#### 2. CLI Abstraction Layer (ast-grep)
-The ast-grep module uses a CLI execution pattern:
-- **cli.ts**: Low-level subprocess spawning with timeout handling and JSON output parsing
-- **constants.ts**: CLI path resolution with fallback chain (cached binary → @ast-grep/cli → platform-specific → Homebrew → download)
-- **downloader.ts**: Binary auto-download for missing dependencies
-- **utils.ts**: Output formatting and truncation handling
-
-#### 3. Connection Pooling (LSP)
-The LSP module implements a singleton `LSPServerManager` with:
-- **Connection pooling**: Reuse LSP clients per workspace root (key: `root::serverId`)
-- **Reference counting**: Track active usage via `refCount`, increment on acquire, decrement on release
-- **Idle cleanup**: Auto-shutdown after 5 minutes of inactivity (check every 60s)
-- **Initialization tracking**: Prevent concurrent initialization races via `initPromise`
-
-#### 4. Safety Limits
-All tools enforce strict safety limits:
-- **Timeout**: 300s (ast-grep, LSP initialization)
-- **Output size**: 1MB (ast-grep)
-- **Match limits**: 500 matches (ast-grep), 200 diagnostics (LSP), 200 references (LSP)
-
-#### 5. Error Handling
-- Clear error messages with installation hints for missing binaries
-- Timeout handling with process cleanup
-- Truncation detection and reporting with reason codes
-- Graceful fallback chains for CLI resolution
-
----
+- `src/tools/index.ts` is the canonical export surface. It re-exports:
+  - `ast_grep_search`, `ast_grep_replace`.
+  - `createBackgroundTools`.
+  - `lsp_diagnostics`, `lsp_find_references`, `lsp_goto_definition`,
+    `lsp_rename`, `lspManager`, `setUserLspConfig`.
+  - `createWebfetchTool`.
+  - `createCouncilTool`.
+- **Common tool schema pattern**: all tool files use `@opencode-ai/plugin/tool` or
+  `@opencode-ai/plugin` `tool` with typed schemas and `ToolDefinition` objects.
+- **AST-grep stack (`ast-grep/`)**:
+  - `cli.ts` handles invocation flow via `runSg`, `getAstGrepPath`,
+    `startBackgroundInit`.
+  - `types.ts` defines `CliLanguage`, `CliMatch`, `SgResult`.
+  - `constants.ts` owns binary resolution (`getSgCliPath`, `findSgCliPathSync`),
+    limits (`DEFAULT_MAX_MATCHES`, `DEFAULT_MAX_OUTPUT_BYTES`, `DEFAULT_TIMEOUT_MS`).
+  - `downloader.ts` implements `ensureAstGrepBinary` and release-specific
+    fallback download.
+  - `utils.ts` centralizes user-facing renderers.
+- **LSP stack (`lsp/`)**:
+  - `client.ts` implements `LSPServerManager` singleton (`lspManager`) and
+    `LSPClient` with `start`, `initialize`, `definition`, `references`,
+    `diagnostics`, `rename`, `stop`.
+  - `config.ts` resolves server selection via `findServerForExtension` and
+    `resolveServerCommand`.
+  - `config-store.ts` persists `setUserLspConfig`/`getUserLspConfig` from
+    OpenCode `lsp` config.
+  - `types.ts` exports protocol-aligned types (`Diagnostic`, `Location`,
+    `WorkspaceEdit`, `ServerLookupResult`, etc.).
+  - `utils.ts` handles formatting, root discovery, `withLspClient`, and
+    `applyWorkspaceEdit`.
+- **Smartfetch stack (`smartfetch/`)**:
+  - `tool.ts` defines `createWebfetchTool` and the complete execution path.
+  - `network.ts` enforces redirect policy, read limits, HTML/binary detection,
+    and `fetchWithRedirects`.
+  - `cache.ts` uses `CACHE` (`LRUCache`) and `buildCacheKey` for memoization.
+  - `utils.ts` normalizes and renders downloaded content (`extractFromHtml`,
+    `cleanFetchedMarkdown`, `joinRenderedContent`).
+  - `binary.ts` persists payloads with `saveBinary`.
+  - `secondary-model.ts` runs `readSecondaryModelFromConfig`/`runSecondaryModelWithFallback`.
 
 ## Flow
 
-### AST-grep Tool Flow
-
-```
-User Request (ast_grep_search or ast_grep_replace)
-    ↓
-Tool definition (ast-grep/tools.ts)
-    ↓
-runSg() (cli.ts)
-    ├─→ getAstGrepPath()
-    │   ├─→ Check cached path
-    │   ├─→ findSgCliPathSync()
-    │   │   ├─→ Cached binary in ~/.cache
-    │   │   ├─→ @ast-grep/cli package
-    │   │   ├─→ Platform-specific package (@ast-grep/cli-*)
-    │   │   └─→ Homebrew (macOS)
-    │   └─→ ensureAstGrepBinary() → download if missing
-    └─→ Build args: pattern, lang, rewrite, globs, paths
-    ↓
-spawn([sg, 'run', '-p', pattern, '--lang', lang, ...])
-    ↓
-Parse JSON output → CliMatch[]
-    ↓
-Handle truncation (max_output_bytes, max_matches, timeout)
-    ↓
-formatSearchResult() / formatReplaceResult() (utils.ts)
-    ├─→ Group by file
-    ├─→ Truncate long text
-    └─→ Add summary
-    ↓
-Add empty result hints (getEmptyResultHint)
-    ↓
-Return formatted output
-```
-
-### LSP Tool Flow
-
-```
-User Request (e.g., lsp_goto_definition)
-    ↓
-Tool definition (lsp/tools.ts)
-    ↓
-withLspClient() (utils.ts)
-    ├─→ findServerForExtension() (config.ts)
-    │   ├─→ Match extension to BUILTIN_SERVERS
-    │   ├─→ Merge with user config from config-store
-    │   └─→ isServerInstalled() → PATH check
-    ├─→ findServerProjectRoot() → server-specific root patterns
-    └─→ lspManager.getClient() (client.ts)
-        ├─→ Check cache (root::serverId)
-        ├─→ If cached: increment refCount, return
-        └─→ If new:
-            ├─→ new LSPClient(root, server)
-            ├─→ client.start() → spawn server
-            ├─→ client.initialize() → LSP handshake
-            └─→ Store in pool with refCount=1
-    ↓
-client.definition() / references() / diagnostics() / rename()
-    ├─→ openFile() → textDocument/didOpen
-    └─→ Send LSP request
-    ↓
-Format result (formatLocation, formatDiagnostic, etc.)
-    ↓
-lspManager.releaseClient() → decrement refCount
-    ↓
-Return formatted output
-```
-
-**LSP Client Lifecycle:**
-```
-start()
-  ├─→ spawn(command)
-  ├─→ Create JSON-RPC connection (vscode-jsonrpc)
-  ├─→ Register handlers (diagnostics, configuration, window)
-  └─→ Wait for process to stabilize
-    ↓
-initialize()
-  ├─→ sendRequest('initialize', capabilities)
-  └─→ sendNotification('initialized')
-    ↓
-[Operational phase]
-  ├─→ openFile() → textDocument/didOpen
-  ├─→ definition() / references() / diagnostics() / rename()
-  └─→ Receive notifications (diagnostics)
-    ↓
-stop()
-  ├─→ sendRequest('shutdown')
-  ├─→ sendNotification('exit')
-  └─→ kill process
-```
-
-### Background Task Flow
-
-```
-User Request (background_task)
-    ↓
-Tool definition (background.ts)
-    ↓
-manager.launch()
-    ├─→ Validate agent against delegation rules
-    ├─→ Create task with unique ID
-    ├─→ Store in BackgroundTaskManager
-    └─→ Return task_id immediately (~1ms)
-    ↓
-[Background execution]
-    ├─→ Agent runs independently
-    ├─→ Completes with result/error
-    └─→ Auto-notify parent session
-    ↓
-User Request (background_output)
-    ↓
-manager.getResult(task_id)
-    ├─→ If timeout > 0: waitForCompletion()
-    └─→ Return status/result/error/duration
-    ↓
-User Request (background_cancel)
-    ↓
-manager.cancel(task_id) or manager.cancel(all)
-    └─→ Cancel pending/starting/running tasks only
-```
-
----
+- **AST-grep path**:
+  - Tool executes (`ast_grep_search`/`ast_grep_replace`) and calls `runSg`.
+  - `runSg` builds CLI args, resolves `sg` via sync cache/path checks,
+    fallback download if missing, and executes with timeout.
+  - JSON output is parsed into `SgResult`, respecting truncation/error states.
+  - `formatSearchResult` / `formatReplaceResult` produce output.
+- **LSP path**:
+  - Tool executes one of four LSP handlers in `lsp/tools.ts`.
+  - `withLspClient` resolves extension using `findServerForExtension` and
+    computes workspace root.
+  - `lspManager.getClient` creates or reuses a pooled `LSPClient`, waits for
+    initialize, and increments/decrements `refCount`.
+  - Client opens file (`openFile`/`ensureDocumentSynced`) then issues protocol
+    requests.
+  - Formatters convert protocol data to plain output strings; edits are applied
+    with `applyWorkspaceEdit`.
+- **Smartfetch path**:
+  - `createWebfetchTool` validates permissions (`ctx.ask`) and timeout, reads
+    secondary model candidates, then checks cache (`CACHE`).
+  - If permitted, it probes llms docs, else performs fetch with redirect
+    fallback and capped read size.
+  - Response is decoded, content-type normalized, converted by format mode, and
+    optionally passed to secondary model (`runSecondaryModelWithFallback`).
+  - For binary, metadata-only or saved-result branches are selected based on
+    `save_binary`, size, and MIME type.
+- **Background/council**:
+  - `createBackgroundTools` maps task lifecycle calls onto
+    `BackgroundTaskManager` operations.
+  - `createCouncilTool` enforces caller guard (`council` / `orchestrator`) before
+    invoking `CouncilManager.runCouncil`.
 
 ## Integration
 
-### Dependencies
-
-#### External Dependencies
-- **@opencode-ai/plugin**: Tool definition schema (`tool`, `ToolDefinition`)
-- **vscode-jsonrpc**: LSP JSON-RPC protocol implementation
-- **vscode-languageserver-protocol**: LSP type definitions
-- **bun**: Subprocess spawning (`spawn`), file operations (`Bun.write`)
-- **which**: PATH resolution for CLI binaries
-
-#### Internal Dependencies
-- **src/background**: `BackgroundTaskManager` for background task tools
-- **src/config**: `SUBAGENT_NAMES`, `PluginConfig`, `TmuxConfig`
-- **src/utils**: `extractZip` for binary extraction
-- **src/utils/logger**: Logging utilities
-
-### Consumers
-
-#### Direct Consumers
-- **src/index.ts**: Main plugin entry point imports all tools
-
-#### Tool Registry
-All tools are exported from `src/tools/index.ts`:
-```typescript
-export { ast_grep_replace, ast_grep_search } from './ast-grep';
-export { createBackgroundTools } from './background';
-export {
-  lsp_diagnostics,
-  lsp_find_references,
-  lsp_goto_definition,
-  lsp_rename,
-  lspManager,
-  setUserLspConfig,
-} from './lsp';
-```
-
-### Configuration
-
-#### LSP Server Configuration
-- **BUILTIN_SERVERS** (lsp/constants.ts): Pre-configured servers for 45+ languages
-- **LANGUAGE_EXTENSIONS** (lsp/constants.ts): Extension to LSP language ID mapping
-- **LSP_INSTALL_HINTS** (lsp/constants.ts): Installation instructions per server
-- **NearestRoot** (lsp/constants.ts): Factory for root pattern matching functions
-
-#### User LSP Configuration
-- **config-store.ts**: Runtime storage for user-provided LSP config from opencode.json
-- Merged at runtime: built-in servers + user config (user config overrides command/extensions/env, root patterns preserved from built-in)
-- Can disable servers with `"disabled": true`
-
-#### AST-grep Configuration
-- **CLI_LANGUAGES** (ast-grep/types.ts): Supported languages
-- **Safety limits**: Timeout (300s), max output (1MB), max matches (500)
-
-### Binary Management
-
-#### AST-grep (ast-grep/downloader.ts)
-- **Version**: 0.40.0 (synced with @ast-grep/cli package)
-- **Platforms**: darwin-arm64, darwin-x64, linux-arm64, linux-x64, win32-x64, win32-arm64, win32-ia32
-- **Install location**: `~/.cache/oh-my-opencode-slim/bin/sg` (Linux/macOS), `%LOCALAPPDATA%\oh-my-opencode-slim\bin\sg.exe` (Windows)
-- **Fallback chain**: @ast-grep/cli → platform-specific package → Homebrew → download from GitHub
-
-### Performance Considerations
-
-- **Connection pooling**: LSP clients reused across tool calls
-- **Idle cleanup**: LSP clients shutdown after 5 minutes inactivity
-- **Output truncation**: Prevent memory issues with large outputs
-- **Timeout enforcement**: All subprocess operations have timeouts
-- **Caching**: CLI paths cached to avoid repeated filesystem checks
-- **Background tasks**: Fire-and-forget pattern for long-running operations
-
----
-
-## File-by-File Summary
-
-### Root Level
-- **index.ts**: Central export point for all tools
-- **background.ts**: Background task management (3 tools: background_task, background_output, background_cancel)
-
-### ast-grep/
-- **index.ts**: Re-exports ast-grep module and types
-- **cli.ts**: `runSg()`, `getAstGrepPath()`, `startBackgroundInit()`, `isCliAvailable()`, `ensureCliAvailable()` - CLI execution layer
-- **types.ts**: `CliLanguage`, `CliMatch`, `SgResult`, `CLI_LANGUAGES` - TypeScript interfaces
-- **utils.ts**: `formatSearchResult()`, `formatReplaceResult()`, `getEmptyResultHint()` - Output formatting
-- **constants.ts**: `findSgCliPathSync()`, `getSgCliPath()`, `setSgCliPath()`, `checkEnvironment()`, `formatEnvironmentCheck()`, safety limits
-- **downloader.ts**: `downloadAstGrep()`, `ensureAstGrepBinary()`, `getCacheDir()`, `getCachedBinaryPath()` - Binary management
-
-### lsp/
-- **index.ts**: Re-exports LSP module, tools, and types
-- **client.ts**: `LSPServerManager` (singleton), `LSPClient` class - full connection lifecycle management
-- **tools.ts**: 4 tools: `lsp_goto_definition`, `lsp_find_references`, `lsp_diagnostics`, `lsp_rename`
-- **types.ts**: LSP type re-exports from vscode-languageserver-protocol (`Diagnostic`, `Location`, `WorkspaceEdit`, etc.)
-- **utils.ts**: `withLspClient()`, `findServerProjectRoot()`, formatters, `applyWorkspaceEdit()`, `formatApplyResult()`
-- **config.ts**: `findServerForExtension()`, `getLanguageId()`, `isServerInstalled()`, `buildMergedServers()`
-- **config-store.ts**: `setUserLspConfig()`, `getUserLspConfig()`, `getAllUserLspConfigs()`, `hasUserLspConfig()`
-- **constants.ts**: `BUILTIN_SERVERS` (45+ servers), `LANGUAGE_EXTENSIONS`, `LSP_INSTALL_HINTS`, `NearestRoot()`, safety limits
+- `src/index.ts` imports these exports and injects them into plugin tool surfaces.
+- `setUserLspConfig` is called during plugin initialization so `findServerForExtension`
+  reflects active `lsp` config.
+- OpenCode-facing dependencies used directly in these modules:
+  - `@opencode-ai/plugin` / `@opencode-ai/plugin/tool` (`tool`, schemas).
+  - `vscode-jsonrpc` + `vscode-languageserver-protocol`.
+  - `which`, `lru-cache`, `bun` runtime APIs, network stack.
+  - DOM extraction libs in smartfetch.
+- Consumers include orchestrator/background agents, `@opencode` task runners, and
+  any extension tests that import tools/types from the `src/tools` modules.