From 7d3cf9bd610c43eb24f84e1f7423ca0308d81f61 Mon Sep 17 00:00:00 2001 From: "Rodrigo Rodriguez (Pragmatismo)" Date: Wed, 18 Mar 2026 10:50:39 -0300 Subject: [PATCH] docs: Add comprehensive bug fixing and feature addition workflows to AGENTS.md - Added detailed bug fixing workflow (6 steps: diagnose, find code, fix, test, commit, document) - Added feature addition workflow (6 steps: plan, implement, BASIC keywords, test, document, deploy) - Includes real examples from today's suggestion bug fix - Security checklists for new features - Testing patterns and commit message templates --- AGENTS.md | 350 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 350 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 269e25d..0055ff7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -358,6 +358,202 @@ After UI interactions, validate backend state via `psql` or `tail` logs. --- +## โž• Adding New Features Workflow + +### Step 1: Plan the Feature + +**Understand requirements:** +1. What problem does this solve? +2. Which module owns this functionality? (Check [Module Responsibility Matrix](../README.md#-module-responsibility-matrix)) +3. What data structures are needed? +4. What are the security implications? + +**Design checklist:** +- [ ] Does it fit existing architecture patterns? +- [ ] Will it require database migrations? +- [ ] Does it need new API endpoints? +- [ ] Will it affect existing features? +- [ ] What are the error cases? + +### Step 2: Implement the Feature + +**Follow the pattern:** +```rust +// 1. Add types to botlib if shared across crates +// botlib/src/models.rs +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct NewFeature { + pub id: Uuid, + pub name: String, +} + +// 2. Add database schema if needed +// botserver/migrations/YYYY-MM-DD-HHMMSS_feature_name/up.sql +CREATE TABLE new_features ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + name VARCHAR(255) NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +// 3. Add Diesel model +// botserver/src/core/shared/models/core.rs +#[derive(Queryable, Insertable)] +#[diesel(table_name = new_features)] +pub struct NewFeatureDb { + pub id: Uuid, + pub name: String, + pub created_at: DateTime, +} + +// 4. Add business logic +// botserver/src/features/new_feature.rs +pub async fn create_feature( + state: &AppState, + name: String, +) -> Result { + // Implementation +} + +// 5. Add API endpoint +// botserver/src/api/routes.rs +async fn create_feature_handler( + Extension(state): Extension>, + Json(payload): Json, +) -> Result, (StatusCode, String)> { + // Handler implementation +} +``` + +**Security checklist:** +- [ ] Input validation (use `sanitize_identifier` for SQL) +- [ ] Authentication required? +- [ ] Authorization checks? +- [ ] Rate limiting needed? +- [ ] Error messages sanitized? (use `log_and_sanitize`) +- [ ] No `unwrap()` or `expect()` in production code + +### Step 3: Add BASIC Keywords (if applicable) + +**For features accessible from .bas scripts:** +```rust +// botserver/src/basic/keywords/new_feature.rs +pub fn new_feature_keyword( + state: Arc, + user_session: UserSession, + engine: &mut Engine, +) { + let state_clone = state.clone(); + let session_clone = user_session.clone(); + + engine + .register_custom_syntax( + ["NEW_FEATURE", "$expr$"], + true, + move |context, inputs| { + let param = context.eval_expression_tree(&inputs[0])?.to_string(); + + // Call async function from sync context + let result = tokio::task::block_in_place(|| { + tokio::runtime::Handle::current().block_on(async { + create_feature(&state_clone, param).await + }) + }); + + match result { + Ok(feature) => Ok(Dynamic::from(feature.name)), + Err(e) => Err(format!("Failed: {}", e).into()), + } + }, + ) + .expect("valid syntax registration"); +} + +// Register in botserver/src/basic/keywords/mod.rs +pub mod new_feature; +pub use new_feature::new_feature_keyword; +``` + +### Step 4: Test the Feature + +**Local testing:** +```bash +# 1. Run migrations +diesel migration run + +# 2. Build and restart +./restart.sh + +# 3. Test via API +curl -X POST http://localhost:9000/api/features \ + -H "Content-Type: application/json" \ + -d '{"name": "test"}' + +# 4. Test via BASIC script +# Create test.bas in /opt/gbo/data/testbot.gbai/testbot.gbdialog/ +# NEW_FEATURE "test" + +# 5. Check logs +tail -f botserver.log | grep -i "new_feature" +``` + +**Integration test:** +```rust +// bottest/tests/new_feature_test.rs +#[tokio::test] +async fn test_create_feature() { + let state = setup_test_state().await; + let result = create_feature(&state, "test".to_string()).await; + assert!(result.is_ok()); +} +``` + +### Step 5: Document the Feature + +**Update documentation:** +- Add to `botbook/src/features/` if user-facing +- Add to module README.md if developer-facing +- Add inline code comments for complex logic +- Update API documentation + +**Example documentation:** +```markdown +## NEW_FEATURE Keyword + +Creates a new feature with the given name. + +**Syntax:** +```basic +NEW_FEATURE "feature_name" +``` + +**Example:** +```basic +NEW_FEATURE "My Feature" +TALK "Feature created!" +``` + +**Returns:** Feature name as string +``` + +### Step 6: Commit & Deploy + +**Commit pattern:** +```bash +git add . +git commit -m "feat: Add NEW_FEATURE keyword + +- Adds new_features table with migrations +- Implements create_feature business logic +- Adds NEW_FEATURE BASIC keyword +- Includes API endpoint at POST /api/features +- Tests: Unit tests for business logic, integration test for API" + +git push alm main +git push origin main +``` + +--- + ## ๐Ÿงช Testing Strategy ### Unit Tests @@ -420,6 +616,160 @@ When ANY error appears in logs during startup or operation: --- +## ๐Ÿ”ง Bug Fixing Workflow + +### Step 1: Reproduce & Diagnose + +**Identify the symptom:** +```bash +# Check recent errors +grep -E " E | W " botserver.log | tail -20 + +# Check specific component +grep "component_name" botserver.log | tail -50 + +# Monitor live +tail -f botserver.log | grep -E "ERROR|WARN" +``` + +**Trace the data flow:** +1. Find where the bug manifests (UI, API, database, cache) +2. Work backwards through the call chain +3. Check logs at each layer + +**Example: "Suggestions not showing"** +```bash +# 1. Check if frontend is requesting suggestions +grep "GET /api/suggestions" botserver.log | tail -5 + +# 2. Check if suggestions exist in cache +/opt/gbo/bin/botserver-stack/bin/cache/bin/valkey-cli --scan --pattern "suggestions:*" + +# 3. Check if suggestions are being generated +grep "ADD_SUGGESTION" botserver.log | tail -10 + +# 4. Verify the Redis key format +grep "Adding suggestion to Redis key" botserver.log | tail -5 +``` + +### Step 2: Find the Code + +**Use code search tools:** +```bash +# Find function/keyword implementation +cd botserver/src && grep -r "ADD_SUGGESTION_TOOL" --include="*.rs" + +# Find where Redis keys are constructed +grep -r "suggestions:" --include="*.rs" | grep format + +# Find struct definition +grep -r "pub struct UserSession" --include="*.rs" +``` + +**Check module responsibility:** +- Refer to [Module Responsibility Matrix](../README.md#-module-responsibility-matrix) +- Check `mod.rs` files for module structure +- Look for related functions in same file + +### Step 3: Fix the Bug + +**Identify root cause:** +- Wrong variable used? (e.g., `user_id` instead of `bot_id`) +- Missing validation? +- Race condition? +- Configuration issue? + +**Make minimal changes:** +```rust +// โŒ BAD: Rewrite entire function +fn add_suggestion(...) { + // 100 lines of new code +} + +// โœ… GOOD: Fix only the bug +fn add_suggestion(...) { + // Change line 318: + - let key = format!("suggestions:{}:{}", user_session.user_id, session_id); + + let key = format!("suggestions:{}:{}", user_session.bot_id, session_id); +} +``` + +**Search for similar bugs:** +```bash +# If you fixed user_id -> bot_id in one place, check all occurrences +grep -n "user_session.user_id" botserver/src/basic/keywords/add_suggestion.rs +``` + +### Step 4: Test Locally + +**Verify the fix:** +```bash +# 1. Build +cargo check -p botserver + +# 2. Restart +./restart.sh + +# 3. Test the specific feature +# - Open browser to http://localhost:3000/ +# - Trigger the bug scenario +# - Verify it's fixed + +# 4. Check logs for errors +tail -20 botserver.log | grep -E "ERROR|WARN" +``` + +### Step 5: Commit & Deploy + +**Commit with clear message:** +```bash +cd botserver +git add src/path/to/file.rs +git commit -m "Fix: Use bot_id instead of user_id in suggestion keys + +- Root cause: Wrong field used in Redis key format +- Impact: Suggestions stored under wrong key, frontend couldn't retrieve +- Files: src/basic/keywords/add_suggestion.rs (5 occurrences) +- Testing: Verified suggestions now appear in UI" +``` + +**Push to remotes:** +```bash +# Push submodule +git push alm main +git push origin main + +# Update root repository +cd .. +git add botserver +git commit -m "Update botserver: Fix suggestion key bug" +git push alm main +git push origin main +``` + +**Production deployment:** +- ALM push triggers CI/CD pipeline +- Wait ~10 minutes for build + deploy +- Service auto-restarts on binary update +- Test in production after deployment + +### Step 6: Document + +**Add to AGENTS-PROD.md if production-relevant:** +- Common symptom +- Diagnosis commands +- Fix procedure +- Prevention tips + +**Update code comments if needed:** +```rust +// Redis key format: suggestions:bot_id:session_id +// Note: Must use bot_id (not user_id) to match frontend queries +let key = format!("suggestions:{}:{}", user_session.bot_id, session_id); +``` + +--- + ## ๐ŸŽจ Frontend Standards ### HTMX-First Approach