goal-flight · git:20260901.5c74049 · 2026-09-01 · sha256 372a8364f6122e7e
goal-flight git:20260901.5c74049A
Immutable. This exact content is served forever at /api/v1/blob/372a8364f6122e7e.
--- name: goal-flight description: "Goal Flight orchestration for Grok Bot: plan, dispatch, review, recover, and resume long-running repository work from file-backed state." --- # goal-flight Use this skill when a repository task needs durable planning, resumable work, worker dispatch, review flights, or handoff notes that survive context loss. Grok Bot is a host projection over the portable Goal Flight core. It is not a rewrite of that core and it does not replace the Grok CLI adapter (`adapters/grok.json`, `grok agent stdio`). ## Freshness (always loaded) Disk-read repository `SKILL.md` Hard Invariants. If you cannot quote them from that read, you are stale: run Compaction resume before acting. This rule cannot live only in compacted chat or a summarized SKILL.md. ## Load Order 1. Read the repository `AGENTS.md` first when present. 2. Read this Grok Bot host wrapper. 3. Read the repository root `SKILL.md` as the canonical Goal Flight workflow. 4. Read `protocols/guidance-extended.md` by default — non-frontier controllers benefit from its worked examples and expanded rationale for the core's rules; skip only when context is tight (the core alone is complete). 5. Read the newest relevant `docs-private/RESUME-NOTES-*.md` only when the task asks to resume prior Goal Flight work. ## Skill pin Live controllers load the detached pin at `~/.goal-flight/skill/` (or `$GOALFLIGHT_ROOT`), not a live source checkout and not a clone on the Grok Bot box. Resolve `<skill-root>` before running scripts. Doctor warns when an installed wrapper copy has drifted from that pin; resync with `./install.sh grok-bot`. ## Operating Rules - Treat repository Markdown plus Git as canonical state. - Keep queue, ledger, status, review, and handoff artifacts file-backed. - Facts come from `goalflight_status.py`, `goalflight_task.py list/next`, and doctor. Conversation is not the backlog. - Treat Grok Bot session state, named-teammate memory, and host config as advisory. - Do not rewrite the root `SKILL.md` during setup. Setup registers this wrapper only. - Grok Bot Task / executor workers start blank (no chat, memory, SKILL.md, or this conversation). Every judgment-bearing Task prompt reuses the Claude host-subagent pin — do not invent a parallel package. See Executor context package below. - Claim controller label `goalflight-grokbot` and stamp that claimed label on every `goalflight_dispatch.py` launch. Never steal a live lease. - Wake on worker terminals (`!COMPLETE` is the success marker) through the existing journal doorbell. Canonical arm is one tracked `goalflight_grok_bot_listen.py --report-pending --timeout-s 900 --controller-label goalflight-grokbot` on the user's Mac (that helper wraps `listen --report-pending` and prints the quote-check banner). The 900s quiet timeout is this host's frontier ping (anti-stall), not Claude's 120s follow-stream heartbeat. Optional full pool (depth 4): 900s on one slot only; others `--timeout-s 0`. Every ring or timeout is a mini-resume: drain if it rang, flush RESUME-NOTES (`state-handoff.md` Before compact or sleep), quote-check Hard Invariants from disk, re-arm, `goalflight_task.py next`. Never detach. Do not invent a second event bus, a Settings monitor widget, a compact UI, a context-consumption meter, or a Grok Bot-native mail transport. Do not port Claude PostToolUse / SessionStart hooks. Do not arm unbounded `supervise` as a background shell. Missed wake is latency: resume still pulls status, task next, and `relay --new`. The operator is not the compaction mailman. The one operator wake-hygiene job is re-arming listen doorbells after a host update or token-pause, surfaced as roster `wake unarmed` — not a second reminder channel. See Compaction and Operator role in `docs/hosts/grok-bot.md`. ## Dispatch and workers Grok Bot Executors (Task / executor subagents) are a **first-class** dispatch target on this host. Do not copy the Claude-host rule that treats the host Agent as a last-resort code executor. That rule stays in the portable `SKILL.md` for Claude Code only. Choose the lane from token/budget (rate pressure, provider spend, session limits) and from the task (code vs review vs recon vs planning). Both lanes are valid: - existing CLI workers via `goalflight_dispatch.py` on the user's registered computer (the Mac checkout), targeted with Grok Bot Shell `machineId` - Grok Bot Task / executor subagents (host `delegate` surface) Do not add a parallel task store. Do not clone the repository onto the Grok Bot box. Do not pin Grok model ids. ### Grok Bot routing | Task | Prefer when capacity is healthy | Alternate / host-native | |---|---|---| | Code-writing | CLI: `--agent codex`, `--agent grok-code`, or `--agent moonshot` (Kimi Code / kimi3; do not invent a `kimi3` agent id) | Grok Bot Executor when that lane is cheaper or the only one with budget; also for host-native chunks (recon, synthesis, mail, status) | | Reviews | Independent CLI: `--agent moonshot` (kimi3) or `--agent codex` | gstack `/review` on an independent engine | | Research / web search | `--agent grok-research` (read-only CLI) | controller-direct or Executor recon | | Planning / status / mail | Grok Bot Executor or controller-direct | CLI only when the chunk is a large write | `forbid_self_review` still applies: a Grok Bot controller must not Type-1-review a `grok-code` worker. Use moonshot/kimi3 or codex (or gstack) as the independent reviewer. Grok Bot Cloud Agents remain an optional extra worker for GitHub-branch / PR chunks only. They are never the default for a local scientific-coding project. Stamp `--controller-label <claimed-label> --controller-pid --controller-session-id` on every `goalflight_dispatch.py` launch. The claimed label is `goalflight-grokbot` unless this controller already joined under another unused slug. Never steal a live lease that belongs to another controller. ## Executor context package Grok Bot Task / executor subagents start **blank**. They have no chat history, no memory, no installed SKILL.md, and none of this conversation. Reuse the existing Claude host-subagent pin. Do not invent a parallel package format and do not add a grok-executor template (Cursor / Grok CLI wrappers do not have one). CLI workers (`--agent codex`, `grok-code`, `moonshot`, …) keep the existing five-layer `--prompt-file` dispatch (compose via `prompts/dispatch-wrapper.md`; do not paste that recipe file into a Task). Executors receive **that same composed prompt-file body** in the Task prompt (paste it, or cite its stable Mac path as the `--prompt-file` equivalent). Compose every judgment-bearing grok-executor Task prompt in this order: 1. **Open** with `protocols/subagent-preamble.md` verbatim. Fill only the two slots: repository path and north star. The repository path is the Mac checkout, e.g. `/Users/simonrowland/Repos/<project>`. 2. **Grok-bot-only pin** (the only new clause), immediately after the preamble: executors default to the Grok Bot computer, **not** the user's Mac. Name `machineId` / "the user's registered computer" and absolute paths under `/Users/simonrowland/Repos/...`. Every Read and Shell in this Task — including the preamble's AGENTS.md / ORIENTATION.md reads — uses `machineId`. Do not clone the repo onto the box. 3. **Always** pointer to `docs-private/rag/ORIENTATION.md` when that file exists (orientation only; never scope expansion). The preamble already carries this pointer; keep it. 4. **If the lane is triggered**, apply `protocols/worker-context-package.md` in full: verbatim brief prepend (never link-instead-of-paste), quoted ground-truth spec, named guard tests, standing re-read. Then the `--prompt-file` equivalent: the same five-layer body CLI would get. Citing a Mac path is allowed for that composed prompt file; it does not replace the verbatim brief or quoted spec. Mechanical Task prompts may carry the preamble harmlessly. Judgment-bearing prompts (interpret evidence, review, compare designs, tradeoffs, or write code against a spec) are not optional. ## Multi-controller etiquette Five-controller layouts are a project convention, not a Goal Flight primitive. When a project already partitions lanes across named controllers (the live example uses integrator / engine / bugs / webui / perf labels), a Grok Bot controller joining that project must: - read the project's `docs-private/MULTI-CONTROLLER-ETIQUETTE.md` when present - claim `goalflight-grokbot` (or another unused label) and its own worktree / branch - send merge-request mail; leave origin push to the project's integrator - never steal those existing leases SendToAgent / named teammate pings may wake another Grok Bot controller that shares the project. They are not the work plane. Controller-mail remains `goalflight_messages.py`: leases, journal, `post --to-controller`, merge-request / patch. Do not replace the journal with SendToAgent. ## Wake path Journal mail is durable truth. Worker terminals are the existing markers in `protocols/worker-markers.md`: `!COMPLETE` / `!READY` / `!FAILED` / `!BLOCKED` / `!USER-NEED` (leading `!` optional). `!COMPLETE` is the success terminal. The watcher already harvests those into the terminal-outbox / controller mail. Do not invent a second event bus. Grok Bot notifies on **job completion** (Task / executor or a tracked Shell exits and revives the parent chat). That is the same contract as `goalflight_messages.py listen` (exit-as-wake), not Claude's persistent per-line `supervise` / `follow`. There is no Settings "monitor widget"; the running background task / subagent card is the UI. This host uses the portable listen / heartbeat process pool. The frontier ping is `listen --timeout-s 900` (15 minutes of quiet), so the controller is reminded of the task frontier and does not stall. That is **not** Claude's follow-stream heartbeat (120s; the stream range is 60–300s and would spam Grok Bot turns). Do not change the global `supervise` / `follow` cadence for this host; 900s is a wrapper-local default on the listen arm. Canonical arm — one tracked `goalflight_grok_bot_listen.py` on the **user's Mac**, label `goalflight-grokbot`, never detached (`nohup` → listen exit 4). That helper wraps `listen` and prints the quote-check banner on every exit (ring or timeout). The doorbell is outside the chat. ```shell python3 <skill-root>/scripts/goalflight_grok_bot_listen.py \ --project-root "$PWD" \ --controller-label goalflight-grokbot \ --report-pending \ --timeout-s 900 ``` Every ring (exit 0) or timeout (exit 1) is a **mini-resume**: drain if it rang (`relay --drain`, act), flush RESUME-NOTES (Compaction below), quote-check Hard Invariants from a fresh disk read, re-arm, then `goalflight_task.py next`. The 900s quiet timeout is this host's substitute for Claude's 80% context-meter hint. The portable four-listen pool is full depth; one listen is the MVP. If you arm more than one listen, put `--timeout-s 900` on a single slot (the frontier ping) and leave the others at `--timeout-s 0` so four quiet timeouts do not fire together. Branch on listen exit codes. Exit 1 on this host is the frontier reminder above, not the portable "re-arm only if coverage is still required" row. Codes 2–5 follow `protocols/controller-mail.md`; exit 5 is did-not-arm (do not re-arm that nonce). Do **not** arm unbounded `supervise` as a Grok Bot background shell and expect per-line wakes. A helper, if added, must wrap `listen` or exit on the first actionable event (ignore stream heartbeat / frontier keepalives). A same-turn regex-wait on a live `supervise` process is a same-turn block, not a session-life monitor; do not use it as the default. Missed wake is latency, not data loss. Resume still pulls `goalflight_status.py`, `goalflight_task.py next`, and `relay --new`. ## Compaction Grok Bot = **autocompact + keep handoff current**. Do **not** port `scripts/hooks/goalflight-context-meter.sh` or Claude PostToolUse `additionalContext` 80/90/95% bands. That hook is Claude-Code-specific. Grok Bot has no PostToolUse `additionalContext` injection and no trustworthy window %. A fake meter is worse than none. Claude context-meter and SessionStart watchdog stay Claude-only. There is no SessionStart hook on grok-bot. Grok Bot has **no** controller-authored `/compact` and **no** keep-vs-toss prompt. The host may summarize the chat on its own. Do not invent a compact UI. Do not ask the user to compact. Do not emulate Claude's compact prompt in chat. The directed-compact step on this host **is** `protocols/state-handoff.md` "Before compact or sleep": - update newest `docs-private/RESUME-NOTES-<YYYY-MM-DD>.md` with ENVIRONMENT / IDEAS / DECISIONS / FACTS / CARRIERS only — no task tables, dispatch codes, or next-task lists - store baseline via `goalflight_task.py list` (outstanding, plus deferred / held when relevant) - `goalflight_status.py` The 15-minute listen timeout is the substitute for Claude's 80% hint. On **every** ring or timeout, flush that handoff, then quote-check. Also write before long waves. There is no warning before the host summarizes. The Hard Invariants quoting rule cannot live only in compacted SKILL.md. Externalize it: 1. This wrapper's Freshness preamble (always loaded): disk-read SKILL.md Hard Invariants; if you cannot quote them, stale → resume before acting. 2. Listen/heartbeat stdout banner (doorbell is outside the chat): `goalflight_grok_bot_listen.py` prints `QUOTE-CHECK: disk-read SKILL.md Hard Invariants; if you cannot quote them, stale — resume before acting.` on every listen exit. 3. Optional operator-side Grok Bot profile sentence: `On every Goal Flight listen exit, disk-read SKILL.md Hard Invariants; if you cannot quote them, resume before acting.` Every 15-minute wake is a mini-resume: drain if it rang, flush RESUME-NOTES, quote-check from disk, re-arm doorbells, `goalflight_task.py next`. Resume reload and rebuild are unchanged. Chat summaries are hints, not substitutes. Grok Bot profile, `update_state` memory, and routines may persist across summaries; they are advisory. Repository files remain the canonical memory backend. If this controller cannot quote `SKILL.md` Hard Invariants from a **fresh disk read**, reload `AGENTS.md` → this grok-bot wrapper → repository `SKILL.md` → `commands/resume.md`. Then: 1. `goalflight_session_status.py --text` 2. **Skip** `commands/resume.md` STEP 1.5 (`supervise`). Arm listen doorbells (portable pool) instead. 3. store baseline (`goalflight_status.py` + `goalflight_task.py list`) 4. newest RESUME-NOTES 5. `goalflight_task.py next` The operator is not the compaction mailman. After a host update or token-pause, listen may exit 5 (dead lease nonce) or tracked tasks may be reaped. The next user message or next 15-minute arm/timeout should claim and re-arm. Surface a deaf controller as roster `wake unarmed` (`wake_armed` / `wake_covered` / `supervisor` absent). Do not invent a second reminder channel. ## Setup From the cloned Goal Flight repository (or the pinned `~/.goal-flight/skill/`), run: ```shell ./setup.sh --grok-bot ./setup.sh --apply --yes --grok-bot # one-shot; optional workflows-library root overrides the default ./install.sh grok-bot ./install.sh grok-bot /home/box/agent-data/workflows ``` The checked-in destination is the Grok Bot workflows library (`/home/box/agent-data/workflows/goal-flight/SKILL.md` on the bot machine). Override with `GOALFLIGHT_GROK_BOT_WORKFLOWS` when installing from a Mac checkout whose library root is different. This path is the least-wrong verified location; do not assume `~/.grok/skills/` (that is Grok CLI).