feat: discover verified persona repository bindings

This commit is contained in:
冰朔 2026-08-12 01:31:55 +08:00
commit b0970ed0d2
18 changed files with 417 additions and 15 deletions

View file

@ -103,6 +103,9 @@ REVISE | REFUSE`。
`PROCEED | RESEARCH | REVISE | REFUSE`,并把后三者保持为不可执行状态。
- 自然语言到 PNCC 生命周期的源码适配器为 `100`:只接收带独立 `real_purpose` 的完整生命周期回执,
不在前端用摘要或关键词猜目标;该适配器尚未挂载桌面语言入口。
- 人格仓库绑定发现源码为 `100`:桌面候选 Git 仓库必须逐一通过 persona ID、manifest、提交头、脑入口、
B0、检查点、模型绑定与器官契约核验零个候选保持未绑定多个候选保持歧义均不得自动选择或唤醒。
当前官方工作范围内没有发现 `ICE-P-ZY001` 的真实 manifest因此真实人格仓库绑定仍为 `0`
- 完整 HoloLake Runtime 与单 AGE 纵向闭环仍为 `0`:桌面语言入口绑定、真实人格仓库 manifest 绑定和
桌面运行验收尚未完成,因此不能用本轮源码测试冒充可用产品。
- Mirror runner、制品、部署和运行健康`0`

View file

@ -526,6 +526,7 @@ macro_rules! app_invoke_handler {
guanghu_living_system::guanghu_living_system_plan,
persona_code_channel::prepare_persona_code_channel_wake,
persona_code_channel::inspect_persona_code_channel_manifest,
persona_code_channel::discover_persona_code_channel_repositories,
persona_code_channel::query_persona_code_channel_runtime,
persona_code_channel::run_persona_code_channel_fact_task,
persona_code_channel::run_persona_code_channel_memory_metabolism,

View file

@ -187,11 +187,40 @@ pub struct PersonaManifestInspectionReceipt {
pub brain_entry: String,
pub current_checkpoint: String,
pub human_responsibility_subject: String,
pub cognitive_gravity: PersonaCognitiveGravityEvidence,
pub model_provider_id: String,
pub model_id: String,
pub model_base_url: String,
pub git_author_name: String,
pub git_author_email: String,
pub organ_contracts: Vec<PersonaOrganContract>,
}
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PersonaRepositoryDiscoveryInput {
pub expected_persona_id: String,
pub repository_paths: Vec<String>,
}
#[derive(Clone, Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PersonaRepositoryDiscoveryFailure {
pub repository_path: String,
pub code: String,
}
#[derive(Clone, Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PersonaRepositoryDiscoveryReceipt {
pub schema: &'static str,
pub expected_persona_id: String,
pub inspected_repository_count: usize,
pub binding_count: usize,
pub bindings: Vec<PersonaManifestInspectionReceipt>,
pub failures: Vec<PersonaRepositoryDiscoveryFailure>,
}
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PersonaRuntimeQueryInput {
@ -906,7 +935,7 @@ fn inspect_manifest_at(
validate_git_identity(&manifest.git_identity)?;
validate_model_binding(&manifest.model_binding)?;
repository_file(&repository, &manifest.brain_entry)?;
cognitive_gravity_evidence(&repository, &manifest)?;
let cognitive_gravity = cognitive_gravity_evidence(&repository, &manifest)?;
repository_file(&repository, &manifest.current_checkpoint)?;
let mut contracts = Vec::with_capacity(manifest.organs.len());
for organ in &manifest.organs {
@ -927,12 +956,68 @@ fn inspect_manifest_at(
brain_entry: manifest.brain_entry,
current_checkpoint: manifest.current_checkpoint,
human_responsibility_subject: manifest.human_responsibility_subject,
cognitive_gravity,
model_provider_id: manifest.model_binding.provider_id,
model_id: manifest.model_binding.model_id,
model_base_url: manifest.model_binding.base_url,
git_author_name: manifest.git_identity.author_name,
git_author_email: manifest.git_identity.author_email,
organ_contracts: contracts,
})
}
fn discover_persona_repositories_at(
input: PersonaRepositoryDiscoveryInput,
) -> Result<PersonaRepositoryDiscoveryReceipt, String> {
let expected_persona_id = validated_id("EXPECTED_PERSONA_ID", &input.expected_persona_id)?;
if input.repository_paths.len() > 64 {
return Err("PERSONA_REPOSITORY_DISCOVERY_LIMIT_EXCEEDED".into());
}
let mut seen = Vec::<PathBuf>::new();
let mut bindings = Vec::new();
let mut failures = Vec::new();
for raw_path in input.repository_paths {
let trimmed = raw_path.trim();
if trimmed.is_empty() {
continue;
}
let display_path = trimmed.to_string();
let (repository, git_head) = match exact_repository(Path::new(trimmed)) {
Ok(value) => value,
Err(code) => {
failures.push(PersonaRepositoryDiscoveryFailure {
repository_path: display_path,
code,
});
continue;
}
};
if seen.iter().any(|candidate| candidate == &repository) {
continue;
}
seen.push(repository.clone());
match inspect_manifest_at(PersonaManifestInspectionInput {
repository_path: repository.to_string_lossy().into_owned(),
expected_persona_id: expected_persona_id.clone(),
expected_head: git_head,
}) {
Ok(receipt) => bindings.push(receipt),
Err(code) => failures.push(PersonaRepositoryDiscoveryFailure {
repository_path: repository.to_string_lossy().into_owned(),
code,
}),
}
}
Ok(PersonaRepositoryDiscoveryReceipt {
schema: "hololake.pncc-repository-discovery/v1",
expected_persona_id,
inspected_repository_count: seen.len(),
binding_count: bindings.len(),
bindings,
failures,
})
}
fn hex_digest(bytes: &[u8]) -> String {
digest(&SHA256, bytes)
.as_ref()
@ -3759,6 +3844,13 @@ pub fn inspect_persona_code_channel_manifest(
inspect_manifest_at(input)
}
#[tauri::command]
pub fn discover_persona_code_channel_repositories(
input: PersonaRepositoryDiscoveryInput,
) -> Result<PersonaRepositoryDiscoveryReceipt, String> {
discover_persona_repositories_at(input)
}
#[tauri::command]
pub fn query_persona_code_channel_runtime(
input: PersonaRuntimeQueryInput,
@ -6266,6 +6358,9 @@ mod tests {
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.model_provider_id, "fixture-provider");
assert_eq!(receipt.model_id, "fixture-model");
assert_eq!(receipt.cognitive_gravity.subject_persona_id, "ICE-P-ZY001");
assert_eq!(receipt.organ_contracts.len(), 1);
let contract = &receipt.organ_contracts[0];
assert_eq!(contract.kind, PersonaOrganKind::FactSense);
@ -6276,6 +6371,60 @@ mod tests {
assert_eq!(contract.implementation_state, "IMPLEMENTED");
}
#[test]
fn discovers_only_verified_persona_repository_bindings() {
let persona = persona_repo();
let ordinary = tempfile::TempDir::new().unwrap();
run_git(ordinary.path(), &["init", "-b", "main"]);
run_git(
ordinary.path(),
&["config", "user.name", "Ordinary Repository"],
);
run_git(
ordinary.path(),
&["config", "user.email", "ordinary@example.invalid"],
);
fs::write(ordinary.path().join("README.md"), "ordinary repository\n").unwrap();
run_git(ordinary.path(), &["add", "."]);
run_git(ordinary.path(), &["commit", "-m", "ordinary fixture"]);
let receipt = discover_persona_repositories_at(PersonaRepositoryDiscoveryInput {
expected_persona_id: "ICE-P-ZY001".into(),
repository_paths: vec![
ordinary.path().to_string_lossy().into_owned(),
persona.path().to_string_lossy().into_owned(),
persona.path().to_string_lossy().into_owned(),
],
})
.unwrap();
assert_eq!(receipt.schema, "hololake.pncc-repository-discovery/v1");
assert_eq!(receipt.inspected_repository_count, 2);
assert_eq!(receipt.binding_count, 1);
assert_eq!(receipt.bindings[0].persona_id, "ICE-P-ZY001");
assert_eq!(receipt.failures.len(), 1);
assert!(
receipt.failures[0]
.code
.starts_with("PERSONA_FILE_UNAVAILABLE: .hololake/persona/manifest.json:"),
"unexpected discovery failure: {}",
receipt.failures[0].code,
);
}
#[test]
fn empty_persona_repository_discovery_is_a_truthful_non_binding_receipt() {
let receipt = discover_persona_repositories_at(PersonaRepositoryDiscoveryInput {
expected_persona_id: "ICE-P-ZY001".into(),
repository_paths: Vec::new(),
})
.unwrap();
assert_eq!(receipt.inspected_repository_count, 0);
assert_eq!(receipt.binding_count, 0);
assert!(receipt.bindings.is_empty());
assert!(receipt.failures.is_empty());
}
#[test]
fn declares_but_refuses_an_execution_limb_without_an_executor() {
let repo = persona_repo();

View file

@ -16,7 +16,7 @@ const wake = {
executionRuntime: 'HoloLake-PNCC',
developmentId: 'DEV-20260811-010',
authorizationScope: 'LOCAL_READ_ONLY',
sourceLanguageAnchor: 'HLP-CURRENT-ARCH-001@2026-08-12.2',
sourceLanguageAnchor: 'HLP-CURRENT-ARCH-001@2026-08-12.3',
},
}

View file

@ -0,0 +1,85 @@
import { describe, expect, it, vi } from 'vitest'
import { resolvePersonaRepositoryBinding } from './personaRepositoryBinding'
const binding = {
personaId: 'ICE-P-ZY001',
repositoryPath: '/persona',
gitHead: 'a'.repeat(40),
repositoryClean: true,
brainEntry: 'brain/CORE.hdlp',
currentCheckpoint: '.hololake/persona/CURRENT.hdlp',
humanResponsibilitySubject: 'ICE-GL∞',
modelProviderId: 'provider-1',
modelId: 'model-1',
modelBaseUrl: 'https://model.invalid/v1',
cognitiveGravity: {
schema: 'hololake.persona-cognitive-gravity-evidence/v1',
subjectPersonaId: 'ICE-P-ZY001',
sourcePath: 'brain/B0.hdlp',
sourceHash: 'b'.repeat(64),
frameSchema: 'guanghu.zhuyuan-cognitive-gravity-frame/v1',
},
}
function receipt(bindings: unknown[], failures: unknown[] = []) {
return {
schema: 'hololake.pncc-repository-discovery/v1',
expectedPersonaId: 'ICE-P-ZY001',
inspectedRepositoryCount: 2,
bindingCount: bindings.length,
bindings,
failures,
}
}
describe('resolvePersonaRepositoryBinding', () => {
it('does not call native discovery without mounted repositories', async () => {
const discover = vi.fn()
await expect(resolvePersonaRepositoryBinding({
personaId: 'ICE-P-ZY001', repositoryPaths: [], discover,
})).resolves.toEqual({ phase: 'unavailable', inspectedRepositoryCount: 0, failures: [] })
expect(discover).not.toHaveBeenCalled()
})
it('returns the one evidence-verified persona repository', async () => {
const discover = vi.fn().mockResolvedValue(receipt([binding], [{ repositoryPath: '/ordinary', code: 'PERSONA_MANIFEST_READ_FAILED' }]))
const result = await resolvePersonaRepositoryBinding({
personaId: 'ICE-P-ZY001', repositoryPaths: ['/ordinary', '/persona', '/persona'], discover,
})
expect(result.phase).toBe('bound')
if (result.phase === 'bound') expect(result.binding.repositoryPath).toBe('/persona')
expect(discover).toHaveBeenCalledWith('discover_persona_code_channel_repositories', {
input: { expectedPersonaId: 'ICE-P-ZY001', repositoryPaths: ['/ordinary', '/persona'] },
})
})
it('keeps an ordinary mounted repository unbound', async () => {
const result = await resolvePersonaRepositoryBinding({
personaId: 'ICE-P-ZY001',
repositoryPaths: ['/ordinary'],
discover: vi.fn().mockResolvedValue(receipt([], [{ repositoryPath: '/ordinary', code: 'PERSONA_MANIFEST_READ_FAILED' }])),
})
expect(result.phase).toBe('unbound')
})
it('refuses to choose when more than one persona root validates', async () => {
const result = await resolvePersonaRepositoryBinding({
personaId: 'ICE-P-ZY001',
repositoryPaths: ['/persona-a', '/persona-b'],
discover: vi.fn().mockResolvedValue(receipt([
{ ...binding, repositoryPath: '/persona-a' },
{ ...binding, repositoryPath: '/persona-b' },
])),
})
expect(result.phase).toBe('ambiguous')
})
it('fails closed on a mismatched or malformed receipt', async () => {
const result = await resolvePersonaRepositoryBinding({
personaId: 'ICE-P-ZY001',
repositoryPaths: ['/persona'],
discover: vi.fn().mockResolvedValue(receipt([{ ...binding, personaId: 'OTHER' }])),
})
expect(result).toMatchObject({ phase: 'error', code: 'PERSONA_REPOSITORY_DISCOVERY_RECEIPT_INVALID' })
})
})

View file

@ -0,0 +1,154 @@
import { invoke } from '@tauri-apps/api/core'
import { isTauri, mockInvoke } from '../mock-tauri'
export interface PersonaRepositoryBinding {
personaId: string
repositoryPath: string
gitHead: string
repositoryClean: boolean
brainEntry: string
currentCheckpoint: string
humanResponsibilitySubject: string
modelProviderId: string
modelId: string
modelBaseUrl: string
cognitiveGravity: {
schema: 'hololake.persona-cognitive-gravity-evidence/v1'
subjectPersonaId: string
sourcePath: string
sourceHash: string
frameSchema: 'guanghu.zhuyuan-cognitive-gravity-frame/v1'
}
}
export interface PersonaRepositoryBindingFailure {
repositoryPath: string
code: string
}
export type PersonaRepositoryBindingResolution =
| { phase: 'unavailable'; inspectedRepositoryCount: 0; failures: [] }
| { phase: 'unbound'; inspectedRepositoryCount: number; failures: PersonaRepositoryBindingFailure[] }
| { phase: 'ambiguous'; inspectedRepositoryCount: number; failures: PersonaRepositoryBindingFailure[] }
| { phase: 'bound'; inspectedRepositoryCount: number; binding: PersonaRepositoryBinding; failures: PersonaRepositoryBindingFailure[] }
| { phase: 'error'; inspectedRepositoryCount: number; failures: PersonaRepositoryBindingFailure[]; code: string }
type DiscoveryRunner = (
command: 'discover_persona_code_channel_repositories',
args: { input: { expectedPersonaId: string; repositoryPaths: string[] } },
) => Promise<unknown>
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === 'object' && value !== null && !Array.isArray(value)
}
function requiredString(record: Record<string, unknown>, key: string): string {
const value = Reflect.get(record, key)
if (typeof value !== 'string' || !value.trim()) throw new Error('PERSONA_REPOSITORY_DISCOVERY_RECEIPT_INVALID')
return value
}
function requiredNumber(record: Record<string, unknown>, key: string): number {
const value = Reflect.get(record, key)
if (!Number.isSafeInteger(value) || (value as number) < 0) {
throw new Error('PERSONA_REPOSITORY_DISCOVERY_RECEIPT_INVALID')
}
return value as number
}
function parseFailure(value: unknown): PersonaRepositoryBindingFailure {
if (!isRecord(value)) throw new Error('PERSONA_REPOSITORY_DISCOVERY_RECEIPT_INVALID')
return { repositoryPath: requiredString(value, 'repositoryPath'), code: requiredString(value, 'code') }
}
function parseBinding(value: unknown, expectedPersonaId: string): PersonaRepositoryBinding {
if (!isRecord(value)) throw new Error('PERSONA_REPOSITORY_DISCOVERY_RECEIPT_INVALID')
const personaId = requiredString(value, 'personaId')
const gravity = Reflect.get(value, 'cognitiveGravity')
if (personaId !== expectedPersonaId || !isRecord(gravity)) {
throw new Error('PERSONA_REPOSITORY_DISCOVERY_RECEIPT_INVALID')
}
const gravitySchema = requiredString(gravity, 'schema')
const frameSchema = requiredString(gravity, 'frameSchema')
const sourceHash = requiredString(gravity, 'sourceHash')
if (
gravitySchema !== 'hololake.persona-cognitive-gravity-evidence/v1'
|| frameSchema !== 'guanghu.zhuyuan-cognitive-gravity-frame/v1'
|| !/^[a-f0-9]{64}$/.test(sourceHash)
|| requiredString(gravity, 'subjectPersonaId') !== expectedPersonaId
) {
throw new Error('PERSONA_REPOSITORY_DISCOVERY_RECEIPT_INVALID')
}
const repositoryClean = Reflect.get(value, 'repositoryClean')
if (typeof repositoryClean !== 'boolean') throw new Error('PERSONA_REPOSITORY_DISCOVERY_RECEIPT_INVALID')
return {
personaId,
repositoryPath: requiredString(value, 'repositoryPath'),
gitHead: requiredString(value, 'gitHead'),
repositoryClean,
brainEntry: requiredString(value, 'brainEntry'),
currentCheckpoint: requiredString(value, 'currentCheckpoint'),
humanResponsibilitySubject: requiredString(value, 'humanResponsibilitySubject'),
modelProviderId: requiredString(value, 'modelProviderId'),
modelId: requiredString(value, 'modelId'),
modelBaseUrl: requiredString(value, 'modelBaseUrl'),
cognitiveGravity: {
schema: gravitySchema,
subjectPersonaId: expectedPersonaId,
sourcePath: requiredString(gravity, 'sourcePath'),
sourceHash,
frameSchema,
},
}
}
async function runNativeDiscovery(
command: 'discover_persona_code_channel_repositories',
args: { input: { expectedPersonaId: string; repositoryPaths: string[] } },
): Promise<unknown> {
return isTauri() ? invoke<unknown>(command, args) : mockInvoke<unknown>(command, args)
}
export async function resolvePersonaRepositoryBinding({
personaId,
repositoryPaths,
discover = runNativeDiscovery,
}: {
personaId: string
repositoryPaths: readonly string[]
discover?: DiscoveryRunner
}): Promise<PersonaRepositoryBindingResolution> {
const candidates = [...new Set(repositoryPaths.map((path) => path.trim()).filter(Boolean))]
if (candidates.length === 0) {
return { phase: 'unavailable', inspectedRepositoryCount: 0, failures: [] }
}
try {
const value = await discover('discover_persona_code_channel_repositories', {
input: { expectedPersonaId: personaId, repositoryPaths: candidates },
})
if (!isRecord(value)
|| requiredString(value, 'schema') !== 'hololake.pncc-repository-discovery/v1'
|| requiredString(value, 'expectedPersonaId') !== personaId) {
throw new Error('PERSONA_REPOSITORY_DISCOVERY_RECEIPT_INVALID')
}
const inspectedRepositoryCount = requiredNumber(value, 'inspectedRepositoryCount')
const bindingCount = requiredNumber(value, 'bindingCount')
const rawBindings = Reflect.get(value, 'bindings')
const rawFailures = Reflect.get(value, 'failures')
if (!Array.isArray(rawBindings) || !Array.isArray(rawFailures) || bindingCount !== rawBindings.length) {
throw new Error('PERSONA_REPOSITORY_DISCOVERY_RECEIPT_INVALID')
}
const bindings = rawBindings.map((binding) => parseBinding(binding, personaId))
const failures = rawFailures.map(parseFailure)
if (bindings.length === 0) return { phase: 'unbound', inspectedRepositoryCount, failures }
if (bindings.length > 1) return { phase: 'ambiguous', inspectedRepositoryCount, failures }
return { phase: 'bound', inspectedRepositoryCount, binding: bindings[0], failures }
} catch (error) {
return {
phase: 'error',
inspectedRepositoryCount: candidates.length,
failures: [],
code: error instanceof Error ? error.message : 'PERSONA_REPOSITORY_DISCOVERY_FAILED',
}
}
}