@@ -271,6 +271,134 @@ elprobe run libform
271271functional=yes source=package-backed-plugin
272272```
273273
274+ ### Pending restart runtime marker hardening
275+
276+ Package-backed proxy plugins are discovered by PMMP before EasyLibrary itself
277+ is enabled. That boot order matters.
278+
279+ Before the hardening, this sequence could produce a false pending state:
280+
281+ 1 . a package install/update was staged;
282+ 2 . the server restarted;
283+ 3 . the generated proxy plugin loaded the new package successfully;
284+ 4 . EasyLibrary refreshed the proxy mount marker after loading;
285+ 5 . the refresh rewrote ` .easylib-package-plugin.json ` without remembering that
286+ the proxy had already booted.
287+
288+ The status service could then still report:
289+
290+ ``` text
291+ installed-pending-restart
292+ ```
293+
294+ even though PMMP had already loaded the package-backed plugin for the current
295+ session.
296+
297+ The generated proxy now records runtime evidence in the marker:
298+
299+ ``` json
300+ {
301+ "loaded-at" : 1781923400 ,
302+ "loaded-path" : " .../plugin_data/EasyLibrary/packages/libform/2.0.0"
303+ }
304+ ```
305+
306+ When EasyLibrary refreshes hidden proxy mounts, it preserves those runtime
307+ fields instead of erasing them. The package status service now clears
308+ restart-required metadata only when both checks are true:
309+
310+ - the active runtime path matches the staged package path;
311+ - the runtime loaded at or after the staged install/update/rollback timestamp.
312+
313+ This avoids two bad states:
314+
315+ - false pending restart after a successful restart;
316+ - false active state when a new package target was staged after the currently
317+ loaded runtime.
318+
319+ Validation performed with ` libform ` :
320+
321+ ``` text
322+ /easylibrary packages install libform stable confirm
323+ restart
324+ /easylibrary packages status libform
325+ libform / LibForm v2.0.0 [active]
326+ - Restart-required markers were cleared because the package is active.
327+
328+ /easylibrary packages doctor
329+ Packages: 13 / installed: 13 / active: 13 / pending restart: 0
330+ Problems: 0
331+
332+ elprobe run libform
333+ functional=yes source=package-backed-plugin
334+ ```
335+
336+ ### Dependency-safe removal
337+
338+ Remove is now dependency-aware for installed packages.
339+
340+ Example:
341+
342+ ``` text
343+ /easylibrary packages remove libpacket
344+ ```
345+
346+ If ` libcommand ` is still installed and requires ` LibPacket ` , the command is
347+ blocked with a concrete reason:
348+
349+ ``` text
350+ Cannot remove while installed packages require it: LibCommand.
351+ Remove or migrate those dependent packages first, then retry this command.
352+ ```
353+
354+ Why this matters:
355+
356+ - ` remove ` is restart-based, so breaking the next boot is easy if a dependency
357+ disappears silently;
358+ - package-backed plugins participate in PMMP ` depend ` resolution;
359+ - the package manager must refuse an unsafe detach before writing state.
360+
361+ This guard is intentionally conservative. It checks installed package manifests
362+ and blocks removal when another installed package declares the target as a hard
363+ dependency.
364+
365+ ### Temporary cleanup allowlist
366+
367+ Cleanup was narrowed to package-manager temporary paths only.
368+
369+ It now targets:
370+
371+ ``` text
372+ .downloads
373+ .staging
374+ _incoming*
375+ .incoming*
376+ ```
377+
378+ It intentionally preserves:
379+
380+ ``` text
381+ packages/<id>/<version>/
382+ .backups/
383+ ```
384+
385+ Why this matters:
386+
387+ - installed package versions are active or rollback candidates;
388+ - ` .backups ` is part of rollback safety;
389+ - interrupted downloads/staging folders should be disposable;
390+ - accidental broad cleanup should not remove usable packages.
391+
392+ Validation:
393+
394+ ``` text
395+ /easylibrary packages cleanup
396+ /easylibrary packages cleanup confirm
397+ ```
398+
399+ The dry-run and apply output both mention the allowlist and state that installed
400+ package versions and backups are preserved.
401+
274402### Release asset install validation
275403
276404The full package-backed server was rebuilt from official GitHub Release
@@ -955,6 +1083,7 @@ Cleanup currently removes temporary package manager data only:
9551083.downloads
9561084.staging
9571085_incoming*
1086+ .incoming*
9581087` ` `
9591088
9601089Installed package versions and `.backups` are preserved because backups are part
0 commit comments