合并master并解决资源画布冲突
合并 origin/master 最新提交 保留精修事务、候选图层与失败门户逻辑 同步生成恢复、Direct Codex 清理和资源画布删除交互
This commit is contained in:
@@ -164,12 +164,14 @@
|
||||
3. 回合结束时客户端只确定性复核安全与最低来源边界:可信平台图片、身份与同 Canvas 关系成立,`game/index.html` 存在,游戏源码至少引用一份已登记陶泥儿图片。随后由受限 Chromium 对 desktop/mobile 做真实运行、截图、异常、交互及 Canvas/WebGL 图片渲染观察,并把缺口回灌同一 Codex thread 有界整改。固定四切片、固定文件名和固定 `drawImage` 次数不再阻断完成;最终仍未观察到平台素材进入任一视口核心渲染时才拒绝登记版本。详细契约以第 13 节为准。
|
||||
4. 资源画布增加“游戏代码”分区。HTML、CSS、JavaScript 和其它可执行源码进入该分区;玩法说明、配置和 Agent 文本回执仍归“文档”。已有资源布局若没有代码分区位置,将由现有布局 reconcile 自动补位。
|
||||
5. 产品界面只展示“陶泥儿”“智能创作”等产品术语;Codex app-server 仅保留为内部执行实现和开发诊断名称,不在普通项目聊天、首页创建状态或设置说明中直接暴露。
|
||||
6. 每次直连回合在游戏代码复核与登记成功后,必须在项目写锁内推进一次 durable project revision,并以该 revision 创建首个 `initial-*` 或后续 `agent-*` 正式版本。禁止修改 manifest 后沿用旧 revision;外层工作台会把同 revision 的不同 manifest 判为冲突并拒绝投影,表现为磁盘已有游戏代码和版本、客户端仍显示 0 项。
|
||||
7. direct app-server 禁用 shell / unified exec 时仍必须能可靠修改已有游戏。每轮系统提示词在大段仓库文档之前注入当前 `game/index.html`、`game/style.css`、`game/game.js` 的有界脱敏快照,使 Codex 的原生 file-change 能基于真实旧内容生成补丁;不得退化为猜测变量名的盲补丁。回合前后以三个代码文件的内容指纹判断是否发生真实修改;无修改且 manifest 已同步的回合不得推进 revision 或伪造新项目版本。
|
||||
6. 项目与首页 direct 系统提示词必须把对外产品身份固定为“陶泥儿”。询问身份、名称或能力时以陶泥儿自称,不把 Codex、ChatGPT、OpenAI、模型或通用 AI 助手当作名称;只有用户明确询问底层实现时才可说明内部使用 Codex app-server,并继续保持陶泥儿这一对外身份。direct 缺失 system message 时使用同一陶泥儿兜底,legacy ToolHost 的内部 Codex 技术提示保持独立。
|
||||
7. 每次直连回合在游戏代码复核与登记成功后,必须在项目写锁内推进一次 durable project revision,并以该 revision 创建首个 `initial-*` 或后续 `agent-*` 正式版本。禁止修改 manifest 后沿用旧 revision;外层工作台会把同 revision 的不同 manifest 判为冲突并拒绝投影,表现为磁盘已有游戏代码和版本、客户端仍显示 0 项。
|
||||
8. direct app-server 禁用 shell / unified exec 时仍必须能可靠修改已有游戏。每轮系统提示词在大段仓库文档之前注入当前 `game/index.html`、`game/style.css`、`game/game.js` 的有界脱敏快照,使 Codex 的原生 file-change 能基于真实旧内容生成补丁;不得退化为猜测变量名的盲补丁。回合前后以三个代码文件的内容指纹判断是否发生真实修改;无修改且 manifest 已同步的回合不得推进 revision 或伪造新项目版本。
|
||||
|
||||
### 验收
|
||||
|
||||
- Rust 单测覆盖:可信完整图集缺少固定切片仍可进入 Codex;只有规范图和背景图但历史图集不可安全恢复时不得重复发起付费生成;缺可信平台图片、来源身份不成立、PNG 不可解码或源码完全没有平台素材引用时继续拒绝完成。浏览器证据测试必须区分旁侧 `<img>` 与 Canvas/WebGL 实际渲染,并证明 desktop/mobile 任一视口缺少核心素材观察都会回灌同 thread 整改。
|
||||
- 身份合同测试覆盖项目 prompt、首页 prompt 与 direct 缺省 baseInstructions 均以陶泥儿为对外身份,同时证明 legacy ToolHost 的内部 Codex fallback 未被改写。客户端完整重启后,用同一项目分别询问“你是谁”和“你是不是 Codex”,回复必须以陶泥儿自称;仅在第二问可补充底层执行技术。
|
||||
- 资源投影与 AppSurface 测试覆盖:`game/index.html`、`game/style.css`、`game/game.js` 显示于“游戏代码”,不再显示于“文档”。
|
||||
- 连续两次直连回合必须保留同一批游戏代码资产 ID,project revision 单调推进,并形成 `initial-* -> agent-*` 的父子版本链;外层资源管理在新 revision 到达后显示游戏代码和项目版本,不能停留在生成前快照。
|
||||
- 已有项目修改测试必须证明系统提示词包含有界当前游戏源码、敏感行被过滤,基于该上下文的 file-change 可以命中;Codex 明确未修改文件时,revision 与版本数量保持不变。
|
||||
@@ -310,7 +312,7 @@
|
||||
|
||||
### 14.2 审核索引与五类 Skill
|
||||
|
||||
客户端内置 `agc-skill-pack.v1` 清单。每项只公开名称、用途、触发条件、所需工具、版本和内容 SHA-256;审核文件变化时必须在同次变更重算对应指纹。启动时逐文件复核清单和编译进客户端的内容,任何缺失、额外文件、路径越界或指纹不匹配都失败关闭;路径边界显式拒绝反斜杠、Windows 盘符、UNC、绝对路径和 `..`,不能因测试运行在 Linux 就把 Windows 绝对路径当作普通相对文件名。审核包只包含:
|
||||
客户端内置 `agc-skill-pack.v1` 清单。每项只公开名称、用途、触发条件、所需工具、版本和内容 SHA-256;审核文本统一按 UTF-8 读取并将 CRLF 规范为 LF 后计算指纹和安装,避免编辑器产生的混合换行让同一 Git 内容在 Windows 与 Linux 上得到不同结果。审核文件的语义内容变化时必须在同次变更重算对应指纹并提升版本。启动时逐文件复核清单和编译进客户端的内容,任何缺失、额外文件、路径越界、非 UTF-8 内容或规范化后的指纹不匹配都失败关闭;路径边界显式拒绝反斜杠、Windows 盘符、UNC、绝对路径和 `..`,不能因测试运行在 Linux 就把 Windows 绝对路径当作普通相对文件名。审核包只包含:
|
||||
|
||||
1. `agc-project-structure`:项目根、`game/`、`assets/`、`.agent/` 的职责和禁止创建平行项目的约束。
|
||||
2. `taonier-art-assets`:陶泥儿标准美术包、平台来源、警告语义和真实素材使用;`grid-2x2` 与四切片只是推荐路径,不是所有游戏的完成门。
|
||||
@@ -357,3 +359,49 @@ DirectHome 继续禁用 MCP、命令和写入。DirectProject 仍禁用通用 sh
|
||||
- 同一真实项目已由 Codex 把平台背景、规范图棋子和核心图集实际接入 `game/index.html / style.css / game.js`。真实 Chromium 报告 `passed=true`:desktop/mobile 均为 `readyState=complete`、Canvas 非空、无 console error 与 exception;desktop 仅有非致命 `favicon.ico` 404。两张截图确认桌面和手机均完整显示甜点星球三消画面,且结构化运行时证据观察到平台图片进入渲染。
|
||||
- 真实复跑同时暴露并修复两个收尾缺陷:DirectProject 不能沿用普通 LLM 的 180 秒整回合超时,现改为 15 分钟基础空闲窗口、MCP 工具活动期 110 分钟空闲窗口、整个 turn 120 分钟硬上限;DirectHome 与旧 ToolHost 继续保持原超时。系统提示词和浏览器整改回灌同时明确 shell/unified_exec 被安全禁用时应使用已注入的游戏文件快照与结构化证据,不得误报“没有读取工具所以无法验收”,也不得要求 Codex 直接保存 `.agent` 版本。定向回归为 Direct Runtime 35/35、Codex app-server 23/23(另 1 项真实账号测试按设计 ignored)。
|
||||
- 最后一轮改后 GUI 复验在桌面控制被物理 Escape 中止后未继续自动操作;非 UI CLI 又因不继承 GUI 登录态而得到 `usage-limit-exceeded`。因此本节只把已落盘的真实生图、幂等复用和双视口浏览器证据记为已完成,不把改后最终聊天回复或新增项目版本伪报为已验收;下次从当前客户端发送普通项目消息即可复核新的等待窗口与证据回灌文案。
|
||||
|
||||
## 15. Direct Interaction Event v1 合同(2026-08-22)
|
||||
|
||||
### 15.1 现役缺口与目标
|
||||
|
||||
现役 direct 链路虽然在 app-server 内部能接收消息增量,但普通项目聊天仍主要等待 Tauri command 完整返回后才展示助手正文;旧 `game-creator-agent-progress` 只能表达少量阶段,不能作为 direct 回合的正文增量、顺序、终态和隔离合同。本次新增 Direct Interaction Event v1,让用户在终态返回前看到安全活动状态和已产生的用户可见回复,不恢复 Supervisor 或引入第二个 Runtime 真相源。
|
||||
|
||||
### 15.2 事件与字段
|
||||
|
||||
Tauri 事件名固定为 `game-creator-direct-turn-update`,payload 只包含以下字段:
|
||||
|
||||
- `projectPath`:发起回合的项目键,只用于本地路由与隔离,不渲染到用户文案。
|
||||
- `turnId`:本次 direct 提交的稳定回合标识,与项目键共同定位唯一的临时回复。
|
||||
- `sequence`:回合内严格递增的非负整数,用于拒绝重复、迟到和乱序回退。
|
||||
- `status`:只允许 `accepted | running | streaming | finalizing | completed | failed`。
|
||||
- `activity`:只允许 `request-accepted | understanding | project-inspection | file-change | controlled-tool | validation | response-finalization | none` 这些安全类别;它是粗粒度活动标识,不是工具日志。
|
||||
- `accumulatedText`:截至当前序号的完整助手可见正文,前端原位替换临时回复,不将其追加为多条消息。
|
||||
- `updatedAt`:事件产生时间,只用于展示和诊断,不参与顺序判定。
|
||||
|
||||
`activity` 及其对应的展示文案不得泄漏模型 reasoning、工具原始参数、内部路径、Provider、认证信息或未脱敏错误。`accumulatedText` 只能来自助手面向用户的正文增量,不得混入 reasoning、tool call/item、raw arguments、stderr 或内部诊断。
|
||||
|
||||
app-server 的 `turn/plan/updated`、reasoning summary、MCP progress、文件 patch/output、命令 output 和验证类通知只能按通知方法名映射为上述固定 `activity`,不得把通知 params 传入 observer。连续同类高频活动应在进入 turn channel 前有界合并;该合并不得影响 `AgentMessageDelta` 正文和 terminal 终态。
|
||||
|
||||
### 15.3 生命周期与前端门禁
|
||||
|
||||
1. 每次 direct 提交必须先建立 `projectPath + turnId` 的临时回复,生命周期按 `accepted -> running -> streaming -> finalizing -> completed` 前进;没有正文增量时可跳过 `streaming`,任一非终态都可进入 `failed`,终态后不再接受该回合事件。
|
||||
2. 前端只处理 `projectPath` 等于当前项目且 `turnId` 等于当前活动回合的事件。对同一 `projectPath + turnId`,只接受 `sequence` 大于已接收最大值的事件;时间戳更新不能绕过该单调门禁。
|
||||
3. 组件存活期内可保留一个全局 Tauri 事件监听。切换项目、切换活动 `turnId` 或 command 完成、失败时,必须清理对应的临时回复、活动文案和最大 `sequence` 等回合关联状态;组件卸载时再清理该全局监听。迟到事件不得污染新项目或新回合。
|
||||
4. `failed` 必须结束流式态并清理未完成正文,失败展示继续经现有安全错误映射,不把增量文本伪装成已完成回复。
|
||||
5. WorkspaceLauncher 实际项目工作台必须在消息列表内渲染持续可见的同回合过程卡:没有正文时展示当前安全活动,正文 delta 到达后在同一卡内展开累计正文。过程卡不能退化为输入框下方的小号 workspace 状态;用户位于列表底部时活动和正文更新应自动跟随,用户主动上滚后不得强制拉回。
|
||||
|
||||
### 15.4 权威与持久化边界
|
||||
|
||||
`game-creator-direct-turn-update` 是 Tauri 进程内的易失通知,只用于提升当前页面的过程可见性;不将事件本身写入项目对话、manifest 或其它 durable 状态,不用它推导跨进程回合已完成。
|
||||
|
||||
Tauri command 成功返回的 final `String` 是本次回合唯一的终态助手正文和持久化权威。前端收到 command 结果后,用该 `String` 原位收口同一 `turnId` 的临时回复,并且只持久化一条最终 assistant 消息。`completed.accumulatedText` 仍只是临时展示,不得先行或重复持久化,也不得覆盖 command 的 final `String`。
|
||||
|
||||
本合同是 direct 链路的独立交互投影,不复用 legacy `AgentRuntimeResult`,不恢复 Supervisor 的任务、receipt 或消息真相。本次只保证当前 Tauri command 存活期内的流式展示与最终持久化,不宣称已实现 durable reconnect、跨客户端恢复增量或重连后继续同一未完回合。
|
||||
|
||||
### 15.5 验收合同
|
||||
|
||||
- terminal command 返回前,用户消息下方必须持续渲染同回合过程卡;纯工具阶段显示安全活动,真实正文 delta 到达时在同一卡内原位更新临时回复。
|
||||
- 对同一 `projectPath + turnId` 注入重复、倒序和迟到的 `sequence`,页面必须拒绝小于或等于已接收最大值的事件,不得发生正文或状态回退。
|
||||
- command 成功后只展示并持久化一条以 final `String` 为正文的 assistant 消息;临时回复、`completed` 事件和 command result 不得形成多条最终消息。
|
||||
- command 失败、`failed`、项目切换和回合切换均必须清理临时回复、活动状态和序号门禁;组件卸载时必须清理全局监听;旧事件不得出现在新上下文。
|
||||
- 单测、AppSurface 回归与真实客户端验收均要覆盖 WorkspaceLauncher 实际工作台、长工具通知 replay、自动跟随和手动上滚保护;事件和 UI 文案不得出现 reasoning、raw arguments、tool item、stderr、内部路径、Provider、凭据或未脱敏错误。
|
||||
|
||||
@@ -14242,6 +14242,7 @@
|
||||
- Windows 锁文件决策:提升权限进程新建 `.agent/.manifest.json.lock` 时,Windows 可能把 owner 设为 `Administrators`。仅在固定锁路径已取得不共享独占句柄并确认是普通、非 reparse、单链接文件后,才初始化为当前 `TokenUser`;随后再次复核句柄并执行原有 owner/DACL 校验,不放宽既有异常对象的安全规则。
|
||||
- Provider Schema 决策:`agent.route_manifest.missingAssetSlots` 不再广告 OpenAI-compatible 代理拒绝的 `uniqueItems`;Runtime 继续排序去重,Schema 子集门禁新增该关键字,真实 Provider smoke 必须在发布前证明工具目录可被接受。
|
||||
- 运行决策:Godot 项目提交给 Project Supervisor 时使用 `standard` Run Profile,避免触发 Web 专用 `game/index.html`、HTTP preview 与自主 Web 完成门。Godot 编辑器启动和内嵌运行预览不在本切片范围。
|
||||
|
||||
## 2026-08-15 Jenkins 容器预览部署使用独立控制面
|
||||
|
||||
- 决策:多人内网容器预览不把操作表单塞进 Jenkins 页面,也不让 SPA 直接操作 Docker。独立 `preview-deployer` SPA 通过同源 Axum 代理触发固定 `shared/Genarrative-Preview-Deployer` Job;浏览器只持有控制面 HttpOnly 会话,Jenkins service account 和 API Token 只存在服务端环境。
|
||||
@@ -14357,7 +14358,7 @@
|
||||
|
||||
## 2026-08-21 JavaScript 工程统一为 npm workspaces
|
||||
|
||||
- 决策:根、Admin、AGC、Desktop、Mobile、Preview Deployer、三个 `packages/*` 和 Spine validator 统一进入显式 npm workspaces;固定 `packageManager=npm@10.9.7`,CI 镜像显式安装并校验同版 npm。仓库只提交根 `package-lock.json`,安装、CI、Jenkins 和容器缓存都只从根执行一次 `npm ci`。
|
||||
- 决策:根、Admin、AGC、Desktop、Mobile、Preview Deployer、三个 `packages/*` 和 Spine validator 统一进入显式 npm workspaces;固定 `packageManager=npm@10.9.7`,CI 镜像显式安装并校验同版 npm。Jenkins Web Build 不能假定系统 npm 已同步,每个独立 `bash -lc` 都必须 source `scripts/jenkins-prepare-npm-env.sh`,由该入口在 Jenkins 用户的版本隔离目录持久准备 npm `10.9.7`。仓库只提交根 `package-lock.json`,安装、CI、Jenkins 和容器缓存都只从根执行一次 `npm ci`。
|
||||
- 依赖边界:每个 workspace manifest 拥有自身直接依赖,根不再为子 App 重复声明。内部私有包使用匹配版本的普通 semver `0.1.0`,由 npm 自动链接;当前 npm 不接受 `workspace:*`。npm 默认 hoist,因此依赖所有权按 manifest 和 lock 的 workspace entry 检查,不能按统一 `node_modules` 或 lock 全局包条目判断。
|
||||
- 原生边界:根 H5 与 Desktop manifest 继续禁止 Tauri JS guest,AGC workspace 可以声明;统一 lock 出现 AGC guest 是合法聚合结果。Expo 沿用默认 npm monorepo 支持。AGC Cubone bundle、TypeScript、Tauri CLI 与 Windows Codex sidecar 都必须兼容根提升位置,不得依赖子 App 固定 `node_modules` 层级。
|
||||
- 锁与平台:删除 AGC 和 Spine 子 lock;统一根 lock 必须保留 optional、bundled 和跨平台二进制节点。Linux 干净安装不能替代 Windows AGC sidecar、Android Expo/EAS 或可用 macOS/iOS runner 的平台构建证据。
|
||||
@@ -14369,8 +14370,25 @@
|
||||
- 依据:当前完整模块首次 publish / init 的进程 RSS 会超过 `896m`,cgroup 会直接 OOM kill `spacetimedb-standalone`,客户端表现为上传连接提前关闭,后续重试连接拒绝。提高 ping 或 publish 重试次数不能修复内存上限。
|
||||
- 边界:这是本地/预发完整容器的模块实例化门槛,不修改生产服务资源合同;门禁同时锁定基础 Compose 与预览 override 均为 `2g`。
|
||||
|
||||
## 2026-08-22 Jenkins 预览只向 API 运行镜像内置固定 secrets
|
||||
## 2026-08-22 Jenkins 预览只向 API 运行镜像内置固定运行时配置
|
||||
|
||||
- 决策:预览 secrets 权威源固定为 Jenkins 宿主 `/data/jenkins/preview-secrets/.env.secrets.local`;目录 / 文件由 Jenkins 运行账号所有且权限分别为 `0700` / `0600`,缺失、链接、非普通文件、owner 异常或权限过宽时构建失败关闭。
|
||||
- 构建边界:只通过 BuildKit secret mount 把文件提供给 `api-runtime` stage,并安装为 `/srv/genarrative/.env.secrets.local` (`genarrative:genarrative`, `0400`)。文件不进 Git、build context、日志或 artifact,不进入 Web / Nginx、SpacetimeDB 或其它镜像。容器显式运行 env 优先覆盖内置值。
|
||||
- 更新与分发:固定源文件更新后必须重建并替换镜像,只重启容器无效。镜像可读者必然可提取内置 secrets,因此只允许留在当前受信任内网 Docker 主机,禁止 push、`docker save` 或作为 artifact 导出到跨信任边界的 registry、主机或存储。
|
||||
- 决策:预览 `.env.local` 与 secrets 权威源固定为 Jenkins 宿主 `/data/jenkins/preview-secrets/.env.local`、`/data/jenkins/preview-secrets/.env.secrets.local`;目录 / 文件由 Jenkins 运行账号所有且权限分别为 `0700` / `0600`,缺失、链接、非普通文件、owner 异常或权限过宽时构建失败关闭。
|
||||
- 构建边界:只通过两个 BuildKit secret mount 把固定宿主副本提供给 `api-runtime` stage,并安装为 `/srv/genarrative/.env.local`、`/srv/genarrative/.env.secrets.local` (`genarrative:genarrative`, `0400`)。固定宿主副本不进 Git、build context、日志或 artifact,不进入 Web / Nginx、SpacetimeDB 或其它镜像;仓库工作区 `.env.local` 不得替代它们。容器显式运行 env 优先覆盖内置值。
|
||||
- 更新与分发:任一固定源文件更新后必须重建并替换 API 与 worker 镜像,只重启容器无效。镜像可读者必然可提取内置运行时配置,因此只允许留在当前受信任内网 Docker 主机,禁止 push、`docker save` 或作为 artifact 导出到跨信任边界的 registry、主机或存储。
|
||||
|
||||
## 2026-08-22 AGC Tauri 命令调用可达性失败关闭
|
||||
|
||||
- 决策:`check-config.mjs` 的 App 调用扫描必须识别现役精确形态:裸 `invoke`、`directInvoke`、素材画布的 `invokeInput` / `invokeAuthenticatedInput` wrapper,以及对象字段 `.invoke`;不以包含 `invoke` 的任意名称、动态命令变量、注释、字符串、模板或正则文本作为可达证据。
|
||||
- allowlist 边界:前端源码已调用的命令不得继续保留在 explicit native-only allowlist。allowlist 只承载确实由原生窗口或原生侧流程触发、App 源码不直接调用的 handler;源码调用与 allowlist 必须互斥。
|
||||
- 门禁:逐文件使用仓库锁定的 TypeScript AST 解析,设置文件数量、单文件 / 总源码长度、命令长度和调用数量上限。回归测试同时锁定直接、wrapper、对象字段的正例与诱饵 / 动态 / 畸形输入的反例,并证明删除真实 wrapper 调用后 handler 可达性检查失败,不能由错误 allowlist 继续误绿。
|
||||
|
||||
## 2026-08-22 AGC 素材画布生成恢复与提交边界
|
||||
|
||||
- 凭据失败:`configuration-missing` / `authentication-required` 不是永久业务失败。尚无远端副作用时保留原 generation、commit 与 idempotency 身份并按 `context-preparing` / `prepared` 恢复;已有 operation 时只能进入 reconciliation。旧 `failed` 账本仅按这两个错误码和已有副作用证据白名单迁移,确定性业务失败继续终态。
|
||||
- 提交边界:恢复先按项目、草稿和终态预过滤,再解析凭据;上下文准备完成后、首次可计费 POST 前必须重新校验冻结的平台账号会话。草稿一旦 cancelled,不再公开投影、下载后 staging 或提交资产,私有账本保留最后一份 durable 证据。
|
||||
- staging 原子恢复:稳定 staging token 必须同时校验媒体类型、摘要、尺寸与已有文件。图片先落盘或 metadata 先落盘的同身份半提交允许补齐后幂等重放;任一身份或内容冲突失败关闭并保留现场,不覆盖残片。
|
||||
|
||||
## 2026-08-22 AGC 素材画布模态框焦点合同
|
||||
|
||||
- 素材生成确认、离开确认和旧服务身份确认沿用现有独立 modal,不在当前面板下方追加内容。modal 打开后焦点必须进入对话框,并同时隔离工具栏、画布视口、缩放/小地图、状态区和并存操作层,使背景从键盘焦点顺序与 accessibility tree 中退出。
|
||||
- `Tab` / `Shift+Tab` 必须在当前 modal 内双向循环;非异步 pending 状态允许 `Escape` 安全关闭。关闭后优先恢复到原触发器,自动弹出的 modal 则回退到可操作的工具栏入口,不能把焦点遗留在已卸载节点或被隔离背景中。
|
||||
|
||||
@@ -4235,8 +4235,8 @@
|
||||
- 现象:内置 Skill 文件集合没有缺失,原生测试却统一报内容指纹不匹配;另一个测试在 Linux 上把 `C:\\temp\\SKILL.md` 判为安全相对路径,受控资源工具可能继续处理 Windows 盘符或反斜杠遍历形式。
|
||||
- 原因:审核文件定稿后未按最终字节重新生成 manifest SHA-256;同时 `std::path::Path` 只按当前宿主语义解析路径,Linux 不会把 Windows 盘符和反斜杠视为绝对路径或分隔符。
|
||||
- 处理:Skill 文件变化与 manifest 指纹更新必须同次提交,并提升审核包版本;资源引用只接受使用 `/` 的普通相对段,显式拒绝反斜杠、冒号盘符、UNC、绝对路径和父目录段,再查询审核清单。不要先把反斜杠替换成 `/` 后再做安全检查。
|
||||
- 回归补充:即使 Skill 文件本轮没有变化,也不能从旧提交或旧构建结果复制清单指纹;必须对当前工作树最终字节现场重算,并在提交前运行原生 Skill Pack 校验。运行时只报告排序后的首个不匹配项,不能据此假定其余 Skill 已通过。
|
||||
- 验证:逐项按排序后的 `relativePath + NUL + file bytes + NUL` 重算并核对 manifest;Rust 单测同时覆盖 POSIX 绝对路径、`..`、`C:\\...`、`C:/...`、UNC 和反斜杠相对路径,受控 MCP 工具也必须把 Windows 绝对路径投影为 `isError=true`。
|
||||
- 回归补充:即使 Skill 文件本轮没有变化,也不能从旧提交或旧构建结果复制清单指纹;必须对当前工作树按 UTF-8 读取、将 CRLF 规范为 LF 后现场重算,并在提交前运行原生 Skill Pack 校验。Git 的 `eol=lf` 不能阻止编辑器在干净工作树里留下少量混合 CRLF,而 Cargo `include_bytes!` 会读取这些原始字节;因此运行时计算与安装也必须使用同一规范化函数。运行时只报告排序后的首个不匹配项,不能据此假定其余 Skill 已通过。
|
||||
- 验证:逐项按排序后的 `relativePath + NUL + canonical UTF-8 LF bytes + NUL` 重算并核对 manifest;Rust 单测同时覆盖 LF / CRLF 指纹等价、安装结果只含 LF、POSIX 绝对路径、`..`、`C:\\...`、`C:/...`、UNC 和反斜杠相对路径,受控 MCP 工具也必须把 Windows 绝对路径投影为 `isError=true`。
|
||||
|
||||
## Gitea CI 预构建镜像不能只靠 tag 判断内容
|
||||
|
||||
@@ -4864,8 +4864,8 @@
|
||||
|
||||
- 现象:构建时使用 BuildKit secret mount,日志和普通 build context 都没有出现明文,于是误以为最终镜像也能不可提取地保存 secrets,随后将镜像 push 或导出给不同信任域。
|
||||
- 原因:BuildKit secret mount 只避免秘密作为 `ARG` / `COPY` 进入构建上下文和中间指令;一旦 Dockerfile 把 mount 的内容安装到最终 rootfs,任何能读取、保存或运行该镜像的主体都可以提取它。
|
||||
- 处理:预览固定 secrets 只从 Jenkins 宿主受控路径读取,严格校验目录 `0700`、文件 `0600`、owner、普通文件与非链接边界;只将其安装到 `api-runtime:/srv/genarrative/.env.secrets.local` 并设为 `0400`,明确排除 Nginx、Web、artifact 和其它镜像。镜像禁止推送或导出到跨信任边界。
|
||||
- 更新与验证:源文件变更不会改动已存镜像,必须重建并替换容器;不能用重启代替。验收同时扫描 transcript/context/artifact 零泄漏,检查只有 API 最终 rootfs 存在目标文件,并验证容器显式运行 env 优先覆盖内置值。
|
||||
- 处理:预览固定 `.env.local` 与 secrets 只从 Jenkins 宿主受控路径读取,严格校验目录 `0700`、文件 `0600`、owner、普通文件与非链接边界;只将它们安装到 `api-runtime:/srv/genarrative/.env.local` 与 `/srv/genarrative/.env.secrets.local` 并设为 `0400`,明确排除 Nginx、Web、artifact 和其它镜像。镜像禁止推送或导出到跨信任边界。
|
||||
- 更新与验证:任一源文件变更不会改动已存镜像,必须重建并替换 API 与 worker 容器;不能用重启代替。验收同时扫描 transcript/context/artifact 零泄漏,检查只有 API 与 worker 最终 rootfs 存在目标文件,并验证容器显式运行 env 优先覆盖内置值。
|
||||
|
||||
## SpacetimeDB ping 健康不代表完整模块能在内存上限内实例化(2026-08-22)
|
||||
|
||||
|
||||
@@ -51,9 +51,9 @@ SpacetimeDB 2.7 CLI 发布到受控 Compose 网络地址时固定使用 `--yes=r
|
||||
|
||||
## 预览 secrets 内置
|
||||
|
||||
Jenkins 节点上的预览 secrets 权威来源固定为 `/data/jenkins/preview-secrets/.env.secrets.local`。该文件不进 Git、Docker build context、构建日志或 artifact;构建时只通过 BuildKit `secret` mount 临时提供给 `api-runtime` stage,并在该运行镜像中安装为 `/srv/genarrative/.env.secrets.local`,权限固定为 `0400`。`nginx-runtime`、Web 静态产物、SpacetimeDB 镜像及其它镜像不得包含该文件。
|
||||
Jenkins 节点上的预览运行时配置权威来源固定为 `/data/jenkins/preview-secrets/.env.local` 与 `/data/jenkins/preview-secrets/.env.secrets.local`。这两个固定宿主副本不进 Git、Docker build context、构建日志或 artifact;构建时分别通过 BuildKit `secret` mount 临时提供给 `api-runtime` stage,并在该运行镜像中安装为 `/srv/genarrative/.env.local` 与 `/srv/genarrative/.env.secrets.local`,权限固定为 `0400`。`nginx-runtime`、Web 静态产物、SpacetimeDB 镜像及其它镜像不得包含这些文件。仓库工作区中的 `.env.local` 不得替代固定宿主副本作为构建输入。
|
||||
|
||||
宿主固定目录应由 Jenkins 运行账号所有且权限为 `0700`,源文件权限为 `0600`;缺失、不是普通文件、owner 不匹配或权限过宽时,预览构建必须失败关闭。源文件变更后必须重新构建并替换预览镜像,只重启容器不会刷新已内置的内容。容器启动时显式注入的运行环境变量优先级高于镜像内的 `.env.secrets.local`,用于按实例覆盖非通用值。
|
||||
宿主固定目录应由 Jenkins 运行账号所有且权限为 `0700`,两个源文件权限均为 `0600`;缺失、不是普通文件、owner 不匹配或权限过宽时,预览构建必须失败关闭。任一源文件变更后必须重新构建并替换 API 与 worker 预览镜像,只重启容器不会刷新已内置的内容。容器启动时显式注入的运行环境变量优先级高于镜像内的 `.env.local` 与 `.env.secrets.local`,用于按实例覆盖非通用值。
|
||||
|
||||
这种方案只隐藏构建传输过程,不能让内置后的 secrets 对镜像持有者保密:能读取、保存或运行 `api-runtime` 镜像的人可以提取该文件。因此该镜像只能留在当前受信任内网 Docker 主机,禁止 push 到公共或跨信任边界的 registry,也禁止通过 `docker save`/构建 artifact 导出传播。需要跨边界分发时必须改用不含 secrets 的镜像与运行时密钥注入。
|
||||
|
||||
@@ -118,7 +118,7 @@ Jenkins 在构建完成、归档 artifact 和更新 REST 状态之间可能短
|
||||
- Jenkins service account 只授予 `shared/Genarrative-Preview-Deployer` 的 `Job/Read`、`Job/Build` 和读取构建产物所需权限,不授 `Overall/Administer`、`Job/Configure` 或 `Job/Delete`。
|
||||
- 后端固定 Jenkins origin、Job 路径和参数白名单;客户端不能传 URL、Job 名、Compose project、容器名、宿主端口或 Jenkins 凭据。
|
||||
- Git 查询固定使用本机 Gitea SSH 地址和服务端只读凭据;客户端不能传 remote、SSH 参数或凭据。Git 缓存只写入预览控制服务的受控状态目录,搜索接口需要控制台会话且结果有数量上限。
|
||||
- 预览 secrets 只从固定宿主路径读取,构建前校验 owner、类型和权限;不允许分支、Jenkins 参数或控制面请求改写 secrets 路径、BuildKit secret ID 或镜像内目标路径。
|
||||
- 预览 `.env.local` 与 secrets 只从固定宿主路径读取,构建前校验目录和文件的 owner、类型和权限;不允许分支、Jenkins 参数或控制面请求改写这些路径、BuildKit secret ID 或镜像内目标路径。
|
||||
- Jenkins POST 支持动态 Crumb;API Token 即使免 Crumb,也不能把 Token 放进 URL 或日志。
|
||||
- API 默认只接受同源请求,写请求校验 Origin;内网本身不作为认证。
|
||||
- 同一 deployment 的发布和卸载串行执行;重复请求必须幂等或明确返回冲突。
|
||||
|
||||
@@ -1163,7 +1163,7 @@ game-project/
|
||||
|
||||
- 普通项目对话只由一个 project-bound Codex app-server thread 执行。客户端系统提示词只放最小工程合同、当前游戏源码有界快照、项目 prompts 和审核 Skill 索引;不再批量读取项目 `.codex/.agents/.hermes` Skill 正文,也不恢复 Supervisor、专业 Agent 或 harness。
|
||||
- 首页恢复“做游戏 / 做素材 / 做方案”三个创作类型,默认“做游戏”。该选择与设置页的 Agent Runtime 模式无关;每次首页提交仍只自动创建一个新项目并进入项目工作台。用户正文原样进入项目对话,`game|art|doc` 仅作为受限结构化首轮上下文传给同一 Codex thread,不拼接“初始意图”文案、不产生首页对话、不切换 Provider 或恢复旧 Runtime 编排。
|
||||
- `agc-skill-pack.v1` 只包含项目结构、陶泥儿美术、Web 游戏实现、真实浏览器试玩、客户端资源投影五项 Skill。清单记录用途、触发条件、所需工具、版本和内容 SHA-256;任何审核文件变化都必须同步重算对应清单指纹。客户端把审核文件安装到隔离目录后通过 app-server `skills/extraRoots/set + skills/list` 注册并复核,完整正文由 Codex 原生 Skill 机制按意图加载,一层引用只能经 `agc_read_skill_resource` 读取清单内 Markdown。引用路径按平台无关规则拒绝反斜杠、盘符、UNC、绝对路径和 `..`,不能依赖当前宿主的 `std::path` 语义判断其它平台路径。
|
||||
- `agc-skill-pack.v1` 只包含项目结构、陶泥儿美术、Web 游戏实现、真实浏览器试玩、客户端资源投影五项 Skill。清单记录用途、触发条件、所需工具、版本和内容 SHA-256;审核文本按 UTF-8 读取并将 CRLF 规范为 LF 后计算指纹和安装,避免混合换行造成 Windows / Linux 构建结果漂移,语义内容变化时必须同步重算对应清单指纹并提升版本。客户端把审核文件安装到隔离目录后通过 app-server `skills/extraRoots/set + skills/list` 注册并复核,完整正文由 Codex 原生 Skill 机制按意图加载,一层引用只能经 `agc_read_skill_resource` 读取清单内 Markdown。引用路径按平台无关规则拒绝反斜杠、盘符、UNC、绝对路径和 `..`,不能依赖当前宿主的 `std::path` 语义判断其它平台路径。
|
||||
- DirectProject 只连接客户端内置的 `agc_tools` STDIO MCP,工具固定为审核引用读取、标准陶泥儿美术准备和 desktop/mobile 浏览器试玩。MCP 进程只做协议;真实浏览器和付费 External v1 调用通过随机 loopback 地址回到客户端主进程,因此不复制 GUI 登录态、开发者 Key 或项目路径到模型上下文。三项工具固定自动批准,通用 shell、任意网络、多 Agent、插件和外部 MCP 继续关闭。
|
||||
- 陶泥儿生成继续复用既有私有 Key、持久幂等账本、operation 恢复、来源/下载/PNG 解码和 manifest 登记。完整可信图集缺切片可以继续,固定四切片只是推荐路径;凭据失效、来源不明或结果未知时失败关闭,不能自动换 Key 或重新扣费。
|
||||
- 自定义 LLM API Key 路由只在 DirectHome/DirectProject 经 loopback `/responses` 流式代理转发。代理不注入 Key,只要求请求自带 Bearer,并剥离开发网关错误携带的 `X-Codex-*` ChatGPT 账户额度头,防止隔离 app-server 把 API Provider 误判为余额 0;旧 ToolHost 保持原 Provider 行为。
|
||||
|
||||
@@ -86,7 +86,7 @@ AGC 的 TypeScript、Vite/Vitest bundle 和 Windows Codex sidecar 不允许硬
|
||||
## CI、Jenkins 与容器
|
||||
|
||||
- Gitea 四个 job 每个只执行一次带重试的根 `npm ci`,不再单独安装 AGC。
|
||||
- Jenkins Web Build 在安装前必须精确校验 npm `10.9.7`;`RUN_NPM_CI` 只控制一次根 `npm ci`。
|
||||
- Jenkins Web Build 必须在每个独立 shell 中加载 `scripts/jenkins-prepare-npm-env.sh`;该入口在 Jenkins 运行用户的版本隔离目录准备并优先使用 npm `10.9.7`,根 workspace 安装前再精确校验版本;`RUN_NPM_CI` 只控制一次根 `npm ci`。
|
||||
- Gitea CI 镜像只维护一个 npm lock SHA 与一份 npm cache;预热上下文必须包含根 lock 和全部 workspace manifests,使根 `npm ci` 能解析 workspace。
|
||||
- CI 镜像仍分别维护 server-rs、Desktop Tauri、AGC Tauri 三份 Cargo lock cache;npm 单锁不改变 Rust lock 边界。
|
||||
- API 镜像的 Web builder 必须显式安装并校验 npm `10.9.7`,再复制全部 workspace manifests、执行根 `npm ci`,之后才复制源码并构建主站与后台。
|
||||
|
||||
@@ -260,7 +260,7 @@ npm run check
|
||||
|
||||
仓库级 Gitea Actions 工作流固定为 `.gitea/workflows/project-ci.yml`,在向 `master` 推送、创建或更新 PR,以及手工触发时运行。工作流拆成四个必须通过的 job:
|
||||
|
||||
所有 CI job 和 Jenkins Web Build 在根 workspace 安装前都必须确认 `npm --version` 为 `10.9.7`;旧固定镜像缺少版本元数据时只能报告 `npm_version=partial` 并由当前 job 的根 `npm ci` 继续校验 lock,不能把过渡状态当作工具链已闭合。
|
||||
所有 CI job 和 Jenkins Web Build 在根 workspace 安装前都必须确认 `npm --version` 为 `10.9.7`。Gitea job 使用预构建镜像内的固定版本;Jenkins Web Build 在每个独立 `bash -lc` 中 source `scripts/jenkins-prepare-npm-env.sh`,首次为 Jenkins 运行用户的版本隔离目录引导同版 npm,后续复用并把该 `bin` 放到 `PATH` 首位。旧固定镜像缺少版本元数据时只能报告 `npm_version=partial` 并由当前 job 的根 `npm ci` 继续校验 lock,不能把过渡状态当作工具链已闭合。
|
||||
|
||||
- `Repository checks`:调用唯一入口 `npm run check:repository-ci`,执行 `npm run lint`、AI 游戏创作壳 AppSurface 定向测试、主站与后台生产构建和提交差异空白检查。本地 master `pre-push` 复用同一入口,禁止在 workflow 与 hook 中维护两份近似命令。
|
||||
- `Frontend tests`:按唯一根 workspace lockfile 执行一次干净的 `npm ci`,再独立执行根 `npm run test`、`npm run bgfilter-worker:smoke-test`、`npm run check:production-health-patrol`、`npm run check:production-api-release` 和 `npm run check:production-api-deploy`,让 Vitest、Node test smoke harness 及不依赖真实服务的生产巡检 / 发布 / 部署行为 fixture 在 Gitea job 中持续执行;其中 `.test.mjs` 使用 Node test runner,不依赖 Vitest 的 `scripts/**/*.test.ts` 收集规则。
|
||||
@@ -610,7 +610,7 @@ Jenkins Copy Artifact 必须保持 `Production` 权限模式;产物生产者
|
||||
|
||||
`Genarrative-Web-Build` 的主站构建失败若出现 Rollup 报错 `"xxx" is not exported by "src/services/publicWorkCode.ts"`,优先按前端公开作品号工具缺失处理,而不是排查 Jenkins 节点环境。修复时要让 `publicWorkCode.ts` 的 `build<Play>PublicWorkCode` 与 `isSame<Play>PublicWorkCode` 成对导出,并补 `src/services/publicWorkCode.test.ts` 覆盖对应玩法前缀;随后用 `npm run build:production-release -- --component web --name <临时名>` 复现 Jenkins web 构建路径。
|
||||
|
||||
`Genarrative-Web-Build` 在运行根 Vitest 前必须按唯一根 `package-lock.json` 执行一次干净的 `npm ci`。根 lock 聚合全部 workspace,因此会安装 AI 游戏创作壳合法声明的 `@tauri-apps/api`、`@tauri-apps/plugin-http` 等 Tauri guest;这些依赖仍只归属 AGC workspace,不得加入根 H5 或 Desktop manifest。排查收集失败时先运行 `npm run check:npm-workspaces` 并核对根 lock 的 workspace entry,禁止恢复第二份 lock 或子目录安装。
|
||||
`Genarrative-Web-Build` 先通过 `scripts/jenkins-prepare-npm-env.sh` 在 Jenkins 运行用户的持久版本目录准备 npm `10.9.7`,显式提升该 `bin` 后校验真实版本,不依赖系统 `/usr/bin/npm` 或 `packageManager` 声明自动切版。在运行根 Vitest 前必须按唯一根 `package-lock.json` 执行一次干净的 `npm ci`。根 lock 聚合全部 workspace,因此会安装 AI 游戏创作壳合法声明的 `@tauri-apps/api`、`@tauri-apps/plugin-http` 等 Tauri guest;这些依赖仍只归属 AGC workspace,不得加入根 H5 或 Desktop manifest。排查收集失败时先运行 `npm run check:npm-workspaces` 并核对根 lock 的 workspace entry,禁止恢复第二份 lock 或子目录安装。
|
||||
|
||||
`Genarrative-Web-Build` 会把 `build/<version>/web.tar.gz`、`web.tar.gz.sha256`、`release-manifest.json` 和 `scripts/deploy/production-web-deploy.sh` 直接归档为 Jenkins 构建产物;`Genarrative-Web-Deploy` 只通过 `copyArtifacts` 从指定上游构建复制这些产物和部署脚本,不再在目标机器 checkout Git,再执行随构建归档的 `scripts/deploy/production-web-deploy.sh`。Web 发布不再读取构建机本地缓存目录,也不再通过 release agent `rsync` 回构建机拉取大包;如果 deploy 找不到 `web.tar.gz`,应先检查上游 Web Build 是否按同一 `BUILD_VERSION` 成功归档产物。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user