Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -646,3 +646,9 @@ of the plan.
routes explicitly to the vendored doperpowers:execplan doctrine (one
self-contained plan, executed in-thread by the worker itself) and both
blocks forbid sub-agent/collab fan-out by name.
- 2026-07-17: the two per-engine execution blocks described above collapsed
into one `references/engine-blocks/execution.md` — implement/spike workers
migrated to the one-harness model (Claude-harness daemon; engine label =
model route via the clodex gateway), so the codex-CLI block and its
vendored-doctrine routing no longer exist. See
`docs/doperpowers/execplans/2026-07-17-implement-worker-clodex-migration.md`.
13 changes: 13 additions & 0 deletions docs/doperpowers/specs/2026-07-10-codex-workers-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -731,3 +731,16 @@ mechanical rather than lucky.
**superseded** by `specs/2026-07-12-native-review-recovery-design.md`:
one native `codex exec review` engine for both species, owned by a
substrate script.
- 2026-07-17: The codex-CLI implement/spike worker species this spec created
is **retired from dispatch** (ExecPlan:
`docs/doperpowers/execplans/2026-07-17-implement-worker-clodex-migration.md`).
The dispatch ritual now spawns every implement/spike worker as a
Claude-harness daemon via `daemon-spawn.sh`; the engine label survives as
a model ROUTE (`codex` = clodex gateway settings/GPT models,
`claude` = plain Claude models), mirroring the review loop's 2026-07-15
migration. The per-engine execution blocks collapsed into one
`references/engine-blocks/execution.md` (the `.agents/skills`
vendored-doctrine pointer was codex-CLI-only and is gone with it).
`codex-spawn.sh`/`codex-resume.sh` and the codex read/kill paths remain
as legacy machinery for existing bound sessions; full deletion is a
separate follow-up.
7 changes: 4 additions & 3 deletions skills/implementing-tickets/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ audit trail, not requests. Full design + rationale:
| `references/implement-worker-protocol.md` | the Implement Worker Protocol — rendered (`{{PLACEHOLDERS}}`) into every spawn prompt |
| `references/spike-worker-protocol.md` | the Spike Worker Protocol — rendered instead when the ticket's category is `spike` (the exploration lane below) |
| `references/implement-decompose.md` | runtime-opened decomposition procedure — the protocol carries only a pointer (`{{DECOMPOSE_DOC}}` = absolute path); the worker opens it when Check-2 says decompose. Conditional-large protocol blocks live this way: procedure in a plugin file, instance facts in the prompt |
| `references/engine-blocks/` | per-engine EXECUTION text (claude: TDD/execplan skills; codex: the same discipline via the vendored `.agents/skills` doctrine) — both keep interactive-session skills (writing-plans, subagent-driven-development) out of daemon workers; composed into the protocol at render time (implement protocol only — spikes are exploration, not TDD) |
| `references/engine-blocks/execution.md` | the EXECUTION text — one block for both model routes, since every worker is a Claude-harness session (the engine label picks the model route: `codex` = clodex gateway/GPT, `claude` = plain Claude); keeps interactive-session skills (writing-plans, subagent-driven-development) out of daemon workers; composed into the protocol at render time (implement protocol only — spikes are exploration, not TDD) |
| The Ticket Gate | the pre-code pass/park verdict (below) |
| board schema + dispatch ritual | owned by doperpowers:issue-tracker (states, scripts, the mechanical ritual, the wake ritual) |
| `scripts/` | empty this phase — the auto-attach trigger (`implement-dispatch.sh` + workflow template) lands here next phase |
Expand Down Expand Up @@ -141,8 +141,9 @@ What changes and what doesn't:
registered `--spawned-by <spike>` with honest gate-triage against the
IMPLEMENT gate; murkier outcomes stay a Recommendation line for the
human.
- Research-heavy spikes often want `engine:claude` (web reach); the label
mechanism is unchanged.
- The engine label picks a model route only (web reach is harness-level —
every worker has it); choose per the work's model fit, mechanism
unchanged.
- Category labels are plain words by design (`bug`/`enhancement` always
were) — in a consumer repo that already used a descriptive `spike`
label, existing tickets carrying it now read as spike-lane tickets:
Expand Down

This file was deleted.

23 changes: 15 additions & 8 deletions skills/issue-tracker/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,10 @@ pick by repo visibility:
normal. Derived from GitHub PR state on every snapshot — never a label,
never auto-closed.
2. Resolve the ENGINE — ticket label `engine:claude`/`engine:codex` →
`$WORKER_ENGINE` → default `codex`. Render the worker protocol
`$WORKER_ENGINE` → default `codex`. Every worker is ONE species — a
Claude-harness daemon; the engine names only its model route (`codex` =
the clodex gateway settings, GPT models through the local proxy;
`claude` = plain Claude models). Render the worker protocol
(`doperpowers:implementing-tickets`): category `spike` →
`references/spike-worker-protocol.md`, else
`references/implement-worker-protocol.md`. Substitute every
Expand All @@ -149,17 +152,21 @@ pick by repo visibility:
issue body from `gh issue view <n> --json body`, `ENGINE_NAME` = the
engine, `REPO_FACTS` = `git show origin/<default-branch>:.doperpowers/repo-facts.md`
(or a "(no repo-facts manifest)" note when absent), and — implement
protocol only — `EXECUTION_BLOCK` = the engine's
`references/engine-blocks/execution-<engine>.md` and `DECOMPOSE_DOC` =
the ABSOLUTE path of implementing-tickets'
protocol only — `EXECUTION_BLOCK` = implementing-tickets'
`references/engine-blocks/execution.md` (one block, both routes) and
`DECOMPOSE_DOC` = the ABSOLUTE path of implementing-tickets'
`references/implement-decompose.md` (a runtime-opened procedure: the
prompt carries only the pointer; the worker opens it when Check-2
says decompose).
3. codex: `codex-spawn.sh "<n>-<slug>" "<prompt>" <repo> <worktree-name>`
(model/effort default gpt-5.6-sol/high — override with
`$CODEX_MODEL` / `$CODEX_EFFORT` as args 5–6). claude:
`daemon-spawn.sh "<n>-<slug>" "<prompt>" <repo> <worktree-name>`. Both
3. Spawn via `daemon-spawn.sh "<n>-<slug>" "<prompt>" <repo> <worktree-name>`
from `orchestrating-daemons` — always a worktree; workers write code.
The codex route prefixes the gateway env and pins the gateway's model
alias as arg 5:
`DAEMON_CLAUDE_SETTINGS="${CLODEX_SETTINGS:-$HOME/.claude/clodex-settings.json}" DAEMON_CLAUDE_EFFORT="${CLODEX_EFFORT:-xhigh}" daemon-spawn.sh … fable`
(daemon-spawn persists settings/effort into the registry meta;
daemon-resume restores them on every fork — without that a gateway
worker silently reverts to plain models on its first resume). The
claude route passes no gateway env; the model inherits unless pinned.
4. `board-bind.sh <uuid> <n>`. Write NOTHING else: the worker's first board
write is its gate verdict — `in-progress` (+ a `[gate]` comment) means
the gate passed; a park state means it failed.
Expand Down
8 changes: 4 additions & 4 deletions skills/orchestrating-daemons/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ description: Use when spawning, resuming, tracking, or debugging durable backgro

## Overview

A **daemon** is a durable background `claude` session, spawned with `claude --bg` so it runs as its own process, is visible in `claude agents`, and survives this session ending. The substrate drives two engines under one registry: `claude --bg` daemons and detached `codex exec` workers (`engine: codex` in the meta) — the board pipeline picks per dispatch (label → `WORKER_ENGINE` → codex). This skill is the *substrate*: the scripts that spawn, resume, track, and retire daemons, and the mechanics that make those operations safe. It is not an orchestration doctrine — the fleets that used to be driven from here now live in the board pipeline, where workers escalate via park states and nobody judges their turn-ends.
A **daemon** is a durable background `claude` session, spawned with `claude --bg` so it runs as its own process, is visible in `claude agents`, and survives this session ending. The board pipeline dispatches Claude-harness daemons only; its engine label picks the model ROUTE of the spawn (`codex` = the clodex gateway settings via `DAEMON_CLAUDE_SETTINGS`, GPT models through the local proxy; `claude` = plain Claude models). Detached `codex exec` workers (`engine: codex` in the meta) are a **legacy species**: existing registry metas stay readable, resumable, and retirable, but no pipeline path creates new ones. This skill is the *substrate*: the scripts that spawn, resume, track, and retire daemons, and the mechanics that make those operations safe. It is not an orchestration doctrine — the fleets that used to be driven from here now live in the board pipeline, where workers escalate via park states and nobody judges their turn-ends.

**Where work goes** (decide this before spawning anything):

Expand Down Expand Up @@ -36,8 +36,8 @@ Paths are relative to this skill's directory. The scripts hide every sharp edge
| `daemon-list.sh [status]` | Fleet view; optional status filter. |
| `daemon-mark.sh <id> <status> [note]` | Record a judgment state (`awaiting-human`, `done`) + why. |
| `daemon-retire.sh <id> [purge]` | Drop from active fleet; transcript stays resumable. |
| `codex-spawn.sh [--no-wait] <name> <task> [cwd] [worktree] [model] [effort]` | Spawn a detached `codex exec --json` worker into the same registry (`engine: codex`, pid liveness). Defaults gpt-5.6-sol/high. Launch in a bg shell. |
| `codex-resume.sh <id> <message>` | Continue a codex daemon (`codex exec resume` — same session id, no forking). Launch in a bg shell. |
| `codex-spawn.sh [--no-wait] <name> <task> [cwd] [worktree] [model] [effort]` | LEGACY — retired from board dispatch (no pipeline path spawns codex-CLI workers; kept until no bound codex sessions remain). Spawns a detached `codex exec --json` worker into the same registry (`engine: codex`, pid liveness). |
| `codex-resume.sh <id> <message>` | Continue a LEGACY codex daemon (`codex exec resume` — same session id, no forking). Launch in a bg shell. |

## Driving an ad-hoc daemon by hand

Expand Down Expand Up @@ -87,7 +87,7 @@ A daemon also goes `blocked` when it calls **AskUserQuestion** — headless, nob

A daemon can also block on a **harness permission prompt** that holds a tool call before it ever reaches the transcript (observed live: an AskUserQuestion call stuck at the permission layer). The recorded reply then carries a `[blocked on a harness prompt …]` marker instead of a rendered question — the daemon's last text states what it wanted; resume with your answer/instruction (the pending call is interrupted), or `claude attach` the session to approve it interactively.

Codex workers get the same posture, spelled differently: `--sandbox
Legacy codex workers get the same posture, spelled differently: `--sandbox
workspace-write` plus the approvals auto-reviewer (`-c
approval_policy=on-request -c approvals_reviewer=…`) — safe ops continue,
genuinely unsafe escalations are declined in-flight (fail-closed). A codex
Expand Down
19 changes: 14 additions & 5 deletions skills/orchestrating-daemons/scripts/daemon-finalize.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,14 @@ case "$status" in working|blocked) ;; *) echo "noop"; exit 0 ;; esac

cur="$(_meta_get "$uuid" current)"; [ -n "$cur" ] || cur="$uuid"
# `state` alone lies for a finished session whose harness process lingers —
# it stays "working" indefinitely. `status` is the turn signal (busy while a
# turn runs, idle after); normalize the lingering shape to done before the
# case table. Observed live 2026-07-15 on a finished review worker.
# it stays "working" (observed live 2026-07-15 on a finished review worker)
# or "blocked" (observed live 2026-07-17 on a cleanly-parked gateway implement
# worker) indefinitely. `status` is the turn signal (busy while a turn runs,
# idle after); normalize both lingering shapes before the case table. An ended
# blocked-shape turn finalizes through the blocked reply renderer: when the
# transcript ends on a pending AskUserQuestion the question surfaces in the
# reply, otherwise the recorded reply is the turn text with the harness-prompt
# marker — either way the session is over and resumable.
state="$(claude agents --json --all 2>/dev/null | CUR="$cur" python3 -c '
import json, os, sys
try:
Expand All @@ -39,8 +44,8 @@ except Exception:
for r in rows:
if r.get("sessionId") == os.environ["CUR"]:
st = r.get("state") or ""
if st == "working" and r.get("status") == "idle":
st = "done"
if r.get("status") == "idle" and st in ("working", "blocked"):
st = "done" if st == "working" else "done-blocked"
print(st)
break
')"
Expand All @@ -52,6 +57,10 @@ case "$state" in
_record_reply "$cur" "$uuid" "done"
_meta_set "$uuid" status "idle" updated "$(_now)"
echo "idle" ;;
done-blocked)
_record_reply "$cur" "$uuid" "blocked"
_meta_set "$uuid" status "idle" updated "$(_now)"
echo "idle" ;;
error|stopped)
_record_reply "$cur" "$uuid" "$state"
_meta_set "$uuid" status "error" updated "$(_now)"
Expand Down
34 changes: 30 additions & 4 deletions skills/reviewing-prs/scripts/land-dispatch.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,16 @@
# Env:
# LOCAL_REPO canonical local clone of the target repo (default: $PWD)
# BOARD_REPO owner/name (default: resolved from LOCAL_REPO via gh)
# WORKER_ENGINE claude|codex (default codex); an engine:* PR label wins
# LAND_MODEL optional claude model override for the land daemon
# WORKER_ENGINE which MODEL ROUTE the land daemon uses: codex|claude
# (default codex). Every worker is a Claude-harness daemon;
# "codex" rides the clodex gateway settings (GPT models via
# the local proxy), "claude" = plain Claude models. An
# engine:* PR label wins over the env.
# CLODEX_SETTINGS gateway settings file for the codex route
# (default ~/.claude/clodex-settings.json)
# CLODEX_EFFORT reasoning effort for the codex route (default xhigh)
# LAND_MODEL optional model override for the land daemon (gateway
# route defaults to fable, claude route to inherit)
# LAND_ENABLED staged rollout (default false = DRY-RUN mode: the worker
# analyzes and posts what it WOULD do; merges nothing)
# BOARD_SCRIPTS issue-tracker scripts dir override (tests)
Expand Down Expand Up @@ -177,7 +185,18 @@ if [ -n "$meta" ]; then
case "$status" in
working|blocked)
if _is_live "$current" "$w_engine" "$w_pid" "$w_host" "$w_boot"; then
echo "#$pr: skip active land worker"; exit 0
if [ "$w_engine" = "codex" ]; then
echo "#$pr: skip active land worker"; exit 0
fi
# A claude-species lander has no self-finalizer: a finished turn
# lingers status=working while its session stays visible in
# `claude agents`. Finalize first (as review-dispatch does) — only
# a genuinely live turn is an active worker; anything else
# (idle/error/absent/noop) is a finished lander to retire.
fin="$("$DAEMON_SCRIPTS/daemon-finalize.sh" "$uuid" 2>/dev/null || true)"
if [ "$fin" = "live" ]; then
echo "#$pr: skip active land worker"; exit 0
fi
fi
_retire "$uuid" ;;
*) _retire "$uuid" ;; # finished/retired — an explicit dispatch is a fresh signal
Expand Down Expand Up @@ -286,8 +305,15 @@ PY
)" || { rm -rf "$control_dir"; die "#$pr: prompt render failed"; }
[ -n "$prompt" ] || { rm -rf "$control_dir"; die "#$pr: empty prompt — not dispatching"; }

# ONE worker species, two model routes (mirrors review-dispatch.sh): the
# default "codex" engine is a GATEWAY worker — the same Claude-harness daemon
# pointed at the local gateway (GPT models) via --settings. engine:claude
# opts a PR into plain Claude models. No path spawns a codex-CLI worker.
if [ "$engine" = "codex" ]; then
spawn_out="$("$DAEMON_SCRIPTS/codex-spawn.sh" --no-wait "land-pr-$pr" "$prompt" "$wt" "")" \
spawn_out="$(DAEMON_CLAUDE_SETTINGS="${CLODEX_SETTINGS:-$HOME/.claude/clodex-settings.json}" \
DAEMON_CLAUDE_EFFORT="${CLODEX_EFFORT:-xhigh}" \
"$DAEMON_SCRIPTS/daemon-spawn.sh" --no-wait "land-pr-$pr" "$prompt" "$wt" "" \
"${LAND_MODEL:-fable}")" \
|| { rm -rf "$control_dir"; die "#$pr: land worker spawn failed"; }
else
spawn_out="$("$DAEMON_SCRIPTS/daemon-spawn.sh" --no-wait "land-pr-$pr" "$prompt" "$wt" "" "${LAND_MODEL:-}")" \
Expand Down
Loading