Skip to content

test(gbrain-sync): stub pgrep so the pin case is hermetic - #2689

Open
szsunyuan wants to merge 2 commits into
garrytan:mainfrom
szsunyuan:test/gbrain-sync-hermetic-autopilot-probe
Open

test(gbrain-sync): stub pgrep so the pin case is hermetic#2689
szsunyuan wants to merge 2 commits into
garrytan:mainfrom
szsunyuan:test/gbrain-sync-hermetic-autopilot-probe

Conversation

@szsunyuan

Copy link
Copy Markdown
Contributor

Why (in your own words)

keeps a symlink-equivalent pinned source registered as-is is supposed to pin the symlink path, not the operator's daemon. It is the only non---dry-run --code-only child in test/gstack-gbrain-sync.test.ts, so it hits #1734's detectAutopilot()pgrep -f "gbrain autopilot". If autopilot is up, the child correctly exits 1: refused: gbrain autopilot active (process:gbrain autopilot). The test only asserts r.status === 0, so it looks like a symlink/pin failure. CI is green because CI has no daemon. The refuse is correct. The test never neutralized the probe.

The fixture already prepends bindir to PATH and stubs gbrain. defaultProcessRunning invokes bare pgrep, which is PATH-resolved. Drop a pgrep that exits 1 into that same bindir. Blank GBRAIN_HOME so an inherited lock under $GBRAIN_HOME/.gbrain cannot refuse before pgrep. The child cannot inject processRunning the way test/gbrain-guards.test.ts does.

This is a test-isolation fix, not a product fix. Real /sync-gbrain still refuses while autopilot is live.

Fixes #2685.

Why this shape

Author offered the stub or an env hatch. Stub is the smaller blast radius. An env override on detectAutopilot would weaken a data-loss guard. Skip-if-autopilot would hide the pin case on the machines that follow the documented setup. Did not edit lib/gbrain-guards.ts.

What it does

  • That one it writes an executable pgrep stub (exit 1) next to the existing gbrain stub, and blanks GBRAIN_HOME on the child.

What it deliberately does not do

  • Env hatch / skip-if-autopilot on detectAutopilot
  • Production guard changes
  • Stub pgrep in other tests in this file (they are --dry-run or --no-code)
  • Stub pgrep in test/gbrain-sync-skip.test.ts (sibling --code-only file; those cases do not assert exitCode === 0, so they false-pass on a refuse instead of going red)
  • VERSION / CHANGELOG / /ship

AI was used for assistance.

Live evidence

Temp HOME / GSTACK_HOME only. Never rm'd real ~/.gbrain. Did not start real gbrain autopilot (that daemon can race a destructive walk). Recreated the author's process signal with a dummy whose argv contains gbrain autopilot. Host /usr/bin/pgrep -f "gbrain autopilot" went to exit 0. Then the same named it:

Tip (ad84005, no stub), dummy up — the issue:

expect(r.status).toBe(0)
Expected: 0
Received: 1

(fail) gstack-gbrain-sync CLI > keeps a symlink-equivalent pinned source registered as-is [593.11ms]
  0 pass  1 fail

Same fixture without --quiet:

status=1
ERR   code  refused: gbrain autopilot active (process:gbrain autopilot). Stop autopilot, then re-run /sync-gbrain.
  0 ok, 1 error, 0 skipped

This branch, dummy still up — the fix:

(pass) gstack-gbrain-sync CLI > keeps a symlink-equivalent pinned source registered as-is [836.46ms]
  1 pass  0 fail

Quiet machine (no dummy, pgrep exit 1, GBRAIN_HOME unset): tip is already green. That is why this laptop looked fine until we planted the signal. Author's red is machine-specific; CI has no daemon. After the dummy was killed, host pgrep was exit 1 again.

On this Bun, child os.homedir() honors HOME, so operator ~/.gbrain/autopilot.lock is not visible to the child. The remaining lock residual was inherited GBRAIN_HOME; the child now blanks it.

Scope

  • Changed: test/gstack-gbrain-sync.test.ts (one it)
  • Verified live by: dummy-process recreation above (tip red / branch green, same host pgrep match); bun test test/gstack-gbrain-sync.test.ts (42 pass).
  • Did NOT test: real gbrain autopilot --install. A live lock under an operator GBRAIN_HOME (child now blanks it). Paid evals. Full bun run test.

Liveness proof (required)

GSTACK PR typed live into the browser address bar:

GSTACK PR typed live

Checklist

Test plan

  • Quiet machine, tip, no stub → named it passes (no signal)
  • Dummy argv gbrain autopilot, tip, no stub → named it fails, status 1
  • Same dummy still up, this branch → named it passes
  • bun test test/gstack-gbrain-sync.test.ts → 42 pass
  • Dummy killed; host pgrep exit 1 again

Fork PRs do not get eval secrets; the free file above is the gate.

szsunyuan and others added 2 commits August 24, 2026 18:00
The only non-dry-run --code-only child hits garrytan#1734's PATH-resolved
autopilot probe. A live host daemon is a correct refuse; the test
cannot inject processRunning. Neutralize pgrep in the fixture bindir
instead of adding a production env hatch.

Co-authored-by: Cursor <cursoragent@cursor.com>
Lock paths are checked before pgrep. Spreading process.env let a runner
GBRAIN_HOME with a live lock refuse the case before the stub ran.

Co-authored-by: Cursor <cursoragent@cursor.com>
@trunk-io

trunk-io Bot commented Aug 24, 2026

Copy link
Copy Markdown

Merging to main in this repository is managed by Trunk.

  • To merge this pull request, check the box to the left or comment /trunk merge below.

After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here

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.

test(gbrain-sync): "keeps a symlink-equivalent pinned source registered as-is" fails on any machine running gbrain autopilot

1 participant