mirror of
https://github.com/cexll/myclaude.git
synced 2026-02-05 02:30:26 +08:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
326ad85c74 | ||
|
|
e66bec0083 | ||
|
|
eb066395c2 | ||
|
|
b49dad842a | ||
|
|
d98086c661 | ||
|
|
0420646258 | ||
|
|
19a8d8e922 | ||
|
|
669b1d82ce | ||
|
|
a21c31fd89 | ||
|
|
773f133111 | ||
|
|
4f5d24531c | ||
|
|
cc24d43c8b | ||
|
|
27d4ac8afd |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -7,3 +7,4 @@
|
||||
__pycache__
|
||||
.coverage
|
||||
coverage.out
|
||||
references
|
||||
|
||||
635
README.md
635
README.md
@@ -3,29 +3,13 @@
|
||||
# Claude Code Multi-Agent Workflow System
|
||||
|
||||
[](https://smithery.ai/skills?ns=cexll&utm_source=github&utm_medium=badge)
|
||||
|
||||
|
||||
[](https://www.gnu.org/licenses/agpl-3.0)
|
||||
[](https://claude.ai/code)
|
||||
[](https://github.com/cexll/myclaude)
|
||||
[](https://github.com/cexll/myclaude)
|
||||
|
||||
> AI-powered development automation with multi-backend execution (Codex/Claude/Gemini)
|
||||
> AI-powered development automation with multi-backend execution (Codex/Claude/Gemini/OpenCode)
|
||||
|
||||
## Core Concept: Multi-Backend Architecture
|
||||
|
||||
This system leverages a **dual-agent architecture** with pluggable AI backends:
|
||||
|
||||
| Role | Agent | Responsibility |
|
||||
|------|-------|----------------|
|
||||
| **Orchestrator** | Claude Code | Planning, context gathering, verification, user interaction |
|
||||
| **Executor** | codeagent-wrapper | Code editing, test execution (Codex/Claude/Gemini backends) |
|
||||
|
||||
**Why this separation?**
|
||||
- Claude Code excels at understanding context and orchestrating complex workflows
|
||||
- Specialized backends (Codex for code, Claude for reasoning, Gemini for prototyping) excel at focused execution
|
||||
- Backend selection via `--backend codex|claude|gemini` matches the model to the task
|
||||
|
||||
## Quick Start(Please execute in Powershell on Windows)
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
git clone https://github.com/cexll/myclaude.git
|
||||
@@ -33,199 +17,23 @@ cd myclaude
|
||||
python3 install.py --install-dir ~/.claude
|
||||
```
|
||||
|
||||
## Workflows Overview
|
||||
## Modules Overview
|
||||
|
||||
### 0. OmO Multi-Agent Orchestrator (Recommended for Complex Tasks)
|
||||
|
||||
**Intelligent multi-agent orchestration that routes tasks to specialized agents based on risk signals.**
|
||||
|
||||
```bash
|
||||
/omo "analyze and fix this authentication bug"
|
||||
```
|
||||
|
||||
**Agent Hierarchy:**
|
||||
| Agent | Role | Backend | Model |
|
||||
|-------|------|---------|-------|
|
||||
| `oracle` | Technical advisor | Claude | claude-opus-4-5 |
|
||||
| `librarian` | External research | Claude | claude-sonnet-4-5 |
|
||||
| `explore` | Codebase search | OpenCode | grok-code |
|
||||
| `develop` | Code implementation | Codex | gpt-5.2 |
|
||||
| `frontend-ui-ux-engineer` | UI/UX specialist | Gemini | gemini-3-pro |
|
||||
| `document-writer` | Documentation | Gemini | gemini-3-flash |
|
||||
|
||||
**Routing Signals (Not Fixed Pipeline):**
|
||||
- Code location unclear → `explore`
|
||||
- External library/API → `librarian`
|
||||
- Risky/multi-file change → `oracle`
|
||||
- Implementation needed → `develop` / `frontend-ui-ux-engineer`
|
||||
|
||||
**Common Recipes:**
|
||||
- Explain code: `explore`
|
||||
- Small fix with known location: `develop` directly
|
||||
- Bug fix, location unknown: `explore → develop`
|
||||
- Cross-cutting refactor: `explore → oracle → develop`
|
||||
- External API integration: `explore + librarian → oracle → develop`
|
||||
|
||||
**Best For:** Complex bug investigation, multi-file refactoring, architecture decisions
|
||||
|
||||
---
|
||||
|
||||
### 1. Dev Workflow (Recommended)
|
||||
|
||||
**The primary workflow for most development tasks.**
|
||||
|
||||
```bash
|
||||
/dev "implement user authentication with JWT"
|
||||
```
|
||||
|
||||
**6-Step Process:**
|
||||
1. **Requirements Clarification** - Interactive Q&A to clarify scope
|
||||
2. **Codex Deep Analysis** - Codebase exploration and architecture decisions
|
||||
3. **Dev Plan Generation** - Structured task breakdown with test requirements
|
||||
4. **Parallel Execution** - Codex executes tasks concurrently
|
||||
5. **Coverage Validation** - Enforce ≥90% test coverage
|
||||
6. **Completion Summary** - Report with file changes and coverage stats
|
||||
|
||||
**Key Features:**
|
||||
- Claude Code orchestrates, Codex executes all code changes
|
||||
- Automatic task parallelization for speed
|
||||
- Mandatory 90% test coverage gate
|
||||
- Rollback on failure
|
||||
|
||||
**Best For:** Feature development, refactoring, bug fixes with tests
|
||||
|
||||
---
|
||||
|
||||
### 2. BMAD Agile Workflow
|
||||
|
||||
**Full enterprise agile methodology with 6 specialized agents.**
|
||||
|
||||
```bash
|
||||
/bmad-pilot "build e-commerce checkout system"
|
||||
```
|
||||
|
||||
**Agents:**
|
||||
| Agent | Role |
|
||||
|-------|------|
|
||||
| Product Owner | Requirements & user stories |
|
||||
| Architect | System design & tech decisions |
|
||||
| Tech Lead | Sprint planning & task breakdown |
|
||||
| Developer | Implementation |
|
||||
| Code Reviewer | Quality assurance |
|
||||
| QA Engineer | Testing & validation |
|
||||
|
||||
**Process:**
|
||||
```
|
||||
Requirements → Architecture → Sprint Plan → Development → Review → QA
|
||||
↓ ↓ ↓ ↓ ↓ ↓
|
||||
PRD.md DESIGN.md SPRINT.md Code REVIEW.md TEST.md
|
||||
```
|
||||
|
||||
**Best For:** Large features, team coordination, enterprise projects
|
||||
|
||||
---
|
||||
|
||||
### 3. Requirements-Driven Workflow
|
||||
|
||||
**Lightweight requirements-to-code pipeline.**
|
||||
|
||||
```bash
|
||||
/requirements-pilot "implement API rate limiting"
|
||||
```
|
||||
|
||||
**Process:**
|
||||
1. Requirements generation with quality scoring
|
||||
2. Implementation planning
|
||||
3. Code generation
|
||||
4. Review and testing
|
||||
|
||||
**Best For:** Quick prototypes, well-defined features
|
||||
|
||||
---
|
||||
|
||||
### 4. Development Essentials
|
||||
|
||||
**Direct commands for daily coding tasks.**
|
||||
|
||||
| Command | Purpose |
|
||||
|---------|---------|
|
||||
| `/code` | Implement a feature |
|
||||
| `/debug` | Debug an issue |
|
||||
| `/test` | Write tests |
|
||||
| `/review` | Code review |
|
||||
| `/optimize` | Performance optimization |
|
||||
| `/refactor` | Code refactoring |
|
||||
| `/docs` | Documentation |
|
||||
|
||||
**Best For:** Quick tasks, no workflow overhead needed
|
||||
|
||||
## Enterprise Workflow Features
|
||||
|
||||
- **Multi-backend execution:** `codeagent-wrapper --backend codex|claude|gemini` (default `codex`) so you can match the model to the task without changing workflows.
|
||||
- **GitHub workflow commands:** `/gh-create-issue "short need"` creates structured issues; `/gh-issue-implement 123` pulls issue #123, drives development, and prepares the PR.
|
||||
- **Skills + hooks activation:** .claude/hooks run automation (tests, reviews), while `.claude/skills/skill-rules.json` auto-suggests the right skills. Keep hooks enabled in `.claude/settings.json` to activate the enterprise workflow helpers.
|
||||
|
||||
---
|
||||
|
||||
## Version Requirements
|
||||
|
||||
### Codex CLI
|
||||
**Minimum version:** Check compatibility with your installation
|
||||
|
||||
The codeagent-wrapper uses these Codex CLI features:
|
||||
- `codex e` - Execute commands (shorthand for `codex exec`)
|
||||
- `--skip-git-repo-check` - Skip git repository validation
|
||||
- `--json` - JSON stream output format
|
||||
- `-C <workdir>` - Set working directory
|
||||
- `resume <session_id>` - Resume previous sessions
|
||||
|
||||
**Verify Codex CLI is installed:**
|
||||
```bash
|
||||
which codex
|
||||
codex --version
|
||||
```
|
||||
|
||||
### Claude CLI
|
||||
**Minimum version:** Check compatibility with your installation
|
||||
|
||||
Required features:
|
||||
- `--output-format stream-json` - Streaming JSON output format
|
||||
- `--setting-sources` - Control setting sources (prevents infinite recursion)
|
||||
- `--dangerously-skip-permissions` - Skip permission prompts (use with caution)
|
||||
- `-p` - Prompt input flag
|
||||
- `-r <session_id>` - Resume sessions
|
||||
|
||||
**Security Note:** The wrapper adds `--dangerously-skip-permissions` for Claude by default. Set `CODEAGENT_SKIP_PERMISSIONS=false` to disable if you need permission prompts.
|
||||
|
||||
**Verify Claude CLI is installed:**
|
||||
```bash
|
||||
which claude
|
||||
claude --version
|
||||
```
|
||||
|
||||
### Gemini CLI
|
||||
**Minimum version:** Check compatibility with your installation
|
||||
|
||||
Required features:
|
||||
- `-o stream-json` - JSON stream output format
|
||||
- `-y` - Auto-approve prompts (non-interactive mode)
|
||||
- `-r <session_id>` - Resume sessions
|
||||
- `-p` - Prompt input flag
|
||||
|
||||
**Verify Gemini CLI is installed:**
|
||||
```bash
|
||||
which gemini
|
||||
gemini --version
|
||||
```
|
||||
|
||||
---
|
||||
| Module | Description | Documentation |
|
||||
|--------|-------------|---------------|
|
||||
| [do](skills/do/README.md) | **Recommended** - 7-phase feature development with codeagent orchestration | `/do` command |
|
||||
| [dev](dev-workflow/README.md) | Lightweight dev workflow with Codex integration | `/dev` command |
|
||||
| [omo](skills/omo/README.md) | Multi-agent orchestration with intelligent routing | `/omo` command |
|
||||
| [bmad](bmad-agile-workflow/README.md) | BMAD agile workflow with 6 specialized agents | `/bmad-pilot` command |
|
||||
| [requirements](requirements-driven-workflow/README.md) | Lightweight requirements-to-code pipeline | `/requirements-pilot` command |
|
||||
| [essentials](development-essentials/README.md) | Core development commands and utilities | `/code`, `/debug`, etc. |
|
||||
| [sparv](skills/sparv/README.md) | SPARV workflow (Specify→Plan→Act→Review→Vault) | `/sparv` command |
|
||||
| course | Course development (combines dev + product-requirements + test-cases) | Composite module |
|
||||
|
||||
## Installation
|
||||
|
||||
### Modular Installation (Recommended)
|
||||
|
||||
```bash
|
||||
# Install all enabled modules (dev + essentials by default)
|
||||
# Install all enabled modules
|
||||
python3 install.py --install-dir ~/.claude
|
||||
|
||||
# Install specific module
|
||||
@@ -234,173 +42,72 @@ python3 install.py --module dev
|
||||
# List available modules
|
||||
python3 install.py --list-modules
|
||||
|
||||
# Force overwrite existing files
|
||||
# Force overwrite
|
||||
python3 install.py --force
|
||||
```
|
||||
|
||||
### Available Modules
|
||||
### Module Configuration
|
||||
|
||||
| Module | Default | Description |
|
||||
|--------|---------|-------------|
|
||||
| `dev` | ✓ Enabled | Dev workflow + Codex integration |
|
||||
| `essentials` | ✓ Enabled | Core development commands |
|
||||
| `bmad` | Disabled | Full BMAD agile workflow |
|
||||
| `requirements` | Disabled | Requirements-driven workflow |
|
||||
|
||||
### What Gets Installed
|
||||
|
||||
```
|
||||
~/.claude/
|
||||
├── bin/
|
||||
│ └── codeagent-wrapper # Main executable
|
||||
├── CLAUDE.md # Core instructions and role definition
|
||||
├── commands/ # Slash commands (/dev, /code, etc.)
|
||||
├── agents/ # Agent definitions
|
||||
├── skills/
|
||||
│ └── codex/
|
||||
│ └── SKILL.md # Codex integration skill
|
||||
├── config.json # Configuration
|
||||
└── installed_modules.json # Installation status
|
||||
```
|
||||
|
||||
### Customizing Installation Directory
|
||||
|
||||
By default, myclaude installs to `~/.claude`. You can customize this using the `INSTALL_DIR` environment variable:
|
||||
|
||||
```bash
|
||||
# Install to custom directory
|
||||
INSTALL_DIR=/opt/myclaude bash install.sh
|
||||
|
||||
# Update your PATH accordingly
|
||||
export PATH="/opt/myclaude/bin:$PATH"
|
||||
```
|
||||
|
||||
**Directory Structure:**
|
||||
- `$INSTALL_DIR/bin/` - codeagent-wrapper binary
|
||||
- `$INSTALL_DIR/skills/` - Skill definitions
|
||||
- `$INSTALL_DIR/config.json` - Configuration file
|
||||
- `$INSTALL_DIR/commands/` - Slash command definitions
|
||||
- `$INSTALL_DIR/agents/` - Agent definitions
|
||||
|
||||
**Note:** When using a custom installation directory, ensure that `$INSTALL_DIR/bin` is added to your `PATH` environment variable.
|
||||
|
||||
### Configuration
|
||||
|
||||
Edit `config.json` to customize:
|
||||
Edit `config.json` to enable/disable modules:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "1.0",
|
||||
"install_dir": "~/.claude",
|
||||
"modules": {
|
||||
"dev": {
|
||||
"enabled": true,
|
||||
"operations": [
|
||||
{"type": "merge_dir", "source": "dev-workflow"},
|
||||
{"type": "copy_file", "source": "memorys/CLAUDE.md", "target": "CLAUDE.md"},
|
||||
{"type": "copy_file", "source": "skills/codex/SKILL.md", "target": "skills/codex/SKILL.md"},
|
||||
{"type": "run_command", "command": "bash install.sh"}
|
||||
]
|
||||
}
|
||||
"dev": { "enabled": true },
|
||||
"bmad": { "enabled": false },
|
||||
"requirements": { "enabled": false },
|
||||
"essentials": { "enabled": false },
|
||||
"omo": { "enabled": false },
|
||||
"sparv": { "enabled": false },
|
||||
"do": { "enabled": false },
|
||||
"course": { "enabled": false }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Operation Types:**
|
||||
| Type | Description |
|
||||
|------|-------------|
|
||||
| `merge_dir` | Merge subdirs (commands/, agents/) into install dir |
|
||||
| `copy_dir` | Copy entire directory |
|
||||
| `copy_file` | Copy single file to target path |
|
||||
| `run_command` | Execute shell command |
|
||||
|
||||
---
|
||||
|
||||
## Codex Integration
|
||||
|
||||
The `codex` skill enables Claude Code to delegate code execution to Codex CLI.
|
||||
|
||||
### Usage in Workflows
|
||||
|
||||
```bash
|
||||
# Codex is invoked via the skill
|
||||
codeagent-wrapper - <<'EOF'
|
||||
implement @src/auth.ts with JWT validation
|
||||
EOF
|
||||
```
|
||||
|
||||
### Parallel Execution
|
||||
|
||||
```bash
|
||||
codeagent-wrapper --parallel <<'EOF'
|
||||
---TASK---
|
||||
id: backend_api
|
||||
workdir: /project/backend
|
||||
---CONTENT---
|
||||
implement REST endpoints for /api/users
|
||||
|
||||
---TASK---
|
||||
id: frontend_ui
|
||||
workdir: /project/frontend
|
||||
dependencies: backend_api
|
||||
---CONTENT---
|
||||
create React components consuming the API
|
||||
EOF
|
||||
```
|
||||
|
||||
### Install Codex Wrapper
|
||||
|
||||
```bash
|
||||
# Automatic (via dev module)
|
||||
python3 install.py --module dev
|
||||
|
||||
# Manual
|
||||
bash install.sh
|
||||
```
|
||||
|
||||
#### Windows
|
||||
|
||||
Windows installs place `codeagent-wrapper.exe` in `%USERPROFILE%\bin`.
|
||||
|
||||
```powershell
|
||||
# PowerShell (recommended)
|
||||
powershell -ExecutionPolicy Bypass -File install.ps1
|
||||
|
||||
# Batch (cmd)
|
||||
install.bat
|
||||
```
|
||||
|
||||
**Add to PATH** (if installer doesn't detect it):
|
||||
|
||||
```powershell
|
||||
# PowerShell - persistent for current user
|
||||
[Environment]::SetEnvironmentVariable('PATH', "$HOME\bin;" + [Environment]::GetEnvironmentVariable('PATH','User'), 'User')
|
||||
|
||||
# PowerShell - current session only
|
||||
$Env:PATH = "$HOME\bin;$Env:PATH"
|
||||
```
|
||||
|
||||
```batch
|
||||
REM cmd.exe - persistent for current user (use PowerShell method above instead)
|
||||
REM WARNING: This expands %PATH% which includes system PATH, causing duplication
|
||||
REM Note: Using reg add instead of setx to avoid 1024-character truncation limit
|
||||
reg add "HKCU\Environment" /v Path /t REG_EXPAND_SZ /d "%USERPROFILE%\bin;%PATH%" /f
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Workflow Selection Guide
|
||||
|
||||
| Scenario | Recommended Workflow |
|
||||
|----------|---------------------|
|
||||
| New feature with tests | `/dev` |
|
||||
| Quick bug fix | `/debug` or `/code` |
|
||||
| Large multi-sprint feature | `/bmad-pilot` |
|
||||
| Prototype or POC | `/requirements-pilot` |
|
||||
| Code review | `/review` |
|
||||
| Performance issue | `/optimize` |
|
||||
| Scenario | Recommended |
|
||||
|----------|-------------|
|
||||
| Feature development (default) | `/do` |
|
||||
| Lightweight feature | `/dev` |
|
||||
| Bug investigation + fix | `/omo` |
|
||||
| Large enterprise project | `/bmad-pilot` |
|
||||
| Quick prototype | `/requirements-pilot` |
|
||||
| Simple task | `/code`, `/debug` |
|
||||
|
||||
---
|
||||
## Core Architecture
|
||||
|
||||
| Role | Agent | Responsibility |
|
||||
|------|-------|----------------|
|
||||
| **Orchestrator** | Claude Code | Planning, context gathering, verification |
|
||||
| **Executor** | codeagent-wrapper | Code editing, test execution (Codex/Claude/Gemini/OpenCode) |
|
||||
|
||||
## Backend CLI Requirements
|
||||
|
||||
| Backend | Required Features |
|
||||
|---------|-------------------|
|
||||
| Codex | `codex e`, `--json`, `-C`, `resume` |
|
||||
| Claude | `--output-format stream-json`, `-r` |
|
||||
| Gemini | `-o stream-json`, `-y`, `-r` |
|
||||
|
||||
## Directory Structure After Installation
|
||||
|
||||
```
|
||||
~/.claude/
|
||||
├── bin/codeagent-wrapper
|
||||
├── CLAUDE.md
|
||||
├── commands/
|
||||
├── agents/
|
||||
├── skills/
|
||||
└── config.json
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
- [Codeagent-Wrapper Guide](docs/CODEAGENT-WRAPPER.md)
|
||||
- [Hooks Documentation](docs/HOOKS.md)
|
||||
- [codeagent-wrapper](codeagent-wrapper/README.md)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
@@ -408,214 +115,38 @@ reg add "HKCU\Environment" /v Path /t REG_EXPAND_SZ /d "%USERPROFILE%\bin;%PATH%
|
||||
|
||||
**Codex wrapper not found:**
|
||||
```bash
|
||||
# Installer auto-adds PATH, check if configured
|
||||
if [[ ":$PATH:" != *":$HOME/.claude/bin:"* ]]; then
|
||||
echo "PATH not configured. Reinstalling..."
|
||||
bash install.sh
|
||||
fi
|
||||
|
||||
# Or manually add (idempotent command)
|
||||
[[ ":$PATH:" != *":$HOME/.claude/bin:"* ]] && echo 'export PATH="$HOME/.claude/bin:$PATH"' >> ~/.zshrc
|
||||
```
|
||||
|
||||
**Permission denied:**
|
||||
```bash
|
||||
python3 install.py --install-dir ~/.claude --force
|
||||
bash install.sh
|
||||
```
|
||||
|
||||
**Module not loading:**
|
||||
```bash
|
||||
# Check installation status
|
||||
cat ~/.claude/installed_modules.json
|
||||
|
||||
# Reinstall specific module
|
||||
python3 install.py --module dev --force
|
||||
python3 install.py --module <name> --force
|
||||
```
|
||||
|
||||
### Version Compatibility Issues
|
||||
|
||||
**Backend CLI not found:**
|
||||
**Backend CLI errors:**
|
||||
```bash
|
||||
# Check if backend CLIs are installed
|
||||
which codex
|
||||
which claude
|
||||
which gemini
|
||||
|
||||
# Install missing backends
|
||||
# Codex: Follow installation instructions at https://codex.docs
|
||||
# Claude: Follow installation instructions at https://claude.ai/docs
|
||||
# Gemini: Follow installation instructions at https://ai.google.dev/docs
|
||||
which codex && codex --version
|
||||
which claude && claude --version
|
||||
which gemini && gemini --version
|
||||
```
|
||||
|
||||
**Unsupported CLI flags:**
|
||||
```bash
|
||||
# If you see errors like "unknown flag" or "invalid option"
|
||||
## FAQ
|
||||
|
||||
# Check backend CLI version
|
||||
codex --version
|
||||
claude --version
|
||||
gemini --version
|
||||
| Issue | Solution |
|
||||
|-------|----------|
|
||||
| "Unknown event format" | Logging display issue, can be ignored |
|
||||
| Gemini can't read .gitignore files | Remove from .gitignore or use different backend |
|
||||
| `/dev` slow | Check logs, try faster model, use single repo |
|
||||
| Codex permission denied | Set `approval_policy = "never"` in ~/.codex/config.yaml |
|
||||
|
||||
# For Codex: Ensure it supports `e`, `--skip-git-repo-check`, `--json`, `-C`, and `resume`
|
||||
# For Claude: Ensure it supports `--output-format stream-json`, `--setting-sources`, `-r`
|
||||
# For Gemini: Ensure it supports `-o stream-json`, `-y`, `-r`, `-p`
|
||||
|
||||
# Update your backend CLI to the latest version if needed
|
||||
```
|
||||
|
||||
**JSON parsing errors:**
|
||||
```bash
|
||||
# If you see "failed to parse JSON output" errors
|
||||
|
||||
# Verify the backend outputs stream-json format
|
||||
codex e --json "test task" # Should output newline-delimited JSON
|
||||
claude --output-format stream-json -p "test" # Should output stream JSON
|
||||
|
||||
# If not, your backend CLI version may be too old or incompatible
|
||||
```
|
||||
|
||||
**Infinite recursion with Claude backend:**
|
||||
```bash
|
||||
# The wrapper prevents this with `--setting-sources ""` flag
|
||||
# If you still see recursion, ensure your Claude CLI supports this flag
|
||||
|
||||
claude --help | grep "setting-sources"
|
||||
|
||||
# If flag is not supported, upgrade Claude CLI
|
||||
```
|
||||
|
||||
**Session resume failures:**
|
||||
```bash
|
||||
# Check if session ID is valid
|
||||
codex history # List recent sessions
|
||||
claude history
|
||||
|
||||
# Ensure backend CLI supports session resumption
|
||||
codex resume <session_id> "test" # Should continue from previous session
|
||||
claude -r <session_id> "test"
|
||||
|
||||
# If not supported, use new sessions instead of resume mode
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## FAQ (Frequently Asked Questions)
|
||||
|
||||
### Q1: `codeagent-wrapper` execution fails with "Unknown event format"
|
||||
|
||||
**Problem:**
|
||||
```
|
||||
Unknown event format: {"type":"turn.started"}
|
||||
Unknown event format: {"type":"assistant", ...}
|
||||
```
|
||||
|
||||
**Solution:**
|
||||
This is a logging event format display issue and does not affect actual functionality. It will be fixed in the next version. You can ignore these log outputs.
|
||||
|
||||
**Related Issue:** [#96](https://github.com/cexll/myclaude/issues/96)
|
||||
|
||||
---
|
||||
|
||||
### Q2: Gemini cannot read files ignored by `.gitignore`
|
||||
|
||||
**Problem:**
|
||||
When using `codeagent-wrapper --backend gemini`, files in directories like `.claude/` that are ignored by `.gitignore` cannot be read.
|
||||
|
||||
**Solution:**
|
||||
- **Option 1:** Remove `.claude/` from your `.gitignore` file
|
||||
- **Option 2:** Ensure files that need to be read are not in `.gitignore` list
|
||||
|
||||
**Related Issue:** [#75](https://github.com/cexll/myclaude/issues/75)
|
||||
|
||||
---
|
||||
|
||||
### Q3: `/dev` command parallel execution is very slow
|
||||
|
||||
**Problem:**
|
||||
Using `/dev` command for simple features takes too long (over 30 minutes) with no visibility into task progress.
|
||||
|
||||
**Solution:**
|
||||
1. **Check logs:** Review `C:\Users\User\AppData\Local\Temp\codeagent-wrapper-*.log` to identify bottlenecks
|
||||
2. **Adjust backend:**
|
||||
- Try faster models like `gpt-5.1-codex-max`
|
||||
- Running in WSL may be significantly faster
|
||||
3. **Workspace:** Use a single repository instead of monorepo with multiple sub-projects
|
||||
|
||||
**Related Issue:** [#77](https://github.com/cexll/myclaude/issues/77)
|
||||
|
||||
---
|
||||
|
||||
### Q4: Codex permission denied with new Go version
|
||||
|
||||
**Problem:**
|
||||
After upgrading to the new Go-based Codex implementation, execution fails with permission denied errors.
|
||||
|
||||
**Solution:**
|
||||
Add the following configuration to `~/.codex/config.yaml` (Windows: `c:\user\.codex\config.toml`):
|
||||
```yaml
|
||||
model = "gpt-5.1-codex-max"
|
||||
model_reasoning_effort = "high"
|
||||
model_reasoning_summary = "detailed"
|
||||
approval_policy = "never"
|
||||
sandbox_mode = "workspace-write"
|
||||
disable_response_storage = true
|
||||
network_access = true
|
||||
```
|
||||
|
||||
**Key settings:**
|
||||
- `approval_policy = "never"` - Remove approval restrictions
|
||||
- `sandbox_mode = "workspace-write"` - Allow workspace write access
|
||||
- `network_access = true` - Enable network access
|
||||
|
||||
**Related Issue:** [#31](https://github.com/cexll/myclaude/issues/31)
|
||||
|
||||
---
|
||||
|
||||
### Q5: How to disable default bypass/skip-permissions mode
|
||||
|
||||
**Background:**
|
||||
By default, codeagent-wrapper enables bypass mode for both Codex and Claude backends:
|
||||
- `CODEX_BYPASS_SANDBOX=true` - Bypasses Codex sandbox restrictions
|
||||
- `CODEAGENT_SKIP_PERMISSIONS=true` - Skips Claude permission prompts
|
||||
|
||||
**To disable (if you need sandbox/permission protection):**
|
||||
```bash
|
||||
export CODEX_BYPASS_SANDBOX=false
|
||||
export CODEAGENT_SKIP_PERMISSIONS=false
|
||||
```
|
||||
|
||||
Or add to your shell profile (`~/.zshrc` or `~/.bashrc`):
|
||||
```bash
|
||||
echo 'export CODEX_BYPASS_SANDBOX=false' >> ~/.zshrc
|
||||
echo 'export CODEAGENT_SKIP_PERMISSIONS=false' >> ~/.zshrc
|
||||
```
|
||||
|
||||
**Note:** Disabling bypass mode will require manual approval for certain operations.
|
||||
|
||||
---
|
||||
|
||||
**Still having issues?** Visit [GitHub Issues](https://github.com/cexll/myclaude/issues) to search or report new issues.
|
||||
|
||||
---
|
||||
|
||||
## Documentation
|
||||
- **[Codeagent-Wrapper Guide](docs/CODEAGENT-WRAPPER.md)** - Multi-backend execution wrapper
|
||||
- **[Hooks Documentation](docs/HOOKS.md)** - Custom hooks and automation
|
||||
|
||||
### Additional Resources
|
||||
- **[Installation Log](install.log)** - Installation history and troubleshooting
|
||||
|
||||
---
|
||||
See [GitHub Issues](https://github.com/cexll/myclaude/issues) for more.
|
||||
|
||||
## License
|
||||
|
||||
AGPL-3.0 License - see [LICENSE](LICENSE)
|
||||
AGPL-3.0 - see [LICENSE](LICENSE)
|
||||
|
||||
## Support
|
||||
|
||||
- **Issues**: [GitHub Issues](https://github.com/cexll/myclaude/issues)
|
||||
- **Documentation**: [docs/](docs/)
|
||||
|
||||
---
|
||||
|
||||
**Claude Code + Codex = Better Development** - Orchestration meets execution.
|
||||
- [GitHub Issues](https://github.com/cexll/myclaude/issues)
|
||||
- [Documentation](docs/)
|
||||
|
||||
517
README_CN.md
517
README_CN.md
@@ -2,25 +2,11 @@
|
||||
|
||||
[](https://www.gnu.org/licenses/agpl-3.0)
|
||||
[](https://claude.ai/code)
|
||||
[](https://github.com/cexll/myclaude)
|
||||
[](https://github.com/cexll/myclaude)
|
||||
|
||||
> AI 驱动的开发自动化 - 多后端执行架构 (Codex/Claude/Gemini)
|
||||
> AI 驱动的开发自动化 - 多后端执行架构 (Codex/Claude/Gemini/OpenCode)
|
||||
|
||||
## 核心概念:多后端架构
|
||||
|
||||
本系统采用**双智能体架构**与可插拔 AI 后端:
|
||||
|
||||
| 角色 | 智能体 | 职责 |
|
||||
|------|-------|------|
|
||||
| **编排者** | Claude Code | 规划、上下文收集、验证、用户交互 |
|
||||
| **执行者** | codeagent-wrapper | 代码编辑、测试执行(Codex/Claude/Gemini 后端)|
|
||||
|
||||
**为什么分离?**
|
||||
- Claude Code 擅长理解上下文和编排复杂工作流
|
||||
- 专业后端(Codex 擅长代码、Claude 擅长推理、Gemini 擅长原型)专注执行
|
||||
- 通过 `--backend codex|claude|gemini` 匹配模型与任务
|
||||
|
||||
## 快速开始(windows上请在Powershell中执行)
|
||||
## 快速开始
|
||||
|
||||
```bash
|
||||
git clone https://github.com/cexll/myclaude.git
|
||||
@@ -28,72 +14,125 @@ cd myclaude
|
||||
python3 install.py --install-dir ~/.claude
|
||||
```
|
||||
|
||||
## 工作流概览
|
||||
## 模块概览
|
||||
|
||||
### 0. OmO 多智能体编排器(复杂任务推荐)
|
||||
| 模块 | 描述 | 文档 |
|
||||
|------|------|------|
|
||||
| [do](skills/do/README.md) | **推荐** - 7 阶段功能开发 + codeagent 编排 | `/do` 命令 |
|
||||
| [dev](dev-workflow/README.md) | 轻量级开发工作流 + Codex 集成 | `/dev` 命令 |
|
||||
| [omo](skills/omo/README.md) | 多智能体编排 + 智能路由 | `/omo` 命令 |
|
||||
| [bmad](bmad-agile-workflow/README.md) | BMAD 敏捷工作流 + 6 个专业智能体 | `/bmad-pilot` 命令 |
|
||||
| [requirements](requirements-driven-workflow/README.md) | 轻量级需求到代码流水线 | `/requirements-pilot` 命令 |
|
||||
| [essentials](development-essentials/README.md) | 核心开发命令和工具 | `/code`, `/debug` 等 |
|
||||
| [sparv](skills/sparv/README.md) | SPARV 工作流 (Specify→Plan→Act→Review→Vault) | `/sparv` 命令 |
|
||||
| course | 课程开发(组合 dev + product-requirements + test-cases) | 组合模块 |
|
||||
|
||||
**基于风险信号智能路由任务到专业智能体的多智能体编排系统。**
|
||||
## 核心架构
|
||||
|
||||
| 角色 | 智能体 | 职责 |
|
||||
|------|-------|------|
|
||||
| **编排者** | Claude Code | 规划、上下文收集、验证 |
|
||||
| **执行者** | codeagent-wrapper | 代码编辑、测试执行(Codex/Claude/Gemini/OpenCode 后端)|
|
||||
|
||||
## 工作流详解
|
||||
|
||||
### do 工作流(推荐)
|
||||
|
||||
7 阶段功能开发,通过 codeagent-wrapper 编排多个智能体。**大多数功能开发任务的首选工作流。**
|
||||
|
||||
```bash
|
||||
/omo "分析并修复这个认证 bug"
|
||||
/do "添加用户登录功能"
|
||||
```
|
||||
|
||||
**智能体层级:**
|
||||
| 智能体 | 角色 | 后端 | 模型 |
|
||||
|-------|------|------|------|
|
||||
| `oracle` | 技术顾问 | Claude | claude-opus-4-5 |
|
||||
| `librarian` | 外部研究 | Claude | claude-sonnet-4-5 |
|
||||
| `explore` | 代码库搜索 | OpenCode | grok-code |
|
||||
| `develop` | 代码实现 | Codex | gpt-5.2 |
|
||||
| `frontend-ui-ux-engineer` | UI/UX 专家 | Gemini | gemini-3-pro |
|
||||
| `document-writer` | 文档撰写 | Gemini | gemini-3-flash |
|
||||
**7 阶段:**
|
||||
| 阶段 | 名称 | 目标 |
|
||||
|------|------|------|
|
||||
| 1 | Discovery | 理解需求 |
|
||||
| 2 | Exploration | 映射代码库模式 |
|
||||
| 3 | Clarification | 解决歧义(**强制**)|
|
||||
| 4 | Architecture | 设计实现方案 |
|
||||
| 5 | Implementation | 构建功能(**需审批**)|
|
||||
| 6 | Review | 捕获缺陷 |
|
||||
| 7 | Summary | 记录结果 |
|
||||
|
||||
**路由信号(非固定流水线):**
|
||||
- 代码位置不明确 → `explore`
|
||||
- 外部库/API → `librarian`
|
||||
- 高风险/多文件变更 → `oracle`
|
||||
- 需要实现 → `develop` / `frontend-ui-ux-engineer`
|
||||
|
||||
**常用配方:**
|
||||
- 解释代码:`explore`
|
||||
- 位置已知的小修复:直接 `develop`
|
||||
- Bug 修复,位置未知:`explore → develop`
|
||||
- 跨模块重构:`explore → oracle → develop`
|
||||
- 外部 API 集成:`explore + librarian → oracle → develop`
|
||||
|
||||
**适用场景:** 复杂 bug 调查、多文件重构、架构决策
|
||||
**智能体:**
|
||||
- `code-explorer` - 代码追踪、架构映射
|
||||
- `code-architect` - 设计方案、文件规划
|
||||
- `code-reviewer` - 代码审查、简化建议
|
||||
- `develop` - 实现代码、运行测试
|
||||
|
||||
---
|
||||
|
||||
### 1. Dev 工作流(推荐)
|
||||
### Dev 工作流
|
||||
|
||||
**大多数开发任务的首选工作流。**
|
||||
轻量级开发工作流,适合简单功能开发。
|
||||
|
||||
```bash
|
||||
/dev "实现 JWT 用户认证"
|
||||
```
|
||||
|
||||
**6 步流程:**
|
||||
1. **需求澄清** - 交互式问答明确范围
|
||||
2. **Codex 深度分析** - 代码库探索和架构决策
|
||||
3. **开发计划生成** - 结构化任务分解和测试要求
|
||||
4. **并行执行** - Codex 并发执行任务
|
||||
5. **覆盖率验证** - 强制 ≥90% 测试覆盖率
|
||||
6. **完成总结** - 文件变更和覆盖率报告
|
||||
|
||||
**核心特性:**
|
||||
- Claude Code 编排,Codex 执行所有代码变更
|
||||
- 自动任务并行化提升速度
|
||||
- 强制 90% 测试覆盖率门禁
|
||||
- 失败自动回滚
|
||||
|
||||
**适用场景:** 功能开发、重构、带测试的 bug 修复
|
||||
1. 需求澄清 - 交互式问答
|
||||
2. Codex 深度分析 - 代码库探索
|
||||
3. 开发计划生成 - 结构化任务分解
|
||||
4. 并行执行 - Codex 并发执行
|
||||
5. 覆盖率验证 - 强制 ≥90%
|
||||
6. 完成总结 - 报告生成
|
||||
|
||||
---
|
||||
|
||||
### 2. BMAD 敏捷工作流
|
||||
### OmO 多智能体编排器
|
||||
|
||||
**包含 6 个专业智能体的完整企业敏捷方法论。**
|
||||
基于风险信号智能路由任务到专业智能体。
|
||||
|
||||
```bash
|
||||
/omo "分析并修复这个认证 bug"
|
||||
```
|
||||
|
||||
**智能体层级:**
|
||||
| 智能体 | 角色 | 后端 |
|
||||
|-------|------|------|
|
||||
| `oracle` | 技术顾问 | Claude |
|
||||
| `librarian` | 外部研究 | Claude |
|
||||
| `explore` | 代码库搜索 | OpenCode |
|
||||
| `develop` | 代码实现 | Codex |
|
||||
| `frontend-ui-ux-engineer` | UI/UX 专家 | Gemini |
|
||||
| `document-writer` | 文档撰写 | Gemini |
|
||||
|
||||
**常用配方:**
|
||||
- 解释代码:`explore`
|
||||
- 位置已知的小修复:直接 `develop`
|
||||
- Bug 修复(位置未知):`explore → develop`
|
||||
- 跨模块重构:`explore → oracle → develop`
|
||||
|
||||
---
|
||||
|
||||
### SPARV 工作流
|
||||
|
||||
极简 5 阶段工作流:Specify → Plan → Act → Review → Vault。
|
||||
|
||||
```bash
|
||||
/sparv "实现订单导出功能"
|
||||
```
|
||||
|
||||
**核心规则:**
|
||||
- **10 分规格门**:得分 0-10,必须 >=9 才能进入 Plan
|
||||
- **2 动作保存**:每 2 次工具调用写入 journal.md
|
||||
- **3 失败协议**:连续 3 次失败后停止并上报
|
||||
- **EHRB**:高风险操作需明确确认
|
||||
|
||||
**评分维度(各 0-2 分):**
|
||||
1. Value - 为什么做,可验证的收益
|
||||
2. Scope - MVP + 不在范围内的内容
|
||||
3. Acceptance - 可测试的验收标准
|
||||
4. Boundaries - 错误/性能/兼容/安全边界
|
||||
5. Risk - EHRB/依赖/未知 + 处理方式
|
||||
|
||||
---
|
||||
|
||||
### BMAD 敏捷工作流
|
||||
|
||||
完整企业敏捷方法论 + 6 个专业智能体。
|
||||
|
||||
```bash
|
||||
/bmad-pilot "构建电商结账系统"
|
||||
@@ -104,43 +143,36 @@ python3 install.py --install-dir ~/.claude
|
||||
|-------|------|
|
||||
| Product Owner | 需求与用户故事 |
|
||||
| Architect | 系统设计与技术决策 |
|
||||
| Tech Lead | Sprint 规划与任务分解 |
|
||||
| Scrum Master | Sprint 规划与任务分解 |
|
||||
| Developer | 实现 |
|
||||
| Code Reviewer | 质量保证 |
|
||||
| QA Engineer | 测试与验证 |
|
||||
|
||||
**流程:**
|
||||
```
|
||||
需求 → 架构 → Sprint计划 → 开发 → 审查 → QA
|
||||
↓ ↓ ↓ ↓ ↓ ↓
|
||||
PRD.md DESIGN.md SPRINT.md Code REVIEW.md TEST.md
|
||||
```
|
||||
|
||||
**适用场景:** 大型功能、团队协作、企业项目
|
||||
**审批门:**
|
||||
- PRD 完成后(90+ 分)需用户审批
|
||||
- 架构完成后(90+ 分)需用户审批
|
||||
|
||||
---
|
||||
|
||||
### 3. 需求驱动工作流
|
||||
### 需求驱动工作流
|
||||
|
||||
**轻量级需求到代码流水线。**
|
||||
轻量级需求到代码流水线。
|
||||
|
||||
```bash
|
||||
/requirements-pilot "实现 API 限流"
|
||||
```
|
||||
|
||||
**流程:**
|
||||
1. 带质量评分的需求生成
|
||||
2. 实现规划
|
||||
3. 代码生成
|
||||
4. 审查和测试
|
||||
|
||||
**适用场景:** 快速原型、明确定义的功能
|
||||
**100 分质量评分:**
|
||||
- 功能清晰度:30 分
|
||||
- 技术具体性:25 分
|
||||
- 实现完整性:25 分
|
||||
- 业务上下文:20 分
|
||||
|
||||
---
|
||||
|
||||
### 4. 开发基础命令
|
||||
### 开发基础命令
|
||||
|
||||
**日常编码任务的直接命令。**
|
||||
日常编码任务的直接命令。
|
||||
|
||||
| 命令 | 用途 |
|
||||
|------|------|
|
||||
@@ -152,16 +184,12 @@ PRD.md DESIGN.md SPRINT.md Code REVIEW.md TEST.md
|
||||
| `/refactor` | 代码重构 |
|
||||
| `/docs` | 编写文档 |
|
||||
|
||||
**适用场景:** 快速任务,无需工作流开销
|
||||
|
||||
---
|
||||
|
||||
## 安装
|
||||
|
||||
### 模块化安装(推荐)
|
||||
|
||||
```bash
|
||||
# 安装所有启用的模块(默认:dev + essentials)
|
||||
# 安装所有启用的模块
|
||||
python3 install.py --install-dir ~/.claude
|
||||
|
||||
# 安装特定模块
|
||||
@@ -170,314 +198,77 @@ python3 install.py --module dev
|
||||
# 列出可用模块
|
||||
python3 install.py --list-modules
|
||||
|
||||
# 强制覆盖现有文件
|
||||
# 强制覆盖
|
||||
python3 install.py --force
|
||||
```
|
||||
|
||||
### 可用模块
|
||||
### 模块配置
|
||||
|
||||
| 模块 | 默认 | 描述 |
|
||||
|------|------|------|
|
||||
| `dev` | ✓ 启用 | Dev 工作流 + Codex 集成 |
|
||||
| `essentials` | ✓ 启用 | 核心开发命令 |
|
||||
| `bmad` | 禁用 | 完整 BMAD 敏捷工作流 |
|
||||
| `requirements` | 禁用 | 需求驱动工作流 |
|
||||
|
||||
### 安装内容
|
||||
|
||||
```
|
||||
~/.claude/
|
||||
├── bin/
|
||||
│ └── codeagent-wrapper # 主可执行文件
|
||||
├── CLAUDE.md # 核心指令和角色定义
|
||||
├── commands/ # 斜杠命令 (/dev, /code 等)
|
||||
├── agents/ # 智能体定义
|
||||
├── skills/
|
||||
│ └── codex/
|
||||
│ └── SKILL.md # Codex 集成技能
|
||||
├── config.json # 配置文件
|
||||
└── installed_modules.json # 安装状态
|
||||
```
|
||||
|
||||
### 自定义安装目录
|
||||
|
||||
默认情况下,myclaude 安装到 `~/.claude`。您可以使用 `INSTALL_DIR` 环境变量自定义安装目录:
|
||||
|
||||
```bash
|
||||
# 安装到自定义目录
|
||||
INSTALL_DIR=/opt/myclaude bash install.sh
|
||||
|
||||
# 相应更新您的 PATH
|
||||
export PATH="/opt/myclaude/bin:$PATH"
|
||||
```
|
||||
|
||||
**目录结构:**
|
||||
- `$INSTALL_DIR/bin/` - codeagent-wrapper 可执行文件
|
||||
- `$INSTALL_DIR/skills/` - 技能定义
|
||||
- `$INSTALL_DIR/config.json` - 配置文件
|
||||
- `$INSTALL_DIR/commands/` - 斜杠命令定义
|
||||
- `$INSTALL_DIR/agents/` - 智能体定义
|
||||
|
||||
**注意:** 使用自定义安装目录时,请确保将 `$INSTALL_DIR/bin` 添加到您的 `PATH` 环境变量中。
|
||||
|
||||
### 配置
|
||||
|
||||
编辑 `config.json` 自定义:
|
||||
编辑 `config.json` 启用/禁用模块:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "1.0",
|
||||
"install_dir": "~/.claude",
|
||||
"modules": {
|
||||
"dev": {
|
||||
"enabled": true,
|
||||
"operations": [
|
||||
{"type": "merge_dir", "source": "dev-workflow"},
|
||||
{"type": "copy_file", "source": "memorys/CLAUDE.md", "target": "CLAUDE.md"},
|
||||
{"type": "copy_file", "source": "skills/codex/SKILL.md", "target": "skills/codex/SKILL.md"},
|
||||
{"type": "run_command", "command": "bash install.sh"}
|
||||
]
|
||||
}
|
||||
"dev": { "enabled": true },
|
||||
"bmad": { "enabled": false },
|
||||
"requirements": { "enabled": false },
|
||||
"essentials": { "enabled": false },
|
||||
"omo": { "enabled": false },
|
||||
"sparv": { "enabled": false },
|
||||
"do": { "enabled": false },
|
||||
"course": { "enabled": false }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**操作类型:**
|
||||
| 类型 | 描述 |
|
||||
|------|------|
|
||||
| `merge_dir` | 合并子目录 (commands/, agents/) 到安装目录 |
|
||||
| `copy_dir` | 复制整个目录 |
|
||||
| `copy_file` | 复制单个文件到目标路径 |
|
||||
| `run_command` | 执行 shell 命令 |
|
||||
|
||||
---
|
||||
|
||||
## Codex 集成
|
||||
|
||||
`codex` 技能使 Claude Code 能够将代码执行委托给 Codex CLI。
|
||||
|
||||
### 工作流中的使用
|
||||
|
||||
```bash
|
||||
# 通过技能调用 Codex
|
||||
codeagent-wrapper - <<'EOF'
|
||||
在 @src/auth.ts 中实现 JWT 验证
|
||||
EOF
|
||||
```
|
||||
|
||||
### 并行执行
|
||||
|
||||
```bash
|
||||
codeagent-wrapper --parallel <<'EOF'
|
||||
---TASK---
|
||||
id: backend_api
|
||||
workdir: /project/backend
|
||||
---CONTENT---
|
||||
实现 /api/users 的 REST 端点
|
||||
|
||||
---TASK---
|
||||
id: frontend_ui
|
||||
workdir: /project/frontend
|
||||
dependencies: backend_api
|
||||
---CONTENT---
|
||||
创建消费 API 的 React 组件
|
||||
EOF
|
||||
```
|
||||
|
||||
### 安装 Codex Wrapper
|
||||
|
||||
```bash
|
||||
# 自动(通过 dev 模块)
|
||||
python3 install.py --module dev
|
||||
|
||||
# 手动
|
||||
bash install.sh
|
||||
```
|
||||
|
||||
#### Windows 系统
|
||||
|
||||
Windows 系统会将 `codeagent-wrapper.exe` 安装到 `%USERPROFILE%\bin`。
|
||||
|
||||
```powershell
|
||||
# PowerShell(推荐)
|
||||
powershell -ExecutionPolicy Bypass -File install.ps1
|
||||
|
||||
# 批处理(cmd)
|
||||
install.bat
|
||||
```
|
||||
|
||||
**添加到 PATH**(如果安装程序未自动检测):
|
||||
|
||||
```powershell
|
||||
# PowerShell - 永久添加(当前用户)
|
||||
[Environment]::SetEnvironmentVariable('PATH', "$HOME\bin;" + [Environment]::GetEnvironmentVariable('PATH','User'), 'User')
|
||||
|
||||
# PowerShell - 仅当前会话
|
||||
$Env:PATH = "$HOME\bin;$Env:PATH"
|
||||
```
|
||||
|
||||
```batch
|
||||
REM cmd.exe - 永久添加(当前用户)(建议使用上面的 PowerShell 方法)
|
||||
REM 警告:此命令会展开 %PATH% 包含系统 PATH,导致重复
|
||||
REM 注意:使用 reg add 而非 setx 以避免 1024 字符截断限制
|
||||
reg add "HKCU\Environment" /v Path /t REG_EXPAND_SZ /d "%USERPROFILE%\bin;%PATH%" /f
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 工作流选择指南
|
||||
|
||||
| 场景 | 推荐工作流 |
|
||||
|------|----------|
|
||||
| 带测试的新功能 | `/dev` |
|
||||
| 快速 bug 修复 | `/debug` 或 `/code` |
|
||||
| 大型多 Sprint 功能 | `/bmad-pilot` |
|
||||
| 原型或 POC | `/requirements-pilot` |
|
||||
| 代码审查 | `/review` |
|
||||
| 性能问题 | `/optimize` |
|
||||
| 场景 | 推荐 |
|
||||
|------|------|
|
||||
| 功能开发(默认) | `/do` |
|
||||
| 轻量级功能 | `/dev` |
|
||||
| Bug 调查 + 修复 | `/omo` |
|
||||
| 大型企业项目 | `/bmad-pilot` |
|
||||
| 快速原型 | `/requirements-pilot` |
|
||||
| 简单任务 | `/code`, `/debug` |
|
||||
|
||||
---
|
||||
## 后端 CLI 要求
|
||||
|
||||
| 后端 | 必需功能 |
|
||||
|------|----------|
|
||||
| Codex | `codex e`, `--json`, `-C`, `resume` |
|
||||
| Claude | `--output-format stream-json`, `-r` |
|
||||
| Gemini | `-o stream-json`, `-y`, `-r` |
|
||||
|
||||
## 故障排查
|
||||
|
||||
### 常见问题
|
||||
|
||||
**Codex wrapper 未找到:**
|
||||
```bash
|
||||
# 安装程序会自动添加 PATH,检查是否已添加
|
||||
if [[ ":$PATH:" != *":$HOME/.claude/bin:"* ]]; then
|
||||
echo "PATH not configured. Reinstalling..."
|
||||
bash install.sh
|
||||
fi
|
||||
|
||||
# 或手动添加(幂等性命令)
|
||||
[[ ":$PATH:" != *":$HOME/.claude/bin:"* ]] && echo 'export PATH="$HOME/.claude/bin:$PATH"' >> ~/.zshrc
|
||||
```
|
||||
|
||||
**权限被拒绝:**
|
||||
```bash
|
||||
python3 install.py --install-dir ~/.claude --force
|
||||
bash install.sh
|
||||
```
|
||||
|
||||
**模块未加载:**
|
||||
```bash
|
||||
# 检查安装状态
|
||||
cat ~/.claude/installed_modules.json
|
||||
|
||||
# 重新安装特定模块
|
||||
python3 install.py --module dev --force
|
||||
python3 install.py --module <name> --force
|
||||
```
|
||||
|
||||
---
|
||||
## FAQ
|
||||
|
||||
## 常见问题 (FAQ)
|
||||
| 问题 | 解决方案 |
|
||||
|------|----------|
|
||||
| "Unknown event format" | 日志显示问题,可忽略 |
|
||||
| Gemini 无法读取 .gitignore 文件 | 从 .gitignore 移除或使用其他后端 |
|
||||
| `/dev` 执行慢 | 检查日志,尝试更快模型,使用单一仓库 |
|
||||
| Codex 权限拒绝 | 在 ~/.codex/config.yaml 设置 `approval_policy = "never"` |
|
||||
|
||||
### Q1: `codeagent-wrapper` 执行时报错 "Unknown event format"
|
||||
|
||||
**问题描述:**
|
||||
执行 `codeagent-wrapper` 时出现错误:
|
||||
```
|
||||
Unknown event format: {"type":"turn.started"}
|
||||
Unknown event format: {"type":"assistant", ...}
|
||||
```
|
||||
|
||||
**解决方案:**
|
||||
这是日志事件流的显示问题,不影响实际功能执行。预计在下个版本中修复。如需排查其他问题,可忽略此日志输出。
|
||||
|
||||
**相关 Issue:** [#96](https://github.com/cexll/myclaude/issues/96)
|
||||
|
||||
---
|
||||
|
||||
### Q2: Gemini 无法读取 `.gitignore` 忽略的文件
|
||||
|
||||
**问题描述:**
|
||||
使用 `codeagent-wrapper --backend gemini` 时,无法读取 `.claude/` 等被 `.gitignore` 忽略的目录中的文件。
|
||||
|
||||
**解决方案:**
|
||||
- **方案一:** 在项目根目录的 `.gitignore` 中取消对 `.claude/` 的忽略
|
||||
- **方案二:** 确保需要读取的文件不在 `.gitignore` 忽略列表中
|
||||
|
||||
**相关 Issue:** [#75](https://github.com/cexll/myclaude/issues/75)
|
||||
|
||||
---
|
||||
|
||||
### Q3: `/dev` 命令并行执行特别慢
|
||||
|
||||
**问题描述:**
|
||||
使用 `/dev` 命令开发简单功能耗时过长(超过30分钟),无法了解任务执行状态。
|
||||
|
||||
**解决方案:**
|
||||
1. **检查日志:** 查看 `C:\Users\User\AppData\Local\Temp\codeagent-wrapper-*.log` 分析瓶颈
|
||||
2. **调整后端:**
|
||||
- 尝试使用 `gpt-5.1-codex-max` 等更快的模型
|
||||
- 在 WSL 环境下运行速度可能更快
|
||||
3. **工作区选择:** 使用独立的代码仓库而非包含多个子项目的 monorepo
|
||||
|
||||
**相关 Issue:** [#77](https://github.com/cexll/myclaude/issues/77)
|
||||
|
||||
---
|
||||
|
||||
### Q4: 新版 Go 实现的 Codex 权限不足
|
||||
|
||||
**问题描述:**
|
||||
升级到新版 Go 实现的 Codex 后,出现权限不足的错误。
|
||||
|
||||
**解决方案:**
|
||||
在 `~/.codex/config.yaml` 中添加以下配置(Windows: `c:\user\.codex\config.toml`):
|
||||
```yaml
|
||||
model = "gpt-5.1-codex-max"
|
||||
model_reasoning_effort = "high"
|
||||
model_reasoning_summary = "detailed"
|
||||
approval_policy = "never"
|
||||
sandbox_mode = "workspace-write"
|
||||
disable_response_storage = true
|
||||
network_access = true
|
||||
```
|
||||
|
||||
**关键配置说明:**
|
||||
- `approval_policy = "never"` - 移除审批限制
|
||||
- `sandbox_mode = "workspace-write"` - 允许工作区写入权限
|
||||
- `network_access = true` - 启用网络访问
|
||||
|
||||
**相关 Issue:** [#31](https://github.com/cexll/myclaude/issues/31)
|
||||
|
||||
---
|
||||
|
||||
### Q5: 执行时遇到权限拒绝或沙箱限制
|
||||
|
||||
**问题描述:**
|
||||
运行 codeagent-wrapper 时出现权限错误或沙箱限制。
|
||||
|
||||
**解决方案:**
|
||||
设置以下环境变量:
|
||||
```bash
|
||||
export CODEX_BYPASS_SANDBOX=true
|
||||
export CODEAGENT_SKIP_PERMISSIONS=true
|
||||
```
|
||||
|
||||
或添加到 shell 配置文件(`~/.zshrc` 或 `~/.bashrc`):
|
||||
```bash
|
||||
echo 'export CODEX_BYPASS_SANDBOX=true' >> ~/.zshrc
|
||||
echo 'export CODEAGENT_SKIP_PERMISSIONS=true' >> ~/.zshrc
|
||||
```
|
||||
|
||||
**注意:** 这些设置会绕过安全限制,请仅在可信环境中使用。
|
||||
|
||||
---
|
||||
|
||||
**仍有疑问?** 请访问 [GitHub Issues](https://github.com/cexll/myclaude/issues) 搜索或提交新问题。
|
||||
|
||||
---
|
||||
更多问题请访问 [GitHub Issues](https://github.com/cexll/myclaude/issues)。
|
||||
|
||||
## 许可证
|
||||
|
||||
AGPL-3.0 License - 查看 [LICENSE](LICENSE)
|
||||
AGPL-3.0 - 查看 [LICENSE](LICENSE)
|
||||
|
||||
## 支持
|
||||
|
||||
- **问题反馈**: [GitHub Issues](https://github.com/cexll/myclaude/issues)
|
||||
- **文档**: [docs/](docs/)
|
||||
|
||||
---
|
||||
|
||||
**Claude Code + Codex = 更好的开发** - 编排遇见执行。
|
||||
- [GitHub Issues](https://github.com/cexll/myclaude/issues)
|
||||
- [文档](docs/)
|
||||
|
||||
109
bmad-agile-workflow/README.md
Normal file
109
bmad-agile-workflow/README.md
Normal file
@@ -0,0 +1,109 @@
|
||||
# bmad - BMAD Agile Workflow
|
||||
|
||||
Full enterprise agile methodology with 6 specialized agents, UltraThink analysis, and repository-aware development.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
python install.py --module bmad
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
/bmad-pilot <PROJECT_DESCRIPTION> [OPTIONS]
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `--skip-tests` | Skip QA testing phase |
|
||||
| `--direct-dev` | Skip SM planning, go directly to development |
|
||||
| `--skip-scan` | Skip initial repository scanning |
|
||||
|
||||
## Workflow Phases
|
||||
|
||||
| Phase | Agent | Deliverable | Description |
|
||||
|-------|-------|-------------|-------------|
|
||||
| 0 | Orchestrator | `00-repo-scan.md` | Repository scanning with UltraThink analysis |
|
||||
| 1 | Product Owner (PO) | `01-product-requirements.md` | PRD with 90+ quality score required |
|
||||
| 2 | Architect | `02-system-architecture.md` | Technical design with 90+ score required |
|
||||
| 3 | Scrum Master (SM) | `03-sprint-plan.md` | Sprint backlog with stories and estimates |
|
||||
| 4 | Developer | Implementation code | Multi-sprint implementation |
|
||||
| 4.5 | Reviewer | `04-dev-reviewed.md` | Code review (Pass/Pass with Risk/Fail) |
|
||||
| 5 | QA Engineer | Test suite | Comprehensive testing and validation |
|
||||
|
||||
## Agents
|
||||
|
||||
| Agent | Role |
|
||||
|-------|------|
|
||||
| `bmad-orchestrator` | Repository scanning, workflow coordination |
|
||||
| `bmad-po` | Requirements gathering, PRD creation |
|
||||
| `bmad-architect` | System design, technology decisions |
|
||||
| `bmad-sm` | Sprint planning, task breakdown |
|
||||
| `bmad-dev` | Code implementation |
|
||||
| `bmad-review` | Code review, quality assessment |
|
||||
| `bmad-qa` | Testing, validation |
|
||||
|
||||
## Approval Gates
|
||||
|
||||
Two mandatory stop points require explicit user approval:
|
||||
|
||||
1. **After PRD** (Phase 1 → 2): User must approve requirements before architecture
|
||||
2. **After Architecture** (Phase 2 → 3): User must approve design before implementation
|
||||
|
||||
## Output Structure
|
||||
|
||||
```
|
||||
.claude/specs/{feature_name}/
|
||||
├── 00-repo-scan.md
|
||||
├── 01-product-requirements.md
|
||||
├── 02-system-architecture.md
|
||||
├── 03-sprint-plan.md
|
||||
└── 04-dev-reviewed.md
|
||||
```
|
||||
|
||||
## UltraThink Methodology
|
||||
|
||||
Applied throughout the workflow for deep analysis:
|
||||
|
||||
1. **Hypothesis Generation** - Form hypotheses about the problem
|
||||
2. **Evidence Collection** - Gather evidence from codebase
|
||||
3. **Pattern Recognition** - Identify recurring patterns
|
||||
4. **Synthesis** - Create comprehensive understanding
|
||||
5. **Validation** - Cross-check findings
|
||||
|
||||
## Interactive Confirmation Flow
|
||||
|
||||
PO and Architect phases use iterative refinement:
|
||||
|
||||
1. Agent produces initial draft + quality score
|
||||
2. Orchestrator presents to user with clarification questions
|
||||
3. User provides responses
|
||||
4. Agent refines until quality >= 90
|
||||
5. User confirms to save deliverable
|
||||
|
||||
## When to Use
|
||||
|
||||
- Large multi-sprint features
|
||||
- Enterprise projects requiring documentation
|
||||
- Team coordination scenarios
|
||||
- Projects needing formal approval gates
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
bmad-agile-workflow/
|
||||
├── README.md
|
||||
├── commands/
|
||||
│ └── bmad-pilot.md
|
||||
└── agents/
|
||||
├── bmad-orchestrator.md
|
||||
├── bmad-po.md
|
||||
├── bmad-architect.md
|
||||
├── bmad-sm.md
|
||||
├── bmad-dev.md
|
||||
├── bmad-review.md
|
||||
└── bmad-qa.md
|
||||
```
|
||||
@@ -1,8 +1,5 @@
|
||||
GO ?= go
|
||||
|
||||
BINARY ?= codeagent
|
||||
CMD_PKG := ./cmd/codeagent
|
||||
|
||||
TOOLS_BIN := $(CURDIR)/bin
|
||||
TOOLCHAIN ?= go1.22.0
|
||||
GOLANGCI_LINT_VERSION := v1.56.2
|
||||
@@ -14,7 +11,8 @@ STATICCHECK := $(TOOLS_BIN)/staticcheck
|
||||
.PHONY: build test lint clean install
|
||||
|
||||
build:
|
||||
$(GO) build -o $(BINARY) $(CMD_PKG)
|
||||
$(GO) build -o codeagent ./cmd/codeagent
|
||||
$(GO) build -o codeagent-wrapper ./cmd/codeagent-wrapper
|
||||
|
||||
test:
|
||||
$(GO) test ./...
|
||||
@@ -35,4 +33,5 @@ clean:
|
||||
@python3 -c 'import glob, os; paths=["codeagent","codeagent.exe","codeagent-wrapper","codeagent-wrapper.exe","coverage.out","cover.out","coverage.html"]; paths += glob.glob("coverage*.out") + glob.glob("cover_*.out") + glob.glob("*.test"); [os.remove(p) for p in paths if os.path.exists(p)]'
|
||||
|
||||
install:
|
||||
$(GO) install $(CMD_PKG)
|
||||
$(GO) install ./cmd/codeagent
|
||||
$(GO) install ./cmd/codeagent-wrapper
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
`codeagent-wrapper` 是一个用 Go 编写的“多后端 AI 代码代理”命令行包装器:用统一的 CLI 入口封装不同的 AI 工具后端(Codex / Claude / Gemini / Opencode),并提供一致的参数、配置与会话恢复体验。
|
||||
|
||||
入口:`cmd/codeagent/main.go`(生成二进制名:`codeagent`)。
|
||||
入口:`cmd/codeagent/main.go`(生成二进制名:`codeagent`)和 `cmd/codeagent-wrapper/main.go`(生成二进制名:`codeagent-wrapper`)。两者行为一致。
|
||||
|
||||
## 功能特性
|
||||
|
||||
@@ -22,12 +22,14 @@
|
||||
|
||||
```bash
|
||||
go install ./cmd/codeagent
|
||||
go install ./cmd/codeagent-wrapper
|
||||
```
|
||||
|
||||
安装后确认:
|
||||
|
||||
```bash
|
||||
codeagent version
|
||||
codeagent-wrapper version
|
||||
```
|
||||
|
||||
## 使用示例
|
||||
@@ -148,4 +150,3 @@ make test
|
||||
make lint
|
||||
make clean
|
||||
```
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
version = "6.0.0-alpha1"
|
||||
version = "6.1.2"
|
||||
defaultWorkdir = "."
|
||||
defaultTimeout = 7200 // seconds (2 hours)
|
||||
defaultCoverageTarget = 90.0
|
||||
|
||||
@@ -635,6 +635,7 @@ func runSingleMode(cfg *Config, name string) int {
|
||||
WorkDir: cfg.WorkDir,
|
||||
Mode: cfg.Mode,
|
||||
SessionID: cfg.SessionID,
|
||||
Backend: cfg.Backend,
|
||||
Model: cfg.Model,
|
||||
ReasoningEffort: cfg.ReasoningEffort,
|
||||
Agent: cfg.Agent,
|
||||
@@ -648,6 +649,12 @@ func runSingleMode(cfg *Config, name string) int {
|
||||
return result.ExitCode
|
||||
}
|
||||
|
||||
// Validate that we got a meaningful output message
|
||||
if strings.TrimSpace(result.Message) == "" {
|
||||
logError(fmt.Sprintf("no output message: backend=%s returned empty result.Message with exit_code=0", cfg.Backend))
|
||||
return 1
|
||||
}
|
||||
|
||||
fmt.Println(result.Message)
|
||||
if result.SessionID != "" {
|
||||
fmt.Printf("\n---\nSESSION_ID: %s\n", result.SessionID)
|
||||
|
||||
@@ -1913,6 +1913,37 @@ func TestRun_PassesReasoningEffortToTaskSpec(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRun_NoOutputMessage_ReturnsExitCode1AndWritesStderr(t *testing.T) {
|
||||
defer resetTestHooks()
|
||||
cleanupLogsFn = func() (CleanupStats, error) { return CleanupStats{}, nil }
|
||||
t.Setenv("TMPDIR", t.TempDir())
|
||||
|
||||
selectBackendFn = func(name string) (Backend, error) {
|
||||
return testBackend{name: name, command: "echo"}, nil
|
||||
}
|
||||
|
||||
runTaskFn = func(task TaskSpec, silent bool, timeout int) TaskResult {
|
||||
return TaskResult{ExitCode: 0, Message: ""}
|
||||
}
|
||||
|
||||
isTerminalFn = func() bool { return true }
|
||||
stdinReader = strings.NewReader("")
|
||||
|
||||
os.Args = []string{"codeagent-wrapper", "task"}
|
||||
|
||||
var code int
|
||||
errOutput := captureStderr(t, func() {
|
||||
code = run()
|
||||
})
|
||||
|
||||
if code != 1 {
|
||||
t.Fatalf("run() exit=%d, want 1", code)
|
||||
}
|
||||
if !strings.Contains(errOutput, "no output message") {
|
||||
t.Fatalf("stderr missing sentinel error text; got:\n%s", errOutput)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunBuildCodexArgs_NewMode(t *testing.T) {
|
||||
const key = "CODEX_BYPASS_SANDBOX"
|
||||
t.Setenv(key, "false")
|
||||
@@ -3667,10 +3698,8 @@ func TestVersionFlag(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
want := "codeagent-wrapper version 6.0.0-alpha1\n"
|
||||
|
||||
if output != want {
|
||||
t.Fatalf("output = %q, want %q", output, want)
|
||||
if !strings.HasPrefix(output, "codeagent-wrapper version ") {
|
||||
t.Fatalf("output = %q, want prefix %q", output, "codeagent-wrapper version ")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3683,10 +3712,8 @@ func TestVersionShortFlag(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
want := "codeagent-wrapper version 6.0.0-alpha1\n"
|
||||
|
||||
if output != want {
|
||||
t.Fatalf("output = %q, want %q", output, want)
|
||||
if !strings.HasPrefix(output, "codeagent-wrapper version ") {
|
||||
t.Fatalf("output = %q, want prefix %q", output, "codeagent-wrapper version ")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3699,10 +3726,8 @@ func TestVersionLegacyAlias(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
want := "codeagent-wrapper version 6.0.0-alpha1\n"
|
||||
|
||||
if output != want {
|
||||
t.Fatalf("output = %q, want %q", output, want)
|
||||
if !strings.HasPrefix(output, "codeagent-wrapper version ") {
|
||||
t.Fatalf("output = %q, want prefix %q", output, "codeagent-wrapper version ")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ func (ClaudeBackend) Env(baseURL, apiKey string) map[string]string {
|
||||
env["ANTHROPIC_BASE_URL"] = baseURL
|
||||
}
|
||||
if apiKey != "" {
|
||||
env["ANTHROPIC_API_KEY"] = apiKey
|
||||
env["ANTHROPIC_AUTH_TOKEN"] = apiKey
|
||||
}
|
||||
return env
|
||||
}
|
||||
|
||||
193
codeagent-wrapper/internal/executor/env_inject_test.go
Normal file
193
codeagent-wrapper/internal/executor/env_inject_test.go
Normal file
@@ -0,0 +1,193 @@
|
||||
package executor
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
backend "codeagent-wrapper/internal/backend"
|
||||
config "codeagent-wrapper/internal/config"
|
||||
)
|
||||
|
||||
// TestEnvInjectionWithAgent tests the full flow of env injection with agent config
|
||||
func TestEnvInjectionWithAgent(t *testing.T) {
|
||||
// Setup temp config
|
||||
tmpDir := t.TempDir()
|
||||
configDir := filepath.Join(tmpDir, ".codeagent")
|
||||
if err := os.MkdirAll(configDir, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Write test config with agent that has base_url and api_key
|
||||
configContent := `{
|
||||
"default_backend": "codex",
|
||||
"agents": {
|
||||
"test-agent": {
|
||||
"backend": "claude",
|
||||
"model": "test-model",
|
||||
"base_url": "https://test.api.com",
|
||||
"api_key": "test-api-key-12345678"
|
||||
}
|
||||
}
|
||||
}`
|
||||
configPath := filepath.Join(configDir, "models.json")
|
||||
if err := os.WriteFile(configPath, []byte(configContent), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Override HOME to use temp dir
|
||||
oldHome := os.Getenv("HOME")
|
||||
os.Setenv("HOME", tmpDir)
|
||||
defer os.Setenv("HOME", oldHome)
|
||||
|
||||
// Reset config cache
|
||||
config.ResetModelsConfigCacheForTest()
|
||||
defer config.ResetModelsConfigCacheForTest()
|
||||
|
||||
// Test ResolveAgentConfig
|
||||
agentBackend, model, _, _, baseURL, apiKey, _ := config.ResolveAgentConfig("test-agent")
|
||||
t.Logf("ResolveAgentConfig: backend=%q, model=%q, baseURL=%q, apiKey=%q",
|
||||
agentBackend, model, baseURL, apiKey)
|
||||
|
||||
if agentBackend != "claude" {
|
||||
t.Errorf("expected backend 'claude', got %q", agentBackend)
|
||||
}
|
||||
if baseURL != "https://test.api.com" {
|
||||
t.Errorf("expected baseURL 'https://test.api.com', got %q", baseURL)
|
||||
}
|
||||
if apiKey != "test-api-key-12345678" {
|
||||
t.Errorf("expected apiKey 'test-api-key-12345678', got %q", apiKey)
|
||||
}
|
||||
|
||||
// Test Backend.Env
|
||||
b := backend.ClaudeBackend{}
|
||||
env := b.Env(baseURL, apiKey)
|
||||
t.Logf("Backend.Env: %v", env)
|
||||
|
||||
if env == nil {
|
||||
t.Fatal("expected non-nil env from Backend.Env")
|
||||
}
|
||||
if env["ANTHROPIC_BASE_URL"] != baseURL {
|
||||
t.Errorf("expected ANTHROPIC_BASE_URL=%q, got %q", baseURL, env["ANTHROPIC_BASE_URL"])
|
||||
}
|
||||
if env["ANTHROPIC_AUTH_TOKEN"] != apiKey {
|
||||
t.Errorf("expected ANTHROPIC_AUTH_TOKEN=%q, got %q", apiKey, env["ANTHROPIC_AUTH_TOKEN"])
|
||||
}
|
||||
}
|
||||
|
||||
// TestEnvInjectionLogic tests the exact logic used in executor
|
||||
func TestEnvInjectionLogic(t *testing.T) {
|
||||
// Setup temp config
|
||||
tmpDir := t.TempDir()
|
||||
configDir := filepath.Join(tmpDir, ".codeagent")
|
||||
if err := os.MkdirAll(configDir, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
configContent := `{
|
||||
"default_backend": "codex",
|
||||
"agents": {
|
||||
"explore": {
|
||||
"backend": "claude",
|
||||
"model": "MiniMax-M2.1",
|
||||
"base_url": "https://api.minimaxi.com/anthropic",
|
||||
"api_key": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.test"
|
||||
}
|
||||
}
|
||||
}`
|
||||
configPath := filepath.Join(configDir, "models.json")
|
||||
if err := os.WriteFile(configPath, []byte(configContent), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
oldHome := os.Getenv("HOME")
|
||||
os.Setenv("HOME", tmpDir)
|
||||
defer os.Setenv("HOME", oldHome)
|
||||
|
||||
config.ResetModelsConfigCacheForTest()
|
||||
defer config.ResetModelsConfigCacheForTest()
|
||||
|
||||
// Simulate the executor logic
|
||||
cfgBackend := "claude" // This should come from taskSpec.Backend
|
||||
agentName := "explore"
|
||||
|
||||
// Step 1: Get backend config (usually empty for claude without global config)
|
||||
baseURL, apiKey := config.ResolveBackendConfig(cfgBackend)
|
||||
t.Logf("Step 1 - ResolveBackendConfig(%q): baseURL=%q, apiKey=%q", cfgBackend, baseURL, apiKey)
|
||||
|
||||
// Step 2: If agent specified, get agent config
|
||||
if agentName != "" {
|
||||
agentBackend, _, _, _, agentBaseURL, agentAPIKey, _ := config.ResolveAgentConfig(agentName)
|
||||
t.Logf("Step 2 - ResolveAgentConfig(%q): backend=%q, baseURL=%q, apiKey=%q",
|
||||
agentName, agentBackend, agentBaseURL, agentAPIKey)
|
||||
|
||||
// Step 3: Check if agent backend matches cfg backend
|
||||
if strings.EqualFold(strings.TrimSpace(agentBackend), strings.TrimSpace(cfgBackend)) {
|
||||
baseURL, apiKey = agentBaseURL, agentAPIKey
|
||||
t.Logf("Step 3 - Backend match! Using agent config: baseURL=%q, apiKey=%q", baseURL, apiKey)
|
||||
} else {
|
||||
t.Logf("Step 3 - Backend mismatch: agent=%q, cfg=%q", agentBackend, cfgBackend)
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Get env vars from backend
|
||||
b := backend.ClaudeBackend{}
|
||||
injected := b.Env(baseURL, apiKey)
|
||||
t.Logf("Step 4 - Backend.Env: %v", injected)
|
||||
|
||||
// Verify
|
||||
if len(injected) == 0 {
|
||||
t.Fatal("Expected env vars to be injected, got none")
|
||||
}
|
||||
|
||||
expectedURL := "https://api.minimaxi.com/anthropic"
|
||||
if injected["ANTHROPIC_BASE_URL"] != expectedURL {
|
||||
t.Errorf("ANTHROPIC_BASE_URL: expected %q, got %q", expectedURL, injected["ANTHROPIC_BASE_URL"])
|
||||
}
|
||||
|
||||
if _, ok := injected["ANTHROPIC_AUTH_TOKEN"]; !ok {
|
||||
t.Error("ANTHROPIC_AUTH_TOKEN not set")
|
||||
}
|
||||
|
||||
// Step 5: Test masking
|
||||
for k, v := range injected {
|
||||
masked := maskSensitiveValue(k, v)
|
||||
t.Logf("Step 5 - Env log: %s=%s", k, masked)
|
||||
}
|
||||
}
|
||||
|
||||
// TestTaskSpecBackendPropagation tests that taskSpec.Backend is properly used
|
||||
func TestTaskSpecBackendPropagation(t *testing.T) {
|
||||
// Simulate what happens in RunCodexTaskWithContext
|
||||
taskSpec := TaskSpec{
|
||||
ID: "test",
|
||||
Task: "hello",
|
||||
Backend: "claude",
|
||||
Agent: "explore",
|
||||
}
|
||||
|
||||
// This is the logic from executor.go lines 889-916
|
||||
cfg := &config.Config{
|
||||
Mode: "new",
|
||||
Task: taskSpec.Task,
|
||||
Backend: "codex", // default
|
||||
}
|
||||
|
||||
var backend Backend = nil // nil in single mode
|
||||
commandName := "codex" // default
|
||||
|
||||
if backend != nil {
|
||||
cfg.Backend = backend.Name()
|
||||
} else if taskSpec.Backend != "" {
|
||||
cfg.Backend = taskSpec.Backend
|
||||
} else if commandName != "" {
|
||||
cfg.Backend = commandName
|
||||
}
|
||||
|
||||
t.Logf("taskSpec.Backend=%q, cfg.Backend=%q", taskSpec.Backend, cfg.Backend)
|
||||
|
||||
if cfg.Backend != "claude" {
|
||||
t.Errorf("expected cfg.Backend='claude', got %q", cfg.Backend)
|
||||
}
|
||||
}
|
||||
333
codeagent-wrapper/internal/executor/env_logging_test.go
Normal file
333
codeagent-wrapper/internal/executor/env_logging_test.go
Normal file
@@ -0,0 +1,333 @@
|
||||
package executor
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
backend "codeagent-wrapper/internal/backend"
|
||||
)
|
||||
|
||||
func TestMaskSensitiveValue(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
key string
|
||||
value string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "API_KEY with long value",
|
||||
key: "ANTHROPIC_AUTH_TOKEN",
|
||||
value: "sk-ant-api03-xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
||||
expected: "sk-a****xxxx",
|
||||
},
|
||||
{
|
||||
name: "api_key lowercase",
|
||||
key: "api_key",
|
||||
value: "abcdefghijklmnop",
|
||||
expected: "abcd****mnop",
|
||||
},
|
||||
{
|
||||
name: "AUTH_TOKEN",
|
||||
key: "AUTH_TOKEN",
|
||||
value: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9",
|
||||
expected: "eyJh****VCJ9",
|
||||
},
|
||||
{
|
||||
name: "SECRET",
|
||||
key: "MY_SECRET",
|
||||
value: "super-secret-value-12345",
|
||||
expected: "supe****2345",
|
||||
},
|
||||
{
|
||||
name: "short key value (8 chars)",
|
||||
key: "API_KEY",
|
||||
value: "12345678",
|
||||
expected: "****",
|
||||
},
|
||||
{
|
||||
name: "very short key value",
|
||||
key: "API_KEY",
|
||||
value: "abc",
|
||||
expected: "****",
|
||||
},
|
||||
{
|
||||
name: "empty key value",
|
||||
key: "API_KEY",
|
||||
value: "",
|
||||
expected: "",
|
||||
},
|
||||
{
|
||||
name: "non-sensitive BASE_URL",
|
||||
key: "ANTHROPIC_BASE_URL",
|
||||
value: "https://api.anthropic.com",
|
||||
expected: "https://api.anthropic.com",
|
||||
},
|
||||
{
|
||||
name: "non-sensitive MODEL",
|
||||
key: "MODEL",
|
||||
value: "claude-3-opus",
|
||||
expected: "claude-3-opus",
|
||||
},
|
||||
{
|
||||
name: "case insensitive - Key",
|
||||
key: "My_Key",
|
||||
value: "1234567890abcdef",
|
||||
expected: "1234****cdef",
|
||||
},
|
||||
{
|
||||
name: "case insensitive - TOKEN",
|
||||
key: "ACCESS_TOKEN",
|
||||
value: "access123456789",
|
||||
expected: "acce****6789",
|
||||
},
|
||||
{
|
||||
name: "partial match - apikey",
|
||||
key: "MYAPIKEY",
|
||||
value: "1234567890",
|
||||
expected: "1234****7890",
|
||||
},
|
||||
{
|
||||
name: "partial match - secretvalue",
|
||||
key: "SECRETVALUE",
|
||||
value: "abcdefghij",
|
||||
expected: "abcd****ghij",
|
||||
},
|
||||
{
|
||||
name: "9 char value (just above threshold)",
|
||||
key: "API_KEY",
|
||||
value: "123456789",
|
||||
expected: "1234****6789",
|
||||
},
|
||||
{
|
||||
name: "exactly 8 char value (at threshold)",
|
||||
key: "API_KEY",
|
||||
value: "12345678",
|
||||
expected: "****",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := maskSensitiveValue(tt.key, tt.value)
|
||||
if result != tt.expected {
|
||||
t.Errorf("maskSensitiveValue(%q, %q) = %q, want %q", tt.key, tt.value, result, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMaskSensitiveValue_NoLeakage(t *testing.T) {
|
||||
// Ensure sensitive values are never fully exposed
|
||||
sensitiveKeys := []string{"API_KEY", "api_key", "AUTH_TOKEN", "SECRET", "access_token", "MYAPIKEY"}
|
||||
longValue := "this-is-a-very-long-secret-value-that-should-be-masked"
|
||||
|
||||
for _, key := range sensitiveKeys {
|
||||
t.Run(key, func(t *testing.T) {
|
||||
masked := maskSensitiveValue(key, longValue)
|
||||
// Should not contain the full value
|
||||
if masked == longValue {
|
||||
t.Errorf("key %q: value was not masked", key)
|
||||
}
|
||||
// Should contain mask marker
|
||||
if !strings.Contains(masked, "****") {
|
||||
t.Errorf("key %q: masked value %q does not contain ****", key, masked)
|
||||
}
|
||||
// First 4 chars should be visible
|
||||
if !strings.HasPrefix(masked, longValue[:4]) {
|
||||
t.Errorf("key %q: masked value should start with first 4 chars", key)
|
||||
}
|
||||
// Last 4 chars should be visible
|
||||
if !strings.HasSuffix(masked, longValue[len(longValue)-4:]) {
|
||||
t.Errorf("key %q: masked value should end with last 4 chars", key)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMaskSensitiveValue_NonSensitivePassthrough(t *testing.T) {
|
||||
// Non-sensitive keys should pass through unchanged
|
||||
nonSensitiveKeys := []string{
|
||||
"ANTHROPIC_BASE_URL",
|
||||
"BASE_URL",
|
||||
"MODEL",
|
||||
"BACKEND",
|
||||
"WORKDIR",
|
||||
"HOME",
|
||||
"PATH",
|
||||
}
|
||||
value := "any-value-here-12345"
|
||||
|
||||
for _, key := range nonSensitiveKeys {
|
||||
t.Run(key, func(t *testing.T) {
|
||||
result := maskSensitiveValue(key, value)
|
||||
if result != value {
|
||||
t.Errorf("key %q: expected passthrough but got %q", key, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestClaudeBackendEnv tests that ClaudeBackend.Env returns correct env vars
|
||||
func TestClaudeBackendEnv(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
baseURL string
|
||||
apiKey string
|
||||
expectKeys []string
|
||||
expectNil bool
|
||||
}{
|
||||
{
|
||||
name: "both base_url and api_key",
|
||||
baseURL: "https://api.custom.com",
|
||||
apiKey: "sk-test-key-12345",
|
||||
expectKeys: []string{"ANTHROPIC_BASE_URL", "ANTHROPIC_AUTH_TOKEN"},
|
||||
},
|
||||
{
|
||||
name: "only base_url",
|
||||
baseURL: "https://api.custom.com",
|
||||
apiKey: "",
|
||||
expectKeys: []string{"ANTHROPIC_BASE_URL"},
|
||||
},
|
||||
{
|
||||
name: "only api_key",
|
||||
baseURL: "",
|
||||
apiKey: "sk-test-key-12345",
|
||||
expectKeys: []string{"ANTHROPIC_AUTH_TOKEN"},
|
||||
},
|
||||
{
|
||||
name: "both empty",
|
||||
baseURL: "",
|
||||
apiKey: "",
|
||||
expectNil: true,
|
||||
},
|
||||
{
|
||||
name: "whitespace only",
|
||||
baseURL: " ",
|
||||
apiKey: " ",
|
||||
expectNil: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
b := backend.ClaudeBackend{}
|
||||
env := b.Env(tt.baseURL, tt.apiKey)
|
||||
|
||||
if tt.expectNil {
|
||||
if env != nil {
|
||||
t.Errorf("expected nil env, got %v", env)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if env == nil {
|
||||
t.Fatal("expected non-nil env")
|
||||
}
|
||||
|
||||
for _, key := range tt.expectKeys {
|
||||
if _, ok := env[key]; !ok {
|
||||
t.Errorf("expected key %q in env", key)
|
||||
}
|
||||
}
|
||||
|
||||
// Verify values are correct
|
||||
if tt.baseURL != "" && strings.TrimSpace(tt.baseURL) != "" {
|
||||
if env["ANTHROPIC_BASE_URL"] != strings.TrimSpace(tt.baseURL) {
|
||||
t.Errorf("ANTHROPIC_BASE_URL = %q, want %q", env["ANTHROPIC_BASE_URL"], strings.TrimSpace(tt.baseURL))
|
||||
}
|
||||
}
|
||||
if tt.apiKey != "" && strings.TrimSpace(tt.apiKey) != "" {
|
||||
if env["ANTHROPIC_AUTH_TOKEN"] != strings.TrimSpace(tt.apiKey) {
|
||||
t.Errorf("ANTHROPIC_AUTH_TOKEN = %q, want %q", env["ANTHROPIC_AUTH_TOKEN"], strings.TrimSpace(tt.apiKey))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestEnvLoggingIntegration tests that env vars are properly masked in logs
|
||||
func TestEnvLoggingIntegration(t *testing.T) {
|
||||
b := backend.ClaudeBackend{}
|
||||
baseURL := "https://api.minimaxi.com/anthropic"
|
||||
apiKey := "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.longjwttoken"
|
||||
|
||||
env := b.Env(baseURL, apiKey)
|
||||
if env == nil {
|
||||
t.Fatal("expected non-nil env")
|
||||
}
|
||||
|
||||
// Verify that when we log these values, sensitive ones are masked
|
||||
for k, v := range env {
|
||||
masked := maskSensitiveValue(k, v)
|
||||
|
||||
if k == "ANTHROPIC_BASE_URL" {
|
||||
// URL should not be masked
|
||||
if masked != v {
|
||||
t.Errorf("BASE_URL should not be masked: got %q, want %q", masked, v)
|
||||
}
|
||||
}
|
||||
|
||||
if k == "ANTHROPIC_AUTH_TOKEN" {
|
||||
// API key should be masked
|
||||
if masked == v {
|
||||
t.Errorf("API_KEY should be masked, but got original value")
|
||||
}
|
||||
if !strings.Contains(masked, "****") {
|
||||
t.Errorf("masked API_KEY should contain ****: got %q", masked)
|
||||
}
|
||||
// Should still show first 4 and last 4 chars
|
||||
if !strings.HasPrefix(masked, v[:4]) {
|
||||
t.Errorf("masked value should start with first 4 chars of original")
|
||||
}
|
||||
if !strings.HasSuffix(masked, v[len(v)-4:]) {
|
||||
t.Errorf("masked value should end with last 4 chars of original")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestGeminiBackendEnv tests GeminiBackend.Env for comparison
|
||||
func TestGeminiBackendEnv(t *testing.T) {
|
||||
b := backend.GeminiBackend{}
|
||||
env := b.Env("https://custom.api", "gemini-api-key-12345")
|
||||
|
||||
if env == nil {
|
||||
t.Fatal("expected non-nil env")
|
||||
}
|
||||
|
||||
// Check that GEMINI env vars are set
|
||||
if _, ok := env["GOOGLE_GEMINI_BASE_URL"]; !ok {
|
||||
t.Error("expected GOOGLE_GEMINI_BASE_URL in env")
|
||||
}
|
||||
if _, ok := env["GEMINI_API_KEY"]; !ok {
|
||||
t.Error("expected GEMINI_API_KEY in env")
|
||||
}
|
||||
|
||||
// Verify masking works for Gemini keys too
|
||||
for k, v := range env {
|
||||
masked := maskSensitiveValue(k, v)
|
||||
if strings.Contains(strings.ToLower(k), "key") {
|
||||
if masked == v && len(v) > 0 {
|
||||
t.Errorf("key %q should be masked", k)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestCodexBackendEnv tests CodexBackend.Env
|
||||
func TestCodexBackendEnv(t *testing.T) {
|
||||
b := backend.CodexBackend{}
|
||||
env := b.Env("https://custom.api", "codex-api-key-12345")
|
||||
|
||||
if env == nil {
|
||||
t.Fatal("expected non-nil env for codex")
|
||||
}
|
||||
|
||||
// Check for OPENAI env vars
|
||||
if _, ok := env["OPENAI_BASE_URL"]; !ok {
|
||||
t.Error("expected OPENAI_BASE_URL in env")
|
||||
}
|
||||
if _, ok := env["OPENAI_API_KEY"]; !ok {
|
||||
t.Error("expected OPENAI_API_KEY in env")
|
||||
}
|
||||
}
|
||||
133
codeagent-wrapper/internal/executor/env_stderr_test.go
Normal file
133
codeagent-wrapper/internal/executor/env_stderr_test.go
Normal file
@@ -0,0 +1,133 @@
|
||||
package executor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
config "codeagent-wrapper/internal/config"
|
||||
)
|
||||
|
||||
type fakeCmd struct {
|
||||
env map[string]string
|
||||
}
|
||||
|
||||
func (f *fakeCmd) Start() error { return nil }
|
||||
func (f *fakeCmd) Wait() error { return nil }
|
||||
func (f *fakeCmd) StdoutPipe() (io.ReadCloser, error) {
|
||||
return io.NopCloser(strings.NewReader("")), nil
|
||||
}
|
||||
func (f *fakeCmd) StderrPipe() (io.ReadCloser, error) {
|
||||
return nil, errors.New("fake stderr pipe error")
|
||||
}
|
||||
func (f *fakeCmd) StdinPipe() (io.WriteCloser, error) {
|
||||
return nil, errors.New("fake stdin pipe error")
|
||||
}
|
||||
func (f *fakeCmd) SetStderr(io.Writer) {}
|
||||
func (f *fakeCmd) SetDir(string) {}
|
||||
func (f *fakeCmd) SetEnv(env map[string]string) {
|
||||
if len(env) == 0 {
|
||||
return
|
||||
}
|
||||
if f.env == nil {
|
||||
f.env = make(map[string]string, len(env))
|
||||
}
|
||||
for k, v := range env {
|
||||
f.env[k] = v
|
||||
}
|
||||
}
|
||||
func (f *fakeCmd) Process() processHandle { return nil }
|
||||
|
||||
func TestEnvInjection_LogsToStderrAndMasksKey(t *testing.T) {
|
||||
// Arrange ~/.codeagent/models.json via HOME override.
|
||||
tmpDir := t.TempDir()
|
||||
configDir := filepath.Join(tmpDir, ".codeagent")
|
||||
if err := os.MkdirAll(configDir, 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
const baseURL = "https://api.minimaxi.com/anthropic"
|
||||
const apiKey = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.test"
|
||||
models := `{
|
||||
"agents": {
|
||||
"explore": {
|
||||
"backend": "claude",
|
||||
"model": "MiniMax-M2.1",
|
||||
"base_url": "` + baseURL + `",
|
||||
"api_key": "` + apiKey + `"
|
||||
}
|
||||
}
|
||||
}`
|
||||
if err := os.WriteFile(filepath.Join(configDir, "models.json"), []byte(models), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
oldHome := os.Getenv("HOME")
|
||||
if err := os.Setenv("HOME", tmpDir); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() { _ = os.Setenv("HOME", oldHome) }()
|
||||
|
||||
config.ResetModelsConfigCacheForTest()
|
||||
defer config.ResetModelsConfigCacheForTest()
|
||||
|
||||
// Capture stderr (RunCodexTaskWithContext prints env injection lines there).
|
||||
r, w, err := os.Pipe()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
oldStderr := os.Stderr
|
||||
os.Stderr = w
|
||||
defer func() { os.Stderr = oldStderr }()
|
||||
|
||||
readDone := make(chan string, 1)
|
||||
go func() {
|
||||
defer r.Close()
|
||||
b, _ := io.ReadAll(r)
|
||||
readDone <- string(b)
|
||||
}()
|
||||
|
||||
var cmd *fakeCmd
|
||||
restoreRunner := SetNewCommandRunner(func(ctx context.Context, name string, args ...string) CommandRunner {
|
||||
cmd = &fakeCmd{}
|
||||
return cmd
|
||||
})
|
||||
defer restoreRunner()
|
||||
|
||||
// Act: force an early return right after env injection by making StderrPipe fail.
|
||||
_ = RunCodexTaskWithContext(
|
||||
context.Background(),
|
||||
TaskSpec{Task: "hi", WorkDir: ".", Backend: "claude", Agent: "explore"},
|
||||
nil,
|
||||
"claude",
|
||||
nil,
|
||||
nil,
|
||||
false,
|
||||
false,
|
||||
1,
|
||||
)
|
||||
|
||||
_ = w.Close()
|
||||
got := <-readDone
|
||||
|
||||
// Assert: env was injected into the command and logging is present with masking.
|
||||
if cmd == nil || cmd.env == nil {
|
||||
t.Fatalf("expected cmd env to be set, got cmd=%v env=%v", cmd, nil)
|
||||
}
|
||||
if cmd.env["ANTHROPIC_BASE_URL"] != baseURL {
|
||||
t.Fatalf("ANTHROPIC_BASE_URL=%q, want %q", cmd.env["ANTHROPIC_BASE_URL"], baseURL)
|
||||
}
|
||||
if cmd.env["ANTHROPIC_AUTH_TOKEN"] != apiKey {
|
||||
t.Fatalf("ANTHROPIC_AUTH_TOKEN=%q, want %q", cmd.env["ANTHROPIC_AUTH_TOKEN"], apiKey)
|
||||
}
|
||||
|
||||
if !strings.Contains(got, "Env: ANTHROPIC_BASE_URL="+baseURL) {
|
||||
t.Fatalf("stderr missing base URL env log; stderr=%q", got)
|
||||
}
|
||||
if !strings.Contains(got, "Env: ANTHROPIC_AUTH_TOKEN=eyJh****test") {
|
||||
t.Fatalf("stderr missing masked API key log; stderr=%q", got)
|
||||
}
|
||||
}
|
||||
@@ -940,6 +940,11 @@ func RunCodexTaskWithContext(parentCtx context.Context, taskSpec TaskSpec, backe
|
||||
// Load gemini env from ~/.gemini/.env if exists
|
||||
if cfg.Backend == "gemini" {
|
||||
fileEnv = loadGeminiEnv()
|
||||
if cfg.Mode != "resume" && strings.TrimSpace(cfg.Model) == "" {
|
||||
if model := fileEnv["GEMINI_MODEL"]; model != "" {
|
||||
cfg.Model = model
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useStdin := taskSpec.UseStdin
|
||||
@@ -1062,6 +1067,12 @@ func RunCodexTaskWithContext(parentCtx context.Context, taskSpec TaskSpec, backe
|
||||
}
|
||||
if injected := envBackend.Env(baseURL, apiKey); len(injected) > 0 {
|
||||
cmd.SetEnv(injected)
|
||||
// Log injected env vars with masked API keys (to file and stderr)
|
||||
for k, v := range injected {
|
||||
msg := fmt.Sprintf("Env: %s=%s", k, maskSensitiveValue(k, v))
|
||||
logInfoFn(msg)
|
||||
fmt.Fprintln(os.Stderr, " "+msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1444,3 +1455,19 @@ func terminateCommand(cmd commandRunner) *forceKillTimer {
|
||||
|
||||
return &forceKillTimer{timer: timer, done: done}
|
||||
}
|
||||
|
||||
// maskSensitiveValue masks sensitive values like API keys for logging.
|
||||
// Values containing "key", "token", or "secret" (case-insensitive) are masked.
|
||||
// For values longer than 8 chars: shows first 4 + **** + last 4.
|
||||
// For shorter values: shows only ****.
|
||||
func maskSensitiveValue(key, value string) string {
|
||||
keyLower := strings.ToLower(key)
|
||||
if strings.Contains(keyLower, "key") || strings.Contains(keyLower, "token") || strings.Contains(keyLower, "secret") {
|
||||
if len(value) > 8 {
|
||||
return value[:4] + "****" + value[len(value)-4:]
|
||||
} else if len(value) > 0 {
|
||||
return "****"
|
||||
}
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
12
config.json
12
config.json
@@ -169,6 +169,18 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"do": {
|
||||
"enabled": false,
|
||||
"description": "7-phase feature development workflow with codeagent orchestration",
|
||||
"operations": [
|
||||
{
|
||||
"type": "copy_dir",
|
||||
"source": "skills/do",
|
||||
"target": "skills/do",
|
||||
"description": "Install do skill with hooks"
|
||||
}
|
||||
]
|
||||
},
|
||||
"course": {
|
||||
"enabled": false,
|
||||
"description": "课程开发工作流,包含 dev、产品需求和测试用例技能",
|
||||
|
||||
143
go.work.sum
Normal file
143
go.work.sum
Normal file
@@ -0,0 +1,143 @@
|
||||
cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM=
|
||||
cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4=
|
||||
cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg=
|
||||
cloud.google.com/go/compute v1.24.0/go.mod h1:kw1/T+h/+tK2LJK0wiPPx1intgdAM3j/g3hFDlscY40=
|
||||
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
|
||||
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
||||
cloud.google.com/go/firestore v1.15.0 h1:/k8ppuWOtNuDHt2tsRV42yI21uaGnKDEQnRFeBpbFF8=
|
||||
cloud.google.com/go/firestore v1.15.0/go.mod h1:GWOxFXcv8GZUtYpWHw/w6IuYNux/BtmeVTMmjrm4yhk=
|
||||
cloud.google.com/go/iam v1.1.5 h1:1jTsCu4bcsNsE4iiqNT5SHwrDRCfRmIaaaVFhRveTJI=
|
||||
cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8=
|
||||
cloud.google.com/go/longrunning v0.5.5 h1:GOE6pZFdSrTb4KAiKnXsJBtlE6mEyaW44oKyMILWnOg=
|
||||
cloud.google.com/go/longrunning v0.5.5/go.mod h1:WV2LAxD8/rg5Z1cNW6FJ/ZpX4E4VnDnoTk0yawPBB7s=
|
||||
cloud.google.com/go/storage v1.35.1 h1:B59ahL//eDfx2IIKFBeT5Atm9wnNmj3+8xG/W4WB//w=
|
||||
cloud.google.com/go/storage v1.35.1/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8=
|
||||
github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA=
|
||||
github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4=
|
||||
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
|
||||
github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w=
|
||||
github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
|
||||
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
|
||||
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
|
||||
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
|
||||
github.com/googleapis/gax-go/v2 v2.12.3 h1:5/zPPDvw8Q1SuXjrqrZslrqT7dL/uJT2CQii/cLCKqA=
|
||||
github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBHwWRvkNFJUQcS4=
|
||||
github.com/googleapis/google-cloud-go-testing v0.0.0-20210719221736-1c9a4c676720 h1:zC34cGQu69FG7qzJ3WiKW244WfhDC3xxYMeNOX2gtUQ=
|
||||
github.com/googleapis/google-cloud-go-testing v0.0.0-20210719221736-1c9a4c676720/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||
github.com/hashicorp/consul/api v1.28.2 h1:mXfkRHrpHN4YY3RqL09nXU1eHKLNiuAN4kHvDQ16k/8=
|
||||
github.com/hashicorp/consul/api v1.28.2/go.mod h1:KyzqzgMEya+IZPcD65YFoOVAgPpbfERu4I/tzG6/ueE=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
||||
github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c=
|
||||
github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc=
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
|
||||
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
|
||||
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY=
|
||||
github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
|
||||
github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/nats-io/nats.go v1.34.0 h1:fnxnPCNiwIG5w08rlMcEKTUw4AV/nKyGCOJE8TdhSPk=
|
||||
github.com/nats-io/nats.go v1.34.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8=
|
||||
github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI=
|
||||
github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc=
|
||||
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo=
|
||||
github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk=
|
||||
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/sagikazarmark/crypt v0.19.0 h1:WMyLTjHBo64UvNcWqpzY3pbZTYgnemZU8FBZigKc42E=
|
||||
github.com/sagikazarmark/crypt v0.19.0/go.mod h1:c6vimRziqqERhtSe0MhIvzE1w54FrCHtrXb5NH/ja78=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
go.etcd.io/etcd/api/v3 v3.5.12 h1:W4sw5ZoU2Juc9gBWuLk5U6fHfNVyY1WC5g9uiXZio/c=
|
||||
go.etcd.io/etcd/api/v3 v3.5.12/go.mod h1:Ot+o0SWSyT6uHhA56al1oCED0JImsRiU9Dc26+C2a+4=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.12 h1:EYDL6pWwyOsylrQyLp2w+HkQ46ATiOvoEdMarindU2A=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.12/go.mod h1:seTzl2d9APP8R5Y2hFL3NVlD6qC/dOT+3kvrqPyTas4=
|
||||
go.etcd.io/etcd/client/v2 v2.305.12 h1:0m4ovXYo1CHaA/Mp3X/Fak5sRNIWf01wk/X1/G3sGKI=
|
||||
go.etcd.io/etcd/client/v2 v2.305.12/go.mod h1:aQ/yhsxMu+Oht1FOupSr60oBvcS9cKXHrzBpDsPTf9E=
|
||||
go.etcd.io/etcd/client/v3 v3.5.12 h1:v5lCPXn1pf1Uu3M4laUE2hp/geOTc5uPcYYsNe1lDxg=
|
||||
go.etcd.io/etcd/client/v3 v3.5.12/go.mod h1:tSbBCakoWmmddL+BKVAJHa9km+O/E+bumDe9mSbPiqw=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw=
|
||||
go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
|
||||
go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
|
||||
go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
|
||||
go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
|
||||
go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
|
||||
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
|
||||
go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
|
||||
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
|
||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
|
||||
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI=
|
||||
golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
google.golang.org/api v0.171.0 h1:w174hnBPqut76FzW5Qaupt7zY8Kql6fiVjgys4f58sU=
|
||||
google.golang.org/api v0.171.0/go.mod h1:Hnq5AHm4OTMt2BUVjael2CWZFD6vksJdWCWiUAmjC9o=
|
||||
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
|
||||
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
|
||||
google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y=
|
||||
google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2 h1:rIo7ocm2roD9DcFIX67Ym8icoGCKSARAiPljFhh5suQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c h1:lfpJ/2rWPa/kJgxyyXM8PrNnfCzcmxJ265mADgwmvLI=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
|
||||
google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk=
|
||||
google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
36
install.py
36
install.py
@@ -121,8 +121,11 @@ def save_settings(ctx: Dict[str, Any], settings: Dict[str, Any]) -> None:
|
||||
_save_json(settings_path, settings)
|
||||
|
||||
|
||||
def find_module_hooks(module_name: str, cfg: Dict[str, Any], ctx: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
||||
"""Find hooks.json for a module if it exists."""
|
||||
def find_module_hooks(module_name: str, cfg: Dict[str, Any], ctx: Dict[str, Any]) -> Optional[tuple]:
|
||||
"""Find hooks.json for a module if it exists.
|
||||
|
||||
Returns tuple of (hooks_config, plugin_root_path) or None.
|
||||
"""
|
||||
# Check for hooks in operations (copy_dir targets)
|
||||
for op in cfg.get("operations", []):
|
||||
if op.get("type") == "copy_dir":
|
||||
@@ -130,18 +133,19 @@ def find_module_hooks(module_name: str, cfg: Dict[str, Any], ctx: Dict[str, Any]
|
||||
hooks_file = target_dir / "hooks" / "hooks.json"
|
||||
if hooks_file.exists():
|
||||
try:
|
||||
return _load_json(hooks_file)
|
||||
return (_load_json(hooks_file), str(target_dir))
|
||||
except (ValueError, FileNotFoundError):
|
||||
pass
|
||||
|
||||
# Also check source directory during install
|
||||
for op in cfg.get("operations", []):
|
||||
if op.get("type") == "copy_dir":
|
||||
target_dir = ctx["install_dir"] / op["target"]
|
||||
source_dir = ctx["config_dir"] / op["source"]
|
||||
hooks_file = source_dir / "hooks" / "hooks.json"
|
||||
if hooks_file.exists():
|
||||
try:
|
||||
return _load_json(hooks_file)
|
||||
return (_load_json(hooks_file), str(target_dir))
|
||||
except (ValueError, FileNotFoundError):
|
||||
pass
|
||||
|
||||
@@ -153,7 +157,18 @@ def _create_hook_marker(module_name: str) -> str:
|
||||
return f"__module:{module_name}__"
|
||||
|
||||
|
||||
def merge_hooks_to_settings(module_name: str, hooks_config: Dict[str, Any], ctx: Dict[str, Any]) -> None:
|
||||
def _replace_hook_variables(obj: Any, plugin_root: str) -> Any:
|
||||
"""Recursively replace ${CLAUDE_PLUGIN_ROOT} in hook config."""
|
||||
if isinstance(obj, str):
|
||||
return obj.replace("${CLAUDE_PLUGIN_ROOT}", plugin_root)
|
||||
elif isinstance(obj, dict):
|
||||
return {k: _replace_hook_variables(v, plugin_root) for k, v in obj.items()}
|
||||
elif isinstance(obj, list):
|
||||
return [_replace_hook_variables(item, plugin_root) for item in obj]
|
||||
return obj
|
||||
|
||||
|
||||
def merge_hooks_to_settings(module_name: str, hooks_config: Dict[str, Any], ctx: Dict[str, Any], plugin_root: str = "") -> None:
|
||||
"""Merge module hooks into settings.json."""
|
||||
settings = load_settings(ctx)
|
||||
settings.setdefault("hooks", {})
|
||||
@@ -161,6 +176,10 @@ def merge_hooks_to_settings(module_name: str, hooks_config: Dict[str, Any], ctx:
|
||||
module_hooks = hooks_config.get("hooks", {})
|
||||
marker = _create_hook_marker(module_name)
|
||||
|
||||
# Replace ${CLAUDE_PLUGIN_ROOT} with actual path
|
||||
if plugin_root:
|
||||
module_hooks = _replace_hook_variables(module_hooks, plugin_root)
|
||||
|
||||
for hook_type, hook_entries in module_hooks.items():
|
||||
settings["hooks"].setdefault(hook_type, [])
|
||||
|
||||
@@ -707,10 +726,11 @@ def execute_module(name: str, cfg: Dict[str, Any], ctx: Dict[str, Any]) -> Dict[
|
||||
raise
|
||||
|
||||
# Handle hooks: find and merge module hooks into settings.json
|
||||
hooks_config = find_module_hooks(name, cfg, ctx)
|
||||
if hooks_config:
|
||||
hooks_result = find_module_hooks(name, cfg, ctx)
|
||||
if hooks_result:
|
||||
hooks_config, plugin_root = hooks_result
|
||||
try:
|
||||
merge_hooks_to_settings(name, hooks_config, ctx)
|
||||
merge_hooks_to_settings(name, hooks_config, ctx, plugin_root)
|
||||
result["operations"].append({"type": "merge_hooks", "status": "success"})
|
||||
result["has_hooks"] = True
|
||||
except Exception as exc:
|
||||
|
||||
90
requirements-driven-workflow/README.md
Normal file
90
requirements-driven-workflow/README.md
Normal file
@@ -0,0 +1,90 @@
|
||||
# requirements - Requirements-Driven Workflow
|
||||
|
||||
Lightweight requirements-to-code pipeline with interactive quality gates.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
python install.py --module requirements
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
/requirements-pilot <FEATURE_DESCRIPTION> [OPTIONS]
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `--skip-tests` | Skip testing phase entirely |
|
||||
| `--skip-scan` | Skip initial repository scanning |
|
||||
|
||||
## Workflow Phases
|
||||
|
||||
| Phase | Description | Output |
|
||||
|-------|-------------|--------|
|
||||
| 0 | Repository scanning | `00-repository-context.md` |
|
||||
| 1 | Requirements confirmation | `requirements-confirm.md` (90+ score required) |
|
||||
| 2 | Implementation | Code + `requirements-spec.md` |
|
||||
|
||||
## Quality Scoring (100-point system)
|
||||
|
||||
| Category | Points | Focus |
|
||||
|----------|--------|-------|
|
||||
| Functional Clarity | 30 | Input/output specs, success criteria |
|
||||
| Technical Specificity | 25 | Integration points, constraints |
|
||||
| Implementation Completeness | 25 | Edge cases, error handling |
|
||||
| Business Context | 20 | User value, priority |
|
||||
|
||||
## Sub-Agents
|
||||
|
||||
| Agent | Role |
|
||||
|-------|------|
|
||||
| `requirements-generate` | Create technical specifications |
|
||||
| `requirements-code` | Implement functionality |
|
||||
| `requirements-review` | Code quality evaluation |
|
||||
| `requirements-testing` | Test case creation |
|
||||
|
||||
## Approval Gate
|
||||
|
||||
One mandatory stop point after Phase 1:
|
||||
- Requirements must achieve 90+ quality score
|
||||
- User must explicitly approve before implementation begins
|
||||
|
||||
## Testing Decision
|
||||
|
||||
After code review passes (≥90%):
|
||||
- `--skip-tests`: Complete without testing
|
||||
- No option: Interactive prompt with smart recommendations based on task complexity
|
||||
|
||||
## Output Structure
|
||||
|
||||
```
|
||||
.claude/specs/{feature_name}/
|
||||
├── 00-repository-context.md
|
||||
├── requirements-confirm.md
|
||||
└── requirements-spec.md
|
||||
```
|
||||
|
||||
## When to Use
|
||||
|
||||
- Quick prototypes
|
||||
- Well-defined features
|
||||
- Smaller scope tasks
|
||||
- When full BMAD workflow is overkill
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
requirements-driven-workflow/
|
||||
├── README.md
|
||||
├── commands/
|
||||
│ └── requirements-pilot.md
|
||||
└── agents/
|
||||
├── requirements-generate.md
|
||||
├── requirements-code.md
|
||||
├── requirements-review.md
|
||||
└── requirements-testing.md
|
||||
```
|
||||
186
skills/do/README.md
Normal file
186
skills/do/README.md
Normal file
@@ -0,0 +1,186 @@
|
||||
# do - Feature Development Orchestrator
|
||||
|
||||
7-phase feature development workflow orchestrating multiple agents via codeagent-wrapper.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
python install.py --module do
|
||||
```
|
||||
|
||||
Installs:
|
||||
- `~/.claude/skills/do/` - skill files
|
||||
- hooks auto-merged into `~/.claude/settings.json`
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
/do <feature description>
|
||||
```
|
||||
|
||||
Examples:
|
||||
```
|
||||
/do add user login feature
|
||||
/do implement order export to CSV
|
||||
```
|
||||
|
||||
## 7-Phase Workflow
|
||||
|
||||
| Phase | Name | Goal | Key Actions |
|
||||
|-------|------|------|-------------|
|
||||
| 1 | Discovery | Understand requirements | AskUserQuestion + code-architect draft |
|
||||
| 2 | Exploration | Map codebase patterns | 2-3 parallel code-explorer tasks |
|
||||
| 3 | Clarification | Resolve ambiguities | **MANDATORY** - must answer before proceeding |
|
||||
| 4 | Architecture | Design implementation | 2 parallel code-architect approaches |
|
||||
| 5 | Implementation | Build the feature | **Requires approval** - develop agent |
|
||||
| 6 | Review | Catch defects | 2-3 parallel code-reviewer tasks |
|
||||
| 7 | Summary | Document results | code-reviewer summary |
|
||||
|
||||
## Agents
|
||||
|
||||
| Agent | Purpose | Prompt Location |
|
||||
|-------|---------|----------------|
|
||||
| `code-explorer` | Code tracing, architecture mapping | `agents/code-explorer.md` |
|
||||
| `code-architect` | Design approaches, file planning | `agents/code-architect.md` |
|
||||
| `code-reviewer` | Code review, simplification | `agents/code-reviewer.md` |
|
||||
| `develop` | Implement code, run tests | global config |
|
||||
|
||||
To customize agents, create same-named files in `~/.codeagent/agents/` to override.
|
||||
|
||||
## Hard Constraints
|
||||
|
||||
1. **Never write code directly** - delegate all changes to codeagent-wrapper agents
|
||||
2. **Phase 3 is mandatory** - do not proceed until questions are answered
|
||||
3. **Phase 5 requires approval** - stop after Phase 4 if not approved
|
||||
4. **Pass complete context forward** - every agent gets the Context Pack
|
||||
5. **Parallel-first** - run independent tasks via `codeagent-wrapper --parallel`
|
||||
6. **Update state after each phase** - keep `.claude/do.local.md` current
|
||||
|
||||
## Context Pack Template
|
||||
|
||||
```text
|
||||
## Original User Request
|
||||
<verbatim request>
|
||||
|
||||
## Context Pack
|
||||
- Phase: <1-7 name>
|
||||
- Decisions: <requirements/constraints/choices>
|
||||
- Code-explorer output: <paste or "None">
|
||||
- Code-architect output: <paste or "None">
|
||||
- Code-reviewer output: <paste or "None">
|
||||
- Develop output: <paste or "None">
|
||||
- Open questions: <list or "None">
|
||||
|
||||
## Current Task
|
||||
<specific task>
|
||||
|
||||
## Acceptance Criteria
|
||||
<checkable outputs>
|
||||
```
|
||||
|
||||
## Loop State Management
|
||||
|
||||
When triggered via `/do <task>`, initializes `.claude/do.local.md` with:
|
||||
- `active: true`
|
||||
- `current_phase: 1`
|
||||
- `max_phases: 7`
|
||||
- `completion_promise: "<promise>DO_COMPLETE</promise>"`
|
||||
|
||||
After each phase, update frontmatter:
|
||||
```yaml
|
||||
current_phase: <next phase number>
|
||||
phase_name: "<next phase name>"
|
||||
```
|
||||
|
||||
When all 7 phases complete, output:
|
||||
```
|
||||
<promise>DO_COMPLETE</promise>
|
||||
```
|
||||
|
||||
To abort early, set `active: false` in the state file.
|
||||
|
||||
## Stop Hook
|
||||
|
||||
A Stop hook is registered after installation:
|
||||
1. Creates `.claude/do.local.md` state file
|
||||
2. Updates `current_phase` after each phase
|
||||
3. Stop hook checks state, blocks exit if incomplete
|
||||
4. Outputs `<promise>DO_COMPLETE</promise>` when finished
|
||||
|
||||
Manual exit: Set `active` to `false` in the state file.
|
||||
|
||||
## Parallel Execution Examples
|
||||
|
||||
### Phase 2: Exploration (3 parallel tasks)
|
||||
```bash
|
||||
codeagent-wrapper --parallel <<'EOF'
|
||||
---TASK---
|
||||
id: p2_similar_features
|
||||
agent: code-explorer
|
||||
workdir: .
|
||||
---CONTENT---
|
||||
Find similar features, trace end-to-end.
|
||||
|
||||
---TASK---
|
||||
id: p2_architecture
|
||||
agent: code-explorer
|
||||
workdir: .
|
||||
---CONTENT---
|
||||
Map architecture for relevant subsystem.
|
||||
|
||||
---TASK---
|
||||
id: p2_conventions
|
||||
agent: code-explorer
|
||||
workdir: .
|
||||
---CONTENT---
|
||||
Identify testing patterns and conventions.
|
||||
EOF
|
||||
```
|
||||
|
||||
### Phase 4: Architecture (2 approaches)
|
||||
```bash
|
||||
codeagent-wrapper --parallel <<'EOF'
|
||||
---TASK---
|
||||
id: p4_minimal
|
||||
agent: code-architect
|
||||
workdir: .
|
||||
---CONTENT---
|
||||
Propose minimal-change architecture.
|
||||
|
||||
---TASK---
|
||||
id: p4_pragmatic
|
||||
agent: code-architect
|
||||
workdir: .
|
||||
---CONTENT---
|
||||
Propose pragmatic-clean architecture.
|
||||
EOF
|
||||
```
|
||||
|
||||
## ~/.codeagent/models.json Configuration
|
||||
|
||||
Optional. Uses codeagent-wrapper built-in config by default. To customize:
|
||||
|
||||
```json
|
||||
{
|
||||
"agents": {
|
||||
"code-explorer": {
|
||||
"backend": "claude",
|
||||
"model": "claude-sonnet-4-5-20250929"
|
||||
},
|
||||
"code-architect": {
|
||||
"backend": "claude",
|
||||
"model": "claude-sonnet-4-5-20250929"
|
||||
},
|
||||
"code-reviewer": {
|
||||
"backend": "claude",
|
||||
"model": "claude-sonnet-4-5-20250929"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Uninstall
|
||||
|
||||
```bash
|
||||
python install.py --uninstall --module do
|
||||
```
|
||||
331
skills/do/SKILL.md
Normal file
331
skills/do/SKILL.md
Normal file
@@ -0,0 +1,331 @@
|
||||
---
|
||||
name: do
|
||||
description: This skill should be used for structured feature development with codebase understanding. Triggers on /do command. Provides a 7-phase workflow (Discovery, Exploration, Clarification, Architecture, Implementation, Review, Summary) using codeagent-wrapper to orchestrate code-explorer, code-architect, code-reviewer, and develop agents in parallel.
|
||||
allowed-tools: ["Bash(${SKILL_DIR}/scripts/setup-do.sh:*)"]
|
||||
---
|
||||
|
||||
# do - Feature Development Orchestrator
|
||||
|
||||
An orchestrator for systematic feature development. Invoke agents via `codeagent-wrapper`, never write code directly.
|
||||
|
||||
## Loop Initialization (REQUIRED)
|
||||
|
||||
When triggered via `/do <task>`, **first** initialize the loop state:
|
||||
|
||||
```bash
|
||||
"${SKILL_DIR}/scripts/setup-do.sh" "<task description>"
|
||||
```
|
||||
|
||||
This creates `.claude/do.local.md` with:
|
||||
- `active: true`
|
||||
- `current_phase: 1`
|
||||
- `max_phases: 7`
|
||||
- `completion_promise: "<promise>DO_COMPLETE</promise>"`
|
||||
|
||||
## Loop State Management
|
||||
|
||||
After each phase, update `.claude/do.local.md` frontmatter:
|
||||
```yaml
|
||||
current_phase: <next phase number>
|
||||
phase_name: "<next phase name>"
|
||||
```
|
||||
|
||||
When all 7 phases complete, output the completion signal:
|
||||
```
|
||||
<promise>DO_COMPLETE</promise>
|
||||
```
|
||||
|
||||
To abort early, set `active: false` in the state file.
|
||||
|
||||
## Hard Constraints
|
||||
|
||||
1. **Never write code directly.** Delegate all code changes to `codeagent-wrapper` agents.
|
||||
2. **Phase 3 (Clarification) is mandatory.** Do not proceed until questions are answered.
|
||||
3. **Phase 5 (Implementation) requires explicit approval.** Stop after Phase 4 if not approved.
|
||||
4. **Pass complete context forward.** Every agent invocation includes the Context Pack.
|
||||
5. **Parallel-first.** Run independent tasks via `codeagent-wrapper --parallel`.
|
||||
6. **Update state after each phase.** Keep `.claude/do.local.md` current.
|
||||
|
||||
## Agents
|
||||
|
||||
| Agent | Purpose | Prompt |
|
||||
|-------|---------|--------|
|
||||
| `code-explorer` | Trace code, map architecture, find patterns | `agents/code-explorer.md` |
|
||||
| `code-architect` | Design approaches, file plans, build sequences | `agents/code-architect.md` |
|
||||
| `code-reviewer` | Review for bugs, simplicity, conventions | `agents/code-reviewer.md` |
|
||||
| `develop` | Implement code, run tests | (uses global config) |
|
||||
|
||||
## Context Pack Template
|
||||
|
||||
```text
|
||||
## Original User Request
|
||||
<verbatim request>
|
||||
|
||||
## Context Pack
|
||||
- Phase: <1-7 name>
|
||||
- Decisions: <requirements/constraints/choices>
|
||||
- Code-explorer output: <paste or "None">
|
||||
- Code-architect output: <paste or "None">
|
||||
- Code-reviewer output: <paste or "None">
|
||||
- Develop output: <paste or "None">
|
||||
- Open questions: <list or "None">
|
||||
|
||||
## Current Task
|
||||
<specific task>
|
||||
|
||||
## Acceptance Criteria
|
||||
<checkable outputs>
|
||||
```
|
||||
|
||||
## 7-Phase Workflow
|
||||
|
||||
### Phase 1: Discovery
|
||||
|
||||
**Goal:** Understand what to build.
|
||||
|
||||
**Actions:**
|
||||
1. Use AskUserQuestion for: user-visible behavior, scope, constraints, acceptance criteria
|
||||
2. Invoke `code-architect` to draft requirements checklist and clarifying questions
|
||||
|
||||
```bash
|
||||
codeagent-wrapper --agent code-architect - . <<'EOF'
|
||||
## Original User Request
|
||||
/do <request>
|
||||
|
||||
## Context Pack
|
||||
- Code-explorer output: None
|
||||
- Code-architect output: None
|
||||
|
||||
## Current Task
|
||||
Produce requirements checklist and identify missing information.
|
||||
Output: Requirements, Non-goals, Risks, Acceptance criteria, Questions (<= 10)
|
||||
|
||||
## Acceptance Criteria
|
||||
Concrete, testable checklist; specific questions; no implementation.
|
||||
EOF
|
||||
```
|
||||
|
||||
### Phase 2: Exploration
|
||||
|
||||
**Goal:** Map codebase patterns and extension points.
|
||||
|
||||
**Actions:** Run 2-3 `code-explorer` tasks in parallel (similar features, architecture, tests/conventions).
|
||||
|
||||
```bash
|
||||
codeagent-wrapper --parallel <<'EOF'
|
||||
---TASK---
|
||||
id: p2_similar_features
|
||||
agent: code-explorer
|
||||
workdir: .
|
||||
---CONTENT---
|
||||
## Original User Request
|
||||
/do <request>
|
||||
|
||||
## Context Pack
|
||||
- Code-architect output: <Phase 1 output>
|
||||
|
||||
## Current Task
|
||||
Find 1-3 similar features, trace end-to-end. Return: key files with line numbers, call flow, extension points.
|
||||
|
||||
## Acceptance Criteria
|
||||
Concrete file:line map + reuse points.
|
||||
|
||||
---TASK---
|
||||
id: p2_architecture
|
||||
agent: code-explorer
|
||||
workdir: .
|
||||
---CONTENT---
|
||||
## Original User Request
|
||||
/do <request>
|
||||
|
||||
## Context Pack
|
||||
- Code-architect output: <Phase 1 output>
|
||||
|
||||
## Current Task
|
||||
Map architecture for relevant subsystem. Return: module map + 5-10 key files.
|
||||
|
||||
## Acceptance Criteria
|
||||
Clear boundaries; file:line references.
|
||||
|
||||
---TASK---
|
||||
id: p2_conventions
|
||||
agent: code-explorer
|
||||
workdir: .
|
||||
---CONTENT---
|
||||
## Original User Request
|
||||
/do <request>
|
||||
|
||||
## Context Pack
|
||||
- Code-architect output: <Phase 1 output>
|
||||
|
||||
## Current Task
|
||||
Identify testing patterns, conventions, config. Return: test commands + file locations.
|
||||
|
||||
## Acceptance Criteria
|
||||
Test commands + relevant test file paths.
|
||||
EOF
|
||||
```
|
||||
|
||||
### Phase 3: Clarification (MANDATORY)
|
||||
|
||||
**Goal:** Resolve all ambiguities before design.
|
||||
|
||||
**Actions:**
|
||||
1. Invoke `code-architect` to generate prioritized questions from Phase 1+2 outputs
|
||||
2. Use AskUserQuestion to present questions and wait for answers
|
||||
3. **Do not proceed until answered or defaults accepted**
|
||||
|
||||
### Phase 4: Architecture
|
||||
|
||||
**Goal:** Produce implementation plan fitting existing patterns.
|
||||
|
||||
**Actions:** Run 2 `code-architect` tasks in parallel (minimal-change vs pragmatic-clean).
|
||||
|
||||
```bash
|
||||
codeagent-wrapper --parallel <<'EOF'
|
||||
---TASK---
|
||||
id: p4_minimal
|
||||
agent: code-architect
|
||||
workdir: .
|
||||
---CONTENT---
|
||||
## Original User Request
|
||||
/do <request>
|
||||
|
||||
## Context Pack
|
||||
- Code-explorer output: <ALL Phase 2 outputs>
|
||||
- Code-architect output: <Phase 1 + Phase 3 answers>
|
||||
|
||||
## Current Task
|
||||
Propose minimal-change architecture: reuse existing abstractions, minimize new files.
|
||||
Output: file touch list, risks, edge cases.
|
||||
|
||||
## Acceptance Criteria
|
||||
Concrete blueprint; minimal moving parts.
|
||||
|
||||
---TASK---
|
||||
id: p4_pragmatic
|
||||
agent: code-architect
|
||||
workdir: .
|
||||
---CONTENT---
|
||||
## Original User Request
|
||||
/do <request>
|
||||
|
||||
## Context Pack
|
||||
- Code-explorer output: <ALL Phase 2 outputs>
|
||||
- Code-architect output: <Phase 1 + Phase 3 answers>
|
||||
|
||||
## Current Task
|
||||
Propose pragmatic-clean architecture: introduce seams for testability.
|
||||
Output: file touch list, testing plan, risks.
|
||||
|
||||
## Acceptance Criteria
|
||||
Implementable blueprint with build sequence and tests.
|
||||
EOF
|
||||
```
|
||||
|
||||
Use AskUserQuestion to let user choose approach.
|
||||
|
||||
### Phase 5: Implementation (Approval Required)
|
||||
|
||||
**Goal:** Build the feature.
|
||||
|
||||
**Actions:**
|
||||
1. Use AskUserQuestion: "Approve starting implementation?" (Approve / Not yet)
|
||||
2. If approved, invoke `develop`:
|
||||
|
||||
```bash
|
||||
codeagent-wrapper --agent develop - . <<'EOF'
|
||||
## Original User Request
|
||||
/do <request>
|
||||
|
||||
## Context Pack
|
||||
- Code-explorer output: <ALL Phase 2 outputs>
|
||||
- Code-architect output: <selected Phase 4 blueprint + Phase 3 answers>
|
||||
|
||||
## Current Task
|
||||
Implement with minimal change set following chosen architecture.
|
||||
- Follow Phase 2 patterns
|
||||
- Add/adjust tests per Phase 4 plan
|
||||
- Run narrowest relevant tests
|
||||
|
||||
## Acceptance Criteria
|
||||
Feature works end-to-end; tests pass; diff is minimal.
|
||||
EOF
|
||||
```
|
||||
|
||||
### Phase 6: Review
|
||||
|
||||
**Goal:** Catch defects and unnecessary complexity.
|
||||
|
||||
**Actions:** Run 2-3 `code-reviewer` tasks in parallel (correctness, simplicity).
|
||||
|
||||
```bash
|
||||
codeagent-wrapper --parallel <<'EOF'
|
||||
---TASK---
|
||||
id: p6_correctness
|
||||
agent: code-reviewer
|
||||
workdir: .
|
||||
---CONTENT---
|
||||
## Original User Request
|
||||
/do <request>
|
||||
|
||||
## Context Pack
|
||||
- Code-architect output: <Phase 4 blueprint>
|
||||
- Develop output: <Phase 5 output>
|
||||
|
||||
## Current Task
|
||||
Review for correctness, edge cases, failure modes. Assume adversarial inputs.
|
||||
|
||||
## Acceptance Criteria
|
||||
Issues with file:line references and concrete fixes.
|
||||
|
||||
---TASK---
|
||||
id: p6_simplicity
|
||||
agent: code-reviewer
|
||||
workdir: .
|
||||
---CONTENT---
|
||||
## Original User Request
|
||||
/do <request>
|
||||
|
||||
## Context Pack
|
||||
- Code-architect output: <Phase 4 blueprint>
|
||||
- Develop output: <Phase 5 output>
|
||||
|
||||
## Current Task
|
||||
Review for KISS: remove bloat, collapse needless abstractions.
|
||||
|
||||
## Acceptance Criteria
|
||||
Actionable simplifications with justification.
|
||||
EOF
|
||||
```
|
||||
|
||||
Use AskUserQuestion: Fix now / Fix later / Proceed as-is.
|
||||
|
||||
### Phase 7: Summary
|
||||
|
||||
**Goal:** Document what was built.
|
||||
|
||||
**Actions:** Invoke `code-reviewer` to produce summary:
|
||||
|
||||
```bash
|
||||
codeagent-wrapper --agent code-reviewer - . <<'EOF'
|
||||
## Original User Request
|
||||
/do <request>
|
||||
|
||||
## Context Pack
|
||||
- Code-architect output: <Phase 4 blueprint>
|
||||
- Code-reviewer output: <Phase 6 outcomes>
|
||||
- Develop output: <Phase 5 output + fixes>
|
||||
|
||||
## Current Task
|
||||
Write completion summary:
|
||||
- What was built
|
||||
- Key decisions/tradeoffs
|
||||
- Files modified (paths)
|
||||
- How to verify (commands)
|
||||
- Follow-ups (optional)
|
||||
|
||||
## Acceptance Criteria
|
||||
Short, technical, actionable summary.
|
||||
EOF
|
||||
```
|
||||
34
skills/do/agents/code-architect.md
Normal file
34
skills/do/agents/code-architect.md
Normal file
@@ -0,0 +1,34 @@
|
||||
---
|
||||
name: code-architect
|
||||
description: Designs feature architectures by analyzing existing codebase patterns and conventions, then providing comprehensive implementation blueprints with specific files to create/modify, component designs, data flows, and build sequences
|
||||
tools: Glob, Grep, LS, Read, NotebookRead, WebFetch, TodoWrite, WebSearch, KillShell, BashOutput
|
||||
model: sonnet
|
||||
color: green
|
||||
---
|
||||
|
||||
You are a senior software architect who delivers comprehensive, actionable architecture blueprints by deeply understanding codebases and making confident architectural decisions.
|
||||
|
||||
## Core Process
|
||||
|
||||
**1. Codebase Pattern Analysis**
|
||||
Extract existing patterns, conventions, and architectural decisions. Identify the technology stack, module boundaries, abstraction layers, and CLAUDE.md guidelines. Find similar features to understand established approaches.
|
||||
|
||||
**2. Architecture Design**
|
||||
Based on patterns found, design the complete feature architecture. Make decisive choices - pick one approach and commit. Ensure seamless integration with existing code. Design for testability, performance, and maintainability.
|
||||
|
||||
**3. Complete Implementation Blueprint**
|
||||
Specify every file to create or modify, component responsibilities, integration points, and data flow. Break implementation into clear phases with specific tasks.
|
||||
|
||||
## Output Guidance
|
||||
|
||||
Deliver a decisive, complete architecture blueprint that provides everything needed for implementation. Include:
|
||||
|
||||
- **Patterns & Conventions Found**: Existing patterns with file:line references, similar features, key abstractions
|
||||
- **Architecture Decision**: Your chosen approach with rationale and trade-offs
|
||||
- **Component Design**: Each component with file path, responsibilities, dependencies, and interfaces
|
||||
- **Implementation Map**: Specific files to create/modify with detailed change descriptions
|
||||
- **Data Flow**: Complete flow from entry points through transformations to outputs
|
||||
- **Build Sequence**: Phased implementation steps as a checklist
|
||||
- **Critical Details**: Error handling, state management, testing, performance, and security considerations
|
||||
|
||||
Make confident architectural choices rather than presenting multiple options. Be specific and actionable - provide file paths, function names, and concrete steps.
|
||||
51
skills/do/agents/code-explorer.md
Normal file
51
skills/do/agents/code-explorer.md
Normal file
@@ -0,0 +1,51 @@
|
||||
---
|
||||
name: code-explorer
|
||||
description: Deeply analyzes existing codebase features by tracing execution paths, mapping architecture layers, understanding patterns and abstractions, and documenting dependencies to inform new development
|
||||
tools: Glob, Grep, LS, Read, NotebookRead, WebFetch, TodoWrite, WebSearch, KillShell, BashOutput
|
||||
model: sonnet
|
||||
color: yellow
|
||||
---
|
||||
|
||||
You are an expert code analyst specializing in tracing and understanding feature implementations across codebases.
|
||||
|
||||
## Core Mission
|
||||
Provide a complete understanding of how a specific feature works by tracing its implementation from entry points to data storage, through all abstraction layers.
|
||||
|
||||
## Analysis Approach
|
||||
|
||||
**1. Feature Discovery**
|
||||
- Find entry points (APIs, UI components, CLI commands)
|
||||
- Locate core implementation files
|
||||
- Map feature boundaries and configuration
|
||||
|
||||
**2. Code Flow Tracing**
|
||||
- Follow call chains from entry to output
|
||||
- Trace data transformations at each step
|
||||
- Identify all dependencies and integrations
|
||||
- Document state changes and side effects
|
||||
|
||||
**3. Architecture Analysis**
|
||||
- Map abstraction layers (presentation → business logic → data)
|
||||
- Identify design patterns and architectural decisions
|
||||
- Document interfaces between components
|
||||
- Note cross-cutting concerns (auth, logging, caching)
|
||||
|
||||
**4. Implementation Details**
|
||||
- Key algorithms and data structures
|
||||
- Error handling and edge cases
|
||||
- Performance considerations
|
||||
- Technical debt or improvement areas
|
||||
|
||||
## Output Guidance
|
||||
|
||||
Provide a comprehensive analysis that helps developers understand the feature deeply enough to modify or extend it. Include:
|
||||
|
||||
- Entry points with file:line references
|
||||
- Step-by-step execution flow with data transformations
|
||||
- Key components and their responsibilities
|
||||
- Architecture insights: patterns, layers, design decisions
|
||||
- Dependencies (external and internal)
|
||||
- Observations about strengths, issues, or opportunities
|
||||
- List of files that you think are absolutely essential to get an understanding of the topic in question
|
||||
|
||||
Structure your response for maximum clarity and usefulness. Always include specific file paths and line numbers.
|
||||
46
skills/do/agents/code-reviewer.md
Normal file
46
skills/do/agents/code-reviewer.md
Normal file
@@ -0,0 +1,46 @@
|
||||
---
|
||||
name: code-reviewer
|
||||
description: Reviews code for bugs, logic errors, security vulnerabilities, code quality issues, and adherence to project conventions, using confidence-based filtering to report only high-priority issues that truly matter
|
||||
tools: Glob, Grep, LS, Read, NotebookRead, WebFetch, TodoWrite, WebSearch, KillShell, BashOutput
|
||||
model: sonnet
|
||||
color: red
|
||||
---
|
||||
|
||||
You are an expert code reviewer specializing in modern software development across multiple languages and frameworks. Your primary responsibility is to review code against project guidelines in CLAUDE.md with high precision to minimize false positives.
|
||||
|
||||
## Review Scope
|
||||
|
||||
By default, review unstaged changes from `git diff`. The user may specify different files or scope to review.
|
||||
|
||||
## Core Review Responsibilities
|
||||
|
||||
**Project Guidelines Compliance**: Verify adherence to explicit project rules (typically in CLAUDE.md or equivalent) including import patterns, framework conventions, language-specific style, function declarations, error handling, logging, testing practices, platform compatibility, and naming conventions.
|
||||
|
||||
**Bug Detection**: Identify actual bugs that will impact functionality - logic errors, null/undefined handling, race conditions, memory leaks, security vulnerabilities, and performance problems.
|
||||
|
||||
**Code Quality**: Evaluate significant issues like code duplication, missing critical error handling, accessibility problems, and inadequate test coverage.
|
||||
|
||||
## Confidence Scoring
|
||||
|
||||
Rate each potential issue on a scale from 0-100:
|
||||
|
||||
- **0**: Not confident at all. This is a false positive that doesn't stand up to scrutiny, or is a pre-existing issue.
|
||||
- **25**: Somewhat confident. This might be a real issue, but may also be a false positive. If stylistic, it wasn't explicitly called out in project guidelines.
|
||||
- **50**: Moderately confident. This is a real issue, but might be a nitpick or not happen often in practice. Not very important relative to the rest of the changes.
|
||||
- **75**: Highly confident. Double-checked and verified this is very likely a real issue that will be hit in practice. The existing approach is insufficient. Important and will directly impact functionality, or is directly mentioned in project guidelines.
|
||||
- **100**: Absolutely certain. Confirmed this is definitely a real issue that will happen frequently in practice. The evidence directly confirms this.
|
||||
|
||||
**Only report issues with confidence ≥ 80.** Focus on issues that truly matter - quality over quantity.
|
||||
|
||||
## Output Guidance
|
||||
|
||||
Start by clearly stating what you're reviewing. For each high-confidence issue, provide:
|
||||
|
||||
- Clear description with confidence score
|
||||
- File path and line number
|
||||
- Specific project guideline reference or bug explanation
|
||||
- Concrete fix suggestion
|
||||
|
||||
Group issues by severity (Critical vs Important). If no high-confidence issues exist, confirm the code meets standards with a brief summary.
|
||||
|
||||
Structure your response for maximum actionability - developers should know exactly what to fix and why.
|
||||
15
skills/do/hooks/hooks.json
Normal file
15
skills/do/hooks/hooks.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"description": "do loop hook for 7-phase workflow",
|
||||
"hooks": {
|
||||
"Stop": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/stop-hook.sh"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
123
skills/do/hooks/stop-hook.sh
Executable file
123
skills/do/hooks/stop-hook.sh
Executable file
@@ -0,0 +1,123 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
phase_name_for() {
|
||||
case "${1:-}" in
|
||||
1) echo "Discovery" ;;
|
||||
2) echo "Exploration" ;;
|
||||
3) echo "Clarification" ;;
|
||||
4) echo "Architecture" ;;
|
||||
5) echo "Implementation" ;;
|
||||
6) echo "Review" ;;
|
||||
7) echo "Summary" ;;
|
||||
*) echo "Phase ${1:-unknown}" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
json_escape() {
|
||||
local s="${1:-}"
|
||||
s=${s//\\/\\\\}
|
||||
s=${s//\"/\\\"}
|
||||
s=${s//$'\n'/\\n}
|
||||
s=${s//$'\r'/\\r}
|
||||
s=${s//$'\t'/\\t}
|
||||
printf "%s" "$s"
|
||||
}
|
||||
|
||||
project_dir="${CLAUDE_PROJECT_DIR:-$PWD}"
|
||||
state_file="${project_dir}/.claude/do.local.md"
|
||||
|
||||
if [ ! -f "$state_file" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
stdin_payload=""
|
||||
if [ ! -t 0 ]; then
|
||||
stdin_payload="$(cat || true)"
|
||||
fi
|
||||
|
||||
frontmatter_get() {
|
||||
local key="$1"
|
||||
awk -v k="$key" '
|
||||
BEGIN { in_fm=0 }
|
||||
NR==1 && $0=="---" { in_fm=1; next }
|
||||
in_fm==1 && $0=="---" { exit }
|
||||
in_fm==1 {
|
||||
if ($0 ~ "^"k":[[:space:]]*") {
|
||||
sub("^"k":[[:space:]]*", "", $0)
|
||||
gsub(/^[[:space:]]+|[[:space:]]+$/, "", $0)
|
||||
if ($0 ~ /^".*"$/) { sub(/^"/, "", $0); sub(/"$/, "", $0) }
|
||||
print $0
|
||||
exit
|
||||
}
|
||||
}
|
||||
' "$state_file"
|
||||
}
|
||||
|
||||
active_raw="$(frontmatter_get active || true)"
|
||||
active_lc="$(printf "%s" "$active_raw" | tr '[:upper:]' '[:lower:]')"
|
||||
case "$active_lc" in
|
||||
true|1|yes|on) ;;
|
||||
*) exit 0 ;;
|
||||
esac
|
||||
|
||||
current_phase_raw="$(frontmatter_get current_phase || true)"
|
||||
max_phases_raw="$(frontmatter_get max_phases || true)"
|
||||
phase_name="$(frontmatter_get phase_name || true)"
|
||||
completion_promise="$(frontmatter_get completion_promise || true)"
|
||||
|
||||
current_phase=1
|
||||
if [[ "${current_phase_raw:-}" =~ ^[0-9]+$ ]]; then
|
||||
current_phase="$current_phase_raw"
|
||||
fi
|
||||
|
||||
max_phases=7
|
||||
if [[ "${max_phases_raw:-}" =~ ^[0-9]+$ ]]; then
|
||||
max_phases="$max_phases_raw"
|
||||
fi
|
||||
|
||||
if [ -z "${phase_name:-}" ]; then
|
||||
phase_name="$(phase_name_for "$current_phase")"
|
||||
fi
|
||||
|
||||
if [ -z "${completion_promise:-}" ]; then
|
||||
completion_promise="<promise>DO_COMPLETE</promise>"
|
||||
fi
|
||||
|
||||
phases_done=0
|
||||
if [ "$current_phase" -ge "$max_phases" ]; then
|
||||
phases_done=1
|
||||
fi
|
||||
|
||||
promise_met=0
|
||||
if [ -n "$completion_promise" ]; then
|
||||
if [ -n "$stdin_payload" ] && printf "%s" "$stdin_payload" | grep -Fq -- "$completion_promise"; then
|
||||
promise_met=1
|
||||
else
|
||||
body="$(
|
||||
awk '
|
||||
BEGIN { in_fm=0; body=0 }
|
||||
NR==1 && $0=="---" { in_fm=1; next }
|
||||
in_fm==1 && $0=="---" { body=1; in_fm=0; next }
|
||||
body==1 { print }
|
||||
' "$state_file"
|
||||
)"
|
||||
if [ -n "$body" ] && printf "%s" "$body" | grep -Fq -- "$completion_promise"; then
|
||||
promise_met=1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$phases_done" -eq 1 ] && [ "$promise_met" -eq 1 ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$phases_done" -eq 0 ]; then
|
||||
reason="do loop incomplete: current phase ${current_phase}/${max_phases} (${phase_name}). Continue with remaining phases; update ${state_file} current_phase/phase_name after each phase. Include completion_promise in final output when done: ${completion_promise}. To exit early, set active to false."
|
||||
else
|
||||
reason="do reached final phase (current_phase=${current_phase} / max_phases=${max_phases}, phase_name=${phase_name}), but completion_promise not detected: ${completion_promise}. Please include this marker in your final output (or write it to ${state_file} body), then finish; to force exit, set active to false."
|
||||
fi
|
||||
|
||||
printf '{"decision":"block","reason":"%s"}\n' "$(json_escape "$reason")"
|
||||
exit 0
|
||||
111
skills/do/scripts/setup-do.sh
Executable file
111
skills/do/scripts/setup-do.sh
Executable file
@@ -0,0 +1,111 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage: setup-do.sh [options] PROMPT...
|
||||
|
||||
Creates (or overwrites) project state file:
|
||||
.claude/do.local.md
|
||||
|
||||
Options:
|
||||
--max-phases N Default: 7
|
||||
--completion-promise STR Default: <promise>DO_COMPLETE</promise>
|
||||
-h, --help Show this help
|
||||
EOF
|
||||
}
|
||||
|
||||
die() {
|
||||
echo "❌ $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
phase_name_for() {
|
||||
case "${1:-}" in
|
||||
1) echo "Discovery" ;;
|
||||
2) echo "Exploration" ;;
|
||||
3) echo "Clarification" ;;
|
||||
4) echo "Architecture" ;;
|
||||
5) echo "Implementation" ;;
|
||||
6) echo "Review" ;;
|
||||
7) echo "Summary" ;;
|
||||
*) echo "Phase ${1:-unknown}" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
max_phases=7
|
||||
completion_promise="<promise>DO_COMPLETE</promise>"
|
||||
declare -a prompt_parts=()
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
--max-phases)
|
||||
[ $# -ge 2 ] || die "--max-phases requires a value"
|
||||
max_phases="$2"
|
||||
shift 2
|
||||
;;
|
||||
--completion-promise)
|
||||
[ $# -ge 2 ] || die "--completion-promise requires a value"
|
||||
completion_promise="$2"
|
||||
shift 2
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
while [ $# -gt 0 ]; do
|
||||
prompt_parts+=("$1")
|
||||
shift
|
||||
done
|
||||
break
|
||||
;;
|
||||
-*)
|
||||
die "Unknown argument: $1 (use --help)"
|
||||
;;
|
||||
*)
|
||||
prompt_parts+=("$1")
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
prompt="${prompt_parts[*]:-}"
|
||||
[ -n "$prompt" ] || die "PROMPT is required (use --help)"
|
||||
|
||||
if ! [[ "$max_phases" =~ ^[0-9]+$ ]] || [ "$max_phases" -lt 1 ]; then
|
||||
die "--max-phases must be a positive integer"
|
||||
fi
|
||||
|
||||
project_dir="${CLAUDE_PROJECT_DIR:-$PWD}"
|
||||
state_dir="${project_dir}/.claude"
|
||||
state_file="${state_dir}/do.local.md"
|
||||
|
||||
mkdir -p "$state_dir"
|
||||
|
||||
phase_name="$(phase_name_for 1)"
|
||||
|
||||
cat > "$state_file" << EOF
|
||||
---
|
||||
active: true
|
||||
current_phase: 1
|
||||
phase_name: "$phase_name"
|
||||
max_phases: $max_phases
|
||||
completion_promise: "$completion_promise"
|
||||
---
|
||||
|
||||
# do loop state
|
||||
|
||||
## Prompt
|
||||
$prompt
|
||||
|
||||
## Notes
|
||||
- Update frontmatter current_phase/phase_name as you progress
|
||||
- When complete, include the frontmatter completion_promise in your final output
|
||||
EOF
|
||||
|
||||
echo "Initialized: $state_file"
|
||||
echo "phase: 1/$max_phases ($phase_name)"
|
||||
echo "completion_promise: $completion_promise"
|
||||
@@ -1,14 +1,14 @@
|
||||
# OmO Multi-Agent Orchestration
|
||||
# omo - Multi-Agent Orchestration
|
||||
|
||||
OmO (Oh-My-OpenCode) is a multi-agent orchestration skill that delegates tasks to specialized agents based on routing signals.
|
||||
OmO is a multi-agent orchestration skill that routes tasks to specialized agents based on risk signals.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
python3 install.py --module omo
|
||||
python install.py --module omo
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
## Usage
|
||||
|
||||
```
|
||||
/omo <your task>
|
||||
@@ -18,59 +18,107 @@ python3 install.py --module omo
|
||||
|
||||
| Agent | Role | Backend | Model |
|
||||
|-------|------|---------|-------|
|
||||
| oracle | Technical advisor | claude | claude-opus-4-5-20251101 |
|
||||
| librarian | External research | claude | claude-sonnet-4-5-20250929 |
|
||||
| explore | Codebase search | opencode | opencode/grok-code |
|
||||
| develop | Code implementation | codex | gpt-5.2 |
|
||||
| frontend-ui-ux-engineer | UI/UX specialist | gemini | gemini-3-pro-preview |
|
||||
| document-writer | Documentation | gemini | gemini-3-flash-preview |
|
||||
| `oracle` | Technical advisor | claude | claude-opus-4-5 |
|
||||
| `librarian` | External research | claude | claude-sonnet-4-5 |
|
||||
| `explore` | Codebase search | opencode | grok-code |
|
||||
| `develop` | Code implementation | codex | gpt-5.2 |
|
||||
| `frontend-ui-ux-engineer` | UI/UX specialist | gemini | gemini-3-pro |
|
||||
| `document-writer` | Documentation | gemini | gemini-3-flash |
|
||||
|
||||
## How It Works
|
||||
## Routing Signals (Not Fixed Pipeline)
|
||||
|
||||
1. `/omo` analyzes your request via routing signals
|
||||
2. Based on task type, it either:
|
||||
- Answers directly (analysis/explanation tasks - no code changes)
|
||||
- Delegates to specialized agents (implementation tasks)
|
||||
- Fires parallel agents (exploration + research)
|
||||
This skill is **routing-first**, not a mandatory conveyor belt.
|
||||
|
||||
| Signal | Add Agent |
|
||||
|--------|----------|
|
||||
| Code location/behavior unclear | `explore` |
|
||||
| External library/API usage unclear | `librarian` |
|
||||
| Risky change (multi-file, public API, security, perf) | `oracle` |
|
||||
| Implementation required | `develop` / `frontend-ui-ux-engineer` |
|
||||
| Documentation needed | `document-writer` |
|
||||
|
||||
### Skipping Heuristics
|
||||
|
||||
- Skip `explore` when exact file path + line number is known
|
||||
- Skip `oracle` when change is local + low-risk (single area, clear fix)
|
||||
- Skip implementation agents when user only wants analysis
|
||||
|
||||
## Common Recipes
|
||||
|
||||
| Task | Recipe |
|
||||
|------|--------|
|
||||
| Explain code | `explore` |
|
||||
| Small fix with known location | `develop` directly |
|
||||
| Bug fix, location unknown | `explore → develop` |
|
||||
| Cross-cutting refactor | `explore → oracle → develop` |
|
||||
| External API integration | `explore + librarian → oracle → develop` |
|
||||
| UI-only change | `explore → frontend-ui-ux-engineer` |
|
||||
| Docs-only change | `explore → document-writer` |
|
||||
|
||||
## Context Pack Template
|
||||
|
||||
Every agent invocation includes:
|
||||
|
||||
```text
|
||||
## Original User Request
|
||||
<original request>
|
||||
|
||||
## Context Pack (include anything relevant; write "None" if absent)
|
||||
- Explore output: <...>
|
||||
- Librarian output: <...>
|
||||
- Oracle output: <...>
|
||||
- Known constraints: <tests to run, time budget, repo conventions>
|
||||
|
||||
## Current Task
|
||||
<specific task description>
|
||||
|
||||
## Acceptance Criteria
|
||||
<clear completion conditions>
|
||||
```
|
||||
|
||||
## Agent Invocation
|
||||
|
||||
```bash
|
||||
codeagent-wrapper --agent <agent_name> - <workdir> <<'EOF'
|
||||
## Original User Request
|
||||
...
|
||||
|
||||
## Context Pack
|
||||
...
|
||||
|
||||
## Current Task
|
||||
...
|
||||
|
||||
## Acceptance Criteria
|
||||
...
|
||||
EOF
|
||||
```
|
||||
|
||||
Timeout: 2 hours.
|
||||
|
||||
## Examples
|
||||
|
||||
```bash
|
||||
# Refactoring
|
||||
/omo Help me refactor this authentication module
|
||||
# Analysis only
|
||||
/omo how does this function work?
|
||||
# → explore
|
||||
|
||||
# Feature development
|
||||
/omo I need to add a new payment feature with frontend UI and backend API
|
||||
# Bug fix with unknown location
|
||||
/omo fix the authentication bug
|
||||
# → explore → develop
|
||||
|
||||
# Research
|
||||
/omo What authentication scheme does this project use?
|
||||
```
|
||||
# Feature with external API
|
||||
/omo add Stripe payment integration
|
||||
# → explore + librarian → oracle → develop
|
||||
|
||||
## Agent Delegation
|
||||
|
||||
Delegates via codeagent-wrapper with full Context Pack:
|
||||
|
||||
```bash
|
||||
codeagent-wrapper --agent oracle - . <<'EOF'
|
||||
## Original User Request
|
||||
Analyze the authentication architecture and recommend improvements.
|
||||
|
||||
## Context Pack (include anything relevant; write "None" if absent)
|
||||
- Explore output: [paste explore output if available]
|
||||
- Librarian output: None
|
||||
- Oracle output: None
|
||||
|
||||
## Current Task
|
||||
Review auth architecture, identify risks, propose minimal improvements.
|
||||
|
||||
## Acceptance Criteria
|
||||
Output: recommendation, action plan, risk assessment, effort estimate.
|
||||
EOF
|
||||
# UI change
|
||||
/omo redesign the dashboard layout
|
||||
# → explore → frontend-ui-ux-engineer
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Agent-model mappings are configured in `~/.codeagent/models.json`:
|
||||
Agent-model mappings in `~/.codeagent/models.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -80,34 +128,28 @@ Agent-model mappings are configured in `~/.codeagent/models.json`:
|
||||
"oracle": {
|
||||
"backend": "claude",
|
||||
"model": "claude-opus-4-5-20251101",
|
||||
"description": "Technical advisor",
|
||||
"yolo": true
|
||||
},
|
||||
"librarian": {
|
||||
"backend": "claude",
|
||||
"model": "claude-sonnet-4-5-20250929",
|
||||
"description": "Researcher",
|
||||
"yolo": true
|
||||
},
|
||||
"explore": {
|
||||
"backend": "opencode",
|
||||
"model": "opencode/grok-code",
|
||||
"description": "Code search"
|
||||
"model": "opencode/grok-code"
|
||||
},
|
||||
"frontend-ui-ux-engineer": {
|
||||
"backend": "gemini",
|
||||
"model": "gemini-3-pro-preview",
|
||||
"description": "Frontend engineer"
|
||||
"model": "gemini-3-pro-preview"
|
||||
},
|
||||
"document-writer": {
|
||||
"backend": "gemini",
|
||||
"model": "gemini-3-flash-preview",
|
||||
"description": "Documentation"
|
||||
"model": "gemini-3-flash-preview"
|
||||
},
|
||||
"develop": {
|
||||
"backend": "codex",
|
||||
"model": "gpt-5.2",
|
||||
"description": "codex develop",
|
||||
"yolo": true,
|
||||
"reasoning": "xhigh"
|
||||
}
|
||||
@@ -115,6 +157,14 @@ Agent-model mappings are configured in `~/.codeagent/models.json`:
|
||||
}
|
||||
```
|
||||
|
||||
## Hard Constraints
|
||||
|
||||
1. **Never write code yourself** - delegate to implementation agents
|
||||
2. **Always pass context forward** - include original request + prior outputs
|
||||
3. **No direct grep/glob for non-trivial exploration** - use `explore`
|
||||
4. **No external docs guessing** - use `librarian`
|
||||
5. **Use fewest agents possible** - skipping is normal
|
||||
|
||||
## Requirements
|
||||
|
||||
- codeagent-wrapper with `--agent` support
|
||||
|
||||
@@ -1,96 +1,169 @@
|
||||
# SPARV - Unified Development Workflow (Simplified)
|
||||
# sparv - SPARV Workflow
|
||||
|
||||
[]()
|
||||
[]()
|
||||
Minimal 5-phase workflow: **S**pecify → **P**lan → **A**ct → **R**eview → **V**ault.
|
||||
|
||||
**SPARV** is an end-to-end development workflow: maximize delivery quality with minimal rules while avoiding "infinite iteration + self-rationalization."
|
||||
|
||||
```
|
||||
S-Specify → P-Plan → A-Act → R-Review → V-Vault
|
||||
Clarify Plan Execute Review Archive
|
||||
```
|
||||
|
||||
## Key Changes (Over-engineering Removed)
|
||||
|
||||
- External memory merged from 3 files into 1 `.sparv/journal.md`
|
||||
- Specify scoring simplified from 100-point to 10-point scale (threshold `>=9`)
|
||||
- Reboot Test reduced from 5 questions to 3 questions
|
||||
- Removed concurrency locks (Claude is single-threaded; locks only cause failures)
|
||||
Completes "requirements → verifiable delivery" in one pass with external memory.
|
||||
|
||||
## Installation
|
||||
|
||||
SPARV is installed at `~/.claude/skills/sparv/`.
|
||||
|
||||
Install from ZIP:
|
||||
|
||||
```bash
|
||||
unzip sparv.zip -d ~/.claude/skills/
|
||||
python install.py --module sparv
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
Installs to `~/.claude/skills/sparv/`.
|
||||
|
||||
Run in project root:
|
||||
## Usage
|
||||
|
||||
```
|
||||
/sparv <task description>
|
||||
```
|
||||
|
||||
## Core Rules (Mandatory)
|
||||
|
||||
| Rule | Description |
|
||||
|------|-------------|
|
||||
| **10-Point Specify Gate** | Spec score 0-10; must be >=9 to enter Plan |
|
||||
| **2-Action Save** | Append to `.sparv/journal.md` every 2 tool calls |
|
||||
| **3-Failure Protocol** | Stop and escalate after 3 consecutive failures |
|
||||
| **EHRB** | Explicit confirmation for high-risk (production/sensitive/destructive/billing/security) |
|
||||
| **Fixed Phase Names** | `specify|plan|act|review|vault` in `state.yaml` |
|
||||
|
||||
## 5-Phase Workflow
|
||||
|
||||
### Phase 1: Specify (10-Point Scale)
|
||||
|
||||
Each dimension scores 0/1/2, total 0-10:
|
||||
|
||||
| Dimension | Focus |
|
||||
|-----------|-------|
|
||||
| Value | Why do it, verifiable benefits/metrics |
|
||||
| Scope | MVP + what's out of scope |
|
||||
| Acceptance | Testable acceptance criteria |
|
||||
| Boundaries | Error/performance/compatibility/security limits |
|
||||
| Risk | EHRB/dependencies/unknowns + handling |
|
||||
|
||||
- `score < 9`: Keep asking questions; do not enter Plan
|
||||
- `score >= 9`: Write `completion_promise`, then enter Plan
|
||||
|
||||
### Phase 2: Plan
|
||||
|
||||
- Break into atomic tasks (2-5 minute granularity)
|
||||
- Each task has verifiable output/test point
|
||||
- Write plan to `.sparv/journal.md`
|
||||
|
||||
### Phase 3: Act
|
||||
|
||||
- **TDD Rule**: No failing test → no production code
|
||||
- Auto-write journal every 2 actions (PostToolUse hook)
|
||||
- 3-Failure Protocol enforced
|
||||
|
||||
### Phase 4: Review
|
||||
|
||||
- Two stages: Spec conformance → Code quality
|
||||
- Maximum 3 fix rounds; escalate if exceeded
|
||||
- Run 3-question reboot test before session ends
|
||||
|
||||
### Phase 5: Vault
|
||||
|
||||
- Archive current session to `.sparv/history/`
|
||||
- Update knowledge base `.sparv/kb.md`
|
||||
|
||||
## Enhanced Rules (v1.1)
|
||||
|
||||
### Uncertainty Declaration (G3)
|
||||
|
||||
When any Specify dimension scores < 2:
|
||||
```
|
||||
UNCERTAIN: <what> | ASSUMPTION: <fallback>
|
||||
UNCERTAIN: deployment target | ASSUMPTION: Docker container
|
||||
UNCERTAIN: auth method | OPTIONS: JWT / OAuth2 / Session
|
||||
```
|
||||
|
||||
### Requirement Routing
|
||||
|
||||
| Mode | Condition | Flow |
|
||||
|------|-----------|------|
|
||||
| **Quick** | score >= 9 AND <= 3 files AND no EHRB | Specify → Act → Review |
|
||||
| **Full** | otherwise | Specify → Plan → Act → Review → Vault |
|
||||
|
||||
### Knowledge Base Maintenance
|
||||
|
||||
During Vault phase, update `.sparv/kb.md`:
|
||||
- **Patterns**: Reusable code patterns discovered
|
||||
- **Decisions**: Architectural choices + rationale
|
||||
- **Gotchas**: Common pitfalls + solutions
|
||||
|
||||
### CHANGELOG Update
|
||||
|
||||
For non-trivial changes:
|
||||
```bash
|
||||
~/.claude/skills/sparv/scripts/changelog-update.sh --type <Added|Changed|Fixed|Removed> --desc "..."
|
||||
```
|
||||
|
||||
## External Memory
|
||||
|
||||
Initialize (run in project root):
|
||||
```bash
|
||||
~/.claude/skills/sparv/scripts/init-session.sh --force
|
||||
```
|
||||
|
||||
Creates:
|
||||
|
||||
```
|
||||
.sparv/
|
||||
├── state.yaml
|
||||
├── journal.md
|
||||
└── history/
|
||||
├── state.yaml # State machine
|
||||
├── journal.md # Unified log
|
||||
├── kb.md # Knowledge base
|
||||
└── history/ # Archive directory
|
||||
```
|
||||
|
||||
## External Memory System (Two Files)
|
||||
|
||||
- `state.yaml`: State (minimum fields: `session_id/current_phase/action_count/consecutive_failures`)
|
||||
- `journal.md`: Unified log (Plan/Progress/Findings all go here)
|
||||
|
||||
After archiving:
|
||||
|
||||
```
|
||||
.sparv/history/<session_id>/
|
||||
├── state.yaml
|
||||
└── journal.md
|
||||
```
|
||||
| File | Purpose |
|
||||
|------|--------|
|
||||
| `state.yaml` | session_id, current_phase, action_count, consecutive_failures |
|
||||
| `journal.md` | Plan/Progress/Findings unified log |
|
||||
| `kb.md` | patterns/decisions/gotchas |
|
||||
| `history/` | Archived sessions |
|
||||
|
||||
## Key Numbers
|
||||
|
||||
| Number | Meaning |
|
||||
|--------|---------|
|
||||
|--------|--------|
|
||||
| **9/10** | Specify score passing threshold |
|
||||
| **2** | Write to journal every 2 tool calls |
|
||||
| **3** | Failure retry limit / Review fix limit |
|
||||
| **3** | Reboot Test question count |
|
||||
| **12** | Default max iterations (optional safety valve) |
|
||||
|
||||
## Script Tools
|
||||
|
||||
| Script | Purpose |
|
||||
|--------|--------|
|
||||
| `init-session.sh` | Initialize `.sparv/`, generate state + journal |
|
||||
| `save-progress.sh` | Maintain action_count, append journal |
|
||||
| `check-ehrb.sh` | Scan diff/text, output ehrb_flags |
|
||||
| `failure-tracker.sh` | Maintain consecutive_failures |
|
||||
| `reboot-test.sh` | 3-question self-check |
|
||||
| `archive-session.sh` | Archive to history/ |
|
||||
| `changelog-update.sh` | Update CHANGELOG.md |
|
||||
|
||||
## Auto Hooks
|
||||
|
||||
Configured in `hooks/hooks.json`:
|
||||
|
||||
- **PostToolUse**: `save-progress.sh` (2-Action save)
|
||||
- **PreToolUse**: `check-ehrb.sh --diff --dry-run` (prompt only)
|
||||
- **Stop**: `reboot-test.sh --strict` (3-question self-check)
|
||||
|
||||
## Failure Tracking
|
||||
|
||||
```bash
|
||||
~/.claude/skills/sparv/scripts/init-session.sh --force
|
||||
~/.claude/skills/sparv/scripts/save-progress.sh "Edit" "done"
|
||||
~/.claude/skills/sparv/scripts/check-ehrb.sh --diff --fail-on-flags
|
||||
~/.claude/skills/sparv/scripts/failure-tracker.sh fail --note "tests are flaky"
|
||||
~/.claude/skills/sparv/scripts/reboot-test.sh --strict
|
||||
~/.claude/skills/sparv/scripts/archive-session.sh
|
||||
# Record failure
|
||||
~/.claude/skills/sparv/scripts/failure-tracker.sh fail --note "short blocker"
|
||||
|
||||
# Reset counter
|
||||
~/.claude/skills/sparv/scripts/failure-tracker.sh reset
|
||||
```
|
||||
|
||||
## Hooks
|
||||
## Uninstall
|
||||
|
||||
Hooks defined in `hooks/hooks.json`:
|
||||
|
||||
- PostToolUse: 2-Action auto-write to `journal.md`
|
||||
- PreToolUse: EHRB risk prompt (default dry-run)
|
||||
- Stop: 3-question reboot test (strict)
|
||||
|
||||
## References
|
||||
|
||||
- `SKILL.md`: Skill definition (for agent use)
|
||||
- `references/methodology.md`: Methodology quick reference
|
||||
|
||||
---
|
||||
|
||||
*Quality over speed—iterate until truly complete.*
|
||||
```bash
|
||||
python install.py --uninstall --module sparv
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user