Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
823d980
feat(env): guard managed downloads under system-only
myuron Oct 21, 2026
9111d54
feat(shim): use only system tools under system-only
myuron Oct 22, 2026
0ae0cb4
feat(setup): require system-only support from targets
myuron Oct 25, 2026
0173f16
fix(shim): restore shim error prefixes and stabilize CI checks
myuron Oct 25, 2026
9d0ed91
fix(shim): enforce system-only restrictions in child process PATH
myuron Oct 27, 2026
7e9cc00
fix(vpx): skip managed installs for system-only tools
myuron Oct 27, 2026
6b5d4fa
fix(shim): stop system-only loops through forwarding tools
myuron Oct 28, 2026
ac7e269
fix(shim): keep foreign tools in a shared bin eligible under system-only
myuron Oct 28, 2026
83eab53
fix(upgrade): probe system-only support before touching the target di…
myuron Oct 28, 2026
ca76a28
refactor(command): classify the first PATH match for system tools
myuron Oct 31, 2026
6f58c4c
fix(shim): fail system-only shims instead of forwarding to PATH
myuron Oct 31, 2026
a4eb134
fix(shim): select system-only tools by the first PATH match
myuron Nov 1, 2026
97f6d08
fix(shim): stop adding managed Node.js directories that expose system…
myuron Nov 2, 2026
fb64f12
fix(global): reject managed npm for global packages when npm is syste…
myuron Nov 2, 2026
ab7703b
revert(global): stop rejecting managed npm for global packages when n…
myuron Nov 5, 2026
8798016
feat(shim): make VP_NODE_MANAGER=system-only cover all package managers
myuron Nov 5, 2026
c768665
feat(env): replace VP_NODE_MANAGER=system-only with VP_ENV_FORBIDDEN
myuron Nov 5, 2026
d76d9a3
feat(setup): save every component as system_first under VP_ENV_FORBIDDEN
myuron Nov 5, 2026
8bfb442
feat(setup): install Vite+ dependencies with system node and pnpm und…
myuron Nov 5, 2026
fb62f10
Merge remote-tracking branch 'upstream/main' into feat/system-only-shim
myuron Nov 5, 2026
389ff25
fix(setup): check system tools before setup changes anything under VP…
myuron Nov 5, 2026
f3c81b1
fix(pm): guard the pnpm bootstrap under VP_ENV_FORBIDDEN
myuron Nov 5, 2026
6ba1d09
fix(setup): keep upgrade.log lockfile hints consistent with the syste…
myuron Nov 5, 2026
7f0efc0
test(snapshots): skip package-manager prewarm for the env-forbidden s…
myuron Nov 5, 2026
dfebbec
fix(env): check the child Node.js under VP_ENV_FORBIDDEN
myuron Nov 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 35 additions & 5 deletions .github/scripts/test-install-bootstrap.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ $originalCheck = $env:VP_SELF_SETUP_SUPPORT_CHECK
$originalPath = $env:Path
$originalRegistry = $env:NPM_CONFIG_REGISTRY
$originalVpShell = $env:VP_SHELL
$managementVariables = @('VP_ENV_FORBIDDEN', 'VP_NODE_MANAGER', 'VP_PM_MANAGER', 'VP_NPM_MANAGER', 'VP_PNPM_MANAGER', 'VP_YARN_MANAGER', 'VP_BUN_MANAGER')
$originalManagement = @{}
foreach ($name in $managementVariables) { $originalManagement[$name] = [Environment]::GetEnvironmentVariable($name) }
$fixtureSha = '0123456789012345678901234567890123456789'
New-Item -ItemType Directory -Path "$testRoot/package", "$testRoot/tmp", "$testRoot/scripts" | Out-Null
Set-Content -LiteralPath "$testRoot/package/vp.exe" -Value 'Payload fixture'
Expand All @@ -78,17 +81,23 @@ if ($args.Count -eq 0) {
$expectedVpShell = if ($scenario -eq 'supported-pr') { 'fish' } else { 'powershell' }
if ($env:VP_SHELL -ne $expectedVpShell) { exit 96 }
if ($scenario -eq 'supported-pr' -and $env:NPM_CONFIG_REGISTRY -ne 'https://registry-bridge.viteplus.dev/') { exit 97 }
if ($scenario -like 'env-forbidden*' -and $env:VP_ENV_FORBIDDEN -cne '1') { exit 94 }
Write-Output ("`$script:InstallDir = '{0}'" -f "$testRoot/data")
Write-Output ("`$script:ShimDir = '{0}'" -f "$testRoot/installed bin")
Write-Output ("`$script:CacheDir = '{0}'" -f "$testRoot/cache")
Write-Output ("`$script:ConfigDir = '{0}'" -f "$testRoot/config")
Write-Output ("`$script:StateDir = '{0}'" -f "$testRoot/state")
exit 0
}
if ($env:VP_SELF_SETUP_SUPPORT_CHECK -ne '1') { exit 99 }
# Only VP_ENV_FORBIDDEN=1 asks for the second response line.
$expectedCheck = if ($scenario -like 'env-forbidden*') { 'env-forbidden' } else { '1' }
if ($env:VP_SELF_SETUP_SUPPORT_CHECK -cne $expectedCheck) { exit 99 }
New-Item -ItemType File -Path "$testRoot/binary-probed" | Out-Null
if ($scenario -in @('legacy', 'legacy-remote', 'legacy-failure', 'pr')) { Write-Output 'Usage: vp [COMMAND]' }
else { Write-Output 'vite-plus-self-setup-v1' }
if ($scenario -in @('legacy', 'legacy-remote', 'legacy-failure', 'pr', 'env-forbidden-legacy')) { Write-Output 'Usage: vp [COMMAND]' }
else {
Write-Output 'vite-plus-self-setup-v1'
if ($expectedCheck -eq 'env-forbidden' -and $scenario -ne 'env-forbidden-v1') { Write-Output 'vite-plus-self-setup-env-forbidden' }
}
exit 0
'@ | Set-Content -LiteralPath "$testRoot/package/binary.ps1"
@'
Expand Down Expand Up @@ -196,6 +205,11 @@ function Test-SelfSetupSupport {
param($BinarySource)
& $probe -BinarySource (Join-Path (Split-Path $BinarySource) 'binary.ps1')
}
$envForbiddenProbe = ${function:Test-EnvForbiddenSupport}
function Test-EnvForbiddenSupport {
param($BinarySource)
& $envForbiddenProbe -BinarySource (Join-Path (Split-Path $BinarySource) 'binary.ps1')
}
$handoff = ${function:Invoke-InstallHandoff}
function Invoke-InstallHandoff {
param($BinarySource)
Expand All @@ -205,6 +219,7 @@ function Invoke-InstallHandoff {
try {
foreach ($scenario in @(
'supported', 'legacy', 'legacy-remote', 'legacy-failure', 'failure', 'pr', 'supported-pr',
'env-forbidden', 'env-forbidden-v1', 'env-forbidden-legacy', 'forbidden-value-true',
'metadata-error', 'metadata-missing-version', 'metadata-network-error', 'platform-error', 'platform-network-error',
'provenance-missing', 'provenance-malformed', 'provenance-dotted-key', 'tarball-missing',
'integrity-missing', 'integrity-malformed', 'integrity-unsupported', 'integrity-noncanonical',
Expand All @@ -220,9 +235,16 @@ try {
$script:PackageMetadata = $null
Remove-Item -LiteralPath "$testRoot/legacy", "$testRoot/binary-invoked", "$testRoot/binary-probed" -ErrorAction SilentlyContinue
$env:VP_SELF_SETUP_SUPPORT_CHECK = if ($scenario -eq 'supported') { 'original' } else { $null }
foreach ($name in $managementVariables) { [Environment]::SetEnvironmentVariable($name, $null, 'Process') }
switch ($scenario) {
{ $_ -like 'env-forbidden*' } { $env:VP_ENV_FORBIDDEN = '1' }
# Only the exact value 1 stops management.
'forbidden-value-true' { $env:VP_ENV_FORBIDDEN = 'true' }
}
$isEnvForbiddenFailure = $scenario -in @('env-forbidden-v1', 'env-forbidden-legacy')
$isIntegrityFailure = $scenario -like 'integrity-*'
$isMetadataFailure = $scenario -match '^(metadata-|platform-|provenance-|tarball-missing$)'
$expectedExit = if ($isIntegrityFailure -or $isMetadataFailure) {
$expectedExit = if ($isIntegrityFailure -or $isMetadataFailure -or $isEnvForbiddenFailure) {
1
} elseif ($scenario -in @('failure', 'legacy-failure')) {
42
Expand Down Expand Up @@ -260,13 +282,20 @@ try {
Write-Host "PASS: $scenario"
continue
}
if ($isEnvForbiddenFailure) {
Assert (Test-Path -LiteralPath "$testRoot/binary-probed") 'VP_ENV_FORBIDDEN support was not probed'
Assert (-not (Test-Path -LiteralPath "$testRoot/binary-invoked")) 'An unsupported binary was invoked with VP_ENV_FORBIDDEN'
Assert (-not (Test-Path -LiteralPath "$testRoot/legacy")) 'VP_ENV_FORBIDDEN reached legacy setup'
Write-Host "PASS: $scenario"
continue
}
Assert ($env:VP_SHELL -eq $initialVpShell) 'Setup changed the caller shell'
if ($scenario -eq 'supported') {
Assert (($env:Path -split ';')[0] -eq "$testRoot/installed bin") 'Installed bin directory was not added to the current PATH'
} elseif ($scenario -eq 'failure') {
Assert ($env:Path -eq $originalPath) 'Failed setup changed the current PATH'
}
$usesBinary = $scenario -in @('supported', 'supported-pr', 'failure')
$usesBinary = $scenario -in @('supported', 'supported-pr', 'failure', 'env-forbidden', 'forbidden-value-true')
Assert ((Test-Path -LiteralPath "$testRoot/binary-invoked") -eq $usesBinary) 'Incorrect binary invocation'
Assert ((Test-Path -LiteralPath "$testRoot/legacy") -eq (-not $usesBinary)) 'Incorrect legacy invocation'
if ($scenario -eq 'pr') {
Expand Down Expand Up @@ -325,6 +354,7 @@ try {
$env:Path = $originalPath
$env:NPM_CONFIG_REGISTRY = $originalRegistry
$env:VP_SHELL = $originalVpShell
foreach ($name in $managementVariables) { [Environment]::SetEnvironmentVariable($name, $originalManagement[$name], 'Process') }
$env:TEMP = $originalTemp
Remove-Item -LiteralPath $testRoot -Recurse -Force
$global:LASTEXITCODE = 0
Expand Down
34 changes: 30 additions & 4 deletions .github/scripts/test-install-bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,30 @@ if [ "$#" -eq 0 ]; then
if [[ "$scenario" == *pr ]]; then
test "$NPM_CONFIG_REGISTRY" = https://registry-bridge.viteplus.dev/ || exit 97
fi
if [[ "$scenario" == env-forbidden* ]]; then
test "${VP_ENV_FORBIDDEN:-}" = 1 || exit 95
fi
printf 'INSTALL_DIR=%q\n' "$test_root/data"
printf 'SHIM_DIR=%q\n' "$test_root/installed bin"
printf 'CACHE_DIR=%q\n' "$test_root/cache"
printf 'CONFIG_DIR=%q\n' "$test_root/config"
printf 'STATE_DIR=%q\n' "$test_root/state"
exit 0
fi
test "${VP_SELF_SETUP_SUPPORT_CHECK:-}" = 1 || exit 99
# Only VP_ENV_FORBIDDEN=1 asks for the second response line.
case "$scenario:${VP_SELF_SETUP_SUPPORT_CHECK:-}" in
env-forbidden*:env-forbidden) ;;
*:1) ;;
*) exit 99 ;;
esac
touch "$test_root/binary-probed"
case "$scenario" in
legacy|legacy-failure|piped-legacy|piped-legacy-failure|pr) printf 'Usage: vp [COMMAND]\n' ;;
*) printf 'vite-plus-self-setup-v1\n' ;;
legacy|legacy-failure|piped-legacy|piped-legacy-failure|pr|env-forbidden-legacy) printf 'Usage: vp [COMMAND]\n' ;;
*)
printf 'vite-plus-self-setup-v1\n'
if [ "$VP_SELF_SETUP_SUPPORT_CHECK" = env-forbidden ] && [ "$scenario" != env-forbidden-v1 ]; then
printf 'vite-plus-self-setup-env-forbidden\n'
fi ;;
esac
BINARY
chmod +x "$test_root/package/vp"
Expand Down Expand Up @@ -128,6 +140,7 @@ curl() {
}

for scenario in supported legacy legacy-failure piped-legacy piped-legacy-failure failure pr supported-pr \
env-forbidden env-forbidden-v1 env-forbidden-legacy forbidden-value-true \
missing-hash-tools missing-hash-tools-pr \
escaped-integrity escaped-integrity-pr escaped-integrity-all escaped-integrity-lower escaped-integrity-key escaped-integrity-slash \
integrity-missing integrity-malformed integrity-unsupported integrity-noncanonical integrity-wrong-type \
Expand Down Expand Up @@ -156,6 +169,12 @@ for scenario in supported legacy legacy-failure piped-legacy piped-legacy-failur
fi
if [[ "$scenario" == *pr ]]; then PR_VERSION=2406; fi
if [ "$scenario" = supported ]; then export VP_SELF_SETUP_SUPPORT_CHECK=original; fi
unset VP_ENV_FORBIDDEN VP_NODE_MANAGER VP_PM_MANAGER VP_NPM_MANAGER VP_PNPM_MANAGER VP_YARN_MANAGER VP_BUN_MANAGER
case "$scenario" in
env-forbidden*) export VP_ENV_FORBIDDEN=1 ;;
# Only the exact value 1 stops management.
forbidden-value-true) export VP_ENV_FORBIDDEN=true ;;
esac
main
test "$NPM_CONFIG_REGISTRY" = https://custom.example
test "$INSTALL_DIR" = "$test_root/data"
Expand Down Expand Up @@ -186,14 +205,21 @@ for scenario in supported legacy legacy-failure piped-legacy piped-legacy-failur
test "$status" -eq 42
elif [[ "$scenario" == *legacy-failure ]]; then
test "$status" -eq 43
elif [ "$scenario" = env-forbidden-v1 ] || [ "$scenario" = env-forbidden-legacy ]; then
test "$status" -ne 0
grep -q 'does not support VP_ENV_FORBIDDEN' "$test_root/output"
test -f "$test_root/binary-probed"
elif [ "$status" -ne 0 ]; then
cat "$test_root/output"
exit 1
fi
case "$scenario" in
supported|supported-pr|failure|missing-hash-tools*|escaped-integrity*)
supported|supported-pr|failure|missing-hash-tools*|escaped-integrity*|env-forbidden|forbidden-value-true)
test -f "$test_root/binary-invoked"
test ! -f "$test_root/legacy" ;;
env-forbidden-v1|env-forbidden-legacy)
test ! -f "$test_root/binary-invoked"
test ! -f "$test_root/legacy" ;;
legacy|legacy-failure|piped-legacy|piped-legacy-failure|pr)
test -f "$test_root/legacy"
test ! -f "$test_root/binary-invoked" ;;
Expand Down
21 changes: 21 additions & 0 deletions .github/scripts/test-install-legacy-remote.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,27 @@ try {
# setup-vp evaluates downloaded text in a script block, with no sibling legacy file.
# A child process also keeps installer exit calls from bypassing server cleanup.
$powershell = (Get-Process -Id $PID).Path

# A legacy release cannot honor VP_ENV_FORBIDDEN, so the installer must stop before legacy setup.
# Restore the workflow's value afterwards; the install below reproduces setup-vp with it.
$previousEnvForbidden = $env:VP_ENV_FORBIDDEN
$env:VP_ENV_FORBIDDEN = '1'
try {
# Windows PowerShell 5.1 turns redirected child stderr into errors, which 'Stop' would throw.
$ErrorActionPreference = 'Continue'
$output = & $powershell -NoProfile -Command '& ([scriptblock]::Create((irm -TimeoutSec 15 $env:VP_TEST_INSTALLER_URL)))' 2>&1 | Out-String
$exitCode = $LASTEXITCODE
$ErrorActionPreference = 'Stop'
if ($exitCode -eq 0) { throw 'The installer accepted VP_ENV_FORBIDDEN for a legacy release' }
if (-not $output.Contains('does not support VP_ENV_FORBIDDEN')) { throw "Unexpected VP_ENV_FORBIDDEN failure: $output" }
} finally {
$ErrorActionPreference = 'Stop'
$env:VP_ENV_FORBIDDEN = $previousEnvForbidden
}
if (Test-Path -LiteralPath (Join-Path $env:VP_HOME 'bin/vp.exe')) { throw 'The VP_ENV_FORBIDDEN attempt installed vp' }
$requests = @(Select-String -LiteralPath $stderr -Pattern 'GET /install-legacy.bin ' -SimpleMatch)
if ($requests.Count -ne 1) { throw 'The VP_ENV_FORBIDDEN attempt fetched the legacy script' }

& $powershell -NoProfile -Command '& ([scriptblock]::Create((irm -TimeoutSec 15 $env:VP_TEST_INSTALLER_URL)))'
if ($LASTEXITCODE -ne 0) { throw "Remote install failed with exit code $LASTEXITCODE" }

Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,33 @@ steps = [
{ argv = ["vp", "not-a-command"], comment = "Once marked, the binary dispatches commands normally", continue-on-failure = true },
]

[[case]]
name = "command_self_setup_env_forbidden_probe"
vp = "global"
env = { VP_SKIP_DEPS_INSTALL = "1" }
steps = [
{ argv = ["vpt", "rm", "$VP_HOME/current/bin/.vp-setup-complete"], snapshot = false },
{ argv = ["vp", "--help"], envs = [["VP_SELF_SETUP_SUPPORT_CHECK", "env-forbidden"]], comment = "The env-forbidden check value adds a second line after the unchanged v1 response" },
{ argv = ["vp", "--help"], envs = [["VP_SELF_SETUP_SUPPORT_CHECK", "Env-Forbidden"]], comment = "Only the exact lowercase value asks for VP_ENV_FORBIDDEN support" },
["vpt", "stat-file", "$VP_HOME/current/bin/.vp-setup-complete", "--assert", "missing"],
]

[[case]]
name = "command_self_setup_env_forbidden_in_place"
vp = "global"
skip-platforms = ["windows"]
env = { VP_SELF_SETUP_NO_MODIFY_PATH = "1", NPM_CONFIG_REGISTRY = "http://127.0.0.1:9" }
steps = [
{ argv = ["vpt", "rm", "$VP_HOME/current/bin/.vp-setup-complete"], comment = "An interrupted upgrade left the active installation unmarked", snapshot = false },
{ argv = ["vpt", "write-file", "$VP_HOME/current/bin/vp-install-lock.yaml", "release lockfile\n"], comment = "The release lockfile is present, so setup would restore it into the installation", snapshot = false },
{ argv = ["vpt", "write-file", "$VP_HOME/current/node_modules/.vp-install-complete", "stale receipt\n"], comment = "A stale receipt makes setup reinstall the dependencies", snapshot = false },
{ argv = ["vpt", "write-file", "$VP_HOME/current/pnpm-lock.yaml", "existing lockfile\n"], snapshot = false },
{ argv = ["vp", "--help"], envs = [["VP_ENV_FORBIDDEN", "1"], ["PATH", "${VP_HOME}/bin"]], comment = "With only the Vite+ shims on PATH, setup fails before it prepares the lockfile", continue-on-failure = true },
["vpt", "print-file", "$VP_HOME/current/node_modules/.vp-install-complete"],
["vpt", "print-file", "$VP_HOME/current/pnpm-lock.yaml"],
["vpt", "stat-file", "$VP_HOME/current/bin/.vp-setup-complete", "--assert", "missing"],
]

[[case]]
name = "command_self_setup_handoff"
vp = "global"
Expand Down Expand Up @@ -60,6 +87,20 @@ steps = [
["vpt", "stat-file", "home/cache/.vp-owned", "--assert", "file"],
]

[[case]]
name = "command_self_setup_env_forbidden_config"
vp = "global"
skip-platforms = ["windows"]
steps = [
{ argv = ["vpt", "mkdir", "-p", "external", "forbidden", "not-forbidden"], snapshot = false },
{ argv = ["vpt", "cp", "$VP_HOME/bin/vp", "external/vp"], snapshot = false },
{ argv = ["vpt", "chmod", "+x", "external/vp"], snapshot = false },
{ argv = ["./external/vp"], tty = false, envs = [["VP_HOME", "${workspace}/forbidden"], ["VP_SKIP_DEPS_INSTALL", "1"], ["VP_VERSION", "forbidden-test"], ["VP_SELF_SETUP_NO_MODIFY_PATH", "1"], ["VP_ENV_FORBIDDEN", "1"], ["VP_NODE_MANAGER", "yes"], ["VP_PM_MANAGER", "yes"], ["VP_NPM_MANAGER", "yes"], ["VP_PNPM_MANAGER", "yes"], ["VP_YARN_MANAGER", "yes"], ["VP_BUN_MANAGER", "yes"]], comment = "VP_ENV_FORBIDDEN=1 saves every component as system_first, overriding explicit VP_*_MANAGER=yes", snapshot = false },
["vpt", "print-file", "forbidden/config.json"],
{ argv = ["./external/vp"], tty = false, envs = [["VP_HOME", "${workspace}/not-forbidden"], ["VP_SKIP_DEPS_INSTALL", "1"], ["VP_VERSION", "forbidden-test"], ["VP_SELF_SETUP_NO_MODIFY_PATH", "1"], ["VP_ENV_FORBIDDEN", "true"], ["VP_NODE_MANAGER", "yes"], ["VP_PM_MANAGER", "yes"], ["VP_NPM_MANAGER", "yes"], ["VP_PNPM_MANAGER", "yes"], ["VP_YARN_MANAGER", "yes"], ["VP_BUN_MANAGER", "yes"]], comment = "Only the exact value 1 enables VP_ENV_FORBIDDEN; other values keep the VP_*_MANAGER choices", snapshot = false },
["vpt", "print-file", "not-forbidden/config.json"],
]

[[case]]
name = "command_self_setup_combined_default"
vp = "global"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# command_self_setup_env_forbidden_config

## `vpt mkdir -p external forbidden not-forbidden`


## `vpt cp $VP_HOME/bin/vp external/vp`


## `vpt chmod +x external/vp`


## `VP_HOME=${workspace}/forbidden VP_SKIP_DEPS_INSTALL=1 VP_VERSION=forbidden-test VP_SELF_SETUP_NO_MODIFY_PATH=1 VP_ENV_FORBIDDEN=1 VP_NODE_MANAGER=yes VP_PM_MANAGER=yes VP_NPM_MANAGER=yes VP_PNPM_MANAGER=yes VP_YARN_MANAGER=yes VP_BUN_MANAGER=yes ./external/vp`

VP_ENV_FORBIDDEN=1 saves every component as system_first, overriding explicit VP_*_MANAGER=yes


## `vpt print-file forbidden/config.json`

```
{
"nodeShimMode": "system_first",
"packageManagerShimModes": {
"bun": "system_first",
"npm": "system_first",
"pnpm": "system_first",
"yarn": "system_first"
}
}
```

## `VP_HOME=${workspace}/not-forbidden VP_SKIP_DEPS_INSTALL=1 VP_VERSION=forbidden-test VP_SELF_SETUP_NO_MODIFY_PATH=1 VP_ENV_FORBIDDEN=true VP_NODE_MANAGER=yes VP_PM_MANAGER=yes VP_NPM_MANAGER=yes VP_PNPM_MANAGER=yes VP_YARN_MANAGER=yes VP_BUN_MANAGER=yes ./external/vp`

Only the exact value 1 enables VP_ENV_FORBIDDEN; other values keep the VP_*_MANAGER choices


## `vpt print-file not-forbidden/config.json`

```
{
"packageManagerShimModes": {
"bun": "managed",
"npm": "managed",
"pnpm": "managed",
"yarn": "managed"
}
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# command_self_setup_env_forbidden_in_place

## `vpt rm $VP_HOME/current/bin/.vp-setup-complete`

An interrupted upgrade left the active installation unmarked


## `vpt write-file $VP_HOME/current/bin/vp-install-lock.yaml 'release lockfile
'`

The release lockfile is present, so setup would restore it into the installation


## `vpt write-file $VP_HOME/current/node_modules/.vp-install-complete 'stale receipt
'`

A stale receipt makes setup reinstall the dependencies


## `vpt write-file $VP_HOME/current/pnpm-lock.yaml 'existing lockfile
'`


## `VP_ENV_FORBIDDEN=1 PATH=${VP_HOME}/bin vp --help`

With only the Vite+ shims on PATH, setup fails before it prepares the lockfile

**Exit code:** 1

```
error: Setup error: VP_ENV_FORBIDDEN=1: Vite+ installs its dependencies with the system 'node', but the Vite+ shim at '<home>/.vite-plus/bin/node' comes first on PATH; run `vp env off node` to move the shims after the system tools
```

## `vpt print-file $VP_HOME/current/node_modules/.vp-install-complete`

```
stale receipt
```

## `vpt print-file $VP_HOME/current/pnpm-lock.yaml`

```
existing lockfile
```

## `vpt stat-file $VP_HOME/current/bin/.vp-setup-complete --assert missing`

```
<home>/.vite-plus/current/bin/.vp-setup-complete: missing
```
Loading
Loading