glove/tests/container/linux_managed_session_test.cpp
trvon 825a129fbd
feat(refinement): evaluate fixtures in sandbox
Model and PTY cannot self-report pass or failure. Glove now runs
each refinement-eval-v1 session through a declarative evaluator that
checks bounded fixture assertions (termination cause, exit code, max
latency, required and forbidden transcript literals) against audited
resource events, then binds the evaluated outcome inside the
authenticated receipt digest. Capability advances to version 1 with
the evaluator landed.
2026-07-31 16:07:43 -04:00

1085 lines
45 KiB
C++

#include "glove/container/digest.hpp"
#include "glove/container/profile.hpp"
#include "glove/container/receipt_chain.hpp"
#include "glove/container/receipt_producer.hpp"
#include "glove/supervisor/library_bundle.hpp"
#include "glove/supervisor/linux_session_filesystem.hpp"
#include "glove/supervisor/native_skill_runtime_adapter.hpp"
#include "glove/supervisor/path_alias.hpp"
#include "cgroup_v2.hpp"
#include "linux_managed_session.hpp"
#include "linux_resource_lifecycle.hpp"
#include <sys/stat.h>
#include <unistd.h>
#include <array>
#include <chrono>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <expected>
#include <filesystem>
#include <fstream>
#include <memory>
#include <span>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
namespace {
#define REQUIRE(cond) \
do { \
if (!(cond)) { \
std::fprintf(stderr, "REQUIRE failed: %s @ %s:%d\n", #cond, __FILE__, __LINE__); \
return 1; \
} \
} while (0)
using glove::container::profile;
using glove::container::resource_enforcement_receipt;
using glove::container::resource_limits;
using glove::container::resource_termination_cause;
using glove::container::linux_detail::cgroup_v2_root;
using glove::container::linux_detail::linux_resource_lifecycle;
using glove::supervisor::linux_detail::linux_session_filesystem;
constexpr std::string_view controller_plan_digest =
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
constexpr std::string_view audit_key =
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
struct requested_alias {
std::string alias;
std::filesystem::path source;
std::string target;
glove::supervisor::path_access access = glove::supervisor::path_access::ephemeral_write;
};
class temporary_tree {
public:
temporary_tree() {
std::string pattern = "/tmp/glove-managed-session-test-XXXXXX";
char* created = ::mkdtemp(pattern.data());
if (created != nullptr) {
root_ = created;
}
}
temporary_tree(const temporary_tree&) = delete;
auto operator=(const temporary_tree&) -> temporary_tree& = delete;
temporary_tree(temporary_tree&&) = delete;
auto operator=(temporary_tree&&) -> temporary_tree& = delete;
~temporary_tree() {
std::error_code error;
std::filesystem::remove_all(root_, error);
}
[[nodiscard]] auto root() const -> const std::filesystem::path& { return root_; }
private:
std::filesystem::path root_;
};
auto epoch_ms() -> std::uint64_t {
const auto now = std::chrono::system_clock::now().time_since_epoch();
return static_cast<std::uint64_t>(
std::chrono::duration_cast<std::chrono::milliseconds>(now).count()
);
}
auto policy_for(const requested_alias& requested, std::uint64_t quota)
-> glove::supervisor::path_alias_policy {
const bool read_only = requested.access == glove::supervisor::path_access::read;
return {
.alias = requested.alias,
.host_path = requested.source.string(),
.target_path = requested.target,
.max_ttl_secs = 300,
.access = {{
.access = requested.access,
.materialization = read_only ? glove::supervisor::path_materialization::bind
: glove::supervisor::path_materialization::copy,
.create_policy = read_only ? glove::supervisor::path_create_policy::never
: glove::supervisor::path_create_policy::empty_directory,
.cleanup_policy = read_only ? glove::supervisor::path_cleanup_policy::retain
: glove::supervisor::path_cleanup_policy::remove,
.max_bytes = read_only ? 0 : quota,
}},
};
}
auto make_lifecycle(
cgroup_v2_root& root,
const std::filesystem::path& materialization_root,
std::span<const requested_alias> requested_aliases,
std::string_view session_id,
const resource_limits& limits,
std::vector<glove::supervisor::resolved_library_projection>&& library_projections = {},
std::string_view runtime_id = {}
) -> std::expected<std::unique_ptr<linux_resource_lifecycle>, std::string> {
std::vector<glove::supervisor::resolved_path_grant> grants;
if (!requested_aliases.empty()) {
const auto alias_quota = limits.disk_bytes / 4U;
std::vector<glove::supervisor::path_alias_policy> policies;
policies.reserve(requested_aliases.size());
for (const auto& requested : requested_aliases) {
policies.push_back(policy_for(requested, alias_quota));
}
auto registry = glove::supervisor::path_alias_registry::build(std::move(policies));
if (!registry) {
return std::unexpected(registry.error());
}
grants.reserve(requested_aliases.size());
for (const auto& requested : requested_aliases) {
auto grant = registry->resolve({
.alias = requested.alias,
.access = requested.access,
.ttl_secs = 300,
.max_bytes =
requested.access == glove::supervisor::path_access::read ? 0 : alias_quota,
});
if (!grant) {
return std::unexpected(grant.error());
}
grants.push_back(std::move(*grant));
}
}
auto filesystem = linux_session_filesystem::create(
materialization_root.string(),
session_id,
limits.disk_bytes,
std::move(grants),
std::move(library_projections),
runtime_id
);
if (!filesystem) {
return std::unexpected(filesystem.error());
}
auto cgroup = root.create_session(session_id, limits);
if (!cgroup) {
return std::unexpected(cgroup.error());
}
return linux_resource_lifecycle::create(
std::move(*cgroup), std::move(*filesystem), limits, epoch_ms()
);
}
auto limits_for(std::uint64_t disk_bytes) -> resource_limits {
return {
.cpu_time_ms = 10'000,
.memory_bytes = std::uint64_t{128} * 1024U * 1024U,
.pids = 16,
.wall_time_ms = 5'000,
.disk_bytes = disk_bytes,
.terminal_output_bytes = std::uint64_t{1024} * 1024U,
};
}
auto launch_profile(const resource_limits& limits) -> profile {
profile value;
value.environment = {"PATH=/usr/bin:/bin:/usr/sbin:/sbin"};
value.required_limits = limits;
return value;
}
auto digest_for(std::string_view value) -> std::string {
const auto* bytes = reinterpret_cast<const unsigned char*>(value.data());
return glove::container::sha256_hex(std::span{bytes, value.size()}).value_or("");
}
auto execute_managed(
const profile& prof,
const std::vector<std::string>& argv,
std::unique_ptr<linux_resource_lifecycle> lifecycle
) -> std::expected<resource_enforcement_receipt, std::string> {
if (!lifecycle) {
return std::unexpected(std::string{"test lifecycle is required"});
}
auto binding = glove::container::linux_detail::bind_managed_session(
prof, argv, *lifecycle, controller_plan_digest
);
if (!binding) {
return std::unexpected(binding.error());
}
return glove::container::linux_detail::exec_managed_session(
prof, argv, *binding, std::move(lifecycle)
);
}
// The local REQUIRE macro expands each assertion into branches; the scenario
// itself remains a single linear launch contract.
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
auto mounted_copy_is_isolated_test(
cgroup_v2_root& root,
const std::filesystem::path& materialization_root,
const std::filesystem::path& source,
const std::filesystem::path& file_source,
const std::filesystem::path& reference_source,
std::uint64_t page
) -> int {
const auto limits = limits_for(page * 64U);
const std::vector aliases = {
requested_alias{"project", source, "/workspace/project"},
requested_alias{"single", file_source, "/workspace/single.txt"},
requested_alias{
"reference",
reference_source,
"/workspace/reference",
glove::supervisor::path_access::read,
},
};
auto lifecycle = make_lifecycle(root, materialization_root, aliases, "managed-copy", limits);
REQUIRE(lifecycle.has_value());
std::string script = "set -eu; ";
script += "test \"$(cat /workspace/project/input.txt)\" = seed; ";
script += "printf child > /workspace/project/output.txt; ";
script += "test \"$(cat /workspace/project/output.txt)\" = child; ";
script += "test \"$(cat /workspace/single.txt)\" = standalone; ";
script += "printf changed > /workspace/single.txt; ";
script += "test \"$(cat /workspace/single.txt)\" = changed; ";
script += "test \"$(cat /workspace/reference/reference.txt)\" = trusted; ";
script += "if (printf denied > /workspace/reference/blocked) 2>/dev/null; then exit 81; fi; ";
script += "test -w /tmp; test -w /var/tmp; ";
script += "test \"$(stat -c %d /tmp)\" = \"$(stat -c %d /var/tmp)\"; ";
script += "test ! -e '" + source.string() + "'; ";
script += "printf alpha; printf beta >&2";
const auto prof = launch_profile(limits);
const std::vector argv = {std::string{"/usr/bin/sh"}, std::string{"-c"}, script};
auto binding = glove::container::linux_detail::bind_managed_session(
prof, argv, **lifecycle, controller_plan_digest
);
REQUIRE(binding.has_value());
const auto producer_key_path = materialization_root.parent_path() / "managed-audit.key";
const auto producer_journal_path =
materialization_root.parent_path() / "managed-receipts.journal";
{
std::ofstream key{producer_key_path, std::ios::binary | std::ios::trunc};
key << audit_key << '\n';
key.flush();
REQUIRE(key.good());
}
REQUIRE(::chmod(producer_key_path.c_str(), 0600) == 0);
const glove::container::receipt_audit_producer_config producer_config{
.key_path = producer_key_path,
.journal_path = producer_journal_path,
};
auto producer = glove::container::receipt_audit_producer::initialize(producer_config);
REQUIRE(producer.has_value());
const auto producer_genesis = (*producer)->anchor();
REQUIRE((*producer)->acknowledge_bootstrap(producer_genesis).has_value());
auto terminal = glove::container::linux_detail::exec_managed_session_authenticated(
prof, argv, "managed-copy", *binding, std::move(*lifecycle), **producer
);
REQUIRE(terminal.has_value());
const auto durable_anchor = (*producer)->anchor();
REQUIRE(durable_anchor.sequence == 1);
producer->reset();
auto recovered =
glove::container::receipt_audit_producer::recover(producer_config, producer_genesis);
REQUIRE(recovered.has_value());
auto pending = (*recovered)->page_after(producer_genesis, 10);
REQUIRE(pending.has_value());
REQUIRE(pending->envelopes.size() == 1);
REQUIRE(pending->envelopes[0] == *terminal);
REQUIRE(terminal->receipt.profile_digest == binding->profile_digest);
REQUIRE(terminal->receipt.termination_cause == resource_termination_cause::exited);
REQUIRE(terminal->receipt.exit_code == 0);
REQUIRE(terminal->receipt.observed.disk_bytes > 0);
REQUIRE(terminal->receipt.observed.disk_bytes <= limits.disk_bytes);
REQUIRE(terminal->receipt.observed.terminal_output_bytes == 9);
auto anchor = glove::container::receipt_audit_anchor::create(audit_key);
REQUIRE(anchor.has_value());
REQUIRE(
glove::container::verify_receipt_audit_envelope(
*terminal, audit_key, "managed-copy", controller_plan_digest, **anchor
)
.has_value()
);
REQUIRE(
glove::container::validate_resource_enforcement_receipt(
terminal->receipt,
limits,
glove::container::linux_detail::managed_session_capabilities(),
glove::container::sandbox_backend::linux_production,
binding->profile_digest
)
.has_value()
);
auto tampered_digest = terminal->receipt;
tampered_digest.profile_digest[0] = tampered_digest.profile_digest[0] == 'a' ? 'b' : 'a';
REQUIRE(!glove::container::validate_resource_enforcement_receipt(
tampered_digest,
limits,
glove::container::linux_detail::managed_session_capabilities(),
glove::container::sandbox_backend::linux_production,
binding->profile_digest
)
.has_value());
auto tampered_mechanisms = terminal->receipt;
tampered_mechanisms.mechanisms.disk = glove::container::enforcement_mechanism::unavailable;
REQUIRE(!glove::container::validate_resource_enforcement_receipt(
tampered_mechanisms,
limits,
glove::container::linux_detail::managed_session_capabilities(),
glove::container::sandbox_backend::linux_production,
binding->profile_digest
)
.has_value());
auto tampered_limits = terminal->receipt;
++tampered_limits.configured_limits.wall_time_ms;
REQUIRE(!glove::container::validate_resource_enforcement_receipt(
tampered_limits,
limits,
glove::container::linux_detail::managed_session_capabilities(),
glove::container::sandbox_backend::linux_production,
binding->profile_digest
)
.has_value());
auto tampered_envelope = *terminal;
++tampered_envelope.receipt.observed.disk_bytes;
auto tamper_anchor = glove::container::receipt_audit_anchor::create(audit_key);
REQUIRE(tamper_anchor.has_value());
REQUIRE(
!glove::container::verify_receipt_audit_envelope(
tampered_envelope, audit_key, "managed-copy", controller_plan_digest, **tamper_anchor
)
.has_value()
);
REQUIRE(!std::filesystem::exists(source / "output.txt"));
REQUIRE(!std::filesystem::exists(reference_source / "blocked"));
{
std::ifstream original{file_source};
std::string contents;
original >> contents;
REQUIRE(contents == "standalone");
}
REQUIRE(std::filesystem::is_empty(materialization_root));
return 0;
}
auto managed_policy_rejection_test(
cgroup_v2_root& root,
const std::filesystem::path& materialization_root,
const std::filesystem::path& source,
std::uint64_t page
) -> int {
const auto limits = limits_for(page * 32U);
auto raw_path_lifecycle =
make_lifecycle(root, materialization_root, {}, "managed-raw-path", limits);
REQUIRE(raw_path_lifecycle.has_value());
auto raw_path_profile = launch_profile(limits);
raw_path_profile.filesystem.push_back({.path = source.string(), .writable = false});
auto raw_path =
execute_managed(raw_path_profile, {"/usr/bin/true"}, std::move(*raw_path_lifecycle));
REQUIRE(!raw_path.has_value());
REQUIRE(raw_path.error().find("lifecycle mount set") != std::string::npos);
REQUIRE(std::filesystem::is_empty(materialization_root));
auto runtime_path_lifecycle =
make_lifecycle(root, materialization_root, {}, "managed-runtime-path", limits);
REQUIRE(runtime_path_lifecycle.has_value());
auto runtime_path_profile = launch_profile(limits);
runtime_path_profile.runtime_filesystem.push_back({.path = source.string(), .writable = false});
auto runtime_path = execute_managed(
runtime_path_profile,
{"/bin/sh", "-c", "test -f " + (source / "input.txt").string()},
std::move(*runtime_path_lifecycle)
);
REQUIRE(runtime_path.has_value());
REQUIRE(std::filesystem::is_empty(materialization_root));
auto unmanaged_home_lifecycle =
make_lifecycle(root, materialization_root, {}, "managed-unbound-home", limits);
REQUIRE(unmanaged_home_lifecycle.has_value());
auto unmanaged_home_profile = launch_profile(limits);
unmanaged_home_profile.managed_home_dir = "/home/agent";
auto unmanaged_home = execute_managed(
unmanaged_home_profile, {"/usr/bin/true"}, std::move(*unmanaged_home_lifecycle)
);
REQUIRE(!unmanaged_home.has_value());
REQUIRE(unmanaged_home.error().find("exact scratch projections") != std::string::npos);
REQUIRE(std::filesystem::is_empty(materialization_root));
auto mismatched_lifecycle =
make_lifecycle(root, materialization_root, {}, "managed-limit-mismatch", limits);
REQUIRE(mismatched_lifecycle.has_value());
auto mismatched_limits = limits;
++mismatched_limits.wall_time_ms;
auto mismatched_profile = launch_profile(mismatched_limits);
auto mismatch =
execute_managed(mismatched_profile, {"/usr/bin/true"}, std::move(*mismatched_lifecycle));
REQUIRE(!mismatch.has_value());
REQUIRE(mismatch.error().find("resource limits mismatch") != std::string::npos);
REQUIRE(std::filesystem::is_empty(materialization_root));
auto tampered_lifecycle =
make_lifecycle(root, materialization_root, {}, "managed-binding-tamper", limits);
REQUIRE(tampered_lifecycle.has_value());
const auto prof = launch_profile(limits);
const std::vector argv = {std::string{"/usr/bin/true"}};
auto binding = glove::container::linux_detail::bind_managed_session(
prof, argv, **tampered_lifecycle, controller_plan_digest
);
REQUIRE(binding.has_value());
binding->profile_digest[0] = binding->profile_digest[0] == 'a' ? 'b' : 'a';
auto tampered = glove::container::linux_detail::exec_managed_session(
prof, argv, *binding, std::move(*tampered_lifecycle)
);
REQUIRE(!tampered.has_value());
REQUIRE(tampered.error().find("launch binding mismatch") != std::string::npos);
REQUIRE(std::filesystem::is_empty(materialization_root));
return 0;
}
auto codex_runtime_context_test(
cgroup_v2_root& root,
const std::filesystem::path& materialization_root,
const std::filesystem::path& library_root,
std::uint64_t page
) -> int {
constexpr std::string_view bundle =
R"({"schema_version":1,"source_library_ref":"bafy-codex","source_manifest_digest":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","entries":[{"key":"sage-core","kind":"skill","content_digest":"a8095aa5472d84253e87441d7438235d2b13c13e09de63cbb88609931b8b8947","content":"# Sage core\n"}]})";
const auto bundle_digest = digest_for(bundle);
REQUIRE(bundle_digest.size() == 64U);
const auto bundle_path = library_root / (bundle_digest + ".json");
{
std::ofstream output{bundle_path, std::ios::binary | std::ios::trunc};
output << bundle;
}
REQUIRE(::chmod(bundle_path.c_str(), 0600) == 0);
auto store = glove::supervisor::library_bundle_store::open(library_root);
REQUIRE(store.has_value());
auto projections = store->resolve_projections({{
.projection =
{
.projection_id = "sage-codex",
.content_digest = bundle_digest,
.destination_alias = "libraries",
},
.target_path = "/opt/sage/library-bundles",
}});
REQUIRE(projections.has_value());
const auto limits = limits_for(page * 32U);
auto lifecycle = make_lifecycle(
root,
materialization_root,
{},
"managed-codex-context",
limits,
std::move(*projections),
"codex"
);
REQUIRE(lifecycle.has_value());
auto prof = launch_profile(limits);
prof.environment.push_back("CODEX_HOME=/home/agent/.codex");
prof.managed_home_dir = "/home/agent";
const std::vector argv = {
std::string{"/usr/bin/sh"},
std::string{"-c"},
std::string{"test \"$HOME\" = /home/agent; test \"$CODEX_HOME\" = /home/agent/.codex; "
"test -f /home/agent/.codex/skills/sage-codex-sage-core/SKILL.md; "
"test \"$(cat /home/agent/.codex/skills/sage-codex-sage-core/SKILL.md)\" = '# "
"Sage core'"},
};
auto binding = glove::container::linux_detail::bind_managed_session(
prof, argv, **lifecycle, controller_plan_digest
);
REQUIRE(binding.has_value());
auto terminal = glove::container::linux_detail::exec_managed_session(
prof, argv, *binding, std::move(*lifecycle)
);
REQUIRE(terminal.has_value());
REQUIRE(terminal->exit_code == 0);
REQUIRE(terminal->profile_digest == binding->profile_digest);
REQUIRE(terminal->library_projections.size() == 1U);
REQUIRE(terminal->library_projections.front().content_digest == bundle_digest);
REQUIRE(std::filesystem::is_empty(materialization_root));
struct native_runtime_case {
std::string_view runtime_id;
std::string_view skill_directory;
std::string_view managed_environment;
};
for (const native_runtime_case runtime : {
native_runtime_case{"claude-code", ".claude/skills", ""},
native_runtime_case{"pi", ".pi/agent/skills", ""},
native_runtime_case{"copilot", ".copilot/skills", "COPILOT_HOME=/home/agent/.copilot"},
native_runtime_case{
"opencode", ".config/opencode/skills", "XDG_CONFIG_HOME=/home/agent/.config"
},
}) {
auto native_projections = store->resolve_projections({{
.projection =
{
.projection_id = "sage-codex",
.content_digest = bundle_digest,
.destination_alias = "libraries",
},
.target_path = "/opt/sage/library-bundles",
}});
REQUIRE(native_projections.has_value());
auto native_lifecycle = make_lifecycle(
root,
materialization_root,
{},
std::string{"managed-"} + std::string{runtime.runtime_id} + "-context",
limits,
std::move(*native_projections),
runtime.runtime_id
);
REQUIRE(native_lifecycle.has_value());
auto native_profile = launch_profile(limits);
native_profile.managed_home_dir = "/home/agent";
if (!runtime.managed_environment.empty()) {
native_profile.environment.push_back(std::string{runtime.managed_environment});
}
std::string command = "test \"$HOME\" = /home/agent; test -f /home/agent/" +
std::string{runtime.skill_directory} +
"/sage-codex-sage-core/SKILL.md";
if (!runtime.managed_environment.empty()) {
const auto separator = runtime.managed_environment.find('=');
command += "; test \"$" +
std::string{runtime.managed_environment.substr(0, separator)} + "\" = \"" +
std::string{runtime.managed_environment.substr(separator + 1)} + "\"";
}
const std::vector native_argv = {
std::string{"/usr/bin/sh"},
std::string{"-c"},
std::move(command),
};
auto native_binding = glove::container::linux_detail::bind_managed_session(
native_profile, native_argv, **native_lifecycle, controller_plan_digest
);
REQUIRE(native_binding.has_value());
auto native_terminal = glove::container::linux_detail::exec_managed_session(
native_profile, native_argv, *native_binding, std::move(*native_lifecycle)
);
REQUIRE(native_terminal.has_value());
REQUIRE(native_terminal->exit_code == 0);
REQUIRE(std::filesystem::is_empty(materialization_root));
}
return 0;
}
// A test-only image supplies pinned, operator-like harness installations under
// this one read-only runtime root. The regular containment image intentionally
// has no vendor client, so ordinary unit and workflow lanes retain that guard.
auto real_native_harness_test(
cgroup_v2_root& root,
const std::filesystem::path& materialization_root,
const std::filesystem::path& library_root,
std::uint64_t page
) -> int {
const char* configured_root = ::getenv("GLOVE_TEST_NATIVE_HARNESS_ROOT");
if (configured_root == nullptr || *configured_root == '\0') {
return 0;
}
std::error_code error;
const auto harness_root = std::filesystem::canonical(configured_root, error);
REQUIRE(!error);
REQUIRE(std::filesystem::is_directory(harness_root));
constexpr std::string_view bundle =
R"({"schema_version":1,"source_library_ref":"bafy-native","source_manifest_digest":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","entries":[{"key":"sage-core","kind":"skill","content_digest":"a8095aa5472d84253e87441d7438235d2b13c13e09de63cbb88609931b8b8947","content":"# Sage core\n"}]})";
const auto bundle_digest = digest_for(bundle);
REQUIRE(bundle_digest.size() == 64U);
const auto bundle_path = library_root / (bundle_digest + ".json");
{
std::ofstream output{bundle_path, std::ios::binary | std::ios::trunc};
output << bundle;
}
REQUIRE(::chmod(bundle_path.c_str(), 0600) == 0);
auto store = glove::supervisor::library_bundle_store::open(library_root);
REQUIRE(store.has_value());
struct harness_case {
std::string_view runtime_id;
std::string_view executable;
};
constexpr std::array<harness_case, 4> harnesses{{
{"claude-code", "claude"},
{"pi", "pi"},
{"copilot", "copilot"},
{"opencode", "opencode"},
}};
auto limits = limits_for(page * 256U);
// Vendor startup shapes differ; this is a conformance ceiling, not the
// low-limit enforcement probe elsewhere in this test suite.
limits.memory_bytes = std::uint64_t{1} * 1024U * 1024U * 1024U;
limits.pids = 64;
limits.wall_time_ms = 20'000;
limits.disk_bytes = std::uint64_t{512} * 1024U * 1024U;
const auto bin_directory = harness_root / "node_modules" / ".bin";
const auto node_directory = harness_root / "node-runtime" / "bin";
for (const auto& harness : harnesses) {
const auto adapter =
glove::supervisor::native_skill_runtime_adapter_for(harness.runtime_id);
REQUIRE(adapter.has_value());
const auto executable = bin_directory / harness.executable;
REQUIRE(std::filesystem::is_regular_file(executable));
REQUIRE(::access(executable.c_str(), X_OK) == 0);
auto projections = store->resolve_projections({{
.projection =
{
.projection_id = "sage-native",
.content_digest = bundle_digest,
.destination_alias = "libraries",
},
.target_path = "/opt/sage/library-bundles",
}});
REQUIRE(projections.has_value());
auto lifecycle = make_lifecycle(
root,
materialization_root,
{},
std::string{"managed-real-"} + std::string{harness.runtime_id},
limits,
std::move(*projections),
harness.runtime_id
);
REQUIRE(lifecycle.has_value());
auto prof = launch_profile(limits);
prof.environment = {
"PATH=" + bin_directory.string() + ":" + node_directory.string() + ":/usr/bin:/bin",
"TERM=xterm-256color",
};
for (const auto& variable : adapter->managed_environment) {
prof.environment.push_back(variable);
}
prof.runtime_filesystem.push_back({.path = harness_root.string(), .writable = false});
prof.managed_home_dir = "/home/agent";
const std::vector argv = {executable.string(), std::string{"--version"}};
auto binding = glove::container::linux_detail::bind_managed_session(
prof, argv, **lifecycle, controller_plan_digest
);
REQUIRE(binding.has_value());
auto session = glove::container::linux_detail::start_managed_pty_session(
prof,
argv,
*binding,
std::move(*lifecycle),
{
.transcript_bytes = 64U * 1024U,
.max_read_bytes = 64U * 1024U,
.max_input_frame_bytes = 64U * 1024U,
.input_timeout_ms = 1'000,
.initial_rows = 24,
.initial_columns = 80,
.refinement_evaluator = nullptr,
},
[](::pid_t) -> std::expected<void, std::string> { return {}; }
);
REQUIRE(session.has_value());
auto output = (*session)->wait_read(0, 64U * 1024U, 5'000);
REQUIRE(output.has_value());
auto terminal = (*session)->wait();
REQUIRE(terminal.has_value());
if (terminal->exit_code != 0) {
std::fprintf(
stderr,
"Glove Linux real native harness probe (%.*s) exited %d: %.*s\n",
static_cast<int>(harness.runtime_id.size()),
harness.runtime_id.data(),
terminal->exit_code.value_or(-1),
static_cast<int>(output->bytes.size()),
output->bytes.data()
);
std::fprintf(
stderr,
" termination=%u peak_memory=%llu peak_pids=%u wall=%llu\n",
static_cast<unsigned int>(terminal->termination_cause),
static_cast<unsigned long long>(terminal->observed.peak_memory_bytes),
terminal->observed.peak_pids,
static_cast<unsigned long long>(terminal->observed.wall_time_ms)
);
return 1;
}
REQUIRE(terminal->termination_cause == resource_termination_cause::exited);
REQUIRE(!output->bytes.empty());
REQUIRE(!output->truncated);
REQUIRE(terminal->profile_digest == binding->profile_digest);
REQUIRE(terminal->library_projections.size() == 1U);
REQUIRE(terminal->library_projections.front().content_digest == bundle_digest);
REQUIRE(std::filesystem::is_empty(materialization_root));
std::fprintf(
stderr,
"Glove Linux real native harness probe (%.*s) passed\n",
static_cast<int>(harness.runtime_id.size()),
harness.runtime_id.data()
);
}
return 0;
}
auto child_release_is_gated_by_durable_callback_test(
cgroup_v2_root& root, const std::filesystem::path& materialization_root, std::uint64_t page
) -> int {
const auto limits = limits_for(page * 16U);
const auto prof = launch_profile(limits);
const std::vector argv = {std::string{"/usr/bin/true"}};
auto denied_lifecycle =
make_lifecycle(root, materialization_root, {}, "managed-start-denied", limits);
REQUIRE(denied_lifecycle.has_value());
auto denied_binding = glove::container::linux_detail::bind_managed_session(
prof, argv, **denied_lifecycle, controller_plan_digest
);
REQUIRE(denied_binding.has_value());
bool denied_callback_called = false;
auto denied = glove::container::linux_detail::exec_managed_session(
prof,
argv,
*denied_binding,
std::move(*denied_lifecycle),
[&](::pid_t child) -> std::expected<void, std::string> {
denied_callback_called = child > 0;
return std::unexpected(std::string{"durable running append rejected"});
}
);
REQUIRE(!denied.has_value());
REQUIRE(denied_callback_called);
REQUIRE(denied.error().find("durable running append rejected") != std::string::npos);
REQUIRE(std::filesystem::is_empty(materialization_root));
auto accepted_lifecycle =
make_lifecycle(root, materialization_root, {}, "managed-start-accepted", limits);
REQUIRE(accepted_lifecycle.has_value());
auto accepted_binding = glove::container::linux_detail::bind_managed_session(
prof, argv, **accepted_lifecycle, controller_plan_digest
);
REQUIRE(accepted_binding.has_value());
bool accepted_callback_called = false;
auto accepted = glove::container::linux_detail::exec_managed_session(
prof,
argv,
*accepted_binding,
std::move(*accepted_lifecycle),
[&](::pid_t child) -> std::expected<void, std::string> {
accepted_callback_called = child > 0;
return {};
}
);
REQUIRE(accepted.has_value());
REQUIRE(accepted_callback_called);
REQUIRE(accepted->termination_cause == resource_termination_cause::exited);
REQUIRE(accepted->exit_code == 0);
REQUIRE(std::filesystem::is_empty(materialization_root));
return 0;
}
auto child_disk_exhaustion_test(
cgroup_v2_root& root, const std::filesystem::path& materialization_root, std::uint64_t page
) -> int {
const auto limits = limits_for(page * 16U);
auto lifecycle = make_lifecycle(root, materialization_root, {}, "managed-disk", limits);
REQUIRE(lifecycle.has_value());
const std::string script =
"dd if=/dev/urandom of=/tmp/pressure bs=4096 count=100000 status=none 2>/dev/null; "
"sleep 10";
auto terminal = execute_managed(
launch_profile(limits), {"/usr/bin/sh", "-c", script}, std::move(*lifecycle)
);
REQUIRE(terminal.has_value());
REQUIRE(terminal->termination_cause == resource_termination_cause::disk_limit);
REQUIRE(!terminal->exit_code.has_value());
REQUIRE(terminal->observed.disk_bytes > 0);
REQUIRE(terminal->observed.disk_bytes <= limits.disk_bytes);
REQUIRE(terminal->observed.wall_time_ms < limits.wall_time_ms);
REQUIRE(std::filesystem::is_empty(materialization_root));
return 0;
}
auto child_output_exhaustion_test(
cgroup_v2_root& root, const std::filesystem::path& materialization_root, std::uint64_t page
) -> int {
auto limits = limits_for(page * 16U);
limits.terminal_output_bytes = 64;
auto lifecycle = make_lifecycle(root, materialization_root, {}, "managed-output", limits);
REQUIRE(lifecycle.has_value());
const std::string script = "printf '%0128d' 0; sleep 10";
auto terminal = execute_managed(
launch_profile(limits), {"/usr/bin/sh", "-c", script}, std::move(*lifecycle)
);
REQUIRE(terminal.has_value());
REQUIRE(terminal->termination_cause == resource_termination_cause::terminal_output_limit);
REQUIRE(!terminal->exit_code.has_value());
REQUIRE(terminal->observed.terminal_output_bytes > limits.terminal_output_bytes);
REQUIRE(terminal->observed.wall_time_ms < limits.wall_time_ms);
REQUIRE(std::filesystem::is_empty(materialization_root));
return 0;
}
auto interactive_pty_attach_and_stop_test(
cgroup_v2_root& root, const std::filesystem::path& materialization_root, std::uint64_t page
) -> int {
auto limits = limits_for(page * 16U);
limits.wall_time_ms = 10'000;
const auto prof = launch_profile(limits);
const std::vector argv = {std::string{"/usr/bin/cat"}};
auto ungated_lifecycle =
make_lifecycle(root, materialization_root, {}, "managed-pty-ungated", limits);
REQUIRE(ungated_lifecycle.has_value());
auto ungated_binding = glove::container::linux_detail::bind_managed_session(
prof, argv, **ungated_lifecycle, controller_plan_digest
);
REQUIRE(ungated_binding.has_value());
auto ungated = glove::container::linux_detail::start_managed_pty_session(
prof,
argv,
*ungated_binding,
std::move(*ungated_lifecycle),
{},
glove::container::linux_detail::managed_session_start_gate{}
);
REQUIRE(!ungated.has_value());
REQUIRE(ungated.error().find("child-release gate") != std::string::npos);
REQUIRE(std::filesystem::is_empty(materialization_root));
auto denied_lifecycle =
make_lifecycle(root, materialization_root, {}, "managed-pty-denied", limits);
REQUIRE(denied_lifecycle.has_value());
auto denied_binding = glove::container::linux_detail::bind_managed_session(
prof, argv, **denied_lifecycle, controller_plan_digest
);
REQUIRE(denied_binding.has_value());
auto denied = glove::container::linux_detail::start_managed_pty_session(
prof,
argv,
*denied_binding,
std::move(*denied_lifecycle),
{},
[](::pid_t) -> std::expected<void, std::string> {
return std::unexpected(std::string{"durable PTY running append rejected"});
}
);
REQUIRE(!denied.has_value());
REQUIRE(denied.error().find("durable PTY running append rejected") != std::string::npos);
REQUIRE(std::filesystem::is_empty(materialization_root));
auto lifecycle = make_lifecycle(root, materialization_root, {}, "managed-pty", limits);
REQUIRE(lifecycle.has_value());
auto binding = glove::container::linux_detail::bind_managed_session(
prof, argv, **lifecycle, controller_plan_digest
);
REQUIRE(binding.has_value());
bool gate_called = false;
auto session = glove::container::linux_detail::start_managed_pty_session(
prof,
argv,
*binding,
std::move(*lifecycle),
{
.transcript_bytes = page,
.max_read_bytes = page,
.max_input_frame_bytes = page,
.input_timeout_ms = 1'000,
.initial_rows = 24,
.initial_columns = 80,
.refinement_evaluator = nullptr,
},
[&](::pid_t child) -> std::expected<void, std::string> {
gate_called = child > 0;
return {};
}
);
REQUIRE(session.has_value());
REQUIRE(gate_called);
REQUIRE((*session)->pid() > 0);
REQUIRE((*session)->write_input("hello from pty\n").has_value());
auto output = (*session)->wait_read(0, page, 1'000);
REQUIRE(output.has_value());
REQUIRE(output->bytes.find("hello from pty") != std::string::npos);
REQUIRE(!output->truncated);
REQUIRE((*session)->resize(48, 132).has_value());
bool stop_gate_called = false;
const glove::container::linux_detail::managed_session_stop_gate before_stop =
[&]() -> std::expected<void, std::string> {
stop_gate_called = true;
return {};
};
REQUIRE((*session)->stop(before_stop).has_value());
REQUIRE(stop_gate_called);
REQUIRE((*session)->stop(before_stop).has_value());
auto terminal = (*session)->wait();
REQUIRE(terminal.has_value());
REQUIRE(terminal->termination_cause == resource_termination_cause::signaled);
REQUIRE(!terminal->exit_code.has_value());
REQUIRE(terminal->observed.terminal_output_bytes >= output->bytes.size());
REQUIRE((*session)->wait() == terminal);
stop_gate_called = false;
REQUIRE((*session)->stop(before_stop).has_value());
REQUIRE(!stop_gate_called);
REQUIRE(std::filesystem::is_empty(materialization_root));
return 0;
}
auto declarative_refinement_evaluator_test(
cgroup_v2_root& root,
const std::filesystem::path& materialization_root,
std::uint64_t page
) -> int {
using namespace glove::container;
const auto limits = limits_for(page * 32U);
auto lifecycle =
make_lifecycle(root, materialization_root, {}, "managed-refinement", limits);
REQUIRE(lifecycle.has_value());
refinement_execution_binding execution;
execution.schema_version = 1;
execution.variant = refinement_variant::candidate;
execution.fixture = {"fixture", std::string(64, '0'), "fixtures"};
execution.base = {"base", std::string(64, 'b'), "skills"};
execution.candidate = {"candidate", std::string(64, 'c'), "skills"};
execution.matched_context_digest = std::string(64, '0');
execution.plan_context_digest = std::string(64, 'e');
refinement_fixture_manifest fixture{
.schema = std::string{refinement_fixture_schema},
.evaluation_run_id = "run-managed",
.pair_id = "pair-managed",
.session_id = "managed-refinement",
.variant = refinement_variant::candidate,
.proposal_digest = std::string(64, 'a'),
.base_projection_digest = execution.base.content_digest,
.candidate_projection_digest = execution.candidate.content_digest,
.fixture_id = "prompt-managed",
.fixture_digest = std::string(64, 'd'),
.dataset_ref = "fixture:managed",
.dataset_fingerprint = std::string(64, 'f'),
.seed = 42,
.model =
{
.provider = "test",
.model_id = "synthetic",
.model_family = "synthetic",
.model_revision = std::nullopt,
.tier = "local",
.normalizer_version = 1,
},
.harness = "synthetic",
.module = std::nullopt,
.skill_projection_id = execution.candidate.projection_id,
.skill_projection_digest = execution.candidate.content_digest,
.matched_context_digest = std::string(64, '0'),
.assertions =
{
.expected_termination = resource_termination_cause::exited,
.expected_exit_code = 0,
.required_transcript_literals = {"alpha beta", "done"},
.forbidden_transcript_literals = {"forbidden"},
.max_latency_ms = 2'000,
},
};
fixture.matched_context_digest =
refinement_fixture_context_digest(fixture, execution.plan_context_digest).value();
execution.matched_context_digest = fixture.matched_context_digest;
const auto encoded = canonical_refinement_fixture_bytes(fixture).value();
const auto encoded_bytes = std::span<const unsigned char>{
reinterpret_cast<const unsigned char*>(encoded.data()), encoded.size()
};
execution.fixture.content_digest = sha256_hex(encoded_bytes).value();
auto evaluator = refinement_transcript_evaluator::create(
encoded_bytes, fixture.session_id, execution
);
REQUIRE(evaluator.has_value());
const auto prof = launch_profile(limits);
const std::vector argv = {
std::string{"/usr/bin/sh"},
std::string{"-c"},
std::string{"printf 'alpha '; printf 'beta '; printf done"},
};
auto binding = glove::container::linux_detail::bind_managed_session(
prof, argv, **lifecycle, controller_plan_digest
);
REQUIRE(binding.has_value());
auto session = glove::container::linux_detail::start_managed_pty_session(
prof,
argv,
*binding,
std::move(*lifecycle),
{
.transcript_bytes = page,
.max_read_bytes = page,
.max_input_frame_bytes = page,
.input_timeout_ms = 1'000,
.initial_rows = 24,
.initial_columns = 80,
.refinement_evaluator = *evaluator,
},
[](::pid_t) -> std::expected<void, std::string> { return {}; }
);
REQUIRE(session.has_value());
auto resource = (*session)->wait();
REQUIRE(resource.has_value());
auto refinement = (*session)->wait_refinement();
REQUIRE(refinement.has_value());
REQUIRE(refinement->has_value());
REQUIRE(
(*refinement)->evaluated_outcome->metrics.at("passed") == 1
);
REQUIRE((*refinement)->transcript.byte_count == 15);
REQUIRE(std::filesystem::is_empty(materialization_root));
return 0;
}
auto run() -> int {
temporary_tree tree;
REQUIRE(!tree.root().empty());
const auto materialization_root = tree.root() / "materializations";
const auto source = tree.root() / "source";
const auto file_source = tree.root() / "single-source.txt";
const auto reference_source = tree.root() / "reference";
const auto library_root = tree.root() / "library";
REQUIRE(std::filesystem::create_directory(materialization_root));
REQUIRE(::chmod(materialization_root.c_str(), 0700) == 0);
REQUIRE(std::filesystem::create_directory(source));
REQUIRE(std::filesystem::create_directory(reference_source));
REQUIRE(std::filesystem::create_directory(library_root));
REQUIRE(::chmod(library_root.c_str(), 0700) == 0);
{
std::ofstream input{source / "input.txt"};
input << "seed\n";
std::ofstream single{file_source};
single << "standalone\n";
std::ofstream reference{reference_source / "reference.txt"};
reference << "trusted\n";
}
const long page_size = ::sysconf(_SC_PAGESIZE);
REQUIRE(page_size > 0);
const auto page = static_cast<std::uint64_t>(page_size);
auto root = cgroup_v2_root::prepare_for_current_process();
if (!root) {
std::fprintf(stderr, "managed-session topology unavailable: %s\n", root.error().c_str());
return 77;
}
REQUIRE(
mounted_copy_is_isolated_test(
*root, materialization_root, source, file_source, reference_source, page
) == 0
);
REQUIRE(managed_policy_rejection_test(*root, materialization_root, source, page) == 0);
REQUIRE(codex_runtime_context_test(*root, materialization_root, library_root, page) == 0);
REQUIRE(real_native_harness_test(*root, materialization_root, library_root, page) == 0);
REQUIRE(
child_release_is_gated_by_durable_callback_test(*root, materialization_root, page) == 0
);
REQUIRE(child_disk_exhaustion_test(*root, materialization_root, page) == 0);
REQUIRE(child_output_exhaustion_test(*root, materialization_root, page) == 0);
REQUIRE(interactive_pty_attach_and_stop_test(*root, materialization_root, page) == 0);
REQUIRE(declarative_refinement_evaluator_test(*root, materialization_root, page) == 0);
return 0;
}
} // namespace
auto main() -> int {
return run();
}