← back to Ticket System
keep Codex ticket loop running overnight
daa6624c81aef5d87cb3a2aafdf0f4978169c70e · 2026-08-31 02:29:55 -0700 · Steve Abrams
Files touched
M .gitignoreA CODEX-YOLOFOREVER.mdA com.steve.codex-yoloforever.plistA scripts/codex-yoloforever-prompt.mdA scripts/codex-yoloforever.shA verification/codex-yoloforever-e2e-proof.json
Diff
commit daa6624c81aef5d87cb3a2aafdf0f4978169c70e
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Mon Aug 31 02:29:55 2026 -0700
keep Codex ticket loop running overnight
---
.gitignore | 1 +
CODEX-YOLOFOREVER.md | 17 +++++
com.steve.codex-yoloforever.plist | 35 +++++++++
scripts/codex-yoloforever-prompt.md | 17 +++++
scripts/codex-yoloforever.sh | 100 ++++++++++++++++++++++++++
verification/codex-yoloforever-e2e-proof.json | 29 ++++++++
6 files changed, 199 insertions(+)
diff --git a/.gitignore b/.gitignore
index 3608ca56..772d0548 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
node_modules/
data/yolo-ticket-sync.json
+data/codex-yoloforever/
yolo-ticket-sync.out.log
yolo-ticket-sync.err.log
.env*
diff --git a/CODEX-YOLOFOREVER.md b/CODEX-YOLOFOREVER.md
new file mode 100644
index 00000000..ce036fa4
--- /dev/null
+++ b/CODEX-YOLOFOREVER.md
@@ -0,0 +1,17 @@
+# Codex YOLO Forever
+
+Local unattended Codex ticket loop, scheduled every 10 minutes by launchd. Each invocation is bounded and overlap-safe; the next launch is skipped while a cycle owns the atomic lock.
+
+```sh
+scripts/codex-yoloforever.sh status
+scripts/codex-yoloforever.sh stop
+scripts/codex-yoloforever.sh start
+scripts/codex-yoloforever.sh unlock
+scripts/codex-yoloforever.sh uninstall
+tail -f codex-yoloforever.log
+```
+
+`stop` places a durable sentinel and disables future launchd starts. It lets an active cycle finish rather than interrupting a possibly half-completed operation. `start` removes the sentinel, enables the agent, loads it if needed, and kicks one cycle.
+If a machine crash leaves the atomic lock behind, `unlock` removes it only when launchd does not report the job running.
+
+The prompt requires a fresh canonical ticket snapshot, DTD selection, canonical-owner execution, Cody's adversarial gate, final DTD, empirical E2E proof, ticket logging, and a JSONL loop ledger. It preserves all normal approval gates. The only carried production approval is the exact TK-10993 scope recorded in the prompt; Track C and E retain their additional proof/order constraints.
diff --git a/com.steve.codex-yoloforever.plist b/com.steve.codex-yoloforever.plist
new file mode 100644
index 00000000..a58bf4d5
--- /dev/null
+++ b/com.steve.codex-yoloforever.plist
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>Label</key>
+ <string>com.steve.codex-yoloforever</string>
+ <key>ProgramArguments</key>
+ <array>
+ <string>/bin/zsh</string>
+ <string>/Users/macstudio3/Projects/ticket-system/scripts/codex-yoloforever.sh</string>
+ <string>run</string>
+ </array>
+ <key>WorkingDirectory</key>
+ <string>/Users/macstudio3/Projects/ticket-system</string>
+ <key>RunAtLoad</key>
+ <true/>
+ <key>StartInterval</key>
+ <integer>600</integer>
+ <key>ProcessType</key>
+ <string>Background</string>
+ <key>EnvironmentVariables</key>
+ <dict>
+ <key>HOME</key>
+ <string>/Users/macstudio3</string>
+ <key>PATH</key>
+ <string>/Users/macstudio3/.local/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
+ <key>TK_AGENT</key>
+ <string>codex-yoloforever</string>
+ </dict>
+ <key>StandardOutPath</key>
+ <string>/Users/macstudio3/Projects/ticket-system/codex-yoloforever.launchd.out.log</string>
+ <key>StandardErrorPath</key>
+ <string>/Users/macstudio3/Projects/ticket-system/codex-yoloforever.launchd.err.log</string>
+</dict>
+</plist>
diff --git a/scripts/codex-yoloforever-prompt.md b/scripts/codex-yoloforever-prompt.md
new file mode 100644
index 00000000..2d349016
--- /dev/null
+++ b/scripts/codex-yoloforever-prompt.md
@@ -0,0 +1,17 @@
+You are one bounded cycle of Steve's unattended `/yoloforever` open-ticket loop. Use Codex only; never invoke `claude`, `claude -p`, or the remote Claude YOLO service.
+
+This cycle has a maximum of six execution iterations and must terminate cleanly so launchd can schedule the next cycle. Follow `/yoloforever`, `/ticketmaster`, `/dtd`, `/contrarian` (Cody), `/a2a-contract`, and `/e2e-proof` exactly. Read each selected skill's complete SKILL.md before acting.
+
+1. Set `TK_AGENT=codex-yoloforever`. Read `tk inbox`, then take a fresh ticketmaster snapshot from the canonical `~/.claude/tickets/events.jsonl`. Do not trust a prior ranking.
+2. Exclude work owned by an active agent/session, work that collides with a dirty worktree, and any item whose next step is gated. Select the highest-value safe, reversible, non-colliding open item. Take or resume its canonical ticket and continuously log material actions and correlation evidence there.
+3. Run DTD to choose the exact bounded increment. Then route execution through the canonical owner. Delegation never widens authority; follow the A2A contract and independently verify any handoff.
+4. Invoke Cody the Contrarian on the actual result. Reproduce each claimed defect before promoting it.
+5. Run a final DTD forced choice: SHIP, FIX-THEN-SHIP, HOLD-FOR-STEVE, or KILL. Apply only reproduced, safe, reversible fixes.
+6. End with empirical E2E proof appropriate to the changed boundary. Web/UI work requires CTA plus screenrecord as `/yoloforever` specifies; non-UI work requires the real canary/API/test flow. Write reusable evidence and log it to the ticket and loop ledger.
+7. Append a concise cycle record to `/Users/macstudio3/Projects/ticket-system/data/codex-yoloforever/ledger.jsonl`: timestamp, ticket, action, DTD verdict, Cody verdict/top fix, final DTD verdict, tests/evidence, next seed, gated memos, cost. Use a safe file append mechanism. Then exit; launchd supplies the next cycle.
+
+HARD GATES: never perform customer-facing, destructive/irreversible, spend/money, identity, DNS/domain, publish, send-to-list, remote push, production deploy/write, canonical `dw_unified`, Shopify, or Merchant Center write unless that exact action has explicit current approval. Draft such actions to `~/.claude/yolo-queue/pending-approval/` and proceed only with a conservative safe default. Do not interpret “dangerous mode” as permission to bypass these gates.
+
+The only carried approval is TK-10993 Tracks A/B/C/D/E exactly as previously scoped. It does not extend to any other ticket or action. Track C remains HOLD until a newly rebuilt canary has immutable 400/400 identity-bearing baseline proof. Track E may run only in its revised scoped form after A/B and a fresh preflight. Re-enumerate/dedupe Track D immediately before any approved execution. If these constraints are not satisfied, do not execute the corresponding external write.
+
+Pause safely rather than spin if two consecutive cycles have zero new verified progress and only gated work remains, or if a hard safety/cost/canary tripwire fires. Never send email or messages externally. Keep spend at $0 unless Steve separately and explicitly approves a named spend.
diff --git a/scripts/codex-yoloforever.sh b/scripts/codex-yoloforever.sh
new file mode 100755
index 00000000..235f7791
--- /dev/null
+++ b/scripts/codex-yoloforever.sh
@@ -0,0 +1,100 @@
+#!/bin/zsh
+set -u
+
+ROOT="/Users/macstudio3/Projects/ticket-system"
+LABEL="com.steve.codex-yoloforever"
+STATE_DIR="$ROOT/data/codex-yoloforever"
+LOCK_DIR="$STATE_DIR/cycle.lock"
+STOP_FILE="$STATE_DIR/STOPPED"
+PROMPT_FILE="$ROOT/scripts/codex-yoloforever-prompt.md"
+LOG_FILE="$ROOT/codex-yoloforever.log"
+ERR_FILE="$ROOT/codex-yoloforever.err.log"
+LAST_MESSAGE="$STATE_DIR/last-message.md"
+CODEX="/Users/macstudio3/.local/bin/codex"
+PLIST="$ROOT/com.steve.codex-yoloforever.plist"
+DOMAIN="gui/$(id -u)"
+
+mkdir -p "$STATE_DIR"
+
+status() {
+ local loaded="no" running="no" stopped="no" pid=""
+ launchctl print "$DOMAIN/$LABEL" >/dev/null 2>&1 && loaded="yes"
+ if [[ -d "$LOCK_DIR" ]]; then
+ pid="$(cat "$LOCK_DIR/pid" 2>/dev/null || true)"
+ running="lock-held"
+ fi
+ [[ -f "$STOP_FILE" ]] && stopped="yes"
+ print "label=$LABEL loaded=$loaded running=$running stopped=$stopped pid=${pid:-none}"
+ [[ -f "$STATE_DIR/last-started-at" ]] && print "last_started=$(cat "$STATE_DIR/last-started-at")"
+ [[ -f "$STATE_DIR/last-finished-at" ]] && print "last_finished=$(cat "$STATE_DIR/last-finished-at")"
+ [[ -f "$STATE_DIR/last-exit" ]] && print "last_exit=$(cat "$STATE_DIR/last-exit")"
+}
+
+run_cycle() {
+ if [[ -f "$STOP_FILE" ]]; then
+ print "$(date -u +%FT%TZ) stopped sentinel present; cycle skipped" >> "$LOG_FILE"
+ return 0
+ fi
+
+ if ! mkdir "$LOCK_DIR" 2>/dev/null; then
+ local old_pid="$(cat "$LOCK_DIR/pid" 2>/dev/null || true)"
+ print "$(date -u +%FT%TZ) overlap prevented; lock owner pid=${old_pid:-unknown}" >> "$LOG_FILE"
+ return 0
+ fi
+
+ print $$ > "$LOCK_DIR/pid"
+ date -u +%FT%TZ > "$LOCK_DIR/started-at"
+ cp "$LOCK_DIR/started-at" "$STATE_DIR/last-started-at"
+ trap 'rm -f "$LOCK_DIR/pid" "$LOCK_DIR/started-at"; rmdir "$LOCK_DIR" 2>/dev/null || true' EXIT INT TERM HUP
+
+ print "$(date -u +%FT%TZ) cycle begin pid=$$ engine=codex" >> "$LOG_FILE"
+ TK_AGENT=codex-yoloforever "$CODEX" exec \
+ --approve-for-me \
+ --cd /Users/macstudio3 \
+ --add-dir /private/tmp \
+ --skip-git-repo-check \
+ --color never \
+ --output-last-message "$LAST_MESSAGE" \
+ - < "$PROMPT_FILE" >> "$LOG_FILE" 2>> "$ERR_FILE"
+ local rc=$?
+ print "$rc" > "$STATE_DIR/last-exit"
+ date -u +%FT%TZ > "$STATE_DIR/last-finished-at"
+ print "$(date -u +%FT%TZ) cycle end pid=$$ exit=$rc" >> "$LOG_FILE"
+ return "$rc"
+}
+
+case "${1:-run}" in
+ run) run_cycle ;;
+ status) status ;;
+ stop)
+ date -u +%FT%TZ > "$STOP_FILE"
+ launchctl disable "$DOMAIN/$LABEL" >/dev/null 2>&1 || true
+ print "stopped $LABEL; active cycle, if any, is allowed to finish safely"
+ status
+ ;;
+ start)
+ rm -f "$STOP_FILE"
+ launchctl enable "$DOMAIN/$LABEL"
+ if ! launchctl print "$DOMAIN/$LABEL" >/dev/null 2>&1; then
+ launchctl bootstrap "$DOMAIN" "$PLIST"
+ fi
+ launchctl kickstart "$DOMAIN/$LABEL"
+ print "started $LABEL"
+ status
+ ;;
+ uninstall)
+ date -u +%FT%TZ > "$STOP_FILE"
+ launchctl bootout "$DOMAIN/$LABEL" >/dev/null 2>&1 || true
+ print "unloaded $LABEL; project files retained"
+ ;;
+ unlock)
+ if launchctl print "$DOMAIN/$LABEL" 2>/dev/null | grep -q 'state = running'; then
+ print -u2 "refusing unlock while launchd reports the job running"
+ exit 1
+ fi
+ rm -f "$LOCK_DIR/pid" "$LOCK_DIR/started-at" 2>/dev/null || true
+ rmdir "$LOCK_DIR" 2>/dev/null || true
+ print "cleared inactive lock"
+ ;;
+ *) print -u2 "usage: $0 {run|status|start|stop|unlock|uninstall}"; exit 2 ;;
+esac
diff --git a/verification/codex-yoloforever-e2e-proof.json b/verification/codex-yoloforever-e2e-proof.json
new file mode 100644
index 00000000..4c5b1e95
--- /dev/null
+++ b/verification/codex-yoloforever-e2e-proof.json
@@ -0,0 +1,29 @@
+{
+ "intent": "Keep a bounded Codex-only yoloforever open-ticket cycle running unattended under launchd with DTD and Cody gates",
+ "risk_tier": "R3 local agent/service automation with ticket state",
+ "environment": "macOS gui/501, /Users/macstudio3/Projects/ticket-system",
+ "timestamp": "2026-08-31T09:26:00Z",
+ "ticket": "TK-10993",
+ "baseline": {
+ "existing_remote_monitor_reused": false,
+ "reason": "com.steve.yolo-ticket-sync monitors a remote Claude service and cannot satisfy Codex-only execution",
+ "initial_job_loaded": false
+ },
+ "checks": [
+ {"boundary":"config","assertion":"runner parses, plist validates, patch has no whitespace errors","verdict":"PASS"},
+ {"boundary":"launchd","assertion":"job loaded from ~/Library/LaunchAgents, runs every 600 seconds, and reports state=running","evidence":"launchctl print: pid 72498, runs=3, run interval=600 seconds","verdict":"PASS"},
+ {"boundary":"Codex consumer","assertion":"service invokes codex exec rather than Claude","evidence":"cycle begin pid=72498 engine=codex; Codex SessionStart/UserPromptSubmit hooks","verdict":"PASS"},
+ {"boundary":"duplicate delivery","assertion":"concurrent invocation does not start a second cycle","evidence":"overlap prevented; lock owner pid=72498","verdict":"PASS"},
+ {"boundary":"operator stop/retry","assertion":"stop creates sentinel/disables future launches; start clears sentinel/enables job while preserving active lock","verdict":"PASS"},
+ {"boundary":"safety policy","assertion":"fresh snapshot, DTD, Cody, final DTD, empirical E2E, ledger, exact TK-10993 limits, and unrelated hard gates encoded","verdict":"PASS"},
+ {"boundary":"overnight continuity","assertion":"system and display sleep are prevented","evidence":"caffeinate -dimsu pid 1148; sleep=0 and displaysleep=0","verdict":"PASS"}
+ ],
+ "negative_checks": [
+ "Initial incompatible CLI flags and git trust errors were corrected before verified invocation",
+ "No overlap allowed while cycle lock existed",
+ "No STOPPED sentinel remains after restart"
+ ],
+ "retained_state": "LaunchAgent loaded and enabled; first verified Codex cycle intentionally remains active",
+ "rollback": "stop disables future launches without interrupting active work; uninstall bootouts job and retains project files",
+ "verdict": "PASS"
+}
← 7445e60c Measure ticket runtime from latest status change
·
back to Ticket System
·
record TK-10902 reconciliation proof 43b11230 →