# Project Map opencode-config — Docker-based AI coding assistant with persistent memory (opencode configuration). Runs in Docker via `docker-compose.yml` (dind + opencode services). Root `AGENTS.md` — orchestrator directive (chat = plan only, all via subagents) + global rules (pipeline, code style, language RU) + `## Tool Usage Policy` (таблица tools: commit/create-pr/create-issue/merge-pr/post-review/post-docs-review/pipeline-status/spec-status/memory-doctor/memory-save/memory-search/memory-list/memory-access/tunnel; raw bash заблокирован deny, при сбое tool — STOP, НЕ fallback; `memory-setup` REMOVED PR#103) + `## Bug Discovery Protocol` (агенты создают issues через `create-issue` tool для найденных багов вне scope) + `## Linear Execution` (строго линейный pipeline, параллельные research OK, параллельное исполнение ЗАПРЕЩЕНО) — PR#113. Auto-loaded for project + bind-mounted globally in container — PR#31, PR#63. ## Structure ``` opencode-config/ ├── .github/ │ ├── workflows/ │ │ ├── ci.yml # Lint, test, typecheck, complexity (bootstrap + output-based skip); apt-get install ripgrep + npm ci (.opencode) для keyword search — PR#124 │ │ ├── permissions-check.yml # .opencode/scripts/check-permissions.py validator (step-level skip) │ │ └── adr-check.yml # ADR cross-reference validator (.opencode/scripts/check-adr-refs.py) │ └── dependabot.yml # pip + github-actions ecosystem updates ├── .opencode/ # Project-local opencode config (auto-discovery, zero env var) — PR#23 │ ├── agents/ │ │ ├── docs-reviewer.md # Docs validation subagent (project map + handoff + ADR, uses `commit`+`post-docs-review`+`create_issue` tools; `gh issue list*` allow) — PR#40, PR#46, PR#69, PR#113 │ │ ├── memory-syncer.md # Distills gotchas from handoffs into opencode-memory (`create_issue` tool; `gh issue list*` allow) — PR#69, PR#113 │ │ └── reviewer.md # Code review subagent (verdict via `post-review` tool: APPROVE|REQUEST_CHANGES|NEEDS_DISCUSSION) — PR#46, PR#69 │ ├── commands/ │ │ ├── configure-opencode.md # /configure-opencode — edit opencode.json │ │ ├── feature-spec.md # /feature-spec — SDD-style Q&A for feature planning (loads feature-spec skill) — PR#172 │ │ ├── repo-readme.md # /repo-readme — standardized README generation (frontmatter agent: build, loads repo-readme skill) — PR#158 │ │ ├── run-pipeline.md # /run-pipeline — 7-phase PR pipeline │ │ └── spec.md # /spec — 9-phase spec generation │ ├── skills/ │ │ ├── add-skill/SKILL.md # Create new opencode skill │ │ ├── bug-discovery/SKILL.md # Bug Discovery Protocol — create issue for out-of-scope bugs (create-issue tool, 7 SDD sections, duplicate check) — PR#120, PR#169 │ │ ├── branch/SKILL.md # Branch naming conventions │ │ ├── code-standards/SKILL.md # Universal code style rules │ │ ├── configure-opencode/SKILL.md # Canonical rule: write to .opencode/ │ │ ├── feature-spec/SKILL.md # SDD-style Q&A for feature planning (7 SDD sections, decision criteria, handoff to issue skill) — PR#172 │ │ ├── get-project-map/SKILL.md # Maintain docs/project-map/ │ │ ├── issue/SKILL.md # GitHub issue creation (7 SDD sections template) — PR#169 │ │ ├── memory/SKILL.md # opencode-memory usage guide │ │ ├── run-pipeline/SKILL.md # 7-phase pipeline orchestration │ │ ├── python-development/SKILL.md # Python dev patterns │ │ ├── release/SKILL.md # Tag + GitHub Release │ │ ├── repo-init/SKILL.md # New repository bootstrap │ │ ├── repo-readme/SKILL.md # Standardized README generation (create-readme tool: create vs validate, bilingual Why/What + Features table, GitHub metadata, quick_start_steps clickable steps + conditional bash block; tagline_en/tagline_ru required + delimiter-теги, breaking change note; workflow: create → draw-image (template "cover", slots icon/sub-icon/badge, brand-logos vs Lucide) → validate → fix-цикл) — PR#112, PR#116, PR#118, PR#130, PR#146, PR#151, PR#158 (cover pipeline в workflow) │ │ ├── tunnel/SKILL.md # Cloudflare tunnel toggle (tool `tunnel()`: 1-й вызов start, 2-й stop) — PR#63 (восстановлен, удалён в PR#42) │ │ ├── run-tests/SKILL.md # Test runner guide │ │ └── spec/SKILL.md # 9-phase spec generation (issue body template: 7 SDD sections) — PR#169 │ ├── tools/ │ │ ├── _shared.ts # Shared module for GitHub tools: parseRepo(repo?), runGh(args, repo?, opts?), formatResult(r, toolName) — PR#65 │ │ ├── commit.ts # commit tool wrapper (1 arg message, validates format+staged) — PR#38 │ │ ├── create-issue.ts # create-issue tool wrapper (3 args, validates 7 SDD headings+format+labels; optional repo?: string) — PR#38, PR#65, PR#169 │ │ ├── create-pr.ts # create-pr tool wrapper (3 args, validates format+Closes #N; optional repo?: string) — PR#38, PR#65 │ │ ├── create-readme.ts # create-readme tool (TS plugin, modes: create/validate; standardized bilingual README with features table, include_clone/development_en/ru/quick_start_steps_en/ru optional params, clickable access_url [url](url), conditional bash block via hasBashBlock, RU heading 'Русский' + anchor checks, 6 delimiter pairs for slaid098.dev (summary-en/ru, features-en/ru, tagline-en/ru); tagline_en+tagline_ru required (BREAKING: tagline removed PR#151), content-валидация repo_name (lowercase kebab-case) + tagline_en (no Cyrillic) + tagline_ru (require Cyrillic), validateReadme H1 prefix check `# 🚀 `; generateReadme рендерит `![Cover](assets/cover.png)` после H1 перед tagline-разделителями; validateReadme substring-чек `assets/cover.png` (без file existence — для remote gh api режима); local fs path resolved via path.resolve(context.worktree, file_path) — overwrite existing README; remote gh api) — PR#112, PR#116, PR#118, PR#130, PR#146, PR#149 (quick_start optional + guard), PR#151 (bilingual tagline + repo_name validation, breaking), PR#158 (cover image reference в template + validation), PR#175 (local file_path resolved against context.worktree — overwrite existing README) │ │ ├── draw-image.ts # draw-image tool wrapper (opencode plugin, 5 args: template/title/subtitle?/slots?/out?; spawnSync node cli.ts render → sharp PNG) — PR#133 │ │ ├── merge-pr.ts # merge-pr tool wrapper (orchestrator-safe gh pr merge; optional repo?: string) — PR#30, PR#65 │ │ ├── memory-access.ts # memory-access tool (bump frontmatter last_accessed/access_count, regex replace, atomic write tmp+rename) — PR#101 │ │ ├── memory-doctor.ts # memory-doctor tool (read-only diagnostics: rg {lines, rgWorks} G9, allowSystemFallback:true G5, arch-mismatch detection G2; npm-missing hint G3; markdown ✅/❌ report) — PR#101, PR#124 │ │ ├── memory-list.ts # memory-list tool (pure TS, categories count .md or files in category with frontmatter) — PR#101 │ │ ├── memory-save.ts # memory-save tool (auto-setup mkdir+git init/clone+hook+7 categories, git commit, async reindex via spawn detached+unref) — PR#101 │ │ ├── memory-search.ts # memory-search tool (ripgrep keyword + Python semantic via spawnSync + scoring port + cross-category fallback; stderr warning при rgBin===null) — PR#101, PR#124 │ │ ├── pipeline-status.ts # pipeline-status tool wrapper │ │ ├── post-docs-review.ts # post-docs-review tool wrapper (3 args: pr_number, verdict enum, body; deterministic ## Docs Review Summary heading; optional repo?: string) — PR#46, PR#65 │ │ ├── post-review.ts # post-review tool wrapper (3 args: pr_number, verdict enum, body; deterministic ## Code Review Summary heading; optional repo?: string) — PR#46, PR#65 │ │ ├── spec-status.ts # spec-status tool wrapper │ │ ├── telegram-send.ts # telegram-send plugin-tool wrapper (spawnSync CLI .opencode/telegram/cli.ts; action: text|document|photo; MarkdownV2 default; error → ⚠️ telegram-send failed) — PR#174 │ │ └── tunnel.ts # Cloudflare tunnel toggle tool (start/stop без args) — PR#34 │ ├── draw-image/ # SVG template renderer for on-brand covers (sharp + lucide-static) — PR#133 │ │ ├── package.json # deps: sharp, lucide-static; devDeps: vitest, typescript; postinstall sync-lucide │ │ ├── tsconfig.json # ES2022 Bundler, strict, noEmit │ │ ├── vitest.config.ts # node env, tests/**/*.test.ts │ │ ├── render.mjs # SVG string → PNG via sharp (fontFiles: Geist TTF bundle) │ │ ├── cli.ts # CLI entry: render