Skip to content

fix(harness): resolve conflicting env markers by process ancestry - #1881

Open
swissgrammie wants to merge 3 commits into
kunchenguid:mainfrom
swissgrammie:fm/fix-harness-marker-conflict
Open

fix(harness): resolve conflicting env markers by process ancestry#1881
swissgrammie wants to merge 3 commits into
kunchenguid:mainfrom
swissgrammie:fm/fix-harness-marker-conflict

Conversation

@swissgrammie

Copy link
Copy Markdown

What Changed

  • bin/fm-harness.sh no longer trusts a verified env marker (CLAUDECODE, PI_CODING_AGENT, GROK_AGENT) when more than one is present: detection counts the markers and falls through to the process-ancestry layer when they conflict, so an ambient shell-profile export (e.g. CLAUDECODE=1 leaked into a Pi session) can no longer misidentify the harness.
  • Added an emit_pi_family helper so a pi ancestry verdict still honors the FM_PI_HARNESS=pi-signed launch-boundary selector — but only when PI_CODING_AGENT confirms the Pi family; without it the selector is inert and the verdict stays pi.
  • Extended tests/fm-secondmate-harness.test.sh with five conflicting-marker cases (claude+pi, claude+grok, pi+grok, with and without the signed selector) and updated the detection notes in .agents/skills/harness-adapters/SKILL.md to document the new resolution rule.

Risk Assessment

✅ Low: The fix round correctly implements the prescribed pi-signed conflict resolution at every Pi ancestry verdict, preserves all single-marker and unmarked-ancestry invariants, has no sibling marker-consuming site that reintroduces the failure, and is covered by behavioral tests that would fail without the fix.

Testing

Demonstrated the fix end-to-end with a before/after CLI transcript: under a faked Pi process ancestry with a leaked ambient CLAUDECODE=1, the base-commit fm-harness.sh misreports "claude" while the fixed script reports "pi" (and "pi-signed" only when fm-spawn's selector accompanies Pi's family marker, staying inert without it); single markers still resolve immediately. Then ran the changed test suite (fm-secondmate-harness, containing the five new conflicting-marker assertions) plus the kimi and muse harness-detection suites that share the refactored marker layer — all pass, and the worktree is clean with no transient artifacts left behind.

Evidence: Before/after CLI transcript: conflicting env markers resolved by ancestry

$ # A real Pi session whose shell profile leaked CLAUDECODE=1 (both env markers present). $ # Process ancestry (faked ps): this shell -> Pi engine (Pi.app/bin/pi) -> pi-signed wrapper. --- BASE (2cf0283, before fix) --- CLAUDECODE=1 PI_CODING_AGENT=true fm-harness.sh -> claude CLAUDECODE=1 PI_CODING_AGENT=true FM_PI_HARNESS=pi-signed fm-harness.sh -> claude --- TARGET (64a12d9, after fix) --- CLAUDECODE=1 PI_CODING_AGENT=true fm-harness.sh -> pi CLAUDECODE=1 PI_CODING_AGENT=true FM_PI_HARNESS=pi-signed fm-harness.sh -> pi-signed CLAUDECODE=1 GROK_AGENT=1 FM_PI_HARNESS=pi-signed fm-harness.sh (no Pi family marker) -> pi --- TARGET: single markers still win immediately (no ancestry needed) --- CLAUDECODE=1 fm-harness.sh -> claude GROK_AGENT=1 fm-harness.sh -> grok PI_CODING_AGENT=true FM_PI_HARNESS=pi-signed fm-harness.sh -> pi-signed

$ # A real Pi session whose shell profile leaked CLAUDECODE=1 (both env markers present).
$ # Process ancestry (faked ps): this shell -> Pi engine (Pi.app/bin/pi) -> pi-signed wrapper.

--- BASE (2cf0283, before fix) ---
CLAUDECODE=1 PI_CODING_AGENT=true            fm-harness.sh               -> claude
CLAUDECODE=1 PI_CODING_AGENT=true FM_PI_HARNESS=pi-signed fm-harness.sh  -> claude

--- TARGET (64a12d9, after fix) ---
CLAUDECODE=1 PI_CODING_AGENT=true            fm-harness.sh               -> pi
CLAUDECODE=1 PI_CODING_AGENT=true FM_PI_HARNESS=pi-signed fm-harness.sh  -> pi-signed
CLAUDECODE=1 GROK_AGENT=1 FM_PI_HARNESS=pi-signed fm-harness.sh (no Pi family marker) -> pi

--- TARGET: single markers still win immediately (no ancestry needed) ---
CLAUDECODE=1                                 fm-harness.sh               -> claude
GROK_AGENT=1                                 fm-harness.sh               -> grok
PI_CODING_AGENT=true FM_PI_HARNESS=pi-signed fm-harness.sh               -> pi-signed

Pipeline

Updates from git push no-mistakes

⏭️ **intent** - skipped

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

🔧 **Review** - 2 issues found → auto-fixed ✅
  • ⚠️ bin/fm-harness.sh:56 - Under conflicting markers, a genuine pi-signed session is demoted to 'pi': ancestry can never yield pi-signed (bin/fm-harness.sh:84 maps a pi-signed ancestor to pi), so the exact leak scenario this commit fixes (ambient CLAUDECODE=1 in a real Pi session) returns 'pi' even when FM_PI_HARNESS=pi-signed + PI_CODING_AGENT=true are present. This is reachable beyond shell profiles: fm-spawn.sh:921 sets FM_PI_HARNESS=pi-signed at the launch boundary, and a pi-signed crewmate spawned from a claude-based firstmate inherits CLAUDECODE=1, producing exactly this conflict. Since FM_PI_HARNESS is firstmate's own launch-boundary selector (not an ambient third-party marker), honoring the signed selection once ancestry confirms the Pi family would preserve the SKILL.md invariant that the marker pair selects the signed identity. The demotion is fail-safe and explicitly asserted in tests/fm-secondmate-harness.test.sh:200-201, so it appears deliberate — asking rather than auto-fixing.
  • ℹ️ bin/fm-harness.sh:53 - When markers conflict AND the real harness is not within the 8-hop ancestry walk (e.g. stale markers retained in a multiplexer's stored environment), detection now returns 'unknown' where the old precedence order returned the highest-precedence marker's harness; 'unknown' then fails fm-spawn.sh's verified-adapter validation with a loud error. This trades a silent possible misidentification for an honest failure, which matches the change's stated design — noted for awareness only.

🔧 Fix: honor pi-signed selector when conflict ancestry confirms Pi family
✅ Re-checked - no issues remain.

✅ **Test** - passed

✅ No issues found.

  • Manual before/after demo: ran git show 2cf0283:bin/fm-harness.sh (base) and the target bin/fm-harness.sh under a faked ps Pi.app ancestry with conflicting markers CLAUDECODE=1 PI_CODING_AGENT=trueFM_PI_HARNESS=pi-signed, ± GROK_AGENT=1) and with single markers alone; base printed claude (the bug), target printed pi/pi-signed per the intended rules
  • bash tests/fm-secondmate-harness.test.sh — the changed suite, including the new conflicting-marker cases in test_pi_signed_detection_and_session_lock_identity (all 47 cases pass)
  • bash tests/fm-kimi-harness.test.sh — kimi detection relies on the refactored env-marker layer falling through to ancestry (passes)
  • bash tests/fm-muse-harness.test.sh — muse detection likewise depends on marker-layer fallthrough (passes)
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

@kunchenguid

kunchenguid commented Aug 7, 2026

Copy link
Copy Markdown
Owner

Automated reminder: thanks for the PR! This branch currently has a merge conflict with the base branch.

When you get a chance, please rebase onto (or merge) the latest base branch, resolve the conflict, and push. After that, checks will re-run and the PR will get looked at again.

Noted for firstmate#1881 at ee46797f.

A shell profile exporting CLAUDECODE=1 leaks that marker into a Pi
session, and fm-harness.sh checked CLAUDECODE before PI_CODING_AGENT,
so a real Pi session was misidentified as claude. A verified marker is
now trusted only when it is the sole one present; when several markers
conflict, no env marker is trustworthy alone and detection falls
through to process ancestry, which names the actual harness.

Adds portable regression cases for every conflicting-marker pairing in
tests/fm-secondmate-harness.test.sh and updates the harness-adapters
skill's one-line detection note.
@swissgrammie
swissgrammie force-pushed the fm/fix-harness-marker-conflict branch from ee46797 to 0e7d1b1 Compare August 8, 2026 07:24
@swissgrammie

Copy link
Copy Markdown
Author

Rebased onto the latest main and the conflict is resolved - the branch now sits on top of 833a9a2 with the fix intact (marker-conflict resolution plus the updated grok marker notes). Checks are queued behind fork-PR workflow approval; once approved they should run green (lint + the harness detection suite pass locally).

@kunchenguid kunchenguid removed the wheelhouse:pending-contributor-action Managed by Wheelhouse label Aug 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants