From 9299fc944294bd8e2868c01edb99a0e424f1d58e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=B0=E6=9C=94?= <565183519@qq.com> Date: Wed, 12 Aug 2026 07:02:34 +0800 Subject: [PATCH 1/7] build(hololake): bind mac candidates to exact source --- product-source/hololake-platform/.gitignore | 1 + .../internal-release-packaging/SKILL.md | 9 +- product-source/hololake-platform/package.json | 2 +- .../scripts/build-macos-internal.sh | 17 ++ .../scripts/internal-release-provenance.mjs | 174 ++++++++++++++++++ .../internal-release-provenance.test.mjs | 77 ++++++++ 6 files changed, 278 insertions(+), 2 deletions(-) create mode 100644 product-source/hololake-platform/scripts/internal-release-provenance.mjs create mode 100644 product-source/hololake-platform/scripts/internal-release-provenance.test.mjs diff --git a/product-source/hololake-platform/.gitignore b/product-source/hololake-platform/.gitignore index bd0d42c8a..0683f759b 100644 --- a/product-source/hololake-platform/.gitignore +++ b/product-source/hololake-platform/.gitignore @@ -46,6 +46,7 @@ src-tauri/target # Generated mcp-server bundle (built by scripts/bundle-mcp-server.mjs) src-tauri/resources/mcp-server/ +src-tauri/resources/public-architecture/build-provenance.json # Python cache __pycache__/ diff --git a/product-source/hololake-platform/docs/skills/internal-release-packaging/SKILL.md b/product-source/hololake-platform/docs/skills/internal-release-packaging/SKILL.md index f1ab2768e..62ca4d102 100644 --- a/product-source/hololake-platform/docs/skills/internal-release-packaging/SKILL.md +++ b/product-source/hololake-platform/docs/skills/internal-release-packaging/SKILL.md @@ -26,7 +26,7 @@ pnpm package:internal:windows ## 构建前检查 -1. 工作树干净,当前分支包含目标 UI 和资源。 +1. 工作树干净,当前分支包含目标 UI 和资源,并显式传入当前 `HOLOLAKE_DEVELOPMENT_ID`。 2. `tauri.conf.json`、`Cargo.toml`、`package.json` 版本一致。 3. 运行相关测试、lint、TypeScript/Vite 构建。 4. 确认公共研发入口和 GLS 文件已经进入源码: @@ -45,6 +45,13 @@ pnpm package:internal:windows - Windows 载荷必须为 `PE32+ x86-64`,NSIS 安装包必须存在; - 每个安装包必须生成同名 `.sha256`,回传后再次校验。 +`scripts/internal-release-provenance.mjs` 是来源硬门: + +- 构建前只接受干净工作树,并把 REPO-014 完整提交、根树、`main` 分支、当前架构编号与版本、应用版本、开发编号、分发类型和目标架构写入包内 `build-provenance.json`; +- 打包后必须从应用包中精确找到且只找到一份来源记录,并逐字段回读一致; +- 来源记录在签名前进入应用资源,签名后补写任何文件都会破坏封印,不能作为发布流程; +- 来源记录只证明制品从哪份源码构建,不证明安装、部署、运行健康或人格主控权限。 + 内测 Mac 包是 ad-hoc 签名、未公证;Windows 包在没有商业证书时未做 Authenticode 签名。交付时必须明确说明,不能描述成正式签名发行版。 ## Windows 构建恢复顺序 diff --git a/product-source/hololake-platform/package.json b/product-source/hololake-platform/package.json index 02f376e42..e2e755a19 100644 --- a/product-source/hololake-platform/package.json +++ b/product-source/hololake-platform/package.json @@ -33,7 +33,7 @@ "playwright:integration": "playwright test --config playwright.integration.config.ts", "test:coverage": "node scripts/run-vitest-coverage.mjs", "verify:internal-package": "node scripts/verify-internal-package-content.mjs", - "test:internal-release": "node --test scripts/internal-release-version.test.mjs", + "test:internal-release": "node --test scripts/internal-release-version.test.mjs scripts/internal-release-provenance.test.mjs", "guard:deployment-source": "node scripts/deployment-source-guard.mjs", "test:deployment-source": "node --test scripts/deployment-source-guard.test.mjs", "test:native-authority": "bash scripts/test-guanghu-native-authority.sh && node scripts/validate-guanghu-native-profile.mjs", diff --git a/product-source/hololake-platform/scripts/build-macos-internal.sh b/product-source/hololake-platform/scripts/build-macos-internal.sh index 8d59604a5..614386f6b 100755 --- a/product-source/hololake-platform/scripts/build-macos-internal.sh +++ b/product-source/hololake-platform/scripts/build-macos-internal.sh @@ -7,6 +7,8 @@ cd "$repo_root" [[ "$(uname -s)" == "Darwin" ]] || { echo "macOS internal packages must be built on macOS." >&2; exit 2; } target="${HOLOLAKE_MAC_TARGET:-aarch64-apple-darwin}" +development_id="${HOLOLAKE_DEVELOPMENT_ID:?HOLOLAKE_DEVELOPMENT_ID is required for source-bound packaging}" +distribution="${HOLOLAKE_DISTRIBUTION:-internal}" version="$(node scripts/internal-release-version.mjs src-tauri/tauri.conf.json "${HOLOLAKE_VERSION:-}")" product_name="$(node -e "const fs=require('node:fs'); const value=JSON.parse(fs.readFileSync('src-tauri/tauri.conf.json','utf8')).productName; if(!value) process.exit(1); process.stdout.write(value)")" output_dir="${HOLOLAKE_OUTPUT_DIR:-$repo_root/artifacts/internal/$version}" @@ -14,6 +16,7 @@ target_root="${CARGO_TARGET_DIR:-$repo_root/src-tauri/target}" bundle_dir="$target_root/$target/release/bundle/macos" app="$bundle_dir/${HOLOLAKE_APP_NAME:-$product_name}.app" installer="$output_dir/HoloLake-Era-$version-Mac-internal-aarch64.dmg" +provenance_source="$repo_root/src-tauri/resources/public-architecture/build-provenance.json" tauri_config="${HOLOLAKE_TAURI_CONFIG:-}" if [[ -n "${HOLOLAKE_INSTALLER_BASENAME:-}" ]]; then installer_basename="${HOLOLAKE_INSTALLER_BASENAME//\{version\}/$version}" @@ -30,6 +33,15 @@ else fi command -v hdiutil >/dev/null || { echo "hdiutil is required." >&2; exit 2; } mkdir -p "$output_dir" +[[ ! -e "$provenance_source" ]] || { echo "Stale generated build provenance exists: $provenance_source" >&2; exit 1; } +cleanup_provenance() { rm -f "$provenance_source"; } +trap cleanup_provenance EXIT + +node scripts/internal-release-provenance.mjs generate \ + --output "$provenance_source" \ + --development-id "$development_id" \ + --distribution "$distribution" \ + --target-triple "$target" if [[ "${HOLOLAKE_SKIP_INSTALL:-0}" != "1" ]]; then "${pnpm_cmd[@]}" install --frozen-lockfile @@ -41,6 +53,11 @@ if [[ -n "$tauri_config" ]]; then tauri_args+=(--config "$tauri_config"); fi [[ -d "$app" ]] || { echo "No macOS application bundle was produced: $app" >&2; exit 1; } node scripts/verify-internal-package-content.mjs "$app" +node scripts/internal-release-provenance.mjs verify \ + --bundle "$app" \ + --development-id "$development_id" \ + --distribution "$distribution" \ + --target-triple "$target" codesign --force --deep --sign - "$app" codesign --verify --deep --strict "$app" hdiutil create -volname "HoloLake Era $version Internal" -srcfolder "$app" -ov -format UDZO "$installer" diff --git a/product-source/hololake-platform/scripts/internal-release-provenance.mjs b/product-source/hololake-platform/scripts/internal-release-provenance.mjs new file mode 100644 index 000000000..a7c9b1bee --- /dev/null +++ b/product-source/hololake-platform/scripts/internal-release-provenance.mjs @@ -0,0 +1,174 @@ +#!/usr/bin/env node + +import { execFileSync } from 'node:child_process' +import { mkdir, readFile, readdir, rename, rm, writeFile } from 'node:fs/promises' +import { dirname, join, resolve } from 'node:path' +import { pathToFileURL } from 'node:url' + +const COMMIT_PATTERN = /^[0-9a-f]{40}$/u +const VERSION_PATTERN = /^\d+\.\d+\.\d+$/u +const ARCHITECTURE_VERSION_PATTERN = /^\d{4}-\d{2}-\d{2}\.\d+$/u +const DEVELOPMENT_ID_PATTERN = /^DEV-\d{8}-\d{3}$/u +const CANONICAL_REPOSITORY = 'repo://guanghulab.com/code/bingshuo/hololake-system-architecture' +const CANONICAL_REPOSITORY_ID = 'REPO-014' +const CANONICAL_SOURCE_PATH = 'product-source/hololake-platform' +const PROVENANCE_FILE_NAME = 'build-provenance.json' + +function requireExactString(value, label, pattern) { + if (typeof value !== 'string' || !pattern.test(value)) { + throw new Error(`invalid ${label}`) + } + return value +} + +export function buildInternalReleaseProvenance(input) { + if (input.worktreeClean !== true) { + throw new Error('internal release provenance requires a clean source worktree') + } + if (input.sourceRepository !== CANONICAL_REPOSITORY) { + throw new Error('invalid source repository') + } + if (input.sourceRepositoryId !== CANONICAL_REPOSITORY_ID) { + throw new Error('invalid source repository id') + } + if (input.sourcePath !== CANONICAL_SOURCE_PATH) { + throw new Error('invalid source path') + } + + return { + schema: 'hololake.internal-release-provenance/v1', + architecture: { + id: requireExactString(input.architectureId, 'architecture id', /^HLP-[A-Z0-9-]+$/u), + version: requireExactString(input.architectureVersion, 'architecture version', ARCHITECTURE_VERSION_PATTERN), + }, + build: { + application_version: requireExactString(input.applicationVersion, 'application version', VERSION_PATTERN), + development_id: requireExactString(input.developmentId, 'development id', DEVELOPMENT_ID_PATTERN), + distribution: requireExactString(input.distribution, 'distribution', /^[a-z][a-z0-9-]+$/u), + recorded_at: requireExactString(input.recordedAt, 'recorded at', /^\d{4}-\d{2}-\d{2}T/u), + target_triple: requireExactString(input.targetTriple, 'target triple', /^[a-z0-9-]+$/u), + }, + source: { + branch: requireExactString(input.sourceBranch, 'source branch', /^[A-Za-z0-9._/-]+$/u), + commit: requireExactString(input.sourceCommit, 'source commit', COMMIT_PATTERN), + path: input.sourcePath, + repository: input.sourceRepository, + repository_id: input.sourceRepositoryId, + tree: requireExactString(input.sourceTree, 'source tree', COMMIT_PATTERN), + worktree_clean: true, + }, + } +} + +function expectEqual(actual, expected, label) { + if (actual !== expected) throw new Error(`${label} mismatch`) +} + +export function validateInternalReleaseProvenance(provenance, expected) { + if (!provenance || provenance.schema !== 'hololake.internal-release-provenance/v1') { + throw new Error('provenance schema mismatch') + } + expectEqual(provenance.source?.commit, expected.sourceCommit, 'source commit') + expectEqual(provenance.source?.tree, expected.sourceTree, 'source tree') + expectEqual(provenance.source?.branch, expected.sourceBranch, 'source branch') + expectEqual(provenance.source?.repository, expected.sourceRepository, 'source repository') + expectEqual(provenance.source?.repository_id, expected.sourceRepositoryId, 'source repository id') + expectEqual(provenance.source?.path, expected.sourcePath, 'source path') + expectEqual(provenance.source?.worktree_clean, expected.worktreeClean, 'source worktree state') + expectEqual(provenance.architecture?.id, expected.architectureId, 'architecture id') + expectEqual(provenance.architecture?.version, expected.architectureVersion, 'architecture version') + expectEqual(provenance.build?.application_version, expected.applicationVersion, 'application version') + expectEqual(provenance.build?.development_id, expected.developmentId, 'development id') + expectEqual(provenance.build?.distribution, expected.distribution, 'distribution') + expectEqual(provenance.build?.target_triple, expected.targetTriple, 'target triple') + return true +} + +function git(repositoryRoot, ...args) { + return execFileSync('git', ['-C', repositoryRoot, ...args], { encoding: 'utf8' }).trim() +} + +async function repositoryExpectation({ repositoryRoot, developmentId, distribution, targetTriple }) { + const architecture = JSON.parse(await readFile(join(repositoryRoot, 'routing/hololake-current-architecture.json'), 'utf8')) + const application = JSON.parse(await readFile(join(repositoryRoot, CANONICAL_SOURCE_PATH, 'src-tauri/tauri.conf.json'), 'utf8')) + return { + sourceCommit: git(repositoryRoot, 'rev-parse', 'HEAD'), + sourceTree: git(repositoryRoot, 'rev-parse', 'HEAD^{tree}'), + sourceBranch: git(repositoryRoot, 'branch', '--show-current'), + sourceRepository: CANONICAL_REPOSITORY, + sourceRepositoryId: CANONICAL_REPOSITORY_ID, + sourcePath: CANONICAL_SOURCE_PATH, + architectureId: architecture.architecture_id, + architectureVersion: architecture.version, + applicationVersion: application.version, + developmentId, + distribution, + targetTriple, + worktreeClean: git(repositoryRoot, 'status', '--porcelain=v1', '--untracked-files=all') === '', + } +} + +async function writeJsonAtomic(outputPath, value) { + await mkdir(dirname(outputPath), { recursive: true }) + const temporary = `${outputPath}.${process.pid}.tmp` + await writeFile(temporary, `${JSON.stringify(value, null, 2)}\n`, { flag: 'wx' }) + try { + await rename(temporary, outputPath) + } catch (error) { + await rm(temporary, { force: true }) + throw error + } +} + +async function findProvenanceFiles(directory) { + const found = [] + for (const entry of await readdir(directory, { withFileTypes: true })) { + const entryPath = join(directory, entry.name) + if (entry.isDirectory()) found.push(...await findProvenanceFiles(entryPath)) + else if (entry.isFile() && entry.name === PROVENANCE_FILE_NAME) found.push(entryPath) + } + return found +} + +function option(args, name) { + const index = args.indexOf(name) + if (index === -1 || !args[index + 1]) throw new Error(`${name} is required`) + return args[index + 1] +} + +async function main() { + const [command, ...args] = process.argv.slice(2) + if (!['generate', 'verify'].includes(command)) { + throw new Error('Usage: internal-release-provenance.mjs [options]') + } + + const repositoryRoot = git(process.cwd(), 'rev-parse', '--show-toplevel') + const developmentId = option(args, '--development-id') + const distribution = option(args, '--distribution') + const targetTriple = option(args, '--target-triple') + const expected = await repositoryExpectation({ repositoryRoot, developmentId, distribution, targetTriple }) + + if (command === 'generate') { + const outputPath = resolve(option(args, '--output')) + const provenance = buildInternalReleaseProvenance({ + ...expected, + recordedAt: new Date().toISOString(), + }) + await writeJsonAtomic(outputPath, provenance) + process.stdout.write(`${outputPath}\n`) + return + } + + const bundlePath = resolve(option(args, '--bundle')) + const provenanceFiles = await findProvenanceFiles(bundlePath) + if (provenanceFiles.length !== 1) { + throw new Error(`expected exactly one packaged ${PROVENANCE_FILE_NAME}, found ${provenanceFiles.length}`) + } + const provenance = JSON.parse(await readFile(provenanceFiles[0], 'utf8')) + validateInternalReleaseProvenance(provenance, expected) + process.stdout.write(`${provenanceFiles[0]}\n`) +} + +if (import.meta.url === pathToFileURL(process.argv[1]).href) { + await main() +} diff --git a/product-source/hololake-platform/scripts/internal-release-provenance.test.mjs b/product-source/hololake-platform/scripts/internal-release-provenance.test.mjs new file mode 100644 index 000000000..ea0770af0 --- /dev/null +++ b/product-source/hololake-platform/scripts/internal-release-provenance.test.mjs @@ -0,0 +1,77 @@ +import assert from 'node:assert/strict' +import test from 'node:test' + +import { + buildInternalReleaseProvenance, + validateInternalReleaseProvenance, +} from './internal-release-provenance.mjs' + +const sourceCommit = '1'.repeat(40) +const sourceTree = '2'.repeat(40) + +function input(overrides = {}) { + return { + sourceCommit, + sourceTree, + sourceBranch: 'main', + sourceRepository: 'repo://guanghulab.com/code/bingshuo/hololake-system-architecture', + sourceRepositoryId: 'REPO-014', + sourcePath: 'product-source/hololake-platform', + architectureId: 'HLP-CURRENT-ARCH-001', + architectureVersion: '2026-08-12.16', + applicationVersion: '0.4.6', + developmentId: 'DEV-20260811-010', + distribution: 'local-candidate', + targetTriple: 'aarch64-apple-darwin', + recordedAt: '2026-08-12T07:00:00+08:00', + worktreeClean: true, + ...overrides, + } +} + +test('builds a source-bound local candidate provenance record', () => { + assert.deepEqual(buildInternalReleaseProvenance(input()), { + schema: 'hololake.internal-release-provenance/v1', + architecture: { + id: 'HLP-CURRENT-ARCH-001', + version: '2026-08-12.16', + }, + build: { + application_version: '0.4.6', + development_id: 'DEV-20260811-010', + distribution: 'local-candidate', + recorded_at: '2026-08-12T07:00:00+08:00', + target_triple: 'aarch64-apple-darwin', + }, + source: { + branch: 'main', + commit: sourceCommit, + path: 'product-source/hololake-platform', + repository: 'repo://guanghulab.com/code/bingshuo/hololake-system-architecture', + repository_id: 'REPO-014', + tree: sourceTree, + worktree_clean: true, + }, + }) +}) + +test('refuses to issue provenance for a dirty source tree', () => { + assert.throws( + () => buildInternalReleaseProvenance(input({ worktreeClean: false })), + /clean source worktree/, + ) +}) + +test('validates exact source, architecture, application and development bindings', () => { + const provenance = buildInternalReleaseProvenance(input()) + + assert.equal(validateInternalReleaseProvenance(provenance, input()), true) + assert.throws( + () => validateInternalReleaseProvenance(provenance, input({ sourceCommit: '3'.repeat(40) })), + /source commit mismatch/, + ) + assert.throws( + () => validateInternalReleaseProvenance(provenance, input({ architectureVersion: '2026-08-12.17' })), + /architecture version mismatch/, + ) +}) From b5f8143af2b0f8e681d984a2622875135345c2b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=B0=E6=9C=94?= <565183519@qq.com> Date: Wed, 12 Aug 2026 07:03:13 +0800 Subject: [PATCH 2/7] fix(hololake): label local candidate provenance --- product-source/hololake-platform/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/product-source/hololake-platform/package.json b/product-source/hololake-platform/package.json index e2e755a19..5a4f4009c 100644 --- a/product-source/hololake-platform/package.json +++ b/product-source/hololake-platform/package.json @@ -39,7 +39,7 @@ "test:native-authority": "bash scripts/test-guanghu-native-authority.sh && node scripts/validate-guanghu-native-profile.mjs", "test:native-core": "vitest run --config vitest.guanghu-native.config.ts --coverage", "package:internal:macos": "HOLOLAKE_DISTRIBUTION=personal HOLOLAKE_SOURCE_REPOSITORY_ID=REPO-008 HOLOLAKE_SOURCE_CHANNEL_ID=HLP-CHANNEL-0001 pnpm guard:deployment-source && ./scripts/build-internal-release.sh macos", - "package:local-candidate:macos": "HOLOLAKE_TAURI_CONFIG=src-tauri/tauri.local-candidate.conf.json HOLOLAKE_APP_NAME='HoloLake Era · 本地方向候选 0.4.6' HOLOLAKE_INSTALLER_BASENAME='HoloLake-Era-{version}-Local-Direction-Candidate-Mac-aarch64' ./scripts/build-internal-release.sh macos", + "package:local-candidate:macos": "HOLOLAKE_DISTRIBUTION=local-candidate HOLOLAKE_TAURI_CONFIG=src-tauri/tauri.local-candidate.conf.json HOLOLAKE_APP_NAME='HoloLake Era · 本地方向候选 0.4.6' HOLOLAKE_INSTALLER_BASENAME='HoloLake-Era-{version}-Local-Direction-Candidate-Mac-aarch64' ./scripts/build-internal-release.sh macos", "package:internal:windows": "HOLOLAKE_DISTRIBUTION=personal HOLOLAKE_SOURCE_REPOSITORY_ID=REPO-008 HOLOLAKE_SOURCE_CHANNEL_ID=HLP-CHANNEL-0001 pnpm guard:deployment-source && ./scripts/build-internal-release.sh windows", "package:team:macos": "HOLOLAKE_DISTRIBUTION=team HOLOLAKE_SOURCE_REPOSITORY_ID=REPO-008 HOLOLAKE_SOURCE_CHANNEL_ID=HLP-CHANNEL-0001 pnpm guard:deployment-source && HOLOLAKE_TAURI_CONFIG=src-tauri/tauri.team.conf.json HOLOLAKE_APP_NAME='HoloLake Lighthouse Team Beta 0.2.0' HOLOLAKE_INSTALLER_BASENAME='HoloLake-Lighthouse-{version}-Team-Beta-Mac-aarch64' ./scripts/build-internal-release.sh macos", "package:team:windows": "HOLOLAKE_DISTRIBUTION=team HOLOLAKE_SOURCE_REPOSITORY_ID=REPO-008 HOLOLAKE_SOURCE_CHANNEL_ID=HLP-CHANNEL-0001 pnpm guard:deployment-source && HOLOLAKE_TAURI_CONFIG=src-tauri/tauri.team.conf.json HOLOLAKE_INSTALLER_BASENAME='HoloLake-Era-{version}-Team-Foundation-Windows-x64-setup' ./scripts/build-internal-release.sh windows", From 392d2053414a0c21991808fb9ee462b9e2a8b7ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=B0=E6=9C=94?= <565183519@qq.com> Date: Wed, 12 Aug 2026 07:07:37 +0800 Subject: [PATCH 3/7] fix(hololake): preserve persona boundaries in agent docs --- .../scripts/build-agent-docs.mjs | 25 ++++++++++++++++--- .../scripts/build-agent-docs.test.mjs | 13 +++++++++- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/product-source/hololake-platform/scripts/build-agent-docs.mjs b/product-source/hololake-platform/scripts/build-agent-docs.mjs index 10129a1e4..74a671029 100644 --- a/product-source/hololake-platform/scripts/build-agent-docs.mjs +++ b/product-source/hololake-platform/scripts/build-agent-docs.mjs @@ -115,7 +115,7 @@ function buildIndex(docs) { return lines.join('\n') } -function buildAgentInstructions() { +export function buildAgentInstructions() { return `# AGENTS.md - HoloLake Era Docs Bundle This folder contains local, generated HoloLake Era product docs for AI agents. @@ -127,8 +127,27 @@ Portent is the default best-practice model for structuring HoloLake Era knowledg Recommended lookup flow: 1. Read the active vault's AGENTS.md for vault-specific conventions. -2. Read this folder's index.md for the docs map. -3. Use \`rg\` over this folder for advanced concepts, workflows, shortcuts, Git, AutoGit, AI, Portent, types, properties, relationships, and troubleshooting. +2. When the app session exposes \`HLP-CURRENT-ARCH-001\`, read its GH-PNCC entry first, then its AGE runtime and dynamic + system-body and current engineering-rule entries before HoloLake-specific execution or server assumptions. +3. Read this folder's index.md for the docs map. +4. Use \`rg\` over this folder for advanced concepts, workflows, shortcuts, Git, AutoGit, AI, Portent, types, properties, relationships, and troubleshooting. + +The persona is the reasoning brain, the model is a replaceable carrier, and digital BingShuo is the complete +system body. UI or vault instructions cannot grant server identity. Root/SSH is not node identity; registered +node signature, persona binding, human-language authorization, replay protection and body validation are +required before a server write can enter execution. Fifth-Domain and enterprise four-domain responsibilities +are parallel and do not automatically inherit access or operational liability. + +AGE is the Guanghu persona species; Agent is only an execution mechanism used by AGE. Existing persona ids +remain intact. Runtime pause does not cancel registered existence. Restore a bounded current self and retrieve +old episodes on demand; retrieval indexes are neither the persona nor fact authority. Temporary parallel +workers are scoped, expiring AGE Mirrors and never independent personas or final decision owners. + +One human has one independently operated canonical node: the user's local computer, the user's purchased +server, or a user-owned IDE server deployed by an explicitly authorized team. Guanghu never provides user +runtime servers, never pools users into a shared multi-tenant runtime, never takes custody of private user +data, and never assumes user workload concurrency or fallback execution. Team deployment does not transfer +node ownership. Vault-specific AGENTS.md wins for local conventions. These bundled docs win for HoloLake Era product behavior. ` diff --git a/product-source/hololake-platform/scripts/build-agent-docs.test.mjs b/product-source/hololake-platform/scripts/build-agent-docs.test.mjs index 48299ba20..9ba811a22 100644 --- a/product-source/hololake-platform/scripts/build-agent-docs.test.mjs +++ b/product-source/hololake-platform/scripts/build-agent-docs.test.mjs @@ -1,7 +1,7 @@ import assert from 'node:assert/strict' import test from 'node:test' -import { normalizeDocPath, sectionForFile } from './build-agent-docs.mjs' +import { buildAgentInstructions, normalizeDocPath, sectionForFile } from './build-agent-docs.mjs' test('normalizes Windows doc paths before section grouping', () => { const docPath = normalizeDocPath('concepts\\ai.md') @@ -9,3 +9,14 @@ test('normalizes Windows doc paths before section grouping', () => { assert.equal(docPath, 'concepts/ai.md') assert.equal(sectionForFile(docPath), 'concepts') }) + +test('keeps current persona, system-body and node authority boundaries in every generated bundle', () => { + const instructions = buildAgentInstructions() + + assert.match(instructions, /HLP-CURRENT-ARCH-001/) + assert.match(instructions, /GH-PNCC/) + assert.match(instructions, /AGE is the Guanghu persona species/) + assert.match(instructions, /Root\/SSH is not node identity/) + assert.match(instructions, /One human has one independently operated canonical node/) + assert.match(instructions, /never pools users into a shared multi-tenant runtime/) +}) From dc1a32a52b70fde443a4d7c003847aa018c8cfb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=B0=E6=9C=94?= <565183519@qq.com> Date: Wed, 12 Aug 2026 07:18:46 +0800 Subject: [PATCH 4/7] fix(hololake): avoid no-op agent workspace writes --- .../internal-release-packaging/SKILL.md | 2 ++ .../scripts/local-native-candidate.test.mjs | 2 +- .../src/components/AiWorkspace.test.tsx | 24 +++++++++++++++++++ .../components/aiWorkspaceConversations.ts | 24 ++++++++++++++++--- .../src/lib/aiWorkspaceSessionStore.test.ts | 24 +++++++++++++++++++ .../src/lib/aiWorkspaceSessionStore.ts | 1 - 6 files changed, 72 insertions(+), 5 deletions(-) diff --git a/product-source/hololake-platform/docs/skills/internal-release-packaging/SKILL.md b/product-source/hololake-platform/docs/skills/internal-release-packaging/SKILL.md index 62ca4d102..f20b6e481 100644 --- a/product-source/hololake-platform/docs/skills/internal-release-packaging/SKILL.md +++ b/product-source/hololake-platform/docs/skills/internal-release-packaging/SKILL.md @@ -54,6 +54,8 @@ pnpm package:internal:windows 内测 Mac 包是 ad-hoc 签名、未公证;Windows 包在没有商业证书时未做 Authenticode 签名。交付时必须明确说明,不能描述成正式签名发行版。 +`tauri.local-candidate.conf.json` 的独立 bundle identifier 只保证候选应用可以与已安装版本并存,不隔离运行数据。当前架构仍从共享的 `com.tolaria.app` 命名空间读取设置、挂载知识库和 Agent 会话。需要无扰动验收时,必须用临时 `XDG_CONFIG_HOME` 启动候选,并在临时配置副本上验证;不能把“没有点击保存”当成“没有写盘”。 + ## Windows 构建恢复顺序 1. `pnpm install --frozen-lockfile` diff --git a/product-source/hololake-platform/scripts/local-native-candidate.test.mjs b/product-source/hololake-platform/scripts/local-native-candidate.test.mjs index 2772cb838..5b263246b 100644 --- a/product-source/hololake-platform/scripts/local-native-candidate.test.mjs +++ b/product-source/hololake-platform/scripts/local-native-candidate.test.mjs @@ -4,7 +4,7 @@ import test from 'node:test' const readJson = async path => JSON.parse(await readFile(path, 'utf8')) -test('local native candidate has an isolated macOS identity', async () => { +test('local native candidate has an isolated macOS package identity', async () => { const [base, candidate, packageJson] = await Promise.all([ readJson('src-tauri/tauri.conf.json'), readJson('src-tauri/tauri.local-candidate.conf.json'), diff --git a/product-source/hololake-platform/src/components/AiWorkspace.test.tsx b/product-source/hololake-platform/src/components/AiWorkspace.test.tsx index b4d2ae2bc..a3293eb29 100644 --- a/product-source/hololake-platform/src/components/AiWorkspace.test.tsx +++ b/product-source/hololake-platform/src/components/AiWorkspace.test.tsx @@ -360,6 +360,30 @@ describe('AiWorkspace', () => { expect(screen.queryByRole('button', { name: 'Current work' })).toBeNull() }) + it('does not rewrite unchanged conversation settings when the workspace opens', async () => { + const onConversationSettingsChange = vi.fn() + + render( + , + ) + + await waitFor(() => { + expect(screen.getByRole('button', { name: 'Current work' })).toBeTruthy() + }) + expect(onConversationSettingsChange).not.toHaveBeenCalled() + }) + it('recovers stored sessions that no longer have conversation metadata', async () => { setAiWorkspaceSessionMessages('orphaned-chat', [{ userMessage: 'Recovered prompt', diff --git a/product-source/hololake-platform/src/components/aiWorkspaceConversations.ts b/product-source/hololake-platform/src/components/aiWorkspaceConversations.ts index eaad66b2d..215e398c9 100644 --- a/product-source/hololake-platform/src/components/aiWorkspaceConversations.ts +++ b/product-source/hololake-platform/src/components/aiWorkspaceConversations.ts @@ -197,6 +197,20 @@ function conversationsToSettings(conversations: AiConversation[]): AiWorkspaceCo })) } +function conversationSettingsEqual( + current: AiWorkspaceConversationSetting[], + stored: AiWorkspaceConversationSetting[] | null | undefined, +): boolean { + if (!stored || current.length !== stored.length) return false + return current.every((conversation, index) => { + const persisted = stored[index] + return conversation.archived === (persisted.archived === true) + && conversation.id === persisted.id + && conversation.target_id === (persisted.target_id?.trim() || null) + && conversation.title === persisted.title + }) +} + export function activeConversationForState( conversations: AiConversation[], activeId: ConversationId, @@ -370,10 +384,12 @@ function initialActiveId(conversations: AiConversation[], requestedId: Conversat function useConversationSettingsPersistence({ conversations, onSettingsChange, + settings, settingsReady, }: { conversations: AiConversation[] onSettingsChange?: (conversations: AiWorkspaceConversationSetting[]) => void + settings?: AiWorkspaceConversationSetting[] | null settingsReady: boolean }) { const onSettingsChangeRef = useRef(onSettingsChange) @@ -384,8 +400,10 @@ function useConversationSettingsPersistence({ useEffect(() => { if (!settingsReady) return - onSettingsChangeRef.current?.(conversationsToSettings(conversations)) - }, [conversations, settingsReady]) + const nextSettings = conversationsToSettings(conversations) + if (conversationSettingsEqual(nextSettings, settings)) return + onSettingsChangeRef.current?.(nextSettings) + }, [conversations, settings, settingsReady]) } function useTitleConversationFromAnswer(setConversations: SetConversations) { @@ -490,7 +508,7 @@ export function useConversations({ const titleConversationFromAnswer = useTitleConversationFromAnswer(setConversations) const updateDefaultConversationTargets = useUpdateDefaultConversationTargets(setConversations) - useConversationSettingsPersistence({ conversations, onSettingsChange, settingsReady }) + useConversationSettingsPersistence({ conversations, onSettingsChange, settings, settingsReady }) return { activeId, addConversation, archiveConversation, closeConversation, conversations, deleteConversation, forkConversation, diff --git a/product-source/hololake-platform/src/lib/aiWorkspaceSessionStore.test.ts b/product-source/hololake-platform/src/lib/aiWorkspaceSessionStore.test.ts index e91238f94..4d74c1b7d 100644 --- a/product-source/hololake-platform/src/lib/aiWorkspaceSessionStore.test.ts +++ b/product-source/hololake-platform/src/lib/aiWorkspaceSessionStore.test.ts @@ -178,4 +178,28 @@ describe('aiWorkspaceSessionStore', () => { expect(store.aiWorkspaceSessionSnapshot('native-chat').messages).toHaveLength(1) }) }) + + it('does not rewrite native history when hydration only reads it', async () => { + isTauriState.value = true + invokeMock.mockImplementation(async (command: string) => { + if (command === 'get_ai_workspace_sessions') { + return { + 'native-chat': { + messages: [{ userMessage: 'Native', actions: [], response: 'History', id: 'native-message' }], + status: 'done', + }, + } + } + return undefined + }) + + const store = await import('./aiWorkspaceSessionStore') + + await vi.waitFor(() => { + expect(store.aiWorkspaceSessionSnapshot('native-chat').messages).toHaveLength(1) + }) + await new Promise(resolve => setTimeout(resolve, 300)) + + expect(invokeMock).not.toHaveBeenCalledWith('save_ai_workspace_sessions', expect.anything()) + }) }) diff --git a/product-source/hololake-platform/src/lib/aiWorkspaceSessionStore.ts b/product-source/hololake-platform/src/lib/aiWorkspaceSessionStore.ts index dc94fe39f..e199d38f1 100644 --- a/product-source/hololake-platform/src/lib/aiWorkspaceSessionStore.ts +++ b/product-source/hololake-platform/src/lib/aiWorkspaceSessionStore.ts @@ -160,7 +160,6 @@ async function syncFromNativeStorage(): Promise { const mergedSessions = mergeStoredSessions(sessionStore.getSnapshot(), nativeSessions) sessionStore.replaceSnapshot(mergedSessions) sessionStore.writeStoredSnapshot(mergedSessions) - if (Object.keys(mergedSessions).length > 0) scheduleNativeSessionsWrite(mergedSessions) } function ensureSessionStoreSync(): void { From 1cde630864b8e5e5eec822fdbee66f536b5ff299 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=B0=E6=9C=94?= <565183519@qq.com> Date: Wed, 12 Aug 2026 07:32:17 +0800 Subject: [PATCH 5/7] build(hololake): use runner config loading --- product-source/hololake-platform/package.json | 12 ++++++------ .../scripts/local-native-candidate.test.mjs | 2 ++ .../scripts/run-vitest-coverage.mjs | 4 ++-- product-source/hololake-platform/vite.config.ts | 9 ++++++--- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/product-source/hololake-platform/package.json b/product-source/hololake-platform/package.json index 5a4f4009c..5fc11c5cc 100644 --- a/product-source/hololake-platform/package.json +++ b/product-source/hololake-platform/package.json @@ -8,9 +8,9 @@ "predev": "pnpm test:native-authority", "dev": "vite", "prebuild": "pnpm test:native-authority && pnpm test:native-core", - "build": "tsc -b && vite build", - "build:team-foundation": "VITE_HOLOLAKE_DISTRIBUTION=team-foundation tsc -b && VITE_HOLOLAKE_DISTRIBUTION=team-foundation vite build && node scripts/finalize-team-foundation-build.mjs", - "build:education": "tsc -b && vite build --base=/jd/education/", + "build": "tsc -b && vite build --configLoader runner", + "build:team-foundation": "VITE_HOLOLAKE_DISTRIBUTION=team-foundation tsc -b && VITE_HOLOLAKE_DISTRIBUTION=team-foundation vite build --configLoader runner && node scripts/finalize-team-foundation-build.mjs", + "build:education": "tsc -b && vite build --configLoader runner --base=/jd/education/", "agent-docs": "node scripts/build-agent-docs.mjs", "bundle-mcp": "node scripts/bundle-mcp-server.mjs", "docs:dev": "vitepress dev site --host 127.0.0.1", @@ -25,8 +25,8 @@ "preview": "vite preview", "tauri": "tauri", "pretest": "pnpm test:native-authority", - "test": "vitest run", - "test:watch": "vitest", + "test": "vitest run --configLoader runner", + "test:watch": "vitest --configLoader runner", "test:e2e": "playwright test", "playwright:smoke": "playwright test --config playwright.smoke.config.ts tests/smoke/autosave-low-end-typing.spec.ts tests/smoke/create-note-backing-file.spec.ts tests/smoke/delete-note-nonblocking.spec.ts tests/smoke/example.spec.ts tests/smoke/fix-crash-create-note.spec.ts tests/smoke/quick-open-create-note.spec.ts tests/smoke/save-before-note-switch.spec.ts tests/smoke/h1-untitled-auto-rename.spec.ts tests/smoke/keyboard-command-routing.spec.ts tests/smoke/missing-string-metadata-open-note.spec.ts tests/smoke/multibyte-search-snippet.spec.ts tests/smoke/pull-refresh-open-note.spec.ts tests/smoke/wikilink-path-fix.spec.ts", "playwright:regression": "playwright test tests/smoke/", @@ -37,7 +37,7 @@ "guard:deployment-source": "node scripts/deployment-source-guard.mjs", "test:deployment-source": "node --test scripts/deployment-source-guard.test.mjs", "test:native-authority": "bash scripts/test-guanghu-native-authority.sh && node scripts/validate-guanghu-native-profile.mjs", - "test:native-core": "vitest run --config vitest.guanghu-native.config.ts --coverage", + "test:native-core": "vitest run --config vitest.guanghu-native.config.ts --coverage --configLoader runner", "package:internal:macos": "HOLOLAKE_DISTRIBUTION=personal HOLOLAKE_SOURCE_REPOSITORY_ID=REPO-008 HOLOLAKE_SOURCE_CHANNEL_ID=HLP-CHANNEL-0001 pnpm guard:deployment-source && ./scripts/build-internal-release.sh macos", "package:local-candidate:macos": "HOLOLAKE_DISTRIBUTION=local-candidate HOLOLAKE_TAURI_CONFIG=src-tauri/tauri.local-candidate.conf.json HOLOLAKE_APP_NAME='HoloLake Era · 本地方向候选 0.4.6' HOLOLAKE_INSTALLER_BASENAME='HoloLake-Era-{version}-Local-Direction-Candidate-Mac-aarch64' ./scripts/build-internal-release.sh macos", "package:internal:windows": "HOLOLAKE_DISTRIBUTION=personal HOLOLAKE_SOURCE_REPOSITORY_ID=REPO-008 HOLOLAKE_SOURCE_CHANNEL_ID=HLP-CHANNEL-0001 pnpm guard:deployment-source && ./scripts/build-internal-release.sh windows", diff --git a/product-source/hololake-platform/scripts/local-native-candidate.test.mjs b/product-source/hololake-platform/scripts/local-native-candidate.test.mjs index 5b263246b..a7447450a 100644 --- a/product-source/hololake-platform/scripts/local-native-candidate.test.mjs +++ b/product-source/hololake-platform/scripts/local-native-candidate.test.mjs @@ -20,4 +20,6 @@ test('local native candidate has an isolated macOS package identity', async () = packageJson.scripts['package:local-candidate:macos'], /tauri\.local-candidate\.conf\.json/, ) + assert.match(packageJson.scripts.build, /--configLoader runner/) + assert.match(packageJson.scripts['test:native-core'], /--configLoader runner/) }) diff --git a/product-source/hololake-platform/scripts/run-vitest-coverage.mjs b/product-source/hololake-platform/scripts/run-vitest-coverage.mjs index f67231f54..89b3a92ef 100644 --- a/product-source/hololake-platform/scripts/run-vitest-coverage.mjs +++ b/product-source/hololake-platform/scripts/run-vitest-coverage.mjs @@ -33,8 +33,8 @@ const packageManagerExec = process.env.npm_execpath const isJsExecpath = packageManagerExec && /\.[mc]?js$/i.test(packageManagerExec) const command = isJsExecpath ? process.execPath : 'pnpm' const baseCommandArgs = isJsExecpath - ? [packageManagerExec, 'exec', 'vitest', 'run', '--coverage'] - : ['exec', 'vitest', 'run', '--coverage'] + ? [packageManagerExec, 'exec', 'vitest', 'run', '--coverage', '--configLoader', 'runner'] + : ['exec', 'vitest', 'run', '--coverage', '--configLoader', 'runner'] const clearCacheCommandArgs = isJsExecpath ? [packageManagerExec, 'exec', 'vitest', '--clearCache'] : ['exec', 'vitest', '--clearCache'] diff --git a/product-source/hololake-platform/vite.config.ts b/product-source/hololake-platform/vite.config.ts index 950a30e19..7b24d6b89 100644 --- a/product-source/hololake-platform/vite.config.ts +++ b/product-source/hololake-platform/vite.config.ts @@ -14,11 +14,14 @@ import { type Dirent, } from 'fs' import os from 'os' +import { fileURLToPath } from 'node:url' import { defineConfig, type Plugin } from 'vite' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' import matter from 'gray-matter' +const configDirectory = path.dirname(fileURLToPath(import.meta.url)) + // --- Vault API middleware (dev only) --- interface VaultEntry { @@ -962,7 +965,7 @@ export default defineConfig({ resolve: { alias: { - '@': path.resolve(__dirname, './src'), + '@': path.resolve(configDirectory, './src'), }, }, @@ -972,7 +975,7 @@ export default defineConfig({ define: { ...(process.env.CI || (process.env.TAURI_PLATFORM && !process.env.TAURI_DEBUG) ? {} - : { __DEMO_VAULT_PATH__: JSON.stringify(path.resolve(__dirname, 'demo-vault-v2')) }), + : { __DEMO_VAULT_PATH__: JSON.stringify(path.resolve(configDirectory, 'demo-vault-v2')) }), }, // Prevent vite from obscuring Rust errors @@ -993,7 +996,7 @@ export default defineConfig({ build: { rollupOptions: process.env.VITE_HOLOLAKE_DISTRIBUTION === 'team-foundation' - ? { input: path.resolve(__dirname, 'team-foundation.html') } + ? { input: path.resolve(configDirectory, 'team-foundation.html') } : undefined, // Tauri uses Chromium on Windows and WebKit on macOS/Linux target: process.env.TAURI_PLATFORM === 'windows' ? 'chrome105' : 'safari13', From f01ca6ba5fa6182dc634464ebc33a32126ab00f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=B0=E6=9C=94?= <565183519@qq.com> Date: Wed, 12 Aug 2026 08:00:04 +0800 Subject: [PATCH 6/7] build(hololake): stabilize native quality config loading --- .../scripts/local-native-candidate.test.mjs | 4 ++++ .../scripts/run-hololake-native-quality-gate.sh | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/product-source/hololake-platform/scripts/local-native-candidate.test.mjs b/product-source/hololake-platform/scripts/local-native-candidate.test.mjs index a7447450a..cb853896b 100644 --- a/product-source/hololake-platform/scripts/local-native-candidate.test.mjs +++ b/product-source/hololake-platform/scripts/local-native-candidate.test.mjs @@ -22,4 +22,8 @@ test('local native candidate has an isolated macOS package identity', async () = ) assert.match(packageJson.scripts.build, /--configLoader runner/) assert.match(packageJson.scripts['test:native-core'], /--configLoader runner/) + assert.match( + await readFile('scripts/run-hololake-native-quality-gate.sh', 'utf8'), + /vite build --configLoader runner[\s\S]*vitest run --configLoader runner[\s\S]*--coverage --configLoader runner/, + ) }) diff --git a/product-source/hololake-platform/scripts/run-hololake-native-quality-gate.sh b/product-source/hololake-platform/scripts/run-hololake-native-quality-gate.sh index 6bc6a3e42..4cac32c1b 100755 --- a/product-source/hololake-platform/scripts/run-hololake-native-quality-gate.sh +++ b/product-source/hololake-platform/scripts/run-hololake-native-quality-gate.sh @@ -119,12 +119,12 @@ run_gate frontend_zero_warning_lint \ run_gate frontend_type_contract \ run_package_tool tsc -b run_gate frontend_build \ - run_package_tool vite build + run_package_tool vite build --configLoader runner run_gate frontend_unit_and_integration_tests \ - run_package_tool vitest run + run_package_tool vitest run --configLoader runner run_gate auditable_native_core_lines_and_functions_100 \ run_package_tool vitest run \ - --config vitest.guanghu-native.config.ts --coverage + --config vitest.guanghu-native.config.ts --coverage --configLoader runner run_gate rust_format \ cargo fmt --all --manifest-path "${repository_root}/src-tauri/Cargo.toml" -- --check run_gate rust_unit_and_integration_tests \ From d1c8d7989953147dae95f4b90c9df0d2699073e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=B0=E6=9C=94?= <565183519@qq.com> Date: Wed, 12 Aug 2026 08:06:35 +0800 Subject: [PATCH 7/7] docs(hololake): register current-source candidate --- ...T-SOURCE-LOCAL-CANDIDATE-001-20260812.json | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 deployment/receipts/HLP-CURRENT-SOURCE-LOCAL-CANDIDATE-001-20260812.json diff --git a/deployment/receipts/HLP-CURRENT-SOURCE-LOCAL-CANDIDATE-001-20260812.json b/deployment/receipts/HLP-CURRENT-SOURCE-LOCAL-CANDIDATE-001-20260812.json new file mode 100644 index 000000000..1301b9455 --- /dev/null +++ b/deployment/receipts/HLP-CURRENT-SOURCE-LOCAL-CANDIDATE-001-20260812.json @@ -0,0 +1,52 @@ +{ + "schema": "hololake.current-source-local-candidate-registration-receipt/v1", + "receipt_id": "HLP-CURRENT-SOURCE-LOCAL-CANDIDATE-001-20260812", + "development_id": "DEV-20260811-010", + "repository_id": "REPO-014", + "branch": "main", + "publication_source_commit": "SELF", + "architecture": "HLP-CURRENT-ARCH-001@2026-08-12.16", + "candidate_source": { + "commit": "1cde630864b8e5e5eec822fdbee66f536b5ff299", + "tree": "c420d5993d9e2375e9c6f02763e75ff431aca218", + "application_version": "0.4.6", + "bundle_id": "com.guanghulab.hololake.local-candidate", + "target": "aarch64-apple-darwin", + "dmg_sha256": "cf5606a1a534971c17767f82d696db654a187ede0452683eb4a1dbd5d336bb0a", + "executable_sha256": "e3c1378cbb6ab586950c7a6d297e099ebb4e381ce5c92604fbce434e80b1cd63", + "build_provenance_sha256": "32ec7b597db1f85f754f8cf0c24c3f3662435d757b35e5575b520e74b02da19e" + }, + "verification": { + "frontend_full_suite": "PASS_495_FILES_5067_TESTS", + "native_core": "PASS_15_OF_15_LINES_AND_FUNCTIONS_100", + "native_authority": "PASS_100", + "production_build": "PASS_11062_MODULES", + "package_content": "PASS_100", + "embedded_source_provenance": "PASS_100", + "codesign_deep_strict": "PASS_100", + "dmg_checksum": "PASS_100", + "isolated_world_ui": "PASS_100", + "isolated_agent_workspace_ui": "PASS_100", + "isolated_settings_vaults_sessions_unchanged": "PASS_100", + "real_user_state_unchanged": "PASS_100", + "ghnqg_before_receipt_commit": "PASS_100_AT_f01ca6ba5fa6182dc634464ebc33a32126ab00f5" + }, + "mcp_bundle_boundary": { + "final_build_regeneration": false, + "reuse_source_commit": "392d2053414a0c21991808fb9ee462b9e2a8b7ff", + "inputs_and_locks_changed": false, + "index_js_sha256": "553d690a7723ab9731663ec6dc61b1d5101c348b68ef104f9ff9b4918f5c87c6", + "ws_bridge_js_sha256": "29c67d2a3d194a11f45ed86b350037d63058a4cd4dd4ff9568dc615974f6bb5d", + "claim": "VERIFIED_REUSE_NOT_REGENERATION" + }, + "boundary": { + "candidate_installed": false, + "existing_electron_0_8_0_replaced": false, + "package_identity_is_runtime_data_isolation": false, + "server_deployed": false, + "persona_runtime_health_proven": false, + "trusted_persona_signer_or_key_created": false, + "publication_requires_finalizer_remote_readback": true + }, + "state": "VERIFIED_READY_FOR_PUBLICATION" +}