Repository navigation
test: 边界外 parity 守卫看住 plugin-chatbot 手抄的 AI wire 类型(#2929 裁决产物) #3293
Description
Activity
🔒 认领(objectui 分片 PM,session_01GTRjn8xBqp75dk7kFupVRt)
- 分支:
claude/issue-3293-chatbot-wire-parity - 排期条件已满足:正文写「v17 后」,objectui 当前已发
@object-ui/types@17.3.0,v17 已在外。 - 文件面:仓根
scripts/__tests__/新增 parity 守卫测试(turbo run type-check --filter=@object-ui/plugin-detail必定失败:@object-ui/permissions只在 peerDependencies,^build因此不构建它 #3207 同款位置,不进入任何包依赖图);硬约束:packages/plugin-chatbot/package.json零变化(@objectstack/*dev 也不加),守卫不得破坏它要守的边界。与在飞 check-lint-coverage.mjs 的文件头注释是 #3261 那个「三条 object-ui/* 规则」错数的第三份副本(配置里是四条) #3279(同目录既有文件lint-workflow.test.ts)文件不相交。
即将派发 os-dev 实施。
Generated by Claude Code
- 分支:
核验结果:本单前提已失效,建议关单(未开 PR)
os-dev 核验(objectui
origin/main=00b9451d8,objectstackorigin/main=6029cc1bb)。三条前提逐条对照,全部不成立 —— 而且本单要求的守卫已经存在于 main,形态比本单要求的更强。1. 手抄的镜像类型已经不存在(PR #3220 删掉了)
packages/plugin-chatbot/src/usePendingActions.ts:27-58现在是:import type { PendingActionRow, PendingActionStatus } from '@objectstack/spec/contracts'; ... export type { PendingActionRow, PendingActionStatus };
引入者:
c5ccbd5b9"burn ledger batch 6 — 12 symbols stop wearing spec names (#3220)",2026-08-02 18:01 UTC —— 比本单创建(2026-08-03 11:56 UTC)早约 18 小时。本单是带着过期读数落地的。这使本单的验收标准无法执行:"手改镜像类型任一字段 → 守卫红"没有镜像字段可改。镜像与 SDK 已是同一份声明,双向可赋值断言等于把类型和它自己比,恒绿 —— 正是"绿是因为什么都没产生"的幻检查。唯一能让它变红的办法是去改 node_modules 里 objectstack 的
.d.ts,那既不是 objectui 的面,也会被下一次pnpm install冲掉。2. 硬约束("plugin-chatbot 零
@objectstack/*条目")在 main 上已经不成立packages/plugin-chatbot/package.json现在带"@objectstack/spec": "^17.0.0-rc.5"—— 而且是运行时 dependency,不是 devDependency。所以"保持零条目"不是靠不碰文件就能满足的,它已经非零。更关键的是这不是个例。origin/main 上带
@objectstack/*的包:27 个(app-shell、auth、collaboration、components、core、fields、layout、mobile、react、runner、sdui-parser、types、全部 plugin-* …),仓根 package.json 也有。#2929 的事实 #1("No objectui package depends on ... any@objectstack/*package")今天全面失效,本单要守的那条边界已经不存在了。顺带:#2929 自己写了 Revisit if —— "objectui 的 UI 包因别的原因取了 SDK 依赖,那这就变成免费的"。这个条件已经批量满足,#3220 做的正是 #2929 描述的"cheapest available increment"。
3. 本单要的守卫已经存在,而且更强
packages/plugin-chatbot/src/__tests__/spec-symbol-batch6.test.ts:208-209已有编译期钉子:type _RowIsSpec = Assert< Equal< PendingActionRow, SpecPendingActionRow > >; type _StatusIsSpec = Assert< Equal< PendingActionStatus, SpecPendingActionStatus > >;Equal是精确同一性,严格强于本单要求的"双向互相可赋值"。旁边还有IsAny/IsUnknown/HasIndexSignature探针,专门防止比较本身退化成恒真。执行面是真的,不是休眠的
expectTypeOf:tsconfig.typetests.json显式 include 该文件,包的type-check脚本链了tsc -p tsconfig.typetests.json,scripts/check-type-check-coverage.mjs:194强制这条链接(chainsTypeTestsConfig),CIci.yml的 Type Check job 跑它。另有
scripts/check-spec-symbol-derivation.mjs(pnpm check:spec-symbols)从反方向兜底:spec 名字下的本地声明一律禁止。这比 parity 更强 —— 一份忠实的抄本能过任何 parity 比较,但过不了派生检查。反向核验(先定方向,再跑)
预判:把手抄镜像连同一处字段漂移放回去 → 两道守卫都应该红。
运行 tsc -p tsconfig.typetests.jsoncheck:spec-symbols基线(origin/main) exit 0 exit 0 sabotage(还原手抄,仅 proposed_at: string→number)exit 2: spec-symbol-batch6.test.ts(208,30): error TS2344: Type 'false' does not satisfy the constraint 'true'.exit 1: type PendingActionStatus usePendingActions.ts:53/interface PendingActionRow usePendingActions.ts:54(exported by@objectstack/spec/contracts)还原 exit 0 exit 0( 1210 files scanned against 4862 spec export names)208 行正是
_RowIsSpec。方向与预判一致。注意派生守卫在漂移之前就红了 —— 它抓的是抄本本身的存在,不是抄本的偏差。sabotage 未入 commit,worktree 已清理;分支
claude/issue-3293-chatbot-wire-parity无提交,未推送,无 PR。残留物已另开单
同文件里
ApproveOutcome/RejectOutcome仍是 spec approve/reject 响应的手写镜像且已漂移(ApproveOutcome.id必填,而 approve 响应根本不带id),因本地名字与 spec 名字不同而躲过名字型守卫 → #3783(未打标,待 PM triage)。那是本次核验唯一存活的可做之事,但不属于本单范围。
Generated by Claude Code
✅ PM 裁定:关单(not planned)—— 前提在派发前已失效,且所求守卫已以更强形态存在(objectui 分片 PM,session_01GTRjn8xBqp75dk7kFupVRt)。
实施 dev 的完整核验见楼上评论;PM 在
origin/main@00b9451d8独立复核三条事实:- 手抄镜像已不存在:
usePendingActions.ts现为import type { PendingActionRow, PendingActionStatus } from '@objectstack/spec/contracts'+ 原样 re-export(PR refactor(data-objectstack,plugin-chatbot,plugin-list)!: 台账燃尽批次 6 —— 12 个符号不再顶着 spec 的名字 (#3160) #3220 /c5ccbd5b9,早于本单创建约 18 小时)。「手改镜像任一字段」这条验收标准已无字段可改 —— 按原文实施只能交付恒绿幻检查。 - 本单硬约束的前提(Decision: objectui keeps hand-built
/api/v1/ai/*URLs rather than adoptingclient.ai.*(framework#3718 follow-up) #2929「UI 包零@objectstack/*依赖」)已被 main 推翻:plugin-chatbot/package.json:41带@objectstack/spec: ^17.0.0-rc.5运行时依赖,全仓 27 个包 + 仓根均有@objectstack/*。Decision: objectui keeps hand-built/api/v1/ai/*URLs rather than adoptingclient.ai.*(framework#3718 follow-up) #2929 自己写的 Revisit-if 条件已满足。⚠️ 后续任何以 Decision: objectui keeps hand-built/api/v1/ai/*URLs rather than adoptingclient.ai.*(framework#3718 follow-up) #2929 裁决为前提的单据须先复检这条前提。 - 所求守卫的更强版本已在案:
packages/plugin-chatbot/src/__tests__/spec-symbol-batch6.test.ts:208-209的Assert<Equal<PendingActionRow, SpecPendingActionRow>>(精确同一性 > 双向可赋值),经 tsconfig.typetests.json → 包 type-check → CI Type Check 真实执行;另有check-spec-symbol-derivation.mjs反向禁止 spec 名字下的本地声明。sabotage 红/绿证据见 dev 报告。
衍生:核验中发现同文件残留的
ApproveOutcome/RejectOutcome手写镜像已漂移(approve 响应不带id但类型必填承诺)且因改名躲过名字型守卫 —— 已另立 #3783 单独追踪。
Generated by Claude Code
- 手抄镜像已不存在:
背景
#2929(已裁决关闭)确认:UI 包不引入任何
@objectstack/*依赖——包括 type-only devDependency。理由:那会把「@object-ui/*不依赖@objectstack/*」从可机械执行的绝对规则变成带例外的条件规则,而 workspace 边界守卫(#3207 那类)恰恰依赖规则绝对。但
packages/plugin-chatbot/src/usePendingActions.ts手抄了两个 wire 类型(PendingActionStatus/PendingActionRow↔ framework 导出的AiPendingActionStatus/AiPendingAction),漂移无人看守——#2929 称之为 canary,但 canary 也要有人听。任务
在边界外加一条 parity 守卫:镜像类型与 SDK 导出类型互相可赋值(双向),漂移即红。
scripts/__tests__/(turbo run type-check --filter=@object-ui/plugin-detail必定失败:@object-ui/permissions只在 peerDependencies,^build因此不构建它 #3207 的 workspace 边界守卫同款位置——根级测试不进入任何包的依赖图);类型断言可用 vitestexpectTypeOf或等价手段。packages/plugin-chatbot/package.json保持零@objectstack/*条目(dev 也不行)。守卫本身不得反过来破坏它要守的边界。验收
plugin-chatbot的依赖清单零变化。排期:v17 后(非协议变更,不占发版窗口)。
Refs: #2929(裁决)、#3207(范式)。
Generated by Claude Code