Просмотр исходного кода

feat(windows-ops): Refactor safe-disable-startup -List onto design system

First per-script refactor onto the Terminal Panel Design System.
safe-disable-startup -List now renders as a proper claude-mods panel:
brand chrome, summary line, state-grouped sections (active /
disabled / unknown), inline alerts on corrupt StartupApproved entries,
footer with hotkeys + health indicator.

Also brings the spec + sibling implementations into sync:
- skills/_lib/term.sh TERM_BRAND gains 'windows-ops=🩺|[H]' entry
- docs/TERMINAL-DESIGN.md § 3.2 brand registry table updated
- docs/TERMINAL-DESIGN.md § 9 'Implementation' section renamed to
  'three siblings of the same spec' acknowledging term.sh +
  term.ps1 + Python sibling implementations, with cross-language
  registry-sync discipline noted.

JSON output path (-Json switch) untouched and verified unchanged —
the refactor only touched the human-rendering branch.

Dogfooded against current machine state (22 startup entries across
HKCU/HKLM/WOW64/StartupFolder): renders cleanly with proper grid
alignment, ellipsis-truncates long Comet updater entry name, and
flags the Docker Desktop unknown(0x00) state with an inline alert.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
0xDarkMatter 2 недель назад
Родитель
Сommit
014935280e
3 измененных файлов с 94 добавлено и 17 удалено
  1. 29 10
      docs/TERMINAL-DESIGN.md
  2. 1 0
      skills/_lib/term.sh
  3. 64 7
      skills/windows-ops/scripts/safe-disable-startup.ps1

+ 29 - 10
docs/TERMINAL-DESIGN.md

@@ -101,14 +101,15 @@ Default width: **10 pips** = clean 10% increments. Override only when the data h
 
 #### Brand emoji registry
 
-| Tool   | Unicode | ASCII |
-| ------ | ------- | ----- |
-| fleet  | ⚡       | `[F]` |
-| forge  | 🔨       | `[B]` |
-| psql   | 🐘       | `[P]` |
-| watch  | 📡       | `[M]` |
-| deploy | 🚀       | `[D]` |
-| git    | 🌿       | `[G]` |
+| Tool         | Unicode | ASCII |
+| ------------ | ------- | ----- |
+| fleet        | ⚡       | `[F]` |
+| forge        | 🔨       | `[B]` |
+| psql         | 🐘       | `[P]` |
+| watch        | 📡       | `[M]` |
+| deploy       | 🚀       | `[D]` |
+| git          | 🌿       | `[G]` |
+| windows-ops  | 🩺       | `[H]` |
 
 #### Header indicators
 
@@ -703,9 +704,19 @@ Color map:
 
 ---
 
-## 9. Implementation — `skills/_lib/term.sh`
+## 9. Implementation — three siblings of the same spec
 
-The library is the single source of truth. Skills source it; nothing else needs to know about glyphs or colors.
+This spec is the single source of truth. Three implementations conform to it, one per language family used in the claude-mods toolkit:
+
+| Implementation | Location | Consumers |
+|----------------|----------|-----------|
+| **Bash** | `skills/_lib/term.sh` | `fleet-ops`, any future bash-based skill |
+| **PowerShell** | `skills/_lib/term.ps1` | `windows-ops`, any future PowerShell skill |
+| **Python** | inline `Term` class + module functions in each Python skill | `summon`, any future Python skill |
+
+When extending the registries (new brand emoji, new health state, new diagram icon) update all three. The bash + PowerShell ports share variable names directly (`TERM_BRAND` / `$Script:TermBrand`); the Python implementations carry their own lookup tables but the keys must match.
+
+### Bash usage
 
 ```bash
 LIB="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../_lib" && pwd)"
@@ -713,6 +724,14 @@ LIB="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../_lib" && pwd)"
 term_init
 ```
 
+### PowerShell usage
+
+```powershell
+$LibDir = Join-Path $PSScriptRoot '..\..\_lib'
+. (Join-Path $LibDir 'term.ps1')
+Initialize-Term
+```
+
 ### Helpers
 
 ```bash

+ 1 - 0
skills/_lib/term.sh

@@ -56,6 +56,7 @@ declare -A TERM_BRAND=(
   [watch]="📡|[M]"
   [deploy]="🚀|[D]"
   [git]="🌿|[G]"
+  [windows-ops]="🩺|[H]"
 )
 
 declare -A TERM_HEALTH_GLYPH=(

+ 64 - 7
skills/windows-ops/scripts/safe-disable-startup.ps1

@@ -63,6 +63,8 @@ param(
 
 $ErrorActionPreference = 'Stop'
 . "$PSScriptRoot\_lib\common.ps1"
+. (Join-Path $PSScriptRoot '..\..\_lib\term.ps1')
+Initialize-Term
 
 # Map: registry path -> StartupApproved variant for the overlay
 $pathVariantMap = @(
@@ -123,22 +125,77 @@ function Get-CurrentState {
 # ─────────────────────────────────────────────────────────────────────
 if ($List) {
     $allEntries = Get-RunEntries
-    foreach ($e in $allEntries) {
+    $rows = foreach ($e in $allEntries) {
         $state = Get-CurrentState -EntryName $e.Name -Variant $e.Variant
-        $row = [PSCustomObject]@{
+        [PSCustomObject]@{
             Name    = $e.Name
             State   = $state
             Variant = $e.Variant
             Source  = (Split-Path $e.Path -Leaf) + '\' + (Split-Path $e.Path -Parent | Split-Path -Leaf)
             Command = $e.Command -replace '"',''
         }
-        if ($Json) {
-            [Console]::Out.WriteLine(($row | ConvertTo-Json -Compress))
-        } else {
-            $tag = switch ($state) { 'disabled' {'[X]'} 'enabled' {'[ ]'} default {'[?]'} }
-            [Console]::Out.WriteLine(("{0} {1,-40} {2,-7} {3}" -f $tag, $e.Name.Substring(0, [Math]::Min(40, $e.Name.Length)), $state, $e.Variant))
+    }
+
+    if ($Json) {
+        foreach ($r in $rows) {
+            [Console]::Out.WriteLine(($r | ConvertTo-Json -Compress))
+        }
+        exit $script:EXIT_OK
+    }
+
+    # Group by state for the panel
+    $enabled  = $rows | Where-Object { $_.State -eq 'enabled' -or $_.State -eq 'unmanaged' }
+    $disabled = $rows | Where-Object { $_.State -eq 'disabled' }
+    $unknown  = $rows | Where-Object { $_.State -ne 'enabled' -and $_.State -ne 'unmanaged' -and $_.State -ne 'disabled' }
+
+    Write-TermLine (New-TermPanelOpen -Brand 'windows-ops' -Name 'windows-ops' -Subtitle 'safe-disable-startup' -Indicator "$($rows.Count) entries")
+    Write-TermLine (New-TermPanelVert)
+    $summary = "$($enabled.Count) active · $($disabled.Count) disabled"
+    if ($unknown.Count -gt 0) { $summary += " · $($unknown.Count) unknown" }
+    Write-TermLine (New-TermSummary -Text $summary)
+    Write-TermLine (New-TermPanelVert)
+
+    if ($enabled) {
+        Write-TermLine (New-TermSection -State 'PASS' -Label 'active' -Count $enabled.Count)
+        $last = $enabled[-1]
+        foreach ($e in $enabled) {
+            $variant = switch ($e.Variant) { 'Run' { 'HKCU/HKLM' } 'Run32' { 'WOW64' } 'StartupFolder' { 'startup folder' } default { $e.Variant } }
+            Write-TermLine (New-TermLeaf -Name $e.Name -Meta $variant -IsLast:($e -eq $last))
         }
+        Write-TermLine (New-TermPanelVert)
     }
+
+    if ($disabled) {
+        Write-TermLine (New-TermSection -State 'WARN' -Label 'disabled' -Count $disabled.Count)
+        $last = $disabled[-1]
+        foreach ($e in $disabled) {
+            $variant = switch ($e.Variant) { 'Run' { 'HKCU/HKLM' } 'Run32' { 'WOW64' } 'StartupFolder' { 'startup folder' } default { $e.Variant } }
+            Write-TermLine (New-TermLeaf -Name $e.Name -Meta $variant -IsLast:($e -eq $last))
+        }
+        Write-TermLine (New-TermPanelVert)
+    }
+
+    if ($unknown) {
+        Write-TermLine (New-TermSection -State 'FAILING' -Label 'unknown state' -Count $unknown.Count)
+        $last = $unknown[-1]
+        foreach ($e in $unknown) {
+            $variant = switch ($e.Variant) { 'Run' { 'HKCU/HKLM' } 'Run32' { 'WOW64' } 'StartupFolder' { 'startup folder' } default { $e.Variant } }
+            Write-TermLine (New-TermLeaf -Name $e.Name -Meta $variant -Age $e.State -IsLast:($e -eq $last))
+            Write-TermLine (New-TermAlert -Severity warning -Text 'partial/corrupt StartupApproved entry — verify with Task Manager')
+        }
+        Write-TermLine (New-TermPanelVert)
+    }
+
+    $hk = @(
+        (New-TermHotkey -Key 'E' -Verb 'enable')
+        (New-TermHotkey -Key 'D' -Verb 'disable')
+        (New-TermHotkey -Key '?' -Verb 'help')
+    ) | Join-TermHotkeys
+    $hl = @(
+        (New-TermHealth -State 'healthy' -Text "$($enabled.Count) active")
+    ) | Join-TermHealths
+    Write-TermLine (New-TermPanelClose -Hotkeys $hk -Healths $hl)
+
     exit $script:EXIT_OK
 }