Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ This project embraces controlled chaos: multiple agents work simultaneously, pot
go build ./cmd/multiclaude # Build binary
go install ./cmd/multiclaude # Install to $GOPATH/bin

# CI Guard Rails (run before pushing)
make pre-commit # Fast checks: build + unit tests + verify docs
make check-all # Full CI: all checks that GitHub CI runs
make install-hooks # Install git pre-commit hook

# Test (run before pushing)
go test ./... # All tests
go test ./internal/daemon # Single package
Expand Down Expand Up @@ -284,4 +289,4 @@ multiclaude cleanup # Actually clean up
vim internal/templates/agent-templates/worker.md
go build ./cmd/multiclaude
# New workers will use updated prompt
```
```
125 changes: 125 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Makefile for multiclaude - Local CI Guard Rails
# Run these targets to verify changes before pushing

.PHONY: help build test unit-tests e2e-tests verify-docs coverage check-all pre-commit clean

# Default target
help:
@echo "Multiclaude Local CI Guard Rails"
@echo ""
@echo "Targets that mirror CI checks:"
@echo " make build - Build all packages (CI: Build job)"
@echo " make unit-tests - Run unit tests (CI: Unit Tests job)"
@echo " make e2e-tests - Run E2E tests (CI: E2E Tests job)"
@echo " make verify-docs - Check generated docs are up to date (CI: Verify Generated Docs job)"
@echo " make coverage - Run coverage check (CI: Coverage Check job)"
@echo ""
@echo "Comprehensive checks:"
@echo " make check-all - Run all CI checks locally (recommended before push)"
@echo " make pre-commit - Fast checks suitable for git pre-commit hook"
@echo ""
@echo "Setup:"
@echo " make install-hooks - Install git pre-commit hook"
@echo ""
@echo "Other:"
@echo " make test - Alias for unit-tests"
@echo " make clean - Clean build artifacts"

# Build - matches CI build job
build:
@echo "==> Building all packages..."
@go build -v ./...
@echo "✓ Build successful"

# Unit tests - matches CI unit-tests job
unit-tests:
@echo "==> Running unit tests..."
@command -v tmux >/dev/null 2>&1 || { echo "Error: tmux is required for tests. Install with: sudo apt-get install tmux"; exit 1; }
@go test -coverprofile=coverage.out -covermode=atomic ./internal/... ./pkg/...
@go tool cover -func=coverage.out | tail -1
@echo "✓ Unit tests passed"

# E2E tests - matches CI e2e-tests job
e2e-tests:
@echo "==> Running E2E tests..."
@command -v tmux >/dev/null 2>&1 || { echo "Error: tmux is required for tests. Install with: sudo apt-get install tmux"; exit 1; }
@git config user.email >/dev/null 2>&1 || git config --global user.email "ci@local.dev"
@git config user.name >/dev/null 2>&1 || git config --global user.name "Local CI"
@go test -v ./test/...
@echo "✓ E2E tests passed"

# Verify generated docs - matches CI verify-generated-docs job
verify-docs:
@echo "==> Verifying generated docs are up to date..."
@go generate ./pkg/config/...
@if ! git diff --quiet docs/DIRECTORY_STRUCTURE.md; then \
echo "Error: docs/DIRECTORY_STRUCTURE.md is out of date!"; \
echo "Run 'go generate ./pkg/config/...' or 'make generate' and commit the changes."; \
echo ""; \
echo "Diff:"; \
git diff docs/DIRECTORY_STRUCTURE.md; \
exit 1; \
fi
@echo "==> Verifying extension documentation consistency..."
@go run ./cmd/verify-docs
@echo "✓ Generated docs are up to date"

# Coverage check - matches CI coverage-check job
coverage:
@echo "==> Checking coverage thresholds..."
@command -v tmux >/dev/null 2>&1 || { echo "Error: tmux is required for tests. Install with: sudo apt-get install tmux"; exit 1; }
@go test -coverprofile=coverage.out -covermode=atomic ./internal/... ./pkg/...
@echo ""
@echo "Coverage summary:"
@go tool cover -func=coverage.out | grep "total:" || true
@echo ""
@echo "Per-package coverage:"
@go test -cover ./internal/... ./pkg/... 2>&1 | grep "coverage:" | sort
@echo "✓ Coverage check complete"

# Helper to regenerate docs
generate:
@echo "==> Regenerating documentation..."
@go generate ./pkg/config/...
@echo "✓ Documentation regenerated"

# Alias for unit-tests
test: unit-tests

# Pre-commit: Fast checks suitable for git hook
# Runs build + unit tests + verify docs (skips slower e2e tests)
pre-commit: build unit-tests verify-docs
@echo ""
@echo "✓ All pre-commit checks passed"

# Check all: Complete CI validation locally
# Runs all checks that CI will run
check-all: build unit-tests e2e-tests verify-docs coverage
@echo ""
@echo "=========================================="
@echo "✓ All CI checks passed locally!"
@echo "Your changes are ready to push."
@echo "=========================================="

# Install git hooks
install-hooks:
@echo "==> Installing git pre-commit hook..."
@mkdir -p .git/hooks
@if [ -f .git/hooks/pre-commit ]; then \
echo "Warning: .git/hooks/pre-commit already exists"; \
echo "Backing up to .git/hooks/pre-commit.backup"; \
cp .git/hooks/pre-commit .git/hooks/pre-commit.backup; \
fi
@cp scripts/pre-commit.sh .git/hooks/pre-commit
@chmod +x .git/hooks/pre-commit
@echo "✓ Git pre-commit hook installed"
@echo ""
@echo "The hook will run 'make pre-commit' before each commit."
@echo "To skip the hook temporarily, use: git commit --no-verify"

# Clean build artifacts
clean:
@echo "==> Cleaning build artifacts..."
@rm -f coverage.out
@go clean -cache
@echo "✓ Clean complete"
116 changes: 116 additions & 0 deletions WORKER_NAMING_EXAMPLES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Worker Naming Examples

This document demonstrates the new task-based worker naming feature.

## Before (Random Names)

```bash
$ multiclaude worker create "Fix session ID bug in authentication"
Creating worker 'calm-owl' in repo 'myproject'

$ multiclaude worker create "Add user profile editing"
Creating worker 'jolly-hawk' in repo 'myproject'
```

Workers had random adjective-animal names that provided no context about their purpose.

## After (Task-Based Names)

```bash
$ multiclaude worker create "Fix session ID bug in authentication"
Creating worker 'fix-session-id-bug' in repo 'myproject'

$ multiclaude worker create "Add user profile editing"
Creating worker 'add-user-profile-editing' in repo 'myproject'
```

Workers now have descriptive names derived from their task descriptions.

## How It Works

### 1. Keyword Extraction

The system extracts meaningful keywords from the task description:

```
Task: "Fix the session ID bug in authentication"
Keywords: ["fix", "session", "id", "bug"] (stop words removed: "the", "in")
Name: "fix-session-id-bug"
```

### 2. Sanitization

Names are converted to valid format:

- Lowercase letters only
- Hyphens separate words
- Special characters removed
- Maximum 50 characters

```
Task: "Update API (v2) endpoint configuration!!!"
Keywords: ["update", "api", "v2", "endpoint"]
Name: "update-api-v2-endpoint"
```

### 3. Uniqueness

Duplicate names get numeric suffixes:

```bash
$ multiclaude worker create "Fix bug in login"
Creating worker 'fix-bug-login' in repo 'myproject'

$ multiclaude worker create "Fix bug in login" # Same task
Creating worker 'fix-bug-login-2' in repo 'myproject'

$ multiclaude worker create "Fix bug in login" # Again
Creating worker 'fix-bug-login-3' in repo 'myproject'
```

### 4. Fallback to Random Names

If the task description is invalid or too short, the system falls back to random names:

```bash
$ multiclaude worker create "!!!"
Creating worker 'happy-platypus' in repo 'myproject' # Fallback

$ multiclaude worker create "the a an is" # Only stop words
Creating worker 'clever-dolphin' in repo 'myproject' # Fallback
```

## Manual Override

The `--name` flag still works for manual naming:

```bash
$ multiclaude worker create "Fix bug" --name my-custom-name
Creating worker 'my-custom-name' in repo 'myproject'
```

## Real-World Examples

| Task Description | Generated Name |
|-----------------|----------------|
| "Fix memory leak in database connection pool" | `fix-memory-leak-database` |
| "Implement OAuth2 authentication flow" | `implement-oauth2-authentication-flow` |
| "Refactor user service to use new API" | `refactor-user-service-new` |
| "Add unit tests for payment module" | `add-unit-tests-payment` |
| "Update README with installation instructions" | `update-readme-installation-instructions` |
| "Debug timeout in webhook handler" | `debug-timeout-webhook-handler` |

## Benefits

1. **Clarity**: Immediately understand what each worker is doing
2. **Tracking**: Easier to monitor worker progress in logs and tmux
3. **Git branches**: Branch names like `work/fix-session-id-bug` are self-documenting
4. **PR identification**: PRs are easier to identify from their branch names
5. **Debugging**: When something goes wrong, you know which worker to investigate

## Technical Details

- Implementation: `internal/names/names.go`
- Tests: `internal/names/names_test.go`
- Specification: `WORKER_NAMING_SPEC.md`
- Integration: `internal/cli/cli.go:createWorker()`
106 changes: 106 additions & 0 deletions WORKER_NAMING_SPEC.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# Worker Naming Specification

## Overview

Workers should have descriptive, task-based names instead of random adjective-animal combinations. This makes it easier to identify what each worker is doing at a glance.

## Requirements

### 1. Task Summary Extraction

Extract a 3-4 word summary from the task description using heuristic processing:

- Remove common stop words (a, an, the, is, are, to, for, in, on, at, etc.)
- Identify and extract meaningful keywords (nouns, verbs, technical terms)
- Prioritize words at the beginning of the task description
- Limit to 3-4 words to keep names concise

### 2. Sanitization

Convert the extracted summary to a valid worker name:

- Convert to lowercase
- Replace spaces with hyphens
- Remove or replace special characters (keep only alphanumeric and hyphens)
- Collapse multiple consecutive hyphens into one
- Trim leading/trailing hyphens
- Maximum length: 50 characters (truncate if needed)

### 3. Uniqueness Handling

Ensure worker names are unique within a repository:

- Check if the generated name already exists
- If it exists, append numeric suffix: `-2`, `-3`, etc.
- Keep incrementing until a unique name is found

### 4. Fallback Strategy

If task extraction fails or produces invalid names:

- Fall back to the existing random name generator (`names.Generate()`)
- This ensures workers can always be created, even with unusual task descriptions

### 5. Manual Override

Preserve the existing `--name` flag to allow users to manually specify worker names.

## Examples

| Task Description | Generated Name |
|-----------------|----------------|
| "Fix the session ID bug in authentication" | `fix-session-id-bug` |
| "Add user profile editing feature" | `add-user-profile` |
| "Refactor the database connection logic" | `refactor-database-connection` |
| "Update README documentation" | `update-readme-documentation` |
| "Implement OAuth2 login flow" | `implement-oauth2-login` |
| "Fix bug" (too short) | `fix-bug` |
| "!!!" (invalid) | `happy-platypus` (fallback) |

## Implementation Details

### Stop Words List

Common words to filter out:
```
a, an, the, is, are, am, was, were, be, been, being, have, has, had,
do, does, did, will, would, should, could, may, might, must, can,
to, for, of, in, on, at, by, with, from, as, into, through,
this, that, these, those, it, its, they, their, there, here,
and, or, but, if, because, when, where, how, what, which, who, why
```

### Name Validation

A valid worker name must:
- Be between 3 and 50 characters long
- Contain at least one alphabetic character
- Not start or end with a hyphen
- Contain only lowercase letters, numbers, and hyphens

### Edge Cases

- Empty task description → fallback to random name
- Task with only stop words → fallback to random name
- Task producing name less than 3 characters → fallback to random name
- Very long task → extract key terms and truncate
- Special characters in task → sanitize and remove
- Duplicate name → append numeric suffix

## Testing Requirements

Comprehensive tests must cover:

1. **Basic extraction**: Verify correct keyword extraction from various task descriptions
2. **Sanitization**: Test lowercase conversion, special character handling, hyphen collapsing
3. **Uniqueness**: Test numeric suffix appending for duplicate names
4. **Fallback**: Verify fallback to random names for invalid inputs
5. **Edge cases**: Empty strings, very long strings, special characters only
6. **Integration**: Test within the full worker creation flow

## Migration

Existing code should continue to work:
- The `names.Generate()` function remains available for backward compatibility
- New function `names.FromTask(task string)` implements the task-based naming
- CLI code updated to use `FromTask()` by default, with `Generate()` as fallback
Loading