mirror of
https://github.com/leonvanzyl/autocoder.git
synced 2026-01-30 06:12:06 +00:00
feat: increase command limit to 100 and add optimization guide
Changes: - Increase command limit from 50 to 100 per project - Add examples/OPTIMIZE_CONFIG.md with optimization strategies - Update all documentation references (50 → 100) - Update tests for new limit Rationale: - 50 was too restrictive for projects with many tools (Flutter, etc.) - Users were unknowingly exceeding limit by listing subcommands - 100 provides headroom while maintaining security - New guide teaches wildcard optimization (flutter* vs listing each subcommand) UI feedback idea: Show command count and optimization suggestions (tracked for Phase 3 or future enhancement)
This commit is contained in:
@@ -233,7 +233,7 @@ blocked_commands:
|
|||||||
- Scripts: `./scripts/build.sh` matches the script by name from any directory
|
- Scripts: `./scripts/build.sh` matches the script by name from any directory
|
||||||
|
|
||||||
**Limits:**
|
**Limits:**
|
||||||
- Maximum 50 commands per project config
|
- Maximum 100 commands per project config
|
||||||
- Blocklisted commands (sudo, dd, shutdown, etc.) can NEVER be allowed
|
- Blocklisted commands (sudo, dd, shutdown, etc.) can NEVER be allowed
|
||||||
- Org-level blocked commands cannot be overridden by project configs
|
- Org-level blocked commands cannot be overridden by project configs
|
||||||
|
|
||||||
|
|||||||
230
examples/OPTIMIZE_CONFIG.md
Normal file
230
examples/OPTIMIZE_CONFIG.md
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
# How to Optimize Your allowed_commands.yaml
|
||||||
|
|
||||||
|
## The Problem
|
||||||
|
|
||||||
|
Your config might have redundant commands like this:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
commands:
|
||||||
|
- name: flutter
|
||||||
|
- name: flutter* # ← This already covers EVERYTHING below!
|
||||||
|
- name: flutter test # ← Redundant
|
||||||
|
- name: flutter test --coverage # ← Redundant
|
||||||
|
- name: flutter build apk # ← Redundant
|
||||||
|
- name: flutter build ios # ← Redundant
|
||||||
|
# ... 20+ more flutter commands
|
||||||
|
```
|
||||||
|
|
||||||
|
**Result:** 65 commands when you only need ~10-15
|
||||||
|
|
||||||
|
## How Wildcards Work
|
||||||
|
|
||||||
|
When you have `flutter*`, it matches:
|
||||||
|
- ✅ `flutter` (the base command)
|
||||||
|
- ✅ `flutter test`
|
||||||
|
- ✅ `flutter test --coverage`
|
||||||
|
- ✅ `flutter build apk`
|
||||||
|
- ✅ `flutter build ios`
|
||||||
|
- ✅ `flutter run`
|
||||||
|
- ✅ **ANY command starting with "flutter"**
|
||||||
|
|
||||||
|
**You don't need to list every subcommand separately!**
|
||||||
|
|
||||||
|
## Example: GOD-APP Optimization
|
||||||
|
|
||||||
|
### Before (65 commands)
|
||||||
|
```yaml
|
||||||
|
commands:
|
||||||
|
# Flutter
|
||||||
|
- name: flutter
|
||||||
|
- name: flutter*
|
||||||
|
- name: flutter test
|
||||||
|
- name: flutter test --coverage
|
||||||
|
- name: flutter test --exclude-tags=golden,integration
|
||||||
|
- name: flutter test --tags=golden
|
||||||
|
- name: flutter test --tags=golden --update-goldens
|
||||||
|
- name: flutter test --verbose
|
||||||
|
- name: flutter drive
|
||||||
|
- name: flutter test integration_test/
|
||||||
|
- name: flutter build apk
|
||||||
|
- name: flutter build apk --debug
|
||||||
|
- name: flutter build apk --release
|
||||||
|
- name: flutter build appbundle
|
||||||
|
- name: flutter build ios
|
||||||
|
- name: flutter build ios --debug
|
||||||
|
- name: flutter build ipa
|
||||||
|
- name: flutter build web
|
||||||
|
- name: flutter pub get
|
||||||
|
- name: flutter pub upgrade
|
||||||
|
- name: flutter doctor
|
||||||
|
- name: flutter clean
|
||||||
|
# ... and more
|
||||||
|
|
||||||
|
# Dart
|
||||||
|
- name: dart
|
||||||
|
- name: dartfmt
|
||||||
|
- name: dartanalyzer
|
||||||
|
- name: dart format
|
||||||
|
- name: dart analyze
|
||||||
|
- name: dart fix
|
||||||
|
- name: dart pub
|
||||||
|
```
|
||||||
|
|
||||||
|
### After (15 commands) ✨
|
||||||
|
```yaml
|
||||||
|
commands:
|
||||||
|
# Flutter & Dart (wildcards cover all subcommands)
|
||||||
|
- name: flutter*
|
||||||
|
description: All Flutter SDK commands
|
||||||
|
|
||||||
|
- name: dart*
|
||||||
|
description: All Dart language tools
|
||||||
|
|
||||||
|
# Testing tools
|
||||||
|
- name: patrol
|
||||||
|
description: Patrol integration testing (if needed separately)
|
||||||
|
|
||||||
|
# Coverage tools
|
||||||
|
- name: lcov
|
||||||
|
description: Code coverage tool
|
||||||
|
|
||||||
|
- name: genhtml
|
||||||
|
description: Generate HTML coverage reports
|
||||||
|
|
||||||
|
# Android tools
|
||||||
|
- name: adb*
|
||||||
|
description: Android Debug Bridge commands
|
||||||
|
|
||||||
|
- name: gradle*
|
||||||
|
description: Gradle build system
|
||||||
|
|
||||||
|
# iOS tools (macOS only)
|
||||||
|
- name: xcrun*
|
||||||
|
description: Xcode developer tools
|
||||||
|
|
||||||
|
- name: xcodebuild
|
||||||
|
description: Xcode build system
|
||||||
|
|
||||||
|
- name: simctl
|
||||||
|
description: iOS Simulator control
|
||||||
|
|
||||||
|
- name: ios-deploy
|
||||||
|
description: Deploy to iOS devices
|
||||||
|
|
||||||
|
# Project scripts
|
||||||
|
- name: ./scripts/*.sh
|
||||||
|
description: All project build/test scripts
|
||||||
|
```
|
||||||
|
|
||||||
|
**Reduced from 65 → 15 commands (77% reduction!)**
|
||||||
|
|
||||||
|
## Optimization Checklist
|
||||||
|
|
||||||
|
For each group of commands, ask:
|
||||||
|
|
||||||
|
### ❓ "Do I have the base command AND a wildcard?"
|
||||||
|
```yaml
|
||||||
|
# Bad (redundant)
|
||||||
|
- name: flutter
|
||||||
|
- name: flutter*
|
||||||
|
|
||||||
|
# Good (just the wildcard)
|
||||||
|
- name: flutter*
|
||||||
|
```
|
||||||
|
|
||||||
|
The wildcard already matches the base command!
|
||||||
|
|
||||||
|
### ❓ "Am I listing subcommands individually?"
|
||||||
|
```yaml
|
||||||
|
# Bad (verbose)
|
||||||
|
- name: flutter test
|
||||||
|
- name: flutter test --coverage
|
||||||
|
- name: flutter build apk
|
||||||
|
- name: flutter run
|
||||||
|
|
||||||
|
# Good (one wildcard)
|
||||||
|
- name: flutter*
|
||||||
|
```
|
||||||
|
|
||||||
|
### ❓ "Can I group multiple scripts?"
|
||||||
|
```yaml
|
||||||
|
# If you can't use wildcards for scripts, at least group them logically
|
||||||
|
- name: ./scripts/test.sh
|
||||||
|
- name: ./scripts/build.sh
|
||||||
|
- name: ./scripts/integration_test.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
These are fine - scripts need explicit paths. But if you have 20+ scripts, consider if they're all necessary.
|
||||||
|
|
||||||
|
## Common Wildcards
|
||||||
|
|
||||||
|
| Instead of... | Use... | Covers |
|
||||||
|
|---------------|--------|--------|
|
||||||
|
| flutter, flutter test, flutter build, flutter run | `flutter*` | All flutter commands |
|
||||||
|
| dart, dart format, dart analyze, dart pub | `dart*` | All dart commands |
|
||||||
|
| npm, npm install, npm run, npm test | `npm*` | All npm commands |
|
||||||
|
| cargo, cargo build, cargo test, cargo run | `cargo*` | All cargo commands |
|
||||||
|
| git, git status, git commit, git push | Just `git` | Git is in global defaults |
|
||||||
|
|
||||||
|
## When NOT to Optimize
|
||||||
|
|
||||||
|
Keep separate entries when:
|
||||||
|
1. **Different base commands:** `swift` and `swiftc` are different (though `swift*` covers both)
|
||||||
|
2. **Documentation clarity:** Sometimes listing helps future developers understand what's needed
|
||||||
|
3. **Argument restrictions (Phase 3):** If you'll add argument validation later
|
||||||
|
|
||||||
|
## Quick Optimization Script
|
||||||
|
|
||||||
|
To see what you can reduce:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Count commands by prefix
|
||||||
|
grep "^ - name:" .autocoder/allowed_commands.yaml | \
|
||||||
|
sed 's/^ - name: //' | \
|
||||||
|
cut -d' ' -f1 | \
|
||||||
|
sort | uniq -c | sort -rn
|
||||||
|
```
|
||||||
|
|
||||||
|
If you see multiple commands with the same prefix, use a wildcard!
|
||||||
|
|
||||||
|
## UI Feedback (Future Enhancement)
|
||||||
|
|
||||||
|
Great suggestion! Here's what a UI could show:
|
||||||
|
|
||||||
|
```
|
||||||
|
⚠️ Config Optimization Available
|
||||||
|
|
||||||
|
Your config has 65 commands. We detected opportunities to reduce it:
|
||||||
|
|
||||||
|
• 25 flutter commands → Use flutter* (saves 24 entries)
|
||||||
|
• 8 dart commands → Use dart* (saves 7 entries)
|
||||||
|
• 12 adb commands → Use adb* (saves 11 entries)
|
||||||
|
|
||||||
|
[Optimize Automatically] [Keep As-Is]
|
||||||
|
|
||||||
|
Potential reduction: 65 → 23 commands
|
||||||
|
```
|
||||||
|
|
||||||
|
Or during config editing:
|
||||||
|
|
||||||
|
```
|
||||||
|
📊 Command Usage Stats
|
||||||
|
|
||||||
|
flutter* : 25 subcommands detected
|
||||||
|
dart* : 8 subcommands detected
|
||||||
|
./scripts/*.sh : 7 scripts detected
|
||||||
|
|
||||||
|
💡 Tip: Using wildcards covers all subcommands automatically
|
||||||
|
```
|
||||||
|
|
||||||
|
**This would be a great addition to Phase 3 or beyond!**
|
||||||
|
|
||||||
|
## Your GOD-APP Optimization
|
||||||
|
|
||||||
|
Here's what you could do:
|
||||||
|
|
||||||
|
**Current:** 65 commands (exceeds 50 limit, config rejected!)
|
||||||
|
|
||||||
|
**Optimized:** ~15 commands using wildcards
|
||||||
|
|
||||||
|
Would you like me to create an optimized version of your GOD-APP config?
|
||||||
@@ -72,7 +72,7 @@ commands:
|
|||||||
- ✅ Temporary tools needed during development
|
- ✅ Temporary tools needed during development
|
||||||
|
|
||||||
**Limits:**
|
**Limits:**
|
||||||
- Maximum 50 commands per project
|
- Maximum 100 commands per project
|
||||||
- Cannot override org-level blocked commands
|
- Cannot override org-level blocked commands
|
||||||
- Cannot allow hardcoded blocklist commands (sudo, dd, etc.)
|
- Cannot allow hardcoded blocklist commands (sudo, dd, etc.)
|
||||||
|
|
||||||
@@ -321,13 +321,13 @@ blocked_commands: [] # Rely on hardcoded blocklist only
|
|||||||
- Bad: Adding `xcodebuild` to org config when only one project uses it
|
- Bad: Adding `xcodebuild` to org config when only one project uses it
|
||||||
- Good: Add `xcodebuild` to that project's config
|
- Good: Add `xcodebuild` to that project's config
|
||||||
|
|
||||||
4. **Don't exceed the 50 command limit per project**
|
4. **Don't exceed the 100 command limit per project**
|
||||||
- If you need more, you're probably being too specific
|
- If you need more, you're probably listing subcommands unnecessarily
|
||||||
- Use wildcards instead: `npm-*` covers many npm tools
|
- Use wildcards instead: `flutter*` covers all flutter commands, not just the base
|
||||||
|
|
||||||
5. **Don't ignore validation errors**
|
5. **Don't ignore validation errors**
|
||||||
- If your YAML is rejected, fix the structure
|
- If your YAML is rejected, fix the structure
|
||||||
- Common issues: missing `version`, malformed lists, over 50 commands
|
- Common issues: missing `version`, malformed lists, over 100 commands
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ commands: []
|
|||||||
# - Scripts: "./scripts/build.sh" matches the script by name
|
# - Scripts: "./scripts/build.sh" matches the script by name
|
||||||
#
|
#
|
||||||
# Limits:
|
# Limits:
|
||||||
# - Maximum 50 commands per project
|
# - Maximum 100 commands per project
|
||||||
# - Commands in the blocklist (sudo, dd, shutdown, etc.) can NEVER be allowed
|
# - Commands in the blocklist (sudo, dd, shutdown, etc.) can NEVER be allowed
|
||||||
# - Org-level blocked commands (see ~/.autocoder/config.yaml) cannot be overridden
|
# - Org-level blocked commands (see ~/.autocoder/config.yaml) cannot be overridden
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -491,8 +491,8 @@ def load_project_commands(project_dir: Path) -> Optional[dict]:
|
|||||||
if not isinstance(commands, list):
|
if not isinstance(commands, list):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Enforce 50 command limit
|
# Enforce 100 command limit
|
||||||
if len(commands) > 50:
|
if len(commands) > 100:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Validate each command entry
|
# Validate each command entry
|
||||||
|
|||||||
@@ -263,8 +263,8 @@ commands:
|
|||||||
print(f" Got: {config}")
|
print(f" Got: {config}")
|
||||||
failed += 1
|
failed += 1
|
||||||
|
|
||||||
# Test 4: Over limit (50 commands)
|
# Test 4: Over limit (100 commands)
|
||||||
commands = [f" - name: cmd{i}\n description: Command {i}" for i in range(51)]
|
commands = [f" - name: cmd{i}\n description: Command {i}" for i in range(101)]
|
||||||
config_path.write_text("version: 1\ncommands:\n" + "\n".join(commands))
|
config_path.write_text("version: 1\ncommands:\n" + "\n".join(commands))
|
||||||
config = load_project_commands(project_dir)
|
config = load_project_commands(project_dir)
|
||||||
if config is None:
|
if config is None:
|
||||||
|
|||||||
@@ -326,21 +326,21 @@ def test_invalid_yaml_ignored():
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def test_50_command_limit():
|
def test_100_command_limit():
|
||||||
"""Test that configs with >50 commands are rejected."""
|
"""Test that configs with >100 commands are rejected."""
|
||||||
print("\n" + "=" * 70)
|
print("\n" + "=" * 70)
|
||||||
print("TEST 9: 50 command limit enforced")
|
print("TEST 9: 100 command limit enforced")
|
||||||
print("=" * 70)
|
print("=" * 70)
|
||||||
|
|
||||||
with tempfile.TemporaryDirectory() as tmpdir:
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
project_dir = Path(tmpdir)
|
project_dir = Path(tmpdir)
|
||||||
|
|
||||||
# Create config with 51 commands
|
# Create config with 101 commands
|
||||||
autocoder_dir = project_dir / ".autocoder"
|
autocoder_dir = project_dir / ".autocoder"
|
||||||
autocoder_dir.mkdir()
|
autocoder_dir.mkdir()
|
||||||
|
|
||||||
commands = [
|
commands = [
|
||||||
f" - name: cmd{i}\n description: Command {i}" for i in range(51)
|
f" - name: cmd{i}\n description: Command {i}" for i in range(101)
|
||||||
]
|
]
|
||||||
(autocoder_dir / "allowed_commands.yaml").write_text(
|
(autocoder_dir / "allowed_commands.yaml").write_text(
|
||||||
"version: 1\ncommands:\n" + "\n".join(commands)
|
"version: 1\ncommands:\n" + "\n".join(commands)
|
||||||
@@ -353,10 +353,10 @@ def test_50_command_limit():
|
|||||||
result = asyncio.run(bash_security_hook(input_data, context=context))
|
result = asyncio.run(bash_security_hook(input_data, context=context))
|
||||||
|
|
||||||
if result.get("decision") == "block":
|
if result.get("decision") == "block":
|
||||||
print("✅ PASS: Config with >50 commands rejected")
|
print("✅ PASS: Config with >100 commands rejected")
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
print("❌ FAIL: Config with >50 commands should be rejected")
|
print("❌ FAIL: Config with >100 commands should be rejected")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@@ -376,7 +376,7 @@ def main():
|
|||||||
test_org_blocklist_enforcement,
|
test_org_blocklist_enforcement,
|
||||||
test_org_allowlist_inheritance,
|
test_org_allowlist_inheritance,
|
||||||
test_invalid_yaml_ignored,
|
test_invalid_yaml_ignored,
|
||||||
test_50_command_limit,
|
test_100_command_limit,
|
||||||
]
|
]
|
||||||
|
|
||||||
passed = 0
|
passed = 0
|
||||||
|
|||||||
Reference in New Issue
Block a user