Repository navigation
feat: explicit fetch refspec — wildcard map + touchpoint discipline, managed config keys - #29
Merged
Merged
Conversation
…managed config keys, spec-worktree restructure - Replace per-branch refspec reconciliation with one wildcard map (+refs/heads/*:refs/remotes/origin/*) written at clone and converged at every fetching touchpoint; one predicate per key, no remote comparison, no per-branch bookkeeping. - Touchpoint fetch discipline (sync / info / context --startup / prune): maintain config first, then fetch the default branch plus every tracked branch with one explicit colon refspec each — never a bare fetch. A tracked branch the remote lost fails silently; one closing `git remote prune origin` (gated on the wildcard shape) converges the refs. The default branch is the one loud failure: an ls-remote probe tells "remote lost its default" (reported) from offline (silent). - Config ownership: three managed keys (remote.origin.fetch, fetch.prune, push.default=upstream), each with a three-mode switch — git.fetchAllBranches / git.fetchPrune / git.pushUpstreamByDefault (always/once/never). Every convergence is reported per key with its escape-hatch command; once/never pools are untouched and unreported. The switches govern config ownership, not ref hygiene. - Remove push.autoSetupRemote handling and the doctor 2.37 soft gate; raw mode is plain git. `orbit switch -c` wires upstream config up front; the first push materializes the tracking ref on the spot. - orbit config: key-identity checks (repos.* refusal, branch.prefix validation, the three-mode switches) compare the lowercased key — git config key names are case-insensitive, so a cased spelling must not bypass its guard. Shell completions list the registered keys. - docs: spec-branching -> spec-worktree restructure (Root Decision, Config Ownership, Touchpoint Fetch Discipline, Prune's Git Binding, Git Dependency Closure); spec-lifecycle keeps substrate-independent workspace invariants with the git binding pointed into spec-worktree. Recovery narrative corrected: a branch/worktree deletion takes its reflogs with it; the handle is (was <sha>) + objects surviving gc. - tests: hermetic git config layers (GIT_CONFIG_GLOBAL/SYSTEM=/dev/null); coverage for convergence and one-shot quiet, once/never modes, the count=0 shape, probe tri-state, residue ordering after the sweep, named-only fetch, raw bare push, and the config-key case bypass. Signed-off-by: zheng-weihao <zheng-weihao@outlook.com>
4 tasks done
zheng-weihao
added a commit
to zheng-weihao/orbit
that referenced
this pull request
Aug 13, 2026
…ocal - orbcli#29's touchpoint fetch made every `orbit info` and every session start with worktrees pay N serial remote round-trips (default branch + each tracked branch, one fetch each), multiplying with scoped-branch residue; measured baselines: `orbit info` 4.83s wall / ~0.4s CPU on a repo with 4 tracked branches, 19.7s on a pool carrying more scoped-branch residue, `context --startup` 24.5s with two repos added - ruling: without an async daemon, auto-fetch on a main path taxes a synchronous caller for advisory freshness — low friction outranks it (cf. VSCode's background autofetch never blocking startup); auto-fetch may return only off the main path - info and the context --startup reignite block drop the touchpoint fetch and keep config maintenance (local writes); remoteAhead now reads last-fetched refs, refreshed by sync / prune or the user's own fetch/pull; fetching touchpoints narrow to sync / prune - skill contract (SKILL.md + CONSTRAINTS.md): steps 3/5 state the last-fetched-refs semantics; cold-start sync becomes a two-trigger rule (remoteAhead > 0, or a stale last fetch when the task depends on fresh code) - spec-docs, USAGE, ROADMAP, CHANGELOG and the two info-fetch bats cases sync to the new contract; full suite 367/367 on latest main Signed-off-by: Zheng Weihao <zheng-weihao@outlook.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replaces the per-branch fetch-refspec machinery (three layers each fixing the previous layer's side effects) with a single wildcard map plus a touchpoint discipline, and turns every git config key orbit depends on into managed state with a three-mode escape hatch.
Core mechanism
+refs/heads/*:refs/remotes/origin/*written at clone, converged at every fetching touchpoint (sync/info/context --startup/prune) — one predicate per key, no remote comparison, no per-branch bookkeeping.couldn't find remote refleakage); one closinggit remote prune origin, gated on the wildcard shape, converges the refs. The default branch is the one loud failure: anls-remote --exit-codeprobe tells "remote lost its default branch" (WARNING) from offline (silent).remote.origin.fetch,fetch.prune,push.default=upstream), each with a three-mode switch —git.fetchAllBranches/git.fetchPrune/git.pushUpstreamByDefault=always(default) /once/never. Every convergence is reported per key with its escape-hatch command;once/neverpools are untouched and unreported. The switches govern config ownership, not ref hygiene — ref cleanup follows the layout shape.push.autoSetupRemotehandling and the doctor 2.37 soft gate removed; raw mode is plain git.orbit switch -cwires upstream config up front; the first push materializes the tracking ref on the spot.sync --branchwrites no fetch config (the wildcard already covers the new default).Also in this PR
orbit configkey-identity checks (repos.* refusal,branch.prefixvalidation, the three-mode switches) now compare the lowercased key — git config key names are case-insensitive, so a cased spelling must not bypass its guard.spec-branching→spec-worktree(Root Decision, Config Ownership, Touchpoint Fetch Discipline, Prune's Git Binding, Git Dependency Closure — orbit's git dependencies enumerated as a closed set that only shrinks);spec-lifecyclekeeps substrate-independent workspace invariants and points at the binding. Recovery narrative corrected: branch/worktree deletion takes its reflogs with it; the recovery handle is(was <sha>)+ objects surviving gc.GIT_CONFIG_GLOBAL/SYSTEM=/dev/null); new coverage for convergence + one-shot quiet, once/never modes, the emptied-config (count=0) shape, the probe tri-state, residue ordering after the sweep, named-only fetch, raw bare push, and the config-key case bypass.Breaking changes (in CHANGELOG): per-branch fetch refspec reconciliation removed (converges automatically at the next touchpoint);
push.autoSetupRemoteno longer set (raw-mode users who relied on it:git push -u origin <branch>once).Test plan
make test— 341/341 green(The one-time full-fetch step this change introduces on user-run
git fetch/git pullstays qualitative in the CHANGELOG by design; quantifying it on giant repos is a release-time measurement, tracked on the 0.2.0 checklist — not a gate for this PR.)