下载位置透明 · 文件好管理 · 减少 C 盘垃圾 · 路径不可用时宁可阻止也不走 C 盘
Platform: Windows (PowerShell 5.1+)
curl / wget / Invoke-WebRequest / requests.get / urllib.requestnpm install -g (NOT local npm install without -g)pnpm add -g (v5.4)bun install -g (v5.4)pip install (NOT inside active venv — check VIRTUAL_ENV env var first)uv pip install (v5.4 — same venv rule applies)conda install / conda create / conda env updatecargo install (v5.4 — installs to ~/.cargo/bin)go install (v5.4 — installs to $GOPATH/bin)git clonehuggingface-cli download / modelscope download / ollama pulldocker pullwinget install / choco install / scoop installnpm install (writes to node_modules in cwd)pip install -e . (editable install)EXEMPT_PATHSpowershell
$configPath = "$env:USERPROFILE\.workbuddy\skills\download-guard\config.md"
$content = Get-Content $configPath -Raw -ErrorAction SilentlyContinue
$setupDone = $content -match "SETUP_DONE:\s*true"
$downloadRoot = if ($content -match "DOWNLOAD_ROOT:\s*(.+)") { $Matches[1].Trim() } else { "" }
If SETUP_DONE != true or DOWNLOAD_ROOT empty → run First-time Setup.
Config Integrity Check (v5.4): After reading, verify:
DOWNLOAD_ROOT value is non-empty and starts with a drive letter (e.g. D:\, F:\)SETUP_DONE is either true or false (not corrupted)CommandTypeActioncurl/wget/git clone/model downloadC (safe)Go to Step 2pip install (non-venv)B2Check site-packages locationpip install --user (v5.4)B2+Warn if site-packages on C: — suggest venvnpm install -g / pnpm add -gB1Check prefix + PATH + spacescargo install / go install (v5.4)B3Check binary dir in PATHChange npm prefix / conda envsBRun PATH linkage check
Type A = cache (safe to move), Type B = install dir (must sync PATH), Type C = file storage (safe). Details: see reference.md
Before downloading, check if file already exists in DOWNLOAD_ROOT:
powershell
$today = Get-Date -Format "yyyy-MM-dd"
$existing = Get-ChildItem "$downloadRoot\$today" -Recurse -Filter "*$FileNamePart*" -ErrorAction SilentlyContinue
If found → inform user: "⚠️ Similar file already exists: {path} ({size}). Download again? [y/N]"
Determine download subdirectory (default structure): text
DOWNLOAD_ROOT\YYYY-MM-DD\{sanitized-task-name}\
Rules for {sanitized-task-name}:
generalF:\AI-Downloads\2026-05-26\install-pandas\Run scripts/check-space.ps1 — now includes:
If download size is known (model cards, package metadata, etc.):
"This download ({X}GB) will use {Y}% of available space on {drive}:"Output to user:
text
[DOWNLOAD GUARD] 准备下载
文件 : {filename}
大小 : {known size / unknown}
写入至 : {DOWNLOAD_ROOT}\{YYYY-MM-DD}\{task-name}\
目标盘 : {X} GB 可用 [{OK/WARN/BLOCK}]
C 盘 : {X} GB 可用 [{OK/WARN}]
路径可用 : [{OK / DRIVE_MISSING / NOT_WRITABLE}]
继续执行...
check-space exit codeMeaningAction0OK or WARNProceed1Space too lowBlock, suggest cleanup2 (v5.4)Path unavailableBLOCK — do NOT fall back to C:
Verify the download landed where expected: powershell
Test-Path "{expected_path}"
(Get-Item "{expected_path}").Length
Run scripts/log-download.ps1 (includes auto-cleanup)
Output to user:
text
[DOWNLOAD GUARD] 完成
文件 : {filename} ({size})
位置 : {full path}
已记录 : download-log.md
If verification fails → warn: "⚠️ Downloaded file not found at expected path. Please check manually."
When the Agent writes to config.md, it MUST:
Read-back verify: After writing, re-read the file and confirm DOWNLOAD_ROOT and SETUP_DONE are present and valid
No partial writes: Write the complete file in one operation, never append/patch key fields
Backup on change: Before changing DOWNLOAD_ROOT, keep the previous value as a comment:
text
# PREVIOUS: DOWNLOAD_ROOT: E:\old-path
DOWNLOAD_ROOT: F:\new-path
If config is corrupted: The Agent should detect it (missing required fields, empty DOWNLOAD_ROOT, SETUP_DONE neither true nor false) and ask the user to re-configure
powershell
Get-PSDrive -PSProvider FileSystem |
Where-Object { $_.Free -gt 0 } |
Sort-Object Free -Descending |
ForEach-Object {
$tag = if ($_.Name -eq "C") { " [SYSTEM - NOT recommended]" } else { "" }
" {0}: {1} GB free{2}" -f $_.Name, [math]::Round($_.Free/1GB,1), $tag
}
Show user with recommended default (largest non-C drive):
text
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Download Guard · 首次配置
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
磁盘扫描结果:
F: 132 GB 可用 ← 推荐(空间最大)
E: 97 GB 可用
D: 39 GB 可用
C: 58 GB 可用 [系统盘 - 不推荐]
推荐:F:\AI-Downloads
确认?或输入其他路径:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
{letter}:\AI-Downloads, full path → use as-is)SETUP_DONE: false → true, DOWNLOAD_ROOT: → user choicescan-tool-cache.ps1text
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Download Guard · 环境就绪
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
下载目录 : {DOWNLOAD_ROOT}
可用空间 : {X} GB [{OK/WARN}]
路径可写 : {YES/NO}
C 盘 : {X} GB [{OK/WARN}]
npm cache : {path} [{OK/WARN}]
pip cache : {path} [{OK/WARN}]
npm prefix : {path} [IN PATH: {YES/NO}]
日志 : ~/.workbuddy/download-log.md
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
如有 [WARN],说"帮我修复"即可。
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
(See Step 2-4 in Execution Protocol above)
On the first trigger of each day, output an environment report. Implementation:
powershell
# Track last report date in a temp file
$lastReportFile = "$env:TEMP\download-guard-last-report.txt"
$today = Get-Date -Format "yyyy-MM-dd"
$lastReport = if (Test-Path $lastReportFile) { Get-Content $lastReportFile -Raw } else { "" }
if ($lastReport -ne $today) {
# This is the first trigger today — show environment report
Set-Content -Path $lastReportFile -Value $today -Force
# ... output report ...
}
Report format:
text
[DOWNLOAD GUARD] 今日首次 · 环境快报
下载目录 : {DOWNLOAD_ROOT} ({X} GB 可用)
路径可用 : {OK / DRIVE_MISSING / NOT_WRITABLE}
C 盘 : {X} GB 可用 [{OK/WARN}]
工具缓存 : {all OK / N items on C: [WARN]}
日志条数 : {N} 条
If path unavailable → immediately ask user to update config or reconnect drive.
ScenarioActionFirst setupMust askDaily downloadsDon't ask, just informTarget disk < MIN_FREE_GBMust inform — suggest switchingDOWNLOAD_ROOT drive missing (v5.4)Must inform — BLOCK until fixedDOWNLOAD_ROOT not writable (v5.4)Must inform — BLOCK until fixedC-drive cache foundMust inform — offer to migrateNew disk appearedMay inform — optionalUser asks "where to?"Answer — show current config
Rule: Only prompt on environment changes. Daily ops = inform only. Rule (v5.4): Path unavailable = always BLOCK, never silently fall back to C:.
ConditionActionEntry > LOG_RETENTION_DAYS oldAuto-archiveArchive > LOG_ARCHIVE_MAX_MBDelete oldest archiveLog file > 5MBTrigger archive rotation
Archive naming: ~/.workbuddy/download-log-archive-{YYYY-MM-DD}.md
Set LOG_RETENTION_DAYS: 0 to disable cleanup.
User saysAction"下载了什么" / "下载日志" / "download log"Show last 20 entries"缓存在哪" / "扫描缓存" / "scan cache"Run scan-tool-cache.ps1"迁移缓存" / "migrate cache"Run migrate-cache.ps1"磁盘空间" / "disk space"Run check-space.ps1"刚才下的在哪" / "where's my download"Show last log entry path"下载到哪" / "根目录在哪"Show DOWNLOAD_ROOT"npm 用不了" / "command not found"Check npm prefix in PATH"帮我修复" / "fix warnings"Auto-fix all [WARN] items"修改下载目录" / "change download dir"Update config.md DOWNLOAD_ROOT"清理日志" / "clean log"Trigger log archive cleanup"检查路径" / "check path" (v5.4)Verify DOWNLOAD_ROOT exists, writable, disk healthy"重置配置" / "reset config" (v5.4)Set SETUP_DONE: false, re-run setup"download guard version" / "下载版本" (v5.4)Show current version: 5.4.0"卸载 download guard" / "uninstall download guard"Show cleanup instructions (log files, archives, config)
For full details on path types, PATH fix templates, config params, scripts, and known limitations, see reference.md.