t008.1: Core plugin structure + agent loader#1138
Conversation
…alidation (t008.1) Shell-based plugin loader that discovers installed plugins, validates plugin.json manifests, loads agent definitions, manages lifecycle hooks (init/load/unload), and generates TOON entries for the subagent-index. Chose directory scanning fallback over manifest-only approach to maintain backward compatibility with existing plugins that lack plugin.json.
- Add plugin.json manifest template with agents, hooks, and dependency fields - Add lifecycle hook templates (on-init.sh, on-load.sh, on-unload.sh) - Integrate hooks into aidevops.sh plugin add/enable/disable/remove commands - Update plugins.md with manifest format, agent loader, and hooks documentation - Update plugin init scaffolding to include manifest and hook scripts - Fix ShellCheck: remove unused RESERVED_NAMESPACES, add SC2034 directives for template vars
WalkthroughThis pull request implements a comprehensive plugin lifecycle management system for the AI DevOps framework, adding manifest-driven plugin definition, lifecycle hooks (init/load/unload), and a plugin-loader helper script that handles plugin discovery, validation, agent loading, and hook execution. It also integrates lifecycle hooks into the main CLI and provides template scripts for plugins. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant aidevops.sh
participant plugin-loader-helper.sh
participant Plugin Manifest
participant Lifecycle Hooks
User->>aidevops.sh: cmd_plugin init <namespace>
activate aidevops.sh
aidevops.sh->>aidevops.sh: Scaffold plugin.json & scripts/
aidevops.sh->>plugin-loader-helper.sh: plugin-loader-helper.sh hooks init
deactivate aidevops.sh
activate plugin-loader-helper.sh
plugin-loader-helper.sh->>Plugin Manifest: Read plugin.json
plugin-loader-helper.sh->>Lifecycle Hooks: Execute on-init.sh
Lifecycle Hooks-->>plugin-loader-helper.sh: Hook complete
plugin-loader-helper.sh-->>aidevops.sh: Return status
deactivate plugin-loader-helper.sh
User->>aidevops.sh: cmd_plugin enable <namespace>
activate aidevops.sh
aidevops.sh->>plugin-loader-helper.sh: plugin-loader-helper.sh hooks init
plugin-loader-helper.sh->>Lifecycle Hooks: Execute on-init.sh
Lifecycle Hooks-->>User: Initialization complete
deactivate aidevops.sh
User->>aidevops.sh: cmd_plugin remove <namespace>
activate aidevops.sh
aidevops.sh->>plugin-loader-helper.sh: plugin-loader-helper.sh hooks unload
activate plugin-loader-helper.sh
plugin-loader-helper.sh->>Lifecycle Hooks: Execute on-unload.sh
Lifecycle Hooks-->>plugin-loader-helper.sh: Cleanup complete
plugin-loader-helper.sh-->>aidevops.sh: Return status
deactivate plugin-loader-helper.sh
aidevops.sh->>aidevops.sh: Remove plugin directory
aidevops.sh-->>User: Plugin removed
deactivate aidevops.sh
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
🔍 Code Quality Report�[0;35m[MONITOR]�[0m Code Review Monitoring Report �[0;34m[INFO]�[0m Latest Quality Status: �[0;34m[INFO]�[0m Recent monitoring activity: 📈 Current Quality Metrics
Generated on: Wed Feb 11 15:03:20 UTC 2026 Generated by AI DevOps Framework Code Review Monitoring |
🔍 Code Quality Report�[0;35m[MONITOR]�[0m Code Review Monitoring Report �[0;34m[INFO]�[0m Latest Quality Status: �[0;34m[INFO]�[0m Recent monitoring activity: 📈 Current Quality Metrics
Generated on: Wed Feb 11 15:06:12 UTC 2026 Generated by AI DevOps Framework Code Review Monitoring |
Summary of ChangesHello @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 significantly enhances the Highlights
Changelog
Activity
Using Gemini Code AssistThe 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
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 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
|
|
There was a problem hiding this comment.
Code Review
This pull request introduces a robust plugin architecture with manifests and lifecycle hooks, which is a great enhancement for the framework's extensibility. The new plugin-loader-helper.sh script is comprehensive and the integration into aidevops.sh is well-handled. The documentation and template updates are also thorough.
My review focuses on adherence to the repository's shell scripting style guide and improving error visibility. The identified areas for improvement, concerning logging function duplication, regex for semver validation, and error suppression when running hooks, remain valid and will improve maintainability and debugging for plugin developers.
| log_info() { | ||
| local msg="$1" | ||
| echo -e "${BLUE:-}[plugin-loader]${NC:-} $msg" | ||
| return 0 | ||
| } | ||
|
|
||
| log_success() { | ||
| local msg="$1" | ||
| echo -e "${GREEN:-}[OK]${NC:-} $msg" | ||
| return 0 | ||
| } | ||
|
|
||
| log_warning() { | ||
| local msg="$1" | ||
| echo -e "${YELLOW:-}[WARN]${NC:-} $msg" | ||
| return 0 | ||
| } | ||
|
|
||
| log_error() { | ||
| local msg="$1" | ||
| echo -e "${RED:-}[ERROR]${NC:-} $msg" | ||
| return 0 | ||
| } |
There was a problem hiding this comment.
These log_* functions duplicate the functionality of the print_* functions available from shared-constants.sh, which is sourced on line 27. The repository style guide advises against duplicating these functions to improve maintainability.
Please remove these local log_* functions and use the shared print_* functions instead. You can achieve the same output by prepending the prefix to the message, for example: print_info "[plugin-loader] Discovering plugins...".
References
- The style guide specifies that scripts should source
shared-constants.shfor common functions likeprint_infoandprint_error, and explicitly states not to duplicate them (lines 18-19). The newlog_*functions are duplicates of this functionality. (link) - Rule: For standalone shell scripts, it is acceptable to duplicate simple, self-contained helper functions instead of introducing
sourcedependencies. This comment is valid because the scriptplugin-loader-helper.shalready sourcesshared-constants.shon line 27, meaning it is not a standalone script in the context of avoidingsourcedependencies. Therefore, the rationale for allowing duplication (maintaining script independence) does not apply, and the existing style guide advice against duplication for maintainability remains relevant.
| fi | ||
|
|
||
| # Validate version format (semver-like) | ||
| if [[ -n "$version" ]] && [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]; then |
There was a problem hiding this comment.
The current regex for semver validation does not allow for hyphens in the pre-release identifier (e.g., 1.0.0-beta-1), which is valid according to the SemVer specification. Please update the regex to include hyphens in the character class to ensure correct validation.
| if [[ -n "$version" ]] && [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]; then | |
| if [[ -n "$version" ]] && [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?$ ]]; then |
| fi | ||
|
|
||
| # Run init hook if available | ||
| run_hook "$target" "init" 2>/dev/null || true |
There was a problem hiding this comment.
Suppressing stderr with 2>/dev/null can hide important error messages from the hook script, making debugging difficult. The repository style guide (line 50) discourages blanket suppression of errors. The || true guard is sufficient to prevent the main script from exiting on a hook failure.
Please remove the 2>/dev/null to allow hook errors to be visible. This also applies to lines 439, 458, and 471.
| run_hook "$target" "init" 2>/dev/null || true | |
| run_hook "$target" "init" || true |
References
- The style guide states that
2>/dev/nullis only acceptable when redirecting to log files, not for blanket suppression of errors (line 50). Suppressing stderr from hook scripts can hide important debugging information. (link)
| # Run init hook via plugin-loader if available | ||
| local loader_script="$agents_dir/scripts/plugin-loader-helper.sh" | ||
| if [[ -f "$loader_script" ]]; then | ||
| bash "$loader_script" hooks "$namespace" init 2>/dev/null || true |
There was a problem hiding this comment.
Suppressing stderr with 2>/dev/null can hide important error messages from the hook script, making debugging difficult. The repository style guide (line 50) discourages blanket suppression of errors. The || true guard is sufficient to prevent the main script from exiting on a hook failure.
Please remove the 2>/dev/null to allow hook errors to be visible. This applies to other similar calls in this file (lines 2378, 2401, 2433).
| bash "$loader_script" hooks "$namespace" init 2>/dev/null || true | |
| bash "$loader_script" hooks "$namespace" init || true |
References
- The style guide states that
2>/dev/nullis only acceptable when redirecting to log files, not for blanket suppression of errors (line 50). Suppressing stderr from hook scripts can hide important debugging information. (link)
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
.agents/aidevops/plugins.md (1)
220-225:⚠️ Potential issue | 🟡 MinorDocumentation inconsistency: hooks are now auto-executed on lifecycle events.
Line 223 states "Plugin scripts are NOT auto-executed; they must be explicitly invoked," but the new integration in
aidevops.sh(lines 2242–2246, 2375–2379, 2398–2402, 2430–2434) auto-runs init/unload hooks onplugin add,enable,disable, andremove. This security note should be updated to reflect that lifecycle hooks are executed automatically, while other plugin scripts remain explicitly invoked.aidevops.sh (1)
2296-2306:⚠️ Potential issue | 🟠 MajorMissing lifecycle hooks in the
updateflow.The documentation (
plugins.mdline 208) states theinithook runs on "Install, update, enable," but theupdatecase here re-clones the plugin directory without invoking any lifecycle hooks. Afterrm -rf+git clone, neither theinitnorloadhook is called — unlikeaddandenablewhich both triggerinit.Consider adding the same hook invocation after a successful update:
Proposed fix
if git clone --branch "$branch_name" --depth 1 "$repo" "$clone_dir" 2>&1; then rm -rf "$clone_dir/.git" + # Run init hook after update + local loader_script="$agents_dir/scripts/plugin-loader-helper.sh" + if [[ -f "$loader_script" ]]; then + bash "$loader_script" hooks "$ns" init 2>/dev/null || true + fi print_success "Plugin '$target' updated"The same pattern should be applied inside the bulk-update loop (around line 2329).
🤖 Fix all issues with AI agents
In @.agents/scripts/plugin-loader-helper.sh:
- Around line 269-284: The version check currently reads current_version from
"$HOME/.aidevops/version" which doesn't exist; update the logic that sets
current_version to read the correct VERSION file used by the framework (use the
same source as VERSION_FILE/AGENTS_DIR used elsewhere) — replace the fallback
path with reading either "$HOME/Git/aidevops/VERSION" or "$AGENTS_DIR/VERSION"
(whichever matches the deployed environment), preserving the existing default
fallback of "0.0.0"; ensure the variables min_version and current_version and
the subsequent comparison logic in the plugin loader helper remain unchanged so
log_warning still triggers correctly when current_version is less than
min_version.
- Around line 413-441: The cmd_load function is incorrectly invoking the init
hook on every call; remove the run_hook "$target" "init" invocations from
cmd_load (both the single-target path and the bulk-load loop) so only the load
hook is run during session loads; keep the run_hook "$target" "load" calls
intact, and ensure any init invocation remains only in install/update/enable
flows (not in cmd_load) to match the documented plugin lifecycle.
In @.agents/subagent-index.toon:
- Line 90: Update the TOON header count to match actual entries: replace the
header token "TOON:scripts[74]" with "TOON:scripts[76]" so the declared script
count equals the 76 script entries present (lines following the header under the
TOON:scripts block).
In @.agents/templates/plugin-template/plugin.json:
- Around line 14-17: The subagent "name" field in plugin.json is too generic
("name": "example") and may collide with other plugins; update the "name"
property to a namespaced identifier that includes the package/namespace (e.g.,
use the same namespace token as the "file" field like "{{NAMESPACE}}/example" or
"{{NAMESPACE}}-example") so the subagent name is unique across shared indexes;
change the value of the "name" key in plugin.json accordingly.
🧹 Nitpick comments (1)
.agents/scripts/plugin-loader-helper.sh (1)
97-107:get_plugin_fieldlacksjqavailability check unlike sibling functions.
get_enabled_namespacesandget_all_namespacesboth guard against missingjq, butget_plugin_fielddirectly callsjqwithout checking. The|| echo ""on line 105 catches the failure, but it produces a stderr error message (suppressed by2>/dev/nullon the jq call itself). This works but is inconsistent with the defensive pattern used elsewhere.Optional: add jq guard for consistency
get_plugin_field() { local namespace="$1" local field="$2" if [[ ! -f "$PLUGINS_FILE" ]]; then return 0 fi + if ! command -v jq &>/dev/null; then + return 0 + fi jq -r --arg ns "$namespace" --arg f "$field" \
| # Validate min_version if present | ||
| local min_version | ||
| min_version=$(jq -r '.min_aidevops_version // empty' "$manifest" 2>/dev/null) | ||
| if [[ -n "$min_version" ]]; then | ||
| local current_version | ||
| current_version=$(cat "$HOME/.aidevops/version" 2>/dev/null || echo "0.0.0") | ||
| # Simple version comparison (major.minor only) | ||
| local min_major min_minor cur_major cur_minor | ||
| min_major=$(echo "$min_version" | cut -d. -f1) | ||
| min_minor=$(echo "$min_version" | cut -d. -f2) | ||
| cur_major=$(echo "$current_version" | cut -d. -f1) | ||
| cur_minor=$(echo "$current_version" | cut -d. -f2) | ||
| if [[ "$cur_major" -lt "$min_major" ]] || { [[ "$cur_major" -eq "$min_major" ]] && [[ "$cur_minor" -lt "$min_minor" ]]; }; then | ||
| log_warning "Plugin requires aidevops >= $min_version (current: $current_version)" | ||
| fi | ||
| fi |
There was a problem hiding this comment.
Wrong version file path — version check will always fall back to 0.0.0.
Line 274 reads the current version from $HOME/.aidevops/version, but the framework stores its version at $HOME/Git/aidevops/VERSION (per VERSION_FILE in aidevops.sh line 26) or $AGENTS_DIR/VERSION (the deployed agents version). The file $HOME/.aidevops/version likely never exists, so current_version will always be "0.0.0", effectively making the min_aidevops_version check a no-op (it will always warn).
Proposed fix
if [[ -n "$min_version" ]]; then
local current_version
- current_version=$(cat "$HOME/.aidevops/version" 2>/dev/null || echo "0.0.0")
+ current_version=$(cat "$AGENTS_DIR/VERSION" 2>/dev/null || echo "0.0.0")🤖 Prompt for AI Agents
In @.agents/scripts/plugin-loader-helper.sh around lines 269 - 284, The version
check currently reads current_version from "$HOME/.aidevops/version" which
doesn't exist; update the logic that sets current_version to read the correct
VERSION file used by the framework (use the same source as
VERSION_FILE/AGENTS_DIR used elsewhere) — replace the fallback path with reading
either "$HOME/Git/aidevops/VERSION" or "$AGENTS_DIR/VERSION" (whichever matches
the deployed environment), preserving the existing default fallback of "0.0.0";
ensure the variables min_version and current_version and the subsequent
comparison logic in the plugin loader helper remain unchanged so log_warning
still triggers correctly when current_version is less than min_version.
| # Load all enabled plugin agents | ||
| cmd_load() { | ||
| local target="${1:-}" | ||
|
|
||
| if [[ -n "$target" ]]; then | ||
| if ! is_valid_plugin "$target"; then | ||
| log_error "Plugin '$target' not found or not registered" | ||
| return 1 | ||
| fi | ||
|
|
||
| # Run init hook if available | ||
| run_hook "$target" "init" 2>/dev/null || true | ||
|
|
||
| local agents | ||
| agents=$(load_plugin_agents "$target") | ||
| if [[ -z "$agents" ]]; then | ||
| log_info "No agents found in plugin '$target'" | ||
| return 0 | ||
| fi | ||
|
|
||
| log_success "Loaded agents from '$target':" | ||
| echo "$agents" | while IFS=$'\t' read -r name file desc model; do | ||
| printf " %-20s %-30s %s\n" "$name" "$file" "$desc" | ||
| done | ||
|
|
||
| # Run load hook if available | ||
| run_hook "$target" "load" 2>/dev/null || true | ||
| return 0 | ||
| fi |
There was a problem hiding this comment.
cmd_load incorrectly runs init hook on every invocation.
Lines 424 and 458 run run_hook "$target" "init" each time cmd_load is called. Per the documented semantics (plugins.md line 208), the init hook should run on "Install, update, enable" — not on every session load. The load hook (line 439/471) is the correct one for session-start loading.
Running init on every load could re-execute one-time setup logic (e.g., creating config directories, checking dependencies) unnecessarily, and diverges from what plugin authors will expect from the lifecycle contract.
Proposed fix — remove init hook calls from cmd_load
if [[ -n "$target" ]]; then
if ! is_valid_plugin "$target"; then
log_error "Plugin '$target' not found or not registered"
return 1
fi
- # Run init hook if available
- run_hook "$target" "init" 2>/dev/null || true
-
local agents
agents=$(load_plugin_agents "$target")And in the bulk-load loop:
while IFS= read -r ns; do
[[ -z "$ns" ]] && continue
- # Run init hook
- run_hook "$ns" "init" 2>/dev/null || true
-
local agents
agents=$(load_plugin_agents "$ns")📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| # Load all enabled plugin agents | |
| cmd_load() { | |
| local target="${1:-}" | |
| if [[ -n "$target" ]]; then | |
| if ! is_valid_plugin "$target"; then | |
| log_error "Plugin '$target' not found or not registered" | |
| return 1 | |
| fi | |
| # Run init hook if available | |
| run_hook "$target" "init" 2>/dev/null || true | |
| local agents | |
| agents=$(load_plugin_agents "$target") | |
| if [[ -z "$agents" ]]; then | |
| log_info "No agents found in plugin '$target'" | |
| return 0 | |
| fi | |
| log_success "Loaded agents from '$target':" | |
| echo "$agents" | while IFS=$'\t' read -r name file desc model; do | |
| printf " %-20s %-30s %s\n" "$name" "$file" "$desc" | |
| done | |
| # Run load hook if available | |
| run_hook "$target" "load" 2>/dev/null || true | |
| return 0 | |
| fi | |
| # Load all enabled plugin agents | |
| cmd_load() { | |
| local target="${1:-}" | |
| if [[ -n "$target" ]]; then | |
| if ! is_valid_plugin "$target"; then | |
| log_error "Plugin '$target' not found or not registered" | |
| return 1 | |
| fi | |
| local agents | |
| agents=$(load_plugin_agents "$target") | |
| if [[ -z "$agents" ]]; then | |
| log_info "No agents found in plugin '$target'" | |
| return 0 | |
| fi | |
| log_success "Loaded agents from '$target':" | |
| echo "$agents" | while IFS=$'\t' read -r name file desc model; do | |
| printf " %-20s %-30s %s\n" "$name" "$file" "$desc" | |
| done | |
| # Run load hook if available | |
| run_hook "$target" "load" 2>/dev/null || true | |
| return 0 | |
| fi |
🤖 Prompt for AI Agents
In @.agents/scripts/plugin-loader-helper.sh around lines 413 - 441, The cmd_load
function is incorrectly invoking the init hook on every call; remove the
run_hook "$target" "init" invocations from cmd_load (both the single-target path
and the bulk-load loop) so only the load hook is run during session loads; keep
the run_hook "$target" "load" calls intact, and ensure any init invocation
remains only in install/update/enable flows (not in cmd_load) to match the
documented plugin lifecycle.
| --> | ||
|
|
||
| <!--TOON:scripts[73]{name,purpose}: | ||
| <!--TOON:scripts[74]{name,purpose}: |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
fd 'subagent-index.toon' -x wc -l {}Repository: marcusquinn/aidevops
Length of output: 97
🏁 Script executed:
# Find and read the .agents/subagent-index.toon file
fd 'subagent-index.toon' -x head -200 {} | head -100Repository: marcusquinn/aidevops
Length of output: 9005
🏁 Script executed:
# Get exact line count and extract the TOON:scripts header
fd 'subagent-index.toon' -x sh -c '
echo "=== File Info ==="
wc -l "$1"
echo ""
echo "=== TOON:scripts Header ==="
grep -n "^<!--TOON:scripts" "$1"
echo ""
echo "=== Closing Tag ==="
grep -n "^-->" "$1" | head -1
echo ""
echo "=== Script Entry Count ==="
awk "/^<!--TOON:scripts/{start=NR; next} /^-->/{if(start) {count=NR-start-1; print \"Entries between lines \" start \"+1 and \" NR \"-1 = \" count; exit}}" "$1"
' _ {}Repository: marcusquinn/aidevops
Length of output: 281
TOON script count is incorrect and requires correction.
The header declares TOON:scripts[74] on line 90, but the file contains 76 actual script entries (lines 91–166). Update the header to TOON:scripts[76] to maintain accurate metadata.
🤖 Prompt for AI Agents
In @.agents/subagent-index.toon at line 90, Update the TOON header count to
match actual entries: replace the header token "TOON:scripts[74]" with
"TOON:scripts[76]" so the declared script count equals the 76 script entries
present (lines following the header under the TOON:scripts block).
| "file": "{{NAMESPACE}}/example.md", | ||
| "name": "example", | ||
| "description": "Example subagent", | ||
| "model": "sonnet" |
There was a problem hiding this comment.
Namespace the example subagent name to avoid collisions.
Using "name": "example" can conflict with other plugins’ subagents in shared indexes. Prefer a namespaced name to keep it unique.
🔧 Suggested tweak
- "name": "example",
+ "name": "{{NAMESPACE}}.example",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "file": "{{NAMESPACE}}/example.md", | |
| "name": "example", | |
| "description": "Example subagent", | |
| "model": "sonnet" | |
| "file": "{{NAMESPACE}}/example.md", | |
| "name": "{{NAMESPACE}}.example", | |
| "description": "Example subagent", | |
| "model": "sonnet" |
🤖 Prompt for AI Agents
In @.agents/templates/plugin-template/plugin.json around lines 14 - 17, The
subagent "name" field in plugin.json is too generic ("name": "example") and may
collide with other plugins; update the "name" property to a namespaced
identifier that includes the package/namespace (e.g., use the same namespace
token as the "file" field like "{{NAMESPACE}}/example" or
"{{NAMESPACE}}-example") so the subagent name is unique across shared indexes;
change the value of the "name" key in plugin.json accordingly.



Summary
Core plugin structure and agent loader for the aidevops framework (t008.1).
What's New
plugin-loader-helper.sh— Shell-based agent loader with 8 commands: discover, load, unload, validate, agents, hooks, index, statusplugin.jsonmanifest format — Plugins can declare agents, lifecycle hooks, scripts, dependencies, and minimum version requirementsaidevops plugin add/enable/disable/removeaidevops plugin initnow scaffolds manifest + hook scriptsplugin-loader-helper.sh indexgenerates TOON entries for plugin agentsDesign Decisions
plugin.jsonfall back to directory scanning for backward compatibilityscripts/on-{hook}.sh) or explicit manifest declarationagentsarray when available, otherwise parses YAML frontmatter from .md filesFiles Changed
.agents/scripts/plugin-loader-helper.sh.agents/templates/plugin-template/plugin.json.agents/templates/plugin-template/scripts/on-init.sh.agents/templates/plugin-template/scripts/on-load.sh.agents/templates/plugin-template/scripts/on-unload.shaidevops.sh.agents/aidevops/plugins.md.agents/subagent-index.toonTesting
aidevops plugin initscaffolding includes manifest and hook scripts with correct placeholder substitutionRef #1137
Summary by CodeRabbit
New Features
Documentation
Chores