Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@ The e2e tests require GitHub credentials. There are three ways to provide them:

If only `E2E_GITHUB_USERNAME` and a password source are available, `make e2e-test` will automatically generate a session file before running tests. See `make help` for all available targets.

## Shell scripting

### `return` vs `exit` in executed scripts

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[medium] technical-accuracy

The claim that top-level return in an executed script 'causes a hard error' is imprecise. Without set -e, return at top level prints a diagnostic to stderr and exits with code 2, but the script continues execution — the guard silently fails. Only with set -e does the non-zero exit code cause an abort. Both outcomes are bugs but for different reasons, and the current wording could lead reviewers to skip flagging this pattern in scripts without set -e.

Suggested fix: Reword to describe both failure modes: 'At the top level of an executed script, return fails with exit code 2 and prints a diagnostic. Without set -e, the script continues past the failed return (the guard silently fails to skip execution). With set -e (commonly set -euo pipefail), the non-zero exit code aborts the script.'


`return` is valid only inside functions or in scripts that are `source`d. At the top level of an executed script (one with a shebang or run via `bash script.sh`), `return` causes a hard error — and under `set -euo pipefail`, this aborts the script.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[low] edge-case

The example pattern [[ -n "${LOADED:-}" ]] && return 0 only triggers the return error when the guard variable is set. When unset (common case), && short-circuits and return is never reached, making this a latent bug that passes basic testing but fails when the variable leaks from the environment.

Suggested fix: Consider adding: 'The error only triggers when the guard condition is true (variable is set); when false, && short-circuits and return is never reached, making this a latent bug that may not manifest in simple testing.'


This commonly occurs when inlining library code that was previously `source`d. Library-style load guards like `[[ -n "${LOADED:-}" ]] && return 0` must be removed or replaced when the code is inlined into an executed script.

**When reviewing shell scripts:** Flag any top-level `return` (outside a function body) in a script that is executed rather than sourced as a medium-severity correctness finding. Check for this especially when a PR inlines or moves code from a library/sourced file into an executable script.

## Forge abstraction

All git forge operations (GitHub API calls, PR comments, issue creation, workflow dispatch, etc.) **must** go through the `forge.Client` interface defined in `internal/forge/forge.go`. This is a fundamental architectural rule — the codebase supports multiple forges (GitHub, GitLab, Forgejo) and direct coupling to any single forge breaks the abstraction.
Expand Down
Loading