Skip to content

feat: headless dispatch docs + runner-helper.sh (t109.1, t109.2)#348

Merged
marcusquinn merged 2 commits intomainfrom
feature/headless-dispatch-droids
Feb 5, 2026
Merged

feat: headless dispatch docs + runner-helper.sh (t109.1, t109.2)#348
marcusquinn merged 2 commits intomainfrom
feature/headless-dispatch-droids

Conversation

@marcusquinn
Copy link
Owner

@marcusquinn marcusquinn commented Feb 5, 2026

Summary

  • t109.1: Created tools/ai-assistants/headless-dispatch.md - comprehensive guide for OpenCode headless dispatch patterns including opencode run, opencode serve, --attach warm server, SDK parallel dispatch, custom agents, and CI/CD integration
  • t109.2: Created runner-helper.sh - named headless AI agent instances with create/run/status/list/edit/logs/stop/destroy commands
  • Renamed "droid" to "runner" to avoid naming conflict with Factory.ai's branded Droids product

Changes

File Change
.agent/tools/ai-assistants/headless-dispatch.md New - headless dispatch documentation
.agent/scripts/runner-helper.sh New - runner management CLI (534 lines)
TODO.md Updated t109.1/t109.2 as completed, renamed droid→runner
todo/PLANS.md Updated plan status to In Progress (Phase 2/5), renamed droid→runner
.agent/subagent-index.toon Added headless-dispatch and runner-helper entries
README.md Updated droid-helper→runner-helper reference, script count 163→164

Quality

  • ShellCheck: zero violations on runner-helper.sh
  • Markdownlint: zero violations on headless-dispatch.md
  • Follows existing cron-helper.sh patterns (same code conventions, security patterns)

Summary by CodeRabbit

  • New Features

    • Added a runner management system for creating and managing persistent named AI agent runners with lifecycle commands (create, run, status, list, edit, logs, stop, destroy).
    • Added headless dispatch capability for parallel, non-interactive AI agent execution.
  • Documentation

    • Added comprehensive headless dispatch guide with usage patterns, session management, and CI/CD examples; README updated to reference the new runner helper.

- Create tools/ai-assistants/headless-dispatch.md documenting OpenCode
  headless patterns: opencode run, opencode serve, --attach warm server,
  SDK parallel dispatch, custom agents, CI/CD integration
- Create runner-helper.sh for named headless agent instances with
  create/run/status/list/edit/logs/stop/destroy commands
- Rename 'droid' to 'runner' to avoid Factory.ai naming conflict
- Update TODO.md, PLANS.md, subagent-index.toon, README.md
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 5, 2026

Caution

Review failed

The pull request is closed.

Walkthrough

This PR adds a new runner management system: a Bash CLI (.agent/scripts/runner-helper.sh) that creates and manages named, persistent AI agent runners (create/run/status/list/edit/logs/stop/destroy), integrates with OpenCode for headless execution and session resumption, and updates documentation and planning to replace the "droid" concept with "runner".

Changes

Cohort / File(s) Summary
Runner Management System
.agent/scripts/runner-helper.sh
New Bash CLI (~843 lines) implementing runner lifecycle commands (create, run, status, list, edit, logs, stop, destroy, help); per-runner state (AGENTS.md, config.json, memory.db, session.id, runs/); OpenCode run/attach/resume support; jq and opencode checks; logging and run metadata updates.
Headless Dispatch Documentation
.agent/tools/ai-assistants/headless-dispatch.md
New comprehensive guide (~496 lines) describing headless dispatch patterns (CLI, warm server, SDK, HTTP API), session and runner lifecycle, directory layout, parallel execution strategies, security guidance, and CI/CD examples.
Index & Integration
.agent/subagent-index.toon, README.md
Added headless-dispatch alias/flag to subagent index and registered runner-helper.sh in scripts; README incremented helper count and updated cron examples to use runner-helper.sh.
Planning & TODOs
todo/PLANS.md, TODO.md
Reworked plans to be OpenCode-centric and renamed concepts from "droid" → "runner"; TODO.md contains unresolved merge conflict markers that require manual resolution.

Sequence Diagram

sequenceDiagram
    participant User
    participant RunnerCLI as runner-helper.sh
    participant FS as Filesystem
    participant OpenCode as OpenCode Server
    participant SessionMgr as Session Manager

    User->>RunnerCLI: run <runner> <task> [--attach|--model|--continue]
    RunnerCLI->>FS: read `runners/<name>/config.json` and `AGENTS.md`
    FS-->>RunnerCLI: return config, agent context
    RunnerCLI->>RunnerCLI: compose prompt (AGENTS.md + user task)
    RunnerCLI->>OpenCode: POST /run (prompt, model, session-id)
    OpenCode->>SessionMgr: validate/resume session
    SessionMgr-->>OpenCode: session context (restored or new)
    OpenCode-->>RunnerCLI: stream execution output / exit code
    RunnerCLI->>FS: write run log to `runs/`, update `config.json` (lastRun, lastStatus, runCount)
    RunnerCLI-->>User: display output, status, and run metadata
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🏃‍♂️ Runners wake in folders neat and neat,
AGENTS.md scripts whisper the task to meet,
Sessions resume where last logs lay,
OpenCode hums and sends replies away,
State persists — droid renamed — runners march on fleet.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and concisely summarizes the main changes: adding headless dispatch documentation and the runner-helper script, with task references.
Docstring Coverage ✅ Passed Docstring coverage is 86.36% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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/headless-dispatch-droids

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.

@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 significantly enhances the framework for headless AI agent operations by introducing a dedicated command-line tool for managing persistent agent instances and providing extensive documentation on various dispatch methods. These changes aim to streamline the integration of AI agents into automated workflows, enabling more efficient parallel processing and CI/CD integration, while also clarifying naming conventions for better product alignment.

Highlights

  • New Runner Management CLI: Introduced runner-helper.sh, a new command-line utility for creating, running, managing, and destroying named headless AI agent instances. This script allows for persistent agent identities, configurations, and isolated logging.
  • Comprehensive Headless Dispatch Documentation: Added headless-dispatch.md, a detailed guide covering various patterns for headless AI agent execution. This includes direct CLI dispatch, warm server integration, SDK usage, HTTP API, session management, parallel execution, and CI/CD integration.
  • Renaming Convention: The term 'droid' has been renamed to 'runner' across the codebase and documentation to avoid potential naming conflicts with other products and to better align with the concept of named execution environments.
Changelog
  • .agent/scripts/runner-helper.sh
    • New script added to provide a CLI for managing named headless AI agent instances.
    • Includes commands for create, run, status, list, edit, logs, stop, and destroy runners.
    • Each runner maintains its own AGENTS.md for personality, config.json for settings, and a runs/ directory for execution logs.
    • Supports integration with opencode run for task dispatch, including options for warm server attachment and session continuation.
  • .agent/subagent-index.toon
    • Updated the description for tools/ai-assistants/ to explicitly mention 'headless dispatch'.
    • Added a new entry for runner-helper.sh in the list of helper scripts.
  • .agent/tools/ai-assistants/headless-dispatch.md
    • New documentation file created, serving as a comprehensive guide to headless dispatch patterns.
    • Details methods such as direct CLI (opencode run), warm server (opencode serve + --attach), SDK (TypeScript), and HTTP API (curl).
    • Explains session management features like resuming, forking, and context injection.
    • Provides guidance on parallel execution, custom agents, model provider flexibility, security, and CI/CD integration (e.g., GitHub Actions).
    • Introduces the concept of 'Runners' and their lifecycle, directory structure, and integration with memory and mailbox systems.
  • README.md
    • Updated the total count of helper scripts from 163 to 164.
    • Modified the cron job example to reference runner-helper.sh instead of the deprecated droid-helper.sh.
  • TODO.md
    • Marked tasks t109.1 (Document headless dispatch patterns) and t109.2 (Create runner-helper.sh) as completed.
    • Updated the notes for t109.1 and t109.2 to reflect the creation of headless-dispatch.md and runner-helper.sh, and the renaming from 'droid' to 'runner'.
    • Adjusted notes for related tasks (t109.3, t109.4, t109.5) to consistently use 'runner' terminology.
  • todo/PLANS.md
    • Updated the status of the 'Parallel Agents & Headless Dispatch' plan (p016) from 'Planning' to 'In Progress (Phase 2/5)'.
    • Added a 'Naming decision' note to explain the change from 'droids' to 'runners' to avoid product conflicts.
    • Revised the 'Key insight from source' section to highlight opencode run and --attach for headless dispatch.
    • Updated the 'What we ARE doing' section to reflect the new opencode run patterns, runner-helper.sh, and 'per-runner namespaces'.
    • Marked Phase 1 and Phase 2 of the plan as completed, detailing the specific deliverables for each.
Activity
  • The author has completed the implementation and documentation for headless dispatch patterns (t109.1).
  • The runner-helper.sh script, providing named headless AI agent instances, has been created (t109.2).
  • The overall 'Parallel Agents & Headless Dispatch' plan has progressed to 'In Progress (Phase 2/5)'.
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.

@github-actions
Copy link

github-actions bot commented Feb 5, 2026

🔍 Code Quality Report

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

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

�[0;34m[INFO]�[0m Recent monitoring activity:
Thu Feb 5 21:17:43 UTC 2026: Code review monitoring started
Thu Feb 5 21:17:43 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 2
Thu Feb 5 21:17:43 UTC 2026: Qlty - 0 issues found, auto-formatting applied
Thu Feb 5 21:17:46 UTC 2026: Codacy analysis completed with auto-fixes

📈 Current Quality Metrics

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

Generated on: Thu Feb 5 21:17:48 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

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 introduces a significant and well-implemented feature for managing headless AI agents, runner-helper.sh, accompanied by excellent, comprehensive documentation in headless-dispatch.md. The code is generally of high quality, adhering to good shell scripting practices. The renaming from "droid" to "runner" is applied consistently across all files. I've identified one high-severity issue in the JSON generation logic that could produce invalid output and one medium-severity efficiency improvement. The rest of the changes are solid.

Comment on lines 517 to 536
if [[ "$output_format" == "json" ]]; then
local json_output="["
local first=true
for runner_path in $runners; do
local rname
rname=$(basename "$runner_path")
local config_file="$runner_path/config.json"
if [[ -f "$config_file" ]]; then
if [[ "$first" == "true" ]]; then
first=false
else
json_output+=","
fi
json_output+=$(cat "$config_file")
fi
done
json_output+="]"
echo "$json_output" | jq '.'
return 0
fi

Choose a reason for hiding this comment

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

high

The current implementation for building the JSON output is not robust. It manually concatenates strings and file contents (json_output+=$(cat "$config_file")), which will fail if the config.json files contain characters that need escaping or if the concatenation results in invalid JSON (e.g., due to extra or missing commas). This can lead to malformed JSON output, breaking any downstream tools that consume it. A much safer and more efficient approach is to use jq to construct the entire JSON array.

Suggested change
if [[ "$output_format" == "json" ]]; then
local json_output="["
local first=true
for runner_path in $runners; do
local rname
rname=$(basename "$runner_path")
local config_file="$runner_path/config.json"
if [[ -f "$config_file" ]]; then
if [[ "$first" == "true" ]]; then
first=false
else
json_output+=","
fi
json_output+=$(cat "$config_file")
fi
done
json_output+="]"
echo "$json_output" | jq '.'
return 0
fi
if [[ "$output_format" == "json" ]]; then
# Use jq to safely construct the JSON array. This is more robust
# than string concatenation.
local config_files=()
while IFS= read -r runner_path; do
local config_file="$runner_path/config.json"
if [[ -f "$config_file" ]]; then
config_files+=("$config_file")
fi
done <<< "$runners"
if (( ${#config_files[@]} > 0 )); then
jq -s . "${config_files[@]}"
else
echo "[]"
fi
return 0
fi

Comment on lines 442 to 449
description=$(jq -r '.description // "N/A"' "$config")
model=$(jq -r '.model // "N/A"' "$config")
workdir=$(jq -r '.workdir // "N/A"' "$config")
created=$(jq -r '.created // "N/A"' "$config")
last_run=$(jq -r '.lastRun // "never"' "$config")
last_status=$(jq -r '.lastStatus // "N/A"' "$config")
run_count=$(jq -r '.runCount // 0' "$config")
last_duration=$(jq -r '.lastDuration // "N/A"' "$config")

Choose a reason for hiding this comment

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

medium

This function calls jq eight separate times to read different keys from the same config.json file. This is inefficient as it involves multiple process invocations and file reads for a single operation. You can optimize this by reading all required values in a single jq call, for example by outputting them as a JSON object or as newline-separated values and then parsing them in bash. This will improve performance and reduce resource usage.

@github-actions
Copy link

github-actions bot commented Feb 5, 2026

🔍 Code Quality Report

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

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

�[0;34m[INFO]�[0m Recent monitoring activity:
Thu Feb 5 21:21:45 UTC 2026: Code review monitoring started
Thu Feb 5 21:21:46 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 2
Thu Feb 5 21:21:46 UTC 2026: Qlty - 0 issues found, auto-formatting applied
Thu Feb 5 21:21:48 UTC 2026: Codacy analysis completed with auto-fixes

📈 Current Quality Metrics

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

Generated on: Thu Feb 5 21:21:51 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@sonarqubecloud
Copy link

sonarqubecloud bot commented Feb 5, 2026

@marcusquinn marcusquinn merged commit 606a1e8 into main Feb 5, 2026
10 checks passed
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
TODO.md (2)

294-298: ⚠️ Potential issue | 🔴 Critical

CRITICAL: Unresolved merge conflict in TOON backlog header.

The merge conflict markers indicate conflicting backlog counts (60 vs 80 items), which suggests significant divergence between branches. This prevents TOON parsers and task management tools from functioning correctly.

Action Required:

  1. Review both versions of the backlog to identify which tasks are unique to each branch
  2. Manually merge the task lists, preserving all valid entries
  3. Update the count in the TOON header to reflect the final merged total
  4. Remove all conflict markers (<<<<<<< HEAD, =======, >>>>>>> origin/main)
📋 Resolution guidance

Compare the task entries between lines 299-328 in both versions:

  • HEAD version (lines 299-307): Contains older t109, t110, t111 as separate tasks
  • origin/main version (lines 309-328): Contains expanded t109 with subtasks and additional t110-t118

The origin/main version appears more current given that t109.1 and t109.2 are marked completed (lines 215-218). You'll need to reconcile which tasks from HEAD should be preserved if they're not already in origin/main.


311-311: ⚠️ Potential issue | 🟡 Minor

Naming inconsistency: "droid-helper.sh" should be "runner-helper.sh".

Line 311 references "droid-helper.sh" in the TOON block for t109.2, but the notes at line 218 explicitly state the script was "renamed from 'droid' to 'runner' to avoid Factory.ai naming conflict."

After resolving the merge conflicts, ensure this entry uses "runner-helper.sh" to maintain consistency with the completed rename.

🔧 Suggested fix (post-merge)
-t109.2,Create droid-helper.sh,,agents|scripts|dispatch,4h,4h,,2026-02-03T00:00Z,pending,,,t109
+t109.2,Create runner-helper.sh,,agents|scripts|dispatch,4h,4h,,2026-02-03T00:00Z,completed,,,t109

Note: Also update status from pending to completed since line 217 indicates t109.2 was completed on 2026-02-05.

🤖 Fix all issues with AI agents
In @.agent/scripts/runner-helper.sh:
- Around line 380-389: The timeout invocation is non-portable and cmd_timeout is
not validated; update the runner to detect an available timeout binary (try
gtimeout then timeout) and use that binary via a local variable (e.g.,
timeout_cmd) instead of calling timeout directly, and validate cmd_timeout
before use (ensure it's non-empty, an integer, and >0) falling back to running
the command without a timeout if invalid; locate and change the block using
cmd_timeout, cmd_args, and log_file in runner-helper.sh to perform the
detection/validation and then invoke "$timeout_cmd" "$cmd_timeout"
"${cmd_args[@]}" 2>&1 | tee "$log_file" only when a valid timeout is present.
- Around line 332-343: The script currently reads $dir/session.id for
continuation but never writes it; update the runner-helper.sh flow that calls
"opencode run" so after the run completes you parse the command output (prefer
JSON via --format json if supported or otherwise extract the session id from the
stdout), and write the found session ID to "$dir/session.id"; on non-zero exit
or if no session id is found, remove/clear "$dir/session.id" to avoid stale IDs;
ensure this logic is applied where cmd_args and continue_session are used and
that log_warn/log_info reflect success or clearing.

In @.agent/tools/ai-assistants/headless-dispatch.md:
- Around line 63-495: This file contains lengthy inline CLI/SDK/HTTP examples
under headings like "Dispatch Methods" and "Parallel Execution"; replace those
embedded blocks with progressive-disclosure pointers to the canonical
implementations (e.g., reference the dispatch flow in runner-helper.sh and API
examples in tools/ai-assistants/opencode-server.md using file:line style) and
move the full example content into the owning docs/scripts; apply this pattern
across `.agent/**/*.md` (remove large code fences under "Method 1/2/3/4",
"Session Management", "Parallel Execution", "Runners", and "CI/CD Integration"
and replace them with brief one-line pointers to the authoritative files you
moved the examples to).
- Around line 21-26: The quick reference list omits the `edit` and `logs`
commands for runner-helper; update the documentation block listing the command
summaries (the lines referencing `opencode run`, `opencode serve`, `npm install
`@opencode-ai/sdk``, and especially `runner-helper.sh
[create|run|status|list|stop|destroy]`) to include the full runner-helper
command set by adding `edit` and `logs` into the bracketed options (i.e.,
`runner-helper.sh [create|run|status|list|stop|destroy|edit|logs]`) and ensure
any brief descriptions or examples elsewhere in this section mention how to use
`runner-helper.sh edit` and `runner-helper.sh logs`.
- Around line 259-269: Update the runner directory example so it matches the
runner-helper script output by adding the missing session.id file and runs/
directory to the displayed tree (i.e., include "session.id" and a "runs/" entry
under each runner like code-reviewer and seo-analyst); edit the tree in the
.agent/tools/ai-assistants/headless-dispatch.md example block (the snippet
showing ~/.aidevops/.agent-workspace/runners/) so operators see the exact layout
produced by the script.

In `@todo/PLANS.md`:
- Around line 1974-1980: The TOON plan block uses duplicate IDs (p016, m064,
d039) which collide with existing entries; update the plan block's identifiers
to the next free TOON IDs (e.g., replace p016 with a new p### and update its
related milestone/decision IDs m###/d###) and ensure the same renumbering is
applied to the other affected blocks (lines referenced in the comment: 2080-2085
and 2106-2109) so all TOON tags are unique; also rename any milestone/decision
text that still references "droid-helper.sh" to the new runner name to keep
naming consistent (locate the TOON marker comment starting with "<!--TOON:plan"
and update IDs and text inside that block plus its matching m/d entries).

Comment on lines +332 to +343
# Continue previous session if requested
if [[ "$continue_session" == "true" ]]; then
local session_id=""
if [[ -f "$dir/session.id" ]]; then
session_id=$(cat "$dir/session.id")
fi
if [[ -n "$session_id" ]]; then
cmd_args+=("-s" "$session_id")
else
log_warn "No previous session found for $name, starting fresh"
fi
fi
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's examine the runner-helper.sh file to understand the full context
wc -l .agent/scripts/runner-helper.sh

Repository: marcusquinn/aidevops

Length of output: 99


🏁 Script executed:

# Read the specific sections mentioned in the review (332-343 and 395-408)
sed -n '320,410p' .agent/scripts/runner-helper.sh | cat -n

Repository: marcusquinn/aidevops

Length of output: 2911


🏁 Script executed:

# Search for opencode run invocations and how session IDs are handled
rg "opencode run" .agent/scripts/runner-helper.sh -A 5 -B 5

Repository: marcusquinn/aidevops

Length of output: 360


🏁 Script executed:

# Check if there's any session ID extraction or persistence logic
rg "session\.id" .agent/scripts/runner-helper.sh -A 3 -B 3

Repository: marcusquinn/aidevops

Length of output: 1183


🏁 Script executed:

# Search for any JSON parsing or output format handling in the script
rg "jq|json|format" .agent/scripts/runner-helper.sh | head -20

Repository: marcusquinn/aidevops

Length of output: 1051


🏁 Script executed:

# Search for any extraction of session IDs from command output elsewhere in the repo
rg "session" .agent/scripts/ -l

Repository: marcusquinn/aidevops

Length of output: 1556


🏁 Script executed:

# Look at the full context of where opencode run is executed to see output handling
sed -n '350,420p' .agent/scripts/runner-helper.sh | cat -n

Repository: marcusquinn/aidevops

Length of output: 2261


🏁 Script executed:

# Search for opencode CLI documentation or examples
find . -type f \( -name "*.md" -o -name "*.txt" -o -name "*.sh" \) -exec rg -l "opencode.*--help|opencode.*format|opencode.*session" {} \;

Repository: marcusquinn/aidevops

Length of output: 530


🏁 Script executed:

# Check if there's any README or documentation about opencode
rg "opencode" README.md -A 5 -B 5 2>/dev/null | head -40

Repository: marcusquinn/aidevops

Length of output: 1887


🏁 Script executed:

# Look for opencode test helper to see how it uses opencode run
cat .agent/scripts/opencode-test-helper.sh | head -100

Repository: marcusquinn/aidevops

Length of output: 3520


🏁 Script executed:

# Search for any session ID extraction patterns in all scripts
rg "session_id.*\$\(" .agent/scripts/ -A 2 -B 2

Repository: marcusquinn/aidevops

Length of output: 46


🏁 Script executed:

# Check opencode documentation in the tools directory
ls -la .agent/tools/opencode/

Repository: marcusquinn/aidevops

Length of output: 389


🏁 Script executed:

# Look at opencode-server documentation for session details
cat .agent/tools/opencode/opencode-server.md | grep -i "session\|output\|format" -A 3 -B 1

Repository: marcusquinn/aidevops

Length of output: 136


🏁 Script executed:

# Search for any patterns of capturing command output to extract info
rg "opencode.*\|.*jq|output.*session" .agent/scripts/ -A 3

Repository: marcusquinn/aidevops

Length of output: 357


🏁 Script executed:

# Check the main opencode documentation
cat .agent/tools/opencode/opencode.md | grep -i "session\|output.*format\|--format\|--print\|json" -A 3 -B 1 | head -80

Repository: marcusquinn/aidevops

Length of output: 2202


🏁 Script executed:

# Look for any references to how session IDs are captured or used in workflows
rg "session.*json\|print.*session\|format.*json" .agent/workflows/ -A 2

Repository: marcusquinn/aidevops

Length of output: 46


🏁 Script executed:

# Check how opencode run is used in other helpers
rg "opencode run" .agent/scripts/*.sh -B 2 -A 8 | head -100

Repository: marcusquinn/aidevops

Length of output: 6416


🏁 Script executed:

# Look at the full opencode.md documentation for session/output information
wc -l .agent/tools/opencode/opencode.md

Repository: marcusquinn/aidevops

Length of output: 101


🏁 Script executed:

# Search for specific mention of JSON output or session in opencode.md
cat .agent/tools/opencode/opencode.md | grep -i "json\|session\|--format\|output" -A 2 -B 1 | head -150

Repository: marcusquinn/aidevops

Length of output: 3368


🏁 Script executed:

# Look at the complete runner-helper function to understand full context (lines 280-420)
sed -n '280,420p' .agent/scripts/runner-helper.sh | cat -n

Repository: marcusquinn/aidevops

Length of output: 4900


🏁 Script executed:

# Check if there's any mechanism to extract session ID from opencode logs or output
rg "session.*extract|extract.*session|sed.*session|jq.*session" .agent/scripts/ -A 2

Repository: marcusquinn/aidevops

Length of output: 5898


🏁 Script executed:

# Look at the runner_stop function to see how it uses session.id (should be around line 395-408)
sed -n '395,420p' .agent/scripts/runner-helper.sh | cat -n

Repository: marcusquinn/aidevops

Length of output: 984


🏁 Script executed:

# Let's search for how opencode outputs session information or if there are any examples of parsing its output
rg "\"session\"|'session'|session.*:.*\|" .agent/scripts/ -A 1 | head -50

Repository: marcusquinn/aidevops

Length of output: 46


🏁 Script executed:

# Check if runner_stop function uses the session.id file (the second location mentioned: 395-408)
sed -n '395,450p' .agent/scripts/runner-helper.sh | cat -n

Repository: marcusquinn/aidevops

Length of output: 1931


🏁 Script executed:

# Look for any documentation or examples of opencode output format
cat .agent/tools/opencode/opencode.md | tail -200

Repository: marcusquinn/aidevops

Length of output: 6096


🏁 Script executed:

# Search for how opencode server or API might expose session IDs
rg "opencode.*serve\|--session\|-s\|session" .agent/tools/opencode/opencode.md -A 2 -B 1

Repository: marcusquinn/aidevops

Length of output: 46


🏁 Script executed:

# Search for any documentation about opencode output or session management
rg "session.*ID|ID.*session|opencode.*output|emit.*session" .agent/tools/ -A 2

Repository: marcusquinn/aidevops

Length of output: 3577


🏁 Script executed:

# Check if there's a runner_stop function or any function that deals with stopping sessions
rg "cmd_stop|runner_stop|stop.*session" .agent/scripts/runner-helper.sh -A 15

Repository: marcusquinn/aidevops

Length of output: 1929


🏁 Script executed:

# Look for any indication of how session IDs should be captured
rg "\-s.*session|session.*flag|continue.*session" .agent/scripts/runner-helper.sh -B 2 -A 2

Repository: marcusquinn/aidevops

Length of output: 1120


🏁 Script executed:

# Check the full runner_stop context around lines mentioned (also check 395-408 area)
sed -n '450,550p' .agent/scripts/runner-helper.sh | cat -n

Repository: marcusquinn/aidevops

Length of output: 3662


🏁 Script executed:

# Find the full cmd_stop implementation
rg "^cmd_stop" .agent/scripts/runner-helper.sh -A 30

Repository: marcusquinn/aidevops

Length of output: 742


🏁 Script executed:

# Search for where session.id might be written or cleared
rg "session\.id.*>" .agent/scripts/runner-helper.sh

Repository: marcusquinn/aidevops

Length of output: 46


🏁 Script executed:

# Look for any patterns of capturing output from opencode run
sed -n '300,450p' .agent/scripts/runner-helper.sh | grep -A 10 "cmd_stop"

Repository: marcusquinn/aidevops

Length of output: 46


🏁 Script executed:

# Check if there's any session ID extraction or parsing logic anywhere
rg "sed.*session|grep.*session|session.*extract" .agent/scripts/ -A 2

Repository: marcusquinn/aidevops

Length of output: 3899


🏁 Script executed:

# Look at the headless-dispatch documentation more carefully for session capture patterns
cat .agent/tools/ai-assistants/headless-dispatch.md | grep -A 10 "SESSION_ID"

Repository: marcusquinn/aidevops

Length of output: 1119


Capture and persist session IDs so session continuation and abort work reliably.

The helper reads session.id for --continue and stop operations, but never writes it after a run executes. This breaks both session resumption and the runner-helper stop function, which expects $dir/session.id to exist.

After opencode run completes, extract the session ID from its output and persist it to $dir/session.id. Clear the file on failed runs to avoid stale IDs. This requires understanding how opencode run exposes the session ID—check if it supports --format json, has a --print-session flag, or outputs session info in the default format.

🤖 Prompt for AI Agents
In @.agent/scripts/runner-helper.sh around lines 332 - 343, The script currently
reads $dir/session.id for continuation but never writes it; update the
runner-helper.sh flow that calls "opencode run" so after the run completes you
parse the command output (prefer JSON via --format json if supported or
otherwise extract the session id from the stdout), and write the found session
ID to "$dir/session.id"; on non-zero exit or if no session id is found,
remove/clear "$dir/session.id" to avoid stale IDs; ensure this logic is applied
where cmd_args and continue_session are used and that log_warn/log_info reflect
success or clearing.

Comment on lines +380 to +389
# Execute with timeout
local exit_code=0
local start_time
start_time=$(date +%s)

if timeout "$cmd_timeout" "${cmd_args[@]}" 2>&1 | tee "$log_file"; then
exit_code=0
else
exit_code=$?
fi
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's verify the file exists and examine the code around lines 380-389
wc -l .agent/scripts/runner-helper.sh

Repository: marcusquinn/aidevops

Length of output: 99


🏁 Script executed:

# Read the relevant section of the file to see the actual code
sed -n '370,400p' .agent/scripts/runner-helper.sh

Repository: marcusquinn/aidevops

Length of output: 828


🏁 Script executed:

# Search for existing timeout-related code throughout the scripts directory
rg -n "timeout|gtimeout" .agent/scripts/ -A 2 -B 2

Repository: marcusquinn/aidevops

Length of output: 35337


🏁 Script executed:

# Check for any documentation about setup, dependencies, or timeout handling
rg -n "timeout|coreutils|gtimeout|macOS|Darwin" README.md setup.sh .agent/ --type-list

Repository: marcusquinn/aidevops

Length of output: 453


🏁 Script executed:

# Look for where cmd_timeout is defined and validated
rg -n "cmd_timeout" .agent/scripts/runner-helper.sh -B 5 -A 5

Repository: marcusquinn/aidevops

Length of output: 1306


Add timeout portability check and validate --timeout value to ensure reliability across platforms.

The timeout command isn't available on macOS by default (requires coreutils/gtimeout). Also, cmd_timeout is never validated—empty, non-numeric, or negative values will cause failures. Other scripts in .agent/scripts/ (e.g., linters-local.sh, gsc-sitemap-helper.sh) already implement both patterns; apply the same here for consistency.

🛠️ Proposed fix
    # Execute with timeout
+   local timeout_cmd="timeout"
+   if ! command -v "$timeout_cmd" &>/dev/null; then
+       if command -v gtimeout &>/dev/null; then
+           timeout_cmd="gtimeout"
+       else
+           log_error "timeout command required (install coreutils or gnu-coreutils)"
+           return 1
+       fi
+   fi
+   if ! [[ "$cmd_timeout" =~ ^[0-9]+$ ]] || [[ "$cmd_timeout" -le 0 ]]; then
+       log_error "--timeout must be a positive integer (seconds)"
+       return 1
+   fi
    local exit_code=0
    local start_time
    start_time=$(date +%s)

-   if timeout "$cmd_timeout" "${cmd_args[@]}" 2>&1 | tee "$log_file"; then
+   if "$timeout_cmd" "$cmd_timeout" "${cmd_args[@]}" 2>&1 | tee "$log_file"; then
🤖 Prompt for AI Agents
In @.agent/scripts/runner-helper.sh around lines 380 - 389, The timeout
invocation is non-portable and cmd_timeout is not validated; update the runner
to detect an available timeout binary (try gtimeout then timeout) and use that
binary via a local variable (e.g., timeout_cmd) instead of calling timeout
directly, and validate cmd_timeout before use (ensure it's non-empty, an
integer, and >0) falling back to running the command without a timeout if
invalid; locate and change the block using cmd_timeout, cmd_args, and log_file
in runner-helper.sh to perform the detection/validation and then invoke
"$timeout_cmd" "$cmd_timeout" "${cmd_args[@]}" 2>&1 | tee "$log_file" only when
a valid timeout is present.

Comment on lines +21 to +26
- **One-shot dispatch**: `opencode run "prompt"`
- **Warm server dispatch**: `opencode run --attach http://localhost:4096 "prompt"`
- **Server mode**: `opencode serve [--port 4096]`
- **SDK**: `npm install @opencode-ai/sdk`
- **Runner management**: `runner-helper.sh [create|run|status|list|stop|destroy]`
- **Runner directory**: `~/.aidevops/.agent-workspace/runners/`
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Quick reference omits edit and logs.

The runner-helper summary should include the full command set.

✏️ Suggested tweak
-- **Runner management**: `runner-helper.sh [create|run|status|list|stop|destroy]`
+- **Runner management**: `runner-helper.sh [create|run|status|list|edit|logs|stop|destroy]`
📝 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.

Suggested change
- **One-shot dispatch**: `opencode run "prompt"`
- **Warm server dispatch**: `opencode run --attach http://localhost:4096 "prompt"`
- **Server mode**: `opencode serve [--port 4096]`
- **SDK**: `npm install @opencode-ai/sdk`
- **Runner management**: `runner-helper.sh [create|run|status|list|stop|destroy]`
- **Runner directory**: `~/.aidevops/.agent-workspace/runners/`
- **One-shot dispatch**: `opencode run "prompt"`
- **Warm server dispatch**: `opencode run --attach http://localhost:4096 "prompt"`
- **Server mode**: `opencode serve [--port 4096]`
- **SDK**: `npm install `@opencode-ai/sdk``
- **Runner management**: `runner-helper.sh [create|run|status|list|edit|logs|stop|destroy]`
- **Runner directory**: `~/.aidevops/.agent-workspace/runners/`
🤖 Prompt for AI Agents
In @.agent/tools/ai-assistants/headless-dispatch.md around lines 21 - 26, The
quick reference list omits the `edit` and `logs` commands for runner-helper;
update the documentation block listing the command summaries (the lines
referencing `opencode run`, `opencode serve`, `npm install `@opencode-ai/sdk``,
and especially `runner-helper.sh [create|run|status|list|stop|destroy]`) to
include the full runner-helper command set by adding `edit` and `logs` into the
bracketed options (i.e., `runner-helper.sh
[create|run|status|list|stop|destroy|edit|logs]`) and ensure any brief
descriptions or examples elsewhere in this section mention how to use
`runner-helper.sh edit` and `runner-helper.sh logs`.

Comment on lines +63 to +495
## Dispatch Methods

### Method 1: Direct CLI (`opencode run`)

Simplest approach. Each invocation starts a fresh session (or resumes one).

```bash
# One-shot task
opencode run "Review src/auth.ts for security issues"

# With specific model
opencode run -m anthropic/claude-sonnet-4-20250514 "Generate unit tests for src/utils/"

# With specific agent
opencode run --agent plan "Analyze the database schema"

# JSON output (for parsing)
opencode run --format json "List all exported functions in src/"

# Attach files for context
opencode run -f ./schema.sql -f ./migration.ts "Generate types from this schema"

# Set a session title
opencode run --title "Auth review" "Review the auth middleware"
```

### Method 2: Warm Server (`opencode serve` + `--attach`)

Avoids MCP server cold boot on every dispatch. Recommended for repeated tasks.

```bash
# Terminal 1: Start persistent server
opencode serve --port 4096

# Terminal 2+: Dispatch tasks against it
opencode run --attach http://localhost:4096 "Task 1"
opencode run --attach http://localhost:4096 --agent plan "Review task"
```

### Method 3: SDK (TypeScript)

Full programmatic control. Best for parallel orchestration.

```typescript
import { createOpencode, createOpencodeClient } from "@opencode-ai/sdk"

// Start server + client together
const { client, server } = await createOpencode({
port: 4096,
config: { model: "anthropic/claude-sonnet-4-20250514" },
})

// Or connect to existing server
const client = createOpencodeClient({
baseUrl: "http://localhost:4096",
})
```

### Method 4: HTTP API (curl)

Direct API calls for shell scripts and non-JS integrations.

```bash
SERVER="http://localhost:4096"

# Create session
SESSION_ID=$(curl -sf -X POST "$SERVER/session" \
-H "Content-Type: application/json" \
-d '{"title": "API task"}' | jq -r '.id')

# Send prompt (sync - waits for response)
curl -sf -X POST "$SERVER/session/$SESSION_ID/message" \
-H "Content-Type: application/json" \
-d '{
"model": {"providerID": "anthropic", "modelID": "claude-sonnet-4-20250514"},
"parts": [{"type": "text", "text": "Explain this codebase"}]
}'

# Send prompt (async - returns 204 immediately)
curl -sf -X POST "$SERVER/session/$SESSION_ID/prompt_async" \
-H "Content-Type: application/json" \
-d '{"parts": [{"type": "text", "text": "Run tests in background"}]}'

# Monitor via SSE
curl -N "$SERVER/event"
```

## Session Management

### Resuming Sessions

```bash
# Continue last session
opencode run -c "Continue where we left off"

# Resume specific session by ID
opencode run -s ses_abc123 "Add error handling to the auth module"
```

### Forking Sessions

Create a branch from an existing conversation:

```bash
# Via HTTP API
curl -sf -X POST "http://localhost:4096/session/$SESSION_ID/fork" \
-H "Content-Type: application/json" \
-d '{"messageID": "msg-123"}'
```

```typescript
// Via SDK - create child session
const child = await client.session.create({
body: { parentID: parentSession.id, title: "Subtask" },
})
```

### Context Injection (No Reply)

Inject context without triggering an AI response:

```typescript
await client.session.prompt({
path: { id: sessionId },
body: {
noReply: true,
parts: [{
type: "text",
text: "Context: This project uses Express.js with TypeScript.",
}],
},
})
```

## Parallel Execution

### CLI Parallel (Background Jobs)

```bash
# Start server once
opencode serve --port 4096 &

# Dispatch parallel tasks
opencode run --attach http://localhost:4096 --title "Review" \
"Review src/auth/ for security issues" &
opencode run --attach http://localhost:4096 --title "Tests" \
"Generate unit tests for src/utils/" &
opencode run --attach http://localhost:4096 --title "Docs" \
"Generate API documentation for src/api/" &

wait # Wait for all to complete
```

### SDK Parallel (Promise.all)

```typescript
const client = createOpencodeClient({ baseUrl: "http://localhost:4096" })

// Create parallel sessions
const [review, tests, docs] = await Promise.all([
client.session.create({ body: { title: "Code Review" } }),
client.session.create({ body: { title: "Test Generation" } }),
client.session.create({ body: { title: "Documentation" } }),
])

// Dispatch tasks concurrently
await Promise.all([
client.session.promptAsync({
path: { id: review.data.id },
body: { parts: [{ type: "text", text: "Review src/auth.ts" }] },
}),
client.session.promptAsync({
path: { id: tests.data.id },
body: { parts: [{ type: "text", text: "Generate tests for src/utils/" }] },
}),
client.session.promptAsync({
path: { id: docs.data.id },
body: { parts: [{ type: "text", text: "Generate API docs for src/api/" }] },
}),
])

// Monitor via SSE
const events = await client.event.subscribe()
for await (const event of events.stream) {
if (event.type === "session.status") {
console.log(`Session ${event.properties.id}: ${event.properties.status}`)
}
}
```

## Runners

Runners are named, persistent agent instances with their own identity, instructions, and optionally isolated memory. Managed by `runner-helper.sh`.

### Directory Structure

```text
~/.aidevops/.agent-workspace/runners/
├── code-reviewer/
│ ├── AGENTS.md # Runner personality/instructions
│ ├── config.json # Runner configuration
│ └── memory.db # Runner-specific memories (optional)
└── seo-analyst/
├── AGENTS.md
├── config.json
└── memory.db
```

### Runner Lifecycle

```bash
# Create a runner
runner-helper.sh create code-reviewer \
--description "Reviews code for security and quality" \
--model anthropic/claude-sonnet-4-20250514

# Run a task
runner-helper.sh run code-reviewer "Review src/auth/ for vulnerabilities"

# Run against warm server (faster)
runner-helper.sh run code-reviewer "Review src/auth/" --attach http://localhost:4096

# Check status
runner-helper.sh status code-reviewer

# List all runners
runner-helper.sh list

# Destroy a runner
runner-helper.sh destroy code-reviewer
```

### Custom Runner Instructions

Each runner gets its own `AGENTS.md` that defines its personality:

```markdown
# Code Reviewer

You are a senior code reviewer focused on security and maintainability.

## Rules

- Flag any use of eval(), innerHTML, or raw SQL
- Check for proper input validation
- Verify error handling covers edge cases
- Note missing tests for critical paths

## Output Format

For each file reviewed, output:
1. Severity (critical/warning/info)
2. Line reference (file:line)
3. Issue description
4. Suggested fix
```

### Integration with Memory

Runners can use isolated or shared memory:

```bash
# Store a memory for a specific runner
memory-helper.sh store \
--content "WORKING_SOLUTION: Use parameterized queries for SQL" \
--tags "security,sql" \
--namespace "code-reviewer"

# Recall from runner namespace
memory-helper.sh recall \
--query "SQL injection" \
--namespace "code-reviewer"
```

### Integration with Mailbox

Runners communicate via the existing mailbox system:

```bash
# Coordinator dispatches to runner
mail-helper.sh send \
--to "code-reviewer" \
--type "task_dispatch" \
--payload "Review PR #123 for security issues"

# Runner reports back
mail-helper.sh send \
--to "coordinator" \
--type "status_report" \
--from "code-reviewer" \
--payload "Review complete. 2 critical, 5 warnings found."
```

## Custom Agents for Dispatch

OpenCode supports custom agents via markdown files or JSON config. These complement runners by defining tool access and permissions.

### Markdown Agent (Project-Level)

Place in `.opencode/agents/security-reviewer.md`:

```markdown
---
description: Security-focused code reviewer
mode: subagent
model: anthropic/claude-sonnet-4-20250514
temperature: 0.1
tools:
write: false
edit: false
bash: false
permission:
bash:
"git diff*": allow
"git log*": allow
"grep *": allow
"*": deny
---

You are a security expert. Identify vulnerabilities, check for OWASP Top 10
issues, and verify proper input validation and output encoding.
```

### JSON Agent (Global Config)

In `opencode.json`:

```json
{
"agent": {
"security-reviewer": {
"description": "Security-focused code reviewer",
"mode": "subagent",
"model": "anthropic/claude-sonnet-4-20250514",
"tools": { "write": false, "edit": false }
}
}
}
```

### Using Custom Agents

```bash
# CLI
opencode run --agent security-reviewer "Audit the auth module"

# SDK
const result = await client.session.prompt({
path: { id: session.id },
body: {
agent: "security-reviewer",
parts: [{ type: "text", text: "Audit the auth module" }],
},
})
```

## Model Provider Flexibility

OpenCode supports any provider via `opencode auth login`. Runners inherit the configured provider or override per-runner.

```bash
# Configure providers
opencode auth login # Interactive provider selection

# Override model per dispatch
opencode run -m openrouter/anthropic/claude-sonnet-4-20250514 "Task"
opencode run -m groq/llama-4-scout-17b-16e-instruct "Quick task"
```

Environment variables for non-interactive setup:

```bash
# Provider credentials (stored in ~/.local/share/opencode/auth.json)
opencode auth login

# Or set via environment
export ANTHROPIC_API_KEY="sk-ant-..."
export OPENAI_API_KEY="sk-..."
```

## Security

1. **Network**: Use `--hostname 127.0.0.1` (default) for local-only access
2. **Auth**: Set `OPENCODE_SERVER_PASSWORD` when exposing to network
3. **Permissions**: Use `OPENCODE_PERMISSION` env var for headless autonomy
4. **Credentials**: Never pass secrets in prompts - use environment variables
5. **Cleanup**: Delete sessions after use to prevent data leakage

### Autonomous Mode (CI/CD)

```bash
# Grant all permissions (only in trusted environments)
OPENCODE_PERMISSION='{"*":"allow"}' opencode run "Fix the failing tests"
```

## CI/CD Integration

### GitHub Actions

```yaml
name: AI Code Review
on:
pull_request:
types: [opened, synchronize]

jobs:
ai-review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install OpenCode
run: curl -fsSL https://opencode.ai/install | bash

- name: Run AI Review
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
OPENCODE_PERMISSION: '{"*":"allow"}'
run: |
opencode run --format json \
"Review the changes in this PR for security and quality. Output as markdown." \
> review.md
```

## Related

- `tools/ai-assistants/opencode-server.md` - Full server API reference
- `tools/ai-assistants/overview.md` - AI assistant comparison
- `scripts/runner-helper.sh` - Runner management CLI
- `scripts/cron-dispatch.sh` - Cron-triggered dispatch
- `scripts/cron-helper.sh` - Cron job management
- `scripts/coordinator-helper.sh` - Multi-agent coordination
- `scripts/mail-helper.sh` - Inter-agent mailbox
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Shift to progressive disclosure + file:line pointers.

This doc embeds many long CLI/SDK/HTTP examples. Per the documentation guidelines, keep this file as a high‑level index and point to authoritative sources (scripts or subagent docs) using file:line references. Move the detailed examples into the owning implementation/doc and link here.

📎 Example pattern (replace inline blocks with pointers)
-```bash
-# One-shot task
-opencode run "Review src/auth.ts for security issues"
-...
-```
+See file:.agent/scripts/runner-helper.sh:259-417 for the canonical CLI dispatch flow,
+and tools/ai-assistants/opencode-server.md for API-specific examples.

As per coding guidelines, .agent/**/*.md: Apply progressive disclosure pattern by using pointers to subagents rather than including inline content in agent documentation; include code examples only when authoritative; use file:line references to point to actual implementation instead of inline code snippets.

🤖 Prompt for AI Agents
In @.agent/tools/ai-assistants/headless-dispatch.md around lines 63 - 495, This
file contains lengthy inline CLI/SDK/HTTP examples under headings like "Dispatch
Methods" and "Parallel Execution"; replace those embedded blocks with
progressive-disclosure pointers to the canonical implementations (e.g.,
reference the dispatch flow in runner-helper.sh and API examples in
tools/ai-assistants/opencode-server.md using file:line style) and move the full
example content into the owning docs/scripts; apply this pattern across
`.agent/**/*.md` (remove large code fences under "Method 1/2/3/4", "Session
Management", "Parallel Execution", "Runners", and "CI/CD Integration" and
replace them with brief one-line pointers to the authoritative files you moved
the examples to).

Comment on lines +259 to +269
```text
~/.aidevops/.agent-workspace/runners/
├── code-reviewer/
│ ├── AGENTS.md # Runner personality/instructions
│ ├── config.json # Runner configuration
│ └── memory.db # Runner-specific memories (optional)
└── seo-analyst/
├── AGENTS.md
├── config.json
└── memory.db
```
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Runner directory layout should match runner-helper outputs.

The structure omits session.id and runs/, which are used by the script. Aligning these avoids operator confusion.

🧩 Suggested alignment
 ~/.aidevops/.agent-workspace/runners/
 ├── code-reviewer/
 │   ├── AGENTS.md      # Runner personality/instructions
 │   ├── config.json    # Runner configuration
+│   ├── session.id     # Last session ID (for --continue)
+│   └── runs/          # Run logs
 │   └── memory.db      # Runner-specific memories (optional)
📝 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.

Suggested change
```text
~/.aidevops/.agent-workspace/runners/
├── code-reviewer/
│ ├── AGENTS.md # Runner personality/instructions
│ ├── config.json # Runner configuration
│ └── memory.db # Runner-specific memories (optional)
└── seo-analyst/
├── AGENTS.md
├── config.json
└── memory.db
```
🤖 Prompt for AI Agents
In @.agent/tools/ai-assistants/headless-dispatch.md around lines 259 - 269,
Update the runner directory example so it matches the runner-helper script
output by adding the missing session.id file and runs/ directory to the
displayed tree (i.e., include "session.id" and a "runs/" entry under each runner
like code-reviewer and seo-analyst); edit the tree in the
.agent/tools/ai-assistants/headless-dispatch.md example block (the snippet
showing ~/.aidevops/.agent-workspace/runners/) so operators see the exact layout
produced by the script.

Comment on lines +1974 to 1980
**Status:** In Progress (Phase 2/5)
**Estimate:** ~3d (ai:1.5d test:1d read:0.5d)
**Source:** [alexfazio's X post on droids](https://gist.github.com/alexfazio/dcf2f253d346d8ed2702935b57184582)

<!--TOON:plan{id,title,status,phase,total_phases,owner,tags,est,est_ai,est_test,est_read,logged,started}:
p016,Parallel Agents & Headless Dispatch,planning,0,5,,agents|parallel|headless|dispatch|matrix|memory,3d,1.5d,1d,0.5d,2026-02-03T00:00Z,
p016,Parallel Agents & Headless Dispatch,in_progress,2,5,,agents|parallel|headless|dispatch|runners|memory,3d,1.5d,1d,0.5d,2026-02-03T00:00Z,2026-02-05T00:00Z
-->
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

TOON IDs collide with existing plans/milestones/decisions.

p016 is already used earlier (Install Script Integrity Hardening), and m064/d039 are already used in other plans. Duplicate IDs break TOON indexing and automation. Please renumber this plan block to the next available IDs and update its milestones/decisions consistently. Also align milestone naming with the runner rename (still says droid-helper.sh).

🔁 Suggested renumbering pattern
-<!--TOON:plan{id,title,status,phase,total_phases,owner,tags,est,est_ai,est_test,est_read,logged,started}:
-p016,Parallel Agents & Headless Dispatch,in_progress,2,5,,agents|parallel|headless|dispatch|runners|memory,3d,1.5d,1d,0.5d,2026-02-03T00:00Z,2026-02-05T00:00Z
--->
+<!--TOON:plan{id,title,status,phase,total_phases,owner,tags,est,est_ai,est_test,est_read,logged,started}:
+p019,Parallel Agents & Headless Dispatch,in_progress,2,5,,agents|parallel|headless|dispatch|runners|memory,3d,1.5d,1d,0.5d,2026-02-03T00:00Z,2026-02-05T00:00Z
+-->
@@
-<!--TOON:milestones[5]{id,plan_id,desc,est,actual,scheduled,completed,status}:
-m064,p016,Phase 1: Document headless dispatch patterns,4h,,2026-02-03T00:00Z,,pending
-m065,p016,Phase 2: Create droid-helper.sh,4h,,2026-02-03T00:00Z,,pending
+<!--TOON:milestones[5]{id,plan_id,desc,est,actual,scheduled,completed,status}:
+m095,p019,Phase 1: Document headless dispatch patterns,4h,,2026-02-03T00:00Z,,pending
+m096,p019,Phase 2: Create runner-helper.sh,4h,,2026-02-03T00:00Z,,pending
@@
-<!--TOON:decisions[4]{id,plan_id,decision,rationale,date,impact}:
-d039,p016,Local parallel sessions over containers/cloud,Zero hosting cost shared filesystem no sync needed,2026-02-03,Architecture
+<!--TOON:decisions[4]{id,plan_id,decision,rationale,date,impact}:
+d047,p019,Local parallel sessions over containers/cloud,Zero hosting cost shared filesystem no sync needed,2026-02-03,Architecture

Also applies to: 2080-2085, 2106-2109

🤖 Prompt for AI Agents
In `@todo/PLANS.md` around lines 1974 - 1980, The TOON plan block uses duplicate
IDs (p016, m064, d039) which collide with existing entries; update the plan
block's identifiers to the next free TOON IDs (e.g., replace p016 with a new
p### and update its related milestone/decision IDs m###/d###) and ensure the
same renumbering is applied to the other affected blocks (lines referenced in
the comment: 2080-2085 and 2106-2109) so all TOON tags are unique; also rename
any milestone/decision text that still references "droid-helper.sh" to the new
runner name to keep naming consistent (locate the TOON marker comment starting
with "<!--TOON:plan" and update IDs and text inside that block plus its matching
m/d entries).

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