# Pathrule Pattern: Bash and Shell Automation (1.0.0)
# ::pathrule:package:bash-shell-automation

### [RULE] Quote expansions and use arrays for argument lists  (path: /scripts)
<!-- scope: folder | priority: high | strict -->

The shell performs parameter expansion, word splitting, and glob expansion before a command runs. Unquoted data can therefore become extra flags, paths, or patterns even when the source looked like one string.

- Quote every scalar expansion unless splitting or globbing is the explicitly documented operation.
- Store command arguments in an array and expand the array as arguments; do not build a command string and execute it through eval.
- Read filenames with null-delimited tools or a loop that preserves backslashes and whitespace instead of parsing `ls` output.
- Use `--` before untrusted positional paths where the command supports it so a filename beginning with a dash cannot become an option.

See /tests/shell for the adjacent decision or procedure that completes this constraint.

---

### [RULE] Validate destructive targets as explicit absolute paths  (path: /scripts)
<!-- scope: folder | priority: high | strict -->

An empty variable, unexpected working directory, glob, or failed command substitution can broaden a destructive target from one build directory to a repository, home directory, or filesystem root.

- Require the target variable to be non-empty and resolve it through a trusted parent directory before invoking the destructive command.
- Reject root, home, workspace root, current directory, and any target outside the task-specific parent allowlist.
- Avoid unresolved globs and broad recursive operations; enumerate or construct the intended path and log it before mutation.
- Create temporary directories through the platform tool and remove only the exact path returned, with a trap that cannot expand to a broader fallback.

See /scripts for the adjacent decision or procedure that completes this constraint.

---

### [RULE] Handle failures at process and pipeline boundaries  (path: /scripts)
<!-- scope: folder | priority: high | strict -->

Strict-mode options improve detection but do not replace reasoning about conditionals, substitutions, subshells, pipelines, and commands whose nonzero status is ordinary control flow.

- Enable the script's chosen strict options near the entry point and document any shell compatibility they require.
- Check commands whose failure has domain meaning and emit a specific diagnostic rather than relying on an implicit immediate exit.
- Preserve failure from every meaningful pipeline stage or avoid a pipeline where a temporary file makes error ownership clearer.
- Write traps that capture the intended exit status, stop child work, remove exact temporary resources, and return the original failure rather than masking it with cleanup.

See /.github/workflows for the adjacent decision or procedure that completes this constraint.

---

### [MEMORY] Shell is for orchestration, not an untyped application  (path: /scripts)

Shell excels at connecting commands whose arguments and outputs are already well defined. Its implicit strings and global process state become expensive when the script models nested data or many error states.

- Use shell for short orchestration over stable command interfaces, files, and environment setup.
- Move JSON, YAML, dates, binary data, complex conditionals, concurrency, or long-lived state into a language with a parser and tests.
- Prefer a tool's structured output mode and parse it with an appropriate parser rather than matching human-formatted terminal text.
- Keep the shell entry point as a small compatibility layer that validates arguments and invokes the structured implementation.

See /tests/shell for the rule or workflow that puts this decision into practice.

---

### [MEMORY] CI shell behavior is pinned, not assumed  (path: /.github/workflows)

A script can run under Bash locally and a different shell or version in CI. Startup files, aliases, working directory, locale, and utility variants also change behavior.

- Use an explicit shebang for executable scripts and configure the CI step shell instead of relying on runner defaults.
- Resolve paths from the script location or a declared workspace variable, not from whichever directory invoked the script.
- Set locale and other environment values only when the script depends on their behavior, and avoid mutating common system variables such as HOME for task state.
- Test on every supported operating system and shell family or declare the platform boundary clearly and fail early elsewhere.

See /scripts for the rule or workflow that puts this decision into practice.

---

### [SKILL] review-shell-script  (path: /)

---
name: review-shell-script
description: Review shell automation before it reaches CI, release, migration, or production operations.
---

# Review Shell Script

Run this procedure when the affected surface changes, before the result is promoted to production. Record evidence for every step instead of accepting a plausible-looking result.

- [ ] Run a shell parser and linter, then inspect every expansion, command substitution, array, loop, pipeline, conditional, and trap in context.
- [ ] Exercise empty, whitespace, wildcard, leading-dash, newline, Unicode, missing-file, permission, timeout, and interrupted-process inputs.
- [ ] Resolve every destructive target and prove guards reject broad roots, unresolved variables, unexpected working directories, and symlink escapes.
- [ ] Force each external command to fail and confirm the script reports the right cause, cleans exact resources, stops children, and preserves nonzero status.
- [ ] Inspect tracing and diagnostics for tokens, credentials, personal paths, payloads, and environment values that must not appear in CI logs.

## Exit criteria

The change is complete only when the expected behavior, failure behavior, and rollback path have all been exercised with representative data. Preserve the evidence with the change so the next operator can repeat the same checks.
