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.
Files changed (67) hide show
  1. {devloop-0.2.1 → devloop-0.3.0}/PKG-INFO +97 -17
  2. {devloop-0.2.1 → devloop-0.3.0}/README.md +92 -16
  3. {devloop-0.2.1 → devloop-0.3.0}/pyproject.toml +11 -1
  4. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/__init__.py +1 -1
  5. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/linter.py +79 -89
  6. devloop-0.3.0/src/devloop/agents/sandbox_helper.py +231 -0
  7. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/type_checker.py +24 -14
  8. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/cli/commands/summary.py +27 -1
  9. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/cli/main.py +197 -12
  10. devloop-0.3.0/src/devloop/cli/pyodide_installer.py +132 -0
  11. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/config.py +146 -103
  12. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/context_store.py +40 -0
  13. devloop-0.3.0/src/devloop/core/operational_health.py +282 -0
  14. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/summary_formatter.py +13 -1
  15. devloop-0.3.0/src/devloop/security/__init__.py +15 -0
  16. devloop-0.3.0/src/devloop/security/audit_logger.py +263 -0
  17. devloop-0.3.0/src/devloop/security/bubblewrap_sandbox.py +352 -0
  18. devloop-0.3.0/src/devloop/security/cgroups_helper.py +253 -0
  19. devloop-0.3.0/src/devloop/security/factory.py +207 -0
  20. devloop-0.3.0/src/devloop/security/no_sandbox.py +146 -0
  21. devloop-0.3.0/src/devloop/security/package.json +19 -0
  22. devloop-0.3.0/src/devloop/security/pyodide_runner.js +290 -0
  23. devloop-0.3.0/src/devloop/security/pyodide_sandbox.py +271 -0
  24. devloop-0.3.0/src/devloop/security/sandbox.py +228 -0
  25. {devloop-0.2.1 → devloop-0.3.0}/LICENSE +0 -0
  26. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/__init__.py +0 -0
  27. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/agent_health_monitor.py +0 -0
  28. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/ci_monitor.py +0 -0
  29. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/code_rabbit.py +0 -0
  30. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/doc_lifecycle.py +0 -0
  31. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/echo.py +0 -0
  32. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/file_logger.py +0 -0
  33. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/formatter.py +0 -0
  34. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/git_commit_assistant.py +0 -0
  35. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/performance_profiler.py +0 -0
  36. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/security_scanner.py +0 -0
  37. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/snyk.py +0 -0
  38. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/agents/test_runner.py +0 -0
  39. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/cli/__init__.py +0 -0
  40. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/cli/commands/__init__.py +0 -0
  41. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/cli/commands/custom_agents.py +0 -0
  42. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/cli/commands/feedback.py +0 -0
  43. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/cli/main_v1.py +0 -0
  44. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/collectors/__init__.py +0 -0
  45. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/collectors/base.py +0 -0
  46. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/collectors/filesystem.py +0 -0
  47. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/collectors/git.py +0 -0
  48. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/collectors/manager.py +0 -0
  49. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/collectors/process.py +0 -0
  50. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/collectors/system.py +0 -0
  51. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/__init__.py +0 -0
  52. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/agent.py +0 -0
  53. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/agent_template.py +0 -0
  54. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/amp_integration.py +0 -0
  55. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/auto_fix.py +0 -0
  56. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/context.py +0 -0
  57. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/contextual_feedback.py +0 -0
  58. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/custom_agent.py +0 -0
  59. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/debug_trace.py +0 -0
  60. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/event.py +0 -0
  61. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/event_store.py +0 -0
  62. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/feedback.py +0 -0
  63. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/learning.py +0 -0
  64. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/manager.py +0 -0
  65. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/performance.py +0 -0
  66. {devloop-0.2.1 → devloop-0.3.0}/src/devloop/core/proactive_feedback.py +0 -0
  67. {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.2.1
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
  [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
40
44
  [![Tests Passing](https://img.shields.io/badge/tests-167%20passing-green.svg)](#testing)
41
- [![Production Ready](https://img.shields.io/badge/status-production%20ready-brightgreen.svg)](#status)
45
+ [![Alpha Release](https://img.shields.io/badge/status-alpha-orange.svg)](#status)
42
46
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](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
- **PRODUCTION READY** — Full-featured development automation system. [View detailed implementation status →](./IMPLEMENTATION_STATUS.md)
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 (handles everything automatically)
156
+ # 1. Initialize in your project (interactive setup)
102
157
  devloop init /path/to/your/project
103
158
  ```
104
159
 
105
- The `init` command automatically:
106
- - ✅ Sets up .devloop directory and configuration
107
- - ✅ Creates AGENTS.md and CODING_RULES.md
108
- - Sets up git hooks (if git repo)
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
- - ✅ Configures commit/push discipline enforcement
111
- - ✅ Verifies everything works
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": true,
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/agent.log
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
  [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
6
6
  [![Tests Passing](https://img.shields.io/badge/tests-167%20passing-green.svg)](#testing)
7
- [![Production Ready](https://img.shields.io/badge/status-production%20ready-brightgreen.svg)](#status)
7
+ [![Alpha Release](https://img.shields.io/badge/status-alpha-orange.svg)](#status)
8
8
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](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
- **PRODUCTION READY** — Full-featured development automation system. [View detailed implementation status →](./IMPLEMENTATION_STATUS.md)
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 (handles everything automatically)
118
+ # 1. Initialize in your project (interactive setup)
68
119
  devloop init /path/to/your/project
69
120
  ```
70
121
 
71
- The `init` command automatically:
72
- - ✅ Sets up .devloop directory and configuration
73
- - ✅ Creates AGENTS.md and CODING_RULES.md
74
- - Sets up git hooks (if git repo)
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
- - ✅ Configures commit/push discipline enforcement
77
- - ✅ Verifies everything works
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": true,
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/agent.log
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.2.1"
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,3 +1,3 @@
1
1
  """DevLoop - Background agents for development workflow automation."""
2
2
 
3
- __version__ = "0.2.0"
3
+ __version__ = "0.2.2"
@@ -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 updated environment with venv bin in PATH
202
- import os
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
- stdout, stderr = await proc.communicate()
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.decode())
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 FileNotFoundError:
249
- return LinterResult(success=False, error="ruff command not found")
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 installed
255
- check = await asyncio.create_subprocess_exec(
256
- "eslint",
257
- "--version",
258
- stdout=asyncio.subprocess.PIPE,
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
- stdout, stderr = await proc.communicate()
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.decode())
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 FileNotFoundError:
291
- return LinterResult(success=False, error="eslint command not found")
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 updated environment with venv bin in PATH
297
- import os
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
- proc = await asyncio.create_subprocess_exec(
306
- "ruff",
307
- "check",
308
- "--fix",
309
- str(path),
310
- stdout=asyncio.subprocess.PIPE,
311
- stderr=asyncio.subprocess.PIPE,
312
- env=env,
313
- )
314
- await proc.communicate()
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
- proc = await asyncio.create_subprocess_exec(
319
- "eslint",
320
- "--fix",
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(