From ab5732138ad8dd5ba5cb347a06c1da66a7bdac82 Mon Sep 17 00:00:00 2001 From: Instinct <26149719+InstinctEx@users.noreply.github.com> Date: Mon, 7 Sep 2026 19:34:46 +0300 Subject: [PATCH] fix(web-research): fail loudly when $SCRATCHPAD is unset instead of writing into the repo (#440) * fix(web-research): fail loudly when $SCRATCHPAD is unset The two runnable snippets in 09-web-research.md both start with `cd "$SCRATCHPAD"`, but nothing in the repo ever sets that variable. With it unset the command expands to `cd ""`, which succeeds and leaves the shell in the current directory, so `page.html` and the extracted text land wherever the command was run from. In practice that is the repo checkout, which is exactly what the paragraph directly beneath the curl block forbids: "Write to the session scratchpad directory, never into the repo." Guarding with `${SCRATCHPAD:?...}` turns a silent write into the repo into an immediate, self-explaining failure. The message names where the value comes from so the reader can set it and re-run. * docs(changelog): record the $SCRATCHPAD guard under Unreleased --------- Co-authored-by: nox --- .../job-application-assistant/09-web-research.md | 6 +++--- CHANGELOG.md | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/.claude/skills/job-application-assistant/09-web-research.md b/.claude/skills/job-application-assistant/09-web-research.md index f61ab42..2c37e7d 100644 --- a/.claude/skills/job-application-assistant/09-web-research.md +++ b/.claude/skills/job-application-assistant/09-web-research.md @@ -1,5 +1,5 @@ --- -framework_version: 1.1.0 +framework_version: 1.1.1 --- # Web Research and Fetching @@ -48,7 +48,7 @@ Two details worth knowing, both covered by `tests/test_robots_check.py`: ### The retry: curl with browser headers ```bash -cd "$SCRATCHPAD" && curl -sSL --max-time 45 -o page.html -w "HTTP %{http_code} size=%{size_download}\n" \ +cd "${SCRATCHPAD:?set this to the session scratchpad directory from your system prompt}" && curl -sSL --max-time 45 -o page.html -w "HTTP %{http_code} size=%{size_download}\n" \ -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36' \ -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8' \ -H 'Accept-Language: en-GB,en;q=0.9' \ @@ -65,7 +65,7 @@ Write to the session scratchpad directory, never into the repo. `--compressed` i `WebFetch` converts to markdown for you; curl does not. Strip the tags: ```bash -cd "$SCRATCHPAD" && python3 -c " +cd "${SCRATCHPAD:?set this to the session scratchpad directory from your system prompt}" && python3 -c " import re, html h = open('page.html', encoding='utf-8', errors='replace').read() h = re.sub(r'(?is)<(script|style|noscript|svg)[^>]*>.*?', ' ', h) diff --git a/CHANGELOG.md b/CHANGELOG.md index f6cee2b..c27811a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,21 @@ per-file diff commands. ## [Unreleased] +### Fixed + +- **`09-web-research.md`'s curl snippets no longer write into the repo when `$SCRATCHPAD` + is unset** - both runnable blocks in the 403-escalation path start with `cd "$SCRATCHPAD"`, + and nothing in the repository ever sets that variable (`git grep 'SCRATCHPAD='` returns + nothing). Unset, it expands to `cd ""`, which succeeds and leaves the shell where it + started, so the `&&` chain proceeds and `curl -o page.html` writes to the working + directory - in practice the checkout, which is exactly what the paragraph directly beneath + the curl block forbids ("Write to the session scratchpad directory, never into the repo"). + The file's instruction and its own snippet disagreed, and the snippet won silently. + Both expansions are now guarded with `${SCRATCHPAD:?...}`, turning a silent repo write into + an immediate failure whose message names where the value comes from. Behaviour is unchanged + wherever the variable is set. The same undefined reference in `.claude/commands/rank.md` + was removed by #425 as a side effect of rewriting Step 2/4; this is the remaining instance. + ## [1.7.1] - 2026-09-06 ### Added