Wave 5+6: plugin ABI hardening, build modernization, ABI/security docs
Some checks failed
CI / Determine matrix (push) Has been cancelled
CI / ${{ matrix.os }} / ${{ matrix.build_type }} (push) Has been cancelled

Wave 5 (9 parallel agents):
- W1.1 atomic diag callback + DLL handle release on shutdown (lin)
- W2.1 unify cross-DLL heap discipline (host->alloc/free/strdup) (chen)
- W2.2 secure_zero api_key on shutdown for deepseek/anthropic (cao)
- W3 CMake modernization: target-based cxx_std_20, dstalk_boost_config
  INTERFACE lib, root-level RUNTIME_OUTPUT_DIRECTORY (hu)
- W4 GitHub Actions CI with dynamic Linux/Windows matrix (ma)
- W5.1 SSE buffer_body to cut peak memory ~67% on 32K streams (zhou)
- W6.1 LSP JSON-RPC frame parser hardened against header reordering (sun)
- W7 smoke test: copy plugin DLLs post-build + Boost.JSON src.hpp fix
  for full 9-plugin load coverage (wang)
- W8.1 README slimmed 398->92, Diataxis docs/ skeleton (deng)

Wave 6 (6 parallel agents):
- W9.1 docs/explanation: architecture + plugin-lifecycle (deng)
- W9.3 log credential leak audit (0 vulns, audit trail in
  docs/explanation/security-logging.md) (cao)
- W9.4 docs/reference/plugin-abi.md - 7-point ABI contract (lin)
- W9.6 CLI /history command + status integration (zhao)
- W9.8 plugin_loader fault tolerance: per-plugin failure no longer
  aborts dstalk_init (huang)
- W9.10 host_api unit tests: tests/host_api_test.cpp, 8 cases (liu)

CEO oversight (preexisting bugs fixed during Wave 5 verification):
- lsp_plugin.cpp:449 forward decl mismatch (int vs void)
- tools_plugin.cpp:109 missing forward decl

Multi-agent collaboration framework:
- agents/WORKFLOW.md: 6-stage protocol, two-tier governance,
  prompt template, technical constraints registry

Build: cmake --build 0 error / 0 warning. Tests: 2/2 100% pass.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-05-27 05:39:10 +08:00
parent 4433218853
commit 5766938524
49 changed files with 1640 additions and 449 deletions

View File

@@ -9,8 +9,10 @@
#endif
#include <algorithm>
#include <cstdio>
#include <queue>
#include <stdexcept>
#include <unordered_set>
namespace dstalk {
@@ -199,9 +201,14 @@ std::vector<int> PluginLoader::topological_sort() const
int PluginLoader::initialize_all(const dstalk_host_api_t* host_api)
{
if (!host_api) return -1;
try {
std::vector<int> order = topological_sort();
std::unordered_set<std::string> failed_names;
int failed_count = 0;
for (int id : order) {
auto it = plugins_.find(id);
if (it == plugins_.end()) continue;
@@ -209,16 +216,40 @@ int PluginLoader::initialize_all(const dstalk_host_api_t* host_api)
PluginInfo& plugin = it->second;
if (plugin.initialized) continue;
// 检查依赖是否已失败
bool dep_unavailable = false;
for (const auto& dep_name : plugin.dependencies) {
if (failed_names.count(dep_name)) {
dep_unavailable = true;
break;
}
}
if (dep_unavailable) {
fprintf(stderr, "[WARN] Plugin '%s' skipped: dependency unavailable\n",
plugin.name.c_str());
failed_names.insert(plugin.name);
failed_count++;
continue;
}
if (plugin.info->on_init) {
int result = plugin.info->on_init(host_api);
if (result != 0) {
return -1;
fprintf(stderr, "[ERROR] Plugin '%s' init failed (code %d)\n",
plugin.name.c_str(), result);
failed_names.insert(plugin.name);
failed_count++;
continue; // 不设置 initialized=true
}
}
plugin.initialized = true;
}
return 0;
return failed_count;
} catch (const std::runtime_error&) {
// 循环依赖
return -1;
} catch (const std::exception&) {
return -1;
}
@@ -272,13 +303,24 @@ void PluginLoader::shutdown_all()
if (it == plugins_.end()) continue;
PluginInfo& plugin = it->second;
if (!plugin.initialized) continue;
if (plugin.info->on_shutdown) {
if (plugin.initialized && plugin.info->on_shutdown) {
plugin.info->on_shutdown();
}
plugin.initialized = false;
}
// 释放所有 DLL 句柄
for (auto& [id, plugin] : plugins_) {
if (plugin.handle) {
#ifdef _WIN32
FreeLibrary((HMODULE)plugin.handle);
#else
dlclose(plugin.handle);
#endif
plugin.handle = nullptr;
}
}
plugins_.clear();
}
const PluginInfo* PluginLoader::get_plugin(int plugin_id) const