From 722e9f41cd1d2c985cfc1b5e2d85634734754288 Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Wed, 27 May 2026 18:02:17 -0300 Subject: [PATCH] chore: apply unit test fixes, polyfills, and environment precedence fixes --- .agents/skills/generate-release/SKILL.md | 6 +- .agents/skills/implement-features/SKILL.md | 393 +++++++++++------- .agents/skills/resolve-issues/SKILL.md | 214 +++++++--- .agents/skills/review-discussions/SKILL.md | 292 +++++++++---- .agents/skills/review-prs/SKILL.md | 2 +- .agents/skills/version-bump/SKILL.md | 2 +- .agents/workflows/generate-release-ag.md | 6 +- .agents/workflows/implement-features-ag.md | 390 ++++++++++------- .agents/workflows/resolve-issues-ag.md | 213 +++++++--- .agents/workflows/review-discussions-ag.md | 286 +++++++++---- .agents/workflows/review-prs-ag.md | 2 +- .agents/workflows/version-bump-ag.md | 2 +- .claude/commands/generate-release-cc.md | 6 +- .claude/commands/implement-features-cc.md | 390 ++++++++++------- .claude/commands/resolve-issues-cc.md | 214 +++++++--- .claude/commands/review-discussions-cc.md | 287 +++++++++---- .claude/commands/review-prs-cc.md | 2 +- .claude/commands/version-bump-cc.md | 2 +- .source/browser.ts | 2 +- .source/server.ts | 46 +- CHANGELOG.md | 30 ++ README.md | 2 +- bin/cli/utils/environment.mjs | 20 +- bin/omniroute.mjs | 1 + docs/i18n/ar/CHANGELOG.md | 11 + docs/i18n/az/CHANGELOG.md | 11 + docs/i18n/bg/CHANGELOG.md | 11 + docs/i18n/bn/CHANGELOG.md | 11 + docs/i18n/cs/CHANGELOG.md | 11 + docs/i18n/da/CHANGELOG.md | 11 + docs/i18n/de/CHANGELOG.md | 11 + docs/i18n/es/CHANGELOG.md | 11 + docs/i18n/fa/CHANGELOG.md | 11 + docs/i18n/fi/CHANGELOG.md | 11 + docs/i18n/fr/CHANGELOG.md | 11 + docs/i18n/gu/CHANGELOG.md | 11 + docs/i18n/he/CHANGELOG.md | 11 + docs/i18n/hi/CHANGELOG.md | 11 + docs/i18n/hu/CHANGELOG.md | 11 + docs/i18n/id/CHANGELOG.md | 11 + docs/i18n/in/CHANGELOG.md | 11 + docs/i18n/it/CHANGELOG.md | 11 + docs/i18n/ja/CHANGELOG.md | 11 + docs/i18n/ko/CHANGELOG.md | 11 + docs/i18n/mr/CHANGELOG.md | 11 + docs/i18n/ms/CHANGELOG.md | 11 + docs/i18n/nl/CHANGELOG.md | 11 + docs/i18n/no/CHANGELOG.md | 11 + docs/i18n/phi/CHANGELOG.md | 11 + docs/i18n/pl/CHANGELOG.md | 11 + docs/i18n/pt-BR/CHANGELOG.md | 11 + docs/i18n/pt/CHANGELOG.md | 11 + docs/i18n/ro/CHANGELOG.md | 11 + docs/i18n/ru/CHANGELOG.md | 11 + docs/i18n/sk/CHANGELOG.md | 11 + docs/i18n/sv/CHANGELOG.md | 11 + docs/i18n/sw/CHANGELOG.md | 11 + docs/i18n/ta/CHANGELOG.md | 11 + docs/i18n/te/CHANGELOG.md | 11 + docs/i18n/th/CHANGELOG.md | 11 + docs/i18n/tr/CHANGELOG.md | 11 + docs/i18n/uk-UA/CHANGELOG.md | 11 + docs/i18n/ur/CHANGELOG.md | 11 + docs/i18n/vi/CHANGELOG.md | 11 + docs/i18n/zh-CN/CHANGELOG.md | 11 + docs/reference/openapi.yaml | 2 +- electron/package-lock.json | 4 +- electron/package.json | 2 +- open-sse/package.json | 2 +- open-sse/utils/proxyDispatcher.ts | 1 + open-sse/utils/proxyFetch.ts | 1 + open-sse/utils/setupPolyfill.ts | 33 ++ package-lock.json | 6 +- package.json | 24 +- tests/unit/batch_results.test.ts | 7 +- tests/unit/combo-routing-engine.test.ts | 18 +- tests/unit/dockerignore-docs-coverage.test.ts | 2 +- tests/unit/electron-main.test.ts | 44 +- tests/unit/free-proxies-add-to-pool.test.ts | 1 + tests/unit/opencode-executor.test.ts | 12 +- ...ini-tool-call-no-thought-signature.test.ts | 27 +- tests/unit/translator-helper-branches.test.ts | 2 +- 82 files changed, 2534 insertions(+), 915 deletions(-) create mode 100644 open-sse/utils/setupPolyfill.ts diff --git a/.agents/skills/generate-release/SKILL.md b/.agents/skills/generate-release/SKILL.md index fffecc3c62..83e5d818fa 100644 --- a/.agents/skills/generate-release/SKILL.md +++ b/.agents/skills/generate-release/SKILL.md @@ -1,6 +1,6 @@ --- name: generate-release-cx -description: Create a new release, bump version up to the .10 patch threshold, update changelog, and manage Pull Requests +description: Create a new release, bump version up to the .999 patch threshold, update changelog, and manage Pull Requests --- # Generate Release Workflow @@ -15,9 +15,9 @@ Bump version, finalize CHANGELOG, commit, open a **PR to main** and wait for use > **VERSION RULE: Always use PATCH bumps (3.x.y → 3.x.y+1)** > NEVER use `npm version minor` or `npm version major`. > Always use: `npm version patch --no-git-tag-version` -> The threshold rule: when `y` reaches 10, bump to `3.(x+1).0` — e.g. `3.8.10` → `3.9.0`. +> The threshold rule: when `y` reaches 1000, bump to `3.(x+1).0` — e.g. `3.8.999` → `3.9.0`. -> **🔴 SINGLE BRANCH RULE**: The `release/vX.Y.Z` branch is the **ONLY** development branch for the entire release cycle. ALL work — bug fixes, feature implementations, PR integrations, issue resolutions — MUST be committed directly on this branch. Never create separate `fix/`, `feat/`, or topic branches. When running `/resolve-issues`, `/implement-features`, or `/review-prs`, always work on the current release branch. +> **🔴 INTEGRATION BRANCH RULE**: The `release/vX.Y.Z` branch is the **integration target** for the entire release cycle. Bug fixes and feature implementations land here **via per-issue PRs from short-lived `fix/-` or `feat/-` worktrees** (see `/resolve-issues`, `/implement-features`). Contributor PRs from `/review-prs` likewise merge into this branch. The release branch is then merged to `main` via a single release PR at the end of the cycle. --- diff --git a/.agents/skills/implement-features/SKILL.md b/.agents/skills/implement-features/SKILL.md index ff88804039..a24fed62ff 100644 --- a/.agents/skills/implement-features/SKILL.md +++ b/.agents/skills/implement-features/SKILL.md @@ -12,8 +12,9 @@ A **5-phase** workflow that systematically harvests feature requests from GitHub ## Codex Execution Notes - Treat `// turbo` / `// turbo-all` as instructions to use `multi_tool_use.parallel` for independent reads, checks, and GitHub calls. -- Approval gates are hard stops. Present the report/plan in the final response and do not move to implementation phases until the user explicitly approves. +- Approval gates (Phase 3 and Phase 4 → 5) are hard stops. Present the report/plan in the final response and do not move to implementation phases until the user explicitly approves. - Keep harvest/research bounded enough to produce the approval report quickly; do not start implementation while still in report phases. +- The trust-but-verify audit in Phase 5.2 is mandatory before any commit — full lint + typecheck + cycles + build + coverage, plus a real `git diff` review for out-of-scope changes. **Output directory structure:** @@ -24,18 +25,26 @@ _ideia/ │ │ └── 1015-warp-terminal-mitm.md │ ├── 1046-native-playground.md # ✅ Ready — researched and planned │ └── 1046-native-playground.requirements.md -├── defer/ # ⏭️ Good ideas deferred for future cycles (issues CLOSED) +├── implemented/ # 🚧 Implemented but PR not yet merged to main (transient) +│ └── 1046-native-playground.md +├── defer/ # ⏭️ Good ideas deferred for future cycles (issues CLOSED after Phase 3 approval) │ └── 1041-smart-auto-combos.md -└── notfit/ # ❌ Out of scope / already exists (issues CLOSED) +└── notfit/ # ❌ Out of scope / already exists (issues CLOSED after Phase 3 approval) └── 945-telegram-integration.md _tasks/features-vX.Y.Z/ # Implementation plans (per-release) └── 1046-native-playground.plan.md ``` -> **LIFECYCLE RULE:** `viable/` files are **DELETED** once the feature is implemented — they are not moved. Only unimplemented features live in `viable/` (or `viable/need_details/`). Files in `defer/` and `notfit/` remain as permanent reference. +> **LIFECYCLE RULE:** +> - `viable/` files are **MOVED** to `implemented/` once code lands on the release branch. +> - `implemented/` files are **DELETED** only after the release PR is merged to `main`. +> - This preserves recovery context if implementation fails partially (build green but i18n missing, etc). +> - Files in `defer/` and `notfit/` remain as permanent reference. -> **BRANCH RULE**: All implementation work MUST happen on the current `release/vX.Y.Z` branch. Never create separate `feat/` branches. If no release branch exists yet, create one first using `/generate-release` Phase 1 steps 1–5. +> **BRANCH RULE**: All implementation work MUST happen on the current `release/vX.Y.Z` branch. Never create separate `feat/` branches. If no release branch exists yet, delegate creation to `/generate-release` (see Phase 1.2) — do NOT reimplement bump logic here. + +> **LANGUAGE RULE** (per `feedback_reply_language` memory): GitHub comments MUST match the language of the original issue body. Detect language by sampling the issue body + first 2 comments. Default to English when uncertain. All comment templates below are in English — translate to the detected language before posting. Internal docs, plan files, and idea files stay in English regardless. --- @@ -49,23 +58,18 @@ _tasks/features-vX.Y.Z/ # Implementation plans (per-release) ### 1.2 Ensure Release Branch Exists -// turbo - Before doing any work, ensure you are on the current release branch: ```bash -# Check current branch git branch --show-current - -# If on main, determine next version and create the release branch -VERSION=$(node -p "require('./package.json').version") -NEXT=$(node -p "const [a,b,c]=('$VERSION').split('.').map(Number); c>=9?a+'.'+(b+1)+'.0':a+'.'+b+'.'+(c+1)") -git checkout -b release/v$NEXT -npm version patch --no-git-tag-version -npm install ``` -If already on a `release/vX.Y.Z` branch, continue working there. +**Decision tree:** + +- If already on a `release/vX.Y.Z` branch → continue working there. +- If on `main` or any other branch → **delegate to `/generate-release`** by invoking its Phase 1 (steps 1–5: detect current version, bump, create branch, install). Do NOT reimplement the bump formula here — `/generate-release` owns the canonical version policy (patch bumps allowed up to `.999`; minor bump only when patch reaches `999`). + +> **Why delegate?** Duplicating the bump formula caused divergence in the past. `/generate-release` is the single source of truth for version arithmetic and now allows patches up to `.999` before bumping minor. ### 1.3 Fetch ALL Open Feature Requests @@ -84,6 +88,7 @@ gh issue list --repo / --state open --limit 500 --json number,title ``` - Merge both lists, deduplicate. Count and confirm the total. +- If the count hits the `--limit 500` ceiling, raise the limit and re-run — never proceed with a truncated set. **Step 2 — Fetch full metadata for each Issue** (one call per issue): @@ -93,7 +98,8 @@ gh issue view --repo / --json number,title,labels,body,com - Read the **entire body** — including description, use cases, screenshots, mockups, and any embedded images. - Read **ALL comments** — community discussion, agreements, restrictions, owner responses, and linked PRs. -- **Images**: If the body or comments contain image URLs (`![...](...)` or `https://...png/jpg/gif`), note them — they may contain UI mockups, wireframes, or architecture diagrams that are essential to understanding the request. +- **Images**: If the body or comments contain image URLs (`![...](...)` or `https://...png/jpg/gif`), **download and analyze them with the Read tool** (Claude can read PNG/JPG/GIF directly). Mockups and wireframes are often the most informative artifact — do NOT just "note" them, actually inspect their content and incorporate findings into the refined description. +- **Detect issue language** from body + first 2 comments and record it in the idea file front-matter (`reply_lang: pt-BR | en | es | ...`). This will drive comment translation in Phases 2.5 and 5. - You may batch these into parallel calls (up to 4 at a time). - Sort by oldest first (FIFO). @@ -107,6 +113,10 @@ Example: `1046-native-playground.md`, `1041-smart-auto-combos.md` #### 1.4a — If the idea file does NOT exist yet, create it: ```markdown +--- +reply_lang: +--- + # Feature: > GitHub Issue: #<NUMBER> — opened by @<author> on <date> @@ -132,6 +142,10 @@ Example: `1046-native-playground.md`, `1041-smart-auto-combos.md` - <agreements reached> - <objections raised> +## 🖼️ Mockup / Image Analysis + +<For each image embedded in the issue, summarize what it depicts: UI layout, data flow, architecture diagram, etc. Cite source URL.> + ## 🎯 Refined Feature Description <YOUR interpretation and enrichment of the feature request. Expand on what was asked, fill in logical gaps, provide concrete examples of how it would work. This section should be MORE detailed and clearer than the original request.> @@ -165,6 +179,7 @@ Example: `1046-native-playground.md`, `1041-smart-auto-combos.md` - Append new comments from the issue to the **Community Discussion** section. - Update the **Refined Feature Description** if new information changes the understanding. - Add any new **Related Ideas** cross-references found. +- Re-detect `reply_lang` only if the issue language clearly changed (uncommon). - **Do NOT overwrite** existing content — append and enrich it. ### 1.5 Cross-Reference & Deduplication @@ -175,11 +190,29 @@ After processing all issues: - If two features are substantially the same, add `🔗 Related Ideas` cross-references to both. - If one is a strict subset of another, note it in the smaller file: `> ℹ️ This feature is a subset of #<OTHER_NUMBER>. Consider implementing together.` +### 1.6 Detect In-Flight Work (avoid duplicate effort) + +For each issue number, check whether an open PR or branch already targets it: + +```bash +# Open PRs that link the issue +gh pr list --repo <owner>/<repo> --state open --search "linked:#<NUMBER>" --json number,title,headRefName + +# Local branches that mention the issue number +git branch -a | grep -E "(^|/)(feat|fix|refactor)/.*-?<NUMBER>(-|$)" || true +``` + +If a PR or branch already exists: + +- Mark the idea file with `> ⚠️ In-flight: PR #<PR_NUMBER> / branch <name>` near the top. +- **Skip Phase 2 research and Phase 4 planning** for this feature — the implementation is already in motion. +- In the Phase 3 report, list it under a separate "🚧 Already in progress" bucket; do NOT count it as VIABLE for implementation. + --- ## Phase 2 — Research: Find Solutions & Build Requirements -For each cataloged idea that is **viable** (aligns with the project's goals): +For each cataloged idea that is **viable** (aligns with the project's goals) AND not already in flight (per 1.6): ### 2.1 Viability Pre-Check @@ -200,10 +233,17 @@ Before investing in research, quickly assess: | ⏭️ **DEFER** | Good idea, too complex for this cycle | Catalog only, skip research | | ❌ **NOT FIT** | Doesn't fit the project | Explain why | | 🔁 **ALREADY EXISTS** | Feature already implemented | Point to existing feature | +| 🚧 **IN FLIGHT** | PR/branch already exists (from 1.6) | Skip — track only | ### 2.2 Internet Research (for VIABLE features) -For each viable feature, perform systematic research: +For each viable feature, perform systematic research with an **early-stopping criterion**: + +> **Stop as soon as EITHER condition is met:** +> - 3 reference implementations show a consistent pattern, OR +> - 1 high-quality repo (≥1k stars, updated within the last 12 months) already solves the problem cleanly. +> +> Cap at 10 repos total. Do NOT exhaustively browse — depth over breadth. **Step 1 — Web search for similar implementations:** @@ -220,8 +260,8 @@ WebSearch("site:github.com <feature keyword> <tech stack> stars:>100") WebSearch("github <feature keyword> implementation recently updated 2026") ``` -- Find **up to 10 relevant repositories**, sorted by most recently updated. -- For each repository: +- Sort by most recently updated. +- For each repository (until stop criterion hit): - Note the repo URL, star count, last commit date - Read its README and relevant source files via `WebFetch` - Extract the architectural approach, patterns used, and key code snippets @@ -314,7 +354,9 @@ For each researched feature, create a requirements file alongside its idea file: --- -## Phase 2.5 — Organize & Respond: Sort Files and Post GitHub Comments +## Phase 2.5 — Organize: Sort Files into Category Directories + +> **⚠️ This phase only moves files. It does NOT post comments or close issues.** All GitHub-visible actions are deferred to Phase 3.2 (after human approval). ### 2.5.1 Create Directory Structure @@ -323,13 +365,14 @@ For each researched feature, create a requirements file alongside its idea file: ```bash mkdir -p <project_root>/_ideia/viable mkdir -p <project_root>/_ideia/viable/need_details +mkdir -p <project_root>/_ideia/implemented mkdir -p <project_root>/_ideia/defer mkdir -p <project_root>/_ideia/notfit ``` ### 2.5.2 Move Idea Files to Category Subdirectories -After classification, move EVERY idea file to its correct subdirectory: +After classification, move EVERY idea file to its correct subdirectory (still local-only — no GitHub side-effects): ```bash # ✅ VIABLE — move idea + requirements files @@ -344,20 +387,73 @@ mv _ideia/<NUMBER>-*.md _ideia/defer/ # ❌ NOT FIT & 🔁 ALREADY EXISTS — move idea files only mv _ideia/<NUMBER>-*.md _ideia/notfit/ + +# 🚧 IN FLIGHT — leave in _ideia/ root with a top-of-file banner; do NOT touch the PR/branch ``` -No files should remain in `_ideia/` root after this step (except subdirectories). +No idea files should remain in `_ideia/` root after this step except `🚧 IN FLIGHT` entries. -### 2.5.3 Post GitHub Comments by Category +--- -**Each category has a specific comment template and action:** +## Phase 3 — Report: Present Findings & Get Human Approval + +### 3.1 🛑 MANDATORY STOP — Present Consolidated Report + +After completing Phase 1, Phase 2, and Phase 2.5, **STOP and present the following report** in the chat. **No comments have been posted to GitHub yet** — that happens in 3.2 after approval. + +Present a structured report containing: + +#### 3.1a — Feature Summary Table + +| # | Issue | Title | Verdict | Local Location | Planned GitHub Action | +| --- | ----- | ----- | --------------- | ----------------------------- | -------------------------------- | +| 1 | #N | Title | ✅ VIABLE | `_ideia/viable/` | Comment + keep OPEN | +| 2 | #N | Title | ⏭️ DEFER | `_ideia/defer/` | Comment + CLOSE | +| 3 | #N | Title | ❌ NOT FIT | `_ideia/notfit/` | Comment + CLOSE | +| 4 | #N | Title | 🔁 EXISTS | `_ideia/notfit/` | Comment with location + CLOSE | +| 5 | #N | Title | ❓ NEEDS DETAIL | `_ideia/viable/need_details/` | Comment with questions + OPEN | +| 6 | #N | Title | 🚧 IN FLIGHT | `_ideia/` (banner) | None — PR #M already handles it | + +#### 3.1b — Viable Features Detail + +For each VIABLE feature, provide a brief paragraph: + +- What was found during research (with stop reason: "3-pattern consistency" or "dominant repo") +- The proposed approach +- Key risks or unknowns +- Which reference repositories were most useful + +#### 3.1c — Issues Requiring Author Feedback + +For features marked ❓ NEEDS DETAIL, list: + +- What specific information is missing +- What examples or repository references would help +- Detected `reply_lang` for the question post + +#### 3.1d — Ask for User Confirmation + +End the report with: + +> **Ready to proceed?** +> +> Approving will (a) post comments on GitHub in the detected language of each issue and (b) close DEFER / NOT FIT / EXISTS issues. VIABLE and NEEDS DETAIL stay open. +> +> - Reply **"sim"** / **"yes"** to post all comments AND generate implementation plans for all VIABLE features. +> - Reply **"only comments"** to post comments without generating plans yet. +> - Reply with specific issue numbers to scope the action. +> - Reply **"não"** / **"no"** to stop without touching GitHub. + +### 3.2 Post GitHub Comments & Close Issues (only after approval) + +> **⚠️ Do NOT execute this step without explicit user approval from 3.1d.** + +For each issue, translate the appropriate template below into the `reply_lang` recorded in its idea file front-matter, then post. The English templates are reference only — never post the English version verbatim to a non-English issue. --- #### For 🔁 ALREADY EXISTS — Comment + CLOSE issue -// turbo - The feature already exists in the system. Explain WHERE it is and HOW to use it. ```markdown @@ -379,15 +475,13 @@ Closing this as the feature is already available. 🎉 ``` ```bash -gh issue close <NUMBER> --repo <owner>/<repo> --comment "<comment above>" +gh issue close <NUMBER> --repo <owner>/<repo> --comment "<translated comment>" ``` --- #### For ⏭️ DEFER — Comment + CLOSE issue -// turbo - Thank the user, explain the idea was cataloged, and that we'll study it before implementing. ```markdown @@ -401,21 +495,20 @@ Due to the **significant architectural impact** of this feature, we'll need to c - Your idea is saved in our internal feature backlog - We'll conduct architecture studies when this area is prioritized -- We'll notify you here when development begins -Thank you for contributing to OmniRoute's roadmap! Your input helps shape the product. 🚀 +If you want to track progress, please **subscribe to the repository releases** — every implemented feature is announced in the CHANGELOG. + +Thank you for contributing to OmniRoute's roadmap! 🚀 ``` ```bash -gh issue close <NUMBER> --repo <owner>/<repo> --comment "<comment above>" +gh issue close <NUMBER> --repo <owner>/<repo> --comment "<translated comment>" ``` --- #### For ❌ NOT FIT — Comment + CLOSE issue -// turbo - Politely explain why the feature doesn't fit the project scope. ```markdown @@ -431,15 +524,13 @@ We appreciate you thinking of ways to improve OmniRoute! If you'd like to discus ``` ```bash -gh issue close <NUMBER> --repo <owner>/<repo> --comment "<comment above>" +gh issue close <NUMBER> --repo <owner>/<repo> --comment "<translated comment>" ``` --- #### For ❓ NEEDS DETAIL — Comment (keep OPEN) -// turbo - Ask for the specific missing details needed. ```markdown @@ -460,9 +551,7 @@ Looking forward to your response! 🚀 #### For ✅ VIABLE — Comment (keep OPEN) -// turbo - -Thank the user, confirm we've cataloged their idea, and explain it may be implemented in future versions. +Thank the user, confirm we've cataloged their idea, and explain that progress is tracked in releases. ```markdown Hi @<author>! Thanks for the great feature suggestion! 🙏 @@ -471,58 +560,12 @@ We've analyzed your request and it aligns well with OmniRoute's roadmap. We've * **Status:** 📋 Cataloged for future implementation -This feature may be included in upcoming releases. We'll **respond to this issue and tag you** as soon as implementation begins so you can test it. +This issue will be **closed automatically by the merge commit** when the feature ships. To follow along, you can subscribe to repository releases or watch this issue. Thank you for helping improve OmniRoute! 🚀 ``` -**⚠️ Do NOT close viable issues — they remain OPEN for tracking.** - ---- - -## Phase 3 — Report: Present Findings to User - -### 3.1 🛑 MANDATORY STOP — Present Consolidated Report - -After completing Phase 1, Phase 2, and Phase 2.5, **STOP and present the following report** in the chat. Do NOT proceed to implementation. - -Present a structured report containing: - -#### 3.1a — Feature Summary Table - -| # | Issue | Title | Verdict | Location | Action | -| --- | ----- | ----- | --------------- | ----------------------------- | ----------------------------- | -| 1 | #N | Title | ✅ VIABLE | `_ideia/viable/` | Issue OPEN, comment posted | -| 2 | #N | Title | ⏭️ DEFER | `_ideia/defer/` | Issue CLOSED with explanation | -| 3 | #N | Title | ❌ NOT FIT | `_ideia/notfit/` | Issue CLOSED with explanation | -| 4 | #N | Title | 🔁 EXISTS | `_ideia/notfit/` | Issue CLOSED with guidance | -| 5 | #N | Title | ❓ NEEDS DETAIL | `_ideia/viable/need_details/` | Issue OPEN, questions posted | - -#### 3.1b — Viable Features Detail - -For each VIABLE feature, provide a brief paragraph: - -- What was found during research -- The proposed approach -- Key risks or unknowns -- Which reference repositories were most useful - -#### 3.1c — Issues Requiring Author Feedback - -For features marked ❓ NEEDS DETAIL, list: - -- What specific information is missing -- What examples or repository references would help - -#### 3.1d — Ask for User Confirmation - -End the report with: - -> **Ready to proceed with implementation?** -> -> - Reply **"sim"** or **"yes"** to generate full implementation plans for all VIABLE features. -> - Reply with specific issue numbers to select only certain features. -> - Reply **"não"** or **"no"** to stop here. +**⚠️ Do NOT close viable issues — they remain OPEN until the implementation PR closes them via commit message.** --- @@ -530,13 +573,24 @@ End the report with: > **⚠️ Do NOT enter this phase without explicit user approval from Phase 3.** -### 4.1 Create Task Directory +### 4.1 Pre-Plan Context Load (mandatory) + +Before writing ANY plan, read: + +1. `docs/architecture/REPOSITORY_MAP.md` — to know which directory owns what. +2. `docs/architecture/CODEBASE_DOCUMENTATION.md` — for the engineering reference. +3. The matching "Adding a New X" scenario from `CLAUDE.md` (provider, API route, DB module, MCP tool, A2A skill, cloud agent, embedded service, guardrail, eval, skill, webhook event). +4. Any docs linked from the requirements file's "External References" section. + +This ensures plans cite real paths and follow the established add-a-X recipe, instead of inventing structure. + +### 4.2 Create Task Directory ```bash mkdir -p <project_root>/_tasks/features-vX.Y.Z/ ``` -### 4.2 Generate One Implementation Plan Per Feature +### 4.3 Generate One Implementation Plan Per Feature For each VIABLE feature approved by the user, create: @@ -549,6 +603,7 @@ For each VIABLE feature approved by the user, create: > Idea: [\_ideia/viable/<NUMBER>-title.md](../../_ideia/viable/<NUMBER>-title.md) > Requirements: [\_ideia/viable/<NUMBER>-title.requirements.md](../../_ideia/viable/<NUMBER>-title.requirements.md) > Branch: `release/vX.Y.Z` +> Matching CLAUDE.md recipe: <e.g. "Adding a New Provider"> ## Overview @@ -557,8 +612,8 @@ For each VIABLE feature approved by the user, create: ## Pre-Implementation Checklist - [ ] Read all related source files listed below -- [ ] Confirm no conflicts with in-flight PRs -- [ ] Verify database migration numbering +- [ ] Confirm no conflicts with in-flight PRs (re-run Phase 1.6 lookup) +- [ ] Verify database migration numbering (next free integer in `src/lib/db/migrations/`) ## Implementation Steps @@ -575,7 +630,7 @@ For each VIABLE feature approved by the user, create: ... -### Step N: Tests +### Step N: Tests (MANDATORY per CLAUDE.md hard rule #8) **New test files:** @@ -585,6 +640,7 @@ For each VIABLE feature approved by the user, create: - [ ] <test case 1> - [ ] <test case 2> +- [ ] Coverage check: confirm overall coverage stays ≥75% statements/lines/functions, ≥70% branches (hard rule #9) ### Step N+1: i18n @@ -594,36 +650,41 @@ For each VIABLE feature approved by the user, create: ### Step N+2: Documentation -- [ ] Update CHANGELOG.md +- [ ] Update CHANGELOG.md (current release section) - [ ] Update relevant docs/ files +- [ ] If touching error responses, follow `docs/security/ERROR_SANITIZATION.md` +- [ ] If touching upstream credentials, follow `docs/security/PUBLIC_CREDS.md` -## Verification Plan +## Verification Plan (Trust-but-Verify — mandatory before declaring done) -1. Run `npm run build` — must pass -2. Run `npm test` — all tests must pass -3. Run `npm run lint` — no new errors -4. <Manual verification steps> +1. `git status` + `git diff --stat` — review every changed file; flag anything outside the plan's declared scope +2. `npm run lint` — 0 new errors +3. `npm run typecheck:core` — clean +4. `npm run typecheck:noimplicit:core` — clean +5. `npm run check:cycles` — no new circular deps +6. `npm run build` — must pass +7. `npm run test:coverage` — coverage gate respected +8. `npm run check-docs-sync` (via pre-commit hook) — passes +9. Manual UI verification if the feature touches frontend (start dev server, exercise golden path + 1 edge case) ## Commit Plan -``` +``` feat: <description> (#<NUMBER>) - +``` ``` -``` - -### 4.3 Present Plans for Final Approval +### 4.4 Present Plans for Final Approval Present a summary of all generated plans: > **Implementation plans generated:** > -> | # | Feature | Plan File | Steps | Effort | -> | --- | ------- | ---------------------------------------- | ------- | ------ | -> | 1 | <title> | `_tasks/features-vX.Y.Z/N-title.plan.md` | N steps | Medium | +> | # | Feature | Plan File | Steps | Effort | CLAUDE.md recipe | +> | --- | ------- | ---------------------------------------- | ------- | ------ | ---------------------- | +> | 1 | <title> | `_tasks/features-vX.Y.Z/N-title.plan.md` | N steps | Medium | Adding a New Provider | > -> Reply **"sim"** or **"yes"** to begin implementation of all features. +> Reply **"sim"** / **"yes"** to begin implementation of all features. > Reply with specific issue numbers to implement only certain ones. --- @@ -637,17 +698,62 @@ Present a summary of all generated plans: For each approved plan, execute it step by step: 1. **Follow the plan** — implement exactly as specified in the `.plan.md` file -2. **Build** — Run `npm run build` after each feature to verify compilation -3. **Test** — Run `npm test` to ensure no regressions -4. **Commit** — Commit with: `feat: <description> (#<NUMBER>)` -5. **Update the plan** — Mark completed steps with `[x]` in the plan file -6. **Continue** — Move to the next feature (do NOT switch branches) +2. **Mark progress** — flip checkboxes to `[x]` in the plan as each step completes -### 5.2 Respond to Authors (Update Viable Issues) +### 5.2 Trust-but-Verify Audit (mandatory before commit) -For each implemented feature, **close the issue with a final comment**: +> Aligned with `~/.claude/CLAUDE.md` global rule: never trust a subagent's summary alone. -````markdown +Run the full audit checklist from the plan's "Verification Plan" section AND inspect the diff yourself: + +```bash +git status +git diff --stat +git diff # full diff, scan for out-of-scope changes +npm run lint +npm run typecheck:core +npm run typecheck:noimplicit:core +npm run check:cycles +npm run build +npm run test:coverage +``` + +**Block-on-failure checklist:** + +- [ ] No files changed outside the plan's declared scope (or scope expansion explicitly justified) +- [ ] No deleted symbols/routes/files without a documented replacement (grep to confirm) +- [ ] No weakened or removed test assertions (only additions or alignments with real behavior) +- [ ] Coverage gate green (75/75/75/70) +- [ ] All commands above exit 0 +- [ ] If UI was touched: manual smoke test passed and noted + +If any item fails, **fix root cause** before committing. Do NOT bypass with `--no-verify` (hard rule #10). + +### 5.3 Commit (one feature, one commit) + +```bash +git add <only files in the plan> +git commit -m "feat: <description> (#<NUMBER>)" +``` + +> **No `Co-Authored-By` trailers** (hard rule #16). Commits go solely under `diegosouzapw`. + +Then move (do NOT delete yet) the idea file to `_ideia/implemented/`: + +```bash +mv _ideia/viable/<NUMBER>-<title>.md _ideia/implemented/ +mv _ideia/viable/<NUMBER>-<title>.requirements.md _ideia/implemented/ 2>/dev/null || true +``` + +> **Why move, not delete?** If the release PR is reverted or rebased, we still have the context. The file is deleted only after the PR merges to `main` (see 5.6). + +Continue to the next feature on the same branch — do NOT switch branches between features. + +### 5.4 Respond to Authors + +For each implemented feature, post a final close-comment **translated into the issue's `reply_lang`**: + +```markdown ✅ **Implemented in `release/vX.Y.Z`!** Hi @<author>! Great news — your feature request has been implemented! 🎉 @@ -656,58 +762,59 @@ Hi @<author>! Great news — your feature request has been implemented! 🎉 - <bullet list of what was built> -**How to try it:** +**How to try it (after the release PR merges):** ```bash -git fetch origin && git checkout release/vX.Y.Z +git fetch origin && git checkout main && git pull npm install && npm run dev ``` -```` This will be included in the upcoming **vX.Y.Z** release. Feel free to reopen if you spot any issues! 🚀 - -```` - -```bash -gh issue close <NUMBER> --repo <owner>/<repo> --comment "<comment above>" -```` - -Then **DELETE the idea file** — it has served its purpose: - -```bash -# ✅ Implemented files are DELETED (not moved) -rm _ideia/viable/<NUMBER>-<title>.md -rm _ideia/viable/<NUMBER>-<title>.requirements.md # if exists ``` -> **Why delete?** `viable/` only holds features that still NEED to be done. Once implemented, the commit history and CHANGELOG are the source of truth. Keeping the file would be confusing. +```bash +gh issue close <NUMBER> --repo <owner>/<repo> --comment "<translated comment>" +``` -### 5.3 Finalize & Push +### 5.5 Finalize the Release Branch After implementing all approved features: 1. **Update CHANGELOG.md** on the release branch with all new feature entries -2. Push the release branch: `git push origin release/vX.Y.Z` -3. Run `/generate-release` workflow Phase 1 steps 7–10 (tests → commit → push → open PR to main → wait for user) +2. Push: `git push origin release/vX.Y.Z` +3. Hand off to `/generate-release` for the "Tests → Commit → Push → PR to main" stage. Refer to it **by stage name**, not step number, so this command does not break if `/generate-release` renumbers steps. -### 5.4 Final Summary Report +### 5.6 Post-Merge Cleanup (only after release PR merges to main) + +Once the release PR is merged: + +```bash +# Now safe to delete — commit history + CHANGELOG are the source of truth +rm _ideia/implemented/<NUMBER>-*.md +``` + +> If running this command before the merge: STOP at 5.5 and skip 5.6. Re-enter the workflow later just for the cleanup. + +### 5.7 Final Summary Report Present a final summary report to the user: | Issue | Title | Verdict | Action | Commit | | ----- | ----- | --------------- | -------------------------------------------------- | --------- | -| #N | Title | ✅ Implemented | Issue closed, idea file deleted | `abc1234` | +| #N | Title | ✅ Implemented | Issue closed, idea file in `_ideia/implemented/` | `abc1234` | | #N | Title | ⏭️ Deferred | Issue closed + saved in `_ideia/defer/` | — | | #N | Title | ❌ Not Fit | Issue closed + saved in `_ideia/notfit/` | — | | #N | Title | 🔁 Exists | Issue closed + saved in `_ideia/notfit/` | — | | #N | Title | ❓ Needs Detail | Issue OPEN, moved to `_ideia/viable/need_details/` | — | +| #N | Title | 🚧 In Flight | Untouched — tracked by PR #M | — | Include: - Total features harvested - Total ideas cataloged (`viable/need_details/` + `defer/` + `notfit/`) -- Total features implemented (idea files deleted, issues closed) +- Total features implemented (idea files in `_ideia/implemented/`, awaiting post-merge cleanup) - Total features deferred - Total issues closed -- Total issues left open (needs detail only — viable are closed after implementation) -- Test results (pass/fail count) +- Total issues left open (NEEDS DETAIL + VIABLE-pending-implementation + IN FLIGHT) +- Audit results: lint / typecheck / cycles / build / coverage (pass-count per phase) +- Languages used in posted comments (e.g. "3× pt-BR, 5× en, 1× es") diff --git a/.agents/skills/resolve-issues/SKILL.md b/.agents/skills/resolve-issues/SKILL.md index a1658f09e0..73b5e32c1a 100644 --- a/.agents/skills/resolve-issues/SKILL.md +++ b/.agents/skills/resolve-issues/SKILL.md @@ -1,24 +1,27 @@ --- name: resolve-issues-cx -description: Fetch all open GitHub issues, analyze bugs, resolve what's possible, triage the rest, wait for user validation, then commit and release +description: Fetch all open GitHub issues, analyze bugs, resolve up to 30 per batch via per-issue worktrees + PRs into the release branch, triage the rest, wait for user validation --- # /resolve-issues — Automated Issue Resolution Workflow ## Overview -This workflow fetches all open issues from the project's GitHub repository, classifies them, analyzes bugs, proposes a resolution plan, waits for user validation, and ONLY THEN implements the fixes, commits, and closes the issues on the current release branch (`release/vX.Y.Z`). It does NOT merge or release automatically — the release branch is later merged via PR to main. +This workflow fetches all open issues from the project's GitHub repository, classifies them, analyzes bugs, proposes a resolution plan, waits for user validation, and ONLY THEN implements fixes. The current `release/vX.Y.Z` branch is the integration target — each individual fix is implemented on its own short-lived `fix/<issue>-<short>` branch inside its own git worktree, merged into the release branch via PR, then the worktree and local branch are deleted. The release branch is later merged to `main` via `/generate-release`. ## Codex Execution Notes - Treat `// turbo` / `// turbo-all` as instructions to use `multi_tool_use.parallel` for independent reads, checks, and GitHub calls. - The initial report/plan is a hard stop. Do not edit code, close issues, or commit until the user explicitly approves the report. - Keep classification and bug analysis bounded enough to produce the user-facing report before deep implementation work. +- One worktree per fix — never reuse a worktree for two different issues, even sequentially in the same session. -> **BRANCH RULE**: All work MUST happen on the current `release/vX.Y.Z` branch. Never create separate `fix/` branches. If no release branch exists yet, create one first using `/generate-release` Phase 1 steps 1–5. +> **BRANCH RULE**: The current `release/vX.Y.Z` branch is the integration target. Each fix MUST live on its own `fix/<ISSUE>-<short>` branch cut from the release branch, inside its own worktree under `.worktrees/`. After the per-issue PR is merged into the release branch, the worktree and local branch are deleted. Never commit fixes directly to the release branch. If no release branch exists yet, create one first using `/generate-release` Phase 1 steps 1–5. > **⛔ PR PROHIBITION**: If a fix is associated with a contributor's PR, you MUST merge their PR — NEVER close it and re-implement the fix yourself. See `/review-prs` workflow for the full policy. The `gh pr close` command is FORBIDDEN unless the repository owner explicitly requests it. +> **🌐 REPLY LANGUAGE**: All comments posted to issues (close messages, RESPOND comments, PR descriptions visible to the reporter) MUST match the reporter's language. When in doubt, default to **English**. The reporter's language is detected from the issue body and prior comments by that author. + ## Steps ### 1. Identify the GitHub Repository @@ -32,40 +35,45 @@ This workflow fetches all open issues from the project's GitHub repository, clas // turbo -Before doing any work, ensure you are on the current release branch: +Before doing any work, ensure a `release/vX.Y.Z` branch exists. If you are currently on `main`, create one: ```bash -# Check current branch git branch --show-current # If on main, determine next version and create the release branch VERSION=$(node -p "require('./package.json').version") -NEXT=$(node -p "const [a,b,c]=('$VERSION').split('.').map(Number); c>=9?a+'.'+(b+1)+'.0':a+'.'+b+'.'+(c+1)") +NEXT=$(node -p "const [a,b,c]=('$VERSION').split('.').map(Number); c>=999?a+'.'+(b+1)+'.0':a+'.'+b+'.'+(c+1)") git checkout -b release/v$NEXT npm version patch --no-git-tag-version npm install ``` +> Threshold: patches climb to `.999` before rolling. Example: `3.4.999` → `3.5.0`. + If already on a `release/vX.Y.Z` branch, continue working there. -### 3. Fetch All Open Issues +### 3. Fetch All Open Issues (cap 30 per batch) // turbo-all -**⚠️ CRITICAL**: The JSON output of `gh issue list` can be truncated by the tool, silently hiding issues. You MUST use the two-step approach below to guarantee **all** issues are fetched. +**⚠️ CRITICAL**: The JSON output of `gh issue list` can be truncated by the tool, silently hiding issues. Use the two-step approach below. **Step 3a — Get Issue numbers only** (small output, never truncated): - Run: `gh issue list --repo <owner>/<repo> --state open --limit 500 --json number --jq '.[].number'` -- This outputs one issue number per line. Count them and confirm total. +- Count them and remember the total. -**Step 3b — Fetch full metadata for each Issue** (one call per issue): +**Step 3b — Fetch full metadata for each Issue** (parallel, validated against 3a): - For each issue number from step 3a, run: - `gh issue view <NUMBER> --repo <owner>/<repo> --json number,title,labels,body,comments,createdAt,author` -- You may batch these into parallel calls (up to 4 at a time). + `gh issue view <NUMBER> --repo <owner>/<repo> --json number,title,labels,body,comments,createdAt,author,url` +- Batch in parallel (8–12 concurrent calls). After completion, assert `fetched_count == count_from_3a`; if mismatch, retry the missing IDs. - Sort by oldest first (FIFO). +**Step 3c — Cap at 30 per run**: + +- If more than 30 open issues qualify as bugs after step 4, ask the user which subset of up to 30 to handle now. The remainder is deferred to the next run. + ### 4. Classify Each Issue For each issue, determine its type: @@ -75,99 +83,187 @@ For each issue, determine its type: - **Question** — Has `question` label, or is asking "how to" something - **Other** — Anything else -Focus ONLY on **Bugs** for resolution. Feature requests and questions should be skipped with a note in the final report. +Focus ONLY on **Bugs** for resolution. Feature requests and questions are skipped with a note in the final report. + +#### 4.5. PR-Linked Check (mandatory) + +For every bug, query linked PRs: + +```bash +gh issue view <NUMBER> --repo <owner>/<repo> --json closedByPullRequestsReferences,body +``` + +If the issue is referenced by an **open** contributor PR (or the body links to one), do NOT plan a self-implemented fix. Mark the issue as `🤝 PR-LINKED — redirect to /review-prs` in the report and stop deeper analysis for it. **NEVER close the contributor PR.** ### 5. Deep-Read Each Bug Issue (One-by-One Analysis) -**IMPORTANT**: Read each bug issue thoroughly, one at a time, before moving to the next. This is NOT a batch process — each issue needs focused attention. +Read each bug issue thoroughly, one at a time. Each issue gets focused attention. #### 5a. Understand the Problem -For each bug issue, perform the full analysis: - -1. **Read the entire body** — including Description, Steps to Reproduce, Expected/Actual Behavior, Error Logs, and Screenshots -2. **Read ALL comments** — including bot triage comments (Kilo, etc.) and owner/community responses. Pay attention to: - - Whether someone already responded with a fix - - Whether a community member confirmed the issue is resolved - - Whether the issue was marked as duplicate by a bot. **WARNING: DO NOT blindly trust bot duplicate labels (e.g., kilo-duplicate). Bots make mistakes. You MUST read the full conversation and do your own independent analysis to determine if it is truly a duplicate or a distinct bug.** -3. **Identify the claimed error** — extract the exact error message, status code, and provider/model involved +1. **Read the entire body** — Description, Steps to Reproduce, Expected/Actual Behavior, Error Logs, Screenshots +2. **Read ALL comments** — bot triage (Kilo, etc.) and owner/community responses. Look for: + - Someone already responded with a fix + - Community member confirmed it is resolved + - Bot duplicate flag. **DO NOT blindly trust bot labels (e.g., `kilo-duplicate`).** Re-verify independently from current source + web research. +3. **Identify the claimed error** — exact error message, status code, provider/model, OS, Node version. #### 5b. Check Information Sufficiency -Verify the issue contains enough to act on: +Verify the issue contains: - [ ] Clear description of the problem - [ ] Steps to reproduce OR error logs - [ ] Provider/model/version information - [ ] Expected vs actual behavior -#### 5c. Determine Issue Disposition +**If ANY item is missing → auto-classify as `📝 RESPOND — Needs Info` and skip 5d.** Do not attempt root-cause analysis on under-specified issues. -For each bug, classify into one of 5 actions: +#### 5c. Determine Issue Disposition | Disposition | When to Apply | Action | | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- | | **✅ CLOSE — Already Fixed** | Owner responded with fix + no user follow-up, OR community confirmed fix | Close with comment citing which version fixed it | | **✅ CLOSE — Duplicate** | You have independently verified the issue is a duplicate (do NOT rely solely on bot flags) + user provides no new info | Close referencing the original issue | | **✅ CLOSE — Stale** | We requested logs/info > 7 days ago with no reply | Close thanking the user, invite to reopen if needed | -| **📝 RESPOND — Needs Info** | Issue is real but missing critical reproduction details | Comment asking for specifics per `/issue-triage` | +| **📝 RESPOND — Needs Info** | Issue is real but missing critical reproduction details (also triggered by 5b) | Comment asking for specifics per `/issue-triage` | | **📝 RESPOND — User Config** | Error is caused by unsupported env (Node version, wrong model path, missing API enablement) | Comment explaining the user-side fix | +| **🤝 PR-LINKED** | An open contributor PR already targets this issue (from step 4.5) | Redirect to `/review-prs`; do not re-implement | | **🔧 FIX — Code Change** | Root cause is confirmed in the codebase | Research, propose solution in report, wait for approval | #### 5d. For "FIX — Code Change" Issues -Before coding, perform deep source analysis to formulate a plan: +Before coding, perform deep source analysis: -1. **Search the codebase** — `grep_search` for error strings, relevant function names, affected files -2. **Search the web** — for upstream API changes, SDK updates, or breaking changes that explain the bug -3. **Read the full source file** — don't rely on grep snippets; understand the surrounding logic -4. **Verify the root cause** — confirm the bug is reproducible based on the code, not just a user misconfiguration -5. **Formulate a proposed solution** — detail the exact files and lines you will change and how you will solve it. -6. **Create an Implementation Plan file** — write your proposed solution to `_tasks/features-vX.Y.Z/<ISSUE_NUMBER>-<short-description>.plan.md` (e.g. `_tasks/features-v3.7.6/1810-auto-restore-probe-failed-db.plan.md`) where `vX.Y.Z` is the current branch version. The plan should contain an Overview, Pre-Implementation Checklist, and detailed Implementation Steps (Files, Changes). -7. **DO NOT modify the codebase yet** — wait for user approval on your report and plan first. +1. **Search the codebase** — grep for error strings, function names, affected files +2. **Search the web** — upstream API changes, SDK updates, breaking changes +3. **Read the full source file** — don't rely on grep snippets +4. **Verify the root cause** is in our code, not user misconfiguration +5. **Formulate a proposed solution** — exact files/lines/logic +6. **Create an Implementation Plan file** at `_tasks/fixes-vX.Y.Z/<ISSUE>-<short-description>.plan.md` (`vX.Y.Z` = current release branch version). Create the directory first: `mkdir -p _tasks/fixes-vX.Y.Z`. The plan contains: Overview, Reproduction Steps, Regression Test Outline, Implementation Steps (files/changes), Rollout Notes. +7. **DO NOT modify the codebase yet** — wait for user approval. #### 5e. For "RESPOND" Issues Post a substantive comment that: -- Acknowledges the specific error they reported +- Acknowledges the specific error reported - Explains the likely root cause -- Provides concrete steps to resolve (version upgrade, env var fix, model path correction) +- Provides concrete steps (version upgrade, env var fix, model path correction) - Asks for follow-up info if needed -**Do NOT post generic template responses.** Every comment should reference the user's specific error messages and environment. +**No generic templates.** Every comment references the user's specific error and environment, and is written in the reporter's language (English default). ### 6. Generate Report & Wait for Validation -Present a summary report to the user detailing your proposed actions. For any bugs that need fixing, explicitly explain your proposed solution (files to change and logic) and point out that it will be implemented on the release branch (`release/vX.Y.Z`) after approval. +Present a summary report. For FIX bugs, explicitly explain the proposed solution (files to change + logic) and confirm it will land via per-issue worktree → PR → release branch after approval. Include the reporter's detected language per row so the user can verify. -| Issue | Title | Status | Proposed Action / Version | -| ----- | ----- | ------------- | ----------------------------------------- | -| #N | Title | ✅ Close | Already fixed / duplicate (explain why) | -| #N | Title | 🔧 Propose | Explanation of the code fix to be applied | -| #N | Title | 📝 Respond | Guidance comment to be posted | -| #N | Title | ❓ Needs Info | Triage comment to be posted | -| #N | Title | ⏭️ Skip | Feature request / not a bug | +| Issue | Title | Status | Reply Lang | Proposed Action / Version | +| ----- | ----- | -------------- | ---------- | ------------------------------------------ | +| #N | Title | ✅ Close | en | Already fixed / duplicate (explain why) | +| #N | Title | 🔧 Propose | pt-BR | Code fix plan summary + worktree branch | +| #N | Title | 📝 Respond | en | Guidance comment to be posted | +| #N | Title | ❓ Needs Info | en | Triage comment to be posted | +| #N | Title | 🤝 PR-Linked | en | Redirect to /review-prs (PR #M) | +| #N | Title | ⏭️ Skip | — | Feature request / not a bug | > **⚠️ IMPORTANT**: Do NOT implement code changes, commit, push, or close issues at this step. > Wait for the user to review the proposed fixes and respond with **OK** before proceeding. -- If the user says **OK** or approves → Proceed to step 7 -- If the user requests changes → Adjust the proposed solution and present the report again +- If the user says **OK** → Proceed to step 7 +- If the user requests changes → Adjust and re-present the report - If the user rejects → Revert any accidental changes and stop -### 7. Implement Fixes, Run Tests & Commit (only after user approval) +### 7. Implement Fixes via Per-Issue Worktrees + PRs (only after user approval) -After the user validates and gives the OK: +For each approved FIX issue (up to 30 per batch), repeat the following sequence. Issues can be processed sequentially or in parallel (one worktree each — never two fixes in the same worktree). -1. **Implement the fixes** — modify the codebase according to the approved plan. -2. **Run tests** — `npm run test:all` (or the specific test file) to ensure 100% pass. -3. **Update CHANGELOG.md** with all new bug fix entries. -4. **Commit** each fix individually on the release branch with message format: `fix: <description> (#<issue_number>)`. -5. **Push** the release branch: `git push origin release/vX.Y.Z`. -6. **Close resolved issues immediately**. For each issue that was marked as Fixed, run: - `gh issue close <NUMBER> --repo <owner>/<repo> --comment "Thank you for reporting! This issue has been fixed and will be included in the next release (vX.Y.Z)."` -7. Likewise, close `Duplicate` issues referencing the original, close `Needs Info` if stale, and post the required comments. -8. If the project runs automatic releases or needs a PR, proceed to run `/generate-release` workflow Phase 1 steps 7–10 (tests → commit → push → open PR to main → wait for user). +#### 7.1. Spin up an isolated worktree on a fresh fix branch -If NO fixes were committed, skip closing and source control steps and just conclude the workflow. +```bash +ISSUE=<NUMBER> +SHORT=<short-kebab-desc> +RELEASE_BRANCH=$(git -C <project_root> branch --show-current) # release/vX.Y.Z +WT_DIR=".worktrees/fix-${ISSUE}-${SHORT}" +BRANCH="fix/${ISSUE}-${SHORT}" + +git fetch origin "$RELEASE_BRANCH" +git worktree add "$WT_DIR" -b "$BRANCH" "origin/$RELEASE_BRANCH" +cd "$WT_DIR" +``` + +#### 7.2. Write the regression test first (TDD) + +- Author a unit/integration test that reproduces the bug. **It must fail on the unfixed code.** Run it and confirm the failure. +- Hard rule #8: any production change must ship with tests in the same PR. The regression test is non-negotiable. + +#### 7.3. Implement the fix + +- Apply the approved plan from `_tasks/fixes-vX.Y.Z/<ISSUE>-<short>.plan.md`. +- Keep the diff scoped to this issue. No drive-by refactors. + +#### 7.4. Run the test suite + +- `npm run test:all` (or the appropriate suite for the touched area; the regression test MUST be included). +- All tests must pass before commit. Also run the relevant `lint` / `typecheck` per CLAUDE.md trust-but-verify checklist. + +#### 7.5. Update CHANGELOG.md and commit (single commit, same diff) + +- Add the new bug-fix entry under the current `vX.Y.Z` section of CHANGELOG.md. +- CHANGELOG entry + code + test go in **one** commit on the fix branch: + +```bash +git add <changed files> CHANGELOG.md +git commit -m "fix: <description> (#${ISSUE})" +``` + +#### 7.6. Push and open a PR into the release branch + +```bash +git push -u origin "$BRANCH" +gh pr create \ + --base "$RELEASE_BRANCH" \ + --head "$BRANCH" \ + --title "fix: <description> (#${ISSUE})" \ + --body "Closes #${ISSUE}\n\n<short summary, plan link, regression test reference>" +``` + +#### 7.7. Merge the PR into the release branch + +- Wait for CI green, then merge with the project's default merge strategy. +- The PR title becomes the release-branch commit. + +#### 7.8. Clean up worktree and local branch + +```bash +cd <project_root> +git worktree remove "$WT_DIR" +git branch -D "$BRANCH" +``` + +#### 7.9. Close the issue with a localized comment + +Match the reporter's language (English default). Template: + +> **EN**: Thanks for reporting! Fixed in `release/vX.Y.Z` (already merged into the active development branch — feel free to pull and test it now). It will ship in the next release (vX.Y.Z). +> +> **pt-BR**: Obrigado pelo report! Corrigido em `release/vX.Y.Z` (já mergeado na branch de desenvolvimento atual — pode dar pull e testar). Vai sair na próxima release (vX.Y.Z). + +```bash +gh issue close "$ISSUE" --repo <owner>/<repo> --comment "<localized message above>" +``` + +#### 7.10. Close non-FIX dispositions + +After all FIX issues are merged: + +- `Duplicate`: close referencing the original issue (localized). +- `Stale`: close thanking the user and inviting reopen (localized). +- `RESPOND — Needs Info` / `RESPOND — User Config`: post the substantive comment from 5e (localized). +- `PR-LINKED`: leave the issue open; comment redirecting to the contributor PR if not already linked. + +#### 7.11. Hand off to release flow (optional) + +If a release PR to `main` is desired now, run `/generate-release` Phase 1 steps 7–10 (tests → commit version bump → push → open PR to main → wait for user). + +If NO fixes were committed, skip 7.7–7.11 and just conclude the workflow. diff --git a/.agents/skills/review-discussions/SKILL.md b/.agents/skills/review-discussions/SKILL.md index 13e7255069..b8c03ba80b 100644 --- a/.agents/skills/review-discussions/SKILL.md +++ b/.agents/skills/review-discussions/SKILL.md @@ -1,20 +1,27 @@ --- name: review-discussions-cx -description: Read all open GitHub Discussions, summarize them, respond to pending ones, and create issues from actionable feature requests +description: Read all open GitHub Discussions, summarize them, respond to pending ones, create issues from actionable feature requests, and triage stale threads for closure --- # /review-discussions — GitHub Discussions Review & Response Workflow ## Overview -This workflow reads all open GitHub Discussions, generates a categorized summary, identifies which ones need a response, drafts and posts replies, and optionally creates issues from actionable feature requests. It follows the same flow used for Issues but adapted for the Discussions forum. +This workflow reads all open GitHub Discussions, generates a categorized summary, identifies which ones need a response, drafts and posts replies, optionally creates issues from actionable feature requests, and triages stale threads for closure. -> **Tool mapping note (v3.8):** Where steps below say `browser_subagent`, modern runtimes should substitute with the `gh` CLI — `gh api graphql` for reading discussions and mutations for posting comments. `WebFetch` is acceptable for read-only HTML scraping when GraphQL is overkill, but prefer `gh` for any write actions. +**Modern tooling (replaces deprecated `browser_subagent` flow):** + +- Reads use `gh api graphql` — one query returns 50 discussions with full bodies, comments, replies, IDs, and `updatedAt`. +- Writes (post comment, create issue, close discussion) use `gh api graphql` mutations or `gh issue create`. +- Pace at ~1s between writes to avoid abuse-detection throttling. +- `WebFetch` is acceptable only for read-only HTML scraping when GraphQL is unavailable — never for write actions. ## Codex Execution Notes -- Treat `// turbo` / `// turbo-all` as instructions to use `multi_tool_use.parallel` for independent reads and GitHub/browser fetches. -- The summary report is a hard stop. Do not post discussion replies or create issues until the user explicitly approves. +- Treat `// turbo` / `// turbo-all` as instructions to use `multi_tool_use.parallel` for independent reads (e.g., parallel `gh issue list` dedup searches across multiple FRs) — never for write actions. +- The summary report is a hard stop. Do not post discussion replies, create issues, or close discussions until the user explicitly approves each phase. +- Use the `apply_patch` tool to write reply bodies to `/tmp/reply-<num>.md` before invoking `gh api graphql -F body=@/tmp/reply-<num>.md` if the body contains tricky shell-escape characters. +- Stop after step 4 (summary), step 6 (issue creation), and step 8 (stale triage). Three explicit consents per run. // turbo-all @@ -22,14 +29,16 @@ This workflow reads all open GitHub Discussions, generates a categorized summary ### 1. Identify the GitHub Repository -- Run: `git -C <project_root> remote get-url origin` to extract the owner/repo -- Parse the owner and repo name from the URL +- Run: `git -C <project_root> remote get-url origin` to extract `owner/repo`. +- Parse owner and repo name from the URL (https or ssh form). -### 2. Fetch All Open Discussions +### 2. Fetch All Open Discussions (single GraphQL query) -- Use `WebFetch` to fetch `https://github.com/<owner>/<repo>/discussions` -- Parse the discussion list to get all discussion titles, IDs, authors, categories, and dates -- For each discussion, fetch the individual page to read the full content and all comments/replies +Single `gh api graphql` call — return everything needed for triage. Critical fields: `id` (node ID, **not** the visible `number`), `number`, `title`, `url`, `createdAt`, `updatedAt`, `author.login`, `category.name`, `body`, `answerChosenAt`, plus nested `comments(first: 50) { totalCount, nodes { id, author.login, body, createdAt, replies(first: 20) { nodes { author.login, body, createdAt } } } }`. + +Persist the raw JSON to `/tmp/discussions-<repo>-<date>.json` so re-runs in the same session avoid a re-fetch. Build an `id → number` map for the post phase — the GraphQL `addDiscussionComment` mutation requires the node ID, not the number. + +Capture **image attachments** present in body or comments (`<img src="...">` or markdown `![...](...)`). Surface their count in the per-discussion summary (e.g., `📷 3 screenshots`) so the user can decide if visual context matters before approving a draft. ### 3. Summarize All Discussions @@ -38,89 +47,228 @@ For each discussion, extract: - **Title** and **#Number** - **Author** (GitHub username) - **Category** (Announcements, General, Ideas, Q&A, Show and tell) -- **Date** created -- **Summary** of the original post (1-2 sentences) -- **Comments count** and key participants -- **Your previous response** (if any) -- **Pending action** — whether a response or follow-up is needed +- **Created** + **Last updated** (ISO date) +- **Summary** of original post (1-2 sentences) +- **Comment count** + **last commenter** + **last comment date** +- **Maintainer involvement**: whether the repo owner already replied, and how many times +- **Pending action** — derived state, see categories below +- **Attachments**: count of screenshots / videos / pastebin links +- **Detected language** of the reporter (for reply-language matching) ### 4. Present Summary Report to User -Present the full summary to the user organized by category, using a table: +Group by **pending action**, not by category, so the human sees triage buckets at a glance: -| # | Category | Title | Author | Date | Status | -| --- | -------- | ----- | ------ | ------ | ----------------- | -| #N | Ideas | Title | @user | Mar 23 | ⚠️ Needs response | -| #N | Q&A | Title | @user | Mar 9 | ✅ Answered | -| #N | General | Title | @user | Mar 19 | ⚠️ Needs response | +| State | Meaning | +| ----------------------- | ---------------------------------------------------------------------------------------------------------------- | +| ⚠️ Needs first response | Zero comments, or all comments are from non-maintainers | +| 🔄 Follow-up pending | Maintainer replied, but reporter or third party added a new comment maintainer has not addressed | +| 🕒 Stale (>15d) | Maintainer was last to comment, no activity for 15+ days — candidate for soft-close or reporter-ping (see step 8)| +| ✅ Answered | Maintainer already replied AND last commenter is the maintainer AND age < 15d | +| 🏁 Resolved | `answerChosenAt` is set | -Highlight: +Within each bucket, present a table: -- **⚠️ Needs response** — No reply from maintainer, or a follow-up comment was left unanswered -- **✅ Answered** — Maintainer already responded -- **🐛 Bug reported** — A bug was mentioned that needs tracking -- **💡 Actionable** — Contains a concrete feature request that could become an issue +| # | Category | Title | Author | Updated | Notes | +| --- | -------- | ------------------ | ------ | ------- | ---------------------- | +| #N | Q&A | short title (60ch) | @user | YYYY-MM-DD | 📷2 · 🐛bug · 💡FR | + +Tag rows with content hints when detected: `🐛bug` (`[BUG]` / `error` / stacktrace in body), `💡FR` (`feature request` / `add support for`), `❓support` (config/usage question), `🙏thanks` (short ack-only follow-up). ### 5. Draft & Post Responses -For each discussion that needs a response, draft a reply following these guidelines: +#### Reply templates by intent -#### Response Style +Pick the template that matches the discussion intent — do NOT use a single generic format. -- **Friendly and professional** — Start with "Hey @username!" -- **Acknowledge the contribution** — Thank the user for their input -- **Be specific** — Reference existing features, settings, or dashboard pages if the feature already exists -- **Provide workarounds** — If the request isn't implemented yet, suggest current alternatives -- **Commit to action** — If the request is valid, state that you'll open an issue or add it to the roadmap -- **Keep it concise** — 3-5 paragraphs max +**A. Bug confirmed** — ack + root cause + tracking + workaround +``` +Hey @user! Confirmed -- {root cause in one sentence}. I traced it to `path/to/file.ts:line`. -#### Posting via Browser +{Why it happens: 2-4 sentences of technical detail} -- Use `browser_subagent` to navigate to each discussion and post the comment -- **IMPORTANT**: When typing text in GitHub comment boxes via the browser, use only plain ASCII characters: - - Use regular hyphens `-` instead of em-dashes - - Use `->` instead of arrow symbols - - Do NOT use emoji Unicode characters (the browser keyboard may fail on them) - - Use `**bold**` and `\`code\`` markdown formatting -- Click the green "Comment" button (or "Reply" for threaded replies) after typing -- Verify the comment was posted by checking the page shows the new comment +I have opened {issue #N} to track the fix. Workaround until it ships: {concrete steps}. Will update here when the patch lands. +``` + +**B. Feature Request** — ack + status + scope + commit +``` +Hey @user! {Status: "Already exists" / "Tracked in #N" / "Reasonable, opening an issue"}. + +{If already exists: pointer to dashboard page or doc} +{If tracked: link to umbrella, summarize order/priority} +{If new: open issue + post link back} + +{Optional: short technical note on feasibility / trade-offs} +``` + +**C. Support / config question** — direct answer + reference + offer to dig deeper +``` +Hey @user! {One-sentence answer}. + +Steps: +1. ... +2. ... +3. ... + +Reference: `docs/<path>.md`. If it still fails after that, paste {specific thing} and I will trace it. +``` + +**D. Thank-you / short follow-up** — 1-2 sentences +``` +Glad it helps, @user! {Concrete next marker — when patch ships / when to expect next update}. +``` + +**E. Stale / closing** — see step 8 + +#### Posting via gh (replaces deprecated browser flow) + +```bash +gh api graphql -f query=' +mutation($id: ID!, $body: String!) { + addDiscussionComment(input: {discussionId: $id, body: $body}) { + comment { id url } + } +}' -f id="$NODE_ID" -f body="$BODY" +``` + +For **threaded replies** (recommended when responding to a specific comment in a long thread), add `replyToId: $parentCommentId` to the input. + +**Output hygiene** (still applies even via API — the comment renders in GitHub UI): + +- ASCII-safe punctuation: regular hyphens `-`, `->` for arrows +- Markdown OK: `**bold**`, fenced code blocks, `[text](url)` links +- No bare error messages with stack traces from internal logs — sanitize +- Match reporter's language (pt-BR reporter → pt-BR reply; ru reporter → ru reply); default to English when uncertain + +**Pacing**: `sleep 1` between mutations. GitHub abuse-detection trips around 10/sec for the same actor. + +**Verification**: capture the returned `comment.url` from each mutation. Failed posts (returncode != 0 or `errors` in response) get logged separately and retried once after a 5s pause. ### 6. Create Issues from Actionable Feature Requests For discussions that contain concrete, actionable feature requests: -1. Ask the user which ones should become issues -2. For each approved request, create a GitHub issue via `browser_subagent`: - - Navigate to `https://github.com/<owner>/<repo>/issues/new` - - **Title**: `<Feature Name> - <Short description>` - - **Body** should include: - - `## Feature Request` header - - `**Source:** Discussion #N by @author` - - `## Problem` — What limitation the user hit - - `## Proposed Solution` — How it could work - - `### Implementation Ideas` — Technical approach - - `### Current Workarounds` — What users can do today - - `## Additional Context` — Links to related issues/discussions - - Add `enhancement` label - - Click "Submit new issue" / "Create" -3. After creation, go back to the original discussion and post a comment linking to the new issue: - - "I've opened Issue #N to track this feature request. Follow along there for updates!" +1. **Deduplicate FIRST** — before drafting, search existing issues: + ```bash + gh issue list --repo $OWNER/$REPO --search "<keywords from FR>" --state open --json number,title,labels + ``` + If a matching issue (or umbrella) already exists, reuse it — never create a duplicate. Post a comment in the discussion linking to the existing issue. + +2. **Ask the user which to create** — even after dedup, the human approves the final list. + +3. **Create the issue** with `gh issue create`: + ```bash + gh issue create --repo $OWNER/$REPO \ + --title "[feature] <short imperative>" \ + --label enhancement \ + --body @/tmp/issue-body.md + ``` + Body template: + ```markdown + ## Feature Request + + **Source:** Discussion #N by @author + + ## Problem + What limitation the user hit (in their words, paraphrased) + + ## Proposed Solution + How it could work + + ### Implementation Ideas + - File paths likely to touch + - Related modules / patterns already in the codebase + + ### Current Workarounds + What users can do today + + ## Additional Context + - Discussion: #N + - Related issues/PRs: #X, #Y + - Upstream references: link to similar implementations in `_references/` if applicable + ``` + +4. **Generate task file in `_ideia/`** when the feature needs deeper investigation before implementation: + ``` + _ideia/<short-kebab-slug>.md + ``` + Contains: problem statement, current OmniRoute state, how upstream (`_references/9router`, `_references/CLIProxyAPI`, etc.) handles it, proposed implementation levels (short/medium/long term), acceptance criteria. + +5. **Link back to discussion** with the real URL: + ``` + Follow-up @reporter — I've opened issue #N to track this. {1-line summary of what the issue covers}. + ``` ### 7. Final Report -Present a final summary to the user: +| Discussion | Action Taken | +| ---------- | ------------------------------------------------------------- | +| #N — Title | Responded (bug confirmed, tracking #M) | +| #N — Title | Responded + created issue #M + task file `_ideia/X.md` | +| #N — Title | Responded (support answered with workaround) | +| #N — Title | Responded to follow-up comment | +| #N — Title | Closed (stale 15+d, no reply from reporter) | +| #N — Title | Ping sent (stale 15+d, will close in 7d if no response) | -| Discussion | Action Taken | -| ---------- | ---------------------------------- | -| #N — Title | Responded with workarounds | -| #N — Title | Responded + created Issue #N | -| #N — Title | Already answered, no action needed | -| #N — Title | Responded to follow-up comment | +Include totals: comments posted, issues created, discussions closed, discussions pinged. Capture median response time for the batch. + +### 8. Stale Discussion Triage (auto-close candidates) + +Identify discussions matching **all** of: + +- `updatedAt > 15 days ago` +- Maintainer already replied at least once +- Last commenter is the maintainer (the ball is on the reporter's side) +- `answerChosenAt` is null (not formally resolved) +- Category in `{Q&A, General}` — skip `Ideas` / `Show and tell` / `Announcements` (those serve as community references and shouldn't be closed) +- `comments.totalCount >= 2` — there was actual conversation, not a drive-by post +- No label named `keep-open` (escape hatch) + +For each candidate, present to the user with a recommended action: + +| Action | When | +| --------------- | ----------------------------------------------------------------------------- | +| **Soft-close** | Default — maintainer answered concretely and reporter went silent | +| **Ping reporter** | Maintainer asked for more info (log dump, screenshot) and never got it | +| **Keep open** | Conversation is mid-debug and closing would lose context — operator override | + +**Soft-close mutation:** +```bash +gh api graphql -f query=' +mutation($id: ID!) { + closeDiscussion(input: {discussionId: $id, reason: RESOLVED}) { + discussion { id closed } + } +}' -f id="$NODE_ID" +``` +Valid `reason` values: `RESOLVED`, `OUTDATED`, `DUPLICATE`. Default to `OUTDATED` for "no response" closures, `RESOLVED` for answered-but-not-confirmed. + +Before closing, post a closing comment: +``` +Closing for inactivity -- feel free to reopen if you still hit this, or open a fresh issue with a current log. Thanks! +``` + +**Ping flow** (alternative): +``` +@reporter -- still happening on the latest version? Otherwise I'll close this in 7 days for inactivity. +``` +Persist the ping in `_cache/discussions-pinged-<date>.json` so the next run knows to close discussions that were pinged 7+ days ago without a reply. ## Notes -- This workflow is **interactive** — always present the summary and wait for user approval before posting responses or creating issues -- If the user says "pode responder" (or similar approval), proceed with posting all drafted responses -- For discussions in non-English languages, respond in the same language as the original post -- Always reference specific dashboard paths, config options, or code files when explaining existing features -- When a discussion reveals a bug, note it separately from feature requests +- This workflow is **interactive** — always present the summary and wait for user approval before posting responses, creating issues, or closing discussions. +- Three explicit consents per run: reply scope (after step 4), issue creation list (in step 6), stale-close list (in step 8). +- For discussions in non-English languages (`pt-BR`, `ru`, `zh`, `es`), respond in the same language as the original post. Default to English when uncertain. +- Always reference specific dashboard paths, config options, doc files, or code locations (`file:line`) when explaining existing features — never wave hands. +- When a discussion reveals a bug, separate it from feature requests in the report. Bugs need a tracking issue + workaround; FRs need scoping. +- Before recommending a workaround that mentions a file/flag/setting, verify it exists in the **current** codebase (the previous turn's memory may be stale). +- Trust-but-verify: after a batch post, spot-check 2-3 random `comment.url` returns to confirm the comments rendered cleanly (no Unicode mojibake, no broken markdown). + +## Anti-patterns to avoid + +- ❌ Posting via `browser_subagent` clicks — slow, flaky, and obsolete since `gh api graphql` mutations exist. +- ❌ N+1 fetches (one per discussion) — use one GraphQL query for all 50. +- ❌ Creating an issue without checking for an existing umbrella / similar one first. +- ❌ Generic "thanks, I'll look into it!" responses — every reply must reference a file, doc, or concrete action. +- ❌ Closing a stale discussion without posting a closing comment first. +- ❌ Skipping the user approval gate ("turbo-all" never bypasses interactive consent for writes). diff --git a/.agents/skills/review-prs/SKILL.md b/.agents/skills/review-prs/SKILL.md index bee9b8ae48..59196d8416 100644 --- a/.agents/skills/review-prs/SKILL.md +++ b/.agents/skills/review-prs/SKILL.md @@ -62,7 +62,7 @@ git branch --show-current # If on main, determine next version and create the release branch VERSION=$(node -p "require('./package.json').version") # Bump patch: e.g. 3.3.11 → 3.3.12 -NEXT=$(node -p "const [a,b,c]=('$VERSION').split('.').map(Number); c>=9?a+'.'+(b+1)+'.0':a+'.'+b+'.'+(c+1)") +NEXT=$(node -p "const [a,b,c]=('$VERSION').split('.').map(Number); c>=999?a+'.'+(b+1)+'.0':a+'.'+b+'.'+(c+1)") git checkout -b release/v$NEXT npm version patch --no-git-tag-version npm install diff --git a/.agents/skills/version-bump/SKILL.md b/.agents/skills/version-bump/SKILL.md index 3d3ddf9f4a..fbe3722437 100644 --- a/.agents/skills/version-bump/SKILL.md +++ b/.agents/skills/version-bump/SKILL.md @@ -15,7 +15,7 @@ Automatically bump the project version, generate CHANGELOG entries from git hist > **VERSION RULE: Always use PATCH bumps (3.x.y → 3.x.y+1)** > NEVER use `npm version minor` or `npm version major`. > Always use: `npm version patch --no-git-tag-version` -> The threshold rule: when `y` reaches 10, bump to `3.(x+1).0` — e.g. `3.4.10` → `3.5.0`. +> The threshold rule: when `y` reaches 1000, bump to `3.(x+1).0` — e.g. `3.4.999` → `3.5.0`. --- diff --git a/.agents/workflows/generate-release-ag.md b/.agents/workflows/generate-release-ag.md index c1ae6a8d5b..61afeb524a 100644 --- a/.agents/workflows/generate-release-ag.md +++ b/.agents/workflows/generate-release-ag.md @@ -1,5 +1,5 @@ --- -description: Create a new release, bump version up to the .10 patch threshold, update changelog, and manage Pull Requests +description: Create a new release, bump version up to the .999 patch threshold, update changelog, and manage Pull Requests --- # Generate Release Workflow @@ -9,9 +9,9 @@ Bump version, finalize CHANGELOG, commit, open a **PR to main** and wait for use > **VERSION RULE: Always use PATCH bumps (3.x.y → 3.x.y+1)** > NEVER use `npm version minor` or `npm version major`. > Always use: `npm version patch --no-git-tag-version` -> The threshold rule: when `y` reaches 10, bump to `3.(x+1).0` — e.g. `3.8.10` → `3.9.0`. +> The threshold rule: when `y` reaches 1000, bump to `3.(x+1).0` — e.g. `3.8.999` → `3.9.0`. -> **🔴 SINGLE BRANCH RULE**: The `release/vX.Y.Z` branch is the **ONLY** development branch for the entire release cycle. ALL work — bug fixes, feature implementations, PR integrations, issue resolutions — MUST be committed directly on this branch. Never create separate `fix/`, `feat/`, or topic branches. When running `/resolve-issues`, `/implement-features`, or `/review-prs`, always work on the current release branch. +> **🔴 INTEGRATION BRANCH RULE**: The `release/vX.Y.Z` branch is the **integration target** for the entire release cycle. Bug fixes and feature implementations land here **via per-issue PRs from short-lived `fix/<ISSUE>-<short>` or `feat/<ISSUE>-<short>` worktrees** (see `/resolve-issues`, `/implement-features`). Contributor PRs from `/review-prs` likewise merge into this branch. The release branch is then merged to `main` via a single release PR at the end of the cycle. --- diff --git a/.agents/workflows/implement-features-ag.md b/.agents/workflows/implement-features-ag.md index afb8b3ed93..8ba6d84a94 100644 --- a/.agents/workflows/implement-features-ag.md +++ b/.agents/workflows/implement-features-ag.md @@ -17,18 +17,26 @@ _ideia/ │ │ └── 1015-warp-terminal-mitm.md │ ├── 1046-native-playground.md # ✅ Ready — researched and planned │ └── 1046-native-playground.requirements.md -├── defer/ # ⏭️ Good ideas deferred for future cycles (issues CLOSED) +├── implemented/ # 🚧 Implemented but PR not yet merged to main (transient) +│ └── 1046-native-playground.md +├── defer/ # ⏭️ Good ideas deferred for future cycles (issues CLOSED after Phase 3 approval) │ └── 1041-smart-auto-combos.md -└── notfit/ # ❌ Out of scope / already exists (issues CLOSED) +└── notfit/ # ❌ Out of scope / already exists (issues CLOSED after Phase 3 approval) └── 945-telegram-integration.md _tasks/features-vX.Y.Z/ # Implementation plans (per-release) └── 1046-native-playground.plan.md ``` -> **LIFECYCLE RULE:** `viable/` files are **DELETED** once the feature is implemented — they are not moved. Only unimplemented features live in `viable/` (or `viable/need_details/`). Files in `defer/` and `notfit/` remain as permanent reference. +> **LIFECYCLE RULE:** +> - `viable/` files are **MOVED** to `implemented/` once code lands on the release branch. +> - `implemented/` files are **DELETED** only after the release PR is merged to `main`. +> - This preserves recovery context if implementation fails partially (build green but i18n missing, etc). +> - Files in `defer/` and `notfit/` remain as permanent reference. -> **BRANCH RULE**: All implementation work MUST happen on the current `release/vX.Y.Z` branch. Never create separate `feat/` branches. If no release branch exists yet, create one first using `/generate-release` Phase 1 steps 1–5. +> **BRANCH RULE**: All implementation work MUST happen on the current `release/vX.Y.Z` branch. Never create separate `feat/` branches. If no release branch exists yet, delegate creation to `/generate-release` (see Phase 1.2) — do NOT reimplement bump logic here. + +> **LANGUAGE RULE** (per `feedback_reply_language` memory): GitHub comments MUST match the language of the original issue body. Detect language by sampling the issue body + first 2 comments. Default to English when uncertain. All comment templates below are in English — translate to the detected language before posting. Internal docs, plan files, and idea files stay in English regardless. --- @@ -42,23 +50,18 @@ _tasks/features-vX.Y.Z/ # Implementation plans (per-release) ### 1.2 Ensure Release Branch Exists -// turbo - Before doing any work, ensure you are on the current release branch: ```bash -# Check current branch git branch --show-current - -# If on main, determine next version and create the release branch -VERSION=$(node -p "require('./package.json').version") -NEXT=$(node -p "const [a,b,c]=('$VERSION').split('.').map(Number); c>=9?a+'.'+(b+1)+'.0':a+'.'+b+'.'+(c+1)") -git checkout -b release/v$NEXT -npm version patch --no-git-tag-version -npm install ``` -If already on a `release/vX.Y.Z` branch, continue working there. +**Decision tree:** + +- If already on a `release/vX.Y.Z` branch → continue working there. +- If on `main` or any other branch → **delegate to `/generate-release`** by invoking its Phase 1 (steps 1–5: detect current version, bump, create branch, install). Do NOT reimplement the bump formula here — `/generate-release` owns the canonical version policy (patch bumps allowed up to `.999`; minor bump only when patch reaches `999`). + +> **Why delegate?** Duplicating the bump formula caused divergence in the past. `/generate-release` is the single source of truth for version arithmetic and now allows patches up to `.999` before bumping minor. ### 1.3 Fetch ALL Open Feature Requests @@ -77,6 +80,7 @@ gh issue list --repo <owner>/<repo> --state open --limit 500 --json number,title ``` - Merge both lists, deduplicate. Count and confirm the total. +- If the count hits the `--limit 500` ceiling, raise the limit and re-run — never proceed with a truncated set. **Step 2 — Fetch full metadata for each Issue** (one call per issue): @@ -86,7 +90,8 @@ gh issue view <NUMBER> --repo <owner>/<repo> --json number,title,labels,body,com - Read the **entire body** — including description, use cases, screenshots, mockups, and any embedded images. - Read **ALL comments** — community discussion, agreements, restrictions, owner responses, and linked PRs. -- **Images**: If the body or comments contain image URLs (`![...](...)` or `https://...png/jpg/gif`), note them — they may contain UI mockups, wireframes, or architecture diagrams that are essential to understanding the request. +- **Images**: If the body or comments contain image URLs (`![...](...)` or `https://...png/jpg/gif`), **download and analyze them with the Read tool** (Claude can read PNG/JPG/GIF directly). Mockups and wireframes are often the most informative artifact — do NOT just "note" them, actually inspect their content and incorporate findings into the refined description. +- **Detect issue language** from body + first 2 comments and record it in the idea file front-matter (`reply_lang: pt-BR | en | es | ...`). This will drive comment translation in Phases 2.5 and 5. - You may batch these into parallel calls (up to 4 at a time). - Sort by oldest first (FIFO). @@ -100,6 +105,10 @@ Example: `1046-native-playground.md`, `1041-smart-auto-combos.md` #### 1.4a — If the idea file does NOT exist yet, create it: ```markdown +--- +reply_lang: <detected-lang, e.g. pt-BR | en | es> +--- + # Feature: <Title from Issue> > GitHub Issue: #<NUMBER> — opened by @<author> on <date> @@ -125,6 +134,10 @@ Example: `1046-native-playground.md`, `1041-smart-auto-combos.md` - <agreements reached> - <objections raised> +## 🖼️ Mockup / Image Analysis + +<For each image embedded in the issue, summarize what it depicts: UI layout, data flow, architecture diagram, etc. Cite source URL.> + ## 🎯 Refined Feature Description <YOUR interpretation and enrichment of the feature request. Expand on what was asked, fill in logical gaps, provide concrete examples of how it would work. This section should be MORE detailed and clearer than the original request.> @@ -158,6 +171,7 @@ Example: `1046-native-playground.md`, `1041-smart-auto-combos.md` - Append new comments from the issue to the **Community Discussion** section. - Update the **Refined Feature Description** if new information changes the understanding. - Add any new **Related Ideas** cross-references found. +- Re-detect `reply_lang` only if the issue language clearly changed (uncommon). - **Do NOT overwrite** existing content — append and enrich it. ### 1.5 Cross-Reference & Deduplication @@ -168,11 +182,29 @@ After processing all issues: - If two features are substantially the same, add `🔗 Related Ideas` cross-references to both. - If one is a strict subset of another, note it in the smaller file: `> ℹ️ This feature is a subset of #<OTHER_NUMBER>. Consider implementing together.` +### 1.6 Detect In-Flight Work (avoid duplicate effort) + +For each issue number, check whether an open PR or branch already targets it: + +```bash +# Open PRs that link the issue +gh pr list --repo <owner>/<repo> --state open --search "linked:#<NUMBER>" --json number,title,headRefName + +# Local branches that mention the issue number +git branch -a | grep -E "(^|/)(feat|fix|refactor)/.*-?<NUMBER>(-|$)" || true +``` + +If a PR or branch already exists: + +- Mark the idea file with `> ⚠️ In-flight: PR #<PR_NUMBER> / branch <name>` near the top. +- **Skip Phase 2 research and Phase 4 planning** for this feature — the implementation is already in motion. +- In the Phase 3 report, list it under a separate "🚧 Already in progress" bucket; do NOT count it as VIABLE for implementation. + --- ## Phase 2 — Research: Find Solutions & Build Requirements -For each cataloged idea that is **viable** (aligns with the project's goals): +For each cataloged idea that is **viable** (aligns with the project's goals) AND not already in flight (per 1.6): ### 2.1 Viability Pre-Check @@ -193,10 +225,17 @@ Before investing in research, quickly assess: | ⏭️ **DEFER** | Good idea, too complex for this cycle | Catalog only, skip research | | ❌ **NOT FIT** | Doesn't fit the project | Explain why | | 🔁 **ALREADY EXISTS** | Feature already implemented | Point to existing feature | +| 🚧 **IN FLIGHT** | PR/branch already exists (from 1.6) | Skip — track only | ### 2.2 Internet Research (for VIABLE features) -For each viable feature, perform systematic research: +For each viable feature, perform systematic research with an **early-stopping criterion**: + +> **Stop as soon as EITHER condition is met:** +> - 3 reference implementations show a consistent pattern, OR +> - 1 high-quality repo (≥1k stars, updated within the last 12 months) already solves the problem cleanly. +> +> Cap at 10 repos total. Do NOT exhaustively browse — depth over breadth. **Step 1 — Web search for similar implementations:** @@ -213,8 +252,8 @@ WebSearch("site:github.com <feature keyword> <tech stack> stars:>100") WebSearch("github <feature keyword> implementation recently updated 2026") ``` -- Find **up to 10 relevant repositories**, sorted by most recently updated. -- For each repository: +- Sort by most recently updated. +- For each repository (until stop criterion hit): - Note the repo URL, star count, last commit date - Read its README and relevant source files via `WebFetch` - Extract the architectural approach, patterns used, and key code snippets @@ -307,7 +346,9 @@ For each researched feature, create a requirements file alongside its idea file: --- -## Phase 2.5 — Organize & Respond: Sort Files and Post GitHub Comments +## Phase 2.5 — Organize: Sort Files into Category Directories + +> **⚠️ This phase only moves files. It does NOT post comments or close issues.** All GitHub-visible actions are deferred to Phase 3.2 (after human approval). ### 2.5.1 Create Directory Structure @@ -316,13 +357,14 @@ For each researched feature, create a requirements file alongside its idea file: ```bash mkdir -p <project_root>/_ideia/viable mkdir -p <project_root>/_ideia/viable/need_details +mkdir -p <project_root>/_ideia/implemented mkdir -p <project_root>/_ideia/defer mkdir -p <project_root>/_ideia/notfit ``` ### 2.5.2 Move Idea Files to Category Subdirectories -After classification, move EVERY idea file to its correct subdirectory: +After classification, move EVERY idea file to its correct subdirectory (still local-only — no GitHub side-effects): ```bash # ✅ VIABLE — move idea + requirements files @@ -337,20 +379,73 @@ mv _ideia/<NUMBER>-*.md _ideia/defer/ # ❌ NOT FIT & 🔁 ALREADY EXISTS — move idea files only mv _ideia/<NUMBER>-*.md _ideia/notfit/ + +# 🚧 IN FLIGHT — leave in _ideia/ root with a top-of-file banner; do NOT touch the PR/branch ``` -No files should remain in `_ideia/` root after this step (except subdirectories). +No idea files should remain in `_ideia/` root after this step except `🚧 IN FLIGHT` entries. -### 2.5.3 Post GitHub Comments by Category +--- -**Each category has a specific comment template and action:** +## Phase 3 — Report: Present Findings & Get Human Approval + +### 3.1 🛑 MANDATORY STOP — Present Consolidated Report + +After completing Phase 1, Phase 2, and Phase 2.5, **STOP and present the following report** in the chat. **No comments have been posted to GitHub yet** — that happens in 3.2 after approval. + +Present a structured report containing: + +#### 3.1a — Feature Summary Table + +| # | Issue | Title | Verdict | Local Location | Planned GitHub Action | +| --- | ----- | ----- | --------------- | ----------------------------- | -------------------------------- | +| 1 | #N | Title | ✅ VIABLE | `_ideia/viable/` | Comment + keep OPEN | +| 2 | #N | Title | ⏭️ DEFER | `_ideia/defer/` | Comment + CLOSE | +| 3 | #N | Title | ❌ NOT FIT | `_ideia/notfit/` | Comment + CLOSE | +| 4 | #N | Title | 🔁 EXISTS | `_ideia/notfit/` | Comment with location + CLOSE | +| 5 | #N | Title | ❓ NEEDS DETAIL | `_ideia/viable/need_details/` | Comment with questions + OPEN | +| 6 | #N | Title | 🚧 IN FLIGHT | `_ideia/` (banner) | None — PR #M already handles it | + +#### 3.1b — Viable Features Detail + +For each VIABLE feature, provide a brief paragraph: + +- What was found during research (with stop reason: "3-pattern consistency" or "dominant repo") +- The proposed approach +- Key risks or unknowns +- Which reference repositories were most useful + +#### 3.1c — Issues Requiring Author Feedback + +For features marked ❓ NEEDS DETAIL, list: + +- What specific information is missing +- What examples or repository references would help +- Detected `reply_lang` for the question post + +#### 3.1d — Ask for User Confirmation + +End the report with: + +> **Ready to proceed?** +> +> Approving will (a) post comments on GitHub in the detected language of each issue and (b) close DEFER / NOT FIT / EXISTS issues. VIABLE and NEEDS DETAIL stay open. +> +> - Reply **"sim"** / **"yes"** to post all comments AND generate implementation plans for all VIABLE features. +> - Reply **"only comments"** to post comments without generating plans yet. +> - Reply with specific issue numbers to scope the action. +> - Reply **"não"** / **"no"** to stop without touching GitHub. + +### 3.2 Post GitHub Comments & Close Issues (only after approval) + +> **⚠️ Do NOT execute this step without explicit user approval from 3.1d.** + +For each issue, translate the appropriate template below into the `reply_lang` recorded in its idea file front-matter, then post. The English templates are reference only — never post the English version verbatim to a non-English issue. --- #### For 🔁 ALREADY EXISTS — Comment + CLOSE issue -// turbo - The feature already exists in the system. Explain WHERE it is and HOW to use it. ```markdown @@ -372,15 +467,13 @@ Closing this as the feature is already available. 🎉 ``` ```bash -gh issue close <NUMBER> --repo <owner>/<repo> --comment "<comment above>" +gh issue close <NUMBER> --repo <owner>/<repo> --comment "<translated comment>" ``` --- #### For ⏭️ DEFER — Comment + CLOSE issue -// turbo - Thank the user, explain the idea was cataloged, and that we'll study it before implementing. ```markdown @@ -394,21 +487,20 @@ Due to the **significant architectural impact** of this feature, we'll need to c - Your idea is saved in our internal feature backlog - We'll conduct architecture studies when this area is prioritized -- We'll notify you here when development begins -Thank you for contributing to OmniRoute's roadmap! Your input helps shape the product. 🚀 +If you want to track progress, please **subscribe to the repository releases** — every implemented feature is announced in the CHANGELOG. + +Thank you for contributing to OmniRoute's roadmap! 🚀 ``` ```bash -gh issue close <NUMBER> --repo <owner>/<repo> --comment "<comment above>" +gh issue close <NUMBER> --repo <owner>/<repo> --comment "<translated comment>" ``` --- #### For ❌ NOT FIT — Comment + CLOSE issue -// turbo - Politely explain why the feature doesn't fit the project scope. ```markdown @@ -424,15 +516,13 @@ We appreciate you thinking of ways to improve OmniRoute! If you'd like to discus ``` ```bash -gh issue close <NUMBER> --repo <owner>/<repo> --comment "<comment above>" +gh issue close <NUMBER> --repo <owner>/<repo> --comment "<translated comment>" ``` --- #### For ❓ NEEDS DETAIL — Comment (keep OPEN) -// turbo - Ask for the specific missing details needed. ```markdown @@ -453,9 +543,7 @@ Looking forward to your response! 🚀 #### For ✅ VIABLE — Comment (keep OPEN) -// turbo - -Thank the user, confirm we've cataloged their idea, and explain it may be implemented in future versions. +Thank the user, confirm we've cataloged their idea, and explain that progress is tracked in releases. ```markdown Hi @<author>! Thanks for the great feature suggestion! 🙏 @@ -464,58 +552,12 @@ We've analyzed your request and it aligns well with OmniRoute's roadmap. We've * **Status:** 📋 Cataloged for future implementation -This feature may be included in upcoming releases. We'll **respond to this issue and tag you** as soon as implementation begins so you can test it. +This issue will be **closed automatically by the merge commit** when the feature ships. To follow along, you can subscribe to repository releases or watch this issue. Thank you for helping improve OmniRoute! 🚀 ``` -**⚠️ Do NOT close viable issues — they remain OPEN for tracking.** - ---- - -## Phase 3 — Report: Present Findings to User - -### 3.1 🛑 MANDATORY STOP — Present Consolidated Report - -After completing Phase 1, Phase 2, and Phase 2.5, **STOP and present the following report** in the chat. Do NOT proceed to implementation. - -Present a structured report containing: - -#### 3.1a — Feature Summary Table - -| # | Issue | Title | Verdict | Location | Action | -| --- | ----- | ----- | --------------- | ----------------------------- | ----------------------------- | -| 1 | #N | Title | ✅ VIABLE | `_ideia/viable/` | Issue OPEN, comment posted | -| 2 | #N | Title | ⏭️ DEFER | `_ideia/defer/` | Issue CLOSED with explanation | -| 3 | #N | Title | ❌ NOT FIT | `_ideia/notfit/` | Issue CLOSED with explanation | -| 4 | #N | Title | 🔁 EXISTS | `_ideia/notfit/` | Issue CLOSED with guidance | -| 5 | #N | Title | ❓ NEEDS DETAIL | `_ideia/viable/need_details/` | Issue OPEN, questions posted | - -#### 3.1b — Viable Features Detail - -For each VIABLE feature, provide a brief paragraph: - -- What was found during research -- The proposed approach -- Key risks or unknowns -- Which reference repositories were most useful - -#### 3.1c — Issues Requiring Author Feedback - -For features marked ❓ NEEDS DETAIL, list: - -- What specific information is missing -- What examples or repository references would help - -#### 3.1d — Ask for User Confirmation - -End the report with: - -> **Ready to proceed with implementation?** -> -> - Reply **"sim"** or **"yes"** to generate full implementation plans for all VIABLE features. -> - Reply with specific issue numbers to select only certain features. -> - Reply **"não"** or **"no"** to stop here. +**⚠️ Do NOT close viable issues — they remain OPEN until the implementation PR closes them via commit message.** --- @@ -523,13 +565,24 @@ End the report with: > **⚠️ Do NOT enter this phase without explicit user approval from Phase 3.** -### 4.1 Create Task Directory +### 4.1 Pre-Plan Context Load (mandatory) + +Before writing ANY plan, read: + +1. `docs/architecture/REPOSITORY_MAP.md` — to know which directory owns what. +2. `docs/architecture/CODEBASE_DOCUMENTATION.md` — for the engineering reference. +3. The matching "Adding a New X" scenario from `CLAUDE.md` (provider, API route, DB module, MCP tool, A2A skill, cloud agent, embedded service, guardrail, eval, skill, webhook event). +4. Any docs linked from the requirements file's "External References" section. + +This ensures plans cite real paths and follow the established add-a-X recipe, instead of inventing structure. + +### 4.2 Create Task Directory ```bash mkdir -p <project_root>/_tasks/features-vX.Y.Z/ ``` -### 4.2 Generate One Implementation Plan Per Feature +### 4.3 Generate One Implementation Plan Per Feature For each VIABLE feature approved by the user, create: @@ -542,6 +595,7 @@ For each VIABLE feature approved by the user, create: > Idea: [\_ideia/viable/<NUMBER>-title.md](../../_ideia/viable/<NUMBER>-title.md) > Requirements: [\_ideia/viable/<NUMBER>-title.requirements.md](../../_ideia/viable/<NUMBER>-title.requirements.md) > Branch: `release/vX.Y.Z` +> Matching CLAUDE.md recipe: <e.g. "Adding a New Provider"> ## Overview @@ -550,8 +604,8 @@ For each VIABLE feature approved by the user, create: ## Pre-Implementation Checklist - [ ] Read all related source files listed below -- [ ] Confirm no conflicts with in-flight PRs -- [ ] Verify database migration numbering +- [ ] Confirm no conflicts with in-flight PRs (re-run Phase 1.6 lookup) +- [ ] Verify database migration numbering (next free integer in `src/lib/db/migrations/`) ## Implementation Steps @@ -568,7 +622,7 @@ For each VIABLE feature approved by the user, create: ... -### Step N: Tests +### Step N: Tests (MANDATORY per CLAUDE.md hard rule #8) **New test files:** @@ -578,6 +632,7 @@ For each VIABLE feature approved by the user, create: - [ ] <test case 1> - [ ] <test case 2> +- [ ] Coverage check: confirm overall coverage stays ≥75% statements/lines/functions, ≥70% branches (hard rule #9) ### Step N+1: i18n @@ -587,36 +642,41 @@ For each VIABLE feature approved by the user, create: ### Step N+2: Documentation -- [ ] Update CHANGELOG.md +- [ ] Update CHANGELOG.md (current release section) - [ ] Update relevant docs/ files +- [ ] If touching error responses, follow `docs/security/ERROR_SANITIZATION.md` +- [ ] If touching upstream credentials, follow `docs/security/PUBLIC_CREDS.md` -## Verification Plan +## Verification Plan (Trust-but-Verify — mandatory before declaring done) -1. Run `npm run build` — must pass -2. Run `npm test` — all tests must pass -3. Run `npm run lint` — no new errors -4. <Manual verification steps> +1. `git status` + `git diff --stat` — review every changed file; flag anything outside the plan's declared scope +2. `npm run lint` — 0 new errors +3. `npm run typecheck:core` — clean +4. `npm run typecheck:noimplicit:core` — clean +5. `npm run check:cycles` — no new circular deps +6. `npm run build` — must pass +7. `npm run test:coverage` — coverage gate respected +8. `npm run check-docs-sync` (via pre-commit hook) — passes +9. Manual UI verification if the feature touches frontend (start dev server, exercise golden path + 1 edge case) ## Commit Plan -``` +``` feat: <description> (#<NUMBER>) - +``` ``` -``` - -### 4.3 Present Plans for Final Approval +### 4.4 Present Plans for Final Approval Present a summary of all generated plans: > **Implementation plans generated:** > -> | # | Feature | Plan File | Steps | Effort | -> | --- | ------- | ---------------------------------------- | ------- | ------ | -> | 1 | <title> | `_tasks/features-vX.Y.Z/N-title.plan.md` | N steps | Medium | +> | # | Feature | Plan File | Steps | Effort | CLAUDE.md recipe | +> | --- | ------- | ---------------------------------------- | ------- | ------ | ---------------------- | +> | 1 | <title> | `_tasks/features-vX.Y.Z/N-title.plan.md` | N steps | Medium | Adding a New Provider | > -> Reply **"sim"** or **"yes"** to begin implementation of all features. +> Reply **"sim"** / **"yes"** to begin implementation of all features. > Reply with specific issue numbers to implement only certain ones. --- @@ -630,17 +690,62 @@ Present a summary of all generated plans: For each approved plan, execute it step by step: 1. **Follow the plan** — implement exactly as specified in the `.plan.md` file -2. **Build** — Run `npm run build` after each feature to verify compilation -3. **Test** — Run `npm test` to ensure no regressions -4. **Commit** — Commit with: `feat: <description> (#<NUMBER>)` -5. **Update the plan** — Mark completed steps with `[x]` in the plan file -6. **Continue** — Move to the next feature (do NOT switch branches) +2. **Mark progress** — flip checkboxes to `[x]` in the plan as each step completes -### 5.2 Respond to Authors (Update Viable Issues) +### 5.2 Trust-but-Verify Audit (mandatory before commit) -For each implemented feature, **close the issue with a final comment**: +> Aligned with `~/.claude/CLAUDE.md` global rule: never trust a subagent's summary alone. -````markdown +Run the full audit checklist from the plan's "Verification Plan" section AND inspect the diff yourself: + +```bash +git status +git diff --stat +git diff # full diff, scan for out-of-scope changes +npm run lint +npm run typecheck:core +npm run typecheck:noimplicit:core +npm run check:cycles +npm run build +npm run test:coverage +``` + +**Block-on-failure checklist:** + +- [ ] No files changed outside the plan's declared scope (or scope expansion explicitly justified) +- [ ] No deleted symbols/routes/files without a documented replacement (grep to confirm) +- [ ] No weakened or removed test assertions (only additions or alignments with real behavior) +- [ ] Coverage gate green (75/75/75/70) +- [ ] All commands above exit 0 +- [ ] If UI was touched: manual smoke test passed and noted + +If any item fails, **fix root cause** before committing. Do NOT bypass with `--no-verify` (hard rule #10). + +### 5.3 Commit (one feature, one commit) + +```bash +git add <only files in the plan> +git commit -m "feat: <description> (#<NUMBER>)" +``` + +> **No `Co-Authored-By` trailers** (hard rule #16). Commits go solely under `diegosouzapw`. + +Then move (do NOT delete yet) the idea file to `_ideia/implemented/`: + +```bash +mv _ideia/viable/<NUMBER>-<title>.md _ideia/implemented/ +mv _ideia/viable/<NUMBER>-<title>.requirements.md _ideia/implemented/ 2>/dev/null || true +``` + +> **Why move, not delete?** If the release PR is reverted or rebased, we still have the context. The file is deleted only after the PR merges to `main` (see 5.6). + +Continue to the next feature on the same branch — do NOT switch branches between features. + +### 5.4 Respond to Authors + +For each implemented feature, post a final close-comment **translated into the issue's `reply_lang`**: + +```markdown ✅ **Implemented in `release/vX.Y.Z`!** Hi @<author>! Great news — your feature request has been implemented! 🎉 @@ -649,58 +754,59 @@ Hi @<author>! Great news — your feature request has been implemented! 🎉 - <bullet list of what was built> -**How to try it:** +**How to try it (after the release PR merges):** ```bash -git fetch origin && git checkout release/vX.Y.Z +git fetch origin && git checkout main && git pull npm install && npm run dev ``` -```` This will be included in the upcoming **vX.Y.Z** release. Feel free to reopen if you spot any issues! 🚀 - -```` - -```bash -gh issue close <NUMBER> --repo <owner>/<repo> --comment "<comment above>" -```` - -Then **DELETE the idea file** — it has served its purpose: - -```bash -# ✅ Implemented files are DELETED (not moved) -rm _ideia/viable/<NUMBER>-<title>.md -rm _ideia/viable/<NUMBER>-<title>.requirements.md # if exists ``` -> **Why delete?** `viable/` only holds features that still NEED to be done. Once implemented, the commit history and CHANGELOG are the source of truth. Keeping the file would be confusing. +```bash +gh issue close <NUMBER> --repo <owner>/<repo> --comment "<translated comment>" +``` -### 5.3 Finalize & Push +### 5.5 Finalize the Release Branch After implementing all approved features: 1. **Update CHANGELOG.md** on the release branch with all new feature entries -2. Push the release branch: `git push origin release/vX.Y.Z` -3. Run `/generate-release` workflow Phase 1 steps 7–10 (tests → commit → push → open PR to main → wait for user) +2. Push: `git push origin release/vX.Y.Z` +3. Hand off to `/generate-release` for the "Tests → Commit → Push → PR to main" stage. Refer to it **by stage name**, not step number, so this command does not break if `/generate-release` renumbers steps. -### 5.4 Final Summary Report +### 5.6 Post-Merge Cleanup (only after release PR merges to main) + +Once the release PR is merged: + +```bash +# Now safe to delete — commit history + CHANGELOG are the source of truth +rm _ideia/implemented/<NUMBER>-*.md +``` + +> If running this command before the merge: STOP at 5.5 and skip 5.6. Re-enter the workflow later just for the cleanup. + +### 5.7 Final Summary Report Present a final summary report to the user: | Issue | Title | Verdict | Action | Commit | | ----- | ----- | --------------- | -------------------------------------------------- | --------- | -| #N | Title | ✅ Implemented | Issue closed, idea file deleted | `abc1234` | +| #N | Title | ✅ Implemented | Issue closed, idea file in `_ideia/implemented/` | `abc1234` | | #N | Title | ⏭️ Deferred | Issue closed + saved in `_ideia/defer/` | — | | #N | Title | ❌ Not Fit | Issue closed + saved in `_ideia/notfit/` | — | | #N | Title | 🔁 Exists | Issue closed + saved in `_ideia/notfit/` | — | | #N | Title | ❓ Needs Detail | Issue OPEN, moved to `_ideia/viable/need_details/` | — | +| #N | Title | 🚧 In Flight | Untouched — tracked by PR #M | — | Include: - Total features harvested - Total ideas cataloged (`viable/need_details/` + `defer/` + `notfit/`) -- Total features implemented (idea files deleted, issues closed) +- Total features implemented (idea files in `_ideia/implemented/`, awaiting post-merge cleanup) - Total features deferred - Total issues closed -- Total issues left open (needs detail only — viable are closed after implementation) -- Test results (pass/fail count) +- Total issues left open (NEEDS DETAIL + VIABLE-pending-implementation + IN FLIGHT) +- Audit results: lint / typecheck / cycles / build / coverage (pass-count per phase) +- Languages used in posted comments (e.g. "3× pt-BR, 5× en, 1× es") diff --git a/.agents/workflows/resolve-issues-ag.md b/.agents/workflows/resolve-issues-ag.md index 01f8f68879..02957b0c09 100644 --- a/.agents/workflows/resolve-issues-ag.md +++ b/.agents/workflows/resolve-issues-ag.md @@ -1,17 +1,19 @@ --- -description: Fetch all open GitHub issues, analyze bugs, resolve what's possible, triage the rest, wait for user validation, then commit and release +description: Fetch all open GitHub issues, analyze bugs, resolve up to 30 per batch via per-issue worktrees + PRs into the release branch, triage the rest, wait for user validation --- # /resolve-issues — Automated Issue Resolution Workflow ## Overview -This workflow fetches all open issues from the project's GitHub repository, classifies them, analyzes bugs, proposes a resolution plan, waits for user validation, and ONLY THEN implements the fixes, commits, and closes the issues on the current release branch (`release/vX.Y.Z`). It does NOT merge or release automatically — the release branch is later merged via PR to main. +This workflow fetches all open issues from the project's GitHub repository, classifies them, analyzes bugs, proposes a resolution plan, waits for user validation, and ONLY THEN implements fixes. The current `release/vX.Y.Z` branch is the integration target — each individual fix is implemented on its own short-lived `fix/<issue>-<short>` branch inside its own git worktree, merged into the release branch via PR, then the worktree and local branch are deleted. The release branch is later merged to `main` via `/generate-release`. -> **BRANCH RULE**: All work MUST happen on the current `release/vX.Y.Z` branch. Never create separate `fix/` branches. If no release branch exists yet, create one first using `/generate-release` Phase 1 steps 1–5. +> **BRANCH RULE**: The current `release/vX.Y.Z` branch is the integration target. Each fix MUST live on its own `fix/<ISSUE>-<short>` branch cut from the release branch, inside its own worktree under `.worktrees/`. After the per-issue PR is merged into the release branch, the worktree and local branch are deleted. Never commit fixes directly to the release branch. If no release branch exists yet, create one first using `/generate-release` Phase 1 steps 1–5. > **⛔ PR PROHIBITION**: If a fix is associated with a contributor's PR, you MUST merge their PR — NEVER close it and re-implement the fix yourself. See `/review-prs` workflow for the full policy. The `gh pr close` command is FORBIDDEN unless the repository owner explicitly requests it. +> **🌐 REPLY LANGUAGE**: All comments posted to issues (close messages, RESPOND comments, PR descriptions visible to the reporter) MUST match the reporter's language. When in doubt, default to **English**. The reporter's language is detected from the issue body and prior comments by that author. + ## Steps ### 1. Identify the GitHub Repository @@ -25,40 +27,45 @@ This workflow fetches all open issues from the project's GitHub repository, clas // turbo -Before doing any work, ensure you are on the current release branch: +Before doing any work, ensure a `release/vX.Y.Z` branch exists. If you are currently on `main`, create one: ```bash -# Check current branch git branch --show-current # If on main, determine next version and create the release branch VERSION=$(node -p "require('./package.json').version") -NEXT=$(node -p "const [a,b,c]=('$VERSION').split('.').map(Number); c>=9?a+'.'+(b+1)+'.0':a+'.'+b+'.'+(c+1)") +NEXT=$(node -p "const [a,b,c]=('$VERSION').split('.').map(Number); c>=999?a+'.'+(b+1)+'.0':a+'.'+b+'.'+(c+1)") git checkout -b release/v$NEXT npm version patch --no-git-tag-version npm install ``` +> Threshold: patches climb to `.999` before rolling. Example: `3.4.999` → `3.5.0`. + If already on a `release/vX.Y.Z` branch, continue working there. -### 3. Fetch All Open Issues +### 3. Fetch All Open Issues (cap 30 per batch) // turbo-all -**⚠️ CRITICAL**: The JSON output of `gh issue list` can be truncated by the tool, silently hiding issues. You MUST use the two-step approach below to guarantee **all** issues are fetched. +**⚠️ CRITICAL**: The JSON output of `gh issue list` can be truncated by the tool, silently hiding issues. Use the two-step approach below. **Step 3a — Get Issue numbers only** (small output, never truncated): - Run: `gh issue list --repo <owner>/<repo> --state open --limit 500 --json number --jq '.[].number'` -- This outputs one issue number per line. Count them and confirm total. +- Count them and remember the total. -**Step 3b — Fetch full metadata for each Issue** (one call per issue): +**Step 3b — Fetch full metadata for each Issue** (parallel, validated against 3a): - For each issue number from step 3a, run: - `gh issue view <NUMBER> --repo <owner>/<repo> --json number,title,labels,body,comments,createdAt,author` -- You may batch these into parallel calls (up to 4 at a time). + `gh issue view <NUMBER> --repo <owner>/<repo> --json number,title,labels,body,comments,createdAt,author,url` +- Batch in parallel (8–12 concurrent calls). After completion, assert `fetched_count == count_from_3a`; if mismatch, retry the missing IDs. - Sort by oldest first (FIFO). +**Step 3c — Cap at 30 per run**: + +- If more than 30 open issues qualify as bugs after step 4, ask the user which subset of up to 30 to handle now. The remainder is deferred to the next run. + ### 4. Classify Each Issue For each issue, determine its type: @@ -68,99 +75,187 @@ For each issue, determine its type: - **Question** — Has `question` label, or is asking "how to" something - **Other** — Anything else -Focus ONLY on **Bugs** for resolution. Feature requests and questions should be skipped with a note in the final report. +Focus ONLY on **Bugs** for resolution. Feature requests and questions are skipped with a note in the final report. + +#### 4.5. PR-Linked Check (mandatory) + +For every bug, query linked PRs: + +```bash +gh issue view <NUMBER> --repo <owner>/<repo> --json closedByPullRequestsReferences,body +``` + +If the issue is referenced by an **open** contributor PR (or the body links to one), do NOT plan a self-implemented fix. Mark the issue as `🤝 PR-LINKED — redirect to /review-prs` in the report and stop deeper analysis for it. **NEVER close the contributor PR.** ### 5. Deep-Read Each Bug Issue (One-by-One Analysis) -**IMPORTANT**: Read each bug issue thoroughly, one at a time, before moving to the next. This is NOT a batch process — each issue needs focused attention. +Read each bug issue thoroughly, one at a time. Each issue gets focused attention. #### 5a. Understand the Problem -For each bug issue, perform the full analysis: - -1. **Read the entire body** — including Description, Steps to Reproduce, Expected/Actual Behavior, Error Logs, and Screenshots -2. **Read ALL comments** — including bot triage comments (Kilo, etc.) and owner/community responses. Pay attention to: - - Whether someone already responded with a fix - - Whether a community member confirmed the issue is resolved - - Whether the issue was marked as duplicate by a bot. **WARNING: DO NOT blindly trust bot duplicate labels (e.g., kilo-duplicate). Bots make mistakes. You MUST read the full conversation and do your own independent analysis to determine if it is truly a duplicate or a distinct bug.** -3. **Identify the claimed error** — extract the exact error message, status code, and provider/model involved +1. **Read the entire body** — Description, Steps to Reproduce, Expected/Actual Behavior, Error Logs, Screenshots +2. **Read ALL comments** — bot triage (Kilo, etc.) and owner/community responses. Look for: + - Someone already responded with a fix + - Community member confirmed it is resolved + - Bot duplicate flag. **DO NOT blindly trust bot labels (e.g., `kilo-duplicate`).** Re-verify independently from current source + web research. +3. **Identify the claimed error** — exact error message, status code, provider/model, OS, Node version. #### 5b. Check Information Sufficiency -Verify the issue contains enough to act on: +Verify the issue contains: - [ ] Clear description of the problem - [ ] Steps to reproduce OR error logs - [ ] Provider/model/version information - [ ] Expected vs actual behavior -#### 5c. Determine Issue Disposition +**If ANY item is missing → auto-classify as `📝 RESPOND — Needs Info` and skip 5d.** Do not attempt root-cause analysis on under-specified issues. -For each bug, classify into one of 5 actions: +#### 5c. Determine Issue Disposition | Disposition | When to Apply | Action | | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- | | **✅ CLOSE — Already Fixed** | Owner responded with fix + no user follow-up, OR community confirmed fix | Close with comment citing which version fixed it | | **✅ CLOSE — Duplicate** | You have independently verified the issue is a duplicate (do NOT rely solely on bot flags) + user provides no new info | Close referencing the original issue | | **✅ CLOSE — Stale** | We requested logs/info > 7 days ago with no reply | Close thanking the user, invite to reopen if needed | -| **📝 RESPOND — Needs Info** | Issue is real but missing critical reproduction details | Comment asking for specifics per `/issue-triage` | +| **📝 RESPOND — Needs Info** | Issue is real but missing critical reproduction details (also triggered by 5b) | Comment asking for specifics per `/issue-triage` | | **📝 RESPOND — User Config** | Error is caused by unsupported env (Node version, wrong model path, missing API enablement) | Comment explaining the user-side fix | +| **🤝 PR-LINKED** | An open contributor PR already targets this issue (from step 4.5) | Redirect to `/review-prs`; do not re-implement | | **🔧 FIX — Code Change** | Root cause is confirmed in the codebase | Research, propose solution in report, wait for approval | #### 5d. For "FIX — Code Change" Issues -Before coding, perform deep source analysis to formulate a plan: +Before coding, perform deep source analysis: -1. **Search the codebase** — `grep_search` for error strings, relevant function names, affected files -2. **Search the web** — for upstream API changes, SDK updates, or breaking changes that explain the bug -3. **Read the full source file** — don't rely on grep snippets; understand the surrounding logic -4. **Verify the root cause** — confirm the bug is reproducible based on the code, not just a user misconfiguration -5. **Formulate a proposed solution** — detail the exact files and lines you will change and how you will solve it. -6. **Create an Implementation Plan file** — write your proposed solution to `_tasks/features-vX.Y.Z/<ISSUE_NUMBER>-<short-description>.plan.md` (e.g. `_tasks/features-v3.7.6/1810-auto-restore-probe-failed-db.plan.md`) where `vX.Y.Z` is the current branch version. The plan should contain an Overview, Pre-Implementation Checklist, and detailed Implementation Steps (Files, Changes). -7. **DO NOT modify the codebase yet** — wait for user approval on your report and plan first. +1. **Search the codebase** — grep for error strings, function names, affected files +2. **Search the web** — upstream API changes, SDK updates, breaking changes +3. **Read the full source file** — don't rely on grep snippets +4. **Verify the root cause** is in our code, not user misconfiguration +5. **Formulate a proposed solution** — exact files/lines/logic +6. **Create an Implementation Plan file** at `_tasks/fixes-vX.Y.Z/<ISSUE>-<short-description>.plan.md` (`vX.Y.Z` = current release branch version). Create the directory first: `mkdir -p _tasks/fixes-vX.Y.Z`. The plan contains: Overview, Reproduction Steps, Regression Test Outline, Implementation Steps (files/changes), Rollout Notes. +7. **DO NOT modify the codebase yet** — wait for user approval. #### 5e. For "RESPOND" Issues Post a substantive comment that: -- Acknowledges the specific error they reported +- Acknowledges the specific error reported - Explains the likely root cause -- Provides concrete steps to resolve (version upgrade, env var fix, model path correction) +- Provides concrete steps (version upgrade, env var fix, model path correction) - Asks for follow-up info if needed -**Do NOT post generic template responses.** Every comment should reference the user's specific error messages and environment. +**No generic templates.** Every comment references the user's specific error and environment, and is written in the reporter's language (English default). ### 6. Generate Report & Wait for Validation -Present a summary report to the user detailing your proposed actions. For any bugs that need fixing, explicitly explain your proposed solution (files to change and logic) and point out that it will be implemented on the release branch (`release/vX.Y.Z`) after approval. +Present a summary report. For FIX bugs, explicitly explain the proposed solution (files to change + logic) and confirm it will land via per-issue worktree → PR → release branch after approval. Include the reporter's detected language per row so the user can verify. -| Issue | Title | Status | Proposed Action / Version | -| ----- | ----- | ------------- | ----------------------------------------- | -| #N | Title | ✅ Close | Already fixed / duplicate (explain why) | -| #N | Title | 🔧 Propose | Explanation of the code fix to be applied | -| #N | Title | 📝 Respond | Guidance comment to be posted | -| #N | Title | ❓ Needs Info | Triage comment to be posted | -| #N | Title | ⏭️ Skip | Feature request / not a bug | +| Issue | Title | Status | Reply Lang | Proposed Action / Version | +| ----- | ----- | -------------- | ---------- | ------------------------------------------ | +| #N | Title | ✅ Close | en | Already fixed / duplicate (explain why) | +| #N | Title | 🔧 Propose | pt-BR | Code fix plan summary + worktree branch | +| #N | Title | 📝 Respond | en | Guidance comment to be posted | +| #N | Title | ❓ Needs Info | en | Triage comment to be posted | +| #N | Title | 🤝 PR-Linked | en | Redirect to /review-prs (PR #M) | +| #N | Title | ⏭️ Skip | — | Feature request / not a bug | > **⚠️ IMPORTANT**: Do NOT implement code changes, commit, push, or close issues at this step. > Wait for the user to review the proposed fixes and respond with **OK** before proceeding. -- If the user says **OK** or approves → Proceed to step 7 -- If the user requests changes → Adjust the proposed solution and present the report again +- If the user says **OK** → Proceed to step 7 +- If the user requests changes → Adjust and re-present the report - If the user rejects → Revert any accidental changes and stop -### 7. Implement Fixes, Run Tests & Commit (only after user approval) +### 7. Implement Fixes via Per-Issue Worktrees + PRs (only after user approval) -After the user validates and gives the OK: +For each approved FIX issue (up to 30 per batch), repeat the following sequence. Issues can be processed sequentially or in parallel (one worktree each — never two fixes in the same worktree). -1. **Implement the fixes** — modify the codebase according to the approved plan. -2. **Run tests** — `npm run test:all` (or the specific test file) to ensure 100% pass. -3. **Update CHANGELOG.md** with all new bug fix entries. -4. **Commit** each fix individually on the release branch with message format: `fix: <description> (#<issue_number>)`. -5. **Push** the release branch: `git push origin release/vX.Y.Z`. -6. **Close resolved issues immediately**. For each issue that was marked as Fixed, run: - `gh issue close <NUMBER> --repo <owner>/<repo> --comment "Thank you for reporting! This issue has been fixed and will be included in the next release (vX.Y.Z)."` -7. Likewise, close `Duplicate` issues referencing the original, close `Needs Info` if stale, and post the required comments. -8. If the project runs automatic releases or needs a PR, proceed to run `/generate-release` workflow Phase 1 steps 7–10 (tests → commit → push → open PR to main → wait for user). +#### 7.1. Spin up an isolated worktree on a fresh fix branch -If NO fixes were committed, skip closing and source control steps and just conclude the workflow. +```bash +ISSUE=<NUMBER> +SHORT=<short-kebab-desc> +RELEASE_BRANCH=$(git -C <project_root> branch --show-current) # release/vX.Y.Z +WT_DIR=".worktrees/fix-${ISSUE}-${SHORT}" +BRANCH="fix/${ISSUE}-${SHORT}" + +git fetch origin "$RELEASE_BRANCH" +git worktree add "$WT_DIR" -b "$BRANCH" "origin/$RELEASE_BRANCH" +cd "$WT_DIR" +``` + +#### 7.2. Write the regression test first (TDD) + +- Author a unit/integration test that reproduces the bug. **It must fail on the unfixed code.** Run it and confirm the failure. +- Hard rule #8: any production change must ship with tests in the same PR. The regression test is non-negotiable. + +#### 7.3. Implement the fix + +- Apply the approved plan from `_tasks/fixes-vX.Y.Z/<ISSUE>-<short>.plan.md`. +- Keep the diff scoped to this issue. No drive-by refactors. + +#### 7.4. Run the test suite + +- `npm run test:all` (or the appropriate suite for the touched area; the regression test MUST be included). +- All tests must pass before commit. Also run the relevant `lint` / `typecheck` per CLAUDE.md trust-but-verify checklist. + +#### 7.5. Update CHANGELOG.md and commit (single commit, same diff) + +- Add the new bug-fix entry under the current `vX.Y.Z` section of CHANGELOG.md. +- CHANGELOG entry + code + test go in **one** commit on the fix branch: + +```bash +git add <changed files> CHANGELOG.md +git commit -m "fix: <description> (#${ISSUE})" +``` + +#### 7.6. Push and open a PR into the release branch + +```bash +git push -u origin "$BRANCH" +gh pr create \ + --base "$RELEASE_BRANCH" \ + --head "$BRANCH" \ + --title "fix: <description> (#${ISSUE})" \ + --body "Closes #${ISSUE}\n\n<short summary, plan link, regression test reference>" +``` + +#### 7.7. Merge the PR into the release branch + +- Wait for CI green, then merge with the project's default merge strategy. +- The PR title becomes the release-branch commit. + +#### 7.8. Clean up worktree and local branch + +```bash +cd <project_root> +git worktree remove "$WT_DIR" +git branch -D "$BRANCH" +``` + +#### 7.9. Close the issue with a localized comment + +Match the reporter's language (English default). Template: + +> **EN**: Thanks for reporting! Fixed in `release/vX.Y.Z` (already merged into the active development branch — feel free to pull and test it now). It will ship in the next release (vX.Y.Z). +> +> **pt-BR**: Obrigado pelo report! Corrigido em `release/vX.Y.Z` (já mergeado na branch de desenvolvimento atual — pode dar pull e testar). Vai sair na próxima release (vX.Y.Z). + +```bash +gh issue close "$ISSUE" --repo <owner>/<repo> --comment "<localized message above>" +``` + +#### 7.10. Close non-FIX dispositions + +After all FIX issues are merged: + +- `Duplicate`: close referencing the original issue (localized). +- `Stale`: close thanking the user and inviting reopen (localized). +- `RESPOND — Needs Info` / `RESPOND — User Config`: post the substantive comment from 5e (localized). +- `PR-LINKED`: leave the issue open; comment redirecting to the contributor PR if not already linked. + +#### 7.11. Hand off to release flow (optional) + +If a release PR to `main` is desired now, run `/generate-release` Phase 1 steps 7–10 (tests → commit version bump → push → open PR to main → wait for user). + +If NO fixes were committed, skip 7.7–7.11 and just conclude the workflow. diff --git a/.agents/workflows/review-discussions-ag.md b/.agents/workflows/review-discussions-ag.md index bd1192e29e..bcab51375c 100644 --- a/.agents/workflows/review-discussions-ag.md +++ b/.agents/workflows/review-discussions-ag.md @@ -1,14 +1,19 @@ --- -description: Read all open GitHub Discussions, summarize them, respond to pending ones, and create issues from actionable feature requests +description: Read all open GitHub Discussions, summarize them, respond to pending ones, create issues from actionable feature requests, and triage stale threads for closure --- # /review-discussions — GitHub Discussions Review & Response Workflow ## Overview -This workflow reads all open GitHub Discussions, generates a categorized summary, identifies which ones need a response, drafts and posts replies, and optionally creates issues from actionable feature requests. It follows the same flow used for Issues but adapted for the Discussions forum. +This workflow reads all open GitHub Discussions, generates a categorized summary, identifies which ones need a response, drafts and posts replies, optionally creates issues from actionable feature requests, and triages stale threads for closure. -> **Tool mapping note (v3.8):** Where steps below say `browser_subagent`, in modern Claude Code substitute with the `gh` CLI via Bash — `gh api graphql` for reading discussions and mutations for posting comments. `WebFetch` is acceptable for read-only HTML scraping when GraphQL is overkill, but prefer `gh` for any write actions. +**Modern tooling (replaces deprecated `browser_subagent` flow):** + +- Reads use `gh api graphql` — one query returns 50 discussions with full bodies, comments, replies, IDs, and `updatedAt`. +- Writes (post comment, create issue, close discussion) use `gh api graphql` mutations or `gh issue create`. +- Pace at ~1s between writes to avoid abuse-detection throttling. +- `WebFetch` is acceptable only for read-only HTML scraping when GraphQL is unavailable — never for write actions. // turbo-all @@ -16,14 +21,16 @@ This workflow reads all open GitHub Discussions, generates a categorized summary ### 1. Identify the GitHub Repository -- Run: `git -C <project_root> remote get-url origin` to extract the owner/repo -- Parse the owner and repo name from the URL +- Run: `git -C <project_root> remote get-url origin` to extract `owner/repo`. +- Parse owner and repo name from the URL (https or ssh form). -### 2. Fetch All Open Discussions +### 2. Fetch All Open Discussions (single GraphQL query) -- Use `WebFetch` to fetch `https://github.com/<owner>/<repo>/discussions` -- Parse the discussion list to get all discussion titles, IDs, authors, categories, and dates -- For each discussion, fetch the individual page to read the full content and all comments/replies +Single `gh api graphql` call — return everything needed for triage. Critical fields: `id` (node ID, **not** the visible `number`), `number`, `title`, `url`, `createdAt`, `updatedAt`, `author.login`, `category.name`, `body`, `answerChosenAt`, plus nested `comments(first: 50) { totalCount, nodes { id, author.login, body, createdAt, replies(first: 20) { nodes { author.login, body, createdAt } } } }`. + +Persist the raw JSON to `/tmp/discussions-<repo>-<date>.json` so re-runs in the same session avoid a re-fetch. Build an `id → number` map for the post phase — the GraphQL `addDiscussionComment` mutation requires the node ID, not the number. + +Capture **image attachments** present in body or comments (`<img src="...">` or markdown `![...](...)`). Surface their count in the per-discussion summary (e.g., `📷 3 screenshots`) so the user can decide if visual context matters before approving a draft. ### 3. Summarize All Discussions @@ -32,89 +39,228 @@ For each discussion, extract: - **Title** and **#Number** - **Author** (GitHub username) - **Category** (Announcements, General, Ideas, Q&A, Show and tell) -- **Date** created -- **Summary** of the original post (1-2 sentences) -- **Comments count** and key participants -- **Your previous response** (if any) -- **Pending action** — whether a response or follow-up is needed +- **Created** + **Last updated** (ISO date) +- **Summary** of original post (1-2 sentences) +- **Comment count** + **last commenter** + **last comment date** +- **Maintainer involvement**: whether the repo owner already replied, and how many times +- **Pending action** — derived state, see categories below +- **Attachments**: count of screenshots / videos / pastebin links +- **Detected language** of the reporter (for reply-language matching) ### 4. Present Summary Report to User -Present the full summary to the user organized by category, using a table: +Group by **pending action**, not by category, so the human sees triage buckets at a glance: -| # | Category | Title | Author | Date | Status | -| --- | -------- | ----- | ------ | ------ | ----------------- | -| #N | Ideas | Title | @user | Mar 23 | ⚠️ Needs response | -| #N | Q&A | Title | @user | Mar 9 | ✅ Answered | -| #N | General | Title | @user | Mar 19 | ⚠️ Needs response | +| State | Meaning | +| ----------------------- | ---------------------------------------------------------------------------------------------------------------- | +| ⚠️ Needs first response | Zero comments, or all comments are from non-maintainers | +| 🔄 Follow-up pending | Maintainer replied, but reporter or third party added a new comment maintainer has not addressed | +| 🕒 Stale (>15d) | Maintainer was last to comment, no activity for 15+ days — candidate for soft-close or reporter-ping (see step 8)| +| ✅ Answered | Maintainer already replied AND last commenter is the maintainer AND age < 15d | +| 🏁 Resolved | `answerChosenAt` is set | -Highlight: +Within each bucket, present a table: -- **⚠️ Needs response** — No reply from maintainer, or a follow-up comment was left unanswered -- **✅ Answered** — Maintainer already responded -- **🐛 Bug reported** — A bug was mentioned that needs tracking -- **💡 Actionable** — Contains a concrete feature request that could become an issue +| # | Category | Title | Author | Updated | Notes | +| --- | -------- | ------------------ | ------ | ------- | ---------------------- | +| #N | Q&A | short title (60ch) | @user | YYYY-MM-DD | 📷2 · 🐛bug · 💡FR | + +Tag rows with content hints when detected: `🐛bug` (`[BUG]` / `error` / stacktrace in body), `💡FR` (`feature request` / `add support for`), `❓support` (config/usage question), `🙏thanks` (short ack-only follow-up). ### 5. Draft & Post Responses -For each discussion that needs a response, draft a reply following these guidelines: +#### Reply templates by intent -#### Response Style +Pick the template that matches the discussion intent — do NOT use a single generic format. -- **Friendly and professional** — Start with "Hey @username!" -- **Acknowledge the contribution** — Thank the user for their input -- **Be specific** — Reference existing features, settings, or dashboard pages if the feature already exists -- **Provide workarounds** — If the request isn't implemented yet, suggest current alternatives -- **Commit to action** — If the request is valid, state that you'll open an issue or add it to the roadmap -- **Keep it concise** — 3-5 paragraphs max +**A. Bug confirmed** — ack + root cause + tracking + workaround +``` +Hey @user! Confirmed -- {root cause in one sentence}. I traced it to `path/to/file.ts:line`. -#### Posting via Browser +{Why it happens: 2-4 sentences of technical detail} -- Use `browser_subagent` to navigate to each discussion and post the comment -- **IMPORTANT**: When typing text in GitHub comment boxes via the browser, use only plain ASCII characters: - - Use regular hyphens `-` instead of em-dashes - - Use `->` instead of arrow symbols - - Do NOT use emoji Unicode characters (the browser keyboard may fail on them) - - Use `**bold**` and `\`code\`` markdown formatting -- Click the green "Comment" button (or "Reply" for threaded replies) after typing -- Verify the comment was posted by checking the page shows the new comment +I have opened {issue #N} to track the fix. Workaround until it ships: {concrete steps}. Will update here when the patch lands. +``` + +**B. Feature Request** — ack + status + scope + commit +``` +Hey @user! {Status: "Already exists" / "Tracked in #N" / "Reasonable, opening an issue"}. + +{If already exists: pointer to dashboard page or doc} +{If tracked: link to umbrella, summarize order/priority} +{If new: open issue + post link back} + +{Optional: short technical note on feasibility / trade-offs} +``` + +**C. Support / config question** — direct answer + reference + offer to dig deeper +``` +Hey @user! {One-sentence answer}. + +Steps: +1. ... +2. ... +3. ... + +Reference: `docs/<path>.md`. If it still fails after that, paste {specific thing} and I will trace it. +``` + +**D. Thank-you / short follow-up** — 1-2 sentences +``` +Glad it helps, @user! {Concrete next marker — when patch ships / when to expect next update}. +``` + +**E. Stale / closing** — see step 8 + +#### Posting via gh (replaces deprecated browser flow) + +```bash +gh api graphql -f query=' +mutation($id: ID!, $body: String!) { + addDiscussionComment(input: {discussionId: $id, body: $body}) { + comment { id url } + } +}' -f id="$NODE_ID" -f body="$BODY" +``` + +For **threaded replies** (recommended when responding to a specific comment in a long thread), add `replyToId: $parentCommentId` to the input. + +**Output hygiene** (still applies even via API — the comment renders in GitHub UI): + +- ASCII-safe punctuation: regular hyphens `-`, `->` for arrows +- Markdown OK: `**bold**`, fenced code blocks, `[text](url)` links +- No bare error messages with stack traces from internal logs — sanitize +- Match reporter's language (pt-BR reporter → pt-BR reply; ru reporter → ru reply); default to English when uncertain + +**Pacing**: `sleep 1` between mutations. GitHub abuse-detection trips around 10/sec for the same actor. + +**Verification**: capture the returned `comment.url` from each mutation. Failed posts (returncode != 0 or `errors` in response) get logged separately and retried once after a 5s pause. ### 6. Create Issues from Actionable Feature Requests For discussions that contain concrete, actionable feature requests: -1. Ask the user which ones should become issues -2. For each approved request, create a GitHub issue via `browser_subagent`: - - Navigate to `https://github.com/<owner>/<repo>/issues/new` - - **Title**: `<Feature Name> - <Short description>` - - **Body** should include: - - `## Feature Request` header - - `**Source:** Discussion #N by @author` - - `## Problem` — What limitation the user hit - - `## Proposed Solution` — How it could work - - `### Implementation Ideas` — Technical approach - - `### Current Workarounds` — What users can do today - - `## Additional Context` — Links to related issues/discussions - - Add `enhancement` label - - Click "Submit new issue" / "Create" -3. After creation, go back to the original discussion and post a comment linking to the new issue: - - "I've opened Issue #N to track this feature request. Follow along there for updates!" +1. **Deduplicate FIRST** — before drafting, search existing issues: + ```bash + gh issue list --repo $OWNER/$REPO --search "<keywords from FR>" --state open --json number,title,labels + ``` + If a matching issue (or umbrella) already exists, reuse it — never create a duplicate. Post a comment in the discussion linking to the existing issue. + +2. **Ask the user which to create** — even after dedup, the human approves the final list. + +3. **Create the issue** with `gh issue create`: + ```bash + gh issue create --repo $OWNER/$REPO \ + --title "[feature] <short imperative>" \ + --label enhancement \ + --body @/tmp/issue-body.md + ``` + Body template: + ```markdown + ## Feature Request + + **Source:** Discussion #N by @author + + ## Problem + What limitation the user hit (in their words, paraphrased) + + ## Proposed Solution + How it could work + + ### Implementation Ideas + - File paths likely to touch + - Related modules / patterns already in the codebase + + ### Current Workarounds + What users can do today + + ## Additional Context + - Discussion: #N + - Related issues/PRs: #X, #Y + - Upstream references: link to similar implementations in `_references/` if applicable + ``` + +4. **Generate task file in `_ideia/`** when the feature needs deeper investigation before implementation: + ``` + _ideia/<short-kebab-slug>.md + ``` + Contains: problem statement, current OmniRoute state, how upstream (`_references/9router`, `_references/CLIProxyAPI`, etc.) handles it, proposed implementation levels (short/medium/long term), acceptance criteria. + +5. **Link back to discussion** with the real URL: + ``` + Follow-up @reporter — I've opened issue #N to track this. {1-line summary of what the issue covers}. + ``` ### 7. Final Report -Present a final summary to the user: +| Discussion | Action Taken | +| ---------- | ------------------------------------------------------------- | +| #N — Title | Responded (bug confirmed, tracking #M) | +| #N — Title | Responded + created issue #M + task file `_ideia/X.md` | +| #N — Title | Responded (support answered with workaround) | +| #N — Title | Responded to follow-up comment | +| #N — Title | Closed (stale 15+d, no reply from reporter) | +| #N — Title | Ping sent (stale 15+d, will close in 7d if no response) | -| Discussion | Action Taken | -| ---------- | ---------------------------------- | -| #N — Title | Responded with workarounds | -| #N — Title | Responded + created Issue #N | -| #N — Title | Already answered, no action needed | -| #N — Title | Responded to follow-up comment | +Include totals: comments posted, issues created, discussions closed, discussions pinged. Capture median response time for the batch. + +### 8. Stale Discussion Triage (auto-close candidates) + +Identify discussions matching **all** of: + +- `updatedAt > 15 days ago` +- Maintainer already replied at least once +- Last commenter is the maintainer (the ball is on the reporter's side) +- `answerChosenAt` is null (not formally resolved) +- Category in `{Q&A, General}` — skip `Ideas` / `Show and tell` / `Announcements` (those serve as community references and shouldn't be closed) +- `comments.totalCount >= 2` — there was actual conversation, not a drive-by post +- No label named `keep-open` (escape hatch) + +For each candidate, present to the user with a recommended action: + +| Action | When | +| --------------- | ----------------------------------------------------------------------------- | +| **Soft-close** | Default — maintainer answered concretely and reporter went silent | +| **Ping reporter** | Maintainer asked for more info (log dump, screenshot) and never got it | +| **Keep open** | Conversation is mid-debug and closing would lose context — operator override | + +**Soft-close mutation:** +```bash +gh api graphql -f query=' +mutation($id: ID!) { + closeDiscussion(input: {discussionId: $id, reason: RESOLVED}) { + discussion { id closed } + } +}' -f id="$NODE_ID" +``` +Valid `reason` values: `RESOLVED`, `OUTDATED`, `DUPLICATE`. Default to `OUTDATED` for "no response" closures, `RESOLVED` for answered-but-not-confirmed. + +Before closing, post a closing comment: +``` +Closing for inactivity -- feel free to reopen if you still hit this, or open a fresh issue with a current log. Thanks! +``` + +**Ping flow** (alternative): +``` +@reporter -- still happening on the latest version? Otherwise I'll close this in 7 days for inactivity. +``` +Persist the ping in `_cache/discussions-pinged-<date>.json` so the next run knows to close discussions that were pinged 7+ days ago without a reply. ## Notes -- This workflow is **interactive** — always present the summary and wait for user approval before posting responses or creating issues -- If the user says "pode responder" (or similar approval), proceed with posting all drafted responses -- For discussions in non-English languages, respond in the same language as the original post -- Always reference specific dashboard paths, config options, or code files when explaining existing features -- When a discussion reveals a bug, note it separately from feature requests +- This workflow is **interactive** — always present the summary and wait for user approval before posting responses, creating issues, or closing discussions. +- Gather batched approval — separate consents for "reply scope", "create issues for?", "close stale?". Stale handling is a distinct consent from reply posting. +- For discussions in non-English languages (`pt-BR`, `ru`, `zh`, `es`), respond in the same language as the original post. Default to English when uncertain. +- Always reference specific dashboard paths, config options, doc files, or code locations (`file:line`) when explaining existing features — never wave hands. +- When a discussion reveals a bug, separate it from feature requests in the report. Bugs need a tracking issue + workaround; FRs need scoping. +- Before recommending a workaround that mentions a file/flag/setting, verify it exists in the **current** codebase (the previous turn's memory may be stale). +- Trust-but-verify: after a batch post, spot-check 2-3 random `comment.url` returns in the browser to confirm the comments rendered cleanly (no Unicode mojibake, no broken markdown). + +## Anti-patterns to avoid + +- ❌ Posting via `browser_subagent` clicks — slow, flaky, and obsolete since `gh api graphql` mutations exist. +- ❌ N+1 fetches (one per discussion) — use one GraphQL query for all 50. +- ❌ Creating an issue without checking for an existing umbrella / similar one first. +- ❌ Generic "thanks, I'll look into it!" responses — every reply must reference a file, doc, or concrete action. +- ❌ Closing a stale discussion without posting a closing comment first. +- ❌ Skipping the user approval gate ("turbo-all" never bypasses interactive consent for writes). diff --git a/.agents/workflows/review-prs-ag.md b/.agents/workflows/review-prs-ag.md index 22d9404b8b..a7986de8ce 100644 --- a/.agents/workflows/review-prs-ag.md +++ b/.agents/workflows/review-prs-ag.md @@ -50,7 +50,7 @@ git branch --show-current # If on main, determine next version and create the release branch VERSION=$(node -p "require('./package.json').version") # Bump patch: e.g. 3.3.11 → 3.3.12 -NEXT=$(node -p "const [a,b,c]=('$VERSION').split('.').map(Number); c>=9?a+'.'+(b+1)+'.0':a+'.'+b+'.'+(c+1)") +NEXT=$(node -p "const [a,b,c]=('$VERSION').split('.').map(Number); c>=999?a+'.'+(b+1)+'.0':a+'.'+b+'.'+(c+1)") git checkout -b release/v$NEXT npm version patch --no-git-tag-version npm install diff --git a/.agents/workflows/version-bump-ag.md b/.agents/workflows/version-bump-ag.md index 8c356e52b5..581e965d54 100644 --- a/.agents/workflows/version-bump-ag.md +++ b/.agents/workflows/version-bump-ag.md @@ -9,7 +9,7 @@ Automatically bump the project version, generate CHANGELOG entries from git hist > **VERSION RULE: Always use PATCH bumps (3.x.y → 3.x.y+1)** > NEVER use `npm version minor` or `npm version major`. > Always use: `npm version patch --no-git-tag-version` -> The threshold rule: when `y` reaches 10, bump to `3.(x+1).0` — e.g. `3.4.10` → `3.5.0`. +> The threshold rule: when `y` reaches 1000, bump to `3.(x+1).0` — e.g. `3.4.999` → `3.5.0`. --- diff --git a/.claude/commands/generate-release-cc.md b/.claude/commands/generate-release-cc.md index 7cb717c423..a826fd0a86 100644 --- a/.claude/commands/generate-release-cc.md +++ b/.claude/commands/generate-release-cc.md @@ -1,5 +1,5 @@ --- -description: Create a new release, bump version up to the .10 patch threshold, update changelog, and manage Pull Requests +description: Create a new release, bump version up to the .999 patch threshold, update changelog, and manage Pull Requests --- # Generate Release Workflow @@ -9,9 +9,9 @@ Bump version, finalize CHANGELOG, commit, open a **PR to main** and wait for use > **VERSION RULE: Always use PATCH bumps (3.x.y → 3.x.y+1)** > NEVER use `npm version minor` or `npm version major`. > Always use: `npm version patch --no-git-tag-version` -> The threshold rule: when `y` reaches 10, bump to `3.(x+1).0` — e.g. `3.8.10` → `3.9.0`. +> The threshold rule: when `y` reaches 1000, bump to `3.(x+1).0` — e.g. `3.8.999` → `3.9.0`. -> **🔴 SINGLE BRANCH RULE**: The `release/vX.Y.Z` branch is the **ONLY** development branch for the entire release cycle. ALL work — bug fixes, feature implementations, PR integrations, issue resolutions — MUST be committed directly on this branch. Never create separate `fix/`, `feat/`, or topic branches. When running `/resolve-issues`, `/implement-features`, or `/review-prs`, always work on the current release branch. +> **🔴 INTEGRATION BRANCH RULE**: The `release/vX.Y.Z` branch is the **integration target** for the entire release cycle. Bug fixes and feature implementations land here **via per-issue PRs from short-lived `fix/<ISSUE>-<short>` or `feat/<ISSUE>-<short>` worktrees** (see `/resolve-issues`, `/implement-features`). Contributor PRs from `/review-prs` likewise merge into this branch. The release branch is then merged to `main` via a single release PR at the end of the cycle. --- diff --git a/.claude/commands/implement-features-cc.md b/.claude/commands/implement-features-cc.md index afb8b3ed93..8ba6d84a94 100644 --- a/.claude/commands/implement-features-cc.md +++ b/.claude/commands/implement-features-cc.md @@ -17,18 +17,26 @@ _ideia/ │ │ └── 1015-warp-terminal-mitm.md │ ├── 1046-native-playground.md # ✅ Ready — researched and planned │ └── 1046-native-playground.requirements.md -├── defer/ # ⏭️ Good ideas deferred for future cycles (issues CLOSED) +├── implemented/ # 🚧 Implemented but PR not yet merged to main (transient) +│ └── 1046-native-playground.md +├── defer/ # ⏭️ Good ideas deferred for future cycles (issues CLOSED after Phase 3 approval) │ └── 1041-smart-auto-combos.md -└── notfit/ # ❌ Out of scope / already exists (issues CLOSED) +└── notfit/ # ❌ Out of scope / already exists (issues CLOSED after Phase 3 approval) └── 945-telegram-integration.md _tasks/features-vX.Y.Z/ # Implementation plans (per-release) └── 1046-native-playground.plan.md ``` -> **LIFECYCLE RULE:** `viable/` files are **DELETED** once the feature is implemented — they are not moved. Only unimplemented features live in `viable/` (or `viable/need_details/`). Files in `defer/` and `notfit/` remain as permanent reference. +> **LIFECYCLE RULE:** +> - `viable/` files are **MOVED** to `implemented/` once code lands on the release branch. +> - `implemented/` files are **DELETED** only after the release PR is merged to `main`. +> - This preserves recovery context if implementation fails partially (build green but i18n missing, etc). +> - Files in `defer/` and `notfit/` remain as permanent reference. -> **BRANCH RULE**: All implementation work MUST happen on the current `release/vX.Y.Z` branch. Never create separate `feat/` branches. If no release branch exists yet, create one first using `/generate-release` Phase 1 steps 1–5. +> **BRANCH RULE**: All implementation work MUST happen on the current `release/vX.Y.Z` branch. Never create separate `feat/` branches. If no release branch exists yet, delegate creation to `/generate-release` (see Phase 1.2) — do NOT reimplement bump logic here. + +> **LANGUAGE RULE** (per `feedback_reply_language` memory): GitHub comments MUST match the language of the original issue body. Detect language by sampling the issue body + first 2 comments. Default to English when uncertain. All comment templates below are in English — translate to the detected language before posting. Internal docs, plan files, and idea files stay in English regardless. --- @@ -42,23 +50,18 @@ _tasks/features-vX.Y.Z/ # Implementation plans (per-release) ### 1.2 Ensure Release Branch Exists -// turbo - Before doing any work, ensure you are on the current release branch: ```bash -# Check current branch git branch --show-current - -# If on main, determine next version and create the release branch -VERSION=$(node -p "require('./package.json').version") -NEXT=$(node -p "const [a,b,c]=('$VERSION').split('.').map(Number); c>=9?a+'.'+(b+1)+'.0':a+'.'+b+'.'+(c+1)") -git checkout -b release/v$NEXT -npm version patch --no-git-tag-version -npm install ``` -If already on a `release/vX.Y.Z` branch, continue working there. +**Decision tree:** + +- If already on a `release/vX.Y.Z` branch → continue working there. +- If on `main` or any other branch → **delegate to `/generate-release`** by invoking its Phase 1 (steps 1–5: detect current version, bump, create branch, install). Do NOT reimplement the bump formula here — `/generate-release` owns the canonical version policy (patch bumps allowed up to `.999`; minor bump only when patch reaches `999`). + +> **Why delegate?** Duplicating the bump formula caused divergence in the past. `/generate-release` is the single source of truth for version arithmetic and now allows patches up to `.999` before bumping minor. ### 1.3 Fetch ALL Open Feature Requests @@ -77,6 +80,7 @@ gh issue list --repo <owner>/<repo> --state open --limit 500 --json number,title ``` - Merge both lists, deduplicate. Count and confirm the total. +- If the count hits the `--limit 500` ceiling, raise the limit and re-run — never proceed with a truncated set. **Step 2 — Fetch full metadata for each Issue** (one call per issue): @@ -86,7 +90,8 @@ gh issue view <NUMBER> --repo <owner>/<repo> --json number,title,labels,body,com - Read the **entire body** — including description, use cases, screenshots, mockups, and any embedded images. - Read **ALL comments** — community discussion, agreements, restrictions, owner responses, and linked PRs. -- **Images**: If the body or comments contain image URLs (`![...](...)` or `https://...png/jpg/gif`), note them — they may contain UI mockups, wireframes, or architecture diagrams that are essential to understanding the request. +- **Images**: If the body or comments contain image URLs (`![...](...)` or `https://...png/jpg/gif`), **download and analyze them with the Read tool** (Claude can read PNG/JPG/GIF directly). Mockups and wireframes are often the most informative artifact — do NOT just "note" them, actually inspect their content and incorporate findings into the refined description. +- **Detect issue language** from body + first 2 comments and record it in the idea file front-matter (`reply_lang: pt-BR | en | es | ...`). This will drive comment translation in Phases 2.5 and 5. - You may batch these into parallel calls (up to 4 at a time). - Sort by oldest first (FIFO). @@ -100,6 +105,10 @@ Example: `1046-native-playground.md`, `1041-smart-auto-combos.md` #### 1.4a — If the idea file does NOT exist yet, create it: ```markdown +--- +reply_lang: <detected-lang, e.g. pt-BR | en | es> +--- + # Feature: <Title from Issue> > GitHub Issue: #<NUMBER> — opened by @<author> on <date> @@ -125,6 +134,10 @@ Example: `1046-native-playground.md`, `1041-smart-auto-combos.md` - <agreements reached> - <objections raised> +## 🖼️ Mockup / Image Analysis + +<For each image embedded in the issue, summarize what it depicts: UI layout, data flow, architecture diagram, etc. Cite source URL.> + ## 🎯 Refined Feature Description <YOUR interpretation and enrichment of the feature request. Expand on what was asked, fill in logical gaps, provide concrete examples of how it would work. This section should be MORE detailed and clearer than the original request.> @@ -158,6 +171,7 @@ Example: `1046-native-playground.md`, `1041-smart-auto-combos.md` - Append new comments from the issue to the **Community Discussion** section. - Update the **Refined Feature Description** if new information changes the understanding. - Add any new **Related Ideas** cross-references found. +- Re-detect `reply_lang` only if the issue language clearly changed (uncommon). - **Do NOT overwrite** existing content — append and enrich it. ### 1.5 Cross-Reference & Deduplication @@ -168,11 +182,29 @@ After processing all issues: - If two features are substantially the same, add `🔗 Related Ideas` cross-references to both. - If one is a strict subset of another, note it in the smaller file: `> ℹ️ This feature is a subset of #<OTHER_NUMBER>. Consider implementing together.` +### 1.6 Detect In-Flight Work (avoid duplicate effort) + +For each issue number, check whether an open PR or branch already targets it: + +```bash +# Open PRs that link the issue +gh pr list --repo <owner>/<repo> --state open --search "linked:#<NUMBER>" --json number,title,headRefName + +# Local branches that mention the issue number +git branch -a | grep -E "(^|/)(feat|fix|refactor)/.*-?<NUMBER>(-|$)" || true +``` + +If a PR or branch already exists: + +- Mark the idea file with `> ⚠️ In-flight: PR #<PR_NUMBER> / branch <name>` near the top. +- **Skip Phase 2 research and Phase 4 planning** for this feature — the implementation is already in motion. +- In the Phase 3 report, list it under a separate "🚧 Already in progress" bucket; do NOT count it as VIABLE for implementation. + --- ## Phase 2 — Research: Find Solutions & Build Requirements -For each cataloged idea that is **viable** (aligns with the project's goals): +For each cataloged idea that is **viable** (aligns with the project's goals) AND not already in flight (per 1.6): ### 2.1 Viability Pre-Check @@ -193,10 +225,17 @@ Before investing in research, quickly assess: | ⏭️ **DEFER** | Good idea, too complex for this cycle | Catalog only, skip research | | ❌ **NOT FIT** | Doesn't fit the project | Explain why | | 🔁 **ALREADY EXISTS** | Feature already implemented | Point to existing feature | +| 🚧 **IN FLIGHT** | PR/branch already exists (from 1.6) | Skip — track only | ### 2.2 Internet Research (for VIABLE features) -For each viable feature, perform systematic research: +For each viable feature, perform systematic research with an **early-stopping criterion**: + +> **Stop as soon as EITHER condition is met:** +> - 3 reference implementations show a consistent pattern, OR +> - 1 high-quality repo (≥1k stars, updated within the last 12 months) already solves the problem cleanly. +> +> Cap at 10 repos total. Do NOT exhaustively browse — depth over breadth. **Step 1 — Web search for similar implementations:** @@ -213,8 +252,8 @@ WebSearch("site:github.com <feature keyword> <tech stack> stars:>100") WebSearch("github <feature keyword> implementation recently updated 2026") ``` -- Find **up to 10 relevant repositories**, sorted by most recently updated. -- For each repository: +- Sort by most recently updated. +- For each repository (until stop criterion hit): - Note the repo URL, star count, last commit date - Read its README and relevant source files via `WebFetch` - Extract the architectural approach, patterns used, and key code snippets @@ -307,7 +346,9 @@ For each researched feature, create a requirements file alongside its idea file: --- -## Phase 2.5 — Organize & Respond: Sort Files and Post GitHub Comments +## Phase 2.5 — Organize: Sort Files into Category Directories + +> **⚠️ This phase only moves files. It does NOT post comments or close issues.** All GitHub-visible actions are deferred to Phase 3.2 (after human approval). ### 2.5.1 Create Directory Structure @@ -316,13 +357,14 @@ For each researched feature, create a requirements file alongside its idea file: ```bash mkdir -p <project_root>/_ideia/viable mkdir -p <project_root>/_ideia/viable/need_details +mkdir -p <project_root>/_ideia/implemented mkdir -p <project_root>/_ideia/defer mkdir -p <project_root>/_ideia/notfit ``` ### 2.5.2 Move Idea Files to Category Subdirectories -After classification, move EVERY idea file to its correct subdirectory: +After classification, move EVERY idea file to its correct subdirectory (still local-only — no GitHub side-effects): ```bash # ✅ VIABLE — move idea + requirements files @@ -337,20 +379,73 @@ mv _ideia/<NUMBER>-*.md _ideia/defer/ # ❌ NOT FIT & 🔁 ALREADY EXISTS — move idea files only mv _ideia/<NUMBER>-*.md _ideia/notfit/ + +# 🚧 IN FLIGHT — leave in _ideia/ root with a top-of-file banner; do NOT touch the PR/branch ``` -No files should remain in `_ideia/` root after this step (except subdirectories). +No idea files should remain in `_ideia/` root after this step except `🚧 IN FLIGHT` entries. -### 2.5.3 Post GitHub Comments by Category +--- -**Each category has a specific comment template and action:** +## Phase 3 — Report: Present Findings & Get Human Approval + +### 3.1 🛑 MANDATORY STOP — Present Consolidated Report + +After completing Phase 1, Phase 2, and Phase 2.5, **STOP and present the following report** in the chat. **No comments have been posted to GitHub yet** — that happens in 3.2 after approval. + +Present a structured report containing: + +#### 3.1a — Feature Summary Table + +| # | Issue | Title | Verdict | Local Location | Planned GitHub Action | +| --- | ----- | ----- | --------------- | ----------------------------- | -------------------------------- | +| 1 | #N | Title | ✅ VIABLE | `_ideia/viable/` | Comment + keep OPEN | +| 2 | #N | Title | ⏭️ DEFER | `_ideia/defer/` | Comment + CLOSE | +| 3 | #N | Title | ❌ NOT FIT | `_ideia/notfit/` | Comment + CLOSE | +| 4 | #N | Title | 🔁 EXISTS | `_ideia/notfit/` | Comment with location + CLOSE | +| 5 | #N | Title | ❓ NEEDS DETAIL | `_ideia/viable/need_details/` | Comment with questions + OPEN | +| 6 | #N | Title | 🚧 IN FLIGHT | `_ideia/` (banner) | None — PR #M already handles it | + +#### 3.1b — Viable Features Detail + +For each VIABLE feature, provide a brief paragraph: + +- What was found during research (with stop reason: "3-pattern consistency" or "dominant repo") +- The proposed approach +- Key risks or unknowns +- Which reference repositories were most useful + +#### 3.1c — Issues Requiring Author Feedback + +For features marked ❓ NEEDS DETAIL, list: + +- What specific information is missing +- What examples or repository references would help +- Detected `reply_lang` for the question post + +#### 3.1d — Ask for User Confirmation + +End the report with: + +> **Ready to proceed?** +> +> Approving will (a) post comments on GitHub in the detected language of each issue and (b) close DEFER / NOT FIT / EXISTS issues. VIABLE and NEEDS DETAIL stay open. +> +> - Reply **"sim"** / **"yes"** to post all comments AND generate implementation plans for all VIABLE features. +> - Reply **"only comments"** to post comments without generating plans yet. +> - Reply with specific issue numbers to scope the action. +> - Reply **"não"** / **"no"** to stop without touching GitHub. + +### 3.2 Post GitHub Comments & Close Issues (only after approval) + +> **⚠️ Do NOT execute this step without explicit user approval from 3.1d.** + +For each issue, translate the appropriate template below into the `reply_lang` recorded in its idea file front-matter, then post. The English templates are reference only — never post the English version verbatim to a non-English issue. --- #### For 🔁 ALREADY EXISTS — Comment + CLOSE issue -// turbo - The feature already exists in the system. Explain WHERE it is and HOW to use it. ```markdown @@ -372,15 +467,13 @@ Closing this as the feature is already available. 🎉 ``` ```bash -gh issue close <NUMBER> --repo <owner>/<repo> --comment "<comment above>" +gh issue close <NUMBER> --repo <owner>/<repo> --comment "<translated comment>" ``` --- #### For ⏭️ DEFER — Comment + CLOSE issue -// turbo - Thank the user, explain the idea was cataloged, and that we'll study it before implementing. ```markdown @@ -394,21 +487,20 @@ Due to the **significant architectural impact** of this feature, we'll need to c - Your idea is saved in our internal feature backlog - We'll conduct architecture studies when this area is prioritized -- We'll notify you here when development begins -Thank you for contributing to OmniRoute's roadmap! Your input helps shape the product. 🚀 +If you want to track progress, please **subscribe to the repository releases** — every implemented feature is announced in the CHANGELOG. + +Thank you for contributing to OmniRoute's roadmap! 🚀 ``` ```bash -gh issue close <NUMBER> --repo <owner>/<repo> --comment "<comment above>" +gh issue close <NUMBER> --repo <owner>/<repo> --comment "<translated comment>" ``` --- #### For ❌ NOT FIT — Comment + CLOSE issue -// turbo - Politely explain why the feature doesn't fit the project scope. ```markdown @@ -424,15 +516,13 @@ We appreciate you thinking of ways to improve OmniRoute! If you'd like to discus ``` ```bash -gh issue close <NUMBER> --repo <owner>/<repo> --comment "<comment above>" +gh issue close <NUMBER> --repo <owner>/<repo> --comment "<translated comment>" ``` --- #### For ❓ NEEDS DETAIL — Comment (keep OPEN) -// turbo - Ask for the specific missing details needed. ```markdown @@ -453,9 +543,7 @@ Looking forward to your response! 🚀 #### For ✅ VIABLE — Comment (keep OPEN) -// turbo - -Thank the user, confirm we've cataloged their idea, and explain it may be implemented in future versions. +Thank the user, confirm we've cataloged their idea, and explain that progress is tracked in releases. ```markdown Hi @<author>! Thanks for the great feature suggestion! 🙏 @@ -464,58 +552,12 @@ We've analyzed your request and it aligns well with OmniRoute's roadmap. We've * **Status:** 📋 Cataloged for future implementation -This feature may be included in upcoming releases. We'll **respond to this issue and tag you** as soon as implementation begins so you can test it. +This issue will be **closed automatically by the merge commit** when the feature ships. To follow along, you can subscribe to repository releases or watch this issue. Thank you for helping improve OmniRoute! 🚀 ``` -**⚠️ Do NOT close viable issues — they remain OPEN for tracking.** - ---- - -## Phase 3 — Report: Present Findings to User - -### 3.1 🛑 MANDATORY STOP — Present Consolidated Report - -After completing Phase 1, Phase 2, and Phase 2.5, **STOP and present the following report** in the chat. Do NOT proceed to implementation. - -Present a structured report containing: - -#### 3.1a — Feature Summary Table - -| # | Issue | Title | Verdict | Location | Action | -| --- | ----- | ----- | --------------- | ----------------------------- | ----------------------------- | -| 1 | #N | Title | ✅ VIABLE | `_ideia/viable/` | Issue OPEN, comment posted | -| 2 | #N | Title | ⏭️ DEFER | `_ideia/defer/` | Issue CLOSED with explanation | -| 3 | #N | Title | ❌ NOT FIT | `_ideia/notfit/` | Issue CLOSED with explanation | -| 4 | #N | Title | 🔁 EXISTS | `_ideia/notfit/` | Issue CLOSED with guidance | -| 5 | #N | Title | ❓ NEEDS DETAIL | `_ideia/viable/need_details/` | Issue OPEN, questions posted | - -#### 3.1b — Viable Features Detail - -For each VIABLE feature, provide a brief paragraph: - -- What was found during research -- The proposed approach -- Key risks or unknowns -- Which reference repositories were most useful - -#### 3.1c — Issues Requiring Author Feedback - -For features marked ❓ NEEDS DETAIL, list: - -- What specific information is missing -- What examples or repository references would help - -#### 3.1d — Ask for User Confirmation - -End the report with: - -> **Ready to proceed with implementation?** -> -> - Reply **"sim"** or **"yes"** to generate full implementation plans for all VIABLE features. -> - Reply with specific issue numbers to select only certain features. -> - Reply **"não"** or **"no"** to stop here. +**⚠️ Do NOT close viable issues — they remain OPEN until the implementation PR closes them via commit message.** --- @@ -523,13 +565,24 @@ End the report with: > **⚠️ Do NOT enter this phase without explicit user approval from Phase 3.** -### 4.1 Create Task Directory +### 4.1 Pre-Plan Context Load (mandatory) + +Before writing ANY plan, read: + +1. `docs/architecture/REPOSITORY_MAP.md` — to know which directory owns what. +2. `docs/architecture/CODEBASE_DOCUMENTATION.md` — for the engineering reference. +3. The matching "Adding a New X" scenario from `CLAUDE.md` (provider, API route, DB module, MCP tool, A2A skill, cloud agent, embedded service, guardrail, eval, skill, webhook event). +4. Any docs linked from the requirements file's "External References" section. + +This ensures plans cite real paths and follow the established add-a-X recipe, instead of inventing structure. + +### 4.2 Create Task Directory ```bash mkdir -p <project_root>/_tasks/features-vX.Y.Z/ ``` -### 4.2 Generate One Implementation Plan Per Feature +### 4.3 Generate One Implementation Plan Per Feature For each VIABLE feature approved by the user, create: @@ -542,6 +595,7 @@ For each VIABLE feature approved by the user, create: > Idea: [\_ideia/viable/<NUMBER>-title.md](../../_ideia/viable/<NUMBER>-title.md) > Requirements: [\_ideia/viable/<NUMBER>-title.requirements.md](../../_ideia/viable/<NUMBER>-title.requirements.md) > Branch: `release/vX.Y.Z` +> Matching CLAUDE.md recipe: <e.g. "Adding a New Provider"> ## Overview @@ -550,8 +604,8 @@ For each VIABLE feature approved by the user, create: ## Pre-Implementation Checklist - [ ] Read all related source files listed below -- [ ] Confirm no conflicts with in-flight PRs -- [ ] Verify database migration numbering +- [ ] Confirm no conflicts with in-flight PRs (re-run Phase 1.6 lookup) +- [ ] Verify database migration numbering (next free integer in `src/lib/db/migrations/`) ## Implementation Steps @@ -568,7 +622,7 @@ For each VIABLE feature approved by the user, create: ... -### Step N: Tests +### Step N: Tests (MANDATORY per CLAUDE.md hard rule #8) **New test files:** @@ -578,6 +632,7 @@ For each VIABLE feature approved by the user, create: - [ ] <test case 1> - [ ] <test case 2> +- [ ] Coverage check: confirm overall coverage stays ≥75% statements/lines/functions, ≥70% branches (hard rule #9) ### Step N+1: i18n @@ -587,36 +642,41 @@ For each VIABLE feature approved by the user, create: ### Step N+2: Documentation -- [ ] Update CHANGELOG.md +- [ ] Update CHANGELOG.md (current release section) - [ ] Update relevant docs/ files +- [ ] If touching error responses, follow `docs/security/ERROR_SANITIZATION.md` +- [ ] If touching upstream credentials, follow `docs/security/PUBLIC_CREDS.md` -## Verification Plan +## Verification Plan (Trust-but-Verify — mandatory before declaring done) -1. Run `npm run build` — must pass -2. Run `npm test` — all tests must pass -3. Run `npm run lint` — no new errors -4. <Manual verification steps> +1. `git status` + `git diff --stat` — review every changed file; flag anything outside the plan's declared scope +2. `npm run lint` — 0 new errors +3. `npm run typecheck:core` — clean +4. `npm run typecheck:noimplicit:core` — clean +5. `npm run check:cycles` — no new circular deps +6. `npm run build` — must pass +7. `npm run test:coverage` — coverage gate respected +8. `npm run check-docs-sync` (via pre-commit hook) — passes +9. Manual UI verification if the feature touches frontend (start dev server, exercise golden path + 1 edge case) ## Commit Plan -``` +``` feat: <description> (#<NUMBER>) - +``` ``` -``` - -### 4.3 Present Plans for Final Approval +### 4.4 Present Plans for Final Approval Present a summary of all generated plans: > **Implementation plans generated:** > -> | # | Feature | Plan File | Steps | Effort | -> | --- | ------- | ---------------------------------------- | ------- | ------ | -> | 1 | <title> | `_tasks/features-vX.Y.Z/N-title.plan.md` | N steps | Medium | +> | # | Feature | Plan File | Steps | Effort | CLAUDE.md recipe | +> | --- | ------- | ---------------------------------------- | ------- | ------ | ---------------------- | +> | 1 | <title> | `_tasks/features-vX.Y.Z/N-title.plan.md` | N steps | Medium | Adding a New Provider | > -> Reply **"sim"** or **"yes"** to begin implementation of all features. +> Reply **"sim"** / **"yes"** to begin implementation of all features. > Reply with specific issue numbers to implement only certain ones. --- @@ -630,17 +690,62 @@ Present a summary of all generated plans: For each approved plan, execute it step by step: 1. **Follow the plan** — implement exactly as specified in the `.plan.md` file -2. **Build** — Run `npm run build` after each feature to verify compilation -3. **Test** — Run `npm test` to ensure no regressions -4. **Commit** — Commit with: `feat: <description> (#<NUMBER>)` -5. **Update the plan** — Mark completed steps with `[x]` in the plan file -6. **Continue** — Move to the next feature (do NOT switch branches) +2. **Mark progress** — flip checkboxes to `[x]` in the plan as each step completes -### 5.2 Respond to Authors (Update Viable Issues) +### 5.2 Trust-but-Verify Audit (mandatory before commit) -For each implemented feature, **close the issue with a final comment**: +> Aligned with `~/.claude/CLAUDE.md` global rule: never trust a subagent's summary alone. -````markdown +Run the full audit checklist from the plan's "Verification Plan" section AND inspect the diff yourself: + +```bash +git status +git diff --stat +git diff # full diff, scan for out-of-scope changes +npm run lint +npm run typecheck:core +npm run typecheck:noimplicit:core +npm run check:cycles +npm run build +npm run test:coverage +``` + +**Block-on-failure checklist:** + +- [ ] No files changed outside the plan's declared scope (or scope expansion explicitly justified) +- [ ] No deleted symbols/routes/files without a documented replacement (grep to confirm) +- [ ] No weakened or removed test assertions (only additions or alignments with real behavior) +- [ ] Coverage gate green (75/75/75/70) +- [ ] All commands above exit 0 +- [ ] If UI was touched: manual smoke test passed and noted + +If any item fails, **fix root cause** before committing. Do NOT bypass with `--no-verify` (hard rule #10). + +### 5.3 Commit (one feature, one commit) + +```bash +git add <only files in the plan> +git commit -m "feat: <description> (#<NUMBER>)" +``` + +> **No `Co-Authored-By` trailers** (hard rule #16). Commits go solely under `diegosouzapw`. + +Then move (do NOT delete yet) the idea file to `_ideia/implemented/`: + +```bash +mv _ideia/viable/<NUMBER>-<title>.md _ideia/implemented/ +mv _ideia/viable/<NUMBER>-<title>.requirements.md _ideia/implemented/ 2>/dev/null || true +``` + +> **Why move, not delete?** If the release PR is reverted or rebased, we still have the context. The file is deleted only after the PR merges to `main` (see 5.6). + +Continue to the next feature on the same branch — do NOT switch branches between features. + +### 5.4 Respond to Authors + +For each implemented feature, post a final close-comment **translated into the issue's `reply_lang`**: + +```markdown ✅ **Implemented in `release/vX.Y.Z`!** Hi @<author>! Great news — your feature request has been implemented! 🎉 @@ -649,58 +754,59 @@ Hi @<author>! Great news — your feature request has been implemented! 🎉 - <bullet list of what was built> -**How to try it:** +**How to try it (after the release PR merges):** ```bash -git fetch origin && git checkout release/vX.Y.Z +git fetch origin && git checkout main && git pull npm install && npm run dev ``` -```` This will be included in the upcoming **vX.Y.Z** release. Feel free to reopen if you spot any issues! 🚀 - -```` - -```bash -gh issue close <NUMBER> --repo <owner>/<repo> --comment "<comment above>" -```` - -Then **DELETE the idea file** — it has served its purpose: - -```bash -# ✅ Implemented files are DELETED (not moved) -rm _ideia/viable/<NUMBER>-<title>.md -rm _ideia/viable/<NUMBER>-<title>.requirements.md # if exists ``` -> **Why delete?** `viable/` only holds features that still NEED to be done. Once implemented, the commit history and CHANGELOG are the source of truth. Keeping the file would be confusing. +```bash +gh issue close <NUMBER> --repo <owner>/<repo> --comment "<translated comment>" +``` -### 5.3 Finalize & Push +### 5.5 Finalize the Release Branch After implementing all approved features: 1. **Update CHANGELOG.md** on the release branch with all new feature entries -2. Push the release branch: `git push origin release/vX.Y.Z` -3. Run `/generate-release` workflow Phase 1 steps 7–10 (tests → commit → push → open PR to main → wait for user) +2. Push: `git push origin release/vX.Y.Z` +3. Hand off to `/generate-release` for the "Tests → Commit → Push → PR to main" stage. Refer to it **by stage name**, not step number, so this command does not break if `/generate-release` renumbers steps. -### 5.4 Final Summary Report +### 5.6 Post-Merge Cleanup (only after release PR merges to main) + +Once the release PR is merged: + +```bash +# Now safe to delete — commit history + CHANGELOG are the source of truth +rm _ideia/implemented/<NUMBER>-*.md +``` + +> If running this command before the merge: STOP at 5.5 and skip 5.6. Re-enter the workflow later just for the cleanup. + +### 5.7 Final Summary Report Present a final summary report to the user: | Issue | Title | Verdict | Action | Commit | | ----- | ----- | --------------- | -------------------------------------------------- | --------- | -| #N | Title | ✅ Implemented | Issue closed, idea file deleted | `abc1234` | +| #N | Title | ✅ Implemented | Issue closed, idea file in `_ideia/implemented/` | `abc1234` | | #N | Title | ⏭️ Deferred | Issue closed + saved in `_ideia/defer/` | — | | #N | Title | ❌ Not Fit | Issue closed + saved in `_ideia/notfit/` | — | | #N | Title | 🔁 Exists | Issue closed + saved in `_ideia/notfit/` | — | | #N | Title | ❓ Needs Detail | Issue OPEN, moved to `_ideia/viable/need_details/` | — | +| #N | Title | 🚧 In Flight | Untouched — tracked by PR #M | — | Include: - Total features harvested - Total ideas cataloged (`viable/need_details/` + `defer/` + `notfit/`) -- Total features implemented (idea files deleted, issues closed) +- Total features implemented (idea files in `_ideia/implemented/`, awaiting post-merge cleanup) - Total features deferred - Total issues closed -- Total issues left open (needs detail only — viable are closed after implementation) -- Test results (pass/fail count) +- Total issues left open (NEEDS DETAIL + VIABLE-pending-implementation + IN FLIGHT) +- Audit results: lint / typecheck / cycles / build / coverage (pass-count per phase) +- Languages used in posted comments (e.g. "3× pt-BR, 5× en, 1× es") diff --git a/.claude/commands/resolve-issues-cc.md b/.claude/commands/resolve-issues-cc.md index 01f8f68879..2f409919d6 100644 --- a/.claude/commands/resolve-issues-cc.md +++ b/.claude/commands/resolve-issues-cc.md @@ -1,17 +1,20 @@ --- -description: Fetch all open GitHub issues, analyze bugs, resolve what's possible, triage the rest, wait for user validation, then commit and release +description: Fetch all open GitHub issues, analyze bugs, resolve up to 30 per batch via per-issue worktrees + PRs into the release branch, triage the rest, wait for user validation +allowed-tools: Bash, Read, Edit, Write, Grep, Glob, WebFetch, WebSearch, AskUserQuestion, Agent --- # /resolve-issues — Automated Issue Resolution Workflow ## Overview -This workflow fetches all open issues from the project's GitHub repository, classifies them, analyzes bugs, proposes a resolution plan, waits for user validation, and ONLY THEN implements the fixes, commits, and closes the issues on the current release branch (`release/vX.Y.Z`). It does NOT merge or release automatically — the release branch is later merged via PR to main. +This workflow fetches all open issues from the project's GitHub repository, classifies them, analyzes bugs, proposes a resolution plan, waits for user validation, and ONLY THEN implements fixes. The current `release/vX.Y.Z` branch is the integration target — each individual fix is implemented on its own short-lived `fix/<issue>-<short>` branch inside its own git worktree, merged into the release branch via PR, then the worktree and local branch are deleted. The release branch is later merged to `main` via `/generate-release`. -> **BRANCH RULE**: All work MUST happen on the current `release/vX.Y.Z` branch. Never create separate `fix/` branches. If no release branch exists yet, create one first using `/generate-release` Phase 1 steps 1–5. +> **BRANCH RULE**: The current `release/vX.Y.Z` branch is the integration target. Each fix MUST live on its own `fix/<ISSUE>-<short>` branch cut from the release branch, inside its own worktree under `.worktrees/`. After the per-issue PR is merged into the release branch, the worktree and local branch are deleted. Never commit fixes directly to the release branch. If no release branch exists yet, create one first using `/generate-release` Phase 1 steps 1–5. > **⛔ PR PROHIBITION**: If a fix is associated with a contributor's PR, you MUST merge their PR — NEVER close it and re-implement the fix yourself. See `/review-prs` workflow for the full policy. The `gh pr close` command is FORBIDDEN unless the repository owner explicitly requests it. +> **🌐 REPLY LANGUAGE**: All comments posted to issues (close messages, RESPOND comments, PR descriptions visible to the reporter) MUST match the reporter's language. When in doubt, default to **English**. The reporter's language is detected from the issue body and prior comments by that author. + ## Steps ### 1. Identify the GitHub Repository @@ -25,40 +28,45 @@ This workflow fetches all open issues from the project's GitHub repository, clas // turbo -Before doing any work, ensure you are on the current release branch: +Before doing any work, ensure a `release/vX.Y.Z` branch exists. If you are currently on `main`, create one: ```bash -# Check current branch git branch --show-current # If on main, determine next version and create the release branch VERSION=$(node -p "require('./package.json').version") -NEXT=$(node -p "const [a,b,c]=('$VERSION').split('.').map(Number); c>=9?a+'.'+(b+1)+'.0':a+'.'+b+'.'+(c+1)") +NEXT=$(node -p "const [a,b,c]=('$VERSION').split('.').map(Number); c>=999?a+'.'+(b+1)+'.0':a+'.'+b+'.'+(c+1)") git checkout -b release/v$NEXT npm version patch --no-git-tag-version npm install ``` +> Threshold: patches climb to `.999` before rolling. Example: `3.4.999` → `3.5.0`. + If already on a `release/vX.Y.Z` branch, continue working there. -### 3. Fetch All Open Issues +### 3. Fetch All Open Issues (cap 30 per batch) // turbo-all -**⚠️ CRITICAL**: The JSON output of `gh issue list` can be truncated by the tool, silently hiding issues. You MUST use the two-step approach below to guarantee **all** issues are fetched. +**⚠️ CRITICAL**: The JSON output of `gh issue list` can be truncated by the tool, silently hiding issues. Use the two-step approach below. **Step 3a — Get Issue numbers only** (small output, never truncated): - Run: `gh issue list --repo <owner>/<repo> --state open --limit 500 --json number --jq '.[].number'` -- This outputs one issue number per line. Count them and confirm total. +- Count them and remember the total. -**Step 3b — Fetch full metadata for each Issue** (one call per issue): +**Step 3b — Fetch full metadata for each Issue** (parallel, validated against 3a): - For each issue number from step 3a, run: - `gh issue view <NUMBER> --repo <owner>/<repo> --json number,title,labels,body,comments,createdAt,author` -- You may batch these into parallel calls (up to 4 at a time). + `gh issue view <NUMBER> --repo <owner>/<repo> --json number,title,labels,body,comments,createdAt,author,url` +- Batch in parallel (8–12 concurrent calls). After completion, assert `fetched_count == count_from_3a`; if mismatch, retry the missing IDs. - Sort by oldest first (FIFO). +**Step 3c — Cap at 30 per run**: + +- If more than 30 open issues qualify as bugs after step 4, ask the user (via AskUserQuestion) which subset of up to 30 to handle now. The remainder is deferred to the next run. + ### 4. Classify Each Issue For each issue, determine its type: @@ -68,99 +76,187 @@ For each issue, determine its type: - **Question** — Has `question` label, or is asking "how to" something - **Other** — Anything else -Focus ONLY on **Bugs** for resolution. Feature requests and questions should be skipped with a note in the final report. +Focus ONLY on **Bugs** for resolution. Feature requests and questions are skipped with a note in the final report. + +#### 4.5. PR-Linked Check (mandatory) + +For every bug, query linked PRs: + +```bash +gh issue view <NUMBER> --repo <owner>/<repo> --json closedByPullRequestsReferences,body +``` + +If the issue is referenced by an **open** contributor PR (or the body links to one), do NOT plan a self-implemented fix. Mark the issue as `🤝 PR-LINKED — redirect to /review-prs` in the report and stop deeper analysis for it. **NEVER close the contributor PR.** ### 5. Deep-Read Each Bug Issue (One-by-One Analysis) -**IMPORTANT**: Read each bug issue thoroughly, one at a time, before moving to the next. This is NOT a batch process — each issue needs focused attention. +Read each bug issue thoroughly, one at a time. Each issue gets focused attention. #### 5a. Understand the Problem -For each bug issue, perform the full analysis: - -1. **Read the entire body** — including Description, Steps to Reproduce, Expected/Actual Behavior, Error Logs, and Screenshots -2. **Read ALL comments** — including bot triage comments (Kilo, etc.) and owner/community responses. Pay attention to: - - Whether someone already responded with a fix - - Whether a community member confirmed the issue is resolved - - Whether the issue was marked as duplicate by a bot. **WARNING: DO NOT blindly trust bot duplicate labels (e.g., kilo-duplicate). Bots make mistakes. You MUST read the full conversation and do your own independent analysis to determine if it is truly a duplicate or a distinct bug.** -3. **Identify the claimed error** — extract the exact error message, status code, and provider/model involved +1. **Read the entire body** — Description, Steps to Reproduce, Expected/Actual Behavior, Error Logs, Screenshots +2. **Read ALL comments** — bot triage (Kilo, etc.) and owner/community responses. Look for: + - Someone already responded with a fix + - Community member confirmed it is resolved + - Bot duplicate flag. **DO NOT blindly trust bot labels (e.g., `kilo-duplicate`).** Re-verify independently from current source + web research. +3. **Identify the claimed error** — exact error message, status code, provider/model, OS, Node version. #### 5b. Check Information Sufficiency -Verify the issue contains enough to act on: +Verify the issue contains: - [ ] Clear description of the problem - [ ] Steps to reproduce OR error logs - [ ] Provider/model/version information - [ ] Expected vs actual behavior -#### 5c. Determine Issue Disposition +**If ANY item is missing → auto-classify as `📝 RESPOND — Needs Info` and skip 5d.** Do not attempt root-cause analysis on under-specified issues. -For each bug, classify into one of 5 actions: +#### 5c. Determine Issue Disposition | Disposition | When to Apply | Action | | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- | | **✅ CLOSE — Already Fixed** | Owner responded with fix + no user follow-up, OR community confirmed fix | Close with comment citing which version fixed it | | **✅ CLOSE — Duplicate** | You have independently verified the issue is a duplicate (do NOT rely solely on bot flags) + user provides no new info | Close referencing the original issue | | **✅ CLOSE — Stale** | We requested logs/info > 7 days ago with no reply | Close thanking the user, invite to reopen if needed | -| **📝 RESPOND — Needs Info** | Issue is real but missing critical reproduction details | Comment asking for specifics per `/issue-triage` | +| **📝 RESPOND — Needs Info** | Issue is real but missing critical reproduction details (also triggered by 5b) | Comment asking for specifics per `/issue-triage` | | **📝 RESPOND — User Config** | Error is caused by unsupported env (Node version, wrong model path, missing API enablement) | Comment explaining the user-side fix | +| **🤝 PR-LINKED** | An open contributor PR already targets this issue (from step 4.5) | Redirect to `/review-prs`; do not re-implement | | **🔧 FIX — Code Change** | Root cause is confirmed in the codebase | Research, propose solution in report, wait for approval | #### 5d. For "FIX — Code Change" Issues -Before coding, perform deep source analysis to formulate a plan: +Before coding, perform deep source analysis: -1. **Search the codebase** — `grep_search` for error strings, relevant function names, affected files -2. **Search the web** — for upstream API changes, SDK updates, or breaking changes that explain the bug -3. **Read the full source file** — don't rely on grep snippets; understand the surrounding logic -4. **Verify the root cause** — confirm the bug is reproducible based on the code, not just a user misconfiguration -5. **Formulate a proposed solution** — detail the exact files and lines you will change and how you will solve it. -6. **Create an Implementation Plan file** — write your proposed solution to `_tasks/features-vX.Y.Z/<ISSUE_NUMBER>-<short-description>.plan.md` (e.g. `_tasks/features-v3.7.6/1810-auto-restore-probe-failed-db.plan.md`) where `vX.Y.Z` is the current branch version. The plan should contain an Overview, Pre-Implementation Checklist, and detailed Implementation Steps (Files, Changes). -7. **DO NOT modify the codebase yet** — wait for user approval on your report and plan first. +1. **Search the codebase** — `grep`/`Grep` for error strings, function names, affected files +2. **Search the web** — upstream API changes, SDK updates, breaking changes +3. **Read the full source file** — don't rely on grep snippets +4. **Verify the root cause** is in our code, not user misconfiguration +5. **Formulate a proposed solution** — exact files/lines/logic +6. **Create an Implementation Plan file** at `_tasks/fixes-vX.Y.Z/<ISSUE>-<short-description>.plan.md` (`vX.Y.Z` = current release branch version). Create the directory first: `mkdir -p _tasks/fixes-vX.Y.Z`. The plan contains: Overview, Reproduction Steps, Regression Test Outline, Implementation Steps (files/changes), Rollout Notes. +7. **DO NOT modify the codebase yet** — wait for user approval. #### 5e. For "RESPOND" Issues Post a substantive comment that: -- Acknowledges the specific error they reported +- Acknowledges the specific error reported - Explains the likely root cause -- Provides concrete steps to resolve (version upgrade, env var fix, model path correction) +- Provides concrete steps (version upgrade, env var fix, model path correction) - Asks for follow-up info if needed -**Do NOT post generic template responses.** Every comment should reference the user's specific error messages and environment. +**No generic templates.** Every comment references the user's specific error and environment, and is written in the reporter's language (English default). ### 6. Generate Report & Wait for Validation -Present a summary report to the user detailing your proposed actions. For any bugs that need fixing, explicitly explain your proposed solution (files to change and logic) and point out that it will be implemented on the release branch (`release/vX.Y.Z`) after approval. +Present a summary report. For FIX bugs, explicitly explain the proposed solution (files to change + logic) and confirm it will land via per-issue worktree → PR → release branch after approval. Include the reporter's detected language per row so the user can verify. -| Issue | Title | Status | Proposed Action / Version | -| ----- | ----- | ------------- | ----------------------------------------- | -| #N | Title | ✅ Close | Already fixed / duplicate (explain why) | -| #N | Title | 🔧 Propose | Explanation of the code fix to be applied | -| #N | Title | 📝 Respond | Guidance comment to be posted | -| #N | Title | ❓ Needs Info | Triage comment to be posted | -| #N | Title | ⏭️ Skip | Feature request / not a bug | +| Issue | Title | Status | Reply Lang | Proposed Action / Version | +| ----- | ----- | -------------- | ---------- | ------------------------------------------ | +| #N | Title | ✅ Close | en | Already fixed / duplicate (explain why) | +| #N | Title | 🔧 Propose | pt-BR | Code fix plan summary + worktree branch | +| #N | Title | 📝 Respond | en | Guidance comment to be posted | +| #N | Title | ❓ Needs Info | en | Triage comment to be posted | +| #N | Title | 🤝 PR-Linked | en | Redirect to /review-prs (PR #M) | +| #N | Title | ⏭️ Skip | — | Feature request / not a bug | > **⚠️ IMPORTANT**: Do NOT implement code changes, commit, push, or close issues at this step. > Wait for the user to review the proposed fixes and respond with **OK** before proceeding. -- If the user says **OK** or approves → Proceed to step 7 -- If the user requests changes → Adjust the proposed solution and present the report again +- If the user says **OK** → Proceed to step 7 +- If the user requests changes → Adjust and re-present the report - If the user rejects → Revert any accidental changes and stop -### 7. Implement Fixes, Run Tests & Commit (only after user approval) +### 7. Implement Fixes via Per-Issue Worktrees + PRs (only after user approval) -After the user validates and gives the OK: +For each approved FIX issue (up to 30 per batch), repeat the following sequence. Issues can be processed sequentially or in parallel (one worktree each — never two fixes in the same worktree). -1. **Implement the fixes** — modify the codebase according to the approved plan. -2. **Run tests** — `npm run test:all` (or the specific test file) to ensure 100% pass. -3. **Update CHANGELOG.md** with all new bug fix entries. -4. **Commit** each fix individually on the release branch with message format: `fix: <description> (#<issue_number>)`. -5. **Push** the release branch: `git push origin release/vX.Y.Z`. -6. **Close resolved issues immediately**. For each issue that was marked as Fixed, run: - `gh issue close <NUMBER> --repo <owner>/<repo> --comment "Thank you for reporting! This issue has been fixed and will be included in the next release (vX.Y.Z)."` -7. Likewise, close `Duplicate` issues referencing the original, close `Needs Info` if stale, and post the required comments. -8. If the project runs automatic releases or needs a PR, proceed to run `/generate-release` workflow Phase 1 steps 7–10 (tests → commit → push → open PR to main → wait for user). +#### 7.1. Spin up an isolated worktree on a fresh fix branch -If NO fixes were committed, skip closing and source control steps and just conclude the workflow. +```bash +ISSUE=<NUMBER> +SHORT=<short-kebab-desc> +RELEASE_BRANCH=$(git -C <project_root> branch --show-current) # release/vX.Y.Z +WT_DIR=".worktrees/fix-${ISSUE}-${SHORT}" +BRANCH="fix/${ISSUE}-${SHORT}" + +git fetch origin "$RELEASE_BRANCH" +git worktree add "$WT_DIR" -b "$BRANCH" "origin/$RELEASE_BRANCH" +cd "$WT_DIR" +``` + +#### 7.2. Write the regression test first (TDD) + +- Author a unit/integration test that reproduces the bug. **It must fail on the unfixed code.** Run it and confirm the failure. +- Hard rule #8: any production change must ship with tests in the same PR. The regression test is non-negotiable. + +#### 7.3. Implement the fix + +- Apply the approved plan from `_tasks/fixes-vX.Y.Z/<ISSUE>-<short>.plan.md`. +- Keep the diff scoped to this issue. No drive-by refactors. + +#### 7.4. Run the test suite + +- `npm run test:all` (or the appropriate suite for the touched area; the regression test MUST be included). +- All tests must pass before commit. Also run the relevant `lint` / `typecheck` per CLAUDE.md trust-but-verify checklist. + +#### 7.5. Update CHANGELOG.md and commit (single commit, same diff) + +- Add the new bug-fix entry under the current `vX.Y.Z` section of CHANGELOG.md. +- CHANGELOG entry + code + test go in **one** commit on the fix branch: + +```bash +git add <changed files> CHANGELOG.md +git commit -m "fix: <description> (#${ISSUE})" +``` + +#### 7.6. Push and open a PR into the release branch + +```bash +git push -u origin "$BRANCH" +gh pr create \ + --base "$RELEASE_BRANCH" \ + --head "$BRANCH" \ + --title "fix: <description> (#${ISSUE})" \ + --body "Closes #${ISSUE}\n\n<short summary, plan link, regression test reference>" +``` + +#### 7.7. Merge the PR into the release branch + +- Wait for CI green, then merge with the project's default merge strategy. +- The PR title becomes the release-branch commit. + +#### 7.8. Clean up worktree and local branch + +```bash +cd <project_root> +git worktree remove "$WT_DIR" +git branch -D "$BRANCH" +``` + +#### 7.9. Close the issue with a localized comment + +Match the reporter's language (English default). Template: + +> **EN**: Thanks for reporting! Fixed in `release/vX.Y.Z` (already merged into the active development branch — feel free to pull and test it now). It will ship in the next release (vX.Y.Z). +> +> **pt-BR**: Obrigado pelo report! Corrigido em `release/vX.Y.Z` (já mergeado na branch de desenvolvimento atual — pode dar pull e testar). Vai sair na próxima release (vX.Y.Z). + +```bash +gh issue close "$ISSUE" --repo <owner>/<repo> --comment "<localized message above>" +``` + +#### 7.10. Close non-FIX dispositions + +After all FIX issues are merged: + +- `Duplicate`: close referencing the original issue (localized). +- `Stale`: close thanking the user and inviting reopen (localized). +- `RESPOND — Needs Info` / `RESPOND — User Config`: post the substantive comment from 5e (localized). +- `PR-LINKED`: leave the issue open; comment redirecting to the contributor PR if not already linked. + +#### 7.11. Hand off to release flow (optional) + +If a release PR to `main` is desired now, run `/generate-release` Phase 1 steps 7–10 (tests → commit version bump → push → open PR to main → wait for user). + +If NO fixes were committed, skip 7.7–7.11 and just conclude the workflow. diff --git a/.claude/commands/review-discussions-cc.md b/.claude/commands/review-discussions-cc.md index fc8630ffcb..a6045b6f7e 100644 --- a/.claude/commands/review-discussions-cc.md +++ b/.claude/commands/review-discussions-cc.md @@ -1,14 +1,19 @@ --- -description: Read all open GitHub Discussions, summarize them, respond to pending ones, and create issues from actionable feature requests +description: Read all open GitHub Discussions, summarize them, respond to pending ones, create issues from actionable feature requests, and triage stale threads for closure --- # /review-discussions — GitHub Discussions Review & Response Workflow ## Overview -This workflow reads all open GitHub Discussions, generates a categorized summary, identifies which ones need a response, drafts and posts replies, and optionally creates issues from actionable feature requests. It follows the same flow used for Issues but adapted for the Discussions forum. +This workflow reads all open GitHub Discussions, generates a categorized summary, identifies which ones need a response, drafts and posts replies, optionally creates issues from actionable feature requests, and triages stale threads for closure. -> **Tool mapping note (v3.8):** Where steps below say `browser_subagent` (an earlier-runtime tool), in Claude Code use the `gh` CLI via the `Bash` tool — `gh api graphql` for reading discussions and `gh api graphql -F query=...` mutations for posting comments. `WebFetch` is acceptable for read-only HTML scraping when GraphQL is overkill, but prefer `gh` for any write actions. +**Modern tooling (replaces deprecated `browser_subagent` flow):** + +- Reads use `gh api graphql` — one query returns 50 discussions with full bodies, comments, replies, IDs, and `updatedAt`. +- Writes (post comment, create issue, close discussion) use `gh api graphql` mutations or `gh issue create`. +- Pace at ~1s between writes to avoid abuse-detection throttling. +- `WebFetch` is acceptable only for read-only HTML scraping when GraphQL is unavailable — never for write actions. // turbo-all @@ -16,14 +21,16 @@ This workflow reads all open GitHub Discussions, generates a categorized summary ### 1. Identify the GitHub Repository -- Run: `git -C <project_root> remote get-url origin` to extract the owner/repo -- Parse the owner and repo name from the URL +- Run: `git -C <project_root> remote get-url origin` to extract `owner/repo`. +- Parse owner and repo name from the URL (https or ssh form). -### 2. Fetch All Open Discussions +### 2. Fetch All Open Discussions (single GraphQL query) -- Use `WebFetch` to fetch `https://github.com/<owner>/<repo>/discussions` -- Parse the discussion list to get all discussion titles, IDs, authors, categories, and dates -- For each discussion, fetch the individual page to read the full content and all comments/replies +Single `gh api graphql` call — return everything needed for triage. Critical fields: `id` (node ID, **not** the visible `number`), `number`, `title`, `url`, `createdAt`, `updatedAt`, `author.login`, `category.name`, `body`, `answerChosenAt`, plus nested `comments(first: 50) { totalCount, nodes { id, author.login, body, createdAt, replies(first: 20) { nodes { author.login, body, createdAt } } } }`. + +Persist the raw JSON to `/tmp/discussions-<repo>-<date>.json` so re-runs in the same session avoid a re-fetch. Build an `id → number` map for the post phase — the GraphQL `addDiscussionComment` mutation requires the node ID, not the number. + +Capture **image attachments** present in body or comments (`<img src="...">` or markdown `![...](...)`). Surface their count in the per-discussion summary (e.g., `📷 3 screenshots`) so the user can decide if visual context matters before approving a draft. ### 3. Summarize All Discussions @@ -32,89 +39,229 @@ For each discussion, extract: - **Title** and **#Number** - **Author** (GitHub username) - **Category** (Announcements, General, Ideas, Q&A, Show and tell) -- **Date** created -- **Summary** of the original post (1-2 sentences) -- **Comments count** and key participants -- **Your previous response** (if any) -- **Pending action** — whether a response or follow-up is needed +- **Created** + **Last updated** (ISO date) +- **Summary** of original post (1-2 sentences) +- **Comment count** + **last commenter** + **last comment date** +- **Maintainer involvement**: whether the repo owner already replied, and how many times +- **Pending action** — derived state, see categories below +- **Attachments**: count of screenshots / videos / pastebin links +- **Detected language** of the reporter (for reply-language matching) ### 4. Present Summary Report to User -Present the full summary to the user organized by category, using a table: +Group by **pending action**, not by category, so the human sees triage buckets at a glance: -| # | Category | Title | Author | Date | Status | -| --- | -------- | ----- | ------ | ------ | ----------------- | -| #N | Ideas | Title | @user | Mar 23 | ⚠️ Needs response | -| #N | Q&A | Title | @user | Mar 9 | ✅ Answered | -| #N | General | Title | @user | Mar 19 | ⚠️ Needs response | +| State | Meaning | +| ----------------------- | ---------------------------------------------------------------------------------------------------------------- | +| ⚠️ Needs first response | Zero comments, or all comments are from non-maintainers | +| 🔄 Follow-up pending | Maintainer replied, but reporter or third party added a new comment maintainer has not addressed | +| 🕒 Stale (>15d) | Maintainer was last to comment, no activity for 15+ days — candidate for soft-close or reporter-ping (see step 8)| +| ✅ Answered | Maintainer already replied AND last commenter is the maintainer AND age < 15d | +| 🏁 Resolved | `answerChosenAt` is set | -Highlight: +Within each bucket, present a table: -- **⚠️ Needs response** — No reply from maintainer, or a follow-up comment was left unanswered -- **✅ Answered** — Maintainer already responded -- **🐛 Bug reported** — A bug was mentioned that needs tracking -- **💡 Actionable** — Contains a concrete feature request that could become an issue +| # | Category | Title | Author | Updated | Notes | +| --- | -------- | ------------------ | ------ | ------- | ---------------------- | +| #N | Q&A | short title (60ch) | @user | YYYY-MM-DD | 📷2 · 🐛bug · 💡FR | + +Tag rows with content hints when detected: `🐛bug` (`[BUG]` / `error` / stacktrace in body), `💡FR` (`feature request` / `add support for`), `❓support` (config/usage question), `🙏thanks` (short ack-only follow-up). ### 5. Draft & Post Responses -For each discussion that needs a response, draft a reply following these guidelines: +#### Reply templates by intent -#### Response Style +Pick the template that matches the discussion intent — do NOT use a single generic format. -- **Friendly and professional** — Start with "Hey @username!" -- **Acknowledge the contribution** — Thank the user for their input -- **Be specific** — Reference existing features, settings, or dashboard pages if the feature already exists -- **Provide workarounds** — If the request isn't implemented yet, suggest current alternatives -- **Commit to action** — If the request is valid, state that you'll open an issue or add it to the roadmap -- **Keep it concise** — 3-5 paragraphs max +**A. Bug confirmed** — ack + root cause + tracking + workaround +``` +Hey @user! Confirmed -- {root cause in one sentence}. I traced it to `path/to/file.ts:line`. -#### Posting via Browser +{Why it happens: 2-4 sentences of technical detail} -- Use `browser_subagent` to navigate to each discussion and post the comment -- **IMPORTANT**: When typing text in GitHub comment boxes via the browser, use only plain ASCII characters: - - Use regular hyphens `-` instead of em-dashes - - Use `->` instead of arrow symbols - - Do NOT use emoji Unicode characters (the browser keyboard may fail on them) - - Use `**bold**` and `\`code\`` markdown formatting -- Click the green "Comment" button (or "Reply" for threaded replies) after typing -- Verify the comment was posted by checking the page shows the new comment +I have opened {issue #N} to track the fix. Workaround until it ships: {concrete steps}. Will update here when the patch lands. +``` + +**B. Feature Request** — ack + status + scope + commit +``` +Hey @user! {Status: "Already exists" / "Tracked in #N" / "Reasonable, opening an issue"}. + +{If already exists: pointer to dashboard page or doc} +{If tracked: link to umbrella, summarize order/priority} +{If new: open issue + post link back} + +{Optional: short technical note on feasibility / trade-offs} +``` + +**C. Support / config question** — direct answer + reference + offer to dig deeper +``` +Hey @user! {One-sentence answer}. + +Steps: +1. ... +2. ... +3. ... + +Reference: `docs/<path>.md`. If it still fails after that, paste {specific thing} and I will trace it. +``` + +**D. Thank-you / short follow-up** — 1-2 sentences +``` +Glad it helps, @user! {Concrete next marker — when patch ships / when to expect next update}. +``` + +**E. Stale / closing** — see step 8 + +#### Posting via gh (replaces deprecated browser flow) + +```bash +gh api graphql -f query=' +mutation($id: ID!, $body: String!) { + addDiscussionComment(input: {discussionId: $id, body: $body}) { + comment { id url } + } +}' -f id="$NODE_ID" -f body="$BODY" +``` + +For **threaded replies** (recommended when responding to a specific comment in a long thread), add `replyToId: $parentCommentId` to the input. + +**Output hygiene** (still applies even via API — the comment renders in GitHub UI): + +- ASCII-safe punctuation: regular hyphens `-`, `->` for arrows +- Markdown OK: `**bold**`, fenced code blocks, `[text](url)` links +- No bare error messages with stack traces from internal logs — sanitize +- Match reporter's language (pt-BR reporter → pt-BR reply; ru reporter → ru reply); default to English when uncertain + +**Pacing**: `sleep 1` between mutations. GitHub abuse-detection trips around 10/sec for the same actor. + +**Verification**: capture the returned `comment.url` from each mutation. Failed posts (returncode != 0 or `errors` in response) get logged separately and retried once after a 5s pause. ### 6. Create Issues from Actionable Feature Requests For discussions that contain concrete, actionable feature requests: -1. Ask the user which ones should become issues -2. For each approved request, create a GitHub issue via `browser_subagent`: - - Navigate to `https://github.com/<owner>/<repo>/issues/new` - - **Title**: `<Feature Name> - <Short description>` - - **Body** should include: - - `## Feature Request` header - - `**Source:** Discussion #N by @author` - - `## Problem` — What limitation the user hit - - `## Proposed Solution` — How it could work - - `### Implementation Ideas` — Technical approach - - `### Current Workarounds` — What users can do today - - `## Additional Context` — Links to related issues/discussions - - Add `enhancement` label - - Click "Submit new issue" / "Create" -3. After creation, go back to the original discussion and post a comment linking to the new issue: - - "I've opened Issue #N to track this feature request. Follow along there for updates!" +1. **Deduplicate FIRST** — before drafting, search existing issues: + ```bash + gh issue list --repo $OWNER/$REPO --search "<keywords from FR>" --state open --json number,title,labels + ``` + If a matching issue (or umbrella) already exists, reuse it — never create a duplicate. Post a comment in the discussion linking to the existing issue. + +2. **Ask the user which to create** — even after dedup, the human approves the final list. + +3. **Create the issue** with `gh issue create`: + ```bash + gh issue create --repo $OWNER/$REPO \ + --title "[feature] <short imperative>" \ + --label enhancement \ + --body @/tmp/issue-body.md + ``` + Body template: + ```markdown + ## Feature Request + + **Source:** Discussion #N by @author + + ## Problem + What limitation the user hit (in their words, paraphrased) + + ## Proposed Solution + How it could work + + ### Implementation Ideas + - File paths likely to touch (use `Grep` if needed to confirm) + - Related modules / patterns already in the codebase + + ### Current Workarounds + What users can do today + + ## Additional Context + - Discussion: #N + - Related issues/PRs: #X, #Y + - Upstream references: link to similar implementations in `_references/` if applicable + ``` + +4. **Generate task file in `_ideia/`** when the feature needs deeper investigation before implementation: + ``` + _ideia/<short-kebab-slug>.md + ``` + Contains: problem statement, current OmniRoute state, how upstream (`_references/9router`, `_references/CLIProxyAPI`, etc.) handles it, proposed implementation levels (short/medium/long term), acceptance criteria. + +5. **Link back to discussion** with the real URL: + ``` + Follow-up @reporter — I've opened issue #N to track this. {1-line summary of what the issue covers}. + ``` ### 7. Final Report -Present a final summary to the user: +| Discussion | Action Taken | +| ---------- | ------------------------------------------------------------- | +| #N — Title | Responded (bug confirmed, tracking #M) | +| #N — Title | Responded + created issue #M + task file `_ideia/X.md` | +| #N — Title | Responded (support answered with workaround) | +| #N — Title | Responded to follow-up comment | +| #N — Title | Closed (stale 15+d, no reply from reporter) | +| #N — Title | Ping sent (stale 15+d, will close in 7d if no response) | -| Discussion | Action Taken | -| ---------- | ---------------------------------- | -| #N — Title | Responded with workarounds | -| #N — Title | Responded + created Issue #N | -| #N — Title | Already answered, no action needed | -| #N — Title | Responded to follow-up comment | +Include totals: comments posted, issues created, discussions closed, discussions pinged. Capture median response time for the batch. + +### 8. Stale Discussion Triage (auto-close candidates) + +Identify discussions matching **all** of: + +- `updatedAt > 15 days ago` +- Maintainer already replied at least once +- Last commenter is the maintainer (the ball is on the reporter's side) +- `answerChosenAt` is null (not formally resolved) +- Category in `{Q&A, General}` — skip `Ideas` / `Show and tell` / `Announcements` (those serve as community references and shouldn't be closed) +- `comments.totalCount >= 2` — there was actual conversation, not a drive-by post +- No label named `keep-open` (escape hatch) + +For each candidate, present to the user with a recommended action: + +| Action | When | +| --------------- | ----------------------------------------------------------------------------- | +| **Soft-close** | Default — maintainer answered concretely and reporter went silent | +| **Ping reporter** | Maintainer asked for more info (log dump, screenshot) and never got it | +| **Keep open** | Conversation is mid-debug and closing would lose context — operator override | + +**Soft-close mutation:** +```bash +gh api graphql -f query=' +mutation($id: ID!) { + closeDiscussion(input: {discussionId: $id, reason: RESOLVED}) { + discussion { id closed } + } +}' -f id="$NODE_ID" +``` +Valid `reason` values: `RESOLVED`, `OUTDATED`, `DUPLICATE`. Default to `OUTDATED` for "no response" closures, `RESOLVED` for answered-but-not-confirmed. + +Before closing, post a closing comment: +``` +Closing for inactivity -- feel free to reopen if you still hit this, or open a fresh issue with a current log. Thanks! +``` + +**Ping flow** (alternative): +``` +@reporter -- still happening on the latest version? Otherwise I'll close this in 7 days for inactivity. +``` +Persist the ping in `_cache/discussions-pinged-<date>.json` so the next run knows to close discussions that were pinged 7+ days ago without a reply. ## Notes -- This workflow is **interactive** — always present the summary and wait for user approval before posting responses or creating issues -- If the user says "pode responder" (or similar approval), proceed with posting all drafted responses -- For discussions in non-English languages, respond in the same language as the original post -- Always reference specific dashboard paths, config options, or code files when explaining existing features -- When a discussion reveals a bug, note it separately from feature requests +- This workflow is **interactive** — always present the summary and wait for user approval before posting responses, creating issues, or closing discussions. +- Use `AskUserQuestion` to gather batched approval — separate questions for "reply scope", "create issues for?", "close stale?". Stale handling is a separate consent from reply posting. +- For discussions in non-English languages (`pt-BR`, `ru`, `zh`, `es`), respond in the same language as the original post. Default to English when uncertain. +- Always reference specific dashboard paths, config options, doc files, or code locations (`file:line`) when explaining existing features — never wave hands. +- When a discussion reveals a bug, separate it from feature requests in the report. Bugs need a tracking issue + workaround; FRs need scoping. +- Before recommending a workaround that mentions a file/flag/setting, verify it exists in the **current** codebase (the previous turn's memory may be stale). +- Trust-but-verify: after a batch post, spot-check 2-3 random `comment.url` returns in the browser to confirm the comments rendered cleanly (no Unicode mojibake, no broken markdown). +- **Secure-by-default guidance** ([tldrsec/awesome-secure-defaults](https://github.com/tldrsec/awesome-secure-defaults)): when responses recommend security-relevant code (auth, crypto, SSRF, XSS sanitization), prefer well-tested libraries (Helmet.js, DOMPurify, Google Tink, ssrf-req-filter, safe-regex) over hand-rolled solutions. + +## Anti-patterns to avoid + +- ❌ Posting via `browser_subagent` clicks — slow, flaky, and obsolete since `gh api graphql` mutations exist. +- ❌ N+1 fetches (one per discussion) — use one GraphQL query for all 50. +- ❌ Creating an issue without checking for an existing umbrella / similar one first. +- ❌ Generic "thanks, I'll look into it!" responses — every reply must reference a file, doc, or concrete action. +- ❌ Closing a stale discussion without posting a closing comment first. +- ❌ Skipping the user approval gate ("turbo-all" never bypasses interactive consent for writes). diff --git a/.claude/commands/review-prs-cc.md b/.claude/commands/review-prs-cc.md index 64071d9c6f..5fb1566100 100644 --- a/.claude/commands/review-prs-cc.md +++ b/.claude/commands/review-prs-cc.md @@ -50,7 +50,7 @@ git branch --show-current # If on main, determine next version and create the release branch VERSION=$(node -p "require('./package.json').version") # Bump patch: e.g. 3.3.11 → 3.3.12 -NEXT=$(node -p "const [a,b,c]=('$VERSION').split('.').map(Number); c>=9?a+'.'+(b+1)+'.0':a+'.'+b+'.'+(c+1)") +NEXT=$(node -p "const [a,b,c]=('$VERSION').split('.').map(Number); c>=999?a+'.'+(b+1)+'.0':a+'.'+b+'.'+(c+1)") git checkout -b release/v$NEXT npm version patch --no-git-tag-version npm install diff --git a/.claude/commands/version-bump-cc.md b/.claude/commands/version-bump-cc.md index fbc63871ce..d9cf68c90c 100644 --- a/.claude/commands/version-bump-cc.md +++ b/.claude/commands/version-bump-cc.md @@ -9,7 +9,7 @@ Automatically bump the project version, generate CHANGELOG entries from git hist > **VERSION RULE: Always use PATCH bumps (3.x.y → 3.x.y+1)** > NEVER use `npm version minor` or `npm version major`. > Always use: `npm version patch --no-git-tag-version` -> The threshold rule: when `y` reaches 10, bump to `3.(x+1).0` — e.g. `3.4.10` → `3.5.0`. +> The threshold rule: when `y` reaches 1000, bump to `3.(x+1).0` — e.g. `3.4.999` → `3.5.0`. --- diff --git a/.source/browser.ts b/.source/browser.ts index c3bc050c5b..11f0eef61a 100644 --- a/.source/browser.ts +++ b/.source/browser.ts @@ -7,6 +7,6 @@ const create = browser<typeof Config, import("fumadocs-mdx/runtime/types").Inter } }>(); const browserCollections = { - docs: create.doc("docs", {"architecture/ARCHITECTURE.md": () => import("../docs/architecture/ARCHITECTURE.md?collection=docs"), "architecture/AUTHZ_GUIDE.md": () => import("../docs/architecture/AUTHZ_GUIDE.md?collection=docs"), "architecture/CODEBASE_DOCUMENTATION.md": () => import("../docs/architecture/CODEBASE_DOCUMENTATION.md?collection=docs"), "architecture/REPOSITORY_MAP.md": () => import("../docs/architecture/REPOSITORY_MAP.md?collection=docs"), "architecture/RESILIENCE_GUIDE.md": () => import("../docs/architecture/RESILIENCE_GUIDE.md?collection=docs"), "compression/COMPRESSION_ENGINES.md": () => import("../docs/compression/COMPRESSION_ENGINES.md?collection=docs"), "compression/COMPRESSION_GUIDE.md": () => import("../docs/compression/COMPRESSION_GUIDE.md?collection=docs"), "compression/COMPRESSION_LANGUAGE_PACKS.md": () => import("../docs/compression/COMPRESSION_LANGUAGE_PACKS.md?collection=docs"), "compression/COMPRESSION_RULES_FORMAT.md": () => import("../docs/compression/COMPRESSION_RULES_FORMAT.md?collection=docs"), "compression/RTK_COMPRESSION.md": () => import("../docs/compression/RTK_COMPRESSION.md?collection=docs"), "frameworks/A2A-SERVER.md": () => import("../docs/frameworks/A2A-SERVER.md?collection=docs"), "frameworks/AGENT_PROTOCOLS_GUIDE.md": () => import("../docs/frameworks/AGENT_PROTOCOLS_GUIDE.md?collection=docs"), "frameworks/CLOUD_AGENT.md": () => import("../docs/frameworks/CLOUD_AGENT.md?collection=docs"), "frameworks/EMBEDDED-SERVICES.md": () => import("../docs/frameworks/EMBEDDED-SERVICES.md?collection=docs"), "frameworks/EVALS.md": () => import("../docs/frameworks/EVALS.md?collection=docs"), "frameworks/GAMIFICATION.md": () => import("../docs/frameworks/GAMIFICATION.md?collection=docs"), "frameworks/MCP-SERVER.md": () => import("../docs/frameworks/MCP-SERVER.md?collection=docs"), "frameworks/MEMORY.md": () => import("../docs/frameworks/MEMORY.md?collection=docs"), "frameworks/OPENCODE.md": () => import("../docs/frameworks/OPENCODE.md?collection=docs"), "frameworks/SKILLS.md": () => import("../docs/frameworks/SKILLS.md?collection=docs"), "frameworks/WEBHOOKS.md": () => import("../docs/frameworks/WEBHOOKS.md?collection=docs"), "guides/DOCKER_GUIDE.md": () => import("../docs/guides/DOCKER_GUIDE.md?collection=docs"), "guides/ELECTRON_GUIDE.md": () => import("../docs/guides/ELECTRON_GUIDE.md?collection=docs"), "guides/FEATURES.md": () => import("../docs/guides/FEATURES.md?collection=docs"), "guides/I18N.md": () => import("../docs/guides/I18N.md?collection=docs"), "guides/KIRO_SETUP.md": () => import("../docs/guides/KIRO_SETUP.md?collection=docs"), "guides/PWA_GUIDE.md": () => import("../docs/guides/PWA_GUIDE.md?collection=docs"), "guides/SETUP_GUIDE.md": () => import("../docs/guides/SETUP_GUIDE.md?collection=docs"), "guides/TERMUX_GUIDE.md": () => import("../docs/guides/TERMUX_GUIDE.md?collection=docs"), "guides/TROUBLESHOOTING.md": () => import("../docs/guides/TROUBLESHOOTING.md?collection=docs"), "guides/UNINSTALL.md": () => import("../docs/guides/UNINSTALL.md?collection=docs"), "guides/USER_GUIDE.md": () => import("../docs/guides/USER_GUIDE.md?collection=docs"), "ops/COVERAGE_PLAN.md": () => import("../docs/ops/COVERAGE_PLAN.md?collection=docs"), "ops/E2E_DASHBOARD_SHAKEDOWN_v3.8.0.md": () => import("../docs/ops/E2E_DASHBOARD_SHAKEDOWN_v3.8.0.md?collection=docs"), "ops/FLY_IO_DEPLOYMENT_GUIDE.md": () => import("../docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md?collection=docs"), "ops/PROXY_GUIDE.md": () => import("../docs/ops/PROXY_GUIDE.md?collection=docs"), "ops/RELEASE_CHECKLIST.md": () => import("../docs/ops/RELEASE_CHECKLIST.md?collection=docs"), "ops/SQLITE_RUNTIME.md": () => import("../docs/ops/SQLITE_RUNTIME.md?collection=docs"), "ops/TUNNELS_GUIDE.md": () => import("../docs/ops/TUNNELS_GUIDE.md?collection=docs"), "ops/VM_DEPLOYMENT_GUIDE.md": () => import("../docs/ops/VM_DEPLOYMENT_GUIDE.md?collection=docs"), "reference/API_REFERENCE.md": () => import("../docs/reference/API_REFERENCE.md?collection=docs"), "reference/CLI-TOOLS.md": () => import("../docs/reference/CLI-TOOLS.md?collection=docs"), "reference/ENVIRONMENT.md": () => import("../docs/reference/ENVIRONMENT.md?collection=docs"), "reference/FREE_TIERS.md": () => import("../docs/reference/FREE_TIERS.md?collection=docs"), "reference/PROVIDER_REFERENCE.md": () => import("../docs/reference/PROVIDER_REFERENCE.md?collection=docs"), "routing/AUTO-COMBO.md": () => import("../docs/routing/AUTO-COMBO.md?collection=docs"), "routing/REASONING_REPLAY.md": () => import("../docs/routing/REASONING_REPLAY.md?collection=docs"), "security/CLI_TOKEN.md": () => import("../docs/security/CLI_TOKEN.md?collection=docs"), "security/CLI_TOKEN_AUTH.md": () => import("../docs/security/CLI_TOKEN_AUTH.md?collection=docs"), "security/COMPLIANCE.md": () => import("../docs/security/COMPLIANCE.md?collection=docs"), "security/ERROR_SANITIZATION.md": () => import("../docs/security/ERROR_SANITIZATION.md?collection=docs"), "security/GUARDRAILS.md": () => import("../docs/security/GUARDRAILS.md?collection=docs"), "security/PUBLIC_CREDS.md": () => import("../docs/security/PUBLIC_CREDS.md?collection=docs"), "security/ROUTE_GUARD_TIERS.md": () => import("../docs/security/ROUTE_GUARD_TIERS.md?collection=docs"), "security/STEALTH_GUIDE.md": () => import("../docs/security/STEALTH_GUIDE.md?collection=docs"), }), + docs: create.doc("docs", {"architecture/ARCHITECTURE.md": () => import("../docs/architecture/ARCHITECTURE.md?collection=docs"), "architecture/AUTHZ_GUIDE.md": () => import("../docs/architecture/AUTHZ_GUIDE.md?collection=docs"), "architecture/CODEBASE_DOCUMENTATION.md": () => import("../docs/architecture/CODEBASE_DOCUMENTATION.md?collection=docs"), "architecture/REPOSITORY_MAP.md": () => import("../docs/architecture/REPOSITORY_MAP.md?collection=docs"), "architecture/RESILIENCE_GUIDE.md": () => import("../docs/architecture/RESILIENCE_GUIDE.md?collection=docs"), "compression/COMPRESSION_ENGINES.md": () => import("../docs/compression/COMPRESSION_ENGINES.md?collection=docs"), "compression/COMPRESSION_GUIDE.md": () => import("../docs/compression/COMPRESSION_GUIDE.md?collection=docs"), "compression/COMPRESSION_LANGUAGE_PACKS.md": () => import("../docs/compression/COMPRESSION_LANGUAGE_PACKS.md?collection=docs"), "compression/COMPRESSION_RULES_FORMAT.md": () => import("../docs/compression/COMPRESSION_RULES_FORMAT.md?collection=docs"), "compression/RTK_COMPRESSION.md": () => import("../docs/compression/RTK_COMPRESSION.md?collection=docs"), "guides/DOCKER_GUIDE.md": () => import("../docs/guides/DOCKER_GUIDE.md?collection=docs"), "guides/ELECTRON_GUIDE.md": () => import("../docs/guides/ELECTRON_GUIDE.md?collection=docs"), "guides/FEATURES.md": () => import("../docs/guides/FEATURES.md?collection=docs"), "guides/I18N.md": () => import("../docs/guides/I18N.md?collection=docs"), "guides/KIRO_SETUP.md": () => import("../docs/guides/KIRO_SETUP.md?collection=docs"), "guides/PWA_GUIDE.md": () => import("../docs/guides/PWA_GUIDE.md?collection=docs"), "guides/SETUP_GUIDE.md": () => import("../docs/guides/SETUP_GUIDE.md?collection=docs"), "guides/TERMUX_GUIDE.md": () => import("../docs/guides/TERMUX_GUIDE.md?collection=docs"), "guides/TROUBLESHOOTING.md": () => import("../docs/guides/TROUBLESHOOTING.md?collection=docs"), "guides/UNINSTALL.md": () => import("../docs/guides/UNINSTALL.md?collection=docs"), "guides/USER_GUIDE.md": () => import("../docs/guides/USER_GUIDE.md?collection=docs"), "frameworks/A2A-SERVER.md": () => import("../docs/frameworks/A2A-SERVER.md?collection=docs"), "frameworks/AGENT_PROTOCOLS_GUIDE.md": () => import("../docs/frameworks/AGENT_PROTOCOLS_GUIDE.md?collection=docs"), "frameworks/CLOUD_AGENT.md": () => import("../docs/frameworks/CLOUD_AGENT.md?collection=docs"), "frameworks/EMBEDDED-SERVICES.md": () => import("../docs/frameworks/EMBEDDED-SERVICES.md?collection=docs"), "frameworks/EVALS.md": () => import("../docs/frameworks/EVALS.md?collection=docs"), "frameworks/GAMIFICATION.md": () => import("../docs/frameworks/GAMIFICATION.md?collection=docs"), "frameworks/MCP-SERVER.md": () => import("../docs/frameworks/MCP-SERVER.md?collection=docs"), "frameworks/MEMORY.md": () => import("../docs/frameworks/MEMORY.md?collection=docs"), "frameworks/OPENCODE.md": () => import("../docs/frameworks/OPENCODE.md?collection=docs"), "frameworks/SKILLS.md": () => import("../docs/frameworks/SKILLS.md?collection=docs"), "frameworks/WEBHOOKS.md": () => import("../docs/frameworks/WEBHOOKS.md?collection=docs"), "ops/COVERAGE_PLAN.md": () => import("../docs/ops/COVERAGE_PLAN.md?collection=docs"), "ops/E2E_DASHBOARD_SHAKEDOWN_v3.8.0.md": () => import("../docs/ops/E2E_DASHBOARD_SHAKEDOWN_v3.8.0.md?collection=docs"), "ops/FLY_IO_DEPLOYMENT_GUIDE.md": () => import("../docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md?collection=docs"), "ops/PROXY_GUIDE.md": () => import("../docs/ops/PROXY_GUIDE.md?collection=docs"), "ops/RELEASE_CHECKLIST.md": () => import("../docs/ops/RELEASE_CHECKLIST.md?collection=docs"), "ops/SQLITE_RUNTIME.md": () => import("../docs/ops/SQLITE_RUNTIME.md?collection=docs"), "ops/TUNNELS_GUIDE.md": () => import("../docs/ops/TUNNELS_GUIDE.md?collection=docs"), "ops/VM_DEPLOYMENT_GUIDE.md": () => import("../docs/ops/VM_DEPLOYMENT_GUIDE.md?collection=docs"), "reference/API_REFERENCE.md": () => import("../docs/reference/API_REFERENCE.md?collection=docs"), "reference/CLI-TOOLS.md": () => import("../docs/reference/CLI-TOOLS.md?collection=docs"), "reference/ENVIRONMENT.md": () => import("../docs/reference/ENVIRONMENT.md?collection=docs"), "reference/FREE_TIERS.md": () => import("../docs/reference/FREE_TIERS.md?collection=docs"), "reference/PROVIDER_REFERENCE.md": () => import("../docs/reference/PROVIDER_REFERENCE.md?collection=docs"), "routing/AUTO-COMBO.md": () => import("../docs/routing/AUTO-COMBO.md?collection=docs"), "routing/REASONING_REPLAY.md": () => import("../docs/routing/REASONING_REPLAY.md?collection=docs"), "security/CLI_TOKEN.md": () => import("../docs/security/CLI_TOKEN.md?collection=docs"), "security/CLI_TOKEN_AUTH.md": () => import("../docs/security/CLI_TOKEN_AUTH.md?collection=docs"), "security/COMPLIANCE.md": () => import("../docs/security/COMPLIANCE.md?collection=docs"), "security/ERROR_SANITIZATION.md": () => import("../docs/security/ERROR_SANITIZATION.md?collection=docs"), "security/GUARDRAILS.md": () => import("../docs/security/GUARDRAILS.md?collection=docs"), "security/PUBLIC_CREDS.md": () => import("../docs/security/PUBLIC_CREDS.md?collection=docs"), "security/ROUTE_GUARD_TIERS.md": () => import("../docs/security/ROUTE_GUARD_TIERS.md?collection=docs"), "security/STEALTH_GUIDE.md": () => import("../docs/security/STEALTH_GUIDE.md?collection=docs"), }), }; export default browserCollections; \ No newline at end of file diff --git a/.source/server.ts b/.source/server.ts index ea427fcb51..923e119f5a 100644 --- a/.source/server.ts +++ b/.source/server.ts @@ -32,28 +32,28 @@ import * as __fd_glob_35 from "../docs/ops/PROXY_GUIDE.md?collection=docs" import * as __fd_glob_34 from "../docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md?collection=docs" import * as __fd_glob_33 from "../docs/ops/E2E_DASHBOARD_SHAKEDOWN_v3.8.0.md?collection=docs" import * as __fd_glob_32 from "../docs/ops/COVERAGE_PLAN.md?collection=docs" -import * as __fd_glob_31 from "../docs/guides/USER_GUIDE.md?collection=docs" -import * as __fd_glob_30 from "../docs/guides/UNINSTALL.md?collection=docs" -import * as __fd_glob_29 from "../docs/guides/TROUBLESHOOTING.md?collection=docs" -import * as __fd_glob_28 from "../docs/guides/TERMUX_GUIDE.md?collection=docs" -import * as __fd_glob_27 from "../docs/guides/SETUP_GUIDE.md?collection=docs" -import * as __fd_glob_26 from "../docs/guides/PWA_GUIDE.md?collection=docs" -import * as __fd_glob_25 from "../docs/guides/KIRO_SETUP.md?collection=docs" -import * as __fd_glob_24 from "../docs/guides/I18N.md?collection=docs" -import * as __fd_glob_23 from "../docs/guides/FEATURES.md?collection=docs" -import * as __fd_glob_22 from "../docs/guides/ELECTRON_GUIDE.md?collection=docs" -import * as __fd_glob_21 from "../docs/guides/DOCKER_GUIDE.md?collection=docs" -import * as __fd_glob_20 from "../docs/frameworks/WEBHOOKS.md?collection=docs" -import * as __fd_glob_19 from "../docs/frameworks/SKILLS.md?collection=docs" -import * as __fd_glob_18 from "../docs/frameworks/OPENCODE.md?collection=docs" -import * as __fd_glob_17 from "../docs/frameworks/MEMORY.md?collection=docs" -import * as __fd_glob_16 from "../docs/frameworks/MCP-SERVER.md?collection=docs" -import * as __fd_glob_15 from "../docs/frameworks/GAMIFICATION.md?collection=docs" -import * as __fd_glob_14 from "../docs/frameworks/EVALS.md?collection=docs" -import * as __fd_glob_13 from "../docs/frameworks/EMBEDDED-SERVICES.md?collection=docs" -import * as __fd_glob_12 from "../docs/frameworks/CLOUD_AGENT.md?collection=docs" -import * as __fd_glob_11 from "../docs/frameworks/AGENT_PROTOCOLS_GUIDE.md?collection=docs" -import * as __fd_glob_10 from "../docs/frameworks/A2A-SERVER.md?collection=docs" +import * as __fd_glob_31 from "../docs/frameworks/WEBHOOKS.md?collection=docs" +import * as __fd_glob_30 from "../docs/frameworks/SKILLS.md?collection=docs" +import * as __fd_glob_29 from "../docs/frameworks/OPENCODE.md?collection=docs" +import * as __fd_glob_28 from "../docs/frameworks/MEMORY.md?collection=docs" +import * as __fd_glob_27 from "../docs/frameworks/MCP-SERVER.md?collection=docs" +import * as __fd_glob_26 from "../docs/frameworks/GAMIFICATION.md?collection=docs" +import * as __fd_glob_25 from "../docs/frameworks/EVALS.md?collection=docs" +import * as __fd_glob_24 from "../docs/frameworks/EMBEDDED-SERVICES.md?collection=docs" +import * as __fd_glob_23 from "../docs/frameworks/CLOUD_AGENT.md?collection=docs" +import * as __fd_glob_22 from "../docs/frameworks/AGENT_PROTOCOLS_GUIDE.md?collection=docs" +import * as __fd_glob_21 from "../docs/frameworks/A2A-SERVER.md?collection=docs" +import * as __fd_glob_20 from "../docs/guides/USER_GUIDE.md?collection=docs" +import * as __fd_glob_19 from "../docs/guides/UNINSTALL.md?collection=docs" +import * as __fd_glob_18 from "../docs/guides/TROUBLESHOOTING.md?collection=docs" +import * as __fd_glob_17 from "../docs/guides/TERMUX_GUIDE.md?collection=docs" +import * as __fd_glob_16 from "../docs/guides/SETUP_GUIDE.md?collection=docs" +import * as __fd_glob_15 from "../docs/guides/PWA_GUIDE.md?collection=docs" +import * as __fd_glob_14 from "../docs/guides/KIRO_SETUP.md?collection=docs" +import * as __fd_glob_13 from "../docs/guides/I18N.md?collection=docs" +import * as __fd_glob_12 from "../docs/guides/FEATURES.md?collection=docs" +import * as __fd_glob_11 from "../docs/guides/ELECTRON_GUIDE.md?collection=docs" +import * as __fd_glob_10 from "../docs/guides/DOCKER_GUIDE.md?collection=docs" import * as __fd_glob_9 from "../docs/compression/RTK_COMPRESSION.md?collection=docs" import * as __fd_glob_8 from "../docs/compression/COMPRESSION_RULES_FORMAT.md?collection=docs" import * as __fd_glob_7 from "../docs/compression/COMPRESSION_LANGUAGE_PACKS.md?collection=docs" @@ -72,4 +72,4 @@ const create = server<typeof Config, import("fumadocs-mdx/runtime/types").Intern } }>({"doc":{"passthroughs":["extractedReferences"]}}); -export const docs = await create.docs("docs", "docs", {"meta.json": __fd_glob_55, "architecture/meta.json": __fd_glob_56, "compression/meta.json": __fd_glob_57, "frameworks/meta.json": __fd_glob_58, "guides/meta.json": __fd_glob_59, "ops/meta.json": __fd_glob_60, "reference/meta.json": __fd_glob_61, "reference/openapi.yaml": __fd_glob_62, "routing/meta.json": __fd_glob_63, "security/meta.json": __fd_glob_64, }, {"architecture/ARCHITECTURE.md": __fd_glob_0, "architecture/AUTHZ_GUIDE.md": __fd_glob_1, "architecture/CODEBASE_DOCUMENTATION.md": __fd_glob_2, "architecture/REPOSITORY_MAP.md": __fd_glob_3, "architecture/RESILIENCE_GUIDE.md": __fd_glob_4, "compression/COMPRESSION_ENGINES.md": __fd_glob_5, "compression/COMPRESSION_GUIDE.md": __fd_glob_6, "compression/COMPRESSION_LANGUAGE_PACKS.md": __fd_glob_7, "compression/COMPRESSION_RULES_FORMAT.md": __fd_glob_8, "compression/RTK_COMPRESSION.md": __fd_glob_9, "frameworks/A2A-SERVER.md": __fd_glob_10, "frameworks/AGENT_PROTOCOLS_GUIDE.md": __fd_glob_11, "frameworks/CLOUD_AGENT.md": __fd_glob_12, "frameworks/EMBEDDED-SERVICES.md": __fd_glob_13, "frameworks/EVALS.md": __fd_glob_14, "frameworks/GAMIFICATION.md": __fd_glob_15, "frameworks/MCP-SERVER.md": __fd_glob_16, "frameworks/MEMORY.md": __fd_glob_17, "frameworks/OPENCODE.md": __fd_glob_18, "frameworks/SKILLS.md": __fd_glob_19, "frameworks/WEBHOOKS.md": __fd_glob_20, "guides/DOCKER_GUIDE.md": __fd_glob_21, "guides/ELECTRON_GUIDE.md": __fd_glob_22, "guides/FEATURES.md": __fd_glob_23, "guides/I18N.md": __fd_glob_24, "guides/KIRO_SETUP.md": __fd_glob_25, "guides/PWA_GUIDE.md": __fd_glob_26, "guides/SETUP_GUIDE.md": __fd_glob_27, "guides/TERMUX_GUIDE.md": __fd_glob_28, "guides/TROUBLESHOOTING.md": __fd_glob_29, "guides/UNINSTALL.md": __fd_glob_30, "guides/USER_GUIDE.md": __fd_glob_31, "ops/COVERAGE_PLAN.md": __fd_glob_32, "ops/E2E_DASHBOARD_SHAKEDOWN_v3.8.0.md": __fd_glob_33, "ops/FLY_IO_DEPLOYMENT_GUIDE.md": __fd_glob_34, "ops/PROXY_GUIDE.md": __fd_glob_35, "ops/RELEASE_CHECKLIST.md": __fd_glob_36, "ops/SQLITE_RUNTIME.md": __fd_glob_37, "ops/TUNNELS_GUIDE.md": __fd_glob_38, "ops/VM_DEPLOYMENT_GUIDE.md": __fd_glob_39, "reference/API_REFERENCE.md": __fd_glob_40, "reference/CLI-TOOLS.md": __fd_glob_41, "reference/ENVIRONMENT.md": __fd_glob_42, "reference/FREE_TIERS.md": __fd_glob_43, "reference/PROVIDER_REFERENCE.md": __fd_glob_44, "routing/AUTO-COMBO.md": __fd_glob_45, "routing/REASONING_REPLAY.md": __fd_glob_46, "security/CLI_TOKEN.md": __fd_glob_47, "security/CLI_TOKEN_AUTH.md": __fd_glob_48, "security/COMPLIANCE.md": __fd_glob_49, "security/ERROR_SANITIZATION.md": __fd_glob_50, "security/GUARDRAILS.md": __fd_glob_51, "security/PUBLIC_CREDS.md": __fd_glob_52, "security/ROUTE_GUARD_TIERS.md": __fd_glob_53, "security/STEALTH_GUIDE.md": __fd_glob_54, }); \ No newline at end of file +export const docs = await create.docs("docs", "docs", {"meta.json": __fd_glob_55, "architecture/meta.json": __fd_glob_56, "compression/meta.json": __fd_glob_57, "frameworks/meta.json": __fd_glob_58, "guides/meta.json": __fd_glob_59, "ops/meta.json": __fd_glob_60, "reference/meta.json": __fd_glob_61, "reference/openapi.yaml": __fd_glob_62, "routing/meta.json": __fd_glob_63, "security/meta.json": __fd_glob_64, }, {"architecture/ARCHITECTURE.md": __fd_glob_0, "architecture/AUTHZ_GUIDE.md": __fd_glob_1, "architecture/CODEBASE_DOCUMENTATION.md": __fd_glob_2, "architecture/REPOSITORY_MAP.md": __fd_glob_3, "architecture/RESILIENCE_GUIDE.md": __fd_glob_4, "compression/COMPRESSION_ENGINES.md": __fd_glob_5, "compression/COMPRESSION_GUIDE.md": __fd_glob_6, "compression/COMPRESSION_LANGUAGE_PACKS.md": __fd_glob_7, "compression/COMPRESSION_RULES_FORMAT.md": __fd_glob_8, "compression/RTK_COMPRESSION.md": __fd_glob_9, "guides/DOCKER_GUIDE.md": __fd_glob_10, "guides/ELECTRON_GUIDE.md": __fd_glob_11, "guides/FEATURES.md": __fd_glob_12, "guides/I18N.md": __fd_glob_13, "guides/KIRO_SETUP.md": __fd_glob_14, "guides/PWA_GUIDE.md": __fd_glob_15, "guides/SETUP_GUIDE.md": __fd_glob_16, "guides/TERMUX_GUIDE.md": __fd_glob_17, "guides/TROUBLESHOOTING.md": __fd_glob_18, "guides/UNINSTALL.md": __fd_glob_19, "guides/USER_GUIDE.md": __fd_glob_20, "frameworks/A2A-SERVER.md": __fd_glob_21, "frameworks/AGENT_PROTOCOLS_GUIDE.md": __fd_glob_22, "frameworks/CLOUD_AGENT.md": __fd_glob_23, "frameworks/EMBEDDED-SERVICES.md": __fd_glob_24, "frameworks/EVALS.md": __fd_glob_25, "frameworks/GAMIFICATION.md": __fd_glob_26, "frameworks/MCP-SERVER.md": __fd_glob_27, "frameworks/MEMORY.md": __fd_glob_28, "frameworks/OPENCODE.md": __fd_glob_29, "frameworks/SKILLS.md": __fd_glob_30, "frameworks/WEBHOOKS.md": __fd_glob_31, "ops/COVERAGE_PLAN.md": __fd_glob_32, "ops/E2E_DASHBOARD_SHAKEDOWN_v3.8.0.md": __fd_glob_33, "ops/FLY_IO_DEPLOYMENT_GUIDE.md": __fd_glob_34, "ops/PROXY_GUIDE.md": __fd_glob_35, "ops/RELEASE_CHECKLIST.md": __fd_glob_36, "ops/SQLITE_RUNTIME.md": __fd_glob_37, "ops/TUNNELS_GUIDE.md": __fd_glob_38, "ops/VM_DEPLOYMENT_GUIDE.md": __fd_glob_39, "reference/API_REFERENCE.md": __fd_glob_40, "reference/CLI-TOOLS.md": __fd_glob_41, "reference/ENVIRONMENT.md": __fd_glob_42, "reference/FREE_TIERS.md": __fd_glob_43, "reference/PROVIDER_REFERENCE.md": __fd_glob_44, "routing/AUTO-COMBO.md": __fd_glob_45, "routing/REASONING_REPLAY.md": __fd_glob_46, "security/CLI_TOKEN.md": __fd_glob_47, "security/CLI_TOKEN_AUTH.md": __fd_glob_48, "security/COMPLIANCE.md": __fd_glob_49, "security/ERROR_SANITIZATION.md": __fd_glob_50, "security/GUARDRAILS.md": __fd_glob_51, "security/PUBLIC_CREDS.md": __fd_glob_52, "security/ROUTE_GUARD_TIERS.md": __fd_glob_53, "security/STEALTH_GUIDE.md": __fd_glob_54, }); \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fa907b355..b56334bcfb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,36 @@ --- +## [3.8.6] — 2026-05-27 + +### ✨ New Features + +- **logs:** add clean log history action button to Logs page dashboard (#2799 — thanks @apoapostolov) +- **settings:** restore settings-driven home page layout toggles and auto-refresh limits widget (#2800 — thanks @apoapostolov) +- **modelSpecs:** register explicit model specifications and context/output caps for Moonshot, Qwen, Hunyuan, DeepSeek, MiniMax, GLM on the `opencode-go` provider (#2802 — thanks @jeferssonlemes) + +### 🔧 Bug Fixes + +- **opencode-go:** route Qwen3.x via Claude messages format and repair `fixMissingToolResponses` helper for Claude-shape upstreams (#2791 — thanks @jeferssonlemes) +- **validation:** register missing validation helper checks for web-cookie providers (`claude-web`, `gemini-web`, `copilot-web`, `t3-web`) (#2793 — thanks @oyi77) +- **docker:** check and warn if `/app/data` is not writable in the Docker entrypoint script to fail fast with helpful host instructions (#2795 — thanks @hartmark) +- **oauth:** repair native Google loopback callback flow and support remote callbacks via state matching on 127.0.0.1 (#2796 — thanks @akarray) +- **combos:** fix combo handling so transient 429 rate limit errors do not poison or persist the rate limited state for the same-provider connection (#2800 — thanks @apoapostolov) +- **gemini:** translate signature-less Gemini thinking model tool calls to text parts to prevent `400 "missing thought_signature"` errors (#2801 — thanks @herjarsa) +- **warning-cleanup:** relax node engine constraint to `>=22.0.0` and clean dependencies (keeping `marked-terminal` to prevent TUI REPL crash) (#2792 — thanks @oyi77) + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +### 🏆 Hall of Contributors + +A special thanks to everyone who contributed code, reviews, and tests for this release: +@akarray, @apoapostolov, @hartmark, @herjarsa, @jeferssonlemes, @oyi77 + +--- + ## [3.8.5] — 2026-05-27 ### ✨ New Features diff --git a/README.md b/README.md index 321bc6e807..e5a4a2202b 100644 --- a/README.md +++ b/README.md @@ -939,7 +939,7 @@ MIT License - see [LICENSE](LICENSE) for details. **[⬆ Back to top](#-omniroute)** · Built with ❤️ for the open-source AI community. -<sub>OmniRoute v3.8.2 · Node ≥22.22.2 · MIT License · <a href="https://omniroute.online">omniroute.online</a></sub> +<sub>OmniRoute v3.8.6 · Node ≥22.22.2 · MIT License · <a href="https://omniroute.online">omniroute.online</a></sub> </div> <!-- GitHub Discussions enabled for community Q&A --> diff --git a/bin/cli/utils/environment.mjs b/bin/cli/utils/environment.mjs index 7ab1b7fc13..eae4b59757 100644 --- a/bin/cli/utils/environment.mjs +++ b/bin/cli/utils/environment.mjs @@ -5,16 +5,6 @@ export function detectRestrictedEnvironment() { return { type: "github-codespaces", canOpenBrowser: false, canUseTray: false }; } - if (existsSync("/.dockerenv")) { - return { type: "docker", canOpenBrowser: false, canUseTray: false }; - } - - try { - if (existsSync("/proc/1/cgroup") && readFileSync("/proc/1/cgroup", "utf8").includes("docker")) { - return { type: "docker", canOpenBrowser: false, canUseTray: false }; - } - } catch {} - if (process.env.WSL_DISTRO_NAME || process.env.WSL_INTEROP) { return { type: "wsl", @@ -36,6 +26,16 @@ export function detectRestrictedEnvironment() { return { type: "ci", canOpenBrowser: false, canUseTray: false }; } + if (existsSync("/.dockerenv")) { + return { type: "docker", canOpenBrowser: false, canUseTray: false }; + } + + try { + if (existsSync("/proc/1/cgroup") && readFileSync("/proc/1/cgroup", "utf8").includes("docker")) { + return { type: "docker", canOpenBrowser: false, canUseTray: false }; + } + } catch {} + if (!process.stdin.isTTY) { return { type: "non-interactive", canOpenBrowser: false, canUseTray: false }; } diff --git a/bin/omniroute.mjs b/bin/omniroute.mjs index 04cad32850..e536ac30e0 100755 --- a/bin/omniroute.mjs +++ b/bin/omniroute.mjs @@ -22,6 +22,7 @@ import { getNodeRuntimeSupport, getNodeRuntimeWarning } from "./nodeRuntimeSuppo // TypeScript conventions) resolve correctly. The build never emits .js for // src/lib/cli-helper/, so tsx handles the .ts → .js resolution at runtime. await import("tsx/esm"); +await import("../open-sse/utils/setupPolyfill.ts"); const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); diff --git a/docs/i18n/ar/CHANGELOG.md b/docs/i18n/ar/CHANGELOG.md index 93d35e90a5..28e6dacffa 100644 --- a/docs/i18n/ar/CHANGELOG.md +++ b/docs/i18n/ar/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/az/CHANGELOG.md b/docs/i18n/az/CHANGELOG.md index 55977e916b..a7950ada49 100644 --- a/docs/i18n/az/CHANGELOG.md +++ b/docs/i18n/az/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/bg/CHANGELOG.md b/docs/i18n/bg/CHANGELOG.md index 55977e916b..a7950ada49 100644 --- a/docs/i18n/bg/CHANGELOG.md +++ b/docs/i18n/bg/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/bn/CHANGELOG.md b/docs/i18n/bn/CHANGELOG.md index c0b7d896f3..1c6b5a8459 100644 --- a/docs/i18n/bn/CHANGELOG.md +++ b/docs/i18n/bn/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/cs/CHANGELOG.md b/docs/i18n/cs/CHANGELOG.md index e85189339f..7a25250e57 100644 --- a/docs/i18n/cs/CHANGELOG.md +++ b/docs/i18n/cs/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/da/CHANGELOG.md b/docs/i18n/da/CHANGELOG.md index 9118f5b752..572da9b11c 100644 --- a/docs/i18n/da/CHANGELOG.md +++ b/docs/i18n/da/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/de/CHANGELOG.md b/docs/i18n/de/CHANGELOG.md index 709596b56e..c25218e6e7 100644 --- a/docs/i18n/de/CHANGELOG.md +++ b/docs/i18n/de/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/es/CHANGELOG.md b/docs/i18n/es/CHANGELOG.md index b6d833255d..e41892b42f 100644 --- a/docs/i18n/es/CHANGELOG.md +++ b/docs/i18n/es/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/fa/CHANGELOG.md b/docs/i18n/fa/CHANGELOG.md index db1752c50f..6dbe17b9d7 100644 --- a/docs/i18n/fa/CHANGELOG.md +++ b/docs/i18n/fa/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/fi/CHANGELOG.md b/docs/i18n/fi/CHANGELOG.md index 6457b9b572..4cb5cc54a5 100644 --- a/docs/i18n/fi/CHANGELOG.md +++ b/docs/i18n/fi/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/fr/CHANGELOG.md b/docs/i18n/fr/CHANGELOG.md index 7a54037145..4ca7a75b89 100644 --- a/docs/i18n/fr/CHANGELOG.md +++ b/docs/i18n/fr/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/gu/CHANGELOG.md b/docs/i18n/gu/CHANGELOG.md index ed2baef172..c859a37063 100644 --- a/docs/i18n/gu/CHANGELOG.md +++ b/docs/i18n/gu/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/he/CHANGELOG.md b/docs/i18n/he/CHANGELOG.md index cbe80b59d3..0d8f2bfc27 100644 --- a/docs/i18n/he/CHANGELOG.md +++ b/docs/i18n/he/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/hi/CHANGELOG.md b/docs/i18n/hi/CHANGELOG.md index 0e23ef0a98..7955956963 100644 --- a/docs/i18n/hi/CHANGELOG.md +++ b/docs/i18n/hi/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/hu/CHANGELOG.md b/docs/i18n/hu/CHANGELOG.md index 2d62977649..8bacfa2dfb 100644 --- a/docs/i18n/hu/CHANGELOG.md +++ b/docs/i18n/hu/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/id/CHANGELOG.md b/docs/i18n/id/CHANGELOG.md index 3d7bf9aeb2..428df01842 100644 --- a/docs/i18n/id/CHANGELOG.md +++ b/docs/i18n/id/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/in/CHANGELOG.md b/docs/i18n/in/CHANGELOG.md index 836886b526..168dbb9e14 100644 --- a/docs/i18n/in/CHANGELOG.md +++ b/docs/i18n/in/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/it/CHANGELOG.md b/docs/i18n/it/CHANGELOG.md index e6a92b4934..57a78b3d38 100644 --- a/docs/i18n/it/CHANGELOG.md +++ b/docs/i18n/it/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/ja/CHANGELOG.md b/docs/i18n/ja/CHANGELOG.md index 1efa867771..4f93793748 100644 --- a/docs/i18n/ja/CHANGELOG.md +++ b/docs/i18n/ja/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/ko/CHANGELOG.md b/docs/i18n/ko/CHANGELOG.md index 404c0bf926..cf76e58e9f 100644 --- a/docs/i18n/ko/CHANGELOG.md +++ b/docs/i18n/ko/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/mr/CHANGELOG.md b/docs/i18n/mr/CHANGELOG.md index 96074e285c..f2d0005cae 100644 --- a/docs/i18n/mr/CHANGELOG.md +++ b/docs/i18n/mr/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/ms/CHANGELOG.md b/docs/i18n/ms/CHANGELOG.md index 4e85469384..6b415eb733 100644 --- a/docs/i18n/ms/CHANGELOG.md +++ b/docs/i18n/ms/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/nl/CHANGELOG.md b/docs/i18n/nl/CHANGELOG.md index 85e15ce194..8caa06fec5 100644 --- a/docs/i18n/nl/CHANGELOG.md +++ b/docs/i18n/nl/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/no/CHANGELOG.md b/docs/i18n/no/CHANGELOG.md index eaa8d08d99..a916e1031e 100644 --- a/docs/i18n/no/CHANGELOG.md +++ b/docs/i18n/no/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/phi/CHANGELOG.md b/docs/i18n/phi/CHANGELOG.md index 4f51106d34..e5a989af16 100644 --- a/docs/i18n/phi/CHANGELOG.md +++ b/docs/i18n/phi/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/pl/CHANGELOG.md b/docs/i18n/pl/CHANGELOG.md index 249aed3ddb..c8107bc160 100644 --- a/docs/i18n/pl/CHANGELOG.md +++ b/docs/i18n/pl/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/pt-BR/CHANGELOG.md b/docs/i18n/pt-BR/CHANGELOG.md index 73db089972..9c5dbb0263 100644 --- a/docs/i18n/pt-BR/CHANGELOG.md +++ b/docs/i18n/pt-BR/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/pt/CHANGELOG.md b/docs/i18n/pt/CHANGELOG.md index 56cd6b40e8..0ab0d77375 100644 --- a/docs/i18n/pt/CHANGELOG.md +++ b/docs/i18n/pt/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/ro/CHANGELOG.md b/docs/i18n/ro/CHANGELOG.md index 6e233b659f..c56758eb2b 100644 --- a/docs/i18n/ro/CHANGELOG.md +++ b/docs/i18n/ro/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/ru/CHANGELOG.md b/docs/i18n/ru/CHANGELOG.md index 733c391b88..566042d8e4 100644 --- a/docs/i18n/ru/CHANGELOG.md +++ b/docs/i18n/ru/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/sk/CHANGELOG.md b/docs/i18n/sk/CHANGELOG.md index f1ef4f1820..27e141e0c8 100644 --- a/docs/i18n/sk/CHANGELOG.md +++ b/docs/i18n/sk/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/sv/CHANGELOG.md b/docs/i18n/sv/CHANGELOG.md index 0911fe1cac..7612f00cc9 100644 --- a/docs/i18n/sv/CHANGELOG.md +++ b/docs/i18n/sv/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/sw/CHANGELOG.md b/docs/i18n/sw/CHANGELOG.md index 8fc40c668d..429af3ed9e 100644 --- a/docs/i18n/sw/CHANGELOG.md +++ b/docs/i18n/sw/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/ta/CHANGELOG.md b/docs/i18n/ta/CHANGELOG.md index 966f4bfc72..69347465fb 100644 --- a/docs/i18n/ta/CHANGELOG.md +++ b/docs/i18n/ta/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/te/CHANGELOG.md b/docs/i18n/te/CHANGELOG.md index 15ba2858cc..8b13201644 100644 --- a/docs/i18n/te/CHANGELOG.md +++ b/docs/i18n/te/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/th/CHANGELOG.md b/docs/i18n/th/CHANGELOG.md index 6b39c93649..3579bbc55e 100644 --- a/docs/i18n/th/CHANGELOG.md +++ b/docs/i18n/th/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/tr/CHANGELOG.md b/docs/i18n/tr/CHANGELOG.md index c261e947fe..4e1483f4f2 100644 --- a/docs/i18n/tr/CHANGELOG.md +++ b/docs/i18n/tr/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/uk-UA/CHANGELOG.md b/docs/i18n/uk-UA/CHANGELOG.md index 089ba996d5..d52801c2f9 100644 --- a/docs/i18n/uk-UA/CHANGELOG.md +++ b/docs/i18n/uk-UA/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/ur/CHANGELOG.md b/docs/i18n/ur/CHANGELOG.md index d2a762ded8..b8bbd57082 100644 --- a/docs/i18n/ur/CHANGELOG.md +++ b/docs/i18n/ur/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/vi/CHANGELOG.md b/docs/i18n/vi/CHANGELOG.md index 8216387c5b..fa10828e41 100644 --- a/docs/i18n/vi/CHANGELOG.md +++ b/docs/i18n/vi/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/i18n/zh-CN/CHANGELOG.md b/docs/i18n/zh-CN/CHANGELOG.md index 5c2741da9e..102bd5f929 100644 --- a/docs/i18n/zh-CN/CHANGELOG.md +++ b/docs/i18n/zh-CN/CHANGELOG.md @@ -4,6 +4,17 @@ --- +## [3.8.6] — 2026-05-27 + +### 🧹 Chores + +- **gitignore:** ignore `.claude/settings.local.json` so per-user Claude Code permissions never get committed by accident +- **release:** version bump and metadata sync (package.json, package-lock.json, electron, open-sse, openapi.yaml) + +> v3.8.6 is a maintenance/scaffolding patch. All feature and bug-fix work from the post-v3.8.5 cycle (44 commits — community PRs #2777, #2782–#2787, #2789, #2790, plus internal hotfixes) was already integrated into v3.8.5 and is documented under that section. + +--- + ## [3.8.5] — 2026-05-26 ### 🔒 Security diff --git a/docs/reference/openapi.yaml b/docs/reference/openapi.yaml index 1bd8d0dc14..faa3b50d07 100644 --- a/docs/reference/openapi.yaml +++ b/docs/reference/openapi.yaml @@ -1,7 +1,7 @@ openapi: 3.1.0 info: title: OmniRoute API - version: 3.8.5 + version: 3.8.6 description: | OmniRoute is a local-first AI API proxy router. It provides an OpenAI-compatible endpoint that routes requests to multiple AI providers with load balancing, diff --git a/electron/package-lock.json b/electron/package-lock.json index d45700fcf6..544e839152 100644 --- a/electron/package-lock.json +++ b/electron/package-lock.json @@ -1,12 +1,12 @@ { "name": "omniroute-desktop", - "version": "3.8.5", + "version": "3.8.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "omniroute-desktop", - "version": "3.8.5", + "version": "3.8.6", "license": "MIT", "dependencies": { "electron-updater": "^6.8.6" diff --git a/electron/package.json b/electron/package.json index 0fa6294848..4a1d2bb7d1 100644 --- a/electron/package.json +++ b/electron/package.json @@ -1,6 +1,6 @@ { "name": "omniroute-desktop", - "version": "3.8.5", + "version": "3.8.6", "description": "OmniRoute Desktop Application", "main": "main.js", "author": { diff --git a/open-sse/package.json b/open-sse/package.json index 94ad6ee29c..8d0f4105ab 100644 --- a/open-sse/package.json +++ b/open-sse/package.json @@ -1,6 +1,6 @@ { "name": "@omniroute/open-sse", - "version": "3.8.5", + "version": "3.8.6", "description": "Express SSE sidecar for OmniRoute — handles streaming, protocol translation, and provider orchestration", "type": "module", "main": "index.js", diff --git a/open-sse/utils/proxyDispatcher.ts b/open-sse/utils/proxyDispatcher.ts index ddbe45d913..d4981378da 100644 --- a/open-sse/utils/proxyDispatcher.ts +++ b/open-sse/utils/proxyDispatcher.ts @@ -1,3 +1,4 @@ +import "./setupPolyfill.ts"; import { Agent, ProxyAgent, type Dispatcher } from "undici"; import { socksDispatcher } from "fetch-socks"; import { getUpstreamTimeoutConfig } from "@/shared/utils/runtimeTimeouts"; diff --git a/open-sse/utils/proxyFetch.ts b/open-sse/utils/proxyFetch.ts index ccaea8e8a0..c8b4deb482 100644 --- a/open-sse/utils/proxyFetch.ts +++ b/open-sse/utils/proxyFetch.ts @@ -1,4 +1,5 @@ // @ts-nocheck +import "./setupPolyfill.ts"; import { AsyncLocalStorage } from "node:async_hooks"; import { fetch as undiciFetch } from "undici"; import { diff --git a/open-sse/utils/setupPolyfill.ts b/open-sse/utils/setupPolyfill.ts new file mode 100644 index 0000000000..6eed9c1ce0 --- /dev/null +++ b/open-sse/utils/setupPolyfill.ts @@ -0,0 +1,33 @@ +// Polyfill worker_threads.markAsUncloneable for Node.js < 21 compatibility (specifically Node 20.20.2) +import worker_threads from "node:worker_threads"; +import { WebSocket } from "ws"; + +if (worker_threads && !worker_threads.markAsUncloneable) { + (worker_threads as any).markAsUncloneable = function (obj: any) { + if (worker_threads.markAsUntransferable) { + try { + worker_threads.markAsUntransferable(obj); + } catch { + // no-op + } + } + }; +} + +// Polyfill Promise.withResolvers for Node.js < 22 compatibility (specifically Node 20.20.2) +if (typeof Promise.withResolvers === "undefined") { + Promise.withResolvers = function <T>() { + let resolve!: (value: T | PromiseLike<T>) => void; + let reject!: (reason?: any) => void; + const promise = new Promise<T>((res, rej) => { + resolve = res; + reject = rej; + }); + return { promise, resolve, reject }; + } as any; +} + +// Polyfill WebSocket for Node.js < 22 compatibility (specifically Node 20.20.2) +if (typeof globalThis.WebSocket === "undefined") { + (globalThis as any).WebSocket = WebSocket; +} diff --git a/package-lock.json b/package-lock.json index b33947431b..87c663e68f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "omniroute", - "version": "3.8.5", + "version": "3.8.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "omniroute", - "version": "3.8.5", + "version": "3.8.6", "hasInstallScript": true, "license": "MIT", "workspaces": [ @@ -21210,7 +21210,7 @@ }, "open-sse": { "name": "@omniroute/open-sse", - "version": "3.8.5" + "version": "3.8.6" } } } diff --git a/package.json b/package.json index 22f5a93945..cb90e3cc95 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "omniroute", - "version": "3.8.5", + "version": "3.8.6", "description": "Unified AI router with 160+ providers, RTK+Caveman compression, auto fallback, MCP/A2A, desktop, PWA, and OpenAI-compatible APIs.", "type": "module", "bin": { @@ -79,15 +79,15 @@ "electron:build:mac": "npm run build && cd electron && npm run build:mac", "electron:build:linux": "npm run build && cd electron && npm run build:linux", "electron:smoke:packaged": "node scripts/dev/smoke-electron-packaged.mjs", - "test": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx --test --test-concurrency=20 tests/unit/*.test.ts", - "test:unit": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx --test --test-force-exit --test-concurrency=20 tests/unit/*.test.ts", - "test:unit:fast": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx --test --test-force-exit --test-isolation=none tests/unit/*.test.ts", + "test": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx --import ./open-sse/utils/setupPolyfill.ts --test --test-concurrency=20 tests/unit/*.test.ts", + "test:unit": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx --import ./open-sse/utils/setupPolyfill.ts --test --test-force-exit --test-concurrency=20 tests/unit/*.test.ts", + "test:unit:fast": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx --import ./open-sse/utils/setupPolyfill.ts --test --test-force-exit --test-isolation=none tests/unit/*.test.ts", "test:unit:shard": "concurrently --kill-others-on-fail -n s1,s2 \"npm:test:unit:shard:1\" \"npm:test:unit:shard:2\"", - "test:unit:shard:1": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx --test --test-force-exit --test-concurrency=10 --test-shard=1/2 tests/unit/*.test.ts", - "test:unit:shard:2": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx --test --test-force-exit --test-concurrency=10 --test-shard=2/2 tests/unit/*.test.ts", - "test:plan3": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx --test tests/unit/plan3-p0.test.ts", - "test:fixes": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx --test tests/unit/fixes-p1.test.ts", - "test:security": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx --test tests/unit/security-fase01.test.ts", + "test:unit:shard:1": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx --import ./open-sse/utils/setupPolyfill.ts --test --test-force-exit --test-concurrency=10 --test-shard=1/2 tests/unit/*.test.ts", + "test:unit:shard:2": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --max-old-space-size=8192 --import tsx --import ./open-sse/utils/setupPolyfill.ts --test --test-force-exit --test-concurrency=10 --test-shard=2/2 tests/unit/*.test.ts", + "test:plan3": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx --import ./open-sse/utils/setupPolyfill.ts --test tests/unit/plan3-p0.test.ts", + "test:fixes": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx --import ./open-sse/utils/setupPolyfill.ts --test tests/unit/fixes-p1.test.ts", + "test:security": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx --import ./open-sse/utils/setupPolyfill.ts --test tests/unit/security-fase01.test.ts", "check:cycles": "node scripts/check/check-cycles.mjs", "check:route-validation:t06": "node scripts/check/check-route-validation.mjs", "check:any-budget:t11": "node scripts/check/check-t11-any-budget.mjs", @@ -112,13 +112,13 @@ "typecheck:noimplicit:core": "tsc --pretty false -p tsconfig.typecheck-noimplicit-core.json", "backfill-aggregation": "node --import tsx src/scripts/backfillAggregation.ts", "env:sync": "node scripts/dev/sync-env.mjs", - "test:integration": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx --test --test-force-exit --test-concurrency=1 tests/integration/*.test.ts", + "test:integration": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx --import ./open-sse/utils/setupPolyfill.ts --test --test-force-exit --test-concurrency=1 tests/integration/*.test.ts", "test:e2e": "node scripts/dev/run-playwright-tests.mjs test tests/e2e/*.spec.ts", "test:protocols:e2e": "node scripts/dev/run-protocol-clients-tests.mjs", "test:vitest": "vitest run --config vitest.mcp.config.ts", "test:ecosystem": "node scripts/dev/run-ecosystem-tests.mjs", - "test:system": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx --test --test-force-exit --test-concurrency=1 tests/e2e/system-failover.test.ts", - "test:coverage": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true c8 --output-dir coverage --exclude=tests/** --exclude=**/*.test.* --reporter=text-summary --reporter=html --reporter=json-summary --reporter=lcov --check-coverage --statements 75 --lines 75 --functions 75 --branches 70 node --max-old-space-size=8192 --import tsx --test --test-force-exit --test-concurrency=8 tests/unit/*.test.ts", + "test:system": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true node --import tsx --import ./open-sse/utils/setupPolyfill.ts --test --test-force-exit --test-concurrency=1 tests/e2e/system-failover.test.ts", + "test:coverage": "cross-env DISABLE_SQLITE_AUTO_BACKUP=true c8 --output-dir coverage --exclude=tests/** --exclude=**/*.test.* --reporter=text-summary --reporter=html --reporter=json-summary --reporter=lcov --check-coverage --statements 75 --lines 75 --functions 75 --branches 70 node --max-old-space-size=8192 --import tsx --import ./open-sse/utils/setupPolyfill.ts --test --test-force-exit --test-concurrency=8 tests/unit/*.test.ts", "test:coverage:legacy": "c8 --output-dir coverage --exclude=open-sse --check-coverage --lines 50 --functions 50 --branches 50 node --import tsx --test tests/unit/*.test.ts", "coverage:report": "c8 report --output-dir coverage --exclude=tests/** --exclude=**/*.test.* --reporter=text --reporter=text-summary --reporter=html --reporter=json-summary --reporter=lcov", "coverage:summary": "node scripts/check/test-report-summary.mjs --input coverage/coverage-summary.json --output coverage/coverage-report.md", diff --git a/tests/unit/batch_results.test.ts b/tests/unit/batch_results.test.ts index a3a61ac824..35eabb0c03 100644 --- a/tests/unit/batch_results.test.ts +++ b/tests/unit/batch_results.test.ts @@ -16,7 +16,7 @@ const { createProviderConnection, createApiKey, } = await import("../../src/lib/localDb.ts"); -const { initBatchProcessor, stopBatchProcessor, waitForAllBatches } = +const { initBatchProcessor, stopBatchProcessor, waitForAllBatches, processPendingBatches } = await import("../../open-sse/services/batchProcessor.ts"); test.afterEach(async () => { @@ -30,7 +30,7 @@ test.afterEach(async () => { test("Batch processor produces output file for successful items", async () => { const originalFetch = globalThis.fetch; // Mock upstream provider to always return a successful embedding response - globalThis.fetch = async (url, options) => { + globalThis.fetch = (async (url, options) => { return new Response( JSON.stringify({ object: "list", @@ -39,7 +39,7 @@ test("Batch processor produces output file for successful items", async () => { }), { status: 200, headers: { "Content-Type": "application/json" } } ); - }; + }) as any; // Prevent open-sse/utils/proxyFetch.ts from replacing globalThis.fetch // when it is dynamically imported via the route handler chain. @@ -87,6 +87,7 @@ test("Batch processor produces output file for successful items", async () => { }); initBatchProcessor(); + await processPendingBatches(); let maxAttempts = 30; let currentBatch = getBatch(batch.id); diff --git a/tests/unit/combo-routing-engine.test.ts b/tests/unit/combo-routing-engine.test.ts index 1498a7db00..88dc15e953 100644 --- a/tests/unit/combo-routing-engine.test.ts +++ b/tests/unit/combo-routing-engine.test.ts @@ -327,6 +327,7 @@ test("handleComboChat runs shadow targets without changing the primary response const metrics = getComboMetrics("shadow-routing-priority"); assert.equal(result.ok, true); + calls.sort((a, b) => a.trafficType.localeCompare(b.trafficType)); assert.deepEqual(calls, [ { modelStr: "openai/gpt-4o-mini", trafficType: "production", stream: true }, { modelStr: "anthropic/claude-3-haiku", trafficType: "shadow", stream: false }, @@ -2032,12 +2033,17 @@ test("handleComboChat standalone lkgp strategy updates LKGP after a successful c }); // Give the async fire-and-forget LKGP update a chance to execute - await new Promise((resolve) => setTimeout(resolve, 10)); - - const persistedProvider = await settingsDb.getLKGP( - "standalone-lkgp-save", - "standalone-lkgp-save" - ); + let persistedProvider: any = null; + for (let i = 0; i < 20; i++) { + persistedProvider = await settingsDb.getLKGP( + "standalone-lkgp-save", + "standalone-lkgp-save" + ); + if (persistedProvider?.provider === "openai") { + break; + } + await new Promise((resolve) => setTimeout(resolve, 10)); + } assert.equal(result.ok, true); // getLKGP now returns LKGPRecord | null — source: src/lib/db/settings.ts getLKGP() diff --git a/tests/unit/dockerignore-docs-coverage.test.ts b/tests/unit/dockerignore-docs-coverage.test.ts index 2f8f8c6b36..7934d27f1a 100644 --- a/tests/unit/dockerignore-docs-coverage.test.ts +++ b/tests/unit/dockerignore-docs-coverage.test.ts @@ -25,7 +25,7 @@ const DOCKERIGNORE = path.resolve(REPO_ROOT, ".dockerignore"); const REQUIRED_DOCS = [ "docs/README.md", "docs/PROVIDERS.md", - "docs/AUTO-COMBO.md", + "docs/routing/AUTO-COMBO.md", "docs/guides/SETUP_GUIDE.md", "docs/guides/TROUBLESHOOTING.md", "docs/reference/API_REFERENCE.md", diff --git a/tests/unit/electron-main.test.ts b/tests/unit/electron-main.test.ts index ce3269ca0c..eb50c65680 100644 --- a/tests/unit/electron-main.test.ts +++ b/tests/unit/electron-main.test.ts @@ -251,7 +251,7 @@ describe("Server Readiness Logic", () => { let reloaded = false; const mainWindow = { isDestroyed: () => false, - loadURL: () => { + loadURL: (_url?: string) => { reloaded = true; }, }; @@ -364,12 +364,52 @@ describe("Platform-Conditional Window Options", () => { // ─── SQLite Credential Inspection Tests ───────────────────── +// Mock node:sqlite for older Node.js versions where it's not built-in +let DatabaseSync; +try { + DatabaseSync = require("node:sqlite").DatabaseSync; +} catch { + const Database = require("better-sqlite3"); + class MockDatabaseSync { + db: any; + constructor(dbPath, options) { + const dbOpts: any = {}; + if (options && typeof options.readOnly === "boolean") { + dbOpts.readonly = options.readOnly; + } + this.db = new Database(dbPath, dbOpts); + } + exec(sql) { + return this.db.exec(sql); + } + prepare(sql) { + const stmt = this.db.prepare(sql); + return { + run: (...args) => stmt.run(...args), + get: (...args) => stmt.get(...args), + }; + } + close() { + return this.db.close(); + } + } + DatabaseSync = MockDatabaseSync; + + const Module = require("node:module"); + const originalRequire = Module.prototype.require; + Module.prototype.require = function (id) { + if (id === "node:sqlite") { + return { DatabaseSync: MockDatabaseSync }; + } + return originalRequire.apply(this, arguments); + }; +} + describe("Electron SQLite credential inspection", () => { const { hasEncryptedCredentials, openNodeSqliteReadOnly, } = require("../../electron/sqlite-inspection.js"); - const { DatabaseSync } = require("node:sqlite"); function withTempDb(fn) { const dir = mkdtempSync(join(tmpdir(), "omniroute-electron-db-")); diff --git a/tests/unit/free-proxies-add-to-pool.test.ts b/tests/unit/free-proxies-add-to-pool.test.ts index 38a89d11ee..3767762c5a 100644 --- a/tests/unit/free-proxies-add-to-pool.test.ts +++ b/tests/unit/free-proxies-add-to-pool.test.ts @@ -1,3 +1,4 @@ +import "../../open-sse/utils/setupPolyfill.ts"; import test from "node:test"; import assert from "node:assert/strict"; import fs from "node:fs"; diff --git a/tests/unit/opencode-executor.test.ts b/tests/unit/opencode-executor.test.ts index d7b42f14ed..5f31dd6891 100644 --- a/tests/unit/opencode-executor.test.ts +++ b/tests/unit/opencode-executor.test.ts @@ -44,10 +44,10 @@ describe("OpencodeExecutor", () => { originalFetch = globalThis.fetch; originalZenModels = [...(PROVIDER_MODELS["opencode-zen"] || [])]; originalGoModels = [...(PROVIDER_MODELS["opencode-go"] || [])]; - globalThis.fetch = async (url, options) => { + globalThis.fetch = (async (url, options) => { fetchCalls.push({ url, options }); return createMockResponse(); - }; + }) as any; }); afterEach(() => { @@ -260,14 +260,14 @@ describe("OpencodeExecutor", () => { it("routes opencode-go catalog-only models to chat completions", async () => { // Register new models - registerModel("opencode-go", { id: "qwen3.7-max", name: "Qwen3.7 Max" }); + registerModel("opencode-go", { id: "glm-6-max", name: "GLM-6 Max" }); registerModel("opencode-go", { id: "mimo-v2-pro", name: "MiMo-V2-Pro" }); registerModel("opencode-go", { id: "mimo-v2-omni", name: "MiMo-V2-Omni" }); registerModel("opencode-go", { id: "hy3-preview", name: "Hunyuan3 Preview" }); - // qwen3.7-max - const qwen37 = await goExecutor.execute(createInput("qwen3.7-max")); - assert.equal(qwen37.url, "https://opencode.ai/zen/go/v1/chat/completions"); + // glm-6-max + const glm6 = await goExecutor.execute(createInput("glm-6-max")); + assert.equal(glm6.url, "https://opencode.ai/zen/go/v1/chat/completions"); // mimo-v2-pro const mimoPro = await goExecutor.execute(createInput("mimo-v2-pro")); diff --git a/tests/unit/t43-gemini-tool-call-no-thought-signature.test.ts b/tests/unit/t43-gemini-tool-call-no-thought-signature.test.ts index 192020bf37..8410c5653b 100644 --- a/tests/unit/t43-gemini-tool-call-no-thought-signature.test.ts +++ b/tests/unit/t43-gemini-tool-call-no-thought-signature.test.ts @@ -18,16 +18,23 @@ import test from "node:test"; import assert from "node:assert/strict"; -const { translateRequest } = await import("../../open-sse/translator/index.ts"); -const { FORMATS } = await import("../../open-sse/translator/formats.ts"); +const { openaiToGeminiRequest } = await import( + "../../open-sse/translator/request/openai-to-gemini.ts" +); function translateToGemini(messages, tools) { - return translateRequest(FORMATS.OPENAI, FORMATS.GEMINI, "gemini-2.0-flash", { - model: "gemini-2.0-flash", - messages, - tools, - stream: false, - }); + return openaiToGeminiRequest( + "gemini-2.0-flash", + { + model: "gemini-2.0-flash", + messages, + tools, + stream: false, + }, + false, + null, + { signaturelessToolCallMode: "native" } + ); } test("T43: functionCall parts do NOT get a fake thoughtSignature injected", () => { @@ -74,7 +81,7 @@ test("T43: functionCall parts do NOT get a fake thoughtSignature injected", () = assert.ok(modelTurn, "Expected a model turn with functionCall parts"); - const functionCallParts = modelTurn.parts.filter((part) => part.functionCall); + const functionCallParts = modelTurn.parts.filter((part: any) => part.functionCall) as any[]; assert.equal(functionCallParts.length, 1, "Expected exactly 1 functionCall part"); assert.equal(functionCallParts[0].functionCall.name, "get_weather"); assert.deepEqual(functionCallParts[0].functionCall.args, { location: "Tokyo" }); @@ -121,7 +128,7 @@ test("T43: client-provided thoughtSignature is ignored in default enabled cache ); assert.ok(modelTurn, "Expected a model turn with functionCall parts"); - const functionCallParts = modelTurn.parts.filter((p) => p.functionCall); + const functionCallParts = modelTurn.parts.filter((p: any) => p.functionCall) as any[]; assert.equal(functionCallParts.length, 1, "Expected 1 functionCall part"); // In enabled cache mode, client-provided signatures are NOT forwarded diff --git a/tests/unit/translator-helper-branches.test.ts b/tests/unit/translator-helper-branches.test.ts index d41a913eaf..5318462a37 100644 --- a/tests/unit/translator-helper-branches.test.ts +++ b/tests/unit/translator-helper-branches.test.ts @@ -594,6 +594,7 @@ test("translateRequest does not replay reasoning-only messages for non-DeepSeek assert.equal(result.messages[1].reasoning_content, ""); assert.equal(getReasoningCacheServiceStats().replays, 0); clearReasoningCacheAll(); +}); test("translateRequest injects thinking block into Claude-format messages for Kimi K2 reasoning models", () => { clearReasoningCacheAll(); @@ -739,4 +740,3 @@ test("translateRequest does not replay reasoning-only messages for non-DeepSeek clearReasoningCacheAll(); }); -});