修复 AGC 画布素材卡「引用」无消费者:新增活跃聊天输入区注册表(Issue #602) #605
Open
suzmii
wants to merge 11 commits from
fix/agc-canvas-reference-insert into master
pull from: fix/agc-canvas-reference-insert
merge into: GenarrativeAI:master
GenarrativeAI:master
GenarrativeAI:fix/agc-composer-layout
GenarrativeAI:fix/home-project-naming-async
GenarrativeAI:fix/ci-master-red
GenarrativeAI:feat/game-works-management
GenarrativeAI:contract-lease-refactor
GenarrativeAI:feat/pricing-plan
GenarrativeAI:feat/play-count-with-cache
GenarrativeAI:feat/pricing-plan-limit
GenarrativeAI:codex/payment-service-20261003
GenarrativeAI:codex/profile-invite-gate-fix
GenarrativeAI:codex/profile-invite-entry
GenarrativeAI:feat/agc-ui-motion-ux
GenarrativeAI:feat/ui-editor-model-override
GenarrativeAI:fix/agc-release-gate-channel
GenarrativeAI:fix/dev-loopback-token-trust
GenarrativeAI:feat/tribo3d-integeration
GenarrativeAI:fix/api-timeout
GenarrativeAI:codex/admin-gray-game-publish
GenarrativeAI:codex/remove-agc-codex-restrictions
GenarrativeAI:feat/gptimage2to2.5
GenarrativeAI:backup/agc-macos-dualarch-node-runtime
GenarrativeAI:feat/Crt_Ws
GenarrativeAI:codex/preview-llm-router-config
GenarrativeAI:fix/stroke-width-regression-from-285
GenarrativeAI:agent-organize
GenarrativeAI:feat/game-agent-canvas-resource-workbench-v2
GenarrativeAI:feat/agc-new-workflow
GenarrativeAI:fix/agc-release-version-sync
GenarrativeAI:codex/shared-components-followup
GenarrativeAI:codex/game-agent-runtime-interaction-design
GenarrativeAI:feat/spine-sequence-export-v2
GenarrativeAI:codex/game-agent-run
GenarrativeAI:codex/ui-spritesheet-durable-transaction-latest
GenarrativeAI:feat/art-agent-more-tools
GenarrativeAI:codex/editor-canvas-null-source-repair
GenarrativeAI:hotfix/editor-layout-2mib
GenarrativeAI:codex/showcase
11 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
4fc13bcfe3 |
合并 fix/ci-master-red(PR #609)到 fix/agc-canvas-reference-insert:取得 master 级 CI 修复
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m54s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 4m22s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 5m21s
Project CI / Backend tests (pull_request) Successful in 6m30s
Project CI / Frontend tests (pull_request) Successful in 3m29s
Project CI / Native shell tests (pull_request) Successful in 7m10s
Project CI / AI game creator shell web tests (pull_request) Successful in 3m37s
Project CI / Repository checks (pull_request) Successful in 6m16s
把 #609 的 8/8 全绿修复并进本分支,满足「PR head 必须包含最新 base 提交」的门禁,同时带上共享红修复:check:nginx-spa-routes 的 /pay/<checkoutToken> 前缀路由与 Pingora 路由矩阵、external_mcp::semantic 真值 32、api-server/platform-llm 的 tracing interest 竞态、AGC 壳 Rust shard-4 两条偶发断言 本次 merge 无冲突自动完成:pitfalls.md 两边条目都保留(本分支的 issue #602 条目 + #609 的 2026-10-04 tracing/shard-4/SPA 深链三条) 未改动 #609 引入的任何文件 |
||
|
|
8b11dc4e7a |
语义目录测试的总数断言改回字面量,避免恒真
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m50s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 4m10s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 5m5s
Project CI / Backend tests (pull_request) Successful in 6m30s
Project CI / Frontend tests (pull_request) Successful in 3m12s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m44s
Project CI / Native shell tests (pull_request) Successful in 6m33s
Project CI / Repository checks (pull_request) Successful in 5m5s
- names.len() == MCP_OPERATIONS.len() + TOOLS.len() 在 BTreeSet 去重构造下恒真、没有判别力; 改回固定 47(32 条 legacy 工具 + 15 条语义工具),并注明上面的插入断言已保证两组名字互不覆盖 - 本地实跑:cargo test --locked -p api-server --manifest-path server-rs/Cargo.toml --bin api-server semantic → 18 passed |
||
|
|
ad0430fcd2 |
补上收银台深链 /pay/<checkoutToken> 的前缀路由(Nginx 三模板 + Pingora + 门禁)
- 现状:只把 `/pay`、`/profile/payment` 加进 allowlist 只能让 check:nginx-spa-routes 变绿; payment.rs 生成的 checkoutUrl 是 `/pay/<checkoutToken>`,深链仍落默认 location 的 try_files → 404。同一批漂移里 check:pingora-route-parity 也是红的(Pingora MAIN_SPA_PATHS 缺 /pay、/profile/payment),只是被 lint 链里先失败的门禁掩盖,修一条要跑到链尾 - 真相源:src/routing/activeAppPageRoutes.ts 新增 APP_PREFIX_ROUTE_ENTRIES ('/pay' → payment-checkout),resolveSelectionStageFromPath 改用它 - 门禁:scripts/check-nginx-spa-routes.mjs 要求三份模板都有锚定前缀 location `location ~* "^/pay/[^/]+/?$"`(裸前缀仍由精确 location 负责;前缀 location 必须镜像精确 location 的维护闸与 try_files 回退);新增 scripts/check-nginx-spa-routes.test.mjs 正/反用例 (把前缀写成精确匹配或过宽裸前缀都会红),由 npm run check:nginx-spa-routes 一起执行; check-pingora-route-parity 新增 MAIN_SPA_PREFIX_PATHS 与前端前缀路由的逐条比对 - 模板:deploy/nginx/genarrative.conf、deploy/nginx/genarrative-dev-http.conf、 deploy/container/nginx.conf 各加一条锚定前缀 location - Pingora:MAIN_SPA_PATHS 补 /pay、/profile/payment;新增 MAIN_SPA_PREFIX_PATHS 与 is_main_spa_prefix_path(大小写不敏感,只认「前缀 + 恰好一段」),矩阵新增 pay_checkout_spa_fallback 用例,并给网关补一条前缀正/反单测 - 文档:Pingora 试点文档的路由表与门禁说明、deploy/nginx/README 与本地开发/生产运维文档 同步前缀路由口径与线上 curl 复验方式 - 本地实跑:node --test scripts/check-nginx-spa-routes.test.mjs(4 passed)、 node scripts/check-nginx-spa-routes.mjs(OK,14 SPA routes / 1 prefix routes / 3 templates)、 npm run check:pingora-route-parity(OK,25 routes)、 cargo test -p pingora-gateway -- pay_checkout_deep_link matches_nginx_route_parity_matrix(2 passed) |
||
|
|
9e2cea5b72 |
修复 AGC 壳 Rust shard-4 的两条偶发断言,并补齐 pitfalls 记录
- agent::thread_manager::tests::active_turn_changes_publish_one_notification_per_real_change 偶发 left 8/right 7:测试计数器 DIRECT_ACTIVE_TURNS_EVENT_TEST_COUNT 曾在 2026-10-01 按线程 作用域隔离,2026-10-02 退役 runtime_driver 把它搬进 agent/direct_events.rs 时降级回进程级 static AtomicU64,于是断言会取到宿主 tauri::async_runtime 后台回合在别的线程上的广播 (--test-threads=1 只串行测试线程)。改回 thread_local! Cell,并注明跨线程口径的覆盖取舍 - process_session::tests::process_session_graceful_terminate_keeps_wrapper_alive_for_target_cleanup 偶发 left "exited"/right "terminated":测试命令里 leader 打印 READY 后立刻 exit 0,同组后代 仍存活,trampoline 从 leader 被回收起开始 800ms 宽限;客户端只要晚于宽限才发出 terminate 就只能读到既成事实。改为 leader 用 wait 等后台子进程,让 terminate 必然落在会话仍 running 时 (trap / sleep 0.4 / marker / 断言均未改),并注明该用例的确定性来自 400ms < 800ms 的时间余量 - docs/project-memory/shared-memory/pitfalls.md:更新 graceful terminate 那条已过时的验证口径, 补三条 2026-10-04 条目(tracing interest 竞态、AGC 两条偶发的串台根因、SPA 深链前缀路由) - 本地实跑:修复前把计数器临时改回 AtomicU64 时同一并行口径 17/20 红;修复后并行 20 次全绿、 agent::thread_manager:: 连跑 5 次 72 passed;第 2 条用例是 #[cfg(target_os = "linux")], Windows 本机跑不到,已用真实 Linux 内核(WSL Alpine)验证命令形状(leader 活到 TERM、 同组后代完成 400ms 延迟清理 marker=done 0.41s、清理后组内零残留),CI 侧仍需跑 node apps/ai-game-creator-shell/scripts/run-rust-shell-test-shards.mjs --shards=4 --shard-index=4 复核 |
||
|
|
977b2f0c75 |
修掉并发测试下 HTTP/Provider span 偶发采集为空的 tracing interest 竞态
- 根因:span!/info_span! 宏在 callsite 的缓存 interest 为 never 时会静默返回空 span (tracing-0.1.44/src/macros.rs 的 span! 分支),而 DefaultCallsite::register 只在调用点 首次被命中时计算一次 interest,且当进程里只注册过一个 dispatcher 时会退化成 dispatcher::get_default()——也就是命中线程自己的 dispatcher(tracing-core-0.1.36 callsite.rs 的 Rebuilder::JustOne)。libtest 默认并发下,没有 subscriber 的普通测试线程 一旦抢到 http.request / llm.request 调用点的首次注册,就会把它永久缓存成 never, 于是 CI 偶发看到 0 个 span(app.rs:603、observability_tests.rs:98) - 关键:set_default 与 with_subscriber 在 interest 缓存这件事上**等价**(都只是新建 Dispatch 并触发一次 rebuild_interest,只能纠正“已经注册过”的调用点,纠正不了 JustOne→get_default 这条首次注册分支),所以真正起作用的是**在自家 subscriber 下命中同一个调用点做热身**, 把首次注册的顺序握在自己手里;register_callsite 覆写只用于避免本 subscriber 触发的重建 把其它调用点永久标记成 never - api-server app::tests::http_tracing:不再用 with_subscriber,改为在请求前用同一 http.request 调用点热身到连续两轮采集成功,并在整个请求期间持有 scoped default (已注明 set_default 是线程绑定,只适用于默认的 current_thread #[tokio::test]) - platform-llm observability_tests:新增 run_under_capture 固定整段流程的 scoped default, 并新增 warm_up_provider_span_callsite(用指向刚释放 loopback 端口的最小失败请求命中同一 llm.request 调用点,连续两轮采集成功才继续) - 断言未放宽:仍要求每个被拒绝请求恰好 1 个 HTTP span、每次 Provider 调用恰好 1 个 llm.request span;未使用 sleep - 本地实跑:cargo test -p api-server --bin api-server app::tests::http_tracing(默认并发与 --test-threads=1 各 20 次全绿)、app::tests:: 91 用例并发 10 次全绿、--skip bgfilter_worker --skip wallet_refund_outbox 的 1133 用例全量 bin 2 次全绿;cargo test -p platform-llm --lib (162 passed,含 3 条观测用例)连跑 20 次全绿 |
||
|
|
05707e61e4 |
修正外部 MCP 语义目录测试里写死的 legacy 工具数断言
- 断言 MCP_OPERATIONS.len() == 30 自 #592 起写死。4b529a895(新增支付服务接入与订单收银台) 在内置 OpenAPI 中新增 createExternalPaymentOrder、getExternalPaymentOrder 两条未被 x-mcp-excluded 排除的操作,legacy 可调用工具由 30 合法增至 32(非重复注册、非覆盖) - 断言更新为 32 并注明来源(内置 OpenAPI 去掉 5 条元数据/入口操作后的可调用集合), 保留“语义工具是增量、不得覆盖 legacy 工具”的原意;总数断言改为 MCP_OPERATIONS.len() + TOOLS.len() 派生,避免再次写死 - 本地实跑:cargo test --locked -p api-server --no-fail-fast --manifest-path server-rs/Cargo.toml semantic → 18 passed(含 semantic_catalog_adds_fifteen_tools_without_replacing_legacy_tools) |
||
|
|
26b6e1095b |
修复 Nginx SPA allowlist 缺少 /pay 与 /profile/payment
- src/routing/activeAppPageRoutes.ts 的 STAGE_ROUTE_ENTRIES 已把 payment-checkout→/pay、 profile-payment→/profile/payment 定义为主站对外可直达的 SPA 路由(分别渲染 PaymentCheckoutView 与 PlatformPaymentServiceView),但三份 Nginx 模板的 SPA allowlist 仍停留在加入支付入口之前的集合,导致 check:nginx-spa-routes 在 master 上失败 - deploy/nginx/genarrative.conf、deploy/nginx/genarrative-dev-http.conf、 deploy/container/nginx.conf 的 SPA regex 补上 pay、profile/payment, 保持既有形状(锚定完整路径 + 大小写不敏感 + 允许一个尾部斜杠) - 本地实跑:node scripts/check-nginx-spa-routes.mjs → OK (14 SPA routes, 3 Nginx templates) |
||
|
|
3f18e3dc77 |
按独立评审的三条 P2 收口:空批次不误报、重复注册留线索、文档与实测对齐
Project CI / AI game creator shell Rust crates (pull_request) Failing after 1m35s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 4m20s
Project CI / Backend tests (pull_request) Failing after 4m39s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 5m18s
Project CI / Frontend tests (pull_request) Successful in 3m19s
Project CI / AI game creator shell web tests (pull_request) Successful in 3m43s
Project CI / Native shell tests (pull_request) Successful in 7m28s
Project CI / Repository checks (pull_request) Failing after 4m32s
App.tsx 的监听处对空批次直接返回:空批次没有要插的东西,不能报成「没有可用的聊天输入区」(原因指向错了方向) activeChatComposer.registerActiveChatComposer 增加重复注册检测:dev 下 console.warn 指出后注册者顶替了前者,不改运行时语义(仍然后注册者接管、身份校验照旧兜住乱序卸载) tests/activeChatComposer.test.ts 补两条:空批次不打扰已挂载输入区;重复注册出现告警且乱序注销清不掉更新的句柄 tests/resourceCanvasChatReferenceDrop.test.tsx 补一条:直接构造空批次引用事件时不产生「没有可用的聊天输入区」告警 decision-log 的「影响范围」补记 tests/activeChatComposer.test.ts,「验证」换成合并 master 后的实跑数字;功能说明的用例表补两行 反向证伪:去掉空批次短路、去掉重复注册告警后,上面两条新用例各红一处 |
||
|
|
455b265a75 |
合并 master 到 fix/agc-canvas-reference-insert:按新测试替身与类型门禁解冲突
master 侧(PR #601)新增 tests/tauriRuntimeFake.ts(全仓唯一 window.__TAURI__ 安装点)与 tsconfig.tests.json,测试统一改用 installTauriRuntime / resetTauriRuntime,并新增 check:tests:types 门禁 冲突三处测试文件(resourceCanvasChatReferenceDrop.test.tsx、appSurface/project-development.suite.ts、appSurface/design-agent.suite.ts)按语义两边保留:采用 master 的替身安装点与类型收窄(ResourceReference 过滤),保留本分支的真实 DirectProject 聊天面挂载与端到端草稿断言 App 的 props 类型未导出,新增的两处 chat 节点改用 AppComponent 组件类型别名(与 design-agent.suite.ts 同一写法),通过新的 check:tests:types docs 侧 pitfalls.md / decision-log.md 自动合并:本分支的 issue #602 条目与 master 的「根因 7/8」条目都保留 未在本分支修 master 既有红(check:nginx-spa-routes 缺 /pay 与 /profile/payment、external_mcp::semantic 32 vs 30、http_tracing 偶发、AGC Rust shard 4/4),由上游 fix/ci-master-red 处理 |
||
|
|
f4ada50612 |
自审加固:注册表按 ref 转发注册、插入成功语义与失败留痕对齐
Project CI / Backend tests (pull_request) Failing after 17s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 4m50s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 5m19s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 2m43s
Project CI / Repository checks (pull_request) Failing after 32s
Project CI / Frontend tests (pull_request) Successful in 2m35s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m23s
Project CI / Native shell tests (pull_request) Successful in 6m26s
ActiveChatComposerHandle.insertReferences 改为返回 boolean:由句柄回答这一批有没有真的递到输入区,注册表不再用「有句柄」冒充「插进去了」 insertChatReferences 增加第三种 false(句柄报落空),且只有插入成功才 focus,失败不抢焦点 DirectProjectChatView 改为注册「按 ref 转发」的句柄,注册时不再读 composerHandleRef.current,去掉对父子 effect 顺序的隐式依赖(内层输入区重挂载也不会留下死句柄) DirectProjectComposer 与 PlanningChatView 的转发句柄同步返回 boolean App.tsx 的 dev 失败线索文案改为「没有可用的聊天输入区(未挂载或已卸载)」,覆盖句柄落空这一种 新增 tests/activeChatComposer.test.ts:钉住注册表合同(空批次 / 无输入区 / 句柄报落空不聚焦 / 注销身份校验);反向证伪:去掉身份校验后该用例变红 同步 docs/【功能说明】AGC聊天素材引用-2026-09-08.md 与 shared-memory 决策记录 |
||
|
|
a22e8ee447 |
修复 AGC 画布素材卡「引用」无消费者:新增活跃聊天输入区注册表
Project CI / Backend tests (pull_request) Failing after 18s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 5m44s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 3m2s
Project CI / Repository checks (pull_request) Failing after 30s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 5m10s
Project CI / Frontend tests (pull_request) Successful in 2m43s
Project CI / AI game creator shell web tests (pull_request) Successful in 3m16s
Project CI / Native shell tests (pull_request) Successful in 5m58s
新增 features/project-workspace/activeChatComposer.ts:模块级保存当前挂载的输入区句柄,registerActiveChatComposer 注销时校验身份,insertChatReferences 空批次或无句柄返回 false DirectProjectComposer 用 useImperativeHandle 暴露 DirectProjectComposerHandle(按 ref 转发,句柄稳定),新增可选 ref 入参 DirectProjectChatView 挂载期间注册、卸载注销,并把 composerHandleRef 传给 DirectProjectComposer PlanningChatView 同样注册(句柄按 composerRef 转发),两条链路互斥渲染,同一时刻只有一个句柄 App.tsx 收敛为一处监听:单条「引用」与批量拖拽两个事件都走 insertChatReferences,返回 false 时 dev 下 console.warn chatComposerRef 只保留给策划输入盒自己的 getDraft / clear,不再承担跨面板插入 project-development.suite.ts:工具条「引用」用例改为渲染真实 DirectProject 聊天面,断言草稿里出现引用芯片(键盘 + 鼠标两条通路、光标留在插入之后) resourceCanvasChatReferenceDrop.test.tsx:换成真实 DirectProject 聊天面,批量拖拽断言整批一次落进草稿且顺序 = 拖动集合顺序;新增未登记素材不出「引用」按钮、拖拽只给原因的用例 design-agent.suite.ts:新增策划链路引用插入不回归用例 同步 docs/【功能说明】AGC聊天素材引用-2026-09-08.md、shared-memory 的 pitfalls 与 decision-log |