lanekeeper 0.6.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.
- lanekeeper-0.6.0/LICENSE +21 -0
- lanekeeper-0.6.0/PKG-INFO +669 -0
- lanekeeper-0.6.0/README.md +654 -0
- lanekeeper-0.6.0/pyproject.toml +26 -0
- lanekeeper-0.6.0/setup.cfg +4 -0
- lanekeeper-0.6.0/src/lanekeeper/__init__.py +46 -0
- lanekeeper-0.6.0/src/lanekeeper/adapters/base.py +42 -0
- lanekeeper-0.6.0/src/lanekeeper/adapters/process_adapter.py +116 -0
- lanekeeper-0.6.0/src/lanekeeper/capabilities.py +216 -0
- lanekeeper-0.6.0/src/lanekeeper/cli.py +810 -0
- lanekeeper-0.6.0/src/lanekeeper/config.py +349 -0
- lanekeeper-0.6.0/src/lanekeeper/doctor.py +380 -0
- lanekeeper-0.6.0/src/lanekeeper/environment.py +139 -0
- lanekeeper-0.6.0/src/lanekeeper/frameworks.py +130 -0
- lanekeeper-0.6.0/src/lanekeeper/lanes.py +149 -0
- lanekeeper-0.6.0/src/lanekeeper/layout.py +206 -0
- lanekeeper-0.6.0/src/lanekeeper/lock.py +144 -0
- lanekeeper-0.6.0/src/lanekeeper/paths.py +161 -0
- lanekeeper-0.6.0/src/lanekeeper/ports.py +169 -0
- lanekeeper-0.6.0/src/lanekeeper/state.py +203 -0
- lanekeeper-0.6.0/src/lanekeeper/validator.py +280 -0
- lanekeeper-0.6.0/src/lanekeeper/worktree.py +259 -0
- lanekeeper-0.6.0/src/lanekeeper.egg-info/PKG-INFO +669 -0
- lanekeeper-0.6.0/src/lanekeeper.egg-info/SOURCES.txt +56 -0
- lanekeeper-0.6.0/src/lanekeeper.egg-info/dependency_links.txt +1 -0
- lanekeeper-0.6.0/src/lanekeeper.egg-info/entry_points.txt +2 -0
- lanekeeper-0.6.0/src/lanekeeper.egg-info/requires.txt +1 -0
- lanekeeper-0.6.0/src/lanekeeper.egg-info/top_level.txt +1 -0
- lanekeeper-0.6.0/tests/test_agent_id_allocation.py +54 -0
- lanekeeper-0.6.0/tests/test_capability_gates.py +306 -0
- lanekeeper-0.6.0/tests/test_changed_files.py +142 -0
- lanekeeper-0.6.0/tests/test_cleanup.py +64 -0
- lanekeeper-0.6.0/tests/test_cleanup_honesty.py +192 -0
- lanekeeper-0.6.0/tests/test_concurrency.py +176 -0
- lanekeeper-0.6.0/tests/test_config.py +60 -0
- lanekeeper-0.6.0/tests/test_doctor.py +59 -0
- lanekeeper-0.6.0/tests/test_e2e_3agents.py +138 -0
- lanekeeper-0.6.0/tests/test_e2e_concurrent.py +212 -0
- lanekeeper-0.6.0/tests/test_env_injection.py +133 -0
- lanekeeper-0.6.0/tests/test_env_service_urls.py +84 -0
- lanekeeper-0.6.0/tests/test_environment.py +53 -0
- lanekeeper-0.6.0/tests/test_failure_modes.py +159 -0
- lanekeeper-0.6.0/tests/test_frameworks.py +80 -0
- lanekeeper-0.6.0/tests/test_glob_matching.py +84 -0
- lanekeeper-0.6.0/tests/test_init_gitignore.py +101 -0
- lanekeeper-0.6.0/tests/test_lane_fail_closed.py +185 -0
- lanekeeper-0.6.0/tests/test_lanes.py +66 -0
- lanekeeper-0.6.0/tests/test_layout_detection.py +198 -0
- lanekeeper-0.6.0/tests/test_paths.py +141 -0
- lanekeeper-0.6.0/tests/test_port_audit.py +58 -0
- lanekeeper-0.6.0/tests/test_port_conflicts.py +165 -0
- lanekeeper-0.6.0/tests/test_ports.py +76 -0
- lanekeeper-0.6.0/tests/test_repair_convergence.py +119 -0
- lanekeeper-0.6.0/tests/test_state.py +84 -0
- lanekeeper-0.6.0/tests/test_state_lock.py +50 -0
- lanekeeper-0.6.0/tests/test_validator.py +88 -0
- lanekeeper-0.6.0/tests/test_version.py +48 -0
- lanekeeper-0.6.0/tests/test_worktree.py +54 -0
lanekeeper-0.6.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Lanekeeper Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,669 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: lanekeeper
|
|
3
|
+
Version: 0.6.0
|
|
4
|
+
Summary: Mechanical Safety & Coordination Tool for Running Parallel AI Coding Agents
|
|
5
|
+
Author: Lanekeeper Contributors
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/kish21/parallel-agents
|
|
8
|
+
Project-URL: Repository, https://github.com/kish21/parallel-agents
|
|
9
|
+
Project-URL: Changelog, https://github.com/kish21/parallel-agents/blob/main/CHANGELOG.md
|
|
10
|
+
Requires-Python: >=3.9
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Requires-Dist: pyyaml>=6.0
|
|
14
|
+
Dynamic: license-file
|
|
15
|
+
|
|
16
|
+
# Lanekeeper ⚡
|
|
17
|
+
|
|
18
|
+
[](https://github.com/kish21/parallel-agents/blob/main/CHANGELOG.md)
|
|
19
|
+
[](https://github.com/kish21/parallel-agents/blob/main/LICENSE)
|
|
20
|
+
|
|
21
|
+
**Run multiple AI coding agents safely in the same repository.**
|
|
22
|
+
|
|
23
|
+
Lanekeeper gives each coding agent its own Git worktree, branch, ports, environment, and code boundaries, so agents can work at the same time without accidentally interfering with each other.
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
Your Repository
|
|
27
|
+
│
|
|
28
|
+
┌────────────┼────────────┐
|
|
29
|
+
│ │ │
|
|
30
|
+
▼ ▼ ▼
|
|
31
|
+
Agent 1 Agent 2 Agent 3
|
|
32
|
+
Backend Frontend Tests
|
|
33
|
+
│ │ │
|
|
34
|
+
Worktree Worktree Worktree
|
|
35
|
+
Branch Branch Branch
|
|
36
|
+
Port 8001 Port 8002 Port 8003
|
|
37
|
+
│ │ │
|
|
38
|
+
└────────────┼────────────┘
|
|
39
|
+
▼
|
|
40
|
+
Validate
|
|
41
|
+
│
|
|
42
|
+
▼
|
|
43
|
+
PRs
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Why Lanekeeper?
|
|
49
|
+
|
|
50
|
+
AI coding agents are powerful, but running several agents in the same repository creates real operational problems:
|
|
51
|
+
|
|
52
|
+
* **File Overwrites**: One agent can modify files another agent is actively working on.
|
|
53
|
+
* **Port Clashes**: Two agents can accidentally claim the same development port.
|
|
54
|
+
* **Cross-Talk**: Frontends can connect to another agent's uncommitted backend code.
|
|
55
|
+
* **Migration Conflicts**: Shared database migrations can clash or create duplicate counters.
|
|
56
|
+
* **Out-of-Scope Changes**: An agent can modify central configs, auth, or infrastructure outside its assigned task.
|
|
57
|
+
* **Resource Leaks**: Failed agents can leave behind orphaned processes, blocked ports, or stale git state.
|
|
58
|
+
|
|
59
|
+
Lanekeeper adds a mechanical coordination and safety layer around your coding agents to prevent these problems.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## The Basic Idea
|
|
64
|
+
|
|
65
|
+
There are four fundamental concepts:
|
|
66
|
+
|
|
67
|
+
### 1. Agent
|
|
68
|
+
An agent is an isolated worker session assigned to a specific task.
|
|
69
|
+
```
|
|
70
|
+
agent-001 → "Implement user authentication"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 2. Worktree
|
|
74
|
+
Each agent gets its own physical Git working directory.
|
|
75
|
+
```
|
|
76
|
+
Agent 1 → .lanekeeper/worktrees/agent-001
|
|
77
|
+
Agent 2 → .lanekeeper/worktrees/agent-002
|
|
78
|
+
Agent 3 → .lanekeeper/worktrees/agent-003
|
|
79
|
+
```
|
|
80
|
+
Agents never edit the same physical files simultaneously.
|
|
81
|
+
|
|
82
|
+
### 3. Lane
|
|
83
|
+
A lane defines which part of the codebase an agent is permitted to touch.
|
|
84
|
+
```yaml
|
|
85
|
+
lane: backend
|
|
86
|
+
|
|
87
|
+
allow:
|
|
88
|
+
- src/api/**
|
|
89
|
+
- src/services/**
|
|
90
|
+
- tests/api/**
|
|
91
|
+
|
|
92
|
+
deny:
|
|
93
|
+
- src/frontend/**
|
|
94
|
+
- infrastructure/**
|
|
95
|
+
```
|
|
96
|
+
If the backend agent modifies `src/api/users.py`, that is allowed. If it touches `src/frontend/App.tsx`, validation reports a violation.
|
|
97
|
+
|
|
98
|
+
### 4. Resources
|
|
99
|
+
Each agent receives its own dedicated runtime resources:
|
|
100
|
+
```
|
|
101
|
+
Agent 1 → backend port 8001, frontend port 3001
|
|
102
|
+
Agent 2 → backend port 8002, frontend port 3002
|
|
103
|
+
Agent 3 → backend port 8003, frontend port 3003
|
|
104
|
+
```
|
|
105
|
+
This prevents agents from talking to the wrong development server.
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## 🚀 Quick Start
|
|
110
|
+
|
|
111
|
+
### 1. Install
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
pip install lanekeeper
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
This installs the `lanekeeper` command. Check which build you have with:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
lanekeeper --version
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
From a clone:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
pip install -e .
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### 2. Initialize the Repository
|
|
130
|
+
|
|
131
|
+
`init` reads your repository and generates lanes that match its actual structure, then
|
|
132
|
+
reports how much of the tree they cover:
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
$ lanekeeper init
|
|
136
|
+
🧭 Detected 3 lanes from the repository layout: backend, frontend, platform
|
|
137
|
+
Coverage: 100% of 412 tracked files fall inside a lane.
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
If coverage is low it says so, rather than letting you discover it when validation reports
|
|
141
|
+
legitimate work as out-of-lane. Use `--generic` to keep the starter lanes instead.
|
|
142
|
+
|
|
143
|
+
From your project root:
|
|
144
|
+
```bash
|
|
145
|
+
lanekeeper init
|
|
146
|
+
```
|
|
147
|
+
This creates the `.lanekeeper/` configuration and state directories.
|
|
148
|
+
|
|
149
|
+
Lanekeeper keeps its own files in one directory. To put them somewhere else,
|
|
150
|
+
set `LANEKEEPER_HOME` to a directory name relative to the repository root
|
|
151
|
+
before running any command:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
export LANEKEEPER_HOME=.agents
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Everything lanekeeper writes moves with it — config, state, logs, capability
|
|
158
|
+
cards, the default worktree location, and the rules `init` adds to
|
|
159
|
+
`.gitignore`. Absolute paths and paths containing `..` are rejected, so the
|
|
160
|
+
directory always stays inside the repository.
|
|
161
|
+
|
|
162
|
+
### 3. Create an Agent
|
|
163
|
+
```bash
|
|
164
|
+
lanekeeper spawn \
|
|
165
|
+
--name backend-1 \
|
|
166
|
+
--lane backend \
|
|
167
|
+
--task "Implement user authentication"
|
|
168
|
+
```
|
|
169
|
+
Lanekeeper provisions the isolated worktree, branch, `.env`, and dedicated ports automatically (and optionally starts an agent execution process when `--command` is supplied).
|
|
170
|
+
|
|
171
|
+
### 4. Create Another Agent
|
|
172
|
+
```bash
|
|
173
|
+
lanekeeper spawn \
|
|
174
|
+
--name frontend-1 \
|
|
175
|
+
--lane frontend \
|
|
176
|
+
--task "Build the login interface"
|
|
177
|
+
```
|
|
178
|
+
Now both agents can work simultaneously without collision.
|
|
179
|
+
|
|
180
|
+
### 5. Check Agents
|
|
181
|
+
```bash
|
|
182
|
+
$ lanekeeper status
|
|
183
|
+
|
|
184
|
+
📋 LANEKEEPER — MY-PROJECT
|
|
185
|
+
|
|
186
|
+
Agent ID Name Seat Lane Status Ports Task
|
|
187
|
+
----------------------------------------------------------------------------------------------------
|
|
188
|
+
agent-001 backend-1 SR1 backend RUNNING 8001/3001 Implement user authentication
|
|
189
|
+
agent-002 frontend-1 JR1 frontend RUNNING 8002/3002 Build the login interface
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### 6. Validate an Agent's Work
|
|
193
|
+
```bash
|
|
194
|
+
$ lanekeeper validate agent-001
|
|
195
|
+
|
|
196
|
+
🛡️ VALIDATION REPORT: backend-1 (agent-001)
|
|
197
|
+
Lane: backend
|
|
198
|
+
|
|
199
|
+
[Lane Compliance]
|
|
200
|
+
✓ All 4 changed files are within allowed lane paths.
|
|
201
|
+
|
|
202
|
+
==================================================
|
|
203
|
+
✅ VALIDATION PASSED: PR is safe to submit and merge.
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### 7. Inspect Changed Files
|
|
207
|
+
```bash
|
|
208
|
+
lanekeeper diff agent-001
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### 8. Stop an Agent
|
|
212
|
+
```bash
|
|
213
|
+
lanekeeper stop agent-001
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### 9. Clean Up Safely
|
|
217
|
+
```bash
|
|
218
|
+
lanekeeper cleanup agent-001
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## How It Works
|
|
224
|
+
|
|
225
|
+
```
|
|
226
|
+
WITHOUT LANEKEEPER: WITH LANEKEEPER:
|
|
227
|
+
|
|
228
|
+
Agent A ─────┐ Git Repository
|
|
229
|
+
│ │
|
|
230
|
+
Agent B ─────┼── Same working directory ┌─────────────┼─────────────┐
|
|
231
|
+
│ │ │ │
|
|
232
|
+
Agent C ─────┘ ▼ ▼ ▼
|
|
233
|
+
Agent A Agent B Agent C
|
|
234
|
+
↓ │ │ │
|
|
235
|
+
Conflicts & Leaks Worktree A Worktree B Worktree C
|
|
236
|
+
Branch A Branch B Branch C
|
|
237
|
+
Port 8001 Port 8002 Port 8003
|
|
238
|
+
│ │ │
|
|
239
|
+
▼ ▼ ▼
|
|
240
|
+
Backend Frontend Tests
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
The core difference is **physical isolation**. Agents are not merely prompted to avoid collisions; the tooling physically isolates their files, branches, and ports, and mechanically validates their boundaries.
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## Lanes
|
|
248
|
+
|
|
249
|
+
Lanes are how you define architectural ownership boundaries:
|
|
250
|
+
|
|
251
|
+
```yaml
|
|
252
|
+
lanes:
|
|
253
|
+
backend:
|
|
254
|
+
allow:
|
|
255
|
+
- src/api/**
|
|
256
|
+
- src/services/**
|
|
257
|
+
- tests/api/**
|
|
258
|
+
deny:
|
|
259
|
+
- src/frontend/**
|
|
260
|
+
|
|
261
|
+
frontend:
|
|
262
|
+
allow:
|
|
263
|
+
- src/frontend/**
|
|
264
|
+
- tests/frontend/**
|
|
265
|
+
deny:
|
|
266
|
+
- src/api/**
|
|
267
|
+
|
|
268
|
+
infrastructure:
|
|
269
|
+
allow:
|
|
270
|
+
- infrastructure/**
|
|
271
|
+
- deployment/**
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
```
|
|
275
|
+
backend agent frontend agent infrastructure agent
|
|
276
|
+
↓ ↓ ↓
|
|
277
|
+
backend files frontend files infrastructure files
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
The goal is not to isolate every single file—it is to make parallel execution predictable.
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
### Lane enforcement fails closed
|
|
285
|
+
|
|
286
|
+
Lane policy is only meaningful if it cannot be switched off by accident, so every lane
|
|
287
|
+
lookup is strict:
|
|
288
|
+
|
|
289
|
+
* `spawn --lane <name>` **rejects** a lane that is not declared in `config.yaml`, listing
|
|
290
|
+
the valid lanes. Nothing is provisioned — no branch, no worktree, no port reservation.
|
|
291
|
+
* `validate` and `diff` **refuse** an agent whose lane is no longer declared (for example,
|
|
292
|
+
the lane was renamed or removed after the agent was spawned). They report a failure
|
|
293
|
+
rather than checking the agent against an empty policy.
|
|
294
|
+
|
|
295
|
+
There is deliberately no permissive fallback. An unrecognised lane is a configuration
|
|
296
|
+
error, never a lane that happens to allow every path.
|
|
297
|
+
|
|
298
|
+
> **Commit `.lanekeeper/config.yaml`.** It is the policy every agent is validated
|
|
299
|
+
> against — the team's shared contract. `lanekeeper init` adds ignore rules that keep
|
|
300
|
+
> runtime state and worktrees out of git while leaving the config tracked. Without those
|
|
301
|
+
> rules an agent running `git add -A` would sweep every other agent's worktree into its own
|
|
302
|
+
> commit.
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
## Capability Gates
|
|
306
|
+
|
|
307
|
+
A lane answers **where** a seat may work. A capability card answers **what kind of work it
|
|
308
|
+
is competent to do there**.
|
|
309
|
+
|
|
310
|
+
Each seat has a card declaring its capabilities in three states:
|
|
311
|
+
|
|
312
|
+
| State | Meaning | Effect |
|
|
313
|
+
|---|---|---|
|
|
314
|
+
| `native` | The harness does this reliably. | Proceeds. |
|
|
315
|
+
| `author-required` | It can, but only by running a procedure written for it. | Proceeds **only** if a quality command declaring `satisfies: <capability>` passed. |
|
|
316
|
+
| `unavailable` | It cannot do this safely. | **Hard stop.** Non-zero exit; must escalate. |
|
|
317
|
+
|
|
318
|
+
`config.yaml` maps paths to the capability they require:
|
|
319
|
+
|
|
320
|
+
```yaml
|
|
321
|
+
capability_gates:
|
|
322
|
+
security_review:
|
|
323
|
+
paths: ["**/auth/**", "**/payments/**", "**/tenant/**", "secrets/**"]
|
|
324
|
+
database_migrations:
|
|
325
|
+
paths: ["database/migrations/**", "migrations/**"]
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
So a junior seat rated `security_review: unavailable` cannot get a green validation on an
|
|
329
|
+
auth file — **even when that file is inside its lane**:
|
|
330
|
+
|
|
331
|
+
```
|
|
332
|
+
[Lane Compliance]
|
|
333
|
+
✓ All 1 changed files are within allowed lane paths.
|
|
334
|
+
|
|
335
|
+
[Capability Gates] seat JR1 — evaluated: database_migrations, security_review
|
|
336
|
+
✗ src/backend/auth/login.py
|
|
337
|
+
requires 'security_review' — seat is 'unavailable'
|
|
338
|
+
seat 'JR1' cannot perform 'security_review'. This change must be escalated
|
|
339
|
+
to a seat rated native for it.
|
|
340
|
+
|
|
341
|
+
❌ VALIDATION FAILED: Must resolve errors before merging.
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
This is the mechanical form of the rule in `01-working-agreement.md`: stop when the change
|
|
345
|
+
touches money, auth, tenant isolation, or a migration.
|
|
346
|
+
|
|
347
|
+
### It fails closed, in four ways
|
|
348
|
+
|
|
349
|
+
An unrecognised seat, a seat with no card, a capability the card does not rate, and a
|
|
350
|
+
green-but-untagged quality command are **all denials**. Absence is never permission.
|
|
351
|
+
|
|
352
|
+
### Generating the gate declaration
|
|
353
|
+
|
|
354
|
+
`lanekeeper declare <agent>` produces the PR template's mandatory Gate Declaration
|
|
355
|
+
from recorded state — the seat, its ratings, the gates triggered, and each quality command
|
|
356
|
+
with its real exit code — rather than asking an author to type it from memory.
|
|
357
|
+
|
|
358
|
+
> **What this does not do.** It does not verify that a `native` rating is *honest*. A
|
|
359
|
+
> rating is a claim by the seat's owner; the tool holds the claim in one place, refuses
|
|
360
|
+
> work the claim says the seat cannot do, and makes the declaration an artefact.
|
|
361
|
+
> Rating honesty stays a human review question.
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
## Ports
|
|
365
|
+
|
|
366
|
+
Parallel development servers need independent ports. Instead of hardcoding `8000`:
|
|
367
|
+
|
|
368
|
+
```
|
|
369
|
+
Agent 1 → Port 8001 / 3001
|
|
370
|
+
Agent 2 → Port 8002 / 3002
|
|
371
|
+
Agent 3 → Port 8003 / 3003
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
Allocations are deterministic, checked against the host OS socket state, injected into `.env`, and released upon cleanup.
|
|
375
|
+
|
|
376
|
+
### Service URLs
|
|
377
|
+
|
|
378
|
+
A port number on its own does not connect anything. Browser build tools expose only their
|
|
379
|
+
own prefixed variables to client code — Vite reads `VITE_*`, Next.js reads
|
|
380
|
+
`NEXT_PUBLIC_*` — so a frontend handed `API_PORT=8002` cannot see it, and falls back to
|
|
381
|
+
whatever server is compiled into its source. That is usually another agent's backend.
|
|
382
|
+
|
|
383
|
+
`lanekeeper init` therefore reads the dependencies your repository declares and writes
|
|
384
|
+
the matching URL variables into `.lanekeeper/config.yaml`:
|
|
385
|
+
|
|
386
|
+
```yaml
|
|
387
|
+
environment:
|
|
388
|
+
host: 127.0.0.1
|
|
389
|
+
url_templates:
|
|
390
|
+
API_URL: http://${HOST}:${BACKEND_PORT}
|
|
391
|
+
VITE_API_URL: http://${HOST}:${BACKEND_PORT}
|
|
392
|
+
FRONTEND_URL: http://${HOST}:${FRONTEND_PORT}
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
Each agent's `.env` then resolves them against its own ports:
|
|
396
|
+
|
|
397
|
+
```bash
|
|
398
|
+
# .lanekeeper/worktrees/agent-002/.env
|
|
399
|
+
BACKEND_PORT='8002'
|
|
400
|
+
VITE_API_URL='http://127.0.0.1:8002' # agent-002's own backend, never agent-001's
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
Add, remove, or rename templates to suit your stack; a template naming a port category
|
|
404
|
+
your project does not define is dropped rather than written half-expanded.
|
|
405
|
+
|
|
406
|
+
Lanekeeper does **not** install dependencies. A fresh worktree has no `node_modules` or
|
|
407
|
+
virtualenv, so run your usual install command in it before starting a dev server.
|
|
408
|
+
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
## Agent Lifecycle
|
|
412
|
+
|
|
413
|
+
Agents follow an explicit state machine:
|
|
414
|
+
|
|
415
|
+
```
|
|
416
|
+
CREATED ──► STARTING ──► RUNNING ──┬──► COMPLETED ──► REVIEW
|
|
417
|
+
│ │
|
|
418
|
+
│ └──► FAILED ──► REPAIR ──► RUNNING
|
|
419
|
+
▼
|
|
420
|
+
STOPPED
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
Useful commands:
|
|
424
|
+
```bash
|
|
425
|
+
lanekeeper status
|
|
426
|
+
lanekeeper logs backend-1
|
|
427
|
+
lanekeeper stop backend-1
|
|
428
|
+
lanekeeper restart backend-1
|
|
429
|
+
lanekeeper repair backend-1
|
|
430
|
+
lanekeeper cleanup backend-1
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
---
|
|
434
|
+
|
|
435
|
+
## Mechanical Validation
|
|
436
|
+
|
|
437
|
+
Never rely on an AI agent's word that its work is complete. Lanekeeper independently validates:
|
|
438
|
+
|
|
439
|
+
```bash
|
|
440
|
+
$ lanekeeper validate backend-1
|
|
441
|
+
|
|
442
|
+
Validation: backend-1
|
|
443
|
+
|
|
444
|
+
Git
|
|
445
|
+
✓ Correct branch
|
|
446
|
+
✓ Correct worktree
|
|
447
|
+
|
|
448
|
+
Policy
|
|
449
|
+
✓ All changed files allowed in lane 'backend'
|
|
450
|
+
|
|
451
|
+
Quality
|
|
452
|
+
✓ Tests passed
|
|
453
|
+
✓ Lint passed
|
|
454
|
+
✓ Typecheck passed
|
|
455
|
+
|
|
456
|
+
Result: PASS
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
If an agent touches a forbidden file:
|
|
460
|
+
```
|
|
461
|
+
Validation: backend-1
|
|
462
|
+
|
|
463
|
+
Policy
|
|
464
|
+
✗ Forbidden file modified: src/frontend/App.tsx (Reason: denied)
|
|
465
|
+
|
|
466
|
+
Result: FAIL (Exit code 2)
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
---
|
|
470
|
+
|
|
471
|
+
## Recovery & Diagnostics
|
|
472
|
+
|
|
473
|
+
If an agent process crashes or an orphaned port is left behind:
|
|
474
|
+
|
|
475
|
+
```bash
|
|
476
|
+
$ lanekeeper doctor
|
|
477
|
+
|
|
478
|
+
🩺 LANEKEEPER DOCTOR
|
|
479
|
+
|
|
480
|
+
✓ Git repository: Valid Git repository detected.
|
|
481
|
+
✓ Configuration: Valid config (Project: demo, Max agents: 4).
|
|
482
|
+
✓ Worktrees: All 1 agent worktrees are intact.
|
|
483
|
+
✗ Port allocations: 2 port allocation issue(s) detected.
|
|
484
|
+
↳ Port 3001 still reserved by stopped agent 'agent-001'.
|
|
485
|
+
↳ Port 8001 still reserved by stopped agent 'agent-001'.
|
|
486
|
+
✓ Agent processes: All active agent process states are consistent.
|
|
487
|
+
|
|
488
|
+
⚠️ 1 problem(s) detected. Run 'lanekeeper repair' to fix.
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
`doctor` reports three classes of problem:
|
|
492
|
+
|
|
493
|
+
| Class | Meaning |
|
|
494
|
+
|---|---|
|
|
495
|
+
| **Orphaned** | A port is still reserved by an agent that has stopped, failed, completed, or no longer exists. If a process is *still listening* on it, it is reported as a leaked server. |
|
|
496
|
+
| **Conflict** | The port ledger and an agent's own recorded ports disagree — the dangerous case, because the ledger could hand the same port to a second agent. |
|
|
497
|
+
| **Stale process** | An agent is marked `RUNNING` but its PID is dead. |
|
|
498
|
+
|
|
499
|
+
Run repair to automatically clean up orphaned resources:
|
|
500
|
+
```bash
|
|
501
|
+
lanekeeper repair
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
---
|
|
505
|
+
|
|
506
|
+
## Database Isolation
|
|
507
|
+
|
|
508
|
+
Projects that interact with databases can configure an isolation strategy:
|
|
509
|
+
|
|
510
|
+
```yaml
|
|
511
|
+
database:
|
|
512
|
+
strategy: per-agent
|
|
513
|
+
name_template: "app_${AGENT_ID}"
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
Resulting databases:
|
|
517
|
+
```
|
|
518
|
+
agent-001 → app_agent_001
|
|
519
|
+
agent-002 → app_agent_002
|
|
520
|
+
agent-003 → app_agent_003
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
---
|
|
524
|
+
|
|
525
|
+
## Agent Providers & Adapters
|
|
526
|
+
|
|
527
|
+
Lanekeeper is provider-independent. It uses a pluggable `AgentAdapter` abstraction:
|
|
528
|
+
|
|
529
|
+
```
|
|
530
|
+
Lanekeeper
|
|
531
|
+
│
|
|
532
|
+
Agent Adapter
|
|
533
|
+
│
|
|
534
|
+
┌────────────┼────────────┐
|
|
535
|
+
▼ ▼ ▼
|
|
536
|
+
CLI harness IDE session Custom adapter
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
The orchestration layer handles isolation, ports, and validation; the adapter handles
|
|
540
|
+
execution. No vendor is named anywhere in the tooling or the configuration schema: which
|
|
541
|
+
harness fills a seat is recorded in that seat's capability card (`vendor_harness`), so
|
|
542
|
+
swapping vendors edits one field and changes nothing else.
|
|
543
|
+
|
|
544
|
+
---
|
|
545
|
+
|
|
546
|
+
## 🛠️ CLI Reference
|
|
547
|
+
|
|
548
|
+
| Command | Purpose |
|
|
549
|
+
| :--- | :--- |
|
|
550
|
+
| **`lanekeeper init`** | Initializes repository and creates configuration. |
|
|
551
|
+
| **`lanekeeper doctor`** | Diagnoses repository, worktree, and port health. |
|
|
552
|
+
| **`lanekeeper spawn`** | Provisions an isolated worktree, branch, `.env`, and allocated ports. |
|
|
553
|
+
| **`lanekeeper status`** | Shows active agents, lanes, and allocated ports (`--json` supported). |
|
|
554
|
+
| **`lanekeeper validate`** | Mechanically validates lane compliance and runs test suites. |
|
|
555
|
+
| **`lanekeeper diff`** | Displays changed files classified as `[LANE OK]` vs. `[OUT-OF-LANE]`. |
|
|
556
|
+
| **`lanekeeper inspect`** | Shows detailed agent metadata and environment variables. |
|
|
557
|
+
| **`lanekeeper logs`** | Tails structured execution logs for an agent session. |
|
|
558
|
+
| **`lanekeeper stop`** | Stops an active agent process. |
|
|
559
|
+
| **`lanekeeper restart`** | Restarts an agent in its worktree. |
|
|
560
|
+
| **`lanekeeper repair`** | Repairs stale states and releases orphaned ports. |
|
|
561
|
+
| **`lanekeeper declare`** | Generates the PR gate declaration from recorded state. |
|
|
562
|
+
| **`lanekeeper cleanup`** | Safely removes worktrees and releases port allocations. |
|
|
563
|
+
|
|
564
|
+
---
|
|
565
|
+
|
|
566
|
+
## 💡 Design Philosophy
|
|
567
|
+
|
|
568
|
+
1. **Isolation Over Instructions**: Do not merely instruct agents to avoid collisions; provide physically isolated environments.
|
|
569
|
+
2. **Mechanical Validation Over Trust**: Never assume an agent followed the rules; mechanically verify diffs against lane policies.
|
|
570
|
+
3. **Simple Over Clever**: Coordinate coding agents with clarity; do not build an autonomous swarm or bloated web UI.
|
|
571
|
+
4. **Developer in Control**: Agents propose changes; humans review and merge them.
|
|
572
|
+
5. **Safe Cleanup**: Never sacrifice uncommitted developer work for aggressive cleanup.
|
|
573
|
+
|
|
574
|
+
---
|
|
575
|
+
|
|
576
|
+
## 🚫 What Lanekeeper Is Not
|
|
577
|
+
|
|
578
|
+
* ❌ Not an autonomous AI software company.
|
|
579
|
+
* ❌ Not an AI project manager.
|
|
580
|
+
* ❌ Not a replacement for Git or CI/CD.
|
|
581
|
+
* ❌ Not tied to any single AI vendor or model.
|
|
582
|
+
|
|
583
|
+
It is a **lightweight coordination and safety layer** for parallel AI coding agents.
|
|
584
|
+
|
|
585
|
+
---
|
|
586
|
+
|
|
587
|
+
## 🧪 Automated Testing & Reliability Benchmarks
|
|
588
|
+
|
|
589
|
+
Lanekeeper includes a **tracked 36-test unit, integration, concurrency stress, and failure recovery suite** and an automated reproducibility benchmark runner.
|
|
590
|
+
|
|
591
|
+
### 1. Run the Full Test Suite
|
|
592
|
+
```bash
|
|
593
|
+
python -m unittest discover tests
|
|
594
|
+
```
|
|
595
|
+
```
|
|
596
|
+
....................................
|
|
597
|
+
----------------------------------------------------------------------
|
|
598
|
+
Ran 139 tests in 16.3s
|
|
599
|
+
|
|
600
|
+
OK
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
#### What Is Tested & Proven:
|
|
604
|
+
* **StateLock Integration (`test_state_lock.py`)**: Validates StateLock mutual exclusion under heavy contention (20 simultaneous threads) with zero state lost or overwritten.
|
|
605
|
+
* **Atomic Concurrency & Stress (`test_concurrency.py`, `test_e2e_concurrent.py`)**: Spawns up to 10 agents in parallel threads simultaneously across separate CPU workers to mechanically prove that re-entrant file locking (`StateLock`) assigns unique sequential IDs, dedicated Git worktrees, unique branches, and non-colliding ports atomically with zero lost state.
|
|
606
|
+
* **Failure Modes & Transactional Rollbacks (`test_failure_modes.py`)**: Validates clean port rollback on port exhaustion, clean rollback when worktree creation fails (simulated disk/git failure), dead process diagnosis and recovery in `repair`, and protection of uncommitted developer code during cleanup.
|
|
607
|
+
* **3-Agent Multi-Lane Workflow (`test_e2e_3agents.py`)**: Concurrently spawns Agent A (Backend), Agent B (Frontend), and Agent C (Service), verifies distinct physical worktrees, dedicated branches, and unique ports (`8001/3001`, `8002/3002`, `8003/3003`), validates in-lane edits (pass), proves deliberate cross-lane violations fail with exit code `2`, and cleanly reclaims all resources.
|
|
608
|
+
* **Port Audit & Conflict Detection (`test_ports.py`, `test_port_audit.py`, `test_port_conflicts.py`)**: Validates real OS socket probing (a bound socket is detected and skipped by the allocator), ledger/agent-state drift detection, leaked-server reporting on orphaned ports, and that a failed re-allocation never releases the agent's existing reservations.
|
|
609
|
+
* **Fail-Closed Lane Enforcement (`test_lane_fail_closed.py`)**: Proves that an undeclared lane — a typo at spawn, or a lane deleted from the config afterwards — is rejected outright rather than validating as safe, and that a rejected spawn leaves behind no branch, worktree, or port reservation.
|
|
610
|
+
* **Environment Injection (`test_env_injection.py`)**: Round-trips hostile task strings (quotes, newlines, `$VAR`, backticks, `$(...)`) through a real `/bin/sh` to prove generated `.env` and `.lane` files cannot be escaped or executed.
|
|
611
|
+
* **Capability Gates (`test_capability_gates.py`)**: Proves an `unavailable` capability hard-stops an in-lane file, `native` passes the same file, `author-required` passes only when its verified script exits 0, `forbidden_paths` overrides the lane allow, and four separate fail-closed paths (unknown seat, missing card, unrated capability, untagged command).
|
|
612
|
+
* **Glob Matching (`test_glob_matching.py`)**: Pins segment-aware `**` semantics, including that `**/auth/**` must not match `src/authentic/`, and that a recursive deny pattern actually denies.
|
|
613
|
+
* **Repository Hygiene (`test_init_gitignore.py`)**: Proves `git add -A` cannot stage agent worktrees or runtime state, while the shared lane policy stays tracked.
|
|
614
|
+
* **Diagnostics & Recovery (`test_doctor.py`, `test_cleanup.py`)**: Validates automatic detection of missing worktrees, orphaned port reclamation, and uncommitted developer code protection.
|
|
615
|
+
|
|
616
|
+
---
|
|
617
|
+
|
|
618
|
+
### 2. Run Reproducibility Benchmarks
|
|
619
|
+
```bash
|
|
620
|
+
python benchmarks/benchmark_parallel.py --cycles 5
|
|
621
|
+
```
|
|
622
|
+
```
|
|
623
|
+
======================================================================
|
|
624
|
+
📈 LANEKEEPER: BENCHMARK RESULTS & SYSTEM RELIABILITY METRICS
|
|
625
|
+
======================================================================
|
|
626
|
+
• Total Cycles Executed: 5 / 5
|
|
627
|
+
• Total Agents Spawned: 15
|
|
628
|
+
• Total Execution Time: 7.02s
|
|
629
|
+
----------------------------------------------------------------------
|
|
630
|
+
• Worktree Collision Rate: 0.0% (0 collisions)
|
|
631
|
+
• Port Race Condition Rate: 0.0% (0 collisions)
|
|
632
|
+
• Lane Violation Accuracy: 100.0% (5/5 caught)
|
|
633
|
+
• Worktree Leaks Post-Cleanup: 0
|
|
634
|
+
======================================================================
|
|
635
|
+
✅ PASSED: 5 cycles / 15 agents with 0 observed worktree or port collisions, 5/5 injected lane violations detected, and no leaked resources.
|
|
636
|
+
======================================================================
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
Every number above is measured at run time. The benchmark exits non-zero on any collision,
|
|
640
|
+
leak, or undetected violation, so CI fails rather than printing a clean summary over a bad
|
|
641
|
+
run.
|
|
642
|
+
|
|
643
|
+
---
|
|
644
|
+
|
|
645
|
+
## 📚 Deep-Dive Documentation & Guides
|
|
646
|
+
|
|
647
|
+
| Document | Description |
|
|
648
|
+
| :--- | :--- |
|
|
649
|
+
| **[🎬 End-to-End Walkthrough](https://github.com/kish21/parallel-agents/blob/main/EXAMPLES.md)** | Step-by-step lifecycle of Ticket #102 from assignment to merge. |
|
|
650
|
+
| **[01. Working Agreement](https://github.com/kish21/parallel-agents/blob/main/01-working-agreement.md)** | Definition-of-Done, path boundary contracts, and merge discipline. |
|
|
651
|
+
| **[02. Conflict Management](https://github.com/kish21/parallel-agents/blob/main/02-conflict-management.md)** | Worktree deep-dive, port tables, and Disaster Recovery Runbook. |
|
|
652
|
+
| **[03. Orchestration](https://github.com/kish21/parallel-agents/blob/main/03-orchestration.md)** | Capability cards, scaling 2→4→6 seats, and ROI metrics. |
|
|
653
|
+
| **[04. Agent Setup](https://github.com/kish21/parallel-agents/blob/main/04-agent-setup.md)** | Prompts for Senior/Junior agents and token cost hygiene. |
|
|
654
|
+
| **[05. GitHub Mechanics](https://github.com/kish21/parallel-agents/blob/main/05-github-mechanics.md)** | Board custom fields, disjoint milestones, and single-account routing. |
|
|
655
|
+
| **[06. Free-Tier Operations](https://github.com/kish21/parallel-agents/blob/main/06-free-tier-ops.md)** | CI minute optimization, public vs private repo trade-offs, and verified mirrors. |
|
|
656
|
+
|
|
657
|
+
---
|
|
658
|
+
|
|
659
|
+
## 🤝 Community & Contributing
|
|
660
|
+
|
|
661
|
+
Contributions are welcome! See our community guidelines:
|
|
662
|
+
* **[Contributing Guide](https://github.com/kish21/parallel-agents/blob/main/CONTRIBUTING.md)**
|
|
663
|
+
* **[Security Policy](https://github.com/kish21/parallel-agents/blob/main/SECURITY.md)**
|
|
664
|
+
* **[Code of Conduct](https://github.com/kish21/parallel-agents/blob/main/CODE_OF_CONDUCT.md)**
|
|
665
|
+
|
|
666
|
+
---
|
|
667
|
+
|
|
668
|
+
## License
|
|
669
|
+
[MIT](https://github.com/kish21/parallel-agents/blob/main/LICENSE)
|