feat: add hot-pluggable language shell UI system

This commit is contained in:
冰朔 2026-08-10 12:50:28 +08:00
commit 43578222c2
15 changed files with 592 additions and 5 deletions

View file

@ -0,0 +1,36 @@
# HoloLake 可热插拔 UI 系统 · 2026-08-10
> 记录编号:`HLP-HOT-PLUGGABLE-UI-001`
>
> 开发编号:`DEV-20260810-001`
>
> 状态:`SOURCE_RUNTIME_AND_REGISTRY_IMPLEMENTED · NOT_DESKTOP_INTEGRATED · NOT_DEPLOYED`
## 目标与责任边界
冰朔与 UI 人格体负责完整视觉和交互表达HoloLake 功能车道负责语义、权限、执行、验证、
拉取、接线、构建和部署。UI 包可以整体替换语言壳,但不能拥有现实执行权。
```text
UI 人格体提交声明式 UI 包
→ 代码频道登记
→ HoloLake 校验契约和能力请求
→ 原子激活或保留上一套可用 UI
→ 功能桥提供目标、状态、一次确认和人话回执
```
## 已实现
- `hololake.ui-plugin/v1` 类型、校验器、原子激活与回滚运行时;
- 安全视觉变量与完整声明式布局树;
- React 宿主渲染器,使用现有 shadcn 输入和按钮;
- 参考 UI 包、机器可读注册表、跨人格体交付说明和回归测试;
- 禁止系统内部表面、任意脚本、未声明动作和不安全 token 值。
## 事实边界
本阶段建立的是可运行源码边界和登记格式。它尚未替换 HoloLake 当前主页,尚未接入真实意图
编译器也没有形成或安装新的桌面制品。Stage 010 设置页修改仍保持暂停且未合并。
下一阶段是把 Stage 011 的语言目标投影接入本宿主组件,形成“说一句目标 → 理解与计划 →
无边界自动执行 / 有边界只确认一次 → 人话回执”的第一个真实功能闭环。

View file

@ -1,5 +1,17 @@
# Abstractions # Abstractions
## `HoloLakeUiPlugin`
A versioned, declarative presentation package for one host-owned semantic surface. It contains a manifest,
safe `--hl-world-*` tokens, and a layout tree. `validateUiPlugin` is the authority at the renderer boundary;
`createUiPluginRuntime` provides atomic activation, subscriptions, and last-known-good rollback.
## `LanguageShellBridge`
The narrow behavior boundary supplied by the host to a UI package renderer. Version 1 exposes goal submit
and one reality-boundary answer; evidence expansion remains local presentation state. The bridge never gives
the UI package direct repository, node, model, credential, permission, or deployment access.
Key abstractions and domain models in Tolaria. Key abstractions and domain models in Tolaria.
## Design Philosophy ## Design Philosophy

View file

@ -1,5 +1,16 @@
# Architecture # Architecture
## Hot-pluggable language-shell UI
The language shell accepts a complete declarative UI package through
`src/lib/uiPluginSystem.ts`. Packages can replace layout, copy, and safe semantic visual tokens while the
host retains goal compilation, permission checks, execution, and receipt truth. The React host renderer is
`src/components/HotPluggableLanguageShell.tsx`; registered packages live under `ui-plugins/`.
Activation is validate-then-swap and preserves the previous valid package for rollback. Plugin packages do
not execute JavaScript and cannot request system-internal surfaces. Extending the host action bridge requires
a new reviewed contract version.
Tolaria is a personal knowledge and life management desktop app. It reads a vault of markdown files with YAML frontmatter and presents them in a four-panel UI inspired by Bear Notes. Tolaria is a personal knowledge and life management desktop app. It reads a vault of markdown files with YAML frontmatter and presents them in a four-panel UI inspired by Bear Notes.
## Design Principles ## Design Principles

View file

@ -0,0 +1,28 @@
---
status: accepted
date: 2026-08-10
---
# ADR 0173: Declarative hot-pluggable language-shell UI
## Context
HoloLake's visual language needs focused collaboration across independent UI人格体 without giving a
presentation package authority over identity, permission, planning, execution, or receipts. The existing
theme runtime only changes palettes and cannot replace a complete language-shell composition.
## Decision
HoloLake uses versioned declarative UI packages. A package owns layout, safe visual tokens, copy, and asset
references. The host owns semantic state and a small capability bridge. Version 1 exposes only goal submit,
one boundary answer, and evidence expansion. Four human surfaces are mandatory and system-internal surfaces
are forbidden.
Candidates are validated before activation. Activation replaces the whole package atomically and retains a
last-known-good package for rollback. Arbitrary plugin JavaScript is not executed in the desktop renderer.
## Consequences
UI contributors can redesign the complete language shell and publish packages independently. New behaviors
require a reviewed host capability revision, not an undeclared UI action. Repository registration is distinct
from app integration, artifact construction, installation, and runtime health.

View file

@ -218,6 +218,7 @@ proposed → active → superseded
| [0165](0165-guanghu-native-binary-quality-gate.md) | Guanghu-owned binary code-quality authority | active | | [0165](0165-guanghu-native-binary-quality-gate.md) | Guanghu-owned binary code-quality authority | active |
| [0166](0166-ghnrp-hosted-recovery-consumption.md) | Hosted recovery consumes the GHNRP raw beacon | active | | [0166](0166-ghnrp-hosted-recovery-consumption.md) | Hosted recovery consumes the GHNRP raw beacon | active |
| [0167](0167-gestational-history-continuity-ingestion.md) | Gestational history enters Guanghu through a native continuity protocol | active | | [0167](0167-gestational-history-continuity-ingestion.md) | Gestational history enters Guanghu through a native continuity protocol | active |
| [0173](0173-declarative-hot-pluggable-language-shell-ui.md) | Declarative hot-pluggable language-shell UI | active |
| [0168](0168-guanghu-native-prepartition-disk-layout.md) | Guanghu owns a registered pre-partition native disk layout | active | | [0168](0168-guanghu-native-prepartition-disk-layout.md) | Guanghu owns a registered pre-partition native disk layout | active |
| [0169](0169-model-native-living-galaxy-system.md) | Model-native HoloLake living galaxy system | accepted | | [0169](0169-model-native-living-galaxy-system.md) | Model-native HoloLake living galaxy system | accepted |
| [0170](0170-hololake-inherits-guanghu-native-quality-authority.md) | HoloLake inherits the Guanghu native quality authority | accepted | | [0170](0170-hololake-inherits-guanghu-native-quality-authority.md) | HoloLake inherits the Guanghu native quality authority | accepted |

View file

@ -0,0 +1,57 @@
import { fireEvent, render, screen } from '@testing-library/react'
import { describe, expect, it, vi } from 'vitest'
import { DEFAULT_LANGUAGE_WORLD_UI_PLUGIN } from '@/lib/defaultLanguageWorldUiPlugin'
import { HotPluggableLanguageShell } from './HotPluggableLanguageShell'
describe('HotPluggableLanguageShell', () => {
it('renders host truth through a registered package and delegates actions', () => {
const submitGoal = vi.fn()
const answerConfirmation = vi.fn()
render(<HotPluggableLanguageShell
plugin={DEFAULT_LANGUAGE_WORLD_UI_PLUGIN}
state={{
status: '我正在理解并规划',
confirmationQuestion: '这会公开发布,是否继续?',
receipt: '尚未执行。',
evidence: 'boundary=public_release',
}}
bridge={{ submitGoal, answerConfirmation }}
/>)
fireEvent.change(screen.getByLabelText('language goal'), { target: { value: '发布这个版本' } })
fireEvent.click(screen.getByRole('button', { name: '开始' }))
fireEvent.click(screen.getByRole('button', { name: '同意继续' }))
expect(submitGoal).toHaveBeenCalledWith('发布这个版本')
expect(answerConfirmation).toHaveBeenCalledWith(true)
expect(screen.getByRole('status')).toHaveTextContent('我正在理解并规划')
expect(screen.getByText('尚未执行。')).toBeInTheDocument()
})
it('hot-swaps copy and structure when the package changes', () => {
const next = structuredClone(DEFAULT_LANGUAGE_WORLD_UI_PLUGIN)
next.manifest.id = 'bingshuo.language-world'
next.layout.children = [{
kind: 'stack',
children: [
{ kind: 'text', text: '冰朔,今天从哪里继续?' },
{ kind: 'language_input', action: 'goal.submit', text: '进入' },
{ kind: 'task_status' },
{ kind: 'reality_boundary_confirmation', action: 'confirmation.answer', approveText: '继续', declineText: '停下' },
{ kind: 'human_receipt' },
{ kind: 'evidence_toggle', action: 'evidence.expand', text: '依据' },
],
}]
const props = {
state: { status: '等待目标', confirmationQuestion: null, receipt: null },
bridge: { submitGoal: vi.fn(), answerConfirmation: vi.fn() },
}
const view = render(<HotPluggableLanguageShell plugin={DEFAULT_LANGUAGE_WORLD_UI_PLUGIN} {...props} />)
view.rerender(<HotPluggableLanguageShell plugin={next} {...props} />)
expect(screen.getByText('冰朔,今天从哪里继续?')).toBeInTheDocument()
expect(screen.getByRole('button', { name: '进入' })).toBeInTheDocument()
expect(document.querySelector('[data-ui-plugin="bingshuo.language-world"]')).not.toBeNull()
})
})

View file

@ -0,0 +1,74 @@
import { useEffect, useState } from 'react'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import type { HoloLakeUiPlugin, UiPluginNode } from '@/lib/uiPluginSystem'
import { applyUiPluginTokens, validateUiPlugin } from '@/lib/uiPluginSystem'
export type LanguageShellViewState = {
status: string
confirmationQuestion: string | null
receipt: string | null
evidence?: string | null
}
export type LanguageShellBridge = {
submitGoal(goal: string): void
answerConfirmation(approved: boolean): void
}
type Props = {
plugin: HoloLakeUiPlugin
state: LanguageShellViewState
bridge: LanguageShellBridge
}
export function HotPluggableLanguageShell({ plugin, state, bridge }: Props) {
const validation = validateUiPlugin(plugin)
const [goal, setGoal] = useState('')
const [evidenceOpen, setEvidenceOpen] = useState(false)
useEffect(() => {
if (!validation.ok) return
const root = document.documentElement.style
const names = applyUiPluginTokens(plugin, root)
return () => names.forEach((name) => root.removeProperty(name))
}, [plugin, validation.ok])
if (!validation.ok) throw new Error(`UI_PLUGIN_REJECTED:${validation.errors.join(',')}`)
const renderNode = (node: UiPluginNode, path: string): React.ReactNode => {
const children = node.children?.map((child, index) => renderNode(child, `${path}.${index}`))
switch (node.kind) {
case 'shell': return <main key={path} data-ui-plugin={plugin.manifest.id}>{children}</main>
case 'stack': return <section key={path} className="flex flex-col gap-4">{children}</section>
case 'row': return <div key={path} className="flex items-center gap-3">{children}</div>
case 'text': return <p key={path}>{node.text}</p>
case 'language_input': return (
<form key={path} className="flex gap-3" onSubmit={(event) => { event.preventDefault(); bridge.submitGoal(goal) }}>
<Input value={goal} onChange={(event) => setGoal(event.target.value)} aria-label="language goal" />
<Button type="submit">{node.text}</Button>
</form>
)
case 'task_status': return <p key={path} role="status">{state.status}</p>
case 'reality_boundary_confirmation': return state.confirmationQuestion ? (
<section key={path} aria-label="reality boundary confirmation">
<p>{state.confirmationQuestion}</p>
<div className="flex gap-3">
<Button onClick={() => bridge.answerConfirmation(true)}>{node.approveText}</Button>
<Button variant="outline" onClick={() => bridge.answerConfirmation(false)}>{node.declineText}</Button>
</div>
</section>
) : <span key={path} hidden />
case 'human_receipt': return state.receipt ? <p key={path}>{state.receipt}</p> : <span key={path} hidden />
case 'evidence_toggle': return (
<section key={path}>
<Button variant="ghost" onClick={() => setEvidenceOpen((open) => !open)}>{node.text}</Button>
{evidenceOpen && state.evidence ? <pre>{state.evidence}</pre> : null}
</section>
)
case 'button': return <Button key={path}>{node.text}</Button>
}
}
return renderNode(plugin.layout, 'root')
}

View file

@ -0,0 +1,30 @@
import type { HoloLakeUiPlugin } from './uiPluginSystem'
export const DEFAULT_LANGUAGE_WORLD_UI_PLUGIN: HoloLakeUiPlugin = {
manifest: {
schema: 'hololake.ui-plugin/v1',
id: 'guanghu.default-language-world',
version: '1.0.0',
target: 'language_shell',
requestedCapabilities: ['goal.submit', 'confirmation.answer', 'evidence.expand'],
},
tokens: {
'--hl-world-background': '#07111f',
'--hl-world-foreground': '#f6f1df',
'--hl-world-accent': '#d7bd78',
},
layout: {
kind: 'shell',
children: [{
kind: 'stack',
children: [
{ kind: 'text', text: '你想让世界发生什么?' },
{ kind: 'language_input', action: 'goal.submit', text: '开始' },
{ kind: 'task_status' },
{ kind: 'reality_boundary_confirmation', action: 'confirmation.answer', approveText: '同意继续', declineText: '暂不继续' },
{ kind: 'human_receipt' },
{ kind: 'evidence_toggle', action: 'evidence.expand', text: '查看依据' },
],
}],
},
}

View file

@ -0,0 +1,25 @@
import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { describe, expect, it } from 'vitest'
import { validateUiPlugin, type HoloLakeUiPlugin } from './uiPluginSystem'
type Registry = {
schema: string
plugins: Array<{ id: string; version: string; path: string }>
}
describe('registered UI plugins', () => {
it('resolve to valid packages with matching immutable identities', () => {
const root = resolve(process.cwd(), 'ui-plugins')
const registry = JSON.parse(readFileSync(resolve(root, 'registry.json'), 'utf8')) as Registry
expect(registry.schema).toBe('hololake.ui-plugin-registry/v1')
expect(registry.plugins.length).toBeGreaterThan(0)
for (const entry of registry.plugins) {
const plugin = JSON.parse(readFileSync(resolve(root, entry.path), 'utf8')) as HoloLakeUiPlugin
expect(plugin.manifest.id).toBe(entry.id)
expect(plugin.manifest.version).toBe(entry.version)
expect(validateUiPlugin(plugin)).toEqual({ ok: true, errors: [] })
}
})
})

View file

@ -0,0 +1,94 @@
import { describe, expect, it, vi } from 'vitest'
import {
createUiPluginRuntime,
validateUiPlugin,
type HoloLakeUiPlugin,
} from './uiPluginSystem'
const validPlugin = (): HoloLakeUiPlugin => ({
manifest: {
schema: 'hololake.ui-plugin/v1',
id: 'ice-lake.language-world',
version: '1.0.0',
target: 'language_shell',
requestedCapabilities: ['goal.submit', 'confirmation.answer', 'evidence.expand'],
},
tokens: {
'--hl-world-background': '#07111f',
'--hl-world-foreground': '#f6f1df',
'--hl-world-accent': '#d7bd78',
},
layout: {
kind: 'shell',
children: [
{ kind: 'language_input', action: 'goal.submit', text: '开始' },
{ kind: 'task_status' },
{ kind: 'reality_boundary_confirmation', action: 'confirmation.answer', approveText: '继续', declineText: '暂停' },
{ kind: 'human_receipt' },
{ kind: 'evidence_toggle', action: 'evidence.expand', text: '查看依据' },
],
},
})
describe('uiPluginSystem', () => {
it('accepts a complete declarative language-shell package', () => {
expect(validateUiPlugin(validPlugin())).toEqual({ ok: true, errors: [] })
})
it('rejects packages that hide a required human surface', () => {
const plugin = validPlugin()
plugin.layout.children = plugin.layout.children?.filter((node) => node.kind !== 'human_receipt')
expect(validateUiPlugin(plugin)).toEqual({
ok: false,
errors: ['REQUIRED_SURFACE_MISSING:human_receipt'],
})
})
it('rejects internal controls and undeclared actions', () => {
const plugin = validPlugin()
plugin.layout.children?.push({ kind: 'node_identity' as never })
plugin.layout.children?.push({ kind: 'button', action: 'repository.push' as never })
expect(validateUiPlugin(plugin).errors).toEqual([
'SYSTEM_INTERNAL_SURFACE_FORBIDDEN:node_identity',
'ACTION_NOT_ALLOWED:repository.push',
])
})
it('switches complete packages atomically and can roll back', () => {
const first = validPlugin()
const second = validPlugin()
second.manifest.id = 'bingshuo.language-world'
const runtime = createUiPluginRuntime(first)
const listener = vi.fn()
runtime.subscribe(listener)
expect(runtime.activate(second).ok).toBe(true)
expect(runtime.current().manifest.id).toBe('bingshuo.language-world')
expect(listener).toHaveBeenCalledTimes(1)
expect(runtime.rollback()).toBe(true)
expect(runtime.current().manifest.id).toBe('ice-lake.language-world')
})
it('keeps the last-known-good package when a candidate is invalid', () => {
const first = validPlugin()
const invalid = validPlugin()
invalid.layout.children = []
const runtime = createUiPluginRuntime(first)
expect(runtime.activate(invalid).ok).toBe(false)
expect(runtime.current()).toBe(first)
})
it('rejects unsafe token names and values', () => {
const plugin = validPlugin()
plugin.tokens['background'] = 'red'
plugin.tokens['--hl-world-image'] = 'url(javascript:alert(1))'
expect(validateUiPlugin(plugin).errors).toEqual([
'TOKEN_NAME_NOT_ALLOWED:background',
'TOKEN_VALUE_UNSAFE:--hl-world-image',
])
})
})

View file

@ -0,0 +1,150 @@
import { DEFAULT_HUMAN_SURFACE, SYSTEM_INTERNAL_SURFACE } from './languageOperatingModel'
export const HOLOLAKE_UI_PLUGIN_SCHEMA = 'hololake.ui-plugin/v1' as const
export type UiPluginCapability =
| 'goal.submit'
| 'confirmation.answer'
| 'evidence.expand'
export type UiPluginNodeKind =
| 'shell'
| 'stack'
| 'row'
| 'text'
| 'button'
| typeof DEFAULT_HUMAN_SURFACE[number]
| 'evidence_toggle'
export type UiPluginNode = {
kind: UiPluginNodeKind
id?: string
text?: string
approveText?: string
declineText?: string
action?: UiPluginCapability
children?: UiPluginNode[]
}
export type HoloLakeUiPlugin = {
manifest: {
schema: typeof HOLOLAKE_UI_PLUGIN_SCHEMA
id: string
version: string
target: 'language_shell'
requestedCapabilities: UiPluginCapability[]
}
tokens: Record<string, string>
layout: UiPluginNode
}
export type UiPluginValidation = { ok: boolean; errors: string[] }
const ALLOWED_ACTIONS = new Set<UiPluginCapability>([
'goal.submit',
'confirmation.answer',
'evidence.expand',
])
const SAFE_TOKEN_NAME = /^--hl-world-[a-z0-9-]+$/
const UNSAFE_TOKEN_VALUE = /(?:javascript:|expression\s*\(|@import|<\/?script)/i
function walk(node: UiPluginNode, visit: (node: UiPluginNode) => void): void {
visit(node)
node.children?.forEach((child) => walk(child, visit))
}
export function validateUiPlugin(plugin: HoloLakeUiPlugin): UiPluginValidation {
const errors: string[] = []
const seen = new Set<string>()
if (plugin.manifest.schema !== HOLOLAKE_UI_PLUGIN_SCHEMA) errors.push('SCHEMA_NOT_SUPPORTED')
if (!/^[a-z0-9][a-z0-9.-]+$/.test(plugin.manifest.id)) errors.push('PLUGIN_ID_INVALID')
if (!/^\d+\.\d+\.\d+$/.test(plugin.manifest.version)) errors.push('PLUGIN_VERSION_INVALID')
walk(plugin.layout, (node) => {
seen.add(node.kind)
if ((SYSTEM_INTERNAL_SURFACE as readonly string[]).includes(node.kind)) {
errors.push(`SYSTEM_INTERNAL_SURFACE_FORBIDDEN:${node.kind}`)
}
const actionAllowed = !node.action || ALLOWED_ACTIONS.has(node.action)
if (node.action && !actionAllowed) {
errors.push(`ACTION_NOT_ALLOWED:${node.action}`)
}
if (node.action && actionAllowed && !plugin.manifest.requestedCapabilities.includes(node.action)) {
errors.push(`ACTION_NOT_DECLARED:${node.action}`)
}
if (node.kind === 'language_input' && !node.text?.trim()) errors.push('COPY_REQUIRED:language_input')
if (node.kind === 'reality_boundary_confirmation'
&& (!node.approveText?.trim() || !node.declineText?.trim())) {
errors.push('COPY_REQUIRED:reality_boundary_confirmation')
}
if (node.kind === 'evidence_toggle' && !node.text?.trim()) errors.push('COPY_REQUIRED:evidence_toggle')
})
for (const surface of DEFAULT_HUMAN_SURFACE) {
if (!seen.has(surface)) errors.push(`REQUIRED_SURFACE_MISSING:${surface}`)
}
for (const capability of plugin.manifest.requestedCapabilities) {
if (!ALLOWED_ACTIONS.has(capability)) errors.push(`CAPABILITY_NOT_ALLOWED:${capability}`)
}
for (const [name, value] of Object.entries(plugin.tokens)) {
if (!SAFE_TOKEN_NAME.test(name)) errors.push(`TOKEN_NAME_NOT_ALLOWED:${name}`)
if (UNSAFE_TOKEN_VALUE.test(value)) errors.push(`TOKEN_VALUE_UNSAFE:${name}`)
}
return { ok: errors.length === 0, errors }
}
export type UiPluginRuntime = {
current(): HoloLakeUiPlugin
activate(candidate: HoloLakeUiPlugin): UiPluginValidation
rollback(): boolean
subscribe(listener: (plugin: HoloLakeUiPlugin) => void): () => void
}
export function createUiPluginRuntime(initial: HoloLakeUiPlugin): UiPluginRuntime {
const initialValidation = validateUiPlugin(initial)
if (!initialValidation.ok) throw new Error(initialValidation.errors.join(','))
let active = initial
let previous: HoloLakeUiPlugin | null = null
const listeners = new Set<(plugin: HoloLakeUiPlugin) => void>()
const publish = () => listeners.forEach((listener) => listener(active))
return {
current: () => active,
activate(candidate) {
const result = validateUiPlugin(candidate)
if (!result.ok) return result
previous = active
active = candidate
publish()
return result
},
rollback() {
if (!previous) return false
const replacement = previous
previous = active
active = replacement
publish()
return true
},
subscribe(listener) {
listeners.add(listener)
return () => listeners.delete(listener)
},
}
}
export function applyUiPluginTokens(
plugin: HoloLakeUiPlugin,
target: Pick<CSSStyleDeclaration, 'setProperty' | 'removeProperty'>,
previousTokenNames: readonly string[] = [],
): string[] {
previousTokenNames.forEach((name) => target.removeProperty(name))
Object.entries(plugin.tokens).forEach(([name, value]) => target.setProperty(name, value))
return Object.keys(plugin.tokens)
}

View file

@ -0,0 +1,21 @@
# HoloLake UI 插件交付入口
这里是 UI 人格体与 HoloLake 功能实现之间的稳定边界。UI 贡献者可以提交完整的语言壳布局、
视觉变量、文案和素材引用;功能内核仍由 HoloLake 宿主提供。
## 交付步骤
1. 复制 `packages/guanghu.default-language-world/ui-package.json`
2. 修改 `manifest.id`、语义化 `version``tokens``layout`
3. 保留四个必需表面:`language_input``task_status`
`reality_boundary_confirmation``human_receipt`
4. 只使用三项宿主动作:`goal.submit``confirmation.answer``evidence.expand`
5. 把包加入 `registry.json`,运行:
`pnpm exec vitest run src/lib/uiPluginSystem.test.ts src/lib/uiPluginRegistry.test.ts`
6. 提交到独立分支并附截图。合并、构建、部署由 HoloLake 功能车道完成。
UI 包是声明式数据,不接受任意 JavaScript。它可以重排整套语言壳并替换全部视觉表达
但不能读取节点身份、仓库路由、模型配置、凭据或部署日志,也不能直接执行现实动作。
宿主先校验候选包,再原子切换;校验或渲染失败时保留上一套可用 UI。代码频道发布只证明
UI 包已登记,不等于桌面制品已经接入或部署。

View file

@ -0,0 +1,30 @@
{
"manifest": {
"schema": "hololake.ui-plugin/v1",
"id": "guanghu.default-language-world",
"version": "1.0.0",
"target": "language_shell",
"requestedCapabilities": ["goal.submit", "confirmation.answer", "evidence.expand"]
},
"tokens": {
"--hl-world-background": "#07111f",
"--hl-world-foreground": "#f6f1df",
"--hl-world-accent": "#d7bd78"
},
"layout": {
"kind": "shell",
"children": [
{
"kind": "stack",
"children": [
{ "kind": "text", "text": "你想让世界发生什么?" },
{ "kind": "language_input", "action": "goal.submit", "text": "开始" },
{ "kind": "task_status" },
{ "kind": "reality_boundary_confirmation", "action": "confirmation.answer", "approveText": "同意继续", "declineText": "暂不继续" },
{ "kind": "human_receipt" },
{ "kind": "evidence_toggle", "action": "evidence.expand", "text": "查看依据" }
]
}
]
}
}

View file

@ -0,0 +1,11 @@
{
"schema": "hololake.ui-plugin-registry/v1",
"plugins": [
{
"id": "guanghu.default-language-world",
"version": "1.0.0",
"path": "packages/guanghu.default-language-world/ui-package.json",
"state": "REFERENCE_LAST_KNOWN_GOOD"
}
]
}

View file

@ -1,7 +1,7 @@
{ {
"schema": "hololake.current-architecture/v1", "schema": "hololake.current-architecture/v1",
"architecture_id": "HLP-CURRENT-ARCH-001", "architecture_id": "HLP-CURRENT-ARCH-001",
"version": "2026-08-10.4", "version": "2026-08-10.5",
"state": "CURRENT_CANONICAL", "state": "CURRENT_CANONICAL",
"product": { "product": {
"formal_name": "光湖语言系统 · 通用人工智能操作平台", "formal_name": "光湖语言系统 · 通用人工智能操作平台",
@ -14,6 +14,7 @@
"product-source/hololake-platform/architecture/HOLOLAKE-SYMBIOTIC-PERSONA-ORIGIN-AND-BOUNDARY-20260809.md", "product-source/hololake-platform/architecture/HOLOLAKE-SYMBIOTIC-PERSONA-ORIGIN-AND-BOUNDARY-20260809.md",
"product-source/hololake-platform/architecture/HOLOLAKE-LANGUAGE-PERSONA-DRIVEN-OPERATING-MODEL-20260810.md", "product-source/hololake-platform/architecture/HOLOLAKE-LANGUAGE-PERSONA-DRIVEN-OPERATING-MODEL-20260810.md",
"product-source/hololake-platform/architecture/HOLOLAKE-LAKE-SURFACE-VISUAL-AND-AMBIENT-DWELLING-FORM-20260810.md", "product-source/hololake-platform/architecture/HOLOLAKE-LAKE-SURFACE-VISUAL-AND-AMBIENT-DWELLING-FORM-20260810.md",
"product-source/hololake-platform/architecture/HOLOLAKE-HOT-PLUGGABLE-UI-SYSTEM-20260810.md",
"product-source/hololake-platform/architecture/HOLOLAKE-LANGUAGE-SHELL-STAGE-011-IMPLEMENTATION-20260810.md", "product-source/hololake-platform/architecture/HOLOLAKE-LANGUAGE-SHELL-STAGE-011-IMPLEMENTATION-20260810.md",
"product-source/hololake-platform/architecture/HOLOLAKE-INTENT-REASONING-MAP-20260809.md", "product-source/hololake-platform/architecture/HOLOLAKE-INTENT-REASONING-MAP-20260809.md",
"product-source/hololake-platform/architecture/HOLOLAKE-SYSTEM-ARCHITECTURE-20260809.md", "product-source/hololake-platform/architecture/HOLOLAKE-SYSTEM-ARCHITECTURE-20260809.md",
@ -84,6 +85,12 @@
"implementation": "product-source/hololake-platform/src/lib/languageOperatingModel.ts", "implementation": "product-source/hololake-platform/src/lib/languageOperatingModel.ts",
"tests": "product-source/hololake-platform/src/lib/languageOperatingModel.test.ts", "tests": "product-source/hololake-platform/src/lib/languageOperatingModel.test.ts",
"focused_tests": "5_OF_5_PASS" "focused_tests": "5_OF_5_PASS"
},
"ui_plugin_system": {
"record_id": "HLP-HOT-PLUGGABLE-UI-001",
"schema": "hololake.ui-plugin/v1",
"state": "SOURCE_RUNTIME_AND_REGISTRY_IMPLEMENTED_NOT_DESKTOP_INTEGRATED_NOT_DEPLOYED",
"registry": "product-source/hololake-platform/ui-plugins/registry.json"
} }
}, },
"current_product_assessment": { "current_product_assessment": {
@ -94,11 +101,11 @@
"final_plan_complete": false "final_plan_complete": false
}, },
"continuity": { "continuity": {
"development_id": "DEV-20260809-007", "development_id": "DEV-20260810-001",
"state": "CLOSED_BY_BINGSHUO_CONTINUE_IN_NEW_CONVERSATION", "state": "ACTIVE_HOT_PLUGGABLE_UI_SYSTEM",
"closeout_record": "HLP-DEV-20260809-007-CLOSEOUT-001", "closeout_record": "HLP-DEV-20260809-007-CLOSEOUT-001",
"next_minimum_stage": "LANGUAGE_GOAL_TO_SINGLE_BOUNDARY_CONFIRMATION_TO_HUMAN_RECEIPT_UI", "next_minimum_stage": "INTEGRATE_LANGUAGE_GOAL_RUNTIME_WITH_HOT_PLUGGABLE_UI_HOST",
"next_stage_started": false, "next_stage_started": true,
"heartbeat_automation": "DELETED_2026-08-10" "heartbeat_automation": "DELETED_2026-08-10"
}, },
"truth_boundary": { "truth_boundary": {