fix: backlog items 8, 14, 19 -- UNC WARN, misleading syntax error, cache-lane trap - #408
Conversation
findstr /C:"\\\\" collapsed to a single-backslash literal search (the documented C-runtime backslash-before-quote parsing rule), so it fired unconditionally on every ordinary local CI checkout path, not just UNC paths. The companion check two lines below already does the real, correctly-targeted UNC-prefix detection, so the broken line was simply removed rather than repaired -- root cause of the double-backslash was never identified and removal makes that moot. No test referenced the removed line. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Warning Review limit reached
Next review available in: 7 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe setup script corrects UNC-path detection and reports unresolved interpreters without attempting compilation. The CI workflow distinguishes exact cache hits from prefix restores during corruption handling. Documentation records the corrected behavior and closes the related backlog items. ChangesBootstrapper path and interpreter handling
Cache corruption recovery
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 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 `@docs/agent-closed-backlog.md`:
- Around line 591-593: Update the backlog entry in the unlabeled prologue to
remove the exact run_setup.bat:57-58 reference, citing the removed findstr
UNC-path check or another stable label instead. Preserve the existing
description of the C-runtime backslash-before-quote rule.
- Around line 592-597: The findstr incident descriptions must avoid asserting
unresolved parser behavior. In docs/agent-closed-backlog.md lines 592-597 and
docs/demo-bootstrapper-output.md lines 648-651, remove the two-backslash
explanation and C-runtime parser attribution, and state only that the removed
check emitted [WARN] for an ordinary local path and was removed.
In `@docs/demo-bootstrapper-output.md`:
- Around line 655-657: Update the backlog cross-reference in the documented
UNC-detection note to point to Item 8 in docs/agent-closed-backlog.md instead of
CLAUDE.md's Closed Backlog, preserving the surrounding explanation.
🪄 Autofix (Beta)
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: ASSERTIVE
Plan: Pro Plus
Run ID: d1c22331-6136-479d-8138-08e9f3d7f731
📒 Files selected for processing (4)
CLAUDE.mddocs/agent-closed-backlog.mddocs/demo-bootstrapper-output.mdrun_setup.bat
💤 Files with no reviewable changes (2)
- CLAUDE.md
- run_setup.bat
📜 Review details
⏰ Context from checks skipped due to timeout. (9)
- GitHub Check: auto_merge
- GitHub Check: Batch syntax/run check (contract-uv)
- GitHub Check: Batch syntax/run check (uv-dl-fallback)
- GitHub Check: Batch syntax/run check (justme-test)
- GitHub Check: Batch syntax/run check (conda-full)
- GitHub Check: Batch syntax/run check (cache)
- GitHub Check: Batch syntax/run check (contract-uv-fail)
- GitHub Check: Batch syntax/run check (real)
- GitHub Check: Batch syntax/run check (uv)
🧰 Additional context used
📓 Path-based instructions (3)
**/*
📄 CodeRabbit inference engine (AGENTS.md)
The single-bootstrapper directive requires
run_setup.batto work when dropped next to the application without committed helper files; test-only helpers may live undertests/but cannot be required by the real flow.
Files:
docs/agent-closed-backlog.mddocs/demo-bootstrapper-output.md
**/*.{md,txt}
📄 CodeRabbit inference engine (AGENTS.md)
When documenting
run_setup.bat, cite labels or subroutine names rather than exact line numbers unless a line number provides immediate value for the introducing commit.
Files:
docs/agent-closed-backlog.mddocs/demo-bootstrapper-output.md
**/*.{md,py,bat,ps1,yml,yaml,json}
📄 CodeRabbit inference engine (CLAUDE.md)
Use ASCII-only characters in repository files; avoid emojis, curly quotes, and em dashes.
Files:
docs/agent-closed-backlog.mddocs/demo-bootstrapper-output.md
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: mixmansoundude/Python_vs_Windows
Timestamp: 2026-08-01T02:20:06.201Z
Learning: Freeze scope during an iteration loop; defer newly discovered requirements to the backlog.
Learnt from: CR
Repo: mixmansoundude/Python_vs_Windows
Timestamp: 2026-08-01T02:20:06.201Z
Learning: Fix CI and pipeline issues before test errors, test assertions, and product code; after success, verify no false positives.
…bbit) - Cite the unlabeled prologue in run_setup.bat instead of an exact line range that can drift (repo's own documented citation convention). - The exact internal parsing of findstr /C:"\\\\" (findstr's own additional backslash-doubling layered on cmd.exe's C-runtime backslash-before-quote argument parsing) was never independently verified -- only the observed behavior (fired on an ordinary local path) was confirmed. Softened both documents to state what was actually confirmed rather than asserting a specific, untested parsing mechanism as settled fact. - Fixed the demo doc's cross-reference to point at docs/agent-closed-backlog.md's Item 8 (its actual new home) instead of the stale CLAUDE.md Closed Backlog reference. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 `@docs/agent-closed-backlog.md`:
- Around line 591-595: Remove the unverified findstr backslash-doubling and
cmd.exe C-runtime parsing explanation from docs/agent-closed-backlog.md lines
591-595 and docs/demo-bootstrapper-output.md lines 648-651. In both locations,
retain only the observed warning, ordinary local-path behavior, redundant-check
removal rationale, and separate UNC-prefix guard.
🪄 Autofix (Beta)
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: ASSERTIVE
Plan: Pro Plus
Run ID: c81ff1d4-18d9-4885-9162-086a52aba9cb
📒 Files selected for processing (2)
docs/agent-closed-backlog.mddocs/demo-bootstrapper-output.md
📜 Review details
🧰 Additional context used
📓 Path-based instructions (2)
**/*
📄 CodeRabbit inference engine (AGENTS.md)
The single-bootstrapper directive requires
run_setup.batto work when dropped next to the application without committed helper files; test-only helpers may live undertests/but cannot be required by the real flow.
**/*: Run the full mandatory sanity sweep before every commit, including compilation, linting, delimiter checks, workflow validation, ASCII checks, PowerShell parsing, and pytest.
Update the relevant knowledge document in the same commit when a change teaches or invalidates a lesson; edit existing entries rather than only appending.
When an Active Backlog item is fully resolved, remove it from the active list and move it todocs/agent-closed-backlog.mdwhile preserving its original number.
Freeze scope for the current iteration loop; implement exactly one missing feature slice and add exactly one missing test per loop.
Files:
docs/agent-closed-backlog.mddocs/demo-bootstrapper-output.md
**/*.{md,txt}
📄 CodeRabbit inference engine (AGENTS.md)
When documenting
run_setup.bat, cite labels or subroutine names rather than exact line numbers unless a line number provides immediate value for the introducing commit.
Files:
docs/agent-closed-backlog.mddocs/demo-bootstrapper-output.md
🧠 Learnings (1)
📚 Learning: 2026-08-01T02:27:53.952Z
Learnt from: mixmansoundude
Repo: mixmansoundude/Python_vs_Windows PR: 408
File: docs/agent-closed-backlog.md:0-0
Timestamp: 2026-08-01T02:27:53.952Z
Learning: In the documentation files describing the removed UNC warning check in `run_setup.bat`, state only verified behavior: the check emitted `[WARN] UNC paths not supported` for an ordinary local path and was removed because the separate UNC-prefix guard already handles UNC detection. Do not assert the exact `findstr` or cmd.exe backslash-parsing mechanism, since it was not independently verified.
Applied to files:
docs/agent-closed-backlog.mddocs/demo-bootstrapper-output.md
… error (item 14) :after_env_mode_selection's HP_PY guard relied on :die's call-frame-only exit /b, so on total REQ-009 provider-tier exhaustion, execution fell through ~15 lines to :preflight_compile, which ran py_compile against an empty interpreter path and reported a fabricated "Your Python program has a syntax error" instead of the real "no Python interpreter found" cause. Confirmed via real CI capture (run 30328748330). Fix: the guard now also sets HP_NO_INTERPRETER=1 before calling :die (left the deeper "goto-based hard stop" refactor out of scope -- disproportionate risk for this fix, since it would require tracing every call-stack depth :after_env_mode_selection can be reached from, including REQ-009 cascade re-entry). :preflight_compile checks the flag first and, if set, reports the real cause instead of running py_compile, which also means :run_entry_smoke's existing HP_PREFLIGHT_FAILED check skips the doomed PyInstaller build attempt entirely, not just the misleading message. No test asserted on the old misleading text; the genuine syntax-error path and the one test reaching this code path (self.embed.fallback.decline) are both unaffected, verified before landing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW
Once a restored cache was flagged corrupted, the lane had no code path that ever produced a fresh valid cache again: the "Bootstrap environment" step (the only step that could do a fresh install) and the "Save Miniconda cache" step were both gated on the same HP_CACHE_CORRUPTED flag, so a poisoned blob (saved once, from a restore-keys prefix match) got restored, correctly detected as corrupted, and never replaced -- every single run, permanently. Consistent with the maintainer's own "cache lane never works" report. Fix: "Validate restored conda binary" now distinguishes an EXACT cache-key hit (unfixable in place -- GitHub Actions cache blobs are immutable once saved under a key; left as-is, a smaller cache-deletion-API follow-on not implemented here) from a restore-keys PREFIX match (the common case, since the cache key hashes run_setup.bat, which changes on nearly every PR). On a corrupted prefix match, delete the stale Miniconda3 directory and don't set HP_CACHE_CORRUPTED, letting the run fall through exactly like a genuine cache miss -- a real fresh install and a real fresh save can then happen, breaking the loop. Falls back to the original safe skip-this-run behavior if the directory can't be fully deleted (same AV/indexer file-lock hazard class already documented for run_setup.bat's own :try_embed_fallback swap). Not held back for dedicated multi-cycle verification: cache is one of the 8 matrix lanes that runs on every future PR regardless of subject, so ordinary subsequent work already re-exercises it (maintainer guidance). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 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/batch-check.yml:
- Around line 107-112: Update the comment in the cache handling block to
reference docs/agent-closed-backlog.md instead of CLAUDE.md, preserving the
existing incident description and behavior guidance.
In `@run_setup.bat`:
- Around line 1017-1019: Stop execution immediately after the fatal
interpreter-resolution path calls :die, preventing the script from continuing
into success handling with an invalid HP_PY. Add an unconditional non-zero
termination or transfer to a top-level fatal cleanup label after :die, ensuring
bootstrap cleanup remains correct and the final status cannot be rewritten as
exitCode:0.
- Around line 1017-1019: Update the interpreter validation around HP_PY and the
existing HP_NO_INTERPRETER path to verify that the selected executable both
exists and successfully runs a minimal canary command before continuing. Route
any missing, stale, or non-runnable HP_PY value through the existing explicit
no-interpreter failure path, preserving fail-fast behavior and avoiding silent
fallback.
- Around line 3410-3421: Add regression assertions to the exhaustion-case test
for the HP_NO_INTERPRETER branch, covering the “No Python interpreter is
available” message, absence of “Your Python program has a syntax error,” no
PyInstaller build attempt, and preservation of the error status. Locate the
relevant self.embed.fallback.decline assertions and extend that case without
changing the existing ordinary syntax-error test.
🪄 Autofix (Beta)
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: ASSERTIVE
Plan: Pro Plus
Run ID: 1f68ecd6-b233-4461-9faf-73a7d18d44e7
📒 Files selected for processing (6)
.github/workflows/batch-check.ymlCLAUDE.mddocs/agent-closed-backlog.mddocs/demo-bootstrapper-output.mddocs/open-questions.mdrun_setup.bat
💤 Files with no reviewable changes (1)
- CLAUDE.md
📜 Review details
🧰 Additional context used
📓 Path-based instructions (9)
**/*
📄 CodeRabbit inference engine (AGENTS.md)
The single-bootstrapper directive requires
run_setup.batto work when dropped next to the application without committed helper files; test-only helpers may live undertests/but cannot be required by the real flow.
Files:
docs/open-questions.mddocs/agent-closed-backlog.mddocs/demo-bootstrapper-output.mdrun_setup.bat
**/*.{md,txt}
📄 CodeRabbit inference engine (AGENTS.md)
When documenting
run_setup.bat, cite labels or subroutine names rather than exact line numbers unless a line number provides immediate value for the introducing commit.
Files:
docs/open-questions.mddocs/agent-closed-backlog.mddocs/demo-bootstrapper-output.md
**/.github/workflows/*.{yml,yaml}
📄 CodeRabbit inference engine (AGENTS.md)
**/.github/workflows/*.{yml,yaml}: Use GitHub Actions CI results, especially Job Summary, grouped log tails, and workflow PR failure comments, as the source of truth; local runs are advisory.
Isolate slow, flaky, or environment-dependent diagnostics in separate non-gating lanes usingcontinue-on-errorrather than weakening deterministic gating lanes.
Keep CI parser checks synchronized with exact bootstrapper messages and preserve the single parser-facing iterate signal* Iterate logs: {found|missing}.
The iterate job must upload one artifact namediterate-logs-${run_id}-${run_attempt}containingiterate/_temp/and the job summary; do not alter the intentional pre-flight gate failure for missing NDJSON inputs.
Files:
.github/workflows/batch-check.yml
.github/workflows/*.yml
📄 CodeRabbit inference engine (CLAUDE.md)
Validate workflow YAML with
yamllintandactionlintbefore committing changes.
Files:
.github/workflows/batch-check.yml
run_setup.bat
📄 CodeRabbit inference engine (AGENTS.md)
run_setup.bat: Every branch added torun_setup.bator related helpers must have a CI test, including feature flags, fallback and recovery paths, and fast versus full paths; add an NDJSON assertion and a dedicated lane orHP_*flag when necessary.
All embedded helpers must remain base64 payloads under:define_helper_payloads; changing a payload requires updating the matchingHP_*line from its canonicaltools/source.
Do not remove tilde prefixes from runtime artifact files such as~bootstrap.status.json,~setup.log,~environment.lock.txt, and~env.state.json.
Treat unknown~env.state.jsonschemas as stale and trigger a full rebuild rather than reporting an error.
Update[VERSION_METADATA]after CI verifies a newer Windows, PowerShell, or Python environment, including the verification date and current versions.
run_setup.bat: Keeprun_setup.batself-contained: do not add committed helper files; embed helpers as base64 payloads under:define_helper_payloads.
After every edit torun_setup.bat, runpython tools/check_delimiters.py run_setup.bat.
Invoke conda withcall "%CONDA_BAT%" ...so the parent batch process continues.
All conda installs must use--override-channels -c conda-forgeto prevent defaults-channel contamination.
AvoidEnableDelayedExpansion; if required, scope it as tightly as possible.
Use tilde-prefixed temporary files such as~setup.logand~bootstrap.status.json.
The bootstrapper must write~bootstrap.status.jsonon every run withstate,exitCode, andpyFilesfields.
Test all three bootstrap code paths—cache, real, and conda-full—after significant changes.
Never depend on console scripts during bootstrap; invoke tools through an explicit interpreter or direct Python module/API.
Anchor every bootstrap tool invocation to an explicit Python executable such as%HP_PY%or%CONDA_PREFIX%\python.exe.
Usepython -m pipreqs.pipreqs, not thepipreqsconsole script, and retain the pinned pipreqs versi...
Files:
run_setup.bat
**/*.{bat,cmd}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{bat,cmd}: For batch assignments useset "VAR=value", neverset VAR="value"; quote%VAR%at every filesystem call site, except NSIS/D=parameters, which must remain/D=%VAR%.
Before system-wide installation, silently check elevation withfsutil dirty query %systemdrive% >nul 2>&1; on failure, skip the system-wide path and fall back to per-user installation.
AvoidEnableDelayedExpansionunless it is strictly scoped, and disable it afterward; use careful quoting and escaping rather than silencing errors.
Usetools/sync_payload.pyas the only sanctioned method for re-encoding embeddedHP_*payload lines after editing canonical helper sources; run delimiter checks after payload changes.
Files:
run_setup.bat
**/*.{bat,cmd,ps1,py,yml,yaml,json}
📄 CodeRabbit inference engine (AGENTS.md)
Run delimiter and repository-specific syntax regression checks using
tools/check_delimiters.py, respecting comments, escapes, and here-strings as applicable.
Files:
run_setup.bat
**/*.{py,ps1,psm1,psd1,yml,yaml,json,bat,cmd}
📄 CodeRabbit inference engine (AGENTS.md)
Keep source text ASCII plain text and avoid non-ASCII punctuation.
Files:
run_setup.bat
**/*.{bat,ps1}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{bat,ps1}: Use ASCII-only characters in Windows batch and PowerShell files; avoid emojis, curly quotes, and em dashes.
Preserve CRLF line endings in.batand.ps1files; use LF for other files according to.gitattributes.
Files:
run_setup.bat
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: mixmansoundude/Python_vs_Windows
Timestamp: 2026-08-01T02:54:13.822Z
Learning: Keep knowledge documents current in the same commit when a change teaches or invalidates a lesson; edit existing entries rather than only appending.
Learnt from: CR
Repo: mixmansoundude/Python_vs_Windows
Timestamp: 2026-08-01T02:54:13.822Z
Learning: When an Active Backlog item is fully resolved, remove it from the active file and move it to `docs/agent-closed-backlog.md` while preserving its original number.
Learnt from: CR
Repo: mixmansoundude/Python_vs_Windows
Timestamp: 2026-08-01T02:54:13.822Z
Learning: Freeze scope during an iteration loop; implement exactly one missing feature slice and add exactly one missing test per loop.
Learnt from: CR
Repo: mixmansoundude/Python_vs_Windows
Timestamp: 2026-08-01T02:54:13.822Z
Learning: Fix issues in this order: CI pipeline/configuration, test errors, test assertions, then product code; verify no false positives after achieving a green build.
📚 Learning: 2026-08-01T02:27:53.952Z
Learnt from: mixmansoundude
Repo: mixmansoundude/Python_vs_Windows PR: 408
File: docs/agent-closed-backlog.md:0-0
Timestamp: 2026-08-01T02:27:53.952Z
Learning: In the documentation files describing the removed UNC warning check in `run_setup.bat`, state only verified behavior: the check emitted `[WARN] UNC paths not supported` for an ordinary local path and was removed because the separate UNC-prefix guard already handles UNC detection. Do not assert the exact `findstr` or cmd.exe backslash-parsing mechanism, since it was not independently verified.
Applied to files:
docs/agent-closed-backlog.mddocs/demo-bootstrapper-output.md
🔇 Additional comments (5)
.github/workflows/batch-check.yml (1)
95-96: 📐 Maintainability & Code QualityConfirm required workflow validation.
The supplied validation summary reports delimiter checks. It does not identify
yamllintoractionlintresults. Run both checks before merge.As per coding guidelines, “Validate workflow YAML with
yamllintandactionlintbefore committing changes.”Source: Coding guidelines
docs/open-questions.md (1)
12-12: LGTM!run_setup.bat (1)
57-57: LGTM!docs/demo-bootstrapper-output.md (1)
645-658: LGTM!Also applies to: 2304-2320, 2340-2365
docs/agent-closed-backlog.md (1)
586-618: LGTM!Also applies to: 619-669, 671-728
The item-14 no-interpreter message in :preflight_compile split a
parenthetical across two echo lines ("(uv, conda, a fresh download, a" /
"local virtual environment) failed ..."), both inside the enclosing
if-block. cmd.exe's block parser counts parens in echo text too, so the
stray closing paren prematurely ended the if-block and the next token
("failed") was parsed as a stray command, producing
"failed was unexpected at this time." on every lane whose self-tests
reach HP_NO_INTERPRETER=1 (uv, contract-uv, contract-uv-fail,
uv-dl-fallback, cache, justme-test all failed on commit fd52a3f).
Reworded the message to avoid literal parens entirely, and documented
the hazard class in docs/agent-lessons-learned.md and the fix history
in docs/agent-closed-backlog.md's Item 14 entry.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW
…409) Today's regression (unbalanced parens across two echo lines inside an if-block, PR #408 commit fd52a3f) passed check_delimiters.py clean because a stray (...) pair inside echo text is individually balanced from a whole-file LIFO paren-count perspective -- the hazard is specifically about a cross-line split landing inside an already-open enclosing block, not a raw count mismatch. check_delimiters.py now tracks, for .bat/.cmd files, whether a '(' opened on an echo line while already nested inside another open bracket, and flags it if the matching ')' closes on a different line. Scoped to "already nested" so a harmless top-level echo statement with no enclosing block (a real instance exists in run_setup.bat, :print_fastpath_ambiguous_note) doesn't false-positive. Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW Co-authored-by: Claude <noreply@anthropic.com>
…essons-learned.md Bundled onto this branch per this repo's own established practice of landing multiple independently-ready fixes together rather than idling on separate PRs while a long CI cycle (real/conda-full lanes run ~80-90 min) is already in flight -- see PR #408's own precedent for the same reasoning. Item 12: :embed_dl_retry's genuine mid-download-failure-then-retry-once path had no CI test hook. Added HP_TEST_FORCE_EMBED_DL_FAIL_ONCE (mirrors the existing HP_TEST_FORCE_CONDA_CREATE_NETWORK_FAIL one-shot-then-succeed pattern) plus a new self.embed.dl.retry scenario in tests/selfapps_ux_hardening.ps1 proving retry-then-succeed end-to-end. Item 13: self.warn.longpath silently reported an overall pass even when the bootstrap never actually ran (ranBootstrap:false) -- root-caused to PowerShell's Push-Location failing before cmd /c is ever reached, since default GitHub-hosted Windows runners don't have LongPathsEnabled. Confirmed persistent via a second real CI observation (this session's own PR #410 runs) matching the original finding's exact signature. Fixed by reporting skip=true instead of an overstated pass when the runner cannot even attempt the code path under test, mirroring this repo's established skip-pattern convention. Doc compression (user request, tracked internally all session): trimmed discovery-narrative and superseded-implementation history from docs/agent-lessons-learned.md (1404 -> 1105 lines) and docs/agent-interconnect.md (1827 -> 1355 lines) while preserving every hazard, rule, exact error string, flag name, and table -- these two files are auto-loaded into every future agent session's context via CLAUDE.md's @import mechanism, so their size is a per-session cost for every future agent working in this repo. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW
…compress agent docs (#410) * Bound :exe_smokerun_hints' diagnostic re-run with a timeout (item 15) The diagnostic re-run of a freshly-failed EXE (:exe_smokerun_hints) was the one user-code launch point in run_setup.bat with no timeout at all -- a plain, synchronous `"%ENVNAME%.exe" > "~exe_out.txt" 2>&1`. Any non-determinism in the app (a race, an env check that sometimes succeeds, anything that occasionally blocks on inherited stdin) could hang this second, untimed invocation even though the first invocation legitimately classified as a fast, non-hang failure. Added tools/exe_hint_rerun.ps1 (embedded as HP_EXE_HINT_RERUN), a dedicated bounded-launch helper with an UNCONDITIONAL kill deadline (default 10s) -- deliberately not activity-aware like the sibling ~exe_smokerun.ps1/~failfast_probe.ps1 helpers, since this re-run is diagnostic-only (never shown live) and partial output on a hang is fine and preferred over hanging the bootstrap a second time. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW * Address CodeRabbit review on PR #410: process-tree kill + explicit output path Two real findings from CodeRabbit's review of the item-15 fix: 1. Process.Kill() only terminates the immediately-tracked process, not descendants -- a spawned child inheriting the redirected stdout/stderr pipe (e.g. from a PyInstaller onefile bootloader) can keep it open after the parent is killed, hanging the previously-unbounded ReadToEndAsync().Result forever and defeating the point of the fix. Fixed with taskkill /F /T /PID (process-tree kill) plus an independent bounded final read (Task.Wait) as a second safety net. 2. :exe_smokerun_hints never explicitly set HP_HINT_RERUN_OUT before invoking the helper, relying on its default -- an inherited/leaked value for that env var could silently redirect output away from the file the hint-matching findstr checks actually read. Fixed by setting it explicitly at the call site. New test: ProcessTreeAndDrainTimeout, using a grandchild process that inherits the pipe and outlives its own parent, proving the drain-wait fallback bounds the hang even when taskkill's process-tree behavior can't be exercised in this sandbox (no Windows environment available). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW * Fix real-Windows CI flakiness in PR #410's new exe_hint_rerun tests Two Windows-only bugs surfaced across every CI lane, neither reproducible on Linux: the 8s upper bound for the HP_HINT_RERUN_KILL_MS-override assertion was too tight for a loaded runner (observed 9.235s for a 500ms kill window, mostly pwsh/taskkill.exe startup overhead) -- widened to 13s, which still fails hard if the override were silently ignored. And the grandchild-holds-pipe regression test's own tempfile.TemporaryDirectory() cleanup failed with PermissionError/WinError 5/32, since the deliberately orphaned sleeping grandchild's CWD is an open directory handle on Windows (not an issue on POSIX) -- switched to a manual mkdtemp + best-effort ignore_errors=True rmtree, since the test's own assertions already prove the behavior under test and a leftover temp dir is a harmless CI artifact. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW * Address CodeRabbit nit: add type annotation + docstring to _rmtree_best_effort Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW * Close backlog items 12 and 13; compress agent-interconnect.md/agent-lessons-learned.md Bundled onto this branch per this repo's own established practice of landing multiple independently-ready fixes together rather than idling on separate PRs while a long CI cycle (real/conda-full lanes run ~80-90 min) is already in flight -- see PR #408's own precedent for the same reasoning. Item 12: :embed_dl_retry's genuine mid-download-failure-then-retry-once path had no CI test hook. Added HP_TEST_FORCE_EMBED_DL_FAIL_ONCE (mirrors the existing HP_TEST_FORCE_CONDA_CREATE_NETWORK_FAIL one-shot-then-succeed pattern) plus a new self.embed.dl.retry scenario in tests/selfapps_ux_hardening.ps1 proving retry-then-succeed end-to-end. Item 13: self.warn.longpath silently reported an overall pass even when the bootstrap never actually ran (ranBootstrap:false) -- root-caused to PowerShell's Push-Location failing before cmd /c is ever reached, since default GitHub-hosted Windows runners don't have LongPathsEnabled. Confirmed persistent via a second real CI observation (this session's own PR #410 runs) matching the original finding's exact signature. Fixed by reporting skip=true instead of an overstated pass when the runner cannot even attempt the code path under test, mirroring this repo's established skip-pattern convention. Doc compression (user request, tracked internally all session): trimmed discovery-narrative and superseded-implementation history from docs/agent-lessons-learned.md (1404 -> 1105 lines) and docs/agent-interconnect.md (1827 -> 1355 lines) while preserving every hazard, rule, exact error string, flag name, and table -- these two files are auto-loaded into every future agent session's context via CLAUDE.md's @import mechanism, so their size is a per-session cost for every future agent working in this repo. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW * Close backlog item 10: PVW_PYTHON_EXE/PVW_WORKSPACE test coverage New tests/selfapps_pvw_overrides.ps1 (uv lane only, non-gating) covers the two previously-zero-coverage PVW_* super-user overrides in full per the backlog item's own suggested shape: valid-value paths for both variables, plus 2 representative invalid-value scenarios (a nonexistent PVW_PYTHON_EXE absorbed by the existing interpreter smoke-test WARN, and a PVW_WORKSPACE occupied by a file cascading to the established :uv_venv_fail -> conda-create fallback) rather than the full 5x2 combinatorial matrix, matching the item's own reasoning that the failure-absorption mechanism is shared/generic across most combinations. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW * Redesign exe_hint_rerun timing test to be CI-noise-immune; fix 3 doc regressions from compression The wall-clock timing assertion in tests/test_exe_hint_rerun.py's UnconditionalKill class kept flaking upward across real Windows CI runs (9.235s, 13.468s, 14.578s, 16.328s of overhead for the identical 500ms override, never converging) -- bumping the bound was chasing a moving target instead of fixing the actual problem: the test was inferring correctness from noisy wall-clock time it can't control. Fixed by having tools/exe_hint_rerun.ps1 write its resolved $killMs directly to a new HP_HINT_RERUN_KILLMS_OUT file, unconditionally, right after computing it (production callers never read it, so this costs nothing there). The test now asserts on that value directly -- proving the override was read and used, deterministically, with zero CI-load dependency. A loose 45s wall-clock ceiling remains only as a sanity net against the kill mechanism being completely broken. Also fixes 3 real documentation regressions CodeRabbit's review caught in the doc-compression pass on this same PR: a stale HP_PROBE_ARGS contract description in one section that contradicted the (correct) description in another after the Argv passthrough feature changed it; a provider- cascade call-site list that still described the pre-reorder order (embed after venv/system instead of right after conda) because the compression pass dropped the sentence marking it as historical; and an "always exits 0" claim about tools/autopep_merge.py that doesn't hold -- two of its open() calls aren't wrapped in try/except OSError, unlike a third one that is. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW * Address CodeRabbit nit: add return type annotation to _killms_path Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW --------- Co-authored-by: Claude <noreply@anthropic.com>
… >9-picker test - Fix Part VI's own local scenario index: 4 links still pointed at the pre-reorg anchors (#scenario-34.. through #scenario-37..) even though their visible text had already been renumbered to 28-31. The main table of contents was verified programmatically during the reorg; this local bulleted list inside Part VI's scope note was a second, separate index the check didn't cover. Verified no other stale anchors exist anywhere else in the file via a full anchor-vs-header scan. - Fix 2 markdownlint MD031 violations (missing blank lines around fences). - Trim a residual mechanism claim from the UNC-check writeup (the removed check's exact findstr/backslash-parsing behavior was never independently verified, per an existing CodeRabbit learning from PR #408). - Extend the sourcing-convention paragraph to explicitly cover Part VII's composite walkthroughs (spliced from independently-real fragments) as a third case, distinct from a verbatim capture or a source-only quote. - Fix run_setup.bat's new >9-candidates Tip wording: "to avoid the alphabetical fallback next time" instead of "to skip this question next time" -- no question was actually asked in that branch. - Add tests/selfapps_entry_picker.ps1's second scenario (self.entry.picker. overflow): stages 10 candidate files, asserts the numbered menu is skipped, the overflow log line and Tip guidance both fire, and the alphabetical default is kept. Closes the CI-coverage gap the demo doc itself flagged. Registered in docs/agent-ndjson.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW
…411) * Release-prep pass: reorg demo doc, fix stale content, small product fixes docs/demo-bootstrapper-output.md: - Complete the owner-requested reorg TODO: move the "no .py files" scenario to the front as the doc's simplest, most foundational case; push the AV-Safe Build Path and CLI-interactivity Parts to the end. All 38 scenarios renumbered, table of contents and cross-references rebuilt to match, done as a flow-only pass with no scenario content changed. - Add a house-style note to the intro: describe current behavior, not the doc's own revision history -- drop hedges like "not yet re-confirmed against a fresh capture" and internal backlog-item bookkeeping from scenario prose; real historical gotchas stay welcome. - Remove a stale "[WARN] UNC paths not supported" console line from three capture blocks (the broken check that produced it was already removed from run_setup.bat) and trim the now-inapplicable explanation. - Update the long-path guard writeup to reflect this session's fix to self.warn.longpath (now correctly reports skip:true instead of an inconclusive pass) and fill in a concrete example path length. - Update PVW_PYTHON_EXE/PVW_WORKSPACE and the embed-tier download-retry scenarios to reflect real CI coverage added this session (previously documented as untested/extrapolated). - Add a new Part with five full startup-to-shutdown walkthrough panels: the ordinary happy path, uv cascading to conda on a dependency-resolve failure, warnfix repair+rebuild, hidden-import auto-recovery, and HP_PVW_KNOWN_IDEMPOTENT with actual input/output file contents. run_setup.bat: - :pick_entry_interactive now prints the same "Tip: to skip this question next time" guidance in the >9-candidate-files branch, not just the normal picker menu -- it's the guidance a user who just hit that limit needs most. tools/exe_hint_rerun.ps1: - Update a stale header comment: the descendant-holds-the-pipe taskkill /T path is now confirmed exercised on real Windows CI (two lanes on PR #410), not just the drain-wait fallback. docs/agent-closed-backlog.md: - Add a note that Part/Scenario citations in historical entries reflect the demo doc's structure at the time each entry was written, since the reorg above renumbered everything. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW * Address CodeRabbit review: fix stale TOC anchors, MD031, wording, add >9-picker test - Fix Part VI's own local scenario index: 4 links still pointed at the pre-reorg anchors (#scenario-34.. through #scenario-37..) even though their visible text had already been renumbered to 28-31. The main table of contents was verified programmatically during the reorg; this local bulleted list inside Part VI's scope note was a second, separate index the check didn't cover. Verified no other stale anchors exist anywhere else in the file via a full anchor-vs-header scan. - Fix 2 markdownlint MD031 violations (missing blank lines around fences). - Trim a residual mechanism claim from the UNC-check writeup (the removed check's exact findstr/backslash-parsing behavior was never independently verified, per an existing CodeRabbit learning from PR #408). - Extend the sourcing-convention paragraph to explicitly cover Part VII's composite walkthroughs (spliced from independently-real fragments) as a third case, distinct from a verbatim capture or a source-only quote. - Fix run_setup.bat's new >9-candidates Tip wording: "to avoid the alphabetical fallback next time" instead of "to skip this question next time" -- no question was actually asked in that branch. - Add tests/selfapps_entry_picker.ps1's second scenario (self.entry.picker. overflow): stages 10 candidate files, asserts the numbered menu is skipped, the overflow log line and Tip guidance both fire, and the alphabetical default is kept. Closes the CI-coverage gap the demo doc itself flagged. Registered in docs/agent-ndjson.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW * Address second CodeRabbit review round: sourcing labels, stale coverage note - Sourcing convention: use explicit REAL CI CAPTURE / source-excerpt / [Extrapolated Branch] labels instead of prose that called a source-only excerpt a "job log" -- a source excerpt is not a CI capture and shouldn't be described as one. - Scenario 28's >9-candidates paragraph still said "a real coverage gap, not yet a dedicated test" after the previous commit had already added self.entry.picker.overflow -- fixed to point at the real test/NDJSON registration while keeping [Extrapolated Branch] for the exact console text (that test only dumps a full log to CI on failure). Declined (reason given inline, no code change): CodeRabbit's outside-diff suggestion to add an explicit `exit 0` to tools/exe_hint_rerun.ps1. Its caller (run_setup.bat's EXE-hint-rerun call site) never checks the PowerShell process's own exit code, and three commands run before the first `if errorlevel` check that matters afterward (each of which resets ERRORLEVEL), so the omission is provably inconsequential. Neither sibling helper (exe_smokerun.ps1, failfast_probe.ps1) has an explicit exit code either -- adding one here alone would be inconsistent with an established, already-shipped pattern rather than fixing a real gap. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW * Make cache-lane self-heal regression-testable and its outcome visible Owner asked whether Item 19's cache self-heal fix is holding, then asked for a way to make a regression in it actually surface -- not silently absorbed. Digging into the first real post-fix run's raw job log found direct proof the fix works (corrupted-prefix-match cache -> deleted -> fresh install -> fresh save, all in one run), but also confirmed two real gaps: nothing recorded whether a run's self-heal fired at all, and even a hard failure inside the `cache` lane could never surface as a real CI failure (job-level continue-on-error covers that whole lane). - Extract the inline health-check-and-heal PowerShell out of batch-check.yml into tools/ci_cache_selfheal.ps1, a small parameterized script with 4 distinct exit codes -- including a new one for "self-heal itself failed to clear the stale directory" (the regression case: this fix reverting to its own pre-fix trap). - Add tests/test_ci_cache_selfheal.ps1: a deterministic test exercising all 4 outcomes against a scratch temp directory (including a genuine locked-file reproduction of the heal-failure case), wired into the `real` lane -- a GATING lane -- so a regression here fails CI for real, unlike the ambient `cache` lane which structurally cannot. - Add self.cache.selfheal.fired: an always-emitted visibility row when the ambient cache lane's own self-heal branch fires, recording whether it actually succeeded -- queryable on the diagnostics site instead of requiring a raw-log dig to notice an organic occurrence happened. - Add a loud ::error:: tripwire for the self-heal-failed case, mirroring the existing diag.conda.available.gate pattern -- explicitly documented as not a substitute for the gating test above. - Document the investigation and the fix in docs/agent-closed-backlog.md's Item 19 entry (in place, not appended), including the exact log lines that proved the original fix fired and worked. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW * Address CodeRabbit review: 5th cache-selfheal scenario, doc provenance fixes - tests/test_ci_cache_selfheal.ps1: add the missing "no conda.bat present at all" scenario -- exit code 0 covered two distinct branches in ci_cache_selfheal.ps1 but only one (healthy) had a test. - docs/agent-ndjson.md: fix a mid-identifier line break inside a code span (HP_CACHE_SELFHEAL_ATTEMPTED). - docs/demo-bootstrapper-output.md: Scenario 40a claimed its console dump was "verbatim" while also saying one line was "updated in place" -- a real self-contradiction; reworded to state plainly which line was edited and which lines are real capture. Scenario 37 reworded to lead with the mixed-provenance framing instead of an unqualified "real CI" claim. Scenario 41's cross-reference incorrectly claimed Scenario 37 shows the same WARN line "in situ" -- it actually shows the "(fallback build system)" variant, not "(PyInstaller)"; fixed. Declined (reasons given inline on the PR, no code change): - CodeRabbit's actionlint failure claim at batch-check.yml:3512 (if: false) does not reproduce -- actionlint v1.7.1 runs clean locally against that exact line, which is also pre-existing, documented, intentional code (a toggle switch), not part of this PR's diff. - PSScriptAnalyzer's ShouldProcess nag on New-FakeCondaDir -- no other test helper in this repo implements ShouldProcess (not a repo-native check), and it's disproportionate for a private, unconditionally- invoked test-only helper. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW * Guard against silent fixture-creation failure in cache-selfheal test Address CodeRabbit's outside-diff finding: New-FakeCondaDir used -ErrorAction SilentlyContinue throughout, so a silently-failed Set-Content would leave the fixture directory with no conda.bat -- which ci_cache_selfheal.ps1 correctly treats as a genuine cache miss (exit 0), the same exit code Scenario 1 expects for a HEALTHY conda.bat. That made fixture-creation failure indistinguishable from success instead of failing the test loudly. Declined the broader $ErrorActionPreference = 'Stop' sweep proposed alongside it (reason given inline on the PR): making cleanup (Remove-Item -ErrorAction SilentlyContinue at setup and final teardown) fail-fast would be inconsistent with how every other selfapps test in this repo treats scratch-directory cleanup as best-effort, and could introduce new flakiness on real Windows CI against exactly the AV/indexer file-lock class this repo already designs around elsewhere (see docs/agent-lessons-learned.md). Targeted the actual described failure mode instead: verify the fixture exists after creation, throw if not. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW * Assert Scenario 5's cache dir genuinely starts empty Address CodeRabbit's follow-up finding: New-Item -Force on $dir5 doesn't clear pre-existing content, so a leftover conda.bat from a prior interrupted run (surviving both that run's own best-effort teardown and this run's top-level scratchRoot recreation) could make Scenario 5 silently exercise the wrong branch while still passing on rc==0. Adds an explicit pre-invocation assertion that neither condabin\conda.bat nor Scripts\conda.bat exist before calling the script, throwing if they do. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW --------- Co-authored-by: Claude <noreply@anthropic.com>
…ts() finding Two real bugs found and fixed after the initial push: 1. All 8 CI lanes broke: the new errorlevel-3/2 dispatch's own rem comment split a parenthetical remark's ( and ) across three separate rem lines, nested three levels deep inside real if (...) blocks. cmd.exe's block- closing parser counts parens in rem text exactly like it does in echo text (already documented, PR #408) -- check_delimiters.py doesn't catch this for rem lines since it skips them from paren-scanning entirely, unlike its echo-line handling. Reworded to drop the literal parens. Filed as CLAUDE.md Active Backlog Item 61 to extend the checker itself. 2. CodeRabbit found that Python 3.14+ makes Path.exists() swallow OSError (including PermissionError) and return False instead of raising, which would have made the previous fix's exists() check misclassify a genuine permission failure as "not found" (1) instead of "real error" (3) -- the exact ambiguity this fix exists to close. Replaced the exists() check with a FileNotFoundError-specific catch around read_text() itself. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017SQ1rvJxDbE71pTXJ4QvLV
… deep The previous fix (rem-comment cross-line parens) did not resolve the CI regression -- confirmed via a downloaded diagnostics artifact's real ~envsmoke_bootstrap.log, which showed the identical corruption signature from the original PR #408 incident: "falling was unexpected at this time." -- with "falling" being the next word after "(exit 3)" in the new log-file-only echo line. That paren pair opens and closes on the SAME line, which check_delimiters.py and the established rule both treat as safe -- but that assumption only holds for a genuinely top-level echo statement with no enclosing block. This line sits nested four levels deep inside real if (...) blocks and is a redirected ">> file echo ..." form, not a plain echo -- either factor could be the actual distinguishing condition; not isolated, since removing the parens entirely resolves it regardless of the exact mechanism. Fixed by rewording "(exit 3)" to ", exit 3" -- no literal parens at all. Both this bug and the rem-comment bug shipped in the same original commit and needed two separate rounds of live CI evidence to find; neither was caught by check_delimiters.py or the local sanity sweep. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017SQ1rvJxDbE71pTXJ4QvLV
…not-found case (#445) * Item 52: distinguish pyproj_deps.py's genuine errors from its exit-1 not-found case tools/pyproj_deps.py's top-level except-Exception catch-all exited 1, the same code as its own deliberate "no pyproject.toml / no dependencies" case -- so a real bug in the script (e.g. pyproject.toml existing as a directory, or a permission failure) was silently indistinguishable from the benign case, and run_setup.bat's errorlevel dispatch only ever logged a WARN for errorlevel >= 2. The catch-all now exits 3. A missing pyproject.toml is checked explicitly via Path.exists() before read_text() so it keeps exiting 1 (the existing, common, documented case) rather than falling into the same handler as a genuine error. run_setup.bat gained an errorlevel-3 branch (checked before errorlevel 2, since "if errorlevel N" is a >=N test) that logs a log-file-only line for future debugging, without changing console-visible behavior. New regression test creates pyproject.toml as a directory (cross-platform: IsADirectoryError on POSIX, PermissionError on Windows) and asserts exit 3. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017SQ1rvJxDbE71pTXJ4QvLV * Fix CI-breaking rem-comment paren corruption + CodeRabbit's Path.exists() finding Two real bugs found and fixed after the initial push: 1. All 8 CI lanes broke: the new errorlevel-3/2 dispatch's own rem comment split a parenthetical remark's ( and ) across three separate rem lines, nested three levels deep inside real if (...) blocks. cmd.exe's block- closing parser counts parens in rem text exactly like it does in echo text (already documented, PR #408) -- check_delimiters.py doesn't catch this for rem lines since it skips them from paren-scanning entirely, unlike its echo-line handling. Reworded to drop the literal parens. Filed as CLAUDE.md Active Backlog Item 61 to extend the checker itself. 2. CodeRabbit found that Python 3.14+ makes Path.exists() swallow OSError (including PermissionError) and return False instead of raising, which would have made the previous fix's exists() check misclassify a genuine permission failure as "not found" (1) instead of "real error" (3) -- the exact ambiguity this fix exists to close. Replaced the exists() check with a FileNotFoundError-specific catch around read_text() itself. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017SQ1rvJxDbE71pTXJ4QvLV * Fix second real paren-corruption bug: same-line echo parens, nested 4 deep The previous fix (rem-comment cross-line parens) did not resolve the CI regression -- confirmed via a downloaded diagnostics artifact's real ~envsmoke_bootstrap.log, which showed the identical corruption signature from the original PR #408 incident: "falling was unexpected at this time." -- with "falling" being the next word after "(exit 3)" in the new log-file-only echo line. That paren pair opens and closes on the SAME line, which check_delimiters.py and the established rule both treat as safe -- but that assumption only holds for a genuinely top-level echo statement with no enclosing block. This line sits nested four levels deep inside real if (...) blocks and is a redirected ">> file echo ..." form, not a plain echo -- either factor could be the actual distinguishing condition; not isolated, since removing the parens entirely resolves it regardless of the exact mechanism. Fixed by rewording "(exit 3)" to ", exit 3" -- no literal parens at all. Both this bug and the rem-comment bug shipped in the same original commit and needed two separate rounds of live CI evidence to find; neither was caught by check_delimiters.py or the local sanity sweep. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017SQ1rvJxDbE71pTXJ4QvLV * Correct disproven test claim + regression fixture for the same-line paren gap CodeRabbit review finding: tests/test_check_delimiters_import.py's own test_paren_pair_on_same_echo_line_is_not_flagged asserted a same-line balanced paren pair is "always safe regardless of block nesting" -- the exact assumption this PR's second CI regression just disproved (a same-line pair in a redirected echo, nested 4 levels deep, corrupted cmd.exe parsing). Corrected the comment to stop overclaiming, and added a new regression fixture reproducing the actual proven-unsafe shape, documented as a known checker false-negative (not a safe pattern). Widened CLAUDE.md's Item 61 scope to cover this same-line-but-nested case alongside the already-filed cross-line rem-comment gap. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017SQ1rvJxDbE71pTXJ4QvLV --------- Co-authored-by: Claude <noreply@anthropic.com>
… (Item 61) (#449) * check_delimiters.py: extend cross-line paren tracking to rem comments (Item 61) rem lines were previously fully opaque to the paren-tracking checker (skipped via `continue`), even though cmd.exe's own block-boundary parser counts '('/ ')' characters inside rem text exactly like it does inside echo text -- the same hazard class that broke 6 CI lanes once already (PR #408) and a rem-text sibling a second time (PR #445, Item 52). Routes rem lines through the same character scan and cross-line-close check echo lines already had (StackItem's bool is_echo_open generalized to Optional[str] prose_kind). Making this work correctly against the real run_setup.bat required two more general (not rem-specific) fixes, found only by running the extended checker against it: cmd.exe's own '^' escape character in front of a bracket was not recognized (so the file's own established '^(' / '^)' hazard-defusing convention was itself flagged), and a bare apostrophe was treated as a string-quote delimiter on .bat/.cmd lines with no such concept in real cmd.exe, corrupting cross-line tracking for any rem prose containing an ordinary contraction or possessive. Running the fixed checker against run_setup.bat surfaces 26 genuine, previously-invisible cross-line rem pairs already in the file (not audited here -- flagged as the concrete next follow-up in CLAUDE.md's Item 61 entry, per this repo's one-slice-at-a-time discipline for run_setup.bat). One existing line's own metacharacter listing ("(&, |, ^)") was reworded to resolve the sole false positive the new caret-escape heuristic itself produced, distinguishing a literal example caret from an escape prefix. check_delimiters.py is advisory-only (not wired into any CI gate), so this does not affect the GitHub Actions pipeline. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017SQ1rvJxDbE71pTXJ4QvLV * Address CodeRabbit review: tab-delimited rem, doc wording, stronger test - tools/check_delimiters.py: recognize "rem" followed by a tab (not just a space) as a real rem line in both .bat/.cmd scan passes, via a single shared REM_LINE_RE used at both call sites so they cannot drift apart. cmd.exe treats a tab exactly like a space after "rem"; the previous literal "REM " check silently left such a line's parens untracked by the cross-line-paren hazard check (Major finding, verified by CodeRabbit's own scripted repro before and after the fix). - tests/test_check_delimiters_import.py: added a tab-delimited regression test, and strengthened the apostrophe/standalone-quote regression test to nest inside a real block with a later cross-line rem pair that must still be flagged -- the original fixture had no parens after the quote characters, so a regressed implementation could pass it without proving normal scanning actually resumes. - CLAUDE.md: cite run_setup.bat's file-header block by its stable "LINE-ENDING SELF-CHECK" label instead of approximate line numbers, and correct the remaining-scope wording -- the hazard surfaces from cmd.exe parsing an enclosing block's raw text, not from the block's own condition evaluating true. - docs/agent-lessons-learned.md: mark the preceding paragraph's "does NOT catch it" as explicitly historical (before Item 61) so it no longer reads as contradicting the fix documented immediately after it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017SQ1rvJxDbE71pTXJ4QvLV * Fix stale test-count references after the tab-delimited-rem follow-up CodeRabbit caught this: CLAUDE.md and docs/agent-lessons-learned.md still said "4 new tests" / "13 tests total" after the previous commit's follow-up added a 5th test (tab-delimited rem detection), bringing the real total to 14 tests / 5 added. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017SQ1rvJxDbE71pTXJ4QvLV --------- Co-authored-by: Claude <noreply@anthropic.com>
Summary
Three independent backlog-item fixes landed on this branch while its CI cycles were already running -- bundled here rather than split into separate PRs, since each was ready before the prior commit's CI settled and pushing a new commit resets the required checks anyway.
Item 8 -- broken/redundant UNC-paths WARN check:
run_setup.bat's top-of-filefindstr /C:"\\\\" >nulcheck fired[WARN] UNC paths not supportedon every ordinary local CI checkout path, not just genuine UNC paths.Item 14 -- misleading "syntax error" on total Python-provider exhaustion:
:after_env_mode_selection'sHP_PYguard relied on:die's call-frame-onlyexit /b, so on total REQ-009 provider-tier exhaustion, execution fell through ~15 lines to:preflight_compile, which ranpy_compileagainst an empty interpreter path and reported a fabricated "Your Python program has a syntax error" instead of the real "no Python interpreter found" cause. Confirmed via real CI capture (run30328748330).HP_NO_INTERPRETER=1;:preflight_compilechecks it first and reports the real cause instead, which also skips the doomed PyInstaller build attempt entirely via the existingHP_PREFLIGHT_FAILEDcheck.self.embed.fallback.decline) are both unaffected, verified before landing.Item 19 --
cacheCI lane's self-perpetuating corruption trap:HP_CACHE_CORRUPTEDflag, so a poisoned blob (from arestore-keysprefix match) got restored, correctly detected as corrupted, and never replaced -- every single run, permanently. Matches the maintainer's own "cache lane never works" report.restore-keysPREFIX match (the common case). On a corrupted prefix match, delete the stale directory and don't setHP_CACHE_CORRUPTED, letting the run fall through like a genuine cache miss so a real fresh install + fresh save can happen. Falls back to the original safe behavior if deletion is blocked (same AV/indexer file-lock hazard class already documented for:try_embed_fallback's directory swap).cacheruns on every future PR regardless of subject, so ordinary subsequent work already re-exercises it (maintainer guidance).Test plan
python tools/check_delimiters.py run_setup.bat-- cleanpython -m yamllint .github/workflows/batch-check.yml-- cleanactionlint -oneline .github/workflows/batch-check.yml-- cleantools/run_sanity_sweep.sh(compileall, pyflakes, delimiter check, markdownlint, yamllint, actionlint, ASCII sweep, PowerShell AST parse sweep, full pytest) -- all green, 458 passed / 2 skipped, run fresh after each commitCo-Authored-By: Claude Sonnet 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW