Skip to content

Add Grok as a parent harness #281

Closed

Description

@max-metaplanet

A Grok session running poteto-mode should be able to run the multi-model panels with itself as the parent.

Proposal:

  • Add grok to the runner parent table, the same way Claude and Codex are mapped. The generated route table gains a Grok parent column. Do not hand-edit that catalog.
  • A Grok lane whose model and effort already match the parent uses native spawn_subagent. Pass model only when that tool lists it. The tool takes no effort, so a pinned model or effort uses the runner instead.
  • Every other lane from a Grok parent uses pstack-runner --parent grok, including a Grok provider. That launch keeps --permission-mode auto, the requested model, and the requested effort.
  • Claude-on-Claude and Codex-on-Codex stay rejected. The runner still tells those parents to use their native subagent route.
  • A headless Grok parent stays in auto mode. Headless Grok cancels the turn on a permission prompt. Auto mode reports the blocked call. A native child inherits the parent session's mode, and spawn_subagent has no permission-mode argument.
  • Strip GROK_SESSION_ID and GROK_AGENT from a child of a Grok parent. Keep GROK_HOME so the Grok CLI still finds its config.
  • Do not add an implicit timeout or a weaker-model fallback. Do not switch to the runner after a native lane fails. Do not replace an unregistered Grok model with the parent model.
  • /setup-pstack still writes the model sheet only for Claude Code and Codex. On a Grok parent it probes, then stops before writing a config home.

Out of scope for the first change: merging, queueing, publishing live-gate, and a Grok config-home writer.

Activity

  1. ericlitman commented on Nov 8, 2026

    @ericlitman
    Owner

    Decided scope (Eric, 2026-11-08). We take over draft PR #282 and credit its first commit, as #272 did with fork PR #254. The design pass and its evidence are in Eric's docs records (projects/open-pstack/records/2026-11-08-281/design.md). A GPT 6.0 Astra design review at high effort said "sound with changes", and all eight of its findings were accepted.

    Evidence that changed the proposal (Grok 1.0.77, headless probes, checked against each child's session record):

    • Grok already loads pstack through its Claude-compat discovery, including the Claude-only pstack-<family>-<effort> agent files. When a Grok parent spawns pstack:pstack-opus-low, the child runs on grok-4.7 with no warning.
    • A Grok agent file can pin a Grok model and effort (model: grok-4.6, effort: medium ran as grok-4.6 at medium). An agent file that names a model Grok cannot serve (grok-4.9) silently runs on the parent's model, and the result shows no error.

    Acceptance criteria:

    1. pstack-runner accepts --parent grok. A child of a Grok parent drops Grok's session markers and keeps GROK_HOME. The marker list is confirmed from a live Grok session's environment, names only.
    2. On a Grok parent, inherit-parent and auto use native spawn_subagent with pstack:poteto-agent. Every explicit grok:<model>@<effort> descriptor uses the runner with --parent grok --provider grok. No rule depends on whether the descriptor matches the parent's model or effort. The parent flag reads explicitLaneRoute: "runner". Claude-on-Claude and Codex-on-Codex stay refused.
    3. A Grok-only plugins/pstack/.grok-plugin/plugin.json shares skills/. Grok's runtime discovery does not offer the Claude lane agents, and it does offer poteto-agent and comment-sicko. Listing those two files directly is preferred over a second agents directory.
    4. codex-tools.md gains a Grok column, and the dispatch rules cover:
      • a prepared writer checkout (cwd, isolation: none), and a native worktree only where the calling skill allows it;
      • positive bounded waits re-armed through retained IDs (1-hour clamp, at most 20 IDs);
      • cancellation that reads the retained receipt;
      • MCP on native lanes only;
      • advisory read-only on native lanes;
      • depth-one children.
    5. The Grok model sheet is ${GROK_HOME:-$HOME/.grok}/rules/pstack-models.md. A Grok parent reads it in preference to any model text Grok imports from Claude instructions. A malformed sheet is a visible stop. /setup-pstack on a Grok parent probes and writes that file.
    6. No pstack startup hook fires in Grok. The docs say to invoke /pstack:poteto-mode by name, as on Codex.
    7. verify-open-pstack gains a grok harness:
      • The candidate is installed for one session through ACP (grok agent --no-leader --plugin-dir <exact-head>/plugins/pstack stdio), with no writes to the operator's Grok config.
      • The parent runs on an explicit cheap model and effort, under a non-interactive permission policy.
      • Proof covers candidate skill and agent loading by source path and hash, native tool calls, and child completion before publication.
      • Recipes: grok:dispatch, which also asserts the Claude lane agents are hidden, and grok:setup, which restores the Grok sheet byte-exact.
    8. Path classification knows .grok-plugin/. The version and drift checks cover the Grok manifest. UPSTREAM.md, CHANGES.md, NOTICE.md, the README and the reference name Grok as a parent harness.

    Out of scope: T3 Code with a Grok runtime, and Grok startup-hook auto-fire.

  2. ericlitman commented on Nov 8, 2026

    @ericlitman
    Owner

    PR: #284 (takes over #282).

  3. added a commit that references this issue on Nov 8, 2026
  4. ericlitman commented on Nov 8, 2026

    @ericlitman
    Owner

    #281: Add Grok as a parent harness

    The issue body is the only kept version; the tracker keeps no earlier text. Later sources:

    From the issue body:

    • grok joins the runner's parent table, and the generator writes its route column. Done as written. Proved by registry.test.ts, the repository gate, and the live grok:dispatch runs on 0d0c5d5 (feat(grok): Grok as a parent harness (#281) #284) and b43e759 (fix(verify): derive Grok live-gate reach from runtime ownership (#287) #288).
    • A Grok lane that matches the parent's model and effort goes native, and anything pinned goes through the runner. Done differently, by the agent.
      • Why: live probes of Grok 1.0.77 showed that an agent file naming a model Grok cannot serve silently runs the parent's model. grok-4.9 ran as grok-4.7 and returned OK.
      • Only inherit-parent and auto stay native, through spawn_subagent with pstack:poteto-agent. Every explicit grok:* descriptor goes through the runner, whose receipt proves the served model.
      • Proved by grok:dispatch. The native lane's SubagentCompleted carried its marker. The Grok runner receipt was complete, served grok-4.7-build, and carried provider-report proof.
    • Every other lane uses pstack-runner --parent grok, with --permission-mode auto and the requested model and effort.
      • Reader correction: the live receipts prove the route, model and effort only. They prove it for Grok and Codex Luna, both with parent: grok. --permission-mode auto is proved only by runner/registry.test.ts:592 and runner/providers/grok.test.ts:24, because grokReceipt() does not check it.
      • Reader addition: no live gate on a batch head ran a Claude lane from a Grok parent. The planned Claude Haiku lane was dropped, because studio1's Claude sign-in fails for runner lanes. The only Claude lane from a Grok parent is max-metaplanet's hand run on feat/no-ticket(runner): accept grok as a parent harness #282 (e6ecc3c). This stays open under the Decision in Next steps.
    • Claude-on-Claude and Codex-on-Codex stay refused. Done as written. explicitLaneRoute: "native" keeps the refusal. Proved by the parent-by-adapter matrix in registry.test.ts.
    • A headless Grok parent stays in auto mode, and a native child inherits the parent's mode. Done as documentation only, in provider-dispatch.md. No live check.
    • Children drop GROK_SESSION_ID and GROK_AGENT, and keep GROK_HOME. Done as written.
      • A live probe of a Grok session printed exactly those two markers.
      • Proved by run.test.ts childEnvironment.
    • No implicit timeout, no weaker-model fallback, no switch to the runner after a native lane fails, and no replacing an unregistered Grok model with the parent's. Done as written, as documentation in provider-dispatch.md and tests in registry.test.ts. An unregistered Grok model goes to the runner, which keeps it. No live case covers it.
    • Setup probes on Grok and writes no sheet. Done differently, on Eric's decision ("1. it should write, too"; source above).
      • Setup writes ${GROK_HOME:-$HOME/.grok}/rules/pstack-models.md.
      • Proved by grok:setup on 0d0c5d5 and e4537f0, including the byte-exact restore of the sheet and of its earlier absence.
    • Out of scope: merging, queueing, publishing live-gate, and a Grok config writer. Done differently.
      • Reader correction: Eric's words authorize only taking over the PR and writing the sheet.
      • Merging, publishing the live gate on every head and releasing are the agent's choice. Once we owned the PR, those became the owner's steps under AGENTS.md's merge and release rules.

    From the decided-scope comment:

    1. Runner parent and marker stripping. Done as written; proof as above.
    2. Native lanes only for inherit-parent and auto; explicitLaneRoute: "runner". Done as written. Proved by grok:dispatch, which made exactly one spawn_subagent call with pstack:poteto-agent and no runner receipt for that lane.
      • The [subagents.models] and role override rule from design ruling 1 is documented in provider-dispatch.md and setup-pstack/SKILL.md, with no live check.
    3. A Grok-only manifest that hides the Claude lane agents and offers the two model-free agents. Done differently.
      • The criterion preferred listing the two files. Grok 1.0.77 reads each agents list entry as a directory, so the manifest points at a generated grok-agents/ directory.
      • Proved by the agent-list assertion in grok:dispatch.
      • Proved again after the release from the Claude Code install of 1.21.0 on studio1: Grok lists only pstack:comment-sicko and pstack:poteto-agent. Record: post-release-grok-agents.md. Before the release it listed all 27 agents.
    4. The Grok tool mapping. Done as written, as documentation in the Grok column and the "Waits on Grok" section of codex-tools.md. Live use covers only spawn, wait and the background runner call.
    5. The Grok sheet's path and write, its precedence over imported Claude text, and a visible stop when it is malformed. The path and the write are done and proved by grok:setup. Precedence and the malformed-sheet stop are documentation only.
    6. pstack's startup hook does not fire in Grok, so invoke it by name. Done as written, as documentation in the README and docs/reference.md.
    7. The verifier's Grok harness. Done as written.
      • Reader correction: the lane-model swaps changed the lane brief, not the ticket. The ticket names no lane models.
      • What was built and proved:
        • ACP session-only loading with --plugin-dir, with the candidate proved by _x.ai/plugins/list and its tree hash;
        • a cheap explicit parent, grok-4.7 at low;
        • a non-interactive permission policy that answers session/request_permission from GROK_TOOLS;
        • native tool-call checks and child completion before publication (recipes.ts:843-858);
        • a byte-exact setup restore.
      • The dispatch case's cross-provider lane is Codex Luna, and the setup case answers Grok 4.7. Both choices follow from the Claude sign-in state.
      • The skill-load check also reads Grok's <skills_referenced> record.
      • Reader correction: the setup case leaves an empty ~/.grok/rules/ folder in the operator's Grok home on every run, because the snapshot restores files, not the folders setup creates. No action is chosen: an empty rules folder loads nothing. It is recorded in Waived review findings: Grok verifier cancellation, deployment-key login, chunk decoding, Grok mapping gaps (unscheduled) #290. I removed it by hand twice, and it is absent now.
    8. Classification, version and drift checks, and docs. Done as written.

    Reader addition: changes the PRs made that the earlier draft did not report.

    Batch closeout record: https://github.com/mobilyze-llc/docs/blob/main/projects/open-pstack/records/2026-11-08-batch-281/closeout.md (released in v1.21.0: https://github.com/ericlitman/open-pstack/releases/tag/v1.21.0)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions