`get_readme` and `get_file_content` answered every failure with a string --
`[README not found: HTTP 404]`, `[File not found: HTTP 404]` -- while `main()`
prints any string result on stdout and exits 0. A rate-limited run, a missing
repository and a real README therefore arrived on the same channel with the same
exit code, so a caller reading stdout could not tell a failure from a body.
Both readers now raise `GitHubAPIError` naming the operation, the target and the
underlying HTTP error. The CLI's existing handler already writes an exception to
stderr and exits 1, so a failure leaves the success channel empty and the status
stays visible; a successful fetch is unchanged.
Pins both transports (requests and the urllib fallback), 404 against 403 so a
rate limit cannot read as a missing repository, the file reader's path, and the
CLI contract: non-zero exit, empty stdout, status on stderr.
* fix(github-research): resolve the tree against the repository's default branch
The tree command asked for "main" and, when that was missing, for "master".
A repository whose default branch is neither gets a name-guessing fallback, and
when the stale "master" still resolves GitHub returns it happily: the agent is
handed the tree of an abandoned branch and reports it as the current structure.
Ask for HEAD instead, which GitHub resolves to the repository's own default
branch, so no candidate names are guessed and no extra request is added.
* test(github-research): clarify stale branch tree comment
---------
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
Preserve filename delimiters and literal percent escapes before either HTTP transport builds a Contents API request. Add offline regression coverage for requests and the urllib fallback.