Skip to content

feat: GitHub identity via config-dir profiles#101

Draft
levifig wants to merge 4 commits into
mainfrom
gh-config-dir-profiles
Draft

feat: GitHub identity via config-dir profiles#101
levifig wants to merge 4 commits into
mainfrom
gh-config-dir-profiles

Conversation

@levifig

@levifig levifig commented Jul 8, 2026

Copy link
Copy Markdown
Owner

Change

docs/changes/20260708-gh-config-dir-profiles/ β€” shaped, validated (loaf change check: zero violations, executable). Draft = spikes pending: Decision 5 gates all building on two empirical spikes, and one of them now has a documented counterexample to reproduce first.

What & Why

Successor to the parked PATH shim (PR #100 β€” rejected after implementation on mechanism nature, not correctness). Same invariant β€” per-invocation GitHub identity, agents type bare gh, repo names the account while the machine picks the mechanism β€” achieved through gh's own maintainer-endorsed mechanism: GH_CONFIG_DIR profiles (cli/cli#12145). One config dir per identity, each with a single-account hosts.yml, selected by an env var that is a path, not a secret, wired per-project through harness-native env config (Claude Code settings.local.json first). No PATH edits, no symlink, no binary dispatch, no token material in environments.

The tier vocabulary simplifies: tier 1 convergence (merged in #99 β€” default, zero footprint, disclosed pointer-collision cost) and tier 2 profiles (recommended opt-in). The hook retreats to pure-read verification wherever a profile mapping exists; convergence survives only as the fallback beneath it.

Review focus

  • Decision 5 β€” spike-before-build. The Hypothesis leans on two claims currently backed by a maintainer comment and reasoning: keyring isolation across config dirs, and git push HTTPS inheriting the profile env. GitHub Community Discussion #188559 reports the second one failing (gh honors the profile; git push reverts to the previously-logged-in account). Both spikes run before anything is built; the fog register carries the counterexample and the ships/ships-with-caveats/residual decision tree.
  • Decision 4 β€” the hook's evaluation order: gh auth exemption β†’ wired-and-matching pure-read pass β†’ wired-but-mismatched block (never converge someone's explicit profile choice) β†’ unwired convergence fallback.
  • The Cut list: the shim's rejection recorded with grounds (first rejection-KB seed); GH_TOKEN injection superseded; no auto-wiring ever.
  • Trust boundary: committed config names accounts only; GH_CONFIG_DIR paths live in machine-local files (settings.local.json). The untrusted-repo residual strictly improves over the shim β€” nothing maps accountβ†’profile unless the user wired it.

Verification

Shaping-stage: loaf change check docs/changes/20260708-gh-config-dir-profiles β€” zero violations, executable. U1 spike evidence (V2) will land in this folder's research/ as command-reproducible transcripts before U2–U5 build. H3 inherits the parked Change's DoD: this repo wired as the first production use, the 2026-07-07 account race rerun and won.

Migration / breaking changes

None at this stage. When implemented: strictly opt-in per machine and per project; tier-1 behavior unchanged for everyone else.

Deferred

  • Env wiring for Codex/Cursor/OpenCode/Amp β€” per-harness capability matrix follow-up; manual export documented meanwhile.
  • Terminal automation (direnv/mise recipes) β€” documentation, not machinery.
  • Profile config synchronization β€” accepted duplication until it hurts.

levifig added 4 commits July 8, 2026 01:06
Successor to the parked PATH shim (PR #100): per-identity gh config
profiles selected by GH_CONFIG_DIR β€” a path, not a secret β€” wired
per-project through harness-native env (Claude Code settings.local.json
first), with the github-account hook retreating to pure-read verification
wherever a profile mapping exists and convergence surviving only as
fallback. Maintainer-endorsed mechanism (cli/cli#12145); the native
--account selector was closed unmerged upstream. Spikes gate the build:
keyring isolation per config dir and credential-helper env inheritance.
The shim's rejection is recorded in Cut with grounds β€” mechanism nature,
not correctness β€” seeding the rejection-KB pattern.
…ange

A community report of GH_CONFIG_DIR being honored by gh but not by git
push credential resolution lands as a deliberately disconfirming Source
Input: both U1 spikes sharpen (keychain by-host lookup is the suspected
mechanism), the HTTPS matrix row's spike must reproduce the failure
before deciding ships/ships-with-caveats/residual, and core scope is
explicitly insulated from a failed spike.
…ofiles change

Two more #12145 inputs adjudicated: the maintainer's session-wide
GH_TOKEN export is concurrency-safe (env is per-process, zero disk
mutation β€” verified in the parked change's spike) but rejected as the
wired mechanism, since it puts a live secret in every subprocess env and
cannot be statically wired into harness config; kept as the zero-setup
terminal recipe. The field-proven conditional credential helper
(per-tree or repo-local git config resolving a named token inline)
becomes the likely shipped answer for the HTTPS matrix row β€” the one
surface gh's own mechanisms miss β€” and a U2 wiring candidate. The U1
spike now adjudicates three candidate mechanisms for HTTPS.
Both gate spikes pass with corrections. Keyring isolation is real at the
pointer layer only: profiles scope the active account, but credentials
live once machine-wide in the OS keychain, and --user/GH_TOKEN bypass
profile scoping entirely β€” profile health checks now probe the active
account without --user. Discussion #188559 did not reproduce here but
its mechanism is real (config-merge helper ordering), so GH_CONFIG_DIR
inheritance is documented as unreliable and the repo-local conditional
credential helper ships as the HTTPS mechanism, spike-verified to pin
identity against an adversarial pointer. New residual: a stale
osxkeychain internet-password for github.com found on this machine β€”
status/doctor will warn on the class. Transcripts in research/.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant