expr: implement hashFiles()Verified
hashFiles(pattern...) now globs the patterns against the workspace root and
returns a SHA-256 over the matched files (per-file sha256 combined, sorted) —
deterministic and content-sensitive (not byte-identical to GitHub's value;
cache keys are cave-local). "" when nothing matches.
- Hand-rolled glob matcher (** = any depth, * / ? within a segment; leading ./
ignored) since cl-ppcre isn't a dep.
- The host-side workspace root is threaded into the ${{ }} context as the
keyword key :workspace-root (never collides with a GHA context) via
%gha-context; the runner passes workdir at both eval sites.
Verified: **/glob matches at any depth, distinct hashes per pattern set,
empty string on no match, determinism, and hash changes when a file changes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By:
Claude Opus 4.8 (1M context) <noreply@anthropic.com>