Skip to content

Consolidate local work: skin depth, Live Ops density, WinPSCompat leak fix - #87

Merged
Sev7eNup merged 4 commits into
mainfrom
sync/2026-07-30
Jul 30, 2026
Merged

Consolidate local work: skin depth, Live Ops density, WinPSCompat leak fix#87
Sev7eNup merged 4 commits into
mainfrom
sync/2026-07-30

Conversation

@Sev7eNup

Copy link
Copy Markdown
Owner

Four commits consolidating all local work:

  • Make the desktop icon blue and follow the SPA skin / Rebalance surface depth in the light and dark skins — desktop icon + skin polish.
  • Add run-density strips to Live Ops and gate AI chat prompts on sources — the raw-bar cap hid workflows whose runs all fell past it (they read as idle); the ops graph now carries per-workflow density buckets and lane allocation reserves a lane for density-only workflows. AI chat starter prompts follow the resolved knowledge-source capabilities instead of assuming the privileged DB source. REST/CLI/MCP/docs kept in sync.
  • Stop the in-process pool from leaking WinPSCompat sessions — root cause of unbounded memory/thread growth under scheduled load: local Compress-Archive resolved to the Desktop-edition System32 module and implicit WinCompat spawned one never-closed powershell.exe -s session per pool runspace. Fix bundles Microsoft.PowerShell.Archive 1.2.5 (imported eagerly into the pool) and disables implicit WinCompat for the in-process SDK via powershell.config.json placed next to the SDK assembly, so desktop-only modules fail loudly instead of silently leaking. Guard tests pin both halves; full diagnosis in docs/performance-improvements.md.

Sev7eNup added 4 commits July 30, 2026 23:12
The shell rendered its icons from appicon.png, which is the untinted
orange source art rather than a skin, so the window, tray, exe and
installer all shipped orange while the app itself was blue.

Render the static set from appicon-dark.png instead, and let the window
and tray icon track the color skin at runtime: the SPA already rewrites
<link rel="icon"> to /appicon-<skin>.png on every skin switch, Chromium
reports that as page-favicon-updated, and skins.ts maps it back onto the
generated assets/skins/<id>.* pair. Reusing that signal keeps the
production SPA window preload-less and IPC-free. The exe, installer and
Start-Menu icon cannot follow a skin - Windows resolves those from the
file - which is why the shipped default matters.

Skin ids are not mirrored in the shell. The generator emits one variant
per appicon-*.png the SPA ships and the shell resolves against the files
on disk, so a skin added to the UI without a regenerated icon set keeps
the current icon instead of picking a wrong one. Ids are held to a strict
charset before they reach a path join, since they arrive from the
renderer.

Icon generation moves out of Build-DesktopInstaller.ps1 into
scripts/generate-desktop-icons.ps1 so the from-source dev loop can
populate the gitignored assets folder via `npm run icons`.
Three related tweaks to the same depth system.

Azur (default dark) read as embossed rather than as plates lying on the
page. Scale every depth cue down about a quarter - lit top rim, side and
bottom rims, face gradient, sheen and the whole shadow ramp - keeping the
geometry so the hard contact line survives. The press, primary-button and
input values that do not flow through the tokens are scaled with them;
leaving the press depth untouched against a softened plate would read as
a larger travel than the button has.

The default light skin had no depth layer at all: cards and buttons were
a border on a white fill with no shadow, which is why the surfaces looked
flat. Add a Lumen block mirroring Azur's ingredients and selector list.
One divergence is forced by the physics - a white plate on a near-white
ground has no headroom for a lit top rim, so the bevel runs monotonically
darker downward and the lift comes from the shadow. Alphas are far lower
for the same perceived depth. The button rule deliberately omits
background-color and excludes the tinted variants, which would otherwise
lose their fill and border colour to the bevel.

The shared table column header sat only ~4% under the white card body in
light mode and stopped reading as its own band. Move it one step down the
ramp for light only; dark keeps its value, where a bigger step would
bring back the harsh near-black edge.
Live Ops timeline: the raw-bar cap hid workflows that ran inside the window but
whose runs all fell past it, so they read as idle — the exact misreading the
timeline exists to prevent. The ops graph now carries per-workflow density
buckets, and lane allocation reserves a lane for density-only workflows so their
strip has somewhere to draw.

AI chat: the starter prompts assumed the DB/text2sql knowledge source, which is
off by default and privileged-only. Picking one without it just produced "source
not available". Prompts now follow the resolved capabilities and fall back to a
lite set, held back until caps resolve so the lite set does not flash first.

REST, CLI, MCP, docs and the docs-ui corpus kept in sync.
Root cause of the 9-GB / 472-thread growth of a long-running dev API
(diagnosed via full dump + gcroot): scheduled workflows targeting the
localhost machine run engine-local in the PowerShell SDK runspace pool,
and the SDK ships only the eight core modules. A local Compress-Archive
call therefore resolved to the Windows PowerShell 5.1 copy of
Microsoft.PowerShell.Archive (edition Desktop), which PowerShell loaded
through implicit Windows compatibility: one `powershell.exe -Version 5.1
-s` child (~148 MB) per pool runspace, registered as WinPSCompatSession
in that runspace's session repository and never closed. Pool runspaces
live forever, so sessions, their transport pump threads and child
processes accumulated without bound (~1 MB parent heap per execution
plus a child process per fresh runspace).

Fix, two parts:

- Bundle Microsoft.PowerShell.Archive 1.2.5 (MIT, unmodified, the same
  version full pwsh ships) and import it eagerly into every pool
  runspace via the InitialSessionState, so Compress-/Expand-Archive run
  natively in-process and the auto-loader never goes looking.
- Disable implicit WinCompat for the in-process SDK by placing
  powershell.config.json (DisableImplicitWinCompat) next to
  System.Management.Automation.dll via Directory.Build.targets (build
  and publish layouts). Desktop-only modules now fail loudly ("disabled
  in the settings file") instead of silently spawning compat sessions;
  explicit `Import-Module -UseWindowsPowerShell` remains available, and
  standalone powershell.exe/pwsh process engines are unaffected (own
  PSHOME).

Guard tests pin both halves: the archive roundtrip must resolve from the
bundled PSModules copy, and importing the Desktop-only System32 module
must fail with the settings-file refusal without leaving a session.
Removing the config placement turns the second test red.

Docs: performance-improvements.md gains the full diagnosis session
(including the disproved shared-FormatTable attempt and the gcdump
10M-object sampling pitfall), claude-reference.md and the docs-ui
activities reference describe the engine-local module surface, CLAUDE.md
links both.
@Sev7eNup
Sev7eNup merged commit cdf7441 into main Jul 30, 2026
8 checks passed
@Sev7eNup
Sev7eNup deleted the sync/2026-07-30 branch July 30, 2026 21:16
Sev7eNup added a commit that referenced this pull request Jul 31, 2026
docs: sync after #87 (RunspacePool memory rule of thumb correction)
hshalab pushed a commit to hshalab/NodePilot that referenced this pull request Aug 4, 2026
PR Sev7eNup#87 (WinPSCompat-Session-Leak fix, merged 2026-07-30) added
measurement data showing in-process pool runspaces cost 1.2-1.4 MB
each, not ~30 MB. The 30 MB figure came from the process-spawn path
and does not apply to the RunspaceExecutionEngine's pool.

The "Default-Tuning für 500-par.-WF-Topologie" section still carried
the old rule of thumb, producing contradictory guidance within the
same document. Corrected to match the 2026-07-30 measurement already
present later in the file.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant