Repository navigation
feat(grok): Grok as a parent harness (#281) - #284
Conversation
A Grok parent routes a matching Grok lane through spawn_subagent and every other lane, including a pinned Grok descriptor, through pstack-runner --parent grok. The generated catalog gains a Grok parent column. Claude and Codex still reject their own provider. The parent-by-adapter check is exhaustive over the finite registry. It is the property test for this table. There is no concurrency or permission state machine in the change, so there is no model-based test.
The runner help and reference said every same-provider call is rejected. A Grok parent may run a Grok provider, and the help now says so.
The help assertion now ignores the line wrap, so it checks the sentence the runner prints.
Replace externalSelf with explicitLaneRoute. Claude and Codex parents keep explicit same-provider lanes native, and a Grok parent sends every explicit Grok descriptor to the runner. The generated route table and runner help say so. Grok's identity markers (GROK_AGENT, GROK_SESSION_ID) were confirmed from a live grok 1.0.77 session. Refs #281 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… sheet On a Grok parent, inherit-parent and auto use spawn_subagent with pstack:poteto-agent, and every explicit descriptor uses the runner with --parent grok. The rule that sent a Grok descriptor matching the parent's model and effort to spawn_subagent is gone. codex-tools.md gains a Grok column, a Grok config home and a Waits on Grok section. setup-pstack writes the Grok sheet at <config-home>/rules/pstack-models.md, which Grok loads as a home rule, and a malformed Grok sheet is a visible stop. Refs #281 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
plugins/pstack/.grok-plugin/plugin.json shares skills/ and points agents at grok-agents/, which the registry generator copies from agents/poteto-agent.md and agents/comment-sicko.md and its drift check covers. Grok 1.0.77 treats each entry of an agents list as a directory, so listing the two files loaded no agents; the directory form offers those two and none of the Claude lane agents. Refs #281 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The version check and the static JSON parse cover plugins/pstack/.grok-plugin/plugin.json. AGENTS.md, the README, the reference, CHANGES, UPSTREAM and NOTICE name Grok as a parent harness, credit max-metaplanet's PR #282, and say to run /pstack:poteto-mode by name in Grok. Refs #281 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…:setup recipes The verifier can now run a live case from a real Grok parent. The `grok` transport starts one `grok agent --no-leader --plugin-dir <candidate> --model grok-4.7 --reasoning-effort low stdio` process per case with the operator's HOME and Grok home, and drives it over ACP. It answers `session/request_permission` with allow-once for the recipe tools and reject-once for the rest, records every message in both directions, and closes stdin after the turn. Before the prompt, `_x.ai/plugins/list` must show the candidate as the only loaded pstack, by path and tree hash. The session's summary.json, which must show grok-4.7 at low, and tool_definitions.json, which holds the spawn_subagent enum, are copied into the run root. A turn that ends with a running tool call or an unfinished child session fails. `grok:dispatch` runs one inherit-parent native lane and two runner lanes (grok:grok-4.7@low with --provider grok, and claude:claude-haiku-5-5@low) and asserts native tool calls, receipts verified by provider report, per-run markers, and an agent enum with only the model-free agents. `grok:setup` asserts the written Grok sheet, which the setup snapshot now restores byte for byte. The doctor checks the Grok binary, its agent flags and the `grok models` login line only when a grok feature is named. Refs #281 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`plugins/pstack/.grok-plugin/plugin.json` joins the shared manifests. It has no version-only `hook:startup` reach, because pstack's startup hook does not fire in Grok. The Grok manifest, the dispatch references, setup-pstack, recipes.ts and the transport reach `grok:dispatch`; setup-pstack, recipes.ts, the harness, the setup snapshot and the transport reach `grok:setup`. Neither runs unless named, and self-test adds no Grok session. Refs #281 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds features/grok.md and names the Grok transport, its doctor checks and the Grok sheet snapshot in SKILL.md and the feature map. Refs #281 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #281 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merge Protections🟢 All 2 merge protections satisfied — ready to merge. Show 2 satisfied protections🟢 Queue ready pull requestsAutomatically queue non-draft pull requests targeting main after verify and live-gate pass on the head and every review thread is resolved.
🟢 🚦 Auto-queueWhen all merge protections are satisfied and these conditions match, this pull request will be queued automatically.
|
Live evidence: Open Pstack
|
…odex lane Grok expands /pstack:<skill> in its own prompt and records it in the parent's chat_history.jsonl, so the parent never read_files SKILL.md. The Claude lane and the Opus setup answers depended on a Claude login the gate host does not have for project-only settings; Codex Luna and Grok 4.7 exercise the same Grok-parent routes. Refs #281 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Live evidence: Open Pstack
|
✅ Merged into
|
🛑 7 blocking findings🔴 Critical · Resolve empty GROK_HOME to the default before snapshotting 🔴 High · Reflect is exposed without a Grok copy destination 🔴 High · Grok-only agent changes cannot select Grok verification 🔴 High · Grok live-test reach omits Grok runtime paths 🟡 Medium · Honor cancellation before spawning another Grok session 🟡 Medium · Recognize Grok's deployment-key authentication result 🟡 Medium · Preserve UTF-8 characters across ACP stream chunks WalkthroughThis PR lets a Grok CLI session act as a pstack parent harness alongside Claude Code, Codex and T3 Code. It adds a Grok plugin manifest that shares the existing skills tree but exposes only the model-free
Advisories (2)
Since the last review
Repair promptRead the
Details
First review of this pull request. @unfret review · @unfret status · @unfret help |
There was a problem hiding this comment.
🛑 7 blocking findings
🔴 Critical · Resolve empty GROK_HOME to the default before snapshotting
🔴 High · Reflect is exposed without a Grok copy destination
🔴 High · Grok-only agent changes cannot select Grok verification
🔴 High · Grok live-test reach omits Grok runtime paths
🟡 Medium · Honor cancellation before spawning another Grok session
🟡 Medium · Recognize Grok's deployment-key authentication result
🟡 Medium · Preserve UTF-8 characters across ACP stream chunks
Check
…h, default an empty GROK_HOME Fix-forward for the merged head of ericlitman#284 (Unfret findings v1:1c735e4d, v1:1f3cdb66, v1:ccdebf5c, v1:21c02ebc). Closes ericlitman#285 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Replace the exact-path GROK_REACH list with permission granted in each runtime ownership branch of classify(). Assets, version-only manifests and non-runtime paths stay narrow; unmapped paths still fail. Decided in the step-back exchange after two verdicts found paths missing from the list (ericlitman#284, ericlitman#286). Closes ericlitman#287 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Summary
A Grok CLI session becomes a pstack parent harness, next to Claude Code, Codex and T3 Code. This takes over draft PR #282 by @max-metaplanet. Their three commits are kept with their authorship, and the routing rule is reworked after live probes of Grok 1.0.77.
explicitLaneRoute: "native" | "runner", which replaces feat/no-ticket(runner): accept grok as a parent harness #282'sexternalSelf. Grok's session markersGROK_SESSION_IDandGROK_AGENTare stripped from children, andGROK_HOMEis kept.${GROK_HOME:-$HOME/.grok}/rules/pstack-models.md, which Grok loads as a home rule./setup-pstackon Grok probes and then writes it.codex-tools.mdgains a Grok column and a "Waits on Grok" section covering waits, cancellation, writer checkouts, MCP, read-only and depth-one children.newandload. The docs say to invoke/pstack:poteto-modeby name, as on Codex.grokharness and two recipes.grok:dispatchruns one native lane, one Grok runner lane and one Claude runner lane, and checks that Grok offers only the model-free agents.grok:setupchecks that setup writes the Grok sheet, and restores the operator's Grok sheet byte for byte.Closes #281.
Evidence
Grok 1.0.77 on studio1, headless probes. The served model was read from each child's Grok session record (
summary.json,usage.json).pstack:pstack-opus-low, and the child ran ongrok-4.7-buildwith no error.After: with the Grok manifest, Grok's runtime discovery (
grok inspect --json, from a scratchGROK_HOMEinstall) lists onlypstack:poteto-agentandpstack:comment-sicko, plus 65 skills. Without anagentskey it listed all 27 agents.model: grok-4.6/effort: mediumran grok-4.6 at medium. One naminggrok-4.9, a model that does not exist, silently ran the parent'sgrok-4.7and returnedOK. A native pin has no failure signal. The runner's receipt verifies the served model.agentslist entry as a directory. A list of the two files loaded 0 agents, so the manifest points at a generated directory instead, covered by the registry's drift check._x.ai/plugins/listshowed the--plugin-dircandidate (origin: cli_override) shadowing the installed pstack 1.20.0.grok-4.7@low.Merge Danger
Door: two-way
Reverting this PR returns everything to main's behaviour. No user file is migrated.
Blast Radius: Grok-only
grok:feature is named.Acceptance criteria
The criteria come from the scope comment on #281: #281 (comment)
--parent grok, strips Grok session markers and keepsGROK_HOME, with markers confirmed from a live Grok session. A live probe printed exactlyGROK_AGENTandGROK_SESSION_ID. Tests:registry.test.ts(the parent-by-adapter matrix) andrun.test.ts(childEnvironment). Live: pendinggrok:dispatch.inherit-parent/autouse nativespawn_subagentwithpstack:poteto-agent; every explicitgrok:*descriptor uses the runner; no rule depends on matching the parent; the flag isexplicitLaneRoute: "runner"; Claude-on-Claude and Codex-on-Codex are still refused. The rules are inprovider-dispatch.md,poteto-mode/SKILL.md,codex-tools.mdandsetup-pstack/SKILL.md, and the generated route cell carries them. Tests:registry.test.ts. Live: pendinggrok:dispatch.skills/; Grok does not offer the Claude lane agents and does offerpoteto-agentandcomment-sicko. Proved by runtime discovery (Evidence above) andgrok plugin validate. Live: pendinggrok:dispatch(agent-list assertion). The criterion preferred listing the two files directly. That form loads nothing in Grok 1.0.77, so the manifest uses a generated directory.codex-tools.md. It is a documentation-only item.${GROK_HOME:-$HOME/.grok}/rules/pstack-models.md, is read first, and a malformed sheet is a visible stop; setup probes and writes it. Covered byprovider-dispatch.mdandsetup-pstack/SKILL.md. Live: pendinggrok:setup.docs/reference.md.hooks/hooks.jsonis unchanged.grokharness: ACP session-only load, cheap explicit model, non-interactive permissions, candidate load proof,grok:dispatchandgrok:setupwith byte-exact restore. Covered byscripts/grok.ts,features/grok.mdandrecipes.ts. Its unit tests pass, and the transport passed one live run (Evidence). The recipes are pending the live gate.registry.jsonmaps.grok-plugin/plugin.jsonandgrok-agents/*.skill-collision-repro.shcompares 4 manifests, andpackage.jsonstaticparses the Grok manifest. UPSTREAM, CHANGES, NOTICE, README, reference and AGENTS name the Grok harness.Gate results (head c33565d)
bun run testbun run typecheckbun run staticclaude plugin validate plugins/pstackgrok plugin validate plugins/pstackbun run test+typecheckNot verified
live-gate: not yet published. Planned features:grok:dispatchandgrok:setupwith--self-test, run from this candidate head because the PR changes the verifier.~/.claude/plugins) has not been probed. If Grok reads.grok-pluginthere, the agent fix reaches existing users without a separate Grok install. This is checked on the host after release.~/.grok/rules/: not yet observed under Grok's permission rules.grok:setupcovers it.🤖 Generated with Claude Code