Repository navigation
Commit 50c4ec0
<!-- claude-projects-attribution: {"github_login":"os-warren"} -->
_Requested by **Warren** · [project
thread](https://claude.ai/code/project/chan_01U5RdnAAmkSQmZbqh6FtqZ8?thread=cmsg_01U5RdnAAmkSQmZbqh6FtqZ8QModZH3Kxarp5xssNiWbVr)_
Fixes #29710
Clause-②: no
Metadata-protocol: none
## 维护者速读
- 改了什么:新增门禁 `check:package-naming`。`packages/services/` 下每个包必须叫
`@objectstack/service-名字` 且目录名与包名一致;`@objectstack/plugin-*`
这组名字冻结在今天的十个,新包再用 `plugin-` 前缀直接红。
- 为什么改:Warren 2026-11-03 的裁决「应该用 service-*,包括如何制定仓库规则,避免类似的问题」「plugin-
太笼统,是不是建议逐渐退役这个名字」。推送通道差点按 ADR-0012 叫
`plugin-notification-push`;包名一旦发布就收不回。
- 风险与回滚:只读 `package.json`,不构建、不联网、亚秒级;今天的树全绿。不改名、不挪任何现有包。回滚即撤 PR。
- 先看:① `scripts/check-package-naming.mjs` 的 `judge()` 与
`FROZEN_PLUGIN_NAMES`;② `.github/workflows/lint.yml` 新增的一步(Tier H);③ 同文件
self-test 的两个 fixture 用例。
- 两分钟验证:`pnpm check:package-naming`,应见 self-test 15 例通过,随后一行 ✓,写明 129
个包、18 个 service、恰好 10 个冻结名。
- 需要你做的:审阅并落地(含 `.github/workflows/lint.yml`,Tier H 需维护者合并)。
## What changes
- **New gate `scripts/check-package-naming.mjs`**, on
`scripts/workspace-enumerator.mjs` (the one parse of
`pnpm-workspace.yaml`). Two rules over every workspace manifest:
- `[services-prefix]` / `[dir-mismatch]`: every package whose directory
sits directly under `packages/services/` is named
`@objectstack/service-NAME`, and NAME with the prefix is its directory
basename.
- `[plugin-prefix]` / `[stale-row]`: the set of `@objectstack/plugin-*`
names is a shrink-only ratchet, `FROZEN_PLUGIN_NAMES`, frozen at the ten
the tree carries today: `approvals`, `audit`, `auth`, `dev`, `email`,
`hono-server`, `pinyin-search`, `security`, `sharing`, `webhooks`. A new
name reds with the remedy "name it by its kind" (`service-`,
`connector-`, `driver-`, `embedder-`, `knowledge-`). Growing the set is
refused outright, not offered as a remedy. A frozen name the tree no
longer carries reds too, so the set can only shrink.
- A lit control (at least 50 packages, `@objectstack/spec` present, at
least one member under `packages/services/`) makes an enumeration that
stops reading the tree exit 2, never 0. `--root DIR` judges another
checkout.
- `--self-test` arm: 15 table-driven cases with the sibling battery
floor (pattern of `check-skill-top-level-keys.mjs`), including two that
build a real fixture workspace on disk and judge it through the
enumerator.
- **Wiring**: `check:package-naming` in the root `package.json`
(`--self-test` then the run), and one step in
`.github/workflows/lint.yml` right after
`check:workspace-manifest-cycles`, same shape (`continue-on-error:
true`, rationale comment pointing at the header). There is no
`check:all` aggregator in this repo, so the workflow step is the only CI
wiring; the seat ruled option A, and that makes this PR Tier H.
- **Scope, stated**: the 18 `@object-ui/plugin-*` packages under
`ui/packages/` are a separate scope and are NOT in the frozen set (seat
ruling). A `@objectstack/service-*` package outside `packages/services/`
is not judged (0 today). No existing package is renamed or moved.
- No changeset: the diff is `scripts/**`, the root manifest and a
workflow, none of which publishes (`skip-changeset`).
## Tests
- `node scripts/check-package-naming.mjs --self-test`: exit 0, `✓
check-package-naming self-test: 15 cases pass.`
- `node scripts/check-package-naming.mjs` on this branch: exit 0, `✓
check-package-naming: 129 workspace package(s); all 18 in
packages/services/ are @objectstack/service-* named after their
directory; the @objectstack/plugin-* set is exactly the 10 frozen
names.`
- Red-first on the real tree (fixtures written into the worktree, then
removed; `git status` clean afterwards): `packages/services/plugin-x`
named `@objectstack/plugin-x` plus an eleventh
`packages/plugins/plugin-notification-push` gave exit 1 with three
findings: `[services-prefix] packages/services/plugin-x`,
`[plugin-prefix] packages/plugins/plugin-notification-push`,
`[plugin-prefix] packages/services/plugin-x`.
- #29041's `service-push` branch does not exist yet (no branch or PR for
it on the remote at the time of writing), so the gate has not been run
on it: NOT MEASURED. `@objectstack/service-push` in
`packages/services/service-push` is the shape the gate accepts; `--root`
lets the seat run it on that checkout.
## Acceptance notes
- The frozen set is meant to equal the ten named in #29709's rule text;
that card runs in parallel, and the seat holds the two in step.
- `check:entry-guard` caught the first draft calling `main()` at top
level while exporting `judge`/`readRows`; the second commit puts the
dispatch behind `isEntrypoint` from `invoked-as.mjs`.
## Verification
<details><summary>Local gate union on the final head</summary>
Head `4d2af80c` (rebased on origin/main `9b4fa6cc`). `node
scripts/pm/dispatch-gates.mjs --commands` derived 65 families from the 3
changed paths; each was run with its exit code captured before any pipe,
then reconciled:
```text
node scripts/check-closing-keyword-parity.mjs :: exit 0
node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0
node scripts/check-comment-mask-corpus.mjs :: exit 0
node scripts/check-declaration-mirrors.mjs :: exit 0
node scripts/check-declaration-mirrors.mjs --self-test :: exit 0
node scripts/check-dts-emitted.mjs --self-test :: exit 0
node scripts/check-merged-branch-reaper-outcome.mjs :: exit 0
node scripts/check-merged-branch-reaper-outcome.mjs --self-test :: exit 0
node scripts/check-self-test-wired.mjs :: exit 0
node scripts/check-self-test-wired.mjs --self-test :: exit 0
node scripts/check-self-test-workflow-commands.mjs :: exit 0
node scripts/check-self-test-workflow-commands.mjs --self-test :: exit 0
node scripts/check-step-collectors.mjs :: exit 0
node scripts/check-step-collectors.mjs --self-test :: exit 0
node scripts/check-whole-set-label-write.mjs :: exit 0
node scripts/check-whole-set-label-write.mjs --self-test :: exit 0
node scripts/ci/assert-turbo-remote-cache.mjs --self-test :: exit 0
node scripts/ci/plan-test-core-shards.mjs --self-test :: exit 0
node scripts/ci/prune-turbo-cache.mjs --self-test :: exit 0
node scripts/ci/scheduled-full-run.mjs --self-test :: exit 0
node scripts/docs-audit/check-drift-comment.mjs :: exit 0
node scripts/pm/bare-root-worklist.mjs --self-test :: exit 0
node scripts/pm/ci-failure.mjs --self-test :: exit 0
pnpm check:agent-test-spelling :: exit 0
pnpm check:aggregator-roster :: exit 0
pnpm check:bash32-floor :: exit 0
pnpm check:ci-filter-parity :: exit 0
pnpm check:cli-command-ids :: exit 0
pnpm check:cross-package-test-inputs :: exit 0
pnpm check:declared-population-live :: exit 0
pnpm check:driver-memory-census :: exit 0
pnpm check:dts-closure :: exit 0
pnpm check:dual-build-cjs-loads :: exit 0
pnpm check:entry-guard :: exit 0
pnpm check:gitlink-declared :: exit 0
pnpm check:lean-entry-closure :: exit 0
pnpm check:manifest-repository-directory :: exit 0
pnpm check:merge-driver :: exit 0
pnpm check:node-version :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:package-naming :: exit 0
pnpm check:parse-guard :: exit 0
pnpm check:pm-expected-skips :: exit 0
pnpm check:pm-governed-merges :: exit 0
pnpm check:pm-post-stamped :: exit 0
pnpm check:pm-record-recognisers :: exit 0
pnpm check:pnpm-acquisition :: exit 0
pnpm check:pnpm-filter-targets :: exit 0
pnpm check:pnpm-flag-spellings :: exit 0
pnpm check:ratchet-remedy-authority :: exit 0
pnpm check:refd-timer-probe :: exit 0
pnpm check:required-contexts :: exit 0
pnpm check:scripts-symbol-anchors :: exit 0
pnpm check:select-gate-families :: exit 0
pnpm check:shard-attestation :: exit 0
pnpm check:sourcemap-no-sources-content :: exit 0
pnpm check:stall-guard-budget :: exit 0
pnpm check:stall-guard-headroom :: exit 0
pnpm check:turbo-task-graph :: exit 0
pnpm check:type-check-coverage :: exit 0
pnpm check:type-check-debt :: exit 0
pnpm check:watch-hint-literal :: exit 0
pnpm check:workflow-status-functions :: exit 0
pnpm check:workflow-step-name-quoting :: exit 0
pnpm check:pm-dispatch-gates :: exit 0
pnpm lint :: exit 0
```
`dispatch-gates --ran`: `65 derived famil(ies) accounted for — 65 run, 0
NOT-MEASURED` (exit 0). `check:pm-dispatch-gates`: `1945 cases pass`
(fast tier). Every family CI runs is read from this PR's check-runs.
</details>
## Human Minimum
- [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic.
(not touched)
- [x] 2. Every name I added uses the casing for its kind.
- [x] 3. No formatter ran; `pnpm lint` passes.
- [x] 4. One issue, one branch off an up-to-date `main`, one pull
request.
- [x] 5. A change that publishes carries a changeset, and both
declaration lines are filled in here and in the changeset. (nothing
publishes)
- [x] 6. `packages/spec` touched: its generated artifacts are
regenerated and committed. (not touched)
- [x] 7. No hand edits to `content/docs/references/`,
`packages/*/CHANGELOG.md` or `content/docs/releases/`.
- [x] 8. Title, body and comments are in English. (except the Chinese
maintainer summary the repo asks for)
- [x] The *Before Submitting* list in CONTRIBUTING.md is done.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01JQwxbXkaL8RZJzfDDK793u)_
---------
Co-authored-by: Claude <noreply@anthropic.com>
1 parent ea4dcf9 commit 50c4ec0
3 files changed
Lines changed: 299 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3988 | 3988 | | |
3989 | 3989 | | |
3990 | 3990 | | |
| 3991 | + | |
| 3992 | + | |
| 3993 | + | |
| 3994 | + | |
| 3995 | + | |
| 3996 | + | |
| 3997 | + | |
| 3998 | + | |
| 3999 | + | |
3991 | 4000 | | |
3992 | 4001 | | |
3993 | 4002 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
108 | 108 | | |
109 | 109 | | |
110 | 110 | | |
| 111 | + | |
111 | 112 | | |
112 | 113 | | |
113 | 114 | | |
| |||
0 commit comments