Skip to content

fix: backlog items 8, 14, 19 -- UNC WARN, misleading syntax error, cache-lane trap - #408

Merged
mixmansoundude merged 5 commits into
mainfrom
claude/bootstrapper-execution-branches-ox2izi
Aug 1, 2026
Merged

fix: backlog items 8, 14, 19 -- UNC WARN, misleading syntax error, cache-lane trap#408
mixmansoundude merged 5 commits into
mainfrom
claude/bootstrapper-execution-branches-ox2izi

Conversation

@mixmansoundude

@mixmansoundude mixmansoundude commented Aug 1, 2026

Copy link
Copy Markdown
Owner

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-file findstr /C:"\\\\" >nul check fired [WARN] UNC paths not supported on every ordinary local CI checkout path, not just genuine UNC paths.
  • The companion check two lines below already does the real, correctly-targeted UNC-prefix detection. Removed the broken/redundant line rather than repairing it.
  • No test anywhere referenced the removed line (confirmed via repo-wide grep before removing).

Item 14 -- misleading "syntax error" on total Python-provider exhaustion:

  • :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; :preflight_compile checks it first and reports the real cause instead, which also skips the doomed PyInstaller build attempt entirely via the existing HP_PREFLIGHT_FAILED check.
  • 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.

Item 19 -- cache CI lane's self-perpetuating corruption trap:

  • Once a restored cache was flagged corrupted, the lane had no code path that ever produced a fresh valid cache again: both the only step that could do a fresh install and the save step were gated on the same HP_CACHE_CORRUPTED flag, so a poisoned blob (from a restore-keys prefix match) got restored, correctly detected as corrupted, and never replaced -- every single run, permanently. Matches the maintainer's own "cache lane never works" report.
  • Fix: distinguish an EXACT cache-key hit (unfixable in place; left as-is, needs a cache-deletion API follow-on) from a restore-keys PREFIX match (the common case). On a corrupted prefix match, delete the stale directory and don't set HP_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).
  • Not held back for dedicated multi-cycle verification -- cache runs 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 -- clean
  • python -m yamllint .github/workflows/batch-check.yml -- clean
  • actionlint -oneline .github/workflows/batch-check.yml -- clean
  • tools/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 commit

Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW

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
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@mixmansoundude
mixmansoundude enabled auto-merge (squash) August 1, 2026 02:19
@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@mixmansoundude, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 7 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: c159f9a2-58ab-4024-90f0-c393a877c0eb

📥 Commits

Reviewing files that changed from the base of the PR and between fd52a3f and a0a28b1.

📒 Files selected for processing (6)
  • .github/workflows/batch-check.yml
  • docs/agent-closed-backlog.md
  • docs/agent-lessons-learned.md
  • docs/demo-bootstrapper-output.md
  • run_setup.bat
  • tests/selfapps_ux_hardening.ps1
📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Removed a misleading UNC-path warning for ordinary local paths while preserving valid UNC detection.
    • Improved setup behavior when no Python interpreter can be found, reporting that execution and build steps were skipped.
    • Improved cache recovery by rebuilding installations restored from corrupted cache prefixes when possible.
    • Preserved safe handling for corruption in exact cache matches.
  • Documentation

    • Updated setup output and backlog documentation to reflect these fixes and closed related open questions.

Walkthrough

The 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.

Changes

Bootstrapper path and interpreter handling

Layer / File(s) Summary
Path and interpreter failure handling
run_setup.bat, docs/demo-bootstrapper-output.md, docs/agent-closed-backlog.md
The script uses a direct UNC-prefix check. When no interpreter is resolved, preflight reports the acquisition failure, marks preflight as failed, and skips py_compile. Documentation records both changes.

Cache corruption recovery

Layer / File(s) Summary
Cache corruption recovery
.github/workflows/batch-check.yml, docs/agent-closed-backlog.md, docs/open-questions.md
Exact-key corruption retains the skip behavior. Prefix-restored corrupt caches are deleted and rebuilt when possible. The cache question is removed from the open-items document.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the three backlog fixes: UNC warning behavior, misleading syntax errors, and cache corruption handling.
Description check ✅ Passed The description accurately explains the three fixes, their rationale, affected files, and validation results.
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 claude/bootstrapper-execution-branches-ox2izi

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: 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

📥 Commits

Reviewing files that changed from the base of the PR and between d5a2686 and a1ea693.

📒 Files selected for processing (4)
  • CLAUDE.md
  • docs/agent-closed-backlog.md
  • docs/demo-bootstrapper-output.md
  • run_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.bat to work when dropped next to the application without committed helper files; test-only helpers may live under tests/ but cannot be required by the real flow.

Files:

  • docs/agent-closed-backlog.md
  • docs/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.md
  • docs/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.md
  • docs/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.

Comment thread docs/agent-closed-backlog.md Outdated
Comment thread docs/agent-closed-backlog.md Outdated
Comment thread docs/demo-bootstrapper-output.md Outdated
…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

@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

🤖 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

📥 Commits

Reviewing files that changed from the base of the PR and between a1ea693 and 629f3a9.

📒 Files selected for processing (2)
  • docs/agent-closed-backlog.md
  • docs/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.bat to work when dropped next to the application without committed helper files; test-only helpers may live under tests/ 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 to docs/agent-closed-backlog.md while 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.md
  • docs/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.md
  • docs/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.md
  • docs/demo-bootstrapper-output.md

Comment thread docs/agent-closed-backlog.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
@mixmansoundude mixmansoundude changed the title fix: remove broken/redundant UNC-paths WARN check (backlog item 8) fix: backlog items 8, 14, 19 -- UNC WARN, misleading syntax error, cache-lane trap Aug 1, 2026

@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: 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

📥 Commits

Reviewing files that changed from the base of the PR and between 629f3a9 and fd52a3f.

📒 Files selected for processing (6)
  • .github/workflows/batch-check.yml
  • CLAUDE.md
  • docs/agent-closed-backlog.md
  • docs/demo-bootstrapper-output.md
  • docs/open-questions.md
  • run_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.bat to work when dropped next to the application without committed helper files; test-only helpers may live under tests/ but cannot be required by the real flow.

Files:

  • docs/open-questions.md
  • docs/agent-closed-backlog.md
  • docs/demo-bootstrapper-output.md
  • run_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.md
  • docs/agent-closed-backlog.md
  • docs/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 using continue-on-error rather 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 named iterate-logs-${run_id}-${run_attempt} containing iterate/_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 yamllint and actionlint before committing changes.

Files:

  • .github/workflows/batch-check.yml
run_setup.bat

📄 CodeRabbit inference engine (AGENTS.md)

run_setup.bat: Every branch added to run_setup.bat or 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 or HP_* flag when necessary.
All embedded helpers must remain base64 payloads under :define_helper_payloads; changing a payload requires updating the matching HP_* line from its canonical tools/ 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.json schemas 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: Keep run_setup.bat self-contained: do not add committed helper files; embed helpers as base64 payloads under :define_helper_payloads.
After every edit to run_setup.bat, run python tools/check_delimiters.py run_setup.bat.
Invoke conda with call "%CONDA_BAT%" ... so the parent batch process continues.
All conda installs must use --override-channels -c conda-forge to prevent defaults-channel contamination.
Avoid EnableDelayedExpansion; if required, scope it as tightly as possible.
Use tilde-prefixed temporary files such as ~setup.log and ~bootstrap.status.json.
The bootstrapper must write ~bootstrap.status.json on every run with state, exitCode, and pyFiles fields.
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.
Use python -m pipreqs.pipreqs, not the pipreqs console script, and retain the pinned pipreqs versi...

Files:

  • run_setup.bat
**/*.{bat,cmd}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{bat,cmd}: For batch assignments use set "VAR=value", never set 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 with fsutil dirty query %systemdrive% >nul 2>&1; on failure, skip the system-wide path and fall back to per-user installation.
Avoid EnableDelayedExpansion unless it is strictly scoped, and disable it afterward; use careful quoting and escaping rather than silencing errors.
Use tools/sync_payload.py as the only sanctioned method for re-encoding embedded HP_* 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 .bat and .ps1 files; 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.md
  • docs/demo-bootstrapper-output.md
🔇 Additional comments (5)
.github/workflows/batch-check.yml (1)

95-96: 📐 Maintainability & Code Quality

Confirm required workflow validation.

The supplied validation summary reports delimiter checks. It does not identify yamllint or actionlint results. Run both checks before merge.

As per coding guidelines, “Validate workflow YAML with yamllint and actionlint before 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

Comment thread .github/workflows/batch-check.yml
Comment thread run_setup.bat
Comment thread run_setup.bat
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
@mixmansoundude
mixmansoundude merged commit 8ea3b9d into main Aug 1, 2026
16 checks passed
@mixmansoundude
mixmansoundude deleted the claude/bootstrapper-execution-branches-ox2izi branch August 1, 2026 04:48
mixmansoundude added a commit that referenced this pull request Aug 1, 2026
…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>
mixmansoundude pushed a commit that referenced this pull request Aug 1, 2026
…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
mixmansoundude added a commit that referenced this pull request Aug 1, 2026
…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>
mixmansoundude pushed a commit that referenced this pull request Aug 2, 2026
… >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
mixmansoundude added a commit that referenced this pull request Aug 2, 2026
…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>
mixmansoundude pushed a commit that referenced this pull request Aug 18, 2026
…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
mixmansoundude pushed a commit that referenced this pull request Aug 18, 2026
… 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
mixmansoundude added a commit that referenced this pull request Aug 18, 2026
…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>
mixmansoundude added a commit that referenced this pull request Aug 22, 2026
… (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>
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.

2 participants