Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changeset/unified-framework-release.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@spotpatch/runtime": patch
"@spotpatch/bridge": patch
"@spotpatch/astro": patch
"@spotpatch/vite": patch
"@spotpatch/next": patch
---

Publish the restored shared Agent controls and stable managed-model picker through every framework adapter. Astro and Vite now ship the same shared custom picker as local development, while Next continues to load that exact Runtime entry. Include Astro in the packed npm consumer gate and reject release artifacts that retain the retired native Agent/model controls.

Coordinate the post-release Bridge descriptor discovery fixes in the same adapter release plan. Existing consumers must still refresh their lockfile when updating an adapter.
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,12 @@ jobs:
timeout-minutes: 15
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- uses: ./.github/actions/setup
with:
node-version: 22
- name: Require a release plan for package changes
if: github.event_name == 'pull_request' && !startsWith(github.head_ref, 'changeset-release/')
run: pnpm exec changeset status --since=${{ github.event.pull_request.base.sha }}
- run: pnpm package:validate
11 changes: 7 additions & 4 deletions docs/技术方案/00-索引与导航.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
doc-id: "00-index"
title: "索引与导航"
status: "active"
version: "2.12.0"
last-updated: "2026-09-05"
source-range: "原文开篇说明;全量章节导航(非内容迁移);既有核心/AI/Next 导航;组件数据链路目标规范与 Vite + React 18 Beta 实现状态;外部 Agent 交接与主动适配目标规范及本地验证状态;完整 UI 本地开发 P0/P1 实现与后续真实宿主验收规划;浮动工作台已实现基线与持续 Shell 动效目标方案;上下文问答完整目标规范与未实施状态"
version: "2.13.0"
last-updated: "2026-09-09"
source-range: "原文开篇说明;全量章节导航(非内容迁移);既有核心/AI/Next 导航;组件数据链路目标规范与 Vite + React 18 Beta 实现状态;外部 Agent 交接与主动适配目标规范及本地验证状态;完整 UI 本地开发 P0/P1 实现与后续真实宿主验收规划;跨框架 Runtime 与 npm 发布一致性门禁;浮动工作台已实现基线与持续 Shell 动效目标方案;上下文问答完整目标规范与未实施状态"
参考文献/依赖:
- "01-product-boundary"
- "02-architecture-stack"
Expand All @@ -28,6 +28,7 @@ source-range: "原文开篇说明;全量章节导航(非内容迁移);
- "20-local-development-acceptance"
- "21-floating-workbench-island"
- "22-persistent-shell-motion-system"
- "23-framework-runtime-release-parity"
- "context-qa-00-index"
- "context-qa-01-requirements"
- "context-qa-02-audit-compatibility"
Expand Down Expand Up @@ -78,7 +79,7 @@ source-range: "原文开篇说明;全量章节导航(非内容迁移);

# 索引与导航

2026-09-05 新增 [Astro 功能对齐规范与本轮验收](./Astro适配/02-功能对齐实施方案.md)及 [Astro 包使用说明](../../packages/astro/README.md)。当前代码已接入原生/React 岛屿定位、数据链路、Ask、外部 Agent 和 Astro 可信检查;仍未发布 npm。首轮 [源码设计](./Astro适配/00-方案与验收.md)与[验收记录](./Astro适配/01-实施与验证记录.md)保留为历史,不能替代本轮功能证据。
2026-09-05 新增 [Astro 功能对齐规范与本轮验收](./Astro适配/02-功能对齐实施方案.md)及 [Astro 包使用说明](../../packages/astro/README.md)。当前代码已接入原生/React 岛屿定位、数据链路、Ask、外部 Agent 和 Astro 可信检查,公共包已发布;发布版本与本地 Runtime 的一致性由 [跨框架 Runtime 与发布一致性方案](./23-跨框架Runtime与发布一致性方案.md)约束。首轮 [源码设计](./Astro适配/00-方案与验收.md)与[验收记录](./Astro适配/01-实施与验证记录.md)保留为历史,不能替代本轮功能证据。

本文是 SpotPatch v1 核心、v1.1 可选 AI 扩展、v1.2 产品化工作台、Next.js 支持规划与上下文问答目标方案的规范性开发文档。它定义产品边界、支持矩阵、架构、源码组织、模块职责、公共 API、通信协议、安全要求、关键算法、测试方式和验收标准。实现与本文冲突时,应先更新设计决策,再修改代码,避免“代码先跑起来、规则后补”的失控状态。其中 `上下文问答/` 当前仅是已完成的目标设计,不表示代码已实现。

Expand Down Expand Up @@ -111,6 +112,7 @@ docs/技术方案/
├── 20-本地开发与完整产品验收环境.md
├── 21-浮动工作台与灵动岛交互方案.md
├── 22-持续Shell与灵动岛动效系统方案.md
├── 23-跨框架Runtime与发布一致性方案.md
├── 上下文问答/
│ ├── 00-索引与决策摘要.md
│ ├── 01-需求与产品语义.md
Expand Down Expand Up @@ -191,6 +193,7 @@ docs/技术方案/
| [20-本地开发与完整产品验收环境.md](./20-本地开发与完整产品验收环境.md) | (见 doc-id:20-local-development-acceptance) | 已实现唯一完整 playground 与 Runtime 增量构建;确定性假宿主和真实 Agent 兼容 Gate 待完成 |
| [21-浮动工作台与灵动岛交互方案.md](./21-浮动工作台与灵动岛交互方案.md) | (见 doc-id:21-floating-workbench-island) | 默认右下角、自由拖拽、边缘吸附、会话位置恢复、基础入口反馈、旧定位清理和专项验收;Runtime 已实现,真实浏览器视觉验收待完成 |
| [22-持续Shell与灵动岛动效系统方案.md](./22-持续Shell与灵动岛动效系统方案.md) | (见 doc-id:22-persistent-shell-motion-system) | 单一持续 Shell、独立 GSAP Motion bundle、真实状态投影、Agent 派发反馈与执行岛;代码和自动化 Gate 已完成,真实 Chromium Gate 待完成 |
| [23-跨框架Runtime与发布一致性方案.md](./23-跨框架Runtime与发布一致性方案.md) | (见 doc-id:23-framework-runtime-release-parity) | Vite/Astro/Next 共享 Runtime 的源码所有权、Changeset 扇出、packed npm 消费验证与发布事实边界 |
| [上下文问答/00-索引与决策摘要.md](./上下文问答/00-索引与决策摘要.md) | (见 doc-id:context-qa-00-index) | 专题状态、首阶段边界、核心决策、文档地图和规范所有权 |
| [上下文问答/01-需求与产品语义.md](./上下文问答/01-需求与产品语义.md) | (见 doc-id:context-qa-01-requirements) | 至少一目标、单次问答、显式 Ask/Change、引用与转修改草稿 |
| [上下文问答/02-实仓审计与能力矩阵.md](./上下文问答/02-实仓审计与能力矩阵.md) | (见 doc-id:context-qa-02-audit-compatibility) | change-only 根因、可复用资产、官方能力证据和执行器矩阵 |
Expand Down
135 changes: 135 additions & 0 deletions docs/技术方案/23-跨框架Runtime与发布一致性方案.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
---
doc-id: "23-framework-runtime-release-parity"
title: "跨框架 Runtime 与发布一致性方案"
status: "active"
version: "1.0.0"
last-updated: "2026-09-09"
implementation-status: "implemented-pending-release"
source-range: "Vite、Astro、Next 共享浏览器 Runtime 的源码所有权、构建快照、Changeset 扇出、packed npm 消费验证与发布门禁"
参考文献/依赖:
- "02-architecture-stack"
- "05-runtime-lifecycle"
- "10-ui-diagnostics"
- "11-coding-standards"
- "12-testing-acceptance"
- "20-local-development-acceptance"
- "astro-02-feature-parity"
- "next-08-testing-delivery"
---

# 跨框架 Runtime 与发布一致性方案

## 1. 目的与结论

SpotPatch 的通用工作台、Contextual Ask、数据链路、外部 Agent 控件和动效只能由 `@spotpatch/runtime` 持有一份实现。Vite、Astro 与 Next 可以保留各自的编译、注入、开发服务和生命周期适配,但不得复制或分叉通用 UI。React 不是第四个独立 UI 发布面:普通 React 项目由 `@spotpatch/vite` 接入,Next/Astro React 岛屿仍消费同一 Runtime。

2026-09-09 审计确认,源码所有权没有分叉;用户看到的差异来自发布快照漂移:npm `@spotpatch/astro@0.1.6`、`@spotpatch/vite@1.15.2` 和 `@spotpatch/next@0.11.2` 对应发布提交 `586bc03`,而 `main` 随后才合入 `72fc0d7` 与 `9d6683e` 的 Agent 控件/模型选择器修复。修复没有 Changeset,因而没有产生新 npm 版本。重新执行 `@latest` 只能继续安装旧发布物。

本方案修复发布治理和可执行门禁,不把尚未发布的代码描述成已上线版本。只有 Changesets 发布 PR 合并且 npm dist-tag 更新后,状态才能从 `implemented-pending-release` 改为 `released`。

## 2. 实仓架构事实

| 层级 | 当前实现 | 必须保持的约束 |
| --- | --- | --- |
| 通用 UI | `packages/runtime/src/ui/` | Agent、模型、Ask、数据链路、Shell 只在这里实现 |
| Vite | 独立 runtime browser entry,并用 `noExternal` 内联 Runtime | 发布 Vite 包时必须重新构建共享 UI 快照 |
| Astro | `client` 构建组用 `noExternal: [/^@spotpatch\//]` 内联 Runtime | 发布 Astro 包时必须重新构建共享 UI 快照 |
| Next | client 动态导入 `@spotpatch/runtime/external-handoff-panel` | 发布依赖图必须指向本轮 Runtime,宿主不得复制面板 |
| 服务与连接 | `@spotpatch/dev-server` + `@spotpatch/bridge` | 三个适配器使用同一状态协议和降级语义 |

框架间允许存在有证据的差异,例如 Astro 原生标签与 React 业务组件的目标名称、Astro 导航生命周期、Next RSC 边界和各自验证命令。它们不能被错误归类为 UI 漂移。相同语言、viewport、选择上下文和连接状态下,通用控件、文案、可用状态及交互必须一致。

## 3. 本次故障链

1. `@spotpatch/astro@0.1.6` 发布时,外部 Agent 面板仍使用原生 `select`。
2. 后续 Runtime 修复把 Agent 固定值与模型控件改为共享的可访问自定义 picker,并调整发送/模型等待门禁。
3. Astro 与 Vite 都内联 Runtime;已发布 tarball 不会因仓库 Runtime 源码更新而变化。
4. 修复提交没有 Changeset,`changeset status` 没有待 bump 包,发布工作流因此无法生成新版本。
5. 现有 packed npm consumer 只覆盖 Vite/Next,没有打包、安装或检查 Astro;Astro E2E 验证的是当前 workspace 构建,不是待发布 tarball。
6. 既有文档已把“packed package 与 playground UI 一致”列为 P5,但该项尚未实现为阻断发布的自动化。

## 4. 固定发布规则

### 4.1 Changeset 必须存在

普通 PR 只要改变 workspace package,CI 必须对 PR base 执行 `changeset status --since=<base-sha>`。缺少 Changeset 时失败;Changesets 自动生成的版本 PR 不重复要求已经被消费的 Changeset。

### 4.2 共享交付包必须扇出到全部框架适配器

当待发布 Changeset 包含 `@spotpatch/runtime`、`@spotpatch/shared`、`@spotpatch/dev-server` 或 `@spotpatch/bridge` 时,同一发布计划必须包含:

- `@spotpatch/vite`;
- `@spotpatch/astro`;
- `@spotpatch/next`。

这是发布可发现性和适配器版本升级规则,不表示三个框架具有相同的源码编译能力或相同稳定等级。已有项目的锁文件仍须通过包管理器或各适配器的最新版 setup/init 命令显式刷新,不能仅凭 npm dist-tag 变化假定本地依赖已经更新。

### 4.3 发布物而非源码必须通过一致性检查

Node 22.12+ 的 packed npm consumer 必须把 Astro 与所有公共依赖一起打包、安装并验证:

- Astro 的 CommonJS/ESM export 与 `spotpatch-astro` bin 可用;
- Runtime、Vite bundle、Astro bundle 同时包含当前共享 Agent 控件、双语文案和 picker 标识;
- 三个产物不得保留已淘汰的 `.spotpatch-external-control select`;
- Next client 必须继续加载公共 `@spotpatch/runtime/external-handoff-panel`,不得内置第二套面板;
- packed Astro 包能在一次性真实 Astro 宿主中启动开发模式并注入源码 marker,生产构建不得残留 SpotPatch。

Node 20 低于 Astro 包声明的 `>=22.12.0`,其 packed consumer 继续只验证 Vite/Next,不能把跳过 Astro 写成 Astro 通过证据。

### 4.4 构建产物门禁

`package:validate` 在构建之后检查 Runtime、Vite、Astro 和 Next 的正式产物。该门禁用于发现入口分叉、旧 UI 回流和 bundle 漏构建;Runtime DOM 单测与 Astro 5/6/7 浏览器测试继续验证交互行为。

## 5. 本轮发布计划

本轮 Changeset 显式 patch bump:

| 包 | 预期版本 | 原因 |
| --- | --- | --- |
| `@spotpatch/runtime` | `1.15.3` | 发布共享 Agent 控件与稳定 picker 修复 |
| `@spotpatch/bridge` | `0.4.3` | 发布有界、批量的 descriptor discovery 修复 |
| `@spotpatch/astro` | `0.1.7` | 重建并发布新的 Runtime UI 快照与连接依赖 |
| `@spotpatch/vite` | `1.15.3` | 重建并发布相同 Runtime UI 快照 |
| `@spotpatch/next` | `0.11.3` | 为 `@latest` 提供同轮 Runtime/Bridge 发布入口;已有项目仍须刷新锁文件 |

版本号由 Changesets 版本 PR 最终计算;表内版本基于当前 npm/latest 与 patch 规则,不在功能 PR 中手改 package version。

## 6. 验收与发布顺序

功能 PR 合并前至少执行:

```bash
pnpm format:check
pnpm lint
pnpm typecheck
pnpm test:unit
pnpm package:validate
pnpm test:astro
pnpm test:astro:compatibility
pnpm test:compatibility
pnpm test:production-leakage
pnpm test:e2e:chromium
pnpm test:package-beta
```

本功能分支在 2026-09-09 的实测结果:

| 门禁 | 结果 |
| --- | --- |
| Prettier / ESLint / TypeScript | 通过;TypeScript 覆盖根工程及 21 个带 typecheck 的工作区 |
| Unit | 141 个测试文件通过,982 个测试通过;2 个文件/6 个显式条件测试跳过 |
| Package validate | 11 个公共包的 build、publint、Are the Types Wrong 与 4 条产物一致性检查通过 |
| Packed npm consumer | Node 26.0.0 下,Vite 7.3.6、Astro 7.2.8、Next 16.3.0、React 19.2.8 通过 |
| Astro browser | Astro 5/6/7 共 15 条 Chromium 测试通过 |
| Astro production compatibility | Astro 5.18.2、6.4.8、7.2.8 构建及零 Runtime 残留验证通过 |
| Vite production compatibility | Vite 5.4.21、6.4.3 构建及验证通过 |
| Production suite | bundle budget、框架 UI 产物与生产泄漏共 22 条测试通过 |
| Chromium E2E | React/Vite 主 playground 26 条测试通过 |

以上是本地功能分支证据,不等于 GitHub Actions 多系统矩阵或 npm `@latest` 已发布;后两项仍必须按下述发布流程完成。

合并本功能 PR 后,Changesets Action 创建版本 PR;维护者核对五个包的版本、Changelog 和内部依赖,再合并版本 PR。npm 发布完成后必须用官方 registry 核对五个 dist-tag,并在一次性 Astro/Vite/Next 宿主中重新安装 `@latest`。在 npm 核验完成前,不得对用户声称该 UI 已发布。

## 7. 验收边界

本方案提供源码单一所有权、关键 DOM/文案契约、真实构建产物、packed consumer 和 Astro 5/6/7 浏览器交互证据。它不声称不同操作系统的原生字体栅格或浏览器缩放后像素逐点相同,也不改变 Next 公共预览和外部 Agent 实验性能力的成熟度声明。像素级视觉回归仍可在固定字体、DPR 与 Chromium 镜像后增补,但不能替代本方案的结构、状态与发布物门禁。
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"format": "prettier --write .",
"format:check": "prettier --check .",
"lint": "eslint packages playgrounds experiments/next-adapter scripts tests *.ts --max-warnings 0",
"package:validate": "pnpm build && pnpm --filter './packages/*' exec publint && pnpm --filter './packages/*' exec attw --pack .",
"package:validate": "pnpm build && vitest run tests/production/framework-ui-parity.test.ts && pnpm --filter './packages/*' exec publint && pnpm --filter './packages/*' exec attw --pack .",
"release": "pnpm build && changeset publish",
"test": "pnpm test:unit",
"test:compatibility": "pnpm --filter './playgrounds/compat-vite*' build && pnpm --filter './playgrounds/compat-vite*' verify",
Expand Down
3 changes: 3 additions & 0 deletions packages/astro/tsup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ export default defineConfig([
"src/runtime-data-flow.ts",
],
format: ["esm"],
esbuildOptions(options) {
options.charset = "utf8";
},
platform: "browser",
minify: true,
splitting: false,
Expand Down
3 changes: 3 additions & 0 deletions packages/runtime/tsup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ export default defineConfig({
__SPOTPATCH_INLINE_BRAND_MARK__: "true",
},
dts: true,
esbuildOptions(options) {
options.charset = "utf8";
},
entry: {
index: "src/index.ts",
"contextual-ask-panel": "src/contextual-ask-panel-entry.ts",
Expand Down
Loading
Loading