Repository navigation
Releases: GooDAnDReaDY/dsh-smart-restart
Releases · GooDAnDReaDY/dsh-smart-restart
Release list
v0.1.15
Bug Fixes
- Safe Property & Service Resolution (#49):
- Implemented
safeGet(ctx, prop)inlib/chat-command.jsusing defensivectx.get(prop, false)with proxy-trap isolation. - Replaced direct
ctx.middlewarecheck withsafeGet(ctx, 'middleware'), fixingcannot get property "middleware" without injectcrash under strict Cordis Context Proxy runtimes (DSH 0.2.1-rc.4). - Protected
approvalservice lookup inlib/index.jsviasafeGet(ctx, 'approval'). - Added safe internal logging facade (
logger.warn/info/debug) to prevent uncaught proxy access errors onctx.logger.
- Implemented
- Regression Tests:
- Added strict Cordis v4 proxy suite in
test/activation.test.mjstesting activation with present, absent, and forbidden services.
- Added strict Cordis v4 proxy suite in
v0.1.14
0.1.14
Features
- Direct chat command for safe DSH restart without SSH (#44): Added slash command
/restart(and aliases!restart,/dsh-restart) for instant restart directly from conversation without opening terminal or SSH. Dual-path architecture: registered via@deepseek-ai/dsh-commandsand backed by a resilient fallback chat middleware. Supports interactive confirmation prompts (/restart --confirm,-y), simulation mode (/restart --dry-run), custom delay (/restart --delay=10s), reason tags (/restart --reason="..."), cancellation (/restart cancel,/cancel-restart), and instant health inspection (/restart status). The calling chat session is automatically captured as the post-boot delivery target, and the post-restart health verdict and package diff report are delivered right back into the same conversation.
v0.1.13
0.1.13
Features
- Direct chat command for safe DSH restart without SSH (#44): Added slash command
/restart(and aliases!restart,/dsh-restart) for instant restart directly from conversation without opening terminal or SSH. Dual-path architecture: registered via@deepseek-ai/dsh-commandsand backed by a resilient fallback chat middleware. Supports interactive confirmation prompts (/restart --confirm,-y), simulation mode (/restart --dry-run), custom delay (/restart --delay=10s), reason tags (/restart --reason="..."), cancellation (/restart cancel,/cancel-restart), and instant health inspection (/restart status). The calling chat session is automatically captured as the post-boot delivery target, and the post-restart health verdict and package diff report are delivered right back into the same conversation.
v0.1.12
0.1.12
Features
- Reliability Dashboard & Safe Restart in WebUI (#42):
- Added REST endpoints
GET /dsh-smart-restart/statusandPOST /dsh-smart-restart/restartwith CSRF & peer validation (isTrustedRequest). - Extended
RestartGuardCardwith health verdict badge (Healthy,Degraded,Loop guard active), subsystem checks breakdown (services,unit,port,versions), and recent restarts history table. - Interactive Safe Restart trigger with grace period delay and reason configuration.
- Added REST endpoints
- Grace Period Countdown Banner & Emergency Cancellation (#43):
- WebUI live countdown banner with ticking seconds and emergency cancel action.
- Added HTTP endpoint
POST /dsh-smart-restart/canceland agent tooldsh_restart_cancel. - Halts scheduled timer, clears pending
intent.json, and notifies active agent session.
v0.1.11
0.1.11
Features
- Rich situational snapshot on restart (#40):
dsh_restartnow accepts an optional structuredcontextobject capturing active working state (cwd,branch,worktree,files,tasks,memoryTag, plus arbitrary extra keys). Defaultscwdtoprocess.cwd()when omitted. Context is persisted intointent.jsonacross restarts, reported in post-boot agent notifications under- context: ..., and exposed throughdsh_restart_statustool for immediate resumption of work without manual reorientation. - Diff attribution between boots (#41):
marker.jsonnow records an inventory snapshot of installed packages (dependenciesanddevDependenciesfrompackage.json/ profile configs). On boot,diffPackages()calculates packages added, removed, or upgraded since the previous marker. Package changes are attributed inlast-report.json, exposed viadsh_restart_status.lastDiff, and formatted into the post-boot report under- changes: ....
v0.1.10: Preflight Validation and Graceful Drain
Release v0.1.10
Features
- Pre-flight configuration and environment validation before restart (#38): validates \package.json\ (JSON syntax), \cordis.patch.yml\ / \cordis.yml\ (YAML tab indentation & delimiter balance), systemd unit syntax, and network port conflicts before initiating restart. If any check fails, the restart is aborted, and an actionable diagnostic alert is delivered directly to the chat session via \deliverTo.
- Simulation mode (\dryRun: true) (#38): \dsh_restart\ supports \dryRun: true\ to execute all preflight checks without terminating the harness.
- Graceful drain guard for active agent tasks (#39): inspects running agent turns in \ctx.agents\ and waits for in-flight tasks to finish before terminating the harness (\drainActiveAgents). Configurable via \drainTimeoutMs\ (default \15000\ ms) in plugin config and WebUI settings card. Drain metrics (\drained, \waitedMs, \�ctiveCount) are recorded into \intent.json\ and reported in tool response.
Published to npm: @goodandready/dsh-smart-restart@0.1.10\
v0.1.9 [DSH v0.2.0-rc.2]
English
Security
- Host approval primitive for harness restart (#36):
dsh_restarttool no longer treats{ confirm: true }from the calling LLM agent as final authorization to restart the harness. AddedrequireApproval: Schema.boolean().default(true).volatile()to config and registered atools/pre-executewaterfall hook returning{ kind: 'ask', reason: ... }. Host approval is requested viactx.approval.request()before triggeringsystemctlor process signals. - Systemd unit name validation & detection check (#36):
systemctlRestartArgsnow enforces strict unit name syntax matching/^[A-Za-z0-9@_.-]+\.service$/and validates configured units against the running unit detected from/proc/self/cgroup(allowedUnit). Invalid or unauthorized unit specifications fail closed. - State directory path traversal protection (#36):
resolveSafeStateDir()prevents directory traversal outside$DSH_HOMEvia../sequences, ensuring persistence files remain sandboxed in$DSH_HOME/.restart-guard. - Delay clamping to prevent 32-bit timer overflow (#36):
clampDelayMs()bounds restart delays between 500ms and Node.js 32-bit integer limit2147483647ms, preventing immediate timer fires caused by overflow.
Fixed
- Preflight validation for devDependencies satisfying peerDependencies (#35): added Check #13 (
devDep вЉ† peerRange) todsh-plugin-preflight, ensuring development dependencies always satisfy declared peer compatibility bounds. - Primary agent fallback formalization (#35): clarified and verified
target: 'primary'contract, cleanly falling back fromctx.agents.roots()[0]toctx.agents.list()[0]when delivering post-restart verdicts.
Verification
npm test: 40/40 pass (100%).dsh-plugin-preflight: FAIL=0, WARN=2.- Verified on DSH v0.2.0-rc.2 (isolated MiniPC test contour & MiniAI production contour).
дёж–‡
安全
- Harness 重启的主机批准原иЇпј€#36пј‰пјљ
dsh_restartе·Ґе…·дёЌе†Ќе°†и°ѓз”Ё LLM ж™єиѓЅдЅ“зљ„{ confirm: true }视为重启 harness 的最终授权。配置дёж–°еўћrequireApproval: Schema.boolean().default(true).volatile()пјЊе№¶жіЁе†Њдє†иї”е›ћ{ kind: 'ask', reason: ... }зљ„й«�дј�е…€зє§tools/pre-executewaterfall й’©еђгЂ‚在触发systemctl或进程信号之前,通过ctx.approval.request()统一请求主机授权。 - Systemd еЌ•е…ѓеђЌз§°иЇжі•验证与检测比对(#36пј‰пјљ
systemctlRestartArgsдёҐж јејєе€¶еЌ•е…ѓеђЌз§°иЇжі•符合/^[A-Za-z0-9@_.-]+\.service$/пјЊе№¶е°†й…ЌзЅ®зљ„еЌ•е…ѓдёЋд»Ћ/proc/self/cgroup检测到的жЈењЁиїђиЎЊзљ„еЌ•е…ѓпј€allowedUnitпј‰иї›иЎЊж ЎйЄЊпјЊжњЄз»ЏжЋ€жќѓж€–йќћжі•зљ„еЌ•е…ѓиЇ·ж±‚е°†д»Ґ fail-closed ж–№ејЏж‹’з»ќгЂ‚ - зЉ¶жЂЃз›®еЅ•и·Їеѕ„йЃЌеЋ†й�ІжЉ¤пј€#36пј‰пјљ
resolveSafeStateDir()й�ІжўйЂљиї‡../еєЏе€—йЃЌеЋ†и¶…е‡є$DSH_HOMEпјЊзЎ®дїќжЊЃд№…еЊ–ж–‡д»¶дёҐж јй™ђе€¶ењЁ$DSH_HOME/.restart-guardдёгЂ‚ - й�Іжў 32 дЅЌе®љж—¶е™Ёжєўе‡єзљ„е»¶иїџй’ідЅЌпј€#36пј‰пјљ
clampDelayMs()е°†й‡ЌеђЇе»¶иїџй™ђе€¶ењЁ 500ms е€° Node.js 32 位有符号整数上限2147483647ms 之间,避免溢出导致定时器被截ж–дёє 1ms 立即触发。
дї®е¤Ќ
- devDependencies 满足 peerDependencies 范围的 preflight 验证(#35):在
dsh-plugin-preflightдёж·»еЉ 了检查项 #13пј€devDep вЉ† peerRange),确保开发依赖项始终满足声ж�Ћзљ„еЇ№з‰е…је®№иЊѓе›ґгЂ‚ - **Primary ж™єиѓЅдЅ“дє¤д»�е›ћйЂЂи§„иЊѓеЊ–**пј€#35пј‰пјљж�ЋзЎ®е№¶йЄЊиЇЃдє†
target: 'primary'契约,在交�重启后裁决报告时,当ctx.agents.roots()[0]为空时�雅回退至ctx.agents.list()[0]。
йЄЊиЇЃ
npm test:40/40 通过(100%)。dsh-plugin-preflight:FAIL=0, WARN=2。- 在 DSH v0.2.0-rc.2 上验证通过(MiniPC 独立测试环境与 MiniAI 生产环境)。
Р СѓСЃСЃРєРёР№
Безопасность
- Хостовый примитив подтверждения перезапуска harness (#36): инструмент
dsh_restartбольше не считает аргумент{ confirm: true }от вызывающего LLM-агента достаточным основанием для перезапуска. В схему конфигурации добавлен параметрrequireApproval: Schema.boolean().default(true).volatile(), и зарегистрирован перехватчикtools/pre-executewaterfall, возвращающий{ kind: 'ask', reason: ... }. Перед отправкой сигналов процесса или вызовомsystemctlзапрашивается авторизация черезctx.approval.request(...). - Синтаксическая валидация systemd unit и проверка cgroup (#36):
systemctlRestartArgsпроверяет имя юнита регулярным выражением/^[A-Za-z0-9@_.-]+\.service$/и сравнивает его сallowedUnit, извлечённым из/proc/self/cgroup. Попытки перезапуска сторонних служб отклоняются. - Защита от path traversal в каталоге состояния (#36):
resolveSafeStateDir()блокирует выход за пределы$DSH_HOMEчерез последовательности../, гарантируя безопасное сохранение маркеров в$DSH_HOME/.restart-guard. - Ограничение задержки от переполнения 32-битного таймера Node.js (#36):
clampDelayMs()ограничивает задержку диапазоном от 500 мс до2147483647мс (максимум для signed 32-bit int), исключая сброс в 1 мс при больших числах.
�справлено
- Preflight-проверка соответствия devDependencies диапазонам peerDependencies (#35): добавлена проверка #13 (
devDep ⊆ peerRange) вdsh-plugin-preflight. - Семантика доставки target: 'primary' (#35): формализован контракт доставки отчёта: при отсутствии сессии доставка выполняется в активный корень
ctx.agents.roots()[0], а при его отсутствии — вctx.agents.list()[0].
Проверка
npm test: 40/40 pass (100%).dsh-plugin-preflight: FAIL=0, WARN=2.- Проверено на DSH v0.2.0-rc.2 (изолированный стенд MiniPC и боевой контур MiniAI).
v0.1.8
English
Fixed
- DevDependencies upgraded to ^0.2.0-rc.2 (#25):
@deepseek-ai/dsh-tools,@deepseek-ai/dsh-llm,@deepseek-ai/dsh-session, and@deepseek-ai/dsh-home-pathsbumped to^0.2.0-rc.2, aligning dev toolchain with modern core APIs while preserving peer compatibility with^0.1.7-rc.2 || ^0.2.0-rc.1. - Client settings form unavailable state handling (#26):
RestartGuardCardlogs a warning when settings scope is missing, guards against null scope, and renders a localized unavailable notice (unavailable) instead of attempting unsaveable form interaction. - Core chevron down icon request with graceful SVG fallback (#27): client queries
IconChevronDownOutline14from@deepseek-ai/dsh-client-ui-primitivesadhering to DSH design guidelines, rotating 180° when open, with an inline SVG fallback if the primitive is unavailable. - Cleaned up redundant title expression (#28): eliminated dead ternary in client card header, cleanly referencing
t('title'). - Locale registration cleanup in ctx.effect (#29): locale bundles (
en,zh) are now registered withinctx.effect, returning the unregistration disposer to prevent lingering locale state on plugin reload. - Theme design token alignment (#30): replaced non-standard
--dsw-alias-label-errorwith design tokenvar(--dsw-alias-state-error-primary).
Verification
npm test: 35/35 pass (100%).dsh-plugin-preflight: FAIL=0, WARN=2.- Verified on DSH v0.2.0-rc.2 (isolated MiniPC test contour & MiniAI production contour).
中文
修复
- devDependencies 升级至 ^0.2.0-rc.2(#25):
@deepseek-ai/dsh-tools、@deepseek-ai/dsh-llm、@deepseek-ai/dsh-session与@deepseek-ai/dsh-home-paths升级至^0.2.0-rc.2,开发工具链与现代核心对齐,同时维持peerDependencies兼容性(^0.1.7-rc.2 || ^0.2.0-rc.1)。 - 客户端设置表单不可用状态处理(#26):当设置作用域缺失时
RestartGuardCard记录警告日志(ctx.logger.warn),处理空作用域并展示本地化不可用提示,避免执行无效表单保存。 - 请求核心 Chevron 图标并提供 SVG 回退(#27):客户端从
@deepseek-ai/dsh-client-ui-primitives请求IconChevronDownOutline14,展开时旋转 180°,并在基元不可用时优雅降级为内联 SVG。 - 清理冗余标题三元表达式(#28):移除了客户端卡片头部死三元判断,直接简洁调用
t('title')。 - 在 ctx.effect 中管理本地化清理(#29):语言包(
en、zh)在ctx.effect中注册并返回销毁函数,防止插件热重载时残留本地化状态。 - 主题设计令牌对齐(#30):将非标准的
--dsw-alias-label-error替换为规范设计令牌var(--dsw-alias-state-error-primary)。
验证
npm test:35/35 通过(100%)。dsh-plugin-preflight:FAIL=0, WARN=2。- 在 DSH v0.2.0-rc.2 上验证通过(MiniPC 独立测试环境与 MiniAI 生产环境)。
Русский
Исправлено
- Обновление devDependencies до ^0.2.0-rc.2 (#25):
@deepseek-ai/dsh-tools,@deepseek-ai/dsh-llm,@deepseek-ai/dsh-sessionи@deepseek-ai/dsh-home-pathsобновлены до^0.2.0-rc.2, синхронизируя окружение разработки с современным ядром DSH при сохранении обратной совместимости вpeerDependencies. - Обработка недоступного состояния формы настроек в клиенте (#26):
RestartGuardCardлогирует предупреждение (ctx.logger.warn) при отсутствии скоупа настроек и выводит локализованное сообщениеunavailableвместо попытки рендера неработоспособной формы. - Запрос ядровой иконки шеврона с SVG-фолбэком (#27): клиент запрашивает
IconChevronDownOutline14из@deepseek-ai/dsh-client-ui-primitivesс плавным поворотом на 180° при раскрытии и инлайн-SVG запасным вариантом. - Удаление мертвого тернарного выражения заголовка (#28): в заголовке клиентской карточки убран избыточный мертвый тернарник, обращение к заголовку стандартизировано как
t('title'). - Очистка словарей локализации в ctx.effect (#29): словари (
en,zh) регистрируются внутриctx.effectс возвратом функции отписки для предотвращения утечки состояния при перезагрузках. - Выравнивание дизайн-токена темы оформления (#30): устаревший и несуществующий
--dsw-alias-label-errorзаменен на стандартный токенvar(--dsw-alias-state-error-primary).
Проверка
npm test: 35/35 pass (100%).dsh-plugin-preflight: FAIL=0, WARN=2.- Проверено на DSH v0.2.0-rc.2 (изолированный стенд MiniPC и боевой контур MiniAI).
v0.1.7: Core runtime reliability, boot marker versions & delivery loop guard
English
Fixed
- Boot marker version detection & readBoot integration (#18, #31):
readBoot()now populatesdshVersion(from options orprocess.env.DSH_VERSION) andpluginVersion, and is invoked when writingmarker.jsonto record the exact runtime versions that produced the boot marker. - Post-restart report delivery for primary session (#19):
resolveAgent()now gracefully falls back toctx.agents.roots()[0]orctx.agents.list()[0]whentarget: 'primary'or whensessionIdis empty, ensuring the restart verdict and resumed work are delivered. - Intent preservation without session ID (#20):
intentState()now recognizes intents with recordedreasonorresumeeven if no callersessionIdwas resolved, and cleans upintent.jsonpost-delivery so stale intents do not linger. - Safe delivery retry ticks (#21): wrapped timer ticks and agent delivery in
try/catchand added error logging, preventing unhandled exceptions from terminating background timer loops. - Crash loop restart budget preservation (#22):
history.jsonnow records boot timestamps only when an actual restart occurred (boot.wasRestart === true), preventing cold boots and plugin reloads from exhausting the crash loop restart budget. - Probe timeout cleanup (#23):
probe()health checks now register timers throughsafeSetTimeout()and reliably clear timeout handles on resolution, eliminating dangling timers in the event loop.
Verification
npm test: 30/30 pass.dsh-plugin-preflight: FAIL=0, WARN=3.- Verified on DSH v0.2.0-rc.2 (isolated test contour & production contour).
中文
修复
- 启动标记版本检测与 readBoot 集成(#18, #31):
readBoot()现在填充dshVersion(从选项或process.env.DSH_VERSION)和pluginVersion,并在写入marker.json时调用,以记录生成启动标记的准确运行时版本。 - 主会话重启后报告交付(#19):当
target: 'primary'或sessionId为空时,resolveAgent()优雅地回退到ctx.agents.roots()[0]或ctx.agents.list()[0],确保重启判定和恢复工作得以交付。 - 无会话 ID 的意图保留(#20):
intentState()现在即使未解析到调用方sessionId也能识别包含记录的reason或resume的意图,并在交付后清理intent.json,防止过期意图残留。 - 安全的交付重试定时器(#21):在
try/catch中包装定时器 tick 和 agent 交付,并增加警告日志,防止未处理异常终止后台定时器循环。 - 保护崩溃循环重启配额(#22):
history.json现在仅在实际重启(boot.wasRestart === true)时记录启动时间戳,防止冷启动和插件重载消耗崩溃循环重启配额。 - 探测超时清理(#23):
probe()健康检查现在通过safeSetTimeout()注册定时器,并在解析时可靠清除超时句柄,消除事件循环中的游离定时器。
验证
npm test:30/30 通过。dsh-plugin-preflight:FAIL=0, WARN=3。- 已在 DSH v0.2.0-rc.2(隔离测试环境和生产环境)上验证。
Русский
Исправлено
- Определение версий маркера загрузки и интеграция readBoot (#18, #31):
readBoot()теперь заполняетdshVersion(из опций илиprocess.env.DSH_VERSION) иpluginVersion, и вызывается при записиmarker.jsonдля фиксации точных версий среды выполнения, создавших маркер. - Доставка отчёта после перезапуска для primary-сессии (#19):
resolveAgent()теперь корректно обращается кctx.agents.roots()[0]илиctx.agents.list()[0], когдаtarget: 'primary'илиsessionIdпуст, обеспечивая доставку вердикта и контекста возобновления работы. - Сохранение intent без идентификатора сессии (#20):
intentState()теперь сохраняет intent с записаннымиreasonилиresume, даже еслиsessionIdвызывающей стороны не был определён, и очищаетintent.jsonпосле доставки. - Безопасные retry-тики доставки (#21): таймерные тики и вызовы доставки агенту обёрнуты в
try/catchс логированием предупреждений, что исключает сбои фонового таймера из-за необработанных исключений. - Защита бюджета перезапусков loop guard (#22):
history.jsonтеперь фиксирует метки времени только при реальном перезапуске (boot.wasRestart === true), не сжигая бюджет при холодных стартах или перезагрузках плагина. - Очистка таймера в probe() (#23): проверки здоровья
probe()теперь регистрируют таймеры черезsafeSetTimeout()и сбрасывают их по завершении проверки, устраняя утечки таймеров в event loop.
Проверка
npm test: 30/30 пройдено.dsh-plugin-preflight: FAIL=0, WARN=3.- Проверено на DSH v0.2.0-rc.2 (изолированный тестовый контур и продакшн).
v0.1.6 [DSH v0.2.0-rc.2]
English
Fixed
- Settings unwrapping order (Unwrap -> Validate -> Unwrap):
apply()now unwrapsrawConfigbeforeConfig()schema validation and unwraps the result:plainConfig(Config(plainConfig(rawConfig || {}))). This preventsVolatilebox copy failures or fallbacks to schema defaults when the loader supplies pre-boxed configs. - Unified settings namespace in client seat registration:
plugins.itemseat registration now uses the bare host-plane namespaceid: NS(goodandready-smart-restart), matchingcordis.patch.ymland preventing composite<package>#<row>mismatches. - Config form scope error logging: Eliminated silent empty catch block during client-side config forms / settings scope resolution; errors are now logged via
ctx.logger.warn.
Verification
npm test: 25/25 pass.dsh-plugin-preflight: FAIL=0, WARN=3.- Verified on DSH v0.2.0-rc.2 (isolated test contour & production contour).
中文
修复
- 设置解包顺序 (Unwrap -> Validate -> Unwrap):
apply()现在在Config()模式验证之前解包rawConfig,并解包返回结果:plainConfig(Config(plainConfig(rawConfig || {})))。避免加载器提供预装箱配置时Volatile复制失败或回退到模式默认值。 - 客户端插件槽位注册中的统一设置命名空间:
plugins.item槽位注册现在使用裸主机平面命名空间id: NS(goodandready-smart-restart),与cordis.patch.yml保持一致,防止复合键不匹配。 - 配置表单作用域错误日志:消除了客户端配置表单/设置作用域解析期间的静默空 catch 块;错误现在通过
ctx.logger.warn记录。
验证
npm test:25/25 通过。dsh-plugin-preflight:FAIL=0, WARN=3。- 已在 DSH v0.2.0-rc.2(隔离测试环境和生产环境)上验证。
Русский
Исправлено
- Порядок распаковки настроек (Unwrap -> Validate -> Unwrap):
apply()теперь распаковываетrawConfigдо вызова валидации схемыConfig(), а затем распаковывает результат:plainConfig(Config(plainConfig(rawConfig || {}))). Это предотвращает сбои при копировании боксовVolatileи исключает скрытый откат настроек к дефолтным значениям. - Единый namespace настроек в регистрации клиентского слота: регистрация слота
plugins.itemтеперь использует канонический хостовыйid: NS(goodandready-smart-restart), совпадающий сcordis.patch.yml, исключая несовпадение составного ключа. - Логирование ошибок резолва скоупа: устранен пустой блок
catch (_) {}при резолвеconfigForms/settingsScope, добавлено логированиеctx.logger.warn.
Верификация
npm test: 25/25 успешно.dsh-plugin-preflight: FAIL=0, WARN=3.- Проверено на DSH v0.2.0-rc.2 (изолированный тестовый сервер и боевой контур).