Skip to content

Sampler: pass template names newline-separated so spaced account template names survive - #37

Merged
michieldegezelle merged 5 commits into
mainfrom
sampler-newline-separated-template-names
Aug 5, 2026
Merged

Sampler: pass template names newline-separated so spaced account template names survive#37
michieldegezelle merged 5 commits into
mainfrom
sampler-newline-separated-template-names

Conversation

@michieldegezelle

@michieldegezelle michieldegezelle commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Account template identifiers are directory names and routinely contain spaces (account_templates/Investment- and depreciation details). The handles / account_templates inputs were documented and encoded as space-separated strings, then deliberately word-split into CLI args — so -at received Investment-, and, depreciation, details and the run died:

[error] Config file for account template "Investment-" not found

Hit live in lu_market: https://github.com/silverfin/lu_market/actions/runs/30612771053 (the PR under review changed exactly one file, inside that template).

Change

Both inputs are now one name per line, and the arg arrays are built with mapfile so each line becomes exactly one argv entry. This is already the convention in this repo's own run_tests.yml (TEMPLATE_BUCKETS, with a comment saying why) — the sampler was the only place that regressed to space-joining. firm_ids stays space-separated; it's numeric, so the SC2086 split there is still intentional.

Two supporting bits in the same area:

  • The attempt log line is %q-quoted, so a name containing spaces is visibly one argument.
  • The PR comment renders the names as individually code-quoted, comma-separated entries — a multi-line value inside one backtick pair renders as garbage.

⚠️ Input contract change for callers

A caller still passing a space-joined list now fails loudly (Config file for account template "..." not found) instead of silently sampling templates nobody asked for. I deliberately did not add a space-splitting fallback: for names containing spaces it cannot be made correct, and the loud failure is the honest outcome.

Input descriptions and the README input list are updated to say one per line. The only callers today are the lu_market / nl_market wrappers, which currently run inlined forks of this job (pinned to silverfin-cli's unmerged sampler-compact-diff-v2 branch); their matching fixes are silverfin/lu_market#785 and silverfin/nl_market#914. When those forks are reverted to uses: after silverfin-cli #265 merges, this fix means they don't regress — but the newline-emitting classify half lives in the market repos, so the two halves must land together.

Testing

The name-splitting logic was verified in bash against the real lu_market names (Investment- and depreciation details + Loan details → 3 argv entries, spaces intact); YAML validated. Not yet exercised in a live sampler run — see the market PRs for that.

🤖 Generated with Claude Code


Also in this PR

Three follow-ups that landed on the same branch:

Backtick-safe rendering of names in the PR comment (ddcb0af) — flagged by CodeRabbit (CWE-116). Template names are directory names from the PR's own tree, so a name containing a backtick closed its code span and injected markdown into the bot's comment. Fenced per CommonMark (one more backtick than the longest run inside the name, space-padded when it starts/ends with one) rather than backslash-escaping, which does nothing inside a code span. Names without backticks render byte-identically.

Reject names starting with - (5b88bf3) — flagged by CodeRabbit (CWE-88). Commander stops consuming a variadic option (-h/-at take <names...>) at the first --prefixed token, and a -- separator does not protect variadic values, so a directory named e.g. --from-zip would be reinterpreted as an option. The step now fails with a rename-the-directory message before any CLI call. Only a leading - is rejected; Cut-off and Investment- and depreciation details are unaffected.

Re-pin silverfin-cli to the branch tip (cb7d387) — pre-existing debt from #35, not introduced here. The pin 5accd6b is not an ancestor of sampler-compact-diff-v2: it's a pre-rebase copy of one of its commits, orphaned by the rebase. It still runs, so nothing failed loudly — it just froze this workflow five compact-diff fixes behind the branch it claims to track, including the one that stops --add-diffs-folder filling diffs/ with byte-identical pairs. Now pinned to 1ba5a0f, with a note that re-pinning is required whenever that branch moves (until silverfin-cli#265 merges and this returns to unpinned main).

Validation

Beyond the bash-level checks above, the identical newline fix has now run in production: lu_market run 30920292551 sampled Investment- and depreciation details successfully end-to-end (21 min, artifact uploaded, PR comment posted). This repo's own PRs don't exercise the sampler job, so that market run is the real signal.

Account template identifiers are directory names and routinely contain
spaces ("Investment- and depreciation details"). The sampler encoded the
handles/account_templates inputs as space-separated strings and then
word-split them into CLI args, so -at received "Investment-", "and",
"depreciation", "details" and the run died with:

  [error] Config file for account template "Investment-" not found

Switch both inputs to one-name-per-line and build the arg arrays with
mapfile, so each line becomes exactly one argv entry. This is already the
convention in run_tests.yml (TEMPLATE_BUCKETS) — the sampler was the only
place that regressed to space-joining. firm_ids stays space-separated;
it's numeric.

Also render the names in the PR comment as individually code-quoted,
comma-separated entries (a multi-line value inside one backtick pair
renders as garbage) and %q-quote the attempt log line so a spaced name is
visibly one argument.

Callers must now pass these inputs newline-separated — README and the
input descriptions updated accordingly.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.

Tip: disable this comment in your organization's Code Review settings.

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d47ac7a1-194e-42c7-b17d-b7dbf75fd45d

📥 Commits

Reviewing files that changed from the base of the PR and between cb7d387 and f7397bc.

📒 Files selected for processing (2)
  • .github/workflows/run_sampler.yml
  • README.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • README.md
  • .github/workflows/run_sampler.yml

Walkthrough

The sampler workflow now accepts newline-separated handles and account-template names. It preserves spaces in CLI arguments, rejects names beginning with -, shell-quotes attempt logs, and renders each value separately in PR comments. The README documents the new format.

Changes

Sampler input handling

Layer / File(s) Summary
Input contract and CLI argument construction
.github/workflows/run_sampler.yml, README.md
Inputs use one handle or account-template name per line. Nonblank lines become individual CLI arguments, including names with spaces. Names beginning with - are rejected. The silverfin-cli installation pin is updated.
Argument observability
.github/workflows/run_sampler.yml
Attempt logs use %q quoting. PR comments render each handle or account template as a separate backtick-safe inline code item.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: preserving spaces in account template names by passing them newline-separated.
Description check ✅ Passed The description explains the changes, input contract, testing, documentation updates, and related caller changes in sufficient detail.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sampler-newline-separated-template-names

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
.github/workflows/run_sampler.yml (1)

173-188: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add an automated argv-boundary regression test.

Test a two-line value containing Investment- and depreciation details. Assert that the constructed array contains two names after the -h or -at flag. This protects the primary fix from a future return to shell word splitting.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/run_sampler.yml around lines 173 - 188, Add an automated
regression test for the argument construction around HANDLE_ARGS and
ACCOUNT_ARGS using a two-line input that includes “Investment- and depreciation
details”; assert the resulting array preserves exactly two names after the
relevant -h or -at flag, confirming newline-based parsing does not regress to
shell word splitting.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/run_sampler.yml:
- Around line 375-380: Update the fmtNames formatter used by the HANDLES and
ACCOUNT_TEMPLATES PR comment entries to escape or safely encode backticks within
each trimmed name before wrapping it in Markdown code delimiters. Preserve the
existing newline splitting, whitespace filtering, and comma-separated rendering
behavior.

---

Nitpick comments:
In @.github/workflows/run_sampler.yml:
- Around line 173-188: Add an automated regression test for the argument
construction around HANDLE_ARGS and ACCOUNT_ARGS using a two-line input that
includes “Investment- and depreciation details”; assert the resulting array
preserves exactly two names after the relevant -h or -at flag, confirming
newline-based parsing does not regress to shell word splitting.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4a12af9a-2206-473b-bef9-23470718c1ab

📥 Commits

Reviewing files that changed from the base of the PR and between cecff38 and b8ddd44.

📒 Files selected for processing (2)
  • .github/workflows/run_sampler.yml
  • README.md

Comment thread .github/workflows/run_sampler.yml
michieldegezelle and others added 3 commits August 4, 2026 16:29
Template names are directory names taken from the PR's own tree, so they
are untrusted text. Wrapping them in a single backtick pair let a name
containing a backtick close its code span and inject markdown into the
sampler's PR comment (CWE-116; spoofed links/formatting, not code
execution) — flagged by CodeRabbit on bso_github_actions#37.

Fence each name per CommonMark instead: one more backtick than the longest
run inside the name, plus a space pad when it starts or ends with one.
Names without backticks render exactly as before.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Template names are directory names from the PR's own tree. A name starting
with "-" is read by the CLI's option parser as a FLAG rather than a value:
commander stops consuming a variadic option (-h/-at take <names...>) at the
first "-"-prefixed token, so a directory named e.g. "--from-zip" would be
reinterpreted as an option instead of a template to sample. A leading "--"
separator does not protect variadic values, so the fix is an explicit
guard: fail the step with an actionable message (rename the directory)
before any CLI call.

Flagged by CodeRabbit as CWE-88 on lu_market#785. Names with internal or
trailing hyphens ("Cut-off", "Investment- and depreciation details") are
unaffected — only a leading "-" is rejected.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The pin added in #35 (5accd6b) is not an ancestor of
silverfin-cli's sampler-compact-diff-v2 branch: it's a pre-rebase copy of
"Make --add-diffs-folder's zip write atomic" that the rebase orphaned. It
still runs, so nothing failed loudly — it just silently froze this
workflow five fixes behind the branch it claims to track:

  0bf8f15  Skip the diffs/ zip rewrite when no view.html is found
  b148ffa  Flag-array dedup, diffs-folder count, radio groups
  4598087  Flag-array flip direction + radio-checked attribute boundary
  8b05852  Flag-flip suffix only on the after side of a results diff
  1ba5a0f  Keep byte-identical render pairs out of the diffs/ folder

That last one matters most for adopters of this workflow: without it,
--add-diffs-folder copies before/after view.html for entries flagged on a
data-only change, so diffs/ fills with byte-identical pairs (lu_market run
30920292551 produced 3 such pairs and nothing else).

The market wrappers don't have this problem because they install
#sampler-compact-diff-v2, the branch, and so track fixes automatically.
Documented that re-pinning is required whenever that branch moves, until
silverfin-cli#265 merges and this goes back to unpinned main.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@michieldegezelle

Copy link
Copy Markdown
Collaborator Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
.github/workflows/run_sampler.yml (1)

134-144: 🔒 Security & Privacy | 🔵 Trivial | 🏗️ Heavy lift

Security Misconfiguration (CWE-829): Inclusion of Functionality from Untrusted Control Sphere

Reachability: External

Verify transitive dependency pinning for the privileged install.

The workflow installs the GitHub package before the sampler runs. The commit pin fixes the top-level silverfin-cli source, but the provided workflow does not show a lockfile or integrity check for its transitive dependencies. A changed dependency could execute during npm install while the job-level SF_API_CLIENT_ID and SF_API_SECRET variables are available.

Verify the dependency tree and use a committed lockfile or a reviewed artifact with integrity verification if the dependency tree is not pinned.

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- repository lockfiles ---'
find . -path './.git' -prune -o -type f \
  \( -name package-lock.json -o -name npm-shrinkwrap.json -o -name yarn.lock -o -name pnpm-lock.yaml \) \
  -print

tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT

git clone --filter=blob:none --no-checkout \
  https://github.com/silverfin/silverfin-cli.git "$tmp/cli"
git -C "$tmp/cli" fetch --depth 1 origin 1ba5a0f
git -C "$tmp/cli" checkout --detach 1ba5a0f

printf '%s\n' '--- silverfin-cli lockfiles ---'
find "$tmp/cli" -type f \
  \( -name package-lock.json -o -name npm-shrinkwrap.json \) \
  -print
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/run_sampler.yml around lines 134 - 144, Update the
privileged silverfin-cli installation in the workflow to pin and
integrity-verify its complete dependency tree, not only the Git commit. Use a
committed lockfile or reviewed artifact with integrity metadata, and install
with the corresponding lockfile-enforcing mechanism; verify the selected 1ba5a0f
dependency tree before relying on it.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/run_sampler.yml:
- Around line 200-203: Update the validation error in the NAME loop to use
neutral terminology for values from both HANDLE_NAMES and ACCOUNT_NAMES; replace
“Template name” and “template directory” with wording that applies equally to
reconciliation handles and account names.

In `@README.md`:
- Around line 263-265: Document in the README input contract and the
corresponding `.github/workflows/run_sampler.yml` configuration comments that
`handles` and `account_templates` entries must not begin with `-`. Add this
restriction alongside the existing newline-separated format guidance, without
changing workflow validation behavior.

---

Nitpick comments:
In @.github/workflows/run_sampler.yml:
- Around line 134-144: Update the privileged silverfin-cli installation in the
workflow to pin and integrity-verify its complete dependency tree, not only the
Git commit. Use a committed lockfile or reviewed artifact with integrity
metadata, and install with the corresponding lockfile-enforcing mechanism;
verify the selected 1ba5a0f dependency tree before relying on it.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: dc692bd5-7b80-48df-89dc-50ec2231a8d7

📥 Commits

Reviewing files that changed from the base of the PR and between cecff38 and cb7d387.

📒 Files selected for processing (2)
  • .github/workflows/run_sampler.yml
  • README.md

Comment thread .github/workflows/run_sampler.yml Outdated
Comment thread README.md
Two review points from CodeRabbit on #37:

1. The guard checks handles AND account templates, but the error called
   every value a "Template name" and told the user to rename "the template
   directory" — wrong words for a reconciliation handle. Rather than a
   neutral label, check each list separately so the message names the kind
   ("Reconciliation handle" / "Account template name") and the directory to
   rename (reconciliation_texts/ / account_templates/).

2. The restriction wasn't part of the documented input contract. Added it
   to both `handles`/`account_templates` input descriptions and the README
   input list, including why (variadic -h/-at stop at the first
   "-"-prefixed token; "--" doesn't protect variadic values) and that only
   a LEADING hyphen is affected — "Cut-off" and "Investment- and
   depreciation details" are fine.

Verified in bash: empty list, both lists populated, hostile handle, and
hostile account template each behave correctly (the empty-array call
passes only the two label args, so the loop is a no-op).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@michieldegezelle
michieldegezelle merged commit 2088b7f into main Aug 5, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant