4.9 KiB
id, title, status, wave, depends_on, plan, spec
| id | title | status | wave | depends_on | plan | spec | |
|---|---|---|---|---|---|---|---|
| 02-stale-base-correction | Correct stale commits-panel base to the integration merge-base | done | 2 |
|
plan.md | ../../specs/platform/requirements/workspace-git-status.md |
Task 02: Correct stale commits-panel base to the integration merge-base
When the resolved base commit (from the stored target branch) is a strict ancestor of the
integration merge-base (origin/main → origin/master), anchor the commits panel and
cumulative diff to the integration merge-base instead. Fixes the inflated 31-vs-1 commit count
in the stacked-PR / merged-parent case.
Context / Inputs
- Spec:
docs/specs/platform/requirements/workspace-git-status.md→ "Base-commit staleness and refresh", Failure modes rows, and Scenarios 1–4. - Confirmed root cause (see
plan.md): stored target = merged/deleted stacked parent →computeMergeBasefalls back to stale local ref (ed630b8446, 31 commits) instead ofmerge-base(HEAD, origin/master)(19646efc83, 1 commit). - Seam:
runGitLogForRepoandcomputeMergeBaseinapps/backend/internal/agentctl/server/api/git.go(already prefersorigin/<target>). - Priority list to mirror:
branchDiffCandidatesinapps/backend/internal/agentctl/server/process/workspace_git_status.go(origin/main → origin/master → main → master). For the merge-base,computeMergeBasealready triesorigin/<name>first, so pass baremain/master. - Depends on
GitOperator.IsAncestorfrom task 01.
Implementation
In apps/backend/internal/agentctl/server/api/git.go:
- Add
var integrationMergeBaseCandidates = []string{"main", "master"}. - Add
func (s *Server) integrationMergeBase(ctx context.Context, gitOp *process.GitOperator) string: first non-emptycomputeMergeBase(HEAD, candidate)over the candidates; "" if none resolve. - Add
func (s *Server) correctStaleBase(ctx, gitOp, baseCommit, targetBranch string) string:- Return
baseCommitunchanged whentargetBranchis empty or is itself an integration candidate (main/master, with or withoutorigin/prefix) — avoid redundant self-compare. - Compute
integ := s.integrationMergeBase(...); returnbaseCommitifinteg == ""orinteg == baseCommit. anc, err := gitOp.IsAncestor(ctx, baseCommit, integ); iferr == nil && anc && baseCommit != integreturninteg(stale base is strictly behind the integration line → correct it). Otherwise returnbaseCommit(equal/descendant/diverged/errored → unchanged).
- Return
- In
runGitLogForRepo, after the existing block setsbaseCommitfrom the target-branch merge-base (and beforegitOp.GetLog), setbaseCommit = s.correctStaleBase(c.Request.Context(), gitOp, baseCommit, req.TargetBranch). Preserve the existing inlinesafeBranchRefPatternsanitiser barriers;main/masterliterals are constant and safe. - Keep
runGitLogForRepowithin golangci limits (≤80 lines / ≤50 statements / complexity ≤15) — the logic lives in the extracted helpers above.
Area 2 (cumulative diff parity): confirm whether the live cumulative-diff handler shares this
base resolution. If it computes its own base against the target branch, apply the same
correctStaleBase call there. Do NOT touch lifecycleAdapter.GetCumulativeDiff
(orchestrator snapshot path anchors to a caller-provided SHA by design).
Acceptance
- Regression: stale stacked-parent base is replaced by
merge-base(HEAD, origin/main); commits panel count equalsgit rev-list --first-parent --count <integ-merge-base>..HEAD(1 in repro). - A base equal to / descendant of the integration merge-base is returned unchanged.
- No
origin/*and unrelated history: no error, existing fallback preserved. runGitLogForRepopasses the changed-file linter at the PR base SHA.
Verification
cd apps/backend && go test -run 'TestComputeMergeBase|TestRunGitLogForRepo|TestGetLog' ./internal/agentctl/server/api/...
cd apps/backend && golangci-lint run ./internal/agentctl/server/api/... --new-from-rev="<base-sha>" --timeout=5m
Regression tests go in
apps/backend/internal/agentctl/server/api/git_log_merge_base_test.go (extend, reusing
setupAPITestRepo/runGitAPI/writeFileAPI). Write the stale-parent test FIRST and confirm it
fails before the code change.
Files likely touched
apps/backend/internal/agentctl/server/api/git.goapps/backend/internal/agentctl/server/api/git_log_merge_base_test.go- (only if Area 2 requires it)
apps/backend/internal/agentctl/server/process/workspace_git_status.go
Dependencies
Task 01 (GitOperator.IsAncestor).
Parallelism
sequential.
Output contract
Report: helpers added, exact insertion point in runGitLogForRepo, Area 2 finding
(shared vs separate cumulative-diff base), regression test red→green evidence, go test and
changed-file lint results, blockers/risks. Update this file's status and the task-02 checkbox
in plan.md.