feat: add generic deployment recovery and engine lifecycle - #100
feat: add generic deployment recovery and engine lifecycle#100qinyue0508-cmd wants to merge 75 commits into
Conversation
Windows 11 24H2+ removes the legacy wmic CLI, so CPU/RAM detection on modern Windows returned an empty model and zero RAM. AMD GPUs were also invisible on Windows: the probe chain only knows nvidia-smi/rocm-smi and the sysfs fallback is Linux-only, so AMD APU hosts (Ryzen AI Max+ "Strix Halo") detected no accelerator at all. Replace wmic with `powershell Get-CimInstance` for CPU, RAM, pagefile and CPU load, and add a Windows Win32_VideoController GPU fallback wired into detectGPU through a detectPlatformGPU hook (no-op on non-Windows). AMD identity (name/gfx/arch/unified) is resolved from the PCI device ID via the existing amdPCIToInfo, shared with the Linux sysfs path. CIM cannot report true APU VRAM (Win32 AdapterRAM saturates at 4 GiB) or GPU utilization, so VRAM falls back to OS-visible RAM via the existing unified-memory backfill; exact carve-out still needs amd-smi/rocm-smi. Pure CIM JSON parsers live in cim.go (no build tags) with table-driven tests in cim_test.go using fixtures captured from a real Strix Halo box. Verified on AMD Ryzen AI Max+ 395 (Radeon 8060S, gfx1151): hal detect now reports the GPU (RDNA3.5, driver 32.0.31007.1017), CPU model + 16c/32t, and 32 GB RAM. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
On Strix Halo and similar unified-memory APUs, Windows exposes only a fraction of physical memory to the OS (e.g. 32 GiB of 128 GiB) — the rest is carved out for the iGPU. TotalVisibleMemorySize therefore undersold a 128 GiB box as 32 GiB, which also flowed into the unified-VRAM backfill and the onboarding "统一内存" card. Query Win32_PhysicalMemory (sum of DIMM capacity) and use it as RAM.TotalMiB when it exceeds the OS-visible total; recompute AvailableMiB as total - OS-used so it stays correct for both unified and conventional hosts. Tests (cim_test.go, build-tag-free): parse the Measure-Object Sum JSON; override to 128 GiB on a Strix Halo fixture; no-shrink / no-op on conventional hosts. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
On Strix Halo, Win32 AdapterRAM saturates at 4 GiB and there is no rocm-smi, so the unified-memory backfill set GPU.VRAMMiB = installed RAM (128 GiB). But the OS carves that 128 GiB pool — only ~110 GiB is GPU-addressable (dedicated VRAM + GTT) — so deploy-fit over-stated usable VRAM and could accept a model the iGPU cannot hold. When the AMD iGPU's VRAM is unknown, query the ROCm-capable llama.cpp engine's own `--list-devices` (preferring AIMA_ENGINE_DIR, else PATH) and use its reported device memory (e.g. "ROCm0: ... (110456 MiB, ...)") as GPU.VRAMMiB. Installed RAM — and thus the normalized "unified memory" the UI shows — is unchanged; only the fit-relevant usable VRAM is corrected. Tests (cim_test.go, build-tag-free): parseLlamaROCmVRAMMiB extracts the device total and ignores non-device output. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
On Windows the model scanner only looked at %USERPROFILE% directories, so models on other drives (D:\models, D:\lmstudio\models, ...) were never found and users had to set AIMA_MODEL_DIR by hand. Split GGUF shards were each registered as a separate model, and mmproj projector files showed up as standalone models — both break one-click deploy from the Web UI (a user clicking a single shard would fail to load the model). Scan discovery: - enumerate fixed/removable drives and probe conventional model dirs that exist (<drive>:\models, <drive>:\lmstudio\models, .ollama, HF hub). This stays targeted — it never walks whole drives, so recycle bins and system folders are not pulled in. - AIMA_MODEL_DIR now accepts a list (os.PathListSeparator) for custom dirs. - honor HF_HOME / OLLAMA_MODELS for relocated caches. - harden scanner.yaml skip list ($recycle.bin, system volume information, node_modules, .git, ...) so even an explicit drive-root scan stays clean. GGUF grouping: - collapse "...-00001-of-000NN.gguf" shards into one logical model whose Path is the first shard (llama.cpp auto-loads the rest) and whose size is the sum of all parts — so deploy targets the whole model, not one piece. - drop mmproj projector files. The scanner already skips "mmproj" *dirs* (scanner.yaml); this covers the file-name form, so projectors no longer appear as deployable models. Pure logic (groupGGUFModels, dedupePaths, DefaultScanPaths multi-path) is table-driven tested. Verified on an AMD Strix Halo Windows box: a clean scan now yields 22 grouped models across D:\model, D:\models, D:\models-gguf and D:\lmstudio (drive auto-probe found the latter two on its own), with no shards-as-models, no mmproj, and no recycle/tooling junk. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Engine scan only looked in ~/.aima/dist/{os-arch}/ and PATH for native
engine binaries, so engines installed in arbitrary dirs off the system
drive (e.g. Windows D:\tools\llama-b9180-win-hip-radeon-x64\llama-server.exe)
were invisible and `aima engine scan` returned [].
Add ScanOptions.ExtraDirs, fed from a new AIMA_ENGINE_DIR OS-path-list env
var (mirrors AIMA_MODEL_DIR), and extract scanDirForEngineBinaries so
distDir / extra dirs / PATH share one scan path with consistent dedup and
ID semantics. Once discovered, the existing local-engine overlay reinjects
the binary path as a preinstalled probe, so native deploy resolves the
absolute binary with no further changes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
On the AMD Strix Halo (Radeon 8060S iGPU) rig, scanned on-disk GGUF model names (e.g. Qwen3.5-9B-Q4_K_M) did not match catalog metadata.name, so deploy fell back to auto-detect instead of the curated config. Add metadata.aliases so the local scanner matches, and record llama.cpp b9180 HIP verified decode perf (all 999 layers offloaded, Q4_K_M): qwen3.5-9b 33.8 tok/s (alias only; llamacpp variant already present) qwen3.5-27b 11.7 tok/s (added universal llamacpp variant + GGUF source) glm-4.7-flash 58.9 tok/s (added universal llamacpp variant + GGUF source) qwen3.5-35b-a3b 63.0 tok/s (alias + verified perf; variant already present) New llamacpp variants use gpu_arch "*" so they apply on any device (GGUF is the path for low-VRAM hardware). No Go changes — knowledge-only (INV-1/2). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
AIMA's model scanner lists every weight artifact on disk as an independently deployable model. Speculative draft heads (DFlash / MTP) only make sense paired with their parent model for speculative decoding, yet they showed up as standalone models with a deploy button (e.g. Qwen3.6-35B-A3B-DFlash, Qwen3.6-35B-A3B-DFlash-Q4_K_M). The catalog already names each draft via its parent variant's speculative_config.model, so detection needs no new per-model YAML: - knowledge.NormalizeModelKey: lowercases a model name and strips quantization/precision/layout suffixes (q4_k_m, bf16, ud, unfused, ...) while keeping role tokens like "dflash", so all on-disk artifacts of one logical draft share a key and stay distinct from the parent. - Catalog.SpeculativeDraftModelKeys: harvests speculative_config.model across all variants into a set of normalized draft keys. - annotateModelsFromCatalog: a scanned model whose normalized name is a draft key gets standalone_deploy=false + ui.role=draft (only when not already set); the embedded UI already hides the deploy button on standalone_deploy=false. Knowledge-driven (INV-1/2): no hardcoded model names, derived entirely from the catalog. Parent models and quantization variants are unaffected, and DB rows / deploy-by-name paths are untouched (annotation is applied at model.list time only). Tests: NormalizeModelKey table cases (incl. "glm-4.7-flash" not stripped), SpeculativeDraftModelKeys harvest + nil-catalog, and the annotate wiring (drafts -> non-standalone draft, parent stays deployable). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…services The external-service scanner probes a fixed port list that includes 8080 — llama.cpp's default port — which AIMA's own native deployments also bind. So a model AIMA deployed itself (e.g. Qwen3.6-27B-Q4_K_M on 127.0.0.1:8080) was also surfaced under "external services" as importable, and importing it would register a self-referential backend. Exclude any scanned/persisted service whose host:port matches an AIMA-owned (non-external) proxy backend: - normalizeHostPort: reduce a base URL/address to a comparable host:port, folding localhost/::1/0.0.0.0 to 127.0.0.1. - Reconciler.ownDeploymentAddrs: host:port set of non-external proxy backends. - Scan skips own-deployment addresses (no upsert); List filters them out so a previously-recorded self entry disappears too. Tests: normalizeHostPort table; List excludes the own :8080 deployment while a genuine external service (ollama :11434) is kept. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A scanned (auto-discovered) external service was upserted when found but never reconciled away when it disappeared. So after a model was undeployed and its backend (e.g. native llama.cpp on :8080) stopped, the dead service lingered as a stale "reachable" row and kept showing under external services. On each scan, mark previously-discovered scanned (non-imported, non-own) services that are no longer reachable as unreachable; List now hides scanned, non-imported, unreachable services. Imported services are untouched (they still show, with their status, by user intent). Tests: staleScannedAddrs (skips imported / already-unreachable / own deployments); List hides a vanished scanned :8080 while keeping a reachable :11434 and an offline imported :9000. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Prebuilt aima-windows-amd64.exe + serve.bat + handoff README for collaborator R&D, on the develop + #78-#83 integration (Strix Halo hardware detection, model/ engine scan, draft-head + external-service n_guan, OpenClaw local-model sync). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…Halo On a no-NVIDIA AMD Windows box (Ryzen AI Max+ 395 / Radeon 8060S, RDNA3.5), the only catalog llama.cpp source for windows/amd64 was the CUDA build, which runs CPU-only there; the AMD engines (llamacpp-vulkan / llamacpp-rocm-rdna3) are linux-only. So out-of-the-box auto-download fetched the wrong (CUDA) build and users had to manually install a ROCm/HIP llama.cpp and point AIMA_ENGINE_DIR at it. Add a native engine asset `llamacpp-hip-windows` (gpu_arch RDNA3.5, windows/amd64, source = official llama.cpp `win-hip-radeon-x64.zip`, version b9330). The native engine resolver already skips engines whose source has no binary for the host platform, so on RDNA3.5+Windows this exact-arch, windows-supported asset is selected over the linux-only vulkan asset and the NVIDIA-only universal CUDA source — making `aima deploy <model>` auto-download the right ROCm/HIP build with no AIMA_ENGINE_DIR. Knowledge-only, no Go changes (INV-1). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The engine scanner discovers native binaries in AIMA_ENGINE_DIR, but native
deploy resolved the binary only via dist → BinarySource probe/download → PATH.
When a pre-installed engine was registered via AIMA_ENGINE_DIR but not in dist
or PATH, and the catalog probe-path injection didn't reach the resolved engine
asset (e.g. AMD-Windows, where gpu_arch matching picks a linux-only asset), the
launch command fell back to the bare name ("llama-server") and Windows reported
"'llama-server' is not recognized" — so a model that scanned fine could not be
deployed.
Resolve the native binary against AIMA_ENGINE_DIR too — the SAME dirs the engine
scanner reads — so "scanned ⇒ launchable" holds regardless of catalog/overlay
engine selection. Order: dist → AIMA_ENGINE_DIR → auto-download → PATH. No-op when
AIMA_ENGINE_DIR is unset, so other devices/runtimes are unaffected.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The dist exe filename now carries its version string so a new build does NOT
overwrite the previous one in place. Two builds coexist:
aima-windows-amd64-v0.5-dev-amd-strix-halo-20260610.exe -> v0.5-dev-amd-strix-halo-20260610
latest; adds the out-of-box AMD-HIP llama.cpp engine (#85, #86). serve.bat uses this.
aima-windows-amd64-v0.5-dev-amd-strix-halo.exe -> v0.5-dev-amd-strix-halo
restored 2026-06-09 build (#78-#83 only, no HIP auto-download). Kept for rollback.
Both from source commit fc3ef41; filename == the exe's own `aima version` string.
- #85 llamacpp-hip-windows engine asset (go:embed'd into the exe + in source at
catalog/engines/llamacpp-hip-windows.yaml, pins official b9330 win-hip-radeon-x64):
a no-NVIDIA Strix Halo box auto-downloads the right ROCm/HIP llama.cpp instead of
the CPU-only CUDA universal source.
- #86 native runtime resolves the engine binary against AIMA_ENGINE_DIR
(dist -> AIMA_ENGINE_DIR -> auto-download -> PATH), so a pre-installed llama.cpp
of ANY version is launchable -- the partner's llama.cpp version is supported
whether or not it matches the bundled b9330.
Verified the latest build on the 395 rig: `aima version` ->
v0.5-dev-amd-strix-halo-20260610 / fc3ef41; `aima engine info llamacpp-hip-windows`
-> b9330 asset; `aima hal detect` -> RDNA3.5 gfx1151, ~110 GB VRAM.
README + serve.bat updated (build table; AIMA_ENGINE_DIR now optional).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…' into amd395-win
…-window' into amd395-win
…ge' into amd395-win
…ht' into amd395-win
) New version-stamped build aima-windows-amd64-v0.5-dev-amd-strix-halo-20260612.exe (source commit fa35aa4) on top of the HIP-engine build. Adds, vs the 20260610 exe: #87 native deploy readiness uses the real runtime name (no false "not ready") #88 deploy launcher hidden (no cmd.exe console popup) via VBS launcher #89 Qwen2.5-VL-3B-Instruct catalog knowledge (vlm + aliases + verified perf) #90 zero-config vision: llama.cpp --mmproj auto-wired for VL gguf models #91 openclaw sync preflight-probes :6188 and warns loudly when unreachable serve.bat now points at the 20260612 exe; older builds kept for rollback. README build table + fixes list + OpenClaw data-plane guidance updated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…text A high catalog/user ctx_size (e.g. the 128000 default we now want for agent clients) would OOM llama-server at load on memory-constrained machines — AIMA previously passed ctx_size through unchanged (estimateVRAM ignores the KV cache; CheckFit only adjusts vLLM/SGLang gpu_memory_utilization, never llama.cpp ctx). On deploy, for llama.cpp GGUF models, size the context to the hardware: - Read the model's real architecture from the GGUF header (new model.ReadKVArch: block_count / head_count_kv / head_dim / context_length) and compute exact f16 KV bytes/token — not a guess. - Clamp ctx_size down so weights + projector + KV cache fit usable memory (GPU VRAM for discrete GPUs, RAM minus an OS reserve for unified/CPU hosts), and cap it at the model's trained context. Only ever lowers; never raises. - Graceful no-op when the GGUF arch can't be read or memory is unknown. So a high default degrades gracefully: big boxes get the full context, small ones auto-shrink to what fits instead of failing. Bump Qwen2.5-VL-3B default ctx_size to 128000 (its trained max) now that it's memory-safe; the agent floor (~9.3K of MCP tool schemas) always fits where the model fits. clampContextForMemory / usableMemoryMiB are pure and unit-tested; verified on the Strix Halo rig (request 200000 → clamped to trained 128000). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…K default New version-stamped build aima-windows-amd64-v0.5-dev-amd-strix-halo-20260615.exe (source commit 88ef097) on top of the 20260612 build. Adds: - Hardware-aware ctx_size clamping: reads the GGUF arch and fits the context to memory (weights + projector + KV) and the trained limit, only lowering it. - Qwen2.5-VL-3B default ctx_size 8192 -> 128000, now memory-safe everywhere: big boxes get 128K, constrained boxes auto-shrink instead of OOM-ing. Fixes OpenClaw agent "context overflow" (its MCP-tool-schema prompt exceeds 8192). serve.bat points at the 20260615 exe; older builds kept for rollback. README build table + fixes list + rebuild note updated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…en3-Embedding-4B Set each model's catalog default ctx_size to its full trained context (verified loading + serving on the Strix Halo iGPU, 2026-06-16): - glm-4.7-flash llamacpp variant: ctx_size 8192 -> 202752. - qwen3.6-35b-a3b: add a universal llamacpp GGUF variant (ctx_size 262144) + gguf source + scan-name aliases (Qwen3.6-35B-A3B-UD-Q4_K_M, qwen3.6-35b-a3b-q4_k_m); it previously had only vLLM/Blackwell variants. - new qwen3-embedding-4b.yaml: type embedding, llamacpp variant with embedding=true (-> llama-server --embedding) + ctx_size 40960; serves /v1/embeddings (2560-dim). Deploy-only — embedding models are not written into OpenClaw config by sync. These large ctx defaults are memory-safe via the deploy-time auto-clamp. Also fix usableMemoryMiB to prefer GPU VRAM over system RAM: an all-offloaded llama.cpp model is bounded by GPU memory, and on unified-memory APUs the OS-visible RAM is under-reported (Strix Halo: ~32GB OS vs ~110GB iGPU). The clamp now uses the iGPU pool, so it won't wrongly shrink contexts on such APUs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… fix New aima-windows-amd64-v0.5-dev-amd-strix-halo-20260616.exe (source 80c7216). Adds the verified catalog context windows (GLM-4.7-Flash 202752, Qwen3.6-35B-A3B 262144 with a new llama.cpp variant + aliases, new Qwen3-Embedding-4B in --embedding mode), and the auto-clamp now sizes against the iGPU memory pool instead of under-reported APU system RAM. serve.bat -> 20260616; older builds kept for rollback. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… (env) Two product-level controls so a partner integrating AIMA owns OpenClaw behavior without code changes on their side (both honor CLI sync AND the serve auto-sync loop): - AIMA_OPENCLAW_SET_DEFAULT=false — register the AIMA provider + models but do NOT set OpenClaw's primary/default chat model (leave the user's current primary alone). Unset = previous behavior (AIMA sets it). Threaded as Deps.SetDefaultModel *bool → SyncResult.SkipDefaultModel → mergeChatModelDefault early-returns (preserving prior ownership record so toggling back on works). - AIMA_OPENCLAW_CONFIG=<path>/openclaw.json — write to a custom config dir (e.g. a partner using .byClaw instead of .openclaw). Skills, extensions and managed-state all follow filepath.Dir(ConfigPath), so the whole set relocates. This is purely AIMA-side and independent of the OpenClaw/byClaw product's own layout. Verified on the Strix Halo rig: SET_DEFAULT=false → provider written, primary empty; default → primary set; custom config dir → config+skills land under .byClaw. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…lt + config dir) The 2026-06-16 build now also carries AIMA_OPENCLAW_SET_DEFAULT and AIMA_OPENCLAW_CONFIG (partner-controllable primary-model + custom config dir). Same version-stamped filename; README rebuild note updated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…w sync controls) Q&A capturing this round's partner requests and how each is handled: the four model context windows (tested + yaml'd), embedding-not-synced, AIMA_OPENCLAW_SET_DEFAULT, historical-service-info read paths, and AIMA_OPENCLAW_CONFIG custom dir. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…alog-miss fix) Committing pre-existing uncommitted work from the 2026-06-18 round on this build box (issues 4 & 5 of the integration list), verified building + tests passing: - Issue 4 / B2 — engine image registry via env: AIMA_ENGINE_REGISTRIES / AIMA_ENGINE_REGISTRY merged into resolved registries (engineRegistriesWithEnv), native binary mirror/registry resolution in internal/engine/binary.go, + tests. - Issue 5 / A2 — multi-model OpenClaw sync: models absent from the catalog (no type) were skipped by sync; now fall back to the backend-reported model type so every deployed provider syncs (TestSyncUsesBackendModelTypeWhenCatalogMisses); drop the canManageChatModelDefault guard so the synced model is set as default. Also includes the round's dist artifacts (20260618 exe + P0 assessment doc). Preserved as-is before layering the 2026-06-22 A-item fixes on top. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ch, A6 undeploy hint A1 (P0) — deploy canonicalizes the model name (alias "Qwen2.5-VL-3B-Instruct-Q4_K_M" → "qwen2.5-vl-3b-instruct"), so undeploy/status/logs with the original alias failed to match. Add canonicalModelAlt(cat, name) and retry undeploy/status/logs with the canonical name; surface the original via a requested_model field in deploy results. A5 — make the serve OpenClaw auto-sync loop switchable: `aima serve --no-openclaw-sync` or AIMA_OPENCLAW_SYNC=manual|off|false|0|no disables it (sync then only on explicit `aima openclaw sync`). Default unchanged (auto). A6 — undeploy now prints a hint that model files are kept and how to free disk (`aima model remove --delete-files <name>`); undeploy semantics unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New aima-windows-amd64-v0.5-dev-amd-strix-halo-20260623.exe (source 88b83b5) with the 2026-06-22 doc's A-item fixes: A1 undeploy/status/logs by original name, A5 --no-openclaw-sync / AIMA_OPENCLAW_SYNC switch, A6 undeploy disk-cleanup hint. Adds AIMA集成问题-解决说明-20260623.md (per-item solution guide incl. A3 AIMA_MODEL_DIR multi-dir, A4 AIMA_ENGINE_DIR, A2/A7 status). serve.bat -> 20260623. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
rjckkkkk
left a comment
There was a problem hiding this comment.
结论:当前不能合并,请修改后重新请求 Review。
1. 先清理 PR 范围
当前分支相对 develop 落后 27 个提交、超前 75 个提交,PR 包含 161 个文件和约 2.1 万行新增,并带入 19 个 EXE(约 532 MiB)。这与本 PR 的“通用恢复和 Engine 生命周期”范围不相符。
请从最新 develop 新建干净分支,只迁移本功能相关提交(553324f、41ae8fd、07d34e5),移除旧 AMD395 历史提交、二进制和无关文档。建议进一步拆为两个 PR:
- Deployment Intent / Reconciler / Runtime recovery。
- Engine inventory / ensure / rollback / import。
不要让 develop 为旧分支倒退;冲突应在新功能分支适配最新 develop。
2. 必须修复的功能问题
-
Engine 激活/回滚没有真正控制后续部署。
cmd/aima/resolve.go:368-395从 inventory 选择第一个 available 记录,没有按Active、AssetName、platform、runtime 和 verification 状态筛选。engine.rollback可能显示成功,但新部署仍使用已停用的新版本。 -
Native 健康检查超时后可能永远停留在
starting。internal/runtime/native.go:345-348, 722-723, 790-826没有把健康超时记录为 failed/stalled;internal/recovery/state_machine.go:80-82又明确忽略未 stalled 的 Native starting 状态,因此“不退出但永远不健康”的进程不会被恢复。 -
健康的 Docker/K3S 部署可能被误隔离。 新建/复用 Intent 时
ObservedRestartCount从 0 开始;internal/recovery/state_machine.go:62-78在检查 Ready 之前把累计历史重启数计入本窗口。一个当前健康、历史已有 3 次重启的容器,首次巡检就可能进入 quarantine 并被删除。 -
敏感配置会以字面值
[REDACTED]被回放。cmd/aima/tooldeps_deploy.go:1391-1403将脱敏值写入 Intent,cmd/aima/tooldeps_deploy.go:545-551恢复时又将该 map 作为真实 overrides 使用。带 token/API key 的部署会用错误凭据恢复并反复失败。敏感值应从安全来源重新解析;无法重新解析时应明确拒绝恢复。 -
Catalog 更新会破坏固定版本恢复。
cmd/aima/tooldeps_deploy.go:102-108只把 Intent 版本与当前 Catalog 版本比较;版本变化后直接失败,没有从 Engine inventory 定位 Intent 固定的旧版本。 -
新扫描的预装 Native Engine 无法进入 lifecycle。
cmd/aima/main.go:1132-1159未保存 active/verification 状态,存储后默认为 inactive/unverified;internal/engine/lifecycle.go:123-132会阻止复用,且当前没有完成验证并激活该记录的路径。 -
无可信摘要的 Native 离线包被标记为 verified。
cmd/aima/engine_lifecycle.go:439-446在 Catalog 没有 SHA256 时直接通过,随后302-318仅计算自身哈希就标记verified。自计算哈希不能证明包与预期资产一致。 -
隔离删除失败后不会重试。 quarantine delete 失败后 Intent 仍是 quarantined,但 quarantined Intent 被
internal/sqlite.go:1598-1601排除,后续控制循环不会再次执行删除。
3. 需要补充的回归测试
- ensure v2 → rollback v1 → 新部署实际使用 v1。
- Native 进程存活但健康检查超时后触发恢复。
- 健康容器带历史 restart count 时不会被误隔离。
- 带 API key/token 的恢复不会使用
[REDACTED]。 - Catalog 升级后仍能恢复 Intent 固定的旧 Engine 版本。
- 无可信 SHA256/digest 的离线导入不能进入 verified/active。
- quarantine 删除遇到瞬时失败后可重试,且不会重新部署。
4. 验证说明
当前 HEAD 上 go test ./...、go vet ./...、关键包 race 测试和四平台交叉构建均通过。但现有 GitHub 绿灯来自 amd395-win 的 push workflow,不是 PR 与最新 develop 的合并结果;上述端到端场景也没有被现有测试覆盖。
请完成范围清理、修复上述阻塞项,并在最新 develop 上通过合并结果 CI 后重新请求 Review。
Summary
Validation
go test ./... -count=1go test -race ./internal/recovery ./internal/runtime ./internal/engine ./internal/mcp ./internal/cli ./cmd/aima -count=1go vet ./...ready/healthy, responseAIMA_RECOVERY_OK@rjckkkkk please review.