One gem source rule: path to the ~/dev checkout, no pin, no symlink (os_git first) #1630

Closed
opened 2026-11-06 22:05:45 +00:00 by jared · 3 comments
Owner

Problem

Our own gems reach their consumers in three different ways, and two of them break:

Gem Source today Failure
os_git path: ../os-git, else ~/.claude/plugins/os-git Works only through a symlink that no script creates. A project outside cc-os/plugins cannot use a sibling path. A plugin-cache copy rewrites its lock to an absolute path and fails under BUNDLE_FROZEN.
forgejo-api Forgejo git: source The lock pins a revision. Each gem commit makes each consumer fail or need a lock update. Jared stopped using git sources for this reason.
llm-stack, decision-model, procman path: ~/dev/<repo> Works. No pin, no symlink. A gem commit reaches each consumer with no lock change.

ADR-0303 clause 4 still says the Forgejo git source is the rule and a path source is only a local override. Practice reversed it.

Jared's requirement (2026-11-09): a gem commit must not force a change in any consumer project. The source may name the repository, but no commit, branch, or version pin. This must work on each new machine with no manual step.

Approach

  1. One rule for each gem we own: the consumer Gemfile uses path: to the machine's checkout of the gem's repository, at the fixed location ~/dev/<repo> (for os_git: ~/dev/cc-os/plugins/os-git). Forgejo is how a machine gets and updates the checkout (clone, then pull). Bundler never fetches from Forgejo. A path source records no revision, so a gem commit changes no lock.
  2. Record the rule through /os-adr:create. It supersedes ADR-0303 clause 4 and states the ~/dev/<repo> layout as a machine contract.
  3. Move each os_git consumer to the rule: plugins/os-sdlc, plugins/os-me, plugins/os-backlog. Remove the sibling-or-symlink logic.
  4. Add a machine check to the global plugin setup path (bin/refresh-plugins or the check it calls). It reports each gem repository that a Gemfile names and that is not cloned at ~/dev/<repo>, with the clone command.
  5. Remove the ~/.claude/plugins/os-git link step from docs/implementation-status/os-git.md.

Not in this ticket: moving forgejo-api off its git source. File it as a follow-up with the ADR, because os-backlog and os-sdlc both pin it.

Required work: none beyond the acceptance criteria.

Acceptance criteria

  1. Given a commit to plugins/os-git, when os-sdlc, os-me, and os-backlog boot, then each loads the new code and no Gemfile.lock changes.
  2. Given a machine where ~/.claude/plugins/os-git does not exist, when os-sdlc, os-me, and os-backlog boot, then each boots.
  3. Given a machine without ~/dev/cc-os, when the global plugin setup path runs, then it names the missing checkout and the clone command.
  4. Given the ADR index, when it is searched for the gem source rule, then one Accepted ADR states it and ADR-0303 clause 4 is superseded.

Origin

  • Trigger: review of the os-git Gemfile path: source; rewritten 2026-11-09 after Jared ruled out the symlink and any pinned git source
  • Improvised this session: none
  • Chain: Bundler boot failure, or a lock change on each gem commit ← each gem has its own source pattern ← DESIGN (ADR-0303 clause 4 names a pinned git source; practice moved to path sources with no recorded rule)
  • Root candidate: none found; searched os-git, .claude/plugins/os-git, symlink, refresh-plugins, path source, ADR-0303
  • Where: plugins/*/Gemfile, bin/refresh-plugins, docs/adr/0303-*
  • Session: bc5ad309-36b7-4fe5-a67f-1d90187242eb

VERDICT: CREATE

## Problem Our own gems reach their consumers in three different ways, and two of them break: | Gem | Source today | Failure | |---|---|---| | `os_git` | `path: ../os-git`, else `~/.claude/plugins/os-git` | Works only through a symlink that no script creates. A project outside `cc-os/plugins` cannot use a sibling path. A plugin-cache copy rewrites its lock to an absolute path and fails under `BUNDLE_FROZEN`. | | `forgejo-api` | Forgejo `git:` source | The lock pins a revision. Each gem commit makes each consumer fail or need a lock update. Jared stopped using git sources for this reason. | | `llm-stack`, `decision-model`, `procman` | `path: ~/dev/<repo>` | Works. No pin, no symlink. A gem commit reaches each consumer with no lock change. | ADR-0303 clause 4 still says the Forgejo git source is the rule and a path source is only a local override. Practice reversed it. Jared's requirement (2026-11-09): a gem commit must not force a change in any consumer project. The source may name the repository, but no commit, branch, or version pin. This must work on each new machine with no manual step. ## Approach 1. One rule for each gem we own: the consumer Gemfile uses `path:` to the machine's checkout of the gem's repository, at the fixed location `~/dev/<repo>` (for os_git: `~/dev/cc-os/plugins/os-git`). Forgejo is how a machine gets and updates the checkout (clone, then pull). Bundler never fetches from Forgejo. A path source records no revision, so a gem commit changes no lock. 2. Record the rule through `/os-adr:create`. It supersedes ADR-0303 clause 4 and states the `~/dev/<repo>` layout as a machine contract. 3. Move each `os_git` consumer to the rule: `plugins/os-sdlc`, `plugins/os-me`, `plugins/os-backlog`. Remove the sibling-or-symlink logic. 4. Add a machine check to the global plugin setup path (`bin/refresh-plugins` or the check it calls). It reports each gem repository that a Gemfile names and that is not cloned at `~/dev/<repo>`, with the clone command. 5. Remove the `~/.claude/plugins/os-git` link step from `docs/implementation-status/os-git.md`. Not in this ticket: moving `forgejo-api` off its git source. File it as a follow-up with the ADR, because os-backlog and os-sdlc both pin it. Required work: none beyond the acceptance criteria. ## Acceptance criteria 1. Given a commit to `plugins/os-git`, when os-sdlc, os-me, and os-backlog boot, then each loads the new code and no `Gemfile.lock` changes. 2. Given a machine where `~/.claude/plugins/os-git` does not exist, when os-sdlc, os-me, and os-backlog boot, then each boots. 3. Given a machine without `~/dev/cc-os`, when the global plugin setup path runs, then it names the missing checkout and the clone command. 4. Given the ADR index, when it is searched for the gem source rule, then one Accepted ADR states it and ADR-0303 clause 4 is superseded. ## Origin - Trigger: review of the os-git Gemfile `path:` source; rewritten 2026-11-09 after Jared ruled out the symlink and any pinned git source - Improvised this session: none - Chain: Bundler boot failure, or a lock change on each gem commit ← each gem has its own source pattern ← DESIGN (ADR-0303 clause 4 names a pinned git source; practice moved to path sources with no recorded rule) - Root candidate: none found; searched os-git, .claude/plugins/os-git, symlink, refresh-plugins, path source, ADR-0303 - Where: `plugins/*/Gemfile`, `bin/refresh-plugins`, `docs/adr/0303-*` - Session: bc5ad309-36b7-4fe5-a67f-1d90187242eb VERDICT: CREATE
Author
Owner

From #1594: with no link, every os-backlog CLI command exits 1 and advises bundle install, not ln -s; decision-sweep and wakeup-poll print backtraces. The hook warns and exits 0.

From #1594: with no link, every os-backlog CLI command exits 1 and advises bundle install, not ln -s; decision-sweep and wakeup-poll print backtraces. The hook warns and exits 0.
jared changed title from Create or check the ~/.claude/plugins/os-git link in plugin setup to One gem source rule: path to the ~/dev checkout, no pin, no symlink (os_git first) 2026-11-09 17:24:44 +00:00
Author
Owner

Resolution

Done: os_git is declared by path to ~/dev/cc-os/plugins/os-git in os-sdlc, os-me, and os-backlog (no sibling, no symlink, no pin). bin/refresh-plugins reports each missing ~/dev checkout with its clone command (lib/gem_checkout_check.rb, bin/check-gem-checkouts runs it alone). plugins/os worktree and handoff, and the repo-root links in os, os-adr, os-backlog, os-aidd-lint, fall back to the ~/dev checkout instead of ~/.claude/plugins/os-git. ADR-0310 states the rule; ADR-0303 clause 4 and ADR-0257 item 2 removed by amend; ruling 95 supersedes ruling 56.

Evidence: main 4b8f679c (ADR), 80617272a (ruling 95), 49bc34d87 d747f4e18 63cd44049 merged in f5303d531. AC1: each lock records PATH remote /home/jared/dev/cc-os/plugins/os-git with no revision; the cached copies of os-sdlc, os-me, os-backlog boot under BUNDLE_FROZEN and load os_git from ~/dev/cc-os/plugins/os-git. AC2: no Gemfile or Ruby file under plugins/ reads ~/.claude/plugins/os-git (grep 0 matches outside .md). AC3: gem_checkout_check_test 5 runs 0 failures; sample output names the missing checkout and git clone command. AC4: ADR-0310 Accepted. Link tests: os, os-adr, os-backlog, os-aidd-lint, os-git delegation, os handoff+worktree smoke all green. Plugin cache refreshed by worktree finish with no mutation run active.

Follow-ups: #1648 moves forgejo-api to the path source. Skill and reference .md text that calls ~/.claude/plugins/os-git/bin/os-git goes with #1631 (PATH); the symlink is removed after #1631.

## Resolution **Done:** os_git is declared by path to ~/dev/cc-os/plugins/os-git in os-sdlc, os-me, and os-backlog (no sibling, no symlink, no pin). bin/refresh-plugins reports each missing ~/dev checkout with its clone command (lib/gem_checkout_check.rb, bin/check-gem-checkouts runs it alone). plugins/os worktree and handoff, and the repo-root links in os, os-adr, os-backlog, os-aidd-lint, fall back to the ~/dev checkout instead of ~/.claude/plugins/os-git. ADR-0310 states the rule; ADR-0303 clause 4 and ADR-0257 item 2 removed by amend; ruling 95 supersedes ruling 56. **Evidence:** main 4b8f679c (ADR), 80617272a (ruling 95), 49bc34d87 d747f4e18 63cd44049 merged in f5303d531. AC1: each lock records PATH remote /home/jared/dev/cc-os/plugins/os-git with no revision; the cached copies of os-sdlc, os-me, os-backlog boot under BUNDLE_FROZEN and load os_git from ~/dev/cc-os/plugins/os-git. AC2: no Gemfile or Ruby file under plugins/ reads ~/.claude/plugins/os-git (grep 0 matches outside .md). AC3: gem_checkout_check_test 5 runs 0 failures; sample output names the missing checkout and git clone command. AC4: ADR-0310 Accepted. Link tests: os, os-adr, os-backlog, os-aidd-lint, os-git delegation, os handoff+worktree smoke all green. Plugin cache refreshed by worktree finish with no mutation run active. **Follow-ups:** #1648 moves forgejo-api to the path source. Skill and reference .md text that calls ~/.claude/plugins/os-git/bin/os-git goes with #1631 (PATH); the symlink is removed after #1631. <!-- os-backlog kind: resolution -->
jared closed this issue 2026-11-09 17:40:32 +00:00
Author
Owner

Correction to the follow-ups line: the ~/.claude/plugins/os-git link stays. Every cc-os plugin has the same link, and the shell PATH reads each plugin's bin/ through it. The ban in ADR-0310 covers gem sources only, and no gem source uses the link now.

Correction to the follow-ups line: the `~/.claude/plugins/os-git` link stays. Every cc-os plugin has the same link, and the shell PATH reads each plugin's `bin/` through it. The ban in ADR-0310 covers gem sources only, and no gem source uses the link now.
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.

Dependencies

No dependencies set

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