mirror of
https://github.com/cexll/myclaude.git
synced 2026-02-06 02:34:09 +08:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2856055e2e | ||
|
|
a9c1e8178f | ||
|
|
1afeca88ae | ||
|
|
326ad85c74 | ||
|
|
e66bec0083 | ||
|
|
eb066395c2 | ||
|
|
b49dad842a | ||
|
|
d98086c661 | ||
|
|
0420646258 | ||
|
|
19a8d8e922 |
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -74,7 +74,7 @@ jobs:
|
||||
if [ "${{ matrix.goos }}" = "windows" ]; then
|
||||
OUTPUT_NAME="${OUTPUT_NAME}.exe"
|
||||
fi
|
||||
go build -ldflags="-s -w -X main.version=${VERSION}" -o ${OUTPUT_NAME} ./cmd/codeagent
|
||||
go build -ldflags="-s -w -X main.version=${VERSION}" -o ${OUTPUT_NAME} ./cmd/codeagent-wrapper
|
||||
chmod +x ${OUTPUT_NAME}
|
||||
echo "artifact_path=codeagent-wrapper/${OUTPUT_NAME}" >> $GITHUB_OUTPUT
|
||||
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
package main
|
||||
|
||||
import app "codeagent-wrapper/internal/app"
|
||||
|
||||
func main() {
|
||||
app.Run()
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
version = "6.0.0-alpha1"
|
||||
version = "6.1.2"
|
||||
defaultWorkdir = "."
|
||||
defaultTimeout = 7200 // seconds (2 hours)
|
||||
defaultCoverageTarget = 90.0
|
||||
@@ -24,7 +24,7 @@ const (
|
||||
stdoutCloseReasonWait = "wait-done"
|
||||
stdoutCloseReasonDrain = "drain-timeout"
|
||||
stdoutCloseReasonCtx = "context-cancel"
|
||||
stdoutDrainTimeout = 100 * time.Millisecond
|
||||
stdoutDrainTimeout = 500 * time.Millisecond
|
||||
)
|
||||
|
||||
// Test hooks for dependency injection
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -3698,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 ")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3714,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 ")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3730,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)
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ const (
|
||||
stdoutCloseReasonWait = "wait-done"
|
||||
stdoutCloseReasonDrain = "drain-timeout"
|
||||
stdoutCloseReasonCtx = "context-cancel"
|
||||
stdoutDrainTimeout = 100 * time.Millisecond
|
||||
stdoutDrainTimeout = 500 * time.Millisecond
|
||||
)
|
||||
|
||||
// Hook points (tests can override inside this package).
|
||||
@@ -1067,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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1449,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
|
||||
}
|
||||
|
||||
43
codeagent-wrapper/scripts/benchmark_claude.sh
Executable file
43
codeagent-wrapper/scripts/benchmark_claude.sh
Executable file
@@ -0,0 +1,43 @@
|
||||
#!/bin/bash
|
||||
# Benchmark script for Claude CLI stability test
|
||||
# Tests if the stdoutDrainTimeout fix resolves intermittent failures
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
RUNS=${1:-100}
|
||||
FAIL_COUNT=0
|
||||
SUCCESS_COUNT=0
|
||||
TIMEOUT_COUNT=0
|
||||
|
||||
echo "Running $RUNS iterations..."
|
||||
echo "---"
|
||||
|
||||
for i in $(seq 1 $RUNS); do
|
||||
result=$(timeout 30 codeagent --backend claude --skip-permissions 'say OK' 2>&1) || true
|
||||
|
||||
if echo "$result" | grep -q 'without agent_message'; then
|
||||
((FAIL_COUNT++))
|
||||
echo "[$i] FAIL: without agent_message"
|
||||
elif echo "$result" | grep -q 'timeout'; then
|
||||
((TIMEOUT_COUNT++))
|
||||
echo "[$i] TIMEOUT"
|
||||
elif echo "$result" | grep -q 'OK\|ok'; then
|
||||
((SUCCESS_COUNT++))
|
||||
printf "\r[$i] OK "
|
||||
else
|
||||
((FAIL_COUNT++))
|
||||
echo "[$i] FAIL: unexpected output"
|
||||
echo "$result" | head -3
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "---"
|
||||
echo "Results ($RUNS runs):"
|
||||
echo " Success: $SUCCESS_COUNT ($(echo "scale=1; $SUCCESS_COUNT * 100 / $RUNS" | bc)%)"
|
||||
echo " Fail: $FAIL_COUNT ($(echo "scale=1; $FAIL_COUNT * 100 / $RUNS" | bc)%)"
|
||||
echo " Timeout: $TIMEOUT_COUNT ($(echo "scale=1; $TIMEOUT_COUNT * 100 / $RUNS" | bc)%)"
|
||||
|
||||
if [ $FAIL_COUNT -gt 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
@@ -169,15 +169,15 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"feature-dev": {
|
||||
"do": {
|
||||
"enabled": false,
|
||||
"description": "7-phase feature development workflow with codeagent orchestration",
|
||||
"operations": [
|
||||
{
|
||||
"type": "copy_dir",
|
||||
"source": "skills/feature-dev",
|
||||
"target": "skills/feature-dev",
|
||||
"description": "Install feature-dev skill with hooks"
|
||||
"source": "skills/do",
|
||||
"target": "skills/do",
|
||||
"description": "Install do skill with hooks"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
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.{task_id}.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.{task_id}.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.{task_id}.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
|
||||
```
|
||||
@@ -1,30 +1,30 @@
|
||||
---
|
||||
name: feature-dev
|
||||
description: This skill should be used for structured feature development with codebase understanding. Triggers on /feature-dev 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-feature-dev.sh:*)"]
|
||||
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:*)"]
|
||||
---
|
||||
|
||||
# Feature Development Orchestrator
|
||||
# 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 `/feature-dev <task>`, **first** initialize the loop state:
|
||||
When triggered via `/do <task>`, **first** initialize the loop state:
|
||||
|
||||
```bash
|
||||
"${SKILL_DIR}/scripts/setup-feature-dev.sh" "<task description>"
|
||||
"${SKILL_DIR}/scripts/setup-do.sh" "<task description>"
|
||||
```
|
||||
|
||||
This creates `.claude/feature-dev.local.md` with:
|
||||
This creates `.claude/do.{task_id}.local.md` with:
|
||||
- `active: true`
|
||||
- `current_phase: 1`
|
||||
- `max_phases: 7`
|
||||
- `completion_promise: "<promise>FEATURE_COMPLETE</promise>"`
|
||||
- `completion_promise: "<promise>DO_COMPLETE</promise>"`
|
||||
|
||||
## Loop State Management
|
||||
|
||||
After each phase, update `.claude/feature-dev.local.md` frontmatter:
|
||||
After each phase, update `.claude/do.{task_id}.local.md` frontmatter:
|
||||
```yaml
|
||||
current_phase: <next phase number>
|
||||
phase_name: "<next phase name>"
|
||||
@@ -32,7 +32,7 @@ phase_name: "<next phase name>"
|
||||
|
||||
When all 7 phases complete, output the completion signal:
|
||||
```
|
||||
<promise>FEATURE_COMPLETE</promise>
|
||||
<promise>DO_COMPLETE</promise>
|
||||
```
|
||||
|
||||
To abort early, set `active: false` in the state file.
|
||||
@@ -44,7 +44,7 @@ To abort early, set `active: false` in the state file.
|
||||
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/feature-dev.local.md` current.
|
||||
6. **Update state after each phase.** Keep `.claude/do.{task_id}.local.md` current.
|
||||
|
||||
## Agents
|
||||
|
||||
@@ -90,7 +90,7 @@ To abort early, set `active: false` in the state file.
|
||||
```bash
|
||||
codeagent-wrapper --agent code-architect - . <<'EOF'
|
||||
## Original User Request
|
||||
/feature-dev <request>
|
||||
/do <request>
|
||||
|
||||
## Context Pack
|
||||
- Code-explorer output: None
|
||||
@@ -119,7 +119,7 @@ agent: code-explorer
|
||||
workdir: .
|
||||
---CONTENT---
|
||||
## Original User Request
|
||||
/feature-dev <request>
|
||||
/do <request>
|
||||
|
||||
## Context Pack
|
||||
- Code-architect output: <Phase 1 output>
|
||||
@@ -136,7 +136,7 @@ agent: code-explorer
|
||||
workdir: .
|
||||
---CONTENT---
|
||||
## Original User Request
|
||||
/feature-dev <request>
|
||||
/do <request>
|
||||
|
||||
## Context Pack
|
||||
- Code-architect output: <Phase 1 output>
|
||||
@@ -153,7 +153,7 @@ agent: code-explorer
|
||||
workdir: .
|
||||
---CONTENT---
|
||||
## Original User Request
|
||||
/feature-dev <request>
|
||||
/do <request>
|
||||
|
||||
## Context Pack
|
||||
- Code-architect output: <Phase 1 output>
|
||||
@@ -189,7 +189,7 @@ agent: code-architect
|
||||
workdir: .
|
||||
---CONTENT---
|
||||
## Original User Request
|
||||
/feature-dev <request>
|
||||
/do <request>
|
||||
|
||||
## Context Pack
|
||||
- Code-explorer output: <ALL Phase 2 outputs>
|
||||
@@ -208,7 +208,7 @@ agent: code-architect
|
||||
workdir: .
|
||||
---CONTENT---
|
||||
## Original User Request
|
||||
/feature-dev <request>
|
||||
/do <request>
|
||||
|
||||
## Context Pack
|
||||
- Code-explorer output: <ALL Phase 2 outputs>
|
||||
@@ -236,7 +236,7 @@ Use AskUserQuestion to let user choose approach.
|
||||
```bash
|
||||
codeagent-wrapper --agent develop - . <<'EOF'
|
||||
## Original User Request
|
||||
/feature-dev <request>
|
||||
/do <request>
|
||||
|
||||
## Context Pack
|
||||
- Code-explorer output: <ALL Phase 2 outputs>
|
||||
@@ -267,7 +267,7 @@ agent: code-reviewer
|
||||
workdir: .
|
||||
---CONTENT---
|
||||
## Original User Request
|
||||
/feature-dev <request>
|
||||
/do <request>
|
||||
|
||||
## Context Pack
|
||||
- Code-architect output: <Phase 4 blueprint>
|
||||
@@ -285,7 +285,7 @@ agent: code-reviewer
|
||||
workdir: .
|
||||
---CONTENT---
|
||||
## Original User Request
|
||||
/feature-dev <request>
|
||||
/do <request>
|
||||
|
||||
## Context Pack
|
||||
- Code-architect output: <Phase 4 blueprint>
|
||||
@@ -310,7 +310,7 @@ Use AskUserQuestion: Fix now / Fix later / Proceed as-is.
|
||||
```bash
|
||||
codeagent-wrapper --agent code-reviewer - . <<'EOF'
|
||||
## Original User Request
|
||||
/feature-dev <request>
|
||||
/do <request>
|
||||
|
||||
## Context Pack
|
||||
- Code-architect output: <Phase 4 blueprint>
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"description": "Feature-dev loop hook for 7-phase workflow",
|
||||
"description": "do loop hook for 7-phase workflow",
|
||||
"hooks": {
|
||||
"Stop": [
|
||||
{
|
||||
151
skills/do/hooks/stop-hook.sh
Executable file
151
skills/do/hooks/stop-hook.sh
Executable file
@@ -0,0 +1,151 @@
|
||||
#!/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_dir="${project_dir}/.claude"
|
||||
|
||||
shopt -s nullglob
|
||||
state_files=("${state_dir}"/do.*.local.md)
|
||||
shopt -u nullglob
|
||||
|
||||
if [ ${#state_files[@]} -eq 0 ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
stdin_payload=""
|
||||
if [ ! -t 0 ]; then
|
||||
stdin_payload="$(cat || true)"
|
||||
fi
|
||||
|
||||
frontmatter_get() {
|
||||
local file="$1" key="$2"
|
||||
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
|
||||
}
|
||||
}
|
||||
' "$file"
|
||||
}
|
||||
|
||||
check_state_file() {
|
||||
local state_file="$1"
|
||||
|
||||
local active_raw active_lc
|
||||
active_raw="$(frontmatter_get "$state_file" active || true)"
|
||||
active_lc="$(printf "%s" "$active_raw" | tr '[:upper:]' '[:lower:]')"
|
||||
case "$active_lc" in
|
||||
true|1|yes|on) ;;
|
||||
*) return 0 ;;
|
||||
esac
|
||||
|
||||
local current_phase_raw max_phases_raw phase_name completion_promise
|
||||
current_phase_raw="$(frontmatter_get "$state_file" current_phase || true)"
|
||||
max_phases_raw="$(frontmatter_get "$state_file" max_phases || true)"
|
||||
phase_name="$(frontmatter_get "$state_file" phase_name || true)"
|
||||
completion_promise="$(frontmatter_get "$state_file" completion_promise || true)"
|
||||
|
||||
local current_phase=1
|
||||
if [[ "${current_phase_raw:-}" =~ ^[0-9]+$ ]]; then
|
||||
current_phase="$current_phase_raw"
|
||||
fi
|
||||
|
||||
local 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
|
||||
|
||||
local phases_done=0
|
||||
if [ "$current_phase" -ge "$max_phases" ]; then
|
||||
phases_done=1
|
||||
fi
|
||||
|
||||
local 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
|
||||
local body
|
||||
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
|
||||
rm -f "$state_file"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local reason
|
||||
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 "%s" "$reason"
|
||||
}
|
||||
|
||||
blocking_reasons=()
|
||||
for state_file in "${state_files[@]}"; do
|
||||
reason="$(check_state_file "$state_file")"
|
||||
if [ -n "$reason" ]; then
|
||||
blocking_reasons+=("$reason")
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#blocking_reasons[@]} -eq 0 ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
combined_reason="${blocking_reasons[*]}"
|
||||
printf '{"decision":"block","reason":"%s"}\n' "$(json_escape "$combined_reason")"
|
||||
exit 0
|
||||
@@ -4,14 +4,14 @@ set -euo pipefail
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage: setup-feature-dev.sh [options] PROMPT...
|
||||
Usage: setup-do.sh [options] PROMPT...
|
||||
|
||||
Creates (or overwrites) project state file:
|
||||
.claude/feature-dev.local.md
|
||||
.claude/do.local.md
|
||||
|
||||
Options:
|
||||
--max-phases N Default: 7
|
||||
--completion-promise STR Default: <promise>FEATURE_COMPLETE</promise>
|
||||
--completion-promise STR Default: <promise>DO_COMPLETE</promise>
|
||||
-h, --help Show this help
|
||||
EOF
|
||||
}
|
||||
@@ -35,7 +35,7 @@ phase_name_for() {
|
||||
}
|
||||
|
||||
max_phases=7
|
||||
completion_promise="<promise>FEATURE_COMPLETE</promise>"
|
||||
completion_promise="<promise>DO_COMPLETE</promise>"
|
||||
declare -a prompt_parts=()
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
@@ -81,7 +81,9 @@ fi
|
||||
|
||||
project_dir="${CLAUDE_PROJECT_DIR:-$PWD}"
|
||||
state_dir="${project_dir}/.claude"
|
||||
state_file="${state_dir}/feature-dev.local.md"
|
||||
|
||||
task_id="$(date +%s)-$$-$(head -c 4 /dev/urandom | od -An -tx1 | tr -d ' \n')"
|
||||
state_file="${state_dir}/do.${task_id}.local.md"
|
||||
|
||||
mkdir -p "$state_dir"
|
||||
|
||||
@@ -96,7 +98,7 @@ max_phases: $max_phases
|
||||
completion_promise: "$completion_promise"
|
||||
---
|
||||
|
||||
# feature-dev loop state
|
||||
# do loop state
|
||||
|
||||
## Prompt
|
||||
$prompt
|
||||
@@ -107,5 +109,6 @@ $prompt
|
||||
EOF
|
||||
|
||||
echo "Initialized: $state_file"
|
||||
echo "task_id: $task_id"
|
||||
echo "phase: 1/$max_phases ($phase_name)"
|
||||
echo "completion_promise: $completion_promise"
|
||||
@@ -1,86 +0,0 @@
|
||||
# feature-dev
|
||||
|
||||
7 阶段功能开发工作流,使用 codeagent-wrapper 编排多个 agent。
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
python install.py --module feature-dev
|
||||
```
|
||||
|
||||
安装内容:
|
||||
- `~/.claude/skills/feature-dev/` - skill 文件
|
||||
- hooks 自动合并到 `~/.claude/settings.json`
|
||||
|
||||
## 使用
|
||||
|
||||
```
|
||||
/feature-dev <功能描述>
|
||||
```
|
||||
|
||||
示例:
|
||||
```
|
||||
/feature-dev 添加用户登录功能
|
||||
/feature-dev 实现订单导出 CSV
|
||||
```
|
||||
|
||||
## 工作流阶段
|
||||
|
||||
| 阶段 | 名称 | 目标 |
|
||||
|------|------|------|
|
||||
| 1 | Discovery | 理解需求 |
|
||||
| 2 | Exploration | 探索代码库 |
|
||||
| 3 | Clarification | 澄清疑问(必须) |
|
||||
| 4 | Architecture | 设计方案 |
|
||||
| 5 | Implementation | 实现(需审批) |
|
||||
| 6 | Review | 代码审查 |
|
||||
| 7 | Summary | 总结文档 |
|
||||
|
||||
## Agents
|
||||
|
||||
- `code-explorer` - 代码追踪、架构映射
|
||||
- `code-architect` - 方案设计、文件规划
|
||||
- `code-reviewer` - 代码审查、简化建议
|
||||
- `develop` - 实现代码、运行测试
|
||||
|
||||
Agent 提示词位于 `agents/` 目录。如需自定义,可在 `~/.codeagent/agents/` 创建同名文件覆盖。
|
||||
|
||||
## ~/.codeagent/models.json 配置
|
||||
|
||||
可选。默认使用 codeagent-wrapper 内置配置。如需自定义 agent 模型:
|
||||
|
||||
```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"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Loop 机制
|
||||
|
||||
安装后会注册 Stop hook。当 `/feature-dev` 执行时:
|
||||
|
||||
1. 创建 `.claude/feature-dev.local.md` 状态文件
|
||||
2. 每阶段更新 `current_phase`
|
||||
3. Stop hook 检测状态,未完成时阻止退出
|
||||
4. 完成后输出 `<promise>FEATURE_COMPLETE</promise>` 结束
|
||||
|
||||
手动退出:将状态文件中 `active` 设为 `false`。
|
||||
|
||||
## 卸载
|
||||
|
||||
```bash
|
||||
python install.py --uninstall --module feature-dev
|
||||
```
|
||||
@@ -1,123 +0,0 @@
|
||||
#!/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/feature-dev.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>FEATURE_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="feature-dev 循环未完成:当前阶段 ${current_phase}/${max_phases}(${phase_name})。继续执行剩余阶段;完成每个阶段后更新 ${state_file} 的 current_phase/phase_name。全部完成后在最终输出中包含 completion_promise:${completion_promise}。如需退出,将 active 设为 false。"
|
||||
else
|
||||
reason="feature-dev 已到最终阶段(current_phase=${current_phase} / max_phases=${max_phases},phase_name=${phase_name}),但未检测到 completion_promise:${completion_promise}。请在最终输出中包含该标记(或写入 ${state_file} 正文),然后再结束;如需强制退出,将 active 设为 false。"
|
||||
fi
|
||||
|
||||
printf '{"decision":"block","reason":"%s"}\n' "$(json_escape "$reason")"
|
||||
exit 0
|
||||
@@ -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