shipmate 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,875 @@
1
+ Metadata-Version: 2.4
2
+ Name: shipmate
3
+ Version: 0.1.0
4
+ Summary: Autonomous AI dev agents as Docker containers — add to any project as a submodule
5
+ Author-email: Paul R <paulr978@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/paulr978/shipmate
8
+ Project-URL: Repository, https://github.com/paulr978/shipmate
9
+ Project-URL: Issues, https://github.com/paulr978/shipmate/issues
10
+ Keywords: ai,agents,docker,crewai,autonomous,dev-agents,ci
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
17
+ Classifier: Topic :: Software Development :: Build Tools
18
+ Requires-Python: >=3.12
19
+ Description-Content-Type: text/markdown
20
+ Requires-Dist: crewai>=0.108.0
21
+ Requires-Dist: crewai-tools>=0.38.0
22
+ Requires-Dist: anthropic>=0.52.0
23
+ Requires-Dist: gitpython>=3.1.43
24
+ Requires-Dist: PyGithub>=2.5.0
25
+ Requires-Dist: click>=8.1.7
26
+ Requires-Dist: docker>=7.1.0
27
+ Requires-Dist: pyyaml>=6.0.2
28
+ Requires-Dist: python-dotenv>=1.0.1
29
+ Requires-Dist: rich>=13.7.0
30
+
31
+ # Shipmate — Autonomous AI Development System
32
+
33
+ A reusable, project-local framework that runs autonomous dev agents as Docker containers. Each agent clones the repo, creates a branch, implements a task, validates, pushes, and opens a PR. A persistent PR monitor watches for stale branches and re-spawns agents to rebase and self-heal.
34
+
35
+ Project-agnostic. Configure for any repo via `shipmate.yml` + `.env` — no code changes needed.
36
+
37
+ ---
38
+
39
+ ## Table of Contents
40
+
41
+ - [Quick Start](#quick-start)
42
+ - [Architecture Overview](#architecture-overview)
43
+ - [Directory Structure](#directory-structure)
44
+ - [CLI Reference](#cli-reference)
45
+ - [Agent Lifecycle](#agent-lifecycle)
46
+ - [PR Monitor](#pr-monitor)
47
+ - [Tools Reference](#tools-reference)
48
+ - [Configuration](#configuration)
49
+ - [PR Metadata Format](#pr-metadata-format)
50
+ - [Shared Services Policy](#shared-services-policy)
51
+ - [Conflict & Self-Healing Model](#conflict--self-healing-model)
52
+ - [Reusability Guide](#reusability-guide)
53
+ - [Security Model](#security-model)
54
+ - [Extending the System](#extending-the-system)
55
+ - [Troubleshooting](#troubleshooting)
56
+
57
+ ---
58
+
59
+ ## Quick Start
60
+
61
+ ### Prerequisites
62
+
63
+ - Docker installed and running
64
+ - Python 3.12+
65
+ - `GITHUB_TOKEN` with repo + PR permissions (stored in `.env`)
66
+ - `ANTHROPIC_API_KEY` for Claude API access (stored in `.env`)
67
+
68
+ ### The Easy Way — `launch.sh` / `launch.bat`
69
+
70
+ The launcher handles everything: creates the venv, loads secrets from `.env`, builds Docker images, checks the network, and launches agents.
71
+
72
+ **First time setup:**
73
+ 1. Copy `.env.example` to `.env` at the project root
74
+ 2. Add your `GITHUB_TOKEN` and `ANTHROPIC_API_KEY` to `.env`
75
+ 3. Make sure Docker is running and shared services are up (`make up`)
76
+
77
+ **Then just run:**
78
+
79
+ ```bash
80
+ # Linux/macOS/WSL
81
+ bash shipmate/launch.sh agent "Add pagination to /api/products/"
82
+
83
+ # Windows
84
+ shipmate\launch.bat agent "Add pagination to /api/products/"
85
+ ```
86
+
87
+ The launcher will automatically:
88
+ - Create `shipmate/.venv` if it doesn't exist
89
+ - Install all shipmate dependencies
90
+ - Load secrets from `.env`
91
+ - Validate tokens are present
92
+ - Create the Docker network if needed
93
+ - Build the agent image if needed
94
+ - Launch the agent container
95
+
96
+ **Other launcher commands:**
97
+
98
+ ```bash
99
+ # Launch agent in foreground (watch output live)
100
+ shipmate\launch.bat agent "Fix receipt parser bug" --no-detach
101
+
102
+ # Start the PR monitor
103
+ shipmate\launch.bat monitor
104
+
105
+ # Check running containers
106
+ shipmate\launch.bat status
107
+
108
+ # Stop the monitor
109
+ shipmate\launch.bat stop-monitor
110
+
111
+ # Rebuild Docker images
112
+ shipmate\launch.bat build
113
+
114
+ # Show help
115
+ shipmate\launch.bat help
116
+ ```
117
+
118
+ ### Manual Setup (Alternative)
119
+
120
+ If you prefer to manage things yourself:
121
+
122
+ ```bash
123
+ # 1. Set up shipmate's own venv
124
+ cd shipmate
125
+ setup_venv.bat # Windows
126
+ bash setup_venv.sh # Linux/macOS/WSL
127
+ .venv\Scripts\activate # activate it
128
+
129
+ # 2. Set secrets (or source from .env)
130
+ export GITHUB_TOKEN=ghp_...
131
+ export ANTHROPIC_API_KEY=sk-ant-...
132
+
133
+ # 3. Build and run
134
+ python -m shipmate build
135
+ python -m shipmate run-agent --task "Add pagination to the /api/products/ endpoint"
136
+
137
+ # 4. (Optional) PR monitor
138
+ python -m shipmate build-monitor
139
+ python -m shipmate monitor-start
140
+
141
+ # 5. Check running agents
142
+ python -m shipmate list-agents
143
+
144
+ # Stop the monitor
145
+ python -m shipmate monitor-stop
146
+ ```
147
+
148
+ ---
149
+
150
+ ## Architecture Overview
151
+
152
+ ```
153
+ ┌─────────────────────────────────────────────────────────┐
154
+ │ Your Machine (Host) │
155
+ │ │
156
+ │ python -m shipmate run-agent --task "..." │
157
+ │ │ │
158
+ │ ▼ │
159
+ │ ┌──────────────────┐ ┌──────────────────┐ │
160
+ │ │ Agent Container │ │ Agent Container │ ... │
161
+ │ │ (fresh clone) │ │ (fresh clone) │ │
162
+ │ │ shipmate/dev/task-A │ │ shipmate/dev/task-B │ │
163
+ │ └────────┬─────────┘ └────────┬─────────┘ │
164
+ │ │ │ │
165
+ │ └───────┬───────────────┘ │
166
+ │ ▼ │
167
+ │ ┌────────────────────────────────────────┐ │
168
+ │ │ project_backend_net (from shipmate.yml) │ │
169
+ │ │ ┌──────┐ ┌───────┐ ┌───────┐ │ │
170
+ │ │ │ db │ │ redis │ │ minio │ ... │ │
171
+ │ │ └──────┘ └───────┘ └───────┘ │ │
172
+ │ └────────────────────────────────────────┘ │
173
+ │ │
174
+ │ ┌──────────────────┐ │
175
+ │ │ PR Monitor │ (always-on, polls GitHub) │
176
+ │ │ re-spawns stale │ │
177
+ │ │ agent containers │ │
178
+ │ └──────────────────┘ │
179
+ └─────────────────────────────────────────────────────────┘
180
+ ```
181
+
182
+ ### Core Principles
183
+
184
+ 1. **One task = one container.** Full filesystem isolation. No agent can interfere with another.
185
+ 2. **Shared services are external.** Agents connect to the project's existing Docker network (db, redis, minio) but never own or mutate them destructively.
186
+ 3. **Each agent gets its own branch.** Branch naming: `shipmate/dev/<agent-id>-<task-slug>-<timestamp>`.
187
+ 4. **Each agent opens one PR.** PR body contains hidden metadata so the monitor can reconstruct the task later.
188
+ 5. **Self-healing via PR monitor.** When master advances, the monitor detects stale AI PRs and re-spawns the original agent in rebase mode.
189
+
190
+ ---
191
+
192
+ ## Directory Structure
193
+
194
+ ```
195
+ shipmate/
196
+ ├── __init__.py
197
+ ├── __main__.py # `python -m shipmate` entry point
198
+ ├── main.py # Host-side CLI (click) — tasks, work, dashboard, agents
199
+ ├── task_manager.py # Task queue CRUD (shipmate_tasks.yml backend)
200
+ ├── entrypoint.py # Container lifecycle runner
201
+ ├── Dockerfile # Agent container image
202
+ ├── requirements.txt # Python dependencies
203
+ ├── docker-compose.monitor.yml # Compose file for the PR monitor
204
+ ├── setup_venv.sh # Venv setup script (Linux/macOS/WSL)
205
+ ├── setup_venv.bat # Venv setup script (Windows)
206
+ ├── .venv/ # shipmate's own virtual environment (gitignored)
207
+
208
+ ├── config/
209
+ │ └── project.py # Loads config from env + shipmate.yml (framework code, don't edit)
210
+
211
+ ├── context/
212
+ │ └── project_context.py # Reads repo files → context string for the agent
213
+
214
+ ├── agents/
215
+ │ └── dev_agent.py # CrewAI Agent definition (role, tools, instructions)
216
+
217
+ ├── tasks/
218
+ │ └── dev_task.py # CrewAI Task builder (normal + rebase modes)
219
+
220
+ ├── crews/
221
+ │ └── dev_crew.py # Crew assembly: 1 agent, 1 task, sequential
222
+
223
+ ├── tools/
224
+ │ ├── git_tools.py # 12 git tools (branch, commit, rebase, push, diff...)
225
+ │ ├── github_tools.py # 6 GitHub tools (create PR, comment, list AI PRs...)
226
+ │ ├── file_tools.py # 5 file tools (read, write, list, search, patch)
227
+ │ └── shell_tools.py # 3 shell tools (constrained commands, ruff check/format)
228
+
229
+ ├── monitor/
230
+ │ ├── __init__.py
231
+ │ ├── Dockerfile # Monitor container image
232
+ │ └── pr_monitor.py # Polling service: detects stale PRs, re-spawns agents
233
+
234
+ └── docs/
235
+ └── README.md # This file
236
+ ```
237
+
238
+ ---
239
+
240
+ ## CLI Reference
241
+
242
+ All commands run on the host via `python -m shipmate <command>` or `launch.sh <command>`.
243
+
244
+ ### Task Management
245
+
246
+ #### `task add`
247
+
248
+ Add a task to the queue.
249
+
250
+ ```bash
251
+ launch.sh task add "Add pagination to /api/products/" --priority high
252
+ launch.sh task add "Fix receipt parser bug" --priority critical --id fix-parser
253
+ launch.sh task add "Refactor analytics module" # defaults to normal priority
254
+ ```
255
+
256
+ | Flag | Default | Description |
257
+ |------|---------|-------------|
258
+ | `--priority`, `-p` | `normal` | Priority: `critical`, `high`, `normal`, `low` |
259
+ | `--id` | auto-generated | Custom task ID |
260
+
261
+ #### `task list`
262
+
263
+ Show tasks in the queue.
264
+
265
+ ```bash
266
+ launch.sh task list # pending + running only
267
+ launch.sh task list --all # include done/failed/cancelled
268
+ launch.sh task list -s pending # filter by status
269
+ launch.sh task list -p high # filter by priority
270
+ ```
271
+
272
+ #### `task remove`
273
+
274
+ Remove a task.
275
+
276
+ ```bash
277
+ launch.sh task remove fix-parser
278
+ ```
279
+
280
+ #### `task update`
281
+
282
+ Change a task's priority, status, or description.
283
+
284
+ ```bash
285
+ launch.sh task update fix-parser --priority critical
286
+ launch.sh task update fix-parser --status cancelled
287
+ launch.sh task update fix-parser --description "New description"
288
+ ```
289
+
290
+ #### `work`
291
+
292
+ Pick up pending tasks (by priority) and launch agents.
293
+
294
+ ```bash
295
+ launch.sh work # launch the next highest-priority task
296
+ launch.sh work --all # launch agents for ALL pending tasks
297
+ launch.sh work -n 3 # launch the top 3 tasks
298
+ launch.sh work --no-detach # single task, foreground (watch output)
299
+ ```
300
+
301
+ Tasks are picked in priority order: `critical > high > normal > low`, then FIFO within the same priority.
302
+
303
+ #### `dashboard`
304
+
305
+ Live overview of tasks, running agents, and results.
306
+
307
+ ```bash
308
+ launch.sh dashboard # show once
309
+ launch.sh dashboard -w # auto-refresh every 5 seconds
310
+ ```
311
+
312
+ #### `logs`
313
+
314
+ Shortcut to view agent container logs.
315
+
316
+ ```bash
317
+ launch.sh logs dev-a1b2c3 # last 50 lines
318
+ launch.sh logs dev-a1b2c3 -f # follow (live)
319
+ launch.sh logs dev-a1b2c3 -n 200 # last 200 lines
320
+ ```
321
+
322
+ ### Direct Agent Control
323
+
324
+ #### `run-agent`
325
+
326
+ Launch an agent directly, bypassing the task queue.
327
+
328
+ ```bash
329
+ launch.sh agent "Add pagination to /api/products/" --no-detach
330
+ launch.sh agent "Fix bug" --id my-fix --rebase
331
+ ```
332
+
333
+ | Flag | Default | Description |
334
+ |------|---------|-------------|
335
+ | `--task`, `-t` | (required) | Task description |
336
+ | `--id` | auto | Agent identifier |
337
+ | `--branch`, `-b` | auto | Git branch name |
338
+ | `--rebase` | off | Rebase/conflict-resolution mode |
339
+ | `--detach/--no-detach` | detach | Background or foreground |
340
+
341
+ ### Infrastructure
342
+
343
+ #### `build`
344
+
345
+ Build the agent Docker image.
346
+
347
+ ```bash
348
+ launch.sh build [--no-cache]
349
+ ```
350
+
351
+ #### `monitor` / `stop-monitor`
352
+
353
+ Start/stop the PR monitor.
354
+
355
+ ```bash
356
+ launch.sh monitor [--interval 60]
357
+ launch.sh stop-monitor
358
+ ```
359
+
360
+ #### `status`
361
+
362
+ Show running containers.
363
+
364
+ ```bash
365
+ launch.sh status
366
+ ```
367
+
368
+ #### `list-agents`
369
+
370
+ List running agent containers.
371
+
372
+ ```bash
373
+ python -m shipmate list-agents
374
+ ```
375
+
376
+ ---
377
+
378
+ ## Agent Lifecycle
379
+
380
+ When you run `python -m shipmate run-agent --task "..."`, this is what happens:
381
+
382
+ ```
383
+ Host: main.py
384
+
385
+ ├── Generate agent ID, branch name
386
+ ├── Validate GITHUB_TOKEN and ANTHROPIC_API_KEY
387
+ ├── docker run shipmate-agent:latest with env vars
388
+
389
+ └── Container starts → entrypoint.py
390
+
391
+ ├── 1. Clone repo from GitHub (authenticated via GITHUB_TOKEN)
392
+ ├── 2. Configure git identity (shipmate-<agent-id>)
393
+ ├── 3. Create branch (or checkout existing for rebase)
394
+ ├── 4. Install backend requirements (pip install -r backend/requirements.txt)
395
+ ├── 5. Build project context (reads CLAUDE.md, decisions.md, etc.)
396
+ ├── 6. Run CrewAI dev crew
397
+ │ │
398
+ │ └── dev_agent.py executes the task:
399
+ │ ├── Read existing code (file_tools)
400
+ │ ├── Implement changes (file_tools)
401
+ │ ├── Run validation (shell_tools: ruff check, ruff format)
402
+ │ ├── Commit changes (git_tools)
403
+ │ ├── Push branch (git_tools)
404
+ │ └── Create PR with metadata (github_tools)
405
+
406
+ ├── 7. Log result
407
+ └── 8. Exit (container stops)
408
+ ```
409
+
410
+ ### Rebase Mode
411
+
412
+ When `AGENT_REBASE=true` (set by the monitor or `--rebase` flag):
413
+
414
+ 1. Checkout existing branch
415
+ 2. Fetch latest from origin
416
+ 3. Rebase onto `origin/master`
417
+ 4. Resolve conflicts (simple ones automatically, complex ones flagged)
418
+ 5. Re-run validation
419
+ 6. Force-push the updated branch
420
+ 7. Comment on the PR with a summary
421
+
422
+ ---
423
+
424
+ ## PR Monitor
425
+
426
+ The PR monitor (`monitor/pr_monitor.py`) is a simple polling service — not a CrewAI agent.
427
+
428
+ ### What It Does
429
+
430
+ ```
431
+ Every N seconds:
432
+
433
+ ├── Get latest master SHA from GitHub
434
+ ├── If master hasn't changed → skip
435
+ ├── If master advanced:
436
+ │ ├── List all open PRs on shipmate/* branches
437
+ │ ├── For each PR:
438
+ │ │ ├── Compare branch HEAD to master
439
+ │ │ ├── If stale (behind master):
440
+ │ │ │ ├── Comment on PR: "Re-spawning agent to rebase"
441
+ │ │ │ ├── docker run agent container in rebase mode
442
+ │ │ │ └── Track as active respawn
443
+ │ │ └── If up-to-date → skip
444
+ │ └── Clean up finished respawns
445
+ └── Sleep N seconds
446
+ ```
447
+
448
+ ### Running the Monitor
449
+
450
+ Option A — via CLI:
451
+ ```bash
452
+ python -m shipmate monitor-start --interval 60
453
+ ```
454
+
455
+ Option B — via docker-compose:
456
+ ```bash
457
+ cd shipmate
458
+ docker-compose -f docker-compose.monitor.yml up -d
459
+ ```
460
+
461
+ The monitor container mounts `/var/run/docker.sock` so it can spawn sibling agent containers.
462
+
463
+ ### Environment Variables
464
+
465
+ | Variable | Default | Description |
466
+ |----------|---------|-------------|
467
+ | `GITHUB_TOKEN` | (required) | GitHub PAT |
468
+ | `ANTHROPIC_API_KEY` | (required) | Passed to spawned agents |
469
+ | `GITHUB_REPO` | (required) | Repository to watch |
470
+ | `BASE_BRANCH` | `master` | Branch to monitor |
471
+ | `POLL_INTERVAL` | `60` | Seconds between polls |
472
+ | `DOCKER_NETWORK` | (required) | Network agents join |
473
+ | `AGENT_IMAGE` | `shipmate-agent:latest` | Image for spawned agents |
474
+
475
+ ---
476
+
477
+ ## Tools Reference
478
+
479
+ ### Git Tools (`tools/git_tools.py`)
480
+
481
+ All tools operate on the local repo clone at `/workspace`.
482
+
483
+ | Tool | Description |
484
+ |------|-------------|
485
+ | `create_branch` | Create and checkout a new branch |
486
+ | `checkout_branch` | Checkout an existing branch |
487
+ | `git_fetch` | Fetch from remote |
488
+ | `git_rebase` | Rebase current branch onto another |
489
+ | `git_rebase_continue` | Continue rebase after conflict resolution |
490
+ | `git_rebase_abort` | Abort a rebase |
491
+ | `git_commit` | Stage all changes and commit |
492
+ | `git_push` | Push branch to origin (supports force-with-lease) |
493
+ | `git_diff` | Show stat diff against a base branch |
494
+ | `git_changed_files` | List files changed vs a base branch |
495
+ | `git_status` | Show working tree status |
496
+ | `git_log` | Show recent log entries |
497
+
498
+ ### GitHub Tools (`tools/github_tools.py`)
499
+
500
+ | Tool | Description |
501
+ |------|-------------|
502
+ | `create_pull_request` | Create a PR with optional metadata block |
503
+ | `update_pull_request` | Update PR title/body |
504
+ | `comment_on_pr` | Add a comment to a PR |
505
+ | `list_ai_pull_requests` | List all open PRs on `shipmate/*` branches |
506
+ | `get_pr_metadata` | Extract shipmate metadata from a PR body |
507
+ | `get_pr_changed_files` | List files changed in a PR |
508
+
509
+ ### File Tools (`tools/file_tools.py`)
510
+
511
+ All paths are sandboxed to `/workspace`. Attempts to escape are rejected.
512
+
513
+ | Tool | Description |
514
+ |------|-------------|
515
+ | `read_file` | Read file contents (truncated at 50K chars) |
516
+ | `write_file` | Write/create a file |
517
+ | `list_directory` | Recursive directory listing (configurable depth) |
518
+ | `search_files` | Regex search across files (default: `*.py`) |
519
+ | `patch_file` | Find-and-replace a specific text block in a file |
520
+
521
+ ### Shell Tools (`tools/shell_tools.py`)
522
+
523
+ Shell access is **constrained by an allowlist**. The agent cannot run arbitrary commands.
524
+
525
+ | Tool | Description |
526
+ |------|-------------|
527
+ | `run_shell_command` | Run an allowlisted command |
528
+ | `run_ruff_check` | Run `ruff check` (with optional `--fix`) |
529
+ | `run_ruff_format` | Run `ruff format` |
530
+
531
+ **Built-in allowed prefixes:** `ruff `, `pytest `, `pip install`, `pip list`, `pip show`, `cat `, `head `, `tail `, `wc `, `diff `, `find `, `ls `
532
+
533
+ **Built-in blocked patterns:** `rm -rf`, `rm -r /`, `DROP`, `DELETE FROM`, `TRUNCATE`, `FLUSHALL`, `FLUSHDB`
534
+
535
+ **Project-specific additions** are configured in `shipmate.yml` under `shell.allowed_prefixes` and `shell.blocked_patterns`. These are merged with the built-in lists at runtime.
536
+
537
+ ---
538
+
539
+ ## Configuration
540
+
541
+ shipmate is **project-agnostic**. All project-specific configuration comes from two sources:
542
+
543
+ ### 1. `shipmate.yml` (project root)
544
+
545
+ This file lives at the root of your project (not inside `shipmate/`). It defines everything the agents need to know about your project: validation commands, context files, safety rules, shell allowlists, etc.
546
+
547
+ ```yaml
548
+ github:
549
+ repo: your-org/your-repo
550
+ base_branch: main
551
+ branch_prefix: shipmate/dev
552
+ pr_title_prefix: "[AI]"
553
+
554
+ docker:
555
+ network: your-project_backend_net
556
+
557
+ context_files:
558
+ - README.md
559
+ - docs/architecture.md
560
+
561
+ requirements_file: requirements.txt
562
+
563
+ validation_commands:
564
+ - command: "npm run lint"
565
+ description: "Run linter"
566
+ - command: "npm test"
567
+ description: "Run tests"
568
+
569
+ shared_service_rules:
570
+ - "Do NOT drop or truncate database tables."
571
+ - "Do NOT flush Redis."
572
+
573
+ tech_stack:
574
+ - "Node.js 20"
575
+ - "PostgreSQL 16"
576
+
577
+ shell:
578
+ allowed_prefixes:
579
+ - "npm "
580
+ - "npx "
581
+ blocked_patterns:
582
+ - "npm run db:reset"
583
+
584
+ llm:
585
+ model: claude-sonnet-4-6
586
+ max_tokens: 8192
587
+ ```
588
+
589
+ See the `shipmate.yml` at the root of this repo for a complete example.
590
+
591
+ ### 2. `.env` (secrets + overrides)
592
+
593
+ Secrets and simple overrides go in your `.env` file (gitignored).
594
+
595
+ **Required:**
596
+
597
+ | Variable | Purpose |
598
+ |----------|---------|
599
+ | `GITHUB_TOKEN` | Clone, push, PR operations |
600
+ | `ANTHROPIC_API_KEY` | LLM calls inside agent containers |
601
+
602
+ **Optional overrides** (take precedence over `shipmate.yml`):
603
+
604
+ | Variable | Overrides |
605
+ |----------|-----------|
606
+ | `SHIPMATE_GITHUB_REPO` | `github.repo` |
607
+ | `SHIPMATE_BASE_BRANCH` | `github.base_branch` |
608
+ | `SHIPMATE_DOCKER_NETWORK` | `docker.network` |
609
+ | `SHIPMATE_BRANCH_PREFIX` | `github.branch_prefix` |
610
+ | `SHIPMATE_LLM_MODEL` | `llm.model` |
611
+ | `SHIPMATE_LLM_MAX_TOKENS` | `llm.max_tokens` |
612
+ | `SHIPMATE_POLL_INTERVAL` | `monitor.poll_interval_seconds` |
613
+ | `SHIPMATE_AGENT_IMAGE_NAME` | `agent.image_name` |
614
+ | `SHIPMATE_AGENT_IMAGE_TAG` | `agent.image_tag` |
615
+
616
+ ### 3. `config/project.py` (framework code — do not edit)
617
+
618
+ This file loads values from env vars and `shipmate.yml`. It has no hardcoded project values. You should never need to modify it.
619
+
620
+ ### Priority order
621
+
622
+ ```
623
+ Environment variable > shipmate.yml > built-in default
624
+ ```
625
+
626
+ ---
627
+
628
+ ## PR Metadata Format
629
+
630
+ Every AI-created PR contains a hidden metadata block in its body:
631
+
632
+ ```html
633
+ <!-- SHIPMATE_META
634
+ {
635
+ "task": "Add pagination to /api/products/",
636
+ "agent_id": "dev-a1b2c3",
637
+ "branch": "shipmate/dev/dev-a1b2c3-add-pagination-20260328-143022",
638
+ "created_at": "2026-03-28T14:30:22.000000+00:00",
639
+ "rebase_count": 0
640
+ }
641
+ SHIPMATE_META -->
642
+ ```
643
+
644
+ This block is invisible when viewing the PR on GitHub but parseable by the monitor. It allows the monitor to:
645
+
646
+ - Reconstruct the original task description
647
+ - Re-spawn the exact same agent
648
+ - Track how many times a branch has been rebased
649
+
650
+ The `encode_pr_metadata()` and `decode_pr_metadata()` functions in `tools/github_tools.py` handle serialization.
651
+
652
+ ---
653
+
654
+ ## Shared Services Policy
655
+
656
+ Agents attach to the project's Docker network and can reach shared services. Strict rules apply:
657
+
658
+ ### Allowed
659
+
660
+ - Read from the running database (inspect schema, query data)
661
+ - Read from Redis (check keys, inspect state)
662
+ - Run targeted validation commands (`manage.py check`, `manage.py showmigrations`)
663
+ - Run linting and formatting
664
+ - Run isolated tests if safe (must use per-agent test DB: `test_agent_{agent_id}`)
665
+
666
+ ### Not Allowed
667
+
668
+ - `manage.py migrate` — never migrate the shared development database
669
+ - `manage.py flush` / `manage.py loaddata` / `manage.py dumpdata`
670
+ - `FLUSHALL` / `FLUSHDB` on Redis
671
+ - Delete or overwrite objects in MinIO
672
+ - Any destructive operation on shared infrastructure
673
+
674
+ These rules are enforced at two levels:
675
+ 1. **Shell allowlist** — blocked patterns in `shell_tools.py` prevent the commands from running
676
+ 2. **Agent instructions** — safety rules are injected into the agent's backstory so the LLM avoids attempting them
677
+
678
+ ---
679
+
680
+ ## Conflict & Self-Healing Model
681
+
682
+ ### Automatic Resolution (agent handles)
683
+
684
+ - Simple merge conflicts in different parts of a file
685
+ - Migration numbering conflicts (e.g., two agents both create `0005_...`)
686
+ - Import ordering conflicts
687
+ - Naming conflicts for newly added files/classes if detectable
688
+ - Minor upstream refactors that don't change semantics
689
+
690
+ ### Escalation (agent marks PR for human review)
691
+
692
+ - Semantic conflicts in the same function/method
693
+ - Contradictory schema changes
694
+ - Cases where the task intent is no longer valid after upstream changes
695
+ - Risky shared-service changes
696
+
697
+ When escalating, the agent:
698
+ 1. Updates the PR body with a warning section
699
+ 2. Comments on the PR explaining the conflict
700
+ 3. Leaves the branch in a clean state (rebase aborted if necessary)
701
+
702
+ ---
703
+
704
+ ## Reusability Guide
705
+
706
+ shipmate is designed to be dropped into any project. The `shipmate/` directory contains zero project-specific values.
707
+
708
+ ### Step 1: Copy the directory
709
+
710
+ ```bash
711
+ cp -r shipmate/ /path/to/other-project/shipmate/
712
+ ```
713
+
714
+ ### Step 2: Create `shipmate.yml` at your project root
715
+
716
+ ```yaml
717
+ github:
718
+ repo: your-org/your-repo
719
+ base_branch: main
720
+
721
+ docker:
722
+ network: your-project_backend_net
723
+
724
+ context_files:
725
+ - README.md
726
+
727
+ validation_commands:
728
+ - command: "npm run lint"
729
+ description: "Lint check"
730
+
731
+ tech_stack:
732
+ - "Node.js 20"
733
+ - "Express"
734
+ ```
735
+
736
+ ### Step 3: Add secrets to `.env`
737
+
738
+ ```
739
+ GITHUB_TOKEN=ghp_...
740
+ ANTHROPIC_API_KEY=sk-ant-...
741
+ ```
742
+
743
+ ### Step 4: Update the Dockerfile (if needed)
744
+
745
+ If your project uses a different language/runtime, update `shipmate/Dockerfile` to install the right system dependencies. The default image includes Python 3.12, git, and common build tools.
746
+
747
+ ### What you DON'T need to change
748
+
749
+ - `config/project.py` — reads from env + `shipmate.yml` automatically
750
+ - `tools/shell_tools.py` — shell allowlists/blocklists are configured in `shipmate.yml`
751
+ - CLI, entrypoint, agent/task/crew wiring, git/github tools, PR monitor, metadata format
752
+
753
+ ### Files that are project-specific (live outside `shipmate/`)
754
+
755
+ | File | Purpose |
756
+ |------|---------|
757
+ | `shipmate.yml` | Project config (repo, network, validation, rules) |
758
+ | `.env` | Secrets and optional overrides |
759
+ | `shipmate/Dockerfile` | System deps (only if your stack differs) |
760
+
761
+ ---
762
+
763
+ ## Security Model
764
+
765
+ ### Secrets
766
+
767
+ - `GITHUB_TOKEN` and `ANTHROPIC_API_KEY` are passed as container env vars
768
+ - Never baked into Docker images
769
+ - Never committed to the repo
770
+
771
+ ### GitHub Token Scopes
772
+
773
+ The token needs:
774
+ - `repo` — clone, push branches
775
+ - `pull_request` — create, update, comment on PRs
776
+
777
+ ### Container Isolation
778
+
779
+ - Each agent runs in its own container with its own filesystem
780
+ - Workspace is sandboxed — file tools reject paths outside `/workspace`
781
+ - Shell access is allowlisted — only pre-approved commands run
782
+ - Destructive patterns are explicitly blocked
783
+
784
+ ### Monitor Access
785
+
786
+ The monitor container mounts the Docker socket (`/var/run/docker.sock`) to spawn sibling containers. This is a privileged operation — the monitor should only run in trusted environments.
787
+
788
+ ---
789
+
790
+ ## Extending the System
791
+
792
+ ### Adding a New Tool
793
+
794
+ 1. Create a function in the appropriate `tools/*.py` module
795
+ 2. Decorate with `@tool("tool_name")`
796
+ 3. Add it to the agent's tool list in `agents/dev_agent.py`
797
+
798
+ Example:
799
+
800
+ ```python
801
+ # tools/shell_tools.py
802
+ @tool("run_mypy")
803
+ def run_mypy(path: str = ".") -> str:
804
+ """Run mypy type checker."""
805
+ return _run_command(f"mypy {path}")
806
+ ```
807
+
808
+ Then add `"mypy "` to `shell.allowed_prefixes` in `shipmate.yml` and add the tool import in `dev_agent.py`.
809
+
810
+ ### Adding a New Agent Type
811
+
812
+ 1. Create `agents/frontend_agent.py` (or similar)
813
+ 2. Create a corresponding task in `tasks/frontend_task.py`
814
+ 3. Optionally create a new crew in `crews/frontend_crew.py`
815
+ 4. Add a new CLI command in `main.py` (e.g., `run-frontend-agent`)
816
+
817
+ ### Adding New Validation Commands
818
+
819
+ Update `shipmate.yml` at your project root:
820
+
821
+ ```yaml
822
+ validation_commands:
823
+ - command: "ruff check --fix ."
824
+ description: "Lint check and auto-fix"
825
+ - command: "pytest backend/apps/myapp/tests/ -x"
826
+ description: "Run targeted tests"
827
+
828
+ shell:
829
+ allowed_prefixes:
830
+ - "pytest " # must be in the allowlist for validation to work
831
+ ```
832
+
833
+ ---
834
+
835
+ ## Troubleshooting
836
+
837
+ ### Agent container exits immediately
838
+
839
+ Check logs:
840
+ ```bash
841
+ docker logs shipmate-<agent-id>
842
+ ```
843
+
844
+ Common causes:
845
+ - Missing `GITHUB_TOKEN` or `ANTHROPIC_API_KEY`
846
+ - GitHub token lacks push/PR permissions
847
+ - Agent image not built (`python -m shipmate build`)
848
+
849
+ ### Agent can't reach shared services
850
+
851
+ Make sure the project's Docker network exists and services are running:
852
+ ```bash
853
+ docker network ls | grep backend_net
854
+ make up # from project root
855
+ ```
856
+
857
+ ### Monitor doesn't detect stale PRs
858
+
859
+ - Check monitor logs: `docker logs -f shipmate-monitor`
860
+ - Verify `GITHUB_REPO` and `BASE_BRANCH` are correct
861
+ - PRs must be on `shipmate/*` branches to be detected
862
+
863
+ ### Clone fails inside container
864
+
865
+ - Verify `GITHUB_TOKEN` has `repo` scope
866
+ - For private repos, ensure the token has access
867
+
868
+ ### Rebase fails with complex conflicts
869
+
870
+ The agent will attempt automatic resolution for simple conflicts. If it can't resolve, it will:
871
+ 1. Abort the rebase
872
+ 2. Comment on the PR explaining the conflict
873
+ 3. The PR remains open for human review
874
+
875
+ Check the PR comments for details.