devloop 0.2.1__tar.gz → 0.3.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.
- {devloop-0.2.1 → devloop-0.3.0}/PKG-INFO +97 -17
- {devloop-0.2.1 → devloop-0.3.0}/README.md +92 -16
- {devloop-0.2.1 → devloop-0.3.0}/pyproject.toml +11 -1
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/__init__.py +1 -1
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/linter.py +79 -89
- devloop-0.3.0/src/devloop/agents/sandbox_helper.py +231 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/type_checker.py +24 -14
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/cli/commands/summary.py +27 -1
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/cli/main.py +197 -12
- devloop-0.3.0/src/devloop/cli/pyodide_installer.py +132 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/config.py +146 -103
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/context_store.py +40 -0
- devloop-0.3.0/src/devloop/core/operational_health.py +282 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/summary_formatter.py +13 -1
- devloop-0.3.0/src/devloop/security/__init__.py +15 -0
- devloop-0.3.0/src/devloop/security/audit_logger.py +263 -0
- devloop-0.3.0/src/devloop/security/bubblewrap_sandbox.py +352 -0
- devloop-0.3.0/src/devloop/security/cgroups_helper.py +253 -0
- devloop-0.3.0/src/devloop/security/factory.py +207 -0
- devloop-0.3.0/src/devloop/security/no_sandbox.py +146 -0
- devloop-0.3.0/src/devloop/security/package.json +19 -0
- devloop-0.3.0/src/devloop/security/pyodide_runner.js +290 -0
- devloop-0.3.0/src/devloop/security/pyodide_sandbox.py +271 -0
- devloop-0.3.0/src/devloop/security/sandbox.py +228 -0
- {devloop-0.2.1 → devloop-0.3.0}/LICENSE +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/__init__.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/agent_health_monitor.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/ci_monitor.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/code_rabbit.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/doc_lifecycle.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/echo.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/file_logger.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/formatter.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/git_commit_assistant.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/performance_profiler.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/security_scanner.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/snyk.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/test_runner.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/cli/__init__.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/cli/commands/__init__.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/cli/commands/custom_agents.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/cli/commands/feedback.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/cli/main_v1.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/collectors/__init__.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/collectors/base.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/collectors/filesystem.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/collectors/git.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/collectors/manager.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/collectors/process.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/collectors/system.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/__init__.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/agent.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/agent_template.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/amp_integration.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/auto_fix.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/context.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/contextual_feedback.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/custom_agent.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/debug_trace.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/event.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/event_store.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/feedback.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/learning.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/manager.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/performance.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/proactive_feedback.py +0 -0
- {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/summary_generator.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: devloop
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Intelligent background agents for development workflow automation
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -21,6 +21,10 @@ Classifier: Topic :: Software Development :: Build Tools
|
|
|
21
21
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
22
|
Classifier: Topic :: Software Development :: Quality Assurance
|
|
23
23
|
Classifier: Topic :: Utilities
|
|
24
|
+
Provides-Extra: all-optional
|
|
25
|
+
Provides-Extra: ci-monitor
|
|
26
|
+
Provides-Extra: code-rabbit
|
|
27
|
+
Provides-Extra: snyk
|
|
24
28
|
Requires-Dist: aiofiles (>=23.2,<24.0)
|
|
25
29
|
Requires-Dist: psutil (>=5.9,<6.0)
|
|
26
30
|
Requires-Dist: pydantic (>=2.5,<3.0)
|
|
@@ -38,12 +42,32 @@ Description-Content-Type: text/markdown
|
|
|
38
42
|
|
|
39
43
|
[](https://www.python.org/downloads/)
|
|
40
44
|
[](#testing)
|
|
41
|
-
[](#status)
|
|
42
46
|
[](LICENSE)
|
|
43
47
|
|
|
48
|
+
## ⚠️ ALPHA SOFTWARE - NOT FOR PRODUCTION
|
|
49
|
+
|
|
50
|
+
**DevLoop is currently in active development and is not recommended for production use.**
|
|
51
|
+
|
|
52
|
+
This is **research-quality software**. Use at your own risk. See [Known Limitations & Risks](./history/RISK_ASSESSMENT.md) for details on:
|
|
53
|
+
|
|
54
|
+
- ✗ Subprocess execution not sandboxed (security risk)
|
|
55
|
+
- ✗ Auto-fix may corrupt code (enable only if willing to review changes)
|
|
56
|
+
- ✗ Race conditions possible in file operations (concurrent agent modifications)
|
|
57
|
+
- ✗ Limited error recovery (daemon may not restart automatically)
|
|
58
|
+
- ✗ Configuration migrations not yet supported
|
|
59
|
+
- ✗ No process supervision (manual daemon management)
|
|
60
|
+
|
|
61
|
+
**Suitable for:** Development on side projects, testing automation, research
|
|
62
|
+
**Not suitable for:** Critical code, production systems, untrusted projects
|
|
63
|
+
|
|
64
|
+
[View complete risk assessment →](./history/RISK_ASSESSMENT.md)
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
44
68
|
## Status
|
|
45
69
|
|
|
46
|
-
|
|
70
|
+
🔬 **ALPHA** — Full-featured development automation system in active development. [View detailed implementation status →](./IMPLEMENTATION_STATUS.md)
|
|
47
71
|
|
|
48
72
|
---
|
|
49
73
|
|
|
@@ -68,6 +92,15 @@ All agents run **non-intrusively in the background**, respecting your workflow.
|
|
|
68
92
|
|
|
69
93
|
## Quick Start
|
|
70
94
|
|
|
95
|
+
### ⚠️ Before You Start
|
|
96
|
+
|
|
97
|
+
**ALPHA SOFTWARE DISCLAIMER:**
|
|
98
|
+
- This is research-quality code. Data loss is possible.
|
|
99
|
+
- Only use on projects you can afford to lose or easily recover.
|
|
100
|
+
- Make sure to commit your code to git before enabling DevLoop.
|
|
101
|
+
- Do not enable auto-fix on important code.
|
|
102
|
+
- Some agents may fail silently (see logs for details).
|
|
103
|
+
|
|
71
104
|
### Installation
|
|
72
105
|
|
|
73
106
|
**Prerequisites:** Python 3.11+
|
|
@@ -75,9 +108,31 @@ All agents run **non-intrusively in the background**, respecting your workflow.
|
|
|
75
108
|
#### Option 1: From PyPI (Recommended)
|
|
76
109
|
|
|
77
110
|
```bash
|
|
111
|
+
# Basic installation (all default agents)
|
|
78
112
|
pip install devloop
|
|
113
|
+
|
|
114
|
+
# With optional agents (Snyk security scanning)
|
|
115
|
+
pip install devloop[snyk]
|
|
116
|
+
|
|
117
|
+
# With multiple optional agents
|
|
118
|
+
pip install devloop[snyk,code-rabbit]
|
|
119
|
+
|
|
120
|
+
# With all optional agents
|
|
121
|
+
pip install devloop[all-optional]
|
|
79
122
|
```
|
|
80
123
|
|
|
124
|
+
**Available extras:**
|
|
125
|
+
- `snyk` — Dependency vulnerability scanning via Snyk CLI
|
|
126
|
+
- `code-rabbit` — AI-powered code analysis
|
|
127
|
+
- `ci-monitor` — CI/CD pipeline monitoring
|
|
128
|
+
- `all-optional` — All of the above
|
|
129
|
+
|
|
130
|
+
**Optional sandbox enhancements:**
|
|
131
|
+
- **Pyodide WASM Sandbox** (cross-platform Python sandboxing)
|
|
132
|
+
- Requires: Node.js 18+ (system dependency)
|
|
133
|
+
- Install: See [Pyodide Installation Guide](./docs/PYODIDE_INSTALLATION.md)
|
|
134
|
+
- Works in POC mode without installation for testing
|
|
135
|
+
|
|
81
136
|
#### Option 2: From Source
|
|
82
137
|
|
|
83
138
|
```bash
|
|
@@ -98,17 +153,24 @@ poetry shell
|
|
|
98
153
|
### Initialize & Run (Fully Automated)
|
|
99
154
|
|
|
100
155
|
```bash
|
|
101
|
-
# 1. Initialize in your project (
|
|
156
|
+
# 1. Initialize in your project (interactive setup)
|
|
102
157
|
devloop init /path/to/your/project
|
|
103
158
|
```
|
|
104
159
|
|
|
105
|
-
The `init` command
|
|
106
|
-
- ✅
|
|
107
|
-
- ✅
|
|
108
|
-
-
|
|
160
|
+
The `init` command will:
|
|
161
|
+
- ✅ Set up .devloop directory with default agents
|
|
162
|
+
- ✅ Ask which optional agents you want to enable:
|
|
163
|
+
- **Snyk** — Scan dependencies for vulnerabilities
|
|
164
|
+
- **Code Rabbit** — AI-powered code analysis
|
|
165
|
+
- **CI Monitor** — Track CI/CD pipeline status
|
|
166
|
+
- ✅ Create configuration file with your selections
|
|
167
|
+
- ✅ Set up git hooks (if git repo)
|
|
109
168
|
- ✅ Registers Amp integration (if in Amp)
|
|
110
|
-
|
|
111
|
-
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
# 1a. Alternative: Non-interactive setup (skip optional agent prompts)
|
|
172
|
+
devloop init /path/to/your/project --non-interactive
|
|
173
|
+
```
|
|
112
174
|
|
|
113
175
|
Then just:
|
|
114
176
|
```bash
|
|
@@ -324,7 +386,7 @@ Configure agent behavior in `.devloop/agents.json`:
|
|
|
324
386
|
{
|
|
325
387
|
"global": {
|
|
326
388
|
"autonomousFixes": {
|
|
327
|
-
"enabled":
|
|
389
|
+
"enabled": false,
|
|
328
390
|
"safetyLevel": "safe_only"
|
|
329
391
|
},
|
|
330
392
|
"maxConcurrentAgents": 5,
|
|
@@ -346,11 +408,13 @@ Configure agent behavior in `.devloop/agents.json`:
|
|
|
346
408
|
}
|
|
347
409
|
```
|
|
348
410
|
|
|
349
|
-
**Safety levels:**
|
|
350
|
-
- `safe_only` — Only fix whitespace/indentation
|
|
411
|
+
**Safety levels (Auto-fix):**
|
|
412
|
+
- `safe_only` — Only fix whitespace/indentation (default, recommended)
|
|
351
413
|
- `medium_risk` — Include import/formatting fixes
|
|
352
414
|
- `all` — Apply all fixes (use with caution)
|
|
353
415
|
|
|
416
|
+
⚠️ **Auto-fix Warning:** Currently auto-fixes run without backups or review. **DO NOT enable auto-fix in production** or on critical code. Track [secure auto-fix with backups issue](https://github.com/wioota/devloop/issues/emc).
|
|
417
|
+
|
|
354
418
|
[Full configuration reference →](./docs/configuration.md)
|
|
355
419
|
|
|
356
420
|
---
|
|
@@ -560,17 +624,26 @@ DevLoop follows these core principles:
|
|
|
560
624
|
|
|
561
625
|
## Troubleshooting
|
|
562
626
|
|
|
627
|
+
### ⚠️ If Something Goes Wrong
|
|
628
|
+
|
|
629
|
+
**Recovery steps:**
|
|
630
|
+
1. Stop the daemon: `devloop stop .`
|
|
631
|
+
2. Check the logs: `tail -100 .devloop/devloop.log`
|
|
632
|
+
3. Verify your code in git: `git status`
|
|
633
|
+
4. Recover from git if files were modified: `git checkout <file>`
|
|
634
|
+
5. Report the issue: [GitHub Issues](https://github.com/wioota/devloop/issues)
|
|
635
|
+
|
|
563
636
|
### Agents not running
|
|
564
637
|
|
|
565
638
|
```bash
|
|
566
639
|
# Check status
|
|
567
640
|
devloop status
|
|
568
641
|
|
|
569
|
-
# View logs
|
|
570
|
-
tail -f .devloop/
|
|
642
|
+
# View logs (useful for debugging)
|
|
643
|
+
tail -f .devloop/devloop.log
|
|
571
644
|
|
|
572
|
-
# Enable verbose mode
|
|
573
|
-
devloop watch . --verbose
|
|
645
|
+
# Enable verbose mode for more details
|
|
646
|
+
devloop watch . --foreground --verbose
|
|
574
647
|
```
|
|
575
648
|
|
|
576
649
|
### Performance issues
|
|
@@ -599,6 +672,13 @@ devloop custom-list
|
|
|
599
672
|
ls -la .devloop/custom_agents/
|
|
600
673
|
```
|
|
601
674
|
|
|
675
|
+
### Agent modified my files unexpectedly
|
|
676
|
+
|
|
677
|
+
1. Check git diff: `git diff`
|
|
678
|
+
2. Revert changes: `git checkout -- .`
|
|
679
|
+
3. Disable the problematic agent in `.devloop/agents.json`
|
|
680
|
+
4. Report issue with: `git show HEAD:.devloop/agents.json`
|
|
681
|
+
|
|
602
682
|
[Full troubleshooting guide →](./docs/troubleshooting.md)
|
|
603
683
|
|
|
604
684
|
---
|
|
@@ -4,12 +4,32 @@
|
|
|
4
4
|
|
|
5
5
|
[](https://www.python.org/downloads/)
|
|
6
6
|
[](#testing)
|
|
7
|
-
[](#status)
|
|
8
8
|
[](LICENSE)
|
|
9
9
|
|
|
10
|
+
## ⚠️ ALPHA SOFTWARE - NOT FOR PRODUCTION
|
|
11
|
+
|
|
12
|
+
**DevLoop is currently in active development and is not recommended for production use.**
|
|
13
|
+
|
|
14
|
+
This is **research-quality software**. Use at your own risk. See [Known Limitations & Risks](./history/RISK_ASSESSMENT.md) for details on:
|
|
15
|
+
|
|
16
|
+
- ✗ Subprocess execution not sandboxed (security risk)
|
|
17
|
+
- ✗ Auto-fix may corrupt code (enable only if willing to review changes)
|
|
18
|
+
- ✗ Race conditions possible in file operations (concurrent agent modifications)
|
|
19
|
+
- ✗ Limited error recovery (daemon may not restart automatically)
|
|
20
|
+
- ✗ Configuration migrations not yet supported
|
|
21
|
+
- ✗ No process supervision (manual daemon management)
|
|
22
|
+
|
|
23
|
+
**Suitable for:** Development on side projects, testing automation, research
|
|
24
|
+
**Not suitable for:** Critical code, production systems, untrusted projects
|
|
25
|
+
|
|
26
|
+
[View complete risk assessment →](./history/RISK_ASSESSMENT.md)
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
10
30
|
## Status
|
|
11
31
|
|
|
12
|
-
|
|
32
|
+
🔬 **ALPHA** — Full-featured development automation system in active development. [View detailed implementation status →](./IMPLEMENTATION_STATUS.md)
|
|
13
33
|
|
|
14
34
|
---
|
|
15
35
|
|
|
@@ -34,6 +54,15 @@ All agents run **non-intrusively in the background**, respecting your workflow.
|
|
|
34
54
|
|
|
35
55
|
## Quick Start
|
|
36
56
|
|
|
57
|
+
### ⚠️ Before You Start
|
|
58
|
+
|
|
59
|
+
**ALPHA SOFTWARE DISCLAIMER:**
|
|
60
|
+
- This is research-quality code. Data loss is possible.
|
|
61
|
+
- Only use on projects you can afford to lose or easily recover.
|
|
62
|
+
- Make sure to commit your code to git before enabling DevLoop.
|
|
63
|
+
- Do not enable auto-fix on important code.
|
|
64
|
+
- Some agents may fail silently (see logs for details).
|
|
65
|
+
|
|
37
66
|
### Installation
|
|
38
67
|
|
|
39
68
|
**Prerequisites:** Python 3.11+
|
|
@@ -41,9 +70,31 @@ All agents run **non-intrusively in the background**, respecting your workflow.
|
|
|
41
70
|
#### Option 1: From PyPI (Recommended)
|
|
42
71
|
|
|
43
72
|
```bash
|
|
73
|
+
# Basic installation (all default agents)
|
|
44
74
|
pip install devloop
|
|
75
|
+
|
|
76
|
+
# With optional agents (Snyk security scanning)
|
|
77
|
+
pip install devloop[snyk]
|
|
78
|
+
|
|
79
|
+
# With multiple optional agents
|
|
80
|
+
pip install devloop[snyk,code-rabbit]
|
|
81
|
+
|
|
82
|
+
# With all optional agents
|
|
83
|
+
pip install devloop[all-optional]
|
|
45
84
|
```
|
|
46
85
|
|
|
86
|
+
**Available extras:**
|
|
87
|
+
- `snyk` — Dependency vulnerability scanning via Snyk CLI
|
|
88
|
+
- `code-rabbit` — AI-powered code analysis
|
|
89
|
+
- `ci-monitor` — CI/CD pipeline monitoring
|
|
90
|
+
- `all-optional` — All of the above
|
|
91
|
+
|
|
92
|
+
**Optional sandbox enhancements:**
|
|
93
|
+
- **Pyodide WASM Sandbox** (cross-platform Python sandboxing)
|
|
94
|
+
- Requires: Node.js 18+ (system dependency)
|
|
95
|
+
- Install: See [Pyodide Installation Guide](./docs/PYODIDE_INSTALLATION.md)
|
|
96
|
+
- Works in POC mode without installation for testing
|
|
97
|
+
|
|
47
98
|
#### Option 2: From Source
|
|
48
99
|
|
|
49
100
|
```bash
|
|
@@ -64,17 +115,24 @@ poetry shell
|
|
|
64
115
|
### Initialize & Run (Fully Automated)
|
|
65
116
|
|
|
66
117
|
```bash
|
|
67
|
-
# 1. Initialize in your project (
|
|
118
|
+
# 1. Initialize in your project (interactive setup)
|
|
68
119
|
devloop init /path/to/your/project
|
|
69
120
|
```
|
|
70
121
|
|
|
71
|
-
The `init` command
|
|
72
|
-
- ✅
|
|
73
|
-
- ✅
|
|
74
|
-
-
|
|
122
|
+
The `init` command will:
|
|
123
|
+
- ✅ Set up .devloop directory with default agents
|
|
124
|
+
- ✅ Ask which optional agents you want to enable:
|
|
125
|
+
- **Snyk** — Scan dependencies for vulnerabilities
|
|
126
|
+
- **Code Rabbit** — AI-powered code analysis
|
|
127
|
+
- **CI Monitor** — Track CI/CD pipeline status
|
|
128
|
+
- ✅ Create configuration file with your selections
|
|
129
|
+
- ✅ Set up git hooks (if git repo)
|
|
75
130
|
- ✅ Registers Amp integration (if in Amp)
|
|
76
|
-
|
|
77
|
-
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
# 1a. Alternative: Non-interactive setup (skip optional agent prompts)
|
|
134
|
+
devloop init /path/to/your/project --non-interactive
|
|
135
|
+
```
|
|
78
136
|
|
|
79
137
|
Then just:
|
|
80
138
|
```bash
|
|
@@ -290,7 +348,7 @@ Configure agent behavior in `.devloop/agents.json`:
|
|
|
290
348
|
{
|
|
291
349
|
"global": {
|
|
292
350
|
"autonomousFixes": {
|
|
293
|
-
"enabled":
|
|
351
|
+
"enabled": false,
|
|
294
352
|
"safetyLevel": "safe_only"
|
|
295
353
|
},
|
|
296
354
|
"maxConcurrentAgents": 5,
|
|
@@ -312,11 +370,13 @@ Configure agent behavior in `.devloop/agents.json`:
|
|
|
312
370
|
}
|
|
313
371
|
```
|
|
314
372
|
|
|
315
|
-
**Safety levels:**
|
|
316
|
-
- `safe_only` — Only fix whitespace/indentation
|
|
373
|
+
**Safety levels (Auto-fix):**
|
|
374
|
+
- `safe_only` — Only fix whitespace/indentation (default, recommended)
|
|
317
375
|
- `medium_risk` — Include import/formatting fixes
|
|
318
376
|
- `all` — Apply all fixes (use with caution)
|
|
319
377
|
|
|
378
|
+
⚠️ **Auto-fix Warning:** Currently auto-fixes run without backups or review. **DO NOT enable auto-fix in production** or on critical code. Track [secure auto-fix with backups issue](https://github.com/wioota/devloop/issues/emc).
|
|
379
|
+
|
|
320
380
|
[Full configuration reference →](./docs/configuration.md)
|
|
321
381
|
|
|
322
382
|
---
|
|
@@ -526,17 +586,26 @@ DevLoop follows these core principles:
|
|
|
526
586
|
|
|
527
587
|
## Troubleshooting
|
|
528
588
|
|
|
589
|
+
### ⚠️ If Something Goes Wrong
|
|
590
|
+
|
|
591
|
+
**Recovery steps:**
|
|
592
|
+
1. Stop the daemon: `devloop stop .`
|
|
593
|
+
2. Check the logs: `tail -100 .devloop/devloop.log`
|
|
594
|
+
3. Verify your code in git: `git status`
|
|
595
|
+
4. Recover from git if files were modified: `git checkout <file>`
|
|
596
|
+
5. Report the issue: [GitHub Issues](https://github.com/wioota/devloop/issues)
|
|
597
|
+
|
|
529
598
|
### Agents not running
|
|
530
599
|
|
|
531
600
|
```bash
|
|
532
601
|
# Check status
|
|
533
602
|
devloop status
|
|
534
603
|
|
|
535
|
-
# View logs
|
|
536
|
-
tail -f .devloop/
|
|
604
|
+
# View logs (useful for debugging)
|
|
605
|
+
tail -f .devloop/devloop.log
|
|
537
606
|
|
|
538
|
-
# Enable verbose mode
|
|
539
|
-
devloop watch . --verbose
|
|
607
|
+
# Enable verbose mode for more details
|
|
608
|
+
devloop watch . --foreground --verbose
|
|
540
609
|
```
|
|
541
610
|
|
|
542
611
|
### Performance issues
|
|
@@ -565,6 +634,13 @@ devloop custom-list
|
|
|
565
634
|
ls -la .devloop/custom_agents/
|
|
566
635
|
```
|
|
567
636
|
|
|
637
|
+
### Agent modified my files unexpectedly
|
|
638
|
+
|
|
639
|
+
1. Check git diff: `git diff`
|
|
640
|
+
2. Revert changes: `git checkout -- .`
|
|
641
|
+
3. Disable the problematic agent in `.devloop/agents.json`
|
|
642
|
+
4. Report issue with: `git show HEAD:.devloop/agents.json`
|
|
643
|
+
|
|
568
644
|
[Full troubleshooting guide →](./docs/troubleshooting.md)
|
|
569
645
|
|
|
570
646
|
---
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "devloop"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.3.0"
|
|
4
4
|
description = "Intelligent background agents for development workflow automation"
|
|
5
5
|
authors = ["DevLoop Contributors <devloop@example.com>"]
|
|
6
6
|
license = "MIT"
|
|
@@ -33,6 +33,10 @@ classifiers = [
|
|
|
33
33
|
"Topic :: Utilities"
|
|
34
34
|
]
|
|
35
35
|
packages = [{include = "devloop", from = "src"}]
|
|
36
|
+
include = [
|
|
37
|
+
"src/devloop/security/package.json",
|
|
38
|
+
"src/devloop/security/pyodide_runner.js",
|
|
39
|
+
]
|
|
36
40
|
|
|
37
41
|
[tool.poetry.dependencies]
|
|
38
42
|
python = "^3.11"
|
|
@@ -53,6 +57,12 @@ bandit = "^1.7"
|
|
|
53
57
|
radon = "^6.0"
|
|
54
58
|
types-aiofiles = "^23.2"
|
|
55
59
|
|
|
60
|
+
[tool.poetry.extras]
|
|
61
|
+
snyk = []
|
|
62
|
+
code-rabbit = []
|
|
63
|
+
ci-monitor = []
|
|
64
|
+
all-optional = []
|
|
65
|
+
|
|
56
66
|
[tool.poetry.scripts]
|
|
57
67
|
devloop = "devloop.cli.main:app"
|
|
58
68
|
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
"""Linter agent - runs linters on file changes."""
|
|
2
2
|
|
|
3
|
-
import asyncio
|
|
4
3
|
import json
|
|
5
4
|
from datetime import datetime
|
|
6
5
|
from pathlib import Path
|
|
7
6
|
from typing import Any, Dict, List, Optional
|
|
8
7
|
|
|
8
|
+
from devloop.agents.sandbox_helper import create_agent_sandbox_helper
|
|
9
9
|
from devloop.core.agent import Agent, AgentResult
|
|
10
10
|
from devloop.core.context_store import Finding, Severity
|
|
11
11
|
from devloop.core.event import Event
|
|
12
|
+
from devloop.security.sandbox import CommandNotAllowedError, SandboxTimeoutError
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
class LinterConfig:
|
|
@@ -70,6 +71,11 @@ class LinterAgent(Agent):
|
|
|
70
71
|
)
|
|
71
72
|
self.config = LinterConfig(config or {})
|
|
72
73
|
self._last_run: Dict[str, float] = {} # path -> timestamp for debouncing
|
|
74
|
+
# Initialize sandbox helper for secure command execution
|
|
75
|
+
self.sandbox = create_agent_sandbox_helper(
|
|
76
|
+
agent_name=name,
|
|
77
|
+
agent_type="linter",
|
|
78
|
+
)
|
|
73
79
|
|
|
74
80
|
async def handle(self, event: Event) -> AgentResult:
|
|
75
81
|
"""Handle file change event by running linter."""
|
|
@@ -198,45 +204,32 @@ class LinterAgent(Agent):
|
|
|
198
204
|
async def _run_ruff(self, path: Path) -> LinterResult:
|
|
199
205
|
"""Run ruff on a Python file."""
|
|
200
206
|
try:
|
|
201
|
-
# Get
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
env = os.environ.copy()
|
|
205
|
-
venv_bin = Path(__file__).parent.parent.parent.parent / ".venv" / "bin"
|
|
206
|
-
if venv_bin.exists():
|
|
207
|
-
env["PATH"] = f"{venv_bin}:{env.get('PATH', '')}"
|
|
208
|
-
|
|
209
|
-
# Check if ruff is installed
|
|
210
|
-
check = await asyncio.create_subprocess_exec(
|
|
211
|
-
"ruff",
|
|
212
|
-
"--version",
|
|
213
|
-
stdout=asyncio.subprocess.PIPE,
|
|
214
|
-
stderr=asyncio.subprocess.PIPE,
|
|
215
|
-
env=env,
|
|
216
|
-
)
|
|
217
|
-
await check.communicate()
|
|
218
|
-
|
|
219
|
-
if check.returncode != 0:
|
|
220
|
-
return LinterResult(success=False, error="ruff not installed")
|
|
221
|
-
|
|
222
|
-
# Run ruff with JSON output
|
|
223
|
-
proc = await asyncio.create_subprocess_exec(
|
|
224
|
-
"ruff",
|
|
225
|
-
"check",
|
|
226
|
-
"--output-format",
|
|
227
|
-
"json",
|
|
228
|
-
str(path),
|
|
229
|
-
stdout=asyncio.subprocess.PIPE,
|
|
230
|
-
stderr=asyncio.subprocess.PIPE,
|
|
231
|
-
env=env,
|
|
232
|
-
)
|
|
207
|
+
# Get venv path
|
|
208
|
+
venv_path = Path(__file__).parent.parent.parent.parent / ".venv"
|
|
233
209
|
|
|
234
|
-
|
|
210
|
+
# Check if ruff is available in the sandbox
|
|
211
|
+
if not await self.sandbox.check_tool_available("ruff"):
|
|
212
|
+
return LinterResult(
|
|
213
|
+
success=False, error="ruff not installed or not allowed"
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
# Run ruff with JSON output in sandbox
|
|
217
|
+
if venv_path.exists():
|
|
218
|
+
result = await self.sandbox.run_sandboxed_with_venv(
|
|
219
|
+
["ruff", "check", "--output-format", "json", str(path)],
|
|
220
|
+
venv_path=venv_path,
|
|
221
|
+
cwd=path.parent,
|
|
222
|
+
)
|
|
223
|
+
else:
|
|
224
|
+
result = await self.sandbox.run_sandboxed(
|
|
225
|
+
["ruff", "check", "--output-format", "json", str(path)],
|
|
226
|
+
cwd=path.parent,
|
|
227
|
+
)
|
|
235
228
|
|
|
236
229
|
# ruff returns non-zero if issues found, but that's expected
|
|
237
|
-
if stdout:
|
|
230
|
+
if result.stdout:
|
|
238
231
|
try:
|
|
239
|
-
issues = json.loads(stdout
|
|
232
|
+
issues = json.loads(result.stdout)
|
|
240
233
|
return LinterResult(success=True, issues=issues)
|
|
241
234
|
except json.JSONDecodeError:
|
|
242
235
|
# No issues found or invalid JSON
|
|
@@ -245,39 +238,33 @@ class LinterAgent(Agent):
|
|
|
245
238
|
# No output = no issues
|
|
246
239
|
return LinterResult(success=True, issues=[])
|
|
247
240
|
|
|
248
|
-
except
|
|
249
|
-
|
|
241
|
+
except CommandNotAllowedError as e:
|
|
242
|
+
self.logger.error(f"ruff command not allowed in sandbox: {e}")
|
|
243
|
+
return LinterResult(success=False, error="ruff command not allowed")
|
|
244
|
+
except SandboxTimeoutError:
|
|
245
|
+
return LinterResult(success=False, error="ruff execution timeout")
|
|
246
|
+
except Exception as e:
|
|
247
|
+
self.logger.error(f"Error running ruff in sandbox: {e}")
|
|
248
|
+
return LinterResult(success=False, error=str(e))
|
|
250
249
|
|
|
251
250
|
async def _run_eslint(self, path: Path) -> LinterResult:
|
|
252
251
|
"""Run eslint on a JavaScript/TypeScript file."""
|
|
253
252
|
try:
|
|
254
|
-
# Check if eslint is
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
stderr=asyncio.subprocess.PIPE,
|
|
260
|
-
)
|
|
261
|
-
await check.communicate()
|
|
262
|
-
|
|
263
|
-
if check.returncode != 0:
|
|
264
|
-
return LinterResult(success=False, error="eslint not installed")
|
|
265
|
-
|
|
266
|
-
# Run eslint with JSON output
|
|
267
|
-
proc = await asyncio.create_subprocess_exec(
|
|
268
|
-
"eslint",
|
|
269
|
-
"--format",
|
|
270
|
-
"json",
|
|
271
|
-
str(path),
|
|
272
|
-
stdout=asyncio.subprocess.PIPE,
|
|
273
|
-
stderr=asyncio.subprocess.PIPE,
|
|
274
|
-
)
|
|
253
|
+
# Check if eslint is available in the sandbox
|
|
254
|
+
if not await self.sandbox.check_tool_available("eslint"):
|
|
255
|
+
return LinterResult(
|
|
256
|
+
success=False, error="eslint not installed or not allowed"
|
|
257
|
+
)
|
|
275
258
|
|
|
276
|
-
|
|
259
|
+
# Run eslint with JSON output in sandbox
|
|
260
|
+
result = await self.sandbox.run_sandboxed(
|
|
261
|
+
["eslint", "--format", "json", str(path)],
|
|
262
|
+
cwd=path.parent,
|
|
263
|
+
)
|
|
277
264
|
|
|
278
|
-
if stdout:
|
|
265
|
+
if result.stdout:
|
|
279
266
|
try:
|
|
280
|
-
results = json.loads(stdout
|
|
267
|
+
results = json.loads(result.stdout)
|
|
281
268
|
# ESLint returns array of file results
|
|
282
269
|
if results and len(results) > 0:
|
|
283
270
|
issues = results[0].get("messages", [])
|
|
@@ -287,48 +274,51 @@ class LinterAgent(Agent):
|
|
|
287
274
|
|
|
288
275
|
return LinterResult(success=True, issues=[])
|
|
289
276
|
|
|
290
|
-
except
|
|
291
|
-
|
|
277
|
+
except CommandNotAllowedError as e:
|
|
278
|
+
self.logger.error(f"eslint command not allowed in sandbox: {e}")
|
|
279
|
+
return LinterResult(success=False, error="eslint command not allowed")
|
|
280
|
+
except SandboxTimeoutError:
|
|
281
|
+
return LinterResult(success=False, error="eslint execution timeout")
|
|
282
|
+
except Exception as e:
|
|
283
|
+
self.logger.error(f"Error running eslint in sandbox: {e}")
|
|
284
|
+
return LinterResult(success=False, error=str(e))
|
|
292
285
|
|
|
293
286
|
async def _auto_fix(self, linter: str, path: Path) -> LinterResult:
|
|
294
287
|
"""Attempt to auto-fix issues."""
|
|
295
288
|
try:
|
|
296
|
-
# Get
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
env = os.environ.copy()
|
|
300
|
-
venv_bin = Path(__file__).parent.parent.parent.parent / ".venv" / "bin"
|
|
301
|
-
if venv_bin.exists():
|
|
302
|
-
env["PATH"] = f"{venv_bin}:{env.get('PATH', '')}"
|
|
289
|
+
# Get venv path
|
|
290
|
+
venv_path = Path(__file__).parent.parent.parent.parent / ".venv"
|
|
303
291
|
|
|
304
292
|
if linter == "ruff":
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
293
|
+
if venv_path.exists():
|
|
294
|
+
await self.sandbox.run_sandboxed_with_venv(
|
|
295
|
+
["ruff", "check", "--fix", str(path)],
|
|
296
|
+
venv_path=venv_path,
|
|
297
|
+
cwd=path.parent,
|
|
298
|
+
)
|
|
299
|
+
else:
|
|
300
|
+
await self.sandbox.run_sandboxed(
|
|
301
|
+
["ruff", "check", "--fix", str(path)],
|
|
302
|
+
cwd=path.parent,
|
|
303
|
+
)
|
|
315
304
|
return LinterResult(success=True)
|
|
316
305
|
|
|
317
306
|
elif linter == "eslint":
|
|
318
|
-
|
|
319
|
-
"eslint",
|
|
320
|
-
|
|
321
|
-
str(path),
|
|
322
|
-
stdout=asyncio.subprocess.PIPE,
|
|
323
|
-
stderr=asyncio.subprocess.PIPE,
|
|
324
|
-
env=env,
|
|
307
|
+
await self.sandbox.run_sandboxed(
|
|
308
|
+
["eslint", "--fix", str(path)],
|
|
309
|
+
cwd=path.parent,
|
|
325
310
|
)
|
|
326
|
-
await proc.communicate()
|
|
327
311
|
return LinterResult(success=True)
|
|
328
312
|
|
|
329
313
|
return LinterResult(success=False, error="Auto-fix not supported")
|
|
330
314
|
|
|
315
|
+
except CommandNotAllowedError as e:
|
|
316
|
+
self.logger.error(f"Auto-fix command not allowed in sandbox: {e}")
|
|
317
|
+
return LinterResult(success=False, error="Auto-fix command not allowed")
|
|
318
|
+
except SandboxTimeoutError:
|
|
319
|
+
return LinterResult(success=False, error="Auto-fix execution timeout")
|
|
331
320
|
except Exception as e:
|
|
321
|
+
self.logger.error(f"Error during auto-fix in sandbox: {e}")
|
|
332
322
|
return LinterResult(success=False, error=str(e))
|
|
333
323
|
|
|
334
324
|
async def _write_findings_to_context(
|