Skip to content

feat(core): init 阶段取服务的声明契约改为强制 — check:init-service-contract 门禁 (#4471) - #4631

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-4471-init-service-declared-enforced
Aug 2, 2026
Merged

feat(core): init 阶段取服务的声明契约改为强制 — check:init-service-contract 门禁 (#4471)#4631
os-zhuang merged 1 commit into
mainfrom
claude/issue-4471-init-service-declared-enforced

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Fixes #4471

问题

ADR-0116 / packages/core/src/plugin-order.ts 的顺序契约机制是完备的(dependencies 硬依赖、optionalDependencies 有则排前、requiresServices + assertInitServiceRequirements 具名报错),但所有声明都是自愿的:一个插件在 init()getService('X') 却什么都不声明,没有任何一层会指出来——只会在某个组合顺序下静默拿不到服务,而 miss 又通常藏在 best-effort 的 try/catch + warn 里。#4085#4420 都是这么发生的,后者的代价是数据一致性级别(每次重启丢光在途审批)。

方案(issue 期望的方向一:静态 check:* 门禁)

scripts/check-init-service-contract.mjs — 用 TypeScript AST 扫描 packages/ 下所有插件单元(class 形态与对象字面量形态都覆盖),规则:

接入:根 package.jsoncheck:init-service-contract + lint.yml 新步骤;plugin-order.ts 头注释补充"声明不是自愿的"一段,指向该门禁。

门禁在现有代码上的初次收获(修复前全树 11 处未声明,全部在本 PR 补上声明)

首次运行即抓出 11 处未声明的 init 期消费——正是 issue 说的"少数漏网的那个最贵":

消费方 init 期消费 补上的声明
@objectstack/metadata MetadataPlugin manifest optionalDependencies: [objectql]
@objectstack/rest rest-api-plugin manifest(注册 sys_import_job) 同上
@objectstack/cli serve.ts 两个内联插件 http.server/http-server optionalDependencies: [com.objectstack.server.hono]
service-analytics data(auto-bridge 探测) optionalDependencies: [objectql]
service-datasource admin manifest(Setup 导航) 同上
service-job manifest + cluster optionalDependencies: [objectql, service.cluster]
service-knowledge objectql(RLS 复查) optionalDependencies: [objectql]
service-queue / service-settings / service-storage manifest(注册 sys 表) 同上

每一处都保持原有的"缺 provider 时按设计降级"语义不变——变化只是:两者同时组合时,内核现在确定性地把 provider 排在前面,不再靠注册顺序的运气。

验证

范围外

issue 里"另外值得单独定一条"的日志级别约定(best-effort 降级导致"看起来正常、实则不持久"时不应是 warn)未在本 PR 实现,已另开 issue 跟踪(见 PR 评论关联)。

🤖 Generated with Claude Code

https://claude.ai/code/session_012C2cd7tL8QDoZ2QKN3djJ5


Generated by Claude Code

…ate (#4471)

ADR-0116's ordering contract (dependencies / optionalDependencies /
requiresServices / providesServices) was complete but voluntary: a plugin
resolving getService('X') during init() while declaring nothing was invisible
to every check, failing only under unlucky composition orders — the #4085 and
#4420 failure class, the latter at data-consistency cost.

- scripts/check-init-service-contract.mjs: AST scan of every plugin unit
  (classes and object literals) under packages/. Walks the init() call graph
  transitively (same-class methods, same-file functions — the #4420 call sat
  in a private helper), skips deferred callbacks (hooks) and start(), and
  errors on any init-reachable getService of a workspace-provided service not
  covered by a declaration. 12-case --self-test pins the #4420 pre-fix shape
  caught, all declared shapes passing, and the start()/hook shapes exempt.
- Wired as check:init-service-contract in root package.json and lint.yml.
- Declares the 11 previously undeclared init-time consumers the gate found
  (metadata, rest, two cli serve plugins, analytics, datasource-admin, job,
  knowledge, queue, settings, storage) via optionalDependencies on their
  providers — declared tolerance in the plugin, never a checker-side ledger.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012C2cd7tL8QDoZ2QKN3djJ5
@vercel

vercel Bot commented Aug 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 2, 2026 12:20pm

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation ci/cd dependencies Pull requests that update a dependency file tooling size/l labels Aug 2, 2026
@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 11 package(s): @objectstack/cli, @objectstack/core, @objectstack/metadata, @objectstack/rest, @objectstack/service-analytics, @objectstack/service-datasource, @objectstack/service-job, @objectstack/service-knowledge, @objectstack/service-queue, @objectstack/service-settings, @objectstack/service-storage.

53 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/actions-as-tools.mdx (via @objectstack/core)
  • content/docs/ai/connect-mcp.mdx (via @objectstack/rest)
  • content/docs/ai/knowledge-rag.mdx (via @objectstack/core, @objectstack/service-knowledge)
  • content/docs/ai/natural-language-queries.mdx (via @objectstack/core)
  • content/docs/ai/skills-reference.mdx (via packages/cli)
  • content/docs/api/client-sdk.mdx (via @objectstack/cli)
  • content/docs/api/data-api.mdx (via @objectstack/service-analytics)
  • content/docs/api/data-flow.mdx (via @objectstack/cli)
  • content/docs/api/environment-routing.mdx (via @objectstack/cli)
  • content/docs/api/error-catalog.mdx (via @objectstack/cli)
  • content/docs/api/error-handling-server.mdx (via @objectstack/rest)
  • content/docs/api/index.mdx (via @objectstack/rest, @objectstack/service-analytics)
  • content/docs/api/plugin-endpoints.mdx (via @objectstack/service-storage)
  • content/docs/automation/hook-bodies.mdx (via packages/cli)
  • content/docs/automation/webhooks.mdx (via @objectstack/core)
  • content/docs/concepts/metadata-lifecycle.mdx (via @objectstack/metadata)
  • content/docs/concepts/north-star.mdx (via packages/core)
  • content/docs/deployment/backup-restore.mdx (via @objectstack/cli)
  • content/docs/deployment/cli.mdx (via @objectstack/cli)
  • content/docs/deployment/migration-from-objectql.mdx (via @objectstack/core)
  • content/docs/deployment/self-hosting.mdx (via @objectstack/cli)
  • content/docs/deployment/validating-metadata.mdx (via packages/cli)
  • content/docs/getting-started/your-first-project.mdx (via @objectstack/cli)
  • content/docs/kernel/cluster.mdx (via packages/metadata)
  • content/docs/kernel/contracts/index.mdx (via @objectstack/core)
  • content/docs/kernel/runtime-services/audit-service.mdx (via packages/services/service-settings)
  • content/docs/kernel/runtime-services/data-service.mdx (via packages/cli)
  • content/docs/kernel/runtime-services/examples.mdx (via @objectstack/core)
  • content/docs/kernel/runtime-services/index.mdx (via packages/cli, packages/services/service-settings)
  • content/docs/kernel/runtime-services/settings-service.mdx (via packages/services/service-settings)
  • content/docs/kernel/services-checklist.mdx (via @objectstack/core, @objectstack/metadata, @objectstack/service-analytics, @objectstack/service-job, @objectstack/service-queue, @objectstack/service-storage)
  • content/docs/kernel/services.mdx (via @objectstack/core)
  • content/docs/permissions/authentication.mdx (via @objectstack/cli, @objectstack/core, @objectstack/rest)
  • content/docs/permissions/authorization.mdx (via packages/core)
  • content/docs/permissions/sharing-rules.mdx (via @objectstack/service-analytics)
  • content/docs/plugins/anatomy.mdx (via @objectstack/core)
  • content/docs/plugins/development.mdx (via @objectstack/core)
  • content/docs/plugins/index.mdx (via @objectstack/cli, @objectstack/core, @objectstack/rest)
  • content/docs/plugins/packages.mdx (via @objectstack/cli, @objectstack/core, @objectstack/metadata, @objectstack/rest, @objectstack/service-analytics, @objectstack/service-job, @objectstack/service-queue, @objectstack/service-settings, @objectstack/service-storage)
  • content/docs/protocol/kernel/config-resolution.mdx (via @objectstack/core)
  • content/docs/protocol/kernel/i18n-standard.mdx (via packages/rest)
  • content/docs/protocol/kernel/index.mdx (via @objectstack/core)
  • content/docs/protocol/kernel/lifecycle.mdx (via @objectstack/core)
  • content/docs/protocol/kernel/metadata-service.mdx (via @objectstack/metadata)
  • content/docs/protocol/kernel/plugin-spec.mdx (via @objectstack/cli, @objectstack/core)
  • content/docs/protocol/kernel/realtime-protocol.mdx (via @objectstack/cli)
  • content/docs/protocol/knowledge.mdx (via @objectstack/service-knowledge)
  • content/docs/releases/implementation-status.mdx (via @objectstack/cli, @objectstack/core, @objectstack/rest, @objectstack/service-analytics, @objectstack/service-job, @objectstack/service-knowledge, @objectstack/service-queue, @objectstack/service-settings, @objectstack/service-storage)
  • content/docs/releases/v12.mdx (via @objectstack/core, @objectstack/metadata, @objectstack/rest)
  • content/docs/releases/v15.mdx (via @objectstack/core)
  • content/docs/releases/v16.mdx (via @objectstack/cli)
  • content/docs/releases/v17.mdx (via @objectstack/rest, @objectstack/service-analytics)
  • content/docs/releases/v9.mdx (via @objectstack/metadata, @objectstack/service-analytics, @objectstack/service-settings)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuang
os-zhuang marked this pull request as ready for review August 2, 2026 12:37
@os-zhuang
os-zhuang added this pull request to the merge queue Aug 2, 2026
Merged via the queue into main with commit 9fd9ae7 Aug 2, 2026
22 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-4471-init-service-declared-enforced branch August 2, 2026 12:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cd dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation size/l tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[core/ADR-0116] init 阶段取服务的顺序契约是自愿声明的——不声明就没人拦,#4085 与 #4420 都是这么发生的

2 participants