fix: delete management/ncp.ps1 - it shadowed the ncp.cmd PATH shim
PowerShell resolves ExternalScript (.ps1) ahead of Application (.cmd), and both lived in the directory the installer puts on PATH -- so in PowerShell `ncp` ran the .ps1 and was execution-policy-bound again, the exact thing the .cmd exists to avoid. Its other justification (giving ncp to pwsh on Linux) stopped being true once /usr/local/bin/ncp existed: pwsh runs a PATH symlink to a shell script as an Application. A test now prevents the file coming back. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -82,20 +82,6 @@ EOF
|
|||||||
echo "Registered promethean in ~/.bashrc."
|
echo "Registered promethean in ~/.bashrc."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Same ncp inside PowerShell, if pwsh is installed here. bash functions are
|
|
||||||
# invisible to pwsh, so without this `ncp` is "not recognized" there even
|
|
||||||
# though it works in bash. install-windows.ps1 does this on the Windows side;
|
|
||||||
# this profile lives outside the repo, so a restore has to re-add it.
|
|
||||||
if command -v pwsh >/dev/null; then
|
|
||||||
ps_profile="$HOME/.config/powershell/profile.ps1"
|
|
||||||
if ! grep -q "NexusOS ncp" "$ps_profile" 2>/dev/null; then
|
|
||||||
mkdir -p "$(dirname "$ps_profile")"
|
|
||||||
printf '\n# NexusOS ncp\nfunction ncp { & "%s/management/ncp.ps1" @args }\n' \
|
|
||||||
"$NEXUS_ROOT" >> "$ps_profile"
|
|
||||||
echo "Registered ncp in $ps_profile."
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# The AMD box runs CPU-only (Vega 20, 4GB VRAM thrashes). An NVIDIA box should not.
|
# The AMD box runs CPU-only (Vega 20, 4GB VRAM thrashes). An NVIDIA box should not.
|
||||||
if command -v nvidia-smi >/dev/null && command -v sqlite3 >/dev/null && \
|
if command -v nvidia-smi >/dev/null && command -v sqlite3 >/dev/null && \
|
||||||
[ "$(sqlite3 "$NEXUS_ROOT/synapse/memory/memory.db" \
|
[ "$(sqlite3 "$NEXUS_ROOT/synapse/memory/memory.db" \
|
||||||
|
|||||||
+2
-1
@@ -127,7 +127,8 @@ Write-OK "Web UI built (interface\web\dist)"
|
|||||||
# management\ncp.cmd goes on the machine PATH rather than a `function ncp` in the
|
# management\ncp.cmd goes on the machine PATH rather than a `function ncp` in the
|
||||||
# PowerShell profile. Three reasons the profile route kept biting:
|
# PowerShell profile. Three reasons the profile route kept biting:
|
||||||
# 1. Execution policy defaults to Restricted, which blocks the profile itself -
|
# 1. Execution policy defaults to Restricted, which blocks the profile itself -
|
||||||
# so the function was never defined, and ncp.ps1 could not have run anyway.
|
# so the function was never defined, and the .ps1 it called could not
|
||||||
|
# have run anyway.
|
||||||
# 2. Profiles are a PowerShell thing. cmd, Win+R, Task Scheduler and .lnk
|
# 2. Profiles are a PowerShell thing. cmd, Win+R, Task Scheduler and .lnk
|
||||||
# targets all reported "ncp is not recognized".
|
# targets all reported "ncp is not recognized".
|
||||||
# 3. We are elevated here, so $PROFILE is the ADMIN's profile - the whole
|
# 3. We are elevated here, so $PROFILE is the ADMIN's profile - the whole
|
||||||
|
|||||||
+6
-1
@@ -3,7 +3,12 @@ REM ncp - PATH entry point on Windows. A .cmd, not a .ps1, on purpose: PowerShel
|
|||||||
REM execution policy governs .ps1 only, so this keeps working under the default
|
REM execution policy governs .ps1 only, so this keeps working under the default
|
||||||
REM Restricted policy and from cmd, Win+R, Task Scheduler and .lnk targets - none
|
REM Restricted policy and from cmd, Win+R, Task Scheduler and .lnk targets - none
|
||||||
REM of which load a PowerShell profile. install-windows.ps1 puts this directory on
|
REM of which load a PowerShell profile. install-windows.ps1 puts this directory on
|
||||||
REM the machine PATH. ncp.ps1 stays for pwsh-on-Linux, where there is no PATH shim.
|
REM the machine PATH.
|
||||||
|
REM
|
||||||
|
REM This file must NOT be accompanied by an ncp.ps1 in the same directory:
|
||||||
|
REM PowerShell resolves ExternalScript (.ps1) ahead of Application (.cmd), so a
|
||||||
|
REM sibling ncp.ps1 wins in PowerShell and drags the execution policy back in -
|
||||||
|
REM exactly what this file exists to avoid.
|
||||||
REM
|
REM
|
||||||
REM ASCII only, same rule as the .ps1 files - a test in tests/test_smoke.py enforces it.
|
REM ASCII only, same rule as the .ps1 files - a test in tests/test_smoke.py enforces it.
|
||||||
setlocal
|
setlocal
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
# ncp - PowerShell entry point. The CLI itself is management/ncp.py, the same
|
|
||||||
# file the Linux shell wrapper runs; this only picks an interpreter and forwards
|
|
||||||
# the arguments.
|
|
||||||
#
|
|
||||||
# On Windows, ncp comes from management/ncp.cmd on the machine PATH instead (a
|
|
||||||
# .cmd is not subject to the execution policy and works outside PowerShell too) -
|
|
||||||
# install-windows.ps1 sets that up. This file is what gives ncp to pwsh on Linux,
|
|
||||||
# where restore-linux.sh registers it in $PROFILE.CurrentUserAllHosts as:
|
|
||||||
#
|
|
||||||
# function ncp { & "<repo>/management/ncp.ps1" @args }
|
|
||||||
#
|
|
||||||
# ASCII only, no exceptions: PowerShell 5.1 decodes BOM-less files as ANSI, so a
|
|
||||||
# single Unicode dash eats a quote and the script dies at parse time. A test in
|
|
||||||
# tests/test_smoke.py fails if any .ps1 in this repo gains a non-ASCII byte.
|
|
||||||
|
|
||||||
$Root = Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path)
|
|
||||||
|
|
||||||
# Forward slashes and per-platform venv layout: backslash is a literal character
|
|
||||||
# on Linux, not a separator, so "Promethean\Scripts\python.exe" would resolve to
|
|
||||||
# a single nonsense filename under pwsh on Linux. Windows accepts "/" happily.
|
|
||||||
# $env:OS is the 5.1-safe check; the automatic $IsWindows only exists on PS 6+.
|
|
||||||
$OnWindows = ($env:OS -eq "Windows_NT")
|
|
||||||
if ($OnWindows) {
|
|
||||||
$Py = Join-Path $Root "Promethean/Scripts/python.exe"
|
|
||||||
} else {
|
|
||||||
$Py = Join-Path $Root "Promethean/bin/python3"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Fall back to a system Python so backup/restore still work before the venv is
|
|
||||||
# built - those delegate to the stdlib-only bin/sync.py.
|
|
||||||
if (-not (Test-Path $Py)) {
|
|
||||||
foreach ($candidate in @("python3", "python")) {
|
|
||||||
$found = Get-Command $candidate -ErrorAction SilentlyContinue
|
|
||||||
if ($found) { $Py = $found.Source; break }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (-not (Test-Path $Py)) {
|
|
||||||
Write-Error "No Python found. Run install.sh (Linux) or install-windows.ps1 first."
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
& $Py (Join-Path $Root "management/ncp.py") @args
|
|
||||||
exit $LASTEXITCODE
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# ncp - Linux entry point. The CLI itself is management/ncp.py, which runs
|
# ncp - Linux entry point. The CLI itself is management/ncp.py, which runs
|
||||||
# unchanged on Windows too (see management/ncp.ps1); this stays a shell script
|
# unchanged on Windows too (see management/ncp.cmd); this stays a shell script
|
||||||
# because ~/.bashrc, launch_nexus.sh, bin/restore-linux.sh, controlpanel.py,
|
# because ~/.bashrc, launch_nexus.sh, bin/restore-linux.sh, controlpanel.py,
|
||||||
# bin/panel/nexus-popup.py and management/nexus-app.sh all invoke this path.
|
# bin/panel/nexus-popup.py and management/nexus-app.sh all invoke this path.
|
||||||
#
|
#
|
||||||
|
|||||||
+13
-1
@@ -96,6 +96,18 @@ def test_ncp_is_registered_on_path_not_in_a_shell_profile():
|
|||||||
"model pull must come after the desktop shortcut"
|
"model pull must come after the desktop shortcut"
|
||||||
|
|
||||||
|
|
||||||
|
def test_no_ps1_shadows_the_ncp_path_shim():
|
||||||
|
"""PowerShell resolves ExternalScript (.ps1) ahead of Application (.cmd), so
|
||||||
|
an ncp.ps1 sitting next to ncp.cmd wins in PowerShell and drags the execution
|
||||||
|
policy back in - the exact thing the .cmd exists to avoid. Observed on the
|
||||||
|
Windows VM: `Get-Command ncp -All` listed ncp.ps1 first, from the same
|
||||||
|
directory the installer had just put on PATH."""
|
||||||
|
shim = REPO_ROOT / "management" / "ncp.cmd"
|
||||||
|
assert shim.exists(), "the Windows PATH shim is missing"
|
||||||
|
twin = shim.with_suffix(".ps1")
|
||||||
|
assert not twin.exists(), f"{twin.name} shadows {shim.name} in PowerShell"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_first_playbook_is_the_system_prompt(tmp_path, monkeypatch):
|
def test_first_playbook_is_the_system_prompt(tmp_path, monkeypatch):
|
||||||
store = PlaybookFileStore(tmp_path)
|
store = PlaybookFileStore(tmp_path)
|
||||||
@@ -268,7 +280,7 @@ def test_desktop_stage_is_the_only_one_touching_home():
|
|||||||
# and in the PowerShell profile is how you launch NexusOS at all, and each is
|
# and in the PowerShell profile is how you launch NexusOS at all, and each is
|
||||||
# a grep-guarded no-op on re-run. Desktop config (xfconf, plank, themes,
|
# a grep-guarded no-op on re-run. Desktop config (xfconf, plank, themes,
|
||||||
# os-release) must stay in the desktop stage so --no-desktop really is safe.
|
# os-release) must stay in the desktop stage so --no-desktop really is safe.
|
||||||
shell_wiring = (".bashrc", "powershell/profile.ps1")
|
shell_wiring = (".bashrc",)
|
||||||
home_writes = [ln for ln in runtime.splitlines()
|
home_writes = [ln for ln in runtime.splitlines()
|
||||||
if "$HOME" in ln and not any(w in ln for w in shell_wiring)]
|
if "$HOME" in ln and not any(w in ln for w in shell_wiring)]
|
||||||
assert not home_writes, f"runtime stage writes to $HOME: {home_writes}"
|
assert not home_writes, f"runtime stage writes to $HOME: {home_writes}"
|
||||||
|
|||||||
Reference in New Issue
Block a user