Skip to content

gitfetch: skill directory fetch fails when GH_TOKEN is scoped to a different repo than the skill source #2814

Description

@ggallen

What happens

When a config-registered agent (ADR-0058) references a skill directory in a different repository than the one the minted GH_TOKEN is scoped for, the git sparse checkout fetch fails with:

Error: loading harness: resolving URL-sourced resources: base skills[0]: fetching skill directory skills/issue-labels:
  gitfetch: git fetch: exit status 128: fatal: could not read Username for 'https://github.com': terminal prompts disabled

fetchBaseSkillDir in internal/harness/compose.go always passes opts.GitToken to FetchTree. When the token is an installation token scoped to repo A (e.g. ggallen-sandbox/integration-service) but the skill directory lives in repo B (e.g. fullsend-ai/agents), GitHub returns 401 — even though repo B is public. Sending an invalid-for-this-repo Authorization: Bearer header causes GitHub to reject the request instead of allowing anonymous access.

What should happen

Fetching skill directories from public repositories should succeed regardless of the GH_TOKEN scope. When an authenticated git fetch fails with an auth error, the fetch should retry without the token so that public repos remain accessible.

How to reproduce

  1. Configure a config-registered agent whose harness references a skill directory in a public repo (e.g. fullsend-ai/agents)
  2. Run the agent from an org where the minted GH_TOKEN is scoped to a different repo (e.g. ggallen-sandbox/integration-service)
  3. The harness loading fails at the skill directory fetch step

Observed in workflow run 28487585922 in ggallen-sandbox/.fullsend (v0.25.0). The triage harness in fullsend-ai/agents references skills/issue-labels; the minted triage token is scoped to ggallen-sandbox/integration-service.

Context

Introduced by #2735 / PR #2736 (replaced GitHub Contents API with git sparse checkout). The previous ForgeClient-based approach used the GitHub REST API which handled token scoping differently.

This blocks testing config-driven agent registration (ADR-0058) for any agent whose skills live in a different repo than the target. Related: #2805, #2806 (URL-sourced resource resolution fixes, both merged and in v0.25.0).

Metadata

Metadata

Assignees

No one assigned

    Labels

    component/harnessAgent harness, config, and skills loadingcomponent/skillspriority/highSignificant impact, address soonready-to-codeTriaged and ready for the code agenttype/bugConfirmed defect in existing behavior

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    Status
    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions