feat(guanghu-os): add repository bridge lifecycle
This commit is contained in:
parent
9acee850cd
commit
0d1ded1196
9 changed files with 326 additions and 4 deletions
|
|
@ -14,3 +14,6 @@
|
||||||
|
|
||||||
当前工程门按顺序关闭:挂根前绑定与失败封门、`/run` 启动周期交接、根内监督进程持续运行、
|
当前工程门按顺序关闭:挂根前绑定与失败封门、`/run` 启动周期交接、根内监督进程持续运行、
|
||||||
仓库桥按需唤醒与收回、真实节点启动回执。每一门只能凭当前目标的执行证据升为 100。
|
仓库桥按需唤醒与收回、真实节点启动回执。每一门只能凭当前目标的执行证据升为 100。
|
||||||
|
|
||||||
|
跨根持续监督已经在京东同核 QEMU 中完成。当前最小门是使用独立 Forgejo 数据副本证明仓库桥
|
||||||
|
唤醒、固定主分支读回、失败收回与最终休眠;公网仓库进程不参与该实验。
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
---
|
||||||
|
type: ADR
|
||||||
|
id: "0178"
|
||||||
|
title: "Guanghu bounded repository bridge lifecycle"
|
||||||
|
status: accepted
|
||||||
|
date: 2026-08-16
|
||||||
|
refines: "0177"
|
||||||
|
development_id: "DEV-20260815-001"
|
||||||
|
---
|
||||||
|
|
||||||
|
# 光湖有界仓库桥生命周期
|
||||||
|
|
||||||
|
根内光湖监督实体只接受登记的 `repository-main-readback` 能力和一次性请求编号。执行前必须核验
|
||||||
|
当前机器、仍存活的根监督进程和仓库桥休眠状态;随后依次唤醒隔离仓库桥、读回固定 `main`、
|
||||||
|
重复现场验证,并在成功或失败路径上收回到 `DORMANT`。任意阶段不得接受任意 shell 能力。
|
||||||
|
|
||||||
|
真实公网 Forgejo 与 PID 760 不参与隔离门。现实验证使用独立数据副本、独立回环端口和独立进程;
|
||||||
|
只有最终状态重新休眠且公网仓库不受影响时,才能把这一个隔离谓词记为 100。
|
||||||
|
|
@ -127,6 +127,15 @@ prove physical boot or bounded wake/reclaim of the real repository bridge, so
|
||||||
those predicates and final master control remain `0`. See ADR-0177 and
|
those predicates and final master control remain `0`. See ADR-0177 and
|
||||||
`deployments/JD-FD-PRIMARY/CROSS-ROOT-SUPERVISOR-QEMU-RECEIPT-20260815.hldp`.
|
`deployments/JD-FD-PRIMARY/CROSS-ROOT-SUPERVISOR-QEMU-RECEIPT-20260815.hldp`.
|
||||||
|
|
||||||
|
## Bounded repository bridge lifecycle
|
||||||
|
|
||||||
|
`scripts/guanghu-repository-bridge-lifecycle.sh` requires a live root-supervisor
|
||||||
|
state and one allowlisted repository readback request. It wakes a registered
|
||||||
|
backend, verifies the pinned `main`, and reclaims the backend on both success
|
||||||
|
and failure. `scripts/forgejo-repository-shadow-backend.sh` provides a separate
|
||||||
|
loopback-only Forgejo data plane for physical-node isolation tests; it never
|
||||||
|
targets the public repository process. See ADR-0178.
|
||||||
|
|
||||||
## 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
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
umask 077
|
||||||
|
|
||||||
|
die() {
|
||||||
|
echo "GUANGHU_FORGEJO_SHADOW_FAIL_0: $*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
test_root=${GH_FORGEJO_SHADOW_TEST_ROOT:-}
|
||||||
|
if [[ -n ${test_root} ]]; then
|
||||||
|
test_root=$(readlink -f "${test_root}")
|
||||||
|
config_path=${GH_FORGEJO_SHADOW_CONFIG:?test config is required}
|
||||||
|
dmi_path=${GH_FORGEJO_SHADOW_DMI_PATH:?test DMI path is required}
|
||||||
|
else
|
||||||
|
[[ ${EUID} == 0 ]] || die "root execution is required"
|
||||||
|
[[ -z ${GH_FORGEJO_SHADOW_CONFIG:-}${GH_FORGEJO_SHADOW_DMI_PATH:-} ]] ||
|
||||||
|
die "production path override is forbidden"
|
||||||
|
config_path=/etc/guanghu/forgejo-repository-shadow.conf
|
||||||
|
dmi_path=/sys/class/dmi/id/product_uuid
|
||||||
|
fi
|
||||||
|
|
||||||
|
[[ -f ${config_path} && ! -L ${config_path} ]] || die "configuration is missing or unsafe"
|
||||||
|
schema=
|
||||||
|
node_id=
|
||||||
|
instance_id=
|
||||||
|
backend_id=
|
||||||
|
forgejo_binary=
|
||||||
|
work_path=
|
||||||
|
app_ini=
|
||||||
|
http_port=
|
||||||
|
repository_owner=
|
||||||
|
repository_name=
|
||||||
|
expected_main=
|
||||||
|
run_user=
|
||||||
|
while IFS='=' read -r key value; do
|
||||||
|
case "${key}" in
|
||||||
|
schema|node_id|instance_id|backend_id|forgejo_binary|work_path|app_ini|http_port|repository_owner|repository_name|expected_main|run_user)
|
||||||
|
printf -v "${key}" '%s' "${value}" ;;
|
||||||
|
''|'#'*) ;;
|
||||||
|
*) die "unknown configuration field: ${key}" ;;
|
||||||
|
esac
|
||||||
|
done <"${config_path}"
|
||||||
|
|
||||||
|
[[ ${schema} == guanghu.forgejo-repository-shadow/v1 ]] || die "configuration schema mismatch"
|
||||||
|
[[ ${node_id} == JD-FD-PRIMARY ]] || die "node identity mismatch"
|
||||||
|
[[ $(tr '[:upper:]' '[:lower:]' <"${dmi_path}" | tr -d '\r\n') == "${instance_id}" ]] || die "DMI identity mismatch"
|
||||||
|
[[ ${backend_id} == jd-repository-shadow ]] || die "backend binding mismatch"
|
||||||
|
[[ ${2:-} == "${backend_id}" ]] || die "requested backend mismatch"
|
||||||
|
[[ ${3:-} == repository-main-readback ]] || die "capability is not allowlisted"
|
||||||
|
[[ ${4:-} =~ ^REQ-[A-Za-z0-9._-]+$ ]] || die "request id is malformed"
|
||||||
|
[[ -x ${forgejo_binary} && -f ${app_ini} ]] || die "Forgejo shadow artifact is unavailable"
|
||||||
|
[[ ${http_port} =~ ^[0-9]{4,5}$ ]] || die "HTTP port is malformed"
|
||||||
|
[[ ${repository_owner} =~ ^[a-z0-9-]+$ && ${repository_name} =~ ^[a-z0-9-]+$ ]] || die "repository binding is malformed"
|
||||||
|
[[ ${expected_main} =~ ^[0-9a-f]{40}$ ]] || die "expected main is malformed"
|
||||||
|
[[ ${run_user} == guanghu ]] || die "Forgejo shadow user binding mismatch"
|
||||||
|
[[ -x /usr/sbin/start-stop-daemon ]] || die "process launcher is unavailable"
|
||||||
|
if [[ -n ${test_root} ]]; then
|
||||||
|
for path in "${config_path}" "${work_path}" "${app_ini}"; do
|
||||||
|
resolved=$(readlink -m "${path}")
|
||||||
|
[[ ${resolved} == "${test_root}" || ${resolved} == "${test_root}"/* ]] || die "test path escapes isolated root"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
pid_file=${work_path}/forgejo-shadow.pid
|
||||||
|
readback_file=${work_path}/${4}.main
|
||||||
|
url=http://127.0.0.1:${http_port}/code/${repository_owner}/${repository_name}.git
|
||||||
|
|
||||||
|
process_alive() {
|
||||||
|
[[ -s ${pid_file} ]] || return 1
|
||||||
|
pid=$(cat "${pid_file}")
|
||||||
|
[[ ${pid} =~ ^[0-9]+$ ]] && kill -0 "${pid}" 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
observe() {
|
||||||
|
if process_alive && curl -fsS --max-time 2 "http://127.0.0.1:${http_port}/code/api/v1/version" >/dev/null; then
|
||||||
|
echo ready
|
||||||
|
else
|
||||||
|
echo dormant
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
case "${1:-}" in
|
||||||
|
preflight)
|
||||||
|
[[ -d ${work_path}/repositories/${repository_owner}/${repository_name}.git ]] || die "shadow repository is unavailable"
|
||||||
|
[[ $(git --git-dir="${work_path}/repositories/${repository_owner}/${repository_name}.git" rev-parse refs/heads/main) == "${expected_main}" ]] ||
|
||||||
|
die "shadow repository main mismatch"
|
||||||
|
[[ $(observe) == dormant ]] || die "shadow is not dormant"
|
||||||
|
;;
|
||||||
|
observe) observe ;;
|
||||||
|
wake)
|
||||||
|
[[ $(observe) == dormant ]] || die "shadow is not dormant before wake"
|
||||||
|
/usr/sbin/start-stop-daemon --start --background --make-pidfile --pidfile "${pid_file}" \
|
||||||
|
--chuid "${run_user}" --startas "${forgejo_binary}" -- \
|
||||||
|
web --work-path "${work_path}" --config "${app_ini}"
|
||||||
|
for _ in {1..100}; do [[ $(observe) == ready ]] && break; sleep 0.1; done
|
||||||
|
[[ $(observe) == ready ]] || die "Forgejo shadow readiness failed"
|
||||||
|
;;
|
||||||
|
execute)
|
||||||
|
[[ $(observe) == ready ]] || die "Forgejo shadow is not ready"
|
||||||
|
git ls-remote "${url}" refs/heads/main | awk '{print $1}' >"${readback_file}"
|
||||||
|
;;
|
||||||
|
verify)
|
||||||
|
[[ $(cat "${readback_file}") == "${expected_main}" ]] || die "repository main readback mismatch"
|
||||||
|
[[ $(git ls-remote "${url}" refs/heads/main | awk '{print $1}') == "${expected_main}" ]] || die "live repository main mismatch"
|
||||||
|
;;
|
||||||
|
reclaim)
|
||||||
|
if process_alive; then
|
||||||
|
pid=$(cat "${pid_file}")
|
||||||
|
kill "${pid}" 2>/dev/null || true
|
||||||
|
for _ in {1..100}; do kill -0 "${pid}" 2>/dev/null || break; sleep 0.05; done
|
||||||
|
kill -KILL "${pid}" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
rm -f "${pid_file}"
|
||||||
|
[[ $(observe) == dormant ]] || die "Forgejo shadow reclaim failed"
|
||||||
|
;;
|
||||||
|
*) die "usage: $0 <preflight|observe|wake|execute|verify|reclaim> <backend> <capability> <request>" ;;
|
||||||
|
esac
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
umask 077
|
||||||
|
|
||||||
|
die() {
|
||||||
|
echo "GUANGHU_REPOSITORY_BRIDGE_LIFECYCLE_FAIL_0: $*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
test_root=${GH_REPOSITORY_LIFECYCLE_TEST_ROOT:-}
|
||||||
|
if [[ -n ${test_root} ]]; then
|
||||||
|
test_root=$(readlink -f "${test_root}")
|
||||||
|
config_path=${GH_REPOSITORY_LIFECYCLE_CONFIG:?test config is required}
|
||||||
|
dmi_path=${GH_REPOSITORY_LIFECYCLE_DMI_PATH:?test DMI path is required}
|
||||||
|
root_state=${GH_REPOSITORY_LIFECYCLE_ROOT_STATE:?test root state is required}
|
||||||
|
receipt_root=${GH_REPOSITORY_LIFECYCLE_RECEIPT_ROOT:?test receipt root is required}
|
||||||
|
for path in "${config_path}" "${dmi_path}" "${root_state}" "${receipt_root}"; do
|
||||||
|
resolved=$(readlink -f "${path}")
|
||||||
|
[[ ${resolved} == "${test_root}" || ${resolved} == "${test_root}"/* ]] ||
|
||||||
|
die "test path escapes isolated root"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
[[ ${EUID} == 0 ]] || die "root execution is required"
|
||||||
|
for name in GH_REPOSITORY_LIFECYCLE_CONFIG GH_REPOSITORY_LIFECYCLE_DMI_PATH GH_REPOSITORY_LIFECYCLE_ROOT_STATE GH_REPOSITORY_LIFECYCLE_RECEIPT_ROOT; do
|
||||||
|
[[ -z ${!name:-} ]] || die "production path override is forbidden: ${name}"
|
||||||
|
done
|
||||||
|
config_path=/etc/guanghu/repository-bridge-lifecycle.conf
|
||||||
|
dmi_path=/sys/class/dmi/id/product_uuid
|
||||||
|
root_state=/run/guanghu/root-supervisor/state.json
|
||||||
|
receipt_root=/guanghu/receipts/repository-bridge-lifecycle
|
||||||
|
fi
|
||||||
|
|
||||||
|
[[ -f ${config_path} && ! -L ${config_path} ]] || die "configuration is missing or unsafe"
|
||||||
|
[[ $(stat -c '%a' "${config_path}" 2>/dev/null || stat -f '%Lp' "${config_path}") == 600 ]] ||
|
||||||
|
die "configuration mode must be 0600"
|
||||||
|
|
||||||
|
schema=
|
||||||
|
node_id=
|
||||||
|
instance_id=
|
||||||
|
backend_id=
|
||||||
|
backend_command=
|
||||||
|
capability=
|
||||||
|
while IFS='=' read -r key value; do
|
||||||
|
case "${key}" in
|
||||||
|
schema|node_id|instance_id|backend_id|backend_command|capability) printf -v "${key}" '%s' "${value}" ;;
|
||||||
|
''|'#'*) ;;
|
||||||
|
*) die "unknown configuration field: ${key}" ;;
|
||||||
|
esac
|
||||||
|
done <"${config_path}"
|
||||||
|
|
||||||
|
[[ ${schema} == guanghu.repository-bridge-lifecycle/v1 ]] || die "configuration schema mismatch"
|
||||||
|
[[ ${node_id} == JD-FD-PRIMARY ]] || die "node identity mismatch"
|
||||||
|
[[ ${backend_id} =~ ^[a-z0-9-]+$ ]] || die "backend id is malformed"
|
||||||
|
[[ ${capability} == repository-main-readback ]] || die "capability is not allowlisted"
|
||||||
|
[[ -x ${backend_command} ]] || die "backend command is unavailable"
|
||||||
|
[[ $(tr '[:upper:]' '[:lower:]' <"${dmi_path}" | tr -d '\r\n') == "${instance_id}" ]] ||
|
||||||
|
die "DMI identity mismatch"
|
||||||
|
[[ -f ${root_state} && ! -L ${root_state} ]] || die "root supervisor state is unavailable"
|
||||||
|
state=$(cat "${root_state}")
|
||||||
|
for binding in \
|
||||||
|
'"schema":"guanghu.root-supervisor-state/v1"' \
|
||||||
|
'"node_id":"JD-FD-PRIMARY"' \
|
||||||
|
'"control":"GUANGHU_OS"' \
|
||||||
|
'"stage":"ROOT_SUPERVISOR_ACTIVE"'; do
|
||||||
|
grep -Fq "${binding}" <<<"${state}" || die "root supervisor binding mismatch"
|
||||||
|
done
|
||||||
|
supervisor_pid=$(sed -n 's/.*"pid":\([0-9][0-9]*\).*/\1/p' <<<"${state}")
|
||||||
|
[[ -n ${supervisor_pid} ]] && kill -0 "${supervisor_pid}" 2>/dev/null ||
|
||||||
|
die "root supervisor process is not alive"
|
||||||
|
boot_id=$(sed -n 's/.*"boot_id":"\([0-9a-f-]*\)".*/\1/p' <<<"${state}")
|
||||||
|
[[ ${boot_id} =~ ^[0-9a-f-]{36}$ ]] || die "root supervisor boot id is malformed"
|
||||||
|
|
||||||
|
request_id=${2:-}
|
||||||
|
[[ ${1:-} == run && ${request_id} =~ ^REQ-[A-Za-z0-9._-]+$ ]] ||
|
||||||
|
die "usage: $0 run REQ-<id>"
|
||||||
|
|
||||||
|
reclaim_needed=0
|
||||||
|
cleanup() {
|
||||||
|
if [[ ${reclaim_needed} == 1 ]]; then
|
||||||
|
"${backend_command}" reclaim "${backend_id}" "${capability}" "${request_id}" >/dev/null || true
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
"${backend_command}" preflight "${backend_id}" "${capability}" "${request_id}" >/dev/null
|
||||||
|
[[ $("${backend_command}" observe "${backend_id}" "${capability}" "${request_id}") == dormant ]] ||
|
||||||
|
die "repository bridge is not dormant before wake"
|
||||||
|
"${backend_command}" wake "${backend_id}" "${capability}" "${request_id}" >/dev/null
|
||||||
|
reclaim_needed=1
|
||||||
|
[[ $("${backend_command}" observe "${backend_id}" "${capability}" "${request_id}") == ready ]] ||
|
||||||
|
die "repository bridge readiness readback failed"
|
||||||
|
"${backend_command}" execute "${backend_id}" "${capability}" "${request_id}" >/dev/null
|
||||||
|
"${backend_command}" verify "${backend_id}" "${capability}" "${request_id}" >/dev/null
|
||||||
|
"${backend_command}" reclaim "${backend_id}" "${capability}" "${request_id}" >/dev/null
|
||||||
|
reclaim_needed=0
|
||||||
|
[[ $("${backend_command}" observe "${backend_id}" "${capability}" "${request_id}") == dormant ]] ||
|
||||||
|
die "repository bridge reclaim readback failed"
|
||||||
|
|
||||||
|
mkdir -p "${receipt_root}"
|
||||||
|
temporary=${receipt_root}/${request_id}.json.tmp.$$
|
||||||
|
printf '%s\n' "{\"schema\":\"guanghu.repository-bridge-lifecycle-receipt/v1\",\"node_id\":\"${node_id}\",\"boot_id\":\"${boot_id}\",\"request_id\":\"${request_id}\",\"capability\":\"${capability}\",\"control\":\"GUANGHU_OS\",\"result\":\"PASS_100\",\"initial_state\":\"DORMANT\",\"active_state\":\"READY\",\"final_state\":\"DORMANT\"}" >"${temporary}"
|
||||||
|
chmod 0600 "${temporary}"
|
||||||
|
mv "${temporary}" "${receipt_root}/${request_id}.json"
|
||||||
|
trap - EXIT
|
||||||
|
echo "GUANGHU_REPOSITORY_BRIDGE_LIFECYCLE_PASS_100 request=${request_id} final=DORMANT"
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
source_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
||||||
|
controller=${source_root}/scripts/guanghu-repository-bridge-lifecycle.sh
|
||||||
|
fixture=$(mktemp -d)
|
||||||
|
trap 'rm -rf "${fixture}"' EXIT
|
||||||
|
mkdir -p "${fixture}/state" "${fixture}/receipts"
|
||||||
|
printf '%s\n' f3d4b730-7f02-452f-975b-7091a4800431 >"${fixture}/dmi"
|
||||||
|
printf '%s\n' "{\"schema\":\"guanghu.root-supervisor-state/v1\",\"node_id\":\"JD-FD-PRIMARY\",\"boot_id\":\"11111111-2222-4333-8444-555555555555\",\"pid\":$$,\"control\":\"GUANGHU_OS\",\"stage\":\"ROOT_SUPERVISOR_ACTIVE\"}" >"${fixture}/root-state.json"
|
||||||
|
chmod 0600 "${fixture}/root-state.json"
|
||||||
|
|
||||||
|
cat >"${fixture}/backend" <<'EOF'
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
action=${1:-}
|
||||||
|
case "${action}" in
|
||||||
|
preflight) ;;
|
||||||
|
observe) [[ -f ${FAKE_READY} ]] && echo ready || echo dormant ;;
|
||||||
|
wake) touch "${FAKE_READY}" ;;
|
||||||
|
execute) [[ -f ${FAKE_READY} ]]; printf '%s\n' 'd2686f8cb3bde2426f79d13ad6581f7ea6ed8385' >"${FAKE_READBACK}" ;;
|
||||||
|
verify) [[ $(cat "${FAKE_READBACK}") == d2686f8cb3bde2426f79d13ad6581f7ea6ed8385 ]]; [[ ${FAKE_FAIL_VERIFY:-0} == 0 ]] ;;
|
||||||
|
reclaim) rm -f "${FAKE_READY}" ;;
|
||||||
|
*) exit 64 ;;
|
||||||
|
esac
|
||||||
|
EOF
|
||||||
|
chmod 0755 "${fixture}/backend"
|
||||||
|
|
||||||
|
cat >"${fixture}/controller.conf" <<EOF
|
||||||
|
schema=guanghu.repository-bridge-lifecycle/v1
|
||||||
|
node_id=JD-FD-PRIMARY
|
||||||
|
instance_id=f3d4b730-7f02-452f-975b-7091a4800431
|
||||||
|
backend_id=jd-repository-shadow
|
||||||
|
backend_command=${fixture}/backend
|
||||||
|
capability=repository-main-readback
|
||||||
|
EOF
|
||||||
|
chmod 0600 "${fixture}/controller.conf"
|
||||||
|
|
||||||
|
export GH_REPOSITORY_LIFECYCLE_TEST_ROOT=${fixture}
|
||||||
|
export GH_REPOSITORY_LIFECYCLE_CONFIG=${fixture}/controller.conf
|
||||||
|
export GH_REPOSITORY_LIFECYCLE_DMI_PATH=${fixture}/dmi
|
||||||
|
export GH_REPOSITORY_LIFECYCLE_ROOT_STATE=${fixture}/root-state.json
|
||||||
|
export GH_REPOSITORY_LIFECYCLE_RECEIPT_ROOT=${fixture}/receipts
|
||||||
|
export FAKE_READY=${fixture}/ready
|
||||||
|
export FAKE_READBACK=${fixture}/readback
|
||||||
|
|
||||||
|
"${controller}" run REQ-PASS-001
|
||||||
|
[[ ! -e ${fixture}/ready ]]
|
||||||
|
grep -Fq '"result":"PASS_100"' "${fixture}/receipts/REQ-PASS-001.json"
|
||||||
|
grep -Fq '"final_state":"DORMANT"' "${fixture}/receipts/REQ-PASS-001.json"
|
||||||
|
|
||||||
|
export FAKE_FAIL_VERIFY=1
|
||||||
|
if "${controller}" run REQ-FAIL-001; then
|
||||||
|
echo 'verification failure was accepted' >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
[[ ! -e ${fixture}/ready ]]
|
||||||
|
|
||||||
|
echo GUANGHU_REPOSITORY_BRIDGE_LIFECYCLE_OK
|
||||||
|
|
@ -98,6 +98,8 @@ run_gate guanghu_first_boot_supervisor \
|
||||||
"${source_root}/scripts/test-guanghu-first-boot-supervisor.sh"
|
"${source_root}/scripts/test-guanghu-first-boot-supervisor.sh"
|
||||||
run_gate guanghu_root_supervisor \
|
run_gate guanghu_root_supervisor \
|
||||||
"${source_root}/scripts/test-guanghu-root-supervisor.sh"
|
"${source_root}/scripts/test-guanghu-root-supervisor.sh"
|
||||||
|
run_gate guanghu_repository_bridge_lifecycle \
|
||||||
|
"${source_root}/scripts/test-guanghu-repository-bridge-lifecycle.sh"
|
||||||
run_gate auditable_line_coverage_100_percent \
|
run_gate auditable_line_coverage_100_percent \
|
||||||
bash -c '
|
bash -c '
|
||||||
cargo llvm-cov clean --workspace --manifest-path "$1/Cargo.toml"
|
cargo llvm-cov clean --workspace --manifest-path "$1/Cargo.toml"
|
||||||
|
|
|
||||||
|
|
@ -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-15.13",
|
"version": "2026-08-16.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,7 @@
|
||||||
"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_VERIFY_BOUNDED_ROOT_SUPERVISOR_TO_LINUX_REPOSITORY_BRIDGE_LIFECYCLE_IN_ISOLATION"
|
"next_engineering_gate": "BUILD_AND_VERIFY_REAL_FORGEJO_REPOSITORY_SHADOW_LIFECYCLE_ON_JD_WITHOUT_TOUCHING_PUBLIC_REPOSITORY"
|
||||||
},
|
},
|
||||||
"implementation": {
|
"implementation": {
|
||||||
"guanghu_supervisor_lifecycle_contract_source": 100,
|
"guanghu_supervisor_lifecycle_contract_source": 100,
|
||||||
|
|
@ -78,6 +78,10 @@
|
||||||
"guanghu_cross_root_fixture_builder_source": 100,
|
"guanghu_cross_root_fixture_builder_source": 100,
|
||||||
"jd_host_qemu_cross_switch_root_supervisor": 100,
|
"jd_host_qemu_cross_switch_root_supervisor": 100,
|
||||||
"cross_switch_root_persistent_supervisor": 100,
|
"cross_switch_root_persistent_supervisor": 100,
|
||||||
|
"repository_bridge_lifecycle_controller_source": 100,
|
||||||
|
"forgejo_repository_shadow_backend_source": 100,
|
||||||
|
"repository_bridge_failure_reclaim_contract_test": 100,
|
||||||
|
"jd_real_forgejo_repository_shadow_lifecycle": 0,
|
||||||
"independent_guanghu_first_boot_supervisor": 0,
|
"independent_guanghu_first_boot_supervisor": 0,
|
||||||
"jd_physical_deployment": 0
|
"jd_physical_deployment": 0
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -43,12 +43,12 @@ 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);
|
||||||
assert.equal(
|
assert.equal(
|
||||||
contract.jd_fd_primary.next_engineering_gate,
|
contract.jd_fd_primary.next_engineering_gate,
|
||||||
"IMPLEMENT_AND_VERIFY_BOUNDED_ROOT_SUPERVISOR_TO_LINUX_REPOSITORY_BRIDGE_LIFECYCLE_IN_ISOLATION",
|
"BUILD_AND_VERIFY_REAL_FORGEJO_REPOSITORY_SHADOW_LIFECYCLE_ON_JD_WITHOUT_TOUCHING_PUBLIC_REPOSITORY",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("the physical shadow and host QEMU cycles are registered without impersonating Guanghu-owned boot control", () => {
|
test("the physical shadow and host QEMU cycles are registered without impersonating Guanghu-owned boot control", () => {
|
||||||
assert.equal(contract.version, "2026-08-15.13");
|
assert.equal(contract.version, "2026-08-16.1");
|
||||||
assert.equal(contract.implementation.guanghu_supervisor_lifecycle_contract_source, 100);
|
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.target_readback_and_mandatory_reclaim_state_machine, 100);
|
||||||
assert.equal(contract.implementation.declared_supervisor_core_line_and_function_coverage, 100);
|
assert.equal(contract.implementation.declared_supervisor_core_line_and_function_coverage, 100);
|
||||||
|
|
@ -84,6 +84,10 @@ test("the physical shadow and host QEMU cycles are registered without impersonat
|
||||||
assert.equal(contract.implementation.guanghu_cross_root_fixture_builder_source, 100);
|
assert.equal(contract.implementation.guanghu_cross_root_fixture_builder_source, 100);
|
||||||
assert.equal(contract.implementation.jd_host_qemu_cross_switch_root_supervisor, 100);
|
assert.equal(contract.implementation.jd_host_qemu_cross_switch_root_supervisor, 100);
|
||||||
assert.equal(contract.implementation.cross_switch_root_persistent_supervisor, 100);
|
assert.equal(contract.implementation.cross_switch_root_persistent_supervisor, 100);
|
||||||
|
assert.equal(contract.implementation.repository_bridge_lifecycle_controller_source, 100);
|
||||||
|
assert.equal(contract.implementation.forgejo_repository_shadow_backend_source, 100);
|
||||||
|
assert.equal(contract.implementation.repository_bridge_failure_reclaim_contract_test, 100);
|
||||||
|
assert.equal(contract.implementation.jd_real_forgejo_repository_shadow_lifecycle, 0);
|
||||||
assert.equal(contract.implementation.independent_guanghu_first_boot_supervisor, 0);
|
assert.equal(contract.implementation.independent_guanghu_first_boot_supervisor, 0);
|
||||||
assert.equal(contract.implementation.jd_physical_deployment, 0);
|
assert.equal(contract.implementation.jd_physical_deployment, 0);
|
||||||
assert.equal(contract.current_target_evidence.final_state, "DORMANT");
|
assert.equal(contract.current_target_evidence.final_state, "DORMANT");
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue