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.
|
…) (objectstack-ai#4893) 2026-08-03 的 v17 协议变更派发里,有四类已经付出过代价的经验,现行 skill 里 没有或只写了半截。同日另一车道的 objectstack-ai#4885 已沉淀八条,本单只补它覆盖边界之外的。 pm-dispatch —— Operational notes 由四条扩到八条: - 5:rerun_failed_jobs 复用原 run 的提交/合并 ref,不重算。红的原因若是「基上 缺一个已合并的修复」,重跑无效,只有推新提交才拿得到新的合并 ref(objectstack-ai#4852 因此 在队列外空转 100 分钟)。与 rerun-safety-nightly.yml 无关,后者查的是测试污染。 - 6:读数纪律。cd X && cmd 短路会在错的仓里执行(跨仓一律 git -C); git grep -c | wc -l 数的是文件数不是命中数;裸名 grep 会被幸存家族当子串命中, 退役核验要带引号精确名、更硬的判据是查声明式而非提及。零命中必须用确定存在的 邻近词反查。 - 7:CI 红了先取完整日志归档。completeness check 绿只说明没有 worker 静默死掉; turbo 并发输出相邻不等于因果(test 的 dependsOn 只有 ^build,spec 无 pretest); 不要只看 tail。据错误结论开的 PR 要撤回 draft 并解绑 Fixes。 - 8:共享基础设施类修复按症状复查 main。duplicate-fix-guard.yml 只覆盖「同仓 + 同一个 Fixes #N」,objectstack-ai#4864 与 objectstack-ai#4856 挂在不同 issue 号下,门禁看不到,而后者先合的 60s 会被前者降回 30s。 另在 note 1 上补:「不在 main 上」是二义读数(兼容「排队中」与「没入队」);队列 分支 base sha 串成链,可读出排第几;转 draft 会同时掉 auto-merge 与队列成员资格。 step 7 之后新增「入队与落地」小节:merge=os-regen 的七条路径(含两条文档产物)、 四步同步协议、以及跟到 MERGED 而不是跟到入队为止。 spec-property-retirement: - 新增「四张 ratchet 的可见性按路线相反」—— 枚举值收窄不可见(objectstack-ai#4391),整 def 删除必须变化(objectstack-ai#4834:-12/-23/-5);拿错对照会双向判错。 - 修好第 2 节指向 plugin-runtime.zod.ts:243-248 的先例引用,该文件已被 objectstack-ai#4878 整体删除。 Fixes objectstack-ai#4892 Claude-Session: https://claude.ai/code/session_0176qgxgCXTJCUv4YFLtusP9 Co-authored-by: Claude <noreply@anthropic.com>
…te-limit shape (objectstack-ai#4911) (objectstack-ai#4947) ADR-0049 enforce-or-remove: `ConnectorSchema.rateLimitConfig` declared an outbound throttle that no engine ever applied. The platform's only token bucket (runtime security/rate-limit.ts) is INBOUND; no connector provider reads the key and no seam exists that could. Removed rather than kept — the vocabulary returns with an implementation (objectstack-ai#4834 / PR objectstack-ai#4878 ruling). - `retiredKey()` tombstone on `ConnectorSchema.rateLimitConfig` (non-strict schema — a plain delete would be an ADR-0104 silent strip) - `ConnectorRateLimitConfigSchema`/`ConnectorRateLimitConfig` and the orphaned `RateLimitStrategySchema`/`RateLimitStrategy` removed with it - D2 conversion `connector-rate-limit-config-removed` (retiredFromLoadPath) + D3 chain step at major 17 - objectstack-ai#4684's RENAMED_DEFS entry absorbed: rename-then-delete in the same unreleased major is a delete - baselines updated deliberately (manifest -2 defs, authorable -6 lines +2 [RETIRED], api-surface -4 exports); docs/spec-changes/upgrade guide regenerated Claude-Session: https://claude.ai/code/session_01Ehu85kbvMcrNTUJjwxvLJ9 Co-authored-by: Claude <noreply@anthropic.com>
objectstack-ai#4938) (objectstack-ai#5293) * refactor(spec)!: 退役 `HttpServerConfigSchema` —— 九个键零 reader 且没有任何作者面入口 (objectstack-ai#4938) `system/http-server.zod.ts` 的 `HttpServerConfigSchema` 声明九个键 (`port` / `host` / `cors` / `requestTimeout` / `bodyLimit` / `compression` / `security` / `static` / `trustProxy`),`authorable-surface.json` 全部在册、 `content/docs/references/` 全部渲染成协议文档。两头都是空的: 1. **零 runtime reader** —— 三个仓(objectstack / cloud / objectui)里没有任何 包用它解析过文档或读过它的键;spec 之外唯一的命中是 `shared/http.zod.ts` 里指回来的 "Used by:" 注释。 2. **零作者面入口** —— 比普通的「写得下去、不生效」更彻底。`stack.zod.ts` 没有 `server:` 键,`config-schema.json` 里零命中,也没有 settings manifest 承载它,所以文档承诺的这套配置连**写下去**都做不到。 按 ADR-0049 enforce-or-remove 与 2026-08-04 裁决,退役这个不可达面。 退役形态是**容器,不是整个文件**:`RouteHandlerMetadata`(`packages/rest` 消费)与 `MiddlewareType` / `MiddlewareConfig`(`packages/runtime` 消费) 留下;`shared/http.zod.ts` 的 `CorsConfigSchema` / `RateLimitConfigSchema` / `StaticMountSchema` 各自另有 live consumer,也未被孤立。 **不打 `retiredKey()` tombstone**(playbook 路线 3,objectstack-ai#4834 / PR objectstack-ai#4878 同形): tombstone 是给「写下这个键的人」的话,而唯一能写 server 键的面是 objectstack-ai#5006 的 `StackServerConfigSchema`,它是 `strictObject`,七个键早已按名拒绝并各带处方 —— 本 PR 把那些处方从「no runtime reads it」刷新为指明退役与替代。**不注册 D2 conversion**:没有任何作者源需要改写。代码消费者的通道是 `api-surface.json` (−3)接 release-time 的 `spec-changes.json` diff,加上 changeset。 `cors` 按裁决登记为 `server:` 窄形状的**首个逐键准入候选**(嵌入是真场景), 届时按 objectstack-ai#4910 范式键与执行器一并到位,不以死键形态占导出面。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ErbEDVAg1No9gdg1pgDAGB * chore(spec): 与 main 同步后整体重生成生成物(objectstack-ai#5289 落地后) `git merge origin/main` 零冲突,但 os-regen 驱动在生成物上不做文本合并, 所以按流程把 8 条 os-regen 路径整体 checkout 回 origin/main,再全量重跑 生成器(gen:schema / gen:api-surface / gen:spec-changes / gen:upgrade-guide / gen:docs / gen:skill-refs / gen:skill-docs / gen:strictness-ledger),两侧条目 逐条断言仍在。 - 兄弟侧 objectstack-ai#5289:6 条 `ui/Theme` / `ui/Typography` 的 `[RETIRED]` 标记在册; `ui/Animation` / `ui/ZIndex` 两个 def 仍不在 manifest; `theme-inert-token-scales-removed` 的 D2 条目与 D3 链步完好,并已到达 `spec-changes.json` 与 protocol-upgrade-guide。 - 本侧 objectstack-ai#4938:manifest −1 / authorable −9 / api-surface −3 仍生效; 两处「有意删除」在新基线 f8cfbb4 上按 objectstack-ai#2978 与 objectstack-ai#4650 路径 3 重新自证。 - strictness ledger 整体重跑(未手改数字):`system/` 368 → 366,triaged 总数 476 由 objectstack-ai#5289 带入,非本 PR 改动。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ErbEDVAg1No9gdg1pgDAGB --------- Co-authored-by: Claude <noreply@anthropic.com>
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