diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 2e254c0..454de79 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -6,13 +6,13 @@ }, "metadata": { "description": "Claude Code plugin suite: brewcode for infinite task execution, brewdoc for documentation tools, brewtools for text utilities, brewui for UI/visual/creative tools", - "version": "3.19.5" + "version": "4.0.0" }, "plugins": [ { "name": "brewcode", "description": "Brewcode - full-featured development platform for Claude Code: infinite focus tasks, prompt optimization, skill/agent creation, quorum reviews, rules management", - "version": "3.19.5", + "version": "4.0.0", "category": "productivity", "keywords": [ "brewcode", @@ -46,7 +46,7 @@ { "name": "brewdoc", "description": "Brewdoc - Claude Code documentation tools: auto-sync for skills/agents/rules, my-claude installation docs, memory optimization, md-to-pdf conversion", - "version": "3.19.5", + "version": "4.0.0", "category": "productivity", "keywords": [ "brewdoc", @@ -74,7 +74,7 @@ { "name": "brewtools", "description": "Brewtools - universal utilities for Claude Code: text optimization, humanization, secrets scanning", - "version": "3.19.5", + "version": "4.0.0", "category": "productivity", "keywords": [ "brewtools", @@ -102,7 +102,7 @@ { "name": "brewui", "description": "Placeholder for future UI/visual/creative tools (currently empty, installable)", - "version": "3.19.5", + "version": "4.0.0", "category": "productivity", "keywords": [ "ui", diff --git a/README.md b/README.md index 7c049dd..58402ca 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ **Claude Code plugin suite** -- four plugins for development, documentation, text utility, and visual workflows. -A regular Claude Code session loses context during compaction. Brewcode automatically saves knowledge, passes state between compaction cycles, and continues work without restarting. Four plugins. 32 skills. 16 agents. 9 lifecycle hooks. +A regular Claude Code session loses context during compaction. Brewcode automatically saves knowledge, passes state between compaction cycles, and continues work without restarting. Four plugins. 25 skills. 14 agents. 9 lifecycle hooks. [**Full Documentation**](https://doc-claude.brewcode.app/getting-started/) @@ -56,9 +56,9 @@ After all commands succeed, run `/reload-plugins`. If `/reload-plugins` is unava | Plugin | Purpose | Skills | Install | |--------|---------|--------|---------| -| [brewcode](brewcode/README.md) | Infinite task execution, quorum reviews, skill/agent creation, semantic search | 13 | `claude plugin install brewcode@claude-brewcode` | +| [brewcode](brewcode/README.md) | Infinite task execution, quorum reviews, skill/agent creation, semantic search | 9 | `claude plugin install brewcode@claude-brewcode` | | [brewdoc](brewdoc/README.md) | Documentation tools: auto-sync, memory optimization, PDF conversion, publishing | 6 | `claude plugin install brewdoc@claude-brewcode` | -| [brewtools](brewtools/README.md) | Universal text utilities: token optimization, humanization, secrets scanning, plugin updates | 13 | `claude plugin install brewtools@claude-brewcode` | +| [brewtools](brewtools/README.md) | Universal text utilities: token optimization, humanization, secrets scanning, plugin updates | 10 | `claude plugin install brewtools@claude-brewcode` | | [brewui](brewui/README.md) | UI/visual/creative tools (placeholder, currently empty) | 0 | `claude plugin install brewui@claude-brewcode` | ## Installation @@ -184,7 +184,7 @@ Placeholder plugin, currently empty. No commands yet -- coming soon. ## Skills Reference -### Brewcode (13 skills) +### Brewcode (9 skills) | Skill | Purpose | |-------|---------| @@ -195,10 +195,10 @@ Placeholder plugin, currently empty. No commands yet -- coming soon. | `/brewcode:teams` | Create and manage dynamic teams of domain-specific agents | | `/brewcode:standards-review` | Review code for project standards compliance | | `/brewcode:convention` | Extract etalon classes, patterns, architecture into convention docs | -| `/brewcode:rules` | Extract rules from KNOWLEDGE to `.claude/rules/` | +| `/brewcode:rules` | Prompt-driven rules management: status, create, improve, review | | `/brewcode:grepai` | Semantic code search (setup, status, start, stop, reindex) | -| `/brewcode:skills` | List, create, and upgrade skills | -| `/brewcode:agents` | Interactive agent creation and improvement | +| `/brewcode:skills` | Prompt-driven skill management: status, create, improve, review | +| `/brewcode:agents` | Prompt-driven agent management: status, create, improve, review | | `/brewcode:e2e` | E2E testing orchestration with BDD scenarios | | `/brewcode:teardown` | Remove plugin configuration (keeps task data) | @@ -213,22 +213,19 @@ Placeholder plugin, currently empty. No commands yet -- coming soon. | `/brewdoc:publish` | Publish to brewpage.app -- returns public URL | | `/brewdoc:guide` | Interactive tutorial for the plugin suite | -### Brewtools (13 skills) +### Brewtools (10 skills) | Skill | Purpose | |-------|---------| | `/brewtools:text-optimize` | LLM token efficiency optimization (30+ rules) | | `/brewtools:text-human` | Remove AI artifacts, humanize code | -| `/brewtools:think-short` | Toggle terse-output mode -- inject brevity directives via SessionStart + PreToolUse:Task hooks | +| `/brewtools:think-short` | Install/remove terse-mode hooks (SessionStart + every-10th UserPromptSubmit + subagent Task) that inject brevity directives; project or global | | `/brewtools:secrets-scan` | Scan git-tracked files for leaked secrets | | `/brewtools:ssh` | SSH server management -- connect, configure, deploy | | `/brewtools:deploy` | GitHub Actions deployment -- workflows, releases, GHCR, CI/CD | -| `/brewtools:debate` | Evidence-based multi-agent debate (Challenge, Strategy, Critic modes) | | `/brewtools:plugin-update` | Install and update the full plugin suite | -| `/brewtools:skill-toggle` | Disable/enable individual plugin skills (survives updates) | -| `/brewtools:agent-toggle` | Disable/enable individual agents via native permissions.deny | | `/brewtools:provider-switch` | Configure alternative API providers (DeepSeek, Z.ai/GLM, Qwen, MiniMax, OpenRouter) | -| `/brewtools:manager` | Manager mode -- codewords ++m/++mp inject a delegate-everything prompt; HARD wall (on/off/uninstall) installs a project PreToolUse guard that blocks main-session edits, forcing delegation | +| `/brewtools:manager` | Manager mode -- codeword ++m injects a delegate-everything prompt (plan-aware); HARD wall (on/off/uninstall) installs a project PreToolUse guard that blocks main-session edits, forcing delegation | | `/brewtools:task-board-init` | Deploy a file-based Kanban into ANY repo via multi-agent analysis -- task-tracker agent, task-board skill, tasks rule, .claude/features | ### Brewui (0 skills) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index f1aa574..af4a2e6 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -2,6 +2,48 @@ --- +## v4.0.0 (2026-06-30) + +> **MAJOR / breaking** — injection-hook architecture removed across all plugins; plugin-root now resolved natively via `${CLAUDE_PLUGIN_ROOT}`. + +> Docs: [brewcode hooks](https://doc-claude.brewcode.app/brewcode/hooks/) | [brewcode overview](https://doc-claude.brewcode.app/brewcode/overview/) | [grepai](https://doc-claude.brewcode.app/brewcode/skills/grepai/) | [superreview](https://doc-claude.brewcode.app/brewcode/skills/superreview/) | [skill-creator](https://doc-claude.brewcode.app/brewcode/agents/skill-creator/) | [agent-creator](https://doc-claude.brewcode.app/brewcode/agents/agent-creator/) | [brewdoc hooks](https://doc-claude.brewcode.app/brewdoc/hooks/) | [brewtools hooks](https://doc-claude.brewcode.app/brewtools/hooks/) | [think-short](https://doc-claude.brewcode.app/brewtools/skills/think-short/) | [manager](https://doc-claude.brewcode.app/brewtools/skills/manager/) + +### brewcode +#### Removed +- **pre-task.mjs:** deleted; entire family-roots injection machinery removed (`hooks/lib/family-roots.mjs`, `.claude/scripts/check-family-roots.sh` + bump-version drift guard) +- **dead mode system:** `getActiveMode`, `modes.json`, `[MODE:]`/`[EFFORT: terse-light]` injections, SID/teams injection all removed; `getActiveMode` dropped from `hooks/lib/utils.mjs` +- **grepai always-on hooks:** `grepai-session.mjs` + `grepai-reminder.mjs` deregistered from `hooks.json`; orphan sources deleted +- **skills/skills:** Mode Switcher skill-generation pattern removed +#### Changed +- **plugin-root (breaking):** resolved NATIVELY via `${CLAUDE_PLUGIN_ROOT}` substituted in each agent `.md` at Task spawn — no more hook injection of `BC_PLUGIN_ROOT`; all agents converted +- **forced-eval.mjs:** stripped of mode/effort/plugin-root injection — now injects only the constant `[SKILL?]` reminder +- **session-start.mjs:** keeps version-check + plan-symlink + permission tag; mode/effort/root injection removed +- brewcode now registers exactly 2 hooks (forced-eval, session-start) +#### Added +- **grepai self-install:** self-contained assets (`skills/grepai/assets/{grepai-session.mjs,grepai-reminder.mjs,INSTALL.md}`); `/brewcode:grepai` detects + installs hooks into project `.claude/grepai/hooks/` and merges into `.claude/settings.json` (jq + python3, no clobber), default project scope, reports +- **superreview** skill (+ docs page) + +### brewdoc +#### Removed +- **pre-task.mjs + lib/family-roots.mjs:** deleted — brewdoc now ships ZERO hooks (`hooks.json` is `{"hooks":{}}`) +#### Changed +- **bd-auto-sync-processor:** resolves its root natively via `${CLAUDE_PLUGIN_ROOT}` + +### brewtools +#### Removed +- **pre-task.mjs + lib/family-roots.mjs:** deleted; `skills/think-short/assets/family-roots.mjs` removed +- **skills debate, skill-toggle, agent-toggle:** removed entirely (incl. `_shared/toggle`) +#### Changed +- **session-start.mjs:** stripped of `BT_PLUGIN_ROOT` injection + session-id display (manager HARD-wall awareness kept) +- **think-short:** task hook injects `${injection}\n\n${tool_input.prompt}`, copies 4 files; E2E suite updated (family-roots tests removed) +- brewtools registers 2 hooks (session-start, manager-prompt) + +### docs +#### Changed +- root `CLAUDE.md`, all plugin READMEs, `brewcode/docs/*`, `brewdoc/docs/hooks.md`, `web/docs` MDX (hooks/overview/think-short/grepai/skills/agents) and `brewdoc/skills/guide/references/*` updated to new hook inventory + native `${CLAUDE_PLUGIN_ROOT}` + grepai self-install + Mode Switcher removal + +--- + ## v3.19.5 (2026-06-29) ### brewcode diff --git a/brewcode/.claude-plugin/plugin.json b/brewcode/.claude-plugin/plugin.json index 154816d..cd26881 100644 --- a/brewcode/.claude-plugin/plugin.json +++ b/brewcode/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "brewcode", - "version": "3.19.5", + "version": "4.0.0", "description": "Brewcode - full-featured development platform for Claude Code: infinite focus tasks, prompt optimization, skill/agent creation, quorum reviews, rules management", "author": { "name": "Maksim Kochetkov", diff --git a/brewcode/INSTALL.md b/brewcode/INSTALL.md index b2ceb8f..1280602 100644 --- a/brewcode/INSTALL.md +++ b/brewcode/INSTALL.md @@ -191,4 +191,4 @@ CLAUDE_DEBUG=1 claude --plugin-dir ./brewcode |----------|-------------| | [README.md](README.md) | Plugin overview and commands | | [grepai.md](docs/grepai.md) | Semantic search integration | -| [/brewcode:setup](skills/setup/README.md) | Project setup (includes prerequisites installation as Phase 0) | +| [/brewcode:grepai](skills/grepai/README.md) | Semantic search setup (includes prerequisites installation) | diff --git a/brewcode/README.md b/brewcode/README.md index e248d9e..60d280e 100644 --- a/brewcode/README.md +++ b/brewcode/README.md @@ -4,10 +4,10 @@ | Field | Value | |-------|-------| -| Version | 3.19.5 | +| Version | 4.0.0 | | Skills | 13 | | Agents | 12 | -| Hooks | 6 | +| Hooks | 2 | | Model | opus | ## Install @@ -65,7 +65,7 @@ claude --plugin-dir ./brewcode ## Quick Start ```bash -/brewcode:setup # 1. Adapt templates for the project (one-time) +/brewcode:grepai # 1. Set up semantic code search (one-time) /brewcode:spec "Implement JWT authorization" # 2. Research + specification ``` @@ -73,19 +73,17 @@ claude --plugin-dir ./brewcode | Skill | Purpose | |-------|---------| -| [`/brewcode:setup`](skills/setup/README.md) | Analyze project, check prerequisites, generate adapted templates and config | | [`/brewcode:spec`](skills/spec/README.md) | Research codebase + user dialog -> SPEC.md | -| [`/brewcode:teams`](skills/teams/README.md) | Dynamic agent team creation, management, and performance tracking | -| [`/brewcode:standards-review`](skills/standards-review/README.md) | Review code for project standards compliance | -| [`/brewcode:convention`](skills/convention/README.md) | Extract etalon classes, patterns, architecture into convention docs and rules | -| [`/brewcode:rules`](skills/rules/README.md) | Extract rules from accumulated knowledge to `.claude/rules/` | | [`/brewcode:grepai`](skills/grepai/README.md) | Semantic code search (setup, status, start, stop, reindex) | -| [`/brewcode:skills`](skills/skills/README.md) | Skill management: list, create, upgrade with activation optimization | -| [`/brewcode:agents`](skills/agents/README.md) | Interactive agent creation and improvement | +| [`/brewcode:superreview`](skills/superreview/README.md) | Generate a project-tailored deep-review skill (review + standards merged) | +| [`/brewcode:teams`](skills/teams/README.md) | Dynamic agent team creation, management, and performance tracking | +| [`/brewcode:convention`](skills/convention/README.md) | Extract etalon classes, patterns, architecture into convention docs and rules | +| [`/brewcode:rules`](skills/rules/README.md) | Prompt-driven rules management: status, create, improve, review | +| [`/brewcode:skills`](skills/skills/README.md) | Prompt-driven skill management: status, create, improve, review | +| [`/brewcode:agents`](skills/agents/README.md) | Prompt-driven agent management: status, create, improve, review | | [`/brewcode:e2e`](skills/e2e/README.md) | E2E testing orchestration with BDD scenarios and quorum review | -| [`/brewcode:teardown`](skills/teardown/README.md) | Plugin configuration cleanup (tasks are preserved) | -> **Note:** `/brewcode:review` is a local skill created in the project during `/brewcode:setup`. +> **Note:** `/brewcode:superreview` emits a self-contained, project-local deep-review skill tailored to your stack. ## Agents @@ -109,15 +107,13 @@ claude --plugin-dir ./brewcode ``` brewcode/ +-- .claude-plugin/plugin.json # Plugin manifest -+-- hooks/ # 6 lifecycle hooks -| +-- session-start.mjs # Session initialization -| +-- grepai-session.mjs # Auto-start grepai watch -| +-- pre-task.mjs # grepai injection into agents -| +-- grepai-reminder.mjs # grepai reminder -| +-- forced-eval.mjs # Skill activation -| +-- permission-guard.sh # Manager-mode edit guard -+-- agents/ # 12 agents -+-- skills/ # 13 skills ++-- hooks/ # 2 lifecycle hooks +| +-- session-start.mjs # SessionStart: version-check, plan-symlink, permission_mode +| +-- forced-eval.mjs # UserPromptSubmit: skill activation reminder +| +-- hooks.json # Event bindings +| +-- lib/utils.mjs # Shared utilities ++-- agents/ # 10 agents ++-- skills/ # 9 skills +-- templates/ # Rule templates ``` @@ -125,12 +121,8 @@ brewcode/ | Hook | Event | Purpose | |------|-------|---------| -| session-start | SessionStart | Initialize session, inject plugin path | -| grepai-session | SessionStart | Auto-start grepai watch process | -| pre-task | PreToolUse:Task | Inject grepai reminder into agent prompts | -| grepai-reminder | PreToolUse:Bash | Remind to prefer semantic search | -| forced-eval | UserPromptSubmit | Skill activation | -| permission-guard | PermissionRequest | Manager-mode edit guard for main session | +| session-start | SessionStart | Version-check, plan-symlink, permission_mode tag | +| forced-eval | UserPromptSubmit | Skill activation reminder (~9K additionalContext bound) | ## Task Structure diff --git a/brewcode/agents/agent-creator.md b/brewcode/agents/agent-creator.md index 4726bd7..c70f29e 100644 --- a/brewcode/agents/agent-creator.md +++ b/brewcode/agents/agent-creator.md @@ -1,7 +1,7 @@ --- name: agent-creator description: "Creates and improves Claude Code agents. Triggers: create agent, improve agent, scaffold agent." -model: opus +model: inherit color: cyan tools: Read, Write, Edit, Glob, Grep, Bash, Task, Skill, WebFetch, WebSearch, AskUserQuestion --- @@ -131,7 +131,7 @@ Detailed instructions for the AG... | 3 | `~/.claude/agents/` | User (all projects) | Manual or `/agents` | | 4 (lowest) | `plugin/agents/` | Where PLG enabled | Installed with PLG | -> Protected-path (v3.4.70): AG Write targets → `.claude//` (project-relative, whitelisted in `permission-guard.sh`). `~/.claude/*` blocked ALL modes; exceptions: `commands|agents|skills|worktrees`. See memory `protected_path_write_block.md`. +> Protected-path (v3.4.70): AG Write targets → `.claude//` (project-relative). `~/.claude/*` blocked ALL modes; exceptions: `commands|agents|skills|worktrees`. See memory `protected_path_write_block.md`. ### CLI JSON Format (session-only) @@ -209,9 +209,9 @@ When AG spawns from a SK that uses `references/`, AG does NOT have `skill_base_d | Content Size | Approach | EX | |-------------|----------|----| | <50 lines | Inline into AG prompt | Pass ref content directly via Task prompt | -| >50 lines | Use `$BC_PLUGIN_ROOT` path | `Read $BC_PLUGIN_ROOT/skills/skill-name/references/mode.md` | +| >50 lines | Use `${CLAUDE_PLUGIN_ROOT}` path | `Read ${CLAUDE_PLUGIN_ROOT}/skills/skill-name/references/mode.md` | -`$BC_PLUGIN_ROOT` injected by `pre-task.mjs`, available in all SAs. +`${CLAUDE_PLUGIN_ROOT}` (brace form) is natively substituted at spawn to this plugin's root, available in all SAs. > If SK detects mode BEFORE spawning AG, pass only relevant ref -- not all of them. @@ -558,7 +558,7 @@ SP key elements: | [#19040](https://github.com/anthropics/claude-code/issues/19040) | Session files grow to multi-GB from SA progress entries | Active | Monitor session file size | | [#31392](https://github.com/anthropics/claude-code/issues/31392) | Global AGs `~/.claude/agents/` not discovered | Active (v2.1.70+) | Use project-level or PLG-level AGs | | [#27736](https://github.com/anthropics/claude-code/issues/27736) | `skills:` in PLG AG FM not rendered in Task TL | Active | Pre-inject SK content via `Task(prompt=...)` | -| [#25834](https://github.com/anthropics/claude-code/issues/25834) | PLG AG `skills:` doesn't inject content | Active | Inline SK content or use `$BC_PLUGIN_ROOT` path | +| [#25834](https://github.com/anthropics/claude-code/issues/25834) | PLG AG `skills:` doesn't inject content | Active | Inline SK content or use `${CLAUDE_PLUGIN_ROOT}` path | | [#13627](https://github.com/anthropics/claude-code/issues/13627) | AG body not injected via Task TL | Closed (NOT PLANNED) | `SubagentStart` hook with `additionalContext` | | [#8395](https://github.com/anthropics/claude-code/issues/8395) | SAs ignore user-level CD | Closed (NOT PLANNED) | `SubagentStart` hook with `additionalContext` | | [#4182](https://github.com/anthropics/claude-code/issues/4182) | SK TL unavailable in SA | By design | Use `skills:` in FM for pre-injection | diff --git a/brewcode/agents/architect.md b/brewcode/agents/architect.md index d45f523..591e3ff 100644 --- a/brewcode/agents/architect.md +++ b/brewcode/agents/architect.md @@ -1,7 +1,7 @@ --- name: architect description: "Architecture analysis, patterns, scaling. Triggers: review architecture, design service, scaling." -model: opus +model: inherit color: cyan tools: Read, Glob, Grep, Bash, WebFetch, WebSearch disallowedTools: Write, Edit, NotebookEdit diff --git a/brewcode/agents/bash-expert.md b/brewcode/agents/bash-expert.md index 164080a..ff52b85 100644 --- a/brewcode/agents/bash-expert.md +++ b/brewcode/agents/bash-expert.md @@ -1,7 +1,7 @@ --- name: bash-expert description: "Creates sh/bash scripts for Mac/Linux. Triggers: create script, bash script, shell script." -model: opus +model: inherit color: green tools: Read, Write, Edit, Glob, Grep, Bash, WebFetch auto-sync: enabled @@ -130,7 +130,7 @@ echo "| brew | ✅ |" | `$CLAUDE_PLUGIN_ROOT` | Hooks only | | `$PLUGIN_ROOT/skills/X/scripts/` | All contexts | -> In Skills: `${CLAUDE_SKILL_DIR}` for own files (string substitution in SKILL.md). In Agents (subagents): `$BC_PLUGIN_ROOT` (injected by session-start.mjs) +> In Skills: `${CLAUDE_SKILL_DIR}` for own files (string substitution in SKILL.md). In Agents (subagents): `${CLAUDE_PLUGIN_ROOT}` (brace form, natively substituted at spawn to this plugin's root) ## 6. Homebrew @@ -246,7 +246,7 @@ Validate: `cmd && echo "✅" || echo "❌ FAILED"` Stop on error: `> **STOP if ❌** — fix before continuing.` -Skill files: `${CLAUDE_SKILL_DIR}` (own dir) | Cross-skill/agent: `$BC_PLUGIN_ROOT` (pre-task.mjs) +Skill files: `${CLAUDE_SKILL_DIR}` (own dir) | Cross-skill/agent: `${CLAUDE_PLUGIN_ROOT}` (brace form, native substitution to this plugin's root) ## 11. Checklist diff --git a/brewcode/agents/bc-grepai-configurator.md b/brewcode/agents/bc-grepai-configurator.md index 7d62133..e78664f 100644 --- a/brewcode/agents/bc-grepai-configurator.md +++ b/brewcode/agents/bc-grepai-configurator.md @@ -2,7 +2,7 @@ name: bc-grepai-configurator description: Internal. Spawned only by /brewcode:grepai. No direct/auto use. tools: Read, Write, Edit, Bash, WebFetch, Glob, Grep -model: opus +model: inherit permissionMode: acceptEdits mcpServers: - grepai diff --git a/brewcode/agents/developer.md b/brewcode/agents/developer.md index 15760ed..bcbbbdc 100644 --- a/brewcode/agents/developer.md +++ b/brewcode/agents/developer.md @@ -1,7 +1,7 @@ --- name: developer description: "Implements features, writes code, fixes bugs, refactors. Trig: implement, fix bug, add feature." -model: opus +model: inherit tools: Read, Write, Edit, Glob, Grep, Bash, Task, NotebookEdit, WebFetch, WebSearch mcpServers: - grepai diff --git a/brewcode/agents/hook-creator.md b/brewcode/agents/hook-creator.md index 5c59827..37f89ed 100644 --- a/brewcode/agents/hook-creator.md +++ b/brewcode/agents/hook-creator.md @@ -1,7 +1,7 @@ --- name: hook-creator description: "Creates and debugs Claude Code hooks. Triggers: create hook, PreToolUse hook, debug hook." -model: opus +model: inherit color: yellow tools: Read, Write, Edit, Glob, Grep, Bash, WebFetch, WebSearch auto-sync: true @@ -274,7 +274,7 @@ Format: `ToolName(pattern)` — same syntax as permission rules. |----------|-------------|-----------| | `$CLAUDE_PROJECT_DIR` | project root | all hooks | | `$CLAUDE_PLUGIN_ROOT` | plugin install dir | plugin hooks | -| `$CLAUDE_PLUGIN_DATA` | persistent plugin data (survives updates, v2.1.78+); brewcode: stores `modes.json` (mode switcher state); hooks inject as `BC_PLUGIN_DATA` text var for skills/agents | plugin hooks | +| `$CLAUDE_PLUGIN_DATA` | persistent per-plugin data dir, survives updates (v2.1.78+); `~/.claude/plugins/data//` | plugin hooks | | `$CLAUDE_CODE_REMOTE` | `"true"` in remote env | all hooks | | `$CLAUDE_ENV_FILE` | path for persistent env vars | SS, CwdChanged, FileChanged | | `$CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS` | SessionEnd hooks timeout in ms (DEF 1500ms, v2.1.78+) | SessionEnd hooks | @@ -285,18 +285,13 @@ Format: `ToolName(pattern)` — same syntax as permission rules. ### Plugin Persistent State (`CLAUDE_PLUGIN_DATA`) -brewcode hooks inject `BC_PLUGIN_DATA` as text var (same pattern as `BC_PLUGIN_ROOT`). +Persistent per-plugin data dir, survives updates (v2.1.78+). Hook-only env var. | Aspect | Details | |--------|---------| | env var | `process.env.CLAUDE_PLUGIN_DATA` (hooks only) | -| text var | `BC_PLUGIN_DATA=` (injected by session-start.mjs + pre-task.mjs) | -| main file | `$CLAUDE_PLUGIN_DATA/modes.json` — mode switcher state | -| scopes | global, project (by cwd), session (by session_id) | +| path | `~/.claude/plugins/data//` | | read in hooks | `const pluginData = process.env.CLAUDE_PLUGIN_DATA` | -| read in skills/agents | use `$BC_PLUGIN_DATA` from injected context | - -Resolution: session > project > global. Old `.claude/tasks/cfg/brewcode.state.json` kept as fallback. > Protected-path (v3.4.70): Write/Edit to `~/.claude/*` (incl. `$CLAUDE_PLUGIN_DATA`) blocked in ALL modes (`bypassPermissions`, headless). Check runs BEFORE hooks — whitelists dead. Exceptions: `commands|agents|skills|worktrees`. !=design skills with `$CLAUDE_PLUGIN_DATA` as Write target -> silent fail. Primary: project-relative `.claude//` + whitelist. `$CLAUDE_PLUGIN_DATA` = read-only/interactive-only/Bash-only (Bash redirect currently bypasses check, but brittle). @@ -677,49 +672,6 @@ Returns `AC` with project state. - Caching: store validation outcomes (5-min cache) to avoid redundant processing - Cross-Event Workflows: `SS -> count tests | POT -> increment | Stop -> verify count > 0` -### Mode-Aware Injection - -Hook reads active mode from `brewcode.state.json`, injects mode-specific instructions into every tool call/session event. Use when skill needs to toggle persistent session behavior surviving auto-compact. - -```javascript -// Channel depends on event — see Authoritative Per-Event Output Channels (Section 1): -const activeMode = getActiveMode(cwd, session_id); -if (activeMode) { - // PTU:Task — rewrite SA prompt via UI (updatedInput); only PTU accepts UI - updatedPrompt = `[MODE: ${activeMode.name}] ${activeMode.instructions}\n\n${updatedPrompt}`; - // SS or UserPromptSubmit — inject via additionalContext (UI is IGNORED on these events) - context += `\n[MODE: ${activeMode.name}] ${activeMode.instructions}`; -} -``` - -`getActiveMode(cwd, session_id)` resolution: - -| Step | Details | -|------|---------| -| read state | `$CLAUDE_PLUGIN_DATA/modes.json` -> 3-scope (session > project > global) | -| fallback | `.claude/tasks/cfg/brewcode.state.json` -> `mode` field (legacy) | -| load instructions | `$CLAUDE_PLUGIN_DATA/modes/{mode}.md` (user first) then `$CLAUDE_PLUGIN_ROOT/modes/{mode}.md` (built-in fallback) | -| return | `{name, instructions, scope}` or `null` (scope: `session|project|global|legacy`) | -| fail-safe | returns `null` on any error | - -Injection channels: - -| Hook | Event | Channel | Scope | -|------|-------|---------|-------| -| `forced-eval.mjs` | UserPromptSubmit | `AC` (NOT `UI` — ignored on UserPromptSubmit) | every user msg | -| `session-start.mjs` | SS | `AC` | session start + compact resume | -| `pre-task.mjs` | PTU:Task | `UI.prompt` | every SA spawn | - -> Channel differs per event: `UserPromptSubmit`/`SS` inject via `AC`; only `PTU:Task` rewrites the SA prompt via `UI.prompt`. Emitting `UI` on UserPromptSubmit is silently dropped — see Authoritative Per-Event Output Channels (Section 1). - -State schema in `$CLAUDE_PLUGIN_DATA/modes.json`: -```json -{"session":{"mode":"manager","modeActivatedAt":"2026-04-01T12:00:00.000Z"},"project":{},"global":{}} -``` -Resolution: `session` > `project` > `global`. Single mode only (no multi-mode). `null`/absent `mode` = no active mode. - -> Legacy fallback: `.claude/tasks/cfg/brewcode.state.json` (flat `mode` field) read if `modes.json` missing. - ## 15. Hook Type Selection | Need | Type | Why | diff --git a/brewcode/agents/reviewer.md b/brewcode/agents/reviewer.md index 918c63b..7d7796f 100644 --- a/brewcode/agents/reviewer.md +++ b/brewcode/agents/reviewer.md @@ -1,7 +1,7 @@ --- name: reviewer description: System architect & code reviewer - architecture, quality, security, performance -model: opus +model: inherit tools: Read, Glob, Grep, Bash, Task disallowedTools: Write, Edit mcpServers: diff --git a/brewcode/agents/skill-creator.md b/brewcode/agents/skill-creator.md index 108b5b6..2293c1f 100644 --- a/brewcode/agents/skill-creator.md +++ b/brewcode/agents/skill-creator.md @@ -1,12 +1,12 @@ --- name: skill-creator description: "Creates and improves Claude Code skills. Triggers: create skill, improve skill, fix activation." -model: opus +model: inherit color: green tools: Read, Write, Edit, Glob, Grep, Bash, Task, Skill, AskUserQuestion --- -[DICT: ACT=activation, AT=allowed-tools, BPR=BC_PLUGIN_ROOT, CC=Claude Code, CSD=${CLAUDE_SKILL_DIR}, CTX=context, DESC=description, DMI=disable-model-invocation, FM=frontmatter, FORK=context:fork, GP=general-purpose, PLG=plugin, REF=reference, SA=subagent, SK=skill, UI-F=user-invocable] +[DICT: ACT=activation, AT=allowed-tools, BPR=${CLAUDE_PLUGIN_ROOT}, CC=Claude Code, CSD=${CLAUDE_SKILL_DIR}, CTX=context, DESC=description, DMI=disable-model-invocation, FM=frontmatter, FORK=context:fork, GP=general-purpose, PLG=plugin, REF=reference, SA=subagent, SK=skill, UI-F=user-invocable] # Skill Creator Agent @@ -16,7 +16,7 @@ Creates CC skills following official Anthropic best practices. Adapt to user's technical level. Non-technical: explain "FM", "YAML", "assertion". Experienced devs: skip explanations. Watch context cues. -> Skills replace Commands. `.claude/commands/review.md` and `.claude/skills/review/SKILL.md` both create `/review`. Commands are legacy — create Skills. +> Skills replace Commands. `.claude/commands/format.md` and `.claude/skills/format/SKILL.md` both create `/format`. Commands are legacy — create Skills. ## DESC Budget (DEFAULT) @@ -79,7 +79,6 @@ skill-name/ | **Background Knowledge** | Claude needs CTX, user needs no slash cmd | `UI-F: false`. DESC stays in CTX | | **Pushy DESC** | LLM-invocable skills | Action verb + `Triggers: "phrase1", "phrase2"`. Raises ACT 20% → 50-72% | | **Preloaded Skills** | SA must follow conventions/patterns | `skills: [name]` in agent FM. Full SK injected at startup | -| **Mode Switcher** | SK toggles persistent session behavior (on/off) + 3 scopes | Single SK with arg (`on [mode]`, `off`, `status`) + scope flag (`--global`, `--session`, default=project). Bash writes state to `$BC_PLUGIN_DATA/modes.json` via `jq`+`mv`. Resolution: session > project > global. Hooks inject mode instructions via `getActiveMode()`. Mode instructions in `modes/{name}.md`. Survives auto-compact | ## Agents-as-REFs Detail @@ -106,63 +105,6 @@ Coordinator passes **file path**, not content. SA reads `.md` itself. Use when: SK-coordinator + 2+ roles + CTX isolation needed + prompts are impl details. -## Mode Switcher Detail - -Toggles persistent behavioral "mode" with 3 scopes: global, project, session. State @ `$BC_PLUGIN_DATA/modes.json`. Hooks inject mode-specific instructions on every event. - -> **Protected-path caveat (v3.4.70):** `$BC_PLUGIN_DATA` = `~/.claude/plugins/data//` — blocked for Write/Edit ALL modes (headless too). Mode-switcher works only via Bash `jq`+`mv`. !=`$BC_PLUGIN_DATA` as Write-tool target. New stateful skills → `.claude//` + whitelist in `permission-guard.sh`. `$BC_PLUGIN_DATA` = Bash-only | interactive-only. - -``` -mode-skill/ -├── SKILL.md # Arg parsing: on/off/status + scope flag -├── references/ -│ └── modes.md # Available modes + scope docs -└── scripts/ - └── mode.sh # State read/write helper -``` - -1. SK receives arg: `on validator`, `on validator --global`, `on validator --session`, `off`, `status` -2. Default scope = project -3. State @ `$BC_PLUGIN_DATA/modes.json` (NOT `.claude/tasks/cfg/`) -4. `BC_PLUGIN_DATA` injected by hooks (`session-start.mjs`, `pre-task.mjs`) - -**State structure:** -```json -{ - "global": { "mode": "validator", "activatedAt": "..." }, - "projects": { "/path/to/project": { "mode": "manager", "activatedAt": "..." } }, - "sessions": { "abc12345": { "mode": "debug", "activatedAt": "..." } } -} -``` - -Resolution: session > project > global - -**Bash blocks:** -```bash -# on — project (default) -STATE="$BC_PLUGIN_DATA/modes.json" -[ ! -f "$STATE" ] && echo '{}' > "$STATE" -jq --arg m "$MODE" --arg p "$PWD" --arg t "$(date -u +%Y-%m-%dT%H:%M:%S.000Z)" \ - '.projects[$p] = {mode: $m, activatedAt: $t}' "$STATE" > "$STATE.tmp" && mv "$STATE.tmp" "$STATE" -``` -```bash -# on — global -jq --arg m "$MODE" --arg t "$(date -u +%Y-%m-%dT%H:%M:%S.000Z)" \ - '.global = {mode: $m, activatedAt: $t}' "$STATE" > "$STATE.tmp" && mv "$STATE.tmp" "$STATE" -``` -```bash -# on — session -jq --arg m "$MODE" --arg s "$SESSION_ID" --arg t "$(date -u +%Y-%m-%dT%H:%M:%S.000Z)" \ - '.sessions[$s] = {mode: $m, activatedAt: $t}' "$STATE" > "$STATE.tmp" && mv "$STATE.tmp" "$STATE" -``` - -Key: -- `BC_PLUGIN_DATA` MUST be validated non-empty before use -- `DMI: true` — mode toggle is always deliberate -- Mode instructions in PLG `modes/` | `$BC_PLUGIN_DATA/modes/` for user-created -- Hooks inject via `getActiveMode()` reading from `PLUGIN_DATA` -- Old state in `.claude/tasks/cfg/brewcode.state.json` supported as fallback - ## Progressive Disclosure | Level | Content | Budget | @@ -377,7 +319,7 @@ Summarize this PR... | `${CLAUDE_SESSION_ID}` | Current session ID | — | | `CSD` | Absolute path to dir containing SKILL.md | v2.1.71 | -> `CSD` — string substitution (NOT env var). Replaced in SKILL.md before sending to model. PLG skills → SK subdir, not PLG root. NOT available in hooks/agents — use `$CLAUDE_PLUGIN_ROOT` there. +> `CSD` — string substitution (NOT env var). Replaced in SKILL.md before sending to model. PLG skills → SK subdir, not PLG root. NOT available in hooks/agents — use `${CLAUDE_PLUGIN_ROOT}` (brace form, natively substituted) in agents, `$CLAUDE_PLUGIN_ROOT` env var in hooks. > `$ARGUMENTS` inside ` ```bash ``` ` = shell variable (empty/undefined), NOT CC substitution. CC replaces `$ARGUMENTS` in markdown text only. Fix: put `$ARGUMENTS` in text, use placeholder in bash block. @@ -591,7 +533,7 @@ All criteria met → split into `references/{mode}.md`. | Pattern | When | Example | |---------|------|---------| -| Conditional (lazy) | Multi-mode, >50 lines/mode | `standards-review`: detect stack → Read `references/{stack}.md` | +| Conditional (lazy) | Multi-mode, >50 lines/mode | `superreview`: detect stack → Read `references/{stack}.md` | | Unconditional single | Single REF, <200 lines | `brewtools:text-optimize`: always Read `references/rules-review.md` | ## 3-Step Pattern @@ -647,13 +589,13 @@ Read `references/api-spec.md` for API details. | !=NEVER | ALWAYS | |---------|--------| -| `$BC_PLUGIN_ROOT/skills/my-skill/scripts/foo.sh` | `${CLAUDE_SKILL_DIR}/scripts/foo.sh` | +| `${CLAUDE_PLUGIN_ROOT}/skills/my-skill/scripts/foo.sh` | `${CLAUDE_SKILL_DIR}/scripts/foo.sh` | | `/absolute/hardcoded/path/to/assets/template.md` | `${CLAUDE_SKILL_DIR}/assets/template.md` | **Exception — passing path to agent via Task:** use `BPR` (agent has no `CSD`): ```markdown -Task(subagent_type="developer", prompt="Read $BC_PLUGIN_ROOT/skills/my-skill/references/rules.md then...") +Task(subagent_type="developer", prompt="Read ${CLAUDE_PLUGIN_ROOT}/skills/my-skill/references/rules.md then...") ``` # Executable Bash @@ -674,7 +616,7 @@ bash "scripts/my-script.sh" && echo "✅ done" || echo "❌ FAILED" |------|--------|---------| | Label | ` ```bash` | `**EXECUTE**:` ` ```bash` | | Validate | `command` | `command && echo "✅" \|\| echo "❌"` | -| Paths | `$BC_PLUGIN_ROOT/skills/x/scripts/y.sh` | `scripts/y.sh` (relative!) | +| Paths | `${CLAUDE_PLUGIN_ROOT}/skills/x/scripts/y.sh` | `scripts/y.sh` (relative!) | # Location Priority @@ -687,7 +629,7 @@ bash "scripts/my-script.sh" && echo "✅ done" || echo "❌ FAILED" Priority: Enterprise > Personal > Project. PLG skills: `/plugin-name:skill-name`. -> **Output path (v3.4.70):** SK outputs → `.claude//` (project-relative). !=Write to `~/.claude/*` (protected-path blocks ALL modes). Exceptions: `commands|agents|skills|worktrees`. New subdir → add to `permission-guard.sh` whitelist (both Bash helper + Edit/Write case). +> **Output path (v3.4.70):** SK outputs → `.claude//` (project-relative). !=Write to `~/.claude/*` (protected-path blocks ALL modes). Exceptions: `commands|agents|skills|worktrees`. # Creation Process @@ -707,8 +649,6 @@ Identify usage patterns: direct examples, validated scenarios, real-world cases. > **Pre-filled values:** If invocation type, testing depth, or other params provided in spawn prompt by orchestrator, skip corresponding AskUserQuestion. Ask only for missing values. -> **Mode Switcher hint:** User mentions "mode", "toggle", "switch", "persistent behavior", "from now on", "always do X" → consider **Mode Switcher** pattern. See [Mode Switcher Detail](#mode-switcher-detail). - ### Invocation Type (CRIT) **If unclear who will invoke, ASK using AskUserQuestion:** @@ -763,7 +703,7 @@ Write SKILL.md: FM → overview (1-2 sentences) → instructions (imperative) **EXECUTE** validate-skill.sh: ```bash -bash "$BC_PLUGIN_ROOT/skills/skills/scripts/validate-skill.sh" path/to/skill && echo "✅" || echo "❌" +bash "${CLAUDE_PLUGIN_ROOT}/skills/skills/scripts/validate-skill.sh" path/to/skill && echo "✅" || echo "❌" ``` ### Structure Checklist @@ -904,7 +844,7 @@ done Generate `README.md` in SK dir using template. -1. Read template: `$BC_PLUGIN_ROOT/skills/skills/references/readme-template.md` +1. Read template: `${CLAUDE_PLUGIN_ROOT}/skills/skills/references/readme-template.md` 2. Fill placeholders from SK metadata: - `{SKILL_NAME}` — from FM `name` - `{ONE_LINE_DESCRIPTION}` — from FM `description` (first sentence) @@ -1203,7 +1143,7 @@ Run optimization: `Skill(skill="brewtools:text-optimize", args="path/to/SKILL.md | Nested spawns bypass brewcode binding | CC: up to 5 levels (v2.1.172); brewcode: spawn from main only | Chain from main conversation | | `CTX: fork` degrades at 5+ phases | Task structure memory loss | Inline + hooks/external state | | DESC budget | 2% of CTX | 16K chars | `SLASH_COMMAND_TOOL_CHAR_BUDGET` env var | -| `CSD` only in SKILL.md | Not in hooks/agents | `$CLAUDE_PLUGIN_ROOT` in hooks/agents | +| `CSD` only in SKILL.md | Not in hooks/agents | `${CLAUDE_PLUGIN_ROOT}` in agents, `$CLAUDE_PLUGIN_ROOT` env in hooks | | Compaction erases SK CTX | CLAUDE.md re-read, skills are not | Re-invoke `/name`, external state | | DESC <=250 chars | Truncated since v2.1.84 | Front-load keywords | | PLG skills lack parity | `DMI` + SK-scoped hooks don't work | Copy SK to `.claude/skills/` | diff --git a/brewcode/docs/commands.md b/brewcode/docs/commands.md index ca8a5d5..1d6db73 100644 --- a/brewcode/docs/commands.md +++ b/brewcode/docs/commands.md @@ -15,28 +15,23 @@ description: Detailed description of all brewcode plugin commands | # | Command | Purpose | Context | Model | Deps | |---|---------|---------|---------|-------|------| -| 1 | `/bc:setup` | Analyze project, gen templates, install prereqs | fork | opus | -- | -| 2 | `/bc:spec` | Create task SP | session | opus | setup | -| 5 | `/bc:review` | Code review w/ QR | fork | opus | setup | -| 6 | `/bc:rules` | Extract rules from KB | session | sonnet | -- | -| 7 | `/bc:grepai` | Semantic code search | session | sonnet | setup | -| 8 | `/bc:teardown` | Remove PLG files | fork | haiku | setup | -| ~~10~~ | ~~`/bc:secrets-scan`~~ | **moved to brewtools** | -- | -- | -- | -| ~~11~~ | ~~`/bc:text-optimize`~~ | **moved to brewtools** | -- | -- | -- | -| ~~12~~ | ~~`/bc:text-human`~~ | **moved to brewtools** | -- | -- | -- | -| 13 | `/bc:skills` | SK management | session | sonnet | -- | -| 14 | `/bc:standards-review` | Standards compliance review | fork | opus | setup | -| 15 | `/bc:agents` | AG creation + improvement | session | opus | -- | -| 16 | `/bc:convention` | Extract conventions/patterns/architecture → rules + docs | session | opus | -- | -| 17 | `/bc:teams` | Create/manage specialized AG teams | session | opus | -- | -| 18 | `/bc:e2e` | E2E testing: BDD scenarios, autotests, review | session | opus | setup | +| 1 | `/bc:spec` | Create task SP | session | opus | -- | +| 2 | `/bc:grepai` | Semantic code search | session | sonnet | -- | +| 3 | `/bc:superreview` | Generate project-tailored deep-review skill | fork | opus | -- | +| 4 | `/bc:rules` | Extract rules from KB | session | sonnet | -- | +| ~~5~~ | ~~`/bc:secrets-scan`~~ | **moved to brewtools** | -- | -- | -- | +| ~~6~~ | ~~`/bc:text-optimize`~~ | **moved to brewtools** | -- | -- | -- | +| ~~7~~ | ~~`/bc:text-human`~~ | **moved to brewtools** | -- | -- | -- | +| 8 | `/bc:skills` | SK management | session | sonnet | -- | +| 9 | `/bc:agents` | AG creation + improvement | session | opus | -- | +| 10 | `/bc:convention` | Extract conventions/patterns/architecture → rules + docs | session | opus | -- | +| 11 | `/bc:teams` | Create/manage specialized AG teams | session | opus | -- | +| 12 | `/bc:e2e` | E2E testing: BDD scenarios, autotests, review | session | opus | -- | ## Execution Order ``` -setup --> spec --> review --> rules - | - grepai / teardown +grepai --> spec --> superreview --> rules ``` --- @@ -50,68 +45,7 @@ setup --> spec --> review --> rules --- -## 1. `/bc:setup` - -Analyzes project structure, tech stack, test frameworks, project AGs. Generates adapted templates + code review SK in `.claude/tasks/templates/`. - -| Param | Value | -|-------|-------| -| Args | `[universal-template-path]` (opt) | -| Context | fork | -| Model | opus | -| Deps | none | -| Tools | Read, Write, Glob, Grep, Bash | - -### Created Files - -| Path | Purpose | -|------|---------| -| `.claude/tasks/templates/SPEC.md.template` | SP template | -| `.claude/tasks/cfg/brewcode.config.json` | PLG cfg | -| `.claude/skills/brewcode-review/SKILL.md` | Code review SK | -| `.claude/skills/brewcode-review/references/` | Prompt + report templates | - -### Bash Scripts - -| Cmd | Phase | Purpose | -|-----|-------|---------| -| `setup.sh scan` | 1 | Scan project structure | -| `setup.sh structure` | 3 | Create dirs | -| `setup.sh sync` | 3 | Sync templates from PLG | -| `setup.sh review` | 3.5 | Copy review SK template | -| `setup.sh config` | 3.6 | Copy cfg | -| `setup.sh validate` | 4 | Validate artifacts | -| `setup.sh all` | all | Run all phases | - -### Workflow - -1. P1: Scan project: language, framework, tests, DB, AGs -2. P2: Consolidate findings, plan adaptation -3. P3: Create structure, sync templates -4. P3.5: Copy + adapt review SK to project stack -5. P3.6: Copy cfg with defaults -6. P4: Validate all artifacts - -### Tech Detection - -| Tech | Indicators | -|------|------------| -| Java/Spring | `pom.xml`, `build.gradle`, `src/main/java`, `@SpringBootApplication` | -| Node.js | `package.json`, `node_modules`, `express`, `nest` | -| Python | `requirements.txt`, `Pipfile`, `pytest`, `unittest` | -| Go | `go.mod`, `*_test.go` | -| Rust | `Cargo.toml` | - -Re-run when: adding AG in `.claude/agents/`, updating `CLAUDE.md`, changing test framework. - -``` -/bc:setup -/bc:setup ~/.claude/templates/SPEC.md.template -``` - ---- - -## 2. `/bc:spec` +## 1. `/bc:spec` Creates SPEC.md via parallel codebase research + interactive user clarification. Includes QR. @@ -120,7 +54,7 @@ Creates SPEC.md via parallel codebase research + interactive user clarification. | Args | Text desc or path to requirements file | | Context | session | | Model | opus | -| Deps | `/bc:setup` (SPEC.md.template must exist) | +| Deps | none | | Tools | Read, Write, Glob, Grep, Bash, Task, AskUserQuestion | ### Created Files @@ -170,81 +104,7 @@ Naming: `YYYYMMDD_HHMMSS` + lowercase slug, e.g. `20260208_143052_auth_feature` --- -## 5. `/bc:review` - -Code review w/ QR consensus. Multiple AGs review in parallel, findings confirmed by quorum, verified by DoubleCheck. Optional Critic phase. - -> SK !=shipped in PLG directly — generated by `/bc:setup` as project SK in `.claude/skills/brewcode-review/SKILL.md`, adapted to project stack. - -| Param | Value | -|-------|-------| -| Args | ` [-q\|--quorum [G-]N-M] [-c\|--critic]` | -| Context | fork | -| Model | opus | -| Deps | `/bc:setup` | -| Tools | Read, Glob, Grep, Task, Bash, Write | - -### Created Files - -| Path | Purpose | -|------|---------| -| `.claude/tasks/reviews/{TS}_{NAME}_report.md` | Review report | - -### Agents - -| AG | Phase | Purpose | -|----|-------|---------| -| Explore | 1 | 5-10 AGs scan codebase | -| reviewer / project | 3 | N AGs per group, parallel review | -| reviewer (opus) | 5 | DoubleCheck — verify confirmed findings | -| reviewer (opus) | 5.5 | Critic — find missed issues (opt, `-c`) | -| reviewer (opus) | 5.75 | DoubleCheck Critic (opt) | - -### Quorum Params - -| Format | Meaning | Example | -|--------|---------|---------| -| `N-M` | N AGs, threshold M | `-q 3-2` (3 AGs, quorum 2) | -| `G-N-M` | G groups, N AGs, threshold M | `-q 4-3-2` (4 groups of 3) | -| Default | 3 AGs, quorum 2 | `-q 3-2` | - -### Review Groups - -| Group | Focus | Files | -|-------|-------|-------| -| main-code | Logic, architecture, security | `src/main/**` | -| tests | Coverage, asserts, quality | `src/test/**` | -| db-layer | Queries, transactions | `**/repositories/**` | - -### Phases - -1. P1: 5-10 Explore AGs scan code in parallel -2. P2: Determine active groups by detected files -3. P3: N AGs per group, each w/ tech-specific checks -4. P4: Cluster findings, confirm by quorum -5. P5: 1 reviewer (opus) verifies all confirmed findings -6. P5.5: Critic (opt, `-c`) — devil's advocate finds missed issues -7. P5.75: DoubleCheck Critic (opt) — verify Critic findings -8. P6: Report w/ P0-P3 priorities - -### Finding Priorities - -| Priority | Source | Description | -|----------|--------|-------------| -| P0 | Critic + DoubleCheck | Verified Critic findings (only w/ `-c`) | -| P1 | Quorum + DoubleCheck | Confirmed + verified | -| P2 | Quorum only | Confirmed, failed DoubleCheck | -| P3 | Exceptions | Blocker/critical w/o quorum | - -``` -/bc:review "Check null-safety in service layer" -/bc:review -q 5-3 -c "Full review of authorization module" -/bc:review requirements/review-checklist.md --quorum 4-3-2 -``` - ---- - -## 6. `/bc:rules` +## 2. `/bc:rules` Extracts anti-patterns + best practices from KB or session ctx → updates `.claude/rules/avoid.md` + `.claude/rules/best-practice.md`. @@ -300,7 +160,7 @@ Rules optimization: dedup by semantic similarity, merge related, prioritize by i --- -## 7. `/bc:grepai` +## 3. `/bc:grepai` Setup + mgmt of semantic code search (grepai: Ollama + bge-m3). Modes: setup, status, start, stop, reindex, optimize, upgrade. @@ -309,7 +169,7 @@ Setup + mgmt of semantic code search (grepai: Ollama + bge-m3). Modes: setup, st | Args | `[setup\|status\|start\|stop\|reindex\|optimize\|upgrade]` | | Context | session | | Model | sonnet | -| Deps | `/bc:setup` (brew, jq via Phase 0) | +| Deps | none | | Tools | Read, Write, Edit, Bash, Task | ### Created Files (setup) @@ -374,48 +234,7 @@ Setup + mgmt of semantic code search (grepai: Ollama + bge-m3). Modes: setup, st --- -## 8. `/bc:teardown` - -Removes all files created by `/bc:setup`. Preserves TK dirs + user rules. - -| Param | Value | -|-------|-------| -| Args | `[--dry-run]` | -| Context | fork | -| Model | haiku | -| Deps | `/bc:setup` | -| Tools | Bash, Read | - -| Script | Purpose | -|--------|---------| -| `teardown.sh` | Remove files (supports `--dry-run`) | - -### Removed - -| Path | Status | -|------|--------| -| `.claude/tasks/templates/` | removed | -| `.claude/tasks/cfg/` | removed | -| `.claude/logs/` | removed | -| `.claude/plans/` | removed | -| `.grepai/` | removed | -| `.claude/skills/brewcode-review/` | removed | - -### Preserved - -| Path | Reason | -|------|--------| -| `.claude/tasks/*_task/` | TK data | -| `.claude/rules/` | User rules | - -``` -/bc:teardown --dry-run -/bc:teardown -``` - ---- - -## 9. `/bc:agents` +## 4. `/bc:agents` Interactive orchestrator for creating + improving Claude Code AGs. Collects requirements via AskUserQuestion, delegates to `agent-creator`, applies `brewtools:text-optimize` (if installed). Optionally updates CLAUDE.md agents table. @@ -459,7 +278,7 @@ Interactive orchestrator for creating + improving Claude Code AGs. Collects requ --- -## 10. `/bc:convention` +## 5. `/bc:convention` Analyzes project to extract etalon classes, patterns, architecture by layer. Generates convention docs in `.claude/convention/` + organizes rules in `.claude/rules/`. @@ -508,7 +327,7 @@ Analyzes project to extract etalon classes, patterns, architecture by layer. Gen --- -## 11. `/bc:teams` +## 6. `/bc:teams` Creates + manages dynamic teams of domain-specific AGs w/ tracking framework. Analyzes project, proposes team (5-20 AGs), creates w/ self-selection protocol + performance tracking. @@ -546,7 +365,7 @@ Creates + manages dynamic teams of domain-specific AGs w/ tracking framework. An --- -## 12. `/bc:e2e` +## 7. `/bc:e2e` Full-cycle E2E testing: setup testing AGs, create BDD scenarios, write autotests, QR. Stack-agnostic, layered test architecture. @@ -555,7 +374,7 @@ Full-cycle E2E testing: setup testing AGs, create BDD scenarios, write autotests | Args | `[setup\|create\|update\|review\|rules\|status] [prompt]` | | Context | session | | Model | opus | -| Deps | `/bc:setup` (for non-setup modes: e2e AGs must exist) | +| Deps | `/bc:e2e setup` (for non-setup modes: e2e AGs must exist) | | Tools | Read, Write, Edit, Glob, Grep, Bash, Task, AskUserQuestion, Skill, WebSearch, WebFetch | ### Modes @@ -586,12 +405,10 @@ Hooks-only, no external runtime. Claude Code hooks provide ctx mgmt. | Hook | Event | Purpose | |------|-------|---------| -| `session-start.mjs` | SessionStart | Session init | -| `grepai-session.mjs` | SessionStart | Auto-start grepai watch | -| `pre-task.mjs` | PreToolUse:Task | grepai reminder + protocol into AG prompts | -| `grepai-reminder.mjs` | PreToolUse:Bash | Reminder to use grepai | -| `forced-eval.mjs` | UserPromptSubmit | Skill activation reminder | -| `permission-guard.sh` | PermissionRequest | Manager-mode edit guard | +| `session-start.mjs` | SessionStart | Session init: version-check, plan-symlink, permission tag | +| `forced-eval.mjs` | UserPromptSubmit | Skill activation reminder ([SKILL?] injection) | + +> grepai hooks (`grepai-session.mjs`, `grepai-reminder.mjs`) self-install per-project via `/brewcode:grepai setup` — they are not part of the plugin's always-on hook set. ## KB Format diff --git a/brewcode/docs/file-tree.md b/brewcode/docs/file-tree.md index 3b9485a..c6dde53 100644 --- a/brewcode/docs/file-tree.md +++ b/brewcode/docs/file-tree.md @@ -17,15 +17,11 @@ brewcode/ # Plugin root directory │ └── plugin.json # Manifest (name, version 3.1.0, skills/ reference) │ ├── hooks/ # Node.js scripts for Claude Code events -│ ├── hooks.json # Binds 4 events (UserPromptSubmit, SessionStart, PreToolUse, PermissionRequest) +│ ├── hooks.json # Binds 2 events (UserPromptSubmit, SessionStart) │ ├── lib/ │ │ └── utils.mjs # readStdin, output, log, lock files, config, state, task parsing -│ ├── session-start.mjs # SessionStart: session log, creates LATEST.md symlink on source='clear' -│ ├── grepai-session.mjs # SessionStart: auto-starts grepai watch if .grepai/ exists, checks MCP server -│ ├── pre-task.mjs # PreToolUse(Task): injects grepai reminder + role constraints -│ ├── grepai-reminder.mjs # PreToolUse(Bash): reminds to use grepai_search -│ ├── forced-eval.mjs # UserPromptSubmit: skill activation reminder -│ └── permission-guard.sh # PermissionRequest: manager-mode edit guard +│ ├── session-start.mjs # SessionStart: version-check, plan-symlink, permission_mode tag +│ └── forced-eval.mjs # UserPromptSubmit: skill activation reminder (~9K additionalContext bound) │ ├── agents/ # Plugin agents (system prompts in Markdown) │ ├── bc-grepai-configurator.md # grepai configurator (opus): project analysis, config.yaml via 5 parallel investigations @@ -40,25 +36,11 @@ brewcode/ # Plugin root directory │ ├── reviewer.md # Reviewer (opus): code review, quality, security, performance │ └── tester.md # Tester (sonnet): SDET/QA - runs tests, analyzes failures │ -├── skills/ # Skills - plugin commands (13 total) -│ │ -│ ├── setup/ # /brewcode:setup - Plugin initialization -│ │ ├── SKILL.md # Project analysis, adapted template generation (opus, fork) -│ │ ├── scripts/ -│ │ │ ├── setup.sh # scan/structure/sync/review/config/validate/all -│ │ │ └── install.sh # state/check-updates/check-timeout/required/grepai/summary -│ │ └── templates/ -│ │ ├── SPEC.md.template # Goal, Scope, Requirements, Analysis, Context Files, Risks, Decisions -│ │ └── brewcode.config.json.template # Config: logging, agents, constraints, autoSync +├── skills/ # Skills - plugin commands (9 total) │ │ │ ├── spec/ # /brewcode:spec - Specification creation │ │ └── SKILL.md # 7 steps: investigation (5-10 parallel agents), dialog, review (opus, session) │ │ -│ ├── rules/ # /brewcode:rules - Extract rules from knowledge -│ │ ├── SKILL.md # KNOWLEDGE.jsonl → avoid.md + best-practice.md, dedup, 20 line limit (sonnet, session) -│ │ └── scripts/ -│ │ └── rules.sh # read/check/create/validate -│ │ │ ├── grepai/ # /brewcode:grepai - Semantic search management │ │ ├── SKILL.md # 7 modes: setup/status/start/stop/reindex/optimize/upgrade (sonnet, session) │ │ ├── config.yaml.example # Example grepai config: embedder, chunking, trace, ignore @@ -77,20 +59,43 @@ brewcode/ # Plugin root directory │ │ ├── verify.sh # Full functionality check │ │ └── create-rule.sh # Creates grepai-first.md in .claude/rules/ │ │ -│ ├── teardown/ # /brewcode:teardown - Plugin files cleanup -│ │ └── SKILL.md # Removes templates/, cfg/, skills/brewcode-review/; preserves tasks (haiku, fork) +│ ├── superreview/ # /brewcode:superreview - Generate project-tailored deep-review skill +│ │ ├── SKILL.md # Generator: emits .claude/skills/superreview/ into target project (opus, fork) +│ │ ├── references/ # Per-stack reviewer guidelines + SKILL.md.template +│ │ └── scripts/ +│ │ └── generate.sh # Scaffold the project-local review skill │ │ -│ ├── secrets-scan/ # [moved to brewtools] /brewcode:secrets-scan -│ │ └── SKILL.md +│ ├── convention/ # /brewcode:convention - Extract conventions/patterns/architecture +│ │ ├── SKILL.md +│ │ ├── references/ +│ │ └── scripts/ +│ │ └── convention.sh │ │ -│ ├── text-human/ # [moved to brewtools] /brewcode:text-human -│ │ └── SKILL.md +│ ├── rules/ # /brewcode:rules - Extract rules from knowledge +│ │ ├── SKILL.md # KNOWLEDGE.jsonl → avoid.md + best-practice.md, dedup, 20 line limit (sonnet, session) +│ │ └── scripts/ +│ │ └── rules.sh # read/check/create/validate │ │ -│ ├── text-optimize/ # [moved to brewtools] /brewcode:text-optimize -│ │ └── SKILL.md +│ ├── skills/ # /brewcode:skills - Skill management +│ │ ├── SKILL.md +│ │ └── scripts/ +│ │ ├── list-skills.sh +│ │ └── validate-skill.sh │ │ -│ └── agents/ # /brewcode:agents - Interactive agent creation/improvement -│ └── SKILL.md # Create/improve agents, delegates to agent-creator + brewtools:text-optimize (opus, session) +│ ├── agents/ # /brewcode:agents - Interactive agent creation/improvement +│ │ └── SKILL.md # Create/improve agents, delegates to agent-creator + brewtools:text-optimize (opus, session) +│ │ +│ ├── teams/ # /brewcode:teams - Dynamic agent team creation/management +│ │ ├── SKILL.md +│ │ └── scripts/ +│ │ ├── detect-mode.sh +│ │ ├── verify-team.sh +│ │ └── trace-ops.sh +│ │ +│ └── e2e/ # /brewcode:e2e - E2E testing orchestration +│ ├── SKILL.md +│ └── scripts/ +│ └── detect-mode.sh │ ├── templates/ │ │ @@ -99,12 +104,8 @@ brewcode/ # Plugin root directory │ │ ├── best-practice.md.template # Best practices: Practice/Context/Source table with YAML frontmatter │ │ └── grepai-first.md.template # grepai priority rule: call examples, tool selection table │ │ -│ └── skills/ -│ └── review/ -│ ├── SKILL.md.template # /brewcode:review template: quorum, groups, Critic mode, DoubleCheck (opus, fork) -│ └── references/ -│ ├── agent-prompt.md # Review agent prompt: group, focus, files, output format -│ └── report-template.md # Review report: P0-P3 priorities, quorum, statistics +│ └── auto-sync/ +│ └── INDEX.jsonl.template # auto-sync index seed │ ├── docs/ │ ├── file-tree.md # This file @@ -135,7 +136,7 @@ Files created by the plugin in the user's project: │ │ ├── brewcode.config.json # User settings: logging, agents, constraints, autoSync │ │ └── brewcode.state.json # Inter-session state: current task, last compaction │ │ - │ ├── templates/ # Adapted templates (from /brewcode:setup) + │ ├── templates/ # Project-local templates (e.g. SPEC.md.template) │ │ ├── SPEC.md.template │ │ ├── SPEC-creation.md │ │ └── ... # Remaining plugin templates @@ -168,24 +169,21 @@ Files created by the plugin in the user's project: | Category | Count | Items | |----------|-------|-------| | Plugin configuration | 2 | plugin.json, hooks.json | -| Hooks (lifecycle) | 6 | forced-eval, grepai-reminder, grepai-session, permission-guard, pre-task, session-start | +| Hooks | 2 | forced-eval, session-start | | Agents | 10 | bc-grepai-configurator, bc-rules-organizer, agent-creator, skill-creator, bash-expert, hook-creator, architect, developer, reviewer, tester | -| Skills (SKILL.md) | 11 | setup, spec, rules, convention, grepai, teardown, standards-review, skills, agents, teams, e2e | -| Bash scripts | 16 | setup(2), rules(1), grepai(13) | -| Templates | 7 | SPEC, config, rules(3), review(3) | +| Skills (SKILL.md) | 9 | spec, grepai, superreview, convention, rules, skills, agents, teams, e2e | +| Bash scripts | 22 | grepai(13), teams(3), skills(2), superreview(1), convention(1), rules(1), e2e(1) | +| Templates | 4 | rules(3), auto-sync(1) | | Documentation | 7 | README, INSTALL, RELEASE-NOTES, grepai.md, file-tree.md, commands.md, flow.md, hooks.md | | npm | 1 | package.json | -| **Total** | **71** | | +| **Total** | **70** | | ## Hook Events | Event | Hooks | Timeout | Purpose | |-------|-------|---------|---------| -| UserPromptSubmit | forced-eval.mjs | 1s | Skill activation reminder | -| SessionStart | session-start.mjs, grepai-session.mjs | 3s, 5s | Initialization, grepai auto-start | -| PreToolUse(Task) | pre-task.mjs | 5s | grepai and constraints injection | -| PreToolUse(Bash) | grepai-reminder.mjs | 1s | grepai reminder | -| PermissionRequest | permission-guard.sh | 1s | Manager-mode edit guard | +| UserPromptSubmit | forced-eval.mjs | 1s | Skill activation reminder (~9K additionalContext bound) | +| SessionStart | session-start.mjs | 3s | Version-check, plan-symlink, permission_mode tag | ## Agent Models diff --git a/brewcode/docs/grepai.md b/brewcode/docs/grepai.md index dc9de88..9cd7599 100644 --- a/brewcode/docs/grepai.md +++ b/brewcode/docs/grepai.md @@ -11,9 +11,8 @@ ``` Claude Code CLI | - +-- SS hook: grepai-session.mjs (auto-start + health check + status) - +-- PTU:Task hook: pre-task.mjs (inject reminder + modify prompt) - +-- PTU:Glob/Grep: grepai-reminder.mjs (remind about GA option) + +-- [project-installed] SS hook: grepai-session.mjs (health check + status) + +-- [project-installed] PTU:Bash: grepai-reminder.mjs (remind to use grepai_search) | v Unified Reminder: "grepai: USE grepai_search FIRST for code exploration" @@ -34,6 +33,9 @@ Unified Reminder: "grepai: USE grepai_search FIRST for code exploration" │ ├── symbols.gob # Call graph data │ └── logs/grepai-watch.log # Daemon log ├── .claude/ +│ ├── grepai/hooks/ # Hook assets installed by /brewcode:grepai setup +│ │ ├── grepai-session.mjs # Copied from brewcode/skills/grepai/assets/ +│ │ └── grepai-reminder.mjs # Copied from brewcode/skills/grepai/assets/ │ ├── rules/grepai-first.md # Attention-forcing rule │ └── logs/brewcode.log # Hook diagnostic log └── CLAUDE.md # Contains "CRITICAL: Use grepai_search FIRST" @@ -42,51 +44,47 @@ brewcode/ ├── skills/grepai/ │ ├── SKILL.md │ ├── config.yaml.example +│ ├── assets/ +│ │ ├── grepai-session.mjs # SS hook asset (installed by setup) +│ │ ├── grepai-reminder.mjs # PTU:Bash hook asset (installed by setup) +│ │ └── INSTALL.md # Install instructions │ └── scripts/ # 11 bash scripts (detect-mode, infra-check, mcp-check, init-index, │ # start, stop, reindex, optimize, upgrade, status, verify, create-rule) ├── agents/bc-grepai-configurator.md -├── templates/rules/grepai-first.md.template -└── hooks/ - ├── grepai-session.mjs # SS hook - ├── grepai-reminder.mjs # PTU:Glob|Grep hook - └── pre-task.mjs # PTU:Task hook +└── templates/rules/grepai-first.md.template ``` --- # ATTENTION SYSTEM -> 7 INJs ensuring GA priority over Glob/Grep. +> 5 INJs ensuring GA priority. INJ #1 and #2 active only after /brewcode:grepai setup installs hooks. **Unified reminder:** `grepai: USE grepai_search FIRST for code exploration` - Prefix `grepai:` for categorization - Uppercase `USE...FIRST` for imperative force - Exact tool name: `grepai_search` -## 7 INJ Points +## 5 INJ Points | # | Point | Hook/File | Event | Scope | Strength | |---|-------|-----------|-------|-------|----------| -| 1 | SS | grepai-session.mjs:146 | SS | Session ctx | MUST | -| 2 | PTU:Task | pre-task.mjs:20,56 | PTU | ALL agents | MUST (prepend) | -| 3 | PTU:Glob/Grep | grepai-reminder.mjs:24 | PTU | Glob/Grep calls | MUST | -| 4 | Rule file | grepai-first.md.template:7 | Always | All files (`**/*`) | CRITICAL | -| 5 | CLAUDE.md | create-rule.sh:18 | Persistent | Project cfg | CRITICAL | -| 6 | Root CLAUDE.md | CLAUDE.md:101 | Always | Global | CRITICAL | -| 7 | Agent prompts | pre-task.mjs (prepend) | Every Task | Line 1 of prompt | MUST | +| 1 | SS | grepai-session.mjs (project-installed) | SS | Session ctx | MUST | +| 2 | PTU:Bash | grepai-reminder.mjs (project-installed) | PTU | Bash calls | MUST | +| 3 | Rule file | grepai-first.md.template:7 | Always | All files (`**/*`) | CRITICAL | +| 4 | CLAUDE.md | create-rule.sh:18 | Persistent | Project cfg | CRITICAL | +| 5 | Root CLAUDE.md | CLAUDE.md:101 | Always | Global | CRITICAL | ## INJ Flow ``` -SS → INJ #1 (grepai-session.mjs): +SS → INJ #1 (grepai-session.mjs, project-installed): Check: .grepai/ exists? + OL running? + index.gob exists? - YES → auto-start watch if needed - → AC: "grepai: USE grepai_search FIRST..." + YES → AC: "grepai: USE grepai_search FIRST..." → systemMessage: "grepai: ready | index: 150MB" -User triggers Task/Glob/Grep → - Task → INJ #2 (pre-task.mjs): prepend reminder to ALL agent prompts - Glob/Grep → INJ #3 (grepai-reminder.mjs): AC reminder +User triggers Bash → + Bash → INJ #2 (grepai-reminder.mjs, project-installed): AC reminder Persistent (always active): INJ #4: .claude/rules/grepai-first.md (paths: **/*) @@ -96,47 +94,22 @@ Persistent (always active): ## Detailed INJ Mechanisms -### INJ #1: grepai-session.mjs (SS) +### INJ #1: grepai-session.mjs (SS, project-installed) ```javascript -// hooks/grepai-session.mjs:143-148 +// skills/grepai/assets/grepai-session.mjs (project-installed by /brewcode:grepai setup) if (status.length === 0) { // All systems healthy hookSpecificOutput.additionalContext = 'grepai: USE grepai_search FIRST for code exploration'; } ``` -Trigger conditions: `.grepai/` exists + OL running (`curl localhost:11434/api/tags`) + `index.gob` exists + `grepai watch` active (or auto-started) +Trigger conditions: `.grepai/` exists + OL running (`curl localhost:11434/api/tags`) + `index.gob` exists + `grepai watch` active. Requires prior setup install. -### INJ #2: pre-task.mjs (PTU:Task) +### INJ #2: grepai-reminder.mjs (PTU:Bash, project-installed) ```javascript -// hooks/pre-task.mjs:20 -const GREPAI_REMINDER = 'grepai: USE grepai_search FIRST for code exploration'; - -// hooks/pre-task.mjs:48-59 -const hasGrepai = existsSync(join(cwd, '.grepai')); -if (hasGrepai) { - updatedPrompt = `${GREPAI_REMINDER}\n\n${updatedPrompt}`; -} -``` - -Scope: ALL agents (Explore, Plan, Bash, developer, tester, reviewer, custom) -Mechanism: prepend — reminder = FIRST line of agent prompt - -Output structure: -```javascript -hookSpecificOutput: { - hookEventName: 'PreToolUse', - permissionDecision: 'allow', - updatedInput: { ...tool_input, prompt: updatedPrompt } -} -``` - -### INJ #3: grepai-reminder.mjs (PTU:Glob|Grep) - -```javascript -// hooks/grepai-reminder.mjs:24-31 +// skills/grepai/assets/grepai-reminder.mjs (project-installed by /brewcode:grepai setup) if (existsSync(grepaiDir)) { output({ hookSpecificOutput: { hookEventName: 'PreToolUse', @@ -145,9 +118,9 @@ if (existsSync(grepaiDir)) { } ``` -Trigger: every Glob or Grep call. Reminds about semantic alternative. +Trigger: every Bash call (PTU:Bash, when installed by setup). Reminds about semantic alternative. -### INJ #4: grepai-first.md.template (Rule) +### INJ #3: grepai-first.md.template (Rule) ```markdown --- @@ -171,24 +144,13 @@ description: grepai-first - semantic search FIRST for code exploration **Decision:** "Need exact text/pattern?" → YES: Grep/Glob, NO: grepai ``` -### INJ #5 & #6: CLAUDE.md (project + root) +### INJ #4 & #5: CLAUDE.md (project + root) ```markdown ## Code Search > **CRITICAL:** Use `grepai_search` FIRST for code exploration. ``` -### INJ #7: Prompt Prepending (Position-Based) - -``` -Agent prompt: - Line 1: grepai: USE grepai_search FIRST for code exploration ← FIRST - Line 2: (empty) - Line 3: [original prompt] -``` - -LLMs process sequentially; first lines have greatest weight (primacy effect) — reminder seen BEFORE any instructions. - ## Attention Strength Escalation | Version | Message | Strength | @@ -196,12 +158,21 @@ LLMs process sequentially; first lines have greatest weight (primacy effect) — | v2.0.57 | `consider grepai_search FIRST` | Advisory | | v2.0.58 | `USE grepai_search FIRST` | Imperative | -## No Opt-Out Design +## Install State Design ``` .grepai/ exists? - YES → all 3 hooks inject (no config to disable; removal = delete .grepai/) - NO → graceful skip, no injection + NO → graceful skip, no injection from any hook + + YES + hooks project-installed (via /brewcode:grepai setup)? + grepai-session.mjs → injects AC at SS + grepai-reminder.mjs → injects AC at PTU:Bash + + YES + hooks NOT installed? + run /brewcode:grepai setup to self-install: + copies assets to .claude/grepai/hooks/ + merges SessionStart + PTU:Bash entries into .claude/settings.json (jq + python3 fallback) + idempotent — safe to re-run ``` --- @@ -218,7 +189,7 @@ LLMs process sequentially; first lines have greatest weight (primacy effect) — | 1a - MCP Server Instructions | `grepai` server `instructions` field | "Use semantic search for CE..." | | 2 - Tools array | MCP server `tools` | `mcp__grepai__grepai_search` schema with full param descriptions | | 3 - User messages (dynamic) | CLAUDE.md + rules + hook AC | grepai-first.md rule injected each turn | -| 4 - Hook injections | grepai-session.mjs, pre-task.mjs | AC + systemMessage at PTU/SS | +| 4 - Hook injections | grepai-session.mjs (project-installed), grepai-reminder.mjs (project-installed) | AC at SS + PTU:Bash | ## Attention Flow: Rule → MCP Tool Descriptions @@ -260,7 +231,6 @@ Use semantic search for code exploration... |-------|--------|-----------| | System prompt (static) | MCP server `instructions` + `tools` | GA instructions + tool defs | | User messages (dynamic) | CLAUDE.md + grepai-first.md + hook AC | Per-turn rule + hook context | -| Subagent prompts | pre-task.mjs prepend | "grepai: USE grepai_search FIRST..." | --- diff --git a/brewcode/hooks/forced-eval.mjs b/brewcode/hooks/forced-eval.mjs index 7264b7c..3b21a3c 100644 --- a/brewcode/hooks/forced-eval.mjs +++ b/brewcode/hooks/forced-eval.mjs @@ -19,12 +19,12 @@ * { * "hookSpecificOutput": { * "hookEventName": "UserPromptSubmit", - * "additionalContext": "skill-check + light hint (full Manager mode via ++m)" + * "additionalContext": "skill-check + delegation hint" * } * } */ -import { readStdin, output, getActiveMode } from './lib/utils.mjs'; +import { readStdin, output } from './lib/utils.mjs'; // Cap text channels under the 2.1.174 10K disk-spill threshold (headroom 9000). const TEXT_CHANNEL_CAP = 9000; @@ -34,18 +34,10 @@ function capText(s, max = TEXT_CHANNEL_CAP) { // --- Skill evaluation reminder --- -// SKILL_CHECK = always-on payload (every prompt). DEFAULT_MODE = light hint when no -// active mode is set; full Manager framing is opt-in on demand via codeword ++m (brewtools:manager). -const SKILL_CHECK = '[SKILL?] Check available skills. If one matches, use Skill tool before responding.'; -const DEFAULT_MODE = '[HINT] Prefer delegating heavy implementation work to sub-agents (Task tool) when it helps. Full Manager mode: type ++m.'; - -function getModeReminder(cwd, sessionId) { - const activeMode = getActiveMode(cwd, sessionId); - if (activeMode) { - return `${SKILL_CHECK}\n[MODE: ${activeMode.name}] ${activeMode.instructions}`; - } - return `${SKILL_CHECK}\n${DEFAULT_MODE}`; -} +// SKILL_CHECK = always-on payload (every prompt). DEFAULT_MODE = light delegation hint. +const SKILL_CHECK = '[SKILL?] If a skill matches this request, use Skill tool first.'; +const DEFAULT_MODE = '[HINT] Delegate heavy implementation to sub-agents via Task tool.'; +const REMINDER_TEXT = `${SKILL_CHECK}\n${DEFAULT_MODE}`; // --- Main --- @@ -86,19 +78,12 @@ async function main() { return; } - // Effort-level prefix (CC 2.1.115+). Folded into injected context. - // NOTE: effort.level is NOT in HOOKS-REFERENCE.md (2.1.195). Presence-guarded existing read; do not expand to other hooks. - const effortLevel = input.effort?.level; - const effortPrefix = effortLevel === 'low' ? '[EFFORT: low | MODE: terse-light]\n' : ''; - // Inject skill-check reminder via additionalContext (updatedInput is ignored // on UserPromptSubmit in CC 2.1.x). - const reminderText = `${effortPrefix}${getModeReminder(cwd, session_id)}`; - output({ hookSpecificOutput: { hookEventName: 'UserPromptSubmit', - additionalContext: capText(reminderText) + additionalContext: capText(REMINDER_TEXT) } }); diff --git a/brewcode/hooks/hooks.json b/brewcode/hooks/hooks.json index 434e5e9..7f446d1 100644 --- a/brewcode/hooks/hooks.json +++ b/brewcode/hooks/hooks.json @@ -22,53 +22,6 @@ "timeout": 3000 } ] - }, - { - "hooks": [ - { - "type": "command", - "command": "node", - "args": ["${CLAUDE_PLUGIN_ROOT}/hooks/grepai-session.mjs"], - "timeout": 5000 - } - ] - } - ], - "PreToolUse": [ - { - "matcher": "Task|Agent", - "hooks": [ - { - "type": "command", - "command": "node", - "args": ["${CLAUDE_PLUGIN_ROOT}/hooks/pre-task.mjs"], - "timeout": 5000 - } - ] - }, - { - "matcher": "Bash", - "hooks": [ - { - "type": "command", - "command": "node", - "args": ["${CLAUDE_PLUGIN_ROOT}/hooks/grepai-reminder.mjs"], - "timeout": 1000 - } - ] - } - ], - "PermissionRequest": [ - { - "matcher": "Edit|Write|MultiEdit|Bash", - "hooks": [ - { - "type": "command", - "command": "bash", - "args": ["${CLAUDE_PLUGIN_ROOT}/hooks/permission-guard.sh"], - "timeout": 1000 - } - ] } ] } diff --git a/brewcode/hooks/lib/utils.mjs b/brewcode/hooks/lib/utils.mjs index 83460bd..8ec61fa 100644 --- a/brewcode/hooks/lib/utils.mjs +++ b/brewcode/hooks/lib/utils.mjs @@ -237,71 +237,3 @@ export function saveState(cwd, state) { log('warn', '[state]', `Failed to save state: ${e.message}`, cwd); } } - -/** - * Get active mode and its instructions (3-scope resolution) - * @param {string} cwd - Current working directory - * @param {string|null} sessionId - Session ID for session-scope resolution - * @returns {{ name: string, instructions: string, scope: string } | null} - */ -export function getActiveMode(cwd, sessionId = null) { - let modeName = null; - let scope = null; - - // 1. Try CLAUDE_PLUGIN_DATA/modes.json with 3-scope resolution - const pluginData = process.env.CLAUDE_PLUGIN_DATA || ''; - if (pluginData) { - const modesPath = join(pluginData, 'modes.json'); - try { - if (existsSync(modesPath)) { - const modes = JSON.parse(readFileSync(modesPath, 'utf8')); - - if (sessionId && modes.sessions?.[sessionId]?.mode) { - modeName = modes.sessions[sessionId].mode; - scope = 'session'; - } else if (cwd && modes.projects?.[cwd]?.mode) { - modeName = modes.projects[cwd].mode; - scope = 'project'; - } else if (modes.global?.mode) { - modeName = modes.global.mode; - scope = 'global'; - } - } - } catch (e) { - log('warn', '[mode]', `Failed to read modes.json: ${e.message}`, cwd); - } - } - - // 2. Fallback to old state file - if (!modeName) { - const state = getState(cwd); - if (state.mode) { - modeName = state.mode; - scope = 'legacy'; - } - } - - if (!modeName) return null; - - // 3. Load instructions: user modes (PLUGIN_DATA) then built-in (PLUGIN_ROOT) - const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT || ''; - const candidates = []; - if (pluginData) candidates.push(join(pluginData, 'modes', `${modeName}.md`)); - if (pluginRoot) candidates.push(join(pluginRoot, 'modes', `${modeName}.md`)); - - for (const modePath of candidates) { - try { - if (existsSync(modePath)) { - const instructions = readFileSync(modePath, 'utf8').trim(); - if (instructions) { - return { name: modeName, instructions, scope }; - } - } - } catch (e) { - log('warn', '[mode]', `Failed to read mode "${modeName}" from ${modePath}: ${e.message}`, cwd); - } - } - - log('warn', '[mode]', `Mode "${modeName}" active (${scope}) but no instructions file found`, cwd); - return null; -} diff --git a/brewcode/hooks/permission-guard.sh b/brewcode/hooks/permission-guard.sh deleted file mode 100644 index f42367d..0000000 --- a/brewcode/hooks/permission-guard.sh +++ /dev/null @@ -1,146 +0,0 @@ -#!/bin/bash -set -euo pipefail - -command -v jq >/dev/null 2>&1 || { echo '{"decision":"block","reason":"jq is required for permission checks but not installed"}'; exit 0; } - -INPUT=$(cat) -TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty') -FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty') - -ALLOW='{"hookSpecificOutput":{"hookEventName":"PermissionRequest","decision":{"behavior":"allow"}}}' - -# --- Helper: check if a single path is within allowed directories --- -is_allowed_path() { - local p="$1" - # Skip global ~/.claude/ - [[ "$p" == "$HOME/.claude/"* || "$p" == "$HOME/.claude" ]] && return 1 - # System temp dirs - [[ "$p" == /tmp/* || "$p" == /tmp || "$p" == /private/tmp/* || "$p" == /private/tmp ]] && return 0 - # Allowed .claude/ subdirectories (both relative .claude/ and absolute */.claude/) - case "$p" in - .claude/tasks/*|.claude/tasks|*/.claude/tasks/*|*/.claude/tasks) return 0 ;; - .claude/tmp/*|.claude/tmp|*/.claude/tmp/*|*/.claude/tmp) return 0 ;; - .claude/reports/*|.claude/reports|*/.claude/reports/*|*/.claude/reports) return 0 ;; - .claude/rules/*|.claude/rules|*/.claude/rules/*|*/.claude/rules) return 0 ;; - .claude/skills/*|.claude/skills|*/.claude/skills/*|*/.claude/skills) return 0 ;; - .claude/scripts/*|.claude/scripts|*/.claude/scripts/*|*/.claude/scripts) return 0 ;; - .claude/agents/*|.claude/agents|*/.claude/agents/*|*/.claude/agents) return 0 ;; - .claude/auto-sync/*|.claude/auto-sync|*/.claude/auto-sync/*|*/.claude/auto-sync) return 0 ;; - .claude/brewdoc/*|.claude/brewdoc|*/.claude/brewdoc/*|*/.claude/brewdoc) return 0 ;; - .claude/hooks/*|.claude/hooks|*/.claude/hooks/*|*/.claude/hooks) return 0 ;; - .claude/private/*|.claude/private|*/.claude/private/*|*/.claude/private) return 0 ;; - .claude/convention/*|.claude/convention|*/.claude/convention/*|*/.claude/convention) return 0 ;; - .claude/plans/*|.claude/plans|*/.claude/plans/*|*/.claude/plans) return 0 ;; - .claude/teams/*|.claude/teams|*/.claude/teams/*|*/.claude/teams) return 0 ;; - .claude/memory/*|.claude/memory|*/.claude/memory/*|*/.claude/memory) return 0 ;; - .claude/settings.json|.claude/settings.local.json|*/.claude/settings.json|*/.claude/settings.local.json) return 0 ;; - .claude/TASK.md|.claude/CLAUDE.md|*/.claude/TASK.md|*/.claude/CLAUDE.md) return 0 ;; - *) return 1 ;; - esac -} - -# --- Bash tool handling --- -if [[ "$TOOL_NAME" == "Bash" ]]; then - CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty') - [[ -z "$CMD" ]] && { echo '{}'; exit 0; } - - # Block network commands unconditionally - if echo "$CMD" | grep -qE '\b(curl|wget|ssh|scp|rsync|nc|ncat|socat|ftp|sftp)\b'; then - echo '{}' - exit 0 - fi - - # Block dangerous redirections / evals - if echo "$CMD" | grep -qE '(>\s*/dev/|>\s*/etc/|\beval\b|\bexec\b|\bsource\b|\b\.\s+/)'; then - echo '{}' - exit 0 - fi - - # For rm: only allow within .claude/tasks/ or .claude/tmp/ or /tmp/ - if echo "$CMD" | grep -qE '\brm\b'; then - RM_PATHS=$(echo "$CMD" | grep -oE '(\.claude|/tmp|/private/tmp)[^ ]*' || true) - [[ -z "$RM_PATHS" ]] && { echo '{}'; exit 0; } - while IFS= read -r rp; do - case "$rp" in - .claude/tasks/*|*/.claude/tasks/*) ;; - .claude/tmp/*|*/.claude/tmp/*) ;; - /tmp/*|/private/tmp/*) ;; - *) echo '{}'; exit 0 ;; - esac - done <<< "$RM_PATHS" - echo "$ALLOW" - exit 0 - fi - - # Extract all path-like tokens that reference .claude/ or temp dirs - # Match: .claude/..., /abs/path/.claude/..., /tmp/..., /private/tmp/... - ALL_PATHS=$(echo "$CMD" | grep -oE '(/[^ "'"'"'|;&>]*/?\.claude/[^ "'"'"'|;&>]*|\.claude/[^ "'"'"'|;&>]*|/tmp/[^ "'"'"'|;&>]*|/private/tmp/[^ "'"'"'|;&>]*)' || true) - - # If no .claude/ or temp paths found, not our concern -- don't auto-allow - [[ -z "$ALL_PATHS" ]] && { echo '{}'; exit 0; } - - # Verify ALL extracted paths are within allowed directories - while IFS= read -r path; do - [[ -z "$path" ]] && continue - if ! is_allowed_path "$path"; then - echo '{}' - exit 0 - fi - done <<< "$ALL_PATHS" - - echo "$ALLOW" - exit 0 -fi - -# --- Edit/Write/MultiEdit tool handling (existing logic) --- -if [ -z "$FILE_PATH" ]; then - echo '{}' - exit 0 -fi - -# Skip global ~/.claude/ — only auto-allow project .claude/ -if [[ "$FILE_PATH" == "$HOME/.claude/"* ]]; then - echo '{}' - exit 0 -fi - -case "$FILE_PATH" in - */.claude/tasks/*|*/.claude/tasks) - echo "$ALLOW" ;; - */.claude/tmp/*|*/.claude/tmp) - echo "$ALLOW" ;; - */.claude/reports/*|*/.claude/reports) - echo "$ALLOW" ;; - */.claude/rules/*|*/.claude/rules) - echo "$ALLOW" ;; - */.claude/skills/*|*/.claude/skills) - echo "$ALLOW" ;; - */.claude/scripts/*|*/.claude/scripts) - echo "$ALLOW" ;; - */.claude/agents/*|*/.claude/agents) - echo "$ALLOW" ;; - */.claude/auto-sync/*|*/.claude/auto-sync) - echo "$ALLOW" ;; - */.claude/brewdoc/*|*/.claude/brewdoc) - echo "$ALLOW" ;; - */.claude/hooks/*|*/.claude/hooks) - echo "$ALLOW" ;; - */.claude/private/*|*/.claude/private) - echo "$ALLOW" ;; - */.claude/convention/*|*/.claude/convention) - echo "$ALLOW" ;; - */.claude/plans/*|*/.claude/plans) - echo "$ALLOW" ;; - */.claude/teams/*|*/.claude/teams) - echo "$ALLOW" ;; - */.claude/memory/*|*/.claude/memory) - echo "$ALLOW" ;; - */.claude/settings.json|*/.claude/settings.local.json) - echo "$ALLOW" ;; - */.claude/TASK.md|*/.claude/CLAUDE.md) - echo "$ALLOW" ;; - /tmp/*|/private/tmp/*) - echo "$ALLOW" ;; - *) - echo '{}' ;; -esac diff --git a/brewcode/hooks/pre-task.mjs b/brewcode/hooks/pre-task.mjs deleted file mode 100644 index 8ad64c2..0000000 --- a/brewcode/hooks/pre-task.mjs +++ /dev/null @@ -1,121 +0,0 @@ -#!/usr/bin/env node -/** - * PreToolUse hook for Task tool - * - Injects grepai reminder for ALL agents (when .grepai/ exists) - * - Injects BC_PLUGIN_ROOT/DATA, active mode, team SID, effort prefix into sub-agent prompts - */ -import { - readStdin, - output, - log, - getActiveMode -} from './lib/utils.mjs'; -import { existsSync } from 'fs'; -import { join } from 'path'; - -const GREPAI_REMINDER = 'grepai: USE grepai_search FIRST for code exploration'; - -async function main() { - let cwd = null; - let session_id = null; - - try { - cwd = process.cwd(); - const input = await readStdin(); - session_id = input.session_id; - cwd = input.cwd || cwd; - const tool_input = input.tool_input; - - // Only process Task tool calls - if (!tool_input) { - output({}); - return; - } - - const subagentType = tool_input.subagent_type; - - // Skip if no subagent type - if (!subagentType) { - output({}); - return; - } - - // Check grepai availability (for ALL agents including system agents) - const grepaiDir = join(cwd, '.grepai'); - const hasGrepai = existsSync(grepaiDir) && existsSync(join(grepaiDir, 'index.gob')); - - let updatedPrompt = tool_input.prompt || ''; - let modified = false; - - // 0.0 Effort-level prefix (CC 2.1.115+). Idempotent: skip if already present. - // NOTE: effort.level is NOT in HOOKS-REFERENCE.md (2.1.195). Presence-guarded existing read; do not expand to other hooks. - const effortLevel = input.effort?.level; - if (effortLevel === 'low' && !updatedPrompt.includes('[EFFORT:')) { - updatedPrompt = `[EFFORT: low | MODE: terse-light]\n${updatedPrompt}`; - modified = true; - log('debug', '[pre-task]', `Injected EFFORT=low prefix for ${subagentType}`, cwd, session_id); - } - - // 0. Inject BC_PLUGIN_ROOT for ALL agents (first injection) - const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT || ''; - if (pluginRoot) { - updatedPrompt = `BC_PLUGIN_ROOT=${pluginRoot}\n\n${updatedPrompt}`; - modified = true; - log('debug', '[pre-task]', `Injected BC_PLUGIN_ROOT for ${subagentType}`, cwd, session_id); - } - - const pluginData = process.env.CLAUDE_PLUGIN_DATA || ''; - if (pluginData) { - updatedPrompt = `BC_PLUGIN_DATA=${pluginData}\n\n${updatedPrompt}`; - modified = true; - log('debug', '[pre-task]', `Injected BC_PLUGIN_DATA for ${subagentType}`, cwd, session_id); - } - - // 0.5 Inject mode instructions for ALL agents - const activeMode = getActiveMode(cwd, session_id); - if (activeMode) { - updatedPrompt = `[MODE: ${activeMode.name}] ${activeMode.instructions}\n\n${updatedPrompt}`; - modified = true; - log('debug', '[pre-task]', `Injected mode "${activeMode.name}" for ${subagentType}`, cwd, session_id); - } - - // 0.7 Inject SID for all agents when teams exist (any agent may participate in teams) - const teamsDir = join(cwd, '.claude', 'teams'); - if (existsSync(teamsDir) && typeof session_id === 'string' && session_id.length >= 8) { - const sid = session_id.slice(0, 8); - updatedPrompt = `SID=${sid}\n\n${updatedPrompt}`; - modified = true; - log('debug', '[pre-task]', `Injected SID=${sid} for ${subagentType}`, cwd, session_id); - } - - // 1. Inject grepai reminder for ALL agents (including Explore, Plan, etc.) - if (hasGrepai) { - updatedPrompt = `${GREPAI_REMINDER}\n\n${updatedPrompt}`; - modified = true; - log('debug', '[pre-task]', `grepai reminder for ${subagentType}`, cwd, session_id); - } - - // Output result - updatedInput MUST be inside hookSpecificOutput per Claude Code docs - // Note: systemMessage removed - logs go to brewcode.log only, not UI - if (modified) { - output({ - hookSpecificOutput: { - hookEventName: 'PreToolUse', - permissionDecision: 'allow', - updatedInput: { - ...tool_input, - prompt: updatedPrompt - } - } - }); - } else { - output({}); - } - } catch (error) { - // On error, pass through without modification - log('error', '[pre-task]', `Error: ${error.message}`, cwd, session_id); - output({}); - } -} - -main(); diff --git a/brewcode/hooks/session-start.mjs b/brewcode/hooks/session-start.mjs index 5084ae7..8358605 100644 --- a/brewcode/hooks/session-start.mjs +++ b/brewcode/hooks/session-start.mjs @@ -20,7 +20,7 @@ * * Cleanup: /brewcode:teardown removes .claude/plans/ directory */ -import { readStdin, output, log, getActiveMode, getState, saveState } from './lib/utils.mjs'; +import { readStdin, output, log, getState, saveState } from './lib/utils.mjs'; import { readFileSync, readdirSync, statSync, mkdirSync, symlinkSync, unlinkSync, existsSync } from 'fs'; import { execFileSync } from 'child_process'; import { join } from 'path'; @@ -30,12 +30,6 @@ const VERSION_CACHE_TTL_MS = 24 * 60 * 60 * 1000; const PLAN_FRESHNESS_MS = 60_000; -// Cap text channels under the 2.1.174 10K disk-spill threshold (headroom 9000). -const TEXT_CHANNEL_CAP = 9000; -function capText(s, max = TEXT_CHANNEL_CAP) { - return (typeof s === 'string' && s.length > max) ? s.slice(0, max) + '\n...[truncated]' : s; -} - /** * Creates symlink .claude/plans/LATEST.md → ~/.claude/plans/.md * Only if newest plan is < 60 seconds old (fresh from Plan Mode) @@ -241,23 +235,8 @@ async function main() { } const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT || ''; - const pluginData = process.env.CLAUDE_PLUGIN_DATA || ''; const sessionShort = session_id?.slice(0, 8) || 'unknown'; - let context = pluginRoot - ? `BC_PLUGIN_ROOT=${pluginRoot}\nbrewcode: active | session: ${sessionShort}` - : `brewcode: active | session: ${sessionShort}`; - - if (pluginData) { - context = `BC_PLUGIN_DATA=${pluginData}\n${context}`; - } - - // Inject active mode - const activeMode = getActiveMode(cwd, session_id); - if (activeMode) { - context += `\n[MODE: ${activeMode.name}] ${activeMode.instructions}`; - } - const versionLines = []; try { const [brewcodeResult, claudeResult] = await Promise.all([ @@ -278,15 +257,12 @@ async function main() { if (pluginRoot) versionLines.push(`check brewcode updates: https://github.com/kochetkov-ma/claude-brewcode/releases/latest`); } - const modeTag = activeMode ? ` | mode: ${activeMode.name}` : ''; // reloadSkills not set: this hook toggles no skill files + // No additionalContext: version/plan info is user-facing (systemMessage) only; + // there is nothing model-facing to inject now that root/mode payloads are gone. const permTag = permMode ? ` | perm: ${permMode}` : ''; output({ - systemMessage: `brewcode: ${pluginRoot} | session: ${sessionShort}${modeTag}${permTag}${versionLines.length ? '\n' + versionLines.join('\n') : ''}`, - hookSpecificOutput: { - hookEventName: 'SessionStart', - additionalContext: capText(context) - } + systemMessage: `brewcode: ${pluginRoot} | session: ${sessionShort}${permTag}${versionLines.length ? '\n' + versionLines.join('\n') : ''}` }); } catch (error) { log('error', '[session-start]', `Error: ${error.message}`, cwd, session_id); diff --git a/brewcode/package.json b/brewcode/package.json index 133222a..7139b75 100644 --- a/brewcode/package.json +++ b/brewcode/package.json @@ -1,6 +1,6 @@ { "name": "claude-plugin-brewcode", - "version": "3.19.5", + "version": "4.0.0", "description": "Infinite task execution with automatic handoff for Claude Code", "keywords": [ "claude-code", @@ -36,6 +36,6 @@ }, "claude-plugin": { "name": "brewcode", - "version": "3.19.5" + "version": "4.0.0" } } diff --git a/brewcode/skills/agents/README.md b/brewcode/skills/agents/README.md index 5621b9d..b9f7d81 100644 --- a/brewcode/skills/agents/README.md +++ b/brewcode/skills/agents/README.md @@ -6,97 +6,87 @@ auto-sync-type: doc # Agents -Interactive agent creation and improvement orchestrator. Create new Claude Code agents or improve existing ones through a guided, multi-step workflow powered by the `agent-creator` subagent. +Manages Claude Code subagents across all scopes — create new agents, improve existing ones, audit quality, or inspect what is installed. Input is ONE free-form natural-language prompt; there are no keyword subcommands. ## Quick Start ``` -/brewcode:agents create backend validator -/brewcode:agents up reviewer +/brewcode:agents ``` +No arguments: presents the interactive menu with Status (agents) pre-selected as the recommended action. + +Pass a free-form prompt to skip the menu entirely: + +``` +/brewcode:agents create a backend validator agent for Java Spring projects +``` + +## How It Works — Unified 6-Step Flow + +Every invocation goes through the same flow: + +1. **Input gate** — reads `$ARGUMENTS`; if empty, goes to the interactive menu. +2. **Auto-mode select** — infers mode from the prompt and announces: + `Mode: (agents) — chosen because ` +3. **No-prompt menu** — when no arguments given, shows a single `AskUserQuestion`: + - Status (agents) [recommended] + - Status (all: agents + rules + skills) + - Create + - Improve + - Review + - List (plain) + - Cancel +4. **Dispatch** — routes to `brewcode:agent-creator` subagent (create / improve / review / batch) or runs Glob `*.md` over agent scopes directly (list mode). +5. **Real status** — rich inventory by scope showing agent names, models, trigger coverage, and last-modified — not a flat file listing. +6. **Mandatory final output** — structured summary of what was created, modified, or reviewed. Omitted only for `list` mode. + ## Modes -| Mode | How to trigger | What it does | -|------|---------------|--------------| -| help | `/brewcode:agents` (no args) | Print usage summary and stop | -| create | `/brewcode:agents create ` | Interactive wizard: scope, model, CLAUDE.md update, then spawns agent-creator | -| up | `/brewcode:agents up ` | Resolve agent file, ask improvement focus, spawn agent-creator to enhance it | -| shorthand | `/brewcode:agents ` | Same as `up` -- any non-keyword argument triggers improve mode | +| Mode | How it activates | What it does | +|------|-----------------|--------------| +| `status` | Default when no other mode is detected | Shows agents per scope, model breakdown, trigger coverage | +| `list` | Explicit only — "list", "show agents", "what agents" | Globs `*.md` over all agent scopes, plain file listing | +| `create` | "create", "add", "new agent" in prompt | agent-creator builds frontmatter + system prompt from description | +| `improve` | "improve", "update", "refine", or agent name/path in prompt | agent-creator enhances an existing agent file per chosen focus | +| `review` | "review", "check", "audit" in prompt | agent-creator audits agent files for quality and coverage gaps | +| `batch` | "all", "multiple", "both" or plural scope detected | agent-creator fans out across all matching agents in one pass | + +## Parameters for Create / Improve + +| Parameter | Options | Notes | +|-----------|---------|-------| +| Scope | Project (`.claude/agents/`), Global (`~/.claude/agents/`), Plugin (`brewcode/agents/`) | Asked via single AskUserQuestion | +| Model | `sonnet` (recommended), `opus` / `fable`, `haiku`, `inherit` | `inherit` omits the `model:` field entirely | +| CLAUDE.md update | Yes / No | Adds or updates the agents table row in CLAUDE.md | +| Improve focus | `triggers`, `system-prompt`, `both`, `full review` | Improve mode only | +| Description budget | <=100 characters | Create mode — used as the agent's frontmatter `description` seed | ## Examples -### Good Usage +```bash +# Open the interactive menu +/brewcode:agents + +# Check the current state of all installed agents +/brewcode:agents what agents do we have -``` # Create a new agent with a plain-English description -/brewcode:agents create database migration checker +/brewcode:agents create a SQL migration reviewer for PostgreSQL -# Improve an existing agent by name (searches known locations) -/brewcode:agents up reviewer +# Improve an existing agent by describing what to fix +/brewcode:agents improve the reviewer agent's trigger keywords -# Improve by explicit path (shorthand -- no "up" keyword needed) -/brewcode:agents .claude/agents/reviewer.md +# Audit all agents for quality issues +/brewcode:agents review all project agents -# Improve a global agent -/brewcode:agents up ~/.claude/agents/my-helper.md +# Plain listing of agent files across all scopes +/brewcode:agents list ``` -### Common Mistakes +## Output — Agent Scopes -``` -# Missing description after "create" -- nothing to create -/brewcode:agents create - -# Trying to improve an agent that does not exist -- will fail with NOT_FOUND -/brewcode:agents up nonexistent-agent - -# Passing multiple keywords -- only the first keyword is recognized -/brewcode:agents create up reviewer -``` - -## Workflow - -### Create Mode - -1. **Questions (single prompt)** -- scope (project / global / plugin), model (sonnet / opus / haiku / inherit), CLAUDE.md update preference. -2. **agent-creator** -- subagent analyzes codebase in parallel, asks clarifying questions about role and tools, writes frontmatter + system prompt, validates against checklist. -3. **brewtools:text-optimize** -- automatic token optimization pass on the generated agent file (requires brewtools plugin). -4. **CLAUDE.md update** -- if approved, adds or creates an agents table row. - -### Improve (up) Mode - -1. **Resolve** -- locates the agent file by name or path across `.claude/agents/`, `~/.claude/agents/`, and `brewcode/agents/`. -2. **Questions (single prompt)** -- improvement focus (triggers, system prompt, both, or full review) and CLAUDE.md update preference. -3. **agent-creator** -- subagent analyzes current strengths and weaknesses, enhances the file per the chosen focus. -4. **brewtools:text-optimize** -- automatic token optimization pass (requires brewtools plugin). -5. **CLAUDE.md update** -- if approved, updates the existing row or adds a new one. - -## Output - -The skill produces a structured report: - -``` -# agents [create|up] - -## Detection -| Field | Value | -| Arguments | ... | -| Mode | create / up / help | -| Target | description or resolved path | - -## Result -| Field | Value | -| Agent | /path/to/agent.md | -| Model | sonnet / opus / haiku / inherit | -| Scope | project / global / plugin | -| CLAUDE.md | updated / skipped | - -## Next Steps -- [recommendations] -``` - -Agent files are written to the directory matching the chosen scope: +Agent files are located in or written to the directory matching the chosen scope: | Scope | Directory | |-------|-----------| @@ -104,12 +94,15 @@ Agent files are written to the directory matching the chosen scope: | Global | `~/.claude/agents/` | | Plugin | `brewcode/agents/` | +Status and list modes report agents from all three scopes simultaneously. Create and improve modes write to whichever scope the user selects during the guided prompt. + ## Tips -- Use **shorthand** (`/brewcode:agents reviewer`) for the fastest path to improving an existing agent -- no `up` keyword needed. +- Run `/brewcode:agents` with no arguments to get the menu — the guided flow is faster than remembering free-form phrases. - The **"inherit" model** option omits the `model:` field entirely, so the agent uses whatever model the calling session runs on. -- After creation, review the generated triggers in the agent's `description` frontmatter -- good triggers are the main driver of automatic agent selection. -- Run `/brewcode:agents up` periodically on high-use agents to incorporate new project context and best practices. +- After creation, verify the generated triggers in the agent's `description` frontmatter — trigger quality is the primary driver of automatic agent selection. +- Use `improve` with focus `triggers` periodically on high-use agents to incorporate new project vocabulary and updated invocation patterns. +- `list` is the fastest way to count agents and spot scope imbalance before a review session. ## Documentation diff --git a/brewcode/skills/agents/SKILL.md b/brewcode/skills/agents/SKILL.md index 1c8a1d0..9ce09ce 100644 --- a/brewcode/skills/agents/SKILL.md +++ b/brewcode/skills/agents/SKILL.md @@ -2,304 +2,125 @@ name: brewcode:agents description: "Creates and improves Claude Code subagents. Triggers: create agent, improve agent, scaffold agent, fix agent." user-invocable: true -argument-hint: "[create |up ] | " +argument-hint: "" allowed-tools: [Read, Write, Edit, Glob, Grep, Bash, Task, AskUserQuestion, Skill] model: opus --- # agents Skill -> **Agent Management:** Create and improve Claude Code agents interactively. +> **Agent Management:** create, improve, review, and report on Claude Code agents from one free-form prompt. -## Phase 1: Parse Arguments +## Constants -Extract mode and target from `$ARGUMENTS`: +| Const | Value | +|-------|-------| +| ARTIFACT | `agents` | +| SPECIALIST | `brewcode:agent-creator` | +| LIST_CMD | Glob `*.md` over `.claude/agents/`, `~/.claude/agents/`, `brewcode/agents/` | -| Pattern | Mode | Target | -|---------|------|--------| -| empty | help | -- | -| `create ` | create | description text | -| `up ` | up | agent name or path | -| `` (not keyword) | **up** (shorthand) | name or path | +## Step 1 — Input gate -**Examples:** -- `/brewcode:agents` --> `help` -- `/brewcode:agents create backend validator` --> `create`, target=`backend validator` -- `/brewcode:agents up reviewer` --> `up`, target=`reviewer` -- `/brewcode:agents .claude/agents/reviewer.md` --> `up`, target=path **(shorthand)** +Treat the **entire** user input (`$ARGUMENTS`) as ONE free-form natural-language prompt. +There is NO keyword grammar and NO argument parser — `argument-hint` is only a loose example. ---- +- prompt non-empty -> go to **Step 2** +- prompt empty / whitespace-only -> go to **Step 3** -## Mode: help (empty args) +## Step 2 — Auto-mode selection -Print usage and stop: +Classify the prompt + recent conversation context into exactly ONE mode: + +| Mode | Chosen when prompt signals | +|------|----------------------------| +| `status` | "статус", "что есть", "состояние", health / overview / "show me" (DEFAULT for any "show me" intent) | +| `list` | explicit "список" / "list" / "перечисли" ONLY | +| `create` | "создай" / "create" / "new" / "добавь" / "scaffold" | +| `improve` | "улучши" / "improve" / "refactor" / "fix" / "почини", OR a bare existing name/path | +| `review` | "ревью" / "review" / "validate" / "проверь корректность" | + +**Batch flag:** plural form, "все" / "all", or multiple names/paths -> fan-out (one specialist spawn per item). + +Then **ANNOUNCE the chosen mode (MANDATORY, before any work):** ``` -# brewcode:agents - -Agent management - create and improve Claude Code agents. - -## Usage -- `/brewcode:agents create ` -- create new agent -- `/brewcode:agents up ` -- improve existing agent -- `/brewcode:agents ` -- improve (shorthand) - -## Examples -- `/brewcode:agents create backend validator` -- `/brewcode:agents up reviewer` -- `/brewcode:agents .claude/agents/reviewer.md` +Mode: (agents) — chosen because ``` ---- +Proceed to **Step 4**. -## Mode: create +## Step 3 — No-prompt menu (single AskUserQuestion, scoped + cross-link) -### Description Budget (DEFAULT) +Ask ONE AskUserQuestion. Question: `What do you want to do with agents?` +Options (in this order): -Frontmatter `description`: <= 100 chars (optimal ~80), single line. Role + 2-3 distinct triggers (comma-list). No filler, no `` blocks in frontmatter. Some registries truncate long descriptions and dilute trigger matching. EN only unless user explicitly asks. +- `Status (agents)` — **(Recommended)** rich status of this artifact +- `Status (all: agents+rules+skills)` — cross-link: run the collector for all three +- `Create new agents` +- `Improve existing agents` +- `Review agents` +- `List (plain)` +- `Nothing / cancel` -### Step 1: AskUserQuestion (batch -- all questions in ONE call) +After the choice: +- `Nothing / cancel` -> stop. +- `create` or `improve` -> ask ONE follow-up AskUserQuestion for the target/description + plus the artifact-specific params (see "Artifact-specific params" below). +- Then ANNOUNCE the mode using the Step 2 format and proceed to **Step 4**. -Ask all 3 questions in a single AskUserQuestion: +## Step 4 — Dispatch -**Q1 -- Placement:** -``` -header: "Agent scope" -question: "Where to place the agent?" -options: - - label: "Project (.claude/agents/)" - description: "Team-shared, scoped to this project" - - label: "Global (~/.claude/agents/)" - description: "Available in all projects" - - label: "Plugin (brewcode/agents/)" - description: "Distributed with plugin" -``` +- `status` -> go to **Step 5**. +- `status (all)` -> go to **Step 5**, running the collector for agents + rules + skills together. +- `list` -> run `LIST_CMD`, print the plain inventory it produces, then STOP (no status assembly). +- `create` -> gather minimal params (Step 3 / artifact-specific), spawn `SPECIALIST` via Task. + Batch -> spawn one `SPECIALIST` per item, ALL in ONE message (parallel). +- `improve` -> resolve target(s), spawn `SPECIALIST` via Task per target (parallel for batch). +- `review` -> spawn `brewcode:reviewer` (two-phase: review -> double-check findings -> report). -**Q2 -- Model:** -``` -header: "Model" -question: "Preferred model?" -options: - - label: "sonnet -- balanced (Recommended)" - description: "Best balance of quality and speed for most agents" - - label: "opus/fable -- hardest tasks" - description: "opus for deep reasoning; fable (claude-fable-5, Mythos-class) for the hardest tasks" - - label: "haiku -- fast/simple" - description: "For quick lookup or simple transformations" - - label: "inherit -- from session" - description: "No model field — agent inherits model from calling session" -``` +## Step 5 — Real status (NOT a flat list) -Model mapping: `sonnet` → `sonnet`, `opus/fable` option → pick `opus` → `opus` or `fable` → `fable` (claude-fable-5, Mythos-class), `haiku` → `haiku`, `inherit` → omit `model:` field entirely. +Delegate collection to ONE Explore/Bash subagent, then assemble a rich status (never a bare list): -**Q3 -- CLAUDE.md update:** -``` -header: "CLAUDE.md" -question: "Update CLAUDE.md agents table after creation?" -options: - - label: "Yes -- add row to agents table" - description: "Adds agent to the agents table in CLAUDE.md" - - label: "No -- skip" - description: "Skip CLAUDE.md update" -``` +- **Inventory by scope:** plugin (BC) / project (`.claude/`) / global (`~/.claude/`) — counts + names + load path. +- **State:** enabled/disabled (toggle markers `_SKILL.md` / `_.md`), model. +- **Overlaps / conflicts:** same-name across scopes (shadowing), duplicate triggers/descriptions, naming collisions. +- **Health flags:** missing README/frontmatter; agents missing `Bash` in `tools:` (macOS search rule); + skills with weak description triggers; rules duplicated in CLAUDE.md. -Save answers as: `SCOPE`, `SCOPE_PATH`, `MODEL`, `UPDATE_CLAUDE_MD`. +For the `Status (all)` menu option: run the SAME collector for agents + rules + skills together. -Path mapping: -- "Project (.claude/agents/)" --> `.claude/agents/` -- "Global (~/.claude/agents/)" --> `~/.claude/agents/` -- "Plugin (brewcode/agents/)" --> `brewcode/agents/` - -### Step 2: Spawn agent-creator +## Step 6 — Final formatted output (MANDATORY for every run except `list`) ``` -Task tool: - subagent_type: "brewcode:agent-creator" - prompt: | - Create an agent for: {DESCRIPTION} - - Placement: {SCOPE} ({SCOPE_PATH}) - Model: {MODEL} - - Follow the agent-creator creation process: - 1. Parallel codebase analysis (Explore agents) - 2. Ask clarifying questions (role, tools, triggers) - 3. Write frontmatter + system prompt - 4. Validate against checklist - - Output: full agent file path after creation. - model: opus +# agents [] +## Detection +| Input | menu)"> | +| Mode | | +| Reason | | +| Targets| | +## Result +(create/improve/review: each output path + specialist agent + scope/model) +## Status +(status mode: full table from Step 5; else short "what changed" for touched artifacts) +## Next Steps +(recommendations; ALWAYS remind to run /docs for any created/changed artifact) ``` -Capture result as `AGENT_PATH`. +For `status` mode the report **is** the Step 5 status table. -### Step 3: Apply text-optimize +## Artifact-specific params (create / improve only) -``` -Skill(skill="brewtools:text-optimize", args="{AGENT_PATH}") -``` - -> **Note:** requires brewtools plugin. If unavailable -- skip or apply text-optimize-fallback manually. - -### Step 4: Update CLAUDE.md (if user approved) - -- Read project CLAUDE.md -- Find agents table (look for `| Agent |` or `| Name |` header row with `| Scope |` or `| Purpose |` columns) -- If table exists: add row `| agent-name | scope | model | triggers |` -- If no table: append section: - ```markdown - ## Agents - - | Agent | Scope | Model | Triggers | - |-------|-------|-------|----------| - | {agent-name} | {scope} | {model} | {triggers} | - ``` -- Use Edit tool (never Write for existing files) - ---- - -## Mode: up (improve existing) - -### Step 1: Resolve path/name - -**EXECUTE** using Bash tool: -```bash -TARGET="UP_TARGET_HERE" -# Trim whitespace -TARGET="$(echo "$TARGET" | xargs)" - -if [[ -z "$TARGET" ]]; then - echo "NO_TARGET" - exit 1 -fi - -# Check if direct file -if [[ -f "$TARGET" ]]; then - echo "FOUND: $TARGET" -elif [[ -f "$TARGET.md" ]]; then - echo "FOUND: $TARGET.md" -elif [[ -d "$TARGET" ]] && [[ -f "$TARGET/$(basename "$TARGET").md" ]]; then - echo "FOUND: $TARGET/$(basename "$TARGET").md" -else - # Search by name in known locations - FOUND="" - for loc in ".claude/agents" "$HOME/.claude/agents" "brewcode/agents"; do - if [[ -f "$loc/$TARGET.md" ]]; then - FOUND="$loc/$TARGET.md" - break - elif [[ -f "$loc/$TARGET" ]]; then - FOUND="$loc/$TARGET" - break - fi - done - if [[ -n "$FOUND" ]]; then - echo "FOUND: $FOUND" - else - echo "NOT_FOUND: $TARGET" - fi -fi -``` - -Replace `UP_TARGET_HERE` with the actual target extracted from `$ARGUMENTS` (strip `up ` prefix if present). - -> **STOP if NOT_FOUND** -- report error and list available agents. - -Read the resolved agent file to extract name, purpose, current content. - -### Step 2: AskUserQuestion (2 questions in ONE call) - -**Q1 -- Focus:** -``` -header: "Improvement focus" -question: "What to improve?" -options: - - label: "Triggers/activation" - description: "Improve description and trigger examples for better auto-detection" - - label: "System prompt quality" - description: "Enhance instructions, checklist, output format" - - label: "Both (Recommended)" - description: "Triggers + system prompt quality" - - label: "Full review + project context" - description: "Complete review including project-specific knowledge update" -``` - -**Q2 -- CLAUDE.md update:** -``` -header: "CLAUDE.md" -question: "Update CLAUDE.md agents table after?" -options: - - label: "Yes" - description: "Update agents table row in CLAUDE.md" - - label: "No" - description: "Skip CLAUDE.md update" -``` - -Save answers as: `IMPROVEMENT_FOCUS`, `UPDATE_CLAUDE_MD`. - -### Step 3: Spawn agent-creator - -``` -Task tool: - subagent_type: "brewcode:agent-creator" - prompt: | - Improve existing agent. Focus: {IMPROVEMENT_FOCUS} - - Agent path: {AGENT_PATH} - Current content: - {AGENT_CONTENT} - - Tasks: - 1. Analyze current strengths/weaknesses - 2. Improve description trigger examples - 3. Enhance system prompt clarity - 4. Apply agent-creator best practices - 5. Save updated file - - Output: full agent file path after update. - model: opus -``` - -### Step 4: Apply text-optimize - -``` -Skill(skill="brewtools:text-optimize", args="{AGENT_PATH}") -``` - -> **Note:** requires brewtools plugin. If unavailable -- skip or apply text-optimize-fallback manually. - -### Step 5: Update CLAUDE.md (if approved) - -Same logic as create Step 4. If row already exists for this agent, update it instead of adding a new one. +For `create`: ONE AskUserQuestion batch — (Q1) scope: Project `.claude/agents/` / +Global `~/.claude/agents/` / Plugin `brewcode/agents/`; (Q2) model: sonnet (Recommended) / +opus-or-fable / haiku / inherit (omit model: field); (Q3) update CLAUDE.md agents table? yes/no. +Frontmatter description budget: <= 100 chars, single line, role + 2-3 triggers, EN only. +Spawn SPECIALIST (brewcode:agent-creator) with the description, scope+path, model. +After creation, if user approved, update the CLAUDE.md agents table via Edit (add/replace row). +For `improve`: resolve agent by name/path across the 3 scopes; ONE AskUserQuestion — +(Q1) focus: triggers / system-prompt / both (Recommended) / full review; (Q2) update CLAUDE.md? yes/no. +Spawn SPECIALIST to improve, then optional CLAUDE.md row update. - ---- - -## Output Format - -```markdown -# agents [{MODE}] - -## Detection - -| Field | Value | -|-------|-------| -| Arguments | `$ARGUMENTS` | -| Mode | `[create|up|help]` | -| Target | `[description or path]` | - -## Result - -| Field | Value | -|-------|-------| -| Agent | `[path]` | -| Model | `[model]` | -| Scope | `[project|global|plugin]` | -| CLAUDE.md | `[updated|skipped]` | - -## Next Steps - -- [recommendations] -``` diff --git a/brewcode/skills/grepai/README.md b/brewcode/skills/grepai/README.md index 19dd5e2..157ac64 100644 --- a/brewcode/skills/grepai/README.md +++ b/brewcode/skills/grepai/README.md @@ -65,6 +65,18 @@ First-time setup takes 5-30+ minutes depending on project size. It checks infras /brewcode:grepai setup <-- fails on missing Ollama or bge-m3 ``` +## Hook Self-Install + +On first `/brewcode:grepai` setup run, the skill self-installs two project hooks: + +1. Detects whether `.claude/grepai/hooks/` already exists (idempotent -- safe to re-run). +2. Default scope: PROJECT. Asks via AskUserQuestion only when scope is ambiguous. +3. Copies `assets/grepai-session.mjs` and `assets/grepai-reminder.mjs` to `.claude/grepai/hooks/`. +4. Merges SessionStart and PreToolUse:Bash entries into `.claude/settings.json` (jq + python3 fallback, no clobber). +5. Reports what was created. + +After install, grepai reminders fire automatically at session start (SS) and on every Bash call (PTU:Bash). + ## Output After `setup` completes, the following is created in your project: diff --git a/brewcode/skills/grepai/SKILL.md b/brewcode/skills/grepai/SKILL.md index 11f98c9..41e0f11 100644 --- a/brewcode/skills/grepai/SKILL.md +++ b/brewcode/skills/grepai/SKILL.md @@ -47,7 +47,7 @@ MODE: [detected mode] | (empty) + no .grepai/ | setup | | (unrecognized text) | prompt | -> **Prerequisites:** Homebrew, Ollama, and the grepai CLI must be installed. The `setup` mode below runs `infra-check.sh` to verify them and reports anything missing. +> **Prerequisites:** Homebrew, Ollama, the bge-m3 model, and the grepai CLI. The `setup` mode below runs `infra-check.sh` to verify them and, if anything is missing, offers to auto-install everything via `scripts/install.sh` (after confirmation). --- @@ -55,14 +55,40 @@ MODE: [detected mode] Full grepai installation and project setup. -### Phase 1: Infrastructure Check +### Phase 1: Infrastructure Check & Auto-Install + +**EXECUTE** using Bash tool: +```bash +bash "${CLAUDE_SKILL_DIR}/scripts/infra-check.sh" && echo "✅ infra-check" || echo "⚠️ infra-check: prerequisites missing" +``` + +- Printed `✅ infra-check` (all present) -> skip to Phase 2. +- Printed `⚠️ infra-check: prerequisites missing` -> continue to auto-install below. + +#### Offer Auto-Install + +> `scripts/install.sh` installs every missing prerequisite via Homebrew: brew, coreutils + `timeout` symlink, jq, ollama (+ service start), the bge-m3 embedding model, and the grepai CLI. It is idempotent — already-installed components are skipped. + +**ASK** (AskUserQuestion): "grepai prerequisites are missing. Auto-install them now? This creates a `timeout` symlink (coreutils) and downloads the grepai CLI + bge-m3 model (~1.5GB)." +Options: "Yes, install" | "Cancel" + +> **If Cancel** -> STOP: "grepai setup cancelled. Install prerequisites manually, then re-run `/brewcode:grepai setup`." + +**EXECUTE** using Bash tool: +```bash +bash "${CLAUDE_SKILL_DIR}/scripts/install.sh" && echo "✅ install" || echo "❌ install FAILED" +``` + +> **STOP if ❌** — check the install output for the failed component and install it manually. + +#### Re-verify **EXECUTE** using Bash tool: ```bash bash "${CLAUDE_SKILL_DIR}/scripts/infra-check.sh" && echo "✅ infra-check" || echo "❌ infra-check FAILED" ``` -> **STOP if ❌** — install missing components before continuing. +> **STOP if ❌** — prerequisites still missing after install; inspect the install output above. ### Phase 2: MCP Configuration & Permissions @@ -85,7 +111,7 @@ This script configures MCP server and allowedTools permissions. | `prompt` | `Configure grepai for this project. Analyze all build files, test patterns, source structure. Generate optimal .grepai/config.yaml.` | | `model` | `opus` | -> **Context:** `BC_PLUGIN_ROOT` is available in agent context (injected by pre-task.mjs hook). +> **Context:** the agent resolves its plugin root natively via `${CLAUDE_PLUGIN_ROOT}` (substituted in its .md at Task spawn). > **WAIT** for agent to complete before proceeding. @@ -109,7 +135,125 @@ bash "${CLAUDE_SKILL_DIR}/scripts/create-rule.sh" && echo "✅ create-rule" || e > **STOP if ❌** — manually create rule in `.claude/rules/`. -### Phase 6: Verification +### Phase 6: Install grepai Hooks (self-install) + +> grepai ships two self-contained hooks that travel into the user's project (NOT +> the plugin): `grepai-session.mjs` (SessionStart — auto-starts `grepai watch` and +> injects "USE grepai_search FIRST" when the index is live) and +> `grepai-reminder.mjs` (PreToolUse:Bash — nudges toward `grepai_search` when a +> `grep/find/rg` command runs). Self-install is idempotent. Runbook + jq/python3 +> merge details: `${CLAUDE_SKILL_DIR}/assets/INSTALL.md`. + +#### Step 1: Detect (idempotent — skip if already installed) + +**EXECUTE** using Bash tool: +```bash +SETTINGS="$PWD/.claude/settings.json" +if [ -f "$SETTINGS" ] && grep -q 'grepai-session.mjs' "$SETTINGS" 2>/dev/null; then + echo "✅ hooks already installed — skip Phase 6" +else + echo "⚠️ hooks not installed — continue" +fi +``` + +- Printed `✅ hooks already installed` -> SKIP to Phase 7. Do NOT re-copy/re-merge. +- Printed `⚠️ hooks not installed` -> continue. + +#### Step 2: Choose scope + +Scope is PROJECT by default. grepai setup always runs against THIS repo, so the +scope is unambiguous — **default to PROJECT and SKIP the questions**. + +Ask via `AskUserQuestion` ONLY when scope is genuinely ambiguous (e.g. the user +explicitly says "for all my projects" / "globally", or there is no obvious single +project root): +- "Install grepai hooks for this Project or Globally?" (options: **Project** / **Global**) +- Confirm hook creation: "grepai will copy two SessionStart + PreToolUse:Bash hooks into `/.claude/grepai/hooks/` and merge them into `settings.json`. Proceed?" (options: **Yes, install** / **Skip hooks**) + +> Skip hooks -> note it and GOTO Phase 7 (search config still works via MCP; only +> the auto-watch + reminder are skipped). + +#### Step 3: Copy + merge (no clobber) + +Follow the runbook. `SRC` = this skill's assets dir; `DST`/`SETTINGS` by scope. +PROJECT writes freely; GLOBAL (`~/.claude/*`) MUST go through the Bash tool only +(protected path — Bash `cp`/`jq`/`python3`/`mv` are allowed, Write/Edit are not). + +**EXECUTE** using Bash tool (PROJECT scope shown; for GLOBAL set the two GLOBAL +paths from the comments): +```bash +SRC="${CLAUDE_SKILL_DIR}/assets" +# PROJECT: DST="$PWD/.claude/grepai/hooks"; SETTINGS="$PWD/.claude/settings.json" +# GLOBAL: DST="$HOME/.claude/grepai/hooks"; SETTINGS="$HOME/.claude/settings.json" +DST="$PWD/.claude/grepai/hooks" +SETTINGS="$PWD/.claude/settings.json" + +mkdir -p "$DST" && cp "$SRC/grepai-session.mjs" "$SRC/grepai-reminder.mjs" "$DST/" \ + && echo "✅ copied to $DST" || { echo "❌ copy FAILED"; exit 1; } + +mkdir -p "$(dirname "$SETTINGS")" +[ -f "$SETTINGS" ] || echo '{}' > "$SETTINGS" +S_CMD="node $DST/grepai-session.mjs" +R_CMD="node $DST/grepai-reminder.mjs" + +if command -v jq >/dev/null 2>&1; then + TMP="$(mktemp)" + jq --arg scmd "$S_CMD" --arg rcmd "$R_CMD" ' + .hooks = (.hooks // {}) + | .hooks.SessionStart = (.hooks.SessionStart // []) + | (if (.hooks.SessionStart | map(.hooks // [] | map(.command // "") | any(test("grepai-session\\.mjs"))) | any) + then . + else (if (.hooks.SessionStart | length) > 0 + then .hooks.SessionStart[0].hooks += [{"type":"command","command":$scmd}] + else .hooks.SessionStart += [{"hooks":[{"type":"command","command":$scmd}]}] end) + end) + | .hooks.PreToolUse = (.hooks.PreToolUse // []) + | (if (.hooks.PreToolUse | map(.hooks // [] | map(.command // "") | any(test("grepai-reminder\\.mjs"))) | any) + then . + else (.hooks.PreToolUse | map((.matcher // "") == "Bash") | index(true)) as $i + | (if $i != null + then .hooks.PreToolUse[$i].hooks += [{"type":"command","command":$rcmd}] + else .hooks.PreToolUse += [{"matcher":"Bash","hooks":[{"type":"command","command":$rcmd}]}] end) + end) + ' "$SETTINGS" > "$TMP" && mv "$TMP" "$SETTINGS" \ + && jq empty "$SETTINGS" >/dev/null 2>&1 && echo "✅ merged $SETTINGS (jq)" || echo "❌ merge FAILED" +elif command -v python3 >/dev/null 2>&1; then + SETTINGS="$SETTINGS" S_CMD="$S_CMD" R_CMD="$R_CMD" python3 - <<'PY' +import json, os +f = os.environ["SETTINGS"]; scmd = os.environ["S_CMD"]; rcmd = os.environ["R_CMD"] +try: data = json.load(open(f)) +except Exception: data = {} +hooks = data.setdefault("hooks", {}) +def has(groups, basename): + return any(basename in (h.get("command") or "") for g in groups for h in g.get("hooks", [])) +ss = hooks.setdefault("SessionStart", []) +if not has(ss, "grepai-session.mjs"): + (ss[0].setdefault("hooks", []).append({"type":"command","command":scmd}) if ss + else ss.append({"hooks":[{"type":"command","command":scmd}]})) +pt = hooks.setdefault("PreToolUse", []) +if not has(pt, "grepai-reminder.mjs"): + bg = next((g for g in pt if g.get("matcher") == "Bash"), None) + (bg.setdefault("hooks", []).append({"type":"command","command":rcmd}) if bg is not None + else pt.append({"matcher":"Bash","hooks":[{"type":"command","command":rcmd}]})) +json.dump(data, open(f,"w"), indent=2) +print("OK") +PY + echo "✅ merged $SETTINGS (python3)" +else + echo "❌ neither jq nor python3 — add the two entries from assets/INSTALL.md manually" +fi +``` + +> **STOP if ❌** — see `${CLAUDE_SKILL_DIR}/assets/INSTALL.md` for the manual entries. + +#### Step 4: Report what was created + +After install, tell the user EXACTLY what changed: +- Hook files copied: `/.claude/grepai/hooks/grepai-session.mjs`, `/.claude/grepai/hooks/grepai-reminder.mjs` +- `settings.json` entries merged: `SessionStart -> node .../grepai-session.mjs`, `PreToolUse(matcher "Bash") -> node .../grepai-reminder.mjs` +- Reminder: a NEW session picks them up (SessionStart fires on next `claude` start / `--resume`); no `/reload-plugins` needed. + +### Phase 7: Verification **EXECUTE** using Bash tool: ```bash @@ -181,7 +325,7 @@ bash "${CLAUDE_SKILL_DIR}/scripts/optimize.sh" && echo "✅ optimize-backup" || | `prompt` | `Re-analyze project and regenerate .grepai/config.yaml. Compare with existing config, optimize boost patterns, update trace languages.` | | `model` | `opus` | -> **Context:** `BC_PLUGIN_ROOT` is available in agent context (injected by pre-task.mjs hook). +> **Context:** the agent resolves its plugin root natively via `${CLAUDE_PLUGIN_ROOT}` (substituted in its .md at Task spawn). > **WAIT** for agent to complete. diff --git a/brewcode/skills/grepai/assets/INSTALL.md b/brewcode/skills/grepai/assets/INSTALL.md new file mode 100644 index 0000000..d6e9fe3 --- /dev/null +++ b/brewcode/skills/grepai/assets/INSTALL.md @@ -0,0 +1,169 @@ +# grepai hooks — install runbook + +Self-contained hook assets. The `/brewcode:grepai` skill copies these into a +target hooks dir and wires `settings.json`. Both files are independent (no shared +lib, no plugin-root deps) and travel together: + +| File | Event | Channel | +|------|-------|---------| +| `grepai-session.mjs` | SessionStart | `systemMessage` (status line) + `additionalContext` ("USE grepai_search FIRST") when index+ollama+mcp are all up; also auto-starts `grepai watch --background` when an index exists and ollama is running | +| `grepai-reminder.mjs` | PreToolUse `Bash` | `additionalContext` ("USE grepai_search FIRST") when a `grep/find/rg/...` command is run AND the project has `.grepai/index.gob`; self-throttled to once / 60s via `.grepai/.reminder-ts` | + +> Scripts are pure ESM, Node built-ins only (`fs`, `path`, `child_process`), no +> plugin-root / npm deps. Each reads stdin, never throws, always exits 0. They +> read project state from `/.grepai/` at runtime — copy location does not +> matter, so they can live anywhere under the project. + +--- + +## Target install dir + +`.claude/grepai/hooks/` under the chosen scope: + +- PROJECT scope -> `/.claude/grepai/hooks/` +- GLOBAL scope -> `~/.claude/grepai/hooks/` (expanded) + +--- + +## settings.json hook entries + +`` = absolute path of the hooks dir the 2 files were copied into +(`/.claude/grepai/hooks` for project, expanded `~/.claude/grepai/hooks` +for global). + +```json +{ + "hooks": { + "SessionStart": [ + { "hooks": [ { "type": "command", "command": "node /grepai-session.mjs" } ] } + ], + "PreToolUse": [ + { "matcher": "Bash", "hooks": [ { "type": "command", "command": "node /grepai-reminder.mjs" } ] } + ] + } +} +``` + +> The exact `command` string form follows the project's existing convention. If +> the project already wires hooks as `{"type":"command","command":"node", +> "args":["..."]}`, mirror that shape instead. Both forms are accepted by CC. + +Merge rule: APPEND into the existing `SessionStart` / `PreToolUse` arrays — never +overwrite. If a project hook already exists for `SessionStart` (or for +`PreToolUse` with `matcher` `Bash`), inject the grepai command INTO that group's +`hooks` array rather than adding a new sibling group. Dedupe by the grepai script +basename: if any existing entry references `grepai-session.mjs` / +`grepai-reminder.mjs`, skip (idempotent re-install). + +--- + +## INSTALL (project or global) + +Set `DST` and `SETTINGS` by scope, then run two steps: (1) copy files, (2) merge +settings (jq with python3 fallback). Project paths are writable with normal +tools; for GLOBAL (`~/.claude/*`) use the Bash tool only — that path is +harness-protected against the Write/Edit tools. + +### Step 1 — copy the 2 hook files + +`SRC` = this `assets/` dir (the skill passes its absolute path). EXECUTE with the +Bash tool: + +```bash +# PROJECT: DST="$PWD/.claude/grepai/hooks" +# GLOBAL: DST="$HOME/.claude/grepai/hooks" +mkdir -p "$DST" && \ +cp "$SRC/grepai-session.mjs" "$SRC/grepai-reminder.mjs" "$DST/" && \ +echo "✅ copied to $DST" || echo "❌ copy FAILED" +``` + +### Step 2 — merge settings.json (jq, python3 fallback) + +Idempotent append + dedupe by script basename, injecting into an existing +SessionStart / PreToolUse(Bash) group when present. EXECUTE with the Bash tool: + +```bash +# PROJECT: SETTINGS="$PWD/.claude/settings.json" +# GLOBAL: SETTINGS="$HOME/.claude/settings.json" +mkdir -p "$(dirname "$SETTINGS")" +[ -f "$SETTINGS" ] || echo '{}' > "$SETTINGS" + +S_CMD="node $DST/grepai-session.mjs" +R_CMD="node $DST/grepai-reminder.mjs" + +if command -v jq >/dev/null 2>&1; then + TMP="$(mktemp)" + jq --arg scmd "$S_CMD" --arg rcmd "$R_CMD" ' + .hooks = (.hooks // {}) + # SessionStart: reuse a group if any, else create one; dedupe by grepai-session.mjs + | .hooks.SessionStart = (.hooks.SessionStart // []) + | (if (.hooks.SessionStart | map(.hooks // [] | map(.command // "") | any(test("grepai-session\\.mjs"))) | any) + then . + else (if (.hooks.SessionStart | length) > 0 + then .hooks.SessionStart[0].hooks += [{"type":"command","command":$scmd}] + else .hooks.SessionStart += [{"hooks":[{"type":"command","command":$scmd}]}] end) + end) + # PreToolUse: reuse a Bash-matcher group if any, else create; dedupe by grepai-reminder.mjs + | .hooks.PreToolUse = (.hooks.PreToolUse // []) + | (if (.hooks.PreToolUse | map(.hooks // [] | map(.command // "") | any(test("grepai-reminder\\.mjs"))) | any) + then . + else (.hooks.PreToolUse | map((.matcher // "") == "Bash") | index(true)) as $i + | (if $i != null + then .hooks.PreToolUse[$i].hooks += [{"type":"command","command":$rcmd}] + else .hooks.PreToolUse += [{"matcher":"Bash","hooks":[{"type":"command","command":$rcmd}]}] end) + end) + ' "$SETTINGS" > "$TMP" && mv "$TMP" "$SETTINGS" && \ + jq empty "$SETTINGS" >/dev/null 2>&1 && echo "✅ merged $SETTINGS (jq)" || echo "❌ merge FAILED" +elif command -v python3 >/dev/null 2>&1; then + SETTINGS="$SETTINGS" S_CMD="$S_CMD" R_CMD="$R_CMD" python3 - <<'PY' +import json, os +f = os.environ["SETTINGS"]; scmd = os.environ["S_CMD"]; rcmd = os.environ["R_CMD"] +try: + data = json.load(open(f)) +except Exception: + data = {} +hooks = data.setdefault("hooks", {}) + +def has(groups, basename): + for g in groups: + for h in g.get("hooks", []): + if basename in (h.get("command") or ""): + return True + return False + +ss = hooks.setdefault("SessionStart", []) +if not has(ss, "grepai-session.mjs"): + if ss: + ss[0].setdefault("hooks", []).append({"type": "command", "command": scmd}) + else: + ss.append({"hooks": [{"type": "command", "command": scmd}]}) + +pt = hooks.setdefault("PreToolUse", []) +if not has(pt, "grepai-reminder.mjs"): + bash_group = next((g for g in pt if g.get("matcher") == "Bash"), None) + if bash_group is not None: + bash_group.setdefault("hooks", []).append({"type": "command", "command": rcmd}) + else: + pt.append({"matcher": "Bash", "hooks": [{"type": "command", "command": rcmd}]}) + +json.dump(data, open(f, "w"), indent=2) +print("OK") +PY + echo "✅ merged $SETTINGS (python3)" +else + echo "❌ neither jq nor python3 available — add the two entries above to $SETTINGS manually" +fi +``` + +> GLOBAL note: `~/.claude/*` blocks the Write/Edit/MultiEdit TOOLS in all +> permission modes, but Bash file writes (`cp`, `jq`, `python3`, `mv`) are +> allowed. Do the global install entirely through the Bash tool, never Edit/Write. + +--- + +## After install + +`/reload-plugins` is NOT needed — these are plain `settings.json` hooks, not +plugin hooks. A NEW session picks them up: SessionStart fires on the next +`claude` start / `--resume`; the PreToolUse:Bash reminder fires immediately in +the next session's tool calls. diff --git a/brewcode/hooks/grepai-reminder.mjs b/brewcode/skills/grepai/assets/grepai-reminder.mjs similarity index 57% rename from brewcode/hooks/grepai-reminder.mjs rename to brewcode/skills/grepai/assets/grepai-reminder.mjs index 06a5d40..5ce2b0c 100644 --- a/brewcode/hooks/grepai-reminder.mjs +++ b/brewcode/skills/grepai/assets/grepai-reminder.mjs @@ -1,26 +1,53 @@ #!/usr/bin/env node - /** - * PreToolUse:Bash hook. + * grepai PreToolUse:Bash Hook (self-contained — installed into a user project) + * * Native Grep/Glob tools were removed on this CC build; code search runs via Bash * (shadow grep->ugrep / find->bfs / rg). Reminds Claude to prefer grepai_search * when a grep/find/rg search command is run through Bash. + * + * SELF-CONTAINED: readStdin / output / log are inlined below. No plugin-root + * paths, no shared lib import. Pure ESM, Node built-ins only. Exits 0 always. */ - import { existsSync, statSync, writeFileSync } from 'fs'; import { join } from 'path'; -import { readStdin, output, log } from './lib/utils.mjs'; + +// --- inlined helpers (from brewcode hooks lib/utils.mjs) ------------------- +async function readStdin() { + const chunks = []; + for await (const chunk of process.stdin) chunks.push(chunk); + const input = Buffer.concat(chunks).toString('utf8'); + try { + return JSON.parse(input); + } catch (e) { + throw new Error(`Invalid stdin JSON: ${e.message}. Input: ${input.substring(0, 100)}`); + } +} + +function output(response) { + try { + console.log(JSON.stringify(response)); + } catch (e) { + console.log(JSON.stringify({ error: `Serialization failed: ${e.message}` })); + } +} + +// Minimal log: stderr only for warn/error, never throws, no file deps. +function log(level, prefix, message) { + if (level === 'error' || level === 'warn') { + try { console.error(`${prefix} ${message}`); } catch {} + } +} +// --------------------------------------------------------------------------- const SEARCH_RE = /(?:^|[|;&(]|&&|\|\|)\s*(?:command\s+)?(grep|egrep|fgrep|ugrep|rg|ag|ack|find|bfs)\b/; async function main() { let cwd = null; - let session_id = null; try { cwd = process.cwd(); const input = await readStdin(); - session_id = input.session_id; cwd = input.cwd || cwd; const command = input.tool_input && input.tool_input.command; @@ -50,10 +77,9 @@ async function main() { } writeFileSync(tsFile, ''); } catch (e) { - log('warn', '[grepai-reminder]', `Throttle write failed: ${e.message}`, cwd, session_id); + log('warn', '[grepai-reminder]', `Throttle write failed: ${e.message}`); } - log('debug', '[grepai-reminder]', 'Reminder triggered', cwd, session_id); output({ hookSpecificOutput: { hookEventName: 'PreToolUse', @@ -64,7 +90,7 @@ async function main() { output({}); } } catch (err) { - log('error', '[grepai-reminder]', `Error: ${err.message}`, cwd, session_id); + log('error', '[grepai-reminder]', `Error: ${err.message}`); output({}); } } diff --git a/brewcode/hooks/grepai-session.mjs b/brewcode/skills/grepai/assets/grepai-session.mjs similarity index 80% rename from brewcode/hooks/grepai-session.mjs rename to brewcode/skills/grepai/assets/grepai-session.mjs index 8c6d696..b349356 100644 --- a/brewcode/hooks/grepai-session.mjs +++ b/brewcode/skills/grepai/assets/grepai-session.mjs @@ -1,19 +1,48 @@ #!/usr/bin/env node /** - * grepai SessionStart Hook + * grepai SessionStart Hook (self-contained — installed into a user project) * * Auto-starts grepai watch when entering a project with .grepai/ configured. * Provides status information via systemMessage. * * NEVER blocks session start - all errors are informational only. - * * Platform: macOS/Linux only. Windows lacks pgrep - auto-start disabled. + * + * SELF-CONTAINED: readStdin / output / log are inlined below. No plugin-root + * paths, no shared lib import. Pure ESM, Node built-ins only. Exits 0 always. */ -import { readStdin, output, log } from './lib/utils.mjs'; import { execSync, spawn } from 'child_process'; import { existsSync, mkdirSync, statSync, readFileSync } from 'fs'; import { join } from 'path'; +// --- inlined helpers (from brewcode hooks lib/utils.mjs) ------------------- +async function readStdin() { + const chunks = []; + for await (const chunk of process.stdin) chunks.push(chunk); + const input = Buffer.concat(chunks).toString('utf8'); + try { + return JSON.parse(input); + } catch (e) { + throw new Error(`Invalid stdin JSON: ${e.message}. Input: ${input.substring(0, 100)}`); + } +} + +function output(response) { + try { + console.log(JSON.stringify(response)); + } catch (e) { + console.log(JSON.stringify({ error: `Serialization failed: ${e.message}` })); + } +} + +// Minimal log: stderr only for warn/error, never throws, no file deps. +function log(level, prefix, message) { + if (level === 'error' || level === 'warn') { + try { console.error(`${prefix} ${message}`); } catch {} + } +} +// --------------------------------------------------------------------------- + async function main() { let cwd = null; let session_id = null; @@ -24,14 +53,10 @@ async function main() { session_id = input.session_id; cwd = input.cwd || cwd; - log('info', '[grepai]', 'SessionStart hook triggered', cwd, session_id); - const result = await checkGrepai(cwd, session_id); - - log('debug', '[grepai]', 'Hook completed', cwd, session_id); output(result); } catch (err) { - log('error', '[grepai]', `Hook error: ${err.message}`, cwd, session_id); + log('error', '[grepai]', `Hook error: ${err.message}`); output({}); } } @@ -43,7 +68,6 @@ async function checkGrepai(cwd, session_id = null) { // No .grepai directory - skip silently (grepai not configured for this project) if (!existsSync(grepaiDir)) { - log('debug', '[grepai]', 'Not configured', cwd, session_id); return { systemMessage: 'grepai: not configured' }; } @@ -53,7 +77,6 @@ async function checkGrepai(cwd, session_id = null) { // Check ollama const ollamaRunning = checkOllama(); - log('debug', '[grepai]', `ollama: ${ollamaRunning ? 'running' : 'stopped'}`, cwd, session_id); if (!ollamaRunning) { status.push('ollama: stopped'); } @@ -71,27 +94,22 @@ async function checkGrepai(cwd, session_id = null) { // >100KB = normal project (display MB) if (stats.size < 20000) { indexStatus = `⚠️ ${sizeKB}KB`; - log('warn', '[grepai]', `index: small (${sizeKB}KB, likely <10 files) - run reindex`, cwd, session_id); } else if (stats.size < 100000) { indexStatus = `${sizeKB}KB`; - log('debug', '[grepai]', `index: ${sizeKB}KB`, cwd, session_id); } else { const sizeMB = (stats.size / (1024 * 1024)).toFixed(1); indexStatus = `${sizeMB}MB`; - log('debug', '[grepai]', `index: ${sizeMB}MB`, cwd, session_id); } } catch (err) { indexStatus = 'error'; - log('warn', '[grepai]', `index stat failed: ${err.message}`, cwd, session_id); + log('warn', '[grepai]', `index stat failed: ${err.message}`); } } else { - log('debug', '[grepai]', 'index: missing', cwd, session_id); status.push('index: missing'); } // Check watch process const watchRunning = checkWatchRunning(cwd); - log('debug', '[grepai]', `watch: ${watchRunning ? 'running' : 'stopped'}`, cwd, session_id); if (!watchRunning && hasIndex && ollamaRunning && process.platform !== 'win32') { shouldAutoStart = true; @@ -99,7 +117,6 @@ async function checkGrepai(cwd, session_id = null) { // Check MCP server const mcpRunning = checkMcpServer(cwd); - log('debug', '[grepai]', `mcp-serve: ${mcpRunning ? 'running' : 'stopped'}`, cwd, session_id); if (!mcpRunning) { status.push('mcp-serve: stopped'); } @@ -107,8 +124,6 @@ async function checkGrepai(cwd, session_id = null) { // Auto-start watch if conditions met if (shouldAutoStart) { try { - log('info', '[grepai]', 'Auto-starting watch', cwd, session_id); - if (!existsSync(logsDir)) { mkdirSync(logsDir, { recursive: true }); } @@ -119,21 +134,20 @@ async function checkGrepai(cwd, session_id = null) { stdio: 'ignore' }); child.on('error', (err) => { - log('warn', '[grepai]', `Watch spawn error: ${err.message}`, cwd, session_id); + log('warn', '[grepai]', `Watch spawn error: ${err.message}`); }); child.unref(); - log('info', '[grepai]', 'Watch spawn initiated', cwd, session_id); status.push('watch: starting'); } catch (err) { - log('warn', '[grepai]', `Watch auto-start failed: ${err.message}`, cwd, session_id); + log('warn', '[grepai]', `Watch auto-start failed: ${err.message}`); status.push('watch: start failed'); } } else if (!watchRunning) { status.push('watch: stopped'); } - // Build status message: "grepai: ready | index: 150KB" or "grepai: ollama: stopped | index: ⚠️ 14KB" + // Build status message let statusMessage; if (status.length === 0) { statusMessage = indexStatus ? `ready | index: ${indexStatus}` : 'ready'; @@ -143,8 +157,6 @@ async function checkGrepai(cwd, session_id = null) { : status.join(', '); } - log('info', '[grepai]', `Status: ${statusMessage}`, cwd, session_id); - const result = { systemMessage: `grepai: ${statusMessage}` }; // Reminder for Claude: only when grepai_search is actually usable (index + ollama + mcp) diff --git a/brewcode/skills/rules/README.md b/brewcode/skills/rules/README.md index ebaadd4..5a5691a 100644 --- a/brewcode/skills/rules/README.md +++ b/brewcode/skills/rules/README.md @@ -6,7 +6,9 @@ auto-sync-type: doc # Rules -Extracts learnings, anti-patterns, and best practices from KNOWLEDGE files, arbitrary files, or the current conversation -- then organizes them into structured `.claude/rules/` files that Claude Code loads automatically on every session. +Captures learnings, anti-patterns, and best practices — from KNOWLEDGE files, arbitrary files, or the current conversation — then organizes them into structured `.claude/rules/` files that Claude Code loads automatically on every session. + +**Target scope:** project `.claude/rules/` only. The skill never writes to `~/.claude/rules/`. ## Quick Start @@ -14,79 +16,103 @@ Extracts learnings, anti-patterns, and best practices from KNOWLEDGE files, arbi /brewcode:rules ``` -Scans the current session for the 5 most impactful findings and writes them to your project rules. +No arguments: presents the interactive menu with Status (rules) pre-selected as the recommended action. + +Pass a free-form prompt to skip the menu entirely: + +``` +/brewcode:rules capture what we learned fixing the N+1 query bug today +``` + +## How It Works — Unified 6-Step Flow + +Every invocation goes through the same flow: + +1. **Input gate** — reads `$ARGUMENTS`; if empty, goes to the interactive menu. +2. **Auto-mode select** — infers mode from the prompt and announces: + `Mode: (rules) — chosen because ` +3. **No-prompt menu** — when no arguments given, shows a single `AskUserQuestion`: + - Status (rules) [recommended] + - Status (all: agents + rules + skills) + - Create + - Improve + - Review + - List (plain) + - Cancel +4. **Dispatch** — routes to `bc-rules-organizer` agent (create / improve / review / batch) or runs `rules.sh list` directly (list mode). +5. **Real status** — rich output showing current rule files, entry counts, and a diff of changes applied. +6. **Mandatory final output** — structured summary of what was written, merged, and skipped. Omitted only for `list` mode. ## Modes -| Mode | Trigger | What it does | -|------|---------|--------------| -| **Session** | `/brewcode:rules` (no arguments) | Extracts top 5 findings from the current conversation, classifies each as avoid or best-practice, writes to rules | -| **File** | `/brewcode:rules path/to/KNOWLEDGE.jsonl` | Parses a KNOWLEDGE.jsonl file, maps entries by type: `t:"X"` to avoid, `t:"V"` to best-practice | -| **Prompt** | `/brewcode:rules path/to/file "your instructions"` | Reads the given file and applies your custom prompt to extract rules from it | -| **List** | `/brewcode:rules list` | Lists all rule files in `.claude/rules/` with entry counts per file | +| Mode | How it activates | What it does | +|------|-----------------|--------------| +| `status` | Default when no other mode is detected | Shows file counts, last-modified, coverage | +| `list` | Explicit only — "list", "show rules", "what rules" | Runs `rules.sh list`, plain file listing | +| `create` | "create", "add", "new rule" in prompt | bc-rules-organizer creates entries from knowledge source | +| `improve` | "improve", "update", "refine" in prompt | bc-rules-organizer refines existing entries | +| `review` | "review", "check", "audit" in prompt | bc-rules-organizer audits rule files for quality | +| `batch` | Multiple sources detected | bc-rules-organizer processes all sources in one pass | + +## Knowledge Sources for Create / Improve + +| Source | Example | +|--------|---------| +| KNOWLEDGE.jsonl path | `/brewcode:rules path/to/KNOWLEDGE.jsonl` — parses `t:"❌"` → avoid, `t:"✅"` → best-practice | +| File path + inline prompt | `/brewcode:rules docs/retro.md "extract SQL anti-patterns"` | +| Session learnings (no path) | `/brewcode:rules capture today's key findings` — extracts 5 most impactful findings as ❌/✅ | ## Examples -### Good Usage - ```bash -# After a debugging session -- capture what you learned +# Open the interactive menu /brewcode:rules -# Import rules from a KNOWLEDGE.jsonl file -/brewcode:rules path/to/KNOWLEDGE.jsonl +# Check the current state of rule files +/brewcode:rules what is the current state of our rules -# Extract SQL-specific rules from a code review document -/brewcode:rules docs/sql-review.md "Extract SQL anti-patterns and best practices" +# Capture session learnings after debugging +/brewcode:rules capture what we learned fixing the auth bug -# Check what rule files exist and how many entries each has +# Import from a KNOWLEDGE.jsonl file +/brewcode:rules path/to/KNOWLEDGE.jsonl add new entries + +# Extract anti-patterns from a review document +/brewcode:rules docs/sql-review.md "extract SQL anti-patterns and best practices" + +# Plain listing of all rule files and entry counts /brewcode:rules list ``` -### Common Mistakes +## Output Files -```bash -# WRONG: Passing a directory instead of a file -/brewcode:rules path/to/ -# FIX: Point to the specific KNOWLEDGE.jsonl file -/brewcode:rules path/to/KNOWLEDGE.jsonl - -# WRONG: Using "list" with extra arguments -/brewcode:rules list some-filter -# FIX: "list" takes no arguments -- it always shows all rule files -/brewcode:rules list - -# WRONG: Expecting global rules to be updated -# The skill ONLY writes to project .claude/rules/, never to ~/.claude/rules/ -``` - -## Output - -Rule files are created or updated in your project's `.claude/rules/` directory: +Rule files are created or updated in `.claude/rules/`: | File | Content | |------|---------| -| `avoid.md` | General anti-patterns (table format: #, Avoid, Instead, Why) | -| `best-practice.md` | General best practices (table format: #, Practice, Context, Source) | -| `{prefix}-avoid.md` | Domain-specific anti-patterns (e.g., `sql-avoid.md`, `test-avoid.md`) | -| `{prefix}-best-practice.md` | Domain-specific practices (e.g., `sql-best-practice.md`) | +| `avoid.md` | General anti-patterns (table: #, Avoid, Instead, Why) | +| `best-practice.md` | General best practices (table: #, Practice, Context, Source) | +| `{prefix}-avoid.md` | Domain-specific anti-patterns, e.g. `sql-avoid.md`, `test-avoid.md` | +| `{prefix}-best-practice.md` | Domain-specific best practices, e.g. `sql-best-practice.md` | -All files use a markdown table format validated by the built-in `rules.sh validate` script. +All files use the markdown table format validated by `rules.sh validate`. -## Deduplication +## Deduplication — 3-Check Protocol -New entries go through a 3-check protocol before being added: +New entries go through three checks before being written: -1. **Within-file similarity** -- entries >70% similar are skipped, 40-70% are merged -2. **Cross-file antonym** -- if an item appears in both avoid and best-practice, only the avoid entry is kept -3. **CLAUDE.md duplicate** -- entries already covered in CLAUDE.md are skipped +1. **Within-file similarity** — entries >70% similar are skipped; 40–70% are merged +2. **Cross-file antonym** — item in both avoid and best-practice → keep the avoid entry only +3. **CLAUDE.md duplicate** — entries already in CLAUDE.md are skipped + +No CLAUDE.md update step: the skill writes rule files only. ## Tips -- Run `/brewcode:rules` at the end of any long debugging or implementation session to capture learnings before they are lost to compaction. -- Use prompt mode with a code review doc or retrospective notes to bulk-import rules from external sources. -- After importing, run `/brewcode:rules list` to verify entry counts and spot unbalanced files. -- Domain-specific rule files (e.g., `test-avoid.md`) keep rules organized and reduce noise for unrelated tasks. +- Run `/brewcode:rules` at the end of any long debugging or implementation session to capture learnings before compaction. +- Use file + prompt mode to bulk-import rules from code review docs or retrospective notes. +- `list` is the fastest way to verify file counts and spot unbalanced rule files. +- Domain-specific files (`test-avoid.md`, `sql-best-practice.md`) reduce noise for unrelated tasks. ## Documentation diff --git a/brewcode/skills/rules/SKILL.md b/brewcode/skills/rules/SKILL.md index 4f2ed1b..6c526c6 100644 --- a/brewcode/skills/rules/SKILL.md +++ b/brewcode/skills/rules/SKILL.md @@ -2,80 +2,131 @@ name: brewcode:rules description: "Syncs KNOWLEDGE.jsonl or session learnings to project rules. Triggers: rules, knowledge sync, extract rules." user-invocable: true -argument-hint: "[list] | [] | [ ]" -allowed-tools: Read, Bash, Task +argument-hint: "" +allowed-tools: [Read, Write, Edit, Glob, Grep, Bash, Task, AskUserQuestion, Skill] model: sonnet --- +# rules Skill + > **TARGET:** Project `.claude/rules/` only. NEVER `~/.claude/rules/` -## Mode Detection +## Constants -**Arguments:** `$ARGUMENTS` +| Const | Value | +|-------|-------| +| ARTIFACT | `rules` | +| SPECIALIST | `bc-rules-organizer` | +| LIST_CMD | `bash "${CLAUDE_SKILL_DIR}/scripts/rules.sh" list` | -| Input | Mode | -|-------|------| -| `list` | List mode | -| ` ` | Prompt mode | -| `` | File mode | -| (empty) | Session mode | +## Step 1 — Input gate -## List Mode +Treat the **entire** user input (`$ARGUMENTS`) as ONE free-form natural-language prompt. +There is NO keyword grammar and NO argument parser — `argument-hint` is only a loose example. -**EXECUTE** and **STOP:** -```bash -bash "${CLAUDE_SKILL_DIR}/scripts/rules.sh" list -``` +- prompt non-empty -> go to **Step 2** +- prompt empty / whitespace-only -> go to **Step 3** -## File / Prompt / Session Mode +## Step 2 — Auto-mode selection -Spawn `bc-rules-organizer` agent via Task tool. +Classify the prompt + recent conversation context into exactly ONE mode: -### Prepare Knowledge by Mode +| Mode | Chosen when prompt signals | +|------|----------------------------| +| `status` | "статус", "что есть", "состояние", health / overview / "show me" (DEFAULT for any "show me" intent) | +| `list` | explicit "список" / "list" / "перечисли" ONLY | +| `create` | "создай" / "create" / "new" / "добавь" / "scaffold" | +| `improve` | "улучши" / "improve" / "refactor" / "fix" / "почини", OR a bare existing name/path | +| `review` | "ревью" / "review" / "validate" / "проверь корректность" | -| Mode | Preparation | -|------|-------------| -| **file** | Read KNOWLEDGE.jsonl; parse `t:"❌"` → avoid, `t:"✅"` → practice | -| **prompt** | Extract `` (first arg), `` (rest) | -| **session** | Extract **5 most impactful** findings: errors, fixes, patterns. Format as `❌` or `✅` | +**Batch flag:** plural form, "все" / "all", or multiple names/paths -> fan-out (one specialist spawn per item). -### Agent Prompt Template +Then **ANNOUNCE the chosen mode (MANDATORY, before any work):** ``` -Update PROJECT .claude/rules/ — NEVER ~/.claude/rules/ - -Plugin templates: $BC_PLUGIN_ROOT/templates/rules/ -Validation: bash "$BC_PLUGIN_ROOT/skills/rules/scripts/rules.sh" validate -Create missing: bash "$BC_PLUGIN_ROOT/skills/rules/scripts/rules.sh" create - -Targets: avoid.md, best-practice.md, {prefix}-avoid.md, {prefix}-best-practice.md - -MODE: {detected mode} -KNOWLEDGE: {prepared from table above} -DEDUP: 3-Check Protocol: - 1. Within-file similarity (>70% skip, 40-70% merge) - 2. Cross-file antonym (avoid↔best-practice — keep avoid only) - 3. CLAUDE.md duplicate (skip if in CLAUDE.md; "CLAUDE.md" forbidden as Source) +Mode: (rules) — chosen because ``` -> `BC_PLUGIN_ROOT` injected by pre-task.mjs hook. +Proceed to **Step 4**. -### Fallback +## Step 3 — No-prompt menu (single AskUserQuestion, scoped + cross-link) -Agent unavailable → error: `bc-rules-organizer not available — install brewcode plugin` +Ask ONE AskUserQuestion. Question: `What do you want to do with rules?` +Options (in this order): + +- `Status (rules)` — **(Recommended)** rich status of this artifact +- `Status (all: agents+rules+skills)` — cross-link: run the collector for all three +- `Create new rules` +- `Improve existing rules` +- `Review rules` +- `List (plain)` +- `Nothing / cancel` + +After the choice: +- `Nothing / cancel` -> stop. +- `create` or `improve` -> ask ONE follow-up AskUserQuestion for the target/description + plus the artifact-specific params (see "Artifact-specific params" below). +- Then ANNOUNCE the mode using the Step 2 format and proceed to **Step 4**. + +## Step 4 — Dispatch + +- `status` -> go to **Step 5**. +- `status (all)` -> go to **Step 5**, running the collector for agents + rules + skills together. +- `list` -> run `LIST_CMD`, print the plain inventory it produces, then STOP (no status assembly). +- `create` -> gather minimal params (Step 3 / artifact-specific), spawn `SPECIALIST` via Task. + Batch -> spawn one `SPECIALIST` per item, ALL in ONE message (parallel). +- `improve` -> resolve target(s), spawn `SPECIALIST` via Task per target (parallel for batch). +- `review` -> spawn `brewcode:reviewer` (two-phase: review -> double-check findings -> report). + +## Step 5 — Real status (NOT a flat list) + +Delegate collection to ONE Explore/Bash subagent, then assemble a rich status (never a bare list): + +- **Inventory by scope:** plugin (BC) / project (`.claude/`) / global (`~/.claude/`) — counts + names + load path. +- **State:** enabled/disabled (toggle markers `_SKILL.md` / `_.md`), model. +- **Overlaps / conflicts:** same-name across scopes (shadowing), duplicate triggers/descriptions, naming collisions. +- **Health flags:** missing README/frontmatter; agents missing `Bash` in `tools:` (macOS search rule); + skills with weak description triggers; rules duplicated in CLAUDE.md. + +For the `Status (all)` menu option: run the SAME collector for agents + rules + skills together. + +## Step 6 — Final formatted output (MANDATORY for every run except `list`) + +``` +# rules [] +## Detection +| Input | menu)"> | +| Mode | | +| Reason | | +| Targets| | +## Result +(create/improve/review: each output path + specialist agent + scope/model) +## Status +(status mode: full table from Step 5; else short "what changed" for touched artifacts) +## Next Steps +(recommendations; ALWAYS remind to run /docs for any created/changed artifact) +``` + +For `status` mode the report **is** the Step 5 status table. + +## Artifact-specific params (create / improve only) + +Note: rules has only an ORGANIZER (bc-rules-organizer), no separate creator — creation is +organizer-driven. For `create`/`improve`: AskUserQuestion for the knowledge source — +(a) KNOWLEDGE.jsonl path (parse t:"❌"->avoid, t:"✅"->practice), (b) inline prompt +( + text), (c) session learnings (extract 5 most impactful findings as ❌/✅). +Spawn SPECIALIST (bc-rules-organizer) with the agent-prompt template: + - Update PROJECT .claude/rules/ — NEVER ~/.claude/rules/ + - Plugin templates: $BC_PLUGIN_ROOT/templates/rules/ + - Validate: bash "$BC_PLUGIN_ROOT/skills/rules/scripts/rules.sh" validate + - Create missing: bash "$BC_PLUGIN_ROOT/skills/rules/scripts/rules.sh" create + - Targets: avoid.md, best-practice.md, {prefix}-avoid.md, {prefix}-best-practice.md + - DEDUP 3-Check: within-file (>70% skip, 40-70% merge); cross-file antonym + (avoid<->best-practice keep avoid only); CLAUDE.md duplicate (skip; "CLAUDE.md" + forbidden as Source). + - BC_PLUGIN_ROOT injected by pre-task.mjs hook. +Fallback if agent unavailable: error "bc-rules-organizer not available — install brewcode plugin". - -## Output - -Forward agent report to user as-is. - -## Error Handling - -| Condition | Action | -|-----------|--------| -| Agent unavailable | Error + install instructions | -| No knowledge found | "No new rules extracted" | -| Plugin not found | STOP + install instructions | diff --git a/brewcode/skills/setup/LICENSE b/brewcode/skills/setup/LICENSE deleted file mode 100644 index b09ce61..0000000 --- a/brewcode/skills/setup/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -MIT License - -Copyright (c) 2025-2026 Maxim Kochetkov (kochetkov-ma) -https://github.com/kochetkov-ma/claude-brewcode - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/brewcode/skills/setup/README.md b/brewcode/skills/setup/README.md deleted file mode 100644 index 8cb29c5..0000000 --- a/brewcode/skills/setup/README.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -auto-sync: enabled -auto-sync-date: 2026-04-01 -auto-sync-type: doc ---- - -# Setup - -Checks prerequisites, then analyzes your project's tech stack, testing framework, database layer, and existing agents to generate tailored templates and a review skill under `.claude/tasks/`. Run this once before using any other brewcode skill (`spec`, `review`). Setup handles all required tooling (brew, coreutils, jq) and optionally sets up grepai for semantic code search. - -## Quick Start - -```bash -/brewcode:setup -``` - -## Prerequisites - -Phase 0 automatically checks and installs the following before project analysis begins: - -| Component | Required | Purpose | -|-----------|----------|---------| -| brew | Yes | Homebrew package manager | -| coreutils+timeout | Yes | GNU timeout for brewcode scripts | -| jq | Yes | JSON processor for hooks | -| ollama + bge-m3 | No | Local embedding model for grepai | -| grepai | No | Semantic code search CLI | - -Required components are installed automatically. Optional components are offered interactively. If all prerequisites are already present, Phase 0 is skipped entirely. - -## Modes - -| Mode | How to trigger | What it does | -|------|---------------|--------------| -| Full auto-detect | `/brewcode:setup` | Scans the project, detects stack, generates all templates and review skill | - -The skill runs these phases: **check prerequisites**, scan, analyze, generate templates, create review skill, and update the global `~/.claude/CLAUDE.md` agents section (with confirmation). - -## Examples - -### Good Usage - -```bash -# First-time setup in a new project -- run before anything else -/brewcode:setup -``` - -```bash -# Setup auto-checks prerequisites -- skips if already installed -/brewcode:setup -# Phase 0: All prerequisites present, skipping installation. -# Phase 1: Scanning project... -``` - -```bash -# After adding new agents to .claude/agents/ -- re-run to pick them up -/brewcode:setup -``` - -```bash -# After switching from JPA to jOOQ -- re-run so templates reflect the new stack -/brewcode:setup -``` - -### Common Mistakes - -```bash -# WRONG: Running /brewcode:spec before setup -# Setup has not run yet, so there are no templates to base the spec on. -/brewcode:spec "Add payment endpoint" - -# FIX: Run setup first, then spec. -/brewcode:setup -/brewcode:spec "Add payment endpoint" -``` - -```bash -# WRONG: Running setup from a different directory than the project root -# The scan script looks at the current working directory for build files and agents. - -# FIX: Open Claude Code at the project root, then run setup. -``` - -## Output - -| File | Location | Purpose | -|------|----------|---------| -| SPEC template | `.claude/tasks/templates/SPEC.md.template` | Specification template for `brewcode:spec` | -| Config | `.claude/tasks/cfg/brewcode.config.json` | Runtime settings (logging level, agent lists) | -| Review skill | `.claude/skills/brewcode-review/SKILL.md` | Tech-specific code review checklist | - -The review skill is generated with checks matched to the detected stack (e.g., Spring DI rules for Java, async patterns for Node.js, error wrapping for Go). - -## Tips - -- Run setup again whenever you change your tech stack, add project agents, or update your test framework. Templates are overwritten; rules are preserved. -- The skill asks for confirmation before modifying `~/.claude/CLAUDE.md`. You can safely decline and still get all project-level templates. -- After setup completes, continue with `spec`. Each downstream skill depends on the templates setup creates. -- Check `.claude/tasks/cfg/brewcode.config.json` to tune logging level and agent injection settings after the initial run. -- Setup handles prerequisites automatically. No need to install anything manually before running it. - -## Documentation - -Full docs: [setup](https://doc-claude.brewcode.app/brewcode/skills/setup/) diff --git a/brewcode/skills/setup/SKILL.md b/brewcode/skills/setup/SKILL.md deleted file mode 100644 index 74c5332..0000000 --- a/brewcode/skills/setup/SKILL.md +++ /dev/null @@ -1,370 +0,0 @@ ---- -name: brewcode:setup -description: "Analyzes project, checks prerequisites, generates adapted brewcode templates. Triggers: setup, brewcode setup." -disable-model-invocation: true -argument-hint: "[universal-template-path]" -allowed-tools: Read, Write, Glob, Grep, Bash, AskUserQuestion -context: fork -model: opus ---- - - - - -## Phase 0: Prerequisites Check - -**Agent:** developer | **Action:** Verify and install required tools - -> Auto-checks prerequisites. If all required components are present, skips to Phase 1 silently. - -### Step 1: State Check - -**EXECUTE** using Bash tool: -```bash -bash "${CLAUDE_SKILL_DIR}/scripts/install.sh" state && echo "✅ state" || echo "❌ state FAILED" -``` - -> **STOP if ❌** — verify install.sh exists in scripts/. - -### Step 2: Evaluate Results - -Parse state output table. Required components: **brew**, **timeout**, **jq**. - -- All required show ✅ -> Skip to Phase 1 (log: "All prerequisites present, skipping installation.") -- Any required show ❌ -> Continue to Step 3 - -### Step 2.5: Load Deferred Tool Schemas - -Call **ToolSearch** with `query: "select:AskUserQuestion"` to load its schema. Required for Claude Code v2.1.107+ where AskUserQuestion is deferred. If ToolSearch fails, continue -- AskUserQuestion may already be loaded. - -### Step 3: Install Required Components - -**EXECUTE** using Bash tool: -```bash -bash "${CLAUDE_SKILL_DIR}/scripts/install.sh" check-timeout && echo "✅ timeout-check" || echo "❌ timeout-check FAILED" -``` - -**If TIMEOUT_EXISTS=false** -> **ASK** (AskUserQuestion): "The `timeout` command is missing. Create symlink to `gtimeout`? This is REQUIRED for brewcode." -Options: "Yes, create" | "Cancel setup" - -> **If cancel** -> STOP: "Setup cancelled. timeout command is required for brewcode." - -**EXECUTE** using Bash tool: -```bash -bash "${CLAUDE_SKILL_DIR}/scripts/install.sh" required && echo "✅ required" || echo "❌ required FAILED" -``` - -> **STOP if ❌** — required components must be installed before continuing. - -If timeout still missing -> **EXECUTE**: `bash "${CLAUDE_SKILL_DIR}/scripts/install.sh" timeout` - -### Step 4: Semantic Search (Optional) - -**If grepai not installed** -> **ASK** (AskUserQuestion): "Install semantic search (grepai)? Enables AI-powered code search (~1.5GB)." -Options: "Yes, install grepai" | "Skip" - -If Yes -> **EXECUTE**: `bash "${CLAUDE_SKILL_DIR}/scripts/install.sh" grepai` - -### Step 5: Summary - -**EXECUTE** using Bash tool: -```bash -bash "${CLAUDE_SKILL_DIR}/scripts/install.sh" summary && echo "✅ summary" || echo "❌ summary FAILED" -``` - ---- - -## Phase 1: Project Structure Analysis - -**Agent:** Explore | **Action:** Scan project and gather intelligence - -> **Context:** BC_PLUGIN_ROOT is available in your context (injected by pre-task.mjs hook). - -**EXECUTE** using Bash tool: -```bash -bash "scripts/setup.sh" scan && echo "✅ scan" || echo "❌ scan FAILED" -``` - -> **STOP if ❌** — check script exists and plugin is installed. - ---- - -## Phase 2: Intelligence Analysis - -**Agent:** Plan | **Action:** Consolidate findings and create adaptation strategy - -Create Adaptation Plan: - -```markdown -# Adaptation Plan - -## Tech Stack -- Language: [Java/Node.js/Python/Go/Rust] -- Framework: [Spring Boot/Express/Django/etc] -- Build: [Maven/Gradle/npm/pip/cargo] - -## Testing -- Framework: [JUnit 5/pytest/Jest/Go testing] -- Assertion: [AssertJ/Hamcrest/Chai/assert] -- Mocking: [Mockito/unittest.mock/Sinon] -- Data: [DBRider/Testcontainers/fixtures] - -## Database -- Type: [PostgreSQL/MySQL/MongoDB/Redis/ClickHouse] -- Access: [JOOQ/JPA/Hibernate/Sequelize/SQLAlchemy] - -## Project Agents -- agent-name: purpose (model) - -## Key Patterns (from CLAUDE.md) -- Pattern 1 -- Pattern 2 -- Pattern 3 - -## Template Adaptations -- Update AGENTS section with project agents -- Add tech-specific constraints -- Customize verification checklists -- Add database-specific final review agent -``` - ---- - -## Phase 3: Template Generation - -**Agent:** developer | **Action:** Sync project templates (SPEC) and rules - -### Create Structure - -**EXECUTE** using Bash tool: -```bash -bash "scripts/setup.sh" structure && echo "✅ structure" || echo "❌ structure FAILED" -``` - -> **STOP if ❌** — verify .claude/tasks directory is writable. - -### Copy/Update Templates - -**EXECUTE** using Bash tool: -```bash -bash "scripts/setup.sh" sync && echo "✅ sync" || echo "❌ sync FAILED" -``` - -> **STOP if ❌** — verify plugin templates exist. -> Templates synced from plugin. Rules created once (never overwritten). Review skill adapted by AI. - ---- - -## Phase 3.5: Copy and Adapt Review Skill - -**Agent:** developer | **Action:** Copy review skill template and adapt for project - -Export project analysis results as environment variables before running the script: -```bash -export DETECTED_TECH="" -export AGENT_COUNT="" -export GROUP_COUNT="" -export MAIN_AGENT="" -export TEST_AGENT="" -export DB_AGENT="" -``` - -**EXECUTE** using Bash tool: -```bash -bash "scripts/setup.sh" review && echo "✅ review" || echo "❌ review FAILED" -``` - -> **STOP if ❌** — verify review template exists in plugin. - -### Adapt Review Skill - -> If you adapt the review skill `description`, keep it <= 120 chars (optimal ~100), single line, what + 3-5 distinct triggers. Some registries truncate long descriptions. - -| Placeholder | Source | Example | -|-------------|--------|---------| -| `{PROJECT_AGENTS_TABLE}` | `.claude/agents/` scan | `\| db_expert \| PostgreSQL \| DB layer \|` | -| `{TECH_SPECIFIC_CHECKS}` | Detected tech stack | See Tech-Specific Checks below | -| `{PROJECT_RULES}` | CLAUDE.md patterns | AssertJ rules, Lombok, logging | -| `{MAIN_AGENT}` | Project agent or `reviewer` | `reviewer` | -| `{TEST_AGENT}` | Project agent or `tester` | `tester` | -| `{DB_AGENT}` | Project agent or `sql_expert` | `db_expert` | -| `{CUSTOM_GROUPS}` | Additional review groups | Security, API validation | -| `{CODEBASE_BLOCKS}` | Detected source patterns | `src/main/**`, `src/test/**` | - -### Tech-Specific Checks Templates - -**Java/Spring:** -| Category | Checks | -|----------|--------| -| DI | Constructor injection, no field injection, @RequiredArgsConstructor | -| Transactions | @Transactional scope, rollback rules, isolation levels | -| Null-safety | Optional usage, @NonNull/@Nullable, null checks | -| N+1 | Eager vs lazy loading, batch fetching, entity graphs | -| Security | @PreAuthorize, input validation, SQL injection | -| Lombok | @Value, @Builder, @Slf4j usage | - -**Node.js/TypeScript:** -| Category | Checks | -|----------|--------| -| Async | Promise handling, unhandled rejections, async/await | -| Types | Strict null checks, type guards, generics | -| Validation | Input sanitization, schema validation (Zod/Joi) | -| Security | XSS prevention, CSRF tokens, helmet.js | -| Imports | ESM vs CJS, barrel exports, circular deps | - -**Python:** -| Category | Checks | -|----------|--------| -| Type hints | Function signatures, return types, generics | -| Exceptions | Specific exception types, context managers | -| Async | asyncio patterns, event loop handling | -| Security | SQL parameterization, input validation | -| Style | PEP8, docstrings, comprehensions | - -**Go:** -| Category | Checks | -|----------|--------| -| Error handling | Error wrapping, sentinel errors, error types | -| Concurrency | Goroutine leaks, channel patterns, sync primitives | -| Memory | Slice capacity, pointer semantics, defer usage | -| Security | SQL injection, input validation | -| Interfaces | Small interfaces, composition | - -### Validation - -**EXECUTE** using Bash tool: -```bash -test -f .claude/skills/brewcode-review/SKILL.md && echo "✅ Review skill created" || echo "❌ Review skill MISSING" -grep -q "Tech-Specific\|tech-specific\|Category.*Checks" .claude/skills/brewcode-review/SKILL.md && echo "✅ Tech checks" || echo "❌ Tech checks MISSING" -``` - -> **STOP if any ❌** — review skill must be created before continuing. - ---- - -## Phase 3.6: Copy Configuration - -**Agent:** developer | **Action:** Copy configuration template for runtime settings - -**EXECUTE** using Bash tool: -```bash -bash "scripts/setup.sh" config && echo "✅ config" || echo "❌ config FAILED" -``` - -> **STOP if ❌** — verify .claude/tasks/cfg directory exists. - -| Setting | Default | Description | -|---------|---------|-------------| -| `logging.level` | info | Hook log verbosity (error/warn/info/debug/trace) | -| `agents.system` | [...] | System agents (excluded from prompt injection) | - -> **Hooks-only architecture:** No external runtime. All context management via Claude Code hooks. - ---- - -## Phase 4: Validation - -**Agent:** developer | **Action:** Verify template structure - -**EXECUTE** using Bash tool: -```bash -bash "scripts/setup.sh" validate && echo "✅ validate" || echo "❌ validate FAILED" -``` - -> **STOP if any ❌** — go back to "Copy Templates" step and fix. - -| Check | Status | -|-------|--------| -| SPEC template | `.claude/tasks/templates/SPEC.md.template` | -| Config file | `.claude/tasks/cfg/brewcode.config.json` | -| Project agents | [N] from `.claude/agents/` | -| Reference Examples | [N] canonical files populated | -| Tech-specific adaptations | Testing framework, DB patterns | -| Review skill | `.claude/skills/brewcode-review/SKILL.md` | - ---- - -## Phase 5: Update Global CLAUDE.md Agents - -**Agent:** developer | **Action:** Update agents section in global CLAUDE.md - -### Step 1: Collect Agents - -**EXECUTE** using Bash tool: -```bash -bash "scripts/setup.sh" agents > /tmp/agents-section.md && cat /tmp/agents-section.md -``` - -> Output = ready-to-insert content. Script collects system + global + plugin agents. -> Internal agents (bc-grepai-configurator) are automatically excluded. - -### Step 2: Analyze Existing CLAUDE.md - -Read `~/.claude/CLAUDE.md`. Find ALL agent-related sections: `## Agents`, `## Agent Selection`, `### Core Agents`, `### Global Utility Agents`, any tables with `Agent | Model | Purpose` columns, any lists of agent names. Identify start/end line boundaries. - -### Step 3: Ask User - -> **Preflight:** Call ToolSearch with `query: "select:AskUserQuestion"` before proceeding. - -**ASK** using AskUserQuestion: "Found agent sections in ~/.claude/CLAUDE.md. Replace with optimized LLM-friendly format?" -Options: "Yes -- replace all agent sections" | "No -- keep current format" - -### Step 4: If YES -- Replace - -> Use content from `/tmp/agents-section.md`. Do not add agents manually -- the script already filters internal agents. - -Using Edit tool: -1. Read `/tmp/agents-section.md` to get exact replacement content -2. Find `## Agents — DELEGATE!` section in `~/.claude/CLAUDE.md` -3. Replace with content from `/tmp/agents-section.md` -4. Preserve `### Global Skills` subsection if it exists (append after agents table) -5. Preserve all non-agent content - -LLM determines section boundaries, not grep. Content comes from script output. - - - ---- - -## Output Format - -```markdown -# Template Adaptation Complete - -## Detection - -| Field | Value | -|-------|-------| -| Arguments | `{received args or empty}` | -| Mode | `full` | - -## Tech Stack - -| Category | Value | -|----------|-------| -| Language | [detected] | -| Framework | [detected] | -| Testing | [framework] | -| Database | [type/access] | -| Project Agents | [N]: `agent1`, `agent2` | - -## Adaptations - -| Section | Changes | -|---------|---------| -| Agents | +[N] project agents | -| Reference Examples | [N] canonical files | -| Phase V | Reviewers for [tech] patterns | -| Final Review | +[db_expert/project agents] | -| Review Skill | Tech-specific checks, project rules | - -## Templates - -**SPEC template:** `.claude/tasks/templates/SPEC.md.template` -**Review skill:** `.claude/skills/brewcode-review/SKILL.md` - -## Usage - -/brewcode:spec "Implement feature X" -/brewcode:review "Check null safety" -``` diff --git a/brewcode/skills/setup/scripts/install.sh b/brewcode/skills/setup/scripts/install.sh deleted file mode 100755 index 28264ed..0000000 --- a/brewcode/skills/setup/scripts/install.sh +++ /dev/null @@ -1,524 +0,0 @@ -#!/bin/bash -set -euo pipefail -# brewcode installer -# Usage: install.sh [options] -# -# Commands: -# state - Check current state of all components -# check-updates - Check for available updates -# check-timeout - Check if timeout command exists -# update-all - Update all outdated components -# required - Install required components (brew, coreutils, jq) -# timeout - Create timeout symlink only -# grepai - Install semantic search (ollama, bge-m3, grepai) -# summary - Show final installation summary - -CMD="${1:-help}" - -# Helper: check ollama service with timeout -ollama_running() { - curl -s --connect-timeout 2 --max-time 5 localhost:11434/api/tags &>/dev/null -} - -# Helper: wait for ollama to start (retry loop) -wait_for_ollama() { - local max_attempts=10 - for i in $(seq 1 $max_attempts); do - if ollama_running; then - return 0 - fi - sleep 1 - done - return 1 -} - -# Helper: log action -if [ -z "${ACTIONS_FILE:-}" ]; then - ACTIONS_FILE=$(mktemp /tmp/ft-install-actions.XXXXXX) - trap 'rm -f "$ACTIONS_FILE"' EXIT -fi -log_action() { - echo "- $1" >> "$ACTIONS_FILE" -} - -# Helper: clear actions at start -clear_actions() { - rm -f "$ACTIONS_FILE" -} - -# Helper: get grepai versions -get_grepai_versions() { - GREPAI_CURRENT="" - GREPAI_LATEST="" - if command -v grepai &>/dev/null; then - GREPAI_CURRENT=$(grepai version 2>&1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || true) - GREPAI_CURRENT="${GREPAI_CURRENT:-unknown}" - fi - if command -v brew &>/dev/null; then - GREPAI_LATEST=$(brew info yoanbernabeu/tap/grepai 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || true) - fi -} - -case "$CMD" in - - state) - clear_actions - echo "=== brewcode Prerequisites ===" - echo "" - echo "| Component | Status | Version | Source | Type |" - echo "|-----------|--------|---------|--------|------|" - - # Required: brew - if command -v brew &>/dev/null; then - VER=$(brew --version 2>&1 | head -1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || true) - VER="${VER:-unknown}" - echo "| brew | ✅ | $VER | - | required |" - else - echo "| brew | ❌ missing | - | - | required |" - fi - - # Required: timeout (coreutils) - if command -v timeout &>/dev/null; then - VER=$(timeout --version 2>&1 | head -1 | grep -oE '[0-9]+\.[0-9]+' | head -1 || true) - VER="${VER:-unknown}" - TIMEOUT_PATH=$(command -v timeout) - if [ -L "$TIMEOUT_PATH" ]; then - echo "| timeout | ✅ | $VER | symlink | required |" - elif brew list coreutils &>/dev/null 2>&1; then - echo "| timeout | ✅ | $VER | brew | required |" - else - echo "| timeout | ✅ | $VER | system | required |" - fi - else - echo "| timeout | ❌ missing | - | - | required |" - fi - - # Required: jq - if command -v jq &>/dev/null; then - VER=$(jq --version 2>&1) - VER="${VER:-unknown}" - if brew list jq &>/dev/null 2>&1; then - echo "| jq | ✅ | $VER | brew | required |" - else - echo "| jq | ✅ | $VER | system | required |" - fi - else - echo "| jq | ❌ missing | - | - | required |" - fi - - # Optional: ollama - if command -v ollama &>/dev/null; then - VER=$(ollama --version 2>&1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || true) - VER="${VER:-unknown}" - SRC=$(brew list ollama &>/dev/null 2>&1 && echo "brew" || echo "system") - if ollama_running; then - echo "| ollama | ✅ running | $VER | $SRC | optional |" - else - echo "| ollama | ⚠️ stopped | $VER | $SRC | optional |" - fi - else - echo "| ollama | - | not installed | - | optional |" - fi - - # Optional: bge-m3 - if command -v ollama &>/dev/null && ollama_running && ollama list 2>/dev/null | grep -q bge-m3; then - echo "| bge-m3 | ✅ | installed | ollama | optional |" - elif command -v ollama &>/dev/null && ! ollama_running; then - echo "| bge-m3 | ? | ollama stopped | - | optional |" - else - echo "| bge-m3 | - | not installed | - | optional |" - fi - - # Optional: grepai - get_grepai_versions - if [ -n "$GREPAI_CURRENT" ]; then - SRC=$(brew list yoanbernabeu/tap/grepai &>/dev/null 2>&1 && echo "brew" || echo "system") - if [ -n "$GREPAI_LATEST" ] && [ "$GREPAI_CURRENT" != "$GREPAI_LATEST" ]; then - echo "| grepai | ⚠️ outdated | $GREPAI_CURRENT → $GREPAI_LATEST | $SRC | optional |" - else - echo "| grepai | ✅ | $GREPAI_CURRENT | $SRC | optional |" - fi - else - echo "| grepai | - | not installed | - | optional |" - fi - ;; - - check-updates) - if ! command -v brew &>/dev/null; then - echo "UPDATES_AVAILABLE=false" - echo "NOTE=brew not installed" - exit 0 - fi - - # Update brew cache first - echo "BREW_CACHE=updating" - brew update --quiet 2>/dev/null && echo "BREW_CACHE=updated" || echo "BREW_CACHE=failed" - - UPDATES="" - NOTES="" - - # Check coreutils (timeout) - only if brew-managed - if brew list coreutils &>/dev/null; then - COREUTILS_CURRENT=$(timeout --version 2>&1 | head -1 | grep -oE '[0-9]+\.[0-9]+' | head -1 || true) - COREUTILS_LATEST=$(brew info coreutils 2>/dev/null | grep -oE '[0-9]+\.[0-9]+' | head -1 || true) - if [ -n "$COREUTILS_CURRENT" ] && [ -n "$COREUTILS_LATEST" ] && [ "$COREUTILS_CURRENT" != "$COREUTILS_LATEST" ]; then - UPDATES="${UPDATES:+$UPDATES }coreutils($COREUTILS_CURRENT→$COREUTILS_LATEST)" - fi - fi - - # Check jq - only if brew-managed - if brew list jq &>/dev/null; then - JQ_CURRENT=$(jq --version 2>&1 | grep -oE '[0-9]+\.[0-9]+(\.[0-9]+)?' | head -1 || true) - JQ_LATEST=$(brew info jq 2>/dev/null | grep -oE '[0-9]+\.[0-9]+' | head -1 || true) - if [ -n "$JQ_CURRENT" ] && [ -n "$JQ_LATEST" ] && [ "$JQ_CURRENT" != "$JQ_LATEST" ]; then - UPDATES="${UPDATES:+$UPDATES }jq($JQ_CURRENT→$JQ_LATEST)" - fi - elif command -v jq &>/dev/null; then - # jq exists but not brew-managed - note it - JQ_PATH=$(command -v jq) - JQ_CURRENT=$(jq --version 2>&1 | grep -oE '[0-9]+\.[0-9]+(\.[0-9]+)?' | head -1 || true) - NOTES="${NOTES:+$NOTES; }jq($JQ_CURRENT) at $JQ_PATH (not brew-managed)" - fi - - # Check grepai - get_grepai_versions - if [ -n "$GREPAI_CURRENT" ] && [ -n "$GREPAI_LATEST" ] && [ "$GREPAI_CURRENT" != "$GREPAI_LATEST" ]; then - UPDATES="${UPDATES:+$UPDATES }grepai($GREPAI_CURRENT→$GREPAI_LATEST)" - fi - - # Trim whitespace - UPDATES="${UPDATES## }" - UPDATES="${UPDATES%% }" - - if [ -n "$UPDATES" ]; then - echo "UPDATES_AVAILABLE=true" - echo "UPDATES=$UPDATES" - else - echo "UPDATES_AVAILABLE=false" - fi - [ -n "$NOTES" ] && echo "NOTES=$NOTES" - ;; - - check-timeout) - if command -v timeout &>/dev/null; then - echo "TIMEOUT_EXISTS=true" - echo "VERSION=$(timeout --version 2>&1 | head -1)" - TIMEOUT_PATH=$(command -v timeout) - if [ -L "$TIMEOUT_PATH" ]; then - SYMLINK_TARGET=$(readlink "$TIMEOUT_PATH") - echo "SYMLINK=$TIMEOUT_PATH → $SYMLINK_TARGET" - else - echo "PATH=$TIMEOUT_PATH" - fi - else - echo "TIMEOUT_EXISTS=false" - if command -v gtimeout &>/dev/null; then - echo "GTIMEOUT_EXISTS=true" - echo "GTIMEOUT_PATH=$(command -v gtimeout)" - echo "HINT=Create symlink: ln -sf \$(brew --prefix)/opt/coreutils/libexec/gnubin/timeout \$(brew --prefix)/bin/timeout" - else - echo "GTIMEOUT_EXISTS=false" - fi - fi - ;; - - update-all) - echo "=== Updating Components ===" - - if ! command -v brew &>/dev/null; then - echo "❌ brew not installed" - exit 1 - fi - - # Update coreutils - if brew list coreutils &>/dev/null; then - OLD_VER=$(timeout --version 2>&1 | head -1 | grep -oE '[0-9]+\.[0-9]+' | head -1 || true) - if brew upgrade coreutils 2>&1 | grep -q "Upgrading"; then - NEW_VER=$(timeout --version 2>&1 | head -1 | grep -oE '[0-9]+\.[0-9]+' | head -1 || true) - echo "✅ coreutils: updated" - log_action "Updated coreutils: $OLD_VER → $NEW_VER" - else - echo "⏭️ coreutils: already latest" - fi - fi - - # Update jq - if brew list jq &>/dev/null; then - OLD_VER=$(jq --version 2>&1 | grep -oE '[0-9]+\.[0-9]+' | head -1 || true) - if brew upgrade jq 2>&1 | grep -q "Upgrading"; then - NEW_VER=$(jq --version 2>&1 | grep -oE '[0-9]+\.[0-9]+' | head -1 || true) - echo "✅ jq: updated" - log_action "Updated jq: $OLD_VER → $NEW_VER" - else - echo "⏭️ jq: already latest" - fi - fi - - # Update grepai - get_grepai_versions - if [ -n "$GREPAI_CURRENT" ] && [ -n "$GREPAI_LATEST" ] && [ "$GREPAI_CURRENT" != "$GREPAI_LATEST" ]; then - echo "Updating grepai: $GREPAI_CURRENT → $GREPAI_LATEST" - if brew upgrade yoanbernabeu/tap/grepai; then - echo "✅ grepai: updated" - log_action "Updated grepai: $GREPAI_CURRENT → $GREPAI_LATEST" - else - echo "⚠️ grepai: update failed" - fi - elif [ -n "$GREPAI_CURRENT" ]; then - echo "⏭️ grepai: already latest ($GREPAI_CURRENT)" - fi - - echo "✅ Updates complete" - ;; - - required) - echo "=== Installing Required Components ===" - - # Homebrew - echo "" - echo "--- Homebrew ---" - if ! command -v brew &>/dev/null; then - echo "Installing Homebrew..." - NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" # nosemgrep: curl-pipe-bash - eval "$(/opt/homebrew/bin/brew shellenv)" 2>/dev/null || eval "$(/usr/local/bin/brew shellenv)" 2>/dev/null || true - command -v brew &>/dev/null && { echo "✅ brew: installed"; log_action "Installed Homebrew"; } || { echo "❌ brew: FAILED"; exit 1; } - else - echo "✅ brew: $(brew --version | head -1)" - fi - - # coreutils - echo "" - echo "--- coreutils ---" - if ! brew list coreutils &>/dev/null; then - echo "Installing coreutils..." - brew install coreutils - echo "✅ coreutils: installed" - log_action "Installed coreutils" - else - echo "✅ coreutils: already installed" - fi - - # jq - echo "" - echo "--- jq ---" - if ! command -v jq &>/dev/null; then - echo "Installing jq..." - brew install jq - command -v jq &>/dev/null && { echo "✅ jq: installed"; log_action "Installed jq"; } || { echo "❌ jq: FAILED"; exit 1; } - else - echo "✅ jq: $(jq --version)" - fi - - echo "" - echo "=== Required Components Done ===" - ;; - - timeout) - echo "=== Creating timeout symlink ===" - if command -v timeout &>/dev/null; then - echo "✅ timeout: already exists" - exit 0 - fi - if ! brew list coreutils &>/dev/null; then - echo "Installing coreutils..." - brew install coreutils - log_action "Installed coreutils" - fi - BREW_BIN=$(brew --prefix)/bin - GTIMEOUT_PATH="$(brew --prefix)/opt/coreutils/libexec/gnubin/timeout" - - # Safety check: don't overwrite regular file - if [ -e "$BREW_BIN/timeout" ] && [ ! -L "$BREW_BIN/timeout" ]; then - echo "⚠️ timeout: file exists (not symlink), skipping" - exit 1 - fi - - if [ -f "$GTIMEOUT_PATH" ]; then - ln -sf "$GTIMEOUT_PATH" "$BREW_BIN/timeout" - echo "✅ timeout: symlink created" - log_action "Created timeout symlink → gtimeout" - else - echo "❌ timeout: gtimeout not found at $GTIMEOUT_PATH" - exit 1 - fi - ;; - - grepai) - echo "=== Installing Semantic Search ===" - - # ollama - echo "" - echo "--- ollama ---" - if ! command -v ollama &>/dev/null; then - echo "Installing ollama..." - brew install ollama - command -v ollama &>/dev/null && { echo "✅ ollama: installed"; log_action "Installed ollama"; } || { echo "❌ ollama: FAILED"; exit 1; } - else - echo "✅ ollama: $(ollama --version 2>&1 | head -1)" - fi - - # Start ollama with retry loop - if command -v ollama &>/dev/null && ! ollama_running; then - echo "Starting ollama service..." - brew services start ollama 2>/dev/null || nohup ollama serve >/dev/null 2>&1 & - disown 2>/dev/null || true - if wait_for_ollama; then - echo "✅ ollama: running" - log_action "Started ollama service" - else - echo "⚠️ ollama: failed to start, run manually: ollama serve" - fi - elif ollama_running; then - echo "✅ ollama: already running" - fi - - # bge-m3 - echo "" - echo "--- bge-m3 ---" - if command -v ollama &>/dev/null && ollama_running; then - if ! ollama list 2>/dev/null | grep -q bge-m3; then - echo "Pulling bge-m3 model (~1.2GB)..." - ollama pull bge-m3 - echo "✅ bge-m3: installed" - log_action "Pulled bge-m3 embedding model" - else - echo "✅ bge-m3: already installed" - fi - else - echo "⚠️ bge-m3: skipped (ollama not running)" - fi - - # grepai - echo "" - echo "--- grepai ---" - get_grepai_versions - if [ -z "$GREPAI_CURRENT" ]; then - echo "Installing grepai..." - brew install yoanbernabeu/tap/grepai - command -v grepai &>/dev/null && { echo "✅ grepai: installed"; log_action "Installed grepai CLI"; } || { echo "❌ grepai: FAILED"; exit 1; } - elif [ -n "$GREPAI_LATEST" ] && [ "$GREPAI_CURRENT" != "$GREPAI_LATEST" ]; then - echo "Updating grepai: $GREPAI_CURRENT → $GREPAI_LATEST" - if brew upgrade yoanbernabeu/tap/grepai; then - echo "✅ grepai: updated" - log_action "Updated grepai: $GREPAI_CURRENT → $GREPAI_LATEST" - else - echo "⚠️ grepai: update failed" - fi - else - echo "✅ grepai: $GREPAI_CURRENT (latest)" - fi - - echo "" - echo "=== Semantic Search Done ===" - ;; - - summary) - # Optional: read actions from env or file - if [ -z "${ACTIONS_FILE:-}" ]; then - ACTIONS_FILE=$(mktemp /tmp/ft-install-actions.XXXXXX) - trap 'rm -f "$ACTIONS_FILE"' EXIT - fi - - echo "" - echo "=== Installation Summary ===" - echo "" - echo "| Component | Status | Installed | Latest | Source |" - echo "|-----------|--------|-----------|--------|--------|" - - # brew - if command -v brew &>/dev/null; then - VER=$(brew --version 2>&1 | head -1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || true) - echo "| brew | ✅ | ${VER:-?} | - | - |" - else - echo "| brew | ❌ | - | - | - |" - fi - - # timeout (coreutils) - if command -v timeout &>/dev/null; then - VER=$(timeout --version 2>&1 | head -1 | grep -oE '[0-9]+\.[0-9]+' | head -1 || true) - LATEST=$(brew info coreutils 2>/dev/null | grep -oE '[0-9]+\.[0-9]+' | head -1 || true) - TIMEOUT_PATH=$(command -v timeout) - if [ -L "$TIMEOUT_PATH" ]; then - SRC="symlink" - elif brew list coreutils &>/dev/null 2>&1; then - SRC="brew" - else - SRC="system" - fi - echo "| timeout | ✅ | ${VER:-?} | ${LATEST:-?} | $SRC |" - else - echo "| timeout | ❌ | - | - | - |" - fi - - # jq - if command -v jq &>/dev/null; then - VER=$(jq --version 2>&1 | grep -oE '[0-9]+\.[0-9]+(\.[0-9]+)?' | head -1 || true) - LATEST=$(brew info jq 2>/dev/null | grep -oE '[0-9]+\.[0-9]+' | head -1 || true) - if brew list jq &>/dev/null 2>&1; then - SRC="brew" - else - SRC="system" - fi - echo "| jq | ✅ | ${VER:-?} | ${LATEST:-?} | $SRC |" - else - echo "| jq | ❌ | - | - | - |" - fi - - # ollama - if command -v ollama &>/dev/null; then - VER=$(ollama --version 2>&1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || true) - LATEST=$(brew info ollama 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || true) - SRC=$(brew list ollama &>/dev/null 2>&1 && echo "brew" || echo "system") - if ollama_running; then - echo "| ollama | ✅ running | ${VER:-?} | ${LATEST:-?} | $SRC |" - else - echo "| ollama | ⚠️ stopped | ${VER:-?} | ${LATEST:-?} | $SRC |" - fi - else - echo "| ollama | ⏭️ skipped | - | - | - |" - fi - - # bge-m3 - if command -v ollama &>/dev/null && ollama_running && ollama list 2>/dev/null | grep -q bge-m3; then - echo "| bge-m3 | ✅ | installed | - | ollama |" - elif command -v ollama &>/dev/null && ! ollama_running; then - echo "| bge-m3 | ? | unknown | - | - |" - else - echo "| bge-m3 | ⏭️ skipped | - | - | - |" - fi - - # grepai - get_grepai_versions - if [ -n "$GREPAI_CURRENT" ]; then - SRC=$(brew list yoanbernabeu/tap/grepai &>/dev/null 2>&1 && echo "brew" || echo "system") - echo "| grepai | ✅ | $GREPAI_CURRENT | ${GREPAI_LATEST:-?} | $SRC |" - else - echo "| grepai | ⏭️ skipped | - | - | - |" - fi - - # Actions performed - echo "" - echo "## Actions Performed" - if [ -f "$ACTIONS_FILE" ]; then - cat "$ACTIONS_FILE" - rm -f "$ACTIONS_FILE" - else - echo "- No actions recorded (all components were already installed)" - fi - ;; - - help|*) - echo "Usage: install.sh " - echo "" - echo "Commands:" - echo " state Check current state of all components" - echo " check-updates Check for available updates" - echo " check-timeout Check if timeout command exists" - echo " update-all Update all outdated components" - echo " required Install required (brew, coreutils, jq)" - echo " timeout Create timeout symlink only" - echo " grepai Install semantic search (ollama, bge-m3, grepai)" - echo " summary Show final installation summary" - ;; - -esac diff --git a/brewcode/skills/setup/scripts/setup.sh b/brewcode/skills/setup/scripts/setup.sh deleted file mode 100755 index b24f2cd..0000000 --- a/brewcode/skills/setup/scripts/setup.sh +++ /dev/null @@ -1,322 +0,0 @@ -#!/bin/bash -# Brewcode Setup Script -# Multi-function script for /brewcode:setup skill -# Usage: setup.sh [options] -# -# Modes: -# scan - Scan project structure (Phase 1) -# structure - Create directories (Phase 3) -# sync - Sync templates from plugin (Phase 3) -# review - Copy review skill template (Phase 3.5) -# config - Copy config file (Phase 3.6) -# validate - Validation checks (Phase 4) -# all - Run all phases - -set -euo pipefail - -MODE="${1:-all}" - -# Self-location: derive plugin root from script path -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -# Path: scripts/setup.sh -> skills/setup/scripts -> skills/setup -> skills -> PLUGIN_ROOT -PLUGIN_ROOT="$(dirname "$(dirname "$(dirname "$SCRIPT_DIR")")")" -PLUGIN_TEMPLATES="$PLUGIN_ROOT/templates" -PLUGIN_SKILLS="$PLUGIN_ROOT/skills" -SETUP_TEMPLATES="$PLUGIN_ROOT/skills/setup/templates" -SETUP_REFERENCES="$PLUGIN_ROOT/skills/setup/references" - -# Validate plugin structure -validate_plugin() { - if [ ! -d "$PLUGIN_ROOT" ]; then - echo "❌ Plugin root not found: $PLUGIN_ROOT" - exit 1 - fi - if [ ! -d "$SETUP_TEMPLATES" ]; then - echo "❌ Setup templates not found: $SETUP_TEMPLATES" - exit 1 - fi -} - -# Phase 1: Scan project structure -scan_project() { - echo "=== Phase 1: Project Scan ===" - echo "" - - echo "--- Build Files ---" - find . -maxdepth 3 -type f \( \ - -name "package.json" -o \ - -name "pom.xml" -o \ - -name "build.gradle" -o \ - -name "build.gradle.kts" -o \ - -name "requirements.txt" -o \ - -name "Pipfile" -o \ - -name "Cargo.toml" -o \ - -name "go.mod" -o \ - -name "composer.json" \ - \) 2>/dev/null || echo "(none found)" - - echo "" - echo "--- Project Agents ---" - find .claude/agents -type f -name "*.md" 2>/dev/null | sort || echo "(none)" - - echo "" - echo "--- Test Directories ---" - find . -type d \( -name "test" -o -name "tests" -o -name "__tests__" \) 2>/dev/null | head -20 || echo "(none)" - - echo "" - echo "--- Sample Test Files ---" - find . -type f \( \ - -name "*Test.java" -o \ - -name "*Test.kt" -o \ - -name "*.test.js" -o \ - -name "*.test.ts" -o \ - -name "*_test.py" -o \ - -name "*_test.go" \ - \) 2>/dev/null | head -10 || echo "(none)" - - echo "" - echo "--- CLAUDE.md ---" - test -f ./CLAUDE.md && echo "✅ CLAUDE.md exists" || echo "⚠️ No CLAUDE.md" - test -f ./.claude/CLAUDE.md && echo "✅ .claude/CLAUDE.md exists" || echo "⚠️ No .claude/CLAUDE.md" -} - -# Phase 3: Create directory structure -create_structure() { - echo "=== Phase 3: Create Structure ===" - mkdir -p .claude/tasks/templates .claude/rules - echo "✅ Created .claude/tasks/templates/" - echo "✅ Created .claude/rules/" -} - -# Phase 3: Sync templates from plugin -sync_templates() { - echo "=== Phase 3: Sync Templates ===" - validate_plugin - - sync_template() { - local src="$1" dst="$2" - if [ ! -f "$dst" ]; then - cp "$src" "$dst" && echo "✅ Created: $dst" - elif ! diff -q "$src" "$dst" >/dev/null 2>&1; then - cp "$src" "$dst" && echo "🔄 Updated: $dst" - else - echo "⏭️ Unchanged: $dst" - fi - } - - sync_template "$SETUP_TEMPLATES/SPEC.md.template" ".claude/tasks/templates/SPEC.md.template" - - # grepai-first: always sync (plugin-managed rule) - if [ -f "$PLUGIN_TEMPLATES/rules/grepai-first.md.template" ]; then - sync_template "$PLUGIN_TEMPLATES/rules/grepai-first.md.template" ".claude/rules/grepai-first.md" - fi - - # Rules: create only if missing (never overwrite user rules) - if [ ! -f ".claude/rules/avoid.md" ]; then - cp "$PLUGIN_TEMPLATES/rules/avoid.md.template" .claude/rules/avoid.md - echo "✅ Created: .claude/rules/avoid.md" - else - echo "⏭️ Preserved: .claude/rules/avoid.md (user rules)" - fi - - if [ ! -f ".claude/rules/best-practice.md" ]; then - cp "$PLUGIN_TEMPLATES/rules/best-practice.md.template" .claude/rules/best-practice.md - echo "✅ Created: .claude/rules/best-practice.md" - else - echo "⏭️ Preserved: .claude/rules/best-practice.md (user rules)" - fi -} - -# Phase 3.5: Copy review skill template -copy_review_skill() { - echo "=== Phase 3.5: Review Skill ===" - validate_plugin - - mkdir -p .claude/skills/brewcode-review - - if [ -f "$PLUGIN_TEMPLATES/skills/review/SKILL.md.template" ]; then - # Constraint: env vars must be single-line (no newlines). sed processes line-by-line, - # so a newline in PROJECT_AGENTS_TABLE or CODEBASE_BLOCKS will silently truncate the substitution. - _sep=$'\x01' - sed \ - -e "s${_sep}{ADAPTATION_TIMESTAMP}${_sep}$(date -u +%Y-%m-%dT%H:%M:%SZ)${_sep}g" \ - -e "s${_sep}{DETECTED_TECH}${_sep}${DETECTED_TECH:-unknown}${_sep}g" \ - -e "s${_sep}{AGENT_COUNT}${_sep}${AGENT_COUNT:-0}${_sep}g" \ - -e "s${_sep}{GROUP_COUNT}${_sep}${GROUP_COUNT:-3}${_sep}g" \ - -e "s${_sep}{MAIN_AGENT}${_sep}${MAIN_AGENT:-reviewer}${_sep}g" \ - -e "s${_sep}{TEST_AGENT}${_sep}${TEST_AGENT:-tester}${_sep}g" \ - -e "s${_sep}{DB_AGENT}${_sep}${DB_AGENT:-sql_expert}${_sep}g" \ - -e "s${_sep}{PROJECT_AGENTS_TABLE}${_sep}${PROJECT_AGENTS_TABLE:-| reviewer | General | All layers |}${_sep}g" \ - -e "s${_sep}{TECH_SPECIFIC_CHECKS}${_sep}${TECH_SPECIFIC_CHECKS:-General code quality checks}${_sep}g" \ - -e "s${_sep}{PROJECT_RULES}${_sep}${PROJECT_RULES:-Standard coding conventions}${_sep}g" \ - -e "s${_sep}{CUSTOM_GROUPS}${_sep}${CUSTOM_GROUPS:-}${_sep}g" \ - -e "s${_sep}{CODEBASE_BLOCKS}${_sep}${CODEBASE_BLOCKS:-src/**}${_sep}g" \ - -e "s${_sep}{REVIEW_PROMPT}${_sep}${REVIEW_PROMPT:-Review for quality and correctness}${_sep}g" \ - "$PLUGIN_TEMPLATES/skills/review/SKILL.md.template" \ - > .claude/skills/brewcode-review/SKILL.md - _runtime_placeholders='CONFIRMED_FINDINGS_JSON|REJECTED_FINDINGS_JSON|DISCARDED_FINDINGS_JSON|FILE_LIST|CRITIC_MISSED_FINDINGS_JSON|CRITIC_CHALLENGES_JSON|CRITIC_BLIND_SPOTS|TOTAL|BLOCKERS|CRITICAL|MAJOR|N|P0_COUNT|ACCEPTED|COUNT|TIMESTAMP|NAME' - _unresolved=$(grep -oE '\{[A-Z_]+\}' .claude/skills/brewcode-review/SKILL.md | sort -u | grep -vE "^\{(${_runtime_placeholders})\}$" || true) - if [ -n "$_unresolved" ]; then - echo "⚠️ WARNING: unresolved setup-time placeholders remain in brewcode-review/SKILL.md" - echo "$_unresolved" - fi - echo "✅ brewcode-review/SKILL.md generated" - else - echo "❌ Template not found: $PLUGIN_TEMPLATES/skills/review/SKILL.md.template" - exit 1 - fi - - # Copy references - if [ -d "$PLUGIN_TEMPLATES/skills/review/references" ]; then - mkdir -p .claude/skills/brewcode-review/references - cp "$PLUGIN_TEMPLATES/skills/review/references/"*.md .claude/skills/brewcode-review/references/ - echo "✅ Copied: references/ (agent-prompt.md, report-template.md)" - fi - - # Verify - test -f .claude/skills/brewcode-review/SKILL.md && echo "✅ Review skill created" || echo "❌ Review skill MISSING" -} - -# Phase 3.6: Copy config -copy_config() { - echo "=== Phase 3.6: Config ===" - validate_plugin - - TEMPLATE="$SETUP_TEMPLATES/brewcode.config.json.template" - PROJECT_CFG=".claude/tasks/cfg/brewcode.config.json" - - mkdir -p .claude/tasks/cfg - - if [ ! -f "$PROJECT_CFG" ]; then - cp "$TEMPLATE" "$PROJECT_CFG" - echo "✅ Config created: $PROJECT_CFG" - else - MERGED=$(jq -s '.[0] * .[1]' "$TEMPLATE" "$PROJECT_CFG" 2>/dev/null) - if [ -n "$MERGED" ]; then - MERGED_HASH=$(echo "$MERGED" | jq -S . | shasum -a 256 | cut -d' ' -f1) - PROJECT_HASH=$(jq -S . "$PROJECT_CFG" 2>/dev/null | shasum -a 256 | cut -d' ' -f1 || true) - if [ "$MERGED_HASH" != "$PROJECT_HASH" ]; then - cp "$PROJECT_CFG" "$PROJECT_CFG.bak" - echo "$MERGED" | jq -S . > "$PROJECT_CFG" - echo "🔄 Config merged (new keys added, user values preserved): $PROJECT_CFG" - echo " Backup: $PROJECT_CFG.bak" - else - echo "⏭️ Config unchanged: $PROJECT_CFG" - fi - else - echo "⚠️ Config merge failed (jq error), keeping existing: $PROJECT_CFG" - fi - fi -} - -# Collect agents for CLAUDE.md -collect_agents() { - echo "=== Collect Agents ===" - echo "" - - # Header - cat << 'EOF' -## Agents — DELEGATE! - -> **MANAGER:** Delegate via Task tool. Never implement directly. - -| Name | Scope | Purpose | -|------|-------|---------| -| Explore | system | Find files, search code | -| Plan | system | Design implementation | -| general-purpose | system | Multi-step research | -EOF - - # Global agents from ~/.claude/agents/ - if [ -d "$HOME/.claude/agents" ]; then - for f in "$HOME/.claude/agents"/*.md; do - [ -f "$f" ] || continue - name=$(grep "^name:" "$f" 2>/dev/null | head -1 | sed 's/^name: *//' | tr -d '"' | xargs || true) - desc=$(grep "^description:" "$f" 2>/dev/null | head -1 | sed 's/^description: *//' | tr -d '"' || true) - # Truncate to 5 words max - purpose=$(echo "$desc" | awk '{for(i=1;i<=5&&i<=NF;i++) printf "%s ", $i}' | xargs) - [ -n "$name" ] && echo "| $name | global | $purpose |" - done - fi - - # Plugin agents from PLUGIN_ROOT/agents/ (excluding internal agents) - # Internal agents (bc-grepai-configurator) are not listed - # because they are only called by the plugin itself, not by users - INTERNAL_AGENTS="bc-grepai-configurator" - if [ -d "$PLUGIN_ROOT/agents" ]; then - for f in "$PLUGIN_ROOT/agents"/*.md; do - [ -f "$f" ] || continue - name=$(grep "^name:" "$f" 2>/dev/null | head -1 | sed 's/^name: *//' | tr -d '"' | xargs || true) - # Skip internal agents - echo "$INTERNAL_AGENTS" | grep -qw "$name" && continue - desc=$(grep "^description:" "$f" 2>/dev/null | head -1 | sed 's/^description: *//' | tr -d '"' || true) - purpose=$(echo "$desc" | awk '{for(i=1;i<=5&&i<=NF;i++) printf "%s ", $i}' | xargs) - [ -n "$name" ] && echo "| $name | plugin | $purpose |" - done - fi -} - -# Phase 4: Validation -validate_setup() { - echo "=== Phase 4: Validation ===" - ERRORS=0 - - test -f .claude/tasks/templates/SPEC.md.template && echo "✅ SPEC template" || { echo "❌ SPEC template MISSING"; ERRORS=$((ERRORS+1)); } - test -f .claude/rules/avoid.md && echo "✅ avoid.md rules" || { echo "❌ avoid.md MISSING"; ERRORS=$((ERRORS+1)); } - test -f .claude/rules/best-practice.md && echo "✅ best-practice.md rules" || { echo "❌ best-practice.md MISSING"; ERRORS=$((ERRORS+1)); } - test -f .claude/tasks/cfg/brewcode.config.json && echo "✅ Config file" || echo "⚠️ Config MISSING (optional)" - - exit $ERRORS -} - -# Main dispatch -case "$MODE" in - scan) - scan_project - ;; - structure) - create_structure - ;; - sync) - sync_templates - ;; - review) - copy_review_skill - ;; - config) - copy_config - ;; - validate) - validate_setup - ;; - agents) - collect_agents - ;; - all) - scan_project - echo "" - create_structure - echo "" - sync_templates - echo "" - copy_review_skill - echo "" - copy_config - echo "" - validate_setup - ;; - *) - echo "Usage: setup.sh " - echo "" - echo "Modes:" - echo " scan - Scan project structure" - echo " structure - Create directories" - echo " sync - Sync templates from plugin" - echo " review - Copy review skill template" - echo " config - Copy config file" - echo " validate - Validation checks" - echo " agents - Collect agents for CLAUDE.md" - echo " all - Run all phases" - exit 1 - ;; -esac diff --git a/brewcode/skills/setup/templates/SPEC.md.template b/brewcode/skills/setup/templates/SPEC.md.template deleted file mode 100644 index 9046d7e..0000000 --- a/brewcode/skills/setup/templates/SPEC.md.template +++ /dev/null @@ -1,45 +0,0 @@ -# {NAME} -> {TIMESTAMP} - -## Goal -{GOAL} - -## Scope - -| In | Out | -|----|-----| -| {IN_SCOPE} | {OUT_OF_SCOPE} | - -## Original Requirements -{FULL_REQUIREMENTS} - -## User Q&A -| # | Question | Answer | -|---|----------|--------| - -## Analysis -### Architecture -{ARCHITECTURE_ANALYSIS} - -### Data & State -{DATA_STATE_ANALYSIS} - -### Impact -| Area | Files | Change | -|------|-------|--------| - -## Context Files -| ID | File | Purpose | -|----|------|---------| - -## Risks -| Risk | Impact | Mitigation | -|------|--------|------------| - -## Decisions -| Decision | Rationale | -|----------|-----------| - -## Research -| Area | Agent | Key Findings | -|------|-------|--------------| diff --git a/brewcode/skills/setup/templates/brewcode.config.json.template b/brewcode/skills/setup/templates/brewcode.config.json.template deleted file mode 100644 index c9678de..0000000 --- a/brewcode/skills/setup/templates/brewcode.config.json.template +++ /dev/null @@ -1,24 +0,0 @@ -{ - "logging": { - "level": "info" - }, - "agents": { - "system": [ - "bd-auto-sync-processor", - "Explore", "Plan", "Bash", "general-purpose", - "claude-code-guide", "skill-creator", "agent-creator", - "text-optimizer", "statusline-setup" - ] - }, - "constraints": { - "enabled": true - }, - "autoSync": { - "intervalDays": 7, - "retention": { - "maxEntries": 200 - }, - "optimize": false, - "parallelAgents": 5 - } -} diff --git a/brewcode/skills/skills/README.md b/brewcode/skills/skills/README.md index bec09ca..25ff291 100644 --- a/brewcode/skills/skills/README.md +++ b/brewcode/skills/skills/README.md @@ -6,144 +6,110 @@ auto-sync-type: doc # Skills -Manage Claude Code skills -- list installed skills, improve existing ones via the skill-creator agent, or create new skills from a prompt or spec file with research-driven generation. +Manages Claude Code skills — check status, create new skills from a free-form prompt, improve or review existing ones. Input is ONE free-form natural-language prompt; there is no keyword grammar. Skill operations are delegated to the `brewcode:skill-creator` specialist agent. + +**Default action:** status (rich inventory). List-by-default is removed — typing `/brewcode:skills` alone now opens the interactive menu. ## Quick Start -```bash +``` /brewcode:skills ``` -Lists all available skills across global, project, and plugin locations. +No arguments: presents the interactive menu with Status (skills) pre-selected as the recommended action. + +Pass a free-form prompt to skip the menu entirely: + +``` +/brewcode:skills create a skill that scans for hardcoded secrets +``` + +## How It Works — Unified 6-Step Flow + +Every invocation goes through the same flow: + +1. **Input gate** — reads `$ARGUMENTS`; if empty, goes to the interactive menu. +2. **Auto-mode select** — infers mode from the prompt and announces: + `Mode: (skills) — chosen because ` +3. **No-prompt menu** — when no arguments given, shows a single `AskUserQuestion`: + - Status (skills) [recommended] + - Status (all: agents + rules + skills) + - Create + - Improve + - Review + - List (plain) + - Cancel +4. **Dispatch** — routes to `brewcode:skill-creator` agent (create / improve / review / batch) or runs `list-skills.sh` directly (list mode). +5. **Real status** — rich inventory showing installed skills grouped by location (global, project, plugin), with description and trigger keywords for each. +6. **Mandatory final output** — structured summary of what was created, changed, or reviewed. Omitted only for `list` mode. ## Modes -| Mode | How to trigger | What it does | -|------|---------------|--------------| -| `list` | `/brewcode:skills` or `/brewcode:skills list` | Lists all skills grouped by location (global, project, plugin) | -| `up` | `/brewcode:skills up ` | Improves one or more skills using the skill-creator agent | -| `up` (shorthand) | `/brewcode:skills ` | Same as `up` -- auto-detected when the argument is not a mode keyword | -| `create` | `/brewcode:skills create ` | Researches the topic (codebase + web), then creates a new skill | -| `create` (from spec) | `/brewcode:skills create ./spec.md` | Reads the spec file and creates a skill based on its contents | +| Mode | How it activates | What it does | +|------|-----------------|--------------| +| `status` | Default when no other mode is detected | Shows skill inventory grouped by location | +| `list` | Explicit only — "list", "show skills", "what skills" | Runs `list-skills.sh`, plain file listing | +| `create` | "create", "add", "new skill" in prompt | skill-creator researches and generates a new SKILL.md + README.md | +| `improve` | "improve", "update", "refine" in prompt | skill-creator rewrites target SKILL.md with optimized content | +| `review` | "review", "check", "audit" in prompt | skill-creator audits skill files for quality and best practices | +| `batch` | Multiple targets detected | skill-creator processes all targets in one pass | + +## Create / Improve Parameters + +When creating or improving a skill, the skill-creator agent asks three questions before generating: + +| Parameter | Options | Notes | +|-----------|---------|-------| +| Invocation type | User-only / LLM-auto / Both | Determines `user-invocable` and matcher strategy | +| Testing depth | Quick (recommended) / Standard / Deep | Drives the scope of Phase 5 E2E evaluation | +| Review type | Simple / Quorum | Quorum available only at Standard or Deep testing depth | + +**Description budget:** the generated `description:` field must be ≤ 120 characters (trigger keywords count toward the budget). + +The full creation pipeline includes Phase 0 Discovery (parallel Explore agents), Phase 4 Review (Simple or 3-reviewer Quorum with DoubleCheck + fix loop), and Phase 5 E2E. This machinery is only reachable via `create` or `improve` mode. ## Examples -### Good Usage - ```bash -# List everything installed -/brewcode:skills list +# Open the interactive menu +/brewcode:skills -# Improve a skill by name (searches global and project locations) -/brewcode:skills up commit - -# Shorthand -- same as above, "up" is implied -/brewcode:skills commit - -# Improve a skill by explicit path -/brewcode:skills up ~/.claude/skills/commit/SKILL.md - -# Shorthand with path -/brewcode:skills brewcode/skills/setup - -# Improve all skills in a folder (parallel agents) -/brewcode:skills ~/.claude/skills/ +# Check the current state of all installed skills +/brewcode:skills what is the current state of our skills # Create a brand new skill from a prompt -/brewcode:skills create "semantic code search" +/brewcode:skills create a skill that scans for hardcoded API keys -# Create a skill from a spec file -/brewcode:skills create ./my-skill-spec.md +# Improve an existing skill by name +/brewcode:skills improve the grepai skill + +# Improve a skill by explicit path +/brewcode:skills update brewcode/skills/grepai + +# Review all skills in a folder for quality +/brewcode:skills review ~/.claude/skills/ + +# Plain listing of all skill files +/brewcode:skills list ``` -### Common Mistakes - -| Mistake | Why it fails | Correct | -|---------|-------------|---------| -| `/brewcode:skills up` (no target) | `up` mode requires a skill name, path, or folder | `/brewcode:skills up commit` | -| `/brewcode:skills create` (no prompt) | `create` mode requires a prompt or spec file path | `/brewcode:skills create "my new skill"` | -| `/brewcode:skills up list` | Interprets `list` as a skill name to improve, not the list mode | `/brewcode:skills list` | - ## Output Depends on mode: -- **list** -- a summary table of all skills grouped by location (global `~/.claude/skills/`, project `.claude/skills/`, plugins). -- **up** -- the skill-creator agent rewrites the target SKILL.md with optimized description, trigger keywords, imperative voice, and best practices. For folders, multiple agents run in parallel. -- **create** -- a new skill directory containing `SKILL.md` and `README.md`, placed in `.claude/skills/` (project) or `~/.claude/skills/` (global). Before creation you are asked whether the skill should be user-invocable, LLM auto-detected, or both. +- **status** — rich inventory table of all skills grouped by location (global `~/.claude/skills/`, project `.claude/skills/`, plugins), with description and trigger keywords for each. +- **list** — plain file listing from `list-skills.sh`. +- **create** — a new skill directory containing `SKILL.md` and `README.md`, placed in `.claude/skills/` (project) or `~/.claude/skills/` (global). +- **improve** — the target `SKILL.md` rewritten with optimized description, trigger keywords, imperative voice, and best practices. +- **review** — a structured audit report with issues found and recommended fixes applied. -## Mode Switcher - -The `create` mode can generate **Mode Switcher** skills — special skills that toggle persistent behavioral modes for the entire Claude Code session. - -### What is a Mode Switcher? - -A mode switcher is a skill that changes how Claude behaves for the rest of the session. For example, "manager mode" makes Claude delegate all tasks via agents, "researcher mode" makes Claude prioritize depth and source verification. - -### How it works - -``` -/brewcode:skills create "toggle research mode" - ↓ - Step 2.5 detects "mode/toggle" keywords - ↓ - Asks: "Create as a Mode Switcher skill?" - ↓ Yes - skill-creator uses Mode Switcher pattern - ↓ - Creates skill with on/off/status arguments - ↓ - Skill writes state → hooks inject instructions -``` - -### Flow - -``` -Skill writes {"mode":"research"} → $CLAUDE_PLUGIN_DATA/modes.json - ↓ - forced-eval.mjs → injects [MODE: research] into every user prompt - session-start.mjs → injects mode into session context (survives compact) - pre-task.mjs → injects mode into every sub-agent prompt -``` - -### Example - -```bash -# Create a mode switcher skill -/brewcode:skills create "toggle deep research mode that prioritizes source verification" - -# The created skill will support: -/my-mode on research # activate mode -/my-mode off # deactivate -/my-mode status # show current mode -``` - -### Creating a mode manually - -1. Create mode instructions file: `brewcode/modes/{name}.md` (plain text) -2. Activate: - ```bash - MODES="$BC_PLUGIN_DATA/modes.json" - [ ! -f "$MODES" ] && echo '{}' > "$MODES" - jq --arg m "research" --arg p "$PWD" --arg t "$(date -u +%Y-%m-%dT%H:%M:%S.000Z)" \ - '.projects[$p] = {mode: $m, activatedAt: $t}' "$MODES" > "$MODES.tmp" && mv "$MODES.tmp" "$MODES" - ``` -3. Deactivate: - ```bash - MODES="$BC_PLUGIN_DATA/modes.json" - jq --arg p "$PWD" 'del(.projects[$p])' "$MODES" > "$MODES.tmp" && mv "$MODES.tmp" "$MODES" - ``` - -> **Legacy fallback:** `.claude/tasks/cfg/brewcode.state.json` (flat `mode` field) is still supported but deprecated. - -Hooks pick up the change automatically — no code modifications needed. ## Tips -- Use the shorthand form (`/brewcode:skills commit`) for quick improvements -- no need to type `up` explicitly. -- Point at a folder (`/brewcode:skills ~/.claude/skills/`) to batch-improve every skill inside it. Each skill gets its own parallel agent. +- Run `/brewcode:skills` with no arguments to see the menu — `Status (skills)` is pre-selected and answers "what do I have installed?" in one step. - The `create` mode checks conversation history first. If the current conversation already contains a workflow worth capturing, it extracts context directly and skips web research. -- After creating a skill, you are offered an optional eval step that runs three test prompts to verify the skill activates correctly. +- After creating a skill, Phase 5 E2E runs three test prompts to verify the skill activates correctly. Choose `Deep` testing depth for safety-critical or frequently-used skills. +- `list` is the fastest mode for verifying file counts — use `status` when you need trigger keywords and descriptions alongside each entry. ## Documentation diff --git a/brewcode/skills/skills/SKILL.md b/brewcode/skills/skills/SKILL.md index 3851b58..685fdc4 100644 --- a/brewcode/skills/skills/SKILL.md +++ b/brewcode/skills/skills/SKILL.md @@ -2,70 +2,142 @@ name: brewcode:skills description: "Lists, improves, creates Claude Code skills. Triggers: create skill, improve skill, fix skill activation." user-invocable: true -argument-hint: "[list|up|create] [target] | " -allowed-tools: [Read, Write, Edit, Glob, Grep, Bash, Task, WebSearch, WebFetch, AskUserQuestion] +argument-hint: "" +allowed-tools: [Read, Write, Edit, Glob, Grep, Bash, Task, WebSearch, WebFetch, AskUserQuestion, Skill] model: opus --- # skills Skill -> **Skill Management:** List, improve, create skills with activation optimization. +> **Skill Management:** status, list, create, improve, review skills via one free-form prompt. -## Parse Arguments +## Constants -Extract mode and target from `$ARGUMENTS`: +| Const | Value | +|-------|-------| +| ARTIFACT | `skills` | +| SPECIALIST | `brewcode:skill-creator` | +| LIST_CMD | `bash "${CLAUDE_SKILL_DIR}/scripts/list-skills.sh"` | -| Pattern | Mode | Target | -|---------|------|--------| -| empty / `list` | list | none | -| `up ` | up | skill name, path, or folder | -| `create ` | create | prompt or path to spec file | -| `` (not a mode) | **up** (default) | skill name, path, or folder | +## Step 1 — Input gate -**Smart Detection:** If first argument is NOT a mode keyword (`list`, `up`, `create`), treat entire input as target for `up` mode. +Treat the **entire** user input (`$ARGUMENTS`) as ONE free-form natural-language prompt. +There is NO keyword grammar and NO argument parser — `argument-hint` is only a loose example. -**Examples:** -- `/brewcode:skills` or `list` → `list` -- `/brewcode:skills up commit` → `up`, target=`commit` -- `/brewcode:skills create "semantic code search"` → `create`, target=prompt -- `/brewcode:skills commit` → `up`, target=`commit` **(shorthand)** -- `/brewcode:skills ~/.claude/skills/` → `up`, target=folder **(shorthand)** +- prompt non-empty -> go to **Step 2** +- prompt empty / whitespace-only -> go to **Step 3** ---- +## Step 2 — Auto-mode selection -## Mode: list +Classify the prompt + recent conversation context into exactly ONE mode: -**EXECUTE** using Bash tool: -```bash -bash "${CLAUDE_SKILL_DIR}/scripts/list-skills.sh" && echo "✅ list" || echo "❌ list FAILED" +| Mode | Chosen when prompt signals | +|------|----------------------------| +| `status` | "статус", "что есть", "состояние", health / overview / "show me" (DEFAULT for any "show me" intent) | +| `list` | explicit "список" / "list" / "перечисли" ONLY | +| `create` | "создай" / "create" / "new" / "добавь" / "scaffold" | +| `improve` | "улучши" / "improve" / "refactor" / "fix" / "почини", OR a bare existing name/path | +| `review` | "ревью" / "review" / "validate" / "проверь корректность" | + +**Batch flag:** plural form, "все" / "all", or multiple names/paths -> fan-out (one specialist spawn per item). + +Then **ANNOUNCE the chosen mode (MANDATORY, before any work):** + +``` +Mode: (skills) — chosen because ``` -> **STOP if ❌** — verify skill base directory is resolved and scripts exist. +Proceed to **Step 4**. + +## Step 3 — No-prompt menu (single AskUserQuestion, scoped + cross-link) + +Ask ONE AskUserQuestion. Question: `What do you want to do with skills?` +Options (in this order): + +- `Status (skills)` — **(Recommended)** rich status of this artifact +- `Status (all: agents+rules+skills)` — cross-link: run the collector for all three +- `Create new skills` +- `Improve existing skills` +- `Review skills` +- `List (plain)` +- `Nothing / cancel` + +After the choice: +- `Nothing / cancel` -> stop. +- `create` or `improve` -> ask ONE follow-up AskUserQuestion for the target/description + plus the artifact-specific params (see "Artifact-specific params" below). +- Then ANNOUNCE the mode using the Step 2 format and proceed to **Step 4**. + +## Step 4 — Dispatch + +- `status` -> go to **Step 5**. +- `status (all)` -> go to **Step 5**, running the collector for agents + rules + skills together. +- `list` -> run `LIST_CMD`, print the plain inventory it produces, then STOP (no status assembly). +- `create` -> gather minimal params (Step 3 / artifact-specific), spawn `SPECIALIST` via Task. + Batch -> spawn one `SPECIALIST` per item, ALL in ONE message (parallel). +- `improve` -> resolve target(s), spawn `SPECIALIST` via Task per target (parallel for batch). +- `review` -> spawn `brewcode:reviewer` (two-phase: review -> double-check findings -> report). + +## Step 5 — Real status (NOT a flat list) + +Delegate collection to ONE Explore/Bash subagent, then assemble a rich status (never a bare list): + +- **Inventory by scope:** plugin (BC) / project (`.claude/`) / global (`~/.claude/`) — counts + names + load path. +- **State:** enabled/disabled (toggle markers `_SKILL.md` / `_.md`), model. +- **Overlaps / conflicts:** same-name across scopes (shadowing), duplicate triggers/descriptions, naming collisions. +- **Health flags:** missing README/frontmatter; agents missing `Bash` in `tools:` (macOS search rule); + skills with weak description triggers; rules duplicated in CLAUDE.md. + +For the `Status (all)` menu option: run the SAME collector for agents + rules + skills together. + +## Step 6 — Final formatted output (MANDATORY for every run except `list`) + +``` +# skills [] +## Detection +| Input | menu)"> | +| Mode | | +| Reason | | +| Targets| | +## Result +(create/improve/review: each output path + specialist agent + scope/model) +## Status +(status mode: full table from Step 5; else short "what changed" for touched artifacts) +## Next Steps +(recommendations; ALWAYS remind to run /docs for any created/changed artifact) +``` + +For `status` mode the report **is** the Step 5 status table. + +## Artifact-specific params (create / improve only) + +Keep the existing Phase 0 (Discovery: 2-3 parallel Explore agents) and Phase 4 (Review: +Simple = reviewer + verify + fix; Quorum = 3 reviewers threshold 2/3 + DoubleCheck + fix) +machinery, but they are reachable ONLY through `create` / `improve` modes — never by default. +For `create`/`improve`: AskUserQuestion for invocation type (User-only / LLM-auto / Both), +testing depth (Quick (Recommended) / Standard / Deep), and review type (Simple / Quorum, +only if Standard/Deep). Frontmatter description budget: <= 120 chars. Spawn SPECIALIST (brewcode:skill-creator) +with discovery results + chosen params. Phase 6 summary == the Step 6 output block (do not +duplicate a second summary). Reference files: ${CLAUDE_SKILL_DIR}/references/review-prompt.md, +e2e-template.md, summary-template.md. --- -## Mode: create / up (Unified Flow) +## create / improve machinery (detail — reachable ONLY via Step 4 create/improve) -Both `create` and `up` follow Phases 0-6. Differences noted per phase. +> Default mode is `status`. The phases below run ONLY after Step 4 dispatches `create` or `improve`. -### Description Budget (DEFAULT) +### Description Budget Frontmatter `description`: <= 120 chars (optimal ~100), single line. What + when + 3-5 distinct triggers (comma-list). No filler, no `` blocks. Some registries truncate long descriptions and dilute trigger matching. EN only unless user explicitly asks. -### Prerequisite (up only): Resolve Target +### Prerequisite (improve only): Resolve Target **EXECUTE** using Bash tool: ```bash -TARGET="$ARGUMENTS" -if [[ "$TARGET" == up\ * ]] || [[ "$TARGET" == "up" ]]; then - TARGET="${TARGET#up }"; TARGET="${TARGET#up}" -fi -TARGET="$(echo "$TARGET" | xargs)" -if [[ -z "$TARGET" ]]; then - echo "❌ No target. Usage: /brewcode:skills up "; exit 1 -fi +TARGET="TARGET_HERE" if [[ -d "$TARGET" ]]; then echo "TYPE: folder"; echo "PATH: $TARGET" find "$TARGET" -name "SKILL.md" -type f 2>/dev/null | head -20 @@ -80,6 +152,7 @@ else done fi ``` +Replace `TARGET_HERE` with the resolved target name/path from Step 4. > **STOP if ❌** — target must resolve to at least one SKILL.md. @@ -87,86 +160,61 @@ fi Spawn 2-3 Explore agents in parallel (single message). -**create mode** — spawn in ONE message: +**create** — spawn in ONE message: 1. `Explore`: Research skill patterns in `$BC_PLUGIN_ROOT/skills/` and `~/.claude/skills/` — structure, naming, frontmatter, references, scripts. 2. `Explore`: Analyze target project structure for `{TOPIC}` — code, APIs, configs, tooling. 3. (Optional) `general-purpose`: Web research for `{TOPIC}` — best practices, similar tools. Use WebSearch/WebFetch. -**up mode** — spawn in ONE message: +**improve** — spawn in ONE message: 1. `Explore`: Analyze skill at `{SKILL_PATH}` — SKILL.md, references/, scripts/, tests/, README.md. Report quality and gaps. 2. `Explore`: Compare `{SKILL_PATH}` against patterns in `$BC_PLUGIN_ROOT/skills/`. Output improvement recommendations. ### Phase 1: User Interaction -**Step 1: Check Conversation History** (create only) -Check if current conversation already contains workflow to capture. If yes: extract tools, steps, corrections, I/O formats for Phase 2. +**Check Conversation History** (create only): if the current conversation already contains a workflow to capture, extract tools, steps, corrections, I/O formats for Phase 2. -**Step 2: Determine Input Type** (create only) +**Determine Input Type** (create only): path to `.md` file -> read as spec; text prompt -> use as research query. -| Input | Action | -|-------|--------| -| Path to `.md` file | Read as spec | -| Text prompt | Use as research query | - -**Step 3: Invocation Type** (AskUserQuestion) +**Invocation Type** (AskUserQuestion): ``` header: "Invocation" question: "Who will invoke this skill?" options: - - label: "User only (slash command)" - description: "disable-model-invocation: true, simple description" - - label: "LLM auto-detect" - description: "Full trigger keyword optimization" - - label: "Both (default)" - description: "User slash command + LLM auto-detection" + - label: "User only (slash command)" — disable-model-invocation: true, simple description + - label: "LLM auto-detect" — full trigger keyword optimization + - label: "Both (default)" — user slash command + LLM auto-detection ``` Save as `INVOCATION_TYPE`. -**Step 4: Mode Switcher Detection** (create only) -**Keywords:** "mode", "toggle", "switch", "persistent", "from now on", "always do", "session behavior" - -If detected — AskUserQuestion: "Create as Mode Switcher skill?" (Yes/No). -If Yes: set `IS_MODE_SWITCHER=true`, then ask scope (Project/Global/Session) via AskUserQuestion, save as `MODE_SCOPE`. - -Validate BC_PLUGIN_DATA: -**EXECUTE** using Bash tool: -```bash -if [ -n "$BC_PLUGIN_DATA" ]; then echo "✅ BC_PLUGIN_DATA=$BC_PLUGIN_DATA"; else echo "❌ BC_PLUGIN_DATA not set"; fi -``` - -> **STOP if ❌** — BC_PLUGIN_DATA required for Mode Switcher. - -**Step 5: Testing Depth** (AskUserQuestion) +**Testing Depth** (AskUserQuestion): ``` header: "Testing Depth" question: "How thoroughly should the skill be tested?" options: - - label: "Quick (default)" — validate-skill.sh + 3-5 test prompts - - label: "Standard" — + unit tests + simple review (1 reviewer + verification) - - label: "Deep" — + quorum review (3 reviewers, threshold 2) + E2E tests + - label: "Quick (Recommended)" — validate-skill.sh + 3-5 test prompts + - label: "Standard" — + unit tests + simple review (1 reviewer + verification) + - label: "Deep" — + quorum review (3 reviewers, threshold 2) + E2E tests ``` Save as `TESTING_DEPTH`. -**Step 6: Review Type** (AskUserQuestion, only if Standard or Deep) +**Review Type** (AskUserQuestion, only if Standard or Deep): ``` header: "Review Type" question: "What review approach?" options: - label: "Simple (default for Standard)" — 1 reviewer + 1 verification agent - - label: "Quorum (default for Deep)" — 3 reviewers parallel, threshold 2/3, DoubleCheck + - label: "Quorum (default for Deep)" — 3 reviewers parallel, threshold 2/3, DoubleCheck ``` Save as `REVIEW_TYPE`. -**Step 7: Plan Confirmation** (AskUserQuestion) - -Output plan summary: Action (Create/Improve), skill path/name, files to create/modify, references used, testing approach, review type. +**Plan Confirmation** (AskUserQuestion). Output plan summary: action (create/improve), skill path/name, files to create/modify, references used, testing approach, review type. ``` header: "Plan Confirmation" @@ -192,16 +240,8 @@ Task(subagent_type="brewcode:skill-creator", model="opus", prompt=" - Invocation type pre-filled: {INVOCATION_TYPE} — skip asking ") -**Mode Switcher additions** (if `IS_MODE_SWITCHER=true`) — append: -- Single skill with argument parsing: on [mode-name], off, status -- State in `$BC_PLUGIN_DATA/modes.json` — structure: `.global`, `.projects["$PWD"]`, `.sessions["$SESSION_ID"]` -- Scope: `{MODE_SCOPE}`, resolution priority: session > project > global -- `disable-model-invocation: true`, mode instructions in `references/` -- Bash MUST validate: `if [ -z "$BC_PLUGIN_DATA" ]; then echo "❌"; exit 1; fi` -After creation (if Mode Switcher): AskUserQuestion — create mode file in `brewcode/modes/`? If yes: spawn `brewcode:hook-creator`. - -**Folder target (multiple skills):** spawn parallel agents in ONE message, one per SKILL.md found. +**Folder target (batch):** spawn parallel agents in ONE message, one per SKILL.md found. ### Phase 3: Validate (automatic) @@ -209,18 +249,14 @@ Skill-creator Steps 5-5.8 run automatically (validate, unit tests, README). No o ### Phase 4: Review -**Skip if `TESTING_DEPTH` is Quick.** - -Read review prompt: `${CLAUDE_SKILL_DIR}/references/review-prompt.md` +**Skip if `TESTING_DEPTH` is Quick.** Read review prompt: `${CLAUDE_SKILL_DIR}/references/review-prompt.md` **Simple Review (`REVIEW_TYPE` = Simple):** - 1. Task(subagent_type="brewcode:reviewer", model="opus", prompt="Review skill quality at: {SKILL_PATH}\n\n{REVIEW_PROMPT_CONTENT}") 2. If findings: Task(subagent_type="brewcode:reviewer", model="sonnet", prompt="Verify these review findings against actual code...\n\n{REVIEWER_FINDINGS}") 3. Confirmed findings: Task(subagent_type="brewcode:skill-creator", model="opus", prompt="Fix verified issues in skill at: {SKILL_PATH}\n\n{CONFIRMED_FINDINGS}") **Quorum Review (`REVIEW_TYPE` = Quorum):** - 1. Three in parallel (ONE message): Task(subagent_type="brewcode:reviewer", model="opus", prompt="Review skill quality at: {SKILL_PATH}\n\n{REVIEW_PROMPT_CONTENT}") Task(subagent_type="brewcode:reviewer", model="opus", prompt="Review skill quality at: {SKILL_PATH}\n\n{REVIEW_PROMPT_CONTENT}") @@ -229,64 +265,27 @@ Read review prompt: `${CLAUDE_SKILL_DIR}/references/review-prompt.md` 3. Task(subagent_type="brewcode:reviewer", model="opus", prompt="DoubleCheck: verify quorum findings against code.\n\n{QUORUM_FINDINGS}") 4. Confirmed: Task(subagent_type="brewcode:skill-creator", model="opus", prompt="Fix verified issues...\n\n{CONFIRMED_FINDINGS}") -> **Collect findings:** After Phase 4 completes, compile all confirmed findings (source, severity, issue, fix applied, verified status) into a structured list. Pass to Phase 6 for summary. +> **Collect findings:** compile all confirmed findings (source, severity, issue, fix applied, verified status) into a structured list for the Step 6 output block. ### Phase 5: E2E Testing (Optional) **Only if `TESTING_DEPTH` is Deep.** Otherwise skip. - 1. Read: `${CLAUDE_SKILL_DIR}/references/e2e-template.md` 2. Create test scenarios in `{SKILL_DIR}/tests/` — 1 per mode (happy path) + 1 edge case per mode. -3. Execute each scenario: - -**EXECUTE** using Bash tool: +3. Execute each scenario — **EXECUTE** using Bash tool: ```bash TMPDIR=$(mktemp -d) mkdir -p "$TMPDIR/.claude/skills" -cp -r "{SKILL_DIR}" "$TMPDIR/.claude/skills/" -cd "$TMPDIR" && timeout 120 claude -p "{PROMPT}" 2>&1 | tee "$TMPDIR/output.log" -{ASSERTION_COMMANDS} +cp -r "SKILL_DIR_HERE" "$TMPDIR/.claude/skills/" +cd "$TMPDIR" && timeout 120 claude -p "PROMPT_HERE" 2>&1 | tee "$TMPDIR/output.log" rm -rf "$TMPDIR" ``` +Replace `SKILL_DIR_HERE` / `PROMPT_HERE` with the skill dir and scenario prompt; append assertion commands before cleanup. -4. Iteration: scenario failure = fix (max 2 retries). Small skill issues = fix + re-run. Major issues = back to Phase 2. +4. Iteration: scenario failure = fix (max 2 retries). Small issues = fix + re-run. Major issues = back to Phase 2. -### Phase 6: Summary +### Final output for create/improve -Read: `${CLAUDE_SKILL_DIR}/references/summary-template.md` - -Fill: action, path, invocation type, testing depth, review type, completed phases checklist, problems found/fixed (Phase 4), test results (Phase 3 + 5), suggestions, skipped phases with reasons. - -Output filled summary to user. +Use the **Step 6 output block** as the single summary (do NOT emit a second report). Reference `${CLAUDE_SKILL_DIR}/references/summary-template.md` to populate the `## Result` / `## Status` detail (action, path, invocation, testing depth, review type, problems found/fixed, test results, suggestions). - ---- - -## Output Format - -> For `list` mode only. For `create`/`up` modes, Phase 6 summary replaces this section. - -```markdown -# skills [list] - -## Detection - -| Field | Value | -|-------|-------| -| Arguments | `$ARGUMENTS` | -| Mode | `list` | -| Target | `none` | - -## Skills Summary - -| Location | Count | Skills | -|----------|-------|--------| -| Global (~/.claude/skills/) | N | skill1, skill2 | -| Project (.claude/skills/) | N | skill3 | -| Plugins | N | plugin:skill1 | - -## Next Steps - -- [recommendations based on results] -``` diff --git a/brewcode/skills/skills/references/summary-template.md b/brewcode/skills/skills/references/summary-template.md index 82863d9..e1c844f 100644 --- a/brewcode/skills/skills/references/summary-template.md +++ b/brewcode/skills/skills/references/summary-template.md @@ -1,30 +1,42 @@ -# Summary Report Template for Skills Orchestrator (Phase 6) +# Step 6 Output Template — skills create/improve detail > **Instructions for orchestrator:** -> - Fill all `{PLACEHOLDERS}` from collected data across phases -> - Remove empty sections (e.g., E2E Tests if Quick mode, Review if None) -> - Checkboxes reflect actual phase completion: `[x]` done, `[ ]` skipped -> - Problems table only includes confirmed and verified findings -> - After generation, remove this instructions block entirely +> - This template is the SINGLE summary. It mirrors the canonical Step 6 output block +> (`# skills []` / `## Detection` / `## Result` / `## Status` / `## Next Steps`). +> Do NOT emit a second report. +> - Fill all `{PLACEHOLDERS}` from collected data across phases. +> - Remove empty sub-tables (e.g., E2E Tests if Quick mode, Problems if none). +> - After generation, remove this instructions block entirely. --- ## Template ```markdown -# Skill {ACTION}: {SKILL_NAME} +# skills [{MODE}] + +## Detection + +| Field | Value | +|-------|-------| +| Input | {PROMPT or "(none -> menu)"} | +| Mode | {MODE} | +| Reason | {WHY_THIS_MODE} | +| Targets | {SKILL_NAME / SKILL_PATH} | + +## Result | Field | Value | |-------|-------| | Location | {SKILL_PATH} | +| Specialist | brewcode:skill-creator | | Action | {ACTION} | | Invocation | {INVOCATION_TYPE} | | Testing Depth | {TESTING_DEPTH} | | Review Type | {REVIEW_TYPE} | | Model | {MODEL} | -## What Was Done - +Phases completed: - [{DISCOVERY}] Discovery (Explore agents) - [{INTERACTION}] User interaction (invocation, testing depth) - [{CREATE}] {ACTION_VERB} (skill-creator) @@ -34,14 +46,14 @@ - [{REVIEW}] Review ({REVIEW_TYPE}) - [{E2E}] E2E Testing -## Problems Found and Fixed +## Status + +### Problems Found and Fixed | # | Source | Severity | Issue | Fix | Verified | |---|--------|----------|-------|-----|----------| | {N} | {PHASE_OR_AGENT} | {HIGH/MEDIUM/LOW} | {DESCRIPTION} | {WHAT_WAS_DONE} | {YES/NO} | -## Test Results - ### Unit Tests | Script | Tests | Passed | Failed | @@ -54,12 +66,9 @@ |----------|------|---------|--------|------------|---------| | {SCENARIO} | {MODE} | {VARIANT} | {PASS/FAIL} | {COUNT} | {NOTES} | -## What Could Be Improved +## Next Steps +- Run `/docs "обнови документацию для brewcode:{SKILL_NAME}"` for any created/changed skill - {SUGGESTION_1} -- {SUGGESTION_2} - -## What Was NOT Done - -- {SKIPPED_ITEM} -- Reason: {WHY} +- Not done: {SKIPPED_ITEM} -- Reason: {WHY} ``` diff --git a/brewcode/skills/standards-review/LICENSE b/brewcode/skills/standards-review/LICENSE deleted file mode 100644 index b09ce61..0000000 --- a/brewcode/skills/standards-review/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -MIT License - -Copyright (c) 2025-2026 Maxim Kochetkov (kochetkov-ma) -https://github.com/kochetkov-ma/claude-brewcode - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/brewcode/skills/standards-review/README.md b/brewcode/skills/standards-review/README.md deleted file mode 100644 index 5fce4b2..0000000 --- a/brewcode/skills/standards-review/README.md +++ /dev/null @@ -1,114 +0,0 @@ ---- -auto-sync: enabled -auto-sync-date: 2026-04-01 -auto-sync-type: doc ---- - -# Standards Review - -Analyzes code changes for project standards compliance, detects duplicate code that can be replaced with existing utilities, and highlights exemplary patterns. Automatically detects your tech stack and applies the right set of rules. - -## Quick Start - -```bash -/brewcode:standards-review -``` - -Reviews all changes on your current branch compared to main. - -## Modes - -| Mode | How to trigger | What it does | -|------|---------------|--------------| -| Branch diff | `/brewcode:standards-review` | Compares current branch to main/master, reviews all changed files | -| Single commit | `/brewcode:standards-review abc123f` | Reviews files changed in the specified commit | -| Folder scan | `/brewcode:standards-review src/main/java` | Reviews all source files in the given directory | -| Custom focus | `/brewcode:standards-review -p "check error handling"` | Adds a custom analysis prompt on top of standard checks | -| With simplify | Answer "Yes" when prompted at start | Runs an extra `/simplify` pass for efficiency, concurrency, and hot-path analysis | - -## Examples - -### Good Usage - -```bash -# Review branch before opening a PR -/brewcode:standards-review - -# Review a specific commit after a colleague's push -/brewcode:standards-review d8c8e69 - -# Review an entire module after refactoring -/brewcode:standards-review src/components - -# Focus on security concerns in authentication code -/brewcode:standards-review src/auth -p "focus on security and input validation" - -# Review Python tests folder for test quality -/brewcode:standards-review tests/ -``` - -### Common Mistakes - -```bash -# Reviewing generated or vendored code -- produces noise, not actionable findings -/brewcode:standards-review node_modules -/brewcode:standards-review src/generated - -# Reviewing the entire repo on a long-lived branch -- too many files, suggest narrowing scope -# (the skill warns you when >50 files are detected) -/brewcode:standards-review / - -# Running without any project rules or CLAUDE.md -- the skill still works -# but findings will be limited to stack-specific guidelines only -``` - -## What It Checks - -**Standards compliance** -- validates code against three layers of rules: -- Project rules from `.claude/rules/*.md` (numbered `avoid#N`, `best-practice#N`) -- Project conventions from `CLAUDE.md` -- Stack-specific guidelines from built-in reference files - -**Duplicate detection** -- uses `grepai_search` to find existing utilities, helpers, and patterns before flagging new code. Similarity scoring determines the recommendation: - -| Similarity | Recommendation | Meaning | -|------------|---------------|---------| -| 90-100% | REUSE | Import the existing code directly | -| 70-89% | EXTEND | Add parameters or configuration to the existing code | -| 50-69% | CONSIDER | Evaluate whether refactoring is worth the effort | -| <50% | KEEP_NEW | New code is justified | - -**Pattern recognition** -- identifies good patterns worth replicating across the codebase. - -**Supported stacks:** - -| Stack | Detected by | File groups analyzed | -|-------|-------------|---------------------| -| Java/Kotlin | `pom.xml`, `build.gradle`, `build.gradle.kts` | entities, services, tests, build configs | -| TypeScript/React | `package.json` with react/typescript | styles, components, tests, build configs | -| Python | `pyproject.toml`, `setup.py`, `requirements.txt` | modules, tests, configs, build files | - -Multi-stack projects are supported -- each stack is processed separately. - -## Output - -A structured `REPORT.md` is saved to `.claude/reports/{timestamp}_standards-review/` containing: - -- **Summary table** -- violation counts by severity, reuse opportunities, good patterns found -- **Violations** -- grouped by severity (error, warning, info) with file, line, rule reference, and suggested fix -- **Reuse opportunities** -- new code mapped to existing code with similarity percentages -- **Good patterns** -- exemplary code worth emulating -- **Reuse statistics** -- total new code blocks, reusable percentage, overall reuse rate - -Severity levels: **error** (must fix), **warning** (should fix), **info** (consider). - -## Tips - -- Run before opening a PR to catch standards issues early -- the branch diff mode is designed for exactly this workflow. -- If the skill detects more than 50 files, narrow the scope to a specific folder or commit to get more focused results. -- Answer "Yes" to the simplify prompt when reviewing performance-sensitive code -- the extra pass analyzes efficiency, concurrency, and hot-path optimizations. -- Make sure `grepai` is configured for your project (`/brewcode:grepai`) to get accurate duplicate detection results. - -## Documentation - -Full docs: [standards-review](https://doc-claude.brewcode.app/brewcode/skills/standards-review/) diff --git a/brewcode/skills/standards-review/SKILL.md b/brewcode/skills/standards-review/SKILL.md deleted file mode 100644 index 3f8c99b..0000000 --- a/brewcode/skills/standards-review/SKILL.md +++ /dev/null @@ -1,310 +0,0 @@ ---- -name: brewcode:standards-review -description: "Reviews code for standards compliance, finds duplicates. Triggers: standards review, check standards, find duplicates." -argument-hint: "[commit|branch|folder] [-p ]" -allowed-tools: Read, Glob, Grep, Task, Bash, Write, mcp__grepai__search, AskUserQuestion, Skill -model: opus ---- - -# Standards Review - -## Review Priorities - -| Priority | Source | Focus | -|----------|--------|-------| -| 1 | Existing code | Search FIRST, import instead of creating | -| 2 | CLAUDE.md | Project standards, conventions, patterns | -| 3 | rules/*.md | Strict rules with numbers — check ALL `[avoid#N]`, `[bp#N]` | -| 4 | references/{stack}.md | Stack-specific guidelines from this skill | - ---- - -## Phase 0: User Confirmation - -**BEFORE any analysis**, ask the user using AskUserQuestion tool: - -> "Run `/simplify` at the end for an additional review pass (efficiency, concurrency, hot-paths)? This will increase execution time." - -| Option | Value | -|--------|-------| -| A | "Yes - run /simplify after report" | -| B | "No - standards review only" | - -**Remember the answer.** If "Yes" - execute Phase 7 after Phase 6. If "No" - stop after Phase 6. - ---- - -## Input - -| Input | Example | Action | -|-------|---------|--------| -| Empty | `/standards-review` | Branch vs main/master | -| Commit | `abc123` | Single commit | -| Folder | `src/main/java/...` | Folder contents | - -**Arguments:** `$ARGUMENTS` - -## Phase 1: Detect Tech Stack - -Check project root for stack indicators: - -| Files Present | Stack | Reference | -|---------------|-------|-----------| -| `pom.xml`, `build.gradle`, `build.gradle.kts` | Java/Kotlin | `references/java-kotlin.md` | -| `package.json` with react/typescript | TypeScript/React | `references/typescript-react.md` | -| `pyproject.toml`, `setup.py`, `requirements.txt` | Python | `references/python.md` | - -> **ACTION:** When stack confirmed → **READ** `references/{stack}.md` (relative to this skill directory) and use as expert guidelines. - -**Multi-stack:** If multiple detected, read ALL matching references, process each separately. - -**Unknown stack:** Use only project's `.claude/rules/` — skip stack reference. - -## Phase 2: Get Files - -Based on detected stack, use appropriate patterns: - -| Stack | Patterns | Command | -|-------|----------|---------| -| Java/Kotlin | `*.java`, `*.kt` | `git diff --name-only ... -- '*.java' '*.kt'` | -| TypeScript/React | `*.ts`, `*.tsx`, `*.js`, `*.jsx` | `git diff --name-only ... -- '*.ts' '*.tsx'` | -| Python | `*.py` | `git diff --name-only ... -- '*.py'` | - -**Commands by input type:** - -```bash -# Commit -git diff --name-only {COMMIT}^..{COMMIT} -- {PATTERNS} | head -50 - -# Branch (auto-detect main/master) -MAIN=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@' || echo "main") -git diff --name-only ${MAIN}...HEAD -- {PATTERNS} | head -50 - -# Folder -find {FOLDER} -type f \( {FIND_PATTERNS} \) | head -50 -``` - -## Phase 3: Load Context - -| Source | Files | Condition | -|--------|-------|-----------| -| Stack reference | `references/{stack}.md` | Based on Phase 1 detection | -| Project rules | `.claude/rules/avoid.md`, `.claude/rules/best-practice.md`, `.claude/rules/*-avoid.md`, `.claude/rules/*-best-practice.md`, `.claude/rules/*.md` | May not exist | -| Project standards | `CLAUDE.md`, `.claude/CLAUDE.md` | May not exist | - -## Search-First Protocol - -Before reviewing code: identify new utilities/helpers/patterns/abstractions → search via `grepai_search`, check common locations → decide based on similarity. - -**Common Locations by Stack:** - -| Stack | Search Paths | -|-------|--------------| -| Java/Kotlin | `**/util/`, `**/common/`, `**/shared/`, `**/core/` | -| TypeScript/React | `**/components/common/`, `**/shared/`, `**/hooks/`, `**/utils/` | -| Python | `**/utils/`, `**/common/`, `**/lib/`, `**/helpers/` | - -**Similarity Decision Matrix:** - -| Similarity | Decision | Action | -|------------|----------|--------| -| 90-100% | REUSE | Import existing | -| 70-89% | EXTEND | Add params/config to existing | -| 50-69% | CONSIDER | Evaluate effort vs benefit | -| <50% | KEEP_NEW | Justified new code | - -### Dynamic Agent Resolution - -Before spawning expert agents, check for project team agents: - -1. If `.claude/teams/` exists — read `team.md` for agent roster with domains -2. If team has code-quality/standards domain agents — prefer over generic reviewer/Explore -3. Priority: **team agent > project agent > plugin agent > system agent** -4. If agent refuses (Task Acceptance Protocol) — re-delegate to suggested colleague (max 2 retries) - -> Always fall back to plugin agents when no project agents match the task domain. - -## Phase 4: Expert Analysis - -### Step 4.1: Group Files by Type - -From Phase 2 file list, group by pattern matching: - -**Java/Kotlin:** - -| Group | Pattern | Focus | -|-------|---------|-------| -| entities | `**/entity/*.java`, `**/model/*.kt` | Entity suffix, DI, Lombok | -| services | `**/service/*.java`, `**/service/*.kt` | Stream API, constructor injection | -| tests | `**/*Test.java`, `**/*Test.kt` | AssertJ, BDD comments, no logs | -| build | `pom.xml`, `build.gradle`, `build.gradle.kts` | Dependencies, plugins, versions | - -**TypeScript/React:** - -| Group | Pattern | Focus | -|-------|---------|-------| -| styles | `**/styles.ts`, `**/*.styled.ts` | Theme tokens, no hardcoded colors | -| components | `**/*.tsx` | Hooks, functional components | -| tests | `**/*.test.tsx`, `**/*.spec.ts` | Jest patterns, coverage | -| build | `package.json`, `tsconfig*.json`, `vite.config.*`, `webpack.config.*` | Dependencies, scripts, bundler config | - -**Python:** - -| Group | Pattern | Focus | -|-------|---------|-------| -| modules | `**/*.py` (non-test) | Type hints, docstrings | -| tests | `**/test_*.py`, `**/*_test.py` | pytest patterns | -| configs | `**/config*.py`, `**/settings*.py` | Environment handling | -| build | `pyproject.toml`, `setup.py`, `setup.cfg`, `requirements*.txt` | Dependencies, tool configs | - -### Step 4.2: Spawn Experts (haiku per group) - -For each non-empty group, spawn parallel haiku agent: - -**Template:** - -``` -Task(subagent_type="Explore", model="haiku", prompt=" -## Standards Review - {EXPERT_TYPE} - -**Stack:** {STACK} -**SEARCH-FIRST:** Use grepai_search for finding existing code before flagging duplicates. - -**Files:** {FILE_LIST} - -**Project Rules:** -{RULES_CONTENT} - -**Stack Guidelines:** -{STACK_REFERENCE_CONTENT} - -**Output JSON:** -{ - \"changes\": [{ - \"location\": \"file:15-20\", - \"description\": \"...\", - \"existing\": \"path/to/similar|null\", - \"reuse\": \"REUSE|EXTEND|CONSIDER|KEEP_NEW\", - \"rating\": \"good|warning|bad\" - }], - \"violations\": [{ - \"file\": \"path\", - \"line\": 42, - \"rule\": \"avoid#5|best-practice#3|stack:entity-suffix\", - \"issue\": \"...\", - \"fix\": \"...\", - \"severity\": \"error|warning|info\" - }] -} -") -``` - ---- - -## Phase 5: Validation (sonnet) - -``` -Task(subagent_type="reviewer", model="sonnet", prompt=" -Validate EACH finding from expert analysis. -Read actual code at file:line locations. -Verify rule actually applies in context. - -**Findings:** {AGGREGATED_JSON} - -**Output:** [ - {\"id\": \"1\", \"verdict\": \"CONFIRM|REJECT\", \"reason\": \"...\"} -] -") -``` - -## Phase 6: Report - -### Create Report Directory - -```bash -TIMESTAMP=$(date +"%Y%m%d-%H%M%S") -REPORT_DIR=".claude/reports/${TIMESTAMP}_standards-review" -mkdir -p "${REPORT_DIR}" -``` - -### REPORT.md Structure - -```markdown -# Standards Review Report - -**Generated:** {TIMESTAMP} -**Stack:** {DETECTED_STACK} -**Scope:** {INPUT_TYPE} - {INPUT_VALUE} -**Files Reviewed:** {COUNT} - -## Summary - -| Category | Count | Severity | -|----------|-------|----------| -| Violations | X | Y errors, Z warnings | -| Reuse Opportunities | X | - | -| Good Patterns | X | - | - -## Violations - -### Errors - -| File | Line | Rule | Issue | Fix | -|------|------|------|-------|-----| -| path | 42 | avoid#5 | Description | Suggested fix | - -### Warnings - -| File | Line | Rule | Issue | Fix | -|------|------|------|-------|-----| - -## Reuse Opportunities - -| New Code | Existing | Similarity | Action | -|----------|----------|------------|--------| -| path:15-20 | util/X.java | 85% | EXTEND | - -## Good Patterns Found - -| File | Pattern | Description | -|------|---------|-------------| -| path | stream-api | Proper use of Stream API | - -## Reuse Statistics - -| Metric | Value | -|--------|-------| -| Total new code blocks | X | -| Reusable (>70%) | Y | -| Reuse rate | Z% | - -## Legend - -**Severity:** error (must fix), warning (should fix), info (consider) -**Reuse:** REUSE (import), EXTEND (modify existing), CONSIDER (evaluate), KEEP_NEW (justified) -**Rating:** good (exemplary), warning (suboptimal), bad (violation) -``` - -## Phase 7: Simplify Pass (conditional) - -**Execute ONLY if user answered "Yes" in Phase 0.** - -After Phase 6 report is written, invoke: - -``` -Skill(skill="simplify", args="{INPUT_VALUE}") -``` - -Where `{INPUT_VALUE}` is the same scope used in this review (commit, branch, or folder from Phase 2). - -> If user answered "No" in Phase 0 - skip this phase entirely. - -## Error Handling - -| Condition | Action | -|-----------|--------| -| No files found | Exit: "No files to review for {SCOPE}" | -| >50 files | Warn user, suggest narrowing scope | -| Unknown stack | Continue with project rules only | -| No rules found | Continue with stack reference only | -| All compliant | Report: "All code compliant with standards" | diff --git a/brewcode/skills/standards-review/references/java-kotlin.md b/brewcode/skills/standards-review/references/java-kotlin.md deleted file mode 100644 index 15896da..0000000 --- a/brewcode/skills/standards-review/references/java-kotlin.md +++ /dev/null @@ -1,223 +0,0 @@ -# Java/Kotlin Standards Reference - -Standards for Java/Kotlin enterprise projects. - -## File Patterns - -| Type | Patterns | -|------|----------| -| Source | `*.java`, `*.kt`, `*.kts` | -| Build | `pom.xml`, `build.gradle`, `build.gradle.kts` | -| Tests | `*Test.java`, `*Test.kt`, `*IT.java` | -| Config | `application.yml`, `application.properties` | - -## Naming Conventions - -### Classes - -| Type | Convention | Example | Verdict | -|------|------------|---------|---------| -| Entity | `*Entity` suffix | `UserEntity`, `OrderEntity` | ✅ REQ | -| DTO Response | `*Response` suffix | `UserResponse`, `OrderListResponse` | ✅ REQ | -| DTO Request | `*Request` suffix | `CreateUserRequest` | ✅ REQ | -| Repository | `*Repository` suffix | `UserRepository` | ✅ REQ | -| Service | `*Service` suffix | `UserService`, `OrderService` | ✅ REQ | -| Controller | `*Controller` suffix | `UserController` | ✅ REQ | - -### Methods - -| Pattern | Example | Status | -|---------|---------|--------| -| Verbs for actions | `createUser`, `findById` | ✅ | -| Boolean prefix | `isActive`, `hasPermission`, `canEdit` | ✅ | -| Stream operations | `toUserResponse`, `mapToEntity` | ✅ | - -## Dependency Injection - -| Rule | Evidence | Verdict | -|------|----------|---------| -| Constructor injection only | Spring recommends, testability | ✅ REQ | -| `@RequiredArgsConstructor` + final fields | Lombok best practice | ✅ REQ | -| No field injection (`@Autowired` on field) | Harder to test, hidden deps | ❌ VIOL | - -**Pattern:** -```java -@Service -@RequiredArgsConstructor -public class UserService { - private final UserRepository userRepository; // final + constructor - private final EmailService emailService; -} -``` - -## Stream API & Functional Style - -| Rule | Evidence | Verdict | -|------|----------|---------| -| Prefer Stream API over loops | Declarative, readable | ✅ REQ | -| Method references over lambdas | `User::getName` vs `u -> u.getName()` | ✅ PREF | -| No side effects in streams | Functional purity | ✅ REQ | -| `collect(Collectors.toList())` → `toList()` | Java 16+ | ✅ PREF | - -**Violations:** -```java -// ❌ Imperative loop -List names = new ArrayList<>(); -for (User user : users) { - names.add(user.getName()); -} - -// ✅ Stream API -List names = users.stream() - .map(User::getName) - .toList(); -``` - -## Immutability - -| Pattern | Usage | Verdict | -|---------|-------|---------| -| `final` fields | All fields unless mutation required | ✅ REQ | -| `List.of()`, `Set.of()`, `Map.of()` | Immutable collections | ✅ PREF | -| `@Value` (Lombok) | Immutable DTOs | ✅ PREF | -| `@Builder` | Complex object construction | ✅ PREF | - -## Library Usage Priority - -> Check existing libraries before writing utility code. - -| Priority | Library | Common APIs | -|----------|---------|-------------| -| 1 | JDK | `Objects`, `Optional`, `String`, `Math`, `Arrays`, `Collections`, `Files`, `Path` | -| 2 | Apache Commons | `StringUtils`, `CollectionUtils`, `Validate`, `FileUtils`, `IOUtils` | -| 3 | Guava | `Preconditions`, `Strings`, `Iterables`, `Lists`, `Maps`, `Multimap` | - -**Common JDK Utilities:** Null check → `Objects.requireNonNull(x, "msg")`, Empty → `str.isBlank()` / `collection.isEmpty()`, Null-safe equals → `Objects.equals(a, b)`, Optional chain → `Optional.ofNullable(x).map(...).orElse(...)` - -## Lombok Annotations - -| Annotation | Usage | Verdict | -|------------|-------|---------| -| `@Slf4j` | Logging | ✅ REQ | -| `@RequiredArgsConstructor` | DI | ✅ REQ | -| `@Builder` | Complex objects | ✅ PREF | -| `@Value` | Immutable DTOs | ✅ PREF | -| `@Data` | Mutable entities only | ⚠️ CAUTION | -| `@Getter/@Setter` | Fine-grained control | ✅ OK | - -## Logging - -| Rule | Evidence | Verdict | -|------|----------|---------| -| Use `@Slf4j` | Lombok, SLF4J facade | ✅ REQ | -| No `System.out.println()` | Not production-ready | ❌ VIOL | -| No logs in tests | Clutter, slow | ❌ VIOL | -| Main code: warn/error only | Performance | ✅ PREF | -| Parameterized logging | `log.info("User: {}", userId)` | ✅ REQ | - -## Test Patterns - -### Structure - -| Rule | Pattern | Verdict | -|------|---------|---------| -| BDD comments | `// GIVEN`, `// WHEN`, `// THEN` | ✅ REQ | -| `@DisplayName` on methods | Readable test names | ✅ REQ | -| No `@DisplayName` on class | Redundant | ✅ PREF | -| No Javadoc in tests | Unnecessary | ✅ REQ | - -### AssertJ - -| Pattern | Status | -|---------|--------| -| `.as("description")` on every assertion | ✅ REQ | -| `assertThat(x).isEqualTo(y)` | ✅ Specific value | -| `assertThat(list).hasSize(5)` | ✅ Specific count | -| `assertThat(x).isNotNull()` | ❌ Too weak | -| `assertThat(x).isNotEmpty()` | ❌ Too weak | -| `assertThat(x).isGreaterThanOrEqualTo(0)` | ❌ Too weak | -| `allSatisfy()` over `forEach` | ✅ REQ | -| `extracting().contains(tuple())` | ✅ For collections | - -**Violations:** -```java -// ❌ Too weak -assertThat(result).isNotNull(); -assertThat(list).isNotEmpty(); - -// ✅ Specific -assertThat(result).isEqualTo(expected); -assertThat(list).hasSize(3); -``` - -### No Conditionals - -| Rule | Evidence | Verdict | -|------|----------|---------| -| No `if` in tests | Unpredictable paths | ❌ VIOL | -| Assert preconditions first | Then unconditional assert | ✅ REQ | - -```java -// ❌ Conditional assertion -if (list.size() > 1) { - assertThat(list.get(1)).isEqualTo(expected); -} - -// ✅ Assert precondition, then assert -assertThat(list).as("precondition").hasSizeGreaterThan(1); -assertThat(list.get(1)).as("second element").isEqualTo(expected); -``` - -## Kotlin-Specific - -| Pattern | Usage | Verdict | -|---------|-------|---------| -| `data class` for DTOs | Immutable by default | ✅ REQ | -| Extension functions | Utility methods | ✅ PREF | -| `?.let {}` over null checks | Idiomatic | ✅ PREF | -| `Duration` conversion | `1.seconds.toJavaDuration()` | ✅ REQ | -| `when` over `if-else` chains | Exhaustive matching | ✅ PREF | - -## Spring Boot Patterns - -| Pattern | Description | Verdict | -|---------|-------------|---------| -| `@Transactional` on service | Not repository | ✅ REQ | -| `ResponseEntity` in controller | Proper HTTP responses | ✅ REQ | -| `@Valid` on request body | Input validation | ✅ REQ | -| Profile-specific config | `application-{profile}.yml` | ✅ REQ | - -## SQL in Code - -| Rule | Evidence | Verdict | -|------|----------|---------| -| No comments in SQL strings | Clutter logs | ✅ REQ | -| Use `.formatted()` | Java 15+ string formatting | ✅ PREF | -| Named parameters | `:paramName` in JPA | ✅ REQ | - -## Common Violations Summary - -| # | Violation | Fix | -|---|-----------|-----| -| 1 | Missing Entity suffix | Add `Entity` to JPA entities | -| 2 | Field injection | Use constructor injection | -| 3 | Loop instead of Stream | Convert to Stream API | -| 4 | `System.out.println` | Use `@Slf4j` | -| 5 | Missing `.as()` in test | Add description to assertion | -| 6 | `isNotNull()` assertion | Use specific value assertion | -| 7 | `if` in test | Assert precondition first | -| 8 | Writing utility that exists | Check JDK/Commons/Guava | -| 9 | Logs in tests | Remove all logging | -| 10 | `@Autowired` on field | Constructor injection | - -## Tools - -| Tool | Purpose | -|------|---------| -| Maven/Gradle | Build | -| Spring Boot | Framework | -| JUnit 5 | Testing | -| AssertJ | Assertions | -| Mockito | Mocking | -| Lombok | Boilerplate | -| WireMock | HTTP mocking | diff --git a/brewcode/skills/standards-review/references/python.md b/brewcode/skills/standards-review/references/python.md deleted file mode 100644 index df8483b..0000000 --- a/brewcode/skills/standards-review/references/python.md +++ /dev/null @@ -1,346 +0,0 @@ -# Python Standards Reference - -Standards for modern Python projects. - -## File Patterns - -| Type | Patterns | -|------|----------| -| Source | `*.py` | -| Tests | `test_*.py`, `*_test.py`, `**/tests/*.py` | -| Config | `pyproject.toml`, `setup.py`, `setup.cfg`, `requirements.txt` | -| Types | `py.typed`, `*.pyi` | - -## Type Hints - -### Required Annotations - -| Location | Requirement | Verdict | -|----------|-------------|---------| -| Function parameters | All params typed | ✅ REQ | -| Function returns | Return type annotated | ✅ REQ | -| Class attributes | Typed in `__init__` or class body | ✅ REQ | -| Module-level vars | Type annotation | ✅ PREF | - -**Pattern:** -```python -# ✅ Fully typed -def process_user(user_id: int, options: dict[str, Any] | None = None) -> User: - ... - -# ❌ Missing types -def process_user(user_id, options=None): - ... -``` - -### Common Type Patterns - -| Need | Type | Example | -|------|------|---------| -| Optional | `X | None` | `name: str | None` | -| List | `list[X]` | `items: list[str]` | -| Dict | `dict[K, V]` | `mapping: dict[str, int]` | -| Callable | `Callable[[Args], Return]` | `handler: Callable[[int], str]` | -| Any dict | `dict[str, Any]` | Config objects | -| Union | `X | Y` | `id: int | str` | - -> **Python 3.10+:** Use `X | Y` over `Union[X, Y]`, `list[X]` over `List[X]` - -## Docstrings - -### Required Locations - -| Location | Requirement | Verdict | -|----------|-------------|---------| -| Modules | Module-level docstring | ✅ REQ | -| Public classes | Class docstring | ✅ REQ | -| Public functions | Function docstring | ✅ REQ | -| Private (`_*`) | Optional | ⚠️ PREF | - -### Format (Google Style) - -```python -def fetch_user(user_id: int, include_profile: bool = False) -> User | None: - """Fetch user by ID from database. - - Args: - user_id: The unique identifier of the user. - include_profile: Whether to include full profile data. - - Returns: - User object if found, None otherwise. - - Raises: - DatabaseError: If database connection fails. - """ -``` - -## Naming Conventions - -| Type | Convention | Example | -|------|------------|---------| -| Modules | snake_case | `user_service.py` | -| Classes | PascalCase | `UserService` | -| Functions | snake_case | `get_user_by_id` | -| Constants | UPPER_SNAKE | `MAX_RETRIES` | -| Private | `_prefix` | `_internal_method` | -| Protected | `__prefix` | `__mangled_name` | - -## Imports - -### Order (isort) - -| Order | Type | Example | -|-------|------|---------| -| 1 | Standard library | `import os`, `from pathlib import Path` | -| 2 | Third-party | `import requests`, `from pydantic import BaseModel` | -| 3 | Local | `from .models import User`, `from myapp.utils import ...` | - -### Style - -| Rule | Evidence | Verdict | -|------|----------|---------| -| Absolute imports | Clarity | ✅ PREF | -| One import per line | Readability | ✅ PREF | -| No wildcard imports | Namespace pollution | ❌ VIOL | -| Group by package | Organization | ✅ REQ | - -```python -# ✅ Good -from collections.abc import Callable, Iterable -from pathlib import Path - -import httpx -from pydantic import BaseModel, Field - -from myapp.models import User -from myapp.utils import validate - -# ❌ Bad -from os import * -from myapp.utils import validate, parse, format, convert, transform -``` - -## Classes - -### Dataclasses - -| Rule | Evidence | Verdict | -|------|----------|---------| -| Use `@dataclass` for data | Less boilerplate | ✅ PREF | -| `frozen=True` for immutable | Thread safety | ✅ PREF | -| Pydantic for validation | Input validation | ✅ PREF | - -```python -# ✅ Dataclass -from dataclasses import dataclass - -@dataclass(frozen=True) -class User: - id: int - name: str - email: str | None = None - -# ✅ Pydantic (with validation) -from pydantic import BaseModel, EmailStr - -class UserCreate(BaseModel): - name: str - email: EmailStr -``` - -### No `__init__` Boilerplate - -| Pattern | When | Example | -|---------|------|---------| -| `@dataclass` | Simple data containers | Most DTOs | -| `pydantic.BaseModel` | Validation needed | API inputs | -| `attrs` | Advanced features | Complex models | - -## Error Handling - -### Exceptions - -| Rule | Evidence | Verdict | -|------|----------|---------| -| Custom exceptions | Clear error types | ✅ PREF | -| Specific catch | No bare `except:` | ✅ REQ | -| Chain exceptions | `raise X from e` | ✅ REQ | -| Context managers | Resource cleanup | ✅ REQ | - -```python -# ✅ Specific exception handling -try: - user = fetch_user(user_id) -except UserNotFoundError: - logger.warning(f"User {user_id} not found") - raise -except DatabaseError as e: - raise ServiceError("Database unavailable") from e - -# ❌ Bare except -try: - ... -except: # Catches everything including KeyboardInterrupt - pass -``` - -## Testing - -### pytest Patterns - -| Rule | Evidence | Verdict | -|------|----------|---------| -| pytest over unittest | Modern, less boilerplate | ✅ PREF | -| Fixtures for setup | Reusable, composable | ✅ REQ | -| Parametrize for variants | DRY testing | ✅ PREF | -| `conftest.py` for shared | Fixture organization | ✅ REQ | - -### Structure - -```python -# test_user_service.py - -import pytest -from myapp.services import UserService - -class TestUserService: - """Tests for UserService.""" - - def test_get_user_returns_user_when_exists(self, user_service: UserService, sample_user: User): - # GIVEN - user_id = sample_user.id - - # WHEN - result = user_service.get_user(user_id) - - # THEN - assert result is not None - assert result.id == user_id - assert result.name == sample_user.name - - def test_get_user_returns_none_when_not_found(self, user_service: UserService): - # GIVEN - nonexistent_id = 99999 - - # WHEN - result = user_service.get_user(nonexistent_id) - - # THEN - assert result is None -``` - -### Assertions - -| Pattern | Usage | Verdict | -|---------|-------|---------| -| `assert x == expected` | Equality | ✅ | -| `assert x is None` | None check | ✅ | -| `pytest.raises(Error)` | Exception testing | ✅ REQ | -| `pytest.approx(x)` | Float comparison | ✅ REQ | - -## Logging - -| Rule | Evidence | Verdict | -|------|----------|---------| -| Use `logging` module | Standard, configurable | ✅ REQ | -| No `print()` in prod | Not production-ready | ❌ VIOL | -| Lazy formatting | `log.info("User: %s", user_id)` | ✅ PREF | -| Logger per module | `logging.getLogger(__name__)` | ✅ REQ | - -```python -# ✅ Proper logging -import logging - -logger = logging.getLogger(__name__) - -def process(data: dict) -> None: - logger.info("Processing data: %s", data.get("id")) - # ... - logger.error("Failed to process: %s", error, exc_info=True) - -# ❌ Print statements -def process(data): - print(f"Processing {data}") -``` - -## Code Style - -### Line Length & Formatting - -| Tool | Purpose | Config | -|------|---------|--------| -| Black | Formatting | `pyproject.toml` | -| Ruff | Linting (fast) | `pyproject.toml` | -| isort | Import sorting | `pyproject.toml` | -| mypy | Type checking | `pyproject.toml` | - -### Comprehensions - -| Pattern | When | Verdict | -|---------|------|---------| -| List comprehension | Simple transforms | ✅ PREF | -| Generator expression | Large/lazy iteration | ✅ PREF | -| `map()`/`filter()` | Simple function application | ✅ OK | -| Multi-line for complex | >1 condition/transform | ✅ OK | - -```python -# ✅ Simple comprehension -names = [user.name for user in users if user.active] - -# ✅ Generator for large data -active_ids = (user.id for user in users if user.active) - -# ✅ Multi-line for complex -results = [ - transform(item) - for item in items - if item.valid - if item.score > threshold -] -``` - -## Common Violations Summary - -| # | Violation | Fix | -|---|-----------|-----| -| 1 | Missing type hints | Add parameter and return types | -| 2 | No docstring | Add Google-style docstring | -| 3 | Bare `except:` | Catch specific exceptions | -| 4 | `print()` in production | Use logging module | -| 5 | Wildcard import | Import specific names | -| 6 | Missing `from e` in reraise | Chain exceptions properly | -| 7 | Mutable default argument | Use `None` + conditional | -| 8 | No `__init__.py` | Add for package recognition | -| 9 | `Union[X, Y]` on 3.10+ | Use `X | Y` syntax | -| 10 | No type: ignore comment | Fix type error or add explanation | - -## Search Locations - -| Type | Paths | -|------|-------| -| Utils | `**/utils/`, `**/helpers/`, `**/lib/` | -| Models | `**/models/`, `**/schemas/`, `**/entities/` | -| Services | `**/services/`, `**/core/` | -| Tests | `**/tests/`, `test_*.py` | -| Config | `**/config/`, `**/settings/` | - -## Dependency Management - -| Tool | Config File | Verdict | -|------|-------------|---------| -| Poetry | `pyproject.toml` | ✅ PREF | -| pip-tools | `requirements.in` → `requirements.txt` | ✅ OK | -| pip | `requirements.txt` | ⚠️ BASIC | - -## Tools - -| Tool | Purpose | -|------|---------| -| pip/poetry | Package management | -| pytest | Testing | -| mypy | Type checking | -| Black | Formatting | -| Ruff | Fast linting | -| isort | Import sorting | -| coverage | Test coverage | diff --git a/brewcode/skills/standards-review/references/typescript-react.md b/brewcode/skills/standards-review/references/typescript-react.md deleted file mode 100644 index c1c57ec..0000000 --- a/brewcode/skills/standards-review/references/typescript-react.md +++ /dev/null @@ -1,268 +0,0 @@ -# TypeScript/React Standards Reference - -Standards for TypeScript/React projects. - -## File Patterns - -| Type | Patterns | -|------|----------| -| Components | `*.tsx`, `*.jsx` | -| Logic | `*.ts`, `*.js` | -| Styles | `*.styled.ts`, `**/styles.ts`, `*.css`, `*.scss` | -| Tests | `*.test.tsx`, `*.spec.ts`, `**/__tests__/*` | -| Config | `package.json`, `tsconfig.json`, `.eslintrc*` | - -## Component Patterns - -### Functional Components Only - -| Rule | Evidence | Verdict | -|------|----------|---------| -| Functional components | React 18+ standard | ✅ REQ | -| No class components | Legacy pattern | ❌ VIOLATION | -| Arrow functions for components | Consistent style | ✅ PREF | - -**Pattern:** -```typescript -// ✅ Functional component -const UserCard: React.FC = ({ user, onEdit }) => { - return
{user.name}
; -}; - -// ❌ Class component -class UserCard extends React.Component { ... } -``` - -### Component Structure - -| Order | Section | -|-------|---------| -| 1 | Type definitions (Props, State) | -| 2 | Component declaration | -| 3 | Hooks (useState, useEffect, custom) | -| 4 | Handlers (event handlers, callbacks) | -| 5 | Render helpers (if needed) | -| 6 | Return JSX | - -## Hooks - -### Built-in Hooks - -| Hook | Usage | Common Mistakes | -|------|-------|-----------------| -| `useState` | Local state | Over-using for derived state | -| `useEffect` | Side effects | Missing cleanup, deps array | -| `useMemo` | Expensive calculations | Premature optimization | -| `useCallback` | Stable callbacks | Over-using everywhere | -| `useRef` | DOM refs, mutable values | Using for state | - -### Custom Hooks - -| Rule | Evidence | Verdict | -|------|----------|---------| -| Extract reusable logic | DRY principle | ✅ REQ | -| `use*` prefix | React convention | ✅ REQ | -| Return object for >2 values | Destructuring clarity | ✅ PREF | - -**Check existing hooks before creating:** `hooks/` or `**/hooks/` directories, `use*.ts` files, grepai_search for similar functionality - -## Styling - -### Theme Tokens - -| Rule | Evidence | Verdict | -|------|----------|---------| -| Use theme tokens | Consistency, theming | ✅ REQ | -| No hardcoded colors | `#fff`, `rgb()` | ❌ VIOLATION | -| No hardcoded spacing | `8px`, `16px` | ❌ VIOLATION | -| No hardcoded fonts | `Arial`, `16px` | ❌ VIOLATION | - -**Violations:** -```typescript -// ❌ Hardcoded values -const Button = styled.button` - color: #3498db; - padding: 8px 16px; - font-size: 14px; -`; - -// ✅ Theme tokens -const Button = styled.button` - color: ${({ theme }) => theme.colors.primary}; - padding: ${({ theme }) => theme.spacing.sm} ${({ theme }) => theme.spacing.md}; - font-size: ${({ theme }) => theme.typography.body.size}; -`; -``` - -### Styled Components - -| Rule | Evidence | Verdict | -|------|----------|---------| -| Colocate styles | Component-scoped | ✅ PREF | -| Extend base components | Reuse patterns | ✅ REQ | -| Check `Components/Common/` | Avoid duplication | ✅ REQ | - -## TypeScript - -### Type Safety - -| Rule | Evidence | Verdict | -|------|----------|---------| -| Explicit prop types | Type safety | ✅ REQ | -| No `any` type | Type erasure | ❌ VIOLATION | -| `unknown` over `any` | Safe narrowing | ✅ PREF | -| Interface for objects | Extensible | ✅ PREF | -| Type for unions/primitives | Clarity | ✅ PREF | - -### Common Patterns - -```typescript -// ✅ Props interface -interface UserCardProps { - user: User; - onEdit?: (id: string) => void; - isLoading?: boolean; -} - -// ✅ Discriminated unions -type ApiResponse = - | { status: 'success'; data: T } - | { status: 'error'; error: string }; - -// ❌ Avoid any -const handleData = (data: any) => { ... } - -// ✅ Use unknown + narrowing -const handleData = (data: unknown) => { - if (isUser(data)) { ... } -}; -``` - -## State Management - -### Local vs Global - -| Scope | Solution | When | -|-------|----------|------| -| Component | `useState` | UI state, form inputs | -| Subtree | Context + `useReducer` | Theme, auth, localized state | -| Global | Redux/Zustand/Jotai | Cross-cutting, cached data | - -### Avoid Prop Drilling - -| Depth | Solution | -|-------|----------| -| 2-3 levels | Props OK | -| 4+ levels | Context or state management | - -## Testing - -### Jest + React Testing Library - -| Rule | Evidence | Verdict | -|------|----------|---------| -| Test behavior, not implementation | RTL philosophy | ✅ REQ | -| Query by role/label | Accessibility | ✅ PREF | -| `screen` over destructure | Clarity | ✅ PREF | -| `userEvent` over `fireEvent` | Realistic events | ✅ PREF | - -**Queries Priority:** - -| Priority | Query | When | -|----------|-------|------| -| 1 | `getByRole` | Buttons, inputs, headings | -| 2 | `getByLabelText` | Form fields | -| 3 | `getByText` | Static text | -| 4 | `getByTestId` | Last resort | - -### Test Structure - -```typescript -describe('UserCard', () => { - it('renders user name', () => { - // GIVEN - const user = { id: '1', name: 'John' }; - - // WHEN - render(); - - // THEN - expect(screen.getByText('John')).toBeInTheDocument(); - }); -}); -``` - -## Performance - -### Memoization - -| Pattern | When | Verdict | -|---------|------|---------| -| `React.memo` | Expensive render, stable props | ✅ AS NEEDED | -| `useMemo` | Expensive calculations | ✅ AS NEEDED | -| `useCallback` | Stable callback for child | ✅ AS NEEDED | - -> **Avoid premature optimization.** Profile first, optimize second. - -### Code Splitting - -| Pattern | Usage | -|---------|-------| -| `React.lazy()` | Route-level splitting | -| Dynamic imports | Feature modules | -| Suspense boundaries | Loading states | - -## Common Violations Summary - -| # | Violation | Fix | -|---|-----------|-----| -| 1 | Hardcoded colors | Use theme tokens | -| 2 | Class component | Convert to functional | -| 3 | Missing TypeScript types | Add explicit types | -| 4 | `any` type | Use `unknown` or specific type | -| 5 | Duplicate styled component | Check Common/, extend existing | -| 6 | Missing useEffect cleanup | Return cleanup function | -| 7 | Prop drilling >3 levels | Use Context | -| 8 | Testing implementation | Test behavior/output | -| 9 | No error boundary | Add for async components | -| 10 | Inline function in render | Extract to useCallback | - -## Search Locations - -| Type | Paths | -|------|-------| -| Common components | `**/components/common/`, `**/components/shared/` | -| Hooks | `**/hooks/`, `**/use*.ts` | -| Utils | `**/utils/`, `**/helpers/` | -| Types | `**/types/`, `**/*.types.ts` | -| Styles/Theme | `**/theme/`, `**/styles/` | - -## Function Declaration Style - -| Pattern | Usage | Verdict | -|---------|-------|---------| -| Arrow function | Components, callbacks | ✅ PREF | -| Function declaration | Hoisted utilities | ✅ OK | -| Consistent per file | Pick one style | ✅ REQ | - -## Import Order - -| Order | Type | -|-------|------| -| 1 | React | -| 2 | External libraries | -| 3 | Internal modules (absolute) | -| 4 | Relative imports | -| 5 | Styles/assets | - -## Tools - -| Tool | Purpose | -|------|---------| -| npm/yarn/pnpm | Package management | -| TypeScript | Type safety | -| ESLint | Linting | -| Prettier | Formatting | -| Jest | Testing | -| React Testing Library | Component testing | -| Storybook | Component docs | diff --git a/brewcode/skills/superreview/README.md b/brewcode/skills/superreview/README.md new file mode 100644 index 0000000..3cbcbf6 --- /dev/null +++ b/brewcode/skills/superreview/README.md @@ -0,0 +1,96 @@ +# brewcode:superreview + +A **HUMAN-invoked generator skill**. It analyzes a target project and writes a self-contained, project-local +`.claude/skills/superreview/` into that repo — a deep code-review skill that merges the old `review` and +`standards-review` into ONE pass. + +Like `skill-creator` and `task-board-init`, this skill produces a working artifact (a skill) rather than doing the +review itself. The **emitted** skill is the one that reviews code. + +## What it generates + +A project-tailored `superreview` skill modeled on the canonical finagra shape: + +1. **Deterministic MODE resolution** — `FULL_PROJECT | EXPLICIT | UNCOMMITTED | LAST_COMMITS`, computed (not guessed), + then ANNOUNCED (mode + branch + concrete scope + file count + focus) before any review. +2. **Domain routing** — each changed file routed to its project domain-owner agent (from `.claude/agents/`). +3. **Rule referencing** — points at the project's real `.claude/rules/*` + `.claude/convention/*` files; agents READ + and CITE them (never restated in the skill). +4. **ONE targeted parallel fan-out** — only the agents the changed files actually need, plus `{0,1,2}` general + cross-cutting agents by judgement. Far fewer spawns than a quorum + separate standards pass + arbiter. +5. **Per-finding adversarial VALIDATION gate** — one arbiter agent reverse-validates EVERY candidate, drops false + positives, then merges + de-dups + prioritizes. +6. **ONE merged P0-P3 report** at `.claude/reports/{TIMESTAMP}_superreview/REPORT.md`. **READ-ONLY** — it recommends + `/simplify` and a Manager-mode fix session; it never edits code. + +## How review + standards-review are merged + +| From | Folded in as | +|------|--------------| +| `review` engine | Canonical structure: deterministic mode, two-phase find->validate, merged report, agent contract | +| `standards-review` | Reuse/duplication focus (rank 3, 90/70/50% reuse matrix), stack detection, file-grouping, per-stack guidelines, `/simplify` hand-off | +| `setup` Phase 3.5 | Tech-specific check tables (Java/Node/Python/Go) folded into the per-stack reference docs; the placeholder->concrete generation mechanism | + +The finagra shape is the canonical structure; standards-review + the review template supply the per-stack checks, +reuse matrix, and report scaffolding baked into that shape. + +## Usage + +Run inside the repo you want to wire up: + +``` +/brewcode:superreview "" [scope] +``` + +- `` — what to emphasize in the emitted skill's focus ordering (e.g. "weight reuse highest", + "always treat auth as P0"). Woven into the emitted Focus table + emphasis line. +- `[scope]` — optional hint. + +Examples: + +``` +/brewcode:superreview "default ordering" +/brewcode:superreview "focus on architecture boundaries and reuse" +/brewcode:superreview "treat any security issue as P0" +``` + +After generation, run the emitted skill in that project: + +``` +/superreview "" [scope: commit|branch|folder] +``` + +## How it works (generator flow) + +| Phase | Action | +|-------|--------| +| 0 | Read the emit templates this skill ships (`references/`) | +| 1 | `generate.sh scan` + analysis: tech stack, build, test, DB, `.claude/agents`, rules/convention, source groups | +| 1.5 | AskUserQuestion for genuinely ambiguous params (arbiter agent, domain mapping, dominant stack) | +| 2 | Export scalar placeholders -> `generate.sh emit` (sed substitution, copies templates + chosen stack ref) | +| 3 | AI fills BLOCK placeholders (agent table, rule pointers, file-group map, focus table) via Edit | +| 4 | `generate.sh validate` — fail if any setup-time `{PLACEHOLDER}` remains | +| 5 | Report what was written | + +## Files + +| File | Role | +|------|------| +| `SKILL.md` | The generator orchestrator | +| `scripts/generate.sh` | `scan` / `emit` / `validate` | +| `references/SKILL.md.template` | The emitted finagra-shape SKILL.md (placeholder slots) | +| `references/agent-prompt.md` | Emitted domain-owner prompt contract | +| `references/report-template.md` | Emitted merged-report layout | +| `references/python.md` · `java-kotlin.md` · `typescript-react.md` · `go.md` | Per-stack reference docs (one emitted) | + +## Re-run triggers + +Regenerate when: a project agent is added/renamed, a rule/convention file changes, the stack changes, or a new source +group is added. Re-running re-wires the emitted skill to the current project shape. + +## Notes + +- The emitted skill is **self-contained** — no plugin dependency, no sibling-skill orchestration. It uses only + project-local agents (`.claude/agents/`) and built-in `Explore` / `reviewer`. +- Stack-generic: Java/Kotlin, Node/TypeScript, Python, Go. +- READ-ONLY by design: it reports, it does not fix. diff --git a/brewcode/skills/superreview/SKILL.md b/brewcode/skills/superreview/SKILL.md new file mode 100644 index 0000000..e0734b8 --- /dev/null +++ b/brewcode/skills/superreview/SKILL.md @@ -0,0 +1,233 @@ +--- +name: brewcode:superreview +description: "Generates a project-tailored deep-review skill (review+standards merged). Triggers: superreview, generate review skill" +user-invocable: true +argument-hint: " [scope]" +allowed-tools: Read, Write, Edit, Glob, Grep, Bash, Task, AskUserQuestion +model: opus +--- + +# Super Review Generator (brewcode:superreview) + +**ROLE:** GENERATOR. This skill is HUMAN-invoked. It analyzes the TARGET project, then WRITES a self-contained, +project-local `.claude/skills/superreview/` into that project — the merged deep-review skill (`review` + `standards-review` +folded into one). It does NOT review code itself; it EMITS the skill that does. + +**OUTPUT:** A project-local skill at `/.claude/skills/superreview/` (SKILL.md + references) modeled exactly on +the canonical finagra shape: deterministic MODE resolution -> ANNOUNCE -> route changed files to project domain-owner +agents -> reference (not restate) the project's `.claude/rules` + convention files -> ONE targeted parallel fan-out -> +per-finding adversarial VALIDATION gate -> ONE merged P0-P3 report at `.claude/reports/{TIMESTAMP}_superreview/REPORT.md`, +READ-ONLY (recommends `/simplify`, never edits). + +> Like `skill-creator` / `task-board-init`: a multi-step analysis that deploys a working artifact into ANY repo. +> The emitted skill is generic-capable (Java/Kotlin, Node/TS, Python, Go) and self-contained — NO plugin dependency, +> NO sibling-skill orchestration once generated. + +**Arguments:** `$ARGUMENTS` — `` (free text: what to emphasize in the emitted skill's focus ordering) +plus optional `[scope]` hint. The fine-tune prompt is woven into the emitted skill's Focus ordering + emphasis. + +--- + +## What the emitted skill merges (review + standards-review) + +| Source | What it contributes to the emitted skill | +|--------|------------------------------------------| +| `review` engine | Canonical STRUCTURE: deterministic mode, two-phase **find -> validate**, single merged P0-P3 report, agent prompt contract, report scaffolding | +| `standards-review` | The **reuse/duplication** focus (rank 3: search-first 90/70/50% reuse matrix), tech-stack detection, file-grouping-by-type, per-stack reviewer guidelines, `/simplify` hand-off | +| `setup` Phase 3.5 | Tech-specific check tables (Java/Node/Python/Go) folded into the per-stack reference docs; the placeholder -> concrete generation mechanism | + +> Reconcile rule: the **finagra shape is the canonical structure**; `standards-review` + the `review` template supply +> the per-stack checks, the reuse matrix, and the report scaffolding that get baked INTO that shape. + +--- + +## Execution + +### Phase 0 — Pre-analysis (read THIS skill's emit material) + +1. Read the emit templates this generator ships (relative to `${CLAUDE_SKILL_DIR}`): + - `references/SKILL.md.template` — the finagra-shape emitted SKILL.md (with `{PLACEHOLDER}` slots) + - `references/agent-prompt.md` — domain-owner agent prompt contract (emitted verbatim, scalar-substituted) + - `references/report-template.md` — emitted report layout + - `references/{python,java-kotlin,typescript-react,go}.md` — per-stack reference docs (one is emitted) +2. Confirm the TARGET project is the current working directory (the repo to be reviewed). All emitted paths are + relative to that repo root. + +### Phase 1 — Analyze the TARGET project + +Gather everything the emitted skill must be wired to. Prefer `grepai_search` first for code exploration; fall back to +Bash search (`grep`->ugrep / `find`->bfs on macOS CC). + +**EXECUTE** using Bash tool (project scan): +```bash +bash "${CLAUDE_SKILL_DIR}/scripts/generate.sh" scan && echo "✅ scan" || echo "❌ scan FAILED" +``` + +The scan reports: build files, `.claude/agents/*`, `.claude/rules/*` + `.claude/convention/*`, test dirs, source dirs. +From it (plus your own reads) determine: + +| Aspect | How to detect | Drives placeholder | +|--------|---------------|--------------------| +| Tech stack | build files: `pom.xml`/`build.gradle*` -> Java/Kotlin; `package.json`+react/ts -> Node/TS; `pyproject.toml`/`requirements*.txt` -> Python; `go.mod` -> Go | `STACK_LABEL`, `STACK_REF`, `SOURCE_GLOB`, `PATHSPEC_GLOBS` | +| Project agents | `.claude/agents/*.md` (name + description); map each to the path group it owns | `DOMAIN_AGENTS_TABLE`, `FILE_GROUP_MAP`, `GENERAL_AGENTS_TABLE` | +| Arbiter / validator | an architecture/reviewer agent in `.claude/agents/`, else built-in `general-purpose` | `ARBITER_AGENT`, `VALIDATOR_AGENT` | +| Rule + convention files | `.claude/rules/*.md` + `.claude/convention/*.md` + `CLAUDE.md` | `RULE_POINTER_TABLE`, `RULE_PREFLIGHT_LIST` | +| Source path groups | top-level source dirs / service dirs / module layout | `FILE_GROUP_MAP` | +| DB / test stack | testcontainers, JPA/JOOQ, pytest, jest, etc. | folded into the per-stack reference note | + +**Multi-stack repos:** if more than one stack is detected, pick the DOMINANT one for the emitted `STACK_REF`, and note +the secondary stack(s) in `DOMAIN_AGENTS_TABLE` / `FILE_GROUP_MAP`. (One stack reference doc is emitted; the rule +pointers cover the rest.) + +### Phase 1.5 — Clarify genuinely ambiguous params (AskUserQuestion) + +Use AskUserQuestion ONLY for params you cannot reliably infer. Never auto-guess a non-obvious choice. Typical questions: + +- Which agent is the **architecture arbiter / Phase-3 validator** when several plausible reviewer/architect agents exist. +- The **domain-owner mapping** when an agent's owned path group is unclear. +- Whether to include a **general second-pass agent** mapping (built-in `general-purpose`) when no project reviewer exists. +- Confirm the **dominant stack** when the repo is genuinely multi-stack. + +> Weave the `` argument into the emitted Focus ordering: if the user said "focus on X / weight Y +> higher", reorder/emphasize the emitted `FOCUS_TABLE` accordingly (e.g. push security to P0-always, or raise reuse to +> rank 1). Record the emphasis in `FOCUS_EMPHASIS`. + +### Phase 2 — Resolve placeholders + emit (scalar substitution) + +Export the SCALAR placeholder values, then run the emit step (mirrors `setup.sh copy_review_skill()` — sed with a +control-char separator; values MUST be single-line): + +```bash +export PROJECT_NAME="" +export STACK_LABEL="" +export STACK_REF="" +export SOURCE_GLOB="<*.py | *.java | *.ts | *.go ...>" +export PATHSPEC_GLOBS="<'*.py' 'requirements*.txt' 'pyproject.toml' 'Dockerfile*' 'docker-compose.yml' '.github/workflows/*.yml'>" +export ARBITER_AGENT="" +export VALIDATOR_AGENT="" +``` + +**EXECUTE** using Bash tool: +```bash +bash "${CLAUDE_SKILL_DIR}/scripts/generate.sh" emit && echo "✅ emit" || echo "❌ emit FAILED" +``` + +> **STOP if ❌** — verify `${CLAUDE_SKILL_DIR}/references/SKILL.md.template` exists and the target `.claude/` is writable. + +This writes `/.claude/skills/superreview/SKILL.md` (scalars substituted), copies `agent-prompt.md` + +`report-template.md` (scalar-substituted), and copies the chosen `${STACK_REF}` into the emitted `references/`. + +### Phase 3 — Adapt the BLOCK placeholders (AI Edit) + +Multi-row tables cannot go through sed (newlines). Using the **Edit** tool, replace each block placeholder in the +EMITTED `/.claude/skills/superreview/SKILL.md` with a table you build from Phase 1 analysis: + +| Block placeholder | Replace with | +|-------------------|--------------| +| `{DOMAIN_AGENTS_TABLE}` | one row per project agent: `\| \| Domain owner — : \|` (built-in `Explore` as graceful fallback row) | +| `{GENERAL_AGENTS_TABLE}` | the `{0,1,2}` cross-cutting agents: `` (quality/correctness 2nd pass) + `` (boundary/architecture arbiter + Phase-3 validator), each with an "include WHEN" rule | +| `{RULE_POINTER_TABLE}` | one row per real `.claude/rules/*.md` + `.claude/convention/*.md`: `\| \| \|` — REFERENCE, never restate | +| `{RULE_PREFLIGHT_LIST}` | the bash `for f in ...; do [ -f "$f" ] || echo "WARN missing rule: $f"; done` listing the SAME real rule files | +| `{FILE_GROUP_MAP}` | one row per source group: `\| \| \| \|` mapping each group to its domain owner; tests group -> the test agent (with test-bloat audit); build group -> the CI/build agent | +| `{FOCUS_TABLE}` | the ranked focus ordering (default: 1 correctness, 2 architecture/boundary, 3 reuse, 4 version pins, 5 business-reqs), REORDERED per the `` | +| `{FOCUS_EMPHASIS}` | one-line note capturing the fine-tune-prompt emphasis (or "default ordering" if none) | +| `{SIMPLIFY_AGENTS}` | comma list of the domain-owner agents the fix-session should delegate to | + +> Keep every emitted row pointing at a REAL agent (`.claude/agents/` or built-in `Explore`/`Plan`/`general-purpose`) and a REAL rule +> file. Do NOT invent agents or rules. Built-in `Explore` is the only allowed fallback for an unavailable domain agent. + +### Phase 4 — Validate (NO `{PLACEHOLDER}` may remain) + +**EXECUTE** using Bash tool: +```bash +bash "${CLAUDE_SKILL_DIR}/scripts/generate.sh" validate && echo "✅ validate" || echo "❌ validate FAILED" +``` + +> **STOP if ❌** — the script lists any unresolved setup-time `{PLACEHOLDER}` left in the emitted SKILL.md / references +> (runtime tokens like `{MODE}`, `{COUNT}`, `{FILE_LIST}` are allow-listed and expected to remain). Go back to Phase 3 +> and Edit the leftovers, then re-run validate. + +### Phase 5 — Report + +Print the generation summary: + +``` +superreview generated -> /.claude/skills/superreview/ + +Stack: {STACK_LABEL} (reference: {STACK_REF}) +Domain agents wired: {N} ({list}) +General agents: {reviewer?}, {ARBITER_AGENT} (arbiter + validator) +Rule pointers: {N} files referenced (not restated) +File groups: {N} ({group->agent}) +Focus: {resolved ordering — fine-tune: } + +Files written: +- .claude/skills/superreview/SKILL.md +- .claude/skills/superreview/references/agent-prompt.md +- .claude/skills/superreview/references/report-template.md +- .claude/skills/superreview/references/{STACK_REF} + +Run it: /superreview "" [scope] (in the target project) +``` + +--- + +## How the emitted skill behaves (what you are generating) + +Recap of the canonical shape the emitted SKILL.md implements (full text in `references/SKILL.md.template`): + +| Phase | Behavior | +|-------|----------| +| Mode detection | Deterministic `FULL_PROJECT \| EXPLICIT \| UNCOMMITTED \| LAST_COMMITS`, COMPUTED not guessed; then ANNOUNCE mode+branch+scope+count+focus BEFORE any review | +| Routing | Group changed files by path; enable ONLY non-empty groups; route each to its domain-owner agent; add `{0,1,2}` general agents by judgement | +| Fan-out | ONE parallel message with the selected agents (find phase); each returns the shared JSON finding contract; search-first before flagging reuse/duplication | +| Validation | ONE arbiter agent reverse-validates EVERY candidate (adversarial, per-finding gate), merges + de-dups + prioritizes P0-P3 | +| Report | ONE merged report at `.claude/reports/{TIMESTAMP}_superreview/REPORT.md`, sorted P0->P3; READ-ONLY; recommends `/simplify` + a Manager-mode fix session; never edits code | + +--- + +## Configuration + +| Setting | Default | Description | +|---------|---------|-------------| +| Emit target | `/.claude/skills/superreview/` | Where the generated skill is written | +| Emit templates | `${CLAUDE_SKILL_DIR}/references/` | Source templates for the generation | +| Generation script | `${CLAUDE_SKILL_DIR}/scripts/generate.sh` | `scan` \| `emit` \| `validate` | +| Stack reference | one of `python.md \| java-kotlin.md \| typescript-react.md \| go.md` | Emitted per the dominant detected stack | +| Block placeholders | AI-filled (Edit) | Tables that cannot go through sed; validated post-emit | + +--- + +## Error Handling + +| Condition | Action | +|-----------|--------| +| No `.claude/agents/` in target | Emit with built-in `general-purpose` + `Explore` only; warn the user the routing is generic | +| No `.claude/rules/`/`.claude/convention/` | Emit a minimal rule-pointer table (`CLAUDE.md` only); WARN; the emitted skill degrades gracefully (preflight WARN) | +| Unknown / unsupported stack | Emit with the closest per-stack ref + project rules only; warn | +| Multi-stack repo | Pick dominant stack for `STACK_REF`; note secondaries in the agent/group tables | +| Unresolved `{PLACEHOLDER}` after Phase 3 | `validate` fails listing them; fix via Edit, re-run validate | +| Target `.claude/` not writable | STOP — ask the user to run from the repo root | + +--- + +## References + +- `references/SKILL.md.template` — the finagra-shape emitted SKILL.md (placeholder slots). +- `references/agent-prompt.md` — domain-owner agent prompt contract (emitted). +- `references/report-template.md` — emitted merged-report layout. +- `references/{python,java-kotlin,typescript-react,go}.md` — per-stack reference docs (one is emitted). +- `scripts/generate.sh` — `scan` / `emit` / `validate`. + + diff --git a/brewcode/skills/superreview/references/SKILL.md.template b/brewcode/skills/superreview/references/SKILL.md.template new file mode 100644 index 0000000..60f8e8f --- /dev/null +++ b/brewcode/skills/superreview/references/SKILL.md.template @@ -0,0 +1,400 @@ +--- +name: superreview +description: "Deep {PROJECT_NAME} code review the MODEL or the USER can invoke: routes changed files to domain-owner agents, checks correctness + architecture + reuse + version pins against the project rules, reverse-validates every finding, writes one merged report. Triggers: review code, deep review, superreview, super review, validate changes, check architecture, check standards, check reuse." +user-invocable: true +argument-hint: " [scope: commit|branch|folder]" +allowed-tools: Read, Glob, Grep, Task, Bash, Write, AskUserQuestion +model: opus +--- + +# Super Review ({PROJECT_NAME}) + +**ROLE:** Self-contained deep-review coordinator + final validator. +**OUTPUT:** ONE merged, de-duplicated, severity-prioritized, validated report. + +The most thorough review in this repo, run INLINE — no sibling skills, no plugin dependency. It: + +0. **deterministically resolves ONE review MODE** and ANNOUNCES it to the user (mode + branch + concrete scope) + BEFORE any review work — no interactive guessing, +1. routes each changed file to its **domain-owner agent** (uses project agents to the MAX), +2. checks **functional correctness + architecture + reuse + version pins + business-requirements** against the + focus ordering below (folds in the old standards-review + review essence), +3. runs a **single, targeted, parallel fan-out** — only the agents the changed files actually need (FEWER spawns + than a multi-vote quorum + a separate standards pass + a separate arbiter), +4. ends with a **VALIDATION phase**: a per-finding adversarial double-check that re-verifies EVERY candidate is + REAL (rejects false positives) BEFORE it lands in the report, then merges + checks consistency. + +> Two-phase by design: **find -> validate**. Only findings that survive per-finding reverse-validation are reported. + +All agents are project-local (`.claude/agents/`) or a built-in (`Explore`/`Plan`/`general-purpose`). This skill +never invokes any sibling skill, NO plugin cache; the validator/arbiter fallback is the +built-in `general-purpose`. + +--- + +## Mode Detection (deterministic — run FIRST, then ANNOUNCE) + +**Arguments:** `$ARGUMENTS` + +At launch, resolve EXACTLY ONE review `{MODE}` by the strict priority order below, then PRINT the resolved mode + +current branch + concrete scope to the user BEFORE any review. The mode is COMPUTED, never guessed interactively; +the same rule applies on `master`/`main` and on feature branches. + +| # | Condition (checked in order) | Resolved `{MODE}` | Scope reviewed | +|---|------------------------------|-------------------|----------------| +| 1 | User prompt asks for the WHOLE project, in any language ("whole project", "entire project", "everything", "all the code", or the same intent in another language) | `FULL_PROJECT` | ALL tracked `{SOURCE_GLOB}` + build/CI files in the repo | +| 2 | User passed an explicit scope token (commit SHA, branch name, or folder path) | `EXPLICIT` | that commit / branch-vs-main / folder | +| 3a | DEFAULT + working tree has UNCOMMITTED changes (`git status --porcelain` non-empty) | `UNCOMMITTED` | working-tree diff vs `HEAD` | +| 3b | DEFAULT + clean tree (everything committed) | `LAST_COMMITS` | last 1-2 commits: `HEAD~2..HEAD` if it exists, else `HEAD~1..HEAD`, else the single root commit | + +> A text prompt that is NOT a whole-project request and NOT a scope token is treated as a `{FOCUS}` directive +> (see Focus below); the mode still resolves via rule 3. + +**Mode-resolution commands** (runnable as-written; `PATHSPEC` = the file globs every mode reviews): + +```bash +PATHSPEC=({PATHSPEC_GLOBS}) + +BRANCH=$(git rev-parse --abbrev-ref HEAD) +PORCELAIN=$(git status --porcelain) +# robust MAIN fallback: the `|| echo main` must bind to git, not sed +MAIN=$(git symbolic-ref --short refs/remotes/origin/HEAD 2>/dev/null); MAIN=${MAIN##*/}; MAIN=${MAIN:-main} + +# Resolve FILES for the chosen mode, then derive an EXACT count (no head-truncation of the count). +# FULL_PROJECT (rule 1): all tracked source + build/CI files +FILES=$(git ls-files -- "${PATHSPEC[@]}") + +# EXPLICIT commit (rule 2): FILES=$(git diff --name-only "${SHA}^..${SHA}" -- "${PATHSPEC[@]}") +# EXPLICIT branch (rule 2): FILES=$(git diff --name-only "${MAIN}...HEAD" -- "${PATHSPEC[@]}") +# EXPLICIT folder (rule 2): build files are included too, not just source +# FILES=$(find "$FOLDER" -type f \( -name '{SOURCE_GLOB}' -o -name 'Dockerfile*' -o -name 'docker-compose.yml' -o -name '*.yml' \)) + +# UNCOMMITTED (rule 3a): working-tree diff vs HEAD (staged + unstaged) +# FILES=$(git diff --name-only HEAD -- "${PATHSPEC[@]}") + +# LAST_COMMITS (rule 3b): nested fallback so a single-commit repo never errors +# if HEAD~2 exists -> HEAD~2..HEAD ; elif HEAD~1 exists -> HEAD~1..HEAD ; else the single root commit +# if git rev-parse --verify -q HEAD~2 >/dev/null; then +# FILES=$(git diff --name-only "HEAD~2..HEAD" -- "${PATHSPEC[@]}") +# elif git rev-parse --verify -q HEAD~1 >/dev/null; then +# FILES=$(git diff --name-only "HEAD~1..HEAD" -- "${PATHSPEC[@]}") +# else +# FILES=$(git show --name-only --pretty="" HEAD -- "${PATHSPEC[@]}") # root commit +# fi + +# EXACT count for the mandatory announcement (count, never the displayed list, is truncated): +COUNT=$(printf '%s\n' "$FILES" | grep -c .) +echo "$FILES" | head -50 # DISPLAY only — truncating the shown list is fine; COUNT above stays exact +``` + +**MANDATORY announcement to the user (before reviewing):** + +``` +superreview MODE = {MODE} +Branch: {BRANCH} +Scope: {commit range | branch-vs-main | folder path | working-tree diff vs HEAD | full project} +Files: {COUNT} ({list, or "see range"}) +Focus: {resolved focus — user directive, else default ordering} +``` + +--- + +## Focus (user directive, else default ordering) + +If the user passed a focus directive in the prompt ("focus on X"), PRIORITIZE it. Otherwise use this DEFAULT focus +order (highest first). Bake this exact ordering into BOTH the shared agent prompt and the validator prompt. + +{FOCUS_TABLE} + +> **Project emphasis:** {FOCUS_EMPHASIS} + +> **Security is explicitly NOT a priority.** Report a security finding ONLY when it is CRITICAL (P0) — e.g. logged +> secret, missing auth on a public path, injection. Do NOT spend agent effort on low/medium security. + +--- + +## Project Agents (project-local + built-in ONLY) + +> Every `subagent_type` below resolves to a real file in `.claude/agents/`, or a built-in (`Explore`/`Plan`/`general-purpose`). +> Do NOT pass a `model` override to project agents — they define their own. NO external/plugin agent is referenced. + +{DOMAIN_AGENTS_TABLE} + +PLUS up to two GENERAL cross-cutting agents — they are NOT auto-spawned every time; **the model DECIDES** whether +(and which) to include, by JUDGEMENT of the scope. Each, if included, runs ONCE over the full changed set: + +{GENERAL_AGENTS_TABLE} + +> For a SMALL, single-domain, low-risk change, the model MAY skip one or BOTH general agents and rely on the +> domain owner alone. Do NOT spawn them reflexively — include only when the guidance above applies. + +--- + +## {PROJECT_NAME} rules — REFERENCE the canonical files, do NOT restate them + +The project rules are authoritative in their own files; this skill does NOT duplicate them. Every agent READS the +files relevant to its area and CITES the rule number it enforces (`avoid#N`, `architecture#N`, `containers#N`, …). +One-line gist per pointer only — the file is the authority. Phase 0 PREFLIGHT-validates that these exist (see below). + +{RULE_POINTER_TABLE} + +> `CLAUDE.md` (+ any per-module `CLAUDE.md`) auto-load and add project context. +> Breach of any cited rule = P0/P1 candidate (per the Focus ordering; security only as P0). + +--- + +## Execution + +### Phase 0 — Preflight, Resolve MODE, ANNOUNCE, read references + +1. **PREFLIGHT — validate the rule files before relying on them.** Verify the canonical rule/convention files + referenced above EXIST; WARN per missing file and degrade gracefully (do NOT hard-fail): + +```bash +{RULE_PREFLIGHT_LIST} +``` + +2. **Resolve `{MODE}` + `{FOCUS}`** per the **Mode Detection** and **Focus** sections above (deterministic; not + interactive). Run the mode-resolution commands to get `{BRANCH}`, `{SCOPE}`, the `FILES` list, and EXACT `COUNT`. +3. Compute a single `TIMESTAMP` for the report dir: + +```bash +TIMESTAMP=$(date +"%Y%m%d-%H%M%S") +``` + +4. **ANNOUNCE to the user** (MANDATORY, before any review) the resolved mode block — `{COUNT}` is the EXACT count + computed in Mode Detection (never truncated); include any `WARN missing rule` lines: + +``` +superreview MODE = {MODE} +Branch: {BRANCH} +Scope: {commit range | branch-vs-main | folder | working-tree diff vs HEAD | full project} +Files: {COUNT} ({displayed list — may be truncated; COUNT stays exact}) +Focus: {resolved focus — user directive, else default ordering} +Rules preflight: {OK | "WARN missing: "} +``` + +5. **READ** `references/{STACK_REF}` (relative to this skill dir) — {STACK_LABEL} stack guidelines passed to every + agent. Also note `references/agent-prompt.md` (the domain-owner prompt contract). +6. If `FILES` is empty (`COUNT == 0`) -> **exit** ("Nothing to deep-review for {MODE} / {SCOPE}."). +7. If `COUNT > 50` (and `{MODE}` != `FULL_PROJECT`) -> warn the user; suggest narrowing (per-folder or per-commit). + For `FULL_PROJECT`, proceed but warn it is a large, slower pass. +8. Optionally study context with a few parallel read-only `Explore` agents (changed-file modules + `.claude/rules/**`). + This is context only, NOT findings. + +### Phase 1 — Agent selection (route changed files to domain owners) + +Group the `{FILE_LIST}` by path. **Enable ONLY the groups whose files actually changed** — this is the key +"fewer agents" constraint: ONE targeted spawn per relevant group, NOT a quorum × N + a separate full standards pass. + +{FILE_GROUP_MAP} + +PLUS up to two GENERAL cross-cutting agents (see **Project Agents** above). They are NOT auto-spawned every time; +**the model DECIDES** whether (and which) to include, by JUDGEMENT of the scope. Each, if included, runs ONCE over +the full changed set (not per group). + +> Total spawns = (number of NON-EMPTY domain groups) + **{0, 1, or 2} general agents (model's call)**. +> Examples: a tiny single-file tweak = its domain owner alone (**1 agent**); a change with non-trivial logic = +> domain owner + `{VALIDATOR_AGENT}` (**2**); a change spanning multiple domains/abstractions = both domain owners + +> `{ARBITER_AGENT}` (+ `{VALIDATOR_AGENT}` if logic is risky) (**3-4**). Far fewer than the old quorum + standards + arbiter +> combo. If a mapped domain agent is unavailable, fall back to built-in `Explore`; note it in the report. + +> **Test-bloat audit:** when the `tests` group is non-empty, its prompt MUST also audit for TEST OVER-PROLIFERATION +> (LLMs over-write tests) — cite the project `testing` rule, do NOT restate it. Flag, as `category: test-quality`: +> redundant tests to DELETE (duplicate coverage, trivial getters, internal-mock-only tests); tests to COLLAPSE/MERGE +> or PARAMETRIZE via HELPER FUNCTIONS; over-granular micro-tests violating "FEW targeted scenario tests over BIG user +> journeys". **NON-NEGOTIABLE:** reducing test COUNT must NOT cost quality — every remaining/merged test stays +> ISOLATED + FAST + REAL (fakes-over-mocks). Also flag any slow or non-isolated test as its own finding; never +> recommend a merge that makes a test slow or non-isolated. Full prompt text in `references/agent-prompt.md`. + +### Phase 2 — ONE parallel fan-out (find candidates) + +Spawn ALL selected agents (the non-empty domain owners + whichever general agents the model chose in Phase 1) in +**ONE message** (parallel). Use the prompt contract in `references/agent-prompt.md`: pass `{FILE_LIST}` (scoped to that +group for domain owners; full set for any included general agent), the resolved `{FOCUS}`, and the +`references/{STACK_REF}` guidelines. Each prompt MUST instruct the agent to **apply `.claude/rules/*` + +`.claude/convention/*` for its area and CITE the rule number it enforces** — the skill does NOT restate the rules; the +agents read the canonical files. Each prompt MUST also embed the focus ordering verbatim so agents spend effort in +priority order, and **report security findings ONLY when CRITICAL (P0)**. Each prompt MUST also include the +**over-complexity / over-engineering** dimension: flag speculative abstractions, needless params/config/methods "just +in case", premature generalization, KISS/YAGNI-removable indirection, and duplicated logic to collapse — `category: +over-complexity`, citing the project best-practices + avoid rules. Every agent returns the SAME JSON shape: + +``` +{ + "findings": [{ + "file": "path/to/file{SOURCE_GLOB}", "lineStart": 42, "lineEnd": 45, + "category": "boundary|architecture|reuse|over-complexity|security|logic|persistence|test-quality|pins|style", + "severity": "blocker|critical|major|minor", + "rule": "avoid#N|best-practices#N|architecture#N|containers#N|... or null", + "title": "...", "description": "...", "suggestion": "...", + "existing": "path|null", "reuse": "REUSE|EXTEND|CONSIDER|KEEP_NEW|null", + "confidence": 0.85 + }] +} +``` + +Each agent MUST search-first (grep / verify imports, prefer `mcp__grepai__search` if available) before flagging any +reuse/duplicate, and read the ACTUAL code at every cited line. Collect every agent's findings into one pool +`{CANDIDATES}` (tag each finding with its producing agent as `source`). + +### Phase 3 — VALIDATION (per-finding adversarial reverse-check, the GATE) + +Spawn ONE `{VALIDATOR_AGENT}` that **independently RE-VERIFIES EVERY candidate finding in reverse** against the real +code BEFORE anything reaches the user report, AND merges the survivors into one consistent, de-duplicated, prioritized +list. This is a per-finding gate, NOT a sample: a finding reaches the report ONLY after it survives reverse-validation. + +``` +Task(subagent_type="{VALIDATOR_AGENT}", prompt=" +## superreview — per-finding VALIDATION + Merge ({PROJECT_NAME}) + +You are the adversarial validator + final arbiter. For EVERY candidate finding (no sampling, no skipping), +READ the ACTUAL code at the cited file:line and try to DISPROVE it. Decide CONFIRM or REJECT per finding. Only +CONFIRMed findings may appear in the final report. Then merge the survivors. + +**Focus ordering (effort + tie-breaks, highest first):** {FOCUS} + Security = report ONLY if CRITICAL (P0); ignore low/medium. + Also validate OVER-COMPLEXITY findings (category over-complexity): speculative abstraction, gold-plating, + premature generalization, KISS/YAGNI-removable indirection, collapsible duplication. Keep them (with the simpler + shape) when real; drop if the complexity is justified. + +**Candidate findings (pool from the domain owners + any included general agents):** +{CANDIDATES} +**Files under review:** {FILE_LIST} +**Focus:** {FOCUS} + +### 1. Reverse-validate EACH candidate (per finding — drop false positives) + a. Existence — does the cited code/line actually exist and exhibit the issue NOW? (REJECT if not / already fixed) + b. Accuracy — is the claim a correct reading of the code? (REJECT if it misreads the code) + c. Actionability — is there a concrete fix path? (REJECT if vague / not actionable) + d. Severity — is the severity right for the focus ordering? (adjust if wrong) + Adversarial: actively argue AGAINST the finding first. It survives ONLY if it withstands a-d. Do this for every + single candidate; none is reported unverified. + +### 2. Merge + de-duplicate ACROSS agents + Same file +/-5 lines + same category = ONE finding. Keep the most detailed description, highest severity, + union of sources (comma-join). A 'duplicate/reuse' miss + an 'architecture' flag on the same code = one row. + +### 3. Prioritize (MANDATORY P0 -> P3) + - P0 = architecture/boundary BLOCKERS + CRITICAL security (logged secret, missing auth, injection) + any miss you RESTORE. + - P1 = confirmed functional-correctness + architecture/boundary issues. + - P2 = reuse misses/duplication + over-complexity + library version-pin violations rated 'error'. + - P3 = business-requirements nits + minor over-complexity + warnings + minor/info. + +### 4. Consistency check on the merged list + No duplicate rows, severities monotonic with priority, every row has file:line + actionable suggestion, + findings ORDERED P0 -> P3. + +**Output JSON ONLY:** +{ + \"findings\": [{ + \"id\": \"P0-1\", \"priority\": \"P0|P1|P2|P3\", \"source\": \"agent(s)\", + \"file\": \"path\", \"lineStart\": 42, \"lineEnd\": 45, + \"category\": \"boundary|architecture|reuse|over-complexity|security|logic|persistence|test-quality|pins|style\", + \"severity\": \"blocker|critical|major|minor\", + \"title\": \"...\", \"description\": \"...\", \"suggestion\": \"...\", + \"existing\": \"path|null\", \"reuse\": \"REUSE|EXTEND|CONSIDER|KEEP_NEW|null\", + \"verdict\": \"CONFIRM\", \"confidence\": 0.9 + }], + \"dropped\": [{\"title\": \"...\", \"reason\": \"already-fixed|false-positive|not-actionable|duplicate-of:P0-1\"}], + \"verdict\": \"APPROVED|CONDITIONAL|REWORK\", + \"stats\": {\"p0\": 0, \"p1\": 0, \"p2\": 0, \"p3\": 0, \"overComplexity\": 0, \"candidates\": 0, \"confirmed\": 0, \"dropped\": 0} +} + +### Verdict rule +- REWORK if any P0; CONDITIONAL if any P1/P2 (no P0); APPROVED if only P3 / none. +") +``` + +Record output as `{MERGED}`. If `{VALIDATOR_AGENT}` is unavailable, run the SAME prompt on the built-in `general-purpose`. + +### Phase 4 — Write the merged report + +```bash +REPORT_DIR=".claude/reports/${TIMESTAMP}_superreview" +mkdir -p "${REPORT_DIR}" +``` + +Write ONE consolidated report to `.claude/reports/{TIMESTAMP}_superreview/REPORT.md` using the layout in +`references/report-template.md`. Findings section is MANDATORY-sorted by priority P0 -> P3 (highest severity first). + +### Phase 5 — Chat summary + +``` +Super Review complete — MODE={MODE} (branch {BRANCH}), {COUNT} files, {N} agents. + +VERDICT: {APPROVED | CONDITIONAL | REWORK} + +Priority breakdown (sorted P0 -> P3): +- P0 (architecture blockers + CRITICAL security + validator-restored): {N} +- P1 (confirmed correctness + architecture/boundary): {N} +- P2 (reuse misses + over-complexity + version-pin errors): {N} +- P3 (business-requirements nits + warnings): {N} +Over-complexity findings: {OC} + +Per-finding reverse-validation dropped {N} candidates (false-positive/already-fixed/duplicate). + +Report: .claude/reports/{TIMESTAMP}_superreview/REPORT.md + +Recommendations / next steps (superreview is READ-ONLY — it does not apply fixes): +- To fix: new session (English) in Manager mode (++m); delegate to the domain-owner agents ({SIMPLIFY_AGENTS}); + P0/P1 first, then P2/P3. +- To reduce over-complexity: {OC} finding(s).{if >0: run the built-in /simplify skill (reviews + APPLIES + reuse/simplification/efficiency cleanups), then re-run superreview.}{if 0: /simplify optional.} + /simplify is a BUILT-IN skill (not this skill, not a plugin); skip if unavailable. +- Optional: /code-review (built-in) for a focused correctness diff pass. +superreview does NOT run /simplify or any skill and does NOT edit code — these are recommendations only. +``` + +--- + +## Configuration + +| Setting | Default | Description | +|---------|---------|-------------| +| Mode | deterministic | `FULL_PROJECT` \| `EXPLICIT` \| `UNCOMMITTED` \| `LAST_COMMITS`; computed + announced | +| Focus | ordered | user directive wins; default = correctness, architecture, reuse, pins, business-reqs; security only if P0 | +| Fan-out | targeted | non-empty domain groups + {0,1,2} general agents, model's call | +| Validation | ALWAYS, per-finding | Phase 3 reverse-checks EVERY candidate; only CONFIRMed findings reported | +| Validator agent | `{VALIDATOR_AGENT}` (fallback built-in `general-purpose`) | Phase 3 merge + validate | +| Report dir | `.claude/reports/{TIMESTAMP}_superreview/` | Merged report, findings sorted P0 -> P3 | +| Max files | 50 (except `FULL_PROJECT`) | Warn + suggest narrowing above this | +| Search tool | `mcp__grepai__search` if available, else `Grep`/`Glob`/Bash | reuse-first search; note which in report | + +--- + +## Error Handling + +| Condition | Action | +|-----------|--------| +| No changed files for scope | **Exit** ("Nothing to deep-review for {SCOPE}") | +| >50 files | Warn the user; suggest narrowing (per-folder or per-commit) | +| A domain agent unavailable | Fall back to built-in `Explore` with the same prompt; note in report | +| `{VALIDATOR_AGENT}` unavailable | Run Phase 3 validation prompt on the built-in `general-purpose`; note in report | +| `grepai` unavailable | Fall back to `Grep`/`Glob`/Bash; state which path was used in the report | +| Agent timeout | Retry once, then mark that source unavailable + warn in report | +| Validation rejects everything | Report "No issues survived validation" — verdict APPROVED | +| All sources clean | Report "No issues found across standards, architecture, and correctness" — verdict APPROVED | + +--- + +## References + +- `references/{STACK_REF}` — {STACK_LABEL} stack guidelines (passed to every agent). +- `references/agent-prompt.md` — domain-owner agent prompt contract (Phase 2) + the group->agent map. +- `references/report-template.md` — merged-report layout (Phase 4). + + diff --git a/brewcode/skills/superreview/references/agent-prompt.md b/brewcode/skills/superreview/references/agent-prompt.md new file mode 100644 index 0000000..e19b684 --- /dev/null +++ b/brewcode/skills/superreview/references/agent-prompt.md @@ -0,0 +1,92 @@ +# Domain-Owner Agent Prompt Template (superreview Phase 2 — {PROJECT_NAME}) + +Each changed-file group is routed to its DOMAIN-OWNER agent (see the group->agent map in `SKILL.md`). Spawn ALL +non-empty groups in ONE message (parallel). Every agent gets the SAME finding contract so Phase 3 can validate and +Phase 4 can merge. + +``` +Task(subagent_type="{AGENT}", prompt=" +## superreview — {GROUP} pass ({PROJECT_NAME}) + +You review ONLY the files below. Read the ACTUAL code. Report STANDARDS + ARCHITECTURE + CORRECTNESS issues. + +**SEARCH-FIRST (HARD rule — reuse-first):** before flagging a 'duplicate' or 'reuse' miss, grep the repo +(Bash grep/find over the shared/util/common/domain/adapters dirs) and verify imports. If grepai +(mcp__grepai__search) is available, prefer it for semantic search. + +**Files:** {FILE_LIST} +**Focus:** {FOCUS} + +### Focus ordering — spend effort in this priority (highest first) + 1. Functional correctness — does the code do what it should? logic, edge cases, race conditions. + 2. Clean architecture / boundary compliance — module/service boundaries, seams, layering, idempotency. + 3. Reuse of EXISTING code — stdlib/native, existing project modules, already-imported libs; do NOT reinvent. + Flag duplication + missed reuse (cite the project reuse-first rule). + 4. Library version pins — exact X.Y.Z, no floating/stale (cite the project pins rule). + 5. Business-requirements compliance. + SECURITY is NOT a priority: report a security finding ONLY when CRITICAL (P0) — logged secret, missing auth on a + public path, injection. Do NOT spend effort on low/medium security. + (If the project fine-tune emphasis in SKILL.md reorders this, follow that ordering.) + +### OVER-COMPLEXITY / over-engineering — report it as findings (category \"over-complexity\") +Actively flag code more complex than the requirement needs: speculative abstractions, needless params/config/methods +'just in case', premature generalization, indirection KISS/YAGNI would remove, duplicated logic that should be +collapsed. Cite the project rule (do NOT restate it): best-practices (ship the simplest version that works) + avoid +(no gold-plating) + avoid (reuse-first). Severity like any other finding; suggest the simpler shape (delete the layer, +inline the one-caller, collapse the dup, reuse existing code). + +### Apply the canonical project rules — READ them, do not assume; CITE the rule # you enforce +The rules are NOT restated here. READ the files relevant to your area (the rule-pointer table in SKILL.md lists them: +`.claude/rules/*` + `.claude/convention/*`) and enforce them; put the exact rule number in each finding's \"rule\" +field (avoid#N, architecture#N, containers#N, best-practices#N, testing#N, …). A breach of any cited rule = P0/P1 +candidate (per the Focus ordering; security only as P0). + +**Output JSON ONLY:** +{ + \"findings\": [{ + \"file\": \"path/to/file{SOURCE_GLOB}\", + \"lineStart\": 42, + \"lineEnd\": 45, + \"category\": \"boundary|architecture|reuse|over-complexity|security|logic|persistence|test-quality|pins|style\", + \"severity\": \"blocker|critical|major|minor\", + \"rule\": \"avoid#N|best-practices#N|architecture#N|containers#N|... (project rule namespace, or null)\", + \"title\": \"Short summary (<=80 chars)\", + \"description\": \"What is wrong + which invariant/rule it breaks\", + \"suggestion\": \"Concrete fix / where code belongs / what to reuse\", + \"existing\": \"path/to/similar|null (for reuse/duplicate findings)\", + \"reuse\": \"REUSE|EXTEND|CONSIDER|KEEP_NEW|null\", + \"confidence\": 0.85 + }] +} + +**Severity guide:** +- blocker: prod outage / security breach / data loss / boundary violation in a critical path. +- critical: significant bug, perf degradation, boundary violation. +- major: important maintainability/correctness issue. +- minor: style, naming, minor improvement. + +Report ONLY issues (not positives). Reference exact lines. Provide actionable suggestions. Read the real code. +") +``` + +> Domain-owner map (Phase 2) lives in `SKILL.md` (the `FILE_GROUP_MAP`). Built-in `Explore` is the only allowed +> fallback if a mapped agent is unavailable. + +## test agent — also audit for TEST BLOAT / over-testing (tests group only) + +When the `tests` group is non-empty, the test agent's prompt MUST add this block (cite the project `testing` rule, do +NOT restate it). Use category `test-quality`; severity per impact. GOAL = reduce test COUNT; isolation + speed + +real-ness are NON-NEGOTIABLE. + +``` +### Test bloat / over-proliferation audit (cite the project testing rule) +LLMs over-write tests — hunt for and report: +- Too many / redundant tests that should be DELETED: duplicate coverage, trivial getters, internal-mock-only + 'did we call X once' tests. +- Tests to COLLAPSE/MERGE, or to PARAMETRIZE via HELPER FUNCTIONS passing args (per the project test convention). +- Over-granular micro-tests violating 'FEW targeted scenario tests over BIG user journeys'. +NON-NEGOTIABLE — never trade quality for fewer tests: every remaining/merged test MUST stay ISOLATED + FAST + REAL +(fakes-over-mocks, testcontainers/real deps where needed). Also FLAG any test that is slow or non-isolated (shared +mutable state, order-dependence, network/real-clock) — that is its own finding. Do NOT recommend a merge that would +make a test slow or non-isolated. Report all as category test-quality, citing the relevant project testing rule #. +``` diff --git a/brewcode/skills/superreview/references/go.md b/brewcode/skills/superreview/references/go.md new file mode 100644 index 0000000..fad9aeb --- /dev/null +++ b/brewcode/skills/superreview/references/go.md @@ -0,0 +1,127 @@ +# Go Standards Reference + +Standards for Go projects. The project's own rules in `.claude/rules/*` + `.claude/convention/*` are authoritative — +where this guidance conflicts, the **project rule WINS**. Cite the project rule # when enforcing. + +## Tech-Specific Checks (priority dimensions) + +| Category | Checks | +|----------|--------| +| Error handling | Wrap with `fmt.Errorf("...: %w", err)`, sentinel errors, `errors.Is`/`errors.As`, never ignore `err` | +| Concurrency | Goroutine leaks, channel close ownership, `context.Context` propagation, `sync` primitives, race-free | +| Memory | Slice capacity/aliasing, pointer vs value semantics, `defer` for cleanup | +| Reuse | stdlib (`strings`, `slices`, `maps`, `errors`, `io`) + existing internal packages before new code | +| Security | SQL parameterization, input validation, no command injection (report only if CRITICAL/P0) | +| Interfaces | Small interfaces, accept interfaces / return structs, composition over inheritance | + +## File Patterns + +| Type | Patterns | +|------|----------| +| Source | `*.go` (non-test) | +| Tests | `*_test.go` | +| Build/Config | `go.mod`, `go.sum`, `Dockerfile*`, `docker-compose.yml`, `.github/workflows/*.yml` | + +## Naming + +| Type | Convention | Example | +|------|------------|---------| +| Packages | short, lowercase, no underscores | `httpclient` | +| Exported | PascalCase | `NewUserService` | +| Unexported | camelCase | `parseConfig` | +| Interfaces | `-er` suffix where natural | `Reader`, `Validator` | +| Errors | `Err*` sentinel / `*Error` type | `ErrNotFound` | + +## Error Handling + +```go +// Wrap with context, preserve the chain +if err != nil { + return fmt.Errorf("fetch user %d: %w", id, err) +} + +// Sentinel comparison +if errors.Is(err, ErrNotFound) { + ... +} +``` + +| Rule | Verdict | +|------|---------| +| Never discard `err` (`_ = f()`) without justification | VIOL | +| Wrap with `%w` to preserve chain | REQ | +| `errors.Is`/`errors.As` over `==`/type assert | PREF | +| No `panic` for ordinary errors (only truly unrecoverable) | REQ | + +## Concurrency + +| Rule | Verdict | +|------|---------| +| Propagate `context.Context` as first arg | REQ | +| Channel close owned by the sender | REQ | +| Guard shared state (`sync.Mutex` / channels) — no data races | REQ | +| No goroutine leaks (every goroutine has a clear exit) | REQ | +| `errgroup` / `sync.WaitGroup` for fan-out | PREF | + +## Interfaces & Structure + +Accept interfaces, return concrete structs. Keep interfaces small (1-3 methods). Define interfaces at the consumer, +not the producer. Prefer composition (embedding) over large interfaces. + +## Logging + +Use the project logger (`slog` / `zap` / `zerolog`); no `fmt.Println` in prod; structured fields over string +concatenation; never log secrets (security — P0); main code at warn/error level. + +## Testing + +| Rule | Verdict | +|------|---------| +| Table-driven tests via HELPER, GIVEN/WHEN/THEN comments | REQ | +| `t.Run(name, ...)` subtests for scenarios | PREF | +| Concrete assertions (`got == want`, full struct compare) over weak nil checks | REQ | +| No conditional asserts (`if` deciding which assert runs) | VIOL | +| `t.Parallel()` only where the test is truly isolated | PREF | +| Real deps / testcontainers where integration matters; fakes over mocks | REQ | + +```go +func TestGetUser(t *testing.T) { + // GIVEN + svc := newServiceWithFake(t) + // WHEN + got, err := svc.GetUser(ctx, 1) + // THEN + require.NoError(t, err) + want := User{ID: 1, Name: "John"} + require.Equal(t, want, got) +} +``` + +## Common Violations + +| # | Violation | Fix | +|---|-----------|-----| +| 1 | Ignored `err` | Handle or wrap with `%w` | +| 2 | `panic` for ordinary error | Return an error | +| 3 | Missing `context.Context` propagation | Pass `ctx` as first arg | +| 4 | Goroutine leak | Ensure a clear exit / `ctx` cancel | +| 5 | Data race on shared state | Mutex / channel | +| 6 | Large interface | Split into small interfaces | +| 7 | `fmt.Println` in prod | Project structured logger | +| 8 | Reinventing stdlib (`slices`/`maps`) | Reuse stdlib | +| 9 | Logged secret | Redact (P0) | +| 10 | Floating dependency / `replace` to a branch | Pin exact module version | + +## Search Locations (reuse-first) + +`internal/`, `pkg/`, `cmd/`, `**/util/`, `**/common/`, `**/shared/`. + +## Dependency Management + +`go.mod` with exact module versions; run `go mod tidy`; avoid `replace` to a moving branch. Pin tool versions used in +CI. The project's canonical version policy (if any) is authoritative — bump in lockstep. + +## Tools + +`go build` / `go test` / `go vet`, `golangci-lint`, `gofmt`/`goimports`, `testify` or stdlib `testing`, +testcontainers-go, `errgroup`. diff --git a/brewcode/skills/superreview/references/java-kotlin.md b/brewcode/skills/superreview/references/java-kotlin.md new file mode 100644 index 0000000..64fe85a --- /dev/null +++ b/brewcode/skills/superreview/references/java-kotlin.md @@ -0,0 +1,129 @@ +# Java/Kotlin Standards Reference + +Standards for Java/Kotlin enterprise projects. The project's own rules in `.claude/rules/*` + `.claude/convention/*` +are authoritative — where this guidance conflicts, the **project rule WINS**. Cite the project rule # when enforcing. + +## Tech-Specific Checks (priority dimensions) + +| Category | Checks | +|----------|--------| +| DI | Constructor injection only, no field `@Autowired`, `@RequiredArgsConstructor` + final fields | +| Transactions | `@Transactional` scope (service not repository), rollback rules, isolation | +| Null-safety | `Optional` usage, `@NonNull`/`@Nullable`, `Objects.requireNonNull` | +| N+1 | Eager vs lazy loading, batch fetching, entity graphs | +| Reuse | JDK -> Apache Commons -> Guava before writing utility code | +| Security | `@PreAuthorize`, input validation, SQL injection (report only if CRITICAL/P0) | +| Lombok | `@Value`/`@Builder`/`@Slf4j`; `@Data` only on mutable entities | + +## File Patterns + +| Type | Patterns | +|------|----------| +| Source | `*.java`, `*.kt`, `*.kts` | +| Build | `pom.xml`, `build.gradle`, `build.gradle.kts` | +| Tests | `*Test.java`, `*Test.kt`, `*IT.java` | +| Config | `application.yml`, `application.properties` | + +## Naming + +| Type | Convention | Example | +|------|------------|---------| +| Entity | `*Entity` suffix | `UserEntity` | +| DTO Response | `*Response` | `UserResponse` | +| DTO Request | `*Request` | `CreateUserRequest` | +| Repository | `*Repository` | `UserRepository` | +| Service | `*Service` | `UserService` | +| Controller | `*Controller` | `UserController` | + +## Dependency Injection + +```java +@Service +@RequiredArgsConstructor +public class UserService { + private final UserRepository userRepository; // final + constructor + private final EmailService emailService; +} +``` + +Field injection (`@Autowired` on a field) = VIOLATION (harder to test, hidden deps). + +## Stream API & Functional Style + +| Rule | Verdict | +|------|---------| +| Prefer Stream API over imperative loops | REQ | +| Method references over lambdas (`User::getName`) | PREF | +| No side effects in streams | REQ | +| `toList()` over `collect(Collectors.toList())` (Java 16+) | PREF | + +## Immutability + +`final` fields by default; `List.of()`/`Set.of()`/`Map.of()` for immutable collections; Lombok `@Value` for +immutable DTOs; `@Builder` for complex construction. + +## Library Usage Priority (reuse-first) + +| Priority | Library | Common APIs | +|----------|---------|-------------| +| 1 | JDK | `Objects`, `Optional`, `String`, `Math`, `Collections`, `Files`, `Path` | +| 2 | Apache Commons | `StringUtils`, `CollectionUtils`, `Validate`, `IOUtils` | +| 3 | Guava | `Preconditions`, `Strings`, `Iterables`, `Lists`, `Maps` | + +## Logging + +`@Slf4j` + SLF4J facade; parameterized `log.info("User: {}", id)`; no `System.out.println`; no logs in tests; main +code at warn/error only. Never log secrets (security — P0). + +## Test Patterns + +| Rule | Verdict | +|------|---------| +| BDD comments `// GIVEN / // WHEN / // THEN` | REQ | +| `@DisplayName` on methods, not class | REQ | +| No Javadoc in tests | REQ | +| `.as("description")` on EVERY AssertJ assertion | REQ | +| Concrete: `isEqualTo(y)` / `hasSize(n)` over weak `isNotNull()` / `isNotEmpty()` / `>=` | REQ | +| No `if` in tests (assert precondition first, then unconditional assert) | VIOL | +| `allSatisfy()` over `forEach`; `extracting().contains(tuple())` for collections | REQ | + +```java +// Weak — avoid +assertThat(result).isNotNull(); +// Specific +assertThat(result).as("created user").isEqualTo(expected); +assertThat(list).as("result size").hasSize(3); +``` + +## Spring Boot Patterns + +`@Transactional` on service; `ResponseEntity` in controllers; `@Valid` on request bodies; +profile-specific `application-{profile}.yml`. + +## Kotlin-Specific + +`data class` for DTOs; extension functions for utilities; `?.let {}` over null checks; `when` over `if-else` chains; +`Duration` conversions explicit. + +## Common Violations + +| # | Violation | Fix | +|---|-----------|-----| +| 1 | Missing Entity suffix | Add `Entity` to JPA entities | +| 2 | Field injection | Constructor injection | +| 3 | Loop instead of Stream | Convert to Stream API | +| 4 | `System.out.println` | Use `@Slf4j` | +| 5 | Missing `.as()` in test | Add description | +| 6 | `isNotNull()` assertion | Specific value assertion | +| 7 | `if` in test | Assert precondition first | +| 8 | Writing utility that exists | Check JDK/Commons/Guava | +| 9 | Logs in tests | Remove all logging | +| 10 | Floating/`@latest` dependency | Pin exact `X.Y.Z` | + +## Search Locations (reuse-first) + +`**/util/`, `**/common/`, `**/shared/`, `**/core/`, `**/helper/`. + +## Tools + +Maven/Gradle, Spring Boot, JUnit 5, AssertJ, Mockito, Lombok, WireMock, Testcontainers. diff --git a/brewcode/skills/superreview/references/python.md b/brewcode/skills/superreview/references/python.md new file mode 100644 index 0000000..84c6159 --- /dev/null +++ b/brewcode/skills/superreview/references/python.md @@ -0,0 +1,177 @@ +# Python Standards Reference + +GENERIC modern-Python guidance (type hints, docstrings, imports, exceptions, comprehensions, testing). The project's +own rules in `.claude/rules/*` + `.claude/convention/*` are authoritative — where this guidance conflicts with a +project rule, the **project rule WINS**. Cite the project rule # when enforcing. + +## Tech-Specific Checks (priority dimensions) + +| Category | Checks | +|----------|--------| +| Type hints | Function signatures, return types, generics, `X \| None` over `Optional[X]` | +| Exceptions | Specific exception types, `raise X from e`, context managers, no bare `except:` | +| Async | `asyncio` patterns, event-loop handling, no blocking calls in async paths | +| Reuse | stdlib (`itertools`, `functools`, `pathlib`) + existing project modules before new code | +| Security | SQL parameterization, input validation; never log secrets (report only if CRITICAL/P0) | +| Style | PEP8, docstrings, comprehensions, no `print()` in prod | + +## File Patterns + +| Type | Patterns | +|------|----------| +| Source | `*.py` | +| Tests | `test_*.py`, `*_test.py`, `**/tests/*.py` | +| Config | `pyproject.toml`, `requirements*.txt` (`setup.py`/`setup.cfg` legacy) | +| Types | `py.typed`, `*.pyi` | + +## Type Hints + +| Location | Requirement | +|----------|-------------| +| Function parameters | All params typed | +| Function returns | Return type annotated | +| Class attributes | Typed in `__init__` or class body | + +> **Python 3.10+:** `X | Y` over `Union[X, Y]`, `list[X]` over `List[X]`. + +```python +# Fully typed +def process_user(user_id: int, options: dict[str, Any] | None = None) -> User: + ... +``` + +## Docstrings (Google style) + +Module + public class + public function docstrings required; private (`_*`) optional. + +```python +def fetch_user(user_id: int, include_profile: bool = False) -> User | None: + """Fetch user by ID. + + Args: + user_id: Unique identifier. + include_profile: Whether to include full profile data. + + Returns: + User if found, None otherwise. + + Raises: + DatabaseError: If the database connection fails. + """ +``` + +## Naming + +| Type | Convention | Example | +|------|------------|---------| +| Modules | snake_case | `user_service.py` | +| Classes | PascalCase | `UserService` | +| Functions | snake_case | `get_user_by_id` | +| Constants | UPPER_SNAKE | `MAX_RETRIES` | +| Private | `_prefix` | `_internal_method` | + +## Imports (isort order) + +1. Standard library 2. Third-party 3. Local. Absolute imports, one per line, no wildcards. + +```python +from collections.abc import Callable +from pathlib import Path + +import httpx +from pydantic import BaseModel + +from app.models import User +``` + +## Classes + +| Pattern | When | +|---------|------| +| `@dataclass` | Simple data containers | +| `@dataclass(frozen=True)` | Immutable values | +| `pydantic.BaseModel` | Validation needed (API inputs) | + +## Error Handling + +| Rule | Verdict | +|------|---------| +| Specific catch (no bare `except:`) | REQ | +| Chain exceptions `raise X from e` | REQ | +| Context managers for resources | REQ | + +```python +try: + user = fetch_user(user_id) +except UserNotFoundError: + logger.warning("User %s not found", user_id) + raise +except DatabaseError as e: + raise ServiceError("Database unavailable") from e +``` + +## Testing (pytest) + +| Rule | Verdict | +|------|---------| +| pytest over unittest | PREF | +| Fixtures + `conftest.py` for shared setup | REQ | +| Fakes over mocks (capture state, assert at end) | REQ | +| Parametrize via HELPER functions, not always `@pytest.mark.parametrize` | per project convention | +| No `if` in test bodies (assert precondition, then unconditional assert) | VIOL | +| Concrete equality (`== expected`) over weak `is not None` / `>=` checks | REQ | + +```python +def test_get_user_returns_user_when_exists(self, user_service, sample_user): + # GIVEN + user_id = sample_user.id + # WHEN + result = user_service.get_user(user_id) + # THEN — full-object equality + assert result == sample_user +``` + +## Logging + +| Rule | Verdict | +|------|---------| +| `logging` module, logger per module | REQ | +| No `print()` in prod | VIOL | +| Lazy formatting `log.info("User: %s", id)` | PREF | +| NEVER log secrets/tokens | VIOL (security — P0) | + +> Tests emit NO logs; main code logs at warn/error only. + +## Style & Tooling + +Black (format), Ruff (lint), isort (imports), mypy (types). Prefer comprehensions for simple transforms; +generator expressions for large/lazy iteration. + +## Common Violations + +| # | Violation | Fix | +|---|-----------|-----| +| 1 | Missing type hints | Add param + return types | +| 2 | No docstring on public API | Add Google-style docstring | +| 3 | Bare `except:` | Catch specific exceptions | +| 4 | `print()` in prod | Use logging | +| 5 | Wildcard import | Import specific names | +| 6 | Missing `from e` in reraise | Chain exceptions | +| 7 | Mutable default arg | Use `None` + conditional | +| 8 | `Union[X, Y]` on 3.10+ | Use `X | Y` | +| 9 | Logged/committed secret | Env + validation only (P0) | +| 10 | Floating/`@latest` dependency | Pin exact `X.Y.Z` | +| 11 | Reinventing stdlib/existing module | Reuse-first: grep + import | + +## Search Locations (reuse-first) + +`**/app/`, `**/adapters/`, `**/domain/`, `**/utils/`, `**/common/`, `**/lib/`, `**/helpers/`, `**/tests/`. + +## Dependency Management + +Pin every dependency to an exact `pkg==X.Y.Z` in `requirements*.txt` / `pyproject.toml`. Shared packages must pin +identically across modules. The canonical pin table (if the project has one) is authoritative — bump in lockstep. + +## Tools + +pip / Poetry / uv (per project), pytest, respx/httpx-mock, testcontainers, mypy, Black, Ruff, isort. diff --git a/brewcode/skills/superreview/references/report-template.md b/brewcode/skills/superreview/references/report-template.md new file mode 100644 index 0000000..0558a5c --- /dev/null +++ b/brewcode/skills/superreview/references/report-template.md @@ -0,0 +1,92 @@ +# Merged Report Layout (superreview Phase 4 — {PROJECT_NAME}) + +Output: `.claude/reports/{TIMESTAMP}_superreview/REPORT.md`. ONE consolidated, validated, P0->P3-sorted report. + +```markdown +# Super Review Report — {PROJECT_NAME} + +**Generated:** {TIMESTAMP} +**Mode:** {MODE} (branch: {BRANCH}) +**Scope:** {concrete scope — commit range | branch-vs-main | folder | working-tree vs HEAD | full project} +**Focus:** {resolved focus — user directive, else default ordering; security only if P0} +**Files Reviewed:** {COUNT} +**Search tool used:** {grepai | Grep/Glob/Bash fallback} +**Agents run (targeted fan-out):** {AGENT_LIST} + +> Findings section below is MANDATORY-sorted by priority P0 -> P3 (highest severity first). + +## Summary Severity Matrix + +| Priority | Meaning | Count | +|----------|---------|-------| +| P0 | Architecture blockers + CRITICAL security + validator-restored misses | {N} | +| P1 | Confirmed correctness + architecture/boundary | {N} | +| P2 | Reuse misses + over-complexity + version-pin errors | {N} | +| P3 | Business-requirements nits + minor over-complexity + warnings | {N} | + +## Merged Prioritized Findings (sorted P0 -> P3, highest severity first) + +| ID | Priority | Source | File:Line | Category | Severity | Title | Suggestion | +|----|----------|--------|-----------|----------|----------|-------|------------| +| P0-1 | P0 | {agent} | path:42-45 | boundary | blocker | ... | ... | + +## Boundary & Architecture + +| File:Line | Invariant | Issue | Fix | +|-----------|-----------|-------|-----| + +## Reuse / Duplicates + +| New Code | Existing | Similarity | Action | Note | +|----------|----------|------------|--------|------| + +## Over-Complexity / Over-Engineering + +| File:Line | What | Rule | Simpler shape | +|-----------|------|------|---------------| +| ... | speculative abstraction / gold-plating / premature generalization / collapsible dup | best-practices#N \| avoid#N | delete layer / inline one-caller / collapse dup / reuse existing | + +## Dropped in Validation (false-positive / already-fixed / de-dup) + +| Title | Reason | +|-------|--------| + +## VERDICT + +**{APPROVED | CONDITIONAL | REWORK}** + +## Stats + +| Metric | Value | +|--------|-------| +| P0 / P1 / P2 / P3 | {a} / {b} / {c} / {d} | +| Over-complexity findings | {OC} | +| Candidate findings (pre-validation) | {N} | +| Confirmed by validation | {N} | +| Dropped by validation | {N} | +| Agents spawned | {N} | +| Files reviewed | {COUNT} | + +## Recommendations / Next steps + +> **superreview is READ-ONLY — it does not apply fixes.** It only reports. Act on the findings as below. + +- **To FIX the findings:** start a NEW session (English), turn on **Manager mode (`++m`)**, and DELEGATE the fixes + to the domain-owner agents. Address **P0/P1 first, then P2/P3**. +- **To reduce over-complexity:** {OC} over-complexity / missed-reuse / duplication findings. + {if {OC} > 0: **run the built-in `/simplify` skill** — it reviews the changed code for reuse / simplification / + efficiency and APPLIES the cleanups. Run it in a fix-session, then re-run superreview to confirm.} + {if {OC} == 0: `/simplify` is OPTIONAL — no over-complexity was flagged.} + `/simplify` is a BUILT-IN Claude Code skill (NOT this skill, NOT a plugin); if it is unavailable, skip it. +- **Optional:** `/code-review` (built-in) for a focused correctness diff pass. + +> These are RECOMMENDATIONS only. superreview does NOT invoke `/simplify`, does NOT call any other skill, and does +> NOT edit code — acting on them is the user's next session. +``` + +## Severity / reuse legend + +- **Priority:** P0 (blocker — fix first) -> P3 (nice-to-have). +- **Severity:** blocker (outage/breach/data-loss) > critical (significant bug/perf/boundary) > major (maintainability) > minor (style). +- **Reuse:** REUSE (import existing 90-100%) | EXTEND (add params to existing 70-89%) | CONSIDER (evaluate 50-69%) | KEEP_NEW (<50%, justified). +- **Verdict:** REWORK if any P0; CONDITIONAL if any P1/P2 (no P0); APPROVED if only P3 / none. diff --git a/brewcode/skills/superreview/references/typescript-react.md b/brewcode/skills/superreview/references/typescript-react.md new file mode 100644 index 0000000..4972953 --- /dev/null +++ b/brewcode/skills/superreview/references/typescript-react.md @@ -0,0 +1,132 @@ +# TypeScript / Node / React Standards Reference + +Standards for TypeScript, Node.js and React projects. The project's own rules in `.claude/rules/*` + +`.claude/convention/*` are authoritative — where this guidance conflicts, the **project rule WINS**. Cite the rule #. + +## Tech-Specific Checks (priority dimensions) + +| Category | Checks | +|----------|--------| +| Async | Promise handling, unhandled rejections, correct async/await, no floating promises | +| Types | Strict null checks, type guards, generics; no `any` (use `unknown` + narrowing) | +| Validation | Input sanitization, schema validation (Zod/Joi) at boundaries | +| Reuse | existing hooks/components/utils before new ones (check `common/`, `shared/`) | +| Security | XSS prevention, CSRF, no injected HTML (report only if CRITICAL/P0) | +| Imports | ESM vs CJS consistency, barrel exports, no circular deps | + +## File Patterns + +| Type | Patterns | +|------|----------| +| Components | `*.tsx`, `*.jsx` | +| Logic | `*.ts`, `*.js` | +| Styles | `*.styled.ts`, `**/styles.ts`, `*.css`, `*.scss` | +| Tests | `*.test.tsx`, `*.spec.ts`, `**/__tests__/*` | +| Config | `package.json`, `tsconfig.json`, `.eslintrc*` | + +## Component Patterns (React) + +Functional components only (no class components). Arrow functions for components. Structure order: types -> declaration +-> hooks -> handlers -> render helpers -> JSX. + +```tsx +const UserCard: React.FC = ({ user, onEdit }) => { + return
{user.name}
; +}; +``` + +## Hooks + +| Hook | Common mistake | +|------|----------------| +| `useState` | Over-using for derived state | +| `useEffect` | Missing cleanup / deps array | +| `useMemo`/`useCallback` | Premature optimization | +| `useRef` | Using for state | + +Custom hooks: `use*` prefix, extract reusable logic, return object for >2 values. **Check existing hooks first** +(`hooks/`, `use*.ts`, grepai_search) before creating. + +## TypeScript Type Safety + +| Rule | Verdict | +|------|---------| +| Explicit prop/return types | REQ | +| No `any` | VIOLATION | +| `unknown` over `any` + narrowing | PREF | +| Interface for objects, type for unions | PREF | + +```tsx +interface UserCardProps { user: User; onEdit?: (id: string) => void; } + +type ApiResponse = + | { status: 'success'; data: T } + | { status: 'error'; error: string }; +``` + +## Styling (if styled-components / theme) + +Use theme tokens; no hardcoded colors/spacing/fonts. Colocate styles; extend base components; check +`components/common/` before adding a new styled component. + +## State Management + +| Scope | Solution | +|-------|----------| +| Component | `useState` | +| Subtree | Context + `useReducer` | +| Global | Redux/Zustand/Jotai | + +Prop drilling >3 levels -> Context or state management. + +## Testing (Jest + React Testing Library) + +| Rule | Verdict | +|------|---------| +| Test behavior, not implementation | REQ | +| Query priority: `getByRole` > `getByLabelText` > `getByText` > `getByTestId` | PREF | +| `screen` over destructure; `userEvent` over `fireEvent` | PREF | +| GIVEN/WHEN/THEN structure | REQ | + +```tsx +it('renders user name', () => { + // GIVEN + const user = { id: '1', name: 'John' }; + // WHEN + render(); + // THEN + expect(screen.getByText('John')).toBeInTheDocument(); +}); +``` + +## Performance + +`React.memo` / `useMemo` / `useCallback` AS NEEDED — profile first, optimize second. `React.lazy()` + Suspense for +route-level code splitting. + +## Common Violations + +| # | Violation | Fix | +|---|-----------|-----| +| 1 | `any` type | `unknown` or specific type | +| 2 | Class component | Convert to functional | +| 3 | Missing types | Add explicit types | +| 4 | Hardcoded colors | Theme tokens | +| 5 | Duplicate styled component | Check Common/, extend existing | +| 6 | Missing useEffect cleanup | Return cleanup function | +| 7 | Prop drilling >3 levels | Use Context | +| 8 | Testing implementation | Test behavior/output | +| 9 | Floating promise / unhandled rejection | await / `.catch` | +| 10 | Floating/`@latest` dependency | Pin exact `X.Y.Z` | + +## Search Locations (reuse-first) + +`**/components/common/`, `**/components/shared/`, `**/hooks/`, `**/utils/`, `**/helpers/`, `**/types/`, `**/theme/`. + +## Import Order + +1. React 2. External libraries 3. Internal (absolute) 4. Relative 5. Styles/assets. + +## Tools + +npm/yarn/pnpm, TypeScript, ESLint, Prettier, Jest, React Testing Library, Vite/webpack, Storybook. diff --git a/brewcode/skills/superreview/scripts/generate.sh b/brewcode/skills/superreview/scripts/generate.sh new file mode 100755 index 0000000..39a5293 --- /dev/null +++ b/brewcode/skills/superreview/scripts/generate.sh @@ -0,0 +1,206 @@ +#!/bin/bash +# brewcode:superreview generator script +# Adapted from setup.sh copy_review_skill(): copies the emit templates into the TARGET project +# (.claude/skills/superreview/) substituting SCALAR placeholders, then validates that NO setup-time +# {PLACEHOLDER} remains. Multi-row BLOCK placeholders are filled by the AI via Edit (see SKILL.md Phase 3). +# +# Usage: generate.sh +# scan - Report target tech stack, agents, rules, source/test dirs (Phase 1) +# emit - Copy + scalar-substitute templates into /.claude/skills/superreview/ (Phase 2) +# validate - Fail if any unresolved setup-time {PLACEHOLDER} remains (Phase 4) + +set -euo pipefail + +MODE="${1:-emit}" + +# Self-location: scripts/generate.sh -> skills/superreview/scripts -> skills/superreview +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +SKILL_DIR="$(dirname "$SCRIPT_DIR")" +REFS="$SKILL_DIR/references" + +# Target is the current working directory (the repo being reviewed) +TARGET=".claude/skills/superreview" +TARGET_REFS="$TARGET/references" + +validate_templates() { + if [ ! -f "$REFS/SKILL.md.template" ]; then + echo "❌ Emit template not found: $REFS/SKILL.md.template" + exit 1 + fi +} + +# ── scan: report what the emitted skill must be wired to ──────────────────────── +scan_target() { + echo "=== superreview: target scan ===" + echo "" + echo "--- Build files ---" + find . -maxdepth 3 -type f \( \ + -name "package.json" -o -name "pom.xml" -o -name "build.gradle" -o \ + -name "build.gradle.kts" -o -name "requirements*.txt" -o -name "pyproject.toml" -o \ + -name "Pipfile" -o -name "Cargo.toml" -o -name "go.mod" -o -name "composer.json" \ + \) 2>/dev/null | sort || echo "(none found)" + + echo "" + echo "--- Project agents (.claude/agents/) ---" + find .claude/agents -type f -name "*.md" 2>/dev/null | sort || echo "(none)" + + echo "" + echo "--- Rules (.claude/rules/) ---" + find .claude/rules -type f -name "*.md" 2>/dev/null | sort || echo "(none)" + + echo "" + echo "--- Conventions (.claude/convention/) ---" + find .claude/convention -type f -name "*.md" 2>/dev/null | sort || echo "(none)" + + echo "" + echo "--- Source / service dirs (top level) ---" + find . -maxdepth 2 -type d \( -name "src" -o -name "app" -o -name "lib" -o \ + -name "pkg" -o -name "internal" -o -name "cmd" \) 2>/dev/null | sort || echo "(none)" + + echo "" + echo "--- Test dirs ---" + find . -type d \( -name "test" -o -name "tests" -o -name "__tests__" \) 2>/dev/null | head -20 || echo "(none)" + + echo "" + echo "--- CLAUDE.md ---" + test -f ./CLAUDE.md && echo "✅ CLAUDE.md" || echo "⚠️ no CLAUDE.md" +} + +# ── emit: copy + scalar-substitute templates into the target ──────────────────── +emit_skill() { + echo "=== superreview: emit ===" + validate_templates + + mkdir -p "$TARGET_REFS" + + # Scalar values (single-line ONLY — sed processes line-by-line; a newline truncates the substitution). + PROJECT_NAME="${PROJECT_NAME:-this project}" + STACK_LABEL="${STACK_LABEL:-the project stack}" + STACK_REF="${STACK_REF:-python.md}" + SOURCE_GLOB="${SOURCE_GLOB:-*}" + PATHSPEC_GLOBS="${PATHSPEC_GLOBS:-'*' 'Dockerfile*' 'docker-compose.yml' '.github/workflows/*.yml'}" + ARBITER_AGENT="${ARBITER_AGENT:-general-purpose}" + VALIDATOR_AGENT="${VALIDATOR_AGENT:-general-purpose}" + GENERATED_AT="$(date -u +%Y-%m-%dT%H:%M:%SZ)" + + _sep=$'\x01' + + # Sanitize every scalar before it lands on a sed RHS: escape backslash FIRST, then ampersand + # (& is the whole-match backreference in sed replacements). Order matters. + for _var in PROJECT_NAME STACK_LABEL STACK_REF SOURCE_GLOB PATHSPEC_GLOBS ARBITER_AGENT VALIDATOR_AGENT GENERATED_AT; do + v="${!_var}"; v="${v//\\/\\\\}"; v="${v//&/\\&}"; printf -v "$_var" '%s' "$v" + done + + _subst() { + # $1 = source template, $2 = destination + sed \ + -e "s${_sep}{PROJECT_NAME}${_sep}${PROJECT_NAME}${_sep}g" \ + -e "s${_sep}{STACK_LABEL}${_sep}${STACK_LABEL}${_sep}g" \ + -e "s${_sep}{STACK_REF}${_sep}${STACK_REF}${_sep}g" \ + -e "s${_sep}{SOURCE_GLOB}${_sep}${SOURCE_GLOB}${_sep}g" \ + -e "s${_sep}{PATHSPEC_GLOBS}${_sep}${PATHSPEC_GLOBS}${_sep}g" \ + -e "s${_sep}{ARBITER_AGENT}${_sep}${ARBITER_AGENT}${_sep}g" \ + -e "s${_sep}{VALIDATOR_AGENT}${_sep}${VALIDATOR_AGENT}${_sep}g" \ + -e "s${_sep}{GENERATED_AT}${_sep}${GENERATED_AT}${_sep}g" \ + "$1" > "$2" + } + + _subst "$REFS/SKILL.md.template" "$TARGET/SKILL.md" + echo "✅ $TARGET/SKILL.md" + + _subst "$REFS/agent-prompt.md" "$TARGET_REFS/agent-prompt.md" + echo "✅ $TARGET_REFS/agent-prompt.md" + + _subst "$REFS/report-template.md" "$TARGET_REFS/report-template.md" + echo "✅ $TARGET_REFS/report-template.md" + + if [ -f "$REFS/$STACK_REF" ]; then + cp "$REFS/$STACK_REF" "$TARGET_REFS/$STACK_REF" + echo "✅ $TARGET_REFS/$STACK_REF" + else + echo "⚠️ stack reference not found: $REFS/$STACK_REF (emitted without per-stack doc)" + fi + + echo "" + echo "Next: AI fills BLOCK placeholders via Edit (SKILL.md Phase 3), then run: generate.sh validate" +} + +# ── validate: no setup-time {PLACEHOLDER} may remain ──────────────────────────── +validate_emit() { + echo "=== superreview: validate ===" + + if [ ! -f "$TARGET/SKILL.md" ]; then + echo "❌ emitted skill missing: $TARGET/SKILL.md — run 'generate.sh emit' first" + exit 1 + fi + + # Runtime tokens the emitted skill legitimately keeps (resolved at REVIEW time, not GENERATION time). + _runtime='MODE|BRANCH|SCOPE|FILES|COUNT|TIMESTAMP|FOCUS|FILE_LIST|AGENT_LIST|CANDIDATES|MERGED|PATHSPEC|MAIN|SHA|FOLDER|GROUP|AGENT|N|OC|REPORT_DIR' + + _errors=0 + for f in "$TARGET/SKILL.md" "$TARGET_REFS/agent-prompt.md" "$TARGET_REFS/report-template.md"; do + [ -f "$f" ] || continue + _unresolved=$(grep -oE '\{[A-Z_]+\}' "$f" | sort -u | grep -vE "^\{(${_runtime})\}$" || true) + if [ -n "$_unresolved" ]; then + echo "❌ unresolved setup-time placeholders in $f:" + echo "$_unresolved" + _errors=$((_errors+1)) + fi + done + + # Agent-reference allowlist: every agent named in the emitted SKILL.md must be a + # project-local agent (.claude/agents/*.md) or a real built-in (Explore|Plan|general-purpose). + _builtins="Explore Plan general-purpose" + _local_agents="" + for _af in .claude/agents/*.md; do + [ -f "$_af" ] || continue + _an="$(basename "$_af" .md)" + _local_agents="$_local_agents $_an" + done + + # (a) explicit subagent_type="NAME" / subagent_type=NAME references + _referenced=$(grep -oE 'subagent_type=("?)[A-Za-z0-9_-]+' "$TARGET/SKILL.md" \ + | sed -E 's/^subagent_type=("?)//' | sort -u || true) + if [ -n "$_referenced" ]; then + while IFS= read -r _name; do + [ -n "$_name" ] || continue + case " $_builtins $_local_agents " in + *" $_name "*) : ;; + *) + echo "❌ unknown agent referenced in SKILL.md: $_name (not in target .claude/agents/ nor built-in Explore|Plan|general-purpose)" + _errors=$((_errors+1)) + ;; + esac + done < allowed + esac + _leak=$(grep -nE "(built-in[^A-Za-z]+\`?${_bare}\`?|fallback[^A-Za-z]+\`?${_bare}\`?|on \`${_bare}\`)" "$TARGET/SKILL.md" || true) + if [ -n "$_leak" ]; then + echo "❌ bare \`${_bare}\` used as a built-in/fallback agent in SKILL.md (not in target .claude/agents/ nor built-in Explore|Plan|general-purpose):" + echo "$_leak" + _errors=$((_errors+1)) + fi + done + + if [ "$_errors" -eq 0 ]; then + echo "✅ no unresolved setup-time placeholders" + fi + exit "$_errors" +} + +case "$MODE" in + scan) scan_target ;; + emit) emit_skill ;; + validate) validate_emit ;; + *) + echo "Usage: generate.sh " + exit 1 + ;; +esac diff --git a/brewcode/skills/teams/README.md b/brewcode/skills/teams/README.md index 085e5c6..f681169 100644 --- a/brewcode/skills/teams/README.md +++ b/brewcode/skills/teams/README.md @@ -155,7 +155,7 @@ Each agent follows a 3-step self-selection before accepting a task: ## Dynamic Agent Resolution -When other skills (spec, plan, start, convention, standards-review) spawn agents, they check for team agents first: +When other skills (spec, convention, superreview, e2e) spawn agents, they check for team agents first: | Priority | Source | Example | |----------|--------|---------| @@ -170,8 +170,8 @@ When other skills (spec, plan, start, convention, standards-review) spawn agents | Skill | Relationship | |-------|-------------| -| `/brewcode:setup` | Run first to analyze project structure | | `/brewcode:spec` | Create task specifications for agents to execute | +| `/brewcode:superreview` | Generate a project-tailored deep-review skill | | `/brewcode:rules` | Extract team insights into project rules | ## Documentation diff --git a/brewcode/templates/skills/review/SKILL.md.template b/brewcode/templates/skills/review/SKILL.md.template deleted file mode 100644 index fc94d42..0000000 --- a/brewcode/templates/skills/review/SKILL.md.template +++ /dev/null @@ -1,460 +0,0 @@ ---- -name: brewcode:review -description: Project-adapted code review with quorum consensus. Triggers "review code", "code review", "/brewcode:review". -user-invocable: true -argument-hint: " [-q|--quorum [G-]N-M] [-c|--critic]" -allowed-tools: Read, Glob, Grep, Task, Bash, Write -context: session -model: opus ---- - -# Code Review - -**ROLE:** Code Review Coordinator | **OUTPUT:** Prioritized findings report - -## Input Handling - -| Input | Action | -|-------|--------| -| Text prompt | Review focus description | -| File path (`.md`, `.txt`) | Read as review instructions | -| `-q N-M` / `--quorum N-M` | N agents per group, M quorum threshold | -| `-q G-N-M` / `--quorum G-N-M` | G groups, N agents/group, M quorum | -| `-c` / `--critic` | Enable Critic phase (after DoubleCheck) | -| Text contains `критик`, `с критиком`, `critic` | Auto-enable Critic | -| Default | `-q 3-2` (3 agents, quorum 2), no critic | - ---- - -## Project Agents - -> Adapted from `.claude/agents/` — specialized reviews - -{PROJECT_AGENTS_TABLE} - - - -## Core Agents (Fallback) - -| Agent | Expertise | -|-------|-----------| -| `reviewer` | Code quality, patterns, architecture | -| `tester` | Test coverage, assertions, mocking | -| `sql_expert` | SQL queries, transactions, N+1 | - ---- - -## Tech-Specific Checks - -> Adapted based on detected tech stack - -{TECH_SPECIFIC_CHECKS} - - - ---- - -## Project Rules - -> Extracted from CLAUDE.md patterns - -{PROJECT_RULES} - - - ---- - -## Review Groups - -| Group | Focus | Agent | Files | -|-------|-------|-------|-------| -| main-code | Logic, architecture, security | {MAIN_AGENT} | `src/main/**` | -| tests | Coverage, assertions, quality | {TEST_AGENT} | `src/test/**` | -| db-layer | Queries, transactions | {DB_AGENT} | `**/repositories/**` | - -{CUSTOM_GROUPS} - - - ---- - -## Execution - -### Phase 1: Codebase Study (Parallel Explore) - -``` -ONE message with 5-10 Explore agents scanning: -{CODEBASE_BLOCKS} -``` - -### Phase 2: Group Formation - -Detected files → enabled groups: -- DB detected → db-layer group -- Tests detected → tests group -- Auth files → security focus - -### Phase 3: Parallel Review - -``` -N agents per group × {GROUP_COUNT} groups = total agents - -Each agent reviews with tech checks, project rules, focus: {REVIEW_PROMPT} -``` - -### Phase 4: Quorum Collection - -```python -confirmed = [] -exceptions = [] -discarded = [] - -for finding in all_findings: - cluster = find_similar_findings(finding, all_findings) - unique_agents = count_unique_agents(cluster) - - if unique_agents >= M: # Quorum threshold - merged = merge_cluster(cluster) - confirmed.append(merged) - elif finding.severity in ['blocker', 'critical']: - exceptions.append(finding) # Priority 3 - else: - discarded.append(finding) -``` - -**Matching rules:** - -| Criterion | Tolerance | Weight | -|-----------|-----------|--------| -| Same file | Exact | Required | -| Line range | ±5 lines | Required | -| Category | Same or equivalent | Required | -| Description | Semantic similarity ≥ 0.6 | Optional | - -**Merge rules:** - -| Field | Strategy | -|-------|----------| -| description | Longest/most detailed | -| severity | Highest in cluster | -| suggestion | First non-null | -| confidence | Average of cluster | -| lineStart/End | Min/Max of cluster | -| agents | List all contributing | - -### Phase 5: DoubleCheck - -Single `reviewer` (Opus) verifies ALL confirmed findings: - -```markdown -Task(subagent_type="reviewer", model="opus", prompt=" - ## DoubleCheck Verification - - For EACH finding below: - 1. **Verify existence:** Issue exists in code? - 2. **Verify accuracy:** Description correct? - 3. **Verify actionability:** Clear fix path? - 4. **Verify severity:** Severity appropriate? - - **Findings to verify:** - {CONFIRMED_FINDINGS_JSON} - - **Output format (JSON array):** - [{ - \"findingId\": \"1\", - \"verdict\": \"CONFIRM|REJECT\", - \"reason\": \"Explanation if REJECT\", - \"severityAdjustment\": \"null|blocker|critical|major|minor\" - }] - - **Verdict rules:** - - CONFIRM: Issue exists, description accurate, actionable - - REJECT: False positive, already fixed, or not actionable -") -``` - -| Verdict | Action | -|---------|--------| -| CONFIRM | Priority 1 (highest confidence) | -| REJECT | Remove from report | -| Severity adjusted | Update severity in report | - -### Phase 5.5: Critic (Optional — Devil's Advocate) - -> Enabled by `-c`/`--critic` flag or keywords `критик`/`с критиком`/`critic` in prompt. - -Single `reviewer` (Opus) challenges entire review. Input: all findings (confirmed, rejected, discarded) + source code. - -**Task:** Find missed issues, challenge DoubleCheck verdicts, identify blind spots. - -```markdown -Task(subagent_type="reviewer", model="opus", prompt=" - ## Critic Review (Devil's Advocate) - - Find what ALL reviewers MISSED. - - **Confirmed findings (DoubleCheck passed):** - {CONFIRMED_FINDINGS_JSON} - - **Rejected findings (DoubleCheck rejected):** - {REJECTED_FINDINGS_JSON} - - **Discarded findings (no quorum):** - {DISCARDED_FINDINGS_JSON} - - **Files under review:** - {FILE_LIST} - - **Output format (JSON):** - { - \"missedFindings\": [{ - \"file\": \"path/to/file.java\", - \"lineStart\": 42, - \"lineEnd\": 45, - \"category\": \"null-safety|security|performance|logic|style|test-quality\", - \"severity\": \"blocker|critical|major|minor\", - \"title\": \"Short summary\", - \"description\": \"Why ALL reviewers missed this\", - \"suggestion\": \"Fix approach\", - \"confidence\": 0.85 - }], - \"challenges\": [{ - \"findingId\": \"P1-3\", - \"type\": \"WRONG_CONFIRM|WRONG_REJECT|SEVERITY_WRONG\", - \"reason\": \"Why the verdict is wrong\", - \"suggestedSeverity\": \"blocker|critical|major|minor|null\" - }], - \"blindSpots\": [\"category with 0 findings that warrants attention\"] - } - - **Rules:** - - Focus on what was MISSED, not what was found - - Challenge at least 1 confirmed finding (stress-test) - - Report blind spots even if no missed issues found - - Confidence reflects how certain you are the issue was missed -") -``` - -**Critic output → Phase 5.75 input** (all findings require verification) - -### Phase 5.75: DoubleCheck Critic - -Single `reviewer` (Opus) verifies ALL Critic output — same role as Phase 5 DoubleCheck. - -```markdown -Task(subagent_type="reviewer", model="opus", prompt=" - ## DoubleCheck: Critic Verification - - Verify ALL findings from the Critic (Devil's Advocate). - Apply the SAME standards as Phase 5 DoubleCheck. - - **Critic missed findings:** - {CRITIC_MISSED_FINDINGS_JSON} - - **Critic challenges:** - {CRITIC_CHALLENGES_JSON} - - **Critic blind spots:** - {CRITIC_BLIND_SPOTS} - - **Source code files:** - {FILE_LIST} - - **For EACH missed finding:** - 1. Does the issue actually exist in code? - 2. Is the description accurate? - 3. Is there a clear fix path? - 4. Is the severity appropriate? - - **For EACH challenge:** - 1. Is the challenge valid? Re-read the original finding and code. - 2. Was the original DoubleCheck verdict correct or wrong? - - **For EACH blind spot:** - 1. Is the category relevant to the reviewed code? - 2. Are there actual issues in that category? - - **Output format (JSON):** - { - \"missedFindings\": [{ - \"findingId\": \"CF-1\", - \"verdict\": \"CONFIRM|REJECT\", - \"reason\": \"Explanation\", - \"severityAdjustment\": \"null|blocker|critical|major|minor\" - }], - \"challenges\": [{ - \"challengeId\": \"CC-1\", - \"verdict\": \"CONFIRM|REJECT\", - \"reason\": \"Explanation\" - }], - \"blindSpots\": [{ - \"spotId\": \"BS-1\", - \"verdict\": \"CONFIRM|REJECT\", - \"reason\": \"Explanation\" - }] - } - - **Verdict rules:** - - CONFIRM: Issue exists / challenge valid / blind spot real - - REJECT: False positive, already covered, or not actionable -") -``` - -**Result processing:** - -| Verdict | Source | Action | -|---------|--------|--------| -| CONFIRM `missedFinding` | Critic | → Priority 0 (verified) | -| REJECT `missedFinding` | Critic | Discard | -| CONFIRM `challenge[WRONG_REJECT]` | Critic | Restore finding → P0 | -| CONFIRM `challenge[WRONG_CONFIRM]` | Critic | Add note to existing finding | -| CONFIRM `challenge[SEVERITY_WRONG]` | Critic | Adjust severity | -| REJECT `challenge` | Critic | Keep original verdict | -| CONFIRM `blindSpot` | Critic | → Report Statistics | -| REJECT `blindSpot` | Critic | Discard | - -### Phase 6: Report - -Output: `.claude/tasks/reviews/{TIMESTAMP}_{NAME}_report.md` - -Priority order: -0. Critic findings — verified by DoubleCheck (when critic enabled) -1. Quorum + DoubleCheck confirmed -2. Quorum only (not DoubleCheck confirmed) -3. Blocker/Critical without quorum (exceptions) - ---- - -## Output Format - -**Without critic:** -``` -Review complete. Found {TOTAL} issues ({BLOCKERS} blocker, {CRITICAL} critical, {MAJOR} major). - -Priority breakdown: -- P1 (Confirmed): {N} issues -- P2 (Quorum only): {N} issues -- P3 (Exceptions): {N} issues - -Full report: .claude/tasks/reviews/{TIMESTAMP}_{NAME}_report.md -``` - -**With critic (`-c`):** -``` -Review complete. Found {TOTAL} issues including {P0_COUNT} critic ({BLOCKERS} blocker, {CRITICAL} critical, {MAJOR} major). - -Priority breakdown: -- P0 (Critic): {N} issues — verified by DoubleCheck -- P1 (Confirmed): {N} issues -- P2 (Quorum only): {N} issues -- P3 (Exceptions): {N} issues - -Critic challenges: {COUNT} verdicts challenged ({ACCEPTED} accepted) -Blind spots: {N} categories flagged - -Full report: .claude/tasks/reviews/{TIMESTAMP}_{NAME}_report.md -``` - ---- - -## Configuration - -| Setting | Default | Description | -|---------|---------|-------------| -| `-q` / `--quorum` | `3-2` | `N-M` (agents-threshold) or `G-N-M` (groups-agents-threshold) | -| Report dir | `.claude/tasks/reviews/` | Output directory | -| Max parallel | 25 | Maximum agents in one message (G×N) | -| Line tolerance | ±5 | Lines overlap for matching | -| Similarity | 0.6 | Semantic similarity for matching | -| `-c` / `--critic` | Off | Enable Critic (Phase 5.5) + DoubleCheck Critic (Phase 5.75) | - ---- - -## Error Handling - -| Condition | Action | -|-----------|--------| -| No files found for block | Skip block, warn in report | -| Agent timeout | Retry once, then mark unavailable | -| No findings | Report "No issues found" with confidence | -| Invalid quorum args | Error: "Invalid -q/--quorum. Format: G-N-M or N-M" | -| No CLAUDE.md | Use default rules only | -| Critic finds 0 issues | Report confidence boost: "Critic found no missed issues" | -| DoubleCheck rejects >50% of Critic findings | Warning in report: "Most critic findings unconfirmed" | -| Critic challenges >50% of P1 | Warning: "High challenge rate — consider re-review" | -| `-c` with `-q 1-1` | Warning: "Critic most valuable with quorum >= 2" | - ---- - -## References - -- `references/agent-prompt.md` — Agent prompt templates (standard + DB-layer + Critic) -- `references/report-template.md` — Report format and naming conventions - ---- - - diff --git a/brewcode/templates/skills/review/references/agent-prompt.md b/brewcode/templates/skills/review/references/agent-prompt.md deleted file mode 100644 index c7382ad..0000000 --- a/brewcode/templates/skills/review/references/agent-prompt.md +++ /dev/null @@ -1,209 +0,0 @@ -# Agent Prompt Template - -Template for parallel review agent invocation. - -```markdown -Task(subagent_type="{AGENT_TYPE}", model="opus", prompt=" - ## Code Review Task - - **Group:** {GROUP_NAME} - **Focus:** {REVIEW_PROMPT} - **Instance:** {INSTANCE_NUMBER} of {TOTAL_INSTANCES} - - **Files to review:** - {FILE_LIST} - - **Project rules (from CLAUDE.md):** - {RELEVANT_RULES} - - **Output format (JSON array):** - ```json - [{ - \"file\": \"path/to/file.java\", - \"lineStart\": 42, - \"lineEnd\": 45, - \"category\": \"null-safety|security|performance|logic|style|test-quality\", - \"severity\": \"blocker|critical|major|minor\", - \"title\": \"Short summary (max 80 chars)\", - \"description\": \"Detailed explanation of the issue\", - \"suggestion\": \"Recommended fix or approach\", - \"confidence\": 0.85 - }] - ``` - - **Categories:** - - null-safety: Potential NPE, missing null checks - - security: Auth bypass, injection, secrets, OWASP top 10 - - performance: N+1 queries, memory leaks, inefficient algorithms - - logic: Business logic errors, race conditions, edge cases - - style: Code style violations, naming, patterns - - test-quality: Missing tests, weak assertions, flaky tests - - **Severity guide:** - - blocker: Production outage, security breach, data loss - - critical: Significant bug, performance degradation - - major: Important issue, maintainability concern - - minor: Style, minor improvement - - **Rules:** - - Report ONLY issues, not positives - - Include confidence score (0.0-1.0) - - Provide actionable suggestions - - Reference specific lines -") -``` - -## DB-Layer Specific Prompt - -For `db-layer` group, use `reviewer` agent with database-focused prompt additions: - -```markdown -Task(subagent_type="reviewer", model="opus", prompt=" - ## Code Review Task - Database Layer - - **Group:** db-layer - **Focus:** {REVIEW_PROMPT} - **Instance:** {INSTANCE_NUMBER} of {TOTAL_INSTANCES} - - **Specialized focus areas:** - - N+1 query detection - - Transaction boundary issues - - Connection pool exhaustion - - SQL injection vulnerabilities - - Missing indexes (based on WHERE/JOIN clauses) - - Improper eager/lazy loading - - Batch operation opportunities - - **Files to review:** - {FILE_LIST} - - ... (rest of standard template) -") -``` - -## Critic Prompt - -For optional Phase 5.5 — Devil's Advocate review. Single `reviewer` (Opus). - -```markdown -Task(subagent_type="reviewer", model="opus", prompt=" - ## Critic Review (Devil's Advocate) - - You are the CRITIC. Your job is to find what ALL other reviewers MISSED. - - **Confirmed findings (DoubleCheck passed):** - {CONFIRMED_FINDINGS_JSON} - - **Rejected findings (DoubleCheck rejected):** - {REJECTED_FINDINGS_JSON} - - **Discarded findings (no quorum):** - {DISCARDED_FINDINGS_JSON} - - **Files under review:** - {FILE_LIST} - - **Output format (JSON):** - { - \"missedFindings\": [{ - \"file\": \"path/to/file.java\", - \"lineStart\": 42, - \"lineEnd\": 45, - \"category\": \"null-safety|security|performance|logic|style|test-quality\", - \"severity\": \"blocker|critical|major|minor\", - \"title\": \"Short summary\", - \"description\": \"Why ALL reviewers missed this\", - \"suggestion\": \"Fix approach\", - \"confidence\": 0.85 - }], - \"challenges\": [{ - \"findingId\": \"P1-3\", - \"type\": \"WRONG_CONFIRM|WRONG_REJECT|SEVERITY_WRONG\", - \"reason\": \"Why the verdict is wrong\", - \"suggestedSeverity\": \"blocker|critical|major|minor|null\" - }], - \"blindSpots\": [\"category with 0 findings that warrants attention\"] - } - - **Rules:** - - Focus on what was MISSED, not what was found - - Challenge at least 1 confirmed finding (stress-test) - - Report blind spots even if no missed issues found - - Confidence reflects how certain you are the issue was missed -") -``` - -## DoubleCheck Critic Prompt - -For Phase 5.75 — verifies ALL Critic output. Same `reviewer` (Opus) role as Phase 5 DoubleCheck. - -```markdown -Task(subagent_type="reviewer", model="opus", prompt=" - ## DoubleCheck: Critic Verification - - Verify ALL findings from the Critic (Devil's Advocate). - Apply the SAME standards as Phase 5 DoubleCheck. - - **Critic missed findings:** - {CRITIC_MISSED_FINDINGS_JSON} - - **Critic challenges:** - {CRITIC_CHALLENGES_JSON} - - **Critic blind spots:** - {CRITIC_BLIND_SPOTS} - - **Source code files:** - {FILE_LIST} - - **For EACH missed finding:** - 1. Does the issue actually exist in code? - 2. Is the description accurate? - 3. Is there a clear fix path? - 4. Is the severity appropriate? - - **For EACH challenge:** - 1. Is the challenge valid? Re-read the original finding and code. - 2. Was the original DoubleCheck verdict correct or wrong? - - **For EACH blind spot:** - 1. Is the category relevant to the reviewed code? - 2. Are there actual issues in that category? - - **Output format (JSON):** - { - \"missedFindings\": [{ - \"findingId\": \"CF-1\", - \"verdict\": \"CONFIRM|REJECT\", - \"reason\": \"Explanation\", - \"severityAdjustment\": \"null|blocker|critical|major|minor\" - }], - \"challenges\": [{ - \"challengeId\": \"CC-1\", - \"verdict\": \"CONFIRM|REJECT\", - \"reason\": \"Explanation\" - }], - \"blindSpots\": [{ - \"spotId\": \"BS-1\", - \"verdict\": \"CONFIRM|REJECT\", - \"reason\": \"Explanation\" - }] - } - - **Verdict rules:** - - CONFIRM: Issue exists / challenge valid / blind spot real - - REJECT: False positive, already covered, or not actionable -") -``` - -## Critic vs DoubleCheck - -| Aspect | DoubleCheck (Phase 5) | Critic (Phase 5.5) | DoubleCheck Critic (Phase 5.75) | -|--------|----------------------|--------------------|---------------------------------| -| **Goal** | Verify existing findings | Find missed issues | Verify Critic output | -| **Input** | Confirmed findings only | All findings + code + rejected | Critic output + code | -| **Output** | CONFIRM/REJECT per finding | New findings + challenges + blind spots | CONFIRM/REJECT per Critic item | -| **When** | Always (Phase 5) | Optional `-c` | Optional `-c` (after Critic) | -| **Adds findings** | No | Yes (P0 candidates) | No (filters P0) | -| **Agent** | `reviewer` (Opus) | `reviewer` (Opus) | `reviewer` (Opus) | -| **Perspective** | Validator — "Is this real?" | Adversary — "What did you miss?" | Validator — "Did Critic get it right?" | \ No newline at end of file diff --git a/brewcode/templates/skills/review/references/report-template.md b/brewcode/templates/skills/review/references/report-template.md deleted file mode 100644 index 05a8280..0000000 --- a/brewcode/templates/skills/review/references/report-template.md +++ /dev/null @@ -1,168 +0,0 @@ -# Report Template - -Output location: `.claude/tasks/reviews/{TIMESTAMP}_{NAME}_report.md` - -Naming convention: -- TIMESTAMP: YYYYMMDD_HHMMSS -- NAME: sanitized REVIEW_PROMPT (first 30 chars) - -## Template - -```markdown -# Code Review Report - -> **Scope:** {REVIEW_PROMPT} -> **Quorum:** {G}-{N}-{M} ({G} groups x {N} agents, threshold {M}) -> **Groups:** {GROUP_NAMES} -> **Total agents:** {G x N} = {TOTAL_AGENTS} -> **Generated:** {TIMESTAMP} -> **Critic:** {Enabled|Disabled} - -## Summary - -| Severity | P0 (Critic) | P1 (Confirmed) | P2 (Quorum) | P3 (Exception) | Total | -|----------|-------------|----------------|-------------|----------------|-------| -| Blocker | {N} | {N} | {N} | {N} | {N} | -| Critical | {N} | {N} | {N} | {N} | {N} | -| Major | {N} | {N} | {N} | {N} | {N} | -| Minor | {N} | {N} | {N} | {N} | {N} | -| **Total** | **{N}** | **{N}** | **{N}** | **{N}** | **{N}** | - ---- - -## Priority 0: Critic Findings (missed by all reviewers) - -> Only present when critic mode enabled (`-c`/`--critic`). - -| # | Severity | File:Line | Category | Issue | Suggestion | Source | -|---|----------|-----------|----------|-------|------------|--------| -| 1 | Critical | `path:42-45` | security | Short description | Fix approach | Critic | - -### P0-1: {Title} - -**File:** `{path}:{lineStart}-{lineEnd}` -**Severity:** {severity} | **Category:** {category} -**Source:** Critic (Devil's Advocate) | **Verified:** DoubleCheck Critic | **Confidence:** {confidence} - -**Description:** -{detailed_description} - -**Why missed:** -{explanation_why_all_reviewers_missed_this} - -**Suggestion:** -{suggestion} - -### Critic Challenges - -| # | Finding | Challenge Type | Reason | -|---|---------|---------------|--------| -| 1 | P1-3 | WRONG_CONFIRM | {reason} | - -### Blind Spots - -| # | Category | Note | -|---|----------|------| -| 1 | {category} | No findings in this area despite relevant code | - ---- - -## Priority 1: Confirmed (Quorum + DoubleCheck) - -| # | Severity | File:Line | Category | Issue | Suggestion | Consensus | -|---|----------|-----------|----------|-------|------------|-----------| -| 1 | Critical | `path:42-45` | security | Short description | Fix approach | 3/3 agents | - -### P1-1: {Title} - -**File:** `{path}:{lineStart}-{lineEnd}` -**Severity:** {severity} | **Category:** {category} -**Consensus:** {agent_count}/{total} agents | **Confidence:** {avg_confidence} - -**Description:** -{detailed_description} - -**Suggestion:** -{suggestion} - -**Reported by:** {agent_list} - ---- - -## Priority 2: Quorum Only (NOT DoubleCheck confirmed) - -| # | Severity | File:Line | Category | Issue | Suggestion | Consensus | -|---|----------|-----------|----------|-------|------------|-----------| -| ... | ... | ... | ... | ... | ... | ... | - ---- - -## Priority 3: Critical Without Quorum (Exceptions) - -> These blocker/critical findings did not reach quorum but warrant attention. - -| # | Severity | File:Line | Category | Issue | Agent | -|---|----------|-----------|----------|-------|-------| -| ... | ... | ... | ... | ... | ... | - ---- - -## Statistics - -| Metric | Value | -|--------|-------| -| Files reviewed | {COUNT} | -| Total findings (pre-quorum) | {COUNT} | -| Quorum passed | {COUNT} ({PERCENT}%) | -| DoubleCheck confirmed | {COUNT} ({PERCENT}%) | -| Discarded (no consensus) | {COUNT} | -| **Critic (when enabled)** | | -| Critic missed findings (raw) | {COUNT} | -| Critic missed findings (verified) | {COUNT} ({PERCENT}%) | -| Critic challenges (raw) | {COUNT} | -| Critic challenges (verified) | {COUNT} ({PERCENT}%) | -| Blind spots (raw / verified) | {COUNT} / {COUNT} | -| DoubleCheck Critic reject rate | {PERCENT}% | - -## Agent Performance - -| Agent | Findings | Confirmed | Rate | -|-------|----------|-----------|------| -| reviewer #1 | {N} | {N} | {PERCENT}% | -| reviewer #2 | {N} | {N} | {PERCENT}% | -| ... | ... | ... | ... | - ---- - -*Generated by brewcode:review | Quorum: {G}-{N}-{M} | Critic: {Enabled|Disabled}* -``` - -## Final Response Format - -**Without critic:** -``` -Review complete. Found {TOTAL} issues ({BLOCKERS} blocker, {CRITICAL} critical, {MAJOR} major). - -Priority breakdown: -- P1 (Confirmed): {COUNT} issues -- P2 (Quorum only): {COUNT} issues -- P3 (Exceptions): {COUNT} issues - -Full report: .claude/tasks/reviews/{TIMESTAMP}_{NAME}_report.md -``` - -**With critic (`-c`):** -``` -Review complete. Found {TOTAL} issues ({BLOCKERS} blocker, {CRITICAL} critical, {MAJOR} major). - -Priority breakdown: -- P0 (Critic): {COUNT} issues — verified by DoubleCheck -- P1 (Confirmed): {COUNT} issues -- P2 (Quorum only): {COUNT} issues -- P3 (Exceptions): {COUNT} issues - -Critic challenges: {COUNT} verdicts challenged ({ACCEPTED} accepted) -Blind spots: {COUNT} categories flagged - -Full report: .claude/tasks/reviews/{TIMESTAMP}_{NAME}_report.md -``` diff --git a/brewdoc/.claude-plugin/plugin.json b/brewdoc/.claude-plugin/plugin.json index 3996bdc..7d056c8 100644 --- a/brewdoc/.claude-plugin/plugin.json +++ b/brewdoc/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "brewdoc", - "version": "3.19.5", + "version": "4.0.0", "description": "Brewdoc - Claude Code documentation tools: auto-sync for skills/agents/rules, my-claude installation docs, memory optimization", "author": { "name": "Maksim Kochetkov", diff --git a/brewdoc/README.md b/brewdoc/README.md index f6d83c9..d2091da 100644 --- a/brewdoc/README.md +++ b/brewdoc/README.md @@ -7,7 +7,7 @@ | Version | 3.18.0 | | Skills | 6 | | Agents | 1 | -| Hooks | 1 | +| Hooks | 0 | ## Install @@ -99,9 +99,7 @@ claude --plugin-dir ./brewdoc brewdoc/ +-- .claude-plugin/plugin.json # Plugin manifest +-- hooks/ -| +-- hooks.json # 1 hook (Pre-Task) -| +-- pre-task.mjs # BD_PLUGIN_ROOT injection -| +-- lib/utils.mjs # I/O utilities +| +-- hooks.json # no hooks ({"hooks":{}}) +-- skills/ | +-- auto-sync/ # Documentation sync | +-- my-claude/ # Installation documentation @@ -113,7 +111,7 @@ brewdoc/ +-- bd-auto-sync-processor.md # File processing agent ``` -> **Brewdoc vs Brewcode:** Brewdoc is a set of documentation utilities. Each skill is self-contained. Brewcode is a task execution engine with infinite context, 9 lifecycle hooks, and session handoff. Both install from the same `claude-brewcode` marketplace but operate independently. +> **Brewdoc vs Brewcode:** Brewdoc is a set of documentation utilities. Each skill is self-contained. Brewcode is a task execution engine with infinite context, 2 hooks, and session handoff. Both install from the same `claude-brewcode` marketplace but operate independently. ## Documentation diff --git a/brewdoc/agents/bd-auto-sync-processor.md b/brewdoc/agents/bd-auto-sync-processor.md index a802109..205317e 100644 --- a/brewdoc/agents/bd-auto-sync-processor.md +++ b/brewdoc/agents/bd-auto-sync-processor.md @@ -14,7 +14,7 @@ Processes single document: analyze, research, apply changes. Prompt contains: `PATH: {path} | TYPE: {type} | FLAGS: {flags}` -> `$BD_PLUGIN_ROOT` is injected by brewdoc's `pre-task.mjs` hook as a separate prefix line at prompt top (not part of the pipe-delimited input). +> `${CLAUDE_PLUGIN_ROOT}` (brace form) is natively substituted at spawn to brewdoc's plugin root. Use it for all plugin resource paths below. ## Workflow @@ -24,9 +24,9 @@ Read file at `path`. Extract frontmatter fields: `auto-sync`, `auto-sync-date`, ### Step 2: Load Instructions -> `BD_PLUGIN_ROOT` is injected as plain text at prompt top by pre-task.mjs hook. Read value from there and substitute literally. If missing — **stop with error:** `BD_PLUGIN_ROOT not in prompt context, cannot load sync instructions.` +> Resolve paths via `${CLAUDE_PLUGIN_ROOT}` (brace form, natively substituted at spawn to this plugin's root). -**Always:** Read `$BD_PLUGIN_ROOT/skills/auto-sync/instructions/sync-{type}.md` for Verification Checklist and Research Directions. +**Always:** Read `${CLAUDE_PLUGIN_ROOT}/skills/auto-sync/instructions/sync-{type}.md` for Verification Checklist and Research Directions. **If `auto-sync-override:` found in frontmatter:** Parse 3 optional fields that **augment or selectively override** the instruction file: - `sources:` — additional glob patterns for context (merged with instruction Research Directions) @@ -38,7 +38,7 @@ Read file at `path`. Extract frontmatter fields: `auto-sync`, `auto-sync-date`, - Document body explicitly describes how it should be updated → use that, skip frontmatter creation - Neither → after Step 5, synthesize `auto-sync-override:` from findings and add to frontmatter (never to body) -**If FLAGS contains `optimize`:** Also read `$BD_PLUGIN_ROOT/skills/auto-sync/instructions/llm-text-rules.md`. +**If FLAGS contains `optimize`:** Also read `${CLAUDE_PLUGIN_ROOT}/skills/auto-sync/instructions/llm-text-rules.md`. Apply text optimization rules from this file to ALL text updates in Step 6. ### Step 3: Build Verification Plan diff --git a/brewdoc/docs/commands.md b/brewdoc/docs/commands.md index 5abad28..41f7522 100644 --- a/brewdoc/docs/commands.md +++ b/brewdoc/docs/commands.md @@ -382,6 +382,4 @@ No arguments. All interaction via `AskUserQuestion`. Each step can be skipped in ## Plugin Variable -| Variable | Injected By | Available In | Value | -|----------|-------------|--------------|-------| -| `BD_PLUGIN_ROOT` | pre-task.mjs | Agents (subagents via Task tool only) | Absolute path to brewdoc plugin root | +brewdoc has no hooks. The `bd-auto-sync-processor` agent resolves its plugin root natively via `${CLAUDE_PLUGIN_ROOT}` — substituted at Task spawn by Claude Code itself. No hook injection is needed. diff --git a/brewdoc/docs/hooks.md b/brewdoc/docs/hooks.md index 1551cc5..43ed632 100644 --- a/brewdoc/docs/hooks.md +++ b/brewdoc/docs/hooks.md @@ -1,295 +1,32 @@ --- auto-sync: enabled -auto-sync-date: 2026-02-28 +auto-sync-date: 2026-06-30 auto-sync-type: doc -description: Detailed description of brewdoc plugin hooks +description: Brewdoc hook configuration -- none active --- # Brewdoc Hooks -## Why Hooks? - -Claude Code plugins can define skills (slash commands) and agents. But agents spawned via the Task tool need to know WHERE the plugin is installed -- the absolute filesystem path changes with each version update and differs across machines. The pre-task hook solves this by automatically injecting `BD_PLUGIN_ROOT` into every subagent prompt. Without this hook, agents would need to hard-code paths that break on updates. - -brewdoc has exactly **1 hook**: - -1. **pre-task.mjs** -- injects `BD_PLUGIN_ROOT` into subagent prompts when skills spawn agents via the Task tool - -Skills running in the main conversation do NOT receive `BD_PLUGIN_ROOT`. They use relative paths or `${CLAUDE_SKILL_DIR}` to reference their own files. - -## Summary Table - -| Hook | Event | Matcher | Timeout | Purpose | -|------|-------|---------|---------|---------| -| `pre-task.mjs` | PreToolUse | `Task` | 3s | Prepend `BD_PLUGIN_ROOT` to subagent prompts | - -## Architecture Overview - -``` -Claude Code Session - | - | User runs /brewdoc:auto-sync or /brewdoc:memory etc. - | Skill runs in main conversation - | (uses relative paths or ${CLAUDE_SKILL_DIR} for own files) - | - | Skill spawns agents via Task tool - | - | PreToolUse:Task - v -+----------------------------------------------+ -| pre-task.mjs | -| | -| BD_PLUGIN_ROOT=/path/to/brewdoc/X.Y.Z | -| | -| --> prepended to agent prompt | -+----------------------------------------------+ - | - v - Agent receives prompt: - "BD_PLUGIN_ROOT=/path/to/brewdoc/X.Y.Z - - [original task prompt]" - | - | Agent reads instruction files: - | $BD_PLUGIN_ROOT/skills/auto-sync/instructions/sync-skill.md - | $BD_PLUGIN_ROOT/skills/memory/references/memory-guide.md - v - Agent completes task -``` - -## BD_PLUGIN_ROOT Variable - -`BD_PLUGIN_ROOT` is the absolute path to the brewdoc plugin root directory. It is derived from the `CLAUDE_PLUGIN_ROOT` environment variable that Claude Code sets for every plugin. - -### Flow - -``` -CLAUDE_PLUGIN_ROOT (env var set by Claude Code) - | - | pre-task.mjs reads it on every Task tool call - v -updatedInput.prompt in PreToolUse output: -"BD_PLUGIN_ROOT=/Users/.../.claude/plugins/cache/claude-brewcode/brewdoc/X.Y.Z - -[original agent prompt]" - | - v -Agent uses $BD_PLUGIN_ROOT to load reference files -``` - -### Injection Mechanism - -| Event | Hook | Channel | Target | -|-------|------|---------|--------| -| PreToolUse:Task | `pre-task.mjs` | `updatedInput.prompt` (prefix) | Subagent prompt | - -### Format - -``` -BD_PLUGIN_ROOT=/Users/maximus/.claude/plugins/cache/claude-brewcode/brewdoc/X.Y.Z -``` - -### Usage - -| Context | How to Use | -|---------|------------| -| Subagents (Task tool) | `$BD_PLUGIN_ROOT` prepended to prompt by pre-task.mjs | -| Skills (main conversation) | Use relative paths or `${CLAUDE_SKILL_DIR}` -- BD_PLUGIN_ROOT is NOT available | -| Hooks | `process.env.CLAUDE_PLUGIN_ROOT` (raw env var) | - ---- - -## Hook I/O Protocol - -Each hook communicates with Claude Code via JSON over stdio: - -1. Reads JSON from stdin (Claude Code sends event data) -2. Processes logic -3. Outputs JSON to stdout (Claude Code reads response) -4. Writes logs to stderr (visible in terminal) - -``` -Claude Code Hook - | | - |-- stdin: JSON event --> | - | | readStdin() -> parse - | | ... logic ... - | | output() -> JSON - |<-- stdout: response -- | - | | -``` - -All hooks use shared utilities from `hooks/lib/utils.mjs`: -- `readStdin()` -- reads and parses JSON from stdin -- `output(response)` -- serializes and writes JSON to stdout -- `log(level, prefix, message, cwd, sessionId)` -- writes to stderr - -**Error handling:** The hook catches all exceptions and calls `output({})` on failure -- silent pass-through, never blocks the session. - ---- - -## pre-task.mjs - -### Configuration - -| Field | Value | -|-------|-------| -| Event | `PreToolUse` | -| Matcher | `Task` tool only | -| Timeout | 3000 ms | -| Output channel | `updatedInput.prompt` | - -### Input +brewdoc ships **no runtime hooks**. The `hooks.json` file exists but is empty: ```json -{ - "session_id": "abc123def456...", - "cwd": "/path/to/project", - "tool_input": { - "subagent_type": "brewdoc:bd-auto-sync-processor", - "prompt": "PATH: doc.md | TYPE: skill | FLAGS: " - } -} +{"hooks":{}} ``` -### Behavior +## Why No Hooks? -| Condition | Result | -|-----------|--------| -| No `tool_input` | Pass-through (`output({})`) | -| No `subagent_type` | Pass-through (`output({})`) | -| `CLAUDE_PLUGIN_ROOT` not set | Pass-through (`output({})`) | -| All conditions met | Prepend `BD_PLUGIN_ROOT=...` to prompt | +A `PreToolUse:Task` hook previously handled plugin root injection for subagents so that agents could locate plugin reference files. This is no longer needed. The `bd-auto-sync-processor` agent resolves its plugin root natively via `${CLAUDE_PLUGIN_ROOT}` -- a brace-form substitution that Claude Code performs at Task spawn time. No hook, no extra injection step. -### Logic +## Path Resolution in bd-auto-sync-processor -``` -input = readStdin() -tool_input = input.tool_input +| Context | Variable | Resolved by | +|---------|----------|-------------| +| Subagent (`bd-auto-sync-processor`) | `${CLAUDE_PLUGIN_ROOT}` | Claude Code at Task spawn | +| Skills (main conversation) | `${CLAUDE_SKILL_DIR}` | Claude Code natively | -if !tool_input or !tool_input.subagent_type: - output({}) -- nothing to inject - return +## Comparison with brewcode -pluginRoot = process.env.CLAUDE_PLUGIN_ROOT || '' -if !pluginRoot: - output({}) -- no path to inject - return - -updatedPrompt = "BD_PLUGIN_ROOT={pluginRoot}\n\n{tool_input.prompt}" - -output: - hookSpecificOutput.hookEventName = "PreToolUse" - hookSpecificOutput.permissionDecision = "allow" - hookSpecificOutput.updatedInput = { ...tool_input, prompt: updatedPrompt } -``` - -### Output - -```json -{ - "hookSpecificOutput": { - "hookEventName": "PreToolUse", - "permissionDecision": "allow", - "updatedInput": { - "subagent_type": "brewdoc:bd-auto-sync-processor", - "prompt": "BD_PLUGIN_ROOT=/path/to/plugin\n\nPATH: doc.md | TYPE: skill | FLAGS: " - } - } -} -``` - -The original `tool_input` is spread into `updatedInput` -- all fields are preserved, only `prompt` is replaced with the prefixed version. - ---- - -## Lifecycle Diagram - -``` -+---------------------------------------------------------------+ -| Claude Code Session | -| | -| User: /brewdoc:memory | -| | | -| v | -| Skill runs in main conversation | -| (uses relative paths or ${CLAUDE_SKILL_DIR} for own files) | -| | | -| | Task(subagent_type="brewdoc:reviewer", prompt="...") | -| | | -| v | -| PreToolUse:Task --> pre-task.mjs --> BD_PLUGIN_ROOT in prompt | -| | | -| v | -| Agent: bd-auto-sync-processor, reviewer, etc. | -| Reads: $BD_PLUGIN_ROOT/skills/.../references/*.md | -| | -| [Task completes] | -| | -| Next agent spawn --> pre-task.mjs again --> BD_PLUGIN_ROOT | -+---------------------------------------------------------------+ -``` - -Key points: - -- `pre-task.mjs` fires on every `Task` tool call -- covers every subagent -- Skills in the main conversation do NOT have `BD_PLUGIN_ROOT` -- they use `${CLAUDE_SKILL_DIR}` or relative paths -- `BD_PLUGIN_ROOT` is only available inside subagent prompts - ---- - -## Library: hooks/lib/utils.mjs - -Shared utilities used by the hook. - -| Function | Signature | Description | -|----------|-----------|-------------| -| `readStdin()` | `() -> Promise` | Reads all chunks from stdin, parses as JSON. Throws on invalid JSON with first 100 chars of input. | -| `output(response)` | `(Object) -> void` | Serializes response to JSON and writes to stdout. On serialization failure, outputs error JSON. | -| `log(level, prefix, message, cwd, sessionId)` | `(string, string, string, string, string?) -> void` | Writes formatted log to stderr. Format: `{LEVEL} [{session_8chars}] {prefix} {message}`. `cwd` parameter kept for API compatibility but unused. | - ---- - -## Comparison with brewcode Hooks - -brewdoc is intentionally minimal. This table explains why brewdoc needs only 1 of brewcode's 7 hooks: - -| Feature | brewcode (7 hooks) | brewdoc (1 hook) | +| Feature | brewcode (2 hooks) | brewdoc (0 hooks) | |---------|-------------------|-------------------| -| Plugin root injection (subagents) | pre-task.mjs (BC_PLUGIN_ROOT) | pre-task.mjs (BD_PLUGIN_ROOT) | -| Plugin root injection (main conversation) | session-start.mjs | not needed (skills use relative paths) | -| KNOWLEDGE injection | pre-task.mjs injects into subagent prompts | not needed | -| Task lifecycle (lock, compact, stop) | pre-compact.mjs, stop.mjs, post-task.mjs | not needed | -| grepai integration | grepai-session.mjs, grepai-reminder.mjs | not needed | -| Plan symlinks | session-start.mjs (LATEST.md) | not needed | -| Session binding | post-task.mjs (lock file) | not needed | - -brewdoc is a documentation tool -- it does not manage long-running multi-phase tasks. It only needs to know where it is installed so agents can locate their instruction and reference files. - ---- - -## hooks.json Reference - -The complete hook registration file: - -```json -{ - "hooks": { - "PreToolUse": [ - { - "matcher": "Task", - "hooks": [ - { - "type": "command", - "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/pre-task.mjs\"", - "timeout": 3000 - } - ] - } - ] - } -} -``` - -- `${CLAUDE_PLUGIN_ROOT}` is expanded by Claude Code at runtime to the plugin's installed path -- `matcher: "Task"` restricts `pre-task.mjs` to fire only on Task tool calls (subagent spawns) +| Plugin root injection (subagents) | hook injects `BC_PLUGIN_ROOT` into prompt | not needed -- native `${CLAUDE_PLUGIN_ROOT}` | +| Session init / skill activation | `session-start.mjs`, `forced-eval.mjs` | not needed | diff --git a/brewdoc/hooks/hooks.json b/brewdoc/hooks/hooks.json index dc4b825..deffac9 100644 --- a/brewdoc/hooks/hooks.json +++ b/brewdoc/hooks/hooks.json @@ -1,17 +1,3 @@ { - "hooks": { - "PreToolUse": [ - { - "matcher": "Task", - "hooks": [ - { - "type": "command", - "command": "node", - "args": ["${CLAUDE_PLUGIN_ROOT}/hooks/pre-task.mjs"], - "timeout": 3000 - } - ] - } - ] - } + "hooks": {} } diff --git a/brewdoc/hooks/pre-task.mjs b/brewdoc/hooks/pre-task.mjs deleted file mode 100644 index 27b6d98..0000000 --- a/brewdoc/hooks/pre-task.mjs +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env node -import { readStdin, output, log } from './lib/utils.mjs'; - -async function main() { - let cwd = null; - let session_id = null; - try { - cwd = process.cwd(); - const input = await readStdin(); - session_id = input.session_id; - cwd = input.cwd || cwd; - const tool_input = input.tool_input; - - if (!tool_input || !tool_input.subagent_type) { - output({}); - return; - } - - const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT || ''; - if (!pluginRoot) { - output({}); - return; - } - - const pluginData = process.env.CLAUDE_PLUGIN_DATA || ''; - const dataLine = pluginData ? `BD_PLUGIN_DATA=${pluginData}\n` : ''; - const updatedPrompt = `BD_PLUGIN_ROOT=${pluginRoot}\n${dataLine}\n${tool_input.prompt || ''}`; - - output({ - hookSpecificOutput: { - hookEventName: 'PreToolUse', - permissionDecision: 'allow', - updatedInput: { - ...tool_input, - prompt: updatedPrompt - } - } - }); - } catch (error) { - log('error', '[pre-task]', `Error: ${error.message}`, cwd, session_id); - output({}); - } -} - -main(); diff --git a/brewdoc/skills/guide/README.md b/brewdoc/skills/guide/README.md index 0ac8993..e9f1d04 100644 --- a/brewdoc/skills/guide/README.md +++ b/brewdoc/skills/guide/README.md @@ -18,7 +18,7 @@ Guide walks you through every feature of the plugin suite across three progressi /brewdoc:guide # Interactive menu /brewdoc:guide overview # Jump to a specific topic /brewdoc:guide killer-flow # Spec/Plan/Start pipeline -/brewdoc:guide agents-catalog # All 16 agents +/brewdoc:guide agents-catalog # All 14 agents ``` ## Topics @@ -29,8 +29,8 @@ Guide walks you through every feature of the plugin suite across three progressi | A: Getting Started | installation | Marketplace setup, installing plugins, verifying versions | | B: Core Workflow | killer-flow | The infinite task pipeline: spec, plan, start | | B: Core Workflow | teams | Dynamic agent teams with self-selection and tracking | -| B: Core Workflow | skills-catalog | All 32 skills with trigger examples | -| C: Mastery | agents-catalog | All 16 agents with roles and model selection | +| B: Core Workflow | skills-catalog | All 25 skills with trigger examples | +| C: Mastery | agents-catalog | All 14 agents with roles and model selection | | C: Mastery | customization | Create custom skills, agents, and hooks | | C: Mastery | integration | CLAUDE.md, rules, memory, teams directory | | C: Mastery | advanced | Grepai, convention, quorum review, secrets scanning | diff --git a/brewdoc/skills/guide/SKILL.md b/brewdoc/skills/guide/SKILL.md index 4eebf0d..60b806e 100644 --- a/brewdoc/skills/guide/SKILL.md +++ b/brewdoc/skills/guide/SKILL.md @@ -255,7 +255,7 @@ bash "${CLAUDE_SKILL_DIR}/scripts/progress.sh" complete "{TOPIC_ID}" You now know everything about the brewcode plugin suite. Useful next steps: - - Run /brewcode:setup in your project + - Index your project with /brewcode:grepai - Create a team with /brewcode:teams create - Start a task with /brewcode:spec "your task description" ``` diff --git a/brewdoc/skills/guide/references/ascii-diagrams.md b/brewdoc/skills/guide/references/ascii-diagrams.md index 2a66b9a..464b014 100644 --- a/brewdoc/skills/guide/references/ascii-diagrams.md +++ b/brewdoc/skills/guide/references/ascii-diagrams.md @@ -16,7 +16,7 @@ Pre-drawn diagrams for the guide skill. Reference by name from topic files. │ convention, e2e │ md-to-pdf │ │ │ rules, grepai │ guide │ │ │ │ publish │ │ -│ + 16 agents │ │ │ +│ + 14 agents │ │ │ │ + 9 hooks │ │ │ └─────────────────┴──────────────┴────────────────┘ ``` @@ -66,25 +66,17 @@ Pre-drawn diagrams for the guide skill. Reference by name from topic files. ## Diagram: Hook Chain ``` -SessionStart PreToolUse:Task PostToolUse:Task - │ │ │ - v v v -┌────────────┐ ┌────────────┐ ┌─────────────┐ -│ session- │ │ pre-task │ │ post-task │ -│ start.mjs │ │ inject ctx │ │ bind session│ -└────────────┘ └────────────┘ └─────────────┘ - │ │ - v v -┌────────────┐ ┌─────────────┐ -│ grepai- │ PreCompact │ Stop │ -│ session │ │ │ event │ -└────────────┘ v └──────┬──────┘ - ┌────────────┐ v - │ pre-compact│ ┌─────────────┐ - │ compact KN │ │ stop.mjs │ - │ write hoff │ │ block if │ - └────────────┘ │ not terminal│ - └─────────────┘ +SessionStart UserPromptSubmit + │ │ + ├───────────────────┐ ┌───────┴───────────┐ + v v v v +┌────────────┐ ┌────────────┐ ┌────────────┐ ┌──────────────┐ +│ bc: │ │ bt: │ │ bc: │ │ bt: │ +│ session- │ │ session- │ │ forced- │ │ manager- │ +│ start.mjs │ │ start.mjs │ │ eval.mjs │ │ prompt.mjs │ +│ version + │ │ HARD-wall │ │ [SKILL?] │ │ ++m/++rr/++r │ +│ perm_mode │ │ awareness │ │ reminder │ │ codewords │ +└────────────┘ └────────────┘ └────────────┘ └──────────────┘ ``` ## Diagram: Project Directory diff --git a/brewdoc/skills/guide/references/topic-advanced.md b/brewdoc/skills/guide/references/topic-advanced.md index 324a093..22890ed 100644 --- a/brewdoc/skills/guide/references/topic-advanced.md +++ b/brewdoc/skills/guide/references/topic-advanced.md @@ -63,16 +63,13 @@ Output goes to `.claude/rules/` as auto-loaded rule files. New code follows your The convention skill identifies etalon (reference) classes in your codebase. These become the standard that generated rules point to. -## Section 3: Standards Review +## Section 3: Deep Code Review Quorum code review with multiple independent perspectives. ```bash -# Plugin skill for standards compliance: -/brewcode:standards-review - -# Local quorum review (generated by /brewcode:setup): -/brewcode:review +# Deep multi-perspective review: +/brewcode:superreview ``` How it works: @@ -113,4 +110,4 @@ How it works: - Zero false positives design — only flags high-confidence matches - Reports file, line number, and credential type -Best practice: run `/brewtools:secrets-scan` before commits as part of your workflow. Combine with `/brewcode:review` for comprehensive pre-merge checks. +Best practice: run `/brewtools:secrets-scan` before commits as part of your workflow. Combine with `/brewcode:superreview` for comprehensive pre-merge checks. diff --git a/brewdoc/skills/guide/references/topic-customization.md b/brewdoc/skills/guide/references/topic-customization.md index 8028f14..34d56ab 100644 --- a/brewdoc/skills/guide/references/topic-customization.md +++ b/brewdoc/skills/guide/references/topic-customization.md @@ -101,31 +101,23 @@ Response channels: `additionalContext` (inject text), `updatedInput` (PreToolUse ### Hooks shipped with brewcode suite -**brewcode (7):** +**brewcode (2):** | Hook | Event | Purpose | |------|-------|---------| -| `session-start.mjs` | SessionStart | Session initialization | -| `grepai-session.mjs` | SessionStart | Auto-starts grepai watch | -| `pre-task.mjs` | PreToolUse:Task\|Agent | Injects grepai + KNOWLEDGE into prompts | -| `grepai-reminder.mjs` | PreToolUse:Glob\|Grep | Reminds to use grepai first | -| `post-task.mjs` | PostToolUse:Task | Binds session, enforces 2-step protocol (success/failure branching) | -| `pre-compact.mjs` | PreCompact | Compacts KNOWLEDGE, writes handoff (respects terminal statuses) | -| `stop.mjs` | Stop | Blocks if not terminal (finished/failed/cancelled/error), cleans lock | +| `session-start.mjs` | SessionStart | Version check, permission_mode tag | +| `forced-eval.mjs` | UserPromptSubmit | Skill-activation [SKILL?] reminder | -**brewtools (3):** +**brewtools (2):** | Hook | Event | Purpose | |------|-------|---------| -| `session-start.mjs` | SessionStart | Sets `BT_PLUGIN_ROOT`, session bootstrap | -| `pre-task.mjs` | PreToolUse:Task\|Agent | Injects `BT_PLUGIN_ROOT` into subagent prompts | -| `manager-prompt.mjs` | UserPromptSubmit | Injects Manager prompt on ++m/++mp codeword | +| `session-start.mjs` | SessionStart | Manager HARD-wall awareness, session bootstrap | +| `manager-prompt.mjs` | UserPromptSubmit | ++m/++rr/++r codeword injection (plan-aware) | -**brewdoc (1):** +**brewdoc (0):** No hooks. -| Hook | Event | Purpose | -|------|-------|---------| -| `pre-task.mjs` | PreToolUse:Task\|Agent | Injects `BD_PLUGIN_ROOT` into subagent prompts | +**brewui (0):** No hooks. ## Section 4: Dynamic Teams diff --git a/brewdoc/skills/guide/references/topic-installation.md b/brewdoc/skills/guide/references/topic-installation.md index 2a31405..a83144c 100644 --- a/brewdoc/skills/guide/references/topic-installation.md +++ b/brewdoc/skills/guide/references/topic-installation.md @@ -51,10 +51,10 @@ You should see all four plugins with matching version numbers. Quick smoke test: ```bash -/brewcode:setup +/brewcode:grepai ``` -If the setup wizard starts, installation is working. +If the grepai setup starts, installation is working. ## Section 4: Updating diff --git a/brewdoc/skills/guide/references/topic-integration.md b/brewdoc/skills/guide/references/topic-integration.md index 34c2a7f..42374e3 100644 --- a/brewdoc/skills/guide/references/topic-integration.md +++ b/brewdoc/skills/guide/references/topic-integration.md @@ -128,6 +128,5 @@ Complete directory layout for a project using brewcode: ``` Key directories: -- `cfg/` — created by `/brewcode:setup`, stores config and state - `tasks/` — each task gets its own isolated directory - `teams/` — created by `/brewcode:teams`, stores generated agents diff --git a/brewdoc/skills/guide/references/topic-killer-flow.md b/brewdoc/skills/guide/references/topic-killer-flow.md index 23da0b7..4fd83ec 100644 --- a/brewdoc/skills/guide/references/topic-killer-flow.md +++ b/brewdoc/skills/guide/references/topic-killer-flow.md @@ -42,7 +42,7 @@ The "infinite" part: tasks survive context window limits automatically. No user intervention needed. The hook chain drives it all: ``` -session-start -> pre-task -> post-task -> pre-compact -> stop +session-start -> forced-eval ``` Pre-compact writes handoff state. Session-start reads it back. The loop is seamless. @@ -66,7 +66,7 @@ Priority levels (highest to lowest): | ✅ | Do this instead | "Always use ORM query builder" | | ℹ️ | Informational fact | "Project uses Spring Boot 3.2" | -Knowledge is injected into every agent prompt via the pre-task hook. Agents learn from previous sessions without re-discovering. +Knowledge persists across sessions. Agents learn from previous sessions without re-discovering. ## Section 4: Task Directory Structure diff --git a/brewdoc/skills/guide/references/topic-overview.md b/brewdoc/skills/guide/references/topic-overview.md index 522cf36..ddb00b7 100644 --- a/brewdoc/skills/guide/references/topic-overview.md +++ b/brewdoc/skills/guide/references/topic-overview.md @@ -19,9 +19,9 @@ One marketplace, four plugins, one version number. Install what you need. | Plugin | Purpose | Key Skills | |--------|---------|------------| -| brewcode | Infinite task execution, agent teams, project automation | setup, spec, plan, start, teams, review, convention, e2e | +| brewcode | Spec authoring, semantic search, deep review, agent teams | spec, grepai, superreview, convention, teams, e2e | | brewdoc | Documentation tools: sync, generate, optimize, publish | auto-sync, my-claude, memory, md-to-pdf, guide, publish | -| brewtools | Universal utilities: text optimization, security scanning | text-optimize, text-human, secrets-scan, ssh, deploy, debate, plugin-update | +| brewtools | Universal utilities: text optimization, security scanning | text-optimize, text-human, secrets-scan, ssh, deploy, plugin-update | | brewui | UI/visual/creative tools (placeholder, empty) | (none yet) | **brewcode** is the core. It runs tasks that survive context limits through automatic handoff. It manages agents, hooks, and knowledge persistence. @@ -44,9 +44,9 @@ The plugins complement each other: All four share the same version number. They update together from the same marketplace. No version mismatches. Example workflow: -1. `/brewcode:setup` initializes a project -2. `/brewcode:spec` + `/brewcode:plan` + `/brewcode:start` executes a feature -3. `/brewdoc:auto-sync` updates affected documentation +1. `/brewcode:grepai` indexes the project for semantic search +2. `/brewcode:spec` defines the feature, then you implement it +3. `/brewcode:superreview` reviews it, `/brewdoc:auto-sync` updates docs 4. `/brewtools:secrets-scan` checks nothing was leaked ## Section 4: What Makes It Unique diff --git a/brewdoc/skills/guide/references/topic-skills-catalog.md b/brewdoc/skills/guide/references/topic-skills-catalog.md index 6c03514..ad2532d 100644 --- a/brewdoc/skills/guide/references/topic-skills-catalog.md +++ b/brewdoc/skills/guide/references/topic-skills-catalog.md @@ -2,29 +2,23 @@ Domain: Core Workflow -## Section 1: Brewcode Skills (13) +## Section 1: Brewcode Skills (9) -The main plugin. Task execution, code quality, project management. +The main plugin. Spec authoring, semantic search, code quality. | Skill | Purpose | |-------|---------| -| `/brewcode:setup` | Analyze project, create templates, check prerequisites | | `/brewcode:spec "desc"` | Create SPEC through research + user interaction | -| `/brewcode:plan` | Create PLAN.md from SPEC with phases and dependencies | -| `/brewcode:start` | Execute plan with infinite context handoff | -| `/brewcode:teams` | Create and manage dynamic agent teams | -| `/brewcode:convention` | Extract code conventions, patterns, architecture | -| `/brewcode:rules` | Convert KNOWLEDGE.jsonl to `.claude/rules/` files | | `/brewcode:grepai` | Setup grepai semantic code search | -| `/brewcode:standards-review` | Review code against project standards | -| `/brewcode:teardown` | Cleanup task files (keeps task directory) | +| `/brewcode:superreview` | Deep multi-perspective quorum code review | +| `/brewcode:convention` | Extract code conventions, patterns, architecture | +| `/brewcode:rules` | Prompt-driven rules management: status, create, improve, review | +| `/brewcode:teams` | Create and manage dynamic agent teams | | `/brewcode:e2e` | Full-cycle E2E test orchestration | -| `/brewcode:skills` | Skill management utilities | -| `/brewcode:agents` | Agent management utilities | +| `/brewcode:skills` | Prompt-driven skill management: status, create, improve, review | +| `/brewcode:agents` | Prompt-driven agent management: status, create, improve, review | -Note: `/brewcode:setup` also generates a local `/brewcode:review` skill for quorum code review (3 reviewers, 2/3 consensus). It is project-specific, not shipped with the plugin. - -Typical flow: `setup` (once) -> `spec` -> `plan` -> `start` -> `standards-review` +Typical flow: `spec` -> implement -> `superreview` (use `grepai` for search) ## Section 2: Brewdoc Skills (6) @@ -39,7 +33,7 @@ Documentation tools. Sync, generate, optimize, export, publish. | `/brewdoc:guide` | Interactive teaching for the plugin suite (this guide) | | `/brewdoc:publish` | Publish content to brewpage.app — text, markdown, or files | -## Section 3: Brewtools Skills (13) +## Section 3: Brewtools Skills (10) Universal utilities. Work in any project, no setup needed. @@ -50,13 +44,10 @@ Universal utilities. Work in any project, no setup needed. | `/brewtools:secrets-scan` | Scan for leaked secrets, credentials, API keys | | `/brewtools:ssh` | SSH server management — connect, configure, deploy, administer remote servers | | `/brewtools:deploy` | GitHub Actions deployment — workflows, releases, GHCR, CI/CD with safety gates | -| `/brewtools:debate` | Evidence-based multi-agent debate with Discovery phase and 3 modes | | `/brewtools:plugin-update` | Check, install, or update brewcode suite plugins from the marketplace | | `/brewtools:provider-switch` | Configure alternative API providers — DeepSeek V4 (priority), Z.ai/GLM, Qwen, MiniMax, OpenRouter | -| `/brewtools:skill-toggle` | Disable/enable individual plugin skills, survives plugin updates | -| `/brewtools:agent-toggle` | Disable/enable individual plugin agents, survives plugin updates | -| `/brewtools:think-short` | Toggle terse-output mode (light/medium/aggressive) to cut token bloat | -| `/brewtools:manager` | Codeword (++m/++mp) Manager prompt + opt-in HARD wall blocking mutating tools (RU+EN) | +| `/brewtools:think-short` | Install terse-mode hooks (project or global) that inject brevity directives to cut token bloat | +| `/brewtools:manager` | Codeword (++m, plan-aware) Manager prompt + opt-in HARD wall blocking mutating tools (RU+EN) | | `/brewtools:task-board-init` | Deploy a file-based Kanban into any repo via multi-agent analysis | These are standalone — no project configuration required. Run them anywhere. @@ -72,23 +63,20 @@ Brewui currently ships no skills -- placeholder for future UI/visual/creative to /brewcode:spec "add user authentication with OAuth2" /brewcode:teams create backend-team /brewcode:convention extract -/brewcode:review -q 3-5 +/brewcode:superreview ``` **Recommended order for new projects:** | Step | Skill | Why | |------|-------|-----| -| 1 | `/brewcode:setup` | Initialize project, detect stack | -| 2 | `/brewcode:grepai` | Enable semantic search | -| 3 | `/brewcode:convention` | Learn existing patterns | -| 4 | `/brewcode:spec "task"` | Define what to build | -| 5 | `/brewcode:plan` | Create execution plan | -| 6 | `/brewcode:start` | Execute the plan | -| 7 | `/brewcode:standards-review` | Review the result | -| 8 | `/brewcode:rules` | Save learnings as rules | +| 1 | `/brewcode:grepai` | Enable semantic search | +| 2 | `/brewcode:convention` | Learn existing patterns | +| 3 | `/brewcode:spec "task"` | Define what to build | +| 4 | `/brewcode:superreview` | Review the result | +| 5 | `/brewcode:rules` | Save learnings as rules | **Tips:** - Skills that modify files always confirm before writing -- Use `/brewcode:setup` first in any new project — it detects your stack and creates templates -- `/brewcode:teardown` removes task artifacts but keeps the task directory for reference +- Use `/brewcode:grepai` first in any new project — it indexes your code for semantic search +- `/brewcode:convention` extracts patterns so new code matches your existing style diff --git a/brewtools/.claude-plugin/plugin.json b/brewtools/.claude-plugin/plugin.json index 6d3bfe8..7201d2b 100644 --- a/brewtools/.claude-plugin/plugin.json +++ b/brewtools/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "brewtools", - "version": "3.19.5", + "version": "4.0.0", "description": "Brewtools - universal utilities for Claude Code: text optimization, humanization, secrets scanning", "author": { "name": "Maksim Kochetkov", diff --git a/brewtools/README.md b/brewtools/README.md index 08fcd90..be9ff15 100644 --- a/brewtools/README.md +++ b/brewtools/README.md @@ -1,11 +1,11 @@ # Brewtools -> Universal text utilities plugin for Claude Code -- token optimization, AI artifact removal, secrets scanning, SSH management, GitHub Actions deployment, evidence-based debate, and plugin updates. +> Universal text utilities plugin for Claude Code -- token optimization, AI artifact removal, secrets scanning, SSH management, GitHub Actions deployment, and plugin updates. | Field | Value | |-------|-------| | Version | 3.18.0 | -| Skills | 13 | +| Skills | 10 | | Agents | 3 | ## Install @@ -41,7 +41,7 @@ Update anytime with `/brewtools:plugin-update`. ## Overview -Brewtools provides standalone utilities: token-efficient optimization with 30+ validated rules, universal AI-artifact removal with greedy flow detection across code/docs/articles/reddit/chat (five domain flows, two-pass strip+inject model), security scanning for leaked credentials, SSH server management, GitHub Actions deployment with safety gates, evidence-based multi-agent debate, and plugin check/install/update. Each skill is self-contained and requires no prior setup. +Brewtools provides standalone utilities: token-efficient optimization with 30+ validated rules, universal AI-artifact removal with greedy flow detection across code/docs/articles/reddit/chat (five domain flows, two-pass strip+inject model), security scanning for leaked credentials, SSH server management, GitHub Actions deployment with safety gates, and plugin check/install/update. Each skill is self-contained and requires no prior setup. ## Installation @@ -83,13 +83,10 @@ claude --plugin-dir ./brewtools | [`/brewtools:secrets-scan`](skills/secrets-scan/README.md) | Scan for leaked secrets and credentials | sonnet | `[--fix]` | | [`/brewtools:ssh`](skills/ssh/SKILL.md) | SSH server management and configuration | opus | `[connect\|deploy\|configure\|...]` | | [`/brewtools:deploy`](skills/deploy/SKILL.md) | GitHub Actions deployment with safety gates | opus | `[release\|workflow\|...]` | -| [`/brewtools:debate`](skills/debate/README.md) | Evidence-based multi-agent debate | sonnet | `[challenge\|strategy\|critic]` | -| [`/brewtools:manager`](skills/manager/README.md) | SOFT: codewords `++m`/`++mp` auto-inject a delegate-everything Manager prompt; `++rr`/`++r` auto-inject review discipline (anti-regression / two-phase double-check) (RU+EN). HARD: `on` installs a PreToolUse guard that blocks Write/Edit/NotebookEdit/WebFetch/MCP-write in the main session (subagents stay free); `off` disarms (registration stays, guard no-ops); `uninstall` deregisters; `level strict\|balanced` tunes the wall | sonnet | `[on\|off\|uninstall\|status\|level \|mode \|edit\|reset] \| ` | +| [`/brewtools:manager`](skills/manager/README.md) | SOFT: codeword `++m` auto-injects a delegate-everything Manager prompt (plan-aware: adds the plan supplement when the session is in plan mode); `++rr`/`++r` auto-inject review discipline (anti-regression / two-phase double-check) (RU+EN). HARD: `on` installs a PreToolUse guard that blocks Write/Edit/NotebookEdit/WebFetch/MCP-write in the main session (subagents stay free); `off` disarms (registration stays, guard no-ops); `uninstall` deregisters; `level strict\|balanced` tunes the wall | sonnet | `[on\|off\|uninstall\|status\|level \|edit\|reset] \| ` | | [`/brewtools:plugin-update`](skills/plugin-update/README.md) | Check/install/update brewcode plugins | sonnet | `[check\|update\|all]` | | [`/brewtools:provider-switch`](skills/provider-switch/README.md) | Configure alternative API providers (DeepSeek V4 [priority], Z.ai/GLM, Qwen, MiniMax, OpenRouter) | opus | `[status\|setup\|help\|]` | -| [`/brewtools:skill-toggle`](skills/skill-toggle/README.md) | Disable/enable individual plugin skills (survives plugin updates) | sonnet | ` [plugin:name] [--scope=global\|project]` | -| [`/brewtools:agent-toggle`](skills/agent-toggle/README.md) | Disable/enable individual plugin agents (survives plugin updates) | sonnet | ` [plugin:name] [--scope=global\|project]` | -| [`/brewtools:think-short`](skills/think-short/README.md) | Toggle terse-output mode — cut preamble/filler via SessionStart + PreToolUse:Task injection | sonnet | `[on\|off\|profile \|status\|blacklist add\|remove ]` | +| [`/brewtools:think-short`](skills/think-short/README.md) | Install/remove terse-mode hooks (SessionStart + every-10th UserPromptSubmit + subagent Task) that inject brevity directives; project or global | sonnet | `[] [Project\|Global]` | | [`/brewtools:task-board-init`](skills/task-board-init/README.md) | Deploy a self-contained file-based Kanban into ANY repo via multi-agent analysis (task-tracker agent + task-board skill + tasks rule + .claude/features/**) | opus | `[target repo path \| empty = cwd]` | ## Agents @@ -107,8 +104,8 @@ brewtools/ +-- .claude-plugin/plugin.json # Plugin manifest +-- hooks/ | +-- hooks.json # Hook registry -| +-- session-start.mjs # BT_PLUGIN_ROOT injection -| +-- pre-task.mjs # BT_PLUGIN_ROOT into subagents +| +-- session-start.mjs # Manager HARD-wall awareness +| +-- manager-prompt.mjs # ++m / ++rr / ++r codeword injection | +-- lib/utils.mjs # I/O utilities +-- skills/ | +-- text-optimize/ # Token optimization @@ -116,12 +113,9 @@ brewtools/ | +-- secrets-scan/ # Secrets scanning | +-- ssh/ # SSH server management | +-- deploy/ # GitHub Actions deployment -| +-- debate/ # Evidence-based multi-agent debate | +-- plugin-update/ # Plugin check / install / update | +-- provider-switch/ # Alternative API provider management -| +-- skill-toggle/ # Disable/enable individual plugin skills -| +-- agent-toggle/ # Disable/enable individual plugin agents -| +-- think-short/ # Terse-output mode toggle +| +-- think-short/ # Terse-mode hooks install/remove | +-- manager/ # Codeword-triggered Manager mode + HARD delegation wall | +-- task-board-init/ # File-based Kanban generator (multi-agent) +-- agents/ @@ -136,8 +130,8 @@ brewtools/ | Hook | Event | Purpose | |------|-------|---------| -| `session-start.mjs` | SessionStart | Inject `BT_PLUGIN_ROOT` into session context | -| `pre-task.mjs` | PreToolUse: Task\|Agent | Inject `BT_PLUGIN_ROOT` into subagent prompts | +| `session-start.mjs` | SessionStart | Manager HARD-wall awareness -- injects guard tag into systemMessage and additionalContext | +| `manager-prompt.mjs` | UserPromptSubmit | Injects `++m` / `++rr` / `++r` manager codewords | ## Documentation @@ -150,12 +144,9 @@ Full docs: [doc-claude.brewcode.app/brewtools/overview](https://doc-claude.brewc | Secrets Scan | [secrets-scan](https://doc-claude.brewcode.app/brewtools/skills/secrets-scan/) | | SSH | [ssh](https://doc-claude.brewcode.app/brewtools/skills/ssh/) | | Deploy | [deploy](https://doc-claude.brewcode.app/brewtools/skills/deploy/) | -| Debate | [debate](https://doc-claude.brewcode.app/brewtools/skills/debate/) | | Manager | [manager](https://doc-claude.brewcode.app/brewtools/skills/manager/) | | Plugin Update | [plugin-update](https://doc-claude.brewcode.app/brewtools/skills/plugin-update/) | | Provider Switch | [provider-switch](https://doc-claude.brewcode.app/brewtools/skills/provider-switch/) | -| Skill Toggle | [skill-toggle](https://doc-claude.brewcode.app/brewtools/skills/skill-toggle/) | -| Agent Toggle | [agent-toggle](https://doc-claude.brewcode.app/brewtools/skills/agent-toggle/) | | Think Short | [think-short](https://doc-claude.brewcode.app/brewtools/skills/think-short/) | | Release Notes | [RELEASE-NOTES.md](../RELEASE-NOTES.md) | diff --git a/brewtools/agents/deploy-admin.md b/brewtools/agents/deploy-admin.md index 52679f2..a982c24 100644 --- a/brewtools/agents/deploy-admin.md +++ b/brewtools/agents/deploy-admin.md @@ -1,7 +1,7 @@ --- name: deploy-admin description: "GitHub Actions deployment: workflows, releases, GHCR, CI/CD. Triggers: deploy, release." -model: opus +model: inherit tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion, WebFetch, WebSearch permissionMode: default --- @@ -13,15 +13,9 @@ permissionMode: default > Last updated: {{LAST_UPDATED}} -## Plugin Root Guard +## Plugin Root -`$BT_PLUGIN_ROOT` is **prompt text injected by hooks**, not a shell env var. - -**On every task start:** - -1. Check `$BT_PLUGIN_ROOT` is present in your context -2. If missing: **STOP** — report error: "BT_PLUGIN_ROOT not injected. Run with brewtools plugin enabled." -3. If present: use as prefix for plugin resource paths +Resolve plugin resource paths via `${CLAUDE_PLUGIN_ROOT}` (brace form, natively substituted at spawn to this plugin's root). Use it as the prefix for all plugin resource paths below. ## Safety Rules @@ -181,7 +175,7 @@ docker push ghcr.io/OWNER/IMAGE:TAG docker push ghcr.io/OWNER/IMAGE:latest ``` -> For full Docker registry auth reference: `Read $BT_PLUGIN_ROOT/skills/ssh/references/docker-auth-flow.md` +> For full Docker registry auth reference: `Read ${CLAUDE_PLUGIN_ROOT}/skills/ssh/references/docker-auth-flow.md` ## SSH Integration @@ -194,7 +188,7 @@ For VPS deployments and health checks, read `CLAUDE.local.md` in project root fo | GHCR login on server | `echo "$TOKEN" \| ssh USER@HOST 'docker login ghcr.io -u USERNAME --password-stdin'` | | Verify deployment | `ssh USER@HOST 'docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"'` | -> For detailed Docker auth flow on servers: `Read $BT_PLUGIN_ROOT/skills/ssh/references/docker-auth-flow.md` +> For detailed Docker auth flow on servers: `Read ${CLAUDE_PLUGIN_ROOT}/skills/ssh/references/docker-auth-flow.md` ## Emergency Stop diff --git a/brewtools/agents/ssh-admin.md b/brewtools/agents/ssh-admin.md index 420447c..7d19245 100644 --- a/brewtools/agents/ssh-admin.md +++ b/brewtools/agents/ssh-admin.md @@ -1,7 +1,7 @@ --- name: ssh-admin description: "Linux server admin: SSH, Docker, systemd, Nginx, SSL. Triggers: ssh admin, server management." -model: opus +model: inherit tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion, WebFetch, WebSearch permissionMode: default --- diff --git a/brewtools/agents/text-optimizer.md b/brewtools/agents/text-optimizer.md index 030f215..626ffde 100644 --- a/brewtools/agents/text-optimizer.md +++ b/brewtools/agents/text-optimizer.md @@ -13,11 +13,11 @@ Lean execution engine: load rules from reference, analyze target, apply optimiza ## Step 0: Load Rules (REQUIRED) -Read `$BT_PLUGIN_ROOT/skills/text-optimize/references/rules-review.md` using Read tool. +Read `${CLAUDE_PLUGIN_ROOT}/skills/text-optimize/references/rules-review.md` using Read tool (`${CLAUDE_PLUGIN_ROOT}` brace form is natively substituted at spawn to this plugin's root). **Verify:** File contains `## C - Claude Behavior` header and `## Sources` section. -> **STOP if read fails or headers missing** — Cannot optimize without rules reference. Report error: `❌ rules-review.md not loaded. Check $BT_PLUGIN_ROOT value.` Do not proceed to Step 1. +> **STOP if read fails or headers missing** — Cannot optimize without rules reference. Report error: `❌ rules-review.md not loaded.` Do not proceed to Step 1. ## Content Type Priorities @@ -48,11 +48,11 @@ Check prompt for mode flag (`-l`, `-s`, `-d`) or context hints. If no flag: - Unknown → use medium (default) ### Step 2: Load References -- Always: Read `$BT_PLUGIN_ROOT/skills/text-optimize/references/rules-review.md` -- Standard mode: Also read `$BT_PLUGIN_ROOT/skills/text-optimize/references/standard-compression.md` -- Deep mode: Also read `$BT_PLUGIN_ROOT/skills/text-optimize/references/deep-compression.md` +- Always: Read `${CLAUDE_PLUGIN_ROOT}/skills/text-optimize/references/rules-review.md` +- Standard mode: Also read `${CLAUDE_PLUGIN_ROOT}/skills/text-optimize/references/standard-compression.md` +- Deep mode: Also read `${CLAUDE_PLUGIN_ROOT}/skills/text-optimize/references/deep-compression.md` -> STOP if rules-review.md read fails — report error: `❌ rules-review.md not loaded. Check $BT_PLUGIN_ROOT value.` +> STOP if rules-review.md read fails — report error: `❌ rules-review.md not loaded.` ### Step 3: Analyze Read target → identify content type from table above → measure baseline (lines, ~tokens) → note critical info to preserve. diff --git a/brewtools/hooks/hooks.json b/brewtools/hooks/hooks.json index ddd14ac..a6029bf 100644 --- a/brewtools/hooks/hooks.json +++ b/brewtools/hooks/hooks.json @@ -1,18 +1,5 @@ { "hooks": { - "PreToolUse": [ - { - "matcher": "Task|Agent", - "hooks": [ - { - "type": "command", - "command": "node", - "args": ["${CLAUDE_PLUGIN_ROOT}/hooks/pre-task.mjs"], - "timeout": 3000 - } - ] - } - ], "SessionStart": [ { "hooks": [ diff --git a/brewtools/hooks/lib/manager-prompts.mjs b/brewtools/hooks/lib/manager-prompts.mjs index 786d34b..2496eb9 100644 --- a/brewtools/hooks/lib/manager-prompts.mjs +++ b/brewtools/hooks/lib/manager-prompts.mjs @@ -11,6 +11,9 @@ import os from 'node:os'; import path from 'node:path'; const VALID_SCOPES = new Set(['project', 'global']); +// 'planmode' is now hook-INTERNAL (selected by ++m when permission_mode === 'plan'), +// not a user-typed codeword. It stays resolvable here so the plan-aware ++m and the +// status explainer can still load its block. export const VALID_MODES = new Set(['full', 'planmode', 'review-regression', 'review-double']); function resolveHome(p) { diff --git a/brewtools/hooks/lib/manager-state.mjs b/brewtools/hooks/lib/manager-state.mjs index cd7b3d9..fe59d6d 100644 --- a/brewtools/hooks/lib/manager-state.mjs +++ b/brewtools/hooks/lib/manager-state.mjs @@ -1,8 +1,11 @@ // brewtools:manager — Manager mode state resolver/writer. -// State shape: { hard:boolean, level:'strict'|'balanced', mode:'full'|'planmode' }. +// State shape: { hard:boolean, level:'strict'|'balanced', mode:'full' }. // hard — HARD wall toggle (PreToolUse guard physically denies main-session tools) // level — HARD wall strictness: 'strict' (deny all non-read) | 'balanced' (allow read-only bash/search) -// mode — soft codeword injection mode: 'full' | 'planmode' +// mode — vestigial informational field, ALWAYS 'full'. No user action sets it; +// kept so status/readers of state.mode keep working. planmode is NOT a stored +// mode — ++m derives it at runtime from permission_mode === 'plan'; planmode +// stays resolvable in manager-prompts.mjs only. // project: /.claude/brewtools/manager/state.json // global: ~/.claude/manager/state.json (protected for Write tool — only writable here) // resolveState: hard + level are PROJECT-ONLY (a global state.json must NOT enable the @@ -39,7 +42,9 @@ export function resolveStatePath(scope, cwd = process.cwd()) { } function clampMode(merged) { - if (!['full', 'planmode'].includes(merged.mode)) merged.mode = 'full'; + // mode is vestigial — always 'full'. planmode is hook-internal (driven by + // permission_mode in manager-prompt.mjs), never stored as state.mode. + if (merged.mode !== 'full') merged.mode = 'full'; return merged; } @@ -143,7 +148,7 @@ function writeAtomic(filePath, obj) { /** * Write (merge) Manager state for a scope, atomically. * @param {string} scope - 'project' | 'global' - * @param {object} partial - fields to merge (e.g. { enabled:false } or { mode:'planmode' }) + * @param {object} partial - fields to merge (e.g. { hard:false } or { level:'strict' }) * @param {string} cwd * @returns {{file:string, action:'written', state:object}} */ diff --git a/brewtools/hooks/manager-prompt.mjs b/brewtools/hooks/manager-prompt.mjs index 40528e0..34257d7 100644 --- a/brewtools/hooks/manager-prompt.mjs +++ b/brewtools/hooks/manager-prompt.mjs @@ -1,10 +1,11 @@ // brewtools:manager — UserPromptSubmit hook. // Injects Manager/Review mode block(s) via additionalContext. Triggers: -// 1. Codeword in prompt (always, regardless of state). Codewords form TWO +// 1. Codeword in prompt (always, regardless of state). THREE codewords in TWO // INDEPENDENT groups; a prompt may activate one from each: -// Manager group (mutually exclusive, ++mp wins over ++m): -// ++mp -> Manager + Plan Mode (planmode) -// ++m -> Manager mode (full) +// Manager group: +// ++m -> Manager mode. PLAN-AWARE: when permission_mode === 'plan' +// it injects the planmode block (full + plan addon); otherwise +// the plain full block. There is NO separate ++mp codeword. // Review group (mutually exclusive, ++rr wins over ++r): // ++rr -> Anti-regression review discipline // ++r -> Two-phase review discipline @@ -13,9 +14,8 @@ // Precedence: each group is detected INDEPENDENTLY. When both groups are present // we inject BOTH blocks (manager block first, then review block), concatenated // with a blank-line separator. When only one group is present, only that block -// is injected. Longer-prefix variants (++mp, ++rr) win over their shorter -// collisions (++m, ++r); the `(?![\w])` lookahead also keeps `++rr` from -// falsely matching ++r and `++mp` from matching ++m. +// is injected. The longer-prefix variant ++rr wins over ++r; the `(?![\w])` +// lookahead also keeps `++rr` from falsely matching ++r. // The review codewords are codeword-ONLY (no ambient/state injection). // Fail-safe: any error -> output({}) so the user's prompt is never broken. @@ -32,22 +32,23 @@ function capText(s, max = 9000) { (async () => { try { - const { prompt = '', cwd } = await readStdin(); + const { prompt = '', cwd, permission_mode } = await readStdin(); const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT; - const hasMP = /(? b === agent || b === agentShort); - if (blocked) { - tsLog('info', `Task(${agent}) — SKIP (agent in blacklist)`, cwd, session_id); - return { prompt: updatedPrompt, injected: false }; - } - } - - // Resolve profile file path - const profile = state.profile; - const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT; - let profilePath; - if (pluginRoot) { - profilePath = path.join(pluginRoot, 'skills/think-short/profiles', `${profile}.md`); - } else { - // Fallback: derive from this file's URL (hooks/ → up 2 → plugin root) - const here = path.dirname(fileURLToPath(import.meta.url)); - profilePath = path.resolve(here, '..', 'skills/think-short/profiles', `${profile}.md`); - } - - let content; - try { - content = await readFile(profilePath, 'utf8'); - } catch (err) { - tsLog('info', `Task(${agent}) — profile read failed at ${profilePath} (${err.message}), skipping`, cwd, session_id); - return { prompt: updatedPrompt, injected: false }; - } - - const lines = content.split('\n').map(l => l.trim()).filter(l => l.length > 0).slice(0, 2); - if (lines.length === 0) { - tsLog('info', `Task(${agent}) — profile empty at ${profilePath}, skipping`, cwd, session_id); - return { prompt: updatedPrompt, injected: false }; - } - - const header = `\n${lines.join('\n')}\n\n`; - const newPrompt = `${header}${updatedPrompt}`; - const injectedLen = header.length; - const origLen = updatedPrompt.length; - - tsLog('info', `Task(${agent}) — injecting profile-lite (~${Math.ceil(injectedLen / 4)} tok)`, cwd, session_id); - if (process.env.CLAUDE_DEBUG === '1') { - tsLog('info', `original prompt length=${origLen}, injected length=${injectedLen}, total=${origLen + injectedLen}`, cwd, session_id); - } - return { prompt: newPrompt, injected: true }; - } catch (err) { - tsLog('info', `Task(${agent}) — unexpected error (${err.message}), skipping`, cwd, session_id); - return { prompt: updatedPrompt, injected: false }; - } -} - -async function main() { - let cwd = null; - let session_id = null; - - try { - cwd = process.cwd(); - const input = await readStdin(); - session_id = input.session_id; - cwd = input.cwd || cwd; - const tool_input = input.tool_input; - - if (!tool_input || !tool_input.subagent_type) { - output({}); - return; - } - - // Auto-enable think-short=light when effort=low (CC 2.1.115+). - await maybeAutoEnableThinkShortLow(input, cwd, session_id); - - let updatedPrompt = tool_input.prompt || ''; - let modified = false; - - const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT || ''; - if (pluginRoot) { - updatedPrompt = `BT_PLUGIN_ROOT=${pluginRoot}\n\n${updatedPrompt}`; - modified = true; - rawLog('debug', '[pre-task]', `Injected BT_PLUGIN_ROOT for ${tool_input.subagent_type}`, cwd, session_id); - } - - // think-short injection (isolated — never breaks BT_PLUGIN_ROOT) - try { - const result = await tryInjectThinkShort(updatedPrompt, tool_input, cwd, session_id); - if (result.injected) { - updatedPrompt = result.prompt; - modified = true; - } - } catch (err) { - tsLog('info', `Task(${tool_input.subagent_type}) — outer guard caught (${err.message}), skipping`, cwd, session_id); - } - - if (modified) { - output({ - hookSpecificOutput: { - hookEventName: 'PreToolUse', - permissionDecision: 'allow', - updatedInput: { - ...tool_input, - prompt: updatedPrompt - } - } - }); - } else { - output({}); - } - } catch (error) { - rawLog('error', '[pre-task]', `Error: ${error.message}`, cwd, session_id); - output({}); - } -} - -main(); diff --git a/brewtools/hooks/session-start.mjs b/brewtools/hooks/session-start.mjs index 906778f..dc00a33 100644 --- a/brewtools/hooks/session-start.mjs +++ b/brewtools/hooks/session-start.mjs @@ -1,113 +1,6 @@ #!/usr/bin/env node -import { readFile, mkdir, writeFile, access } from 'node:fs/promises'; -import path from 'node:path'; -import { fileURLToPath } from 'node:url'; import { readStdin, output, log } from './lib/utils.mjs'; -/** - * Auto-enable think-short=light when effort=low (CC 2.1.115+). - * Idempotent: marker file prevents double-toggle across repeated SessionStart fires. - * Returns true if newly auto-enabled this call. - */ -async function maybeAutoEnableThinkShortLow(input, cwd, session_id) { - try { - // NOTE: effort.level is NOT in HOOKS-REFERENCE.md (2.1.195). Presence-guarded existing read; do not expand to other hooks. - if (input.effort?.level !== 'low') return false; - if (!session_id || !cwd) return false; - - const markerDir = path.join(cwd, '.claude', 'tasks', 'sessions'); - const markerPath = path.join(markerDir, `${session_id}.think-short-effort-low`); - - try { - await access(markerPath); - // Marker exists — already auto-enabled for this session. - return false; - } catch { - // No marker — proceed. - } - - const { resolveEffectiveState, writeState } = await import('../skills/think-short/helpers/state.mjs'); - let state; - try { - state = await resolveEffectiveState(cwd); - } catch { - state = null; - } - - // Only auto-enable if not already enabled (respect explicit user state). - if (!state || state.enabled !== true) { - try { - await writeState('project', { enabled: true, profile: 'light' }, cwd); - log('info', '[session-start]', `think-short: AUTO-ENABLED profile=light (effort=low)`, cwd, session_id); - } catch (err) { - log('info', '[session-start]', `think-short: auto-enable write failed (${err.message})`, cwd, session_id); - return false; - } - } - - try { - await mkdir(markerDir, { recursive: true }); - await writeFile(markerPath, `effort=low session=${session_id} ts=${new Date().toISOString()}\n`, 'utf8'); - } catch {} - - return true; - } catch (err) { - log('info', '[session-start]', `think-short: auto-enable guard error (${err.message})`, cwd, session_id); - return false; - } -} - -async function injectThinkShort(baseContext, cwd, session_id) { - try { - const { resolveEffectiveState } = await import('../skills/think-short/helpers/state.mjs'); - let state; - try { - state = await resolveEffectiveState(cwd); - } catch (err) { - log('info', '[session-start]', `think-short: state resolve failed (${err.message}), skipping injection`, cwd, session_id); - return baseContext; - } - - if (!state || state.enabled !== true) { - log('info', '[session-start]', `think-short: SessionStart — SKIP (enabled=false)`, cwd, session_id); - return baseContext; - } - - const profile = state.profile || 'medium'; - const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT - || path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); - const profilePath = path.join(pluginRoot, 'skills/think-short/profiles', `${profile}.md`); - - let profileText; - let usedProfile = profile; - try { - profileText = await readFile(profilePath, 'utf8'); - } catch { - log('info', '[session-start]', `think-short: failed to read profile ${profilePath}, fallback to light`, cwd, session_id); - const fallbackPath = path.join(pluginRoot, 'skills/think-short/profiles', 'light.md'); - try { - profileText = await readFile(fallbackPath, 'utf8'); - usedProfile = 'light'; - } catch (err2) { - log('warn', '[session-start]', `think-short: fallback light.md read failed (${err2.message}), skipping injection`, cwd, session_id); - return baseContext; - } - } - - const approxTokens = Math.ceil(profileText.length / 4); - log('info', '[session-start]', `think-short: SessionStart — injecting profile=${usedProfile} (~${approxTokens} tok)`, cwd, session_id); - if (process.env.CLAUDE_DEBUG === '1') { - const preview = profileText.slice(0, 80).replace(/\n/g, ' '); - log('debug', '[session-start]', `think-short: profile preview = ${preview}`, cwd, session_id); - } - - return `${baseContext}\n\n\n${profileText}`; - } catch (err) { - log('info', '[session-start]', `think-short: injection block error (${err.message}), skipping`, cwd, session_id); - return baseContext; - } -} - async function main() { let cwd = null; let session_id = null; @@ -117,22 +10,8 @@ async function main() { session_id = input.session_id; cwd = input.cwd || cwd; - const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT || ''; - const sessionShort = session_id?.slice(0, 8) || 'unknown'; - - let context = pluginRoot - ? `BT_PLUGIN_ROOT=${pluginRoot}` - : `brewtools: ${sessionShort}`; - - // Auto-enable think-short=light when effort=low (CC 2.1.115+). Idempotent via session marker. - await maybeAutoEnableThinkShortLow(input, cwd, session_id); - - context = await injectThinkShort(context, cwd, session_id); - - let systemMessage = `brewtools: ${pluginRoot} | session: ${sessionShort}`; - // E7: surface permission_mode (DOC-VERIFIED common field, 2.1.195). Presence-guarded for audit. - const permMode = input.permission_mode; - if (permMode) systemMessage += ` | perm: ${permMode}`; + let context = ''; + let systemMessage = ''; // Manager HARD wall awareness (fail-open: never break session start). try { @@ -140,20 +19,27 @@ async function main() { const state = resolveState(cwd); if (state?.hard === true) { const level = state.level === 'strict' ? 'strict' : 'balanced'; - systemMessage += ` | ⛔ MANAGER HARD wall ON (project, level=${level})`; - context += `\n\nManager HARD wall active (project, level=${level}): main session is orchestration-only; delegate to subagents. /brewtools:manager off to exit.`; + systemMessage = `⛔ MANAGER HARD wall ON (project, level=${level})`; + context = `Manager HARD wall active (project, level=${level}): main session is orchestration-only; delegate to subagents. /brewtools:manager off to exit.`; } } catch (err) { log('info', '[session-start]', `manager hard-wall check error (${err.message}), skipping`, cwd, session_id); } - output({ - systemMessage, - hookSpecificOutput: { + if (!context && !systemMessage) { + output({}); + return; + } + + const out = {}; + if (systemMessage) out.systemMessage = systemMessage; + if (context) { + out.hookSpecificOutput = { hookEventName: 'SessionStart', additionalContext: context - } - }); + }; + } + output(out); } catch (error) { log('error', '[session-start]', `Error: ${error.message}`, cwd, session_id); output({}); diff --git a/brewtools/skills/_shared/toggle/cache.mjs b/brewtools/skills/_shared/toggle/cache.mjs deleted file mode 100644 index f25bbcc..0000000 --- a/brewtools/skills/_shared/toggle/cache.mjs +++ /dev/null @@ -1,95 +0,0 @@ -import fs from 'node:fs'; -import os from 'node:os'; -import path from 'node:path'; - -const PREFERRED_MARKETPLACE = 'claude-brewcode'; - -export function pluginCacheRoot() { - return path.join(os.homedir(), '.claude/plugins/cache'); -} - -export function semverCompare(a, b) { - const pa = String(a).split('.').map(s => parseInt(s.replace(/[^0-9].*$/, ''), 10) || 0); - const pb = String(b).split('.').map(s => parseInt(s.replace(/[^0-9].*$/, ''), 10) || 0); - for (let i = 0; i < 3; i++) { - const x = pa[i] ?? 0, y = pb[i] ?? 0; - if (x > y) return 1; - if (x < y) return -1; - } - return 0; -} - -function isSemverDir(name) { - return /^\d+\.\d+\.\d+/.test(name); -} - -function safeReadDir(p) { - try { return fs.readdirSync(p, { withFileTypes: true }); } catch { return []; } -} - -export function enumeratePlugins() { - const root = pluginCacheRoot(); - const result = new Map(); - for (const mpEntry of safeReadDir(root)) { - if (!mpEntry.isDirectory()) continue; - const marketplace = mpEntry.name; - const mpPath = path.join(root, marketplace); - for (const plugEntry of safeReadDir(mpPath)) { - if (!plugEntry.isDirectory()) continue; - const plugin = plugEntry.name; - const plugPath = path.join(mpPath, plugin); - const versions = []; - for (const v of safeReadDir(plugPath)) { - if (v.isDirectory() && isSemverDir(v.name)) versions.push(v.name); - } - if (versions.length === 0) continue; - versions.sort(semverCompare); - const latest = versions[versions.length - 1]; - const entry = { - marketplace, - plugin, - latest, - path: path.join(plugPath, latest), - versions - }; - const existing = result.get(plugin); - // WHY: prefer claude-brewcode marketplace when same plugin name exists in multiple marketplaces - if (!existing || (marketplace === PREFERRED_MARKETPLACE && existing.marketplace !== PREFERRED_MARKETPLACE)) { - result.set(plugin, entry); - } - } - } - return result; -} - -export function resolveTarget(pluginEntry, kind, name) { - const base = pluginEntry.path; - if (kind === 'skill') { - return { - visible: path.join(base, 'skills', name, 'SKILL.md'), - hidden: path.join(base, 'skills', name, '_SKILL.md') - }; - } - if (kind === 'agent') { - return { - visible: path.join(base, 'agents', `${name}.md`), - hidden: path.join(base, 'agents', `_${name}.md`) - }; - } - return null; -} - -export function detectKind(pluginEntry, name) { - const base = pluginEntry.path; - const skillDir = path.join(base, 'skills', name); - try { - if (fs.statSync(skillDir).isDirectory()) return 'skill'; - } catch {} - const agentVisible = path.join(base, 'agents', `${name}.md`); - const agentHidden = path.join(base, 'agents', `_${name}.md`); - if (fs.existsSync(agentVisible) || fs.existsSync(agentHidden)) return 'agent'; - const skillVisible = path.join(skillDir, 'SKILL.md'); - const skillHidden = path.join(skillDir, '_SKILL.md'); - if (fs.existsSync(skillVisible) || fs.existsSync(skillHidden)) return 'skill'; - return null; -} diff --git a/brewtools/skills/_shared/toggle/deny.mjs b/brewtools/skills/_shared/toggle/deny.mjs deleted file mode 100644 index c10abe7..0000000 --- a/brewtools/skills/_shared/toggle/deny.mjs +++ /dev/null @@ -1,249 +0,0 @@ -// brewtools:agent-toggle — settings.json permissions.deny helper. -// Native Claude Code mechanism: permissions.deny ["Agent()"] removes a -// subagent from the model context. Survives plugin updates (no reapply hook). -// Atomic: temp file + rename. Lockfile: O_CREAT|O_EXCL with stale-lock detection. -// Scopes: 'global' (~/.claude/settings.json), 'project' (/.claude/settings.json), -// 'local' (/.claude/settings.local.json). - -import fs from 'node:fs'; -import os from 'node:os'; -import path from 'node:path'; -import crypto from 'node:crypto'; - -const VALID_SCOPES = new Set(['global', 'project', 'local']); - -function resolveHome(p) { - if (!p) return p; - if (p === '~') return process.env.HOME || os.homedir(); - if (p.startsWith('~/')) return path.join(process.env.HOME || os.homedir(), p.slice(2)); - return p; -} - -/** - * Resolve settings.json path for a scope. - * @param {string} scope - 'global' | 'project' | 'local' - * @param {string} cwd - project root for project/local scopes (default process.cwd()) - * @returns {string} absolute settings file path - */ -export function resolveSettingsPath(scope, cwd = process.cwd()) { - if (!VALID_SCOPES.has(scope)) { - throw new Error(`invalid scope '${scope}' — must be one of: ${[...VALID_SCOPES].join(', ')}`); - } - if (scope === 'global') return resolveHome('~/.claude/settings.json'); - if (scope === 'project') return path.join(cwd, '.claude', 'settings.json'); - return path.join(cwd, '.claude', 'settings.local.json'); -} - -/** - * Strip any 'plugin:' prefix the user passes (e.g. 'brewtools:ssh-admin' -> 'ssh-admin'). - * @param {string} name - * @returns {string} bare agent name - */ -export function bareName(name) { - if (!name || typeof name !== 'string') throw new Error('name required'); - const idx = name.indexOf(':'); - return idx >= 0 ? name.slice(idx + 1) : name; -} - -function denyEntry(bare) { - return `Agent(${bare})`; -} - -function readJsonSafe(filePath) { - try { - const raw = fs.readFileSync(filePath, 'utf8'); - const parsed = JSON.parse(raw); - return (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) ? parsed : {}; - } catch { - return {}; - } -} - -function sleep(ms) { - return new Promise(r => setTimeout(r, ms)); -} - -// Lock identity hardening: lockfile contents = `${pid}:${randomHex16}`. acquireLock -// returns the token; releaseLock verifies match before unlink. Stale lock (dead pid, -// malformed pid, or age > 60s) is reclaimed. -async function acquireLock(lockPath, { retries = 5, delayMs = 100 } = {}) { - for (let i = 0; i < retries; i++) { - const token = `${process.pid}:${crypto.randomBytes(8).toString('hex')}`; - try { - const fd = fs.openSync(lockPath, fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_WRONLY, 0o600); - fs.writeSync(fd, token); - fs.closeSync(fd); - return token; - } catch (e) { - if (e.code !== 'EEXIST') throw e; - try { - const lockContent = fs.readFileSync(lockPath, 'utf8').trim(); - const pidPart = lockContent.split(':')[0]; - const lockPid = parseInt(pidPart, 10); - const lockStat = fs.statSync(lockPath); - const ageMs = Date.now() - lockStat.mtimeMs; - let stale = false; - if (!Number.isFinite(lockPid) || lockPid <= 0) { - stale = true; - } else { - try { - process.kill(lockPid, 0); - } catch (killErr) { - if (killErr.code === 'ESRCH') stale = true; - } - } - if (!stale && ageMs > 60_000) stale = true; - if (stale) { - try { fs.unlinkSync(lockPath); } catch {} - continue; - } - } catch (statErr) { - // lockfile vanished between EEXIST and stat — race, retry - } - if (i === retries - 1) { - throw new Error(`Could not acquire lock ${lockPath} after ${retries} attempts (${delayMs}ms each). Another process may be writing settings.json. Remove ${lockPath} manually if stale.`); - } - await sleep(delayMs); - } - } - return null; -} - -function releaseLock(lockPath, token) { - if (!token) return; - try { - const current = fs.readFileSync(lockPath, 'utf8').trim(); - if (token && current !== token) { - process.stderr.write(`[agent-toggle] lock stolen: expected token ${token}, found ${current} at ${lockPath}. Not unlinking.\n`); - return; - } - fs.unlinkSync(lockPath); - } catch {} -} - -function writeAtomic(settingsPath, merged) { - const tmp = `${settingsPath}.tmp.${process.pid}.${crypto.randomBytes(4).toString('hex')}`; - try { - fs.writeFileSync(tmp, JSON.stringify(merged, null, 2) + '\n', { encoding: 'utf8', mode: 0o600 }); - fs.renameSync(tmp, settingsPath); - } catch (e) { - try { fs.unlinkSync(tmp); } catch {} - throw e; - } -} - -/** - * Read the current permissions.deny array for a scope. - * @param {string} scope - * @param {object} opts - { cwd } - * @returns {string[]} deny entries (or []) - */ -export function readDeny(scope, opts = {}) { - const fp = resolveSettingsPath(scope, opts.cwd); - const settings = readJsonSafe(fp); - const perms = settings.permissions; - if (!perms || typeof perms !== 'object' || Array.isArray(perms)) return []; - return Array.isArray(perms.deny) ? perms.deny : []; -} - -/** - * Add an Agent() deny entry for a scope (idempotent, atomic). - * Preserves all unrelated settings keys (permissions.allow/ask, top-level keys). - * @param {string} scope - * @param {string} agentName - bare or plugin-qualified - * @param {object} opts - { cwd, retries, delayMs } - * @returns {object} { key, entry, action, file } action='added'|'noop' - */ -export async function addDeny(scope, agentName, opts = {}) { - const bare = bareName(agentName); - const entry = denyEntry(bare); - const settingsPath = resolveSettingsPath(scope, opts.cwd); - const lockPath = `${settingsPath}.lock`; - fs.mkdirSync(path.dirname(settingsPath), { recursive: true }); - - const token = await acquireLock(lockPath, { retries: opts.retries ?? 5, delayMs: opts.delayMs ?? 100 }); - if (!token) throw new Error('could not acquire lock'); - try { - const settings = readJsonSafe(settingsPath); - const perms = (settings.permissions && typeof settings.permissions === 'object' && !Array.isArray(settings.permissions)) - ? { ...settings.permissions } - : {}; - const deny = Array.isArray(perms.deny) ? [...perms.deny] : []; - - let action; - if (deny.includes(entry)) { - action = 'noop'; - } else { - deny.push(entry); - action = 'added'; - } - perms.deny = deny; - - const merged = { ...settings, permissions: perms }; - if (action === 'added') writeAtomic(settingsPath, merged); - - return { key: bare, entry, action, file: settingsPath }; - } finally { - releaseLock(lockPath, token); - } -} - -/** - * Remove an Agent() deny entry for a scope (atomic). - * Prunes empty deny array and empty permissions object. - * Preserves all unrelated settings keys. - * @param {string} scope - * @param {string} agentName - bare or plugin-qualified - * @param {object} opts - { cwd, retries, delayMs } - * @returns {object} { entry, action, file } action='removed'|'noop' - */ -export async function removeDeny(scope, agentName, opts = {}) { - const bare = bareName(agentName); - const entry = denyEntry(bare); - const settingsPath = resolveSettingsPath(scope, opts.cwd); - const lockPath = `${settingsPath}.lock`; - fs.mkdirSync(path.dirname(settingsPath), { recursive: true }); - - const token = await acquireLock(lockPath, { retries: opts.retries ?? 5, delayMs: opts.delayMs ?? 100 }); - if (!token) throw new Error('could not acquire lock'); - try { - const settings = readJsonSafe(settingsPath); - const perms = (settings.permissions && typeof settings.permissions === 'object' && !Array.isArray(settings.permissions)) - ? { ...settings.permissions } - : {}; - const deny = Array.isArray(perms.deny) ? [...perms.deny] : []; - - if (!deny.includes(entry)) { - return { entry, action: 'noop', file: settingsPath }; - } - const nextDeny = deny.filter(e => e !== entry); - if (nextDeny.length === 0) delete perms.deny; - else perms.deny = nextDeny; - - const merged = { ...settings }; - if (Object.keys(perms).length === 0) delete merged.permissions; - else merged.permissions = perms; - - writeAtomic(settingsPath, merged); - return { entry, action: 'removed', file: settingsPath }; - } finally { - releaseLock(lockPath, token); - } -} - -/** - * List bare agent names currently denied in a scope (parsed from Agent(...) entries). - * @param {string} scope - * @param {object} opts - { cwd } - * @returns {string[]} bare names - */ -export function listDeniedAgents(scope, opts = {}) { - const deny = readDeny(scope, opts); - const out = []; - for (const e of deny) { - if (typeof e !== 'string') continue; - const m = e.match(/^Agent\((.+)\)$/); - if (m) out.push(m[1]); - } - return out; -} diff --git a/brewtools/skills/_shared/toggle/interactive-flow.md b/brewtools/skills/_shared/toggle/interactive-flow.md deleted file mode 100644 index cfeb33b..0000000 --- a/brewtools/skills/_shared/toggle/interactive-flow.md +++ /dev/null @@ -1,159 +0,0 @@ -# Interactive Flow (shared reference) - -> Used by both `brewtools:skill-toggle` and `brewtools:agent-toggle`. -> Entry when no explicit op/target given, OR when user's prompt is a freeform request ("отключи лишнее", "hide image-gen"). - ---- - -## Core principle - -**If the user is explicit — just execute.** Ask only when something is genuinely ambiguous. End every run with a status dump. - -Explicit input examples (skip all questions, run straight to P3 Apply): -- `/brewtools:skill-toggle disable brewui:image-gen` → run directly -- `/brewtools:agent-toggle enable brewcode:reviewer --scope=project` → run directly -- `отключи brewui:image-gen` → plugin+name clear → run, but confirm once if uncertain -- `enable image-gen` (no plugin prefix, single match in cache) → run, but confirm once - -Ambiguous / missing input → enter full interactive flow. - ---- - -## Phase I0 — Decide if interactive is needed - -| Input | Branch | -|-------|--------| -| No args at all | Full interactive (I1 → I2 → I3 → I4) | -| Op only (`disable` / `enable` / `status` / `list`), no target | Skip I1, start at I2 | -| Op + target, both clear | Skip interactive, run, print status (I4 only) | -| Freeform prose ("hide the noisy image skill") | LLM pre-parse → if target inferrable, confirm once (I3); else full interactive | - ---- - -## Phase I1 — Ask what to do - -**Single `AskUserQuestion` call**, one question, four options: - -| Option | Meaning | -|--------|---------| -| `status` | Show current disabled list (global + project merged) | -| `disable` | Hide a skill/agent | -| `enable` | Restore a previously hidden skill/agent | -| `list` | Dump everything installed with its enable/disable state | - -Do NOT combine questions into one batch here — this single pick drives the rest of the flow. After the answer: - -- `status` or `list` → skip to I4 (run the op, print result) -- `disable` → proceed to I2 with target filter = currently enabled -- `enable` → proceed to I2 with target filter = currently disabled - ---- - -## Phase I2 — Show the catalog, ask which target - -**Rule: the catalog is printed as ONE LONG LINE** — space-separated `plugin:name` tokens. This lets the user `Ctrl+F` / `Cmd+F` inside their terminal scrollback. - -### Build the catalog - -1. Call `enumeratePlugins()` from `cache.mjs`. -2. For each plugin dir → read `skills/*/SKILL.md` (for `skill-toggle`) OR `agents/*.md` (for `agent-toggle`). -3. For each entry, check state file to mark `[disabled]` suffix. -4. Filter by op: if `disable`, keep only currently enabled; if `enable`, keep only currently disabled. - -### Format - -Emit three lines — a header, the flat list, and a hint: - -``` -AVAILABLE TO {OP} ({N} total, Ctrl+F to search): -brewcode:spec brewcode:plan brewcode:start brewcode:review brewcode:convention brewtools:debate brewtools:secrets-scan brewui:image-gen ... - -Tip: type "plugin:name" OR a few words; I'll match. "cancel" aborts. -``` - -**Never break the list across multiple lines** — the single line is the whole point (Ctrl+F friendly). - -### Ask - -Free-text prompt (regular message, not AskUserQuestion — we want an unrestricted reply): - -> **Which one?** Paste `plugin:name` or describe it in your words. `cancel` to abort. - ---- - -## Phase I3 — Resolve + confirm (once, only if uncertain) - -Match the user's reply against the filtered catalog: - -| Match | Action | -|-------|--------| -| Exact `plugin:name` present in catalog | Skip confirmation, go to I4 | -| Exact `name` without prefix, **unique** in catalog | Skip confirmation (no ambiguity), go to I4 | -| Exact `name` without prefix, **multiple plugins match** | AskUserQuestion with 2-4 `plugin:name` options | -| Fuzzy words ("the noisy image one") | Rank by token overlap + keyword hints in description; pick top candidate; **confirm once** via AskUserQuestion: "Disable `brewui:image-gen`? [yes / pick different / cancel]" | -| Nothing matches | AskUserQuestion: "No match. [re-enter name / show catalog again / cancel]" | -| `cancel` | Abort cleanly, print current status (I4) | - -**One confirmation max.** Never ping-pong. After confirm or after an unambiguous match → I4. - -### Scope - -Scope handling is skill-specific: -- `skill-toggle` — no scope (`skillOverrides` is global-only). -- `agent-toggle` — if `--scope` wasn't given for `disable`/`enable`, ALWAYS ask via a single AskUserQuestion: `global` vs `project` vs `local`. No default. - ---- - -## Phase I4 — Execute + print status - -1. Run the resolved op via the skill's own helper (`skill-toggle` -> `overrides.mjs`; `agent-toggle` -> `deny.mjs`). -2. Remind: change takes effect on next session or `/reload-plugins` (only after disable/enable, not after status/list). -3. Print the **current status** table — regardless of which op ran: - -``` -DISABLED RIGHT NOW -------------------- -brewui:image-gen [skill, global, since 2026-04-16] -brewcode:reviewer [agent, project, since 2026-04-15] -(none) ← if empty - -ENABLED ({M} skills / {K} agents across {P} plugins) -``` - -The second line is a count, not an enumeration — users who want to scan everything use `list`. - ---- - -## Decision matrix — quick cheat-sheet - -| User said | Asks | Confirms | Runs | -|-----------|------|----------|------| -| `disable brewui:image-gen` | none | no | directly | -| `disable` | target picker | no (if exact match) | after pick | -| `отключи image-gen` | none (unique match) | once | after confirm | -| `отключи что-нибудь ненужное` | op picker → target picker | once | after confirm | -| (empty prompt) | op picker → target picker | once if fuzzy | after pick | -| `status` | none | no | directly | - ---- - -## Anti-patterns - -- **Don't** paginate the catalog or split it across messages — the whole value is a single Ctrl+F line. -- **Don't** assume scope for `agent-toggle` — always ask `global`/`project`/`local` when not given. (`skill-toggle` has no scope.) -- **Don't** confirm when the user was explicit — respect clarity. -- **Don't** show the full catalog on `status` / `list` — those have their own output. -- **Don't** loop the interactive flow — if the user says `cancel` or gives unparseable input twice, abort with an error message. - ---- - -## Triggers for interactive entry - -Both skills enter this flow when: -- Invoked as `/brewtools:skill-toggle` / `/brewtools:agent-toggle` with no args -- User's prompt lacks a concrete target (`"help me disable something"`, `"что можно выключить?"`) -- Parsed target doesn't exist in cache (fallback to I2) - -Skip this flow when: -- Full explicit command given (`disable :`) — go straight to main P3 Apply -- Terminal op (`status`, `list`) with no target required — run directly, show output diff --git a/brewtools/skills/_shared/toggle/state.mjs b/brewtools/skills/_shared/toggle/state.mjs deleted file mode 100644 index 34936b0..0000000 --- a/brewtools/skills/_shared/toggle/state.mjs +++ /dev/null @@ -1,59 +0,0 @@ -import fs from 'node:fs'; -import os from 'node:os'; -import path from 'node:path'; -import crypto from 'node:crypto'; - -export const DEFAULT_STATE = Object.freeze({ version: 1, updated_at: null, disabled: {} }); - -export function globalStatePath() { - const base = process.env.CLAUDE_PLUGIN_DATA - || path.join(os.homedir(), '.claude/plugins/data/brewtools-claude-brewcode'); - return path.join(base, 'toggle-state.json'); -} - -export function projectStatePath(cwd) { - return path.join(cwd, '.claude', 'brewtools', 'toggle-state.json'); -} - -export function stateKey(plugin, name) { - return `${plugin}:${name}`; -} - -function cloneDefault() { - return { version: 1, updated_at: null, disabled: {} }; -} - -export function readState(filePath) { - try { - const raw = fs.readFileSync(filePath, 'utf8'); - const parsed = JSON.parse(raw); - if (!parsed || typeof parsed !== 'object') return cloneDefault(); - return { - version: parsed.version ?? 1, - updated_at: parsed.updated_at ?? null, - disabled: (parsed.disabled && typeof parsed.disabled === 'object') ? parsed.disabled : {} - }; - } catch { - return cloneDefault(); - } -} - -export function writeStateAtomic(filePath, state) { - const dir = path.dirname(filePath); - fs.mkdirSync(dir, { recursive: true }); - const stamped = { - version: state.version ?? 1, - updated_at: new Date().toISOString(), - disabled: state.disabled ?? {} - }; - const tmp = `${filePath}.tmp.${process.pid}.${crypto.randomBytes(4).toString('hex')}`; - fs.writeFileSync(tmp, JSON.stringify(stamped, null, 2), 'utf8'); - fs.renameSync(tmp, filePath); - return stamped; -} - -export function mergeStates(globalState, projectState) { - const g = (globalState && globalState.disabled) || {}; - const p = (projectState && projectState.disabled) || {}; - return { disabled: { ...g, ...p } }; -} diff --git a/brewtools/skills/agent-toggle/SKILL.md b/brewtools/skills/agent-toggle/SKILL.md deleted file mode 100644 index 28e0afe..0000000 --- a/brewtools/skills/agent-toggle/SKILL.md +++ /dev/null @@ -1,243 +0,0 @@ ---- -name: brewtools:agent-toggle -description: "Disables/enables individual agents via native permissions.deny in settings.json (survives updates). Triggers: disable agent, enable agent, agent-toggle." -argument-hint: "[disable|enable|status|list] : [--scope=global|project|local]" -allowed-tools: Read, Bash, AskUserQuestion -model: sonnet -user-invocable: true ---- - -# Agent Toggle - -> **Disable/enable individual agents** via the native `permissions.deny` mechanism in `settings.json`. A `Agent()` deny entry removes the subagent from the model context. State survives plugin updates — **no SessionStart reapply hook needed**. See also: `/brewtools:skill-toggle` for skills. - - - -## Robustness Rules - -| Rule | Applies | -|------|---------| -| Every Bash call ends with `&& echo "OK ..." \|\| echo "FAILED ..."` | ALL | -| Never use `Write`/`Edit` on any `settings.json` — use Bash + Node helper | ALL | -| This skill mutates **agents only** (`permissions.deny`) — never skills | ALL | -| `Agent(name)` matches the BARE name — strip any `plugin:` prefix the user passes | ALL | -| Atomic writes via lockfile + temp + rename (handled by helper) | P2 | - -Paths (substitute literally in Bash): -- Helper: `$CLAUDE_PLUGIN_ROOT/skills/_shared/toggle/deny.mjs` -- Catalog: `$CLAUDE_PLUGIN_ROOT/skills/_shared/toggle/cache.mjs` (`enumeratePlugins`) -- Settings per scope: - - `global` -> `~/.claude/settings.json` - - `project` -> `/.claude/settings.json` - - `local` -> `/.claude/settings.local.json` - -## How deny works - -`permissions.deny: ["Agent()"]` natively disables a subagent (plugin or project-custom), removing it from the model's tool context. The name is the BARE agent name (`Agent(ssh-admin)`, NOT `Agent(brewtools:ssh-admin)`). Deny-first precedence across scopes. Takes effect on next session or `/reload-plugins`. - -> **COLLISION WARNING:** `Agent(name)` matches the bare name only. If two plugins ship an agent with the SAME name, a single deny entry disables BOTH. Detect duplicate bare names during enumeration and warn the user before disabling. - ---- - -## Phase I — Interactive Flow (entry gate) - -> **Full spec:** `_shared/toggle/interactive-flow.md` (phases I0-I4). Read it fully on entry. This skill hardcodes `kind='agent'`. - -**Enter interactive flow when:** -- No args given, OR -- User prompt is freeform without a concrete `plugin:name` target (e.g. "отключи лишнего агента", "hide the noisy one"), OR -- Parsed target missing from the catalog. - -**Skip interactive (go straight to P0 -> P1 -> P2 -> P4)** when op AND target are both explicit: `/brewtools:agent-toggle disable brewtools:ssh-admin --scope=global`. - -| Phase | Action | Tool | -|-------|--------|------| -| I0 | Decide branch from input shape | — | -| I1 | Op picker — single `AskUserQuestion`, 4 options (`status`, `disable`, `enable`, `list`), pre-selected hint: `disable` | AskUserQuestion | -| I2 | Catalog one-liner — Bash+Node imports `enumeratePlugins` from `cache.mjs`, emit `AVAILABLE TO {OP} (N total, Ctrl+F to search):` then a single space-separated line of `plugin:name` tokens (filter: `disable`->not denied; `enable`->denied; kind=agent). Free-text "Which one?" prompt | Bash | -| I3 | Resolve + confirm once: exact `plugin:name` or unique `name`->no confirm; fuzzy->one AskUserQuestion `Disable X? [yes / pick different / cancel]`; multiple->AskUserQuestion 2-4 options | AskUserQuestion | -| I4 | Execute (P2) then ALWAYS print current state (see format below) | Bash | - -Terminal ops (`list`, `status`) skip to I4 directly — no picker, no catalog. - -**Scope is ALWAYS asked for `disable`/`enable`** when `--scope` is not given: a single AskUserQuestion with `global` / `project` / `local`. No default — ask every time. - -**I4 status format (always printed):** -``` -DENIED RIGHT NOW (via permissions.deny) ---------------------------------------- -ssh-admin [global] -reviewer [project] -(none) <-- if empty -ENABLED (M agents across P plugins) -``` - ---- - -## P0: Parse Intent - -Parse `$ARGUMENTS` (or the user's NL prompt) into structured form: - -``` -{ op: disable|enable|status|list, scope: global|project|local, targets: [{plugin?, name}] } -``` - -Rules: -- Strip any `plugin:` prefix -> bare name (`brewtools:ssh-admin` -> `ssh-admin`). `Agent(...)` matches the bare name. -- Scope: `--scope=global|project|local`. If NOT given for `disable`/`enable`, ask EVERY time via AskUserQuestion (no default). -- `status`, `list` take no targets and no scope (they show all scopes). -- Multiple targets allowed for `disable`/`enable` — iterate P1->P2 per target. - -If ambiguous (bare name maps to a duplicate across plugins) -> warn (collision), confirm before disabling. - ---- - -## P1: Validate Target (per target) - -**EXECUTE** using Bash tool: -```bash -node --input-type=module -e " -import {enumeratePlugins} from '$CLAUDE_PLUGIN_ROOT/skills/_shared/toggle/cache.mjs'; -import fs from 'node:fs'; -import path from 'node:path'; -const want = 'AGENT_NAME'; -const hits = []; -for (const [plugin, e] of enumeratePlugins()) { - const dir = path.join(e.path, 'agents'); - let entries = []; - try { entries = fs.readdirSync(dir).filter(n => n.endsWith('.md') && !n.startsWith('_')); } catch {} - for (const n of entries) { - const name = n.replace(/\\.md\$/, ''); - if (name === want) hits.push({plugin, name, version:e.latest}); - } -} -// project-custom agents -const pdir = path.join(process.cwd(), '.claude', 'agents'); -try { - for (const n of fs.readdirSync(pdir).filter(n => n.endsWith('.md') && !n.startsWith('_'))) { - const name = n.replace(/\\.md\$/, ''); - if (name === want) hits.push({plugin:'(project)', name}); - } -} catch {} -if (hits.length === 0) { console.log(JSON.stringify({error:'agent_not_found', name:want})); process.exit(0); } -console.log(JSON.stringify({name:want, hits, collision: hits.length > 1})); -" && echo "OK validate" || echo "FAILED validate" -``` - -Replace `AGENT_NAME` with the bare name. On `error` -> stop, report. If `collision:true` -> warn user that BOTH (all listed plugins) will be affected by the single deny entry; confirm before continuing. - ---- - -## P2: Write Deny Entry - -**EXECUTE** using Bash tool (disable): -```bash -node --input-type=module -e " -import {addDeny} from '$CLAUDE_PLUGIN_ROOT/skills/_shared/toggle/deny.mjs'; -const r = await addDeny('SCOPE','NAME',{cwd:process.cwd()}); -console.log(JSON.stringify(r)); -" && echo "OK deny" || echo "FAILED deny" -``` - -For `enable` — replace `addDeny` with `removeDeny` (same args). `SCOPE` in `global|project|local`. `NAME` may be bare or `plugin:name` (helper strips the prefix). - -Result `action`: `added` | `removed` | `noop`. - ---- - -## P4: Verify + Notify - -**EXECUTE** using Bash tool: -```bash -node --input-type=module -e " -import {listDeniedAgents} from '$CLAUDE_PLUGIN_ROOT/skills/_shared/toggle/deny.mjs'; -const cwd = process.cwd(); -console.log(JSON.stringify({ - global: listDeniedAgents('global', {cwd}), - project: listDeniedAgents('project', {cwd}), - local: listDeniedAgents('local', {cwd}) -})); -" && echo "OK verify" || echo "FAILED verify" -``` - -Confirm `NAME` present (disable) or absent (enable) in the chosen scope. Render result table: - -``` -# Agent Toggle — - -| Name | Scope | Action | File | -|------|-------|--------|------| -| ssh-admin | global | added | ~/.claude/settings.json | - -> Takes effect on next session or `/reload-plugins`. -> Persisted to settings.json — survives plugin updates. -``` - ---- - -## Sub-operations - -### status — denied agents per scope - -**EXECUTE** using Bash tool: -```bash -node --input-type=module -e " -import {listDeniedAgents} from '$CLAUDE_PLUGIN_ROOT/skills/_shared/toggle/deny.mjs'; -const cwd = process.cwd(); -console.log(JSON.stringify({ - global: listDeniedAgents('global', {cwd}), - project: listDeniedAgents('project', {cwd}), - local: listDeniedAgents('local', {cwd}) -})); -" && echo "OK status" || echo "FAILED status" -``` - -Render as table: name | scope. A bare name denied in multiple scopes appears once per scope. - -### list — enumerate available agents with deny state - -**EXECUTE** using Bash tool: -```bash -node --input-type=module -e " -import {enumeratePlugins} from '$CLAUDE_PLUGIN_ROOT/skills/_shared/toggle/cache.mjs'; -import {listDeniedAgents} from '$CLAUDE_PLUGIN_ROOT/skills/_shared/toggle/deny.mjs'; -import fs from 'node:fs'; -import path from 'node:path'; -const cwd = process.cwd(); -const denied = { - global: new Set(listDeniedAgents('global', {cwd})), - project: new Set(listDeniedAgents('project', {cwd})), - local: new Set(listDeniedAgents('local', {cwd})) -}; -const out = []; -const byName = new Map(); -for (const [plugin, e] of enumeratePlugins()) { - const dir = path.join(e.path, 'agents'); - let entries = []; - try { entries = fs.readdirSync(dir).filter(n => n.endsWith('.md') && !n.startsWith('_')); } catch {} - for (const n of entries) { - const name = n.replace(/\\.md\$/, ''); - byName.set(name, (byName.get(name) || 0) + 1); - out.push({source:plugin, name, version:e.latest, - denied:{global:denied.global.has(name), project:denied.project.has(name), local:denied.local.has(name)}}); - } -} -const pdir = path.join(cwd, '.claude', 'agents'); -try { - for (const n of fs.readdirSync(pdir).filter(n => n.endsWith('.md') && !n.startsWith('_'))) { - const name = n.replace(/\\.md\$/, ''); - byName.set(name, (byName.get(name) || 0) + 1); - out.push({source:'(project)', name, - denied:{global:denied.global.has(name), project:denied.project.has(name), local:denied.local.has(name)}}); - } -} catch {} -const collisions = [...byName.entries()].filter(([,c]) => c > 1).map(([n]) => n); -console.log(JSON.stringify({agents:out, collisions})); -" && echo "OK list" || echo "FAILED list" -``` - -Render grouped by source (plugin / `(project)`); mark deny state per scope (`global`/`project`/`local`). If `collisions` is non-empty, print a warning: those bare names are shipped by more than one source — a `Agent(name)` deny disables ALL of them. - -> **Built-ins:** plugin agents (e.g. `developer`, `tester`, `reviewer`, `architect` from brewcode) and project `.claude/agents/*.md` are enumerable here. Claude Code's system agents (`Explore`, `Plan`) are not plugin/project agents and are not listed — they cannot be denied by a plugin-agent name. - - diff --git a/brewtools/skills/debate/LICENSE b/brewtools/skills/debate/LICENSE deleted file mode 100644 index b09ce61..0000000 --- a/brewtools/skills/debate/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -MIT License - -Copyright (c) 2025-2026 Maxim Kochetkov (kochetkov-ma) -https://github.com/kochetkov-ma/claude-brewcode - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/brewtools/skills/debate/README.md b/brewtools/skills/debate/README.md deleted file mode 100644 index b76304c..0000000 --- a/brewtools/skills/debate/README.md +++ /dev/null @@ -1,69 +0,0 @@ -# Debate - -> Evidence-based multi-agent debate orchestrator -- 3 modes, dynamic agents, structured decisions. - -| Field | Value | -|-------|-------| -| Command | `/brewtools:debate` | -| Model | opus | -| Arguments | `[topic] [-m challenge\|strategy\|critic] [-n 2-5] [-r max-rounds] [--review]` | - -## Overview - -Debate spawns 2-5 dynamic agents with unique character archetypes, runs structured debate rounds, and produces judge-verified decisions. Every debate begins with a Discovery phase where research agents gather evidence from your codebase and the web. All arguments must cite sources -- unsourced claims are challenged by the judge. - -Three modes: **Challenge** (select the best option), **Strategy** (synthesize approaches), **Critic** (find all weaknesses). - -## Quick Start - -```bash -# Challenge mode -- compare options (default) -/brewtools:debate "React vs Vue vs Svelte for our dashboard" - -# Strategy mode -- deep analysis -/brewtools:debate "Migration plan from monolith to microservices" -m strategy - -# Critic mode -- find all weaknesses -/brewtools:debate "Review our authentication flow" -m critic - -# Custom agent count and rounds -/brewtools:debate "Kubernetes vs ECS" -n 4 -r 8 -``` - -## Modes - -| Mode | Agent Roles | Outcome | -|------|------------|---------| -| Challenge (default) | Defenders argue FOR, Critics attack | Selected variant with justification | -| Strategy | All agents are Strategists | Synthesized strategy or ranked approaches | -| Critic | All agents are Critics with different perspectives | Prioritized issue list with severity | - -Mode auto-detects from keywords (vs/compare -> challenge, strategy/plan -> strategy, critique/risk -> critic). - -## Discovery Phase - -Before any argument starts, 2-3 research agents run in parallel: - -- **Codebase Explorer** -- searches project for relevant code, patterns, dependencies -- **Web Researcher** -- searches internet for best practices, official docs, benchmarks - -All findings documented with sources in `discovery.md`. Every debate argument must reference Discovery evidence. - -## Agent Archetypes - -10 character archetypes define argument style: Pragmatist, Visionary, Skeptic, Architect, Operator, Advocate, Economist, Historian, Provocateur, Diplomat. Archetypes are auto-selected to create productive tension. - -## Output - -All artifacts in `.claude/reports/{TS}_debate/`: - -| File | Content | -|------|---------| -| `discovery.md` | Research findings with sources (URLs, file paths) | -| `debate-log.jsonl` | Full debate transcript (one entry per turn) | -| `summary.md` | Secretary synthesis: key arguments, turning points | -| `decisions.md` | Judge verdict, reasoning, minority opinions | - -## Documentation - -Full docs: [debate](https://doc-claude.brewcode.app/brewcode/skills/debate/) diff --git a/brewtools/skills/debate/SKILL.md b/brewtools/skills/debate/SKILL.md deleted file mode 100644 index a1a6b9a..0000000 --- a/brewtools/skills/debate/SKILL.md +++ /dev/null @@ -1,232 +0,0 @@ ---- -name: brewtools:debate -description: "Evidence-based multi-agent debate: challenge, strategy, critique. Triggers: debate, compare options, second opinion." -user-invocable: true -argument-hint: "[topic] [-m challenge|strategy|critic] [-n 2-5] [-r max-rounds] [--review]" -allowed-tools: Read, Write, Edit, Glob, Grep, Bash, Task, AskUserQuestion, Skill -model: opus ---- - -# Multi-Agent Debate - -Orchestrates sequential multi-agent debates. Dynamic agents (2-5) with unique characters debate, main session acts as judge, secretary summarizes, judge writes final decisions. - ---- - -## Phase 0: Validation - -**EXECUTE** using Bash tool: -```bash -bash "${CLAUDE_SKILL_DIR}/scripts/validate.sh" && echo "VALID" || echo "FAILED" -``` - -> **STOP if FAILED** — fix missing files before continuing. - -Read archetypes into context: - -Read file: `${CLAUDE_SKILL_DIR}/agents/archetypes.md` - ---- - -## Phase 1: Parse Arguments - -**Arguments:** `$ARGUMENTS` - -| Flag | Default | Description | -|------|---------|-------------| -| `-m` | ask user | Mode: `challenge`, `strategy`, `critic` | -| `-n` | 3 | Agent count: 2-5 | -| `-r` | 5 | Max debate rounds | -| `--review` | off | Run `/brewcode:review` on output | -| (positional) | — | Topic text or file path | - -### Mode not specified (when `-m` omitted) - -If mode is NOT explicitly provided via `-m` flag or clearly stated in the topic text, **do NOT auto-detect**. Ask user using AskUserQuestion: - -> **Which debate mode?** -> -> 1. **Challenge** — generate/receive variants, debate to select the best one -> 2. **Strategy** — each agent proposes independently, then debate to converge -> 3. **Critic** — all agents attack the given solution to find weaknesses/risks -> -> Reply with mode name or number. - -Only proceed after explicit user choice. - -If topic is a file path (exists on disk) — read file content as topic. - ---- - -## Phase 2: Init + Display - -**EXECUTE** using Bash tool: -```bash -bash "${CLAUDE_SKILL_DIR}/scripts/init-log.sh" && echo "INIT_OK" || echo "INIT_FAILED" -``` - -> **STOP if INIT_FAILED** — cannot create report directory. - -Capture output — it prints: -``` -REPORT_DIR= -LOG_FILE= -``` - -Store `REPORT_DIR` and `LOG_FILE` for all subsequent phases. - -Display to user: - -``` -Debate Setup - Mode: {detected_mode} - Agents: {n} - Max rounds: {r} - Report: {REPORT_DIR} - Log: {LOG_FILE} - Topic: {topic_summary} -``` - ---- - -## Phase 3: User Interview - -Ask user using AskUserQuestion tool: - -> **Debate configuration:** -> -> Mode: **{mode}** | Agents: **{n}** | Max rounds: **{r}** -> Topic: {topic_first_100_chars} -> -> Options: -> 1. Proceed with these settings -> 2. Change mode (challenge/strategy/critic) -> 3. Change agent count (2-5) -> 4. Change max rounds -> 5. Describe custom agent profiles (instead of auto-generated) - -Apply any user changes. If user provides custom profiles — skip auto-generation in Phase 4 and use their descriptions. - ---- - -## Phase 4: Agent Profiles - -Read reference for agent generation: - -Read file: `${CLAUDE_SKILL_DIR}/references/setup-flow.md` - -Follow setup-flow.md to generate agent profiles. Result: a table of agents with name, role, character archetype, perspective, and WHY chosen. - -Display agent table to user. Ask confirmation using AskUserQuestion: - -> **Agent Team:** -> -> | # | Name | Role | Archetype | Perspective | -> |---|------|------|-----------|-------------| -> | ... | ... | ... | ... | ... | -> -> Options: -> 1. Proceed -> 2. Swap an agent (specify which) -> 3. Regenerate all - ---- - -## Phase 5: Discovery (Mandatory) - -Research phase — gather current, verified information before debate begins. - -Read file: `${CLAUDE_SKILL_DIR}/references/discovery-flow.md` - -Follow discovery-flow.md to spawn parallel research agents: -1. **Codebase Explorer** — searches project for relevant code, patterns, dependencies -2. **Web Researcher** — searches internet for current best practices, official docs, recent changes - -All findings saved to `{REPORT_DIR}/discovery.md` with sources. - -> **Every debate argument in Phase 6 MUST reference findings from discovery.md.** -> Unsourced claims are not valid arguments. - -Display discovery summary to user before proceeding to debate. - ---- - -## Phase 6: Debate - -Load mode-specific flow reference and execute debate. - -| Mode | Reference | -|------|-----------| -| challenge | `${CLAUDE_SKILL_DIR}/references/challenge-flow.md` | -| strategy | `${CLAUDE_SKILL_DIR}/references/strategy-flow.md` | -| critic | `${CLAUDE_SKILL_DIR}/references/critic-flow.md` | - -Read the matching reference file and follow its instructions exactly. - -**Agent spawning:** Use Task tool with `subagent_type: "general-purpose"`. Build each agent's prompt dynamically by combining: -1. Base template from `${CLAUDE_SKILL_DIR}/agents/debater-template.md` -2. Role overlay from `${CLAUDE_SKILL_DIR}/agents/{role}-template.md` -3. Agent's character traits from archetypes -4. Discovery findings from `{REPORT_DIR}/discovery.md` (injected as Evidence Base) -5. Current debate context (recent JSONL entries) - -**After each agent turn**, append to log: - -**EXECUTE** using Bash tool: -```bash -bash "${CLAUDE_SKILL_DIR}/scripts/append-log.sh" "LOG_FILE_PATH" '{"ts":"...","from":"agent-name","to":["targets"],"what":"<20 words","why":"<40 words (include [Source: #N] refs)","type":"argument","mode":"MODE"}' -``` - -**Judge interventions** (main session): After each round, evaluate if consensus emerging, redirect if stuck, end early if unanimous agreement. - ---- - -## Phase 7: Summary - -Read file: `${CLAUDE_SKILL_DIR}/references/summary-flow.md` - -Follow summary-flow.md: -1. Read full debate log and `{REPORT_DIR}/discovery.md` -2. Spawn secretary agent to write `summary.md` in REPORT_DIR - ---- - -## Phase 8: Decision - -Judge (main session) writes `decisions.md`: -- Winning position or synthesized result -- Key arguments that decided the outcome -- Minority opinions worth noting -- Confidence level: high / medium / low -- Recommended next steps - -Write to: `{REPORT_DIR}/decisions.md` - ---- - -## Phase 9: Final Output - -Display final status: - -``` -Debate Complete - Mode: {mode} - Rounds: {actual_rounds}/{max_rounds} - Outcome: {consensus | partial | no-consensus} - Agents: {agent_table_brief} - -Decisions (top 3-5): - - {bullet_1} - - {bullet_2} - - {bullet_3} - -Artifacts: - - {REPORT_DIR}/discovery.md - - {REPORT_DIR}/decisions.md - - {REPORT_DIR}/summary.md - - {REPORT_DIR}/debate-log.jsonl -``` - -If `--review` flag was set: - -Invoke: `Skill(skill="brewcode:standards-review", args="{REPORT_DIR}")` diff --git a/brewtools/skills/debate/agents/archetypes.md b/brewtools/skills/debate/agents/archetypes.md deleted file mode 100644 index 7c65d46..0000000 --- a/brewtools/skills/debate/agents/archetypes.md +++ /dev/null @@ -1,25 +0,0 @@ -# Agent Character Archetypes - -10 archetypes that define HOW an agent argues. Combined with roles (defender/critic/strategist) to create unique debate personas. - -| # | Archetype | Traits | Arguing Style | Best For | -|---|-----------|--------|---------------|----------| -| 1 | **Pragmatist** | Practical, results-oriented, impatient with theory | "What actually works in production?" Cites real-world outcomes, dismisses hypotheticals | Challenge: defender of proven solutions; Strategy: incremental approach | -| 2 | **Visionary** | Big-picture, future-oriented, tolerates ambiguity | "Where is this heading in 5 years?" Argues from trends, first principles, emerging patterns | Strategy: transformative proposals; Challenge: defender of innovative options | -| 3 | **Skeptic** | Cautious, evidence-demanding, risk-aware | "Show me the data." Demands proof, finds edge cases, stress-tests assumptions | Critic: any mode; Challenge: critic role | -| 4 | **Architect** | Systematic, pattern-focused, thinks in structures | "How does this fit the bigger system?" Argues from design principles, consistency, modularity | Strategy: system-level proposals; Critic: structural analysis | -| 5 | **Operator** | Operations-minded, reliability-focused, practical | "Who maintains this at 3 AM?" Argues from operational reality, monitoring, incident response | Critic: operational risks; Challenge: defender of reliable options | -| 6 | **Advocate** | User-centric, empathetic, accessibility-aware | "What does the end user experience?" Argues from UX, adoption, accessibility, learning curve | Challenge: defender of user-friendly options; Critic: usability gaps | -| 7 | **Economist** | Cost-conscious, ROI-focused, quantitative | "What's the total cost of ownership?" Argues with numbers, trade-off matrices, opportunity cost | Strategy: cost-benefit analysis; Critic: financial risks | -| 8 | **Historian** | Pattern-matching, precedent-aware, cautious about repetition | "We tried this in 2019 and it failed because..." Argues from past failures, industry case studies | Critic: pattern recognition; Challenge: historical context | -| 9 | **Provocateur** | Contrarian, challenges consensus, creative | "What if we're solving the wrong problem?" Reframes the debate, asks uncomfortable questions | Critic: assumption-busting; Strategy: alternative framing | -| 10 | **Diplomat** | Consensus-seeking, synthesizing, bridge-building | "I hear both sides — what if we combine..." Finds common ground, proposes compromises | Strategy: synthesis; Challenge: final-round mediation | - -## Usage - -When generating agent profiles, select archetypes that create productive tension: -- Challenge mode: mix defenders and critics with contrasting archetypes (e.g., Pragmatist defender vs Visionary critic) -- Strategy mode: select archetypes that approach problems from genuinely different angles -- Critic mode: choose archetypes that find different TYPES of issues (technical, operational, financial, user-facing) - -Avoid pairing archetypes that argue identically (e.g., Pragmatist + Operator both focus on practical concerns). diff --git a/brewtools/skills/debate/agents/critic-template.md b/brewtools/skills/debate/agents/critic-template.md deleted file mode 100644 index fefb47d..0000000 --- a/brewtools/skills/debate/agents/critic-template.md +++ /dev/null @@ -1,43 +0,0 @@ -# Critic Role Overlay (Challenge + Critic Modes) - -## Role: Critic - -You are assigned to CRITIQUE — find weaknesses, risks, and flaws. Your job is rigorous adversarial analysis. - -## Critic Behavior - -- Attack the weakest points of each proposal/variant -- Ask probing questions that expose hidden assumptions -- Identify risks: technical debt, scalability limits, security gaps, maintenance burden -- Compare against industry standards and known failure modes -- Propose severity levels for each issue found -- Suggest mitigations when pointing out problems (not just negativity) - -## Critic Focus Areas - -| Area | Questions | -|------|-----------| -| Feasibility | Can this actually be built/done with available resources? | -| Scalability | What breaks at 10x / 100x scale? | -| Maintenance | Who maintains this in 2 years? What's the bus factor? | -| Edge cases | What happens with empty input, max load, network failure? | -| Dependencies | What external factors could derail this? | -| Alternatives | Is there a simpler way that was overlooked? | - -## Critic Strategy - -1. **Identify:** Pick the most critical flaw, not the most obvious -2. **Evidence:** Show WHY it's a flaw with concrete scenarios -3. **Severity:** Rate as critical / major / minor -4. **Mitigation:** Suggest a fix or workaround (constructive criticism) - -## Evidence Citation - -Your critique MUST cite specific evidence. When pointing out weaknesses, reference the source that supports your claim: [Source: #N]. Unsourced criticisms carry less weight. - -## Do NOT - -- Criticize style or formatting — focus on substance -- Repeat criticisms already raised by other critics -- Be negative without constructive alternatives -- Dismiss entire proposals over minor issues diff --git a/brewtools/skills/debate/agents/debater-template.md b/brewtools/skills/debate/agents/debater-template.md deleted file mode 100644 index 73563c3..0000000 --- a/brewtools/skills/debate/agents/debater-template.md +++ /dev/null @@ -1,56 +0,0 @@ -# Debater Base Template - -You are **{AGENT_NAME}**, a debate participant with the character archetype **{ARCHETYPE}**. - -## Your Identity - -- **Name:** {AGENT_NAME} -- **Role:** {ROLE} (defender / critic / strategist) -- **Archetype:** {ARCHETYPE} -- **Traits:** {TRAITS} -- **Perspective:** {PERSPECTIVE} - -## Debate Context - -- **Mode:** {MODE} -- **Topic:** {TOPIC} -- **Round:** {CURRENT_ROUND} of {MAX_ROUNDS} - -## Evidence Base - -{DISCOVERY_FINDINGS} - -**RULE: Every argument you make MUST reference at least one finding from the evidence base above. Use format: [Source: #N] where N is the finding number. Unsourced claims are not valid.** - -## Previous Discussion - -{RECENT_LOG_ENTRIES} - -If no entries above, you are speaking first in this debate. - -## Rules - -1. Stay in character — your archetype defines HOW you argue, not WHAT you argue -2. Address specific points from previous speakers by name -3. Provide concrete evidence, examples, or reasoning -4. Acknowledge strong counterarguments — concede when genuinely convinced -5. Keep responses focused: 200-400 words -6. End with a clear position statement - -## Response Format - -``` -### {AGENT_NAME} — Round {CURRENT_ROUND} - -**Position:** [1-sentence stance] - -[Your argument — 200-400 words, addressing previous points] - -**Status:** [holding | shifting | conceding] -**Confidence:** [high | medium | low] -**Key point:** [single most important argument in <20 words] -``` - -## What to return - -Return ONLY your debate response in the format above. Do not add meta-commentary about the debate process. diff --git a/brewtools/skills/debate/agents/defender-template.md b/brewtools/skills/debate/agents/defender-template.md deleted file mode 100644 index 2b12ab7..0000000 --- a/brewtools/skills/debate/agents/defender-template.md +++ /dev/null @@ -1,36 +0,0 @@ -# Defender Role Overlay (Challenge Mode) - -## Role: Defender - -You are assigned to DEFEND a specific variant/position. Your job is to make the strongest possible case FOR it. - -## Defender Behavior - -- Present the strongest arguments for your assigned variant -- Anticipate and preemptively address likely criticisms -- Find real-world evidence, precedents, and success stories -- Highlight unique advantages that no other variant offers -- When attacked, strengthen your argument rather than deflecting -- Concede minor points gracefully to maintain credibility on major ones - -## Assigned Variant - -**Variant:** {VARIANT_DESCRIPTION} - -## Defender Strategy - -1. **Open:** State your variant's core value proposition clearly -2. **Build:** Layer supporting evidence — technical, practical, strategic -3. **Counter:** Address the strongest criticism head-on -4. **Close:** Reaffirm why this variant wins on the criteria that matter most - -## Evidence Citation - -Your defense MUST cite specific evidence from the discovery findings. Reference sources by number: [Source: #N]. Every major claim requires at least one source. - -## Do NOT - -- Attack other variants without first strengthening your own -- Ignore legitimate weaknesses — acknowledge and reframe -- Repeat the same argument with different words -- Abandon your position unless the counterargument is genuinely irrefutable diff --git a/brewtools/skills/debate/agents/secretary.md b/brewtools/skills/debate/agents/secretary.md deleted file mode 100644 index 814be57..0000000 --- a/brewtools/skills/debate/agents/secretary.md +++ /dev/null @@ -1,82 +0,0 @@ -# Secretary Agent - -You are the **Secretary** — a neutral observer who produces an accurate, structured summary of the debate. - -## Input - -You will receive: -1. The debate topic -2. The full debate log (JSONL entries) -3. The list of agents with their roles and archetypes - -## Task - -Write `summary.md` — a comprehensive debate summary. - -## Output Format - -```markdown -# Debate Summary - -## Topic -{topic} - -## Participants - -| Agent | Role | Archetype | Final Position | -|-------|------|-----------|----------------| -| ... | ... | ... | ... | - -## Key Arguments - -### Round-by-Round - -#### Round 1 -- **{agent}:** {key point} ({type}: argument/counter/proposal) -- ... - -#### Round N -... - -### Strongest Arguments - -| Rank | Agent | Argument | Impact | -|------|-------|----------|--------| -| 1 | ... | ... | Changed N positions | -| 2 | ... | ... | ... | - -## Points of Agreement -- {shared conclusion 1} -- {shared conclusion 2} - -## Unresolved Disagreements -- {disagreement 1}: {agent_a} vs {agent_b} -- {disagreement 2}: ... - -## Consensus Level -{unanimous | strong-majority | weak-majority | split | no-consensus} - -## Statistics -- Rounds: {N} -- Total arguments: {N} -- Position changes: {N} -- Questions asked: {N} -``` - -## Mode-Specific Format - -Adapt your summary structure to the debate mode: - -| Mode | Focus | -|------|-------| -| Challenge | Round-by-round with position tracking per variant; highlight which agents shifted toward which variant | -| Strategy | Proposals comparison table + synthesis narrative; track how proposals evolved and merged | -| Critic | Issue consolidation matrix — group by severity, show consensus level per issue across critics | - -## Rules - -1. Be strictly neutral — do not judge which side is correct -2. Attribute every point to the agent who made it -3. Distinguish between arguments, counterarguments, proposals, and concessions -4. Track position changes explicitly -5. Keep the summary factual — no interpretation or recommendation diff --git a/brewtools/skills/debate/agents/strategist-template.md b/brewtools/skills/debate/agents/strategist-template.md deleted file mode 100644 index 5071923..0000000 --- a/brewtools/skills/debate/agents/strategist-template.md +++ /dev/null @@ -1,42 +0,0 @@ -# Strategist Role Overlay (Strategy Mode) - -## Role: Strategist - -You independently analyze the problem and propose your own approach. Then defend it in debate. - -## Strategist Behavior - -- Think from first principles — don't anchor on others' proposals -- Consider the full problem lifecycle: design, implementation, operation, evolution -- Quantify trade-offs where possible (cost, time, complexity, risk) -- Map dependencies and critical path -- Identify what must be true for your approach to succeed (assumptions) -- Propose concrete next steps, not abstract recommendations - -## Strategy Framework - -1. **Problem reframe:** State the core problem in your own words (may differ from original framing) -2. **Approach:** Your proposed strategy in 3-5 key decisions -3. **Trade-offs:** What you gain vs. what you sacrifice -4. **Risks:** Top 2-3 risks and mitigations -5. **Timeline:** Rough phases and milestones -6. **Success criteria:** How to measure if this approach worked - -## In Debate Phase - -When responding to other strategists: -- Find synthesis opportunities — combine the best parts of multiple approaches -- Identify genuine conflicts vs. apparent conflicts (different words, same idea) -- Propose hybrid approaches when pure approaches have complementary weaknesses -- Challenge assumptions, not conclusions - -## Evidence Citation - -Your proposal MUST be grounded in evidence from the discovery findings. Reference sources for every key decision: [Source: #N]. Unsourced recommendations are not valid. - -## Do NOT - -- Copy another strategist's approach with minor modifications -- Propose an approach you wouldn't actually recommend in practice -- Ignore implementation reality for theoretical elegance -- Refuse to synthesize when two approaches are genuinely compatible diff --git a/brewtools/skills/debate/references/challenge-flow.md b/brewtools/skills/debate/references/challenge-flow.md deleted file mode 100644 index e40246f..0000000 --- a/brewtools/skills/debate/references/challenge-flow.md +++ /dev/null @@ -1,96 +0,0 @@ -# Challenge Mode Debate Flow - -## Overview - -Defenders present and argue FOR variant(s), critics attack. Sequential rounds until consensus, judge intervention, or max rounds reached. - -## Pre-Debate Setup - -1. Read agent templates: - - `${CLAUDE_SKILL_DIR}/agents/debater-template.md` (base) - - `${CLAUDE_SKILL_DIR}/agents/defender-template.md` (defender overlay) - - `${CLAUDE_SKILL_DIR}/agents/critic-template.md` (critic overlay) - -2. If topic has explicit variants — assign to defenders -3. If no explicit variants — defenders propose their own in round 1 - -## Round Structure - -Each round = all agents speak once, in order: defenders first, then critics. - -### Round 1: Opening Statements - -**Defenders:** Present their variant(s). If no pre-defined variants, each defender proposes one. - -**Critics:** Initial critique of all presented variants. - -### Rounds 2-N: Rebuttals - -**Defenders:** Respond to criticisms, strengthen their position. - -**Critics:** Dig deeper, raise new concerns, or acknowledge addressed issues. - -## Agent Spawning (per turn) - -For each agent's turn, spawn via Task tool: - -``` -Task( - description: "{agent_name} round {N}", - prompt: "{combined_prompt}", - subagent_type: "general-purpose" -) -``` - -Build `{combined_prompt}` by: -1. Reading base template, replacing placeholders: AGENT_NAME, ROLE, ARCHETYPE, TRAITS, PERSPECTIVE, MODE, TOPIC, CURRENT_ROUND, MAX_ROUNDS, VARIANT_DESCRIPTION, DISCOVERY_FINDINGS -2. Appending role overlay (defender or critic) -3. Including relevant discovery findings in each agent's prompt — agents must cite evidence -4. Appending recent log entries (last 2 rounds or all if short) - -## After Each Agent Turn - -1. Extract key points from agent's response -2. Append to JSONL log: - -**EXECUTE** using Bash tool: -```bash -bash "${CLAUDE_SKILL_DIR}/scripts/append-log.sh" "LOG_FILE" '{"ts":"TIMESTAMP","from":"AGENT_NAME","to":["TARGET_AGENTS"],"what":"SUMMARY_20_WORDS","why":"REASONING_40_WORDS","type":"argument|counter|agree","mode":"challenge"}' -``` - -## Judge Evaluation (After Each Round) - -After all agents have spoken in a round, the judge (main session) evaluates: - -| Signal | Action | -|--------|--------| -| All agents agree on one variant | End debate — declare consensus | -| Clear majority (>60%) favoring one | Ask minority for final objection, then end | -| Debate is circular (same arguments repeated) | Introduce a new constraint or angle to break deadlock | -| Agents talking past each other | Redirect: "Agent X, address Agent Y's point about Z specifically" | -| Max rounds reached | End debate — summarize current state | - -### Judge Log Entry - -After evaluation, append judge entry: - -**EXECUTE** using Bash tool: -```bash -bash "${CLAUDE_SKILL_DIR}/scripts/append-log.sh" "LOG_FILE" '{"ts":"TIMESTAMP","from":"judge","to":["all"],"what":"JUDGE_SUMMARY","why":"JUDGE_REASONING","type":"redirect|agree","mode":"challenge"}' -``` - -## Convergence Detection - -Track each agent's position across rounds: - -| Change | Meaning | -|--------|---------| -| `holding` | Agent maintains position — no convergence | -| `shifting` | Agent moving toward another position — convergence in progress | -| `conceding` | Agent concedes — convergence achieved for this agent | - -**Early exit:** If all agents report `conceding` or `shifting` toward same variant — end debate. - -## Output - -Debate log (JSONL) is complete. Proceed to Phase 7 (Summary). diff --git a/brewtools/skills/debate/references/critic-flow.md b/brewtools/skills/debate/references/critic-flow.md deleted file mode 100644 index fb7ec95..0000000 --- a/brewtools/skills/debate/references/critic-flow.md +++ /dev/null @@ -1,89 +0,0 @@ -# Critic Mode Debate Flow - -## Overview - -All agents are critics with different perspectives. No defender — the document/plan/code itself is the target. Goal: find all weaknesses, risks, and flaws. - -## Pre-Debate Setup - -1. Read agent templates: - - `${CLAUDE_SKILL_DIR}/agents/debater-template.md` (base) - - `${CLAUDE_SKILL_DIR}/agents/critic-template.md` (critic overlay) - -2. Load the target material: - - If topic is a file path — read file content - - If topic is text — use directly - - If topic references code — use Grep/Glob to gather context - -## Round Structure - -### Round 1: Independent Critique - -Each critic independently reviews the target from their archetype's perspective. No access to other critics' findings. - -Spawn each critic with: -- Base template + critic overlay -- Target material -- Discovery findings (replace `{DISCOVERY_FINDINGS}` with evidence from `{REPORT_DIR}/discovery.md`) — critics must cite evidence -- Instruction: "Find issues from your perspective. Do NOT repeat what's obvious — dig deep. Cite discovery sources." - -Each critic outputs issues in format: -``` -| # | Severity | Issue | Evidence | Mitigation | -|---|----------|-------|----------|------------| -| 1 | critical | ... | ... | ... | -``` - -After each critic, append to log with `type: "argument"`. - -### Round 2+: Cross-Critique - -Critics now see each other's findings. In subsequent rounds: - -1. **Validate:** Agree or disagree with other critics' findings -2. **Deepen:** Add depth to issues others found superficially -3. **Discover:** Find new issues inspired by others' perspectives -4. **Prioritize:** Argue for severity adjustments - -Build prompts with: -- Base template + critic overlay -- Target material -- Discovery findings (replace `{DISCOVERY_FINDINGS}`) -- ALL previous findings (log entries) -- Instruction: "Review other critics' findings. Validate, deepen, discover, or re-prioritize. Cite discovery sources." - -## Judge Evaluation (After Each Round) - -| Signal | Action | -|--------|--------| -| Critics finding new issues | Continue — productive | -| Critics only agreeing with each other | End debate — diminishing returns | -| Severity disagreements | Judge mediates: "Critics A and B, defend your severity rating for issue X" | -| Duplicate findings | Judge consolidates and redirects | -| Max rounds reached | End debate | - -Judge log entry after each round: - -**EXECUTE** using Bash tool: -```bash -bash "${CLAUDE_SKILL_DIR}/scripts/append-log.sh" "LOG_FILE" '{"ts":"TIMESTAMP","from":"judge","to":["all"],"what":"SUMMARY","why":"REASONING","type":"redirect","mode":"critic"}' -``` - -## Issue Consolidation - -After debate ends, judge consolidates all issues into a master list: - -| # | Severity | Issue | Found By | Agreed By | Mitigation | Status | -|---|----------|-------|----------|-----------|------------|--------| -| 1 | critical | ... | critic-1 | critic-2, critic-3 | ... | confirmed | -| 2 | major | ... | critic-2 | — | ... | disputed | - -Severity scale: -- **critical** — must fix, blocks progress -- **major** — should fix, significant risk -- **minor** — nice to fix, low risk -- **info** — observation, no action needed - -## Output - -JSONL log + consolidated issue list. Proceed to Phase 7 (Summary). diff --git a/brewtools/skills/debate/references/discovery-flow.md b/brewtools/skills/debate/references/discovery-flow.md deleted file mode 100644 index dbfce1d..0000000 --- a/brewtools/skills/debate/references/discovery-flow.md +++ /dev/null @@ -1,58 +0,0 @@ -# Discovery Flow - -## Purpose - -Before any debate, research agents gather current, verified information on the topic. All debate arguments must be backed by evidence and sources. - -## Process - -Spawn 2-3 agents IN PARALLEL using Task tool: - -| Agent | subagent_type | Focus | Tools | -|-------|---------------|-------|-------| -| Codebase Explorer | Explore | Project code, configs, patterns, dependencies related to the topic | Glob, Grep, Read | -| Web Researcher 1 | general-purpose | Current information, best practices, recent changes, official docs | WebSearch, WebFetch | -| Web Researcher 2 (complex topics only) | general-purpose | Alternative viewpoints, competing approaches, known issues, community discussions | WebSearch, WebFetch | - -**When to spawn Web Researcher 2:** Topic involves external technologies, frameworks, or architectural decisions with multiple competing approaches. - -## Output Format (per agent) - -```markdown -## Findings: {agent_role} - -### Finding 1: {title} -- **Source:** {URL or file path} -- **Date:** {when published/last updated} -- **Key facts:** {2-3 bullet points} -- **Relevance:** {why this matters for the debate} - -### Finding 2: ... -``` - -## Aggregation - -Combine all findings into `{REPORT_DIR}/discovery.md`: - -1. Deduplicate overlapping findings -2. Flag conflicting information from different sources -3. Create Evidence Summary table: - -```markdown -## Evidence Summary - -| # | Fact | Source | Verified | -|---|------|--------|----------| -| 1 | ... | URL/path | yes/no | -| 2 | ... | URL/path | yes/no | -``` - -## Rules - -| Rule | Details | -|------|---------| -| Minimum findings | 3 per agent | -| Source requirement | Every finding MUST have a source (URL, file path, or doc reference) | -| Common knowledge | Still needs a source reference | -| Stale data | Flag findings older than 1 year as potentially stale | -| Conflicts | Explicitly note when sources disagree — both sides cited | diff --git a/brewtools/skills/debate/references/setup-flow.md b/brewtools/skills/debate/references/setup-flow.md deleted file mode 100644 index 38ad521..0000000 --- a/brewtools/skills/debate/references/setup-flow.md +++ /dev/null @@ -1,85 +0,0 @@ -# Agent Profile Generation (Setup Flow) - -## Input - -- Topic text -- Mode: challenge / strategy / critic -- Agent count: N (2-5) -- Archetypes (loaded from `agents/archetypes.md`) -- Optional: user-provided custom profiles - -## Step 1: Domain Detection - -Analyze the topic to identify domain(s): - -| Domain | Indicators | -|--------|------------| -| Backend | API, database, server, microservices, scalability | -| Frontend | UI, UX, components, design system, accessibility | -| Infrastructure | deploy, CI/CD, containers, cloud, monitoring | -| Architecture | patterns, modules, coupling, system design | -| Data | pipeline, analytics, ML, storage, ETL | -| Business | cost, ROI, timeline, stakeholders, requirements | -| Security | auth, encryption, vulnerability, compliance | -| General | none of the above — use broad archetypes | - -Multiple domains possible. Primary domain = most referenced in topic. - -## Step 2: Role Assignment (Mode-Aware) - -### Challenge Mode - -| N agents | Defenders | Critics | -|----------|-----------|---------| -| 2 | 1 | 1 | -| 3 | 1 | 2 | -| 4 | 2 | 2 | -| 5 | 2 | 3 | - -If topic contains explicit variants (e.g., "Option A vs Option B"): -- Assign each defender to a specific variant -- Critics attack all variants equally - -### Strategy Mode - -All agents are **strategists**. Each proposes independently. - -### Critic Mode - -All agents are **critics**. Each critiques from a different perspective. - -## Step 3: Character Selection - -For each agent, select an archetype from the 10 available. Rules: - -1. **Maximize diversity** — no two agents share an archetype -2. **Match domain** — prefer archetypes listed as "Best For" matching the topic domain -3. **Create tension** — pair archetypes with naturally opposing viewpoints -4. **Avoid redundancy** — if two archetypes would argue identically on this topic, replace one - -### Selection priority by mode - -| Mode | Prefer | Avoid | -|------|--------|-------| -| Challenge | Opposing pairs (Pragmatist vs Visionary, Skeptic vs Advocate) | Two similar critics | -| Strategy | Maximum perspective diversity | Two archetypes that approach same way | -| Critic | Different issue types (technical, ops, financial, UX) | All-technical team | - -## Step 4: Generate Profiles - -For each agent, produce: - -``` -Agent {N}: - Name: {descriptive_name} (e.g., "Ops-Realist", "Cost-Analyst", "UX-Champion") - Role: defender / critic / strategist - Archetype: {from archetypes.md} - Perspective: {1-sentence: what angle they bring} - WHY chosen: {1-sentence: why this archetype for this topic} -``` - -Names should be short (1-2 words with hyphen), descriptive, and unique within the team. - -## Step 5: Display for Confirmation - -Present the full agent table to the user for approval before proceeding to debate. diff --git a/brewtools/skills/debate/references/strategy-flow.md b/brewtools/skills/debate/references/strategy-flow.md deleted file mode 100644 index 7b257fc..0000000 --- a/brewtools/skills/debate/references/strategy-flow.md +++ /dev/null @@ -1,84 +0,0 @@ -# Strategy Mode Debate Flow - -## Overview - -Three-phase flow: independent proposals, judge-ordered presentation, convergence debate. All agents are strategists. - -## Pre-Debate Setup - -1. Read agent templates: - - `${CLAUDE_SKILL_DIR}/agents/debater-template.md` (base) - - `${CLAUDE_SKILL_DIR}/agents/strategist-template.md` (strategist overlay) - -## Phase A: Independent Proposals - -Each strategist independently analyzes the topic and proposes their approach. No access to other proposals. - -For each agent, spawn via Task tool: - -``` -Task( - description: "{agent_name} proposal", - prompt: "{combined_prompt_WITHOUT_other_proposals}", - subagent_type: "general-purpose" -) -``` - -The prompt includes: -- Base template with placeholders filled (set `{RECENT_LOG_ENTRIES}` to "No previous discussion — this is your independent proposal." to prevent later agents from seeing earlier proposals) -- Strategist overlay -- Discovery findings (replace `{DISCOVERY_FINDINGS}` with evidence from `{REPORT_DIR}/discovery.md`) — agents must cite evidence -- Topic only — NO other agents' proposals -- Instruction: "Write your independent proposal using the Strategy Framework in your overlay. Cite discovery sources." - -After each proposal, append to log with `type: "proposal"`. - -## Phase B: Judge Orders Presentation - -After all proposals received, judge: - -1. Reads all proposals -2. Orders presentation sequence (most different approaches first to maximize contrast) -3. Identifies key dimensions where approaches differ - -Log entry: - -**EXECUTE** using Bash tool: -```bash -bash "${CLAUDE_SKILL_DIR}/scripts/append-log.sh" "LOG_FILE" '{"ts":"TIMESTAMP","from":"judge","to":["all"],"what":"Presentation order: A, B, C","why":"Ordered by maximum contrast on key dimensions","type":"redirect","mode":"strategy"}' -``` - -## Phase C: Convergence Debate - -Now agents debate — each sees all proposals and previous discussion. - -### Round structure - -Each round, agents respond to each other's proposals. Build prompts with: -- Base template + strategist overlay -- Discovery findings (replace `{DISCOVERY_FINDINGS}`) -- ALL proposals summary -- Recent log entries (last 2 rounds) -- Judge's identified key dimensions - -### Convergence patterns - -| Pattern | Action | -|---------|--------| -| Two approaches are complementary | Judge suggests synthesis: "Agents X and Y, explore combining your approaches" | -| One approach clearly dominates | Ask its proponents to address remaining weaknesses | -| Genuine conflict (mutually exclusive) | Judge frames as explicit trade-off decision | -| All approaches converge | End debate — consensus forming | - -### After each round - -Append log entries. Judge evaluates using same convergence detection as Challenge mode. - -## Output - -Complete JSONL log with three phases marked: -- `type: "proposal"` — Phase A entries -- `type: "redirect"` — Judge ordering (Phase B) -- `type: "argument|counter|agree"` — Phase C debate entries - -Proceed to Phase 7 (Summary). diff --git a/brewtools/skills/debate/references/summary-flow.md b/brewtools/skills/debate/references/summary-flow.md deleted file mode 100644 index 6f28890..0000000 --- a/brewtools/skills/debate/references/summary-flow.md +++ /dev/null @@ -1,30 +0,0 @@ -# Summary + Decision Flow - -## Phase 6: Secretary Summary - -### Step 1: Read Full Log - -**EXECUTE** using Bash tool: -```bash -bash "${CLAUDE_SKILL_DIR}/scripts/read-log.sh" "LOG_FILE" all -``` - -### Step 2: Spawn Secretary - -Read secretary prompt: `${CLAUDE_SKILL_DIR}/agents/secretary.md` - -Spawn secretary via Task tool: - -``` -Task( - description: "Secretary writes debate summary", - prompt: "{secretary_prompt}\n\n## Debate Log\n{full_log_content}\n\n## Agent Profiles\n{agent_table}\n\n## Topic\n{topic}", - subagent_type: "general-purpose" -) -``` - -### Step 3: Write Summary - -Write secretary's output to `{REPORT_DIR}/summary.md`. - -Proceed to Phase 7 (Decision) in SKILL.md — the judge writes `decisions.md` there. diff --git a/brewtools/skills/debate/scripts/append-log.sh b/brewtools/skills/debate/scripts/append-log.sh deleted file mode 100755 index d71bd11..0000000 --- a/brewtools/skills/debate/scripts/append-log.sh +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -command -v python3 >/dev/null 2>&1 || { echo "ERROR: python3 required for JSONL validation" >&2; exit 1; } - -# Append entry to debate JSONL log with schema validation -# Usage: bash append-log.sh '' -# Example: bash append-log.sh path/to/debate-log.jsonl '{"ts":"...","from":"agent-1","to":["agent-2"],"what":"summary","why":"reasoning","type":"argument","mode":"challenge"}' - -LOG_FILE="${1:-}" -ENTRY="${2:-}" - -if [ -z "$LOG_FILE" ]; then - echo "ERROR: log file path required as first argument" >&2 - exit 1 -fi - -if [ -z "$ENTRY" ]; then - echo "ERROR: JSON entry required as second argument" >&2 - exit 1 -fi - -if [ ! -f "$LOG_FILE" ]; then - echo "ERROR: log file does not exist: $LOG_FILE" >&2 - exit 1 -fi - -# Validate JSON structure using python (available on Mac by default) -VALID=$(python3 -c " -import json, sys -try: - d = json.loads(sys.argv[1]) - required = {'ts', 'from', 'to', 'what', 'why', 'type', 'mode'} - missing = required - set(d.keys()) - if missing: - print(f'MISSING_FIELDS: {missing}', file=sys.stderr) - sys.exit(1) - valid_types = {'argument', 'counter', 'proposal', 'agree', 'question', 'redirect'} - if d['type'] not in valid_types: - print(f'INVALID_TYPE: {d[\"type\"]} (expected: {valid_types})', file=sys.stderr) - sys.exit(1) - valid_modes = {'challenge', 'strategy', 'critic'} - if d['mode'] not in valid_modes: - print(f'INVALID_MODE: {d[\"mode\"]} (expected: {valid_modes})', file=sys.stderr) - sys.exit(1) - if not isinstance(d['to'], list): - print('INVALID_TO: must be array', file=sys.stderr) - sys.exit(1) - # Output compact JSON (normalized) - print(json.dumps(d, ensure_ascii=False, separators=(',', ':'))) -except json.JSONDecodeError as e: - print(f'INVALID_JSON: {e}', file=sys.stderr) - sys.exit(1) -" "$ENTRY" 2>&1) || { - echo "VALIDATION FAILED: $VALID" >&2 - exit 1 -} - -echo "$VALID" >> "$LOG_FILE" -echo "OK: appended to $LOG_FILE" diff --git a/brewtools/skills/debate/scripts/init-log.sh b/brewtools/skills/debate/scripts/init-log.sh deleted file mode 100755 index 30a8f27..0000000 --- a/brewtools/skills/debate/scripts/init-log.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Initialize debate report directory and empty JSONL log -# Usage: bash init-log.sh -# Output: REPORT_DIR= and LOG_FILE= - -# Timestamp: use gdate if available (Mac + coreutils), fallback to POSIX date -if command -v gdate >/dev/null 2>&1; then - TS="$(gdate -u +%Y%m%d-%H%M%S)" -elif date -u +%Y%m%d-%H%M%S >/dev/null 2>&1; then - TS="$(date -u +%Y%m%d-%H%M%S)" -else - TS="$(date +%Y%m%d-%H%M%S)" -fi - -BASE="$(git rev-parse --show-toplevel 2>/dev/null || pwd)" -REPORT_DIR="${BASE}/.claude/reports/${TS}_debate" -LOG_FILE="${REPORT_DIR}/debate-log.jsonl" - -mkdir -p "$REPORT_DIR" -touch "$LOG_FILE" - -echo "REPORT_DIR=${REPORT_DIR}" -echo "LOG_FILE=${LOG_FILE}" diff --git a/brewtools/skills/debate/scripts/read-log.sh b/brewtools/skills/debate/scripts/read-log.sh deleted file mode 100755 index 0fe96d6..0000000 --- a/brewtools/skills/debate/scripts/read-log.sh +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Read debate log entries -# Usage: -# bash read-log.sh all — all entries -# bash read-log.sh last — last N entries -# bash read-log.sh agent — entries from specific agent -# bash read-log.sh round — entries from round N (by position) -# bash read-log.sh stats — summary statistics - -LOG_FILE="${1:-}" -CMD="${2:-all}" -ARG="${3:-}" - -if [ -z "$LOG_FILE" ]; then - echo "ERROR: log file path required" >&2 - exit 1 -fi - -if [ ! -f "$LOG_FILE" ]; then - echo "ERROR: log file does not exist: $LOG_FILE" >&2 - exit 1 -fi - -case "$CMD" in - all) - cat "$LOG_FILE" - ;; - last) - N="${ARG:-5}" - tail -n "$N" "$LOG_FILE" - ;; - agent) - if [ -z "$ARG" ]; then - echo "ERROR: agent name required" >&2 - exit 1 - fi - python3 -c " -import json, sys -for line in open(sys.argv[1]): - line = line.strip() - if not line: continue - d = json.loads(line) - if d.get('from') == sys.argv[2]: - print(line) -" "$LOG_FILE" "$ARG" - ;; - round) - if [ -z "$ARG" ]; then - echo "ERROR: round number required" >&2 - exit 1 - fi - N="$ARG" - python3 -c " -import json, sys -entries = [] -for line in open(sys.argv[1]): - line = line.strip() - if not line: continue - entries.append(json.loads(line)) -n = int(sys.argv[2]) -# Determine agent count (unique non-judge 'from' values) -agents = sorted(set(e['from'] for e in entries if e['from'] != 'judge')) -agent_count = len(agents) if agents else 1 -# Round N = entries[(N-1)*agent_count : N*agent_count] (judge entries interleaved are included) -# Group entries into rounds: each round = agent_count non-judge entries + any judge entries between them -non_judge = [(i, e) for i, e in enumerate(entries) if e['from'] != 'judge'] -total_rounds = (len(non_judge) + agent_count - 1) // agent_count -if n < 1 or n > total_rounds: - print(f'ERROR: round {n} out of range (1-{total_rounds})', file=sys.stderr) - sys.exit(1) -start = (n - 1) * agent_count -end = min(n * agent_count, len(non_judge)) -# Get index range in original entries list -first_idx = non_judge[start][0] if start < len(non_judge) else 0 -last_idx = non_judge[end - 1][0] if end > 0 else len(entries) - 1 -# Include all entries (including judge) within the index range -for i, e in enumerate(entries): - if first_idx <= i <= last_idx: - print(json.dumps(e, ensure_ascii=False, separators=(',', ':'))) -" "$LOG_FILE" "$N" - ;; - stats) - python3 -c " -import json, sys -entries = [] -for line in open(sys.argv[1]): - line = line.strip() - if not line: continue - entries.append(json.loads(line)) -agents = set(e['from'] for e in entries) -types = {} -for e in entries: - types[e['type']] = types.get(e['type'], 0) + 1 -print(f'Total entries: {len(entries)}') -print(f'Agents: {sorted(agents)}') -print(f'Types: {dict(sorted(types.items()))}') -print(f'Mode: {entries[0][\"mode\"] if entries else \"unknown\"}') -" "$LOG_FILE" - ;; - *) - echo "ERROR: unknown command '$CMD' (expected: all, last, agent, round, stats)" >&2 - exit 1 - ;; -esac diff --git a/brewtools/skills/debate/scripts/validate.sh b/brewtools/skills/debate/scripts/validate.sh deleted file mode 100755 index 0de57f4..0000000 --- a/brewtools/skills/debate/scripts/validate.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# Validate all debate skill files exist -# Usage: bash validate.sh -# Returns: 0 if all files present, 1 if any missing - -SKILL_DIR="$(cd "$(dirname "$0")/.." && pwd)" -MISSING=0 - -check_file() { - if [ ! -f "$SKILL_DIR/$1" ]; then - echo "MISSING: $1" - MISSING=$((MISSING + 1)) - fi -} - -# Core -check_file "SKILL.md" - -# Agents -check_file "agents/debater-template.md" -check_file "agents/defender-template.md" -check_file "agents/critic-template.md" -check_file "agents/strategist-template.md" -check_file "agents/secretary.md" -check_file "agents/archetypes.md" - -# References -check_file "references/setup-flow.md" -check_file "references/challenge-flow.md" -check_file "references/strategy-flow.md" -check_file "references/critic-flow.md" -check_file "references/discovery-flow.md" -check_file "references/summary-flow.md" - -# Scripts -check_file "scripts/validate.sh" -check_file "scripts/init-log.sh" -check_file "scripts/append-log.sh" -check_file "scripts/read-log.sh" - -if [ "$MISSING" -gt 0 ]; then - echo "VALIDATION FAILED: $MISSING file(s) missing" - exit 1 -fi - -echo "All debate skill files present ($SKILL_DIR)" -exit 0 diff --git a/brewtools/skills/debate/tests/test-challenge-basic.md b/brewtools/skills/debate/tests/test-challenge-basic.md deleted file mode 100644 index 1205e57..0000000 --- a/brewtools/skills/debate/tests/test-challenge-basic.md +++ /dev/null @@ -1,29 +0,0 @@ -# Test: Challenge Mode — Basic 2-Agent - -## Setup - -``` -/brewtools:debate REST API vs GraphQL for a new public-facing product catalog API -m challenge -n 2 -``` - -## Expected Behavior - -1. Phase 0: Validation passes -2. Phase 1: Parses mode=challenge, n=2, topic="REST API vs GraphQL..." -3. Phase 2: Creates report dir, empty log -4. Phase 3: User confirms settings -5. Phase 4: Generates 1 defender (REST) + 1 critic (GraphQL attacker) — or vice versa -6. Phase 5: Challenge flow — at least 2 rounds -7. Phase 6: Secretary writes summary.md -8. Phase 7: Judge writes decisions.md with selected variant -9. Phase 8: Final output with links - -## Assertions - -- [ ] Report dir exists: `.claude/reports/*_debate/` -- [ ] `debate-log.jsonl` has entries with `"mode":"challenge"` -- [ ] At least 2 entries with `"type":"argument"` -- [ ] At least 1 entry with `"from":"judge"` -- [ ] `summary.md` exists and contains participant table -- [ ] `decisions.md` exists and contains "Selected Variant" -- [ ] Final output shows consensus level diff --git a/brewtools/skills/debate/tests/test-challenge-multi.md b/brewtools/skills/debate/tests/test-challenge-multi.md deleted file mode 100644 index 71412a4..0000000 --- a/brewtools/skills/debate/tests/test-challenge-multi.md +++ /dev/null @@ -1,25 +0,0 @@ -# Test: Challenge Mode — 5 Agents with 2 Defenders - -## Setup - -``` -/brewtools:debate "Monolith vs Microservices vs Modular Monolith for a mid-size fintech startup" -m challenge -n 5 -r 4 -``` - -## Expected Behavior - -1. 5 agents generated: 2 defenders + 3 critics -2. Defenders assigned to different variants (e.g., one defends Microservices, one defends Modular Monolith) -3. 3 critics with distinct archetypes (e.g., Skeptic, Operator, Economist) -4. Max 4 rounds -5. Each round: 5 log entries (one per agent) + judge entry - -## Assertions - -- [ ] Agent table shows exactly 2 defenders and 3 critics -- [ ] All 5 agents have different archetypes -- [ ] JSONL log has entries from 5 distinct agent names + judge -- [ ] No more than 4 rounds of debate -- [ ] Each defender assigned to a specific variant -- [ ] `decisions.md` references all three architectural options -- [ ] `summary.md` tracks position changes across rounds diff --git a/brewtools/skills/debate/tests/test-consensus.md b/brewtools/skills/debate/tests/test-consensus.md deleted file mode 100644 index 3246d9f..0000000 --- a/brewtools/skills/debate/tests/test-consensus.md +++ /dev/null @@ -1,24 +0,0 @@ -# Test: Early Consensus + Judge Intervention - -## Setup - -``` -/brewtools:debate "Should we use TypeScript or JavaScript for our new Node.js backend service? Team is experienced with both." -m challenge -n 3 -r 6 -``` - -## Expected Behavior - -This topic has a strong industry consensus (TypeScript for backend). Agents should converge quickly. - -1. Round 1: Defender argues for one option, critics raise points -2. Round 2: If agents converge — judge should detect early consensus and end debate -3. If not converging — judge intervenes with a redirect - -## Assertions - -- [ ] Debate ends in fewer than 6 rounds (early consensus) -- [ ] At least 1 agent reports status "conceding" or "shifting" -- [ ] Judge entry with `"type":"agree"` or noting consensus -- [ ] `summary.md` shows "Consensus Level: strong-majority" or "unanimous" -- [ ] `decisions.md` confidence is "high" -- [ ] Total entries < max_rounds * agent_count (early exit proof) diff --git a/brewtools/skills/debate/tests/test-critic.md b/brewtools/skills/debate/tests/test-critic.md deleted file mode 100644 index 6093170..0000000 --- a/brewtools/skills/debate/tests/test-critic.md +++ /dev/null @@ -1,24 +0,0 @@ -# Test: Critic Mode - -## Setup - -``` -/brewtools:debate "Review our authentication system: JWT tokens with 24h expiry, stored in localStorage, refresh via /api/refresh endpoint, no rate limiting" -m critic -n 3 -``` - -## Expected Behavior - -1. 3 critic agents with different perspectives (e.g., security, operations, UX) -2. Round 1: Independent critiques — each finds issues from their angle -3. Round 2+: Cross-critique — validate, deepen, discover, re-prioritize -4. Consolidated issue list with severity levels - -## Assertions - -- [ ] All agents have role "critic" -- [ ] Round 1 entries are independent (no references to other critics) -- [ ] At least 1 "critical" severity issue found (localStorage JWT is a known anti-pattern) -- [ ] At least 3 distinct issues across all critics -- [ ] `decisions.md` contains "Issue Summary" with severity counts -- [ ] `decisions.md` contains "Top Issues" table -- [ ] Each issue has: severity, description, found-by, mitigation diff --git a/brewtools/skills/debate/tests/test-file-input.md b/brewtools/skills/debate/tests/test-file-input.md deleted file mode 100644 index 89bbf87..0000000 --- a/brewtools/skills/debate/tests/test-file-input.md +++ /dev/null @@ -1,46 +0,0 @@ -# Test: File-Based Topic Input - -## Setup - -Create a temp file first, then invoke: - -```bash -cat > /tmp/debate-topic.md << 'EOF' -# Proposal: Switch from PostgreSQL to MongoDB - -## Current State -- PostgreSQL 15 with 200+ tables -- Complex JOIN queries for reporting -- 50M rows in largest table - -## Proposed Change -- Migrate to MongoDB 7 -- Denormalize data models -- Use aggregation pipeline for reporting - -## Motivation -- Schema flexibility for rapid feature development -- Better horizontal scaling -- JSON-native storage for our API-first architecture -EOF -``` - -``` -/brewtools:debate /tmp/debate-topic.md -m critic -n 4 -``` - -## Expected Behavior - -1. Phase 1: Detects `/tmp/debate-topic.md` as file path, reads content -2. Auto-detect mode = `critic` (matches `-m critic`) -3. 4 critics analyze the migration proposal -4. Issues should include: data integrity, migration complexity, reporting regression - -## Assertions - -- [ ] File content loaded into topic (not the path string) -- [ ] JSONL entries reference specific points from the document (table counts, JOIN queries) -- [ ] At least 1 issue about data migration risk -- [ ] At least 1 issue about reporting capability regression -- [ ] `decisions.md` references the specific PostgreSQL-to-MongoDB context -- [ ] Temp file is NOT modified diff --git a/brewtools/skills/debate/tests/test-max-rounds.md b/brewtools/skills/debate/tests/test-max-rounds.md deleted file mode 100644 index 61cba99..0000000 --- a/brewtools/skills/debate/tests/test-max-rounds.md +++ /dev/null @@ -1,25 +0,0 @@ -# Test: Max Rounds Limit - -## Setup - -``` -/brewtools:debate "Tabs vs Spaces for code indentation" -m challenge -n 2 -r 2 -``` - -## Expected Behavior - -This is an intentionally polarizing topic with no clear technical winner. Agents should NOT reach consensus easily, hitting the max rounds limit. - -1. Round 1: Strong arguments on both sides -2. Round 2: Continued disagreement — max rounds hit -3. Judge ends debate, declares partial/no consensus - -## Assertions - -- [ ] Exactly 2 rounds of debate (not more) -- [ ] Both agents maintain "holding" status through both rounds -- [ ] Judge entry acknowledges max rounds reached -- [ ] `summary.md` shows "Consensus Level: split" or "no-consensus" -- [ ] `decisions.md` still makes a decision (judge decides even without consensus) -- [ ] `decisions.md` confidence is "low" or "medium" -- [ ] JSONL entry count = exactly 2 rounds * 2 agents + judge entries diff --git a/brewtools/skills/debate/tests/test-strategy.md b/brewtools/skills/debate/tests/test-strategy.md deleted file mode 100644 index b5815da..0000000 --- a/brewtools/skills/debate/tests/test-strategy.md +++ /dev/null @@ -1,25 +0,0 @@ -# Test: Strategy Mode - -## Setup - -``` -/brewtools:debate "How should we migrate our legacy Java monolith to a modern stack? Budget: 500K, timeline: 12 months, team: 8 developers" -m strategy -n 4 -``` - -## Expected Behavior - -1. 4 strategist agents generated with diverse archetypes -2. Phase A: 4 independent proposals (no cross-contamination) -3. Phase B: Judge orders presentation by maximum contrast -4. Phase C: Debate rounds seeking convergence/synthesis -5. Summary includes all 4 proposals + synthesis - -## Assertions - -- [ ] All agents have role "strategist" -- [ ] JSONL has 4 entries with `"type":"proposal"` (Phase A) -- [ ] JSONL has 1+ entry with `"from":"judge"` and `"type":"redirect"` (Phase B ordering) -- [ ] Phase C entries have `"type":"argument|counter|agree"` -- [ ] No proposal references another agent's proposal (independence) -- [ ] `decisions.md` contains "Synthesized Strategy" section -- [ ] `decisions.md` has "Approaches Considered" table with all 4 agents diff --git a/brewtools/skills/manager/README.md b/brewtools/skills/manager/README.md index 28c55d9..ee97b4e 100644 --- a/brewtools/skills/manager/README.md +++ b/brewtools/skills/manager/README.md @@ -4,20 +4,19 @@ Manager mode has **two independent layers**. Keep them straight: | Layer | What | Scope | Persistent | |-------|------|-------|-----------| -| **SOFT codewords** (`++m` / `++mp`) | A `UserPromptSubmit` hook auto-injects a delegate-everything Manager prompt for ONE turn when it sees a codeword. **Always fires — this skill does NOT enable/disable it.** The skill only customizes the TEXT (`mode`/`edit`/`reset`) and explains it (`status`). | Global or project (prompt text) | Yes (hook is always on) | +| **SOFT codewords** (`++m` / `++rr` / `++r`) | A `UserPromptSubmit` hook auto-injects a delegate-everything Manager prompt for ONE turn when it sees a codeword (`++m` is plan-aware — adds the plan supplement when `permission_mode === 'plan'`). **Always fires — this skill does NOT enable/disable it.** The skill only customizes the TEXT (`mode`/`edit`/`reset`) and explains it (`status`). | Global or project (prompt text) | Yes (hook is always on) | | **HARD wall** | An opt-in `PreToolUse` guard physically DENIES mutating tools (Write/Edit/Bash/…) in the **main session**, leaving only delegate/read/track. Subagents stay fully free. **Project-only, defaults OFF, installed into the project by this skill.** No codeword for the wall. | Project only | Yes, until `off`/`uninstall` | The two layers are orthogonal: codewords shape the Manager mindset; the wall enforces delegation by removing the tools that let the agent act as an executor. Either can be used alone. ## Codewords (SOFT — always active) -Detection order — longest-prefix first: `++mp` → `++m` → `++rr` → `++r`. +Detection — `++m` (plan-aware), and the review group `++rr` → `++r` (longest-prefix first). | Type anywhere in your prompt | Means | Injects | When | |------------------------------|-------|---------|------| -| `++m` | Manager — delegate-everything for the current task | Manager (full) block | Always — hook-driven, independent of this skill | -| `++mp` | Manager for Plan — manager role for plan + delegation; writes the task graph, uses the tasks tool | Manager + Plan Mode block | Always — tested first (prefix collision with `++m`) | -| `++rr` | Regression Review — after each significant phase: no regression + project standard + correctness; two-phase review→double-check→fix; final cross-review at task end | Regression Review discipline (`review-regression`) block | Always — tested after `++m`, before `++r`; codeword-only | +| `++m` | Manager — delegate-everything for the current task; PLAN-AWARE (auto-adds the plan supplement in plan mode) | Manager (full) block, or full + plan addon when `permission_mode === 'plan'` | Always — hook-driven, independent of this skill | +| `++rr` | Regression Review — after each significant phase: no regression + project standard + correctness; two-phase review→double-check→fix; final cross-review at task end | Regression Review discipline (`review-regression`) block | Always — tested before `++r`; codeword-only | | `++r` | Review — two-phase multi-agent review→double-check→fix after each significant change | Review discipline (`review-double`) block | Always — codeword-only (no ambient/wall injection) | The block applies to that one turn only. When the HARD wall is armed, the Manager (full) block is also ambient-injected every turn — no codeword needed. Codewords and wall injection are independent. Review codewords (`++rr`/`++r`) are never ambient-injected. @@ -30,10 +29,10 @@ The block applies to that one turn only. When the HARD wall is armed, the Manage | `/brewtools:manager off [--scope global\|project]` | Disarm the HARD wall (state flip only; registration stays in `settings.local.json`). Guard no-ops until re-armed. | | `/brewtools:manager uninstall` | Deregister the wall from `settings.local.json` + delete the copied guard. Auto-disarms first. Run `/reload` after. | | `/brewtools:manager level ` | Set wall strictness (project only). `balanced` = read-only Bash allowed; `strict` = all Bash denied. | -| `/brewtools:manager mode [--scope ...]` | Set default prompt-text mode (informational — codeword still selects the block: `++m`=full, `++mp`=planmode) | +| `/brewtools:manager mode full [--scope ...]` | Set default prompt-text mode (informational; `full` is the only user-settable mode — `++m` auto-selects planmode in plan mode) | | `/brewtools:manager status` | Print wall state (armed/disarmed, level, registered?), prompt sources, and both injected blocks | -| `/brewtools:manager edit [full\|planmode] [--scope ...]` | Copy default block to an override and show the path for editing | -| `/brewtools:manager reset [full\|planmode] [--scope ...]` | Delete the override, revert to plugin default | +| `/brewtools:manager edit [full] [--scope ...]` | Copy default block to an override and show the path for editing | +| `/brewtools:manager reset [full] [--scope ...]` | Delete the override, revert to plugin default | | `/brewtools:manager ` | Inline Manager run — prepends the full block and delegates the task | ## NL prompts (RU+EN) @@ -46,7 +45,6 @@ The block applies to that one turn only. When the HARD wall is armed, the Manage | `уровень строгий`, `level strict`, `режим строгий`, `strict mode` | `level strict` | | `уровень сбалансированный`, `level balanced`, `режим сбалансированный` | `level balanced` | | `включи глобально`, `enable globally` | `on --scope global` | -| `режим planmode`, `plan mode`, `режим планирования` | `mode planmode` | | `полный режим`, `full mode` | `mode full` | | `статус`, `что сейчас`, `manager status` | `status` | | `поправь промт`, `edit prompt`, `customize` | `edit` | @@ -110,16 +108,15 @@ The `agent_id` linchpin: subagent tool calls carry `agent_id` → guard allows. ## Modes (prompt text) -| Mode | Codeword | Block | -|------|----------|-------| -| `full` | `++m` | Manager role + protocol: decompose → TaskGraph → delegate → observe → integrate. Hands off everything. | -| `planmode` | `++mp` | Full block + Plan Mode addon: the plan itself must encode the whole TaskGraph in English, pre-decomposed with owners, dependencies, and parallel markers. | +| Mode | Selected by | Block | +|------|-------------|-------| +| `full` | `++m` (not in plan mode) | Manager role + protocol: decompose → TaskGraph → delegate → observe → integrate. Hands off everything. | +| `planmode` | `++m` when `permission_mode === 'plan'` (auto — no separate codeword) | Full block + Plan Mode addon: the plan itself must encode the whole TaskGraph in English, pre-decomposed with owners, dependencies, and parallel markers. | ## Customizing the prompt ``` /brewtools:manager edit full # copy default into project override, then edit it -/brewtools:manager edit planmode --scope global /brewtools:manager reset full # drop override, back to plugin default ``` @@ -130,7 +127,8 @@ The `agent_id` linchpin: subagent tool calls carry `agent_id` → guard allows. ``` # Codewords (always work, no setup needed) ++m implement the new caching layer -++mp design the migration from v1 to v2 schema +# In plan mode (permission_mode === 'plan'), ++m auto-adds the plan supplement: +++m design the migration from v1 to v2 schema # Hard wall — install and arm for this project /brewtools:manager on @@ -151,7 +149,6 @@ The `agent_id` linchpin: subagent tool calls carry `agent_id` → guard allows. # → deregisters from settings.local.json, run /reload after # Prompt-text customization (independent of the wall) -/brewtools:manager mode planmode /brewtools:manager edit full /brewtools:manager reset full diff --git a/brewtools/skills/manager/SKILL.md b/brewtools/skills/manager/SKILL.md index ce5204f..7ebb77d 100644 --- a/brewtools/skills/manager/SKILL.md +++ b/brewtools/skills/manager/SKILL.md @@ -1,7 +1,7 @@ --- name: brewtools:manager -description: "Manager mode. on installs+arms a HARD delegation wall into THIS project (PreToolUse denies Write/Edit/Bash in main session, subagents free); off disarms; uninstall removes it. Codewords ++m/++mp auto-inject a delegate-everything prompt; ++rr/++r auto-inject review discipline (anti-regression / two-phase double-check), all independent of this skill. level strict|balanced, status, mode, edit, reset. Triggers: manager, менеджер, hard mode, хард режим, delegate." -argument-hint: "[on|off|uninstall|status|level |mode |edit|reset] | | | " +description: "Manager mode. on installs+arms a HARD delegation wall into THIS project (PreToolUse denies Write/Edit/Bash in main session, subagents free); off disarms; uninstall removes it. Codeword ++m auto-injects a delegate-everything prompt (plan-aware: adds the plan supplement in plan mode); ++rr/++r auto-inject review discipline (anti-regression / two-phase double-check), all independent of this skill. level strict|balanced, status, edit, reset. Triggers: manager, менеджер, hard mode, хард режим, delegate." +argument-hint: "[on|off|uninstall|status|level |edit|reset] | | | " allowed-tools: Read, Bash, AskUserQuestion model: sonnet user-invocable: true @@ -11,11 +11,10 @@ user-invocable: true > Manager mode has **TWO independent layers**. Keep them straight: > -> 1. **SOFT codewords (`++m` / `++mp` / `++rr` / `++r`) — autonomous, hook-driven, ALWAYS fire.** A `UserPromptSubmit` hook (`hooks/manager-prompt.mjs`) watches every prompt; when it sees a codeword it injects the matching block as `additionalContext` for that one turn. This is NOT enabled/disabled by this skill — it works regardless of skill state. The skill only **explains** it (`status`) and **customizes its TEXT** (`mode`/`edit`/`reset`). -> Detection order (longest-prefix first): -> - `++mp` → Manager + Plan Mode (`planmode`) — writes the task graph, uses the tasks tool; tested first (prefix collision with `++m`). -> - `++m` → Manager mode (`full`) — delegate-everything prompt. -> - `++rr` → Regression Review discipline (`review-regression`) — after each significant phase: no regression + project standard + correctness; two-phase review→double-check→fix; final cross-review at task end. Tested after `++m`, before `++r`. +> 1. **SOFT codewords (`++m` / `++rr` / `++r`) — autonomous, hook-driven, ALWAYS fire.** A `UserPromptSubmit` hook (`hooks/manager-prompt.mjs`) watches every prompt; when it sees a codeword it injects the matching block as `additionalContext` for that one turn. This is NOT enabled/disabled by this skill — it works regardless of skill state. The skill only **explains** it (`status`) and **customizes its TEXT** (`edit`/`reset`). +> Detection (longest-prefix first within the review group): +> - `++m` → Manager mode. PLAN-AWARE: when the session is in plan mode (`permission_mode === 'plan'`) it injects the `planmode` block (full + plan addon — writes the task graph, uses the tasks tool); otherwise the plain `full` delegate-everything block. There is NO separate `++mp` codeword. +> - `++rr` → Regression Review discipline (`review-regression`) — after each significant phase: no regression + project standard + correctness; two-phase review→double-check→fix; final cross-review at task end. Tested before `++r`. > - `++r` → Review discipline (`review-double`) — two-phase multi-agent review→double-check→fix after each significant change; codeword-only (no ambient/wall injection). > - When the HARD wall is ON, the Manager (full) block is ALSO auto-injected on EVERY turn — no codeword needed. Codewords and wall injection are independent. > 2. **HARD wall — opt-in, this skill only, PER-PROJECT, INSTALLED-INTO-THE-PROJECT, persistent.** The wall is **NOT** a plugin hook. `on` does two things: it **installs** a self-contained `PreToolUse` guard into THIS project (copies the guard file + idempotently registers it in `/.claude/settings.local.json`) and **arms** it by flipping `state.hard=true`. The registered guard then **physically denies** mutating tools (Write/Edit/Bash/WebFetch/...) in the **main session**, leaving only delegate/read/track. Subagents stay fully free (`agent_id` linchpin). `off` only flips `state.hard=false` (disarm) — registration stays, the guard no-ops. `uninstall` removes the registration. The wall lives in project state + project settings, defaults OFF, persists until `off`/`uninstall`. There is **no codeword** for the wall. @@ -86,7 +85,7 @@ Project install targets (resolved from `process.cwd()`): Parse `$ARGUMENTS` (or the user's NL prompt, RU+EN) into `{ action, scope, mode, level, task }` using `references/intent-routing.md` — **Read and follow it**. -Actions: `on`, `off`, `uninstall`, `status`, `level `, `mode `, `edit [full|planmode]`, `reset [full|planmode]`, `hard-one-shot`, `manager-run`, `inline-run`. +Actions: `on`, `off`, `uninstall`, `status`, `level `, `edit`, `reset`, `hard-one-shot`, `manager-run`, `inline-run`. | Signal | Resolves | |--------|----------| @@ -96,10 +95,8 @@ Actions: `on`, `off`, `uninstall`, `status`, `level `, `mode в хард режиме` / ` in hard mode` | `action=hard-one-shot` — has a REAL task + hard marker | | ` от роли менеджера` / ` as manager` | `action=manager-run` — run task in manager role, wall untouched | | bare task, no control verb, no marker | `action=inline-run` | @@ -249,14 +246,10 @@ console.log(JSON.stringify(r)); " && echo "✅ level set" || echo "❌ FAILED set level" ``` -### mode (PROMPT TEXT ONLY — does not enable/disable anything) - -Same Bash block, `PATCH_JSON = {mode:'full'}` or `{mode:'planmode'}`. This sets only the informational `mode` field. It does **not** toggle the codewords (the hook always maps `++m`→full, `++mp`→planmode) and it does **not** touch the wall. Use `--scope` here only if you mean the prompt-text override scope. - ### status (the MAIN user-facing explainer — ALWAYS the teaching surface) Read merged state, resolve BOTH mode blocks, detect whether the guard is registered in `settings.local.json`, then render the canonical explainer from `references/hard.md`. It must teach the user the FULL model: -1. **How `++m`/`++mp` work** — ALWAYS, per-turn, hook-driven (`manager-prompt.mjs`), independent of this skill — and show BOTH injected blocks (full + planmode). Also state: when the HARD wall is armed, the Manager (full) block is ALSO ambient-injected every turn with no codeword needed (codewords and wall injection are independent). The session-start banner is the other read-only plugin layer. +1. **How `++m` works** — ALWAYS, per-turn, hook-driven (`manager-prompt.mjs`), independent of this skill. `++m` is plan-aware: it injects the planmode block (full + plan addon) when `permission_mode === 'plan'`, else the plain full block — there is NO separate `++mp` codeword. Show BOTH resolved blocks (full + planmode) so the user sees each variant. Also state: when the HARD wall is armed, the Manager (full) block is ALSO ambient-injected every turn with no codeword needed (codewords and wall injection are independent). The session-start banner is the other read-only plugin layer. 2. **The wall delivery model** — it is INSTALLED INTO this project, not a plugin hook: registered (once) in `/.claude/settings.local.json` (personal, gitignored), gated at runtime by project `state.json {hard}`. Report BOTH: is it registered? is it armed (`hard`)? 3. **Current WALL state for THIS project** — `hard` armed/disarmed, `level` strict/balanced, and a brief allowlist summary (what main session may/may not do). 4. **How on/off/uninstall work** — `on` = install+arm (`/reload` only on FIRST install), `off` = disarm only (registration kept), `uninstall` = deregister, `level` = strictness. @@ -295,16 +288,15 @@ Render using the canonical status block in `references/hard.md`, filling in `har # Manager — status ## Codewords (ALWAYS active — hook-driven, independent of this skill) -Type `++m` anywhere → injects the Manager (full) block for that one turn. -Type `++mp` anywhere → injects the Manager + Plan Mode block for that one turn. +Type `++m` anywhere → injects the Manager block for that one turn (plan-aware: planmode block in plan mode, else full). Type `++rr` anywhere → injects the Regression Review contract for that one turn. Type `++r` anywhere → injects the Review contract for that one turn. They fire on every prompt that contains them. This skill never turns them on or off. ---- injected by ++m (full) --- +--- injected by ++m (full — plain mode) --- ---- injected by ++mp (planmode) --- +--- injected by ++m (planmode — when permission_mode === 'plan') --- ## HARD wall (this project) — registered= armed= level= (state source: ) @@ -319,11 +311,11 @@ Level: /brewtools:manager level strict | balanced prompt source: full= planmode= ``` -### edit [mode] (PROMPT TEXT ONLY) +### edit (PROMPT TEXT ONLY) -Default mode = current `mode`. If no project/global override exists for that scope+mode, copy the current effective text into the override path, then print the path + content for the user to edit. This changes only what the codewords inject — it never touches the wall. +Operates on the Manager prompt text (internal mode `full`). If no project/global override exists for that scope, copy the current effective text into the override path, then print the path + content for the user to edit. This changes only what the codewords inject — it never touches the wall. -**EXECUTE** using Bash tool (substitute `SCOPE`, `MODE`): +**EXECUTE** using Bash tool (substitute `SCOPE`): ```bash BT_ROOT="${CLAUDE_PLUGIN_ROOT:-$(ls -d ~/.claude/plugins/cache/claude-brewcode/brewtools/*/ 2>/dev/null | sort -V | tail -1 | sed 's:/*$::')}" test -f "$BT_ROOT/hooks/lib/manager-prompts.mjs" || { echo "❌ BT_ROOT invalid: $BT_ROOT"; exit 1; } @@ -331,7 +323,7 @@ node --input-type=module -e " import {resolvePromptPath, resolvePrompt} from '${BT_ROOT}/hooks/lib/manager-prompts.mjs'; import fs from 'node:fs'; import path from 'node:path'; const cwd = process.cwd(); const root = '${BT_ROOT}'; -const scope = 'SCOPE'; const mode = 'MODE'; +const scope = 'SCOPE'; const mode = 'full'; const dest = resolvePromptPath(scope, mode, cwd); if (!fs.existsSync(dest)) { const cur = resolvePrompt(mode, cwd, root); @@ -346,18 +338,18 @@ if (!fs.existsSync(dest)) { > `SCOPE` here is the prompt-text override scope (`project` default, or `global`), NOT the wall. Global override goes under `~/.claude/manager/prompts/` (protected) — must go through this Node block. Tell the user the path; they (or you, for project scope) edit it with the Edit tool. -### reset [mode] (PROMPT TEXT ONLY) +### reset (PROMPT TEXT ONLY) -Default mode = current `mode`. Delete the override file at the chosen prompt-text scope, reverting to plugin default. Does not touch the wall. +Operates on the Manager prompt text (internal mode `full`). Delete the override file at the chosen prompt-text scope, reverting to plugin default. Does not touch the wall. -**EXECUTE** using Bash tool (substitute `SCOPE`, `MODE`): +**EXECUTE** using Bash tool (substitute `SCOPE`): ```bash BT_ROOT="${CLAUDE_PLUGIN_ROOT:-$(ls -d ~/.claude/plugins/cache/claude-brewcode/brewtools/*/ 2>/dev/null | sort -V | tail -1 | sed 's:/*$::')}" test -f "$BT_ROOT/hooks/lib/manager-prompts.mjs" || { echo "❌ BT_ROOT invalid: $BT_ROOT"; exit 1; } node --input-type=module -e " import {resolvePromptPath} from '${BT_ROOT}/hooks/lib/manager-prompts.mjs'; import fs from 'node:fs'; -const target = resolvePromptPath('SCOPE', 'MODE', process.cwd()); +const target = resolvePromptPath('SCOPE', 'full', process.cwd()); const existed = fs.existsSync(target); if (existed) fs.unlinkSync(target); console.log(JSON.stringify({removed:existed, path:target})); @@ -396,9 +388,9 @@ Same as `manager-run`: prepend the `full` block, build a TaskGraph, delegate, ne ## P3: Status Dump (ALWAYS last) -After ANY non-status action (`on`, `off`, `uninstall`, `level`, `mode`, `edit`, `reset`, `hard-one-shot`, `manager-run`, `inline-run`), end by emitting the resolved status (run the `status` Bash block, or reuse a result you already have). At minimum print: +After ANY non-status action (`on`, `off`, `uninstall`, `level`, `edit`, `reset`, `hard-one-shot`, `manager-run`, `inline-run`), end by emitting the resolved status (run the `status` Bash block, or reuse a result you already have). At minimum print: ``` -registered · armed(hard) · level · state source (project/global/default) · prompt source per mode · codewords (++m=full ALWAYS, ++mp=planmode ALWAYS) +registered · armed(hard) · level · state source (project/global/default) · prompt source per mode · codewords (++m ALWAYS — plan-aware: planmode in plan mode, else full) ``` For `on` that NEWLY registered, and for `uninstall`, also surface the `/reload` note. diff --git a/brewtools/skills/manager/references/hard.md b/brewtools/skills/manager/references/hard.md index e2e3eac..36d8c48 100644 --- a/brewtools/skills/manager/references/hard.md +++ b/brewtools/skills/manager/references/hard.md @@ -146,8 +146,10 @@ current level. # Manager — status ## Codewords (ALWAYS active — hook-driven, independent of this skill) -Type `++m` anywhere in a prompt → injects the Manager (full) block for that one turn. -Type `++mp` anywhere in a prompt → injects the Manager + Plan Mode block for that one turn. +Type `++m` anywhere in a prompt → injects the Manager block for that one turn. PLAN-AWARE: + in plan mode (permission_mode === 'plan') it injects the + Manager + Plan Mode block (full + plan addon); otherwise the + plain full block. There is NO separate `++mp` codeword. Type `++rr` anywhere in a prompt → injects the Regression Review contract for that one turn. Type `++r` anywhere in a prompt → injects the Review contract for that one turn. These fire on EVERY prompt containing them. This skill never enables or disables them; @@ -155,10 +157,10 @@ it only customizes their TEXT via `mode` / `edit` / `reset`. When the HARD wall is ON, the Manager (full) block is ALSO auto-injected every turn — no codeword needed. Codewords and wall injection are independent. ---- injected by ++m (full) --- +--- injected by ++m (full — plain mode) --- ---- injected by ++mp (planmode) --- +--- injected by ++m (planmode — when permission_mode === 'plan', full + plan addon) --- ## HARD wall (this project) — registered= armed= level= (state source: ) diff --git a/brewtools/skills/manager/references/intent-routing.md b/brewtools/skills/manager/references/intent-routing.md index 81de366..1fb10d9 100644 --- a/brewtools/skills/manager/references/intent-routing.md +++ b/brewtools/skills/manager/references/intent-routing.md @@ -10,9 +10,11 @@ verb and carries no hard/manager marker falls through to `inline-run`. > `state.hard`/`state.level` + a guard INSTALLED into the project's > `.claude/settings.local.json`, **PROJECT scope only**, persistent, this skill only. > `on` = install+arm; `off` = disarm (state only); `uninstall` = deregister. -> - **SOFT codewords** `++m`/`++mp` = autonomous hook injection, ALWAYS fire, -> not toggled here. `mode`/`edit`/`reset` only shape the injected TEXT. -> Note: `++mp` is tested BEFORE `++m` (prefix collision — both present ⇒ planmode wins). +> - **SOFT codewords** `++m`/`++rr`/`++r` = autonomous hook injection, ALWAYS fire, +> not toggled here. `edit`/`reset` only shape the injected TEXT. +> Note: `++m` is plan-aware — when the session is in plan mode (permission_mode === 'plan') +> it injects the planmode block (full + plan addon); otherwise the plain full block. +> There is NO separate `++mp` codeword. ## Actions @@ -24,10 +26,8 @@ verb and carries no hard/manager marker falls through to `inline-run`. | status | status, state, what now, show, current | статус, состояние, что сейчас, покажи, текущий | Main explainer: codewords + wall state + how to toggle | | level strict | level strict, strict, strict mode | режим строгий, строгий, строгий режим | Wall strictness = strict | | level balanced | level balanced, balanced, default level | режим сбалансированный, сбалансированный, баланс | Wall strictness = balanced (default) | -| mode full | mode full, full mode, set full | режим full, полный режим, переключи на full | Prompt TEXT only: use full.md block | -| mode planmode | mode planmode, plan mode, planning | режим planmode, режим планирования | Prompt TEXT only: use planmode.md block | -| edit | edit, customize, change prompt, fix prompt | правка, поправь промт, измени промт, кастомизируй | Edit `[full\|planmode]` prompt text | -| reset | reset, restore default, revert | сброс, верни дефолт, сбрось, по умолчанию | Reset `[full\|planmode]` prompt to default | +| edit | edit, customize, change prompt, fix prompt | правка, поправь промт, измени промт, кастомизируй | Edit the Manager prompt text | +| reset | reset, restore default, revert | сброс, верни дефолт, сбрось, по умолчанию | Reset the Manager prompt to default | | hard-one-shot | ` in hard mode`, ` under the wall` | `<задача> в хард режиме`, `<задача> в режиме стены` | Real task + hard marker → wall ON, run, auto-revert OFF | | manager-run | ` as manager`, ` in manager role` | `<задача> от роли менеджера`, `<задача> как менеджер` | Run task in manager role, wall untouched | | inline-run | any bare task/request, no verb, no marker | любой обычный запрос без глагола и маркера | Prepend full block and run as manager, wall untouched. When the wall is ON the full block is already ambient-injected by the hook; the skill still prepends it for consistency (one-shot runs may not have the wall on). | diff --git a/brewtools/skills/skill-toggle/SKILL.md b/brewtools/skills/skill-toggle/SKILL.md deleted file mode 100644 index 138d596..0000000 --- a/brewtools/skills/skill-toggle/SKILL.md +++ /dev/null @@ -1,219 +0,0 @@ ---- -name: brewtools:skill-toggle -description: "Disables/enables individual plugin skills (survives updates). Triggers: disable skill, enable skill, skill-toggle." -argument-hint: "[disable|enable|status|list] : [--mode=off|user-invocable-only|name-only]" -allowed-tools: Read, Bash, AskUserQuestion -model: sonnet -user-invocable: true ---- - -# Skill Toggle - -> **Disable/enable individual plugin skills** via the stable `skillOverrides` mechanism in `~/.claude/settings.json` (Claude Code 2.1.115+). State survives plugin updates — **no SessionStart reapply hook needed**. See also: `/brewtools:agent-toggle` for agents (uses native `permissions.deny`). - - - -## Robustness Rules - -| Rule | Applies | -|------|---------| -| Every Bash call ends with `&& echo "OK ..." \|\| echo "FAILED ..."` | ALL | -| Never use `Write`/`Edit` on `~/.claude/settings.json` — use Bash + Node helper | ALL | -| This skill mutates **skills only** (`skillOverrides`) — never agents | ALL | -| Atomic writes via lockfile + temp + rename (handled by helper) | P2 | - -Paths (substitute literally in Bash): -- Helper: `$CLAUDE_PLUGIN_ROOT/skills/skill-toggle/helpers/overrides.mjs` -- Settings: `~/.claude/settings.json` (resolved to `$HOME/.claude/settings.json`) -- Legacy global state (read-only, backwards visibility): `$CLAUDE_PLUGIN_DATA/toggle-state.json` - -## Override Modes - -| Mode | Effect | -|------|--------| -| `off` | Fully disabled — invisible to user and LLM | -| `user-invocable-only` | Only via `/plugin:skill` slash; LLM cannot auto-invoke | -| `name-only` | Name visible in autocomplete, instructions/body not loaded | -| `on` | (Re-enable) — entry removed from settings.json | - -Default for "disable" intent without explicit mode: `off`. - ---- - -## Phase I — Interactive Flow (entry gate) - -> **Full spec:** `_shared/toggle/interactive-flow.md` (phases I0-I4). Read on entry. This skill hardcodes `kind='skill'`. - -**Enter interactive flow when:** -- No args given, OR -- User prompt is freeform without concrete `plugin:name` (e.g. "отключи лишнее"), OR -- Parsed target missing from cache. - -**Skip interactive (go straight to P0 → P2 → P4)** when op AND target both explicit: `/brewtools:skill-toggle disable brewdoc:md-to-pdf`. - -| Phase | Action | Tool | -|-------|--------|------| -| I0 | Decide branch from input shape | — | -| I1 | Op picker — single `AskUserQuestion`, options: `status`, `disable`, `enable`, `list`, pre-selected: `disable` | AskUserQuestion | -| I2 | Catalog one-liner — Bash+Node imports `enumeratePlugins` from `$CLAUDE_PLUGIN_ROOT/skills/_shared/toggle/cache.mjs`, emit `AVAILABLE TO {OP} (N total):` then space-separated `plugin:name` tokens (filter: `disable`→not in overrides; `enable`→in overrides; kind=skill) | Bash | -| I3 | Resolve + confirm: exact `plugin:name` or unique `name`→no confirm; fuzzy→AskUserQuestion `[yes / pick different / cancel]`; multiple→AskUserQuestion 2-4 options. For `disable`, also ask mode if not specified | AskUserQuestion | -| I4 | Execute (P2) then ALWAYS print current state | Bash | - -Terminal ops (`list`, `status`) skip to I4 directly. - -**I4 status format (always printed):** -``` -DISABLED RIGHT NOW (via skillOverrides) ---------------------------------------- -brewdoc:md-to-pdf off -brewdoc:md-to-pdf user-invocable-only -(none) <-- if empty -ENABLED (M skills across P plugins) -``` - ---- - -## P0: Parse Intent - -Parse `$ARGUMENTS` (or NL prompt) into: - -``` -{ action: disable|enable|toggle|status|list, plugin?, skill?, mode?: off|user-invocable-only|name-only } -``` - -Rules: -- Default mode for `disable` = `off`. User can specify e.g. `--mode=user-invocable-only` or "make it slash-only". -- Target format: `plugin:name` (e.g., `brewdoc:md-to-pdf`). Bare `name` → AskUserQuestion which plugin. -- `status`, `list` take no targets. -- Multiple targets allowed for disable/enable — iterate P2 per target. -- No `--scope` flag — `skillOverrides` is global-only (per Claude Code design). - -If ambiguous (no plugin prefix for disable/enable) → AskUserQuestion with candidate plugins from `enumeratePlugins`. - ---- - -## P1: Validate Target - -**EXECUTE** using Bash tool: -```bash -node --input-type=module -e " -import {enumeratePlugins, resolveTarget} from '$CLAUDE_PLUGIN_ROOT/skills/_shared/toggle/cache.mjs'; -import fs from 'node:fs'; -const p = enumeratePlugins().get('PLUGIN_NAME'); -if (!p) { console.log(JSON.stringify({error:'plugin_not_installed', plugin:'PLUGIN_NAME'})); process.exit(0); } -const t = resolveTarget(p, 'skill', 'SKILL_NAME'); -const exists = fs.existsSync(t.visible) || fs.existsSync(t.hidden); -if (!exists) { console.log(JSON.stringify({error:'skill_not_found', plugin:p.plugin, name:'SKILL_NAME'})); process.exit(0); } -console.log(JSON.stringify({plugin:p.plugin, latest:p.latest, name:'SKILL_NAME'})); -" && echo "OK validate" || echo "FAILED validate" -``` - -Replace `PLUGIN_NAME`, `SKILL_NAME`. On `error` → stop, report. - ---- - -## P2: Write Override - -**EXECUTE** using Bash tool (disable): -```bash -node --input-type=module -e " -import {writeOverride} from '$CLAUDE_PLUGIN_ROOT/skills/skill-toggle/helpers/overrides.mjs'; -const r = await writeOverride('PLUGIN','NAME','MODE'); -console.log(JSON.stringify(r)); -" && echo "OK override" || echo "FAILED override" -``` - -For `disable` → `MODE` ∈ `off | user-invocable-only | name-only` (default `off`). -For `enable` → `MODE='on'` (deletes the entry). - -Substitute `PLUGIN`, `NAME`, `MODE` literally. - ---- - -## P3 — DELETED (no rename step needed) - -> **Persistence:** `~/.claude/settings.json` survives plugin updates — **no SessionStart reapply hook needed for skill-toggle.** The old file-rename approach (P3 in earlier versions) is removed. Plugin cache files are no longer touched by this skill. - -Agent-toggle uses the native `permissions.deny` mechanism (`_shared/toggle/deny.mjs`) — a separate, also update-safe flow. - ---- - -## P4: Verify + Notify - -**EXECUTE** using Bash tool: -```bash -node --input-type=module -e " -import {readOverrides} from '$CLAUDE_PLUGIN_ROOT/skills/skill-toggle/helpers/overrides.mjs'; -const o = readOverrides(); -console.log(JSON.stringify(o)); -" && echo "OK verify" || echo "FAILED verify" -``` - -Confirm `PLUGIN:NAME` present (for disable) or absent (for enable). Render result table: - -``` -# Skill Toggle — - -| Plugin | Name | Mode | Action | File | -|--------|------|------|--------|------| -| brewdoc | md-to-pdf | off | written | ~/.claude/settings.json | - -> Restart session or `/reload-plugins` for the change to take effect. -> Persisted to ~/.claude/settings.json — survives plugin updates. -``` - ---- - -## Sub-operations - -### status — merged view - -Reads both `skillOverrides` (current mechanism) AND legacy `toggle-state.json` (backwards visibility, read-only). - -**EXECUTE** using Bash tool: -```bash -node --input-type=module -e " -import {listOverrides} from '$CLAUDE_PLUGIN_ROOT/skills/skill-toggle/helpers/overrides.mjs'; -import {readState, globalStatePath, projectStatePath} from '$CLAUDE_PLUGIN_ROOT/skills/_shared/toggle/state.mjs'; -const overrides = listOverrides(); -const legacyG = readState(globalStatePath()).disabled || {}; -const legacyP = readState(projectStatePath(process.cwd())).disabled || {}; -const legacy = []; -for (const [k,v] of Object.entries({...legacyG, ...legacyP})) { - if (v && v.kind === 'skill') legacy.push({key:k, ...v, scope: legacyP[k] ? 'project' : 'global'}); -} -console.log(JSON.stringify({overrides, legacy})); -" && echo "OK status" || echo "FAILED status" -``` - -Render two tables: -1. **Current (skillOverrides):** plugin | name | mode -2. **Legacy (toggle-state.json, read-only):** plugin | name | scope | disabled_at — with note: "Legacy state — migrate by re-running disable; legacy file is no longer authoritative for skills." - -### list — enumerate all skills - -**EXECUTE** using Bash tool: -```bash -node --input-type=module -e " -import {enumeratePlugins, resolveTarget} from '$CLAUDE_PLUGIN_ROOT/skills/_shared/toggle/cache.mjs'; -import {readOverrides} from '$CLAUDE_PLUGIN_ROOT/skills/skill-toggle/helpers/overrides.mjs'; -import fs from 'node:fs'; -import path from 'node:path'; -const overrides = readOverrides(); -const out = []; -for (const [plugin, e] of enumeratePlugins()) { - const dir = path.join(e.path, 'skills'); - let entries = []; - try { entries = fs.readdirSync(dir, {withFileTypes:true}).filter(d=>d.isDirectory() && !d.name.startsWith('_')); } catch {} - for (const d of entries) { - const key = plugin + ':' + d.name; - out.push({plugin, name:d.name, version:e.latest, override: overrides[key] || null}); - } -} -console.log(JSON.stringify(out)); -" && echo "OK list" || echo "FAILED list" -``` - -Render grouped by plugin; mark rows with override mode. - - diff --git a/brewtools/skills/skill-toggle/helpers/overrides.mjs b/brewtools/skills/skill-toggle/helpers/overrides.mjs deleted file mode 100644 index 0c3de33..0000000 --- a/brewtools/skills/skill-toggle/helpers/overrides.mjs +++ /dev/null @@ -1,173 +0,0 @@ -// brewtools:skill-toggle — settings.json skillOverrides helper. -// Writes survive plugin updates (Claude Code 2.1.115+). -// Atomic: temp file + rename. Lockfile: O_CREAT|O_EXCL, 5 retries x 100ms. -// Modes: 'off' | 'user-invocable-only' | 'name-only' | 'on' ('on' deletes entry). - -import fs from 'node:fs'; -import os from 'node:os'; -import path from 'node:path'; -import crypto from 'node:crypto'; - -const VALID_MODES = new Set(['off', 'user-invocable-only', 'name-only', 'on']); -const DEFAULT_SETTINGS = '~/.claude/settings.json'; - -function resolveHome(p) { - if (!p) return p; - if (p === '~') return process.env.HOME || os.homedir(); - if (p.startsWith('~/')) return path.join(process.env.HOME || os.homedir(), p.slice(2)); - return p; -} - -function readJsonSafe(filePath) { - try { - const raw = fs.readFileSync(filePath, 'utf8'); - const parsed = JSON.parse(raw); - return (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) ? parsed : {}; - } catch { - return {}; - } -} - -function sleep(ms) { - return new Promise(r => setTimeout(r, ms)); -} - -// Lock identity hardening: lockfile contents = `${pid}:${randomHex16}`. acquireLock -// returns the token; releaseLock verifies match before unlink. -// Failure mode: if a writer stalls >60s another process may steal the lock; the -// stalled writer detects this on release and aborts unlink. A's already-written -// settings.json may have been overwritten by B — token check prevents A from -// further clobbering B's lockfile. -async function acquireLock(lockPath, { retries = 5, delayMs = 100 } = {}) { - for (let i = 0; i < retries; i++) { - const token = `${process.pid}:${crypto.randomBytes(8).toString('hex')}`; - try { - const fd = fs.openSync(lockPath, fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_WRONLY, 0o600); - fs.writeSync(fd, token); - fs.closeSync(fd); - return token; - } catch (e) { - if (e.code !== 'EEXIST') throw e; - // Stale lock detection: malformed PID, dead process, or age > 60s - try { - const lockContent = fs.readFileSync(lockPath, 'utf8').trim(); - const pidPart = lockContent.split(':')[0]; - const lockPid = parseInt(pidPart, 10); - const lockStat = fs.statSync(lockPath); - const ageMs = Date.now() - lockStat.mtimeMs; - let stale = false; - if (!Number.isFinite(lockPid) || lockPid <= 0) { - stale = true; - } else { - try { - process.kill(lockPid, 0); - } catch (killErr) { - if (killErr.code === 'ESRCH') stale = true; - } - } - if (!stale && ageMs > 60_000) stale = true; - if (stale) { - try { fs.unlinkSync(lockPath); } catch {} - continue; - } - } catch (statErr) { - // lockfile vanished between EEXIST and stat — race, retry - } - if (i === retries - 1) { - throw new Error(`Could not acquire lock ${lockPath} after ${retries} attempts (${delayMs}ms each). Another process may be writing settings.json. Remove ${lockPath} manually if stale.`); - } - await sleep(delayMs); - } - } - return null; -} - -function releaseLock(lockPath, token) { - try { - const current = fs.readFileSync(lockPath, 'utf8').trim(); - if (token && current !== token) { - process.stderr.write(`[skill-toggle] lock stolen: expected token ${token}, found ${current} at ${lockPath}. Not unlinking.\n`); - return; - } - fs.unlinkSync(lockPath); - } catch {} -} - -/** - * Read skillOverrides from settings.json. - * @param {string} settingsPath - path with optional ~ prefix - * @returns {object} skillOverrides object, or {} if missing/unreadable - */ -export function readOverrides(settingsPath = DEFAULT_SETTINGS) { - const fp = resolveHome(settingsPath); - const settings = readJsonSafe(fp); - const o = settings.skillOverrides; - return (o && typeof o === 'object' && !Array.isArray(o)) ? o : {}; -} - -/** - * Write a single skill override entry atomically. - * @param {string} plugin - plugin name (e.g. 'brewui') - * @param {string} name - skill name (e.g. 'image-gen') - * @param {string} mode - 'off' | 'user-invocable-only' | 'name-only' | 'on' - * @param {object} opts - { settingsPath, retries, delayMs } - * @returns {object} { key, mode, action, file } - */ -export async function writeOverride(plugin, name, mode, opts = {}) { - if (!plugin || typeof plugin !== 'string') throw new Error('plugin required'); - if (!name || typeof name !== 'string') throw new Error('name required'); - if (!VALID_MODES.has(mode)) throw new Error(`invalid mode '${mode}' — must be one of: ${[...VALID_MODES].join(', ')}`); - - const settingsPath = resolveHome(opts.settingsPath || DEFAULT_SETTINGS); - const lockPath = `${settingsPath}.lock`; - const dir = path.dirname(settingsPath); - fs.mkdirSync(dir, { recursive: true }); - - const lockToken = await acquireLock(lockPath, { retries: opts.retries ?? 5, delayMs: opts.delayMs ?? 100 }); - try { - const settings = readJsonSafe(settingsPath); - const overrides = (settings.skillOverrides && typeof settings.skillOverrides === 'object' && !Array.isArray(settings.skillOverrides)) - ? { ...settings.skillOverrides } - : {}; - const key = `${plugin}:${name}`; - let action; - if (mode === 'on') { - if (key in overrides) { delete overrides[key]; action = 'deleted'; } - else action = 'noop'; - } else { - overrides[key] = mode; - action = 'written'; - } - const merged = { ...settings, skillOverrides: overrides }; - if (Object.keys(overrides).length === 0) delete merged.skillOverrides; - - const tmp = `${settingsPath}.tmp.${process.pid}.${crypto.randomBytes(4).toString('hex')}`; - try { - fs.writeFileSync(tmp, JSON.stringify(merged, null, 2) + '\n', { encoding: 'utf8', mode: 0o600 }); - fs.renameSync(tmp, settingsPath); - } catch (e) { - try { fs.unlinkSync(tmp); } catch {} - throw e; - } - - return { key, mode, action, file: settingsPath }; - } finally { - releaseLock(lockPath, lockToken); - } -} - -/** - * Flat list of all current overrides. - * @param {string} settingsPath - * @returns {Array<{plugin, name, mode}>} - */ -export function listOverrides(settingsPath = DEFAULT_SETTINGS) { - const overrides = readOverrides(settingsPath); - const out = []; - for (const [key, mode] of Object.entries(overrides)) { - const idx = key.indexOf(':'); - if (idx <= 0) continue; - out.push({ plugin: key.slice(0, idx), name: key.slice(idx + 1), mode }); - } - return out; -} diff --git a/brewtools/skills/think-short/README.md b/brewtools/skills/think-short/README.md index f8ddb5f..f25903a 100644 --- a/brewtools/skills/think-short/README.md +++ b/brewtools/skills/think-short/README.md @@ -1,56 +1,45 @@ # Think-Short -Toggle terse-output mode — cuts preamble and filler via SessionStart + PreToolUse:Task injection. +Install-only skill that wires (or removes) three self-contained hooks injecting a terse-output prompt. No on/off toggle, no profiles, no project-level config — only an ephemeral per-session counter in the OS temp dir (`os.tmpdir()/brewtools-think-short/.think-short-counter`), auto-pruned. The hooks own all runtime behavior. -## Commands +## What it does -| Command | What it does | -|---------|-------------| -| `/brewtools:think-short on [--scope global\|project]` | Enable terse mode (default scope: project) | -| `/brewtools:think-short off` | Disable terse mode | -| `/brewtools:think-short profile ` | Set compression profile | -| `/brewtools:think-short status` | Print effective state, source, state files, last 10 log lines | -| `/brewtools:think-short blacklist add\|remove ` | Exclude/include agent from terse injection | +| Hook | Behavior | +|------|----------| +| SessionStart | injects the full terse prompt + resets the per-session counter | +| UserPromptSubmit | injects the full prompt every 10th user prompt (10/20/30…, not the 1st) | +| PreToolUse:`Task\|Agent` | injects the full terse prompt into spawned subagents (coexistence-safe with other Task hooks) | -## NL prompts (RU+EN) +The terse prompt cuts preamble, AI phrasings, and filler, and enforces tool discipline. -| Phrase | Resolves to | -|--------|-------------| -| `включи терсный`, `be terse`, `think-short on` | `on` | -| `выключи терсный`, `turn off`, `think-short off` | `off` | -| `лёгкий режим`, `light`, `уровень 1`, `level 1` | `profile light` | -| `средний режим`, `medium`, `уровень 2`, `level 2` | `profile medium` | -| `агрессивный`, `макс`, `aggressive`, `уровень 3`, `level 3` | `profile aggressive` | -| `включись максимально`, `be terse max` | `on` + `profile aggressive` (combo) | -| `что сейчас`, `think-short status` | `status` | +## Usage -Ambiguous input triggers `AskUserQuestion` with candidate operations. +``` +/brewtools:think-short # install — asks Project or Global +/brewtools:think-short install global # install globally (~/.claude) +/brewtools:think-short install project # install for this repo (.claude) +/brewtools:think-short remove # remove — asks which target +/brewtools:think-short убери глобально # free-text intent also works (RU+EN) +``` -## State files +The skill decides **install vs remove** and **project vs global** (asking when unspecified), then delegates the file work to the `brewcode:hook-creator` agent. -| Scope | Path | -|-------|------| -| Global | `~/.claude/plugins/data/brewtools-claude-brewcode/think-short.json` | -| Project | `.claude/brewtools/think-short.json` | +## Where it installs -Project state wins over global (merge precedence). Default scope for writes is `project` (silent). +| Target | Hooks dir | settings.json | +|--------|-----------|---------------| +| Project | `/.claude/hooks/` | `/.claude/settings.json` | +| Global | `~/.claude/hooks/` | `~/.claude/settings.json` | -State schema: `{"version":1, "enabled":false, "profile":"medium", "blacklist":["debate","docs-writer","architect"], "updated_at":"ISO"}` +Merge is append + dedupe by the `think-short-*.mjs` script path (idempotent re-install). Remove strips entries by those markers and deletes the 4 copied files. Global writes go through Bash only (`~/.claude/*` is a protected path). -## Profiles +## Cadence -| Profile | Directives | Approx tokens | Typical use | -|---------|-----------|---------------|-------------| -| `light` | Be terse. Results first. Think through edits before executing. | ~20 tokens | Light reduction, keeps reasoning visible | -| `medium` | Light + no AI phrasings, no sycophancy. Tool discipline: Grep before Read, Edit over Write, parallel independent calls, no re-Read of just-edited files. | ~60 tokens | Balanced — recommended default | -| `aggressive` | Medium + ASCII-only, no closing fluff, no disclaimers. Full tool discipline: bundle edits, replace_all for N-identical, gather call-sites via Grep before parallel Edits. | ~120 tokens | Maximum suppression — long automated runs | +The UserPromptSubmit hook re-injects on every 10th prompt (counter stored in the OS temp dir per session, reset at SessionStart). This keeps the directive in context across long sessions without spamming every turn. -## Logs +## After install/remove -File: `.claude/logs/brewtools.log` -Prefix: `think-short:` - -Every NL resolution and scope selection is logged at INFO level. +A new session picks up the change automatically — no `/reload-plugins` needed (these are plain settings.json hooks). SessionStart fires on the next `claude` start or `--resume`. ## Docs diff --git a/brewtools/skills/think-short/SKILL.md b/brewtools/skills/think-short/SKILL.md index d1e193e..01ffd36 100644 --- a/brewtools/skills/think-short/SKILL.md +++ b/brewtools/skills/think-short/SKILL.md @@ -1,246 +1,100 @@ --- name: brewtools:think-short -description: "Toggles terse-output mode to cut preamble and filler. Triggers: think-short, be terse, think shorter." -argument-hint: "[on|off|profile |status|blacklist add|remove ] [--scope global|project]" -allowed-tools: Read, Bash, AskUserQuestion +description: "Installs or removes the think-short terse-mode hooks. Triggers: think-short, be terse, terse mode, инжект терс-режим." +argument-hint: "[install|remove] [project|global] | free-text intent" +allowed-tools: Read, Bash, AskUserQuestion, Task model: sonnet user-invocable: true --- # Think-Short -> Toggle terse-output mode. Writes state to `$CLAUDE_PLUGIN_DATA/think-short.json` (global) or `.claude/brewtools/think-short.json` (project). Hooks read state and inject profile-specific directives into SessionStart + PreToolUse:Task. This skill ONLY parses intent and mutates state. +> Install-only skill. It wires three self-contained hooks (SessionStart, UserPromptSubmit, PreToolUse:Task) that inject a terse-output prompt — or removes them. No on/off toggle, no profiles, no project-level config — only an ephemeral per-session counter in the OS temp dir (`os.tmpdir()/brewtools-think-short/.think-short-counter`), auto-pruned. The hooks own all runtime behavior. This skill only decides **install vs remove** and **project vs global**, then delegates the file work to the `brewcode:hook-creator` agent following the runbook. + +## What the hooks do (informational — skill does NOT implement) + +| Hook | Behavior | +|------|----------| +| SessionStart | inject the full terse prompt + reset the per-session counter | +| UserPromptSubmit | inject the full prompt every 10th user prompt (10/20/30…, not the 1st) | +| PreToolUse:`Task\|Agent` | inject the full terse prompt into spawned subagents (coexistence-safe with other Task hooks) | -## Robustness Rules +## BT_ROOT Resolver (use in EVERY bash block) -| Rule | Applies | -|------|---------| -| Every Bash call ends with `&& echo "OK ..." \|\| echo "FAILED ..."` | ALL | -| Never use `Write`/`Edit` on `~/.claude/*` or `$CLAUDE_PLUGIN_DATA` — use Bash + Node `fs` via helpers | ALL | -| State writes go through `writeState()` in `helpers/state.mjs` (atomic, O_NOFOLLOW, 0600, merges defaults + timestamps) | P2 | -| State reads go through `resolveEffectiveState()` in `helpers/state.mjs` (merges hardcoded → global → project → env) | P0, status | -| NL-prompt resolution ALWAYS logged via `log()` from `helpers/state.mjs` at INFO level (auto-prefixed `think-short`), to `.claude/logs/brewtools.log` | P0 | - -### BT_ROOT Resolver - -`$CLAUDE_PLUGIN_ROOT` is NOT inherited by the Bash tool in main-conversation slash invocations. Every Bash block MUST resolve `BT_ROOT` dynamically (no hardcoded version): +`$CLAUDE_PLUGIN_ROOT` is NOT inherited by the Bash tool in main-conversation slash invocations. Resolve dynamically: ```bash BT_ROOT="${CLAUDE_PLUGIN_ROOT:-$(ls -d ~/.claude/plugins/cache/claude-brewcode/brewtools/*/ 2>/dev/null | sort -V | tail -1 | sed 's:/*$::')}" -test -d "$BT_ROOT/skills/think-short/helpers" || { echo "❌ BT_ROOT invalid: $BT_ROOT"; exit 1; } +test -d "$BT_ROOT/skills/think-short/assets" || { echo "❌ BT_ROOT invalid: $BT_ROOT"; exit 1; } ``` -Paths (use `$BT_ROOT` literally in Bash): -- Global state: `$CLAUDE_PLUGIN_DATA/think-short.json` (fallback: `~/.claude/plugins/data/brewtools-claude-brewcode/think-short.json`) — computed by `getPaths(cwd)` -- Project state: `$PWD/.claude/brewtools/think-short.json` — computed by `getPaths(cwd)` -- State helper: `$BT_ROOT/skills/think-short/helpers/state.mjs` — exports `getPaths`, `readPluginDefaults`, `resolveEffectiveState`, `writeState`, `log` -- Safe-write helper: `$BT_ROOT/skills/think-short/helpers/safe-write.mjs` — exports `safeReadJson`, `safeWriteJson` -- Log file: `$PWD/.claude/logs/brewtools.log` (auto-created by `log()`) +Asset paths (all under `$BT_ROOT/skills/think-short/assets/`): +- `INSTALL.md` — full install/remove runbook (project + global + remove) +- `think-short-session.mjs`, `think-short-prompt-counter.mjs`, `think-short-task.mjs`, `family-roots.mjs`, `think-short-prompt.md` — the hook files that travel together (`family-roots.mjs` is imported by `think-short-task.mjs` and MUST be copied alongside it) -State schema: -```json -{"version":1, "enabled":false, "profile":"medium", "blacklist":["debate","docs-writer","architect"], "updated_at":"ISO"} -``` +> Never use `Write`/`Edit` on `~/.claude/*` — protected path, blocked in ALL modes. Global install/remove runs through the Bash tool only (`cp` + `node` merge). The hook-creator agent handles this per the runbook. --- -## P0: Parse Intent +## Step 1 — Decide INTENT (install | remove) -Parse `$ARGUMENTS` into structured form: -``` -{ op: on|off|profile|status|blacklist, profile?: light|medium|aggressive, blacklistOp?: add|remove, agent?: string, scope?: global|project } -``` +Read `$ARGUMENTS`. -### Structural match (exact) +- Default = **install**. +- **remove** only if the prompt clearly says so: `remove`, `uninstall`, `delete`, `убери`, `удали`, `выключи`, `сними`, `off`, `disable`. +- Genuinely ambiguous → `AskUserQuestion` (options: **Install** / **Remove**). -| Input | Resolves to | -|-------|-------------| -| `on [--scope global\|project]` | `{op:on, scope}` | -| `off` | `{op:off}` | -| `profile ` | `{op:profile, profile}` | -| `status` | `{op:status}` | -| `blacklist add ` | `{op:blacklist, blacklistOp:add, agent}` | -| `blacklist remove ` | `{op:blacklist, blacklistOp:remove, agent}` | +## Step 2 — Decide TARGET (project | global) -### NL-prompt fallback (MANDATORY) +- Explicit global → `global`: `global`, `глобально`, `for all projects`, `всех проектах`. +- Explicit project → `project`: `project`, `this repo`, `локально`, `здесь`, `этот проект`. +- NOT specified → `AskUserQuestion`: "Install think-short for this Project or Globally?" (options: **Project** / **Global**). Do not auto-guess. -If no structural match, treat argument as NL prompt: +For **remove** with unspecified target, ask the same Project/Global question (or offer to clean both if the user says "everywhere"). -1. Trim + lowercase. -2. Tokenize + apply synonym table: +## Step 3 — State the plan, then delegate -| Regex / keyword | Resolves to | -|-----------------|-------------| -| `включи\|включись\|enable\|активируй\|turn on\|^on$` | `on` | -| `выключи\|выключись\|disable\|отключи\|turn off\|^off$` | `off` | -| `light\|лайт\|лёгкий\|легкий\|уровень 1\|level 1\|\b1\b` | `profile light` | -| `medium\|мид\|средний\|уровень 2\|level 2\|\b2\b` | `profile medium` | -| `aggressive\|агрессив\|агрессивный\|макс\|максимально\|max\|уровень 3\|level 3\|\b3\b` | `profile aggressive` | -| `status\|статус\|как дела\|что сейчас` | `status` | +Tell the user plainly what will happen, e.g.: -3. **Combos allowed** — e.g. `включись максимально` → `on` + `profile aggressive`. Execute BOTH ops in sequence. -4. **Ambiguous** (0 matches OR >1 mutually-exclusive match that is not a combo) → `AskUserQuestion` with candidate operations as options. -5. After resolution, INFO log: - ``` - think-short: NL-prompt "" → resolved as - ``` +> Installing think-short hooks (SessionStart + UserPromptSubmit + PreToolUse:Task) into `/.claude/` and merging `/.claude/settings.json`. -**EXECUTE** using Bash tool (resolve + log): -```bash -BT_ROOT="${CLAUDE_PLUGIN_ROOT:-$(ls -d ~/.claude/plugins/cache/claude-brewcode/brewtools/*/ 2>/dev/null | sort -V | tail -1 | sed 's:/*$::')}" -test -d "$BT_ROOT/skills/think-short/helpers" || { echo "❌ BT_ROOT invalid: $BT_ROOT"; exit 1; } -node --input-type=module -e " -import {log} from '${BT_ROOT}/skills/think-short/helpers/state.mjs'; -log('info', 'NL-prompt \"INPUT\" → resolved as RESOLVED', process.cwd(), process.env.CLAUDE_CODE_SESSION_ID || null); -" && echo "OK log" || echo "FAILED log" -``` +Then verify assets and delegate to `brewcode:hook-creator` via the Task tool. Pass it: the chosen **action** (install|remove), the chosen **target** (project|global), the absolute **runbook path**, and the absolute **assets source dir**. -Replace `INPUT` and `RESOLVED` literally. The `log()` from `state.mjs` auto-prefixes with `think-short` — do NOT add it again. - ---- - -## P1: Scope Selection - -**Default = `project` scope.** Silent — no AskUserQuestion unless the user explicitly asks for disambiguation. - -| Signal | Scope | -|--------|-------| -| `--scope global` or `--scope=global` present | `global` | -| `--scope project` or `--scope=project` present | `project` | -| User prompt contains explicit ambiguity ("для всех проектов или только здесь", "global or project?", `--ask-scope`) | Use `AskUserQuestion` — options: Project (default) / Global | -| Otherwise (including `--print` / headless / no tty) | `project` (silent default) | - -Always log chosen scope at INFO: -``` -think-short: scope= (, --scope ) -``` - -For `status` — no scope question (reads merged state). For `blacklist` — defaults to project scope silently. - -For combo ops — determine scope ONCE via rules above, apply to all ops. - ---- - -## P2: Mutate State - -**EXECUTE** using Bash tool (substitute `SCOPE`, `PATCH_JSON`, `OP`): +**EXECUTE** using Bash tool (resolve + print the absolute runbook and assets-dir paths to hand off): ```bash BT_ROOT="${CLAUDE_PLUGIN_ROOT:-$(ls -d ~/.claude/plugins/cache/claude-brewcode/brewtools/*/ 2>/dev/null | sort -V | tail -1 | sed 's:/*$::')}" -test -d "$BT_ROOT/skills/think-short/helpers" || { echo "❌ BT_ROOT invalid: $BT_ROOT"; exit 1; } -node --input-type=module -e " -import {writeState, log} from '${BT_ROOT}/skills/think-short/helpers/state.mjs'; -const patch = PATCH_JSON; -const r = await writeState('SCOPE', patch, process.cwd()); -log('info', 'toggle OP applied (scope=SCOPE) → ' + JSON.stringify(patch), process.cwd(), process.env.CLAUDE_CODE_SESSION_ID || null); -console.log(JSON.stringify({scope:'SCOPE', file:r.path, state:r.after})); -" && echo "OK mutate" || echo "FAILED mutate" +test -d "$BT_ROOT/skills/think-short/assets" || { echo "❌ BT_ROOT invalid: $BT_ROOT"; exit 1; } +echo "ASSETS_DIR=$BT_ROOT/skills/think-short/assets" +echo "RUNBOOK=$BT_ROOT/skills/think-short/assets/INSTALL.md" && echo "✅ assets ok" || echo "❌ FAILED" ``` -| Op | `PATCH_JSON` | `OP` | -|----|--------------|------| -| `on` | `{enabled:true}` | `on` | -| `off` | `{enabled:false}` | `off` | -| `profile light` | `{profile:'light'}` | `profile-light` | -| `profile medium` | `{profile:'medium'}` | `profile-medium` | -| `profile aggressive` | `{profile:'aggressive'}` | `profile-aggressive` | -| `blacklist add X` | `{blacklist:[...current,'X']}` (read via `resolveEffectiveState` first, dedupe) | `blacklist-add-X` | -| `blacklist remove X` | `{blacklist:current.filter(a=>a!=='X')}` | `blacklist-remove-X` | +> **STOP if ❌** — plugin cache incomplete; reinstall/update brewtools first. -`writeState` handles: reading existing scope file, merging defaults, atomic write via `safeWriteJson`, stamping `updated_at`, enforcing `version:1`. No manual `fs.existsSync` / `safeWrite` calls needed. - -**Combo ops** (e.g. `on` + `profile aggressive`): pass a single merged patch `{enabled:true, profile:'aggressive'}` — one `writeState` call, atomic. - -**Blacklist mutation** example (inline — single node invocation): - -```bash -BT_ROOT="${CLAUDE_PLUGIN_ROOT:-$(ls -d ~/.claude/plugins/cache/claude-brewcode/brewtools/*/ 2>/dev/null | sort -V | tail -1 | sed 's:/*$::')}" -node --input-type=module -e " -import {resolveEffectiveState, writeState, log} from '${BT_ROOT}/skills/think-short/helpers/state.mjs'; -const s = await resolveEffectiveState(process.cwd()); -const cur = Array.isArray(s.blacklist) ? s.blacklist : []; -const next = Array.from(new Set([...cur, 'AGENT'])); // or: cur.filter(a => a !== 'AGENT') -const r = await writeState('SCOPE', {blacklist: next}, process.cwd()); -log('info', 'blacklist OP AGENT (scope=SCOPE)', process.cwd(), process.env.CLAUDE_CODE_SESSION_ID || null); -console.log(JSON.stringify({scope:'SCOPE', file:r.path, state:r.after})); -" && echo "OK mutate" || echo "FAILED mutate" -``` - ---- - -## P3: Status Output - -For `op=status` — read merged state + metadata and print: +Spawn the agent (substitute `ACTION`, `TARGET`, `RUNBOOK`, `ASSETS_DIR` from above): ``` -think-short: ENABLED (source: project-state) -profile: medium (source: project-state) -blacklist: [debate, docs-writer, architect] -state files: - project: .claude/brewtools/think-short.json (exists, updated 2026-04-20T12:34:56Z) - global: ~/.claude/plugins/data/brewtools-claude-brewcode/think-short.json (missing) -DEFAULT_THINK_SHORT: enabled=false, profile=medium -env override: THINK_SHORT_DEFAULT=(unset) -recent log: - +Task(subagent_type="brewcode:hook-creator", prompt=" +Follow the runbook at RUNBOOK exactly — it self-locates its source via SRC=\$(dirname \"\$RUNBOOK\"). +ACTION = ACTION (install|remove) +TARGET = TARGET (project|global) +RUNBOOK = RUNBOOK (absolute path to assets/INSTALL.md) +ASSETS_DIR = ASSETS_DIR (absolute path to the assets source dir — copy the 4 hook files FROM here) +Copy/merge or strip the 4 think-short hook assets per the runbook's marker convention, copying from ASSETS_DIR. +Project target: Write/Edit settings.json freely. Global target (~/.claude/*): BASH ONLY (cp + node merge), never Write/Edit — protected path. +Merge = append + dedupe by think-short-*.mjs script path. Remove = strip entries by those markers, drop empty event arrays, delete the 4 files. +Report which hooks were installed/removed and the exact settings.json path. +") ``` -**EXECUTE** using Bash tool: -```bash -BT_ROOT="${CLAUDE_PLUGIN_ROOT:-$(ls -d ~/.claude/plugins/cache/claude-brewcode/brewtools/*/ 2>/dev/null | sort -V | tail -1 | sed 's:/*$::')}" -test -d "$BT_ROOT/skills/think-short/helpers" || { echo "❌ BT_ROOT invalid: $BT_ROOT"; exit 1; } -node --input-type=module -e " -import {resolveEffectiveState, getPaths} from '${BT_ROOT}/skills/think-short/helpers/state.mjs'; -import fs from 'node:fs'; -const cwd = process.cwd(); -const state = await resolveEffectiveState(cwd); -const {globalPath, projectPath, pluginJsonPath} = getPaths(cwd); -const gExists = fs.existsSync(globalPath), pExists = fs.existsSync(projectPath); -console.log(JSON.stringify({ - enabled: state.enabled, profile: state.profile, blacklist: state.blacklist, - sources: state.sources, - files: { - global: {path: globalPath, exists: gExists, mtime: gExists ? fs.statSync(globalPath).mtime.toISOString() : null}, - project: {path: projectPath, exists: pExists, mtime: pExists ? fs.statSync(projectPath).mtime.toISOString() : null} - }, - pluginDefaults: state.raw.pluginDefaults, - envOverride: state.raw.env -}, null, 2)); -" && echo "OK status" || echo "FAILED status" +## Step 4 — Report -# Append last 10 log lines matching think-short -grep 'think-short' .claude/logs/brewtools.log 2>/dev/null | tail -10 || echo "(no log entries)" -``` - -Render the final output in the shape shown above. Omit sections that are N/A. - ---- - -## P4: Notify + Reload Reminder - -After mutation (non-status ops), render: - -``` -# Think-Short — -Scope: -File: -State: enabled=, profile=, blacklist=[...] - -> Hooks pick up new state on next SessionStart / PreToolUse:Task — no reload needed. -``` - -For combo ops, show the final merged state after all mutations. - ---- - -## Sub-operation: blacklist - -- `blacklist add ` — append to state.blacklist if absent -- `blacklist remove ` — remove from state.blacklist if present -- Scope defaults to **project** (no AskUserQuestion). Override via `--scope=global`. -- Log every mutation at INFO level with prefix `think-short`. +After hook-creator returns, report: +- which hooks were installed/removed, +- the exact `settings.json` that changed (project or global path), +- reminder: **a new session picks them up automatically — no `/reload` needed** (plain settings.json hooks; SessionStart fires on next `claude` start / `--resume`). --- @@ -248,28 +102,32 @@ For combo ops, show the final merged state after all mutations. | Condition | Response | |-----------|----------| -| `BT_ROOT` resolves but `$BT_ROOT/skills/think-short/helpers` missing | ERROR: `think-short: helpers not found under $BT_ROOT — plugin cache incomplete.` STOP. | +| `BT_ROOT` resolves but `$BT_ROOT/skills/think-short/assets` missing | ERROR: `think-short: assets not found under $BT_ROOT — plugin cache incomplete.` STOP. | | Neither `$CLAUDE_PLUGIN_ROOT` set nor any cached plugin dir found | ERROR: `think-short: cannot locate plugin root — install/update brewtools first.` STOP. | -| NL prompt matches nothing | AskUserQuestion: "Which action? [on / off / profile light / profile medium / profile aggressive / status / cancel]" | -| NL prompt matches >1 mutually-exclusive op (not a combo) | AskUserQuestion with matched candidates as options. | -| User picks `cancel` in any AskUserQuestion | Abort. No state mutation. Log at INFO: `think-short: user cancelled`. | +| Intent ambiguous | AskUserQuestion: Install / Remove. | +| Target unspecified | AskUserQuestion: Project / Global. | +| Global target | Hook-creator MUST use Bash only (`cp` + `node` merge) — `~/.claude/*` is protected. | --- ## Smoke Test -Verify wiring after install/update or when debugging: +Verify the 4 assets exist and the scripts parse before delegating: ```bash BT_ROOT="${CLAUDE_PLUGIN_ROOT:-$(ls -d ~/.claude/plugins/cache/claude-brewcode/brewtools/*/ 2>/dev/null | sort -V | tail -1 | sed 's:/*$::')}" -test -d "$BT_ROOT/skills/think-short/helpers" || { echo "❌ BT_ROOT invalid: $BT_ROOT"; exit 1; } -node --input-type=module -e " -import {resolveEffectiveState} from '${BT_ROOT}/skills/think-short/helpers/state.mjs'; -const s = await resolveEffectiveState(process.cwd()); -console.log('smoke OK:', JSON.stringify(s)); -" && echo '✅ smoke' || echo '❌ smoke FAILED' +A="$BT_ROOT/skills/think-short/assets" +test -d "$A" || { echo "❌ assets dir missing"; exit 1; } +for f in think-short-session.mjs think-short-prompt-counter.mjs think-short-task.mjs family-roots.mjs think-short-prompt.md INSTALL.md; do + test -f "$A/$f" || { echo "❌ missing $f"; exit 1; } +done +node --check "$A/think-short-session.mjs" && \ +node --check "$A/think-short-prompt-counter.mjs" && \ +node --check "$A/think-short-task.mjs" && \ +node --check "$A/family-roots.mjs" && \ +echo "✅ smoke" || echo "❌ smoke FAILED" ``` -Expected: one `smoke OK: {...}` line with `enabled`, `profile`, `blacklist`, `sources`, `raw`, then `✅ smoke`. +Expected: `✅ smoke`. diff --git a/brewtools/skills/think-short/assets/INSTALL.md b/brewtools/skills/think-short/assets/INSTALL.md new file mode 100644 index 0000000..ee59d42 --- /dev/null +++ b/brewtools/skills/think-short/assets/INSTALL.md @@ -0,0 +1,196 @@ +# think-short hooks — install / remove runbook + +Self-contained hook assets. The `/brewtools:think-short` skill copies these into a +target hooks dir and wires `settings.json`. All 4 files travel together: + +| File | Event | Channel | +|------|-------|---------| +| `think-short-session.mjs` | SessionStart | `additionalContext` (full prompt) + resets per-session counter to 0 | +| `think-short-prompt-counter.mjs` | UserPromptSubmit | `additionalContext` (full prompt) every 10th prompt (10,20,30,...) | +| `think-short-task.mjs` | PreToolUse `Task\|Agent` | `updatedInput.prompt` (FULL prompt body minus the `` comment line, prepended to subagent) — coexistence-safe: yields to unknown foreign Task hooks (see note below) | +| `think-short-prompt.md` | (data) | prompt text, read by the 3 scripts from their OWN dir via `import.meta.url` | + +> Scripts are pure ESM, Node built-ins only, no plugin-root / npm deps. They read +> `think-short-prompt.md` from the SAME directory they are copied into, so the 4 +> files MUST stay together. Each reads stdin, never throws, always exits 0. + +Marker files: `/brewtools-think-short/.think-short-counter` +(plain integer). Self-cleaning: SessionStart resets THIS session's marker to 0 and +prunes prior-session markers older than ~1 day; tmp dir is disposable, no project +pollution. + +> **Coexistence (PreToolUse `Task|Agent`).** On CC 2.1.195, two PreToolUse hooks +> that both match the same tool and both return `updatedInput` run IN PARALLEL +> with LAST-WINS (a non-deterministic race) — edits do NOT chain/merge; one hook +> randomly clobbers the others. `think-short-task.mjs` guards against destroying a +> payload it cannot reconstruct: it DETECTS other `Task|Agent` PreToolUse hooks +> (project + user `settings.json`, plus plugin `hooks/hooks.json` under the plugin +> cache), excluding itself and sibling brewcode-family hooks, then decides: +> - no foreign Task hook present -> FIRE: emit `thinkShortBody + original`; +> - any UNKNOWN/foreign Task hook present -> YIELD (no `updatedInput`) so a +> third-party hook whose payload we cannot reconstruct is never clobbered. + +--- + +## settings.json hook entry shape + +`` = absolute path of the hooks dir the 5 files were copied into +(`/.claude/hooks` for project, `~/.claude/hooks` expanded for global). + +```json +{ + "hooks": { + "SessionStart": [ + { "hooks": [ { "type": "command", "command": "node", "args": ["/think-short-session.mjs"] } ] } + ], + "UserPromptSubmit": [ + { "hooks": [ { "type": "command", "command": "node", "args": ["/think-short-prompt-counter.mjs"] } ] } + ], + "PreToolUse": [ + { "matcher": "Task|Agent", "hooks": [ { "type": "command", "command": "node", "args": ["/think-short-task.mjs"] } ] } + ] + } +} +``` + +Merge rule: APPEND into the existing `SessionStart` / `UserPromptSubmit` / +`PreToolUse` arrays — never overwrite. Dedupe by the think-short script path: +if an entry already references the same `think-short-*.mjs` path, skip (idempotent +re-install). Recognizable marker for all think-short entries = any hook whose +`args` contains a path ending in `think-short-session.mjs`, +`think-short-prompt-counter.mjs`, or `think-short-task.mjs`. + +--- + +## PROJECT target (`/.claude/`) + +Project paths are writable with normal tools (`Write`/`Edit`/`Bash` all fine). + +1. Ensure dir: `/.claude/hooks/`. +2. Copy all 4 asset files into `/.claude/hooks/` (preserve filenames). + - Source dir = this `assets/` dir. Derive it from THIS runbook's own path: + the skill passes `RUNBOOK` = absolute path to this `INSTALL.md`, and + `INSTALL.md` lives IN the assets dir, so `SRC="$(dirname "$RUNBOOK")"`. + (Derive the source dir from `RUNBOOK`; do not rely on any plugin env var, + which is injected as prompt text and expands to empty in Bash.) +3. Read `/.claude/settings.json` (create `{}` if absent). +4. Merge the 3 hook entries above (append + dedupe) using `` = + absolute path to `/.claude/hooks`. Use `Edit`/`Write` after computing + the merged JSON. + +EXECUTE copy (project) using the Bash tool (`RUNBOOK` = absolute path to this INSTALL.md): +``` +SRC="$(dirname "$RUNBOOK")" +DST="$PWD/.claude/hooks" +mkdir -p "$DST" && \ +cp "$SRC/think-short-session.mjs" "$SRC/think-short-prompt-counter.mjs" \ + "$SRC/think-short-task.mjs" "$SRC/think-short-prompt.md" "$DST/" && \ +echo "OK copied to $DST" || echo "FAILED" +``` +Then edit `/.claude/settings.json` to merge the 3 entries (absdir = `$DST`). + +--- + +## GLOBAL target (`~/.claude/`) + +CRITICAL: `~/.claude/*` is a HARNESS-PROTECTED path. `Write` / `Edit` / `MultiEdit` +tools are BLOCKED in ALL permission modes (incl. `bypassPermissions`, headless) — +the check runs BEFORE hooks, so a hook cannot override it. Therefore the global +install MUST be done entirely through the **Bash tool** (`cp`, `node`, `cat` +heredoc), never the file-editing tools. + +1. Copy the 4 files via `cp` (Bash). +2. Merge `settings.json` via a `node` one-liner (Bash) that reads, merges + (append + dedupe), and writes back. Bash file writes to `~/.claude/*` are + currently allowed (only the Write/Edit/MultiEdit TOOLS are blocked). + +EXECUTE (global) using the Bash tool (`RUNBOOK` = absolute path to this INSTALL.md): +``` +SRC="$(dirname "$RUNBOOK")" +DST="$HOME/.claude/hooks" +mkdir -p "$DST" && \ +cp "$SRC/think-short-session.mjs" "$SRC/think-short-prompt-counter.mjs" \ + "$SRC/think-short-task.mjs" "$SRC/think-short-prompt.md" "$DST/" && \ +echo "OK copied to $DST" || echo "FAILED" +``` + +Merge settings.json (Bash + node, idempotent append + dedupe by script path): +``` +node -e ' +const fs=require("fs"), os=require("os"), path=require("path"); +const f=path.join(os.homedir(),".claude","settings.json"); +const dir=path.join(os.homedir(),".claude","hooks"); +let s={}; try{s=JSON.parse(fs.readFileSync(f,"utf8"))||{}}catch{} +s.hooks=s.hooks||{}; +const want=[ + ["SessionStart",null,"think-short-session.mjs"], + ["UserPromptSubmit",null,"think-short-prompt-counter.mjs"], + ["PreToolUse","Task|Agent","think-short-task.mjs"], +]; +const marks=["think-short-session.mjs","think-short-prompt-counter.mjs","think-short-task.mjs"]; +const refs=e=>JSON.stringify((e&&e.hooks)||[]); +for(const [ev,matcher,script] of want){ + s.hooks[ev]=s.hooks[ev]||[]; + const has=s.hooks[ev].some(e=>marks.some(m=>refs(e).includes(m)&&refs(e).includes(script))); + if(has) continue; + const entry={hooks:[{type:"command",command:"node",args:[path.join(dir,script)]}]}; + if(matcher) entry.matcher=matcher; + s.hooks[ev].push(entry); +} +fs.writeFileSync(f,JSON.stringify(s,null,2)); +console.log("OK merged "+f); +' +``` + +> For PROJECT target the same `node -e` merge works — point `f` at +> `/.claude/settings.json` and `dir` at `/.claude/hooks`. Or use the +> `Edit` tool since project settings are not protected. + +--- + +## REMOVE (project and/or global) + +Marker = the 3 think-short script basenames. The skill AskUserQuestion's the +target if ambiguous; check BOTH `/.claude/` and `~/.claude/` when unsure. + +For each target: +1. Strip from `settings.json` every hook entry whose `args` reference any of + `think-short-session.mjs`, `think-short-prompt-counter.mjs`, + `think-short-task.mjs`. Drop now-empty event arrays. Leave all other hooks + untouched. +2. Delete the 4 copied files from the hooks dir. + +EXECUTE removal (works for both; set HOOKS_DIR + SETTINGS): +``` +# GLOBAL: HOOKS_DIR="$HOME/.claude/hooks"; SETTINGS="$HOME/.claude/settings.json" +# PROJECT: HOOKS_DIR="$PWD/.claude/hooks"; SETTINGS="$PWD/.claude/settings.json" +node -e ' +const fs=require("fs"); +const f=process.env.SETTINGS, dir=process.env.HOOKS_DIR; +const marks=["think-short-session.mjs","think-short-prompt-counter.mjs","think-short-task.mjs"]; +let s={}; try{s=JSON.parse(fs.readFileSync(f,"utf8"))||{}}catch{s=null} +if(s&&s.hooks){ + for(const ev of Object.keys(s.hooks)){ + if(!Array.isArray(s.hooks[ev])) continue; + s.hooks[ev]=s.hooks[ev].filter(e=>!marks.some(m=>JSON.stringify((e&&e.hooks)||[]).includes(m))); + if(s.hooks[ev].length===0) delete s.hooks[ev]; + } + if(s.hooks&&Object.keys(s.hooks).length===0) delete s.hooks; + fs.writeFileSync(f,JSON.stringify(s,null,2)); + console.log("OK cleaned "+f); +} +' && \ +rm -f "$HOOKS_DIR/think-short-session.mjs" \ + "$HOOKS_DIR/think-short-prompt-counter.mjs" \ + "$HOOKS_DIR/think-short-task.mjs" \ + "$HOOKS_DIR/think-short-prompt.md" && \ +echo "OK removed files from $HOOKS_DIR" || echo "removal had errors" +``` + +> Global removal: file-editing tools are blocked on `~/.claude/*`, so use the +> Bash `node`/`rm` approach above (do NOT use Edit/Write). Project removal may use +> Edit/Write freely. + +> After install or removal: `/reload-plugins` is NOT needed (these are plain +> settings.json hooks, not plugin hooks); a NEW session picks up the change. +> SessionStart hooks fire on the next `claude` start / `--resume`. diff --git a/brewtools/skills/think-short/assets/think-short-prompt-counter.mjs b/brewtools/skills/think-short/assets/think-short-prompt-counter.mjs new file mode 100644 index 0000000..42e84ee --- /dev/null +++ b/brewtools/skills/think-short/assets/think-short-prompt-counter.mjs @@ -0,0 +1,93 @@ +#!/usr/bin/env node +/** + * think-short — UserPromptSubmit hook (self-contained, no plugin-root deps). + * + * Maintains a per-session prompt counter (tmp marker keyed by session_id). + * Increments on every user prompt; re-injects the full think-short prompt + * ONLY every 10th prompt (10, 20, 30, ...). Never on the 1st prompt + * (SessionStart already injected the prompt at session open). + * + * Inject channel: hookSpecificOutput.additionalContext (UserPromptSubmit). + * Fail-open: never throws, always exits 0. On any error -> emits `{}` (no-op). + */ +import { readFile, mkdir, writeFile } from 'node:fs/promises'; +import path from 'node:path'; +import os from 'node:os'; +import { fileURLToPath } from 'node:url'; + +const HERE = path.dirname(fileURLToPath(import.meta.url)); +const PROMPT_PATH = path.join(HERE, 'think-short-prompt.md'); +const MARKER_DIR = path.join(os.tmpdir(), 'brewtools-think-short'); +const INTERVAL = 10; + +async function readStdin() { + const chunks = []; + for await (const chunk of process.stdin) chunks.push(chunk); + const raw = Buffer.concat(chunks).toString('utf8'); + if (!raw.trim()) return {}; + try { + return JSON.parse(raw); + } catch { + return {}; + } +} + +function output(obj) { + process.stdout.write(JSON.stringify(obj)); +} + +async function bumpCounter(session_id) { + // Returns the new count (>=1), or null if counting is unavailable. + if (!session_id || typeof session_id !== 'string') return null; + try { + await mkdir(MARKER_DIR, { recursive: true }); + const markerPath = path.join(MARKER_DIR, `${session_id}.think-short-counter`); + + let count = 0; + try { + const prev = await readFile(markerPath, 'utf8'); + const parsed = parseInt(prev.trim(), 10); + if (Number.isFinite(parsed) && parsed >= 0) count = parsed; + } catch { + // no marker yet -> start from 0 + } + + count += 1; + await writeFile(markerPath, String(count), 'utf8'); + return count; + } catch { + return null; + } +} + +async function main() { + try { + const input = await readStdin(); + const session_id = input.session_id; + + const count = await bumpCounter(session_id); + if (count === null || count <= 0 || count % INTERVAL !== 0) { + output({}); + return; + } + + let promptText = ''; + try { + promptText = await readFile(PROMPT_PATH, 'utf8'); + } catch { + output({}); + return; + } + + output({ + hookSpecificOutput: { + hookEventName: 'UserPromptSubmit', + additionalContext: promptText.trimEnd(), + }, + }); + } catch { + output({}); + } +} + +main(); diff --git a/brewtools/skills/think-short/assets/think-short-prompt.md b/brewtools/skills/think-short/assets/think-short-prompt.md new file mode 100644 index 0000000..02329f0 --- /dev/null +++ b/brewtools/skills/think-short/assets/think-short-prompt.md @@ -0,0 +1,8 @@ + +Be terse. Results first, no preamble/filler/sycophancy. ASCII only. +Grep before Read. Edit over Write. Parallel calls in one message. +Plan the full edit set, then execute. + +Keep code simple - do not over-engineer. Before writing anything new, +check existing code and libraries for the needed functionality. +Prefer extending or abstracting a similar class over adding a new one. diff --git a/brewtools/skills/think-short/assets/think-short-session.mjs b/brewtools/skills/think-short/assets/think-short-session.mjs new file mode 100644 index 0000000..b49898d --- /dev/null +++ b/brewtools/skills/think-short/assets/think-short-session.mjs @@ -0,0 +1,100 @@ +#!/usr/bin/env node +/** + * think-short — SessionStart hook (self-contained, no plugin-root deps). + * + * - Injects the full think-short prompt via hookSpecificOutput.additionalContext. + * - Resets the per-session prompt counter marker to 0 (so the UserPromptSubmit + * counter restarts each session). + * - Prunes stale counter markers left by prior sessions (older than ~1 day) so + * the tmp marker dir stays self-cleaning. + * + * Fail-open: never throws, always exits 0. On any error -> emits `{}` (no-op). + */ +import { readFile, mkdir, writeFile, readdir, stat, unlink } from 'node:fs/promises'; +import path from 'node:path'; +import os from 'node:os'; +import { fileURLToPath } from 'node:url'; + +const HERE = path.dirname(fileURLToPath(import.meta.url)); +const PROMPT_PATH = path.join(HERE, 'think-short-prompt.md'); +const MARKER_DIR = path.join(os.tmpdir(), 'brewtools-think-short'); +const STALE_MS = 24 * 60 * 60 * 1000; // ~1 day + +async function readStdin() { + const chunks = []; + for await (const chunk of process.stdin) chunks.push(chunk); + const raw = Buffer.concat(chunks).toString('utf8'); + if (!raw.trim()) return {}; + try { + return JSON.parse(raw); + } catch { + return {}; + } +} + +function output(obj) { + process.stdout.write(JSON.stringify(obj)); +} + +async function resetCounter(session_id) { + if (!session_id || typeof session_id !== 'string') return; + try { + await mkdir(MARKER_DIR, { recursive: true }); + const markerPath = path.join(MARKER_DIR, `${session_id}.think-short-counter`); + await writeFile(markerPath, '0', 'utf8'); + } catch { + // ignore — counter just won't reset; not fatal + } +} + +// Best-effort: delete counter markers from prior sessions older than ~1 day. +// Never throws; the active session's marker (just reset above) is fresh and so +// is never old enough to be pruned. +async function pruneStaleMarkers() { + const cutoff = Date.now() - STALE_MS; + let names; + try { + names = await readdir(MARKER_DIR); + } catch { + return; // dir absent / unreadable -> nothing to prune + } + for (const name of names) { + if (!name.endsWith('.think-short-counter')) continue; + const p = path.join(MARKER_DIR, name); + try { + const st = await stat(p); + if (st.mtimeMs < cutoff) await unlink(p); + } catch { + // ignore individual file errors + } + } +} + +async function main() { + try { + const input = await readStdin(); + const session_id = input.session_id; + + await resetCounter(session_id); + await pruneStaleMarkers(); + + let promptText = ''; + try { + promptText = await readFile(PROMPT_PATH, 'utf8'); + } catch { + output({}); + return; + } + + output({ + hookSpecificOutput: { + hookEventName: 'SessionStart', + additionalContext: promptText.trimEnd(), + }, + }); + } catch { + output({}); + } +} + +main(); diff --git a/brewtools/skills/think-short/assets/think-short-task.mjs b/brewtools/skills/think-short/assets/think-short-task.mjs new file mode 100644 index 0000000..a67520f --- /dev/null +++ b/brewtools/skills/think-short/assets/think-short-task.mjs @@ -0,0 +1,209 @@ +#!/usr/bin/env node +/** + * think-short — PreToolUse hook for Task|Agent (self-contained, no plugin-root deps). + * + * Injects the FULL think-short prompt into the spawned subagent's prompt via + * hookSpecificOutput.updatedInput.prompt (permissionDecision:"allow") — the + * documented, reliable channel to reach a SUBAGENT prompt on PreToolUse:Task. + * The injected block is the entire think-short-prompt.md MINUS its first line + * (the `` HTML-comment marker — never send a comment into a + * subagent prompt). No "lite"/truncated variant: the subagent gets the same + * full body that SessionStart / UserPromptSubmit inject. + * + * COEXISTENCE SAFETY (why this file is careful): + * Verified on CC 2.1.195 (bundle disassembly + live runs): when multiple + * PreToolUse hooks both match the same tool and both return `updatedInput`, + * Claude Code runs them IN PARALLEL and applies LAST-WINS — a + * non-deterministic race. The edits do NOT chain or merge; one hook randomly + * clobbers the others. To never destroy a payload we cannot reconstruct, this + * hook DETECTS other Task|Agent PreToolUse hooks and: + * - any UNKNOWN/foreign Task hook present -> YIELD (emit `{}`). + * - none present -> FIRE: emit `thinkShortBody + "\n\n" + original`. + * + * Fail-open: never throws, always exits 0. On any error / no prompt -> `{}`. + */ +import fs from 'node:fs'; +import path from 'node:path'; +import os from 'node:os'; +import { fileURLToPath } from 'node:url'; + +const HERE = path.dirname(fileURLToPath(import.meta.url)); +const SELF_BASENAME = path.basename(fileURLToPath(import.meta.url)); // think-short-task.mjs +const PROMPT_PATH = path.join(HERE, 'think-short-prompt.md'); +const CACHE_DIR = path.join(os.homedir(), '.claude', 'plugins', 'cache'); + +// Sibling brewcode-family plugins; their own Task hooks are known/benign, so +// think-short fires alongside them rather than yielding. +const FAMILY_PLUGINS = ['brewcode', 'brewtools', 'brewdoc']; + +async function readStdin() { + const chunks = []; + for await (const chunk of process.stdin) chunks.push(chunk); + const raw = Buffer.concat(chunks).toString('utf8'); + if (!raw.trim()) return {}; + try { + return JSON.parse(raw); + } catch { + return {}; + } +} + +function output(obj) { + process.stdout.write(JSON.stringify(obj)); +} + +// FULL prompt body minus the leading `` comment line. +function loadInjection() { + let text; + try { + text = fs.readFileSync(PROMPT_PATH, 'utf8'); + } catch { + return null; + } + const lines = text.split('\n'); + if (lines.length && /^\s*` +// ───────────────────────────────────────────────────────────────────────────── +{ + const home = join(BASE, 't3a-home'); + mkdirSync(home, { recursive: true }); + const tmp = join(BASE, 't3a-tmp'); + mkdirSync(tmp, { recursive: true }); + mkCachePlugin(home, 'brewtools', '3.19.5'); + // GIVEN: no project or user settings with foreign hooks + mkdirSync(join(home, 'proj', '.claude'), { recursive: true }); + writeFileSync(join(home, 'proj', '.claude', 'settings.json'), JSON.stringify({})); + writeFileSync(join(home, '.claude', 'settings.json'), JSON.stringify({})); + + const ORIGINAL = 'TASK_ORIGINAL'; + const stdin = JSON.stringify({ cwd: join(home, 'proj'), tool_input: { prompt: ORIGINAL } }); + const r = run(TASK_MJS, stdin, { HOME: home, TMPDIR: tmp }); + let t3aok = r.status === 0; + let detail3a = ''; + if (t3aok) { + let out; + try { out = JSON.parse(r.stdout); } catch { t3aok = false; detail3a = 'parse fail'; } + if (t3aok) { + const np = out?.hookSpecificOutput?.updatedInput?.prompt; + const firstLine = np ? np.split('\n')[0] : ''; + const hasBody = np && np.includes('Be terse'); + const noComment = np && !np.includes(''); + const hasOrig = np && np.endsWith(ORIGINAL); + if (!np) { t3aok = false; detail3a = 'no updatedInput.prompt'; } + else if (!hasBody) { t3aok = false; detail3a = `body missing "Be terse": first80="${np.slice(0,80)}"`; } + else if (!noComment) { t3aok = false; detail3a = ' leaked into output'; } + else if (!hasOrig) { t3aok = false; detail3a = `original not at end: "${np.slice(-40)}"`; } + else detail3a = `fires ok; starts="${firstLine}"`; + } + } + if (t3aok) pass('3a-task-only-family-fires', detail3a); + else fail('3a-task-only-family-fires', detail3a); +} + +// ───────────────────────────────────────────────────────────────────────────── +// Test 3b: think-short-task — foreign hook in project settings.json -> YIELDS {} +// GIVEN: project .claude/settings.json has a PreToolUse entry matching Task +// that is NOT a family hook (unknown command path) +// WHEN: run think-short-task.mjs +// THEN: output == {} +// ───────────────────────────────────────────────────────────────────────────── +{ + const home = join(BASE, 't3b-home'); + mkdirSync(home, { recursive: true }); + const tmp = join(BASE, 't3b-tmp'); + mkdirSync(tmp, { recursive: true }); + mkCachePlugin(home, 'brewtools', '3.19.5'); + mkdirSync(join(home, 'proj', '.claude'), { recursive: true }); + + // GIVEN: foreign hook that matches Task + const foreignSettings = { + hooks: { + PreToolUse: [ + { + matcher: 'Task', + hooks: [{ type: 'command', command: '/some/foreign/hook.sh' }], + }, + ], + }, + }; + writeFileSync(join(home, 'proj', '.claude', 'settings.json'), JSON.stringify(foreignSettings)); + writeFileSync(join(home, '.claude', 'settings.json'), JSON.stringify({})); + + const stdin = JSON.stringify({ cwd: join(home, 'proj'), tool_input: { prompt: 'TASK_PROMPT' } }); + const r = run(TASK_MJS, stdin, { HOME: home, TMPDIR: tmp }); + let t3bok = r.status === 0; + let detail3b = ''; + if (t3bok) { + let out; + try { out = JSON.parse(r.stdout); } catch { t3bok = false; detail3b = 'parse fail'; } + if (t3bok) { + const keys = Object.keys(out); + if (keys.length === 0) detail3b = 'output={}'; + else { t3bok = false; detail3b = `expected {} got keys=[${keys}]`; } + } + } + if (t3bok) pass('3b-task-foreign-hook-yields', detail3b); + else fail('3b-task-foreign-hook-yields', detail3b); +} + +// ───────────────────────────────────────────────────────────────────────────── +// Test 3c: think-short-task — no other Task hook at all -> FIRES +// GIVEN: HOME with no plugin cache, no settings +// WHEN: run think-short-task.mjs +// THEN: updatedInput.prompt set (not empty) +// ───────────────────────────────────────────────────────────────────────────── +{ + const home = join(BASE, 't3c-home'); + mkdirSync(home, { recursive: true }); + const tmp = join(BASE, 't3c-tmp'); + mkdirSync(tmp, { recursive: true }); + // GIVEN: no cache dirs; minimal settings + mkdirSync(join(home, '.claude'), { recursive: true }); + writeFileSync(join(home, '.claude', 'settings.json'), JSON.stringify({})); + mkdirSync(join(home, 'proj', '.claude'), { recursive: true }); + writeFileSync(join(home, 'proj', '.claude', 'settings.json'), JSON.stringify({})); + + const ORIGINAL = 'TASK_ORIGINAL_3C'; + const stdin = JSON.stringify({ cwd: join(home, 'proj'), tool_input: { prompt: ORIGINAL } }); + const r = run(TASK_MJS, stdin, { HOME: home, TMPDIR: tmp }); + let t3cok = r.status === 0; + let detail3c = ''; + if (t3cok) { + let out; + try { out = JSON.parse(r.stdout); } catch { t3cok = false; detail3c = 'parse fail'; } + if (t3cok) { + const np = out?.hookSpecificOutput?.updatedInput?.prompt; + if (!np) { t3cok = false; detail3c = 'no updatedInput.prompt'; } + else if (!np.endsWith(ORIGINAL)) { t3cok = false; detail3c = `original not at end`; } + else detail3c = `fires ok; len=${np.length}`; + } + } + if (t3cok) pass('3c-task-no-hooks-fires', detail3c); + else fail('3c-task-no-hooks-fires', detail3c); +} + +// ───────────────────────────────────────────────────────────────────────────── +// Test 4: Fail-open — various bad inputs -> exit 0 + {} +// ───────────────────────────────────────────────────────────────────────────── +{ + const home = join(BASE, 't4-home'); + const tmp = join(BASE, 't4-tmp'); + mkdirSync(home, { recursive: true }); + mkdirSync(tmp, { recursive: true }); + const env = { HOME: home, TMPDIR: tmp }; + + const cases = [ + { name: 'empty-stdin', script: COUNTER_MJS, stdin: '' }, + { name: 'malformed-json', script: COUNTER_MJS, stdin: '{not json' }, + { name: 'missing-session_id', script: COUNTER_MJS, stdin: '{}' }, + { name: 'missing-tool_input', script: TASK_MJS, stdin: JSON.stringify({ cwd: join(home, 'proj') }) }, + { name: 'missing-prompt-field', script: TASK_MJS, stdin: JSON.stringify({ tool_input: {} }) }, + { name: 'session-empty-stdin', script: SESSION_MJS, stdin: '' }, + { name: 'session-malformed', script: SESSION_MJS, stdin: '{bad' }, + ]; + + for (const c of cases) { + // SessionStart always emits additionalContext (even on empty stdin, best-effort). + // Counter/Task should emit {}. + const r = run(c.script, c.stdin, env); + let ok = r.status === 0; + let detail = ''; + if (ok) { + let out; + try { out = JSON.parse(r.stdout); } catch { ok = false; detail = 'parse fail'; } + if (ok) { + // For session on bad input: file read may fail -> {} is acceptable too. + // For counter/task: strictly {}. + const isEmpty = Object.keys(out).length === 0; + const isSession = c.script === SESSION_MJS; + if (!isSession && !isEmpty) { + ok = false; detail = `expected {} got keys=[${Object.keys(out)}]`; + } else { + detail = isEmpty ? 'output={}' : 'output=sessionInject(ok on fail-open)'; + } + } + } + if (ok) pass(`4-fail-open/${c.name}`, detail); + else fail(`4-fail-open/${c.name}`, detail || `exit=${r.status}`); + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// Cleanup +// ───────────────────────────────────────────────────────────────────────────── +try { rmSync(BASE, { recursive: true, force: true }); } catch { /* ignore */ } + +// ───────────────────────────────────────────────────────────────────────────── +// Report +// ───────────────────────────────────────────────────────────────────────────── +console.log('\n=== think-short E2E TEST REPORT ==='); +for (const line of results) console.log(line); +console.log(`\nTOTAL: ${passed + failed} | PASS: ${passed} | FAIL: ${failed}`); +process.exit(failed > 0 ? 1 : 0); diff --git a/brewui/.claude-plugin/plugin.json b/brewui/.claude-plugin/plugin.json index 8e7e3c4..ecea5b6 100644 --- a/brewui/.claude-plugin/plugin.json +++ b/brewui/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "brewui", - "version": "3.19.5", + "version": "4.0.0", "description": "Brewui -- placeholder for future UI/visual/creative tools", "author": { "name": "Maksim Kochetkov", diff --git a/web/docs/src/content/docs/brewcode/agents.mdx b/web/docs/src/content/docs/brewcode/agents.mdx index dd33bf6..a9e49cb 100644 --- a/web/docs/src/content/docs/brewcode/agents.mdx +++ b/web/docs/src/content/docs/brewcode/agents.mdx @@ -9,7 +9,7 @@ import { Card, CardGrid, Callout } from '../../../components/mdx'; # Agents Agents (brewers) are specialized roles defined in markdown files with frontmatter metadata. -Each agent has its own model, toolset, and system prompt. Brewcode includes 12 agents, +Each agent has its own model, toolset, and system prompt. Brewcode includes 10 agents (8 public + 2 internal helpers), from developer to task coordination. ## Summary table diff --git a/web/docs/src/content/docs/brewcode/agents/bash-expert.mdx b/web/docs/src/content/docs/brewcode/agents/bash-expert.mdx index 795b0df..b61fd16 100644 --- a/web/docs/src/content/docs/brewcode/agents/bash-expert.mdx +++ b/web/docs/src/content/docs/brewcode/agents/bash-expert.mdx @@ -151,7 +151,7 @@ Always derive prefix via `$(brew --prefix)` — never hardcode. |----------|-------------| | `$CLAUDE_PLUGIN_ROOT` | Hooks only | | `${CLAUDE_SKILL_DIR}` | Skills (string substitution) | -| `$BC_PLUGIN_ROOT` | Agents (injected by `pre-task.mjs`) | +| `${CLAUDE_PLUGIN_ROOT}` | Agents (native substitution in agent .md at Task spawn) | ### Anti-patterns diff --git a/web/docs/src/content/docs/brewcode/agents/skill-creator.mdx b/web/docs/src/content/docs/brewcode/agents/skill-creator.mdx index ddbaf25..087366b 100644 --- a/web/docs/src/content/docs/brewcode/agents/skill-creator.mdx +++ b/web/docs/src/content/docs/brewcode/agents/skill-creator.mdx @@ -121,7 +121,6 @@ skill-name/ | **Agents-as-References** | Coordinator with multi-step workflow — pass file path to subagent, subagent reads itself. 0 tokens in coordinator context | | **Context Fork** | Standalone task, no history needed, <4 phases — `context: fork` + isolated subagent | | **Executable Bash** | `**EXECUTE** using Bash tool:` keyword + `&& echo "✅" \|\| echo "❌"` + `> STOP if ❌` | -| **Mode Switcher** | "toggle", "persistent behavior", "from now on" → state in `$BC_PLUGIN_DATA/modes.json`, hooks inject on every event | | **Pushy Description** | LLM-invocable skills — action verb + `Triggers: "exact user phrases"`. Raises rate 20% → 50-72% | ### Description format diff --git a/web/docs/src/content/docs/brewcode/hooks.mdx b/web/docs/src/content/docs/brewcode/hooks.mdx index e4227dc..a31af90 100644 --- a/web/docs/src/content/docs/brewcode/hooks.mdx +++ b/web/docs/src/content/docs/brewcode/hooks.mdx @@ -1,6 +1,6 @@ --- title: "Hooks" -description: "All 9 Brewcode hooks: events, channels, logic" +description: "Both Brewcode hooks: events, channels, logic" order: 13 --- @@ -8,23 +8,15 @@ import { Card, CardGrid, Callout, Badge } from '../../../components/mdx'; # Hooks -Hooks (processes) are Node.js scripts attached to Claude Code lifecycle events. -They manage context, inject knowledge into agents, block exit when a task is still active, -and ensure progress transfer between sessions. Brewcode registers 9 hooks in `hooks.json`. +Hooks are Node.js scripts attached to Claude Code lifecycle events. +They inject context and manage session state. Brewcode registers 2 hooks in `hooks.json`. ## Summary table | # | Hook | Event | Matcher | Channel | Timeout | Purpose | |---|------|-------|---------|---------|---------|---------| -| 1 | forced-eval | UserPromptSubmit | -- | additionalContext | 1s | Skill activation (84%) | -| 2 | session-start | SessionStart | -- | additionalContext | 3s | Session initialization, LATEST.md | -| 3 | grepai-session | SessionStart | -- | systemMessage | 5s | Auto-start grepai watch | -| 4 | pre-task | PreToolUse | Task\|Agent | additionalContext, updatedInput | 5s | Knowledge injection into agents | -| 5 | grepai-reminder | PreToolUse | Glob\|Grep | additionalContext | 1s | grepai_search reminder | -| 6 | post-task | PostToolUse | Task\|Agent | additionalContext | 5s | Session binding, 2-step protocol | -| 7 | pre-compact | PreCompact | -- | -- | 60s | Compaction, handoff | -| 8 | stop | Stop | -- | decision | 5s | Exit blocking, lock cleanup | -| 9 | permission-guard | PermissionRequest | Edit\|Write\|MultiEdit\|Bash | hookSpecificOutput | 1s | Auto-allow safe .claude/ writes | +| 1 | forced-eval | UserPromptSubmit | -- | additionalContext | 1s | Skill activation reminder | +| 2 | session-start | SessionStart | -- | additionalContext | 3s | Session init, permission_mode tag | ## Execution flow @@ -33,26 +25,18 @@ UserPromptSubmit └── forced-eval.mjs [SKILL?] Check available skills SessionStart - ├── session-start.mjs Session ID, LATEST.md symlink, handoff - └── grepai-session.mjs Auto-start grepai watch + └── session-start.mjs Version check, plan-symlink, permission_mode tag +``` -PreToolUse:Task - └── pre-task.mjs grepai + KNOWLEDGE + phase context -> agent prompt +## Hook files -PreToolUse:Glob|Grep - └── grepai-reminder.mjs "USE grepai_search FIRST" - -PermissionRequest:Edit|Write|MultiEdit|Bash - └── permission-guard.sh Auto-allow safe .claude/ and /tmp paths - -PostToolUse:Task - └── post-task.mjs Session bind, coordinator reminder - -PreCompact - └── pre-compact.mjs Compact KNOWLEDGE, write handoff, status update - -Stop - └── stop.mjs Block if active task, cleanup lock +``` +brewcode/hooks/ + forced-eval.mjs UserPromptSubmit handler + session-start.mjs SessionStart handler + hooks.json Hook registry (event bindings) + lib/ + utils.mjs Shared I/O, configuration, logging ``` ## I/O protocol @@ -60,13 +44,12 @@ Stop All hooks follow a unified protocol: 1. Read JSON from stdin (via `readStdin()`) -2. Receive fields: `session_id`, `cwd`, `source` (SessionStart), `tool_input` (PreToolUse/PostToolUse), `permission_mode` (all events) +2. Receive fields: `session_id`, `cwd`, `source` (SessionStart), `permission_mode` (all events) 3. Output JSON to stdout (via `output()`) -4. Write logs to stderr and to the file `.claude/tasks/logs/brewcode.log` +4. Write logs to stderr **Shared utilities:** -- `hooks/lib/utils.mjs` -- I/O, lock files, configuration, logging, task parsing -- `hooks/lib/knowledge.mjs` -- KNOWLEDGE.jsonl read/write, compaction, handoff +- `hooks/lib/utils.mjs` -- I/O, configuration, logging --- @@ -99,7 +82,7 @@ and adds a reminder to check available skills. -Initializes the session, logs the session ID, manages Plan Mode symlinks, and reports the active `permission_mode` in the system message for audit. +Initializes the session, checks for brewcode/Claude updates, manages Plan Mode symlinks, and reports the active `permission_mode` in the system message for audit. | Parameter | Value | |-----------|-------| @@ -113,249 +96,26 @@ The hook reads `permission_mode` from the hook payload and appends it to `system | Source | Behavior | |--------|----------| -| `init` | Log session_id | -| `resume` | Log session_id | +| `init` | Log session_id, append permission_mode tag | +| `resume` | Log session_id, append permission_mode tag | | `clear` | Create symlink LATEST.md -> newest plan | -| `compact` + active task | Handoff instructions in additionalContext | -| any + active task lock | Set `hookSpecificOutput.sessionTitle` to active task name (CC 2.1.152+; ignored by older versions) | **LATEST.md symlink:** -1. Checks `~/.claude/plans/` for `.md` files +1. Checks `~/.claude/plans/` for `.md` files 2. Picks the newest one (by mtime) -3. If the file is less than 60 seconds old -- creates `.claude/plans/LATEST.md` -> `~/.claude/plans/.md` -4. Used by the `/brewcode:plan` skill for Plan Mode +3. If the file is less than 60 seconds old -- creates `.claude/plans/LATEST.md` -> `~/.claude/plans/.md` --- -### 3. grepai-session.mjs +## grepai hooks - - -Automatically starts grepai watch when entering a project with a configured `.grepai/`. - -| Parameter | Value | -|-----------|-------| -| Event | SessionStart | -| Channel | systemMessage | -| Timeout | 5000 ms | - -**Logic:** -- If `.grepai/` does not exist -- skips silently -- If `.grepai/` exists -- checks ollama, index, watch process, MCP -- If watch is not running -- starts it automatically -- Reports status via `systemMessage` - - - This hook never blocks session start. All errors are handled as informational. - Platform: macOS/Linux only (Windows not supported due to missing pgrep). + + The grepai hooks are not shipped as always-on brewcode hooks. + They are installed per-project by the /brewcode:grepai self-install skill, which copies hook scripts from + skills/grepai/assets/ into .claude/grepai/hooks/ and merges the entries + into .claude/settings.json. ---- - -### 4. pre-task.mjs - - - -Injects context into the subagent prompt before every Task tool call. - -| Parameter | Value | -|-----------|-------| -| Event | PreToolUse | -| Matcher | Task | -| Channel | additionalContext, updatedInput | -| Timeout | 5000 ms | - -**What it injects:** - -| Component | Condition | Channel | -|-----------|-----------|---------| -| grepai reminder | `.grepai/` exists | additionalContext | -| ## K (knowledge) | brewcode lock active, not a system agent | updatedInput.prompt | -| v3 phase context | `phases/` exists | updatedInput.prompt | -| BC_PLUGIN_ROOT | Always | updatedInput.prompt | - -**Knowledge compression:** KNOWLEDGE.jsonl is compressed to `maxTokens` (default 500 tokens) -via `compressKnowledge()` -- priority ❌ > ✅ > ℹ️. - -**Plan mode:** when `permission_mode === 'plan'` the `## K` (KNOWLEDGE) block is skipped entirely -- plan-mode sessions are read-only explorers and do not need runtime knowledge. - -**System agents** (Explore, Plan, general-purpose) do not receive the `## K` injection. - -**Output bounding:** `additionalContext` is capped at ~9000 chars (10K disk-spill safety, CC 2.1.174+). - ---- - -### 5. grepai-reminder.mjs - - - -Reminds to use `grepai_search` instead of direct Glob/Grep. - -| Parameter | Value | -|-----------|-------| -| Event | PreToolUse | -| Matcher | Glob\|Grep | -| Channel | additionalContext | -| Timeout | 1000 ms | - -**Throttling:** The reminder is shown at most once per 60 seconds (via timestamp file `.grepai/.reminder-ts`). - -**Condition:** Only fires if `.grepai/` and `.grepai/index.gob` exist. - ---- - -### 6. post-task.mjs - - - -Handles the Task tool result: binds the session and reminds about the 2-step protocol. - -| Parameter | Value | -|-----------|-------| -| Event | PostToolUse | -| Matcher | Task | -| Channel | additionalContext | -| Timeout | 5000 ms | - -**Logic:** -- If bc-coordinator finished -- binds session_id to the lock file -- If a worker agent finished ([developer](/brewcode/agents/developer/), [tester](/brewcode/agents/tester/), etc.) -- reminds: "WRITE report -> CALL bc-coordinator" -- System agents -- skipped - ---- - -### 7. pre-compact.mjs - - - -Fires before Claude Code's automatic context compaction. -Saves progress and prepares data for continuation after compact. - -| Parameter | Value | -|-----------|-------| -| Event | PreCompact | -| Channel | -- | -| Timeout | 60000 ms (1 minute) | - -**Actions:** -1. Lock file check (brewcode active + belongs to this session) -2. KNOWLEDGE.jsonl compaction (deduplication, trimming) -3. Handoff entry written to KNOWLEDGE.jsonl -4. Task status updated -> `handoff` - - - Claude Code auto-compact compresses context within the same session. - The session_id stays identical before and after compact. The lock file is not released. - Status handoff means "re-read TASK.md", not "new session". - - ---- - -### 8. stop.mjs - - - -Controls session exit: blocks when a task is active, cleans up the lock when finished. - -| Parameter | Value | -|-----------|-------| -| Event | Stop | -| Channel | decision | -| Timeout | 5000 ms | - -**Terminal statuses:** `finished`, `cancelled`, `failed`, `error`. - -**Logic:** - -| State | Action | -|-------|--------| -| No lock file | Allow exit | -| Lock older than 24 hours | Delete lock, allow exit | -| Task in terminal status | Delete lock, allow exit | -| Task is active | **Block exit** | - - - If a task is active (status not in the terminal set), the hook blocks exit - from Claude Code. To finish a task, use [/brewcode:start](/brewcode/skills/start/) for finalization - or set the task status to finished/failed/cancelled. - - -**Recursion protection:** If `input.stop_hook_active === true`, the hook is skipped -to prevent an infinite loop. - -**additionalContext (CC 2.1.163+):** Stop and SubagentStop events support -`hookSpecificOutput.additionalContext`. `stop.mjs` uses this channel to surface the -blocking reason in the Claude Code UI when exit is prevented. - ---- - -### 9. permission-guard.sh - - - -Auto-allows write operations to safe `.claude/` subdirectories and temp paths, -eliminating manual permission prompts during task execution. Written in bash for minimal overhead. - -| Parameter | Value | -|-----------|-------| -| Event | PermissionRequest | -| Matcher | Edit\|Write\|MultiEdit\|Bash | -| Channel | hookSpecificOutput (decision: allow) | -| Timeout | 1000 ms | - -**Allowed paths for Edit/Write/MultiEdit:** - -| Path pattern | Example | -|--------------|---------| -| `.claude/tasks/*` | `.claude/tasks/20260301_auth_task/PLAN.md` | -| `.claude/tmp/*` | `.claude/tmp/scratch.md` | -| `.claude/reports/*` | `.claude/reports/review.md` | -| `.claude/rules/*` | `.claude/rules/best-practice.md` | -| `.claude/skills/*` | `.claude/skills/custom/SKILL.md` | -| `.claude/scripts/*` | `.claude/scripts/build.sh` | -| `.claude/agents/*` | `.claude/agents/reviewer.md` | -| `.claude/hooks/*` | `.claude/hooks/hooks.json` | -| `.claude/private/*` | `.claude/private/notes.md` | -| `.claude/convention/*` | `.claude/convention/patterns.md` | -| `.claude/plans/*` | `.claude/plans/LATEST.md` | -| `.claude/settings.json` | Project settings | -| `.claude/TASK.md`, `.claude/CLAUDE.md` | Quick-ref files | -| `/tmp/*`, `/private/tmp/*` | System temp directories | - -**Bash tool handling:** - -The hook applies additional safety checks for Bash commands: -- **Network commands blocked:** `curl`, `wget`, `ssh`, `scp`, `rsync`, `nc`, `ftp`, `sftp` -- **Dangerous redirections blocked:** writes to `/dev/`, `/etc/`, `eval`, `exec`, `source` -- **`rm` restricted:** only allowed within `.claude/tasks/`, `.claude/tmp/`, and `/tmp/` -- **Path extraction:** all `.claude/` and temp path tokens are verified against the allow-list - - - The hook explicitly skips the global ~/.claude/ directory. - Only project-level .claude/ paths receive auto-allow. - Writes to ~/.claude/CLAUDE.md or ~/.claude/rules/ still require manual permission. - - -**Decision logic:** - -| State | Action | -|-------|--------| -| Path in allowed list | `allow` -- bypass permission prompt | -| Path outside allowed list | `{}` -- fall through to default prompt | -| No file_path (non-matching tool) | `{}` -- fall through | - -## Configuration - -Hooks read settings from `.claude/tasks/cfg/brewcode.config.json`: - -| Parameter | Default value | Description | -|-----------|---------------|-------------| -| `knowledge.maxEntries` | 100 | Maximum entries in KNOWLEDGE.jsonl | -| `knowledge.maxTokens` | 500 | Maximum tokens in the ## K block for agents | -| `logging.level` | `info` | Logging level (error/warn/info/debug/trace) | -| `agents.system` | (list) | System agents excluded from knowledge injection | -| `autoSync.intervalDays` | 7 | Auto-sync interval | - Download, changelog, and installation instructions. diff --git a/web/docs/src/content/docs/brewcode/overview.mdx b/web/docs/src/content/docs/brewcode/overview.mdx index c62247f..da6e579 100644 --- a/web/docs/src/content/docs/brewcode/overview.mdx +++ b/web/docs/src/content/docs/brewcode/overview.mdx @@ -25,7 +25,7 @@ what to brew, agents (brewers) do the work, and hooks (processes) manage the lif Automatic knowledge transfer between sessions via KNOWLEDGE.jsonl and the handoff mechanism. Tasks continue after compaction without losing progress. - + Full cycle: from project analysis (/brewcode:setup) to task execution (/brewcode:start) and code review (/brewcode:standards-review). @@ -33,9 +33,9 @@ what to brew, agents (brewers) do the work, and hooks (processes) manage the lif Specialized agents: [developer](/brewcode/agents/developer/), [tester](/brewcode/agents/tester/), [reviewer](/brewcode/agents/reviewer/), [architect](/brewcode/agents/architect/), [skill-creator](/brewcode/agents/skill-creator/), [agent-creator](/brewcode/agents/agent-creator/), and coordinators. - - Lifecycle hooks for context management: knowledge injection, grepai integration, - exit blocking when a task is still active. + + Prompt-time skill-activation reminder and session-start version-check. + grepai hooks self-install per project on demand. Integration with grepai -- AI-powered code search via Ollama + bge-m3. @@ -70,29 +70,15 @@ all context is managed through built-in Claude Code events. │ v v │ │ Hooks (processes) Templates + Knowledge │ │ ┌──────────────┐ ┌──────────────────┐ │ - │ │ session-start│ │ PLAN.md.template │ │ - │ │ pre-task │ <──────> │ KNOWLEDGE.jsonl │ │ - │ │ pre-compact │ │ SPEC.md.template │ │ - │ │ stop │ │ artifacts/ │ │ + │ │ session-start│ │ SPEC.md.template │ │ + │ │ forced-eval │ <──────> │ artifacts/ │ │ + │ │ │ │ │ │ + │ │ │ │ │ │ │ └──────────────┘ └──────────────────┘ │ │ │ └──────────────────────────────────────────────────────────┘ ``` -### Task execution flow - -``` -PLAN.md --> phases (phases/) --> agents execute --> hooks manage - │ │ │ - │ Phase Registry │ Task API │ SessionStart - │ (phase table) │ (create/update) │ PreToolUse - │ │ │ PostToolUse - v v │ PreCompact -artifacts/{P}-{N}{T}/ KNOWLEDGE.jsonl │ Stop -{AGENT}_output.md (knowledge accumulation) v - handoff (auto) -``` - ## Plugin structure ``` @@ -100,19 +86,12 @@ brewcode/ ├── .claude-plugin/ │ └── plugin.json # Plugin manifest ├── hooks/ -│ ├── hooks.json # Binding 9 hooks to events -│ ├── session-start.mjs # Session initialization -│ ├── grepai-session.mjs # Auto-start grepai watch -│ ├── pre-task.mjs # Knowledge injection into agents -│ ├── grepai-reminder.mjs # grepai reminder -│ ├── post-task.mjs # Session binding, 2-step protocol -│ ├── pre-compact.mjs # Knowledge compaction, handoff -│ ├── stop.mjs # Exit blocking -│ ├── forced-eval.mjs # Skill activation (84%) +│ ├── hooks.json # 2 hooks (SessionStart, UserPromptSubmit) +│ ├── session-start.mjs # Version-check, plan-symlink, permission tag +│ ├── forced-eval.mjs # Skill activation reminder (84%) │ └── lib/ -│ ├── utils.mjs # I/O, lock files, configuration -│ └── knowledge.mjs # KNOWLEDGE.jsonl operations -├── agents/ # 12 agents +│ └── utils.mjs # I/O, version cache, configuration +├── agents/ # 10 agents │ ├── developer.md # Feature implementation (opus) │ ├── tester.md # Testing (sonnet) │ ├── reviewer.md # Code review (opus) @@ -125,7 +104,7 @@ brewcode/ │ ├── bc-knowledge-manager.md # Knowledge manager (haiku) │ ├── bc-grepai-configurator.md # grepai configurator (opus) │ └── bc-rules-organizer.md # Rules organizer (sonnet) -├── skills/ # 13 skills +├── skills/ # 9 skills │ ├── setup/ # Project analysis, templates │ ├── spec/ # Specification creation │ ├── plan/ # Plan creation @@ -142,45 +121,12 @@ brewcode/ └── templates/ # Rule templates ``` -## Target project structure - -After running [`/brewcode:setup`](/brewcode/skills/setup/) and [`/brewcode:start`](/brewcode/skills/start/), the following appears in your project: - -``` -{PROJECT}/ -└── .claude/ - └── tasks/ - ├── cfg/ - │ ├── brewcode.config.json # Plugin configuration - │ └── brewcode.state.json # Execution state - ├── templates/ # Adapted templates - │ ├── PLAN.md.template - │ ├── SPEC.md.template - │ └── phase*.template - ├── logs/ - │ └── brewcode.log # Hook log - ├── sessions/ - │ └── {session_id}.info # Session information - └── {TS}_{NAME}_task/ # Task directory - ├── PLAN.md # Execution plan - ├── SPEC.md # Specification - ├── KNOWLEDGE.jsonl # Accumulated knowledge - ├── phases/ # Phase files - │ ├── 1-create-entity.md - │ ├── 1V-verify-entity.md - │ └── FR-final-review.md - ├── artifacts/ # Agent reports - │ ├── FINAL.md - │ └── {P}-{N}{T}/ - ├── backup/ # Backups - └── .lock # Session lock file -``` ## Components in detail - 13 skills (recipes) cover the full task lifecycle. + 9 skills (recipes) cover the full task lifecycle. See [Skills](/brewcode/skills/) for details. | Group | Skills | Purpose | @@ -206,58 +152,42 @@ After running [`/brewcode:setup`](/brewcode/skills/setup/) and [`/brewcode:start + dynamic project agents created by [`/brewcode:teams`](/brewcode/skills/teams/) - 9 hooks (processes) manage the lifecycle through Claude Code events. + 2 hooks manage prompt-time injection and session start. See the [Hooks](/brewcode/hooks/) section for details. - | Event | Hooks | Purpose | - |-------|-------|---------| - | UserPromptSubmit | forced-eval | Skill activation | - | SessionStart | session-start, grepai-session | Initialization | - | PreToolUse | pre-task, grepai-reminder | Context injection | - | PostToolUse | post-task | Session binding | - | PreCompact | pre-compact | Knowledge handoff | - | Stop | stop | Exit blocking | + | Event | Hook | Purpose | + |-------|------|---------| + | SessionStart | session-start | Initialization, version-check | + | UserPromptSubmit | forced-eval | Skill activation reminder | -## Recommended launch order +## Quick start -
  • -
    - Project setup -

    Install prerequisites (Phase 0), analyze the project and generate adapted templates.

    -
    -
  • Specification -

    Parallel codebase research, SPEC.md creation.

    +

    Parallel codebase research and user refinement loop. Generates SPEC.md scoped to the project.

  • - Plan -

    Phase generation, quorum review, requirements tracing.

    -
    -
  • -
  • -
    - Execution -

    Launch the task with infinite context and automatic handoff.

    + Semantic search (optional) +

    Configure Ollama-backed semantic search for the project. Run once per project.

  • Team Creation (optional) -

    Create a project-specific agent team with trace system. Agents auto-integrate with spec/plan/start.

    +

    Create a project-specific agent team with performance tracking.

  • - Check [Skills](/brewcode/skills/) for detailed descriptions of all 13 skills, - or go to [Workflow](/brewcode/workflow/) for a deep dive into the full task execution cycle. + Check [Skills](/brewcode/skills/) for detailed descriptions of all available skills, + or explore [Agents](/brewcode/agents/) for the full list of specialized agents. diff --git a/web/docs/src/content/docs/brewcode/skills.mdx b/web/docs/src/content/docs/brewcode/skills.mdx index 79ce61e..dae47b0 100644 --- a/web/docs/src/content/docs/brewcode/skills.mdx +++ b/web/docs/src/content/docs/brewcode/skills.mdx @@ -1,6 +1,6 @@ --- title: "Skills" -description: "All 13 Brewcode skills + 1 dynamic per-project review skill" +description: "All 9 Brewcode skills + 1 dynamic per-project review skill" order: 11 --- @@ -9,86 +9,64 @@ import { Card, CardGrid, Callout, Steps } from '../../../components/mdx'; # Skills Skills (recipes) are slash commands that define *what* to do. Each skill is described in a `SKILL.md` file -with frontmatter metadata and instructions for agents. Brewcode includes 13 skills covering +with frontmatter metadata and instructions for agents. Brewcode includes 9 skills covering the full task lifecycle -- from project analysis to E2E testing. -On top of those, [`/brewcode:review`](/brewcode/skills/review/) is a **special dynamic skill** — it is not shipped with the plugin, it is **generated into every target project** by [`/brewcode:setup`](/brewcode/skills/setup/), tailored to the project's tech stack and agents. See the [review skill page](/brewcode/skills/review/) for details. +On top of those, [`/brewcode:review`](/brewcode/skills/review/) is a **special dynamic skill** — it is not shipped with the plugin, it is **generated into every target project** by [`/brewcode:superreview`](/brewcode/skills/superreview/), tailored to the project's tech stack and agents. See the [review skill page](/brewcode/skills/review/) for details. ## Summary table | # | Skill | Command | Model | Purpose | |---|-------|---------|-------|---------| -| 1 | [setup](/brewcode/skills/setup/) | [`/brewcode:setup`](/brewcode/skills/setup/) | opus | Project analysis, prerequisites, template generation | -| 2 | [spec](/brewcode/skills/spec/) | [`/brewcode:spec`](/brewcode/skills/spec/) | opus | Specification creation through research | -| 3 | [plan](/brewcode/skills/plan/) | [`/brewcode:plan`](/brewcode/skills/plan/) | opus | Plan creation from SPEC or Plan Mode | -| 4 | [start](/brewcode/skills/start/) | [`/brewcode:start`](/brewcode/skills/start/) | opus | Task execution with infinite context | -| 5 | [teams](/brewcode/skills/teams/) | [`/brewcode:teams`](/brewcode/skills/teams/) | opus | Dynamic agent teams with tracking | -| 6 | [convention](/brewcode/skills/convention/) | [`/brewcode:convention`](/brewcode/skills/convention/) | opus | Convention analysis and reference classes | -| 7 | [rules](/brewcode/skills/rules/) | [`/brewcode:rules`](/brewcode/skills/rules/) | sonnet | Knowledge-to-rules synchronization | -| 8 | [grepai](/brewcode/skills/grepai/) | [`/brewcode:grepai`](/brewcode/skills/grepai/) | sonnet | Semantic search management | -| 9 | [teardown](/brewcode/skills/teardown/) | [`/brewcode:teardown`](/brewcode/skills/teardown/) | haiku | Plugin file removal | -| 10 | [standards-review](/brewcode/skills/standards-review/) | [`/brewcode:standards-review`](/brewcode/skills/standards-review/) | opus | Standards compliance review | -| 11 | [skills](/brewcode/skills/skills/) | [`/brewcode:skills`](/brewcode/skills/skills/) | opus | Skill management | -| 12 | [agents](/brewcode/skills/agents/) | [`/brewcode:agents`](/brewcode/skills/agents/) | opus | Agent creation and improvement | -| 13 | [e2e](/brewcode/skills/e2e/) | [`/brewcode:e2e`](/brewcode/skills/e2e/) | opus | E2E testing orchestration | -| ★ | [review (dynamic)](/brewcode/skills/review/) | [`/brewcode:review`](/brewcode/skills/review/) | opus | **Per-project** multi-agent review with quorum — generated by `/brewcode:setup` | +| 1 | [agents](/brewcode/skills/agents/) | [`/brewcode:agents`](/brewcode/skills/agents/) | opus | Agent creation and improvement | +| 2 | [convention](/brewcode/skills/convention/) | [`/brewcode:convention`](/brewcode/skills/convention/) | opus | Convention analysis and reference classes | +| 3 | [e2e](/brewcode/skills/e2e/) | [`/brewcode:e2e`](/brewcode/skills/e2e/) | opus | E2E testing orchestration | +| 4 | [grepai](/brewcode/skills/grepai/) | [`/brewcode:grepai`](/brewcode/skills/grepai/) | sonnet | Semantic search management | +| 5 | [rules](/brewcode/skills/rules/) | [`/brewcode:rules`](/brewcode/skills/rules/) | sonnet | Knowledge-to-rules synchronization | +| 6 | [skills](/brewcode/skills/skills/) | [`/brewcode:skills`](/brewcode/skills/skills/) | opus | Skill management | +| 7 | [spec](/brewcode/skills/spec/) | [`/brewcode:spec`](/brewcode/skills/spec/) | opus | Specification creation through research | +| 8 | [superreview](/brewcode/skills/superreview/) | [`/brewcode:superreview`](/brewcode/skills/superreview/) | opus | Generate a project-tailored deep-review skill (review + standards merged) | +| 9 | [teams](/brewcode/skills/teams/) | [`/brewcode:teams`](/brewcode/skills/teams/) | opus | Dynamic agent teams with tracking | +| ★ | [review (dynamic)](/brewcode/skills/review/) | [`/brewcode:review`](/brewcode/skills/review/) | opus | **Per-project** multi-agent review with quorum — generated by `/brewcode:superreview` | - - Project analysis, template generation - - - Specification creation through research - - - Plan creation from SPEC or Plan Mode - - - Task execution with infinite context - - - Dynamic agent teams with self-selection and tracking + + Agent creation and improvement Convention analysis and reference classes - - Knowledge-to-rules synchronization + + E2E testing: scenarios, autotests, quorum review Semantic search management - - Plugin file removal - - - Standards compliance review + + Knowledge-to-rules synchronization Skill management - - Agent creation and improvement + + Specification creation through research - - E2E testing: scenarios, autotests, quorum review + + Generate a project-tailored deep-review skill (review + standards merged) + + + Dynamic agent teams with self-selection and tracking - Per-project multi-agent review with quorum — generated by /brewcode:setup + Per-project multi-agent review with quorum — generated by /brewcode:superreview ## Lifecycle -The recommended skill execution order for a full task cycle: +The recommended skill execution order for a standard project cycle: -
  • -
    - Setup -

    Analyze project, generate templates, check prerequisites. setup

    -
    -
  • Spec @@ -97,14 +75,8 @@ The recommended skill execution order for a full task cycle:
  • - Plan -

    Create execution plan from SPEC with phases and dependencies. plan

    -
    -
  • -
  • -
    - Start -

    Execute task with infinite context -- automatic session handoff at context limits. start

    + Superreview +

    Generate a per-project deep-review skill tailored to your tech stack and agents. superreview

  • @@ -115,8 +87,8 @@ The recommended skill execution order for a full task cycle:
  • - Teardown -

    Clean up plugin files when task is complete. teardown

    + Teams (optional) +

    Create 5-20 project-specific agents with self-selection and performance tracking. teams

  • @@ -129,28 +101,27 @@ The recommended skill execution order for a full task cycle: ## Skill dependencies ``` -setup --> spec --> plan --> start --> rules - | | | | - | +-- convention | +-- teardown - | | | - | +-- grepai +-- teams +spec --> superreview --> review (dynamic) | - +-- (Phase 0: prerequisites) + +-- grepai (optional) + +-- convention (optional) + +-- rules + +-- teams (optional) ``` /brewcode:teams creates 5-20 project-specific agents with self-selection protocol, - performance tracking, and automatic tuning. Run after /brewcode:setup to build + performance tracking, and automatic tuning. Run /brewcode:teams to build a team adapted to your project's domains and architecture. ## Independent Skills -These skills work standalone -- no prior setup required: +These skills work standalone -- no prerequisite steps required: - - Standards compliance review + + Generate a project-tailored deep-review skill (review + standards merged) Skill management: list, create, improve @@ -165,18 +136,10 @@ These skills work standalone -- no prior setup required: Skills [text-optimize](/brewtools/skills/text-optimize/), [text-human](/brewtools/skills/text-human/), [secrets-scan](/brewtools/skills/secrets-scan/), - [ssh](/brewtools/skills/ssh/), [deploy](/brewtools/skills/deploy/), and [debate](/brewtools/skills/debate/) have been + [ssh](/brewtools/skills/ssh/) and [deploy](/brewtools/skills/deploy/) have been moved to the Brewtools plugin. - - The /brewcode:skills create command can generate Mode Switcher skills — - a special skill type that toggles persistent behavioral modes for the entire session. - Mode instructions are injected into every prompt via hooks and survive auto-compaction. - Keywords like "mode", "toggle", or "persistent" in the create prompt trigger - the Mode Switcher workflow automatically. - - Download, changelog, and installation instructions. diff --git a/web/docs/src/content/docs/brewcode/skills/agents.mdx b/web/docs/src/content/docs/brewcode/skills/agents.mdx index 76a664a..441b63e 100644 --- a/web/docs/src/content/docs/brewcode/skills/agents.mdx +++ b/web/docs/src/content/docs/brewcode/skills/agents.mdx @@ -1,158 +1,82 @@ --- title: "Agents" -description: "Interactive agent creation and improvement orchestrator. Create or improve Claude Code agents." +description: "Manage Claude Code agents — create, improve, review, or list project and global agents with auto-mode selection." order: 1114 --- -import { Callout, Card, CardGrid, Steps, UpdateNotice } from '../../../../components/mdx'; +import { Badge, Callout, Card, CardGrid, Steps, UpdateNotice } from '../../../../components/mdx'; -# agents — create / improve agents +# agents - -**Agents without sharp trigger descriptions misfire constantly.** Claude auto-selects agents by matching your request against their `description` field — a vague description means the wrong agent fires, or none at all. Writing good frontmatter by hand is tedious and error-prone. - - - -**One skill scaffolds or refines any agent.** `/brewcode:agents create` spawns `agent-creator` + runs `text-optimize` on the result. `/brewcode:agents up` improves triggers and system prompt quality on an existing agent. CLAUDE.md agents table update is optional and prompted. - +Give a free-form prompt; the skill auto-selects a mode and tells you why. No keyword grammar. ## Quick reference | Field | Value | |-------|-------| | Command | `/brewcode:agents` | -| Arguments | `[create \|up ] \| ` | +| Input | free-form prompt or empty | +| Specialist | `brewcode:agent-creator` | +| List source | `.claude/agents/`, `~/.claude/agents/`, plugin `agents/` | | Model | opus | -| Context | session | -| Tools | Read, Write, Edit, Glob, Grep, Bash, Task, AskUserQuestion, Skill | ## When to use -- **New agent from scratch** — `create` mode scaffolds frontmatter, system prompt, and trigger phrases in one pass -- **Existing agent misfires** — `up` mode tunes `description` trigger keywords and activation examples -- **System prompt is stale** — `up` with "Full review + project context" option pulls in current codebase patterns -- **CLAUDE.md agents table out of sync** — skill can update the table row automatically after create or improve - -| Scenario | Command | -|----------|---------| -| New agent for backend validation | `/brewcode:agents create backend validator` | -| Improve the reviewer agent | `/brewcode:agents up reviewer` | -| Improve by file path | `/brewcode:agents .claude/agents/reviewer.md` | -| Show usage | `/brewcode:agents` | +- Check the status of all agents across project and global scopes +- Create a new agent from a plain-English description +- Improve an existing agent's trigger phrases or system prompt +- Review an agent for quality, focus, and trigger coverage +- Batch-create or batch-improve a set of agents in one pass ## Examples ```bash -# Create a new agent — guided placement + model + CLAUDE.md questions -/brewcode:agents create backend validator - -# Improve existing agent — shorthand (no "up" prefix needed) -/brewcode:agents reviewer - -# Explicit improve with full path -/brewcode:agents up .claude/agents/tester.md +/brewcode:agents +/brewcode:agents status of my agents +/brewcode:agents create a backend validator agent +/brewcode:agents improve reviewer ``` -Expected output after `create`: - -``` -# agents [create] - -## Detection -| Field | Value | -|----------|-------------------| -| Mode | create | -| Target | backend validator | - -## Result -| Field | Value | -|-----------|--------------------------------| -| Agent | .claude/agents/validator.md | -| Model | sonnet | -| Scope | project | -| CLAUDE.md | updated | - -## Next Steps -- Run /reload-plugins to pick up the new agent -- Test with: "validate the API response schema" -``` - -## Flow +## How it works -
  • -
    - Parse arguments -

    Extracts mode and target from $ARGUMENTS. Empty args → prints usage and stops. Prefix create → create mode. Prefix up or a bare name/path → improve mode.

    -
    -
  • -
  • -
    - Ask clarifying questions (one batch) -

    create: three questions in a single AskUserQuestion call — placement scope (project / global / plugin), preferred model (sonnet / opus / haiku / inherit), and whether to update CLAUDE.md. up: two questions — improvement focus (triggers / system prompt / both / full review) and CLAUDE.md update.

    -
    -
  • -
  • -
    - Resolve target (up mode only) -

    Searches .claude/agents/, ~/.claude/agents/, and brewcode/agents/ for the name or path. Stops with an error and lists available agents if the target is not found.

    -
    -
  • -
  • -
    - Spawn agent-creator subagent -

    Delegates to brewcode:agent-creator via Task tool with full context — description or current file content, placement, model, and improvement focus. Returns the written file path.

    -
    -
  • -
  • -
    - Optimize with text-optimize -

    Runs brewtools:text-optimize on the agent file to trim token bloat without losing meaning. Skipped silently if brewtools is not installed.

    -
    -
  • -
  • -
    - Update CLAUDE.md (if approved) -

    Finds the agents table by header pattern (| Agent | or | Name |) and adds or updates the row. Appends a new ## Agents section if no table exists. Always uses Edit, never Write, on an existing file.

    -
    -
  • -
  • -
    - Print result summary -

    Outputs a detection + result table: mode, target, agent path, model, scope, and CLAUDE.md status. Suggests next steps — typically /reload-plugins and a test invocation phrase.

    -
    -
  • +
  • Input gate

    Reads $ARGUMENTS. An empty prompt skips analysis and jumps directly to the No-prompt menu; a non-empty prompt proceeds to mode selection.

  • +
  • Auto-mode select

    Announces Mode: <mode> (agents) — chosen because ... based on keywords, intent, and target presence in the prompt.

  • +
  • No-prompt menu

    Sends a single AskUserQuestion with options: Status (agents) (recommended), Status (all: agents+rules+skills), Create, Improve, Review, List (plain), Cancel. The skill continues with the chosen mode.

  • +
  • Dispatch

    Routes to the appropriate handler. Create and improve modes delegate to the brewcode:agent-creator specialist via Task tool, passing full context — description, scope, model, and improvement focus.

  • +
  • Real status

    Scans .claude/agents/, ~/.claude/agents/, and plugin agents/ directories; reads each agent file to extract name, model, and trigger count. Reports scope, path, and quality signal per agent.

  • +
  • Final output

    Prints a detection + result table: mode chosen, target, file path, model, scope, and CLAUDE.md update status. Suggests next steps such as /reload-plugins and a test invocation phrase.

  • +## Modes + +| Mode | Trigger | Action | +|------|---------|--------| +| status | default — no explicit mode keyword | Scans all scopes, prints agents with model, scope, and trigger count | +| list | `list` keyword | Globs `*.md` across ALL agent scopes (`.claude/agents/`, `~/.claude/agents/`, `brewcode/agents/`) | +| create | `create ` | Scaffolds a new agent file via `agent-creator`; asks scope, model, CLAUDE.md update | +| improve | `improve ` or bare `` | Tunes description triggers and system prompt quality | +| review | `review ` | Full quality review: trigger coverage, prompt focus, redundancy check | +| batch | auto-detected fan-out flag | Not a menu item — auto-detected from prompt ("batch", "all", "each"); triggers parallel delegation when creating or improving multiple agents | +
    -Phase internals — argument parsing table +Create / improve parameters -| Pattern | Mode | Target | -|---------|------|--------| -| empty | help | — | -| `create ` | create | description text | -| `up ` | up | agent name or path | -| `` (no keyword) | up (shorthand) | name or path | - -Placement path mapping: - -| Selection | Path | -|-----------|------| -| Project | `.claude/agents/` | -| Global | `~/.claude/agents/` | -| Plugin | `brewcode/agents/` | +| Parameter | Options | Notes | +|-----------|---------|-------| +| Scope | Project / Global / Plugin | Project → `.claude/agents/`; Global → `~/.claude/agents/`; Plugin → `brewcode/agents/` | +| Model | sonnet / opus / haiku / inherit | `inherit` keeps the model from the existing file (improve only) | +| CLAUDE.md update | yes / no | Adds or updates the agent row in the agents table; appends a new section if none exists | +| Improve focus | triggers / system prompt / both / full review | For improve and review modes | +| Description | free-form, aim ≤100 chars | Used as the agent `description` frontmatter — drives LLM auto-invocation | +| Specialist | `brewcode:agent-creator` | Handles file scaffolding and prompt engineering |
    - - Same create/improve flow for skills instead of agents. - - - Source SKILL.md and agent-creator subagent. - - - All brewcode skills and agents in one place. - + Sibling: manage project rules + Sibling: manage skills + Plugin overview + SKILL.md diff --git a/web/docs/src/content/docs/brewcode/skills/e2e.mdx b/web/docs/src/content/docs/brewcode/skills/e2e.mdx index 84176c3..df89d18 100644 --- a/web/docs/src/content/docs/brewcode/skills/e2e.mdx +++ b/web/docs/src/content/docs/brewcode/skills/e2e.mdx @@ -169,7 +169,7 @@ import { Card, CardGrid, Callout, Steps, UpdateNotice } from '../../../../compon SKILL.md, mode reference files, detect-mode.sh, and architecture reference.
    - Full plugin overview — all 13 skills, agents, and hooks in one place. + Full plugin overview — all 9 skills, agents, and hooks in one place.
    diff --git a/web/docs/src/content/docs/brewcode/skills/review.mdx b/web/docs/src/content/docs/brewcode/skills/review.mdx index f4dee0a..1977b1b 100644 --- a/web/docs/src/content/docs/brewcode/skills/review.mdx +++ b/web/docs/src/content/docs/brewcode/skills/review.mdx @@ -145,9 +145,6 @@ The skill is committable — check it into version control so your whole team sh Static plugin skill for rule and convention compliance. Complementary — run both for full coverage. - - Evidence-based multi-agent debate. Accepts a --review flag that triggers /brewcode:review on the debate output. - The 460-line template instantiated per project by /brewcode:setup. diff --git a/web/docs/src/content/docs/brewcode/skills/rules.mdx b/web/docs/src/content/docs/brewcode/skills/rules.mdx index 5611114..ca7d60f 100644 --- a/web/docs/src/content/docs/brewcode/skills/rules.mdx +++ b/web/docs/src/content/docs/brewcode/skills/rules.mdx @@ -1,90 +1,90 @@ --- title: "Rules" -description: "Syncs KNOWLEDGE.jsonl or session learnings to project rules. Use when - updating rules, syncing knowledge, extracting learnings, organizing anti-patterns. Trigger keywords - rules, knowledge sync, avoid patterns, best practices, session rules, extract rules." +description: "Syncs KNOWLEDGE.jsonl or session learnings to project rules. Use when updating rules, syncing knowledge, extracting learnings, organizing anti-patterns." order: 1106 --- -import { Card, CardGrid, Badge, Callout, UpdateNotice } from '../../../../components/mdx'; +import { Badge, Callout, Card, CardGrid, Steps, UpdateNotice } from '../../../../components/mdx'; -# rules — build Claude rules +# rules - +Writes to project `.claude/rules/` only — never `~/.claude/rules/`. ## Quick reference | Field | Value | |-------|-------| | Command | `/brewcode:rules` | -| Arguments | `[list] \| [] \| [ ]` | -| Model | sonnet | -| Context | session | -| Tools | Read, Bash, Task | +| Input | `[list] \| [] \| [ ]` | +| Specialist | bc-rules-organizer (Task) | +| List source | `rules.sh list` (Bash) | +| Target dir | `.claude/rules/` (project only) | - - Project .claude/rules/ only. NEVER ~/.claude/rules/ - +## When to use -## Mode Detection +- After fixing a bug: capture what went wrong and the correct pattern +- After a code review: lock in the standards that were enforced +- After a session with many learnings: extract the 5 most impactful findings +- To inspect which rules already exist in the project +- To import structured knowledge from a `KNOWLEDGE.jsonl` file -**Arguments:** `$ARGUMENTS` +## Examples -| Input | Mode | -|-------|------| -| `list` | List mode | -| ` ` | Prompt mode | -| `` | File mode | -| (empty) | Session mode | - -## List Mode - -**EXECUTE** and **STOP:** ```bash -bash "${CLAUDE_SKILL_DIR}/scripts/rules.sh" list +/brewcode:rules +/brewcode:rules what is the current state of our rules +/brewcode:rules capture what we learned fixing the auth bug +/brewcode:rules path/to/KNOWLEDGE.jsonl add new entries +/brewcode:rules list ``` -## File / Prompt / Session Mode +## How it works -Spawn bc-rules-organizer agent via Task tool. + +
  • Input gate

    Reads `$ARGUMENTS`. If the first token is `list`, routes immediately to `rules.sh list` and exits. Otherwise continues to mode detection.

  • +
  • Auto-mode select

    Announces Mode: <mode> (rules) — chosen because <evidence>. Defaults to status when arguments are empty or conversational; detects create, improve, or review from explicit cues. A `.jsonl` path or inline prompt is treated as a knowledge source passed to the organizer, not a separate mode.

  • +
  • No-prompt menu

    When no arguments are given and mode cannot be inferred, sends a single AskUserQuestion with options in this order: Status (rules) (recommended), Status (all: agents+rules+skills), Create, Improve, Review, List (plain), Cancel.

  • +
  • Dispatch

    Routes to bc-rules-organizer via the Task tool, passing the prepared knowledge block and mode. For `list` mode, runs `rules.sh list` directly via Bash instead.

  • +
  • Real status

    Reports which files were created or updated (`avoid.md`, `best-practice.md`, or prefix variants). If bc-rules-organizer is unavailable, outputs: `bc-rules-organizer not available — install brewcode plugin`.

  • +
  • Final output

    Prints a summary of rules added, merged, or skipped, grouped by target file. Skipped entries include the dedup reason (similarity %, cross-file antonym, or CLAUDE.md duplicate).

  • +
    -### Prepare Knowledge by Mode +## Modes -| Mode | Preparation | -|------|-------------| -| **file** | Read KNOWLEDGE.jsonl; parse `t:"❌"` -> avoid, `t:"✅"` -> practice | -| **prompt** | Extract `` (first arg), `` (rest) | -| **session** | Extract **5 most impactful** findings: errors, fixes, patterns. Format as `❌` or `✅` | +| Mode | Trigger | Execution | +|------|---------|-----------| +| `status` (default) | Empty input or conversational status query | Reports current rule files and coverage; delegates to bc-rules-organizer | +| `list` | Explicit `list` argument only | Runs `rules.sh list` directly — no agent spawned | +| `create` | Conversational cue or menu selection | Creates missing rule files from plugin templates; accepts KNOWLEDGE.jsonl or inline prompt as knowledge source | +| `improve` | Conversational cue or menu selection | Rewrites weak or redundant entries for clarity; accepts KNOWLEDGE.jsonl or inline prompt as knowledge source | +| `review` | Conversational cue or menu selection | Reads all rule files and reports coverage gaps | +| `batch` | Auto fan-out flag | Processes multiple knowledge entries in one pass alongside the selected mode | -### Agent Prompt Template +
    +Knowledge sources & dedup -``` -Update PROJECT .claude/rules/ — NEVER ~/.claude/rules/ +**Sources accepted:** -Plugin templates: $BC_PLUGIN_ROOT/templates/rules/ -Validation: bash "$BC_PLUGIN_ROOT/skills/rules/scripts/rules.sh" validate -Create missing: bash "$BC_PLUGIN_ROOT/skills/rules/scripts/rules.sh" create +- `KNOWLEDGE.jsonl` path — parses each line; `t:"❌"` maps to avoid, `t:"✅"` maps to best-practice +- File path + inline prompt — organizer reads the file and uses the prompt as instruction +- Session learnings — the skill selects the 5 most impactful findings from the current conversation and formats them as ❌/✅ pairs -Targets: avoid.md, best-practice.md, {prefix}-avoid.md, {prefix}-best-practice.md +**Output files:** `avoid.md`, `best-practice.md`, `{prefix}-avoid.md`, `{prefix}-best-practice.md` — all inside `.claude/rules/` -MODE: {detected mode} -KNOWLEDGE: {prepared from table above} -DEDUP: 3-Check Protocol: - 1. Within-file similarity (>70% skip, 40-70% merge) - 2. Cross-file antonym (avoid↔best-practice — keep avoid only) - 3. CLAUDE.md duplicate (skip if in CLAUDE.md; "CLAUDE.md" forbidden as Source) -``` +**3-Check dedup protocol:** -> `BC_PLUGIN_ROOT` injected by pre-task.mjs hook. +1. Within-file similarity: >70% match → skip; 40–70% match → merge into existing entry +2. Cross-file antonym check: if the same pattern appears in both avoid and best-practice → keep the avoid entry only +3. CLAUDE.md duplicate: if the content already appears in `CLAUDE.md`, skip entirely. The string `"CLAUDE.md"` is forbidden as a Source value in rule entries -### Fallback +**Specialist:** bc-rules-organizer — acts as organizer only (no separate creator agent). Spawned via the Task tool; the agent resolves paths via native `${CLAUDE_PLUGIN_ROOT}` (substituted in its .md at Task spawn). -Agent unavailable -> error: `bc-rules-organizer not available — install brewcode plugin` +
    - - Download, changelog, and installation instructions. - - - Source code, README, and configuration files. - + Sibling: manage agents + Sibling: manage skills + Plugin overview + SKILL.md - \ No newline at end of file + diff --git a/web/docs/src/content/docs/brewcode/skills/setup.mdx b/web/docs/src/content/docs/brewcode/skills/setup.mdx deleted file mode 100644 index 23c2a21..0000000 --- a/web/docs/src/content/docs/brewcode/skills/setup.mdx +++ /dev/null @@ -1,246 +0,0 @@ ---- -title: "Setup" -description: "Analyzes project structure and tech stack to generate adapted PLAN.md.template in .claude/tasks/templates/." -order: 1101 ---- -import { Badge, Callout, Card, CardGrid, Steps, UpdateNotice } from '../../../../components/mdx'; - -# setup — one-time project init - - -**brewcode needs to know your stack before it can plan.** Without setup, the PLAN.md template is generic — wrong agents, wrong reference files, no tech-specific review checks. Running `/brewcode:setup` once produces a template and review skill calibrated to your actual codebase. - - - -**Prerequisites are handled automatically.** Phase 0 checks for `brew`, `timeout`, and `jq`. If everything is present it completes silently and moves on. Semantic search (grepai) is offered as an optional install — ~1.5 GB, skippable. - - -## Quick reference - -| Field | Value | -|-------|-------| -| Command | `/brewcode:setup` | -| Arguments | `[universal-template-path]` | -| Model | opus | -| Context | fork | -| Tools | Read, Write, Glob, Grep, Bash, AskUserQuestion | - -## When to use - -- **New project** — run once after installing brewcode to generate `.claude/tasks/templates/` -- **Stack changed** — added a new framework, switched DB, introduced a new agent — re-run to refresh templates -- **After reinstall** — templates are synced from the plugin cache; a fresh install wipes them -- **Review skill missing** — `/brewcode:review` depends on `.claude/skills/brewcode-review/SKILL.md` created here - -## Examples - -```bash -# Standard: analyze the current project and generate all templates -/brewcode:setup -``` - -```bash -# Use a custom universal template instead of the plugin default -/brewcode:setup /path/to/my-PLAN.md.template -``` - -```bash -# After setup, start the workflow -/brewcode:spec "Implement payment gateway" -/brewcode:plan -/brewcode:start -``` - -## Flow - - -
  • -
    - Prerequisites check (Phase 0) -

    Detects installed tools: brew, timeout, jq (required), ollama and grepai (optional). Missing required tools are installed automatically. If timeout is absent, the skill asks before creating a gtimeout symlink. Semantic search is offered as an optional upgrade.

    -
    -
  • -
  • -
    - Project scan (Phase 1) -

    The Explore agent scans the repo: language, framework, build tool, test framework, assertion library, mocking library, database type and access layer, and any existing .claude/agents/ entries. Output feeds directly into the adaptation plan.

    -
    -
  • -
  • -
    - Adaptation plan (Phase 2) -

    The Plan agent consolidates scan findings into a structured document: tech stack, testing setup, DB config, detected project agents, key patterns from CLAUDE.md, and a list of template modifications to apply.

    -
    -
  • -
  • -
    - Template generation (Phase 3) -

    Creates .claude/tasks/ directory structure, syncs PLAN / SPEC / KNOWLEDGE templates from the plugin cache, then adapts the PLAN template: inserts project agents, fills Reference Examples with canonical files, customises Phase V reviewers and Final Review agents for the detected stack.

    -
    -
  • -
  • -
    - Review skill + config (Phases 3.5 & 3.6) -

    Copies the review skill template to .claude/skills/brewcode-review/SKILL.md and replaces placeholders ({`{TECH_SPECIFIC_CHECKS}`}, {`{PROJECT_AGENTS_TABLE}`}, etc.) from the adaptation plan. Also copies brewcode.config.json with runtime settings for KNOWLEDGE compaction and stop-hook limits.

    -
    -
  • -
  • -
    - Validation + CLAUDE.md update (Phases 4 & 5) -

    Validates all generated files exist and contain required sections. Then collects all installed agents (excluding internal ones) and offers to replace the agent table in ~/.claude/CLAUDE.md with an LLM-optimised format. Asks before writing.

    -
    -
  • -
    - -
    -Internals & phases — full phase dumps, scripts, and template fragments - -### Phase 0: Prerequisites — script details - -```bash -bash "${CLAUDE_SKILL_DIR}/scripts/install.sh" state -bash "${CLAUDE_SKILL_DIR}/scripts/install.sh" check-timeout -bash "${CLAUDE_SKILL_DIR}/scripts/install.sh" required -bash "${CLAUDE_SKILL_DIR}/scripts/install.sh" grepai # if user accepts -bash "${CLAUDE_SKILL_DIR}/scripts/install.sh" summary -``` - -| Component | Type | Purpose | -|-----------|------|---------| -| brew | required | Package manager | -| coreutils + timeout | required | Command timeout for hooks | -| jq | required | JSON processor used by hooks | -| ollama | optional | Local embedding server | -| bge-m3 | optional | Multilingual embedding model (~1.2 GB) | -| grepai | optional | Semantic code search CLI | - -### Phase 1: Scan script - -```bash -bash "scripts/setup.sh" scan -``` - -### Phase 3: Template structure + sync scripts - -```bash -bash "scripts/setup.sh" structure -bash "scripts/setup.sh" sync -``` - -Template sections the skill adapts: - -| Section | Adaptation | -|---------|-----------| -| Agents | Add project-specific agents from `.claude/agents/` | -| Reference Examples | Fill with project's canonical files (controllers, services, tests) | -| Phase V agents | Customise reviewer focus for detected testing/code patterns | -| Final Review | Add project agents (db_expert, etc.) if relevant tech detected | - -Required sections preserved verbatim: - -```markdown -## Agents — Add project agents above Core Agents -## Reference Examples — R1..RN with project's canonical files -## Phases — Each phase has: Agent, Status, Context (C#), Refs (R#) -## Phase NV: Verification — 2+ agents, one checks patterns compliance -## Final Review — 3+ agents parallel -## Context Index — C1..CN task-specific files -``` - -### Phase 3.5: Review skill placeholders - -| Placeholder | Source | Example | -|-------------|--------|---------| -| `{PROJECT_AGENTS_TABLE}` | `.claude/agents/` scan | `\| db_expert \| PostgreSQL \| DB layer \|` | -| `{TECH_SPECIFIC_CHECKS}` | Detected tech stack | Java/Node/Python/Go tables | -| `{PROJECT_RULES}` | CLAUDE.md patterns | AssertJ rules, Lombok, logging | -| `{MAIN_AGENT}` | Project agent or `reviewer` | `reviewer` | -| `{TEST_AGENT}` | Project agent or `tester` | `tester` | -| `{DB_AGENT}` | Project agent or `sql_expert` | `db_expert` | -| `{CUSTOM_GROUPS}` | Additional review groups | Security, API validation | -| `{CODEBASE_BLOCKS}` | Detected source patterns | `src/main/**`, `src/test/**` | - -Validation: - -```bash -bash "scripts/setup.sh" review -test -f .claude/skills/brewcode-review/SKILL.md && echo "Review skill created" || echo "MISSING" -``` - -### Phase 3.6: Configuration options - -```bash -bash "scripts/setup.sh" config -``` - -| Setting | Default | Description | -|---------|---------|-------------| -| `knowledge.maxEntries` | 100 | Max KNOWLEDGE.jsonl entries after compaction | -| `knowledge.maxTokens` | 500 | Max tokens in `## K` block injected to agents | -| `knowledge.priorities` | `["❌","✅","ℹ️"]` | Priority order for knowledge entries | -| `stop.maxAttempts` | 20 | Stop attempts before escape mechanism triggers | -| `agents.system` | [...] | System agents (excluded from `## K` injection) | - -### Phase 4: Validation script - -```bash -bash "scripts/setup.sh" validate -``` - -| Check | Expected path | -|-------|--------------| -| PLAN template | `.claude/tasks/templates/PLAN.md.template` | -| SPEC template | `.claude/tasks/templates/SPEC.md.template` | -| KNOWLEDGE template | `.claude/tasks/templates/KNOWLEDGE.jsonl.template` | -| Config file | `.claude/tasks/cfg/brewcode.config.json` | -| Review skill | `.claude/skills/brewcode-review/SKILL.md` | - -### Phase 5: CLAUDE.md agent update - -```bash -bash "scripts/setup.sh" agents > /tmp/agents-section.md -``` - -The skill reads `~/.claude/CLAUDE.md`, finds all agent-related sections by LLM analysis (not grep), then asks the user before replacing. Internal agents `bc-coordinator`, `bc-grepai-configurator`, `bc-knowledge-manager` are excluded by the script — do not add them manually. - -### Output format - -```markdown -# Template Adaptation Complete - -## Tech Stack -| Category | Value | -|----------|-------| -| Language | [detected] | -| Framework | [detected] | -| Testing | [framework] | -| Database | [type/access] | -| Project Agents | [N]: `agent1`, `agent2` | - -## Adaptations -| Section | Changes | -|---------|---------| -| Agents | +[N] project agents | -| Reference Examples | [N] canonical files | -| Phase V | Reviewers for [tech] patterns | -| Review Skill | Tech-specific checks, project rules | -``` - -
    - - - - Use the adapted PLAN.md.template — `/brewcode:plan` builds a task plan from SPEC. - - - Configure semantic code search — offered during setup Phase 0. - - - Scripts, install.sh, setup.sh, and template sources. - - - All brewcode skills and the infinite-task execution model. - - - - diff --git a/web/docs/src/content/docs/brewcode/skills/skills.mdx b/web/docs/src/content/docs/brewcode/skills/skills.mdx index f13eeb0..dcb70f7 100644 --- a/web/docs/src/content/docs/brewcode/skills/skills.mdx +++ b/web/docs/src/content/docs/brewcode/skills/skills.mdx @@ -5,146 +5,88 @@ order: 1114 --- import { Badge, Callout, Card, CardGrid, Steps, UpdateNotice } from '../../../../components/mdx'; -# skills — create / improve skills +# skills - -**Skills multiply fast.** Every plugin adds more skills, and Claude's auto-detection starts misfiring — wrong skill fires, redundant triggers compete. Maintaining them manually means hand-editing SKILL.md files and hoping the activation description is optimized. - - - -**One skill, three operations.** `/brewcode:skills` lists what you have, improves what's broken, and creates what's missing — through a guided 7-phase pipeline with optional quorum review and E2E testing. - +Give a free-form prompt; the skill auto-selects a mode and tells you why. Status is the default — a list only on explicit request. ## Quick reference | Field | Value | |-------|-------| | Command | `/brewcode:skills` | -| Arguments | `[list\|up\|create] [target]` | +| Input | free-form prompt, mode keyword, or empty | +| Specialist | `brewcode:skill-creator` agent | +| List source | `list-skills.sh` | | Model | opus | -| Context | session | -| Tools | Read, Write, Edit, Glob, Grep, Bash, Task, WebSearch, WebFetch, AskUserQuestion | - -| Mode | Trigger | Effect | -|------|---------|--------| -| `list` | no args or `list` | Print all skills across global / project / plugins | -| `up` | `up ` or just `` | Improve an existing skill | -| `create` | `create ` | Build a new skill from scratch | ## When to use -- **Audit your library** — `/brewcode:skills` with no args gives a full table of global, project, and plugin skills -- **Fix a skill that doesn't trigger** — `/brewcode:skills up commit` re-optimizes activation phrases and description -- **Batch-improve a folder** — `/brewcode:skills up ~/.claude/skills/` processes every `SKILL.md` in parallel -- **Create from a prompt** — `/brewcode:skills create "semantic code search"` researches and scaffolds a complete skill -- **Create from a spec** — `/brewcode:skills create ./spec.md` reads your spec file as the source of truth +- **Check skill health** — run with no args to see status of all skills across global, project, and plugins +- **Fix a non-triggering skill** — `/brewcode:skills improve commit` re-optimizes activation phrases and description +- **Create from a prompt** — `/brewcode:skills create a semantic code search skill` researches and scaffolds a complete skill +- **Batch improve a folder** — `/brewcode:skills improve ~/.claude/skills/` processes every SKILL.md in parallel +- **Explicit listing** — `/brewcode:skills list` when you need a raw table, not a status summary ## Examples ```bash -# List all skills (global + project + plugins) /brewcode:skills - -# Improve a skill by name — "up" is the default mode -/brewcode:skills commit - -# Improve all skills in a folder at once -/brewcode:skills up ~/.claude/skills/ - -# Create from a text prompt -/brewcode:skills create "semantic code search" - -# Create from a prepared spec file -/brewcode:skills create ./spec.md +/brewcode:skills status +/brewcode:skills create a semantic code search skill +/brewcode:skills improve commit +/brewcode:skills list ``` -## Flow - -Both `create` and `up` run the same 7-phase pipeline. Differences are noted per step. +## How it works -
  • -
    - Discovery -

    2–3 Explore agents run in parallel. For create: scan existing skill patterns, project structure, and optionally web-research the topic. For up: analyze the target skill and compare it against brewcode plugin patterns to identify gaps.

    -
    -
  • -
  • -
    - User interview -

    Seven interactive questions via AskUserQuestion: check conversation history (create only), determine input type (create only), choose invocation type (user / LLM / both), detect Mode Switcher keywords (create only), pick testing depth, pick review type, confirm the plan.

    -
    -
  • -
  • -
    - Create / Improve -

    Spawns the Skill Creator agent with discovery results and user choices. The agent builds the full skill structure: frontmatter, activation triggers, references, and scripts. Folder targets run parallel agents — one per SKILL.md found.

    -
    -
  • -
  • -
    - Validate -

    Automatic inside the Skill Creator agent: structure checks, validate-skill.sh, unit tests for scripts, README generation. No orchestrator action required at this step.

    -
    -
  • -
  • -
    - Review -

    Skipped for Quick depth. Simple review: one reviewer agent plus one verification agent — confirmed findings go back to Skill Creator. Quorum review: three reviewers in parallel, 2/3 threshold, DoubleCheck pass, then Skill Creator fixes verified issues.

    -
    -
  • -
  • -
    - E2E testing -

    Deep depth only. Creates test scenarios (one per mode + edge cases), executes each in an isolated temp project via claude -p. Failed scenarios retry up to 2 times; major failures loop back to Create/Improve.

    -
    -
  • -
  • -
    - Summary -

    Structured report: action, skill path, invocation type, testing depth, review type, phases completed, confirmed findings, test results, and suggestions for follow-up.

    -
    -
  • +
  • Input gate

    The skill reads the argument. Empty, `status`, a create/improve/list keyword, or a free-form sentence — each routes differently. No input triggers the no-prompt menu.

  • +
  • Auto-mode select

    Announces `Mode: <mode> (skills) — chosen because <evidence>` so you always know which branch executed and why the classifier picked it.

  • +
  • No-prompt menu

    When invoked with no argument, presents a single AskUserQuestion with options (in order): Status (skills) — recommended, Status (all: agents+rules+skills), Create, Improve, Review, List (plain), Cancel.

  • +
  • Dispatch

    Routes to the appropriate handler: `list-skills.sh` for list mode, `brewcode:skill-creator` agent for create/improve, parallel agents for batch. Review mode spawns reviewer agents with quorum logic.

  • +
  • Real status

    Status mode scans all SKILL.md files, checks trigger keyword coverage, description budget (<=120 chars), and reports health per skill — not just a file listing.

  • +
  • Final output

    Structured report: mode executed, skills affected, findings, paths written or changed, and suggested next invocation if follow-up is warranted.

  • +## Modes + +| Mode | Trigger | Source / agent | +|------|---------|----------------| +| status (default) | no args or `status` | inline scan, no external script | +| list | `list` keyword only | `list-skills.sh` | +| create | `create <prompt>` or `create <path>` | `brewcode:skill-creator` | +| improve | `improve <name>`, `<path>`, or `<folder>` | `brewcode:skill-creator` | +| review | `review <name>` or `<path>` | reviewer agents + quorum | +| batch | improve with a folder target detected | parallel `brewcode:skill-creator` | +
    -Internals +Create / improve pipeline (advanced) -**Testing depth matrix** +Reachable ONLY via create/improve modes. -| Depth | Validate | Review | E2E | -|-------|----------|--------|-----| -| Quick (default) | ✅ | — | — | -| Standard | ✅ | Simple (1 reviewer + verify) | — | -| Deep | ✅ | Quorum (3 reviewers, 2/3) | ✅ | +**User parameters collected via AskUserQuestion:** -**Mode Switcher pattern** +- Invocation type: User-only / LLM-auto / Both +- Testing depth: Quick / Standard / Deep +- Review type: Simple / Quorum (available for Standard and Deep only) -When `create` detects keywords like "mode", "toggle", "switch", or "persistent", it asks whether to generate a Mode Switcher skill. The generated skill supports three arguments — `on [mode-name]`, `off`, `status` — with state stored in `brewcode.state.json`. Scope priority: session > project > global. A `SessionStart` hook injects mode instructions on every event. +**Pipeline phases:** -**Folder target resolution** +- Phase 0 Discovery: 2–3 parallel Explore agents scan existing skill patterns, project structure, and (for create) web-research the topic. +- Phase 4 Review: Simple = one reviewer + one verify agent. Quorum = three reviewers in parallel, 2/3 consensus threshold, DoubleCheck pass, Skill Creator fixes verified findings. +- Phase 5 E2E: Deep depth only. Isolated temp project, `claude -p` execution, up to 2 retries per failed scenario. -`up ~/.claude/skills/` runs `find -name "SKILL.md" -type f` and spawns one Skill Creator agent per result — all in a single message for parallel execution. +**Description budget:** <=120 chars enforced — trigger keywords must fit within this limit. -**Smart mode detection** - -If the first argument is not a mode keyword (`list`, `up`, `create`), the entire input is treated as a target for `up`. `/brewcode:skills commit` is identical to `/brewcode:skills up commit`. +**Specialist:** `brewcode:skill-creator` agent.
    - - Manage agents the same way — list, improve, or create agent definitions. - - - The agent spawned by this skill to build and validate skill files. - - - Source SKILL.md, scripts, and references. - - - Full brewcode plugin — all skills, agents, and hooks. - + Sibling: manage agents + Sibling: manage rules + Plugin overview + SKILL.md diff --git a/web/docs/src/content/docs/brewcode/skills/standards-review.mdx b/web/docs/src/content/docs/brewcode/skills/standards-review.mdx deleted file mode 100644 index ae5aa00..0000000 --- a/web/docs/src/content/docs/brewcode/skills/standards-review.mdx +++ /dev/null @@ -1,171 +0,0 @@ ---- -title: "Standards Review" -description: "Multi-agent code review against project rules, stack guidelines, and reuse opportunities. Spawns parallel expert agents per file group, validates findings, writes a structured report." -order: 1112 ---- -import { Badge, Callout, Card, CardGrid, Steps, UpdateNotice } from '../../../../components/mdx'; - -# standards-review — check code standards - - -**Manual code review misses pattern creep.** As projects grow, the same utility gets re-implemented three times, `avoid#5` quietly gets skipped, and stack-specific rules (entity suffixes, constructor injection, no hardcoded colors) erode one PR at a time. A single reviewer can't track all of this across a large diff. - - - -**`/brewcode:standards-review` delegates the tedious parts.** Parallel haiku agents cover each file group simultaneously — entities, services, tests, build files — then a sonnet validator confirms every finding against the actual source. The report lands in `.claude/reports/` with violations, reuse opportunities, and good patterns all separated. Optionally chains into `/simplify` for a second pass on efficiency and hot-paths. - - -## Quick reference - -| Field | Value | -|-------|-------| -| Command | `/brewcode:standards-review` | -| Arguments | `[commit\|branch\|folder] [-p ]` | -| Model | opus | -| Context | session | -| Tools | Read, Glob, Grep, Task, Bash, Write, mcp\_\_grepai\_\_search, AskUserQuestion, Skill | - -## When to use - -- **Before merging a feature branch** — run without args to diff the branch against `main`/`master` -- **Spot-check a single commit** — pass the short SHA: `/brewcode:standards-review abc123` -- **Review a folder in isolation** — pass the path: `/brewcode:standards-review src/main/java/com/example/orders` -- **Pre-release compliance sweep** — catch any `avoid#N` violations before tagging -- **After onboarding a new stack** — confirm new files follow project conventions from day one - -## Examples - -```bash -# Review current branch vs main -/brewcode:standards-review - -# Review a specific commit -/brewcode:standards-review a3f9c12 - -# Review a folder -/brewcode:standards-review src/main/java/com/example/payments - -# Natural language triggers also work -"check standards on my branch" -"find duplicates in the current diff" -``` - -## Flow - - -
  • -
    - Confirm scope -

    Before any analysis, asks one question: run /simplify afterward for an efficiency pass? Answer is remembered — no second prompt.

    -
    -
  • -
  • -
    - Detect tech stack -

    Scans project root for pom.xml, package.json, pyproject.toml, and similar markers. Loads the matching references/{stack}.md as expert guidelines. Multiple stacks → all references loaded and processed separately.

    -
    -
  • -
  • -
    - Collect files -

    Runs git diff --name-only (branch or commit) or find (folder). Filters to stack-specific extensions. Hard cap at 50 files — warns if the scope is too broad.

    -
    -
  • -
  • -
    - Load context -

    Reads .claude/rules/avoid.md, best-practice.md, all \*.md rule files, and CLAUDE.md if present. Skips gracefully when files don't exist.

    -
    -
  • -
  • -
    - Spawn expert agents -

    Files are grouped by type (entities, services, tests, build config). One haiku agent fires per non-empty group in parallel. Each agent runs search-first via grepai_search before flagging potential duplicates, then outputs structured JSON with violations and reuse signals.

    -
    -
  • -
  • -
    - Validate findings -

    A sonnet reviewer agent reads every file:line location from the expert JSON, confirms the rule actually applies in context, and returns CONFIRM or REJECT per finding. False positives are dropped.

    -
    -
  • -
  • -
    - Write report -

    Confirmed findings land in .claude/reports/{timestamp}_standards-review/REPORT.md — split into violations (errors / warnings), reuse opportunities (with similarity %, recommended action), and good patterns. If the user said Yes in step 1, invokes /simplify on the same scope.

    -
    -
  • -
    - -## How it works - -The skill runs as an opus orchestrator. It reads your project's rules and stack guidelines once, then fans out to specialist haiku agents — one per file group — that can run in parallel. Each agent is instructed to use `grepai_search` before flagging a potential duplicate, applying the similarity decision matrix (90-100% → REUSE, 70-89% → EXTEND, 50-69% → CONSIDER, below 50% → KEEP\_NEW). A sonnet validation pass eliminates false positives by reading actual source at reported line ranges. The final report separates errors (must fix), warnings (should fix), and informational notes. - -
    -Internals — priority stack, similarity matrix, report structure - -**Review priority order** - -| Priority | Source | Focus | -|----------|--------|-------| -| 1 | Existing codebase | Search FIRST — import instead of creating | -| 2 | `CLAUDE.md` | Project standards, conventions, patterns | -| 3 | `rules/*.md` | Strict rules with numbers — check ALL `[avoid#N]`, `[bp#N]` | -| 4 | `references/{stack}.md` | Stack-specific guidelines bundled with this skill | - -**Similarity decision matrix** - -| Similarity | Decision | Action | -|------------|----------|--------| -| 90–100% | REUSE | Import existing | -| 70–89% | EXTEND | Add params/config to existing | -| 50–69% | CONSIDER | Evaluate effort vs benefit | -| <50% | KEEP\_NEW | Justified new code | - -**Stack groupings (Phase 4)** - -Java/Kotlin groups: `entities`, `services`, `tests`, `build`. -TypeScript/React groups: `styles`, `components`, `tests`, `build`. -Python groups: `modules`, `tests`, `configs`, `build`. - -Each group maps to a pattern (e.g., `**/entity/*.java`) and a focus area (e.g., entity suffix, DI, Lombok). - -**Report structure** - -`REPORT.md` sections: Summary table → Violations (errors / warnings) → Reuse Opportunities → Good Patterns Found → Reuse Statistics → Legend. - -**Phase 7: optional simplify** - -If the user answered "Yes" at Phase 0, the skill invokes: - -``` -Skill(skill="simplify", args="{INPUT_VALUE}") -``` - -where `{INPUT_VALUE}` is the same scope (commit hash, branch, or folder path) used in the review. - -**Error handling** - -| Condition | Action | -|-----------|--------| -| No files found | Exit: "No files to review for {SCOPE}" | -| >50 files | Warn user, suggest narrowing scope | -| Unknown stack | Continue with project rules only | -| No rules found | Continue with stack reference only | -| All compliant | Report: "All code compliant with standards" | - -
    - - - - Quorum code review — 3 agents vote, 2/3 consensus required for any finding. - - - Source code, stack reference files, and SKILL.md. - - - All brewcode skills — infinite tasks, convention extraction, setup. - - - - diff --git a/web/docs/src/content/docs/brewcode/skills/superreview.mdx b/web/docs/src/content/docs/brewcode/skills/superreview.mdx new file mode 100644 index 0000000..0ce795d --- /dev/null +++ b/web/docs/src/content/docs/brewcode/skills/superreview.mdx @@ -0,0 +1,198 @@ +--- +title: "superreview" +description: "Generates a project-tailored deep-review skill that merges code review and standards review into one deterministic pass." +order: 1106 +--- + +import { Badge, Callout, Card, CardGrid, Steps, UpdateNotice } from '../../../../components/mdx'; + + + + + + + **Generator skill.** `/brewcode:superreview` does not review code itself. It analyzes the + target project and writes a self-contained `.claude/skills/superreview/` into it. The emitted + skill does the reviewing. + + +## Quick reference + +| Field | Value | +|-------|-------| +| Command | `/brewcode:superreview "" [scope]` | +| Arguments | `` — free-text priority emphasis woven into the emitted skill; optional `[scope]` hint passed through | +| Model | opus | +| Tools | Read, Write, Edit, Bash, Task, AskUserQuestion | +| Output | `.claude/skills/superreview/` in the target project | + +## What it does + +`superreview` is a generator skill. It scans the target project — enumerating agents, rule files, +source directories, and tech stack — then writes a self-contained review skill wired to that +project's actual structure. No plugin dependency remains after generation. + +The emitted skill fuses two earlier passes: the `review` engine (two-phase find-then-validate, +per-finding adversarial gate, single merged P0-P3 report) and the `standards-review` pass +(reuse and duplication focus, 90/70/50 percent reuse matrix, per-stack guidelines). Both run as +one `/superreview` invocation, producing one report. + +The `` argument shapes the emitted skill's Focus rank table. Values such as +"treat any security issue as P0" or "focus on architecture boundaries and reuse" are woven into +the emitted `SKILL.md` so every `/superreview` run in the target project reflects those priorities. + +## When to use + +| Situation | Command | +|-----------|---------| +| Wire up a new project for deep review | `/brewcode:superreview "default ordering"` | +| Security is the top concern | `/brewcode:superreview "treat any security issue as P0"` | +| Architecture and reuse are the priority | `/brewcode:superreview "focus on architecture boundaries and reuse"` | +| An agent, rule file, or source group changed | Re-run to refresh routing and rule pointers | + +## Example + +``` +/brewcode:superreview "focus on reuse and duplicate-detection" +``` + +The generator scans the project, asks about ambiguous domain mappings if needed, then writes: + +``` +superreview generated -> .claude/skills/superreview/ + +Stack: Node/TypeScript (reference: typescript-react.md) +Domain agents wired: 3 (developer, tester, architect) +Review agents: reviewer, architect +Rule pointers: 5 files referenced (not restated inline) +File groups: 4 (src/developer, tests/tester, infra/architect, docs/general) +Focus: 1 reuse 2 correctness 3 architecture 4 version-pins 5 business-reqs + fine-tune: "focus on reuse and duplicate-detection" + +Files written: + .claude/skills/superreview/SKILL.md + .claude/skills/superreview/references/agent-prompt.md + .claude/skills/superreview/references/report-template.md + .claude/skills/superreview/references/typescript-react.md + +Run it: /superreview "" [scope: commit|branch|folder] +``` + +To run the emitted skill after generation: + +``` +/superreview "focus on reuse" last_3 +``` + +## Workflow + + +
  • +
    + Phase 0 — Load templates +

    The generator reads the four emit templates bundled with the skill: SKILL.md.template, agent-prompt.md, report-template.md, and the stack reference files. These are the scaffold for the emitted skill.

    +
    +
  • +
  • +
    + Phase 1 — Scan the target project +

    Runs generate.sh scan to enumerate agents, rule files, source directories, and tech stack. Produces a SCAN_REPORT with agent list, rule list, source groups, and stack hint.

    +
    +
  • +
  • +
    + Phase 1.5 — Clarify ambiguous params +

    Sends an AskUserQuestion when stack detection is ambiguous, domain-agent mapping is uncertain, or source group boundaries are unclear. Skipped when all params resolve unambiguously from the scan.

    +
    +
  • +
  • +
    + Phase 2 — Scalar substitution +

    Calls generate.sh emit to fill all deterministic placeholder values: agent names, rule file paths, file groups, stack reference path. Writes initial file content to .claude/skills/superreview/.

    +
    +
  • +
  • +
    + Phase 3 — AI fills block placeholders +

    The AI edits the emitted files via the Edit tool to fill block sections: per-domain review rules, focus rank table, tech-stack check list, and adversarial validation prompt.

    +
    +
  • +
  • +
    + Phase 4 — Validate +

    Runs generate.sh validate to confirm no unresolved placeholder tokens remain. Errors block completion and prompt a targeted Phase 3 retry.

    +
    +
  • +
  • +
    + Phase 5 — Report +

    Prints a summary: files written, agent wiring table, focus rank, and the invocation command for the emitted skill.

    +
    +
  • +
    + +## Technical details + +### Emitted skill — review modes + +The emitted `/superreview` is fully self-contained after generation. It resolves the review mode +from the scope argument: + +| Mode | Scope keyword | +|------|---------------| +| `FULL_PROJECT` | No scope, or explicit `full` | +| `EXPLICIT` | Named files or directories | +| `UNCOMMITTED` | `uncommitted` / `staged` | +| `LAST_COMMITS` | `last_N` / `branch` | + +The emitted skill is **READ-ONLY by design** — it reports findings, never edits source code. +Per-finding adversarial validation: for each finding in the parallel fan-out, a second agent pass +challenges it before it enters the merged report. Findings that fail validation are dropped or +downgraded. Output: `.claude/reports/{TIMESTAMP}_superreview/REPORT.md`. + +### Re-run triggers + +Regenerate the emitted skill when any of the following change in the target project: + +- Agent added, removed, or renamed +- Rule or convention file added +- Tech stack changes (new runtime, framework, or language) +- Source group boundaries shift (new top-level directory) + +### Error handling + +| Error | Resolution | +|-------|------------| +| No agents found in target project | Generator stops; create at least one agent first | +| Unknown tech stack | Emits with generic reference; warns to review manually | +| Multi-stack project | Emits one reference per detected stack; adds merge note | +| Unresolved placeholder after Phase 3 | Phase 4 blocks completion; re-run Phase 3 on affected file | +| Unwritable target path | Generator stops; check permissions on `.claude/skills/` | + +### Emitted file structure + +``` +.claude/skills/superreview/ + SKILL.md # emitted review skill (self-contained) + references/ + agent-prompt.md # per-agent review instructions + report-template.md # merged P0-P3 report template + {stack}.md # java-kotlin | typescript-react | python | go +``` + + + + Produces the project SPEC.md. Start with spec before generating a review skill for a new repo. + + + Another generator skill: writes project-wide coding conventions into `.claude/skills/convention/`. + + + Browse templates, generate.sh, and per-stack reference docs in the source tree. + + + Plugin overview: hooks, all skills, all agents. + + + + diff --git a/web/docs/src/content/docs/brewdoc/overview.mdx b/web/docs/src/content/docs/brewdoc/overview.mdx index edf29b3..37c774d 100644 --- a/web/docs/src/content/docs/brewdoc/overview.mdx +++ b/web/docs/src/content/docs/brewdoc/overview.mdx @@ -78,9 +78,7 @@ brewdoc/ ├── .claude-plugin/ │ └── plugin.json # Plugin manifest ├── hooks/ -│ ├── hooks.json # 1 hook (Pre-Task) -│ ├── pre-task.mjs # BD_PLUGIN_ROOT injection -│ └── lib/utils.mjs # I/O utilities +│ └── hooks.json # no hooks registered ({"hooks":{}}) ├── skills/ │ ├── auto-sync/ # Documentation sync │ ├── my-claude/ # Installation documentation @@ -92,9 +90,9 @@ brewdoc/ └── bd-auto-sync-processor # Internal: spawned by /brewdoc:auto-sync ``` -The single hook `pre-task.mjs` injects the `BD_PLUGIN_ROOT` variable into subagent prompts -so they can locate the plugin's instruction files. Skills in the main conversation use -`${CLAUDE_SKILL_DIR}` to access their own files. +Brewdoc ships no runtime hooks. Agent subagents resolve plugin paths via the native +`${CLAUDE_PLUGIN_ROOT}` variable provided by Claude Code at Task spawn. Skills in the +main conversation use `${CLAUDE_SKILL_DIR}` to access their own files. **Brewdoc** is a set of documentation utilities: sync, memory optimization, PDF export. diff --git a/web/docs/src/content/docs/brewdoc/skills/auto-sync.mdx b/web/docs/src/content/docs/brewdoc/skills/auto-sync.mdx index 074c759..a0a7b3e 100644 --- a/web/docs/src/content/docs/brewdoc/skills/auto-sync.mdx +++ b/web/docs/src/content/docs/brewdoc/skills/auto-sync.mdx @@ -96,7 +96,7 @@ Managed directories (`rules/`, `agents/`, `skills/`) are excluded from automatic
  • Parallel processing -

    Spawns bd-auto-sync-processor agents (sonnet model) up to PARALLEL_AGENTS concurrently. Each agent receives PATH | TYPE | FLAGS and BD_PLUGIN_ROOT via the pre-task hook. Agents analyze sources, compare with current doc content, and apply changes.

    +

    Spawns bd-auto-sync-processor agents (sonnet model) up to PARALLEL_AGENTS concurrently. Each agent receives PATH | TYPE | FLAGS; the agent resolves its plugin root natively via ${CLAUDE_PLUGIN_ROOT} (substituted in its .md at Task spawn). Agents analyze sources, compare with current doc content, and apply changes.

  • diff --git a/web/docs/src/content/docs/brewdoc/skills/guide.mdx b/web/docs/src/content/docs/brewdoc/skills/guide.mdx index b954d8f..254e6ef 100644 --- a/web/docs/src/content/docs/brewdoc/skills/guide.mdx +++ b/web/docs/src/content/docs/brewdoc/skills/guide.mdx @@ -8,7 +8,7 @@ import { Badge, Callout, Card, CardGrid, Steps, UpdateNotice } from '../../../.. # guide -**Starting from scratch is overwhelming.** The brewcode suite has 4 plugins, 15+ skills, and 13+ agents. Reading all the docs at once doesn't work — there's no thread, no order, no feedback. Without a guide, most users discover 20% of the features and miss the rest. +**Starting from scratch is overwhelming.** The brewcode suite has 4 plugins, 25 skills, and 14 agents. Reading all the docs at once doesn't work — there's no thread, no order, no feedback. Without a guide, most users discover 20% of the features and miss the rest. diff --git a/web/docs/src/content/docs/brewtools/agents/text-optimizer.mdx b/web/docs/src/content/docs/brewtools/agents/text-optimizer.mdx index 1b97d49..4c00858 100644 --- a/web/docs/src/content/docs/brewtools/agents/text-optimizer.mdx +++ b/web/docs/src/content/docs/brewtools/agents/text-optimizer.mdx @@ -127,7 +127,7 @@ import { Badge, Callout, Card, CardGrid, Steps, UpdateNotice } from '../../../.. Agent definition, rule references, and compression spec files. - All brewtools skills and agents — text, secrets, SSH, deploy, debate. + All brewtools skills and agents — text, secrets, SSH, deploy. diff --git a/web/docs/src/content/docs/brewtools/overview.mdx b/web/docs/src/content/docs/brewtools/overview.mdx index 26221eb..d72bf9d 100644 --- a/web/docs/src/content/docs/brewtools/overview.mdx +++ b/web/docs/src/content/docs/brewtools/overview.mdx @@ -43,10 +43,6 @@ Install the entire suite: GitHub Actions deployment -- workflows, releases, GHCR, CI/CD pipelines with safety gates and rollback support. - - Multi-agent debate orchestrator -- 3 modes (Challenge, Strategy, Critic), - dynamic agents, Discovery phase, structured judge-verified decisions. - Check, install, and update the full brewcode plugin suite in one command. Version status table, install missing plugins, reload prompt. @@ -66,7 +62,6 @@ Install the entire suite: | [`/brewtools:secrets-scan`](/brewtools/skills/secrets-scan/) | Scan for leaked secrets and credentials | sonnet | `[--fix]` | | [`/brewtools:ssh`](/brewtools/skills/ssh/) | SSH server management | opus | `[connect\|configure\|deploy\|admin]` | | [`/brewtools:deploy`](/brewtools/skills/deploy/) | GitHub Actions deployment, CI/CD | opus | `[workflow\|release\|ghcr]` | -| [`/brewtools:debate`](/brewtools/skills/debate/) | Evidence-based multi-agent debate | opus | `[topic] [-m challenge\|strategy\|critic] [-n 2-5] [-r max-rounds]` | | [`/brewtools:plugin-update`](/brewtools/skills/plugin-update/) | Check and update the full brewcode plugin suite | sonnet | `[check\|update\|all]` | | [`/brewtools:provider-switch`](/brewtools/skills/provider-switch/) | Configure alternative API providers | opus | `[status\|setup\|help\|]` | @@ -80,9 +75,9 @@ Install the entire suite: ## Plugin variable -`BT_PLUGIN_ROOT` -- injected by the SessionStart hook into every session context. +Plugin paths resolve natively via `${CLAUDE_PLUGIN_ROOT}` at Task spawn — no hook injection required. Skills in the main conversation use `${CLAUDE_SKILL_DIR}` to access their own files; -subagents use `$BT_PLUGIN_ROOT` to locate plugin resources. +subagents receive `${CLAUDE_PLUGIN_ROOT}` as a built-in variable from Claude Code. ## Architecture @@ -92,8 +87,8 @@ brewtools/ │ └── plugin.json # Plugin manifest ├── hooks/ │ ├── hooks.json # Hook registry -│ ├── session-start.mjs # BT_PLUGIN_ROOT injection -│ ├── pre-task.mjs # BT_PLUGIN_ROOT into subagents +│ ├── session-start.mjs # SessionStart: HARD-wall awareness, manager codeword prep +│ ├── manager-prompt.mjs # UserPromptSubmit: ++m / ++rr / ++r codewords │ └── lib/utils.mjs # I/O utilities ├── skills/ │ ├── text-optimize/ # Token optimization @@ -101,7 +96,6 @@ brewtools/ │ ├── secrets-scan/ # Secrets scanning │ ├── ssh/ # SSH server management │ ├── deploy/ # GitHub Actions deployment -│ ├── debate/ # Evidence-based multi-agent debate │ ├── plugin-update/ # Check, install, and update plugin suite │ └── provider-switch/ # Alternative API provider management └── agents/ diff --git a/web/docs/src/content/docs/brewtools/prompt-injection.mdx b/web/docs/src/content/docs/brewtools/prompt-injection.mdx index 7b30710..97786b3 100644 --- a/web/docs/src/content/docs/brewtools/prompt-injection.mdx +++ b/web/docs/src/content/docs/brewtools/prompt-injection.mdx @@ -10,7 +10,7 @@ import { Badge, Callout, Card, CardGrid, Steps, Tabs, TabItem, UpdateNotice } fr -Type a short codeword -- `++mp`, `++m`, `++rr`, or `++r` -- anywhere in your message. A `UserPromptSubmit` hook intercepts the message before the model sees it and appends the matching operating contract as a hidden system-reminder. You see only what you typed; the model receives your text plus the full contract for that one turn. +Type a short codeword -- `++m`, `++rr`, or `++r` -- anywhere in your message. A `UserPromptSubmit` hook intercepts the message before the model sees it and appends the matching operating contract as a hidden system-reminder. You see only what you typed; the model receives your text plus the full contract for that one turn. ## The injection point @@ -75,7 +75,7 @@ The injected block is a system-reminder -- invisible in the user's transcript bu
  • The UserPromptSubmit hook fires before the model -

    manager-prompt.mjs runs on every user message. It tests codewords longest-prefix first: ++mp++m++rr++r, to avoid prefix collisions. The review codewords (++rr, ++r) are codeword-only -- there is no ambient HARD-wall equivalent for review mode. If no codeword is found (and the HARD wall is off), the hook exits immediately -- zero file I/O, zero overhead.

    +

    manager-prompt.mjs runs on every user message. It matches ++m as a standalone token, and tests the review group longest-prefix first: ++rr++r. When ++m is used in plan mode (permission_mode === 'plan') it also injects the Plan Mode addon. The review codewords (++rr, ++r) are codeword-only -- there is no ambient HARD-wall equivalent for review mode. If no codeword is found (and the HARD wall is off), the hook exits immediately -- zero file I/O, zero overhead.

  • @@ -96,8 +96,7 @@ The injected block is a system-reminder -- invisible in the user's transcript bu | Trigger | Means | When it fires | What gets injected | |---------|-------|--------------|-------------------| -| `++mp` | Manager for Plan | any message containing it (checked first) | full Manager block + Plan Mode addon (TaskGraph in English, parallel indicators) | -| `++m` | Manager | any message containing it (checked after `++mp`) | full Manager block -- delegate-everything orchestrator contract | +| `++m` | Manager | any message containing it | full Manager block -- delegate-everything orchestrator contract; in plan mode also injects the Plan Mode addon (TaskGraph in English, parallel indicators) | | `++rr` | Regression Review | any message containing it (checked after `++m`) | anti-regression review discipline -- review each significant phase for NO regression + project standard + correctness; two-phase review->double-check->fix; final cross-review at task end | | `++r` | Review | any message containing it (checked last; `++rr` tested first) | two-phase review discipline -- multi-agent review after each significant change, review->double-check->fix; codeword-only, no ambient | | HARD wall ON | (state) | every turn, no codeword required | full Manager block (ambient injection alongside any codeword) | @@ -106,7 +105,7 @@ The prompt text is editable and update-proof. Use `/brewtools:manager edit` to c ## Where this is used -The `/brewtools:manager` skill is the control plane for the entire mechanism. It lets you inspect the current effective prompt source (`status`), customize the Manager or Plan Mode text (`edit`/`reset`), arm the HARD delegation wall (`on`/`off`), and run one-shot manager tasks (`inline-run`, `hard-one-shot`, `manager-run`). +The `/brewtools:manager` skill is the control plane for the entire mechanism. It lets you inspect the current effective prompt source (`status`), customize the Manager text (`edit`/`reset`), arm the HARD delegation wall (`on`/`off`), and run one-shot manager tasks (`inline-run`, `hard-one-shot`, `manager-run`). The codeword hook itself (`manager-prompt.mjs`) is always on -- it cannot be toggled by the skill. The skill manages text and state; the hook fires unconditionally on every turn. diff --git a/web/docs/src/content/docs/brewtools/skills.mdx b/web/docs/src/content/docs/brewtools/skills.mdx index 84374e7..dadbe95 100644 --- a/web/docs/src/content/docs/brewtools/skills.mdx +++ b/web/docs/src/content/docs/brewtools/skills.mdx @@ -1,6 +1,6 @@ --- title: "Skills" -description: "All 12 Brewtools skills: commands, parameters, examples" +description: "All 10 Brewtools skills: commands, parameters, examples" order: 31 --- @@ -8,33 +8,25 @@ import { Card, CardGrid, Callout } from '../../../components/mdx'; # Skills -Skills (recipes) are slash commands that define *what* to do. Brewtools includes 13 skills -focused on text processing, security scanning, SSH management, deployment, evidence-based debate, plugin management, and session orchestration -- each works independently with no prior setup required. +Skills (recipes) are slash commands that define *what* to do. Brewtools includes 10 skills +focused on text processing, security scanning, SSH management, deployment, plugin management, and session orchestration -- each works independently with no prior setup required. ## Summary table | # | Skill | Command | Model | Purpose | |---|-------|---------|-------|---------| -| 1 | agent-toggle | `/brewtools:agent-toggle` | sonnet | Disable/enable individual agents (survives updates) | -| 2 | debate | `/brewtools:debate` | opus | Evidence-based multi-agent debate | -| 3 | deploy | `/brewtools:deploy` | opus | GitHub Actions deployment, CI/CD | -| 4 | manager | `/brewtools:manager` | sonnet | Manager mode: codeword ++m/++mp injects delegate-everything prompt | -| 5 | plugin-update | `/brewtools:plugin-update` | sonnet | Install and update the full plugin suite | -| 6 | provider-switch | `/brewtools:provider-switch` | sonnet | Configure alternative API providers | -| 7 | secrets-scan | `/brewtools:secrets-scan` | sonnet | Secrets and key scanning | -| 8 | skill-toggle | `/brewtools:skill-toggle` | sonnet | Disable/enable individual skills (survives updates) | -| 9 | ssh | `/brewtools:ssh` | opus | SSH server management | -| 10 | text-human | `/brewtools:text-human` | sonnet | AI artifact removal from code | -| 11 | text-optimize | `/brewtools:text-optimize` | sonnet | Text optimization for LLMs | -| 12 | think-short | `/brewtools:think-short` | sonnet | Toggle terse-output mode | +| 1 | deploy | `/brewtools:deploy` | opus | GitHub Actions deployment, CI/CD | +| 2 | manager | `/brewtools:manager` | sonnet | Manager mode: codeword ++m injects delegate-everything prompt (plan-aware) | +| 3 | plugin-update | `/brewtools:plugin-update` | sonnet | Install and update the full plugin suite | +| 4 | provider-switch | `/brewtools:provider-switch` | sonnet | Configure alternative API providers | +| 5 | secrets-scan | `/brewtools:secrets-scan` | sonnet | Secrets and key scanning | +| 6 | ssh | `/brewtools:ssh` | opus | SSH server management | +| 7 | task-board-init | `/brewtools:task-board-init` | sonnet | Deploy a file-based Kanban board into any repo | +| 8 | text-human | `/brewtools:text-human` | sonnet | AI artifact removal from code | +| 9 | text-optimize | `/brewtools:text-optimize` | sonnet | Text optimization for LLMs | +| 10 | think-short | `/brewtools:think-short` | sonnet | Toggle terse-output mode | - - Disable/enable individual agents (survives plugin updates) - - - Evidence-based multi-agent debate - GitHub Actions deployment, CI/CD with safety gates @@ -50,12 +42,12 @@ focused on text processing, security scanning, SSH management, deployment, evide Secrets and key scanning - - Disable/enable individual skills (survives plugin updates) - SSH server management with safety gates + + Deploy a file-based Kanban board into any repo + AI artifact removal from code @@ -68,7 +60,7 @@ focused on text processing, security scanning, SSH management, deployment, evide - All twelve skills can be used independently -- they require no prior setup + All ten skills can be used independently -- they require no prior setup and no dependency on Brewcode or Brewdoc plugins. diff --git a/web/docs/src/content/docs/brewtools/skills/agent-toggle.mdx b/web/docs/src/content/docs/brewtools/skills/agent-toggle.mdx deleted file mode 100644 index 17f4593..0000000 --- a/web/docs/src/content/docs/brewtools/skills/agent-toggle.mdx +++ /dev/null @@ -1,204 +0,0 @@ ---- -title: "Agent Toggle" -description: "Disable individual plugin agents without uninstalling. State persists across plugin updates." -order: 3122 ---- -import { Badge, Callout, Card, CardGrid, Steps, UpdateNotice } from '../../../../components/mdx'; - -# agent-toggle — disable / enable agents - - - - -**Claude Code has no native per-agent disable.** When too many agents are installed, the LLM's routing gets confused — it picks `reviewer` when you wanted `developer`, or triggers `ssh-admin` on unrelated tasks. Upstream: [#47747](https://github.com/anthropics/claude-code/issues/47747), [#22345](https://github.com/anthropics/claude-code/issues/22345). - - - -**The fix: rename the agent file.** `agent-toggle` renames `.md` → `_.md` in the plugin cache. The agent vanishes from auto-selection. Reverse to bring it back. State persists across plugin updates. For skills (recipes), see [`/brewtools:skill-toggle`](/brewtools/skills/skill-toggle/). - - -## Quick reference - -| Command | Action | -|---------|--------| -| `disable plugin:name` | Rename `.md` → `_.md`, record in state | -| `enable plugin:name` | Rename `_.md` → `.md`, remove from state | -| `status` | Merged table of all disabled agents (global + project) | -| `list` | All agents across all plugins, marked disabled/enabled | -| `reapply` | Re-apply renames from state (use after a plugin update) | -| `prune` | Drop stale state entries for uninstalled plugins | - -Target format: `plugin:name` — e.g. `brewcode:reviewer`, `brewtools:ssh-admin`. Omitting the plugin prefix triggers a clarification prompt. - -## When to use - -- An agent triggers too aggressively and hijacks tasks meant for another agent -- You need to hide an agent only for a specific project — use `--scope=project` -- You want to exclude a subagent from a plugin without uninstalling the whole plugin -- After a plugin update agents "came back" — `reapply` restores the desired state - -## Examples - -**Disable an agent globally:** -``` -/brewtools:agent-toggle disable brewcode:reviewer -``` - -**Disable for the current project only:** -``` -/brewtools:agent-toggle disable brewcode:tester --scope=project -``` - -**Re-enable an agent:** -``` -/brewtools:agent-toggle enable brewtools:ssh-admin -``` - -**Natural language also works:** -``` -disable the brewcode reviewer agent for this project -``` - -**Check all disabled agents:** -``` -/brewtools:agent-toggle status -``` - -Expected output after disable: - -``` -| Plugin | Name | Kind | Scope | Action | Result | -|----------|----------|-------|--------|---------|----------| -| brewcode | reviewer | agent | global | disable | disabled | - -> Run /reload-plugins for the change to take effect. -``` - -## Interactive mode - - -**Run with no args** — `/brewtools:agent-toggle` — and a guided flow walks you through it. Explicit commands still skip the flow. - - -Four phases: - - -
  • -
    - Pick an op -

    One question, four options: status, disable, enable, or list. Pre-selected: disable.

    -
    -
  • -
  • -
    - Scan the catalog -

    All agents printed as one space-separated line of plugin:name tokens. Use Ctrl+F / Cmd+F to search your terminal scrollback — no pagination, no multi-line clutter.

    -
    -
  • -
  • -
    - Resolve the target -

    Exact plugin:name or unique shortname runs immediately — no confirmation. Fuzzy phrase ("hide a noisy agent") or ambiguous name triggers a single confirmation.

    -
    -
  • -
  • -
    - See the result -

    Every run ends with a status table: what's disabled right now, plus a count of enabled agents. No guessing what state you're in.

    -
    -
  • - - - -**Explicit commands skip the flow.** `disable brewcode:reviewer` runs directly — no questions asked. The interactive path only triggers when your intent is ambiguous. - - -## How it works - - -
  • -
    - P0 — Parse intent -

    Parses $ARGUMENTS or the user's NL prompt into a structured form: op / scope / targets[]. Default scope is global. Override with --scope=project or the phrase "for this project". If a target has no plugin prefix (e.g. just tester), the skill asks which plugin via AskUserQuestion.

    -
    -
  • -
  • -
    - P1 — Validate target -

    Uses enumeratePlugins + resolveTarget to confirm the plugin is installed and the agent file exists in visible or hidden form. Stops with an error if neither path is found.

    -
    -
  • -
  • -
    - P2 — Mutate state -

    Atomically writes or removes a {`{kind:"agent"}`} entry in toggle-state.json (global or project-scoped). Uses a tmp-file + rename pattern via writeStateAtomic.

    -
    -
  • -
  • -
    - P3 — Apply rename -

    Calls disableTarget(visible, hidden) or enableTarget(visible, hidden) from _shared/toggle/apply.mjs. Possible statuses: disabled, enabled, already_disabled, already_enabled, missing.

    -
    -
  • -
  • -
    - P4 — Notify -

    Renders a result table and reminds the user to run /reload-plugins.

    -
    -
  • -
    - -## State files - -Both `agent-toggle` and `skill-toggle` share the **same** `toggle-state.json`. The `kind` field in each entry distinguishes agents (`"kind":"agent"`) from skills (`"kind":"skill"`). - -| Scope | Path | -|-------|------| -| Global (default) | `~/.claude/plugins/data/brewtools-claude-brewcode/toggle-state.json` | -| Project | `/.claude/brewtools/toggle-state.json` | - -Project scope overrides global by key — the same agent can be enabled globally but disabled in one specific project. - -## State schema - -```json -{ - "disabled": { - "brewcode:reviewer": { - "kind": "agent", - "plugin": "brewcode", - "name": "reviewer", - "disabled_at": "2026-04-16T10:00:00.000Z", - "last_applied_version": "3.5.2" - } - } -} -``` - -Shared helpers live in `_shared/toggle/`: `cache.mjs` (path resolution), `state.mjs` (read/write), `apply.mjs` (rename). - -## Surviving plugin updates - - -The `reapply-disables` SessionStart hook fires on every session start. When a new plugin version is detected in the cache, it automatically re-applies all entries from `toggle-state.json`. Drift cases (plugin not installed, file missing) are reported in `additionalContext` with codes `plugin_not_installed` / `file_missing` — no silent failures. - - -## Reload required - - -After any `disable` or `enable`, run `/reload-plugins` or start a new session. Claude Code reads the agent list only at plugin load time — the change does not take effect until then. - - - - - The symmetric operation for skills (recipes) — same mechanism, same state file, `"kind":"skill"`. - - - All brewtools skills and agents in one place. - - - Source code and shared toggle helpers in `_shared/toggle/`. - - - - diff --git a/web/docs/src/content/docs/brewtools/skills/debate.mdx b/web/docs/src/content/docs/brewtools/skills/debate.mdx deleted file mode 100644 index 9773855..0000000 --- a/web/docs/src/content/docs/brewtools/skills/debate.mdx +++ /dev/null @@ -1,164 +0,0 @@ ---- -title: "Debate" -description: "Multi-agent debate orchestrator — 3 modes, Discovery phase, judge-verified decisions." -order: 3118 ---- -import { Card, CardGrid, Callout, Steps, UpdateNotice } from '../../../../components/mdx'; - -# debate — Challenge, Strategy, Critic - - -**Opinion without evidence is noise.** Every debate starts with a mandatory Discovery phase: parallel research agents scan your codebase and the web. Arguments that don't cite Discovery findings don't count — the judge challenges them on the spot. - - - -**Three modes, one command.** Challenge picks the best option from competing variants. Strategy synthesizes independent proposals into a plan. Critic finds every weakness in what you already have. The skill auto-asks which mode if you don't specify. - - -## Quick reference - -| Field | Value | -|-------|-------| -| Command | `/brewtools:debate` | -| Arguments | `[topic] [-m challenge\|strategy\|critic] [-n 2-5] [-r max-rounds] [--review]` | -| Model | opus | -| Agents | 2–5 dynamic debaters + secretary + judge (main session) | -| Output | `discovery.md`, `decisions.md`, `summary.md`, `debate-log.jsonl` | - -## When to use - -| Scenario | Command | -|----------|---------| -| Pick the best technology from several options | `/brewtools:debate "React vs Vue vs Svelte" -m challenge` | -| Design a migration or architecture plan | `/brewtools:debate "monolith to microservices plan" -m strategy` | -| Find all risks in an existing solution | `/brewtools:debate "critique our JWT auth flow" -m critic` | -| Extended analysis with more agents and rounds | `/brewtools:debate "PostgreSQL vs DynamoDB" -n 4 -r 8` | -| Post-debate code review of output | `/brewtools:debate "our deployment pipeline" -m critic --review` | - -## Modes - -| Mode | Goal | Agent setup | -|------|------|-------------| -| **Challenge** (default) | Select the best variant from competing options | Defenders argue FOR, critics attack; judge declares winner | -| **Strategy** | Synthesize the strongest approach from independent proposals | All agents are strategists; goal is convergence, not a winner | -| **Critic** | Find every weakness, risk, and flaw | All agents are critics with different perspectives; no defender | - -## Examples - -```bash -# Challenge mode — compare options (default) -/brewtools:debate "React vs Vue vs Svelte for our new dashboard" - -# Strategy mode — how to approach a problem -/brewtools:debate "Migration plan from monolith to microservices" -m strategy -n 4 - -# Critic mode — stress-test an existing plan -/brewtools:debate "Review our authentication flow" -m critic -n 5 --review -``` - -## Flow - - -
  • -
    - Parse and interview -

    Extracts topic, mode (-m), agent count (-n), and max rounds (-r) from your command. If mode is omitted, asks explicitly — no auto-guessing. Confirms setup via AskUserQuestion before doing anything else.

    -
    -
  • -
  • -
    - Generate agent team -

    Assigns roles (defender / critic / strategist) based on mode, then selects character archetypes (Pragmatist, Skeptic, Visionary, Architect, Operator, and others) to create productive tension. Displays the full agent table and asks for confirmation before proceeding.

    -
    -
  • -
  • -
    - Discovery — mandatory evidence phase -

    Two research agents run in parallel: Codebase Explorer scans your project for relevant code, patterns, and dependencies; Web Researcher fetches current best practices, official docs, and benchmarks. All findings — with file paths and URLs — are saved to discovery.md and injected into every debater's context.

    -
    -
  • -
  • -
    - Debate rounds -

    Agents run sequentially; each reads the shared JSONL log before responding. Every argument must reference a Discovery finding — unsourced claims are challenged by the judge. The judge (main session) monitors for consensus, stalemate, or max rounds and can redirect mid-debate.

    -
    -
  • -
  • -
    - Summary and decision -

    A secretary agent writes summary.md with key arguments, turning points, and agreement areas. The judge then writes decisions.md: winning position (or synthesized result), decisive arguments, minority opinions, confidence level, and recommended next steps.

    -
    -
  • -
  • -
    - Final output -

    Status table: mode, rounds used, outcome (consensus / partial / none), top 3–5 decision bullets, and links to all four artifact files. If --review was set, triggers /brewcode:review on the output.

    -
    -
  • -
    - -
    -Internals: phases, Discovery rules, JSONL schema, agent prompt composition - -**Phases (SKILL.md)** - -| Phase | What happens | -|-------|-------------| -| 0 — Validation | Runs `validate.sh`; stops on failure. Loads `archetypes.md` into context. | -| 1 — Parse | Reads `$ARGUMENTS`; blocks until user picks mode if `-m` omitted. | -| 2 — Init | Runs `init-log.sh`; captures `REPORT_DIR` and `LOG_FILE`. | -| 3 — Interview | `AskUserQuestion` to confirm or adjust mode, agent count, rounds, custom profiles. | -| 4 — Agent profiles | Generates team from `setup-flow.md`; user confirms before proceeding. | -| 5 — Discovery | Parallel research agents per `discovery-flow.md`; saves `discovery.md`. | -| 6 — Debate | Mode-specific flow from `challenge-flow.md` / `strategy-flow.md` / `critic-flow.md`. | -| 7 — Summary | Secretary agent writes `summary.md` from full log + discovery. | -| 8 — Decision | Judge (main session) writes `decisions.md`. | -| 9 — Output | Displays status table; optionally invokes `/brewcode:review`. | - -**Discovery evidence mandate** - -Every argument in Phase 6 MUST cite at least one finding from `discovery.md`. Format: `[Source: #N]` where N is the discovery entry number. The judge tracks sourcing — unsourced claims are challenged and do not count toward consensus. - -**JSONL log schema** - -Each debate turn is one line in `debate-log.jsonl`: - -```jsonl -{"ts":"2026-04-05T14:30:00","from":"agent-1","to":["agent-2"],"what":"React has larger ecosystem","why":"More packages, hiring pool [Source: #3]","type":"argument","mode":"challenge"} -{"ts":"2026-04-05T14:30:15","from":"agent-2","to":["agent-1"],"what":"Ecosystem size != quality","why":"Vue curated ecosystem avoids dependency hell [Source: #7]","type":"counter","mode":"challenge"} -``` - -Entry types: `argument`, `counter`, `proposal`, `agree`, `question`, `redirect`. - -**Agent prompt composition (Phase 6)** - -Each agent's prompt is built dynamically from four layers: -1. Base template — `agents/debater-template.md` -2. Role overlay — `agents/{role}-template.md` (defender / critic / strategist) -3. Character traits — from `archetypes.md` for the assigned archetype -4. Evidence base — full contents of `discovery.md` injected as context - -**Auto-detect keywords (when `-m` is omitted and topic is unambiguous)** - -| Keywords in topic | Detected mode | -|-------------------|---------------| -| compare, choose, vs, best, pick, which, select | `challenge` | -| strategy, approach, plan, how to, design | `strategy` | -| critique, weakness, risk, flaw, review, audit | `critic` | -| (none match) | asks user — never silently defaults | - -
    - - - - Run `/brewcode:review` on debate output with the `--review` flag for a full quorum code review of the decision. - - - Source files: SKILL.md, archetypes, role templates, flow references, scripts. - - - All brewtools skills — text-optimize, secrets-scan, deploy, provider-switch, and more. - - - - diff --git a/web/docs/src/content/docs/brewtools/skills/deploy.mdx b/web/docs/src/content/docs/brewtools/skills/deploy.mdx index 2fc073a..109ea1a 100644 --- a/web/docs/src/content/docs/brewtools/skills/deploy.mdx +++ b/web/docs/src/content/docs/brewtools/skills/deploy.mdx @@ -161,7 +161,7 @@ Every Bash call uses `&& echo "OK" || echo "FAILED"` with fail-fast logic. Max 2 Source code, scripts, and workflow templates.
    - All brewtools skills — text, secrets, SSH, deploy, debate, and more. + All brewtools skills — text, secrets, SSH, deploy, and more.
    diff --git a/web/docs/src/content/docs/brewtools/skills/manager.mdx b/web/docs/src/content/docs/brewtools/skills/manager.mdx index 75f39b1..bf5281b 100644 --- a/web/docs/src/content/docs/brewtools/skills/manager.mdx +++ b/web/docs/src/content/docs/brewtools/skills/manager.mdx @@ -1,6 +1,6 @@ --- title: "Manager" -description: "Type ++m / ++mp / ++rr / ++r anywhere to inject a Manager or review-discipline block for one turn. The HARD wall denies Write/Edit/NotebookEdit/WebFetch/MCP-write in the main session, forcing delegation. RU+EN." +description: "Type ++m / ++rr / ++r anywhere to inject a Manager or review-discipline block for one turn. The HARD wall denies Write/Edit/NotebookEdit/WebFetch/MCP-write in the main session, forcing delegation. RU+EN." order: 3124 --- import { Badge, Callout, Card, CardGrid, Steps, UpdateNotice } from '../../../../components/mdx'; @@ -10,7 +10,7 @@ import { Badge, Callout, Card, CardGrid, Steps, UpdateNotice } from '../../../.. -**What is Manager mode?** You type a short codeword (`++m`, `++mp`, `++rr`, or `++r`) anywhere in your message and Claude instantly activates a discipline contract -- just for that one message. `++m` makes Claude a pure orchestrator that delegates all hands-on work. `++mp` adds a full task-graph planning pass. `++rr` and `++r` inject review discipline (anti-regression / two-phase double-check). No setup required. The codeword is stripped from your message; your actual text is preserved. +**What is Manager mode?** You type a short codeword (`++m`, `++rr`, or `++r`) anywhere in your message and Claude instantly activates a discipline contract -- just for that one message. `++m` makes Claude a pure orchestrator that delegates all hands-on work -- and when you are in plan mode it automatically adds a full task-graph planning pass. `++rr` and `++r` inject review discipline (anti-regression / two-phase double-check). No setup required. The codeword is stripped from your message; your actual text is preserved. ## What actually happens @@ -50,11 +50,10 @@ Your single line becomes: the full Manager contract (highlighted above) + your o | Codeword | Means | What it does | |----------|-------|-------------| | `++m` | Manager | Manager + delegation for the current task -- Claude orchestrates, never codes by hand | -| `++mp` | Manager for Plan | Manager role for plan + delegation -- writes the full task graph in English before starting, uses the tasks tool | | `++rr` | Regression Review | Regression review with double-check -- after each significant phase, run a review focused on no regression + project standard + correctness; two-phase (review → double-check → fix); mandatory final cross-review at task end | | `++r` | Review | Review with double-check -- after each significant change, run a two-phase multi-agent review (review → double-check → fix); codeword-only, no ambient injection or wall state change | -Detection order: `++mp` → `++m` → `++rr` → `++r` (longest-prefix first; `++rr` is always tested before `++r`). +Detection order: within the review group, `++rr` is tested before `++r` (longest-prefix first). `++m` is matched as a standalone token; in plan mode it auto-adds the plan addon. Put the codeword anywhere: start, middle, or end of your message. Everything else is passed through unchanged. @@ -67,7 +66,7 @@ Put the codeword anywhere: start, middle, or end of your message. Everything els | `/brewtools:manager status` | Show what is currently on -- codeword state, wall state, prompt source | | `/brewtools:manager on` | Turn on the HARD wall -- Claude physically cannot write/edit files in this project until you turn it off | | `/brewtools:manager off` | Turn the HARD wall off | -| `/brewtools:manager edit full` | Open the Manager prompt text so you can customize it | +| `/brewtools:manager edit` | Open the Manager prompt text so you can customize it | --- @@ -117,7 +116,7 @@ This is what "delegate everything" means in practice -- the wall makes it physic | Situation | What to type | |-----------|-------------| | Delegate one complex task as Manager, just this turn | `do X ++m` | -| Start a full parallel plan with task breakdown | `plan Y ++mp` | +| Start a full parallel plan with task breakdown (in plan mode) | `plan Y ++m` | | Enforce the delegation rule for a whole project session | `/brewtools:manager on` | | Run one task under the wall then auto-revert | `refactor payment service in hard mode` | | Run task as Manager without changing any wall state | `build release plan as manager` | @@ -178,7 +177,7 @@ The balanced Bash classifier is an allowlist of known-safe read-only commands, N ### How the codeword injection works -On every user message, `manager-prompt.mjs` scans the prompt text. Detection order follows longest-prefix first: `++mp` → `++m` → `++rr` → `++r`. This ensures `++mp` is never mis-matched as `++m`, and `++rr` is never mis-matched as `++r`. If no codeword is present (and the wall is not armed), the hook exits immediately -- no file I/O, zero overhead. +On every user message, `manager-prompt.mjs` scans the prompt text. It matches `++m` as a standalone token, and tests the review group longest-prefix first (`++rr` before `++r`) so `++rr` is never mis-matched as `++r`. If no codeword is present (and the wall is not armed), the hook exits immediately -- no file I/O, zero overhead. The hook resolves the prompt text for the detected mode (`full` or `planmode`) via three-level fallback: @@ -211,9 +210,9 @@ The wall flags (`hard`/`level`) are resolved project-only. Passing `--scope glob Global paths (`~/.claude/*`) are protected from direct Write/Edit tool access (Claude Code v3.4.70+). The skill writes them via bundled Node helpers using atomic lock+tmp+rename. -### Plan Mode addon (`++mp`) +### Plan Mode addon (auto in plan mode) -When `++mp` is detected, the hook injects both the full Manager block and the Plan Mode addon. The addon instructs the model to: write the full TaskGraph in English into the plan before starting; mark tasks with parallel / critical-path indicators; output all task and plan text in English regardless of user prompt language. +When `++m` is used while the session is in plan mode (`permission_mode === 'plan'`), the hook injects both the full Manager block and the Plan Mode addon. The addon instructs the model to: write the full TaskGraph in English into the plan before starting; mark tasks with parallel / critical-path indicators; output all task and plan text in English regardless of user prompt language. @@ -232,10 +231,8 @@ When `++mp` is detected, the hook injects both the full Manager block and the Pl | `level strict` | `/brewtools:manager level strict` | Wall strictness = strict (Bash fully off) | | `level balanced` | `/brewtools:manager level balanced` | Wall strictness = balanced (read-only Bash allowed) | | `status` | `/brewtools:manager status` | Full explainer: codewords + wall state + effective prompt sources | -| `mode full` | `/brewtools:manager mode full` | Set prompt-text mode to `full` (informational only) | -| `mode planmode` | `/brewtools:manager mode planmode` | Set prompt-text mode to `planmode` (informational only) | -| `edit [full\|planmode]` | `/brewtools:manager edit` | Copy plugin default into project override for editing | -| `reset [full\|planmode]` | `/brewtools:manager reset` | Delete project override, revert to plugin default | +| `edit` | `/brewtools:manager edit` | Copy plugin default into project override for editing | +| `reset` | `/brewtools:manager reset` | Delete project override, revert to plugin default | | `hard-one-shot` | ` in hard mode` | Wall ON -- run task as Manager -- auto-revert wall OFF when done (reverts even on failure or abort) | | `manager-run` | ` as manager` | Run task as Manager with wall UNTOUCHED (discipline via injected prompt only -- no wall toggle) | | `inline-run` | `/brewtools:manager ` | Prepend Manager block, execute -- no state change | @@ -247,14 +244,14 @@ When `++mp` is detected, the hook injects both the full Manager block and the Pl ## Codewords (ALWAYS active -- hook-driven, independent of this skill) Type `++m` anywhere -> injects the Manager (full) block for that one turn. -Type `++mp` anywhere -> injects the Manager + Plan Mode block for that one turn. +Type `++m` while in plan mode -> injects the Manager + Plan Mode block for that one turn. Type `++rr` anywhere -> injects the Regression Review contract for that one turn. Type `++r` anywhere -> injects the Review contract for that one turn. --- injected by ++m (full) --- ---- injected by ++mp (planmode) --- +--- injected by ++m (planmode -- auto when permission_mode === 'plan') --- ## HARD wall (this project) -- registered=no armed=OFF level=balanced (state source: default) @@ -277,7 +274,7 @@ Level: /brewtools:manager level strict | balanced Companion output-control skill -- inject brevity directives via SessionStart and per-agent PreToolUse rather than per-prompt codewords.
    - How the `++m` / `++mp` / `++rr` / `++r` codewords inject the Manager / review contract into the model -- the full mechanism explained. + How the `++m` / `++rr` / `++r` codewords inject the Manager / review contract into the model -- the full mechanism explained. All brewtools skills and agents in one place. diff --git a/web/docs/src/content/docs/brewtools/skills/plugin-update.mdx b/web/docs/src/content/docs/brewtools/skills/plugin-update.mdx index 664acb2..1181be5 100644 --- a/web/docs/src/content/docs/brewtools/skills/plugin-update.mdx +++ b/web/docs/src/content/docs/brewtools/skills/plugin-update.mdx @@ -12,7 +12,7 @@ import { Badge, Callout, Card, CardGrid, Steps, UpdateNotice } from '../../../..
    -**One skill checks, installs, and updates the full brewcode suite.** Interactive by default — or pass `check` / `update` / `all` to skip questions. For individual skill toggling, see [`/brewtools:skill-toggle`](/brewtools/skills/skill-toggle/). +**One skill checks, installs, and updates the full brewcode suite.** Interactive by default — or pass `check` / `update` / `all` to skip questions. ## Quick reference @@ -142,12 +142,6 @@ Each command runs via the Bash tool with full output shown. Failures are reporte - - Disable individual skills without uninstalling. State persists across plugin updates. - - - Same disable/enable mechanic for agents instead of skills. - Source code, discovery scripts, and update references. diff --git a/web/docs/src/content/docs/brewtools/skills/skill-toggle.mdx b/web/docs/src/content/docs/brewtools/skills/skill-toggle.mdx deleted file mode 100644 index b83c368..0000000 --- a/web/docs/src/content/docs/brewtools/skills/skill-toggle.mdx +++ /dev/null @@ -1,193 +0,0 @@ ---- -title: "Skill Toggle" -description: "Disable individual plugin skills without uninstalling. State persists across plugin updates." -order: 3121 ---- -import { Badge, Callout, Card, CardGrid, Steps, UpdateNotice } from '../../../../components/mdx'; - -# skill-toggle — disable / enable skills - - -**10+ plugins means dozens of skills flooding Claude's context.** When every skill competes for attention, Claude's auto-selection misfires — wrong skill fires, irrelevant triggers pile up, noise grows with every install. Claude Code has no native per-skill disable ([#47747](https://github.com/anthropics/claude-code/issues/47747), [#22345](https://github.com/anthropics/claude-code/issues/22345)). - - - -**One command silences a skill permanently.** State is stored separately from the plugin cache — `claude plugin update` never resets it. For agents, see [`/brewtools:agent-toggle`](/brewtools/skills/agent-toggle/). - - -## Quick reference - -| Command | Action | -|---------|--------| -| `/brewtools:skill-toggle disable brewdoc:md-to-pdf` | Hide a skill (renames `SKILL.md` → `_SKILL.md`) | -| `/brewtools:skill-toggle enable brewdoc:md-to-pdf` | Restore a hidden skill | -| `/brewtools:skill-toggle status` | Show all disabled skills (merged global + project) | -| `/brewtools:skill-toggle list` | List every installed skill with enabled/disabled state | -| `/brewtools:skill-toggle reapply` | Re-apply state after manual plugin cache changes | -| `/brewtools:skill-toggle prune` | Remove state entries for uninstalled plugins | - -Target format: `plugin:name` — e.g., `brewdoc:md-to-pdf`, `brewcode:convention`. Name without a plugin prefix triggers a clarifying question before any mutation. - -## When to use - -- **Clutter reduction** — hide skills you never invoke to shrink Claude's active context -- **Quieter auto-triggers** — disable skills whose trigger phrases collide with your normal workflow -- **Project-specific overrides** — scope a disable to the current repo without touching global state -- **Keep plugins installed** — the plugin stays updated; only the individual skill is silenced - -## Examples - -```bash -# Disable a skill globally (default scope) -/brewtools:skill-toggle disable brewdoc:md-to-pdf - -# Natural language also works -"disable brewdoc:md-to-pdf" -"hide the md-to-pdf skill" -``` - -```bash -# Disable for current project only -/brewtools:skill-toggle disable brewcode:convention --scope=project - -# Enable a previously disabled skill -/brewtools:skill-toggle enable brewdoc:md-to-pdf -``` - -```bash -# Check what's currently disabled -/brewtools:skill-toggle status - -# See everything — enabled and disabled -/brewtools:skill-toggle list -``` - -```bash -# After a plugin update, re-apply all stored disables -/brewtools:skill-toggle reapply -``` - -## Interactive mode - - -**Run with no args** — `/brewtools:skill-toggle` — and a guided flow walks you through it. Explicit commands still skip the flow. - - -Four phases: - - -
  • -
    - Pick an op -

    One question, four options: status, disable, enable, or list. Pre-selected: disable.

    -
    -
  • -
  • -
    - Scan the catalog -

    All targets printed as one space-separated line of plugin:name tokens. Use Ctrl+F / Cmd+F to search your terminal scrollback — no pagination, no multi-line clutter.

    -
    -
  • -
  • -
    - Resolve the target -

    Exact plugin:name or unique shortname runs immediately — no confirmation. Fuzzy phrase ("the noisy image one") or ambiguous name triggers a single confirmation.

    -
    -
  • -
  • -
    - See the result -

    Every run ends with a status table: what's disabled right now, plus a count of enabled skills. No guessing what state you're in.

    -
    -
  • -
    - - -**Explicit commands skip the flow.** `disable brewdoc:md-to-pdf` runs directly — no questions asked. The interactive path only triggers when your intent is ambiguous. - - -## How it works - - -
  • -
    - Parse intent -

    Extracts operation, scope, and target from your command or natural language. No plugin prefix? Asks which plugin owns the skill before touching anything.

    -
    -
  • -
  • -
    - Validate target -

    Checks the plugin cache for both SKILL.md (enabled) and _SKILL.md (disabled). Unknown plugin or missing skill — stops with an error, no state written.

    -
    -
  • -
  • -
    - Mutate state -

    Writes (disable) or removes (enable) the entry in the appropriate JSON state file — global or project scope. Atomic write via tmp + rename, no partial updates.

    -
    -
  • -
  • -
    - Rename file -

    disable: renames SKILL.md_SKILL.md in the plugin cache. enable: renames back. Claude Code ignores files that don't match SKILL.md.

    -
    -
  • -
  • -
    - Notify -

    Prints a result table: plugin, name, scope, action, result. Reminds you to run /reload-plugins.

    -
    -
  • -
    - -## State files - -| Scope | Path | -|-------|------| -| Global (default) | `~/.claude/plugins/data/brewtools-claude-brewcode/toggle-state.json` | -| Project | `/.claude/brewtools/toggle-state.json` | - -Project scope overrides global per key — a project-level enable wins over a global disable for the same skill. - -## State schema - -```json -{ - "disabled": { - "brewdoc:md-to-pdf": { - "kind": "skill", - "plugin": "brewdoc", - "name": "md-to-pdf", - "disabled_at": "2026-04-16T10:30:00.000Z", - "last_applied_version": "3.5.2" - } - } -} -``` - -## Surviving plugin updates - - -The `reapply-disables` hook fires on every `SessionStart`. It detects when the plugin cache has a new version directory and re-applies all entries from the state file automatically. If a plugin was uninstalled or a skill file is missing, the hook reports the drift (`plugin_not_installed`, `file_missing`) in `additionalContext` — visible at the top of the new session. - - -## Reload required - - -Run `/reload-plugins` or restart the session after any `disable` or `enable`. Claude Code reads skill definitions once at startup — in-flight changes take effect only after a reload. - - - - - Same disable/enable mechanic for agents instead of skills. - - - All brewtools skills in one place. - - - Source code and shared toggle helpers. - - - - diff --git a/web/docs/src/content/docs/brewtools/skills/task-board-init.mdx b/web/docs/src/content/docs/brewtools/skills/task-board-init.mdx index c27eb40..ae25b4f 100644 --- a/web/docs/src/content/docs/brewtools/skills/task-board-init.mdx +++ b/web/docs/src/content/docs/brewtools/skills/task-board-init.mdx @@ -130,7 +130,7 @@ Task IDs follow `UPPER-KEBAB`: `--`. Delegation companion — arm a HARD wall that forces the main session to orchestrate via Task/Agent while subagents stay free. Pairs well with task-board-init for enforcing manager-only orchestration. - All brewtools skills — text-optimize, debate, secrets-scan, deploy, provider-switch, and more. + All brewtools skills — text-optimize, secrets-scan, deploy, provider-switch, and more. Source files — SKILL.md and all six reference templates. diff --git a/web/docs/src/content/docs/brewtools/skills/text-optimize.mdx b/web/docs/src/content/docs/brewtools/skills/text-optimize.mdx index ff6681e..53e625d 100644 --- a/web/docs/src/content/docs/brewtools/skills/text-optimize.mdx +++ b/web/docs/src/content/docs/brewtools/skills/text-optimize.mdx @@ -142,7 +142,7 @@ Natural language also works: `"compress this for context"` → deep mode. `"slim Source code, rule references, and compression guides. - All brewtools skills — text, SSH, deploy, debate, plugin management. + All brewtools skills — text, SSH, deploy, plugin management.
    diff --git a/web/docs/src/content/docs/brewtools/skills/think-short.mdx b/web/docs/src/content/docs/brewtools/skills/think-short.mdx index 4bb37d1..b3661cf 100644 --- a/web/docs/src/content/docs/brewtools/skills/think-short.mdx +++ b/web/docs/src/content/docs/brewtools/skills/think-short.mdx @@ -1,177 +1,135 @@ --- -title: "Think Short" -description: "Toggle terse-output mode — inject brevity directives into main conversation and sub-agent prompts. Cuts preamble/filler/AI-artifacts in output-heavy workflows." -order: 3123 +title: "Think-Short" +description: "Install or remove terse-mode hooks that inject brevity directives at session start, every 10th prompt, and into subagents - project or global scope." +order: 3127 --- import { Badge, Callout, Card, CardGrid, Steps, UpdateNotice } from '../../../../components/mdx'; -# Think Short — terse mode toggle +# Think-Short — install terse-mode hooks - + - -**Output-token bloat kills long workflows.** Preamble ("Let me…"), filler phrases ("Great question!"), unsolicited alternatives, and chain-of-thought verbalization accumulate fast across many sub-agent turns. In a brewcode run with 10+ agents, this can waste thousands of tokens per phase and obscure signal with noise. - +## What it does - -**Three profiles, two injection points.** `light` / `medium` / `aggressive` profiles are injected once per session via SessionStart (cached, no repeat cost) and prepended fresh to every sub-agent prompt via PreToolUse:Task. Agents on the blacklist (`debate`, `docs-writer`, `architect`) are skipped automatically — they need full expressive output. - +`/brewtools:think-short` installs (or removes) a small set of hooks that inject a fixed brevity directive into the Claude Code session. Run the skill with a free-text intent — "make responses shorter", "stop the preamble" — and it asks via `AskUserQuestion` whether to apply to the current **Project** or **Globally**. It then copies four files into the target hooks directory — three hook scripts and `think-short-prompt.md` (the directive body) — and registers three hook entries in the appropriate `settings.json`. The task hook injects the directive by prepending it to the subagent prompt: `${injection}\n\n${tool_input.prompt}`. -## Quick reference +There are no profiles, no on/off toggle, no blacklist, and no persisted configuration. The only runtime state is an ephemeral per-session counter written to the OS temp directory. -| Command | Argument | Action | -|---------|----------|--------| -| `/brewtools:think-short on` | `[--scope global\|project]` | Enable terse mode, default scope = project | -| `/brewtools:think-short off` | — | Disable terse mode | -| `/brewtools:think-short profile ` | `light \| medium \| aggressive` | Set active profile | -| `/brewtools:think-short status` | — | Print effective state, sources, last 10 log lines | -| `/brewtools:think-short blacklist add ` | `` name | Add agent to injection skip-list (e.g. `docs-writer`) | -| `/brewtools:think-short blacklist remove ` | `` name | Remove agent from injection skip-list | +The same directive body is injected at every point: -Default scope for all mutations: `project`. Pass `--scope=global` to write globally. +``` +Be terse. Results first, no preamble/filler/sycophancy. ASCII only. +Grep before Read. Edit over Write. Parallel calls in one message. +Plan the full edit set, then execute. + +Keep code simple - do not over-engineer. Before writing anything new, +check existing code and libraries for the needed functionality. +Prefer extending or abstracting a similar class over adding a new one. +``` ## When to use -- Output-heavy brewcode runs with many sub-agent spawns — reduces noise per phase -- Long single sessions where preamble accumulates across compacts -- Cutting verbose boilerplate from agents that over-explain before acting -- Enforcing ASCII-only output and no smart-quotes in structured data pipelines +| Situation | Suggested invocation | +|-----------|---------------------| +| Long automated runs where preamble accumulates across many subagent turns | `/brewtools:think-short install in this project` | +| Consistent brevity across all projects on this machine | `/brewtools:think-short install globally` | +| Undo a previous installation | `/brewtools:think-short remove` | +| Output-heavy sessions where you want periodic reinforcement, not constant injection | Install project-scope — counter hook fires every 10 turns, not every turn | ## Examples -**Enable with default profile (medium):** +**Install for the current project:** ``` -/brewtools:think-short on +/brewtools:think-short make responses shorter, install in this project ``` -**Switch to aggressive:** +**Install globally (all projects on this machine):** ``` -/brewtools:think-short profile aggressive +/brewtools:think-short install for all my projects globally ``` -**Natural language (resolves to `on` + `profile aggressive`):** +**Remove a previously installed instance:** ``` -go all in +/brewtools:think-short remove the terse hooks ``` -> The skill also accepts Russian natural language (e.g. on/off, profile names, "go aggressive"). The complete RU+EN trigger list lives in the skill's SKILL.md. +In all three cases the skill calls `AskUserQuestion` to confirm scope (Project vs. Global) before writing any files. -**Natural language -- level shorthand:** -``` -level 3 -aggressive -max -level 2 -``` - -**Check current state:** -``` -/brewtools:think-short status -``` - -Expected status output: -``` -think-short: ENABLED (source: project-state) -profile: medium (source: project-state) -blacklist: [debate, docs-writer, architect] -state files: - project: .claude/brewtools/think-short.json (exists, updated 2026-04-20T12:34:56Z) - global: ~/.claude/plugins/data/brewtools-claude-brewcode/think-short.json (missing) -hardcoded defaults: enabled=false, profile=medium -env override: THINK_SHORT_DEFAULT=(unset) -recent log: - think-short: NL-prompt "go all in" -> resolved as on + profile aggressive -``` - -**Disable:** -``` -/brewtools:think-short off -``` - -## Profiles - -| Profile | Directives | Approx tokens | Typical use | -|---------|-----------|---------------|-------------| -| `light` | Be terse. Results first, reasoning only if asked. | ~10 tokens | Light reduction, keeps reasoning visible | -| `medium` | Be terse. No preamble, no filler. Skip AI phrasings. Direct answers. No sycophancy, no unsolicited alternatives. | ~35 tokens | Balanced — recommended default | -| `aggressive` | Be terse. ASCII only. No preamble, closing fluff, sycophancy, restatement, unsolicited alternatives, "as an AI" framing. Results first. Prefer Edit over Write. | ~60 tokens | Maximum suppression — long automated runs | - -## How it works +## Workflow
  • - SessionStart — full profile injection -

    When a new session starts, the SessionStart hook reads the effective state. If enabled, it injects the full profile text into additionalContext. This happens once per session — the profile is cached by the model context, so no repeat token cost on subsequent turns.

    + Run the skill with free-text intent +

    Any invocation of /brewtools:think-short triggers the skill. The argument is a free-text description of what you want — the skill reads intent from natural language, not flags.

  • - PreToolUse:Task — per-agent prepend -

    Before each sub-agent spawn (Task tool), the PreToolUse hook prepends the first 2 lines of the active profile to the agent's prompt. This ensures fresh injection even for agents spawned mid-session after context shifts. Agents in the blacklist are skipped entirely.

    + Scope confirmation (AskUserQuestion) +

    The skill asks: Project (writes to .claude/hooks/ + .claude/settings.json) or Global (writes to ~/.claude/hooks/ + ~/.claude/settings.json). No files are written until you answer.

  • - Blacklist filter -

    Agents named debate, docs-writer, and architect are excluded from injection by default. These agents need full expressive output — injecting brevity directives breaks their output quality. The blacklist is configurable via blacklist add/remove.

    + Hook files copied to target directory +

    Four files are copied: three hook scripts (think-short-session.mjs, think-short-prompt-counter.mjs, think-short-task.mjs) and think-short-prompt.md (the directive body text each hook reads at runtime). For global scope, writes go via Bash (the Write tool is blocked on ~/.claude/* in all permission modes).

  • - State merge — fallback chain -

    Effective state is computed by merging all sources in priority order. The skill reads and writes through helpers/state.mjs and helpers/safe-write.mjs (atomic write, O_NOFOLLOW, mode 0600). Project-scope state wins over global; env override wins over all.

    + Entries merged into settings.json +

    Three hook registrations are added to the matching settings.json — one per hook file. Existing entries from other skills are preserved.

    +
    +
  • +
  • +
    + Hooks active from the next session start +

    The SessionStart hook fires immediately on the next Claude Code session. The counter and Task hooks are active for the same session. Removal is the mirror: re-run the skill, confirm, and all four copied files plus their settings entries are stripped.

  • -## State files +## How it works -| Scope | Path | -|-------|------| -| Global | `$CLAUDE_PLUGIN_DATA/think-short.json` (fallback: `~/.claude/plugins/data/brewtools-claude-brewcode/think-short.json`) | -| Project | `/.claude/brewtools/think-short.json` | +Three hooks are installed, each targeting a different injection point: -Project scope overrides global field-by-field — `enabled`, `profile`, and `blacklist` can each come from different scopes. +| Hook | Event | Behavior | +|------|-------|----------| +| `think-short-session.mjs` | SessionStart | Injects the full directive; resets the per-session prompt counter in `$TMPDIR`; prunes stale counters from prior sessions | +| `think-short-prompt-counter.mjs` | UserPromptSubmit | Injects the directive on every 10th user prompt (turns 10, 20, 30 — never turn 1, which is covered by SessionStart) | +| `think-short-task.mjs` | PreToolUse:Task\|Agent | Injects the full directive into every spawned subagent; coexistence-safe (see below) | -## State schema +The counter hook keeps injection periodic, not per-turn. Turns 2–9 run without re-injection; at turn 10 the hook fires again to reinforce brevity after context drift. -```json -{ - "version": 1, - "enabled": false, - "profile": "medium", - "blacklist": ["debate", "docs-writer", "architect"], - "updated_at": "2026-04-20T12:00:00.000Z" -} -``` +## Installation targets -## Fallback chain +| Scope | Hook files written to | Settings file updated | +|-------|----------------------|-----------------------| +| Project | `.claude/hooks/` | `.claude/settings.json` | +| Global | `~/.claude/hooks/` | `~/.claude/settings.json` (via Bash) | -1. `THINK_SHORT_DEFAULT` env var (`on` / `off` / profile name) — highest priority -2. Project state: `/.claude/brewtools/think-short.json` -3. Global state: `$CLAUDE_PLUGIN_DATA/think-short.json` -4. Hardcoded `DEFAULT_THINK_SHORT` constant in `helpers/state.mjs` — `enabled=false`, `profile=medium`, `blacklist=[debate, docs-writer, architect]` +Global installs use the `Bash` tool for all file operations because `~/.claude/*` is a protected path — the `Write` and `Edit` tools are blocked there in every permission mode, including `bypassPermissions`. -## Injection timeline - -SessionStart profile injection fires once and is cached in the session context — no repeat cost. PreToolUse:Task injection fires fresh on every sub-agent spawn, so agents created later in a long session always receive the current profile. If you toggle or change profile mid-session, the new state applies to the next sub-agent spawn immediately; the main-conversation context retains the earlier SessionStart injection until the next session. - -## Logging +## Task hook injection -All state mutations and NL-prompt resolutions are logged at INFO level to `.claude/brewtools.log`. Filter with `grep 'think-short'` to see only think-short events. The `status` command tails the last 10 matching lines automatically. +`think-short-task.mjs` fires on `PreToolUse:Task` and injects the directive by prepending it to the subagent prompt: `${injection}\n\n${tool_input.prompt}`. Plugin paths resolve natively via `${CLAUDE_PLUGIN_ROOT}` at Task spawn — no coordination between hooks or shared module dependency is required. +## Removal + +Re-run the skill and describe removal intent. The skill deletes all four copied files (the three hook scripts and `think-short-prompt.md`) and strips the corresponding three entries from `settings.json`. It does not touch entries added by other skills or plugins. + - - Complementary token-reduction skill — rewrites prompts and docs for LLM efficiency rather than controlling output verbosity at runtime. + + Installs a HARD wall that blocks main-session edits and forces subagent delegation. Pairs with think-short for focused, low-noise automated runs. All brewtools skills and agents in one place. - Source code — skill, hooks integration, profile texts, and state helpers. + Hook scripts, install/remove logic, and coexistence implementation. diff --git a/web/docs/src/content/docs/faq.mdx b/web/docs/src/content/docs/faq.mdx index 5b10568..160da65 100644 --- a/web/docs/src/content/docs/faq.mdx +++ b/web/docs/src/content/docs/faq.mdx @@ -68,9 +68,9 @@ Paste the following prompt directly into the chat. The coercive phrasing is inte | Plugin | Purpose | Install command | |--------|---------|----------------| -| **brewcode** | Infinite task execution, 13 skills, 12 agents, 9 hooks | `claude plugin install brewcode@claude-brewcode` | +| **brewcode** | Infinite task execution, 9 skills, 10 agents, 9 hooks | `claude plugin install brewcode@claude-brewcode` | | **brewdoc** | Documentation tools: sync, memory, PDF, publishing | `claude plugin install brewdoc@claude-brewcode` | -| **brewtools** | Text utilities, [SSH](/brewtools/skills/ssh/), [deploy](/brewtools/skills/deploy/), [debate](/brewtools/skills/debate/), [plugin-update](/brewtools/skills/plugin-update/) | `claude plugin install brewtools@claude-brewcode` | +| **brewtools** | Text utilities, [SSH](/brewtools/skills/ssh/), [deploy](/brewtools/skills/deploy/), [plugin-update](/brewtools/skills/plugin-update/) | `claude plugin install brewtools@claude-brewcode` | | **brewui** | UI/visual/creative tools (placeholder, empty) | `claude plugin install brewui@claude-brewcode` | All four plugins install from the same `claude-brewcode` marketplace on GitHub. diff --git a/web/docs/src/content/docs/getting-started.mdx b/web/docs/src/content/docs/getting-started.mdx index 43671ec..9242ca9 100644 --- a/web/docs/src/content/docs/getting-started.mdx +++ b/web/docs/src/content/docs/getting-started.mdx @@ -18,10 +18,10 @@ import { Card, CardGrid, Callout, InstallPrompt, Spoiler } from '../../component - The core: infinite tasks, codebase exploration, quorum review, skill/agent/hook creation, prompt optimization. 13 skills · 12 agents · 9 hooks. + The core: infinite tasks, codebase exploration, quorum review, skill/agent/hook creation, prompt optimization. 9 skills · 10 agents · 9 hooks. - Universal utilities: prompt optimization, AI artifact removal, secrets scanning, SSH, deploy, evidence-based debates. 13 skills · 3 agents. + Universal utilities: prompt optimization, AI artifact removal, secrets scanning, SSH, deploy. 10 skills · 3 agents. UI / visual / creative tools (placeholder, currently empty). 0 skills · 0 agents. @@ -47,7 +47,7 @@ import { Card, CardGrid, Callout, InstallPrompt, Spoiler } from '../../component Knowledge is injected into every agent prompt and converted into project rules. - 32 skills and 16 specialized agents across 4 plugins. Built-in tools for + 25 skills and 14 specialized agents across 4 plugins. Built-in tools for creating your own skills, agents, and hooks. Prompt optimization included. @@ -56,8 +56,8 @@ import { Card, CardGrid, Callout, InstallPrompt, Spoiler } from '../../component | Plugin | Purpose | Skills | Agents | Hooks | |--------|---------|--------|--------|-------| -| **brewcode** | Infinite tasks, codebase exploration, review, prompt optimization, skill/agent creation | 13 | 12 | 9 | -| **brewtools** | Text utilities: prompt optimization, AI artifact removal, secrets scanning, SSH, deploy | 13 | 3 | — | +| **brewcode** | Infinite tasks, codebase exploration, review, prompt optimization, skill/agent creation | 9 | 10 | 9 | +| **brewtools** | Text utilities: prompt optimization, AI artifact removal, secrets scanning, SSH, deploy | 10 | 3 | — | | **brewui** | UI / visual / creative tools (placeholder, empty) | 0 | 0 | — | | **brewdoc** | Documentation tools: sync, generation, memory optimization, PDF conversion | 6 | 1 | — | diff --git a/web/docs/src/content/docs/installation.mdx b/web/docs/src/content/docs/installation.mdx index 6138bdb..b412a04 100644 --- a/web/docs/src/content/docs/installation.mdx +++ b/web/docs/src/content/docs/installation.mdx @@ -147,7 +147,7 @@ claude plugin update brewui@claude-brewcode Run your first infinite task in 15 minutes: [setup](/brewcode/skills/setup/), [spec](/brewcode/skills/spec/), [plan](/brewcode/skills/plan/), [start](/brewcode/skills/start/). - Architecture, concepts, all 32 skills, 16 agents, and 9 hooks. + Architecture, concepts, all 25 skills, 14 agents, and 9 hooks. diff --git a/web/docs/src/content/docs/quickstart.mdx b/web/docs/src/content/docs/quickstart.mdx index 57df775..5836f5e 100644 --- a/web/docs/src/content/docs/quickstart.mdx +++ b/web/docs/src/content/docs/quickstart.mdx @@ -97,11 +97,11 @@ By the end you will have a specification, a plan, and a running task with automa - 13 skills for development: infinite tasks, review, semantic search, + 9 skills for development: infinite tasks, review, semantic search, skill and agent creation, dynamic teams. - 13 skills for text utilities: prompt optimization, AI artifact removal, + 10 skills for text utilities: prompt optimization, AI artifact removal, secrets scanning, SSH, deploy. @@ -112,7 +112,7 @@ By the end you will have a specification, a plan, and a running task with automa doc generation, memory optimization, PDF conversion, publishing. - Full list of 13 brewcode skills with commands, parameters, and dependencies. + Full list of 9 brewcode skills with commands, parameters, and dependencies. Create 5-20 project-specific agents with self-selection and performance tracking. diff --git a/web/docs/src/utils/navigation.ts b/web/docs/src/utils/navigation.ts index e1e82cd..ffb49ea 100644 --- a/web/docs/src/utils/navigation.ts +++ b/web/docs/src/utils/navigation.ts @@ -27,13 +27,12 @@ export const navigation: NavSection[] = [ title: 'Skills', slug: 'brewcode/skills', children: [ - { title: 'setup', slug: 'brewcode/skills/setup' }, { title: 'spec', slug: 'brewcode/skills/spec' }, + { title: 'superreview', slug: 'brewcode/skills/superreview' }, { title: 'teams', slug: 'brewcode/skills/teams' }, { title: 'convention', slug: 'brewcode/skills/convention' }, { title: 'rules', slug: 'brewcode/skills/rules' }, { title: 'grepai', slug: 'brewcode/skills/grepai' }, - { title: 'standards-review', slug: 'brewcode/skills/standards-review' }, { title: 'review (dynamic)', slug: 'brewcode/skills/review' }, { title: 'skills', slug: 'brewcode/skills/skills' }, { title: 'agents', slug: 'brewcode/skills/agents' }, @@ -67,14 +66,11 @@ export const navigation: NavSection[] = [ title: 'Skills', slug: 'brewtools/skills', children: [ - { title: 'agent-toggle', slug: 'brewtools/skills/agent-toggle' }, - { title: 'debate', slug: 'brewtools/skills/debate' }, { title: 'deploy', slug: 'brewtools/skills/deploy' }, { title: 'manager', slug: 'brewtools/skills/manager' }, { title: 'plugin-update', slug: 'brewtools/skills/plugin-update' }, { title: 'provider-switch', slug: 'brewtools/skills/provider-switch' }, { title: 'secrets-scan', slug: 'brewtools/skills/secrets-scan' }, - { title: 'skill-toggle', slug: 'brewtools/skills/skill-toggle' }, { title: 'task-board-init', slug: 'brewtools/skills/task-board-init' }, { title: 'ssh', slug: 'brewtools/skills/ssh' }, { title: 'text-human', slug: 'brewtools/skills/text-human' },