feat: add Guanghu Linux subcontrol supervisor contract

This commit is contained in:
冰朔 2026-08-15 16:21:37 +08:00
commit 36996be39a
10 changed files with 803 additions and 3 deletions

View file

@ -105,6 +105,11 @@
- 执行后目标读回,随后停止或冻结副控环境并登记资源回收回执; - 执行后目标读回,随后停止或冻结副控环境并登记资源回收回执;
- 独立 Linux 救援槽保留,不受日常副控生命周期影响。 - 独立 Linux 救援槽保留,不受日常副控生命周期影响。
第一份源码合同位于 `guanghu-os/crates/supervisor`。它已经把请求、策略、能力白名单、授权、
回滚检查点、救援槽、状态迁移、目标读回和失败回收绑定为一个确定性闭环。发生唤醒尝试后,
任何失败都必须回收;只有再次读回副控为 `DORMANT` 才能解除锁定。该合同已有隔离测试,
但尚未接入真实 Linux 虚拟机或容器后端,也没有取得京东整机启动权。
### 阶段 F裸机研究后端 ### 阶段 F裸机研究后端
- 现有 GOSK/GHAL 候选继续作为研究和专用设备后端; - 现有 GOSK/GHAL 候选继续作为研究和专用设备后端;
@ -119,6 +124,7 @@
- 第一条类型化协议执行桥; - 第一条类型化协议执行桥;
- systemd 状态与重启动作的白名单、授权、回滚和目标读回合同; - systemd 状态与重启动作的白名单、授权、回滚和目标读回合同;
- 光湖语言主控的世界启动门、系统服务依赖、公共入口验收和服务器回执合同; - 光湖语言主控的世界启动门、系统服务依赖、公共入口验收和服务器回执合同;
- 光湖监督器与 Linux 副控生命周期的类型化源码合同、失败回收和锁死语义;
- 京东节点已将 `guanghu-language-primary.target` 设为默认目标,并完成一次真实重启后 - 京东节点已将 `guanghu-language-primary.target` 设为默认目标,并完成一次真实重启后
`PASS_100` 回读;本次启动总耗时 36.146 秒; `PASS_100` 回读;本次启动总耗时 36.146 秒;
- 对应单元和集成测试。 - 对应单元和集成测试。
@ -129,7 +135,8 @@
- 全部注册协议的工程实现; - 全部注册协议的工程实现;
- 普通 Linux 管理入口的紧急维护边界收紧。 - 普通 Linux 管理入口的紧急维护边界收紧。
- 光湖独立先启动的监督器; - 光湖独立先启动的监督器;
- Linux 平时休眠、按需唤醒、目标读回和任务后收回的完整生命周期。 - 监督器到真实隔离 Linux 后端的接线;
- Linux 平时休眠、按需唤醒、目标读回和任务后收回的实体生命周期。
因此当前京东有界语言服务控制层为100最终整机光湖 OS 主控为0。Linux-free 或删除 因此当前京东有界语言服务控制层为100最终整机光湖 OS 主控为0。Linux-free 或删除
Linux 不在最终完成公式中。 Linux 不在最终完成公式中。

View file

@ -40,6 +40,13 @@ dependencies = [
"serde_yaml", "serde_yaml",
] ]
[[package]]
name = "guanghu-supervisor"
version = "0.1.0"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.17.1" version = "0.17.1"

View file

@ -5,5 +5,6 @@ members = [
"crates/ghctl", "crates/ghctl",
"crates/hldp-native-compiler", "crates/hldp-native-compiler",
"crates/hldp-runtime", "crates/hldp-runtime",
"crates/supervisor",
] ]
resolver = "2" resolver = "2"

View file

@ -57,6 +57,27 @@ The registered translation chain is:
TCS -> HLDP -> GLC -> GIR -> BTCP -> GOSK -> GHAL -> hardware TCS -> HLDP -> GLC -> GIR -> BTCP -> GOSK -> GHAL -> hardware
``` ```
## Guanghu supervisor and Linux subcontrol lifecycle
`crates/supervisor` implements the first fail-closed source contract for
ADR-0175. A typed, policy-bound capability request can advance only through:
```text
DORMANT -> STARTING -> READY -> EXECUTING -> VERIFYING -> RECLAIMING -> DORMANT
```
The request must bind the exact node, subject, capability, authorization,
rollback checkpoint, backend, required protocol chain, and preserved rescue
slot. Every failure after a wake attempt enters reclaim. A receipt can report
`PASS_100` only after target-side readback and a second observation proving the
Linux subcontrol returned to `DORMANT`; a failed reclaim is
`FAIL_0_LOCKED`.
The deterministic contract and isolation harness are implemented and covered
at 100% of declared source lines and functions. No production Linux
subcontrol backend, independent Guanghu boot supervisor, JD boot change, or
physical cutover is implied by that source result.
## Language-primary boot target ## Language-primary boot target
`guanghu-language-primary.target` makes the accepted cognitive-control model `guanghu-language-primary.target` makes the accepted cognitive-control model

View file

@ -0,0 +1,9 @@
[package]
name = "guanghu-supervisor"
version = "0.1.0"
edition = "2021"
license = "AGPL-3.0-or-later"
description = "Fail-closed lifecycle contract for Guanghu-controlled on-demand Linux subcontrol"
[dependencies]
serde = { version = "1", features = ["derive"] }

View file

@ -0,0 +1,378 @@
use std::fmt;
use serde::{Deserialize, Serialize};
pub const REQUEST_SCHEMA: &str = "guanghu.linux-subcontrol-request/v1";
pub const POLICY_SCHEMA: &str = "guanghu.supervisor-policy/v1";
pub const REQUIRED_PROTOCOL_CHAIN: [&str; 12] = [
"GLS-0301", // message envelope
"GLS-0302", // identity
"GLS-0303", // context
"GLS-0306", // receipt
"GLS-0309", // work order and authorization
"GLS-0311", // witness
"GLS-0130", // compiler
"GLS-0131", // deterministic representation
"GLS-0709", // adapter
"GLS-0710", // immutable module
"GLS-0803", // bounded execution lifecycle
"GLS-0819", // resource reclaim
];
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
pub struct LifecycleRequest {
pub schema: String,
pub request_id: String,
pub subject_id: String,
pub target_node_id: String,
pub protocol_chain: Vec<String>,
pub capability: String,
pub authorization_id: String,
pub rollback_checkpoint_id: String,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
pub struct CapabilityGrant {
pub capability: String,
pub backend_id: String,
pub authorization_id: String,
pub rollback_checkpoint_id: String,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
pub struct SupervisorPolicy {
pub schema: String,
pub policy_id: String,
pub target_node_id: String,
pub rescue_slot_id: String,
pub capability_grants: Vec<CapabilityGrant>,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
pub struct LifecyclePlan {
pub request_id: String,
pub subject_id: String,
pub target_node_id: String,
pub policy_id: String,
pub capability: String,
pub backend_id: String,
pub authorization_id: String,
pub rollback_checkpoint_id: String,
pub rescue_slot_id: String,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum ObservedSubcontrolState {
Dormant,
Ready,
Active,
Failed,
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum SupervisorState {
Dormant,
Starting,
Ready,
Executing,
Verifying,
Reclaiming,
FailedLocked,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
pub struct LifecycleReceipt {
pub schema: String,
pub request_id: String,
pub subject_id: String,
pub target_node_id: String,
pub policy_id: String,
pub capability: String,
pub backend_id: String,
pub authorization_id: String,
pub rollback_checkpoint_id: String,
pub rescue_slot_id: String,
pub rescue_verified: bool,
pub target_state_verified: bool,
pub reclaim_attempted: bool,
pub reclaim_verified: bool,
pub final_state: String,
pub failure_stage: Option<String>,
pub failure_detail: Option<String>,
pub transitions: Vec<SupervisorState>,
}
pub trait LifecycleBackend {
fn rescue_available(&self, rescue_slot_id: &str) -> Result<bool, String>;
fn observe_state(&self, backend_id: &str) -> Result<ObservedSubcontrolState, String>;
fn wake(&self, backend_id: &str) -> Result<(), String>;
fn execute(&self, backend_id: &str, capability: &str) -> Result<(), String>;
fn verify_target(&self, backend_id: &str, capability: &str) -> Result<bool, String>;
fn reclaim(&self, backend_id: &str) -> Result<(), String>;
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SupervisorError(String);
impl SupervisorError {
fn new(message: impl Into<String>) -> Self {
Self(message.into())
}
}
impl fmt::Display for SupervisorError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str(&self.0)
}
}
impl std::error::Error for SupervisorError {}
pub fn compile_request(
request: &LifecycleRequest,
policy: &SupervisorPolicy,
) -> Result<LifecyclePlan, SupervisorError> {
require(
request.schema == REQUEST_SCHEMA,
"unsupported request schema",
)?;
require(policy.schema == POLICY_SCHEMA, "unsupported policy schema")?;
require(
!request.request_id.trim().is_empty(),
"request_id is required",
)?;
require(
!request.subject_id.trim().is_empty(),
"subject_id is required",
)?;
require(
request.target_node_id == policy.target_node_id,
"request target does not match policy target",
)?;
require(
!policy.rescue_slot_id.trim().is_empty(),
"an independent Linux rescue slot is required",
)?;
for protocol in REQUIRED_PROTOCOL_CHAIN {
require(
request
.protocol_chain
.iter()
.any(|candidate| candidate == protocol),
format!("required protocol is missing: {protocol}"),
)?;
}
let grant = policy
.capability_grants
.iter()
.find(|grant| {
grant.capability == request.capability
&& grant.authorization_id == request.authorization_id
&& grant.rollback_checkpoint_id == request.rollback_checkpoint_id
})
.ok_or_else(|| SupervisorError::new("capability mutation is not granted by policy"))?;
require(
!grant.backend_id.trim().is_empty(),
"backend_id is required",
)?;
Ok(LifecyclePlan {
request_id: request.request_id.clone(),
subject_id: request.subject_id.clone(),
target_node_id: request.target_node_id.clone(),
policy_id: policy.policy_id.clone(),
capability: request.capability.clone(),
backend_id: grant.backend_id.clone(),
authorization_id: request.authorization_id.clone(),
rollback_checkpoint_id: request.rollback_checkpoint_id.clone(),
rescue_slot_id: policy.rescue_slot_id.clone(),
})
}
pub fn run_lifecycle(
plan: &LifecyclePlan,
backend: &dyn LifecycleBackend,
) -> Result<LifecycleReceipt, SupervisorError> {
let rescue_verified = backend
.rescue_available(&plan.rescue_slot_id)
.map_err(|error| SupervisorError::new(format!("cannot verify rescue slot: {error}")))?;
require(
rescue_verified,
"independent Linux rescue slot is unavailable",
)?;
let initial_state = backend.observe_state(&plan.backend_id).map_err(|error| {
SupervisorError::new(format!("cannot observe Linux subcontrol: {error}"))
})?;
require(
initial_state == ObservedSubcontrolState::Dormant,
"Linux subcontrol is not dormant before wake",
)?;
let mut transitions = vec![SupervisorState::Dormant, SupervisorState::Starting];
if let Err(error) = backend.wake(&plan.backend_id) {
return Ok(reclaim_after(
plan,
backend,
rescue_verified,
false,
"wake",
error,
transitions,
));
}
match backend.observe_state(&plan.backend_id) {
Ok(ObservedSubcontrolState::Ready) => transitions.push(SupervisorState::Ready),
Ok(state) => {
return Ok(reclaim_after(
plan,
backend,
rescue_verified,
false,
"wake_readiness",
format!("unexpected state after wake: {state:?}"),
transitions,
));
}
Err(error) => {
return Ok(reclaim_after(
plan,
backend,
rescue_verified,
false,
"wake_readiness",
error,
transitions,
));
}
}
transitions.push(SupervisorState::Executing);
if let Err(error) = backend.execute(&plan.backend_id, &plan.capability) {
return Ok(reclaim_after(
plan,
backend,
rescue_verified,
false,
"execution",
error,
transitions,
));
}
transitions.push(SupervisorState::Verifying);
match backend.verify_target(&plan.backend_id, &plan.capability) {
Ok(true) => Ok(reclaim_complete(
plan,
backend,
rescue_verified,
true,
None,
None,
transitions,
)),
Ok(false) => Ok(reclaim_after(
plan,
backend,
rescue_verified,
false,
"target_readback",
"target-side readback did not reach the expected state".to_owned(),
transitions,
)),
Err(error) => Ok(reclaim_after(
plan,
backend,
rescue_verified,
false,
"target_readback",
error,
transitions,
)),
}
}
fn reclaim_after(
plan: &LifecyclePlan,
backend: &dyn LifecycleBackend,
rescue_verified: bool,
target_state_verified: bool,
failure_stage: &str,
failure_detail: String,
transitions: Vec<SupervisorState>,
) -> LifecycleReceipt {
reclaim_complete(
plan,
backend,
rescue_verified,
target_state_verified,
Some(failure_stage.to_owned()),
Some(failure_detail),
transitions,
)
}
fn reclaim_complete(
plan: &LifecyclePlan,
backend: &dyn LifecycleBackend,
rescue_verified: bool,
target_state_verified: bool,
failure_stage: Option<String>,
failure_detail: Option<String>,
mut transitions: Vec<SupervisorState>,
) -> LifecycleReceipt {
transitions.push(SupervisorState::Reclaiming);
let reclaim_verified = backend.reclaim(&plan.backend_id).is_ok()
&& matches!(
backend.observe_state(&plan.backend_id),
Ok(ObservedSubcontrolState::Dormant)
);
if reclaim_verified {
transitions.push(SupervisorState::Dormant);
} else {
transitions.push(SupervisorState::FailedLocked);
}
let passed = target_state_verified && reclaim_verified && failure_stage.is_none();
LifecycleReceipt {
schema: "guanghu.linux-subcontrol-receipt/v1".to_owned(),
request_id: plan.request_id.clone(),
subject_id: plan.subject_id.clone(),
target_node_id: plan.target_node_id.clone(),
policy_id: plan.policy_id.clone(),
capability: plan.capability.clone(),
backend_id: plan.backend_id.clone(),
authorization_id: plan.authorization_id.clone(),
rollback_checkpoint_id: plan.rollback_checkpoint_id.clone(),
rescue_slot_id: plan.rescue_slot_id.clone(),
rescue_verified,
target_state_verified,
reclaim_attempted: true,
reclaim_verified,
final_state: if passed {
"PASS_100"
} else if reclaim_verified {
"FAIL_0"
} else {
"FAIL_0_LOCKED"
}
.to_owned(),
failure_stage,
failure_detail,
transitions,
}
}
fn require(condition: bool, message: impl Into<String>) -> Result<(), SupervisorError> {
if condition {
Ok(())
} else {
Err(SupervisorError::new(message))
}
}

View file

@ -0,0 +1,357 @@
use std::{cell::RefCell, collections::VecDeque};
use guanghu_supervisor::{
compile_request, run_lifecycle, CapabilityGrant, LifecycleBackend, LifecycleRequest,
ObservedSubcontrolState, SupervisorPolicy, SupervisorState, POLICY_SCHEMA, REQUEST_SCHEMA,
REQUIRED_PROTOCOL_CHAIN,
};
fn request() -> LifecycleRequest {
LifecycleRequest {
schema: REQUEST_SCHEMA.to_owned(),
request_id: "REQ-JD-SUBCONTROL-001".to_owned(),
subject_id: "ICE-P-ZY001".to_owned(),
target_node_id: "JD-FD-PRIMARY".to_owned(),
protocol_chain: REQUIRED_PROTOCOL_CHAIN
.iter()
.map(|protocol| (*protocol).to_owned())
.collect(),
capability: "public-entry-readback".to_owned(),
authorization_id: "AUTH-JD-SUBCONTROL-001".to_owned(),
rollback_checkpoint_id: "CHECKPOINT-JD-LINUX-RESCUE-001".to_owned(),
}
}
fn policy() -> SupervisorPolicy {
SupervisorPolicy {
schema: POLICY_SCHEMA.to_owned(),
policy_id: "JD-GUANGHU-SUPERVISOR-001".to_owned(),
target_node_id: "JD-FD-PRIMARY".to_owned(),
rescue_slot_id: "ubuntu-maintenance".to_owned(),
capability_grants: vec![CapabilityGrant {
capability: "public-entry-readback".to_owned(),
backend_id: "isolated-linux-fixture".to_owned(),
authorization_id: "AUTH-JD-SUBCONTROL-001".to_owned(),
rollback_checkpoint_id: "CHECKPOINT-JD-LINUX-RESCUE-001".to_owned(),
}],
}
}
#[test]
fn compiles_only_an_exact_authorized_capability() {
let plan = compile_request(&request(), &policy()).expect("compile exact grant");
assert_eq!(plan.backend_id, "isolated-linux-fixture");
assert_eq!(plan.capability, "public-entry-readback");
assert_eq!(plan.rescue_slot_id, "ubuntu-maintenance");
}
#[test]
fn rejects_missing_protocol_and_invented_authority() {
let mut missing_protocol = request();
missing_protocol
.protocol_chain
.retain(|protocol| protocol != "GLS-0819");
let error =
compile_request(&missing_protocol, &policy()).expect_err("missing lifecycle protocol");
assert!(error.to_string().contains("GLS-0819"));
let mut invented = request();
invented.authorization_id = "AUTH-INVENTED".to_owned();
let error = compile_request(&invented, &policy()).expect_err("invented grant");
assert!(error.to_string().contains("not granted"));
}
struct FakeBackend {
rescue_result: Result<bool, String>,
states: RefCell<VecDeque<Result<ObservedSubcontrolState, String>>>,
wake_result: Result<(), String>,
execute_result: Result<(), String>,
readback_result: Result<bool, String>,
reclaim_result: Result<(), String>,
calls: RefCell<Vec<String>>,
}
impl FakeBackend {
fn successful() -> Self {
Self {
rescue_result: Ok(true),
states: RefCell::new(
[
Ok(ObservedSubcontrolState::Dormant),
Ok(ObservedSubcontrolState::Ready),
Ok(ObservedSubcontrolState::Dormant),
]
.into(),
),
wake_result: Ok(()),
execute_result: Ok(()),
readback_result: Ok(true),
reclaim_result: Ok(()),
calls: RefCell::new(Vec::new()),
}
}
}
impl LifecycleBackend for FakeBackend {
fn rescue_available(&self, rescue_slot_id: &str) -> Result<bool, String> {
self.calls
.borrow_mut()
.push(format!("rescue:{rescue_slot_id}"));
self.rescue_result.clone()
}
fn observe_state(&self, backend_id: &str) -> Result<ObservedSubcontrolState, String> {
self.calls
.borrow_mut()
.push(format!("observe:{backend_id}"));
self.states
.borrow_mut()
.pop_front()
.unwrap_or_else(|| Err("unexpected state observation".to_owned()))
}
fn wake(&self, backend_id: &str) -> Result<(), String> {
self.calls.borrow_mut().push(format!("wake:{backend_id}"));
self.wake_result.clone()
}
fn execute(&self, backend_id: &str, capability: &str) -> Result<(), String> {
self.calls
.borrow_mut()
.push(format!("execute:{backend_id}:{capability}"));
self.execute_result.clone()
}
fn verify_target(&self, backend_id: &str, capability: &str) -> Result<bool, String> {
self.calls
.borrow_mut()
.push(format!("verify:{backend_id}:{capability}"));
self.readback_result.clone()
}
fn reclaim(&self, backend_id: &str) -> Result<(), String> {
self.calls
.borrow_mut()
.push(format!("reclaim:{backend_id}"));
self.reclaim_result.clone()
}
}
#[test]
fn completes_wake_execute_verify_and_reclaim_to_dormant() {
let plan = compile_request(&request(), &policy()).expect("compile");
let backend = FakeBackend::successful();
let receipt = run_lifecycle(&plan, &backend).expect("run lifecycle");
assert_eq!(receipt.final_state, "PASS_100");
assert!(receipt.target_state_verified);
assert!(receipt.reclaim_verified);
assert!(receipt.rescue_verified);
assert_eq!(
receipt.transitions,
[
SupervisorState::Dormant,
SupervisorState::Starting,
SupervisorState::Ready,
SupervisorState::Executing,
SupervisorState::Verifying,
SupervisorState::Reclaiming,
SupervisorState::Dormant,
]
);
assert_eq!(
backend.calls.borrow().last().unwrap(),
"observe:isolated-linux-fixture"
);
}
#[test]
fn failed_target_readback_is_fail_zero_but_reclaims_linux() {
let plan = compile_request(&request(), &policy()).expect("compile");
let mut backend = FakeBackend::successful();
backend.readback_result = Ok(false);
let receipt = run_lifecycle(&plan, &backend).expect("bounded failure receipt");
assert_eq!(receipt.final_state, "FAIL_0");
assert!(!receipt.target_state_verified);
assert!(receipt.reclaim_attempted);
assert!(receipt.reclaim_verified);
assert_eq!(receipt.failure_stage.as_deref(), Some("target_readback"));
assert_eq!(receipt.transitions.last(), Some(&SupervisorState::Dormant));
}
#[test]
fn reclaim_failure_locks_the_supervisor_instead_of_claiming_safety() {
let plan = compile_request(&request(), &policy()).expect("compile");
let mut backend = FakeBackend::successful();
backend.readback_result = Ok(false);
backend.reclaim_result = Err("cannot stop subordinate".to_owned());
backend.states = RefCell::new(
[
Ok(ObservedSubcontrolState::Dormant),
Ok(ObservedSubcontrolState::Ready),
]
.into(),
);
let receipt = run_lifecycle(&plan, &backend).expect("locked failure receipt");
assert_eq!(receipt.final_state, "FAIL_0_LOCKED");
assert!(!receipt.reclaim_verified);
assert_eq!(
receipt.transitions.last(),
Some(&SupervisorState::FailedLocked)
);
}
#[test]
fn missing_rescue_or_non_dormant_linux_prevents_wake() {
let plan = compile_request(&request(), &policy()).expect("compile");
let mut no_rescue = FakeBackend::successful();
no_rescue.rescue_result = Ok(false);
let error = run_lifecycle(&plan, &no_rescue).expect_err("rescue is mandatory");
assert!(error.to_string().contains("rescue"));
assert!(!no_rescue
.calls
.borrow()
.iter()
.any(|call| call.starts_with("wake:")));
let mut active = FakeBackend::successful();
active.states = RefCell::new([Ok(ObservedSubcontrolState::Ready)].into());
let error = run_lifecycle(&plan, &active).expect_err("must begin dormant");
assert!(error.to_string().contains("not dormant"));
assert!(!active
.calls
.borrow()
.iter()
.any(|call| call.starts_with("wake:")));
}
#[test]
fn compile_validation_fails_closed_for_every_required_boundary() {
let mut invalid_request = request();
invalid_request.schema = "wrong".to_owned();
assert!(compile_request(&invalid_request, &policy()).is_err());
let mut invalid_policy = policy();
invalid_policy.schema = "wrong".to_owned();
assert!(compile_request(&request(), &invalid_policy).is_err());
let mut missing_request_id = request();
missing_request_id.request_id = " ".to_owned();
assert!(compile_request(&missing_request_id, &policy()).is_err());
let mut missing_subject = request();
missing_subject.subject_id.clear();
assert!(compile_request(&missing_subject, &policy()).is_err());
let mut wrong_target = request();
wrong_target.target_node_id = "OTHER-NODE".to_owned();
assert!(compile_request(&wrong_target, &policy()).is_err());
let mut missing_rescue = policy();
missing_rescue.rescue_slot_id.clear();
assert!(compile_request(&request(), &missing_rescue).is_err());
let mut wrong_capability = request();
wrong_capability.capability = "unregistered".to_owned();
assert!(compile_request(&wrong_capability, &policy()).is_err());
let mut wrong_rollback = request();
wrong_rollback.rollback_checkpoint_id = "CHECKPOINT-INVENTED".to_owned();
assert!(compile_request(&wrong_rollback, &policy()).is_err());
let mut empty_backend = policy();
empty_backend.capability_grants[0].backend_id.clear();
assert!(compile_request(&request(), &empty_backend).is_err());
}
#[test]
fn observation_errors_before_wake_do_not_mutate_linux() {
let plan = compile_request(&request(), &policy()).expect("compile");
let mut rescue_error = FakeBackend::successful();
rescue_error.rescue_result = Err("rescue probe unavailable".to_owned());
let error = run_lifecycle(&plan, &rescue_error).expect_err("rescue probe error");
assert!(error.to_string().contains("cannot verify rescue"));
let mut state_error = FakeBackend::successful();
state_error.states = RefCell::new([Err("state probe unavailable".to_owned())].into());
let error = run_lifecycle(&plan, &state_error).expect_err("state probe error");
assert!(error.to_string().contains("cannot observe"));
assert!(!state_error
.calls
.borrow()
.iter()
.any(|call| call.starts_with("wake:")));
}
#[test]
fn every_post_wake_failure_attempts_reclaim() {
let plan = compile_request(&request(), &policy()).expect("compile");
let mut wake_failure = FakeBackend::successful();
wake_failure.wake_result = Err("wake failed".to_owned());
wake_failure.states = RefCell::new(
[
Ok(ObservedSubcontrolState::Dormant),
Ok(ObservedSubcontrolState::Dormant),
]
.into(),
);
let receipt = run_lifecycle(&plan, &wake_failure).expect("wake failure receipt");
assert_eq!(receipt.failure_stage.as_deref(), Some("wake"));
assert!(receipt.reclaim_verified);
let mut not_ready = FakeBackend::successful();
not_ready.states = RefCell::new(
[
Ok(ObservedSubcontrolState::Dormant),
Ok(ObservedSubcontrolState::Active),
Ok(ObservedSubcontrolState::Dormant),
]
.into(),
);
let receipt = run_lifecycle(&plan, &not_ready).expect("not-ready failure receipt");
assert_eq!(receipt.failure_stage.as_deref(), Some("wake_readiness"));
let mut readiness_error = FakeBackend::successful();
readiness_error.states = RefCell::new(
[
Ok(ObservedSubcontrolState::Dormant),
Err("readiness probe failed".to_owned()),
Ok(ObservedSubcontrolState::Dormant),
]
.into(),
);
let receipt = run_lifecycle(&plan, &readiness_error).expect("readiness failure receipt");
assert_eq!(receipt.failure_stage.as_deref(), Some("wake_readiness"));
let mut execution_error = FakeBackend::successful();
execution_error.execute_result = Err("capability failed".to_owned());
let receipt = run_lifecycle(&plan, &execution_error).expect("execution failure receipt");
assert_eq!(receipt.failure_stage.as_deref(), Some("execution"));
let mut readback_error = FakeBackend::successful();
readback_error.readback_result = Err("readback probe failed".to_owned());
let receipt = run_lifecycle(&plan, &readback_error).expect("readback failure receipt");
assert_eq!(receipt.failure_stage.as_deref(), Some("target_readback"));
}
#[test]
fn reclaim_requires_a_final_dormant_readback() {
let plan = compile_request(&request(), &policy()).expect("compile");
let mut backend = FakeBackend::successful();
backend.states = RefCell::new(
[
Ok(ObservedSubcontrolState::Dormant),
Ok(ObservedSubcontrolState::Ready),
Ok(ObservedSubcontrolState::Failed),
]
.into(),
);
let receipt = run_lifecycle(&plan, &backend).expect("locked receipt");
assert_eq!(receipt.final_state, "FAIL_0_LOCKED");
assert!(!receipt.reclaim_verified);
}

View file

@ -98,6 +98,7 @@ run_gate auditable_line_coverage_100_percent \
--test compiler_library \ --test compiler_library \
--test compiler_command \ --test compiler_command \
--test world_manifest \ --test world_manifest \
--test supervisor_lifecycle \
--no-report --no-report
cargo llvm-cov report --manifest-path "$1/Cargo.toml" \ cargo llvm-cov report --manifest-path "$1/Cargo.toml" \
--ignore-filename-regex "/src/main\\.rs$" \ --ignore-filename-regex "/src/main\\.rs$" \

View file

@ -1,7 +1,7 @@
{ {
"schema": "guanghu.os-control-architecture/v1", "schema": "guanghu.os-control-architecture/v1",
"record_id": "HLP-GUANGHU-OS-CONTROL-001", "record_id": "HLP-GUANGHU-OS-CONTROL-001",
"version": "2026-08-10.1", "version": "2026-08-15.1",
"state": "CURRENT_CANONICAL", "state": "CURRENT_CANONICAL",
"final_topology": "GUANGHU_MASTER_WITH_ON_DEMAND_LINUX_SUBCONTROL_AND_RESCUE", "final_topology": "GUANGHU_MASTER_WITH_ON_DEMAND_LINUX_SUBCONTROL_AND_RESCUE",
"control_ownership": { "control_ownership": {
@ -39,7 +39,16 @@
"linux_on_demand_subcontrol": 0, "linux_on_demand_subcontrol": 0,
"linux_rescue_preserved": 100, "linux_rescue_preserved": 100,
"final_guanghu_os_master": 0, "final_guanghu_os_master": 0,
"next_engineering_gate": "IMPLEMENT_AND_ISOLATION_TEST_GUANGHU_SUPERVISOR_AND_LINUX_SUBCONTROL_LIFECYCLE_BEFORE_REAL_BOOT_CUTOVER" "next_engineering_gate": "INTEGRATE_A_REAL_ISOLATED_LINUX_BACKEND_AND_GUANGHU_FIRST_BOOT_SUPERVISOR_BEFORE_JD_PHYSICAL_CUTOVER"
},
"implementation": {
"guanghu_supervisor_lifecycle_contract_source": 100,
"typed_policy_authorization_and_rollback_binding": 100,
"target_readback_and_mandatory_reclaim_state_machine": 100,
"declared_supervisor_core_line_and_function_coverage": 100,
"real_isolated_linux_backend": 0,
"independent_guanghu_first_boot_supervisor": 0,
"jd_physical_deployment": 0
}, },
"historical_evidence_policy": { "historical_evidence_policy": {
"bare_metal_gosk_ghal_receipts_remain_valid_for_observed_capabilities": true, "bare_metal_gosk_ghal_receipts_remain_valid_for_observed_capabilities": true,

View file

@ -31,6 +31,16 @@ test("current JD state stays transitional and cannot impersonate final master co
assert.equal(contract.jd_fd_primary.final_guanghu_os_master, 0); assert.equal(contract.jd_fd_primary.final_guanghu_os_master, 0);
}); });
test("source lifecycle progress does not impersonate backend, boot, or JD deployment", () => {
assert.equal(contract.version, "2026-08-15.1");
assert.equal(contract.implementation.guanghu_supervisor_lifecycle_contract_source, 100);
assert.equal(contract.implementation.target_readback_and_mandatory_reclaim_state_machine, 100);
assert.equal(contract.implementation.declared_supervisor_core_line_and_function_coverage, 100);
assert.equal(contract.implementation.real_isolated_linux_backend, 0);
assert.equal(contract.implementation.independent_guanghu_first_boot_supervisor, 0);
assert.equal(contract.implementation.jd_physical_deployment, 0);
});
test("current architecture and global engineering rules project the same control contract", () => { test("current architecture and global engineering rules project the same control contract", () => {
assert.equal(architecture.version, "2026-08-14.1"); assert.equal(architecture.version, "2026-08-14.1");
assert.equal(architecture.server_os_control.machine_projection, "routing/guanghu-os-control-architecture.json"); assert.equal(architecture.server_os_control.machine_projection, "routing/guanghu-os-control-architecture.json");