collab-runtime 0.2.9__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.
- collab_runtime-0.2.9/LICENSE +21 -0
- collab_runtime-0.2.9/PKG-INFO +218 -0
- collab_runtime-0.2.9/README.md +472 -0
- collab_runtime-0.2.9/README_pypi.md +193 -0
- collab_runtime-0.2.9/collab/__init__.py +77 -0
- collab_runtime-0.2.9/collab/__main__.py +11 -0
- collab_runtime-0.2.9/collab_runtime.egg-info/PKG-INFO +218 -0
- collab_runtime-0.2.9/collab_runtime.egg-info/SOURCES.txt +86 -0
- collab_runtime-0.2.9/collab_runtime.egg-info/dependency_links.txt +1 -0
- collab_runtime-0.2.9/collab_runtime.egg-info/entry_points.txt +3 -0
- collab_runtime-0.2.9/collab_runtime.egg-info/requires.txt +5 -0
- collab_runtime-0.2.9/collab_runtime.egg-info/top_level.txt +10 -0
- collab_runtime-0.2.9/pyproject.toml +135 -0
- collab_runtime-0.2.9/scripts/cleanup.py +395 -0
- collab_runtime-0.2.9/scripts/collab_git_hook.py +190 -0
- collab_runtime-0.2.9/scripts/format_code.py +594 -0
- collab_runtime-0.2.9/scripts/generate_tests.py +560 -0
- collab_runtime-0.2.9/scripts/validate_code.py +1397 -0
- collab_runtime-0.2.9/setup.cfg +4 -0
- collab_runtime-0.2.9/src/__init__.py +4 -0
- collab_runtime-0.2.9/src/dashboard/index.html +1131 -0
- collab_runtime-0.2.9/src/live_locks_watcher.py +1982 -0
- collab_runtime-0.2.9/src/lock_client.py +4268 -0
- collab_runtime-0.2.9/src/logging_config.py +259 -0
- collab_runtime-0.2.9/src/main.py +436 -0
- collab_runtime-0.2.9/tests/backend/__init__.py +0 -0
- collab_runtime-0.2.9/tests/backend/functional/__init__.py +0 -0
- collab_runtime-0.2.9/tests/backend/functional/test_package_imports.py +43 -0
- collab_runtime-0.2.9/tests/backend/integration/__init__.py +0 -0
- collab_runtime-0.2.9/tests/backend/integration/test_cli_contract_parity.py +220 -0
- collab_runtime-0.2.9/tests/backend/performance/__init__.py +0 -0
- collab_runtime-0.2.9/tests/backend/reliability/__init__.py +0 -0
- collab_runtime-0.2.9/tests/backend/security/__init__.py +0 -0
- collab_runtime-0.2.9/tests/backend/unit/live_locks_watcher/__init__.py +5 -0
- collab_runtime-0.2.9/tests/backend/unit/live_locks_watcher/_helpers.py +123 -0
- collab_runtime-0.2.9/tests/backend/unit/live_locks_watcher/conftest.py +18 -0
- collab_runtime-0.2.9/tests/backend/unit/live_locks_watcher/test_live_locks_watcher_dashboard.py +188 -0
- collab_runtime-0.2.9/tests/backend/unit/live_locks_watcher/test_live_locks_watcher_developer.py +56 -0
- collab_runtime-0.2.9/tests/backend/unit/live_locks_watcher/test_live_locks_watcher_graceful_shutdown.py +459 -0
- collab_runtime-0.2.9/tests/backend/unit/live_locks_watcher/test_live_locks_watcher_main.py +1925 -0
- collab_runtime-0.2.9/tests/backend/unit/live_locks_watcher/test_live_locks_watcher_module.py +187 -0
- collab_runtime-0.2.9/tests/backend/unit/live_locks_watcher/test_live_locks_watcher_multi_session.py +320 -0
- collab_runtime-0.2.9/tests/backend/unit/live_locks_watcher/test_live_locks_watcher_notify.py +67 -0
- collab_runtime-0.2.9/tests/backend/unit/live_locks_watcher/test_live_locks_watcher_parsing.py +155 -0
- collab_runtime-0.2.9/tests/backend/unit/live_locks_watcher/test_live_locks_watcher_process_helpers.py +684 -0
- collab_runtime-0.2.9/tests/backend/unit/live_locks_watcher/test_live_locks_watcher_processing.py +173 -0
- collab_runtime-0.2.9/tests/backend/unit/live_locks_watcher/test_live_locks_watcher_prompt_abort.py +71 -0
- collab_runtime-0.2.9/tests/backend/unit/live_locks_watcher/test_live_locks_watcher_reconcile.py +516 -0
- collab_runtime-0.2.9/tests/backend/unit/live_locks_watcher/test_live_locks_watcher_scan.py +296 -0
- collab_runtime-0.2.9/tests/backend/unit/lock_client/__init__.py +1 -0
- collab_runtime-0.2.9/tests/backend/unit/lock_client/_helpers.py +132 -0
- collab_runtime-0.2.9/tests/backend/unit/lock_client/test_lock_client_acquire.py +214 -0
- collab_runtime-0.2.9/tests/backend/unit/lock_client/test_lock_client_active.py +104 -0
- collab_runtime-0.2.9/tests/backend/unit/lock_client/test_lock_client_api.py +63 -0
- collab_runtime-0.2.9/tests/backend/unit/lock_client/test_lock_client_cli.py +682 -0
- collab_runtime-0.2.9/tests/backend/unit/lock_client/test_lock_client_daemon.py +3730 -0
- collab_runtime-0.2.9/tests/backend/unit/lock_client/test_lock_client_dashboard.py +438 -0
- collab_runtime-0.2.9/tests/backend/unit/lock_client/test_lock_client_discover.py +241 -0
- collab_runtime-0.2.9/tests/backend/unit/lock_client/test_lock_client_force_release.py +354 -0
- collab_runtime-0.2.9/tests/backend/unit/lock_client/test_lock_client_helper_branches.py +1890 -0
- collab_runtime-0.2.9/tests/backend/unit/lock_client/test_lock_client_history.py +301 -0
- collab_runtime-0.2.9/tests/backend/unit/lock_client/test_lock_client_isolation.py +316 -0
- collab_runtime-0.2.9/tests/backend/unit/lock_client/test_lock_client_pid.py +75 -0
- collab_runtime-0.2.9/tests/backend/unit/lock_client/test_lock_client_reconcile.py +464 -0
- collab_runtime-0.2.9/tests/backend/unit/lock_client/test_lock_client_release.py +77 -0
- collab_runtime-0.2.9/tests/backend/unit/lock_client/test_lock_client_shutdown.py +1110 -0
- collab_runtime-0.2.9/tests/backend/unit/lock_client/test_lock_client_utils.py +474 -0
- collab_runtime-0.2.9/tests/backend/unit/lock_client/test_lock_client_watch.py +866 -0
- collab_runtime-0.2.9/tests/backend/unit/scripts/__init__.py +1 -0
- collab_runtime-0.2.9/tests/backend/unit/scripts/_helpers.py +42 -0
- collab_runtime-0.2.9/tests/backend/unit/scripts/test_cleanup.py +285 -0
- collab_runtime-0.2.9/tests/backend/unit/scripts/test_collab_git_hook.py +280 -0
- collab_runtime-0.2.9/tests/backend/unit/scripts/test_collab_git_hook_ported.py +50 -0
- collab_runtime-0.2.9/tests/backend/unit/scripts/test_format_code.py +368 -0
- collab_runtime-0.2.9/tests/backend/unit/scripts/test_format_code_ported.py +177 -0
- collab_runtime-0.2.9/tests/backend/unit/scripts/test_generate_tests.py +305 -0
- collab_runtime-0.2.9/tests/backend/unit/scripts/test_hook_templates.py +357 -0
- collab_runtime-0.2.9/tests/backend/unit/scripts/test_setup_hook_overlay.py +95 -0
- collab_runtime-0.2.9/tests/backend/unit/scripts/test_validate_code.py +867 -0
- collab_runtime-0.2.9/tests/backend/unit/scripts/test_validate_code_ported.py +237 -0
- collab_runtime-0.2.9/tests/backend/unit/test_entrypoints_main_run.py +83 -0
- collab_runtime-0.2.9/tests/backend/unit/test_logging_config.py +529 -0
- collab_runtime-0.2.9/tests/backend/unit/test_main_watch_pid_file.py +278 -0
- collab_runtime-0.2.9/tests/conftest.py +167 -0
- collab_runtime-0.2.9/tests/frontend/__init__.py +0 -0
- collab_runtime-0.2.9/tests/frontend/jest/__init__.py +0 -0
- collab_runtime-0.2.9/tests/frontend/playwright/__init__.py +0 -0
- collab_runtime-0.2.9/tests/packaging/test_smoke_install.py +76 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 KirilMT
|
|
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,218 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: collab-runtime
|
|
3
|
+
Version: 0.2.9
|
|
4
|
+
Summary: Collaborative file locking runtime
|
|
5
|
+
Author-email: KirilMT <kiril.mt95@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: collaboration,file-locking,supabase,cli,developer-tools
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Topic :: Software Development :: Version Control
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: python-dotenv>=1.2.2
|
|
20
|
+
Requires-Dist: supabase>=2.30.0
|
|
21
|
+
Requires-Dist: httpx>=0.28.1
|
|
22
|
+
Requires-Dist: psutil>=5.9.8
|
|
23
|
+
Requires-Dist: plyer>=2.1.0
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
|
|
26
|
+
# collab-runtime — Collaborative File Locking
|
|
27
|
+
|
|
28
|
+
> Prevent merge conflicts by automatically locking files when a developer starts editing them, using **Supabase Realtime** as the backend.
|
|
29
|
+
|
|
30
|
+
[](https://www.python.org/)
|
|
31
|
+
[](https://github.com/KirilMT/collab/blob/main/LICENSE)
|
|
32
|
+
[](https://pypi.org/project/collab-runtime/)
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## What It Does
|
|
37
|
+
|
|
38
|
+
`collab-runtime` provides a CLI and background daemon that coordinate file-level locking across a development team in real time.
|
|
39
|
+
When a developer opens a file, a lock is acquired in Supabase. Other developers are immediately notified — via desktop notifications, VS Code warnings, or the web dashboard — that the file is in use.
|
|
40
|
+
|
|
41
|
+
**Key features:**
|
|
42
|
+
|
|
43
|
+
- ⚡ **Atomic lock acquisition** — Supabase RPC prevents two developers locking the same file simultaneously
|
|
44
|
+
- 📡 **Real-time broadcast** — Supabase Realtime pushes lock events to all connected clients instantly
|
|
45
|
+
- 🖥️ **Web dashboard** — Live lock status view, force-release controls
|
|
46
|
+
- 🔔 **VS Code extension** — Lock warnings, status bar, output channel
|
|
47
|
+
- 🪝 **Git hooks** — Pre-commit and pre-push hooks block commits of locked files
|
|
48
|
+
- 📋 **Audit trail** — Full lock history with configurable retention
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Prerequisites
|
|
53
|
+
|
|
54
|
+
| Requirement | Version / Notes |
|
|
55
|
+
| ---------------- | ------------------------------------------------------ |
|
|
56
|
+
| Python | 3.10 or higher |
|
|
57
|
+
| Supabase account | [supabase.com](https://supabase.com) — free tier works |
|
|
58
|
+
| Node.js | Only required for the VS Code extension |
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Installation
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pip install collab-runtime
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
For a minimum-version install (ensures you get the latest compatible release):
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
pip install "collab-runtime>=0.2.2"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Quick Start
|
|
77
|
+
|
|
78
|
+
### 1 — Create the Database Schema
|
|
79
|
+
|
|
80
|
+
In your Supabase project, open **SQL Editor** and run the contents of [`schema.sql`](https://github.com/KirilMT/collab/blob/main/schema.sql).
|
|
81
|
+
|
|
82
|
+
This creates the `file_locks` table, `file_locks_history` audit table, the atomic `acquire_lock()` RPC, Row Level Security policies, and Realtime publication.
|
|
83
|
+
|
|
84
|
+
### 2 — Configure Environment Variables
|
|
85
|
+
|
|
86
|
+
Create a `.env` file in your project root:
|
|
87
|
+
|
|
88
|
+
```env
|
|
89
|
+
SUPABASE_URL=https://your-project.supabase.co
|
|
90
|
+
SUPABASE_ANON_KEY=your_anon_key_here
|
|
91
|
+
SUPABASE_SERVICE_ROLE_KEY=your_service_role_key # Required for force-release
|
|
92
|
+
DEVELOPER_ID=your_name # Optional, defaults to git user.name
|
|
93
|
+
LOCK_STRICT=0 # 1 = block on lock errors, 0 = warn only
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
> **Keep `SUPABASE_SERVICE_ROLE_KEY` private — never commit it to version control.**
|
|
97
|
+
|
|
98
|
+
### 3 — Verify Connection
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
collab active
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
If connected, this lists all currently active locks (empty on a fresh setup).
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## CLI Reference
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
# Show all active locks across the team
|
|
112
|
+
collab active
|
|
113
|
+
|
|
114
|
+
# Lock a file before editing
|
|
115
|
+
collab acquire path/to/file.py --reason "Implementing feature X"
|
|
116
|
+
|
|
117
|
+
# Release a lock when done
|
|
118
|
+
collab release path/to/file.py
|
|
119
|
+
|
|
120
|
+
# Check lock status for a specific file
|
|
121
|
+
collab status path/to/file.py
|
|
122
|
+
|
|
123
|
+
# Release all locks held by you
|
|
124
|
+
collab release-all
|
|
125
|
+
|
|
126
|
+
# Force release (requires SUPABASE_SERVICE_ROLE_KEY)
|
|
127
|
+
collab force-release path/to/file.py
|
|
128
|
+
collab force-release-all
|
|
129
|
+
|
|
130
|
+
# Batch operations
|
|
131
|
+
collab acquire-batch path/to/a.py path/to/b.py --reason "Refactoring"
|
|
132
|
+
collab release-batch path/to/a.py path/to/b.py
|
|
133
|
+
|
|
134
|
+
# Reconcile local and remote lock state
|
|
135
|
+
collab reconcile
|
|
136
|
+
|
|
137
|
+
# Lock history and retention
|
|
138
|
+
collab history
|
|
139
|
+
collab history path/to/file.py --limit 50
|
|
140
|
+
collab history-prune --days 30
|
|
141
|
+
|
|
142
|
+
# Background watcher daemon
|
|
143
|
+
collab daemon-start
|
|
144
|
+
collab daemon-start --interval 10 --timeout 480
|
|
145
|
+
collab daemon-status
|
|
146
|
+
collab daemon-stop
|
|
147
|
+
|
|
148
|
+
# Foreground watcher (diagnostics)
|
|
149
|
+
collab watch --interval 5 --timeout 0
|
|
150
|
+
|
|
151
|
+
# Web dashboard (opens in browser)
|
|
152
|
+
collab dashboard
|
|
153
|
+
|
|
154
|
+
# Cleanup orphaned watcher processes
|
|
155
|
+
collab cleanup
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## VS Code Extension
|
|
161
|
+
|
|
162
|
+
The optional VS Code extension provides lock-on-open warnings, a status bar indicator, and one-click dashboard access.
|
|
163
|
+
|
|
164
|
+
**Install from source** (extension is bundled in the [GitHub repository](https://github.com/KirilMT/collab)):
|
|
165
|
+
|
|
166
|
+
1. Press `F1` → **Developer: Install Extension from Location...**
|
|
167
|
+
2. Select the `vscode-extension/collab-locks/` directory
|
|
168
|
+
3. Reload VS Code
|
|
169
|
+
|
|
170
|
+
Once installed, the extension automatically starts and stops the background daemon with your VS Code window.
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## How It Works
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
Developer opens file
|
|
178
|
+
│
|
|
179
|
+
▼
|
|
180
|
+
collab acquire (CLI or extension)
|
|
181
|
+
│
|
|
182
|
+
▼
|
|
183
|
+
Supabase RPC: acquire_lock() ◄─── atomic, unique constraint
|
|
184
|
+
│ prevents double-locking
|
|
185
|
+
▼
|
|
186
|
+
Supabase Realtime broadcast
|
|
187
|
+
│
|
|
188
|
+
├─► VS Code extension → lock warning popup
|
|
189
|
+
├─► Web dashboard → live status update
|
|
190
|
+
└─► Desktop notification (via plyer)
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Lock release follows the same path in reverse and writes an entry to `file_locks_history` for audit.
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Security
|
|
198
|
+
|
|
199
|
+
- Lock correctness is enforced at the database level via atomic RPC — no client-side race conditions.
|
|
200
|
+
- Force-release requires `SUPABASE_SERVICE_ROLE_KEY`; regular releases are scoped to the owning developer.
|
|
201
|
+
- Row Level Security (RLS) is configured on all tables via `schema.sql`.
|
|
202
|
+
- Never commit secrets; use `.env` for local configuration only.
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## Links
|
|
207
|
+
|
|
208
|
+
- 📦 **PyPI:** [pypi.org/project/collab-runtime](https://pypi.org/project/collab-runtime/)
|
|
209
|
+
- 🐙 **GitHub:** [github.com/KirilMT/collab](https://github.com/KirilMT/collab)
|
|
210
|
+
- 🐛 **Issues:** [github.com/KirilMT/collab/issues](https://github.com/KirilMT/collab/issues)
|
|
211
|
+
- 📖 **Full docs:** [github.com/KirilMT/collab/tree/main/docs](https://github.com/KirilMT/collab/tree/main/docs)
|
|
212
|
+
- 🗺️ **Roadmap:** [docs/collab_roadmap.md](https://github.com/KirilMT/collab/blob/main/docs/collab_roadmap.md)
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## License
|
|
217
|
+
|
|
218
|
+
MIT — see [LICENSE](https://github.com/KirilMT/collab/blob/main/LICENSE) for details.
|
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
# Collab Runtime — Collaborative File Locking
|
|
2
|
+
|
|
3
|
+
Prevents merge conflicts by automatically locking files when a developer starts editing them, using Supabase Realtime as the backend.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Prerequisites
|
|
8
|
+
|
|
9
|
+
- **Python** 3.10+
|
|
10
|
+
- **Supabase** account with a project ([supabase.com](https://supabase.com))
|
|
11
|
+
- **Node.js** (only for the VS Code extension)
|
|
12
|
+
- **Git** (for pre-commit hooks integration)
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 5-Minute Setup Guide
|
|
17
|
+
|
|
18
|
+
### 1. Create the Database Schema
|
|
19
|
+
|
|
20
|
+
Open your Supabase project's **SQL Editor** and run the contents of `schema.sql`:
|
|
21
|
+
|
|
22
|
+
**Steps:**
|
|
23
|
+
|
|
24
|
+
1. Open your Supabase project dashboard
|
|
25
|
+
2. Navigate to **SQL Editor** (left sidebar)
|
|
26
|
+
3. Click **New Query**
|
|
27
|
+
4. Copy-paste the full contents of [schema.sql](schema.sql) from this repository
|
|
28
|
+
5. Click **Run**
|
|
29
|
+
|
|
30
|
+
This creates:
|
|
31
|
+
|
|
32
|
+
- `file_locks` table (active locks)
|
|
33
|
+
- `file_locks_history` table (audit trail)
|
|
34
|
+
- `acquire_lock()` RPC function (atomic lock acquisition)
|
|
35
|
+
- Row Level Security policies
|
|
36
|
+
- Realtime publication
|
|
37
|
+
- Auto-history trigger on lock release
|
|
38
|
+
- Automatic history retention (30 days by default)
|
|
39
|
+
|
|
40
|
+
### 2. Install the Package
|
|
41
|
+
|
|
42
|
+
The `collab` command-line tool is distributed as `collab-runtime` on PyPI.
|
|
43
|
+
|
|
44
|
+
**Development Setup (from source):**
|
|
45
|
+
One command handles everything — dependencies, `.env` configuration, and IDE integration:
|
|
46
|
+
|
|
47
|
+
**Windows (PowerShell):**
|
|
48
|
+
|
|
49
|
+
```powershell
|
|
50
|
+
.\scripts\setup-dev.ps1
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Linux/macOS (Bash):**
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
./scripts/setup.sh
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**End-User Install (via pip):**
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
pip install collab-runtime
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The setup script automatically:
|
|
66
|
+
|
|
67
|
+
- Creates a Python virtual environment (`.venv`)
|
|
68
|
+
- Installs `collab-runtime` and its dependencies
|
|
69
|
+
- Prompts for Supabase credentials if `.env` is missing
|
|
70
|
+
- Copies git pre-commit hooks
|
|
71
|
+
- Installs IDE extensions (VS Code, etc.)
|
|
72
|
+
|
|
73
|
+
### 3. Environment Variables
|
|
74
|
+
|
|
75
|
+
After setup, verify your `.env` at the project root has these values:
|
|
76
|
+
|
|
77
|
+
| Variable | Description |
|
|
78
|
+
| --------------------------- | --------------------------------------------------------------- |
|
|
79
|
+
| `SUPABASE_URL` | Your Supabase project URL (from Project Settings → API) |
|
|
80
|
+
| `SUPABASE_ANON_KEY` | Anonymous/public key (from Project Settings → API) |
|
|
81
|
+
| `SUPABASE_SERVICE_ROLE_KEY` | Service role key (**required** for dashboard force-release) |
|
|
82
|
+
| `LOCK_STRICT` | If `1`, git hooks block on lock errors. Default `0` (warn only) |
|
|
83
|
+
|
|
84
|
+
> **Important:** `SUPABASE_SERVICE_ROLE_KEY` is needed for the dashboard's Force Release button. Without it, only your own locks can be released.
|
|
85
|
+
|
|
86
|
+
### 4. Verify Setup
|
|
87
|
+
|
|
88
|
+
After setup, verify the connection:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
collab active
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
If connected, this shows all active locks (initially empty).
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Quick Start — Testing the Locking System
|
|
99
|
+
|
|
100
|
+
Once setup is complete, test the locking system:
|
|
101
|
+
|
|
102
|
+
**Terminal 1 (Lock a file):**
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
collab acquire src/main.py --reason "Testing locking system"
|
|
106
|
+
collab status src/main.py
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**Terminal 2 (View lock in another session):**
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
collab active
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**Then release the lock:**
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
collab release src/main.py
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**View real-time lock changes:**
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
collab dashboard
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Opens in your default browser showing live lock status.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## CLI Reference
|
|
132
|
+
|
|
133
|
+
The `collab` command is installed globally after setup:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# List all active locks
|
|
137
|
+
collab active
|
|
138
|
+
|
|
139
|
+
# Lock a file
|
|
140
|
+
collab acquire path/to/file.py --reason "Feature implementation"
|
|
141
|
+
|
|
142
|
+
# Release a file you locked
|
|
143
|
+
collab release path/to/file.py
|
|
144
|
+
|
|
145
|
+
# Check file status
|
|
146
|
+
collab status path/to/file.py
|
|
147
|
+
|
|
148
|
+
# Release all your locks
|
|
149
|
+
collab release-all
|
|
150
|
+
|
|
151
|
+
# Force release (admin only)
|
|
152
|
+
collab force-release path/to/file.py
|
|
153
|
+
collab force-release-all
|
|
154
|
+
|
|
155
|
+
# Batch lock operations
|
|
156
|
+
collab acquire-batch path/to/a.py path/to/b.py --reason "Batch work"
|
|
157
|
+
collab release-batch path/to/a.py path/to/b.py
|
|
158
|
+
|
|
159
|
+
# Reconcile local and remote lock state
|
|
160
|
+
collab reconcile
|
|
161
|
+
|
|
162
|
+
# Lock history and retention
|
|
163
|
+
collab history
|
|
164
|
+
collab history path/to/file.py --limit 50
|
|
165
|
+
collab history-prune --days 30
|
|
166
|
+
|
|
167
|
+
# Cleanup orphaned watcher processes
|
|
168
|
+
collab cleanup
|
|
169
|
+
|
|
170
|
+
# Start background watcher
|
|
171
|
+
collab daemon-start
|
|
172
|
+
collab daemon-start --interval 10 --timeout 480
|
|
173
|
+
|
|
174
|
+
# Check daemon status
|
|
175
|
+
collab daemon-status
|
|
176
|
+
|
|
177
|
+
# Stop the daemon
|
|
178
|
+
collab daemon-stop
|
|
179
|
+
|
|
180
|
+
# Foreground watcher (internal/diagnostics)
|
|
181
|
+
collab watch --interval 5 --timeout 0
|
|
182
|
+
|
|
183
|
+
# View lock dashboard
|
|
184
|
+
collab dashboard
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## VS Code Extension
|
|
190
|
+
|
|
191
|
+
The extension warns you when a locked file is opened and provides dashboard access.
|
|
192
|
+
|
|
193
|
+
### Installation
|
|
194
|
+
|
|
195
|
+
The extension is primarily distributed via the **Collab Runtime** Python package. When you open a repository in VS Code, the extension will automatically check for the runtime and prompt you to install it if missing.
|
|
196
|
+
|
|
197
|
+
**Automatic Install:**
|
|
198
|
+
|
|
199
|
+
1. Open VS Code in a collab-enabled repository.
|
|
200
|
+
2. If prompted, click **[Install via pip]**.
|
|
201
|
+
|
|
202
|
+
**Manual Install (from source):**
|
|
203
|
+
|
|
204
|
+
1. Press `F1` -> `Developer: Install Extension from Location...`
|
|
205
|
+
2. Select `vscode-extension/collab-locks/`
|
|
206
|
+
3. Reload VS Code
|
|
207
|
+
|
|
208
|
+
**CLI Install:**
|
|
209
|
+
If you have the `collab` CLI installed, the extension is often provisioned automatically by `scripts/setup-dev.ps1`.
|
|
210
|
+
|
|
211
|
+
### Features
|
|
212
|
+
|
|
213
|
+
- **Lock-on-Open Warning** — popup when opening a locked file
|
|
214
|
+
- **Status Bar** — shows current file lock status
|
|
215
|
+
- **Output Channel** — watcher logs in **View → Output → Collab Locks**
|
|
216
|
+
- **Commands** — quick access via Command Palette
|
|
217
|
+
|
|
218
|
+
### Notification Channels
|
|
219
|
+
|
|
220
|
+
Notifications can come from two independent channels:
|
|
221
|
+
|
|
222
|
+
- **VS Code extension notifications** (when extension is installed): lock warnings, status bar updates, output channel events.
|
|
223
|
+
- **Watcher desktop notifications** (runtime via `plyer`): emitted by the watcher for lock/conflict lifecycle events.
|
|
224
|
+
|
|
225
|
+
If the extension is not available, watcher notifications and CLI/dashboard behavior still work.
|
|
226
|
+
|
|
227
|
+
### Extension Configuration
|
|
228
|
+
|
|
229
|
+
Create or update `.env` in your workspace:
|
|
230
|
+
|
|
231
|
+
```env
|
|
232
|
+
SUPABASE_URL=https://your-project.supabase.co
|
|
233
|
+
SUPABASE_ANON_KEY=your_anon_key
|
|
234
|
+
DEVELOPER_ID=your_name # optional: defaults to git config user.name
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Session Identity & Stability
|
|
240
|
+
|
|
241
|
+
Collab uses a stable session identity derived from your developer id, host, and project root.
|
|
242
|
+
This keeps lock ownership consistent across IDE terminals and avoids accidental token churn
|
|
243
|
+
between restarts.
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## Automatic Lifecycle
|
|
248
|
+
|
|
249
|
+
- `collab daemon-start` creates a watcher process namespace tied to this repository.
|
|
250
|
+
- `collab daemon-status` returns exit code `0` when watcher is running and `1` when not running.
|
|
251
|
+
- `collab daemon-stop` requests graceful shutdown and releases process-state artifacts.
|
|
252
|
+
|
|
253
|
+
If a stale PID marker exists, startup logic attempts cleanup and recovery before launching a
|
|
254
|
+
replacement watcher.
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## Kill the Daemon Manually
|
|
259
|
+
|
|
260
|
+
If graceful shutdown fails, remove the watcher process manually:
|
|
261
|
+
|
|
262
|
+
Windows PowerShell:
|
|
263
|
+
|
|
264
|
+
```powershell
|
|
265
|
+
$pidPath = ".daemon.pid"
|
|
266
|
+
if (Test-Path $pidPath) {
|
|
267
|
+
$raw = Get-Content $pidPath -Raw
|
|
268
|
+
if ($raw.Trim().StartsWith("{")) {
|
|
269
|
+
$obj = $raw | ConvertFrom-Json
|
|
270
|
+
taskkill /F /PID $obj.pid
|
|
271
|
+
} else {
|
|
272
|
+
taskkill /F /PID [int]$raw
|
|
273
|
+
}
|
|
274
|
+
Remove-Item $pidPath -Force
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## Database Schema
|
|
281
|
+
|
|
282
|
+
The full schema is in `schema.sql` and includes:
|
|
283
|
+
|
|
284
|
+
- `file_locks` for active locks.
|
|
285
|
+
- `file_locks_history` for audit/history.
|
|
286
|
+
- `acquire_lock(...)` RPC for atomic lock acquisition.
|
|
287
|
+
- release trigger for automatic history writes.
|
|
288
|
+
- optional retention pruning support.
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## Security Model
|
|
293
|
+
|
|
294
|
+
- Lock correctness is enforced in the application workflow plus atomic RPC behavior.
|
|
295
|
+
- Force-release operations require service-role level credentials.
|
|
296
|
+
- Keep `SUPABASE_SERVICE_ROLE_KEY` private; never commit it.
|
|
297
|
+
- Use `.env` only for local secret storage.
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## Directory Structure
|
|
302
|
+
|
|
303
|
+
```
|
|
304
|
+
collab/
|
|
305
|
+
├── src/
|
|
306
|
+
│ ├── lock_client.py # CLI entry point
|
|
307
|
+
│ ├── live_locks_watcher.py # Background watcher
|
|
308
|
+
│ ├── main.py # CLI orchestration + module entry point
|
|
309
|
+
│ ├── dashboard/ # Web UI
|
|
310
|
+
│ └── __init__.py # Package marker
|
|
311
|
+
├── logs/ # Runtime logs (created dynamically)
|
|
312
|
+
├── tests/
|
|
313
|
+
│ ├── backend/
|
|
314
|
+
│ │ ├── unit/ # Unit tests
|
|
315
|
+
│ │ ├── functional/ # Functional tests
|
|
316
|
+
│ │ ├── integration/ # Integration tests
|
|
317
|
+
│ │ ├── security/ # Security tests
|
|
318
|
+
│ │ ├── performance/ # Performance tests
|
|
319
|
+
│ │ └── reliability/ # Reliability tests
|
|
320
|
+
│ └── frontend/
|
|
321
|
+
│ ├── jest/ # Frontend unit placeholder
|
|
322
|
+
│ └── playwright/ # Frontend e2e placeholder
|
|
323
|
+
├── scripts/
|
|
324
|
+
│ ├── setup-dev.ps1 # Windows setup
|
|
325
|
+
│ ├── setup.sh # Linux/macOS setup
|
|
326
|
+
│ ├── format_code.py # Code formatter
|
|
327
|
+
│ ├── validate_code.py # CI validator
|
|
328
|
+
│ └── cleanup.py # Cache cleanup
|
|
329
|
+
├── schema.sql # Supabase database schema
|
|
330
|
+
├── pyproject.toml # Package configuration
|
|
331
|
+
└── README.md # This file
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
336
|
+
## Runtime Logs
|
|
337
|
+
|
|
338
|
+
Logs are stored in `logs/` and the directory is created dynamically at runtime:
|
|
339
|
+
|
|
340
|
+
```
|
|
341
|
+
logs/
|
|
342
|
+
├── collab.log # Production logs
|
|
343
|
+
└── test_collab.log # Test logs
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
View logs in real-time:
|
|
347
|
+
|
|
348
|
+
```bash
|
|
349
|
+
# Linux/macOS
|
|
350
|
+
tail -f logs/collab.log
|
|
351
|
+
|
|
352
|
+
# Windows PowerShell
|
|
353
|
+
Get-Content logs/collab.log -Tail 10 -Wait
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
## Git Integration
|
|
359
|
+
|
|
360
|
+
Pre-commit hooks prevent commits of locked files. To use:
|
|
361
|
+
|
|
362
|
+
```bash
|
|
363
|
+
collab acquire path/to/file.py --reason "Fixing bug #123"
|
|
364
|
+
git add path/to/file.py
|
|
365
|
+
git commit -m "fix: resolve issue"
|
|
366
|
+
collab release path/to/file.py
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
---
|
|
370
|
+
|
|
371
|
+
## Troubleshooting
|
|
372
|
+
|
|
373
|
+
### `collab active` shows "Connection refused"
|
|
374
|
+
|
|
375
|
+
**Fix:** Check credentials in `.env`:
|
|
376
|
+
|
|
377
|
+
```bash
|
|
378
|
+
cat .env # Verify SUPABASE_URL and SUPABASE_ANON_KEY
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### `collab` command not found
|
|
382
|
+
|
|
383
|
+
**Fix:** Ensure your virtual environment is active or install the package:
|
|
384
|
+
|
|
385
|
+
```bash
|
|
386
|
+
pip install collab-runtime
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### `python collab.py daemon-status` fails with file-not-found
|
|
390
|
+
|
|
391
|
+
`collab.py` is not a file in this repository.
|
|
392
|
+
|
|
393
|
+
Use:
|
|
394
|
+
|
|
395
|
+
```bash
|
|
396
|
+
collab daemon-status
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
### VS Code extension not loading
|
|
400
|
+
|
|
401
|
+
**Fix:**
|
|
402
|
+
|
|
403
|
+
1. Reload: `Ctrl+Shift+P` → "Developer: Reload Window"
|
|
404
|
+
2. Check logs: **View → Output → Collab Locks**
|
|
405
|
+
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
## Architecture
|
|
409
|
+
|
|
410
|
+
### Lock Acquisition
|
|
411
|
+
|
|
412
|
+
1. `collab acquire file.py` sends lock request to Supabase
|
|
413
|
+
2. Supabase atomically adds lock (unique constraint prevents conflicts)
|
|
414
|
+
3. Realtime broadcasts lock to all connected clients
|
|
415
|
+
4. VS Code shows lock warning if file is open
|
|
416
|
+
|
|
417
|
+
### Conflict Prevention
|
|
418
|
+
|
|
419
|
+
- File locks use a unique key on `file_path`
|
|
420
|
+
- Only one developer can hold a lock per file
|
|
421
|
+
- Merge conflicts prevented by design
|
|
422
|
+
|
|
423
|
+
### Dashboard
|
|
424
|
+
|
|
425
|
+
```bash
|
|
426
|
+
collab dashboard # Opens in browser with real-time lock view
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
---
|
|
430
|
+
|
|
431
|
+
## Development
|
|
432
|
+
|
|
433
|
+
### Install for Development
|
|
434
|
+
|
|
435
|
+
```bash
|
|
436
|
+
python -m pip install .
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
### Run Tests
|
|
440
|
+
|
|
441
|
+
```bash
|
|
442
|
+
pytest tests/backend tests/frontend
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
### Code Quality
|
|
446
|
+
|
|
447
|
+
```bash
|
|
448
|
+
python scripts/format_code.py
|
|
449
|
+
python scripts/validate_code.py
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
### Create Distribution
|
|
453
|
+
|
|
454
|
+
```bash
|
|
455
|
+
python -m build
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
---
|
|
459
|
+
|
|
460
|
+
## License
|
|
461
|
+
|
|
462
|
+
MIT License — see LICENSE file for details.
|
|
463
|
+
|
|
464
|
+
---
|
|
465
|
+
|
|
466
|
+
## Support
|
|
467
|
+
|
|
468
|
+
For issues, questions, or feature requests:
|
|
469
|
+
|
|
470
|
+
1. Check [issues](../../issues)
|
|
471
|
+
2. Open a [new issue](../../issues/new) with reproduction steps
|
|
472
|
+
3. See [docs/collab_roadmap.md](docs/collab_roadmap.md) for planned features
|