Read the origin remote in os-backlog through the git gem #853

Open
opened 2026-09-30 17:23:56 +00:00 by jared · 4 comments
Owner

Problem

os-backlog reads the git remote in two places. Both start a git process and parse its text output.

plugins/os-backlog/lib/backlog/inspect_command.rb:16
  remote_output = capture("git", "-C", @repo_root, "remote", "-v")
  remote_info = Backlog::Tracker.parse_remote(remote_output)

plugins/os-backlog/lib/backlog/config_write_command.rb:56-59
  def origin_remote
    out, ok = Backlog::Issues::ShellRunner.new.capture("git", "remote", "get-url", "origin")
    ok && !out.strip.empty? ? out.strip : nil
  end

origin_remote also has a defect. It runs in the process working directory, not in @repo_root. When config-write runs for a repository other than the working directory, it stores the wrong remote in the project index. It also creates its own ShellRunner, so no test can replace it. tests/cli_config_write_command_test.rb runs the real git in the test's working directory.

Reproduce

n/a: the working-directory defect needs a config-write call whose repo_root differs from the working directory. Acceptance criterion 2 is the observable check.

Approach

Both call sites read the remote through the git gem. They use the same gem and the same dependency mechanism as the git gem work from session f531ed01.

Required work:

  1. Make the git gem loadable from os-backlog. os-backlog has no Gemfile today. Use the mechanism that session f531ed01 chose for the other plugins.

Rejected: keep git remote through ShellRunner — #845 moves all git commands to the git gem.

Acceptance criteria

  1. Given a repository whose origin is a Forgejo URL, when inspect runs on it, then the findings report the same git_remote kind, owner, and repo as today.
  2. Given config-write runs with a repo_root that is not the working directory, when it upserts the project index, then the stored remote is the origin URL of repo_root.
  3. Given a repository with no origin remote, when config-write runs, then the stored remote is empty.
  4. Given any inspect or config-write run, when it completes, then no git process started for the remote lookup.

Owner sketch

class Backlog::OriginRemote
  def initialize(repo_root)
    @repo = Git.open(repo_root)
  end

  def url
    @repo.remote("origin").url
  end
end

InspectCommand and ConfigWriteCommand use OriginRemote.new(@repo_root). Tracker.parse_remote accepts the URL, not the git remote -v text.

Non-goals

  • The tea and gh calls. A REST-client decision is pending.

Blocked by

  • The git gem work in session f531ed01. Start only after it is on main.

Origin

  • Trigger: #845 shell-call audit, 2026-09-30.
  • Improvised this session: none
  • Chain: config-write can store the wrong remote ← origin_remote runs git in the process working directory with a hard-wired ShellRunner (config_write_command.rb:57) ← IMPROVISATION: no recorded reason.
  • Root candidate: this ticket
  • Where: plugins/os-backlog/lib/backlog/inspect_command.rb, plugins/os-backlog/lib/backlog/config_write_command.rb
  • Session: f090dd39-8ad6-4f4e-8743-7bbedb8f08d4
  • Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/f090dd39-8ad6-4f4e-8743-7bbedb8f08d4.jsonl
## Problem os-backlog reads the git remote in two places. Both start a `git` process and parse its text output. ``` plugins/os-backlog/lib/backlog/inspect_command.rb:16 remote_output = capture("git", "-C", @repo_root, "remote", "-v") remote_info = Backlog::Tracker.parse_remote(remote_output) plugins/os-backlog/lib/backlog/config_write_command.rb:56-59 def origin_remote out, ok = Backlog::Issues::ShellRunner.new.capture("git", "remote", "get-url", "origin") ok && !out.strip.empty? ? out.strip : nil end ``` `origin_remote` also has a defect. It runs in the process working directory, not in `@repo_root`. When config-write runs for a repository other than the working directory, it stores the wrong remote in the project index. It also creates its own `ShellRunner`, so no test can replace it. `tests/cli_config_write_command_test.rb` runs the real `git` in the test's working directory. ## Reproduce n/a: the working-directory defect needs a config-write call whose `repo_root` differs from the working directory. Acceptance criterion 2 is the observable check. ## Approach Both call sites read the remote through the git gem. They use the same gem and the same dependency mechanism as the git gem work from session f531ed01. Required work: 1. Make the git gem loadable from os-backlog. os-backlog has no Gemfile today. Use the mechanism that session f531ed01 chose for the other plugins. Rejected: keep `git remote` through `ShellRunner` — #845 moves all git commands to the git gem. ## Acceptance criteria 1. Given a repository whose `origin` is a Forgejo URL, when inspect runs on it, then the findings report the same `git_remote` kind, owner, and repo as today. 2. Given config-write runs with a `repo_root` that is not the working directory, when it upserts the project index, then the stored `remote` is the `origin` URL of `repo_root`. 3. Given a repository with no `origin` remote, when config-write runs, then the stored `remote` is empty. 4. Given any inspect or config-write run, when it completes, then no `git` process started for the remote lookup. ## Owner sketch ```ruby class Backlog::OriginRemote def initialize(repo_root) @repo = Git.open(repo_root) end def url @repo.remote("origin").url end end ``` `InspectCommand` and `ConfigWriteCommand` use `OriginRemote.new(@repo_root)`. `Tracker.parse_remote` accepts the URL, not the `git remote -v` text. ## Non-goals - The tea and gh calls. A REST-client decision is pending. ## Blocked by - The git gem work in session f531ed01. Start only after it is on main. ## Origin - Trigger: #845 shell-call audit, 2026-09-30. - Improvised this session: none - Chain: config-write can store the wrong remote ← `origin_remote` runs `git` in the process working directory with a hard-wired `ShellRunner` (config_write_command.rb:57) ← IMPROVISATION: no recorded reason. - Root candidate: this ticket - Where: plugins/os-backlog/lib/backlog/inspect_command.rb, plugins/os-backlog/lib/backlog/config_write_command.rb - Session: f090dd39-8ad6-4f4e-8743-7bbedb8f08d4 - Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os/f090dd39-8ad6-4f4e-8743-7bbedb8f08d4.jsonl
Author
Owner

Blocked by #866 (Forgejo dependency recorded).

Blocked by #866 (Forgejo dependency recorded).
Author
Owner

Related finding, recorded 2026-10-03 (session a0dbd5c4). os-sdlc has git calls outside its git adapter Git::Repo: plugins/os-sdlc/lib/os_sdlc/adapter/mutation/check.rb:73 runs git apply as a shell string through ProjectShell.capture3, and plugins/os-sdlc/lib/os_sdlc/adapter/lint_changed/changed_files.rb:11,31 run git through their own capture. No defect is known; an independent judge ranked the move as marginal, and a ticket-skeptic verdict of DROP stopped a separate ticket. Include these call sites when the git gem work is planned. See also #925.

Related finding, recorded 2026-10-03 (session a0dbd5c4). os-sdlc has git calls outside its git adapter `Git::Repo`: `plugins/os-sdlc/lib/os_sdlc/adapter/mutation/check.rb:73` runs `git apply` as a shell string through `ProjectShell.capture3`, and `plugins/os-sdlc/lib/os_sdlc/adapter/lint_changed/changed_files.rb:11,31` run `git` through their own `capture`. No defect is known; an independent judge ranked the move as marginal, and a ticket-skeptic verdict of DROP stopped a separate ticket. Include these call sites when the git gem work is planned. See also #925.
Author
Owner

Resolution

Done: Folded into #1594: origin reads go through OsGit at the repository root, which fixes the wrong-directory defect.

Evidence: main 177518ea; #1594 tests pin a repository other than the process directory.

Follow-ups: none. AC 4 (no git process) is superseded: the spike dropped the in-process adapter, rulings row 37.

## Resolution **Done:** Folded into #1594: origin reads go through OsGit at the repository root, which fixes the wrong-directory defect. **Evidence:** main 177518ea; #1594 tests pin a repository other than the process directory. **Follow-ups:** none. AC 4 (no git process) is superseded: the spike dropped the in-process adapter, rulings row 37.
Author
Owner

Folded into #1594, merged as 177518ea: origin reads go through OsGit at the repository root, which fixes the wrong-directory defect. AC 4 (no git process) is superseded by the dropped in-process adapter (rulings row 37). The tracker refused to close this ticket because it depends on open #866. Remove that dependency or close after #866.

Folded into #1594, merged as 177518ea: origin reads go through OsGit at the repository root, which fixes the wrong-directory defect. AC 4 (no git process) is superseded by the dropped in-process adapter (rulings row 37). The tracker refused to close this ticket because it depends on open #866. Remove that dependency or close after #866.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
jared/cc-os#853
No description provided.