feat(plugin-dev)!: retire the stub table — DevPlugin assembles real plugins, empty slots stay empty (ADR-0115) - #4137
Merged
Conversation
…lugins, empty slots stay empty (ADR-0115, #4104) Executes ADR-0115 in full. The fill-every-slot stub table is deleted: the fabricators (data/auth/security.*/ui, plus the ai/automation/ notification trio #4086 left gated-but-registered), the plugin-dev-only in-memory tier (file-storage/search/realtime/workflow), and the duplicate metadata copy and createMemory* wrappers (the kernel pre-injects core's CORE_FALLBACK_FACTORIES for empty core slots, so behavior is unchanged there). New: init() refuses NODE_ENV=production (escape hatch OS_ALLOW_DEV_PLUGIN_IN_PRODUCTION=1, PD #9), and the assembly auto-wires @objectstack/service-storage (local-disk adapter) and @objectstack/service-realtime (in-memory adapter) when installed — the 3b i18n auto-detect pattern, so zero-config dev keeps working storage/realtime through real implementations. Docs converge on reality (packages.mdx entry, README, class doc, services-checklist i18n rows); breaking changeset carries the full FROM→TO table per retired slot. ADR-0115 gains the post-#4086 reconciliation note (three gated fabricators join Tier A; #4089 closed at source by #4082; executed as one PR at the maintainer's direction). Verified: plugin-dev 10/10, runtime 924/924, core 415/415, eslint clean; end-to-end boot shows retired slots empty (404 / handled=false, /ai/agents keeps its 200 empty-list courtesy), file-storage resolving to SwappableStorageService and realtime to InMemoryRealtimeAdapter, and the kernel's own fallback pre-injection intact. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BEM82RNKyyyTNPYHK1VJJS
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
4 tasks
…previous head Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BEM82RNKyyyTNPYHK1VJJS
…0115 wholesale deletion Main's #4112 (retire the /storage dispatcher bridge, #4087) adjusted the file-storage stub's self-description and its test; both live inside the stub table this branch deletes entirely, and the deletion supersedes the adjustment: the in-memory storage stub is gone and the real @objectstack/service-storage — which #4112 points at — is auto-wired. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BEM82RNKyyyTNPYHK1VJJS
…e deletion absorbs its subset Main landed #4126 (the #4093 security-trio + production-guard subset) while this PR was in flight. Where they overlap, its shipped choices win: the escape hatch is OS_ALLOW_DEV_PLUGIN, the guard is a module-level assertNotProduction(), and empty security slots get one loud 'NOT enforced' boot warn — all ported into this branch's no-stub end state, which supersedes the rest of its plugin-dev diff (comments and stub-table edits inside deleted code). ADR-0115's reconciliation update gains the #4126/#4113 facts; the auth-stub deletion stands (the runtime /auth mock #4113 tracks is the same fabrication with or without it). Verified post-merge: plugin-dev 10/10, runtime 923/923, plugin-hono-server 132/132, eslint clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BEM82RNKyyyTNPYHK1VJJS
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 1 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
os-zhuang
marked this pull request as ready for review
July 30, 2026 11:59
os-zhuang
pushed a commit
that referenced
this pull request
Jul 30, 2026
…superseded, runtime /ui discovery gate kept #4137 retired the entire stub table wholesale (Tiers A+B+C), which includes the data and ui retirements this branch carried incrementally — plugin-dev files resolve to main's state. What this branch still adds is the runtime seam #4137 deliberately left untouched: discovery's routes.ui/services.ui gate on the protocol service that actually serves /ui, which matters more post-ADR-0115 because no boot registers a ui-slot occupant at all now. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018UNGqBQcdJ2RYHtWgntJ9B
os-zhuang
added a commit
that referenced
this pull request
Jul 30, 2026
… it, not the vestigial ui slot (#4093) (#4146) domains/ui.ts serves GET /ui/view/:object off the `protocol` service and 503s without it; the `ui` core-service slot never enters that decision, and nothing in the platform registers a `ui` service — plugin-dev's shapeless placeholder was its only occupant ever, and ADR-0115 (#4137) retired it. Gating routes.ui on slot presence was therefore wrong in both directions: a dev boot with the placeholder but no protocol advertised a route that could only 503, and every boot without a placeholder — production always, and all dev boots post- ADR-0115 — hid a route that serves fine. routes.ui and services.ui now gate on `typeof protocol?.getUiView === 'function'` — the domain handler's own guard, byte for byte, the same rule the mcp advertisement follows (same predicate ⇒ same answer). services.ui reports the serving implementation (provider metadata-protocol, honoring any __serviceInfo it declares), and the unavailable message names the actual remedy — register MetadataPlugin (@objectstack/metadata-protocol) — instead of svcUnavailable's "install a ui plugin", which names a plugin that does not exist. This PR originally also carried plugin-dev's incremental data/ui stub retirements; ADR-0115 (#4137) retired the whole stub table while the branch was open, so that half resolved to main's state and the ADR-0076 annotation now closes out pointing at ADR-0115. The changeset is a runtime-only patch. The one surviving fabricator is outside plugin-dev: the dispatcher's /auth mock fallback, #4113. Tests: with a protocol, /ui is advertised and really serves (getUiView called with the parsed object/type); without one it is not advertised and the remedy is named; a ui-slot occupant with no protocol — the old dev-boot shape — stays un-advertised AND 503s (the slot buys no route); a wrong-shaped protocol mirrors the domain. runtime 936 / plugin-dev 10 / metadata-protocol 110 pass; build 71/71; eslint clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Jul 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #4104. 执行 ADR-0115(PR #4103 裁决)的全部实施。按维护者指示("统一 ADR,并继续完成所有开发"),原定两个实施 PR 收敛为这一个 —— #4089 已被 #4082 在源头修掉,PR 边界失去存在理由。
删掉的(A+B+C 三档一次清空)
dev-plugin.ts的整张 stub 台面消失:data、auth、无形状ui,加 fix(runtime,metadata-protocol): every dispatcher domain gates on handlerReady, not slot occupancy (#4058 step 2) #4086 留下的ai/automation/notification(security.*三件套已由 fix(plugin-dev,plugin-hono-server): retire the security dev stubs; refuse to load under NODE_ENV=production (#4093) #4126 先行删除)。metadata第二份 +cache/queue/job/i18n包装。行为无变化 —— 端到端证实 kernel 本来就用CORE_FALLBACK_FACTORIES(kernel.ts:322)为空的 core 槽位预注入同一批 fallback。file-storage/search/realtime/workflow四个内存实现。DEV_STUB_FACTORIES/DEV_STUB_SELF_INFO/SHAPELESS_STUB_SELF_INFO/NO_DEV_STUB_SERVICES/ 填充循环全部不复存在 —— ADR 终态 grep 为空。新增的
assertNotProduction()在NODE_ENV === 'production'拒绝初始化;逃逸阀OS_ALLOW_DEV_PLUGIN=1(PD [WIP] Create a new release version #9 形状)。@objectstack/service-storage(local 磁盘适配器)与@objectstack/service-realtime(默认内存适配器)作为可选子插件,装了即接线 —— 复用 3b 节 i18n 自动检测先例。零配置 dev 的存储/实时能力由真实现保住。minor进 fixed group。文档收敛(D7)
packages.mdx条目、包 README、class doc、services-checklist.mdx的 i18n 注册表格全部改为装配现实;ADR-0115 增补 post-#4086 对账更新(含 #4126/#4113 的第 4 条事实)。验证(两次合流后最新)
@objectstack/plugin-dev10/10 ·@objectstack/runtime923/923 ·@objectstack/plugin-hono-server132/132 ·@objectstack/core415/415 · eslint 干净 · tsup(含 DTS)通过getService抛错(空槽),/api/v1/automation404,/api/v1/ai/agents保留 200{"agents":[]}礼遇;file-storage解析为真实SwappableStorageService,realtime解析为真实InMemoryRealtimeAdapter;kernel 的CORE_FALLBACK_FACTORIES预注入不受影响。过程记录(CI 一度静默)
PR 创建后 GitHub 对
mergeable_state: dirty(与 main 冲突)的 PR 静默跳过pull_request工作流 —— 空提交与 close/reopen 都无法触发。两次合入 main 解决冲突后恢复正常。风险与缓冲
对外部 17.x-rc 消费者 breaking:changeset 表即处方;#4082/#4086 起 discovery 已把这些槽位如实广告为
stub/不可服务,实际影响面已核实为仓库内零调用点(search/workflow/ui)或有真实替代(其余)。🤖 Generated with Claude Code
https://claude.ai/code/session_01BEM82RNKyyyTNPYHK1VJJS