Skip to content

fix(install): repair stale Winget Node registrations#112055

Open
ooiuuii wants to merge 1 commit into
openclaw:mainfrom
ooiuuii:fix/windows-winget-stale-node
Open

fix(install): repair stale Winget Node registrations#112055
ooiuuii wants to merge 1 commit into
openclaw:mainfrom
ooiuuii:fix/windows-winget-stale-node

Conversation

@ooiuuii

@ooiuuii ooiuuii commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Closes #112051

What Problem This Solves

Fixes an issue where Windows users could not complete OpenClaw setup when Winget retained a Node.js package registration but the actual Node runtime was missing or unusable.

Why This Change Was Made

The installer now captures Winget's result before path refresh commands can overwrite it. When Winget returns the specific no-applicable-upgrade code and Node validation still fails, setup makes one --force repair attempt, refreshes runtime discovery, and reuses the existing Node validation before reporting success.

Other Winget failures are not force-retried, and the repair path is bounded to one attempt.

User Impact

Windows setup can repair a stale Winget Node registration automatically instead of repeating the same "Node.js is still unavailable" failure on every run.

Evidence

  • The regression fixture executes the real Install-Node function with:
    • first Winget result -1978335189 (0x8A15002B),
    • Node unavailable after the normal install,
    • one expected forced call: winget install OpenJS.NodeJS.LTS --source winget --force --accept-package-agreements --accept-source-agreements,
    • Node available after the repair.
  • The fixture asserts exactly two Winget calls and a successful installer return; ordinary failures keep the existing path.
  • Focused regression suite:
    • node scripts/run-vitest.mjs test/scripts/install-ps1.test.ts
    • Result: 1 file passed, 30 tests passed.
  • Formatting: node_modules/.bin/oxfmt --check scripts/install.ps1 test/scripts/install-ps1.test.ts passed.
  • Static check: git diff --check upstream/main...HEAD passed.
  • Pre-commit TruffleHog scan: 0 verified and 0 unverified secrets.
  • Final structured review:
    • python .agents/skills/autoreview/scripts/autoreview --mode branch --base upstream/main
    • Result: autoreview clean: no accepted/actionable findings reported (patch is correct, confidence 0.94).
  • Not tested: the proof does not modify a live machine's Winget registration. It runs the actual installer branch with controlled package-manager and Node-discovery results.

@openclaw-barnacle openclaw-barnacle Bot added scripts Repository scripts size: XS labels Jul 21, 2026
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P0 Emergency: data loss, security bypass, crash loop, or unusable core runtime. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. labels Jul 22, 2026
@clawsweeper

clawsweeper Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 20, 2026, 11:57 PM ET / July 21, 2026, 03:57 UTC.

Summary
The PR records Winget’s first exit code, retries one specific failure with winget install --force, and adds a mocked PowerShell regression fixture for that branch.

PR surface: Tests +35, Other +11. Total +46 across 2 files.

Reproducibility: yes. at source level: the linked report and fixture define a deterministic path where Winget returns 0x8A15002B and Node remains unavailable after the initial install. A real stale-registration Windows/Winget reproduction has not been supplied.

Review metrics: none identified.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🦪 silver shellfish
Patch quality: 🧂 unranked krab
Result: blocked until real behavior proof from a real setup is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Replace the --force retry with an approved recovery or safe fallback that retains hash validation.
  • [P1] Add a regression test whose assertions model the selected supported recovery contract rather than mock success solely by call count.
  • Provide a redacted real Windows/Winget transcript after the corrected flow works; redact paths, account names, and other private data.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR provides focused tests that mock both Winget and Node discovery; it does not show after-fix behavior on a real affected Windows/Winget installation. A redacted Windows terminal transcript is needed after the recovery design is corrected. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Risk before merge

  • [P1] Merging the --force retry permits Winget to proceed after an installer hash mismatch in a first-run setup path, weakening a supply-chain integrity boundary.
  • [P1] The retry repeats an install request after a no-applicable-upgrade result without evidence that it repairs the stale registration, so affected users can remain blocked while the script reports a more specific but unsupported recovery attempt.

Maintainer options:

  1. Replace the force retry (recommended)
    Remove --force and implement a demonstrated Winget recovery or safe fallback that preserves hash verification before merge.
  2. Pause automatic repair
    Keep the existing failure path until an owner approves a package-manager repair contract that covers stale registrations without weakening installer integrity.

Next step before merge

  • [P1] An installer-security and recovery-contract choice is required before a mechanical repair can be safely attempted.

Maintainer decision needed

  • Question: Should Windows setup ever invoke Winget with --force for a stale Node registration, given that the option bypasses installer hash-mismatch protection and is not documented as registration repair?
  • Rationale: Choosing an automatic uninstall/reinstall, a portable-Node fallback, or no automatic repair determines both the installer’s security boundary and the user-data/Node-install preservation contract.
  • Likely owner: steipete — Historical installer ownership is the strongest available routing signal for a security-sensitive Windows installer policy choice.
  • Options:
    • Keep integrity checks and redesign repair (recommended): Remove the --force path, then add only a Winget recovery sequence that is documented and demonstrated to repair the reported state without bypassing hash verification.
    • Use existing safe fallback: Treat this Winget condition as a failed package-manager attempt and continue through the established installer fallback behavior instead of mutating the Winget registration.
    • Accept the force retry: Retain --force only with explicit ownership of the hash-verification trade-off and live proof that it repairs the exact stale-registration state.

Security
Needs attention: The new Winget --force invocation can bypass installer hash-mismatch protection in an unattended setup path.

Review findings

  • [P1] Do not bypass Winget hash verification — scripts/install.ps1:536
  • [P1] Use a repair action that addresses the no-upgrade result — scripts/install.ps1:534-540
Review details

Best possible solution:

Keep hash verification intact and either validate a documented, safe Winget repair sequence on an affected Windows machine or retain the existing safe fallback path rather than adding an automatic --force retry.

Do we have a high-confidence way to reproduce the issue?

Yes, at source level: the linked report and fixture define a deterministic path where Winget returns 0x8A15002B and Node remains unavailable after the initial install. A real stale-registration Windows/Winget reproduction has not been supplied.

Is this the best way to solve the issue?

No. --force is documented for hash-mismatch handling, not stale package registration repair, and the fixture stubs the second call as successful instead of establishing the external Winget behavior.

Full review comments:

  • [P1] Do not bypass Winget hash verification — scripts/install.ps1:536
    --force is documented to ignore a discovered installer hash mismatch and attempt installation. Using it in an automated first-run installer path weakens the package-integrity boundary for the reported error case; use a recovery flow that retains hash verification instead.
    Confidence: 0.99
  • [P1] Use a repair action that addresses the no-upgrade result — scripts/install.ps1:534-540
    The first command returns 0x8A15002B because Winget found no applicable upgrade. Repeating the same install request with --force does not target that condition—the flag concerns hash mismatches—so the real stale registration is likely to remain. The fixture only simulates success after the second mock call and cannot establish this package-manager behavior.
    Confidence: 0.97

Overall correctness: patch is incorrect
Overall confidence: 0.94

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against e679566a1c4d.

Label changes

Label justifications:

  • P0: The linked report describes non-technical Windows users blocked during first useful setup with no successful in-product recovery path.
  • merge-risk: 🚨 security-boundary: The added winget --force command can ignore an installer hash mismatch during automated setup.
  • merge-risk: 🚨 availability: The proposed retry is not shown to change the no-applicable-upgrade state, so the Windows installer can remain unable to provision Node.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🦪 silver shellfish and patch quality is 🧂 unranked krab.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR provides focused tests that mock both Winget and Node discovery; it does not show after-fix behavior on a real affected Windows/Winget installation. A redacted Windows terminal transcript is needed after the recovery design is corrected. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed

PR surface:

Tests +35, Other +11. Total +46 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 0 0 0 0
Tests 1 35 0 +35
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 1 11 0 +11
Total 2 46 0 +46

Security concerns:

  • [high] Force retry weakens installer integrity verification — scripts/install.ps1:536
    Winget documents --force as ignoring a discovered installer hash mismatch and attempting installation; invoking it automatically for the reported registration error broadens execution of an unverified installer.
    Confidence: 0.99

What I checked:

  • Changed installer behavior: The branch invokes winget install ... --force after 0x8A15002B and a failed Node check; this is the entire proposed repair action. (scripts/install.ps1:536, cc8e5cc319aa)
  • Winget option contract: The documented meaning of --force is to ignore a discovered installer hash mismatch and attempt installation; it is not a stale-registration or no-applicable-upgrade repair operation. The reported 0x8A15002B condition therefore has no demonstrated reason to change on the second identical install request.
  • Regression fixture does not exercise Winget semantics: The new fixture makes its Check-Node stub return true solely after two mock calls, regardless of whether the second Winget command could repair a stale registration; it proves control flow, not the external package-manager contract. (test/scripts/install-ps1.test.ts:348, cc8e5cc319aa)
  • Current installer boundary: The public installer documentation describes Windows Node setup through package managers and portable-node fallback, so an automatic package-manager repair must preserve the installer’s safe validation and download-integrity boundaries. Public docs: docs/install/installer.md. (docs/install/installer.md:286, e679566a1c4d)
  • Feature-history signal: Historical installer work at commit 4a3030d is attributed to steipete in the available repository history mirror; current ownership beyond that history signal is uncertain. (scripts/install.ps1:65, 4a3030df9e)

Likely related people:

  • steipete: Available installer history attributes a prior scripts/install.ps1 maintenance commit to steipete; the current installer contract and its Windows recovery behavior are likely adjacent to that work. (role: historical installer contributor; confidence: medium; commits: 4a3030df9e; files: scripts/install.ps1, docs/install/installer.md)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. P0 Emergency: data loss, security bypass, crash loop, or unusable core runtime. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. scripts Repository scripts size: XS status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Windows installer cannot repair stale Winget Node registrations

1 participant