27 tests covering the surface that had none:
- parseGitSourceUrl: bare URLs (github/gitea/gitlab), tree/blob/src
shapes, subpaths, file paths, trailing .git stripping, https-only
enforcement, malformed/missing-segment rejection.
- resolveGitRef: 40-hex SHA passthrough (no network call), default
branch via HEAD symref, named branch, peeled annotated tag, lightweight
tag, ref-not-found, network/401/404 error translation, onAuth
callback shape (token-as-username, x-oauth-basic) and absence.
- openRepoSnapshot: clone args (singleBranch/depth=1/noCheckout),
tree walk filtering trees vs blobs, readFile path, SHA fallback
when tracking ref is null, 404 translation.
Mocks at the isomorphic-git boundary; verifies our adaptation logic,
not isomorphic-git itself.
Known limit surfaced by a test (not fixed here): gitea URLs with
slash-containing branch names like /src/branch/feature/x are
ambiguous without server-side disambiguation. The test uses a
single-segment branch; the multi-segment case needs a separate fix
(refCandidates from longest-to-shortest, resolved against
listServerRefs output).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The skill import/update/file-read pipeline talked to host-specific REST
APIs (GitHub /commits/{ref}, /git/trees/{sha}, raw.githubusercontent.com)
and the recent Gitea support was a parallel shim on top of the same
pattern. The result was multiple ref-resolution shapes that needed
per-host branching, and on Gitea the /commits/{ref} endpoint returns
404 outright -- so even public Gitea/Forgejo repos failed to import.
Replace with a single git-source module backed by isomorphic-git +
memfs. It speaks the smart-HTTP protocol any sane git server already
serves:
- resolveGitRef: one listServerRefs call, no host API. Handles default
branch (symref on HEAD), named branches, annotated/lightweight tags,
and SHA passthrough.
- openRepoSnapshot: shallow singleBranch clone into an in-memory fs;
listFiles via git.walk, readFile via git.readBlob. No tempdirs, no
execFile, no per-host endpoints.
- Universal auth via onAuth (token-as-username) covering GitHub PATs,
GitLab PATs, Gitea/Forgejo tokens.
- parseGitSourceUrl recognises github tree/blob, gitea src/branch|
commit|tag, gitlab /-/tree, bitbucket /src/{ref} URL shapes plus
bare clone URLs.
Stored skill metadata is unchanged (hostname/owner/repo/ref/trackingRef/
repoSkillDir), so existing rows keep working -- the clone URL is
derived at fetch time.
company-portability.ts still imports github-fetch.ts (same broken
pattern, separate feature). Left as a follow-up.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>