fix(bin): isolate Claude hooks under Grok and floor Herdr default presentation - #31
Merged
Conversation
…y with presentation floor
…e floor The real-Herdr presentation E2E still asserted that an unconfigured home is always projected, but the presentation floor added in this change keeps an absent setting flat below Herdr 0.8.0, so the test failed on CI's herdr 0.7.4. The default-on scenario now composes the same client and running-server evidence as the adapter's gate: at or above the floor it keeps the projection assertions, below it it asserts the flat firstmate placement, the floor warning, and its per-release dedupe marker. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Make Grok 1.0.3 safe as this home Firstmate primary on Herdr by semantically adapting upstream commit 06b33aa hook isolation and the public Herdr 0.8.0 default-presentation floor without wholesale parent convergence. Exactly five tracked Claude entries - SessionStart, two Bash PreToolUse hooks, the turn-end Stop guard, and Claude auto-arm Stop - must be inert under either GROK_AGENT or GROK_HOOK_EVENT while the subagent pre-tool guard remains deliberately unguarded because Grok has no native counterpart. An absent Herdr presentation setting must stay flat below 0.8.0, default on at or above the floor, explicit on must remain an opt-in below the floor, explicit off must remain off, client and selected running-server evidence must compose conservatively, and warnings should deduplicate per detected release. Preserve this fork durable wake, send-confirmation, decision-receipt, focus-safe cleanup, session-start run-tier, crew and secondmate selection, Relay policy, quota dispatch, and unrelated parent deltas. Do not spawn Grok crews, change dispatch configuration, touch the live Grok primary session, upgrade live Herdr, install a global guaranteed-delivery session-start hook, merge public parent, or merge the PR. Accepted Grok live proof is grok 1.0.3 inspect JSON from this isolated worktree after the guards plus env-driven execution regressions proving five Claude counterparts inert under Grok and live under Claude while the subagent exception stays armed. A named non-default Herdr lab was attempted twice with the mandated helper and default-session tripwire, but Herdr 0.7.5 refused the fresh shell pane both times with agent_pane_busy before Grok launched; do not retry agent start and document this exact live-matrix limit in the PR body. Open the PR through no-mistakes and finish only when CI-ready checks are green.
What Changed
GROK_AGENTorGROK_HOOK_EVENT), while the subagent pre-tool guard deliberately stays unguarded since Grok has no native counterpart; covered by new env-driven regressions intests/fm-turnend-guard.test.sh.bin/backends/herdr.sh: an absent setting stays flat below 0.8.0 and defaults on at or above it, explicit on/off settings are honored either way, client and selected running-server evidence compose conservatively, and below-floor warnings deduplicate per detected release.bin/fm-spawn.shso journal-exists projection recovery runs whenever a.herdr-presentationjournal exists — independent of the presentation preference or release floor — so previously projected workspaces are recovered instead of stranded (per the review finding fixed in this branch), with docs updated to match.Live-matrix note: a named non-default Herdr lab run was attempted twice with the mandated helper and default-session tripwire, but Herdr 0.7.5 refused the fresh shell pane both times with
agent_pane_busybefore Grok launched; agent start was not retried. Live proof instead comes fromgrok inspect --json(grok 1.0.3, isolated trustedGROK_HOME) plus the env-driven hook regressions listed in the Test section.Risk Assessment
✅ Low: The follow-up commit implements the requested fix exactly — journal-exists recovery now runs unconditionally while the floor/preference gate governs only fresh projections — with sound variable ordering, pure helpers on the new unconditional path, matching docs, and no remaining intent contradictions; the only residual note is an unpinned regression test, which is non-blocking.
Testing
Ran the three targeted suites (turn-end guard, herdr backend, secondmate harness) which all passed, captured grok 1.0.3 inspect JSON from this worktree showing the five guarded Claude hook entries and the deliberately unguarded subagent guard, re-ran the new Grok-inertness regression in isolation to transcript its pass, and produced a manual transcript of the Herdr presentation floor demonstrating default-on at 0.8.0, flat-with-deduplicated-warning below it, honored explicit on/off, and conservative client/server composition; no rendered UI surface exists for this shell/hook change, so CLI transcripts and inspect JSON are the end-user-visible evidence, and the worktree was left clean.
Evidence: grok 1.0.3 inspect JSON from this worktree (5 guarded entries + unguarded subagent exception)
Evidence: Isolated Grok-inertness regression transcript
ok - tracked .claude/settings.json entries: 5 inert under Grok, the documented subagent exception still armed, all live under ClaudeEvidence: Herdr presentation floor end-to-end demo (real adapter, stubbed herdr status)
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
bin/fm-spawn.sh:1666- The journal-exists projection-recovery branch is gated behind fm_backend_herdr_presentation_enabled, so when the unconfigured default now resolves below the 0.8.0 floor, a same-ID restart with an existing state/<id>.herdr-presentation journal skips herdr_projection_existing_meta_allows_flat and fm_backend_herdr_projection_recovery_allows_flat entirely and flat-spawns a new pane. Homes on Herdr 0.7.x that were projecting under the previous unconditional default-on hit this automatically when this change lands: the old projected workspace is stranded and fm-teardown.sh later quarantines the journal ("no workspace cleanup was attempted"), contradicting docs/herdr-backend.md's new claim that cleanup for an existing projection "always runs and never strands a workspace, whatever release the home is on now." Recommend running the journal-exists recovery branch whenever the journal exists and letting the floor gate govern only the fresh-create branch.bin/backends/herdr.sh:160- fm_backend_herdr_version_at_least strips pre-release suffixes, so a version like 0.8.0-preview.* passes the 0.8.0 floor, and fm_backend_herdr_release_floor_verdict deliberately lets that version-only "above" verdict override a below-floor protocol. A hypothetical early 0.8.0 preview at protocol 18 without the focus fixes would therefore project by default. Measured 0.8.0 previews carry protocol 19 and the exact prior-tab restore remains the backstop for this purely visual feature, so this reads as an accepted tradeoff; noting it for the record.docs/turnend-guard.md:61- docs/turnend-guard.md rejects widening the guard to GROK_SESSION_ID because Grok injects it into every child process and it can survive into a Claude session Grok launched — but GROK_AGENT is likewise set for Grok child/tool processes, so a Claude session launched directly from a Grok Bash tool now also loses its SessionStart run and both Bash PreToolUse checks (previously only the Stop entries were GROK_AGENT-guarded). The user intent explicitly mandates all five entries inert under GROK_AGENT, so this is an intent-mandated residual leak worth having on record, not a defect.🔧 Fix: run herdr projection recovery whenever journal exists
1 info still open:
bin/fm-spawn.sh:1676- The fix's new invariant — journal-exists projection recovery runs regardless of the presentation preference or release floor (bin/fm-spawn.sh restructure, documented in docs/herdr-backend.md) — is not pinned by any deterministic test: the presentation e2e exercises recovery only with projection enabled, so a future refactor could silently re-gate the recovery branch. Given this repo's pattern of pinning fixed regressions (e.g. test_tracked_claude_entries_inert_under_grok in the sibling commit), a targeted case asserting recovery runs under explicit off / below-floor with an existing journal would protect the fix; non-blocking.✅ **Test** - passed
✅ No issues found.
grok inspect --jsonfrom this worktree under grok 1.0.3 with an isolated trusted GROK_HOME, confirming 5 guarded Claude entries + the unguarded subagent exception + .grok/hooks counterpartstest_tracked_claude_entries_inert_under_grokin isolation (env-driven regression: 5 entries inert under GROK_HOOK_EVENT-only and GROK_AGENT=1, live under native Claude, subagent exception armed under Grok)bash tests/fm-turnend-guard.test.sh(full suite, exit 0)bash tests/fm-backend-herdr.test.sh(full suite incl. new floor, dedup, marker-safety, server-composition, and release-classifier tests, exit 0)bash tests/fm-secondmate-harness.test.sh(full suite incl. presentation-preference inheritance, exit 0)Manual end-to-end demo offm_backend_herdr_presentation_enabledwith a stubbedherdr status: default-on at 0.8.0, flat + warning at 0.7.5, dedup on repeat, explicit on below floor, explicit off at floor, below-floor running server keeps at-floor client flat✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.