# Shell Linting Design

## Goal

Add a single shell linting entry point for this repository so local checks and
CI use the same rule set.

## Scope

- Lint every repository-owned executable shell script.
- Keep the rule set deterministic and easy to extend.
- Reuse the same shell lint target locally and in GitHub Actions.

## Non-Goals

- Do not lint non-shell languages.
- Do not add formatting opinions beyond `shellcheck`.
- Do not lint generated files or third-party assets.

## Design

### File Discovery

Shell linting should discover repository-owned scripts by scanning for
executable files that contain a shell shebang.

Expected targets:

- `bootstrap`
- `scripts/install-deps`
- `scripts/update-lock.py` is excluded because it is Python, not shell
- future shell entry points under `scripts/` or the repository root

The discovery rule should exclude:

- files inside `.git`
- generated caches such as `__pycache__`
- non-executable files
- vendor or third-party directories if they are ever added

### Local Entry Point

Add a Make target:

- `make lint-shell`

This target should:

- discover the shell files
- run `shellcheck` on each one
- fail the build if any file fails lint

### CI Entry Point

GitHub Actions should call the same `make lint-shell` target so the local and
remote checks stay aligned.

### Error Handling

- If `shellcheck` is missing, fail with a clear message.
- If no shell files are discovered, the target should pass rather than fail.
- If a file fails lint, surface the file name and the `shellcheck` output.

## Validation

The implementation is complete when all of these pass:

- `make lint-shell`
- `make check`
- `python3 -m unittest discover -s tests -p 'test_*.py'`
- GitHub Actions workflow syntax validation

## Open Questions

- None. The discovery rule and target shape are fixed for v0.6.
