fix: AllUsers timeout vs. failure distinction; audit-tool redirect/%* gaps - #406
Conversation
…* gaps CodeRabbit review round on PR #405, 5 findings: - run_setup.bat: :run_installer_timeout hardcodes its RC to 1 on a genuine 60-minute timeout (a sentinel, not the installer's real exit code) -- the AllUsers WARN was presenting that sentinel as exitCode=1 alongside reason=installer_failed. Stopped clearing the subroutine's own HP_INSTALLER_TIMEDOUT flag before return (each call re-sets it fresh at entry, so leaving it live is safe) and branch the WARN on it: reason=timeout with no fabricated exitCode on a real timeout, unchanged wording otherwise. - tests/selfapps_justme.ps1: the failedWordingAbsent negative assertion had silently degraded into one that could never fail -- it matched the exact pre-exitCode-annotation sentence, which no longer appears anywhere verbatim now that the WARN always carries a suffix. Matches the stable message prefix instead. - tools/audit_console_messages.py: normalize() now handles %* (all positional args); extract_records' redirect-skip is now escape-aware (skips a genuine trailing `>`/`>>` file redirect, but not a caret-escaped redirect belonging to a nested command, and not a literal '>=' inside real message text like "running (>=30 days since last update)") -- the old `>>`-only check was letting several genuine single-`>` file-redirected lines (JSON status writes, simulated-failure marker files) through as if they were console output. 4 new regression tests. Declined one CodeRabbit finding on this round (dedicated CI coverage for the AllUsers attempted-failure/timeout branches via a new test-only failure hook) as new-feature scope disproportionate to a review-comment quick-fix pass, per CLAUDE.md's own iteration-loop rule -- reasoning posted on the PR. 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. |
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe change distinguishes Miniconda installer timeouts from exit-code failures, updates fallback diagnostics and regression assertions, documents the timeout path, improves batch console-message auditing, and records backlog and open-question updates. ChangesInstaller, console, and project records
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant MinicondaInstaller
participant run_setup
participant JustMeInstaller
MinicondaInstaller->>run_setup: Return timeout or exit code
run_setup->>run_setup: Preserve timeout state
run_setup->>JustMeInstaller: Log result and retry
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Comment |
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 `@run_setup.bat`:
- Around line 4517-4532: Add CI coverage for the AllUsers retry logging around
the tci_justme branch, using deterministic scenarios for both
HP_CONDA_ALLUSERS_TIMEDOUT=1 and a non-timeout installer failure. Assert timeout
logs include reason=timeout without exitCode, installer failures include
reason=installer_failed with the exit code, and emit NDJSON telemetry for both
scenarios.
- Around line 4478-4482: Update :run_installer_timeout to validate the helper’s
returned status before interpreting its result, and accept only a complete
result record matching <integer exitCode>|<0|1>. Treat missing, malformed, or
unsuccessful-helper results as indeterminate, preserve the timeout signaling,
and return without launching the fallback installer through :tci_justme.
In `@tests/test_audit_console_messages.py`:
- Around line 72-90: Add a test in tests/test_audit_console_messages.py covering
a redirect in a later command segment, such as call :log followed by an
ampersand and echo redirect. Assert through extract_records that the call :log
message remains in the returned records, ensuring suffix-scanning logic is
exercised.
In `@tools/audit_console_messages.py`:
- Around line 88-95: Update extract_records in tools/audit_console_messages.py
to detect redirects only when they are unquoted, not caret-escaped, and occur
within the same command segment as the call :log, preventing later commands from
discarding the record. Add one regression test in
tests/test_audit_console_messages.py covering both a valid same-segment redirect
and a later-command redirect, then run the test with pytest.
🪄 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: 01d2daf5-b7b5-4acf-9899-2ba6783b6165
📒 Files selected for processing (6)
docs/agent-closed-backlog.mddocs/demo-bootstrapper-output.mdrun_setup.battests/selfapps_justme.ps1tests/test_audit_console_messages.pytools/audit_console_messages.py
📜 Review details
⏰ Context from checks skipped due to timeout. (10)
- GitHub Check: auto_merge
- GitHub Check: analyze
- GitHub Check: Batch syntax/run check (contract-uv-fail)
- GitHub Check: Batch syntax/run check (conda-full)
- GitHub Check: Batch syntax/run check (real)
- GitHub Check: Batch syntax/run check (cache)
- GitHub Check: Batch syntax/run check (uv-dl-fallback)
- GitHub Check: Batch syntax/run check (uv)
- GitHub Check: Batch syntax/run check (contract-uv)
- GitHub Check: Batch syntax/run check (justme-test)
🧰 Additional context used
📓 Path-based instructions (12)
**/*
📄 CodeRabbit inference engine (CLAUDE.md)
**/*: Use ASCII-only characters in repository files; avoid emojis, curly quotes, and em-dashes because Windows batch/CMD parsing can break on non-ASCII characters.
Implement exactly one missing feature slice and add exactly one missing test per iteration loop; freeze scope and defer new requirements to the backlog.
When a change teaches or invalidates a lesson, update the relevant knowledge document in the same commit; move fully resolved Active Backlog items todocs/agent-closed-backlog.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:
tests/selfapps_justme.ps1docs/demo-bootstrapper-output.mdtests/test_audit_console_messages.pydocs/agent-closed-backlog.mdtools/audit_console_messages.pyrun_setup.bat
**/*.{bat,ps1}
📄 CodeRabbit inference engine (CLAUDE.md)
Use CRLF line endings for
.batand.ps1files; use LF for other files, as controlled by.gitattributes.
Files:
tests/selfapps_justme.ps1run_setup.bat
tests/selfapps_*.ps1
📄 CodeRabbit inference engine (CLAUDE.md)
Add PowerShell scenario tests using the
tests/selfapps_<scenario>.ps1naming convention and wire new scenarios intotests/harness.ps1and the CI workflow.
Files:
tests/selfapps_justme.ps1
**/*.{ps1,psm1,psd1}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ps1,psm1,psd1}: Prepend TLS 1.2 configuration to every PowerShell 5.1Invoke-WebRequestcall and retain-UseBasicParsing.
Validate touched PowerShell files with PowerShell AST parsing; do not skip validation on Linux, and run modified scripts directly with realistic environment variables when practical.
Files:
tests/selfapps_justme.ps1
**/*.{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:
tests/selfapps_justme.ps1tests/test_audit_console_messages.pytools/audit_console_messages.pyrun_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:
tests/selfapps_justme.ps1tests/test_audit_console_messages.pytools/audit_console_messages.pyrun_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/demo-bootstrapper-output.mddocs/agent-closed-backlog.md
**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Add Python unit tests under
tests/test_<topic>.pyand run them with pytest.
Files:
tests/test_audit_console_messages.pytools/audit_console_messages.py
**/*.{py,sh}
📄 CodeRabbit inference engine (AGENTS.md)
Use
python -m compileall -q .,python -m pyflakes ., and the canonical pipreqs commandpipreqs . --force --mode compat --savepath requirements.auto.txtfor relevant sanity checks.
Files:
tests/test_audit_console_messages.pytools/audit_console_messages.py
**/*.bat
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.bat: In batch files, invoke conda throughcall "%CONDA_BAT%" ...so the parent batch script continues running.
AvoidEnableDelayedExpansionin batch logic; if required, scope it tightly because parent shells may run with/V:ONand cause variable collisions.
Pass--override-channels -c conda-forgeon every conda installation command to prevent defaults-channel contamination.
Use tilde-prefixed temporary files such as~setup.logand~bootstrap.status.jsonso they are easy to ignore and survive crashes.
Do not rely on console scripts during bootstrap; invoke tools through explicit interpreter paths or direct Python module/API calls.
Anchor every bootstrap tool invocation to an explicit Python executable such as%HP_PY%or%CONDA_PREFIX%\python.exe; never rely on PATH or activation to select the interpreter.
Bootstrap must fail fast and explicitly when interpreter, environment, or dependency availability cannot be guaranteed; do not use silent fallbacks unless they are explicitly logged.
Keep non-obvious bootstrap constraints documented inline with comments such as# derived requirement: <why>, including why deterministic module invocation is used instead of a console script.
Files:
run_setup.bat
run_setup.bat
📄 CodeRabbit inference engine (CLAUDE.md)
run_setup.bat: Keeprun_setup.batself-contained: do not add committed helper files; embed helpers as base64 payloads under:define_helper_payloads, refreshing them withtools/sync_payload.pyrather than manually encoding or splicing them.
Runpython tools/check_delimiters.py run_setup.batafter every edit torun_setup.bat.
Ensure every bootstrap run writes~bootstrap.status.jsonwith stateok,no_python_files, orerror, plusexitCodeandpyFilesfields.
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.
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
🔇 Additional comments (6)
run_setup.bat (1)
4494-4494: LGTM!docs/agent-closed-backlog.md (1)
531-553: LGTM!docs/demo-bootstrapper-output.md (1)
1558-1565: LGTM!tests/selfapps_justme.ps1 (1)
63-76: 🎯 Functional CorrectnessNo change required.
tests/selfapps_envsmoke.ps1removestests/~envsmoke/~setup.logbefore runningrun_setup.bat, sofailedWordingAbsentdoes not read stale output.> Likely an incorrect or invalid review comment.tools/audit_console_messages.py (1)
11-14: LGTM!Also applies to: 45-61
tests/test_audit_console_messages.py (1)
30-31: LGTM!Also applies to: 60-69
…redirect CodeRabbit review round on PR #406: extract_records' redirect check scanned the ENTIRE tail after a call :log's closing quote for a real '>'/'>>', which incorrectly treated a redirect on a separately-chained LATER command (e.g. `call :log "[INFO] visible" & echo hidden > log.txt`) as if it belonged to the call :log itself, dropping a genuinely console-visible record. Truncate the tail at the first real (non-caret-escaped) command separator (& or |) before checking for a redirect, so only a redirect in call :log's OWN command segment causes a skip. No current run_setup.bat line hits this (verified via grep), so this is a latent-bug fix, not a live false negative. 2 new regression tests. Declined two other findings on this round, with reasoning posted on the PR: dedicated CI coverage for the AllUsers timeout/failure branches (same new-feature-scope reasoning already given on PR #405 for the identical ask), and validating :run_installer_timeout's result-file shape before accepting it (pre-existing behavior this PR doesn't touch, explicitly "Heavy lift", and the proposed remedy -- not retrying JustMe on an indeterminate result -- has its own real design tradeoff against the current conservative default). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW
Investigated a maintainer report that the cache CI lane "never works," always logging "Cache corrupted, skipping fast-path tests." Traced the mechanism: once a restored cache fails its health check, the one step capable of a fresh install is skipped (gated on HP_CACHE_CORRUPTED), and the save step is gated on the same flag -- so a poisoned cache blob can never be replaced by a fresh one, only re-detected as corrupted forever. Documented as CLAUDE.md Active Backlog item 19 (checked for a number collision against the closed backlog first, per this repo's own established discipline -- 19 was confirmed unused) with a reasoned-through but not-yet-implemented fix, since verifying it needs multiple real cache-lane CI cycles rather than fitting safely into a downtime aside. Added a matching entry to docs/open-questions.md asking whether the fix is worth the multi-cycle verification effort given the lane is already non-gating by design. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW
Owner decision 2026-08-01: the renumber-on-collision convention (and the
effort spent hunting for number collisions against the closed-backlog
archive) is more rigor than a plain-text backlog needs. Relaxed the
Active Backlog numbering intro to treat item numbers as informal, non-
unique labels; moved the decision itself into Known Findings; removed
the old item 18 (which existed only to track renumbering items 8, 10,
12, 13, 14, 15 -- no longer needed under the new rule, those items keep
their current numbers permanently). Item 19 (filed the same session, the
cache-lane finding) is unaffected by this and keeps its number.
Also added a TODO note to docs/demo-bootstrapper-output.md's own intro
(owner request) for a future flow-reorg pass: move Scenario 38 ("No .py
files at all") from the very end of the doc to the front (it's the most
foundational case), push Part I/Part II further down to make room, and
update cross-references -- flagged for its own dedicated pass, not
attempted here given the scope (renumbering ~8 parts' worth of anchors
in a 2500+ line doc) and this session's CI-babysitting context.
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: 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 `@CLAUDE.md`:
- Around line 488-489: Replace the future-dated 2026-08-01 references with the
correct non-future dates: update the owner-decision entry at CLAUDE.md lines
488-489, the cache-diagnosis entry at CLAUDE.md lines 698-699 and
docs/open-questions.md line 14, and the Known Findings decision at CLAUDE.md
lines 939-940. Preserve the surrounding wording and ensure each date reflects
when the decision or diagnosis actually occurred.
In `@docs/open-questions.md`:
- Around line 30-35: Remove the resolved cascade-consent design question and its
explanatory references from the open-questions document, leaving the decision
recorded only in the referenced knowledge documents and preserving the file’s
focus on unanswered questions.
In `@tools/audit_console_messages.py`:
- Around line 52-56: Update SEGMENT_END_RE in tools/audit_console_messages.py to
recognize command separators only when preceded by an even number of consecutive
carets, so ^^& and ^^| remain active separators while odd-parity escapes do not.
Add regression coverage for ^^& and ^^| in tests/test_audit_console_messages.py,
preserving existing separator and redirect behavior.
🪄 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: 1f895f82-96d5-4f93-be7b-48a50c10a4c6
📒 Files selected for processing (5)
CLAUDE.mddocs/demo-bootstrapper-output.mddocs/open-questions.mdtests/test_audit_console_messages.pytools/audit_console_messages.py
📜 Review details
⏰ Context from checks skipped due to timeout. (9)
- GitHub Check: analyze
- GitHub Check: Batch syntax/run check (real)
- GitHub Check: Batch syntax/run check (conda-full)
- GitHub Check: Batch syntax/run check (contract-uv-fail)
- GitHub Check: Batch syntax/run check (uv)
- GitHub Check: Batch syntax/run check (justme-test)
- GitHub Check: Batch syntax/run check (uv-dl-fallback)
- GitHub Check: Batch syntax/run check (contract-uv)
- GitHub Check: Batch syntax/run check (cache)
🧰 Additional context used
📓 Path-based instructions (8)
**/*
📄 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.mdtests/test_audit_console_messages.pytools/audit_console_messages.pyCLAUDE.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/open-questions.mdCLAUDE.mddocs/demo-bootstrapper-output.md
**/*.{bat,ps1,py,yml,json,md}
📄 CodeRabbit inference engine (CLAUDE.md)
Use ASCII-only content; avoid emojis, curly quotes, em-dashes, and other non-ASCII characters.
Files:
docs/open-questions.mdtests/test_audit_console_messages.pytools/audit_console_messages.pyCLAUDE.mddocs/demo-bootstrapper-output.md
**/*.{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:
tests/test_audit_console_messages.pytools/audit_console_messages.py
**/*.{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:
tests/test_audit_console_messages.pytools/audit_console_messages.py
**/*.{py,sh}
📄 CodeRabbit inference engine (AGENTS.md)
Use
python -m compileall -q .,python -m pyflakes ., and the canonical pipreqs commandpipreqs . --force --mode compat --savepath requirements.auto.txtfor relevant sanity checks.
Files:
tests/test_audit_console_messages.pytools/audit_console_messages.py
tests/test_*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Place Python unit tests in
tests/test_<topic>.pyand run them with pytest.
Files:
tests/test_audit_console_messages.py
CLAUDE.md
📄 CodeRabbit inference engine (AGENTS.md)
Run the advisory MD029-only Markdown lint check on
CLAUDE.md; new Active Backlog entries must be bullets with the identifier in prose rather than literal ordered-list markers.
Files:
CLAUDE.md
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: mixmansoundude/Python_vs_Windows
Timestamp: 2026-07-31T22:07:08.038Z
Learning: Freeze scope during an iteration loop; defer new requirements to the backlog.
Learnt from: CR
Repo: mixmansoundude/Python_vs_Windows
Timestamp: 2026-07-31T22:07:08.038Z
Learning: During iteration, fix CI and test infrastructure issues before test assertions, then product code; implement exactly one missing feature and add exactly one missing test per loop.
Learnt from: CR
Repo: mixmansoundude/Python_vs_Windows
Timestamp: 2026-07-31T22:07:08.038Z
Learning: Keep knowledge documents current in the same commit when a change teaches or invalidates a lesson; edit existing entries rather than only appending.
🪛 LanguageTool
docs/open-questions.md
[grammar] ~18-~18: Ensure spelling is correct
Context: ...ix is reasoned through in item 19's own writeup (treat a restore-keys prefix-match co...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
🔇 Additional comments (5)
docs/demo-bootstrapper-output.md (1)
17-36: LGTM!Also applies to: 1572-1580
CLAUDE.md (1)
484-493: 📐 Maintainability & Code QualityNo changes required.
CLAUDE.mdpasses the MD029-only check, and the Active Backlog entry uses a bullet with its identifier in prose.tools/audit_console_messages.py (2)
11-14: LGTM!
52-75: 📐 Maintainability & Code QualityRun the remaining checks in a complete test environment.
The delimiter check reports 19 errors outside the reviewed files. Python syntax passes, but
compileall,pyflakes,pipreqs, and the focused test are not confirmed.tests/test_audit_console_messages.py (1)
30-33: LGTM!Also applies to: 60-71, 72-90
… return annotation CodeRabbit review batch on PR #407: - CLAUDE.md's cascade-consent entry still said it closed "docs/open-questions.md item 1" -- stale after #406 removed that resolved question and item 1 now refers to the unrelated cache-lane question. Switched to descriptive wording. - Added the repo's own "# derived requirement: <why>" tag comments (Key Conventions table) at the caret-parity implementation and its regression test group -- the docstrings already explained the why, but the convention wants the grep-able tag too. - Added an Optional[re.Match] return annotation to _first_unescaped (Ruff ANN202). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW
…ries (#407) * fix: caret-parity bug in audit tool; correct future-dated backlog entries tools/audit_console_messages.py's redirect/separator detection only checked one caret back, so cmd.exe's real parity rule (^^& is a literal caret followed by an ACTIVE separator, not an escaped one) was inverted -- a doubled-caret separator was wrongly treated as escaped, letting a later chained command's redirect wrongly drop the call :log record before it. Replaced the single-lookbehind regexes with an explicit backward caret-count scan; added ^^&/^^| regression cases plus a single-caret contrast case. Also: fixed four 2026-08-01 dates that should read 2026-07-31 (today), and removed docs/open-questions.md's already-resolved cascade-consent paragraph, which contradicted the file's own "only currently-open items" scope. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW * docs/style: fix stale item-1 reference; add derived-requirement tags, return annotation CodeRabbit review batch on PR #407: - CLAUDE.md's cascade-consent entry still said it closed "docs/open-questions.md item 1" -- stale after #406 removed that resolved question and item 1 now refers to the unrelated cache-lane question. Switched to descriptive wording. - Added the repo's own "# derived requirement: <why>" tag comments (Key Conventions table) at the caret-parity implementation and its regression test group -- the docstrings already explained the why, but the convention wants the grep-able tag too. - Added an Optional[re.Match] return annotation to _first_unescaped (Ruff ANN202). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW * docs: add tools/README.md scoping which files are informal vs. load-bearing Requested to reduce review-nitpick friction on genuinely manual, hand-run scripts like audit_console_messages.py -- but most of tools/ is CI-wired or a canonical source for an embedded run_setup.bat payload, so a blanket "nothing here needs rigor" claim would be wrong and risk a future regression. Verified against .github/workflows/*.yml and each file's own header/docstring before writing: only audit_console_messages.py and audit_batch_exit_paths.py are genuinely informal by that standard; everything else defaults to full rigor. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A4iE1BRSkUETwz237XeuTW --------- Co-authored-by: Claude <noreply@anthropic.com>
Summary
PR #405 merged before this follow-up commit (already reviewed and confirmed-addressed by
CodeRabbit on that PR) could be pushed, per this session's "one fix per CI run, don't push while
CI is in progress" constraint. Rebased cleanly onto the new
main(#405's squash-merge tip) withno conflicts; this PR carries only that leftover, already-reviewed work.
run_setup.bat::run_installer_timeouthardcodes its return code to1on a genuine60-minute timeout (a sentinel, not the installer's real exit code) -- the AllUsers WARN was
presenting that sentinel as
exitCode=1alongsidereason=installer_failed, misclassifying atimeout as a normal installer failure. Stopped clearing the subroutine's own
HP_INSTALLER_TIMEDOUTflag before it returns (each call re-sets it fresh at entry, so leaving itlive across
exit /bis safe for every caller), captured it into a newHP_CONDA_ALLUSERS_TIMEDOUTright alongsideHP_CONDA_ALLUSERS_RC, and branch the WARN: on areal timeout it now reports
reason=timeoutwith no fabricatedexitCodefield; unchangedexitCode=..., reason=installer_failedwording otherwise. Demo doc anddocs/agent-closed-backlog.mdupdated to match.tests/selfapps_justme.ps1: thefailedWordingAbsentnegative assertion had silentlydegraded into one that could never fail -- it matched the exact pre-
exitCode-annotationsentence (from an earlier PR #404 fix), which no longer appears anywhere verbatim now that the
WARN always carries a suffix. Matches the stable
Miniconda AllUsers install failedmessageprefix instead, so it once again actually catches a skip-path regression.
tools/audit_console_messages.py:normalize()now handles%*(all positionalarguments), alongside the existing
%~dp0/%1-style handling.extract_records'sredirect-skip is now escape-aware: it correctly skips a genuine trailing
>/>>file redirect(several existing lines -- JSON status writes, simulated-failure marker files -- were previously
NOT being skipped, since the old check only looked for
>>), while still preserving acaret-escaped redirect belonging to a nested command (e.g. a
powershellsubprocess's own2^>nul) and a literal>=inside real message text (e.g. "running (>=30 days since lastupdate)") -- both of which a naive single-
>check would have wrongly treated as a redirect andsilently dropped from the audit. 7 new regression tests across both changes.
Declined one CodeRabbit finding on this round (dedicated CI coverage for the AllUsers
attempted-failure/timeout branches via a new test-only failure hook) as new-feature scope
disproportionate to a review-comment quick-fix pass, per CLAUDE.md's own iteration-loop rule --
reasoning posted on PR #405.
Test plan
python -m compileall -q ./pyflakes-- cleanpython tools/check_delimiters.py run_setup.bat-- cleanyamllint,actionlint-- all cleanpwshAST parse sweep over all.ps1files -- cleanpython -m pytest tests/test_*.py -q-- 453 passed, 2 skippedgit diff --statagainst currentorigin/mainreviewed for scope (6 files, matches theone carried-over commit exactly)
>/>>occurrence in currentecho/call :loglines inrun_setup.bat(11 cases) against the new redirect-detection regex before landingGenerated by Claude Code