Skip to content

t1027: Refactor opencode-aidevops/index.mjs — reduce complexity, extract tools module#1349

Merged
marcusquinn merged 2 commits intomainfrom
feature/t1027
Feb 13, 2026
Merged

t1027: Refactor opencode-aidevops/index.mjs — reduce complexity, extract tools module#1349
marcusquinn merged 2 commits intomainfrom
feature/t1027

Conversation

@marcusquinn
Copy link
Owner

@marcusquinn marcusquinn commented Feb 13, 2026

Summary

Refactor .agents/plugins/opencode-aidevops/index.mjs to reduce complexity and improve maintainability.

Changes

  • Extract tool definitions into separate tools.mjs module (~180 lines moved out)
  • Deduplicate memory tools via createMemoryTool() factory pattern (memory_recall and memory_store shared 16 identical lines each)
  • Reduce registerMcpServers complexity: 44 → 6 (extracted shouldSkipMcp, buildMcpConfigEntry, registerSingleMcp, applyMcpToolPermissions, disableStaleOmocPatterns)
  • Reduce validateReturnStatements complexity: 39 → 13 (extracted matchFunctionDef, braceDepthDelta, hasReturnStatement, recordMissingReturn)
  • Reduce detectOhMyOpenCode complexity: 37 → 6 (extracted detectOmocInOpenCodeConfig, detectOmocConfigFiles, parseOmocConfig, finalizeOmocState, parseJsonc)
  • Reduce createTools complexity: 32 → 3 (moved to tools.mjs with dependency injection)
  • Reduce toolExecuteAfter complexity: 23 → 8 (extracted isBashTool, recordGitPattern, trackBashOperation)
  • Reduce toolExecuteBefore complexity: 19 → 10 (extracted isWriteOrEditTool, logQualityGateResult)
  • Remove unused relative import, consolidate os imports

Verification

  • node --check passes on both files
  • Runtime import test confirms plugin shape (config, tool, hooks, shell.env, compacting)
  • All 6 tools verified: correct description + execute function
  • ESLint cyclomatic complexity: no function over 20 (max 16)
  • Zero behaviour changes — pure structural refactoring

Ref #1347

Summary by CodeRabbit

  • New Features

    • Enhanced compatibility detection and management for OMOC integration.
    • Improved script quality tracking and validation for shell scripts.
  • Refactor

    • Reorganized plugin architecture for better tool management and modularity.
    • Improved MCP registration flow with centralized configuration handling.

… detectOhMyOpenCode, registerMcpServers, validateReturnStatements (t1027)

- Extract all 6 tool definitions from index.mjs into tools.mjs module
- Deduplicate memory_recall/memory_store via createMemoryTool() factory (16 lines each -> shared)
- Split detectOhMyOpenCode(37) into detectOmocInOpenCodeConfig, detectOmocConfigFiles, parseOmocConfig, finalizeOmocState
- Split registerMcpServers(44) into shouldSkipMcp, buildMcpConfigEntry, registerSingleMcp, applyMcpToolPermissions, disableStaleOmocPatterns
- Split validateReturnStatements(39) into matchFunctionDef, braceDepthDelta, hasReturnStatement, recordMissingReturn
- Add shared parseJsonc utility for JSONC comment stripping
- Remove unused relative import from path
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 13, 2026

Caution

Review failed

The pull request is closed.

Walkthrough

Refactored aidevops plugin to extract tool definitions into a new tools.mjs module, reorganizing OMOC detection and MCP registration logic into modular helpers, and enhancing quality gate tracking for shell/markdown/security checks while maintaining the existing AidevopsPlugin API.

Changes

Cohort / File(s) Summary
Plugin Core Refactoring
.agents/plugins/opencode-aidevops/index.mjs
Reorganized OMOC detection logic with new helpers (parseJsonc, detectOmocInOpenCodeConfig, finalizeOmocState). Refactored MCP registration flow using shouldSkipMcp, buildMcpConfigEntry, registerSingleMcp, applyMcpToolPermissions. Enhanced shell quality tracking with matchFunctionDef, braceDepthDelta, hasReturnStatement, recordMissingReturn. Centralized quality gating via logQualityGateResult. Tool definitions now imported from tools.mjs.
Tool Definitions Module
.agents/plugins/opencode-aidevops/tools.mjs
New module introducing createTools factory exporting aidevops, aidevops_memory_recall/store, aidevops_pre_edit_check, aidevops_quality_check, aidevops_install_hooks. Includes memory tool factory, quality check pipeline runners (shell/markdown/secrets), git hook installation helpers, and pre-commit pipeline execution with defensive error handling.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Poem

🔧 Tools once tangled, now in modular grace,
OMOC dances with MCPs in organized space,
Shell scripts audited with precision and care,
Quality gates stand sentinel everywhere,
A-grade DevOps, pristine and fair ✨

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/t1027

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 0 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Fri Feb 13 11:37:45 UTC 2026: Code review monitoring started
Fri Feb 13 11:37:46 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 0

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 0
  • VULNERABILITIES: 0

Generated on: Fri Feb 13 11:37:48 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

…1027)

- Extract isWriteOrEditTool, isBashTool helper predicates
- Extract logQualityGateResult for shared quality gate logging
- Extract recordGitPattern and trackBashOperation from toolExecuteAfter
- toolExecuteAfter: 23 -> 8 cyclomatic complexity
- toolExecuteBefore: 19 -> 10 cyclomatic complexity
- All functions now under 20 (max 16, eslint verified)
@github-actions
Copy link

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 0 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Fri Feb 13 11:40:49 UTC 2026: Code review monitoring started
Fri Feb 13 11:40:49 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 0

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 0
  • VULNERABILITIES: 0

Generated on: Fri Feb 13 11:40:52 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@marcusquinn marcusquinn marked this pull request as ready for review February 13, 2026 11:41
@gemini-code-assist
Copy link

Summary of Changes

Hello @marcusquinn, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request undertakes a significant refactoring of the opencode-aidevops/index.mjs plugin to improve its modularity, reduce complexity, and enhance maintainability. The primary strategy involved extracting various logical blocks, particularly tool definitions and complex utility functions, into smaller, more focused helper functions and a new tools.mjs module. This restructuring ensures that the plugin's core logic remains streamlined and easier to manage, without introducing any behavioral changes.

Highlights

  • Tool Definitions Extraction: All tool definitions were extracted from index.mjs into a new, dedicated tools.mjs module, significantly reducing the size and complexity of the main plugin file.
  • Complexity Reduction in detectOhMyOpenCode: The detectOhMyOpenCode function was refactored by extracting five helper functions (parseJsonc, detectOmocInOpenCodeConfig, parseOmocConfig, detectOmocConfigFiles, finalizeOmocState), reducing its cyclomatic complexity from 37 to 6.
  • Complexity Reduction in registerMcpServers: The registerMcpServers function was refactored by extracting five helper functions (shouldSkipMcp, buildMcpConfigEntry, registerSingleMcp, applyMcpToolPermissions, disableStaleOmocPatterns), reducing its cyclomatic complexity from 44 to 6.
  • Complexity Reduction in validateReturnStatements: The validateReturnStatements function was refactored by extracting four helper functions (matchFunctionDef, braceDepthDelta, hasReturnStatement, recordMissingReturn), reducing its cyclomatic complexity from 39 to 13.
  • Deduplication of Memory Tools: A createMemoryTool() factory pattern was introduced in tools.mjs to deduplicate the logic for aidevops_memory_recall and aidevops_memory_store, which previously shared 16 identical lines each.
  • Simplified toolExecuteBefore and toolExecuteAfter: The toolExecuteBefore and toolExecuteAfter hooks were simplified by extracting their internal logic into dedicated helper functions (isWriteOrEditTool, logQualityGateResult, isBashTool, recordGitPattern, trackBashOperation), improving readability and maintainability.
  • Import Cleanup: The index.mjs file had an unused relative import removed and os imports consolidated for better code hygiene.
Changelog
  • .agents/plugins/opencode-aidevops/index.mjs
    • Removed unused relative import and consolidated os imports.
    • Imported createTools from the new tools.mjs module.
    • Extracted parseJsonc, detectOmocInOpenCodeConfig, parseOmocConfig, detectOmocConfigFiles, and finalizeOmocState functions to modularize OMOC detection logic.
    • Extracted shouldSkipMcp, buildMcpConfigEntry, registerSingleMcp, applyMcpToolPermissions, and disableStaleOmocPatterns functions to simplify MCP server registration.
    • Extracted matchFunctionDef, braceDepthDelta, hasReturnStatement, and recordMissingReturn functions to reduce complexity in return statement validation.
    • Extracted isWriteOrEditTool and logQualityGateResult functions to simplify toolExecuteBefore logic.
    • Extracted isBashTool, recordGitPattern, and trackBashOperation functions to simplify toolExecuteAfter logic.
    • Removed the large, in-line createTools function, replacing it with a call to the external createTools function from tools.mjs.
  • .agents/plugins/opencode-aidevops/tools.mjs
    • Added a new module to encapsulate all tool definitions for the plugin.
    • Introduced createMemoryTool as a factory for aidevops_memory_recall and aidevops_memory_store to reduce code duplication.
    • Created dedicated factory functions (createAidevopsTool, createPreEditCheckTool, createQualityCheckTool, createInstallHooksTool) for each tool.
    • Included helper functions like runPreCommitPipeline, formatQualityResult, runHookHelper, and installGitHookFallback to support tool logic.
    • Exported a main createTools function that orchestrates the creation of all tools, accepting necessary dependencies via arguments.
Activity
  • No human activity has been recorded on this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@sonarqubecloud
Copy link

@marcusquinn marcusquinn merged commit 9086f95 into main Feb 13, 2026
9 of 11 checks passed
@marcusquinn marcusquinn deleted the feature/t1027 branch February 13, 2026 11:42
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request is an excellent refactoring effort that significantly reduces complexity and improves the maintainability of the opencode-aidevops plugin by extracting helper functions and a dedicated tools.mjs module. The use of dependency injection for the tools is a great pattern.

However, the review identified several critical command injection vulnerabilities in the newly created tools.mjs file where user-provided arguments (from an LLM) are used to construct shell commands. These must be addressed. I've also included a couple of minor suggestions to improve code clarity.

Comment on lines +71 to +86
const taskFlag = args.task
? ` --loop-mode --task "${args.task}"`
: "";
try {
const result = execSync(`bash "${script}"${taskFlag}`, {
encoding: "utf-8",
timeout: 10000,
stdio: ["pipe", "pipe", "pipe"],
});
return `Pre-edit check PASSED (exit 0):\n${result.trim()}`;
} catch (err) {
const code = err.status || 1;
const cmdOutput = (err.stdout || "") + (err.stderr || "");
return `Pre-edit check exit ${code}: ${PRE_EDIT_GUIDANCE[code] || "Unknown"}\n${cmdOutput.trim()}`;
}
},

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

Constructing a shell command by concatenating strings with user input is vulnerable to command injection. An attacker could craft args.task to break out of the quotes and execute arbitrary commands. To fix this, use the array-based version of execSync to pass arguments, which avoids shell interpretation.

      try {
        const execArgs = [script];
        if (args.task) {
          execArgs.push("--loop-mode", "--task", args.task);
        }
        const result = execSync("bash", execArgs, {
          encoding: "utf-8",
          timeout: 10000,
          stdio: ["pipe", "pipe", "pipe"],
        });
        return `Pre-edit check PASSED (exit 0):\n${result.trim()}`;
      } catch (err) {
        const code = err.status || 1;
        const cmdOutput = (err.stdout || "") + (err.stderr || "");
        return `Pre-edit check exit ${code}: ${PRE_EDIT_GUIDANCE[code] || "Unknown"}\n${cmdOutput.trim()}`;
      }

Comment on lines +171 to +184
try {
const result = execSync(
`bash "${helperScript}" ${action}`,
{
encoding: "utf-8",
timeout: 15000,
stdio: ["pipe", "pipe", "pipe"],
},
);
return result.trim();
} catch (err) {
const cmdOutput = (err.stdout || "") + (err.stderr || "");
return `Hook ${action} failed:\n${cmdOutput.trim()}`;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The action argument is interpolated into the shell command without quoting or validation, creating a command injection vulnerability. The fix is to validate the action against an allowlist and use the array-based execSync signature to prevent shell interpretation.

  const ALLOWED_ACTIONS = ["install", "uninstall", "status", "test"];
  if (!ALLOWED_ACTIONS.includes(action)) {
    return `Invalid action: "${action}". Must be one of: ${ALLOWED_ACTIONS.join(", ")}`;
  }
  try {
    const result = execSync("bash", [helperScript, action], {
      encoding: "utf-8",
      timeout: 15000,
      stdio: ["pipe", "pipe", "pipe"],
    });
    return result.trim();
  } catch (err) {
    const cmdOutput = (err.stdout || "") + (err.stderr || "");
    return `Hook ${action} failed:\n${cmdOutput.trim()}`;
  }

* @param {function} pipelines.scanForSecrets
* @returns {Record<string, object>}
*/
export function createTools(scriptsDir, run, pipelines) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

Multiple tools created in this function are vulnerable to command injection because they use the run function with a command string constructed with unsanitized user input. This is a critical security risk.

Vulnerable tools and arguments:

  • aidevops: args.command or args
  • aidevops_memory_recall: args.query
  • aidevops_memory_store: args.content

An attacker (or a compromised LLM) could provide a malicious string like status; rm -rf / or foo $(rm -rf /) to execute arbitrary commands.

Recommendation:
The run function should be refactored to accept arguments safely, without shell interpretation. The ideal way is to use an array-based API for executing commands, similar to Node.js's execFile or spawn. The tool definitions should then be updated to pass arguments as an array. For example: run('bash', [helper, 'recall', args.query, ...]).

Comment on lines +1157 to +1159
function isWriteOrEditTool(tool) {
return tool === "Write" || tool === "Edit" || tool === "write" || tool === "edit";
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This check can be simplified by converting the input to a consistent case first, which makes it more robust and easier to read.

Suggested change
function isWriteOrEditTool(tool) {
return tool === "Write" || tool === "Edit" || tool === "write" || tool === "edit";
}
function isWriteOrEditTool(tool) {
const lowerTool = tool.toLowerCase();
return lowerTool === "write" || lowerTool === "edit";
}

Comment on lines +1219 to +1221
function isBashTool(tool) {
return tool === "Bash" || tool === "bash";
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This check can be simplified by converting the input to lowercase first.

Suggested change
function isBashTool(tool) {
return tool === "Bash" || tool === "bash";
}
function isBashTool(tool) {
return tool.toLowerCase() === "bash";
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant