From f1157165b96f8c923e1444bbfad79b02862fdefa Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 31 Jul 2026 12:05:27 +0000 Subject: [PATCH 1/5] docs: show the full disk-space warning block in Scenario 24 The scan previously quoted only the trailing [WARN] REQ-025 log line; the same code path (run_setup.bat's disk-space guard) also echoes three raw *** lines directly to the console before it, which a real user sees in the same run. Add them so the scenario matches what actually prints. --- docs/demo-bootstrapper-output.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/demo-bootstrapper-output.md b/docs/demo-bootstrapper-output.md index f08efddd..dbf543ff 100644 --- a/docs/demo-bootstrapper-output.md +++ b/docs/demo-bootstrapper-output.md @@ -1766,9 +1766,15 @@ these same four guards' CLEAN (silent) pass. ``` **Disk space, REQ-025** (real capture -- warn-only, never a hard block, per REQ-001's rule that a -flag-detectable condition must never gate the Prime Directive): +flag-detectable condition must never gate the Prime Directive). The block emits three raw `echo` +lines before the `[WARN]` line the test asserts on -- all four are console-visible in the same +run; the earlier scan of this scenario quoted only the last one, which undersold what a real user +actually sees: ``` +*** WARNING: Only ~0 GB free disk space detected on this drive. +*** Downloading Python/Miniconda and building your app can need several GB. +*** If setup fails partway through, freeing up disk space is a likely fix. [WARN] REQ-025: low disk space detected (~0 GB free); continuing (warn-only). ``` From 8667fc4639427c026134de4eb61d043b80fd2e44 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 31 Jul 2026 12:24:35 +0000 Subject: [PATCH 2/5] tools: add audit_console_messages.py for demo-doc coverage checks Productionized the ad hoc script used for the bottom-up console-message audit (echo/call:log lines in run_setup.bat vs. docs/demo-bootstrapper- output.md coverage), following the same hand-run, not-wired-into-CI pattern as tools/audit_batch_exit_paths.py, so a future re-review of the demo doc doesn't have to re-derive the extraction/matching logic. --- tools/audit_console_messages.py | 123 ++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 tools/audit_console_messages.py diff --git a/tools/audit_console_messages.py b/tools/audit_console_messages.py new file mode 100644 index 00000000..b72e0aa7 --- /dev/null +++ b/tools/audit_console_messages.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python3 +"""On-demand audit of run_setup.bat's console-visible messages vs. the demo doc. + +Not wired into CI -- run by hand when re-reviewing docs/demo-bootstrapper-output.md +for completeness (see that file's own "living demo report" header) or after a batch +of new `echo`/`call :log` lines have landed in run_setup.bat. + +What it does: + 1. Extracts every `echo ` and `call :log ""` line from run_setup.bat + (skipping blank/`echo off`/`echo on` control lines and lines redirected to a + file with `>>`, which never reach the live console) and normalizes `%VAR%` + tokens to a placeholder so lines differing only by runtime substitution match. + 2. Splits each normalized message on its placeholder tokens and checks whether + every resulting literal segment (length >= 6, to skip noise) appears anywhere + in the demo doc's text -- a heuristic substring match, not a semantic one. + 3. Separately buckets messages that are test-only scaffolding (matched by + `HP_TEST`, `[TEST]`, `simulating`, `injected`/`injecting`, or `corrupt_conda`/ + `corrupt_uv` in the text) -- these never reach a real user (see CLAUDE.md's + "Env-var flags are scaffolding" rule, REQ-019) and are out of the demo doc's + stated scope by design, not a documentation gap. + +What it deliberately does NOT do (and why): it does not attempt semantic or +paraphrase matching, and it does not distinguish a genuinely undocumented feature +from a scenario that narrates the same event with different exact wording (the +demo doc's own stated scope is "representative captures," not an exhaustive +line-by-line transcript). Treat "not found" as "worth a 30-second manual look," +not as proof of a real gap -- when this tool was built, roughly half its +"not found" hits turned out to already be covered by nearby prose in an existing +scenario. Only act on a hit after confirming the surrounding scenario doesn't +already narrate it. +""" +import argparse +import re +import sys +from pathlib import Path + +TEST_ONLY_RE = re.compile( + r'HP_TEST|\[TEST\]|simulating|inject(ed|ing)|corrupt_conda|corrupt_uv', + re.IGNORECASE, +) + + +def normalize(text: str) -> str: + text = re.sub(r'%[^%]+%', '', text) + return re.sub(r'\s+', ' ', text).strip() + + +def extract_records(bat_path: Path): + """Return a list of (line_no, normalized_text) for console-visible lines.""" + records = [] + for i, raw in enumerate(bat_path.read_text(encoding='ascii', errors='replace').splitlines(), 1): + line = raw.strip() + m = re.match(r'^echo\s+(.*)$', line, re.IGNORECASE) + if m: + body = m.group(1) + if body.strip() in ('.', 'off', 'on'): + continue + if '>>' in raw: + continue + records.append((i, normalize(body))) + continue + m = re.search(r'call :log\s+["\']([^"\']*)["\']', line) + if m: + records.append((i, normalize(m.group(1)))) + return records + + +def is_covered(normalized: str, corpus: str) -> bool: + segments = [seg.strip() for seg in normalized.split('') if len(seg.strip()) >= 6] + if not segments: + stripped = normalized.replace('', '').strip() + return len(stripped) < 6 or stripped in corpus + return all(seg in corpus for seg in segments) + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + parser.add_argument('--file', default='run_setup.bat', help='Batch file to scan (default: run_setup.bat)') + parser.add_argument('--demo-doc', default='docs/demo-bootstrapper-output.md', + help='Demo doc to check coverage against (default: docs/demo-bootstrapper-output.md)') + parser.add_argument('--include-test-only', action='store_true', + help='Also report gaps in HP_TEST-gated / simulated lines (excluded by default, see module docstring)') + args = parser.parse_args() + + bat_path = Path(args.file) + doc_path = Path(args.demo_doc) + if not bat_path.exists(): + print(f"error: {bat_path} not found", file=sys.stderr) + return 2 + if not doc_path.exists(): + print(f"error: {doc_path} not found", file=sys.stderr) + return 2 + + records = extract_records(bat_path) + corpus = doc_path.read_text(encoding='utf-8', errors='replace') + + missing = [] + test_only_missing = [] + for lineno, normalized in records: + if is_covered(normalized, corpus): + continue + if TEST_ONLY_RE.search(normalized): + test_only_missing.append((lineno, normalized)) + else: + missing.append((lineno, normalized)) + + print(f"Total console-visible records scanned: {len(records)}") + print(f"Test-only scaffolding, not found (excluded by default, real users never see these): {len(test_only_missing)}") + print(f"Real-user-facing, not found (worth a manual look): {len(missing)}") + print() + for lineno, normalized in missing: + print(f"line {lineno}: {normalized}") + if args.include_test_only: + print() + print("--- test-only scaffolding, not found ---") + for lineno, normalized in test_only_missing: + print(f"line {lineno}: {normalized}") + + return 0 + + +if __name__ == '__main__': + sys.exit(main()) From ee51eb83b6f5b1e55ab8873765d9d137b8a3d21b Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 31 Jul 2026 12:24:35 +0000 Subject: [PATCH 3/5] fix: stale item-7 cross-refs and non-ASCII cursor glyphs (CodeRabbit) batch-check.yml's Miniconda-availability step comments still pointed at CLAUDE.md for Active Backlog item 7, which PR #403 moved out to docs/agent-closed-backlog.md -- update both references to match the pattern already used in docs/agent-ndjson.md. Also replace the two non-ASCII cursor-block characters in demo-bootstrapper-output.md's postexec-checkpoint quotes with a plain ASCII underscore. --- .github/workflows/batch-check.yml | 10 ++++++---- docs/demo-bootstrapper-output.md | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/batch-check.yml b/.github/workflows/batch-check.yml index ef1d1285..e5808ed8 100644 --- a/.github/workflows/batch-check.yml +++ b/.github/workflows/batch-check.yml @@ -331,8 +331,9 @@ jobs: # producing a circular self-skip: confirmed via the GitHub Actions API against the CI runs # for two real commits on PR #390 (efd7a5c, fd7a046) that ~27 real/conda-full-only self- # tests silently "skipped" every run while the job still reported overall SUCCESS. See - # CLAUDE.md's Active Backlog item 7 for the full incident writeup and PR #391 for the - # revert that restored those steps to unconditional (matrix.mode == 'conda-full') form. + # docs/agent-closed-backlog.md's Active Backlog item 7 for the full incident writeup and + # PR #391 for the revert that restored those steps to unconditional (matrix.mode == + # 'conda-full') form. # # This step is now positioned right after "Self-test: real env smoke (CI-only)" # (selfapps_envsmoke.ps1) instead -- traced 2026-07-27 as the genuine first selfapps step @@ -345,8 +346,9 @@ jobs: # own script would otherwise allow, so a nonzero exit there can only mean the conda install # itself failed -- making this the correct point to sample "is conda now really available." # - # Re-wired 2026-07-27 (owner sign-off, full risk/benefit assessment in chat -- see CLAUDE.md - # Active Backlog item 7's own closing entry for the summary) after the corrected POSITION + # Re-wired 2026-07-27 (owner sign-off, full risk/benefit assessment in chat -- see + # docs/agent-closed-backlog.md's Active Backlog item 7 entry for the summary) after the + # corrected POSITION # above was empirically confirmed working across two real conda-full runs (PR #395, #396: # `available` correctly read `true` both times). The 27 downstream conda-full-only self-test # steps below now gate on `steps.conda_avail.outputs.available == 'true'` -- BUT this alone diff --git a/docs/demo-bootstrapper-output.md b/docs/demo-bootstrapper-output.md index dbf543ff..98254b2a 100644 --- a/docs/demo-bootstrapper-output.md +++ b/docs/demo-bootstrapper-output.md @@ -967,7 +967,7 @@ sees: ``` *** Verification finished -- see the Run Status above. *** *** You can run your program again now via the interpreter as an extra diagnostic check. *** - Run again via the interpreter now? [Y/N] █ + Run again via the interpreter now? [Y/N] _ ``` (cursor sits after `[Y/N] `, waiting indefinitely -- `:run_postexec_checkpoint`, an UNBOUNDED @@ -980,7 +980,7 @@ continues to the second prompt: *** Your app is ready. *** *** Want to build an optimized version too? It takes a bit longer to build right now, *** *** but it starts up more reliably on Windows and runs faster once it is built. *** - Build the optimized version now? [Y/N] █ + Build the optimized version now? [Y/N] _ ``` (same shape -- `:offer_optimized_build`, also an unbounded `set /p`, also defaults to decline on From af18495deed17a3d42dd45fc060788fb85858c61 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 31 Jul 2026 12:24:35 +0000 Subject: [PATCH 4/5] docs: fix stale REQ-018 bullet re: activity-aware EXE verification CLAUDE.md Active Backlog item 9: README's REQ-018 bullet said the verification run is "force-stopped after a short interval even if running fine," which is the opposite of the activity-aware-kill behavior that actually shipped (only a completely silent process is force-stopped; any output at all keeps it running as long as needed). Update the bullet to describe the real condition, note the narrower --hidden-import repair-check re-run stays unconditionally time-boxed by design, and move the now-closed item 9 into docs/agent-closed-backlog.md per CLAUDE.md's own directive. No behavior changed -- documentation only. --- CLAUDE.md | 22 ---------------------- README.md | 2 +- docs/agent-closed-backlog.md | 23 +++++++++++++++++++++++ 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index f1854812..9dfd3b22 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -534,28 +534,6 @@ number) in `docs/agent-closed-backlog.md`, which is why the numbering below does `docs/demo-bootstrapper-output.md`'s new default-happy-path scenario as an observed, unexplained anomaly rather than either asserting it's harmless or that it's a bug. -- **9. README.md's `[REQ-018]` bullet describing the mandatory verification run as - "force-stopped after a short interval even if running fine" is stale relative to the - activity-aware-kill behavior actually shipped later -- found 2026-07-29 via a CodeRabbit review - comment on PR #400 that (correctly) flagged a possible mismatch between README's REQ-018 prose - and `docs/demo-bootstrapper-output.md`'s new Scenario 11.** Traced it down: the real, current - WARN text (quoted verbatim in Scenario 10 from a real CI capture) says the opposite of what - README currently claims -- "if it stays completely silent for about 30 seconds it will be - force-stopped, but any output (including a prompt waiting on your input) keeps it running as - long as needed" -- matching CLAUDE.md's own already-documented Closed Backlog entry, - "Activity-aware EXE-smoke kill (docs/plan-cli-interactive-verification.md P0, requirement 3) -- - resolves Open Question 1." That feature shipped after README's REQ-018 section was last written - and the corresponding bullet was apparently never updated to match. **Not fixed in this pass** - -- deliberately left for its own small, dedicated pass rather than edited as a side effect of an - unrelated docs-only PR (`docs/demo-bootstrapper-output.md`'s own scope): README.md is this - repo's authoritative PRD, and CLAUDE.md's own instruction is to reference it, not duplicate or - casually rewrite it. `docs/demo-bootstrapper-output.md`'s Scenario 11 already carries an inline - note explaining the discrepancy so a reader isn't left confused between the two docs in the - meantime. Suggested fix shape: update the REQ-018 bullet's "force-stopped after a short interval - even if running fine" clause to describe the activity-aware condition instead (only a - completely silent process is force-stopped; any output at all keeps the run alive - indefinitely). - - **10. Two of the five `PVW_*` super-user override variables (`PVW_PYTHON_EXE`, `PVW_WORKSPACE`) have ZERO test coverage of any kind, and ALL FIVE have zero coverage of their invalid-value behavior -- found 2026-07-29 while documenting them for `docs/demo-bootstrapper-output.md`'s diff --git a/README.md b/README.md index f234699a..89655a78 100644 --- a/README.md +++ b/README.md @@ -460,7 +460,7 @@ At completion: Running the user's program IS the goal -- a beginner who cannot launch it themselves is exactly who this tool serves -- but each run must be treated as potentially destructive: a program is not guaranteed to be idempotent, and one run can overwrite files, send network requests or email, mutate a database, or actuate connected hardware (e.g. a VISA/serial instrument). The bootstrapper therefore runs the user's code purposefully and at most once per invocation, never repeatedly and never via two launch methods in the same run. - **Fast path is the user's run (frictionless).** When a current, already-verified EXE exists (sources unchanged since it was built), double-clicking the batch runs it directly and untimed, with no prompt and no console interaction -- the double-click is the user's intent to run, and this is the session's single run. A fast non-zero exit is still treated as a stale/broken EXE and triggers a rebuild (REQ-007); a program that keeps running is the user's app, left to run. -- **Verifying a fresh build is time-boxed and announced.** When the bootstrapper builds or rebuilds the EXE, it runs it once to verify, force-stopped after a short interval even if running fine, and preceded by a clear warning that this is a throwaway check so the user does not start real work in it. This is the only run that is killed on a timer. +- **Verifying a fresh build is activity-aware and announced.** When the bootstrapper builds or rebuilds the EXE, it runs it once to verify, preceded by a clear warning that this is a throwaway check so the user does not start real work in it. This run is only force-stopped if it stays completely silent for about 30 seconds; any output at all -- including a prompt waiting on input -- keeps it running for as long as needed, so an interactive program gets a real chance to be exercised. (A separate, narrower re-verification inside the `--hidden-import` auto-recovery loop remains unconditionally time-boxed at ~30 seconds, since it exists only to confirm one specific repair worked.) This is the only primary verification run that can be force-stopped at all. - **After a build, the real run is offered, not forced.** Following a successful build and verification, the bootstrapper offers to launch the app untimed for real, so a beginner need not launch it manually. The offer is consent-gated and names the side-effect/idempotency risk; declining leaves the verified EXE plus the post-flight guidance. - **Consent before any extra run.** Beyond the single automatic run, any further execution -- re-running, or running via the other launch method -- requires explicit consent that names the risk that the program may not be safe to run twice. - **Non-interactive and CI** resolve every gate without hanging: no untimed run, and offers auto-decline. diff --git a/docs/agent-closed-backlog.md b/docs/agent-closed-backlog.md index 2692b2e6..300c2000 100644 --- a/docs/agent-closed-backlog.md +++ b/docs/agent-closed-backlog.md @@ -473,6 +473,29 @@ further.)* --- +### Item 9 (closed 2026-07-31; moved here same pass) + +- **README.md's `[REQ-018]` bullet describing the mandatory verification run as + "force-stopped after a short interval even if running fine" was stale relative to the + activity-aware-kill behavior actually shipped later -- found 2026-07-29 via a CodeRabbit review + comment on PR #400 that (correctly) flagged a possible mismatch between README's REQ-018 prose + and `docs/demo-bootstrapper-output.md`'s new Scenario 11.** Traced it down: the real, current + WARN text (quoted verbatim in Scenario 10 from a real CI capture) said the opposite of what + README claimed -- "if it stays completely silent for about 30 seconds it will be + force-stopped, but any output (including a prompt waiting on your input) keeps it running as + long as needed" -- matching this file's own "Activity-aware EXE-smoke kill + (docs/plan-cli-interactive-verification.md P0, requirement 3) -- resolves Open Question 1" + entry below. That feature shipped after README's REQ-018 section was last written and the + corresponding bullet was never updated to match. + **Fixed 2026-07-31**, in the same pass as the bottom-up console-message audit: the bullet now + reads "Verifying a fresh build is activity-aware and announced," describes the actual + silent-vs-any-output condition, and separately notes that the narrower re-verification inside + the `--hidden-import` auto-recovery loop remains unconditionally time-boxed (unaffected by this + fix, by design -- see this file's own entry on that loop for why). No behavior changed; this + was a documentation-only correction. + +--- + ## Closed Backlog - **Cascade-vs-postexec fix (Active Backlog item 9), 2026-07-25, owner-directed follow-up to a From 2b688ffb9a5e584ee32bb86eaa4d1943bb6b7303 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 31 Jul 2026 12:24:36 +0000 Subject: [PATCH 5/5] fix: tci_justme misleading AllUsers WARN, plus a backlog-number collision Active Backlog item 11 (:tci_justme's WARN unconditionally claims "AllUsers install failed" even when AllUsers was only ever skipped, never attempted): :try_conda_install now sets HP_CONDA_ALLUSERS_ATTEMPTED right before the real install attempt, and :tci_justme branches its log line on that flag -- a genuine failure keeps the original WARN wording, a skip gets a new, honest INFO line. Added a regression assertion to tests/selfapps_justme.ps1 confirming the new wording fires and the old one doesn't, in the non-elevated scenario that test already exercises. Updated demo-doc Scenario 19 to match (marked [Extrapolated Branch] pending a fresh CI capture). While closing this out, found item 11 collided with an already-closed, differently-numbered item from 2026-07-25 (still correctly cited by docs/agent-ndjson.md) -- and the same check on item 9 (closed earlier this session) turned up an identical collision, cited by both docs/agent-ndjson.md and docs/agent-interconnect.md. Renumbered both to 16/17 (the next genuinely unused numbers) when archiving them into docs/agent-closed-backlog.md, and filed a new item 18 documenting that the remaining current items (8, 10, 12, 13, 14, 15) show the same number-reuse signature via a grep-based check, without yet doing the individual verification each one needs before it can be safely renumbered too -- left for a dedicated future pass. --- CLAUDE.md | 59 +++++++++++++++++++------------- docs/agent-closed-backlog.md | 58 +++++++++++++++++++++++++++++-- docs/demo-bootstrapper-output.md | 29 ++++++++++------ run_setup.bat | 12 ++++++- tests/selfapps_justme.ps1 | 17 ++++++--- 5 files changed, 132 insertions(+), 43 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 9dfd3b22..185977e5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -565,30 +565,6 @@ number) in `docs/agent-closed-backlog.md`, which is why the numbering below does so 2-3 representative invalid-value cases would likely cover the real risk without a combinatorial test matrix). -- **11. `:tci_justme`'s `[WARN] Miniconda AllUsers install failed; retrying with JustMe.` log line - fires unconditionally, even when AllUsers was never actually attempted -- found 2026-07-29 - while documenting the Miniconda install chain for `docs/demo-bootstrapper-output.md`'s Part VI, - flagged by a CodeRabbit review on PR #401 and verified against real CI evidence and the actual - `run_setup.bat` source before acting.** `:try_conda_install` has three distinct paths into the - shared `:tci_justme` label: (a) `HP_TEST_NOT_ELEVATED=1` (test-only, simulates a non-admin - environment) skips straight to `:tci_justme` with no AllUsers attempt at all; (b) a real - `fsutil dirty query %systemdrive%` failure (the genuine non-elevated-process detection) does - the same; (c) a real, genuine AllUsers installer failure (`:run_installer_timeout` returning - nonzero) also falls through to `:tci_justme`. All three paths log the identical - `[WARN] Miniconda AllUsers install failed; retrying with JustMe.` line at `:tci_justme` itself, - regardless of which path got there -- so on the common non-elevated real-world machine (paths a - or b), the WARN text is a misnomer: AllUsers was never launched, only skipped, yet the log - claims it "failed." Confirmed directly against real CI capture (run `30328748330`, `justme-test` - and `uv` lanes): both the `[INFO] Not elevated; skipping AllUsers Miniconda install.` line and - the `[WARN] ... AllUsers install failed ...` line appear back-to-back for the identical - non-elevated test run, with no genuine AllUsers attempt in between. **Not fixed in this pass** - -- this PR is documentation-only (see this file's own standing policy on scope); the doc itself - was corrected to explain the shared-label/unconditional-wording behavior accurately rather than - presenting the two log lines as if AllUsers were genuinely attempted-then-failed. Suggested fix - for a future pass: track whether AllUsers was actually launched (e.g. a flag set only inside - the real `:run_installer_timeout` call, checked at `:tci_justme` to select between "skipping" - and "failed" wording) rather than a single unconditional message covering all three paths. - - **12. `:embed_dl_retry`'s genuine mid-download-failure-then-retry-once path (REQ-009 Tier 5) has no CI test hook at all -- found 2026-07-29 while documenting the embed-tier download for `docs/demo-bootstrapper-output.md`'s Part VI, Scenario 20.** Confirmed via `run_setup.bat` @@ -710,6 +686,41 @@ number) in `docs/agent-closed-backlog.md`, which is why the numbering below does of what's shown) -- but a future pass fixing this should also confirm no currently-passing test silently relies on the unbounded behavior before adding a timeout. +- **18. Active Backlog items 8, 10, 12, 13, 14, and 15 all appear to reuse item numbers already + permanently retired by older, unrelated closed items -- found 2026-07-31 while closing out + items 9 and 11 during a `/goal`-directed backlog-fix pass, both of which turned out to have the + identical problem (fixed for those two; this item tracks the rest).** The batch of findings + filed 2026-07-29 while documenting the bootstrapper for `docs/demo-bootstrapper-output.md` + (this file's current items 8, 10, 12, 13, 14, 15, plus the now-fixed 9 and 11) appears to have + picked its numbers by eyeballing what looked unused in THIS file at the time, without checking + `docs/agent-closed-backlog.md`'s own "Closed Backlog" changelog section (2026-07-25 through + 2026-07-27 work) for numbers already retired there. Confirmed for 9 and 11 specifically (both + collided with real, already-closed, differently-numbered items -- see + `docs/agent-closed-backlog.md`'s Item 16 and Item 17 entries for the full trace of each) and + both renumbered to 16/17 when moved out of this file in the same pass that found this. A quick + grep-based check (`grep -n "item N\b"` across `docs/agent-closed-backlog.md`, `docs/agent- + ndjson.md`, `docs/agent-interconnect.md`, `docs/agent-lessons-learned.md` for each of N in + 8, 10, 12, 13, 14, 15) shows a same-number hit in the older Closed Backlog section for every + single one of them, strongly suggesting the same mistake repeats across the whole batch -- + but each was only confirmed by number match, not individually read and verified the way 9 and + 11 were, so **treat this as a strong lead, not a certainty, until each one gets the same + individual check.** Notably, item 14's collision is NOT purely a docs problem: `run_setup.bat` + itself has a live `rem derived requirement: [Active Backlog item 14]` comment (in + `:try_conda_install`, next to the Miniconda installer timeout) that refers to the OLDER, + already-closed item 14 (the 60-minute installer-timeout work), not the current active item 14 + (the misleading post-exhaustion syntax-error message) -- so fixing this properly means checking + inline source comments too, not just docs. **Not fixed in this pass** -- renumbering the + remaining six items correctly requires reading each one's full closed-backlog collision + individually (to write an accurate, non-templated "renumbered from X because Y" note the way + 16/17 got), then re-numbering every cross-reference to each (docs and, per the item-14 finding + above, possibly `run_setup.bat`'s own comments) -- real, careful work, not a batch find-replace, + and disproportionate to fold into an unrelated backlog-fix pass. Suggested approach for a + future pass: process one item at a time (matching this repo's own iteration discipline), confirm + its collision, pick the next genuinely-unused number (19 is next after this item, assuming no + further items get filed first), update its own text plus every cross-reference, and move it to + `docs/agent-closed-backlog.md` only if it was ALSO independently resolved -- an item can be + renumbered without being closed, if its underlying finding is still open. + ## Cold Storage (promising ideas, deliberately shelved -- revisit only if a named trigger fires) Moved to `docs/agent-cold-storage.md` (2026-07-31, to reduce this file's per-session context diff --git a/docs/agent-closed-backlog.md b/docs/agent-closed-backlog.md index 300c2000..220dfd47 100644 --- a/docs/agent-closed-backlog.md +++ b/docs/agent-closed-backlog.md @@ -473,7 +473,61 @@ further.)* --- -### Item 9 (closed 2026-07-31; moved here same pass) +### Item 16 (closed 2026-07-31; moved here same pass; renumbered from 11) + +**Renumbered from 11 to 16 when moving here** -- this finding was originally filed in CLAUDE.md's +Active Backlog as "item 11," but that number was already permanently retired by the older +"Hidden-import auto-recovery exhaustion coverage" entry in this file's own Closed Backlog section +below (closed 2026-07-25, still correctly cited as "item 11" by `docs/agent-ndjson.md`'s +`self.exe.hidden_import.exhaust` entry) -- a genuine number reuse that must have slipped in when +this finding was first logged. Renumbered to 16 and 17 respectively (see the sibling entry right +after this one) -- the next two numbers never used anywhere in this repo's docs -- rather than +leaving the collision in place; no other doc referenced this finding as "item 11" before this +move, so the renumber is clean. **This is one instance of a wider, unrelated bug** -- see the new +Active Backlog entry filed in the same pass for the full scope (items 8, 9, 10, 12, 13, 14, and 15 +all appear to reuse numbers already retired the same way; only 9 and 11 were actually renumbered +here, since those were the two items this pass touched for unrelated reasons). + +- **`:tci_justme`'s `[WARN] Miniconda AllUsers install failed; retrying with JustMe.` log line + fired unconditionally, even when AllUsers was never actually attempted -- found 2026-07-29 + while documenting the Miniconda install chain for `docs/demo-bootstrapper-output.md`'s Part VI, + flagged by a CodeRabbit review on PR #401 and verified against real CI evidence and the actual + `run_setup.bat` source before acting.** `:try_conda_install` has three distinct paths into the + shared `:tci_justme` label: (a) `HP_TEST_NOT_ELEVATED=1` (test-only, simulates a non-admin + environment) skips straight to `:tci_justme` with no AllUsers attempt at all; (b) a real + `fsutil dirty query %systemdrive%` failure (the genuine non-elevated-process detection) does + the same; (c) a real, genuine AllUsers installer failure (`:run_installer_timeout` returning + nonzero) also falls through to `:tci_justme`. All three paths logged the identical + `[WARN] Miniconda AllUsers install failed; retrying with JustMe.` line at `:tci_justme` itself, + regardless of which path got there -- so on the common non-elevated real-world machine (paths a + or b), the WARN text was a misnomer: AllUsers was never launched, only skipped, yet the log + claimed it "failed." Confirmed directly against real CI capture (run `30328748330`, `justme-test` + and `uv` lanes): both the `[INFO] Not elevated; skipping AllUsers Miniconda install.` line and + the `[WARN] ... AllUsers install failed ...` line appeared back-to-back for the identical + non-elevated test run, with no genuine AllUsers attempt in between. + **Fixed 2026-07-31.** `:try_conda_install` now sets `HP_CONDA_ALLUSERS_ATTEMPTED=1` (reset + defensively at subroutine entry) immediately before the real AllUsers install attempt, and + `:tci_justme` branches its log line on whether that flag is defined: the genuine-failure path + keeps the original WARN wording unchanged, while both skip paths now log + `[INFO] Miniconda AllUsers install skipped (not elevated); trying JustMe install instead.` + instead. Confirmed safe against all three existing tests that reach this code path + (`tests/selfapps_justme.ps1`, `tests/selfapps_conda_bothfail.ps1`) -- none asserted on the old + WARN text for the skip-path scenarios they exercise. Added a new regression assertion to + `tests/selfapps_justme.ps1` (`skippedWordingCorrect`/`failedWordingAbsent`) confirming the new + INFO wording fires and the old WARN wording does NOT, in the non-elevated simulation this test + already runs. + +--- + +### Item 17 (closed 2026-07-31; moved here same pass; renumbered from 9) + +**Renumbered from 9 to 17 when moving here** -- filed in CLAUDE.md's Active Backlog as "item 9," +but that number was already permanently retired by the older "Cascade-vs-postexec fix" entry in +this file's own Closed Backlog section below (closed 2026-07-25, still correctly cited as +"item 9" by both `docs/agent-ndjson.md` and `docs/agent-interconnect.md` -- both auto-loaded into +every session). Nothing outside CLAUDE.md's own now-removed entry referenced this finding as +"item 9," so the renumber is clean (see the preceding item's own header for the wider collision +this belongs to). - **README.md's `[REQ-018]` bullet describing the mandatory verification run as "force-stopped after a short interval even if running fine" was stale relative to the @@ -494,8 +548,6 @@ further.)* fix, by design -- see this file's own entry on that loop for why). No behavior changed; this was a documentation-only correction. ---- - ## Closed Backlog - **Cascade-vs-postexec fix (Active Backlog item 9), 2026-07-25, owner-directed follow-up to a diff --git a/docs/demo-bootstrapper-output.md b/docs/demo-bootstrapper-output.md index 98254b2a..e03330fa 100644 --- a/docs/demo-bootstrapper-output.md +++ b/docs/demo-bootstrapper-output.md @@ -1533,26 +1533,33 @@ passing). Miniconda install first attempts an AllUsers (machine-wide) install; if UAC rejects elevation (or the process simply isn't elevated), it skips straight to a JustMe (per-user) install instead, no wasted attempt. **Both the "skip, never attempted" path and a genuine post-attempt AllUsers -failure fall through to the same shared `:tci_justme` label** (`run_setup.bat`), whose log line -unconditionally reads `[WARN] Miniconda AllUsers install failed; retrying with JustMe.` regardless -of which of the two got it there -- so on the common non-elevated machine, the WARN text is a -misnomer (AllUsers was never actually launched, only skipped), confirmed by this real capture -pairing the "Not elevated; skipping" INFO line immediately with the "AllUsers install failed" WARN -line for the identical run: +failure fall through to the same shared `:tci_justme` label** (`run_setup.bat`), but (fixed +2026-07-31, Active Backlog item 16 -- see `docs/agent-closed-backlog.md`) the label +now checks a flag set only right before the real AllUsers install attempt, so the two paths get +distinct wording instead of both unconditionally claiming AllUsers "failed." On the common +non-elevated machine (skip path, `[Extrapolated Branch]` for the new wording -- not yet +re-confirmed against a fresh CI capture): ``` [INFO] Not elevated; skipping AllUsers Miniconda install. -[WARN] Miniconda AllUsers install failed; retrying with JustMe. +[INFO] Miniconda AllUsers install skipped (not elevated); trying JustMe install instead. [INFO] Miniconda installed (JustMe fallback). ``` -**If JustMe ALSO fails** (both installation options exhausted -- AllUsers was skipped, not -attempted-then-failed, per the wording caveat above; REAL CI CAPTURE, same shared label, same -unconditional WARN wording): +A genuine, post-attempt AllUsers failure still gets the original WARN wording (`[Extrapolated +Branch]`, cited from source -- this branch requires a real elevated process whose AllUsers +installer genuinely fails, which no current CI hook forces without also forcing the skip path): ``` -[INFO] Not elevated; skipping AllUsers Miniconda install. [WARN] Miniconda AllUsers install failed; retrying with JustMe. +``` + +**If JustMe ALSO fails** (both installation options exhausted; REAL CI CAPTURE for the skip-path +lines, `[Extrapolated Branch]` for the now-corrected wording): + +``` +[INFO] Not elevated; skipping AllUsers Miniconda install. +[INFO] Miniconda AllUsers install skipped (not elevated); trying JustMe install instead. [ERROR] Miniconda install failed (both AllUsers and JustMe). ``` diff --git a/run_setup.bat b/run_setup.bat index ec8807d5..2e014278 100644 --- a/run_setup.bat +++ b/run_setup.bat @@ -4481,6 +4481,11 @@ exit /b %HP_INSTALLER_RC% rem derived requirement: AllUsers install can fail when UAC rejects elevation even for admin accounts. rem JustMe is the non-admin fallback that installs under the user profile instead. rem Both attempts reuse the already-downloaded installer at %TEMP%\miniconda.exe (no re-download). +rem derived requirement: [Active Backlog item 11] track whether AllUsers was actually launched vs. +rem only skipped, so :tci_justme's own log line can tell the two apart instead of unconditionally +rem claiming AllUsers "failed" even when it was never attempted. Reset defensively at entry in case +rem a future caller invokes this subroutine more than once in the same process. +set "HP_CONDA_ALLUSERS_ATTEMPTED=" rem derived requirement: non-admin machines produce a UAC prompt when AllUsers install is attempted; rem skip directly to JustMe when the process is not elevated. rem HP_TEST_NOT_ELEVATED=1 simulates a non-admin environment for CI coverage of this branch. @@ -4499,13 +4504,18 @@ rem "Installing Anaconda/Miniconda times out after 40 minutes"; multiple conda/c rem ContinuumIO/anaconda-issues GitHub issues reporting the silent installer hanging indefinitely rem at extraction or the post-install script) confirm this is not a theoretical risk. 60 minutes rem is a generous ceiling above the documented ~40 min real-world duration. +set "HP_CONDA_ALLUSERS_ATTEMPTED=1" call :run_installer_timeout "%TEMP%\miniconda.exe" "/InstallationType=AllUsers /AddToPath=0 /RegisterPython=0 /S /D=%MINICONDA_ROOT%" 3600000 "Miniconda AllUsers" if errorlevel 1 goto :tci_justme set "HP_CONDA_INSTALL_MODE=AllUsers" call :log "[INFO] Miniconda installed successfully." goto :eof :tci_justme -call :log "[WARN] Miniconda AllUsers install failed; retrying with JustMe." +if defined HP_CONDA_ALLUSERS_ATTEMPTED ( + call :log "[WARN] Miniconda AllUsers install failed; retrying with JustMe." +) else ( + call :log "[INFO] Miniconda AllUsers install skipped (not elevated); trying JustMe install instead." +) if exist "%MINICONDA_ROOT%" rd /s /q "%MINICONDA_ROOT%" >nul 2>&1 rem derived requirement: [Active Backlog item 10] HP_TEST_FORCE_JUSTME_FAIL=1 deterministically rem forces the JustMe install to fail WITHOUT launching the real installer, so CI can exercise diff --git a/tests/selfapps_justme.ps1 b/tests/selfapps_justme.ps1 index e78208b8..738a4773 100644 --- a/tests/selfapps_justme.ps1 +++ b/tests/selfapps_justme.ps1 @@ -57,7 +57,14 @@ $combinedText = $setupText + $mainSetupText $notElevatedSkip = $combinedText -match 'Not elevated; skipping AllUsers Miniconda install\.' $justmeInstalled = $combinedText -match 'Miniconda installed \(JustMe fallback\)' -$pass = $notElevatedSkip -and $justmeInstalled +# derived requirement: [Active Backlog item 11 fix] the shared :tci_justme label must NOT claim +# AllUsers "failed" when it was only ever skipped (never launched) -- this scenario's own +# HP_TEST_NOT_ELEVATED=1 takes the skip path, so the correct line is the INFO "skipped" wording, +# and the old unconditional WARN "failed" wording must NOT appear at all in this run. +$skippedWordingCorrect = $combinedText -match 'Miniconda AllUsers install skipped \(not elevated\); trying JustMe install instead\.' +$failedWordingAbsent = -not ($combinedText -match 'Miniconda AllUsers install failed; retrying with JustMe\.') + +$pass = $notElevatedSkip -and $justmeInstalled -and $skippedWordingCorrect -and $failedWordingAbsent Write-NdjsonRow ([ordered]@{ id = 'conda.install.justme' @@ -65,9 +72,11 @@ Write-NdjsonRow ([ordered]@{ pass = $pass desc = 'Miniconda JustMe install path executed (non-elevated simulation)' details = [ordered]@{ - notElevatedSkip = $notElevatedSkip - justmeInstalled = $justmeInstalled - setupLog = $setupLogPath + notElevatedSkip = $notElevatedSkip + justmeInstalled = $justmeInstalled + skippedWordingCorrect = $skippedWordingCorrect + failedWordingAbsent = $failedWordingAbsent + setupLog = $setupLogPath } })