JEO — Integrated Agent Orchestration
Keyword:jeo·annotate·UI-review·agentui (deprecated)| Platforms: Claude Code · Codex CLI · Gemini CLI · OpenCode Planning (plannotator) → Development (team/bmad) → QA (agent-browser + agentation) → Cleanup (worktree) with a persistent.jeoproject ledger
When to use this skill
- Run an end-to-end multi-agent workflow with an explicit planning gate
- Add a browser-backed UI feedback loop with
annotateorui-review - Coordinate plan approval, execution, verification, and cleanup in one skill
- Keep long-term rules, short-term system/test plans, active work items, and history in
.jeo/
Rules (always enforced)
- Do not reopen the PLAN gate when the current plan hash already has a terminal result
- Only a revised plan resets
plan_gate_statustopending - Do not process agentation annotations before explicit submit/onSubmit opens the submit gate
- NEVER enter EXECUTE without
plan_approved: true - NEVER run plannotator or agentation with
&(background) - NEVER reopen an unchanged plan after
approved,manual_approved,feedback_required, orinfrastructure_blocked
Authoritative state: .omc/state/jeo-state.json
State Management
All state operations use one script: scripts/jeo-state-update.py
# Initialize (or resume if state exists)
python3 scripts/jeo-state-update.py init "<task>"
# Record checkpoint at each step
python3 scripts/jeo-state-update.py checkpoint <plan|execute|verify|verify_ui|cleanup>
# Record error (auto-increments retry_count; warns at >= 3)
python3 scripts/jeo-state-update.py error "<message>"
# Check resume point
python3 scripts/jeo-state-update.py resume
# Set any field (supports dot notation for nested keys)
python3 scripts/jeo-state-update.py set phase execute
python3 scripts/jeo-state-update.py set agentation.active true.jeo Project Ledger
JEO keeps a human-readable project ledger in .jeo/ and a machine-readable state file in .omc/state/jeo-state.json.
| Path | Purpose |
|---|---|
.jeo/long-term.md | Durable product intent, standing rules, validation contract |
.jeo/short-term.md | Current system slice, unit-test plan, flow-test plan, exit criteria |
.jeo/planned.md | Planned queue and parking-lot items |
.jeo/progress.md | Current delivery stage and timestamped updates |
.jeo/history.md | Append-only completion summaries |
.jeo/tasks/queued/*.md | Queued work-item files |
.jeo/tasks/active/*.md | Single active work-item file (removed on completion after history is written) |
Use scripts/jeo-project-sync.py to keep the ledger in sync:
python3 scripts/jeo-project-sync.py init "<task>"
python3 scripts/jeo-project-sync.py queue api-contract "Harden API contract validation"
python3 scripts/jeo-project-sync.py start-next
python3 scripts/jeo-project-sync.py stage <planning|development|qa|done>
python3 scripts/jeo-project-sync.py progress "<message>"
python3 scripts/jeo-project-sync.py complete <slug> "<summary>"
python3 scripts/jeo-project-sync.py statusPhase mapping
| JEO phase | Delivery stage | .jeo expectation |
|---|---|---|
plan | planning | Review long-term.md, refine short-term.md, confirm the active work item |
execute | development | Update the active task checklist and append implementation notes to progress.md |
verify / verify_ui | qa | Record unit/flow/browser verification evidence in short-term.md and progress.md |
cleanup / done | done | Append to history.md, check off planned.md, remove the task file, queue follow-up work if needed |
Detailed ledger rules: references/DOT_JEO_LEDGER.md
Instructions
Execute steps in order. Each step only proceeds after the previous one completes.
STEP 0: Bootstrap
mkdir -p .omc/state .omc/plans .omc/logs
python3 scripts/jeo-state-update.py init "<detected task>"
python3 scripts/jeo-project-sync.py init "<detected task>"
python3 scripts/jeo-project-sync.py start-nextClaude Code only — hook self-check (run inline):
Verify the ExitPlanMode hook is using claude-plan-gate.py, not raw plannotator. If misconfigured, auto-repair:
import json, os, subprocess, sys
p = os.path.expanduser("~/.claude/settings.json")
if os.path.exists(p):
s = json.load(open(p))
for entry in s.get("hooks", {}).get("PermissionRequest", []):
if entry.get("matcher") == "ExitPlanMode":
for h in entry.get("hooks", []):
cmd = h.get("command", "")
if (cmd.strip() == "plannotator" or cmd.startswith("plannotator ")) and "claude-plan-gate" not in cmd:
print("[JEO][WARN] Hook uses raw plannotator — state tracking disabled. Auto-repairing...", file=sys.stderr)
for candidate in [
os.path.join(os.getcwd(), ".agent-skills/jeo/scripts/setup-claude.sh"),
os.path.expanduser("~/.claude/skills/jeo/scripts/setup-claude.sh"),
os.path.expanduser("~/.agent-skills/jeo/scripts/setup-claude.sh"),
]:
if os.path.exists(candidate):
subprocess.run(["bash", candidate], check=False)
print("[JEO] Hook repaired. Restart Claude Code to apply.", file=sys.stderr)
breakNotify the user:
"JEO activated. Delivery stage: planning..jeoledger initialized. Add theannotatekeyword if a UI feedback loop is needed."
STEP 1: PLAN / Planning (never skip)
python3 scripts/jeo-state-update.py checkpoint plan
python3 scripts/jeo-project-sync.py stage planning
python3 scripts/jeo-project-sync.py progress "Entered planning gate."- Review
.jeo/long-term.md,.jeo/short-term.md,.jeo/planned.md,.jeo/progress.md, and.jeo/history.mdbefore changing scope. - Write
plan.md(include goal, steps, risks, completion criteria, and the current planning/development/QA expectations from.jeo/short-term.md). - Update
.jeo/short-term.mdwith:
- the system slice for this run - the unit-test plan - the flow/browser verification plan
- Invoke plannotator (per platform): Claude Code (hook mode — only supported method): Codex / Gemini / OpenCode (blocking CLI):
# Skip if same plan hash already has terminal gate status # (check plan_gate_status and last_reviewed_plan_hash in jeo-state.json) # Resolve JEO scripts directory _JEO_SCRIPTS="" for _candidate in \ "${JEO_SKILL_DIR:-}/scripts" \ "$HOME/.agent-skills/jeo/scripts" \ "$HOME/.codex/skills/jeo/scripts" \ "$(pwd)/.agent-skills/jeo/scripts" \ "scripts"; do [-f "${_candidate}/plannotator-plan-loop.sh"] && _JEO_SCRIPTS="$_candidate" && break done # Auto-install plannotator if missing bash "${_JEO_SCRIPTS}/ensure-plannotator.sh" || exit 1 # Run blocking plan gate (no &) FEEDBACK_DIR=$(python3 -c "import hashlib,os; h=hashlib.md5(os.getcwd().encode()).hexdigest()[:8]; d=f'/tmp/jeo-{h}'; os.makedirs(d,exist_ok=True); print(d)") bash "${_JEO_SCRIPTS}/plannotator-plan-loop.sh" plan.md "${FEEDBACK_DIR}/plannotator_feedback.txt" 3
- Call EnterPlanMode → write plan content → call ExitPlanMode - The ExitPlanMode PermissionRequest hook fires plannotator automatically - Wait for the hook result before proceeding - NEVER call plannotator via MCP tool or CLI directly in Claude Code
- Check result:
- approved (exit 0) → set phase=execute, plan_approved=true → STEP 2 - Feedback (exit 10) → read feedback, revise plan.md, repeat step 2 - Infrastructure blocked (exit 32) → Conversation Approval Mode: output plan.md to user, ask "approve" or provide feedback. WAIT for user response - Session exited 3 times (exit 30/31) → ask user whether to abort
- When the plan is approved, append a note to
.jeo/progress.mddescribing what is ready to build and what QA must prove.
NEVER: enter EXECUTE without approved: true. NEVER: run with & background.
STEP 2: EXECUTE / Development
python3 scripts/jeo-state-update.py checkpoint execute
python3 scripts/jeo-state-update.py set phase execute
python3 scripts/jeo-project-sync.py stage development
python3 scripts/jeo-project-sync.py progress "Development started from the approved plan."Auto-detect team availability:
TEAM_AVAILABLE=false
if [[ "${CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS:-}" =~ ^(1|true|yes)$ ]]; then
TEAM_AVAILABLE=true
fi
python3 scripts/jeo-state-update.py set team_available $TEAM_AVAILABLECheck next_mode in state (set by claude-plan-gate.py on approval):
| Condition | Action |
|---|---|
next_mode == "ralphmode" | /omc:ralphmode "<task>" |
| Claude Code + omc + team | /omc:team 3:executor "<task>" |
| Claude Code without team | Error — run bash scripts/setup-claude.sh, enable AGENT_TEAMS=1, restart |
| Codex / Gemini / OpenCode | BMAD fallback: /workflow-init then /workflow-status |
While executing, keep the active .jeo/tasks/active/*.md file current using:
# When plan and risks are locked
python3 scripts/jeo-project-sync.py update-checklist planning "Scope captured in plan.md" --done
python3 scripts/jeo-project-sync.py update-checklist planning "Risks and completion criteria written" --done
# As code, docs, and tests are completed
python3 scripts/jeo-project-sync.py update-checklist development "System changes implemented" --done
python3 scripts/jeo-project-sync.py update-checklist development "Unit tests added or updated" --doneNEVER fall back to single-agent execution in Claude Code.
STEP 3: VERIFY / QA
python3 scripts/jeo-state-update.py checkpoint verify
python3 scripts/jeo-state-update.py set phase verify
python3 scripts/jeo-project-sync.py stage qa
python3 scripts/jeo-project-sync.py progress "Entered QA verification."- Browser verification with agent-browser (when browser UI is present):
agent-browser snapshot http://localhost:3000 annotatekeyword detected → enter STEP 3.1- Otherwise → enter STEP 4
- Record QA evidence in
.jeo/short-term.mdusing:python3 scripts/jeo-project-sync.py record-evidence "unit tests: X passing, Y added" python3 scripts/jeo-project-sync.py record-evidence "flow check: <description>" python3 scripts/jeo-project-sync.py record-evidence "browser verification: <outcome>" # Then mark QA checklist items complete python3 scripts/jeo-project-sync.py update-checklist qa "Flow or integration checks recorded" --done python3 scripts/jeo-project-sync.py update-checklist qa "Browser / annotation verification recorded when applicable" --done
STEP 3.1: VERIFY_UI (only when annotate keyword is detected)
Pre-flight check (all platforms):
if ! curl -sf --connect-timeout 2 http://localhost:4747/health >/dev/null 2>&1; then
echo "agentation-mcp not running — skipping VERIFY_UI, proceeding to CLEANUP"
python3 scripts/jeo-state-update.py error "agentation-mcp not running; VERIFY_UI skipped"
# Proceed to STEP 4 (graceful skip, no exit 1)
fiIf server is running:
- Set state:
phase=verify_ui,agentation.active=true,agentation.submit_gate_status=waiting_for_submit - Wait for explicit human submit — do NOT read
/pendingbefore submit
- Claude Code: wait for UserPromptSubmit hook - Others: wait until ANNOTATE_READY (or AGENTUI_READY alias)
- After submit → set
agentation.submit_gate_status=submitted - Process annotations:
- Claude Code (MCP): agentation_watch_annotations (blocking, batchWindowSeconds:10, timeoutSeconds:120) - Others (HTTP): poll GET http://localhost:4747/pending with timeout
- Per-annotation loop:
- acknowledge → navigate code via elementPath (CSS selector) → apply fix → resolve - Dismissed annotations: skip code changes, increment annotations.dismissed
count=0or timeout → proceed to STEP 4- If QA discovers follow-up work, add it immediately:
python3 scripts/jeo-project-sync.py queue follow-up "<new work item>"
NEVER: process draft annotations before submit/onSubmit.
STEP 4: CLEANUP
python3 scripts/jeo-state-update.py checkpoint cleanup
python3 scripts/jeo-state-update.py set phase cleanup
python3 scripts/jeo-project-sync.py stage done- Check for uncommitted changes (warn if present)
- Complete the active
.jeotask and write the permanent summary:python3 scripts/jeo-project-sync.py complete <slug> "<what shipped, what QA proved, what follow-up remains>" - If more work is needed, queue it before leaving cleanup:
python3 scripts/jeo-project-sync.py queue next-step "<follow-up work>" - Run worktree cleanup:
bash scripts/worktree-cleanup.sh || git worktree prune - Set
phase=done
Quick Start
# Install JEO
npx skills add https://github.com/akillness/oh-my-skills --skill jeo
# Full install (all tools + components)
bash scripts/install.sh --all
# Check status
bash scripts/check-status.sh
# Per-platform setup
bash scripts/setup-claude.sh # Claude Code hooks
bash scripts/setup-codex.sh # Codex CLI config
bash scripts/setup-gemini.sh # Gemini CLI hooks
bash scripts/setup-opencode.sh # OpenCode pluginPlatform Configuration
Claude Code
Hook config (~/.claude/settings.json):
{
"hooks": {
"PermissionRequest": [{
"matcher": "ExitPlanMode",
"hooks": [{"type": "command", "command": "python3 ~/.claude/skills/jeo/scripts/claude-plan-gate.py", "timeout": 1800}]
}],
"UserPromptSubmit": [{
"matcher": "*",
"hooks": [{"type": "command", "command": "python3 ~/.claude/skills/jeo/scripts/claude-agentation-submit-hook.py", "timeout": 300}]
}]
},
"mcpServers": {
"agentation": {"command": "npx", "args": ["-y", "agentation-mcp", "server"]}
}
}Codex CLI
Config (~/.codex/config.toml):
notify = ["python3", "~/.codex/hooks/jeo-notify.py"]
[tui]
notifications = ["agent-turn-complete"]developer_instructionsmust be a top-level string (not a[table]), or Codex fails withinvalid type: map, expected a string.
Gemini CLI
Instructions in ~/.gemini/GEMINI.md. AfterAgent hook as safety net in ~/.gemini/settings.json. Agent must call plannotator directly in blocking mode to receive feedback in the same turn.
OpenCode
Plugins in opencode.json. Slash commands: /jeo-plan, /jeo-exec, /jeo-annotate, /jeo-cleanup.
State File Reference
Path: {worktree}/.omc/state/jeo-state.json
| Field | Values | Description | |||||
|---|---|---|---|---|---|---|---|
phase | `plan\ | execute\ | verify\ | verify_ui\ | cleanup\ | done` | Current workflow phase |
delivery_stage | `planning\ | development\ | qa\ | done` | Human-readable stage mirrored into .jeo/progress.md | ||
plan_approved | bool | Whether plan was approved | |||||
plan_gate_status | `pending\ | approved\ | feedback_required\ | infrastructure_blocked\ | manual_approved` | Plan gate result | |
plan_current_hash | sha256 or null | Current plan.md hash | |||||
last_reviewed_plan_hash | sha256 or null | Hash of last reviewed plan | |||||
plan_review_method | `plannotator\ | manual\ | null` | How plan was approved | |||
team_available | bool | Whether team mode is available | |||||
retry_count | int | Error retry count (ask user at >= 3) | |||||
last_error | string or null | Most recent error | |||||
checkpoint | string or null | Last entered phase (for resume) | |||||
jeo.root | path | Project-local planning ledger root | |||||
jeo.active_task | string or null | Active .jeo work item slug | |||||
jeo.last_sync_at | ISO 8601 or null | Last .jeo sync timestamp | |||||
agentation.active | bool | Whether VERIFY_UI watch loop is running | |||||
agentation.submit_gate_status | `idle\ | waiting_for_submit\ | submitted` | Submit gate state | |||
agentation.exit_reason | `all_resolved\ | timeout\ | user_cancelled\ | error\ | null` | How watch loop ended |
Examples
Example 1: New feature with .jeo ledger
python3 scripts/jeo-project-sync.py init "Build exportable analytics dashboard"
python3 scripts/jeo-project-sync.py start-next
python3 scripts/jeo-project-sync.py stage planningThen run the normal JEO flow: plan approval → development → QA → cleanup. When done:
python3 scripts/jeo-project-sync.py complete 000-primary "Dashboard shipped with unit tests, flow checks, and browser verification."Example 2: Add follow-up work discovered during QA
python3 scripts/jeo-project-sync.py queue qa-follow-up "Fix chart legend overlap on small screens"
python3 scripts/jeo-project-sync.py progress "Queued QA follow-up from annotate review."Best practices
- Plan first: always review the plan with ralph+plannotator before executing (catches wrong approaches early)
- Team first: omc team mode is most efficient in Claude Code
- bmad fallback: use BMAD in environments without team (Codex, Gemini)
- Keep
.jeohonest: long-term is durable, short-term is current, history is append-only - One active task file: keep only one file under
.jeo/tasks/active/at a time - Complete means summarize + delete task file: write history first, then remove the task file
- Worktree cleanup: run
worktree-cleanup.shimmediately after work completes (prevents branch pollution) - State persistence: use
.omc/state/jeo-state.jsonand.jeo/together across sessions - annotate: use the
annotatekeyword to run the agentation watch loop for complex UI changes (precise code changes via CSS selector).agentuiis a backward-compatible alias.
Troubleshooting
| Issue | Solution |
|---|---|
| plannotator not running | JEO auto-runs ensure-plannotator.sh; if it fails: bash scripts/check-status.sh |
| plannotator not opening (Claude Code) | It's hook-only. Use EnterPlanMode → ExitPlanMode. Check: cat ~/.claude/settings.json |
| Same plan re-reviewed (Codex) | Compare last_reviewed_plan_hash with current plan.md hash — skip if match + terminal status |
| Codex startup failure | Re-run bash scripts/setup-codex.sh — developer_instructions must be a top-level string |
| team mode not working | Run bash scripts/setup-claude.sh, restart Claude Code, verify AGENT_TEAMS=1 |
| agentation not opening | Check curl http://localhost:4747/health and /sessions |
| annotation not in code | Include summary field when calling agentation_resolve_annotation |
.jeo not updating | Run python3 scripts/jeo-project-sync.py status and ensure .jeo/ exists at the git root |
| worktree conflict | git worktree prune && git worktree list |
References
- oh-my-claudecode — Claude Code multi-agent
- plannotator — visual plan/diff review
- BMAD Method — structured AI development workflow
- Agent Skills Spec — skill format specification
- agentation — UI annotation → agent code fix (
annotate;agentuibackward compatible) .jeoledger reference — project-local planning, development, and QA ledger