gstack icon indicating copy to clipboard operation
gstack copied to clipboard

fix: sourceLocalPath handles wrapped {sources:[...]} shape from gbrain v0.20+

Open jakehann11 opened this issue 1 month ago • 1 comments

Summary

bin/gstack-gbrain-sync.ts:sourceLocalPath() (added in v1.40.0.0 as part of the hostname-fold migration helpers) types the gbrain response as a flat Array<{ id, local_path }> and calls .find() on it directly. gbrain v0.20+ returns {sources: [...]} (object wrapping the array), not a flat array.

Result: /sync-gbrain crashes immediately on the orchestrator's first call to sourceLocalPath with:

gstack-gbrain-sync fatal: list.find is not a function.
(In 'list.find((s) => s.id === sourceId)', 'list.find' is undefined)

The sibling helpers probeSource and sourcePageCount in lib/gbrain-sources.ts already handle the wrapped shape correctly (parse {sources?: Array<...>}, fall back to []). This PR brings sourceLocalPath in line.

The fix accepts both shapes (flat array OR {sources: [...]}) for backward compatibility with any older gbrain still in the wild.

Reproduction

  • gstack v1.40.0.0 + gbrain v0.35.0.0 on Windows (MINGW64). Likely reproduces on macOS/Linux too — this is a pure data-shape bug, not a platform issue.
  • Invoke /sync-gbrain in any repo that already has registered sources (e.g., from gbrain sources add ... --path ...).
  • Orchestrator crashes before completing stage 1.

Workaround for affected users until this lands: skip the orchestrator and call gbrain sync --all --no-pull --yes directly.

Test plan

  • [x] New regression test handles {sources: [...]} wrapped shape (gbrain v0.20+) mocks the actual v0.20+ response shape and asserts the lookup succeeds.
  • [x] New regression test returns null when the source is missing in the wrapped shape covers the empty-array case.
  • [x] Existing tests preserved (flat-array shape still supported for backward compat).
  • [ ] CI verifies on Linux (the existing makeShim infra uses #!/bin/sh shebang scripts so the test pattern doesn't run on Windows directly; pre-existing limitation).

🤖 Generated with Claude Code

jakehann11 avatar May 17 '26 22:05 jakehann11

This appears to overlap with #1564: both fix sourceLocalPath() in bin/gstack-gbrain-sync.ts for the same wrapped {sources:[...]} gbrain response and the same list.find is not a function crash.

I'd treat #1564 as the canonical PR because it was opened earlier and also covers the malformed wrapped payload case with an Array.isArray(list) guard before .find(). If this PR stays active, the missing malformed-payload guard/test should be ported here; otherwise closing this as duplicate avoids two competing fixes for the same path.

jbetala7 avatar May 18 '26 06:05 jbetala7

Thanks @jakehann11 — sourceLocalPath fix shipped in v1.42.0.0 Daegu wave (#1594) as the chosen patch.

garrytan avatar May 26 '26 03:05 garrytan