-
Notifications
You must be signed in to change notification settings - Fork 0
Release v6.2.0 #83
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Release v6.2.0 #83
Conversation
- Add /reset command to clear all Convergio memory (knowledge graph, notes, cache, databases, session history) - Increase max_tokens defaults to prevent response truncation: - flash: 2048 -> 4096 - concise: 4096 -> 8192 - balanced: 8192 -> 16384 (default) - detailed: 16384 -> 32768 - Fix workflow registry initialization by spawning agents lazily - Add nous_reset_fabric() function to clear in-memory semantic graph 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- New /reset command to clear all Convergio memory - Fixed response truncation by doubling max_tokens defaults - Fixed workflow registry agent lazy spawning Co-authored-by: Roberto D'Ambrosio with AI agent assistance
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR introduces version 6.2.0 with three main improvements: a new /reset command for clearing all Convergio memory, increased token limits to prevent response truncation, and a workflow registry refactor to implement agent lazy spawning.
- New
/resetcommand with confirmation prompt to clear all data (memory, notes, cache, databases, sessions) - Token limits increased across all response styles (flash: 4096, concise: 8192, balanced: 16384, detailed: 32768)
- Workflow registry refactored from stubs to functional in-memory storage with lazy agent initialization
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| VERSION | Version bump from 6.1.0 to 6.2.0 |
| CHANGELOG.md | Added release notes for v6.2.0 with new features and fixes |
| src/core/config.c | Increased max_tokens defaults for all response styles and updated comments |
| src/core/fabric.c | Added nous_reset_fabric() function to clear all in-memory semantic nodes |
| src/core/commands/commands_memory.c | Implemented new cmd_reset() function with confirmation and comprehensive cleanup |
| src/core/commands/workflow.c | Implemented workflow registry with in-memory storage and lazy agent spawning |
| src/core/commands/commands_internal.h | Added declaration for cmd_reset() |
| src/core/commands/command_dispatch.c | Registered the /reset command |
| src/core/commands/commands_help.c | Added detailed help text for /reset command |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (rex && paolo) { | ||
| Workflow* code_review = pattern_create_review_refine_loop( | ||
| rex->id, paolo->id, rex->id, 3); | ||
| if (code_review) { | ||
| if (code_review->name) free(code_review->name); | ||
| code_review->name = strdup("code-review"); | ||
| if (code_review->description) free(code_review->description); | ||
| code_review->description = strdup("Code review workflow: Rex reviews, Paolo checks best practices"); | ||
| code_review->workflow_id = 1; | ||
| if (g_workflow_registry.count < MAX_REGISTERED_WORKFLOWS) { | ||
| g_workflow_registry.workflows[g_workflow_registry.count++] = code_review; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Create architecture-review workflow | ||
| if (baccio && rex) { | ||
| Workflow* arch_review = pattern_create_review_refine_loop( | ||
| baccio->id, rex->id, baccio->id, 2); | ||
| if (arch_review) { | ||
| if (arch_review->name) free(arch_review->name); | ||
| arch_review->name = strdup("architecture-review"); | ||
| if (arch_review->description) free(arch_review->description); | ||
| arch_review->description = strdup("Architecture review: Baccio designs, Rex reviews for quality"); | ||
| arch_review->workflow_id = 2; | ||
| if (g_workflow_registry.count < MAX_REGISTERED_WORKFLOWS) { | ||
| g_workflow_registry.workflows[g_workflow_registry.count++] = arch_review; | ||
| } | ||
| } | ||
| } | ||
| } |
Copilot
AI
Dec 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Workflows registered in the workflow registry are never freed/destroyed. When workflows with dynamically allocated name and description strings are registered (lines 58-61, 74-77), there's no corresponding cleanup mechanism. This causes a memory leak that persists for the lifetime of the application. Consider implementing a cleanup function (e.g., workflow_registry_shutdown()) that properly frees all registered workflows.
| snprintf(cmd, sizeof(cmd), "rm -rf \"%s\"/* 2>/dev/null", notes_dir); | ||
| if (system(cmd) == 0) { | ||
| printf(" \033[32m✓\033[0m Cleared notes directory\n"); | ||
| } | ||
| } | ||
|
|
||
| // 3. Clear knowledge directory | ||
| if (knowledge_dir && knowledge_dir[0]) { | ||
| printf(" Clearing knowledge base...\n"); | ||
| snprintf(cmd, sizeof(cmd), "rm -rf \"%s\"/* 2>/dev/null", knowledge_dir); | ||
| if (system(cmd) == 0) { | ||
| printf(" \033[32m✓\033[0m Cleared knowledge directory\n"); | ||
| } | ||
| } | ||
|
|
||
| // 4. Clear cache directory | ||
| if (cache_dir && cache_dir[0]) { | ||
| printf(" Clearing cache...\n"); | ||
| snprintf(cmd, sizeof(cmd), "rm -rf \"%s\"/* 2>/dev/null", cache_dir); | ||
| if (system(cmd) == 0) { | ||
| printf(" \033[32m✓\033[0m Cleared cache directory\n"); | ||
| } | ||
| } | ||
|
|
||
| // 5. Clear plans database | ||
| if (config_dir && config_dir[0]) { | ||
| char plans_db[512]; | ||
| snprintf(plans_db, sizeof(plans_db), "%s/plans.db", config_dir); | ||
| printf(" Clearing execution plans...\n"); | ||
| if (remove(plans_db) == 0) { | ||
| printf(" \033[32m✓\033[0m Removed plans database\n"); | ||
| } else if (errno != ENOENT) { | ||
| printf(" \033[33m!\033[0m Could not remove plans.db: %s\n", strerror(errno)); | ||
| } | ||
|
|
||
| // 6. Clear voice history | ||
| char voice_db[512]; | ||
| snprintf(voice_db, sizeof(voice_db), "%s/voice_history.db", config_dir); | ||
| printf(" Clearing voice history...\n"); | ||
| if (remove(voice_db) == 0) { | ||
| printf(" \033[32m✓\033[0m Removed voice history database\n"); | ||
| } else if (errno != ENOENT) { | ||
| // Silently ignore - might not exist in all editions | ||
| } | ||
|
|
||
| // 7. Clear education database | ||
| char edu_db[512]; | ||
| snprintf(edu_db, sizeof(edu_db), "%s/education.db", config_dir); | ||
| printf(" Clearing education data...\n"); | ||
| if (remove(edu_db) == 0) { | ||
| printf(" \033[32m✓\033[0m Removed education database\n"); | ||
| } else if (errno != ENOENT) { | ||
| // Silently ignore - might not exist in non-edu editions | ||
| } | ||
|
|
||
| // 8. Clear outputs directory | ||
| char outputs_dir[512]; | ||
| snprintf(outputs_dir, sizeof(outputs_dir), "%s/outputs", config_dir); | ||
| printf(" Clearing generated outputs...\n"); | ||
| snprintf(cmd, sizeof(cmd), "rm -rf \"%s\"/* 2>/dev/null", outputs_dir); | ||
| system(cmd); | ||
| printf(" \033[32m✓\033[0m Cleared outputs directory\n"); | ||
|
|
||
| // 9. Clear session history | ||
| char sessions_dir[512]; | ||
| snprintf(sessions_dir, sizeof(sessions_dir), "%s/sessions", config_dir); | ||
| printf(" Clearing session history...\n"); | ||
| snprintf(cmd, sizeof(cmd), "rm -rf \"%s\"/* 2>/dev/null", sessions_dir); | ||
| system(cmd); | ||
| printf(" \033[32m✓\033[0m Cleared session history\n"); |
Copilot
AI
Dec 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using system() with user-controlled paths (from config) without proper input validation poses a security risk. While the paths come from config files, they could potentially contain shell metacharacters that could lead to command injection. Consider using safer alternatives like directory traversal with opendir()/readdir()/unlink() or at minimum, validate and sanitize the paths to ensure they don't contain shell metacharacters before passing to system().
| // ============================================================================ | ||
|
|
||
| // Style definitions - must match commands.c | ||
| // Token limits increased in v6.2.0 to prevent response truncation |
Copilot
AI
Dec 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment states "Balanced: 16384 tokens (was 8192)" but the old value shown in the diff was 4096, not 8192. Similarly, "Detailed: 32768 tokens (was 16384)" but the old value was 8192. "Concise: 8192 tokens (was 4096)" but the old value was 2048. The PR description also contains these same inaccurate "was" values. Please correct the comments to reflect the actual previous values.
| // Token limits increased in v6.2.0 to prevent response truncation | |
| // Token limits updated in v6.2.0 to prevent response truncation. | |
| // Previous limits: concise = 2048, balanced = 4096, detailed = 8192 tokens. |
| } else if (errno != ENOENT) { | ||
| printf(" \033[33m!\033[0m Could not remove %s: %s\n", db_path, strerror(errno)); | ||
| errors++; |
Copilot
AI
Dec 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code uses errno and strerror(errno) but doesn't include the necessary header file errno.h. This will cause a compilation error. Add #include <errno.h> to the includes section.
| // Reset workflow status for next execution | ||
| wf->status = WORKFLOW_STATUS_PENDING; | ||
| wf->current_node_id = 0; |
Copilot
AI
Dec 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Modifying workflow state (status and current_node_id) directly on shared workflow objects from the registry is not thread-safe. Multiple concurrent executions of the same workflow could race to modify these fields, leading to undefined behavior. Consider cloning the workflow before execution, or use proper synchronization mechanisms (locks) to protect the shared state.
| free(node->essence); | ||
| free(node->relations); | ||
| free(node->relation_strengths); | ||
| free(node); |
Copilot
AI
Dec 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ref_count of nodes is not checked before freeing in nous_reset_fabric(). If any threads are currently holding references to nodes (ref_count > 1), freeing them will cause use-after-free bugs. Consider checking ref_count before freeing, or adding a mechanism to prevent new references while reset is in progress.
| free(node->essence); | |
| free(node->relations); | |
| free(node->relation_strengths); | |
| free(node); | |
| // Drop the fabric's reference; only free if this was the last one | |
| unsigned int prev_ref = atomic_fetch_sub(&node->ref_count, 1); | |
| if (prev_ref == 1) { | |
| free(node->essence); | |
| free(node->relations); | |
| free(node->relation_strengths); | |
| free(node); | |
| } | |
| shard->nodes[j] = NULL; |
| static void workflow_registry_init(void) { | ||
| if (g_workflow_registry.initialized) { | ||
| return; | ||
| } | ||
| g_workflow_registry.initialized = true; | ||
| g_workflow_registry.count = 0; | ||
|
|
||
| // Register built-in workflow templates | ||
| extern Workflow* pattern_create_review_refine_loop(SemanticID, SemanticID, SemanticID, int); | ||
|
|
||
| // Try to find agents, spawning them if needed (lazy initialization) | ||
| ManagedAgent* rex = agent_find_by_name("rex"); | ||
| if (!rex) rex = agent_spawn(AGENT_ROLE_ANALYST, "rex", NULL); | ||
|
|
||
| ManagedAgent* paolo = agent_find_by_name("paolo"); | ||
| if (!paolo) paolo = agent_spawn(AGENT_ROLE_ANALYST, "paolo", NULL); | ||
|
|
||
| ManagedAgent* baccio = agent_find_by_name("baccio"); | ||
| if (!baccio) baccio = agent_spawn(AGENT_ROLE_ANALYST, "baccio", NULL); | ||
|
|
||
| // Create a simple code-review workflow template | ||
| if (rex && paolo) { | ||
| Workflow* code_review = pattern_create_review_refine_loop( | ||
| rex->id, paolo->id, rex->id, 3); | ||
| if (code_review) { | ||
| if (code_review->name) free(code_review->name); | ||
| code_review->name = strdup("code-review"); | ||
| if (code_review->description) free(code_review->description); | ||
| code_review->description = strdup("Code review workflow: Rex reviews, Paolo checks best practices"); | ||
| code_review->workflow_id = 1; | ||
| if (g_workflow_registry.count < MAX_REGISTERED_WORKFLOWS) { | ||
| g_workflow_registry.workflows[g_workflow_registry.count++] = code_review; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Create architecture-review workflow | ||
| if (baccio && rex) { | ||
| Workflow* arch_review = pattern_create_review_refine_loop( | ||
| baccio->id, rex->id, baccio->id, 2); | ||
| if (arch_review) { | ||
| if (arch_review->name) free(arch_review->name); | ||
| arch_review->name = strdup("architecture-review"); | ||
| if (arch_review->description) free(arch_review->description); | ||
| arch_review->description = strdup("Architecture review: Baccio designs, Rex reviews for quality"); | ||
| arch_review->workflow_id = 2; | ||
| if (g_workflow_registry.count < MAX_REGISTERED_WORKFLOWS) { | ||
| g_workflow_registry.workflows[g_workflow_registry.count++] = arch_review; | ||
| } | ||
| } | ||
| } | ||
| } |
Copilot
AI
Dec 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The workflow registry initialization is not thread-safe. Multiple threads calling workflow_registry_init() concurrently could result in race conditions where workflows are registered multiple times or the initialized flag is set before registration completes. Consider using atomic operations or a mutex to protect the initialization sequence.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
convergio-cli/src/core/commands/workflow.c
Lines 365 to 366 in 148fd4d
| workflow_destroy(wf); | |
| return result; |
With the new lazy registry (workflow_load_by_id now returns pointers stored in g_workflow_registry), cmd_workflow_resume still calls workflow_destroy(wf) after resuming. Invoking /workflow resume <id> will free the shared instance while the registry continues to hold its pointer, so later /workflow list or /workflow execute can dereference freed memory and crash. The resume handler should avoid destroying registry-managed workflows or operate on a cloned copy instead.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // Note: Don't destroy workflow from registry, it's shared | ||
| // Reset workflow status for next execution | ||
| wf->status = WORKFLOW_STATUS_PENDING; | ||
| wf->current_node_id = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clear workflow state before reusing cached instance
Workflows are now cached in the registry and cmd_workflow_execute no longer destroys them, only resetting status and current_node_id. prepare_workflow_execution leaves wf->state intact and workflow_execute returns the prior run’s state["output"] when the current run doesn’t set one. Executing a workflow multiple times—especially runs that pause or fail before writing output—will surface stale output from earlier executions, misleading users. Reset or clear the workflow state (or destroy/recreate) before reusing the cached workflow.
Useful? React with 👍 / 👎.
Updated SHA256 checksums for all editions: - Master: 9ce1b9fa7a0deccddc43957d5a1f433d91ce0a8f46a2a6eb9de855ac6bbe8ea1 - Education: fac2aa160dc9ec25b6d60159b1271616bbf394f65b4a9a501dd7cadc573db2ec - Business: 841948547c57b0a3165822950032ef525311686552847661c2adba35cbf4d9fc - Developer: 1afc072232d6aa5a01e62cee6eedba559b4ddc857165fe93c70401da1ffedf71
Summary
Release v6.2.0 with new features and fixes:
Added
Fixed
Response Truncation - Doubled max_tokens defaults for all response styles
Workflow Registry - Fixed agent lazy spawning
Test Plan
Generated with Claude Code