Decomposed "Foundation Setup - Install Dependencies & Configure Tailwind" phase into 6 executable tasks: 1. Install Tailwind CSS, PostCSS & Autoprefixer 2. Map MUI theme to Tailwind design tokens 3. Setup CSS variables for dynamic theming 4. Install Radix UI primitives 5. Initialize shadcn/ui and setup component directory 6. Move MUI to devDependencies and verify setup Tasks follow logical dependency chain with final human verification checkpoint before proceeding with component migration. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
3.6 KiB
3.6 KiB
Git, Process, and Logging Modules
Three infrastructure modules supporting agent execution.
Git Module (src/git/)
Manages git worktrees for isolated agent workspaces.
Architecture
- Port:
WorktreeManagerinterface - Adapter:
SimpleGitWorktreeManagerusing simple-git library
WorktreeManager Methods
| Method | Purpose |
|---|---|
create(id, branch, baseBranch?) |
Create worktree with new branch (default base: 'main') |
remove(id) |
Clean up worktree directory |
list() |
All worktrees including main |
get(id) |
Specific worktree by ID |
diff(id) |
Changed files vs HEAD |
merge(id, targetBranch) |
Merge worktree branch into target |
Worktree Storage
Worktrees stored in .cw-worktrees/ subdirectory of the repo. Each agent gets a worktree at .cw-worktrees/agent/<alias>/.
Merge Flow
- Check out target branch
git merge <source> --no-edit- On success: emit
worktree:merged - On conflict:
git merge --abort, emitworktree:conflictwith conflicting file list - Restore original branch
Project Clones
cloneProject(url, destPath)— Simple git clone wrapperensureProjectClone(project, workspaceRoot)— Idempotent: checks if clone exists, clones if notgetProjectCloneDir(name, id)— Canonical path:repos/<sanitized-name>-<id>/
Events Emitted
worktree:created, worktree:removed, worktree:merged, worktree:conflict
Process Module (src/process/)
Spawns, tracks, and controls child processes.
Classes
ProcessRegistry — In-memory metadata store:
register(info),unregister(id),get(id),getAll(),getByPid(pid),updateStatus(id, status)
ProcessManager — Lifecycle management:
| Method | Purpose |
|---|---|
spawn(options) |
Spawn detached process (survives parent exit) |
stop(id) |
SIGTERM → wait 5s → SIGKILL |
stopAll() |
Stop all running processes in parallel |
restart(id) |
Stop + re-spawn with same options |
isRunning(id) |
Check with process.kill(pid, 0) |
Spawn Details
- Uses
execawithdetached: true,stdio: 'ignore' - Calls
subprocess.unref()so parent can exit - Exit handler updates registry and emits events
Events Emitted
process:spawned, process:stopped, process:crashed
Logger Module (src/logger/)
Structured logging via pino.
Usage
import { createModuleLogger } from './logger/index.js';
const log = createModuleLogger('my-module');
log.info({ key: 'value' }, 'message');
Configuration
| Env Var | Effect |
|---|---|
CW_LOG_LEVEL |
Override log level |
CW_LOG_PRETTY |
Set to '1' for human-readable output |
NODE_ENV=development |
Default to 'debug' level |
Output
- Default: JSON to stderr (fd 2)
- Pretty mode: pino-pretty to stdout with colors and timestamps
Logging Module (src/logging/)
File-based per-process output capture (separate from pino).
Classes
LogManager — Directory management:
- Base dir:
~/.cw/logs/ - Structure:
{processId}/stdout.log,{processId}/stderr.log cleanOldLogs(retainDays)— removes old directories by mtime
ProcessLogWriter — File I/O with timestamps:
open()— create directories and append-mode WriteStreamswriteStdout(data)/writeStderr(data)— prefix each line with[YYYY-MM-DD HH:mm:ss.SSS]- Handles backpressure (waits for drain event)
- Emits
log:entryevent via EventBus
Factory
import { createLogger } from './logging/index.js';
const writer = createLogger(processId, eventBus);
await writer.open();
await writer.writeStdout('output data');
await writer.close();