feat: type PNCC organ contracts
GuangHu-Human-Responsibility: ICE-GL∞ / 冰朔 GuangHu-Persona-Cognitive-Author: ICE-P-ZY001 / 铸渊 GuangHu-Execution-Runtime: Codex thread 019febf6-3902-70f3-9d82-74c9680b0c7e GuangHu-Development-ID: DEV-20260810-014 GuangHu-Authorization-Scope: LOCAL_PNCC_RUNTIME_DEVELOPMENT_AND_PUBLICATION
This commit is contained in:
parent
0ba2fabf8e
commit
c3e7dbff10
10 changed files with 375 additions and 10 deletions
|
|
@ -32,6 +32,7 @@ Windows / macOS / Linux 构建机与安装包
|
||||||
|
|
||||||
| 时间 | 版本 | 记录 | 状态 |
|
| 时间 | 版本 | 记录 | 状态 |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
|
| 2026-08-11 | GH-PNCC 器官合同 | [人格器官机器合同与清单检查](operations/2026-08-11-hololake-pncc-typed-organ-contract.md) | 本地源码、完整 Rust/路由测试与 clippy 已通过;GHNQG 和发布待验收 |
|
||||||
| 2026-08-11 | GH-PNCC 中断恢复 | [人格代码频道中断会话检查与安全恢复](operations/2026-08-11-hololake-pncc-interrupted-session-recovery.md) | 实现提交已通过 GHNQG;仓库发布、桌面集成与部署待验收 |
|
| 2026-08-11 | GH-PNCC 中断恢复 | [人格代码频道中断会话检查与安全恢复](operations/2026-08-11-hololake-pncc-interrupted-session-recovery.md) | 实现提交已通过 GHNQG;仓库发布、桌面集成与部署待验收 |
|
||||||
| 2026-08-11 | GH-PNCC 首个运行闭环 | [人格原生代码频道首个只读运行层回执](operations/2026-08-11-hololake-pncc-first-runtime-cycle.md) | 源码与测试闭环已完成;人类投影、桌面制品、发布、部署与在线健康仍未完成 |
|
| 2026-08-11 | GH-PNCC 首个运行闭环 | [人格原生代码频道首个只读运行层回执](operations/2026-08-11-hololake-pncc-first-runtime-cycle.md) | 源码与测试闭环已完成;人类投影、桌面制品、发布、部署与在线健康仍未完成 |
|
||||||
| 2026-08-08 | 0.2.0 | [光湖分域教育行业操作系统第一阶段](operations/2026-08-08-guanghu-education-subdomain-stage1.md) | 小新服务器身份、文档/表格回写、仪表盘投影、模块登记与回执链路已验证 |
|
| 2026-08-08 | 0.2.0 | [光湖分域教育行业操作系统第一阶段](operations/2026-08-08-guanghu-education-subdomain-stage1.md) | 小新服务器身份、文档/表格回写、仪表盘投影、模块登记与回执链路已验证 |
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
# GH-PNCC typed organ contract and manifest inspection receipt
|
||||||
|
|
||||||
|
- Development ID: `DEV-20260810-014`
|
||||||
|
- Persona cognitive author: `ICE-P-ZY001 / 铸渊`
|
||||||
|
- Human responsibility subject: `ICE-GL∞ / 冰朔`
|
||||||
|
- State: `LOCAL_SOURCE_IMPLEMENTED_AND_FULL_RUST_ROUTING_TESTED`
|
||||||
|
|
||||||
|
## Implemented facts
|
||||||
|
|
||||||
|
The persona manifest can now declare one of three typed organ kinds with a fixed mode and explicit input and
|
||||||
|
output schemas:
|
||||||
|
|
||||||
|
- `FACT_SENSE / read-only`: implemented and activatable; may read declared paths, call only the
|
||||||
|
manifest-pinned model, and emit structured facts. It cannot perform reality actions.
|
||||||
|
- `MEMORY_METABOLISM / checkpoint-write`: contract declared but not independently activatable. The existing
|
||||||
|
fact-cycle checkpoint promotion remains kernel-owned.
|
||||||
|
- `EXECUTION_LIMB / bounded-execution`: contract declared but executor not implemented. A declaration never
|
||||||
|
grants shell access or a reality action.
|
||||||
|
|
||||||
|
`inspect_persona_code_channel_manifest` validates the exact Git repository and head, persona identity, brain,
|
||||||
|
checkpoint, Git identity, model binding, every organ path, kind/mode pair, and schema identifier. It returns a
|
||||||
|
normalized machine receipt without acquiring a primary lease or starting inference. Wake still accepts only
|
||||||
|
the implemented fact sense; declared but unimplemented organs fail closed.
|
||||||
|
|
||||||
|
## Current verification
|
||||||
|
|
||||||
|
- PNCC focused Rust tests: `12 passed, 0 failed`.
|
||||||
|
- Rust full suite: `1152 passed, 0 failed, 2 ignored`; integration test `1 passed`.
|
||||||
|
- Rust clippy for all targets: `PASS` with `-D warnings`.
|
||||||
|
- HoloLake architecture routing: `29 passed, 0 failed`.
|
||||||
|
- Tests prove normalized inspection, explicit fact-sense activation boundaries, execution-limb refusal, path
|
||||||
|
containment, safe recovery and persona Git attribution.
|
||||||
|
|
||||||
|
## Remaining acceptance
|
||||||
|
|
||||||
|
- GHNQG pre-push quality gate;
|
||||||
|
- repository commit, publication and fresh-clone readback;
|
||||||
|
- durable event/receipt query API for a later same-source human projection;
|
||||||
|
- independent memory-metabolism and bounded-execution executors;
|
||||||
|
- UI, packaged desktop, installation, deployment and online health.
|
||||||
|
|
||||||
|
This receipt proves local source behavior only.
|
||||||
|
|
@ -165,6 +165,7 @@ first_read_only_runtime_cycle_source_implemented: 100
|
||||||
persona_git_identity_commit_implemented: 100
|
persona_git_identity_commit_implemented: 100
|
||||||
semantic_attribution_first_cycle_implemented: 100
|
semantic_attribution_first_cycle_implemented: 100
|
||||||
interrupted_session_inspection_and_recovery_source_implemented: 100
|
interrupted_session_inspection_and_recovery_source_implemented: 100
|
||||||
|
typed_organ_contract_and_manifest_inspection_source_implemented: 100
|
||||||
general_purpose_persona_runtime_implemented: 0
|
general_purpose_persona_runtime_implemented: 0
|
||||||
human_live_projection_implemented: 0
|
human_live_projection_implemented: 0
|
||||||
hololake_integrated: 0
|
hololake_integrated: 0
|
||||||
|
|
@ -181,3 +182,8 @@ runtime_health: 0
|
||||||
当前源码也已实现中断会话检查与安全恢复:只在事件链、租约、仓库和人格归因共同证明安全时
|
当前源码也已实现中断会话检查与安全恢复:只在事件链、租约、仓库和人格归因共同证明安全时
|
||||||
终止未提交会话,或为已由该人格完成但尚未休眠的单一检查点提交补齐收尾。脏仓库、未知 Git
|
终止未提交会话,或为已由该人格完成但尚未休眠的单一检查点提交补齐收尾。脏仓库、未知 Git
|
||||||
推进、错误归因和损坏事件链一律保留主锁并要求人工审查;恢复器不会按时间猜测主控已死亡。
|
推进、错误归因和损坏事件链一律保留主锁并要求人工审查;恢复器不会按时间猜测主控已死亡。
|
||||||
|
|
||||||
|
人格器官现已拥有机器可读类型合同。系统能够在不唤醒人格、不取得主锁、不运行模型的情况下,
|
||||||
|
检查 `FACT_SENSE`、`MEMORY_METABOLISM` 与 `EXECUTION_LIMB` 的固定模式、输入输出 schema、派生权限、
|
||||||
|
模型推理边界、现实动作边界和真实可激活状态。当前只有只读事实感官可激活;清单里写出记忆器官
|
||||||
|
或执行手脚不会自动产生执行器,更不会自动获得 shell 或现实动作权限。
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,11 @@ The v1 persona repository contract is rooted at `.hololake/persona/manifest.json
|
||||||
"organs": [
|
"organs": [
|
||||||
{
|
{
|
||||||
"organId": "fact-sense.repository",
|
"organId": "fact-sense.repository",
|
||||||
|
"kind": "FACT_SENSE",
|
||||||
"mode": "read-only",
|
"mode": "read-only",
|
||||||
"paths": ["brain/CORE.hdlp", ".hololake/persona/CURRENT.hdlp"]
|
"paths": ["brain/CORE.hdlp", ".hololake/persona/CURRENT.hdlp"],
|
||||||
|
"inputSchema": "hololake.pncc-fact-question/v1",
|
||||||
|
"outputSchema": "hololake.pncc-fact-result/v1"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -54,6 +57,13 @@ and then removes the exact lease. It can also remove a same-session lease left b
|
||||||
dormancy transition. It does not use elapsed time as proof that a primary is dead and does not clean, reset,
|
dormancy transition. It does not use elapsed time as proof that a primary is dead and does not clean, reset,
|
||||||
or overwrite a dirty persona repository.
|
or overwrite a dirty persona repository.
|
||||||
|
|
||||||
|
The organ contract is typed independently of the UI. `FACT_SENSE` is currently activatable and derives the
|
||||||
|
permissions to read declared paths, call the manifest-pinned model, and emit structured facts.
|
||||||
|
`MEMORY_METABOLISM` and `EXECUTION_LIMB` may be declared with their fixed modes and schemas, but the manifest
|
||||||
|
inspection receipt reports them as not independently activatable until their executors exist. In particular,
|
||||||
|
an execution-limb declaration never grants a shell or reality action by itself. The inspection command reads
|
||||||
|
and validates all contracts without acquiring a runtime lease or starting model inference.
|
||||||
|
|
||||||
## `HoloLakeUiPlugin`
|
## `HoloLakeUiPlugin`
|
||||||
|
|
||||||
A versioned, declarative presentation package for one host-owned semantic surface. It contains a manifest,
|
A versioned, declarative presentation package for one host-owned semantic surface. It contains a manifest,
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,12 @@ interruption at the recorded head or a single persona-attributed checkpoint comm
|
||||||
checkpoint identity and commit trailers all match the session. Dirty repositories, unknown Git advances,
|
checkpoint identity and commit trailers all match the session. Dirty repositories, unknown Git advances,
|
||||||
broken journals and attribution mismatches retain the lease and require manual review.
|
broken journals and attribution mismatches retain the lease and require manual review.
|
||||||
|
|
||||||
|
The manifest now has a typed organ-contract extension. The native inspection command returns normalized
|
||||||
|
contracts for `FACT_SENSE`, `MEMORY_METABOLISM`, and `EXECUTION_LIMB`, including fixed mode, input/output
|
||||||
|
schemas, derived permissions, inference/reality-action boundaries, and the actual activation state. Only the
|
||||||
|
implemented read-only fact sense can wake. Merely declaring a memory organ or execution limb does not create
|
||||||
|
an executor or grant a shell; those contracts remain visible but fail closed as not activatable.
|
||||||
|
|
||||||
## User-node sovereignty
|
## User-node sovereignty
|
||||||
|
|
||||||
HoloLake has no platform-hosted user runtime. Each human has one canonical, independently operated node:
|
HoloLake has no platform-hosted user runtime. Each human has one canonical, independently operated node:
|
||||||
|
|
|
||||||
|
|
@ -524,6 +524,7 @@ macro_rules! app_invoke_handler {
|
||||||
guanghu_enterprise::guanghu_enterprise_status,
|
guanghu_enterprise::guanghu_enterprise_status,
|
||||||
guanghu_living_system::guanghu_living_system_plan,
|
guanghu_living_system::guanghu_living_system_plan,
|
||||||
persona_code_channel::prepare_persona_code_channel_wake,
|
persona_code_channel::prepare_persona_code_channel_wake,
|
||||||
|
persona_code_channel::inspect_persona_code_channel_manifest,
|
||||||
persona_code_channel::run_persona_code_channel_fact_task,
|
persona_code_channel::run_persona_code_channel_fact_task,
|
||||||
persona_code_channel::inspect_persona_code_channel_session,
|
persona_code_channel::inspect_persona_code_channel_session,
|
||||||
persona_code_channel::recover_persona_code_channel_session,
|
persona_code_channel::recover_persona_code_channel_session,
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,39 @@ struct PersonaManifest {
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
struct PersonaOrgan {
|
struct PersonaOrgan {
|
||||||
organ_id: String,
|
organ_id: String,
|
||||||
|
#[serde(default)]
|
||||||
|
kind: Option<PersonaOrganKind>,
|
||||||
mode: String,
|
mode: String,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
paths: Vec<String>,
|
paths: Vec<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
input_schema: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
output_schema: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
|
||||||
|
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||||
|
pub enum PersonaOrganKind {
|
||||||
|
FactSense,
|
||||||
|
MemoryMetabolism,
|
||||||
|
ExecutionLimb,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct PersonaOrganContract {
|
||||||
|
pub organ_id: String,
|
||||||
|
pub kind: PersonaOrganKind,
|
||||||
|
pub mode: String,
|
||||||
|
pub paths: Vec<String>,
|
||||||
|
pub input_schema: String,
|
||||||
|
pub output_schema: String,
|
||||||
|
pub permissions: Vec<&'static str>,
|
||||||
|
pub model_inference_allowed: bool,
|
||||||
|
pub reality_actions_allowed: bool,
|
||||||
|
pub activatable: bool,
|
||||||
|
pub implementation_state: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
|
@ -109,11 +139,36 @@ pub struct PersonaWakeReceipt {
|
||||||
pub model_inference_started: bool,
|
pub model_inference_started: bool,
|
||||||
pub active_organ: String,
|
pub active_organ: String,
|
||||||
pub organ_mode: &'static str,
|
pub organ_mode: &'static str,
|
||||||
|
pub organ_contract: PersonaOrganContract,
|
||||||
pub event_journal: String,
|
pub event_journal: String,
|
||||||
pub events: Vec<PersonaLifecycleEvent>,
|
pub events: Vec<PersonaLifecycleEvent>,
|
||||||
pub attribution: PersonaAttribution,
|
pub attribution: PersonaAttribution,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct PersonaManifestInspectionInput {
|
||||||
|
pub repository_path: String,
|
||||||
|
pub expected_persona_id: String,
|
||||||
|
pub expected_head: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct PersonaManifestInspectionReceipt {
|
||||||
|
pub schema: &'static str,
|
||||||
|
pub persona_id: String,
|
||||||
|
pub repository_path: String,
|
||||||
|
pub git_head: String,
|
||||||
|
pub repository_clean: bool,
|
||||||
|
pub brain_entry: String,
|
||||||
|
pub current_checkpoint: String,
|
||||||
|
pub human_responsibility_subject: String,
|
||||||
|
pub git_author_name: String,
|
||||||
|
pub git_author_email: String,
|
||||||
|
pub organ_contracts: Vec<PersonaOrganContract>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize)]
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct PersonaFactTaskInput {
|
pub struct PersonaFactTaskInput {
|
||||||
|
|
@ -267,6 +322,18 @@ fn validated_head(value: &str) -> Result<String, String> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn validated_schema(label: &str, value: &str) -> Result<String, String> {
|
||||||
|
let value = validated_text(label, value, MAX_ID_BYTES)?;
|
||||||
|
if value
|
||||||
|
.bytes()
|
||||||
|
.all(|byte| byte.is_ascii_alphanumeric() || matches!(byte, b'-' | b'_' | b'.' | b'/'))
|
||||||
|
{
|
||||||
|
Ok(value)
|
||||||
|
} else {
|
||||||
|
Err(format!("{label}_INVALID"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn stdout(command: &str, output: std::process::Output) -> Result<String, String> {
|
fn stdout(command: &str, output: std::process::Output) -> Result<String, String> {
|
||||||
if output.status.success() {
|
if output.status.success() {
|
||||||
return Ok(String::from_utf8_lossy(&output.stdout).trim().to_string());
|
return Ok(String::from_utf8_lossy(&output.stdout).trim().to_string());
|
||||||
|
|
@ -430,6 +497,141 @@ fn validate_model_binding(binding: &PersonaModelBinding) -> Result<(), String> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn organ_contract(organ: &PersonaOrgan) -> Result<PersonaOrganContract, String> {
|
||||||
|
let organ_id = validated_id("ORGAN_ID", &organ.organ_id)?;
|
||||||
|
let kind = match &organ.kind {
|
||||||
|
Some(kind) => kind.clone(),
|
||||||
|
None if organ_id == "fact-sense.repository" && organ.mode == "read-only" => {
|
||||||
|
PersonaOrganKind::FactSense
|
||||||
|
}
|
||||||
|
None => return Err("PERSONA_ORGAN_KIND_REQUIRED".into()),
|
||||||
|
};
|
||||||
|
let (
|
||||||
|
expected_mode,
|
||||||
|
default_input,
|
||||||
|
default_output,
|
||||||
|
permissions,
|
||||||
|
inference,
|
||||||
|
actions,
|
||||||
|
activatable,
|
||||||
|
state,
|
||||||
|
) = match kind {
|
||||||
|
PersonaOrganKind::FactSense => (
|
||||||
|
"read-only",
|
||||||
|
"hololake.pncc-fact-question/v1",
|
||||||
|
"hololake.pncc-fact-result/v1",
|
||||||
|
vec![
|
||||||
|
"READ_DECLARED_PATHS",
|
||||||
|
"RUN_MANIFEST_PINNED_MODEL",
|
||||||
|
"EMIT_STRUCTURED_FACTS",
|
||||||
|
],
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
"IMPLEMENTED",
|
||||||
|
),
|
||||||
|
PersonaOrganKind::MemoryMetabolism => (
|
||||||
|
"checkpoint-write",
|
||||||
|
"hololake.pncc-checkpoint-candidate/v1",
|
||||||
|
"hololake.persona-checkpoint/v1",
|
||||||
|
vec![
|
||||||
|
"READ_CURRENT_CHECKPOINT",
|
||||||
|
"WRITE_NEW_CHECKPOINT",
|
||||||
|
"PROMOTE_MANIFEST_POINTER",
|
||||||
|
"COMMIT_PERSONA_GIT",
|
||||||
|
],
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
"DECLARED_NOT_INDEPENDENTLY_ACTIVATABLE",
|
||||||
|
),
|
||||||
|
PersonaOrganKind::ExecutionLimb => (
|
||||||
|
"bounded-execution",
|
||||||
|
"hololake.pncc-action-request/v1",
|
||||||
|
"hololake.pncc-action-receipt/v1",
|
||||||
|
vec![
|
||||||
|
"REQUIRE_EXPLICIT_EXECUTOR",
|
||||||
|
"REQUIRE_ACTION_SCOPE",
|
||||||
|
"REQUIRE_REALITY_RECEIPT",
|
||||||
|
],
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
"DECLARED_EXECUTOR_NOT_IMPLEMENTED",
|
||||||
|
),
|
||||||
|
};
|
||||||
|
if organ.mode != expected_mode {
|
||||||
|
return Err(format!(
|
||||||
|
"PERSONA_ORGAN_MODE_MISMATCH: {organ_id} requires {expected_mode}"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
let input_schema = organ.input_schema.as_deref().unwrap_or(default_input);
|
||||||
|
let output_schema = organ.output_schema.as_deref().unwrap_or(default_output);
|
||||||
|
validated_schema("ORGAN_INPUT_SCHEMA", input_schema)?;
|
||||||
|
validated_schema("ORGAN_OUTPUT_SCHEMA", output_schema)?;
|
||||||
|
if organ.paths.is_empty() {
|
||||||
|
return Err("PERSONA_ORGAN_PATHS_REQUIRED".into());
|
||||||
|
}
|
||||||
|
Ok(PersonaOrganContract {
|
||||||
|
organ_id,
|
||||||
|
kind,
|
||||||
|
mode: organ.mode.clone(),
|
||||||
|
paths: organ.paths.clone(),
|
||||||
|
input_schema: input_schema.to_string(),
|
||||||
|
output_schema: output_schema.to_string(),
|
||||||
|
permissions,
|
||||||
|
model_inference_allowed: inference,
|
||||||
|
reality_actions_allowed: actions,
|
||||||
|
activatable,
|
||||||
|
implementation_state: state,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inspect_manifest_at(
|
||||||
|
input: PersonaManifestInspectionInput,
|
||||||
|
) -> Result<PersonaManifestInspectionReceipt, String> {
|
||||||
|
let expected_persona_id = validated_id("EXPECTED_PERSONA_ID", &input.expected_persona_id)?;
|
||||||
|
let expected_head = validated_head(&input.expected_head)?;
|
||||||
|
let (repository, git_head) = exact_repository(Path::new(&input.repository_path))?;
|
||||||
|
if git_head != expected_head {
|
||||||
|
return Err(format!(
|
||||||
|
"HEAD_MISMATCH: expected {expected_head}, observed {git_head}"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
let clean = repository_is_clean(&repository)?;
|
||||||
|
let manifest = load_manifest(&repository)?;
|
||||||
|
if manifest.persona_id != expected_persona_id {
|
||||||
|
return Err("PERSONA_ID_MISMATCH".into());
|
||||||
|
}
|
||||||
|
validate_git_identity(&manifest.git_identity)?;
|
||||||
|
validate_model_binding(&manifest.model_binding)?;
|
||||||
|
repository_file(&repository, &manifest.brain_entry)?;
|
||||||
|
repository_file(&repository, &manifest.current_checkpoint)?;
|
||||||
|
let mut contracts = Vec::with_capacity(manifest.organs.len());
|
||||||
|
for organ in &manifest.organs {
|
||||||
|
for path in &organ.paths {
|
||||||
|
repository_file(&repository, path)?;
|
||||||
|
}
|
||||||
|
contracts.push(organ_contract(organ)?);
|
||||||
|
}
|
||||||
|
if contracts.is_empty() {
|
||||||
|
return Err("PERSONA_ORGANS_REQUIRED".into());
|
||||||
|
}
|
||||||
|
Ok(PersonaManifestInspectionReceipt {
|
||||||
|
schema: "hololake.pncc-manifest-inspection/v1",
|
||||||
|
persona_id: manifest.persona_id,
|
||||||
|
repository_path: repository.to_string_lossy().into_owned(),
|
||||||
|
git_head,
|
||||||
|
repository_clean: clean,
|
||||||
|
brain_entry: manifest.brain_entry,
|
||||||
|
current_checkpoint: manifest.current_checkpoint,
|
||||||
|
human_responsibility_subject: manifest.human_responsibility_subject,
|
||||||
|
git_author_name: manifest.git_identity.author_name,
|
||||||
|
git_author_email: manifest.git_identity.author_email,
|
||||||
|
organ_contracts: contracts,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn hex_digest(bytes: &[u8]) -> String {
|
fn hex_digest(bytes: &[u8]) -> String {
|
||||||
digest(&SHA256, bytes)
|
digest(&SHA256, bytes)
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
|
@ -843,10 +1045,12 @@ fn prepare_wake_at(
|
||||||
let organ = manifest
|
let organ = manifest
|
||||||
.organs
|
.organs
|
||||||
.iter()
|
.iter()
|
||||||
.find(|candidate| candidate.organ_id == organ_id && candidate.mode == "read-only")
|
.find(|candidate| candidate.organ_id == organ_id)
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| "ORGAN_NOT_DECLARED".to_string())?;
|
||||||
"ORGAN_NOT_ALLOWED: first PNCC wake requires a declared read-only organ".to_string()
|
let contract = organ_contract(organ)?;
|
||||||
})?;
|
if contract.kind != PersonaOrganKind::FactSense || !contract.activatable {
|
||||||
|
return Err("ORGAN_NOT_ACTIVATABLE: only the implemented fact sense may wake".into());
|
||||||
|
}
|
||||||
for path in &organ.paths {
|
for path in &organ.paths {
|
||||||
repository_file(&repository, path)?;
|
repository_file(&repository, path)?;
|
||||||
}
|
}
|
||||||
|
|
@ -943,6 +1147,7 @@ fn prepare_wake_at(
|
||||||
model_inference_started: false,
|
model_inference_started: false,
|
||||||
active_organ: organ.organ_id.clone(),
|
active_organ: organ.organ_id.clone(),
|
||||||
organ_mode: "read-only",
|
organ_mode: "read-only",
|
||||||
|
organ_contract: contract,
|
||||||
event_journal: journal.to_string_lossy().into_owned(),
|
event_journal: journal.to_string_lossy().into_owned(),
|
||||||
events,
|
events,
|
||||||
attribution: input.attribution,
|
attribution: input.attribution,
|
||||||
|
|
@ -1590,6 +1795,13 @@ pub fn prepare_persona_code_channel_wake(
|
||||||
prepare_wake_at(&runtime_root, input, &session_id, ×tamp)
|
prepare_wake_at(&runtime_root, input, &session_id, ×tamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn inspect_persona_code_channel_manifest(
|
||||||
|
input: PersonaManifestInspectionInput,
|
||||||
|
) -> Result<PersonaManifestInspectionReceipt, String> {
|
||||||
|
inspect_manifest_at(input)
|
||||||
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn run_persona_code_channel_fact_task(
|
pub async fn run_persona_code_channel_fact_task(
|
||||||
input: PersonaFactTaskInput,
|
input: PersonaFactTaskInput,
|
||||||
|
|
@ -1692,8 +1904,11 @@ mod tests {
|
||||||
},
|
},
|
||||||
"organs": [{
|
"organs": [{
|
||||||
"organId":"fact-sense.repository",
|
"organId":"fact-sense.repository",
|
||||||
|
"kind":"FACT_SENSE",
|
||||||
"mode":"read-only",
|
"mode":"read-only",
|
||||||
"paths":["brain/CORE.hdlp", ".hololake/persona/CURRENT.hdlp"]
|
"paths":["brain/CORE.hdlp", ".hololake/persona/CURRENT.hdlp"],
|
||||||
|
"inputSchema":"hololake.pncc-fact-question/v1",
|
||||||
|
"outputSchema":"hololake.pncc-fact-result/v1"
|
||||||
}]
|
}]
|
||||||
}"#,
|
}"#,
|
||||||
)
|
)
|
||||||
|
|
@ -1784,6 +1999,14 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn manifest_inspection(repo: &Path) -> PersonaManifestInspectionInput {
|
||||||
|
PersonaManifestInspectionInput {
|
||||||
|
repository_path: repo.to_string_lossy().into_owned(),
|
||||||
|
expected_persona_id: "ICE-P-ZY001".into(),
|
||||||
|
expected_head: head(repo),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn prepares_exact_persona_git_wake_with_hash_chained_events() {
|
fn prepares_exact_persona_git_wake_with_hash_chained_events() {
|
||||||
let repo = persona_repo();
|
let repo = persona_repo();
|
||||||
|
|
@ -1801,6 +2024,10 @@ mod tests {
|
||||||
assert_eq!(receipt.runtime_state, "BOUND_NOT_INFERENCING");
|
assert_eq!(receipt.runtime_state, "BOUND_NOT_INFERENCING");
|
||||||
assert!(!receipt.model_inference_started);
|
assert!(!receipt.model_inference_started);
|
||||||
assert_eq!(receipt.active_organ, "fact-sense.repository");
|
assert_eq!(receipt.active_organ, "fact-sense.repository");
|
||||||
|
assert_eq!(receipt.organ_contract.kind, PersonaOrganKind::FactSense);
|
||||||
|
assert!(receipt.organ_contract.model_inference_allowed);
|
||||||
|
assert!(!receipt.organ_contract.reality_actions_allowed);
|
||||||
|
assert!(receipt.organ_contract.activatable);
|
||||||
assert_eq!(receipt.events.len(), 3);
|
assert_eq!(receipt.events.len(), 3);
|
||||||
assert_eq!(receipt.events[0].kind, "WAKING");
|
assert_eq!(receipt.events[0].kind, "WAKING");
|
||||||
assert_eq!(receipt.events[1].kind, "BRAIN_BOUND");
|
assert_eq!(receipt.events[1].kind, "BRAIN_BOUND");
|
||||||
|
|
@ -1842,7 +2069,7 @@ mod tests {
|
||||||
"2026-08-11T00:00:00.000Z",
|
"2026-08-11T00:00:00.000Z",
|
||||||
)
|
)
|
||||||
.unwrap_err()
|
.unwrap_err()
|
||||||
.contains("ORGAN_NOT_ALLOWED"));
|
.contains("ORGAN_NOT_DECLARED"));
|
||||||
|
|
||||||
prepare_wake_at(
|
prepare_wake_at(
|
||||||
runtime.path(),
|
runtime.path(),
|
||||||
|
|
@ -2177,4 +2404,71 @@ mod tests {
|
||||||
assert_eq!(receipt.recovery_action, "RELEASED_DORMANT_LEASE");
|
assert_eq!(receipt.recovery_action, "RELEASED_DORMANT_LEASE");
|
||||||
assert!(!runtime.path().join("leases/ICE-P-ZY001.json").exists());
|
assert!(!runtime.path().join("leases/ICE-P-ZY001.json").exists());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn inspects_normalized_organ_contracts_without_starting_a_runtime() {
|
||||||
|
let repo = persona_repo();
|
||||||
|
let receipt = inspect_manifest_at(manifest_inspection(repo.path())).unwrap();
|
||||||
|
assert_eq!(receipt.persona_id, "ICE-P-ZY001");
|
||||||
|
assert!(receipt.repository_clean);
|
||||||
|
assert_eq!(receipt.organ_contracts.len(), 1);
|
||||||
|
let contract = &receipt.organ_contracts[0];
|
||||||
|
assert_eq!(contract.kind, PersonaOrganKind::FactSense);
|
||||||
|
assert_eq!(contract.mode, "read-only");
|
||||||
|
assert!(contract.activatable);
|
||||||
|
assert!(contract.model_inference_allowed);
|
||||||
|
assert!(!contract.reality_actions_allowed);
|
||||||
|
assert_eq!(contract.implementation_state, "IMPLEMENTED");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn declares_but_refuses_an_execution_limb_without_an_executor() {
|
||||||
|
let repo = persona_repo();
|
||||||
|
let repository = repo.path().canonicalize().unwrap();
|
||||||
|
let manifest_path = repository.join(MANIFEST_PATH);
|
||||||
|
let mut manifest: serde_json::Value =
|
||||||
|
serde_json::from_slice(&fs::read(&manifest_path).unwrap()).unwrap();
|
||||||
|
manifest["organs"]
|
||||||
|
.as_array_mut()
|
||||||
|
.unwrap()
|
||||||
|
.push(serde_json::json!({
|
||||||
|
"organId": "execution-limb.shell",
|
||||||
|
"kind": "EXECUTION_LIMB",
|
||||||
|
"mode": "bounded-execution",
|
||||||
|
"paths": ["brain/CORE.hdlp"],
|
||||||
|
"inputSchema": "hololake.pncc-action-request/v1",
|
||||||
|
"outputSchema": "hololake.pncc-action-receipt/v1"
|
||||||
|
}));
|
||||||
|
fs::write(
|
||||||
|
&manifest_path,
|
||||||
|
serde_json::to_vec_pretty(&manifest).unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
run_git(&repository, &["add", "."]);
|
||||||
|
run_git(&repository, &["commit", "-m", "declare execution limb"]);
|
||||||
|
|
||||||
|
let inspection = inspect_manifest_at(manifest_inspection(&repository)).unwrap();
|
||||||
|
let execution = inspection
|
||||||
|
.organ_contracts
|
||||||
|
.iter()
|
||||||
|
.find(|contract| contract.kind == PersonaOrganKind::ExecutionLimb)
|
||||||
|
.unwrap();
|
||||||
|
assert!(execution.reality_actions_allowed);
|
||||||
|
assert!(!execution.activatable);
|
||||||
|
assert_eq!(
|
||||||
|
execution.implementation_state,
|
||||||
|
"DECLARED_EXECUTOR_NOT_IMPLEMENTED"
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut input = wake_input(&repository);
|
||||||
|
input.organ_id = "execution-limb.shell".into();
|
||||||
|
assert!(prepare_wake_at(
|
||||||
|
tempfile::TempDir::new().unwrap().path(),
|
||||||
|
input,
|
||||||
|
"PNCC-SESSION-EXECUTION-REFUSED",
|
||||||
|
"2026-08-11T00:00:00.000Z",
|
||||||
|
)
|
||||||
|
.unwrap_err()
|
||||||
|
.contains("ORGAN_NOT_ACTIVATABLE"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,7 @@
|
||||||
"human_projection": "HOLOLAKE_LIVE_READ_MODEL",
|
"human_projection": "HOLOLAKE_LIVE_READ_MODEL",
|
||||||
"forgejo_role": "OPTIONAL_COMPATIBILITY_COLLABORATION_ADAPTER",
|
"forgejo_role": "OPTIONAL_COMPATIBILITY_COLLABORATION_ADAPTER",
|
||||||
"runtime_implemented": true,
|
"runtime_implemented": true,
|
||||||
"runtime_scope": "FIRST_READ_ONLY_FACT_CYCLE_AND_FAIL_CLOSED_INTERRUPTED_SESSION_RECOVERY_SOURCE_IMPLEMENTED_AND_TESTED",
|
"runtime_scope": "READ_ONLY_FACT_CYCLE_FAIL_CLOSED_RECOVERY_AND_TYPED_ORGAN_MANIFEST_INSPECTION_SOURCE_IMPLEMENTED_AND_TESTED",
|
||||||
"desktop_integrated": false,
|
"desktop_integrated": false,
|
||||||
"development_id": "DEV-20260810-014"
|
"development_id": "DEV-20260810-014"
|
||||||
},
|
},
|
||||||
|
|
@ -343,7 +343,7 @@
|
||||||
"DEV-20260810-013"
|
"DEV-20260810-013"
|
||||||
],
|
],
|
||||||
"closeout_record": "HLP-DEV-20260809-007-CLOSEOUT-001",
|
"closeout_record": "HLP-DEV-20260809-007-CLOSEOUT-001",
|
||||||
"next_minimum_stage": "GH_PNCC_GENERAL_PURPOSE_ORGAN_CONTRACT_WITHOUT_UI",
|
"next_minimum_stage": "GH_PNCC_DURABLE_EVENT_AND_RECEIPT_QUERY_API_WITHOUT_UI",
|
||||||
"next_stage_started": true,
|
"next_stage_started": true,
|
||||||
"heartbeat_automation": "pncc",
|
"heartbeat_automation": "pncc",
|
||||||
"heartbeat_state": "ACTIVE_EVERY_10_MINUTES_UNTIL_TASK_TERMINAL"
|
"heartbeat_state": "ACTIVE_EVERY_10_MINUTES_UNTIL_TASK_TERMINAL"
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,7 @@
|
||||||
"first_read_only_runtime_cycle_source_implemented": 100,
|
"first_read_only_runtime_cycle_source_implemented": 100,
|
||||||
"persona_git_identity_commit_implemented": 100,
|
"persona_git_identity_commit_implemented": 100,
|
||||||
"interrupted_session_inspection_and_recovery_source_implemented": 100,
|
"interrupted_session_inspection_and_recovery_source_implemented": 100,
|
||||||
|
"typed_organ_contract_and_manifest_inspection_source_implemented": 100,
|
||||||
"general_purpose_persona_runtime_implemented": 0,
|
"general_purpose_persona_runtime_implemented": 0,
|
||||||
"human_live_projection_implemented": 0,
|
"human_live_projection_implemented": 0,
|
||||||
"hololake_integrated": 0,
|
"hololake_integrated": 0,
|
||||||
|
|
|
||||||
|
|
@ -73,12 +73,16 @@ test("the first source runtime cycle stays distinct from integration and deploym
|
||||||
channel.truth.interrupted_session_inspection_and_recovery_source_implemented,
|
channel.truth.interrupted_session_inspection_and_recovery_source_implemented,
|
||||||
100,
|
100,
|
||||||
);
|
);
|
||||||
|
assert.equal(
|
||||||
|
channel.truth.typed_organ_contract_and_manifest_inspection_source_implemented,
|
||||||
|
100,
|
||||||
|
);
|
||||||
assert.equal(channel.truth.general_purpose_persona_runtime_implemented, 0);
|
assert.equal(channel.truth.general_purpose_persona_runtime_implemented, 0);
|
||||||
assert.equal(channel.truth.human_live_projection_implemented, 0);
|
assert.equal(channel.truth.human_live_projection_implemented, 0);
|
||||||
assert.equal(architecture.persona_native_code_channel.runtime_implemented, true);
|
assert.equal(architecture.persona_native_code_channel.runtime_implemented, true);
|
||||||
assert.equal(
|
assert.equal(
|
||||||
architecture.persona_native_code_channel.runtime_scope,
|
architecture.persona_native_code_channel.runtime_scope,
|
||||||
"FIRST_READ_ONLY_FACT_CYCLE_AND_FAIL_CLOSED_INTERRUPTED_SESSION_RECOVERY_SOURCE_IMPLEMENTED_AND_TESTED",
|
"READ_ONLY_FACT_CYCLE_FAIL_CLOSED_RECOVERY_AND_TYPED_ORGAN_MANIFEST_INSPECTION_SOURCE_IMPLEMENTED_AND_TESTED",
|
||||||
);
|
);
|
||||||
assert.equal(channel.truth.hololake_integrated, 0);
|
assert.equal(channel.truth.hololake_integrated, 0);
|
||||||
assert.equal(channel.truth.artifact_built, 0);
|
assert.equal(channel.truth.artifact_built, 0);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue