refactor(spec)!: 退役 plugin-runtime 家族五个 schema —— 无任何 runtime 实现的「Dynamic Loading」词表 (#4834, ADR-0049) - #4878
Conversation
…ing" vocabulary no runtime implemented (#4834, ADR-0049) ADR-0049 enforce-or-remove, maintainer-ruled REMOVE. `DynamicLoadRequestSchema`, `DynamicUnloadRequestSchema`, `DynamicPluginResultSchema`, `PluginSourceSchema` and `DynamicPluginOperationSchema` (+ seven type aliases) declared runtime load / unload / reload of plugins without a kernel restart — sources, integrity hashes, sandboxing, drain strategies, dependent-cascade policy. None of those operations exists. Bare-name scan of objectstack, cloud (5df2c69) and objectui (785b8a5): zero references outside this package's declaration, its unit tests and the generated artifacts, each empty result control-verified against a known-present neighbour. The whole module is deleted. #3896 removed this module's discovery/sandbox config island and left these five in place explicitly ("operation contracts, not security promises; the enforce-or-remove call on them is a design decision rather than a correction") — a suspension that lived only in a changeset paragraph with no issue carrying it. #4834 is that decision. Route: whole-def removal (#4650 route 3). No `retiredKey()` tombstones — nothing parses these schemas, so a prescription could never be received; the same disposition this module set in #3896. The `json-schema.manifest.json` ratchet (#2978) demanded the five def keys be deleted deliberately, and gen:schema then reported all 23 authorable-surface deletions as carrying their own proof ("def no longer emitted by this build"). This subsumes the kernel half of #4657: `DynamicLoadRequest.activationEvents`'s `retiredKey()` tombstone goes with the shape that carried it, which is strictly stronger than the tombstone ("this request shape does not exist" > "this one key does not exist"). The studio half (`StudioPluginManifest.activationEvents`) is untouched and still enforced. The #4657 D3 entry is corrected rather than deleted — its studio half is live and its history must keep replaying. - ADR-0087 D3 semantic migration `plugin-runtime-family-retired` (no `sys_metadata` source exists for a D2 rewrite: these are root request/result payload shapes, embedded in no parent schema) - compiler-API export pin with three anti-vacuity guards, `holdersOf(name)` exactly `[]` across all 16 entries — sabotage-verified - PLUGIN_STANDARDS.md §5.3 + capability table now say "Not built", not ✅ - baselines regenerated from rebuilt source; changeset carries the merged two-layer migration narrative Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0176qgxgCXTJCUv4YFLtusP9
…gin-runtime-family-retire # Conflicts: # packages/spec/src/migrations/registry.ts
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
📓 Docs Drift CheckThis PR changes 1 package(s): 106 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
…gin-runtime-family-retire
二次同步完成(
|
| 条目 | 归属 | 位置 | spec-changes.json |
|---|---|---|---|
plugin-activation-events-retired |
#4657 | migrations/registry.ts semantic |
2 |
batch-row-result-schema-shape |
#4793 / #4841 | migrations/registry.ts:942 semantic |
2 |
hook-body-crypto-hash-removed |
#4391 / #4871 | conversions/registry.ts:3460(D2),wired at migrations/registry.ts:824 |
2 |
plugin-runtime-family-retired |
本单 | migrations/registry.ts semantic |
2 |
一条未丢。注意 hook-body-crypto-hash-removed 是 D2 conversion(不在 semantic[]),按 conversionIds 挂在 step17 上 —— 用 id: '...' 扫 migrations/registry.ts 会得到 0,这是形态差异不是丢失。
ratchet delta 相对新 main —— 纯删除,零新增
| 生成物 | 删 | 增 |
|---|---|---|
api-surface.json |
−12 | 0 |
authorable-surface.json |
−23 | 0 |
json-schema.manifest.json |
−5 | 0 |
dual-source-exports.baseline.json |
0 | 0(未触碰) |
check:generated 在合并后直接就是 current,无需重生成 —— #4852 未动任何生成物。因此本次没有 git checkout origin/main -- 文件 + 整体重生成的动作可做,也没有触发 #4868(os-regen 未挂起任何 deferred artifact)。
精确名 0 命中(⚠️ 全名带引号匹配,规避子串误撞)
api-surface.json 中,#4616 / #4657 / 本单的退役名逐个精确查,全部 0:
EmailTemplateSchema (const) 0 ActivationEventSchema (const) 0
SMSTemplateSchema (const) 0 ActivationEvent (type) 0
PushNotificationSchema (const) 0 DynamicLoadRequestSchema (const) 0
InAppNotificationSchema (const) 0 PluginSourceSchema (const) 0
EmailTemplate / SMSTemplate / DynamicPluginOperation (type) 0
PushNotification / InAppNotification (type) 0
对照验证(证明匹配器不是恒返 0):EmailTemplateDefinitionSchema (const) = 1、PluginSchema (const) = 1、NotificationSeveritySchema (const) = 1。这正是子串匹配会误撞的那个 EmailTemplateDefinition 家族 —— 精确名下它安然存活,退役名归零。
合并后重跑读数
| 项 | 读数 |
|---|---|
gen:schema / check:generated |
✅ All 8 generated artifacts are up to date |
check:dual-source-exports |
✅ 0 accepted dual-source(4264 names / 16 entry points,171 re-exported) |
check:strictness-ledger(#4852 新量尺) |
✅ 67 files / 5 triaged dirs,site counts match;remaining-strip 51 open files / 325 sites,counts match |
| 源码审计组 | ✅ check:liveness / check:empty-state / check:skill-examples / check:react-declaration-parity / check:variant-docs / check:exported-any 全 PASS |
check:authorable-surface / check:api-surface / check:spec-changes / check:upgrade-guide / check:skill-refs / check:skill-docs |
✅ 全 PASS |
spec test |
✅ 295 files / 7360 tests passed |
spec typecheck |
✅ tsc --noEmit 无输出 |
| 全仓 typecheck | ✅ 122 successful, 122 total |
| 全仓 build | ✅ 71 successful, 71 total |
HEAD f30f045e5 已 push。未 un-draft、未 auto-merge,等你操作。
Generated by Claude Code
Generated by Claude Code
✅ 验收通过 —— 已转正 + auto-merge同步后的 head 1. 同步形态合规两次都是 merge commit, 2. step17 四条条目并存(os-regen 静默吞并的检验点)今天已在三个 PR 上实证:
四条全在,一条没丢。 旁证:#4391 的 D2 conversion 在 3. ratchet delta 相对新 main —— 纯删除、零新增
这正是整 def 删除该有的形态。 对照组:#4391 是枚举值收窄,四张 ratchet 全部字节相同 —— 两种退役形态在仪器上的可见性差异,今天各测到一例,互为佐证。 4. 十二个名字的存活声明:全 0对六个
残留提及逐条看过,全部是注释、pin 测试的断言词、迁移散文,没有一处活声明: ⛔ 这一步必须用带引号的精确名:裸名 5.
|
Fixes #4834
按维护者裁决(remove)删除
packages/spec/src/kernel/plugin-runtime.zod.ts的五个 schema 及全部类型别名。整个文件就此清空,因此文件本身与kernel/index.ts的 re-export 一并删除 —— 文件里除这五个 def 外只剩两块 REMOVED 注释(#3896 的 discovery/sandbox 岛、#4657 的ActivationEventSchema),没有任何残留活物。删除的十二个名字:
DynamicLoadRequestSchema/DynamicUnloadRequestSchema/DynamicPluginResultSchema/PluginSourceSchema/DynamicPluginOperationSchema,以及DynamicLoadRequest/DynamicUnloadRequest/DynamicPluginResult/PluginSource/DynamicPluginOperation/DynamicLoadRequestInput/DynamicUnloadRequestInput。1. 三仓消费方复核(裸名扫描 + 对照验证)
扫描词为五个 schema 名 + 五个类型名(裸名
DynamicLoadRequest等同时覆盖...Schema与...Input)。git -C /workspace/objectui grep,785b8a5exit=1)PluginContext→ROADMAP.md、packages/core/src/registry/PluginSystem.ts、packages/types/src/plugin-scope.ts等命中;@objectstack/spec/kernelimporter 命中 10+ 文件(app-shell/.../PackagesPage.tsx、core/src/validation/schema-validator.ts…)git -C /workspace/cloud grep,5df2c69exit=1)PluginContext→packages/objectos-runtime/src/ai-token-guardrail-plugin.ts等;@objectstack/spec/kernelimporter →apps/objectos/test/always-on-slate.test.ts、packages/objectos-runtime/src/capability-loader.ts等⛔ 两个 sibling 仓全程用
git -C 路径 grep形式(带-C参数),没有cd。空结果均以「确定存在的邻近词反查」证伪了「扫描器/路径坏了」这一解释。另核:
*.form.ts、packages/cli、skills/、examples/四处零命中 —— 因此本单不涉及 form input 裁剪,也不触发 i18n bundle 变更(pnpm check:i18n实跑 OK 佐证)。2. 退役形态:#4650 路径 3(门禁实跑裁定,非照抄先例)
没有走
retiredKey()墓碑:这五个 schema 已无任何东西去 parse,「一份没人能收到的处方就是噪音」—— 正是本模块自己在 #3896 立下的先例。第一次
gen:schema实报 ——json-schema.manifest.jsonratchet(#2978)先开火:按其指示有意删除五个 manifest key 后重跑,per-key ratchet 自行判定为路径 3:
四张 ratchet 确有变化(#4391 的「枚举值收窄对 ratchet 不可见」异常信号未出现,符合整 def 删除的预期)。相对
origin/main的净 delta,零新增:api-surface.jsonauthorable-surface.jsonjson-schema.manifest.jsoncontent/docs/references/kernel/plugin-runtime.mdx删除,meta.json/index.mdx由gen:docs重算3. ADR-0087 conversion 逐条评估
对照两侧先例:需要 D2 的是有作者源 /
sys_metadata行可改写的(#4734enable.trash、#4391crypto.hashtoken);不需要的是纯导出面或 runtime 请求形状(#4767 / #4783 / #4616 / #4657)。逐个论证:DynamicLoadRequestSchema— runtime 请求载荷形状,根 schema,无任何父 schema 嵌入它,不在 stack 树内(applyConversions接在normalizeStackInput上,只走 stack 树)。四仓零 caller,连「构造过一个」的证据都不存在。无 D2:conversion 要改写的源不存在,伪造一个永远命中不了的 conversion 只会制造「已自动迁移」的假象。DynamicUnloadRequestSchema— 同上,请求形状。无 D2。DynamicPluginResultSchema— 响应/结果形状,连作者面都谈不上(作者从不写 result,只可能去读)。这正是 skill 里点名的EnhancedApiError.fieldErrors那一类:response-surface with no source to rewrite → 登记为 D3 SemanticMigration,不是 D2。无 D2。PluginSourceSchema— 本单里唯一需要单独判断「是否出现在作者源里」的一个。结论:否。它的唯一可达路径是DynamicLoadRequest.source(gen:schema的可达性 BFS 亦证实:它不从任何 metadata-type root 可达,故其 authorable-surface 条目本就是 over-collection),既不是独立 metadata type,也不被.stack.ts/objectstack.config.ts的任何键嵌入 ——stack.plugins走z.array(z.unknown()),manifest走自己的形状。没有sys_metadata行能携带它。无 D2。DynamicPluginOperationSchema— 纯枚举 def,唯一可达路径是DynamicPluginResult.operation,随之而去。无 D2。→ 五个全部无 D2,统一登记为一条 ADR-0087 D3 SemanticMigration
plugin-runtime-family-retired(与 #4616 / #4767 / #4783 同一处置)。4. #4657 D3 条目
plugin-activation-events-retired的处置 —— 保留并修正理由(以事实而非直觉裁定):该条目是双 surface 的,
kernel.dynamicLoadRequest.activationEvents / studio.studioPluginManifest.activationEvents。studio 那一半至今活着:StudioPluginManifest是defineStudioPlugin的入参,仍以 strict parse + guidance 拒绝该键。删掉整条会连同一个仍在生效的迁移记录一起删掉,历史链也断。因此:条目保留,kernel 半边的散文改写为记录本次 supersede(不再声称存在一个
retiredKey()墓碑 —— 那是删除后立刻会变成假话的一句),acceptanceCriteria同步改为「kernel 侧适用 #4834 的更强判据:根本不存在DynamicLoadRequest可以把这个键写进去」。step17 的rationale也补了一段 supersede 说明。这就是 skill §4「a correction must propagate to every one of these lines」那条纪律。5. 两层迁移话术(合并写清)
DynamicLoadRequestSchema上挂着 #4657 刚立的activationEvents墓碑,整 def 删除会连墓碑一起带走。这是合法的 —— 「整个请求形状已移除」严格强于「该键已移除」—— 但作者收到的指令因此变了,changeset 与 D3 都按两层合并写:6. Pin + sabotage 实跑
新增
packages/spec/src/kernel/plugin-runtime-retirement.test.ts:TypeScript compiler-API 程序,从package.json的 exports map 枚举全部公共入口,对十二个名字断言holdersOf(name)精确相等[](不是not.toContain)。三道防空转守卫:入口枚举必须含.与./kernel且多于 10 项;每个入口的 module symbol 必须解析成功;holdersOf必须能在存在的名字上找到 holder(holdersOf('PluginSchema')含./kernel)。另有 runtime namespace 一致性断言与「模块本身已不存在,深路径 import 也拿不到」。sabotage 三项实跑输出:
即:复活声明红、从别的入口顶名 re-export 红、空转检验被守卫拦住而非静默通过。
同时改了 #4657 的 pin(
activation-events-retirement.test.ts):它的防空转锚点原本用DynamicLoadRequestSchema/PluginSourceSchema(被退役键的父形状),现改为存活邻居PluginSchema/PluginContextSchema;其 kernel 侧 parse 断言随墓碑一并移除,studio 侧断言原样保留。7. 验证读数(全部实跑)
gen:schemacheck:generatedcheck:authorable-surfacecheck:api-surfacecheck:dual-source-exportscheck:liveness/check:empty-state/check:skill-examples/check:react-declaration-parity/check:variant-docs/check:strictness-ledger/check:exported-any全 PASScheck:spec-changes/check:upgrade-guide/check:skill-refs/check:skill-docspnpm check:i18ntesttypechecktsc --noEmit无输出8. 同步记录
push 前
git fetch origin main发现 main 前进到0e96e4628(#4871 / #4391crypto.hash退役,同样动 spec 生成物),按 AGENTS.md §3 走git merge origin/main(未 rebase、未 force-push)。packages/spec/src/migrations/registry.ts冲突:双方都在 step17 的rationale尾部追加段落。两边条目全部保留(我方 supersede 段在前,对方以 "Finally it removes…" 开头的段在后),并把我方末行结尾的引号加逗号改为引号接\n\n续接。git checkout origin/main --加文件路径的方式取 main 版,重新施加本单的基线删除(23 authorable 行 + 5 manifest key),再pnpm install --frozen-lockfile→build→check:generated --fix整体重新生成,不做任何文本合并。commit 时 os-regen 守卫确认spec-changes.json与protocol-upgrade-guide.md两件 deferred artifact 均 current。9. 其他
content/docs/releases/一个字未碰。packages/spec/PLUGIN_STANDARDS.md§5.3 改写为 REMOVED 说明(顺带带走POST /data/sharing/rules绕过SharingRuleSchema:criteria缺失或拼错静默变成"共享该对象全部记录",与 ADR-0049 "never seeded as a permissive match-all" 直接冲突 #3896 之后就已失效的PluginDiscoveryConfigSchema/DynamicLoadingConfigSchema两行陈述),§5.4 能力表Dynamic Loading由 ✅ 改为 ❌ Not built;PROTOCOL_MAP.md删除该模块行。packages/spec/scripts/build-docs.ts的 kernel 分节页序列表仍含'plugin-runtime'—— 有意不动:该列表是排序提示,对不存在的页面本就宽容(同列表里feature/dev-plugin两个已退役家族的页名至今保留),gen:docs已产出正确的meta.json,改它不改变任何输出。🤖 Generated with Claude Code
https://claude.ai/code/session_0176qgxgCXTJCUv4YFLtusP9