diff --git a/.opencode/skills/repo-readme/SKILL.md b/.opencode/skills/repo-readme/SKILL.md index cd730a2..6e7c99e 100644 --- a/.opencode/skills/repo-readme/SKILL.md +++ b/.opencode/skills/repo-readme/SKILL.md @@ -6,14 +6,14 @@ description: Use when creating or updating README.md for any slaid098 repository # Repo README Стандартизация `README.md` во всех репозиториях slaid098 через тулзу -`create-readme`. Тулза гарантирует структуру (разделители, Support block, -Quick Start, language switcher). Скилл даёт контекст: когда вызывать тулзу и -какие параметры передавать. +`create-readme`. Тулза гарантирует структуру (разделители, Features table, +Support block, Quick Start, language switcher). Скилл даёт контекст: когда +вызывать тулзу и какие параметры передавать. ## 1. Когда использовать тулзу - **Новый репо** → `create-readme` (mode: `create`) — генерирует - стандартизированный README с нуля. + стандартизированный двуязычный README с нуля. - **Проверка существующего README** → `create-readme` (mode: `validate`) — проверяет, что структура соответствует стандарту витрины. - **После ручных правок README** → всегда `validate`. Любая правка руками @@ -23,20 +23,7 @@ Quick Start, language switcher). Скилл даёт контекст: когд Не генерируй README вручную через Write — структура критична для парсинга витриной. Только через тулзу `create-readme`. -## 2. Tier system - -Тулза принимает параметр `tier`: - -- **`flagship`** — флагманские проекты (Anti-Detect MCP, Mobile Whisper и - т.п.). Полный набор параметров: `demo_gif` (демо-гифка), `custom_sections`, - `telegram`. Используется для заметных проектов на витрине. -- **`utility`** (default) — бытовые утилиты. Минимальный набор: `problem` / - `solution` (EN+RU), `quick_start`. `demo_gif` игнорируется. - -Выбор tier влияет только на блок `demo_gif` после EN-разделителей. Остальная -структура одинакова для обоих tier'ов. - -## 3. GitHub metadata (отдельный шаг, НЕ в тулзе) +## 2. GitHub metadata (отдельный шаг, НЕ в тулзе) `create-readme` отвечает только за файл `README.md`. Метаданные репозитория настраиваются отдельно через `gh repo edit` (это bash, не тулза): @@ -47,7 +34,7 @@ Quick Start, language switcher). Скилл даёт контекст: когд Метаданные не дублируют README — они для карточки репо на GitHub и поиска. -## 4. Workflow +## 3. Workflow 1. `create-readme` (mode: `create`) → генерирует README с гарантированной структурой. @@ -62,20 +49,25 @@ Quick Start, language switcher). Скилл даёт контекст: когд (`owner/name`) — тулза сделает PUT через `gh api repos/{owner}/{repo}/contents/README.md` с base64-контентом и SHA. -## 5. Зачем разделители (контекст для агента) +## 4. Зачем разделители (контекст для агента) Витрина **slaid098.dev** скачивает raw `README.md` из каждого репо и -извлекает фрагмент между разделителями: +извлекает фрагменты между разделителями: - `` ... `` — английский - блок для карточки. -- `` ... `` — русский блок. + блок Why/What для карточки. +- `` ... `` — английская + таблица фич. +- `` ... `` — русский блок + Зачем/Что. +- `` ... `` — русская + таблица фич. Поэтому структура README **должна быть гарантирована тулзой**, а не агентом. Агент может менять текст *внутри* разделителей, но не должен удалять/двигать сами разделители. `validate` ловит такие нарушения. -## 6. Шаблон README (reference) +## 5. Шаблон README (reference) Тулза `create-readme` генерирует ровно эту структуру (параметры подставляются): @@ -90,14 +82,22 @@ repos/{owner}/{repo}/contents/README.md` с base64-контентом и SHA. ## 🇬🇧 English -### 🔴 Problem -{problem_en} +### ❓ Why +{why_en} -### 🟢 Solution -{solution_en} -{custom_sections_en — доп. секции, если переданы} +### ✅ What +{what_en} -{demo_gif строка, только если tier=flagship} + + +### Features + +| Feature | Description | +|---------|-------------| +| {emoji} {name} | {description} | +... + +{custom_sections_en — доп. секции, если переданы} ### ⚡ Quick Start \`\`\`bash @@ -110,14 +110,23 @@ git clone https://github.com/slaid098/{repo_name}.git ## 🇷🇺 Русская версия -### 🔴 Проблема -{problem_ru} +### ❓ Зачем +{why_ru} -### 🟢 Решение -{solution_ru} -{custom_sections_ru — доп. секции, если переданы} +### ✅ Что +{what_ru} + +### Фичи + +| Фича | Описание | +|------|----------| +| {emoji} {name} | {description} | +... + +{custom_sections_ru — доп. секции, если переданы} + ### ⚡ Быстрый старт \`\`\`bash git clone https://github.com/slaid098/{repo_name}.git @@ -126,18 +135,19 @@ git clone https://github.com/slaid098/{repo_name}.git --- -## 💬 Support & Contact / Поддержка и связь +## 💬 Support and contacts / Поддержка и контакты -Have questions, need custom features, or want to support this project? -👉 **[Visit Support & Contact Page](https://slaid098.dev/support)** +Have questions or want to support? +👉 **[slaid098.dev/support](https://slaid098.dev/support)** {telegram строка, если передан} ``` -`validate` проверяет: наличие обоих EN/RU разделителей, непустой контент -между ними, ссылку `slaid098.dev/support`, секции Quick Start (EN) и Быстрый -старт (RU), language switcher `[English]` / `[Русский]`. +`validate` проверяет: наличие всех 4 пар EN/RU разделителей (summary + +features), непустой контент между ними, ссылку `slaid098.dev/support`, секции +Quick Start (EN) и Быстрый старт (RU), language switcher `[English]` / +`[Русский]`. -## 7. Независимость от repo-init +## 6. Независимость от repo-init - Скилл `repo-init` создаёт **пустой** `README.md` как часть инициализации репо. @@ -146,17 +156,16 @@ Have questions, need custom features, or want to support this project? - Может применяться к существующим репо без `repo-init` — тулза перезапишет `README.md` (локально) или обновит через GitHub API (с SHA). -## 8. Параметры тулзы (кратко) +## 7. Параметры тулзы (кратко) `create-readme`: - `mode` — `"create"` | `"validate"` (обязательный). -- `repo_name`, `tagline`, `problem_en`, `solution_en`, `problem_ru`, - `solution_ru`, `quick_start` — обязательны для `create`. -- `tier` — `"flagship"` | `"utility"` (default `utility`). -- `telegram` — username без `@` (optional). -- `demo_gif` — путь/URL (только для `flagship`). +- `repo_name`, `tagline`, `why_en`, `what_en`, `why_ru`, `what_ru`, + `quick_start`, `features_en`, `features_ru` — обязательны для `create`. +- `features_en` / `features_ru` — массив `{ emoji, name, description }[]`. - `custom_sections_en` / `custom_sections_ru` — массивы `{ title, content }` (optional). +- `telegram` — username без `@` (optional). - `repo` — `owner/name` для удалённой операции (optional). - `file_path` — локальный путь (default `README.md`). diff --git a/.opencode/tools/create-readme.ts b/.opencode/tools/create-readme.ts index a420f3f..c8b32b0 100644 --- a/.opencode/tools/create-readme.ts +++ b/.opencode/tools/create-readme.ts @@ -2,19 +2,21 @@ import { spawnSync } from "child_process" import { readFileSync, writeFileSync } from "fs" import { tool } from "@opencode-ai/plugin" +type Feature = { emoji: string; name: string; description: string } + type CustomSection = { title: string; content: string } type CreateArgs = { repo_name: string tagline: string - problem_en: string - solution_en: string - problem_ru: string - solution_ru: string + why_en: string + what_en: string + why_ru: string + what_ru: string quick_start: string - tier?: "flagship" | "utility" + features_en: Feature[] + features_ru: Feature[] telegram?: string - demo_gif?: string custom_sections_en?: CustomSection[] custom_sections_ru?: CustomSection[] } @@ -26,6 +28,16 @@ function extractBetween(text: string, start: string, end: string): string | null return text.substring(s + start.length, e) } +function renderFeaturesTable(features: Feature[], isRu: boolean): string { + const header = isRu + ? "### Фичи\n\n| Фича | Описание |\n|------|----------|\n" + : "### Features\n\n| Feature | Description |\n|---------|-------------|\n" + const rows = features + .map((f) => `| ${f.emoji} ${f.name} | ${f.description} |`) + .join("\n") + return header + rows +} + function generateReadme(args: CreateArgs): string { const customEn = (args.custom_sections_en || []) .map((s) => `\n\n### ${s.title}\n${s.content}`) @@ -33,10 +45,8 @@ function generateReadme(args: CreateArgs): string { const customRu = (args.custom_sections_ru || []) .map((s) => `\n\n### ${s.title}\n${s.content}`) .join("") - const demoLine = - args.tier === "flagship" && args.demo_gif ? `\n![Demo](${args.demo_gif})\n` : "" const telegramLine = args.telegram - ? `💬 **Direct Telegram:** [@${args.telegram}](https://t.me/${args.telegram})` + ? `\n💬 **Direct Telegram:** [@${args.telegram}](https://t.me/${args.telegram})` : "" return `# 🚀 ${args.repo_name} @@ -49,13 +59,17 @@ function generateReadme(args: CreateArgs): string { ## 🇬🇧 English -### 🔴 Problem -${args.problem_en} +### ❓ Why +${args.why_en} -### 🟢 Solution -${args.solution_en}${customEn} +### ✅ What +${args.what_en} -${demoLine} + + +${renderFeaturesTable(args.features_en, false)} +${customEn} + ### ⚡ Quick Start \`\`\`bash git clone https://github.com/slaid098/${args.repo_name}.git @@ -67,13 +81,17 @@ ${args.quick_start} ## 🇷🇺 Русская версия -### 🔴 Проблема -${args.problem_ru} +### ❓ Зачем +${args.why_ru} -### 🟢 Решение -${args.solution_ru}${customRu} +### ✅ Что +${args.what_ru} + +${renderFeaturesTable(args.features_ru, true)} +${customRu} + ### ⚡ Быстрый старт \`\`\`bash git clone https://github.com/slaid098/${args.repo_name}.git @@ -82,43 +100,45 @@ ${args.quick_start} --- -## 💬 Support & Contact / Поддержка и связь +## 💬 Support and contacts / Поддержка и контакты -Have questions, need custom features, or want to support this project? -👉 **[Visit Support & Contact Page](https://slaid098.dev/support)** -${telegramLine} +Have questions or want to support? +👉 **[slaid098.dev/support](https://slaid098.dev/support)**${telegramLine} ` } function validateReadme(content: string): { ok: boolean; issues: string[] } { const issues: string[] = [] - if (!content.includes("")) - issues.push("Missing delimiter") - if (!content.includes("")) - issues.push("Missing delimiter") - if (!content.includes("")) - issues.push("Missing delimiter") - if (!content.includes("")) - issues.push("Missing delimiter") + const delimiters = [ + "summary-en:start", + "summary-en:end", + "features-en:start", + "features-en:end", + "summary-ru:start", + "summary-ru:end", + "features-ru:start", + "features-ru:end", + ] + for (const d of delimiters) { + if (!content.includes(``)) + issues.push(`Missing delimiter`) + } - const enContent = extractBetween( - content, - "", - "", - ) - if (enContent !== null && !enContent.trim()) - issues.push("EN summary content between delimiters is empty") - const ruContent = extractBetween( - content, - "", - "", - ) - if (ruContent !== null && !ruContent.trim()) - issues.push("RU summary content between delimiters is empty") + const pairs = [ + { start: "", end: "", label: "EN summary" }, + { start: "", end: "", label: "EN features" }, + { start: "", end: "", label: "RU summary" }, + { start: "", end: "", label: "RU features" }, + ] + for (const p of pairs) { + const between = extractBetween(content, p.start, p.end) + if (between !== null && !between.trim()) + issues.push(`${p.label} content between delimiters is empty`) + } if (!content.includes("slaid098.dev/support")) - issues.push("Missing Support & Contact link (slaid098.dev/support)") + issues.push("Missing Support link (slaid098.dev/support)") if (!content.includes("Quick Start")) issues.push("Missing 'Quick Start' section (English)") if (!content.includes("Быстрый старт")) @@ -133,7 +153,7 @@ function validateReadme(content: string): { ok: boolean; issues: string[] } { export default tool({ description: - "Create or validate README.md for slaid098 repositories. 'create' mode generates a standardized bilingual README with delimiter tags (, ) parsed by the slaid098.dev showcase. 'validate' mode checks an existing README against the standard. Supports local file (fs) and remote (gh api repos/{owner}/{repo}/contents/README.md) operation.", + "Create or validate README.md for slaid098 repositories. 'create' mode generates a standardized bilingual README with delimiter tags (, , , ) parsed by the slaid098.dev showcase. 'validate' mode checks an existing README against the standard. Supports local file (fs) and remote (gh api repos/{owner}/{repo}/contents/README.md) operation.", args: { mode: tool.schema .enum(["create", "validate"]) @@ -146,38 +166,50 @@ export default tool({ .string() .optional() .describe("Short English tagline (1 sentence). Required for create mode."), - problem_en: tool.schema + why_en: tool.schema .string() .optional() - .describe("Problem statement in English (1-2 sentences). Required for create mode."), - solution_en: tool.schema + .describe("Why this exists — in English (1-2 sentences). Required for create mode."), + what_en: tool.schema .string() .optional() - .describe("Solution in English (1-2 sentences). Required for create mode."), - problem_ru: tool.schema + .describe("What it does — in English (1-2 sentences). Required for create mode."), + why_ru: tool.schema .string() .optional() - .describe("Problem statement in Russian (1-2 sentences). Required for create mode."), - solution_ru: tool.schema + .describe("Зачем этот проект — на русском (1-2 предложения). Required for create mode."), + what_ru: tool.schema .string() .optional() - .describe("Solution in Russian (1-2 sentences). Required for create mode."), + .describe("Что делает — на русском (1-2 предложения). Required for create mode."), quick_start: tool.schema .string() .optional() .describe("Install/setup command (e.g. 'pip install -r requirements.txt'). Required for create mode."), - tier: tool.schema - .enum(["flagship", "utility"]) + features_en: tool.schema + .array( + tool.schema.object({ + emoji: tool.schema.string(), + name: tool.schema.string(), + description: tool.schema.string(), + }), + ) .optional() - .describe("Repository tier: 'flagship' (enables demo_gif) or 'utility' (minimal). Default: 'utility'."), + .describe("Array of features for EN table. Each: { emoji, name, description }. Required for create mode."), + features_ru: tool.schema + .array( + tool.schema.object({ + emoji: tool.schema.string(), + name: tool.schema.string(), + description: tool.schema.string(), + }), + ) + .optional() + .describe("Array of features for RU table. Each: { emoji, name, description }. Required for create mode."), telegram: tool.schema .string() .optional() .describe("Telegram username without @. Optional; adds Direct Telegram line to Support section."), - demo_gif: tool.schema - .string() - .optional() - .describe("Path or URL to demo GIF. Only emitted when tier='flagship'."), custom_sections_en: tool.schema .array( tool.schema.object({ @@ -186,7 +218,7 @@ export default tool({ }), ) .optional() - .describe("Additional sections rendered inside EN delimiters (after Solution)."), + .describe("Additional sections rendered after EN features block (outside delimiters)."), custom_sections_ru: tool.schema .array( tool.schema.object({ @@ -195,7 +227,7 @@ export default tool({ }), ) .optional() - .describe("Additional sections rendered inside RU delimiters (after Решение)."), + .describe("Additional sections rendered after RU features block (outside delimiters)."), repo: tool.schema .string() .optional() @@ -208,33 +240,36 @@ export default tool({ async execute(args, context) { try { const file_path = args.file_path ?? "README.md" - const tier = args.tier ?? "utility" if (args.mode === "create") { const required: Record = { repo_name: args.repo_name, tagline: args.tagline, - problem_en: args.problem_en, - solution_en: args.solution_en, - problem_ru: args.problem_ru, - solution_ru: args.solution_ru, + why_en: args.why_en, + what_en: args.what_en, + why_ru: args.why_ru, + what_ru: args.what_ru, quick_start: args.quick_start, } for (const [k, v] of Object.entries(required)) { if (!v) return `❌ ${k} is required for create mode` } + if (!args.features_en || args.features_en.length === 0) + return `❌ features_en is required for create mode` + if (!args.features_ru || args.features_ru.length === 0) + return `❌ features_ru is required for create mode` const content = generateReadme({ repo_name: args.repo_name!, tagline: args.tagline!, - problem_en: args.problem_en!, - solution_en: args.solution_en!, - problem_ru: args.problem_ru!, - solution_ru: args.solution_ru!, + why_en: args.why_en!, + what_en: args.what_en!, + why_ru: args.why_ru!, + what_ru: args.what_ru!, quick_start: args.quick_start!, - tier, + features_en: args.features_en!, + features_ru: args.features_ru!, telegram: args.telegram, - demo_gif: args.demo_gif, custom_sections_en: args.custom_sections_en, custom_sections_ru: args.custom_sections_ru, }) diff --git a/README.md b/README.md index dbedf28..5d2e164 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,39 @@ -# opencode-config +# 🚀 opencode-config +> Portable AI coding assistant config with memory & subagent pipeline -Personal opencode setup — Docker-based AI coding assistant with pipeline automation. +[English](#-english) | [Русский](#-русская-версия) -## Русский +--- -### Быстрый старт +## 🇬🇧 English + +### ❓ Why +Moving your AI coding assistant config to a new server meant setting everything up from scratch every time. Plus no versioning — break a skill and you can't rollback to what worked. + +### ✅ What +A ready-to-run Docker config. Clone, fill `.env`, start — it works. Versioning via Git, memory syncs through a private repository. + + + +### Features + +| Feature | Description | +|---------|-------------| +| 🐳 Portable | Docker config — runs on any server with one command | +| 📦 Versioning | Git under the hood — rollback to any config version | +| 🌐 Global skills | All skills mounted via volume — work across all projects | +| 🧠 Portable memory | Markdown + git, syncs through private repo — assistant remembers everything | +| 🔍 Dual search | Keyword (ripgrep) always works, semantic — optional via OpenAI API | +| 🔧 Pipeline | ISSUE → IMPLEMENT → DOCS → CI → REVIEW → MERGE → MEMORY | +| 🤖 Subagent orchestration | Orchestrator only plans, subagents execute | +| 📋 Linear execution | One pipeline at a time — no branch conflicts | +| 🐛 Auto-issue | Bug found mid-task — agent creates GitHub issue and continues | +| 🛠️ Skills & commands | Built-in skills and slash commands, main one — `/run-pipeline` | +| 👥 Subagents | Built-in role-based agents — review, docs, memory sync | + + +### ⚡ Quick Start ```bash git clone https://github.com/slaid098/opencode-config.git cd opencode-config @@ -13,33 +41,37 @@ cp .env.example .env docker compose up -d ``` -Доступ: http://localhost:4096 +--- -### Структура +## 🇷🇺 Русская версия -| Путь | Описание | + +### ❓ Зачем +Перенос конфига на новый сервер требовал настройки с нуля каждый раз. Плюс отсутствие версионирования — накосячил со скиллом и не можешь посмотреть, как было раньше. + +### ✅ Что +Готовый конфиг в Docker. Клонировал, заполнил `.env`, запустил — работает. Версионирование через Git, память синкается через приватный репозиторий. + + + +### Фичи + +| Фича | Описание | |------|----------| -| `AGENTS.md` | Глобальные правила оркестратора | -| `.opencode/` | Конфигурация проекта | -| `.opencode/agents/` | Определения subagent'ов | -| `.opencode/skills/` | Определения skills (14 skills) | -| `.opencode/scripts/` | Python скрипты (pipeline-status, spec-status) | -| `src/` | Python RAG CLI | -| `docs/` | Handoffs, ADRs, project map | -| `docker-compose.yml` | Docker compose конфиг | - -### Конфигурация - -Скопируйте `.env.example` → `.env`, заполните ключи. - -### Память - -Файловая память (markdown + git) с keyword и semantic поиском. 5 tools: `memory-save`, `memory-search`, `memory-list`, `memory-access`, `memory-doctor`. Zero-config — первый `memory-save` создаёт репозиторий и индекс автоматически. Semantic поиск опционален: работает если задан `OPENAI_BASE_URL`, иначе keyword (ripgrep) всегда работает как fallback. - -## English - -### Quick start +| 🐳 Переносимость | Docker-конфиг — поднимается на любом сервере одной командой | +| 📦 Версионирование | Git под капотом — откат к любой версии конфига | +| 🌐 Глобальные скиллы | Все скиллы прокидываются через volume — работают во всех проектах | +| 🧠 Переносимая память | Markdown + git, синк через приватный репозиторий — ассистент помнит всё | +| 🔍 Двойной поиск | Keyword (ripgrep) всегда работает, semantic — опционально через OpenAI API | +| 🔧 Пайплайн | ISSUE → IMPLEMENT → DOCS → CI → REVIEW → MERGE → MEMORY | +| 🤖 Subagent-оркестрация | Оркестратор только планирует, исполняют subagent'ы | +| 📋 Линейное выполнение | Один пайплайн за раз — без конфликтов веток | +| 🐛 Auto-issue | Баг найден в процессе — агент сам создаёт GitHub issue и продолжает работу | +| 🛠️ Скиллы и команды | Встроенные скиллы и slash-команды, основной — `/run-pipeline` | +| 👥 Subagent'ы | Встроенные агенты по ролям — review, docs, memory sync | + +### ⚡ Быстрый старт ```bash git clone https://github.com/slaid098/opencode-config.git cd opencode-config @@ -47,29 +79,9 @@ cp .env.example .env docker compose up -d ``` -Access at http://localhost:4096 +--- -### Structure +## 💬 Support and contacts / Поддержка и контакты -| Path | Description | -|------|-------------| -| `AGENTS.md` | Global orchestrator rules | -| `.opencode/` | Project configuration | -| `.opencode/agents/` | Subagent definitions | -| `.opencode/skills/` | Skill definitions (14 skills) | -| `.opencode/scripts/` | Python scripts (pipeline-status, spec-status) | -| `src/` | Python RAG CLI | -| `docs/` | Handoffs, ADRs, project map | -| `docker-compose.yml` | Docker compose config | - -### Configuration - -Copy `.env.example` → `.env`, fill in keys. - -### Memory - -File-based memory (markdown + git) with keyword and semantic search. 5 tools: `memory-save`, `memory-search`, `memory-list`, `memory-access`, `memory-doctor`. Zero-config — first `memory-save` creates the repo and index automatically. Semantic search is optional: works if `OPENAI_BASE_URL` is set, otherwise keyword (ripgrep) always works as fallback. - -## License - -MIT — see [LICENSE](LICENSE). +Have questions or want to support? +👉 **[slaid098.dev/support](https://slaid098.dev/support)** diff --git a/docs/decisions/051-pr-116-readme-standard-v2.md b/docs/decisions/051-pr-116-readme-standard-v2.md new file mode 100644 index 0000000..ad21e5d --- /dev/null +++ b/docs/decisions/051-pr-116-readme-standard-v2.md @@ -0,0 +1,47 @@ +# ADR-051: README standard v2 — Why/What + Features table + +## Статус +Accepted (2026-07-29) + +## Контекст + +Витрина slaid098.dev парсит `README.md` из каждого репозитория: извлекает +фрагменты между разделителями. В стандарте v1 (ADR-049, PR#112) были 2 пары +разделителей (`summary-en/ru`) с Problem/Solution текстом и опциональный +`tier` (flagship/utility), влияющий только на блок `demo_gif`. Problem/Solution +оказался не универсален — не каждый проект укладывается в "проблема → решение" +(например, конфиг-репозитории, утилиты). Tier system усложнял поддержку: два +пути генерации, флаг demo_gif, разные описания параметров. Витрине нужна +таблица фич для каждой карточки — в v1 её не было. + +## Решение + +Перейти на стандарт v2: + +- **Why/What** вместо Problem/Solution — универсальная структура: зачем + существует проект и что делает. Применима к любому репо. +- **Features table** — обязательная часть README. Каждая фича: `{ emoji, name, + description }`. Рендерится в markdown-таблицу между новыми разделителями + `` и ``. +- **4 пары разделителей** (summary-en, features-en, summary-ru, features-ru) — + витрина парсит и summary, и features независимо. +- **Tier system убран** — один формат для всех репо, без условной логики. +- **`custom_sections_en/ru` вне delimiter tags** — после `features-en:end`, + до Quick Start. Раньше были внутри summary delimiter. +- **`demo_gif` убран** — не использовался витриной. +- `validate` проверяет наличие и непустоту всех 4 пар разделителей. + +## Альтернативы + +- **Сохранить Problem/Solution** — отвергнуто: не универсально. Не каждый + проект укладывается в "проблема → решение" (конфиг-репозитории, утилиты). + Why/What применимо к любому репо. +- **Сохранить tier system (flagship/utility)** — отвергнуто: усложнял поддержку + (два пути генерации, флаг demo_gif, разные описания параметров). Один формат + для всех репо проще в поддержке. +- **Оставить 2 пары разделителей (summary только)** — отвергнуто: витрина не + может парсить features независимо от summary. 4 пары позволяют извлекать и + summary, и таблицу фич как независимые блоки per language. +- **Держать custom_sections внутри summary delimiter** — отвергнуто: перенос + вне delimiter tags (после features-en:end, до Quick Start) разделяет + пользовательский контент и парсимый витриной. diff --git a/docs/handoff/pr-116-readme-standard-v2.md b/docs/handoff/pr-116-readme-standard-v2.md new file mode 100644 index 0000000..5b88721 --- /dev/null +++ b/docs/handoff/pr-116-readme-standard-v2.md @@ -0,0 +1,62 @@ +--- +pr: 116 +title: feat(readme): new bilingual standard v2 with features table +--- + +## Что сделано + +Обновлён `create-readme` tool (`.opencode/tools/create-readme.ts`): +- Убраны параметры `tier` (flagship/utility), `demo_gif`, `problem_en/ru`, + `solution_en/ru` — из типа `CreateArgs`, schema, `execute()`. +- Добавлены параметры `why_en`, `what_en`, `why_ru`, `what_ru`, + `features_en`, `features_ru` (массив `{ emoji, name, description }[]`). +- Добавлена функция `renderFeaturesTable()` для рендеринга markdown-таблицы + фич. +- `generateReadme()` переписан под новый шаблон: Why/What вместо + Problem/Solution, Features table между ``, + `custom_sections` теперь вне delimiter tags (после features-en:end, до + Quick Start). +- `validateReadme()` обновлён: проверяет 4 пары разделителей (summary-en/ru + + features-en/ru), непустой контент в каждой паре. +- `description` тулзы обновлён (упоминание 4 пар разделителей). +- `.describe()` для новых параметров; убраны для tier/demo_gif/problem/solution. + +Обновлён скилл `repo-readme` (`.opencode/skills/repo-readme/SKILL.md`): +- §2 (Tier system) убран полностью, секции перенумерованы (3→2, 4→3, …, 8→7). +- §1 убрано упоминание tier. +- §4 (Зачем разделители) — обновлён список: 4 пары (summary + features, EN + + RU). +- §5 (Шаблон README) — новый шаблон с Why/What + Features table. +- §7 (Параметры тулзы) — обновлён список: убраны tier/demo_gif/problem/solution, + добавлены why/what/features_en/features_ru. + +`README.md` перегенерирован по новому стандарту (11 фич в Features table, EN + +RU). + +`docs/project-map/README.md` — описания `repo-readme/SKILL.md` и +`create-readme.ts` обновлены (убрано "tier system", добавлено "features table, +4 delimiter pairs"). + +Проверки: `tsc --noEmit` (с `--types node`) чисто; `pytest +tests/test_permissions.py` OK; `check-permissions.py` OK. + +## Почему + +Problem/Solution не универсален для всех репо — не каждый проект укладывается +в "проблема → решение". Tier system усложнял поддержку (два пути генерации). +Features table — обязательная часть для витрины slaid098.dev: каждая карточка +должна показывать фичи. 4 пары разделителей (summary + features, EN + RU) +позволяют витрине парсить и summary, и таблицу фич независимо. + +## Pending + +— + +## Watch out + +`custom_sections_en/ru` теперь рендерятся ВНЕ delimiter tags — после +`` и до `### ⚡ Quick Start`. В старом формате они +были внутри ``. `validate` проверяет 4 пары +разделителей вместо 2 — все существующие README, сгенерированные старой +версией тулзы, не пройдут валидацию (нет features-en/ru delimiter pairs). +Требуется перегенерация через `create-readme` (mode: create). diff --git a/docs/project-map/README.md b/docs/project-map/README.md index 2727221..ef4a285 100644 --- a/docs/project-map/README.md +++ b/docs/project-map/README.md @@ -35,7 +35,7 @@ opencode-config/ │ │ ├── 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, tier system, GitHub metadata) — PR#112 +│ │ ├── repo-readme/SKILL.md # Standardized README generation (create-readme tool: create vs validate, bilingual Why/What + Features table, GitHub metadata) — PR#112, PR#116 │ │ ├── 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 @@ -44,7 +44,7 @@ opencode-config/ │ │ ├── commit.ts # commit tool wrapper (1 arg message, validates format+staged) — PR#38 │ │ ├── create-issue.ts # create-issue tool wrapper (3 args, validates format+labels; optional repo?: string) — PR#38, PR#65 │ │ ├── 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 slaid098.dev delimiters; local fs + remote gh api) — PR#112 +│ │ ├── create-readme.ts # create-readme tool (TS plugin, modes: create/validate; standardized bilingual README with features table, 4 delimiter pairs for slaid098.dev; local fs + remote gh api) — PR#112, PR#116 │ │ ├── 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, Python src.memory importability, env vars, memory dir, RAG index; markdown ✅/❌ report) — PR#101