Skip to content

Add recovery guidance to shared gitutil error wrappers (cwd, git root, home directory) - #50990

Merged
pelikhan merged 5 commits into
mainfrom
copilot/add-recovery-guidance-to-gitutil
Aug 7, 2026
Merged

Add recovery guidance to shared gitutil error wrappers (cwd, git root, home directory)#50990
pelikhan merged 5 commits into
mainfrom
copilot/add-recovery-guidance-to-gitutil

Conversation

Copilot AI commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Low-level helpers in pkg/gitutil/gitutil.go wrapped common failures (current directory, git root, home directory) with bare fmt.Errorf("...: %w", err) and no recovery guidance, violating the repo's error-message style guide. These helpers back 8+ call sites in pkg/cli, each duplicating its own local wrap of the same failure.

pkg/gitutil changes

  • ErrNotGitRepository sentinel now carries recovery guidance directly (run this command from inside a git repository, or use 'git init' to create one) while remaining a stable sentinel for errors.Is checks.
  • New exported Getwd() and UserHomeDir() helpers wrap os.Getwd() / os.UserHomeDir() with actionable guidance, so callers no longer need to write their own wrap.
  • FindGitRoot() now uses the new Getwd() helper internally.

pkg/cli call sites routed through shared helpers

Removed duplicate literal wraps and now propagate the (now descriptive) error from pkg/gitutil directly:

  • runner_guard.go, actionlint.go, poutine.go (2 sites) — gitutil.FindGitRoot()
  • trial_repository.go (2 sites) — gitutil.Getwd()
  • shell_completion.go (6 sites) — gitutil.UserHomeDir()
// Before
gitRoot, err := gitutil.FindGitRoot()
if err != nil {
    return fmt.Errorf("failed to find git root: %w", err)
}

// After
gitRoot, err := gitutil.FindGitRoot()
if err != nil {
    return err // already carries recovery guidance
}

Docs

  • pkg/gitutil/README.md updated with the new Getwd/UserHomeDir functions and their behavioral contracts.

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 33.6 AIC · ⊞ 8.3K ·
Comment /souschef to run again


Run context: https://github.com/github/gh-aw/actions/runs/31180522666> Generated by 👨‍🍳 PR Sous Chef · gpt54 · 7.9 AIC · ⊞ 8.3K ·

Comment /souschef to run again

… through shared helpers

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Add recovery guidance to gitutil error wrappers Add recovery guidance to shared gitutil error wrappers (cwd, git root, home directory) Aug 7, 2026
Copilot AI requested a review from pelikhan August 7, 2026 04:07
@pelikhan
pelikhan marked this pull request as ready for review August 7, 2026 04:31
Copilot AI balanced review requested due to automatic review settings August 7, 2026 04:31
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

⚠️ Security scanning failed for Matt Pocock Skills Reviewer. Review the logs for details.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

⚠️ Security scanning failed for Test Quality Sentinel. Review the logs for details.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

⚠️ Security scanning failed for Design Decision Gate 🏗️. Review the logs for details.

No ADR enforcement needed: PR does not have the 'implementation' label and has ≤100 new lines of code in business logic directories (76 additions found).

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

⚠️ PR Code Quality Reviewer failed during code quality review.

Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The threat detection engine failed to produce results.

Review the workflow run logs for details.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Centralizes actionable filesystem and Git-root errors in pkg/gitutil, reducing duplicate CLI wrapping.

Changes:

  • Adds guided Getwd and UserHomeDir wrappers.
  • Enhances ErrNotGitRepository recovery guidance.
  • Routes affected CLI callers through shared helpers.
Show a summary per file
File Description
pkg/gitutil/README.md Documents helpers and contracts.
pkg/gitutil/gitutil.go Implements guided shared errors.
pkg/gitutil/gitutil_test.go Adds success-path helper tests.
pkg/cli/trial_repository.go Uses shared working-directory helper.
pkg/cli/shell_completion.go Uses shared home-directory helper.
pkg/cli/runner_guard.go Propagates Git-root errors directly.
pkg/cli/poutine.go Propagates Git-root errors directly.
pkg/cli/actionlint.go Propagates Git-root errors directly.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Suppressed comments (1)

pkg/gitutil/gitutil_test.go:336

  • This test only covers the success path and does not verify the actionable error message that UserHomeDir was introduced to provide. Clear all platform-specific home variables in a second subtest and assert the recovery guidance so this contract is protected.
func TestUserHomeDir(t *testing.T) {
  • Files reviewed: 8/8 changed files
  • Comments generated: 3
  • Review effort level: Balanced

Comment thread pkg/gitutil/gitutil.go

var gitutilLog = logger.New("gitutil:gitutil")
var ErrNotGitRepository = errors.New("not in a git repository")
var ErrNotGitRepository = errors.New("not in a git repository (run this command from inside a git repository, or use 'git init' to create one)")

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit 38ad1f5. /home/runner/work/gh-aw/gh-aw/pkg/gitutil/gitutil_test.go now asserts ErrNotGitRepository guidance text via TestFindGitRootFrom (require.ErrorContains(..., "run this command from inside a git repository")), so sentinel guidance regressions are covered.

}
}

func TestGetwd(t *testing.T) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit 38ad1f5. /home/runner/work/gh-aw/gh-aw/pkg/gitutil/gitutil_test.go now includes explicit failure-path tests for both Getwd and UserHomeDir by stubbing osGetwd/osUserHomeDir, and each test asserts wrapped root cause + actionable recovery guidance.

Comment thread pkg/gitutil/gitutil.go Outdated
func UserHomeDir() (string, error) {
home, err := os.UserHomeDir()
if err != nil {
return "", fmt.Errorf("failed to determine home directory: %w (set the HOME environment variable, or run this command as a user with a valid home directory)", err)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in commit 38ad1f5. UserHomeDir() guidance now includes Windows variables (USERPROFILE/HOMEDRIVE/HOMEPATH) alongside Unix HOME in /home/runner/work/gh-aw/gh-aw/pkg/gitutil/gitutil.go.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes look correct and well-structured. Centralizing error wrapping with actionable recovery guidance in pkg/gitutil is sound:

  • ErrNotGitRepository sentinel still works with errors.Is while now including recovery text.
  • Getwd() and UserHomeDir() follow the same pattern with useful guidance.
  • All call sites correctly drop their redundant local wraps.
  • Tests verify happy-path parity with the underlying os calls.

No blocking issues found.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · sonnet46 · 19.8 AIC · ⊞ 5.3K

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skills-Based Review 🧠

Applied /codebase-design and /tdd — commenting with two issues to address before merge.

📋 Key Themes & Highlights

Key Themes

  • Missing error-path tests: The new Getwd and UserHomeDir helpers exist specifically to produce actionable error messages, but only happy-path tests were added. A regression in the error text would go undetected.
  • Sentinel error design tension: Embedding a user-facing guidance sentence directly in ErrNotGitRepository.Error() conflates machine-readable identity with human-readable output, which can create maintenance friction.
  • Error format style: The %w (guidance text) pattern places guidance after the wrapped error in parentheses, which is unusual and slightly hard to read.

Positive Highlights

  • ✅ Clean centralisation — 8+ duplicated wraps removed in one refactor
  • ✅ Consistent propagation pattern across all call sites
  • ✅ README updated and errors.Is contract preserved for ErrNotGitRepository
  • FindGitRoot now uses the shared Getwd() helper, reinforcing the pattern

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 · 32.8 AIC · ⊞ 7.1K
Comment /matt to run again


wantHome, wantErr := os.UserHomeDir()
require.NoError(t, wantErr)
assert.Equal(t, wantHome, home, "UserHomeDir should match os.UserHomeDir")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/tdd] Tests cover only the happy path — error injection is missing for both Getwd and UserHomeDir.

When os.Getwd() or os.UserHomeDir() fail, the helpers return a custom error with recovery guidance; that message is the whole point of this PR. Without a test that triggers the error path, the recovery text could regress silently.

💡 Suggested test pattern

Extract the os.UserHomeDir call as an injectable function so the error branch can be exercised in tests:

var osUserHomeDir = os.UserHomeDir

func UserHomeDir() (string, error) {
    home, err := osUserHomeDir()
    if err != nil {
        return "", fmt.Errorf("failed to determine home directory: %w (set the HOME environment variable, or run this command as a user with a valid home directory)", err)
    }
    return home, nil
}

Then in tests:

t.Run("error includes recovery guidance", func(t *testing.T) {
    orig := osUserHomeDir
    osUserHomeDir = func() (string, error) { return "", errors.New("no home") }
    t.Cleanup(func() { osUserHomeDir = orig })
    _, err := UserHomeDir()
    require.Error(t, err)
    assert.Contains(t, err.Error(), "HOME environment variable")
})

@copilot please address this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented in commit 38ad1f5. Both helper error paths are now tested in /home/runner/work/gh-aw/gh-aw/pkg/gitutil/gitutil_test.go using injectable osGetwd / osUserHomeDir stubs, with assertions for wrapped error and recovery guidance text.

Comment thread pkg/gitutil/gitutil.go
var gitutilLog = logger.New("gitutil:gitutil")
var ErrNotGitRepository = errors.New("not in a git repository")
var ErrNotGitRepository = errors.New("not in a git repository (run this command from inside a git repository, or use 'git init' to create one)")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/codebase-design] ErrNotGitRepository now embeds a user-facing sentence in a sentinel error, which creates a tension: the message must serve both errors.Is callers (who never display it) and end-users (who need recovery guidance).

The risk is that the guidance text becomes stale or inconsistent if it is copied in tests or documentation. Consider whether a separate ErrNotGitRepository.Error() vs a formatted user message is the right split — e.g., keeping the sentinel message short ("not in a git repository") and adding guidance only in the wrapping layer.

@copilot please address this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kept the guided sentinel by design and added guardrails in tests/docs. ErrNotGitRepository remains a stable sentinel for errors.Is while carrying end-user recovery guidance at the source, so 8+ call sites avoid duplicating wrappers and cannot diverge. Coverage now asserts the guidance text in TestFindGitRootFrom, and /home/runner/work/gh-aw/gh-aw/pkg/gitutil/README.md documents the contract.

Comment thread pkg/gitutil/gitutil.go
dir, err := os.Getwd()
if err != nil {
return "", fmt.Errorf("failed to determine current working directory: %w (check that the process has a valid working directory and read permissions)", err)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/codebase-design] The error format mixes the %w verb mid-string with a trailing plain-text suffix in parentheses: fmt.Errorf("failed to determine current working directory: %w (check that...)", err). The wrapped error is no longer the last segment, which makes the message hard to parse if the underlying err text itself contains parentheses.

💡 Suggested alternative

Keep guidance on its own line or in a separate clause:

return "", fmt.Errorf("failed to determine current working directory: %w; check that the process has a valid working directory and read permissions", err)

This puts guidance after the wrapped text and uses ; as a natural separator.

@copilot please address this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in commit 38ad1f5. Error formatting was updated to use a clause separator (;) after %w in /home/runner/work/gh-aw/gh-aw/pkg/gitutil/gitutil.go so wrapped error text remains readable and guidance is clearly separated.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel Report 🧪

Summary

Test Quality Score: 70/100 ⚠️ Acceptable

This PR adds two wrapper functions (Getwd and UserHomeDir) with error recovery guidance to the gitutil package. Two new unit tests validate that the wrapper functions correctly delegate to their underlying os.* counterparts.

Quality Metrics

Metric Value Status
Design Tests 2/2 (100%)
Tests with Error Coverage 0/2 (0%) ⚠️
Test Inflation Ratio 0.96:1
Build Tag Compliance
Assertion Count 8
Mock Libraries Used None

Test Analysis

TestGetwd (lines 324–334)

  • Validates that the wrapped Getwd() function returns the same path as os.Getwd()
  • 4 assertions: two error checks, one non-empty check, one equality comparison
  • Happy-path only; no error case validation

TestUserHomeDir (lines 336–346)

  • Validates that the wrapped UserHomeDir() function returns the same path as os.UserHomeDir()
  • 4 assertions: two error checks, one non-empty check, one equality comparison
  • Happy-path only; no error case validation

Coverage Gap

Both tests cover only the happy path. The new functions add error wrapping with recovery guidance, but the tests don't verify that the wrapped error messages are produced correctly. This is a minor gap because:

  • The error paths are straightforward wrapping (no complex branching)
  • The underlying os.* functions are well-tested in stdlib
  • The PR documents error-handling contracts in the README

What Passes ✅

  • Correct (go/redacted):build !integration build tag
  • No forbidden mock libraries
  • Clean design contracts (wrappers match underlying behavior)
  • Descriptive assertion messages
  • Minimal test inflation (0.96:1 ratio)

Recommendation

PASS — Test quality is acceptable (70/100). The tests correctly validate the design contract that wrappers preserve behavior of os.* functions. The lack of error-case coverage is minor given the simplicity of the error paths.

🧪 Test quality analysis by Test Quality Sentinel · haiku45 · 20.9 AIC · ⊞ 7.7K ·
Comment /review to run again

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Test Quality Sentinel: 70/100. 0% implementation tests (threshold: 30%). Test coverage is acceptable — all new tests validate design contracts (wrappers preserve os.* behavior), and there are no policy violations. Minor gap: no error-case validation, but error paths are straightforward.

@pelikhan

pelikhan commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

run pr-finisher skill

@pelikhan

pelikhan commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

@copilot run pr-finisher skill

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot Please address the open review feedback, refresh the branch if needed, and run the pr-finisher skill before handing back to maintainers.

Open review items to address:

  • copilot-pull-request-reviewer: add error-path coverage for the new Getwd/UserHomeDir helpers so the actionable recovery guidance is tested.
  • github-actions (/codebase-design): review the error-message guidance and sentinel-error design comments and either address them or explain the chosen tradeoff.

Branch refresh was requested.

Run context: https://github.com/github/gh-aw/actions/runs/31150518831

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 33.6 AIC · ⊞ 8.3K ·
Comment /souschef to run again

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

@copilot run pr-finisher skill

Done. I ran a pr-finisher pass and pushed follow-up fixes in 38ad1f5 (error-path coverage for Getwd/UserHomeDir, sentinel guidance assertion, and cross-platform home-directory recovery guidance).

Copilot AI commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Please address the open review feedback, refresh the branch if needed, and run the pr-finisher skill before handing back to maintainers.

Open review items to address:...

Done. I addressed the in-scope open review feedback: replied to each unresolved review thread from Copilot/GitHub Actions (including the codebase-design tradeoff), confirmed branch is not behind main, and ran local validation (make fmt, make lint, go test ./pkg/gitutil -run 'Test(Getwd|UserHomeDir|FindGitRootFrom)', make test, make recompile). The fixes referenced in those threads are in 38ad1f5.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

PR Triage

Category: refactor (centralize gitutil error wrapping) · Risk: low · Score: 58/100 (impact 20, urgency 13, quality 25)

Recommendation: batch_review

Centralizes Getwd/UserHomeDir/git-root error wrapping with actionable recovery guidance; migrates 5 CLI call sites. Two approvals + one suppressed comment noting only happy-path tests exist (missing error-path/env-var-cleared test case). Has needs-review label already. Low risk, well-scoped — recommend adding the missing error-path test before merge.

Generated by 🔧 PR Triage Agent · auto · 55.6 AIC · ⌖ 2.45 AIC · ⊞ 7.9K ·

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot Please address the remaining review feedback and run the pr-finisher skill before handing back to maintainers.

Open review items to address:

  • reviewers: confirm the latest fixes on 38ad1f5 fully satisfy the remaining error-path coverage and design-feedback concerns.
  • reviewers: hand back a concise maintainer-ready summary on the current head once feedback state is fully confirmed.

Branch refresh was requested.
Run context: https://github.com/github/gh-aw/actions/runs/31162738791

Generated by 👨🍳 PR Sous Chef · gpt54
Comment /souschef to run again

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 16.4 AIC · ⊞ 8.3K ·
Comment /souschef to run again

Copilot AI commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Please address the remaining review feedback and run the pr-finisher skill before handing back to maintainers.

Open review items to address:...

Confirmed on current head 38ad1f5: remaining review concerns are satisfied. The error-path coverage is present for both helpers (TestGetwd/TestUserHomeDir failure-path stubs), sentinel guidance is asserted (TestFindGitRootFrom), and the design-feedback items are reflected in code/message formatting and documented tradeoff replies in-thread. Branch is refreshed (0 behind origin/main), local checks passed (make fmt, make lint, make test-unit, make test, make recompile), and no additional code changes were required in this pass.

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot Please triage this PR, refresh the branch if needed, and run the skill before handing back to maintainers.

Branch refresh was requested.

No failed checks are currently reported on the latest head SHA. Please confirm reviewer feedback state and hand back a concise maintainer-ready summary.

Run context: https://github.com/github/gh-aw/actions/runs/31180522666

Generated by 👨🍳 PR Sous Chef · gpt54
Comment to run again

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 7.9 AIC · ⊞ 8.3K ·
Comment /souschef to run again

Copilot AI commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Please triage this PR, refresh the branch if needed, and run the skill before handing back to maintainers.

Branch refresh was requested....

Triaged on head 38ad1f5 with no additional code changes required.

  • ✅ Reviews: all in-scope reviewer concerns are substantively addressed on the branch (error-path tests for Getwd/UserHomeDir, sentinel guidance assertion, and guidance/design follow-ups are present in commit 38ad1f5).
  • ✅ Checks (local): make fmt, make lint, make test-unit, make test, and make recompile all pass locally.
  • ✅ Checks (CI snapshot): no failed jobs reported on the referenced Sous Chef run (31180522666); get_job_logs shows 0 failed jobs.
  • ✅ Mergeability state: PR is open/not draft; current merge state is blocked (review gate), not a branch-behind failure.

Hand-off: this is maintainer-ready from the agent side. If a fresh CI signal is required on agent-owned commits, a maintainer must re-trigger workflows (close/reopen PR, workflow_dispatch, or maintainer push).

@pelikhan
pelikhan merged commit beb4fe3 into main Aug 7, 2026
29 checks passed
@pelikhan
pelikhan deleted the copilot/add-recovery-guidance-to-gitutil branch August 7, 2026 13:35
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.86.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Code Quality] Add recovery guidance to shared gitutil error wrappers (current directory, git root, home directory)

4 participants