Repository navigation
Commit 1697d5c
fix(cli):
<!-- claude-projects-attribution: {"github_login":"os-elon-musk"} -->
_Requested by **Elon** · [project
thread](https://claude.ai/code/project/chan_01WedDzV26nniwxv7jC88B9D?thread=cmsg_01WedDzV26nniwxv7jC88B9D9HSxC7WngZADjXgb6UHCVp)_
domain:devx#1 · os-elon-musk · session_016WV4cyadQ5Zhih2y1GNTQm
Part of #30804
Clause-②: no
Metadata-protocol: none
## 维护者速读
- **改了什么**:`os lint` 的 `naming/namespace-prefix`
从「只报包内重名」扩为「每个裸的包内元数据名都报」(28 类),`fix` 给出 `<ns>_<name>`;`os generate`
写出的脚手架名同步带前缀。
- **为什么改**:裁决 C(#30798「同意 c」)——包作者写的每个元数据名都带命名空间;本 PR 是第二阶段的 lint
一半,示例与模板改名在 PR 2。
- **风险与回滚**:仍是 warning,不拒收;只有 `os lint --strict` 会因它失败,仓内没有 CI
车道这样跑示例。回滚即 revert。
- **先看**:① `lint.ts` 的 `namespacePrefixIssues` 与
`NAME_JUDGED_ELSEWHERE`(豁免表);② `project-namespace.ts` 的
`carriesPackageNamespace`(lint 与 generate 共用的一个判定)。
- **两分钟验证**:`pnpm --filter @objectstack/cli exec vitest run
test/lint-namespace-prefix.test.ts`;或在 `examples/app-todo` 跑 `os lint`,看
20 条新警告各带 `fix`。
- **需要你做的**:裁一个开放问题——`showcase.export_data` 这类点号能力名是否算已带命名空间(本 PR 默认算,见
Acceptance notes)。
## What changes
**`naming/namespace-prefix` warns on every bare package-authored name.**
In a package that declares `manifest.namespace`, every top-level item in
every manifest collection (`PLURAL_TO_SINGULAR`, 28 of its 31 keys)
whose `name` does not carry the namespace gets one warning. The message
states the contract, and the `fix` is the rename:
```text
⚠ Flow "onboard" does not carry the package namespace "crm". Every metadata name a package authors starts with its namespace, as object names do, so that no two installed packages can hold the same name — rename it to "crm_onboard" and update every reference that spells it.
```
The judged collections are apps, pages, dashboards, reports, datasets,
actions, flows, jobs, positions, permissions, capabilities,
sharingRules, queues, assignmentRules, apis, webhooks, agents, tools,
skills, ragPipelines, hooks, mappings, picklists, analyticsCubes,
connectors, datasources, emailTemplates and books. The set is derived
from the spec map, so a collection added there is judged the day it
lands.
**What is not judged, and why** (`NAME_JUDGED_ELSEWHERE` plus the
predicate):
| Not judged | Reason |
|:--|:--|
| `objects` | `defineStack`'s `validateNamespacePrefix` already refuses
a bare object name |
| `views` | a container is named for its bound object; a view item is
`<object>.<key>` |
| `docs` | the doc lint's own `docs/namespace-prefix` error |
| object / picklist extensions, translations, fields, `functions` | not
in the collection map: each names the item it extends, has no name of
its own, is keyed inside its object, or is a code handler |
| an item that declares `overrides` | ADR-0146 D2: it replaces the base
package's item of the same name |
| a package with no `manifest.namespace` | nothing to prefix with, the
object rule's posture |
A name **carries** the namespace when it is the namespace itself (the
ADR-0019 namespace-named app), starts with `<ns>_`, starts with `<ns>.`
(the dotted capability shape `CapabilitySchema` documents,
`billing.refund`), or starts with the platform-reserved `sys_`. That is
one predicate, `carriesPackageNamespace` in
`utils/project-namespace.ts`.
**The duplicate finding stays**, under the same rule id, for any name
declared twice in one package, prefixed or not (apps, pages, dashboards,
flows, reports, datasets, and actions on their `objectName:name` key).
It no longer offers the prefixed spelling as its rename, because the new
finding carries that, and its message no longer says the prefix is "an
optional convention". It now has no `fix`.
**`os generate` writes prefixed names (bounded in-place fix, accepted by
the seat).** Before, only object names got the prefix, so in a
namespaced project `os g flow onboard` wrote `onboard_flow`, and the new
warning fired on a fresh scaffold. Now the action, flow, dashboard, app,
skill, picklist, permission set and dataset generators write `<ns>_…`
through `namespacedItemName`, which uses the same predicate, so a
scaffold is never written in a spelling the lint reports. A name that
already carries the namespace is never doubled. The namespace is now
read for every generator. The refusal when the config does not load
still applies only to `namesObject` generators, because a bare
non-object name is a warning and not a refusal. The `namesObject` flag
still means "writes an object name".
**Changeset:** `'@objectstack/cli': patch`.
## Why
Ruling C on #30798 (maintainer, verbatim 「同意 c」): every package-authored
metadata name carries its namespace, phased. Two installed packages that
share a bare name such as `send_email` often resolve to only one of
them, silently. This is phase 2's lint half. Phase 1 (#30803) is the
registration backstop, phase 3 (#30806) turns it into a refusal, and
#30805 covers the skills. PR 2 of this card renames the examples and
templates.
## Acceptance notes
- **Open question for a ruling (dotted capability names).** app-showcase
declares `showcase.export_data` and `showcase.restricted_ops` in
namespace `showcase`. CapabilitySchema's name regex admits a dot, and
its own example is `billing.refund`. This PR treats `<ns>.` as carrying
the namespace. Its test has a twin: `billing.refund` under namespace
`crm` still warns. If the ruling is strict `<ns>_` only, the dotted
clause comes out of `carriesPackageNamespace`, and PR 2 renames the two
capabilities and their three `requiredPermissions` references. Phase 3
(#30806) needs the same answer.
- **Open question for phase 3: `functions`.** They are not in the
collection map, so this rule does not judge them. The audit behind
#30798 named function handlers as a collision class, so #30806 may want
them in its refusal.
- **Baseline bare-name counts under this rule** (origin/main `100303c0`,
before PR 2). Duplicates are 0 everywhere.
| Config | Bare | By type |
|:--|--:|:--|
| `examples/app-todo` | 20 | actions 8, reports 5, flows 4, dashboards
1, datasets 1, hooks 1 |
| `examples/app-crm` | 7 | positions 3, dashboards 1, datasets 1,
permissions 1, hooks 1 |
| `examples/app-showcase` | 12 | positions 10, sharingRules 2 (14 under
a strict `<ns>_` reading: plus capabilities 2) |
| `examples/app-multi-package` | 1 | apps 1 (`multi_crm` in package
`crm`, so the fix is `crm_multi_crm`) |
| `create-objectstack` blank template | 0 | only `blank_note`; every
other barrel is empty |
| `examples/embed-objectql` | 0 | declares no manifest namespace |
- **No CI lane turns these warnings red.** The rule is reached only
through `lintConfig` (`os lint`, `os lint --eval`), never from `os
validate`, `os build` or `os compile`. `os lint` exits 1 on warnings
only under `--strict`, and nothing in `.github/workflows`, `scripts/` or
the example and template `package.json` files passes it.
`check:i18n-coverage` counts only `i18n/` rules. The tests that lint
real examples filter to their own rule or assert exit 0. A warning costs
3 points of the `os lint` score, and no example's score is pinned.
- **Pins this PR changes on purpose.** The old tests asserted that a
bare name is silent, and those assertions are rewritten.
`generate-object-namespace-prefix.test.ts`'s census of #20197 ("prefixes
every object name, and only object names") now expects every scaffold's
own name prefixed. Its `namesObject` derivation holds the scaffold's own
name fixed, except on the object scaffold.
`generate-scaffold-validates.test.ts`'s #21325 binding check pins the
scaffold's own `name` on its own and searches only the rest of the
artifact for a stray object reference. `generate-stack-reach.test.ts`
expects `my_app_approve` / `my_app_approval_changed_flow`.
- **ADR-0048 §5's lint bullet** is out of date. Per the seat's route, it
is corrected in its own one-file `docs/adr` PR (Tier H), not here.
- **Out of scope here:** `skills/objectstack-platform/SKILL.md:121`
still describes the old rule (#30805). `content/docs/ui/doc-pages.mdx`
L70–83 says the prefix is "no longer load-bearing for uniqueness" (PR
2's docs pass).
## Human Minimum
- [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic.
(`packages/spec` not touched.)
- [x] 2. Every name I added uses the casing for its kind.
- [x] 3. No formatter ran; `pnpm lint` passes. (eslint
`--no-inline-config` on every changed file: exit 0.)
- [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.
- [x] 6. `packages/spec` touched: its generated artifacts are
regenerated and committed. (n/a)
- [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.
- [x] The *Before Submitting* list in CONTRIBUTING.md is done.
## Verification
All at head `c4ad5c80` (origin/main `d996c381` merged in).
- `pnpm --filter @objectstack/cli exec vitest run` (unit + integration
projects): 590 files passed, 1 skipped; 7272 tests passed, 9 skipped.
- The nightly e2e tier (`OS_TEST_TIERS=nightly`) on the 19 files that
generate, scaffold, init or lint (`generate-*.e2e`,
`init-created-files-summary.e2e`, `scaffold-emission-policy.e2e`,
`starter-field-consumers.e2e`, `jsx-gate-manifest-notice.e2e`,
`lint-*.e2e`): 19 files, 250 tests, all passed.
- `pnpm --filter @objectstack/cli typecheck` (`tsc --noEmit` and
`check:test-typecheck`): exit 0. The test layer needed
`--max-old-space-size=8192`, because it ran out of heap at the default.
- eslint `--no-inline-config` on the 9 changed `.ts` files: exit 0.
- `pnpm --filter @objectstack/spec run check:liveness`: exit 0.
- `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack`: exit 0, 61 commands, all run, all exit 0.
Two first exited 3 (PREREQUISITE NOT MET) and went green on a re-run
once the prerequisite was met. `check-plugin-teardown-shape --self-test`
needed its pinned fixture commit fetched into the shallow clone.
`check:dual-build-cjs-loads` needed 7 packages built (studio,
client-react, embedder-openai, knowledge-memory, knowledge-ragflow,
service-cluster-redis, service-knowledge). `--ran` reconciliation: exit
0, 61 derived, 61 run, 0 NOT-MEASURED.
<details><summary>The 61 gates and their exit codes</summary>
```text
node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0
node scripts/check-adr-0087-registration.mjs --self-test :: exit 0
node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0
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-adoption.mjs :: exit 0
node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0
node scripts/check-comment-mask-corpus.mjs :: exit 0
node scripts/check-dts-emitted.mjs --self-test :: exit 0
node scripts/check-empty-changeset.mjs --base origin/main :: exit 0
node scripts/check-empty-changeset.mjs --self-test :: exit 0
node scripts/check-issue-citations.mjs :: exit 0
node scripts/check-plugin-teardown-shape.mjs :: exit 0
node scripts/check-plugin-teardown-shape.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/docs-audit/check-affected-docs.mjs :: exit 0
node scripts/docs-audit/check-drift-comment.mjs :: exit 0
node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0
node scripts/release-pending-publish.mjs --self-test :: exit 0
pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0
pnpm check:changeset-gate-self-tests :: exit 0
pnpm check:ci-filter-parity :: exit 0
pnpm check:cli-test-child-env :: exit 0
pnpm check:closed-ceremony-text :: exit 0
pnpm check:cross-package-test-inputs :: exit 0
pnpm check:dispatcher-error-vocabulary :: exit 0
pnpm check:doc-authoring :: 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:engine-double-contract :: exit 0
pnpm check:gitlink-declared :: exit 0
pnpm check:i18n :: exit 0
pnpm check:i18n-coverage :: exit 0
pnpm check:i18n-walk-parity :: exit 0
pnpm check:issue-citations :: exit 0
pnpm check:keyed-text-bounds :: exit 0
pnpm check:lean-entry-closure :: exit 0
pnpm check:logger-receiver-detach :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:objectql-double-limit :: exit 0
pnpm check:org-identifier :: exit 0
pnpm check:page-declaration-shape :: exit 0
pnpm check:platform-object-tenancy-census :: exit 0
pnpm check:published-files :: exit 0
pnpm check:query-options-erasure :: exit 0
pnpm check:refd-timer-probe :: exit 0
pnpm check:registry-log-declared :: exit 0
pnpm check:rest-log-spy-declared :: exit 0
pnpm check:slot-lookup :: exit 0
pnpm check:sourcemap-no-sources-content :: exit 0
pnpm check:system-context-census :: exit 0
pnpm check:test-source-alias :: exit 0
pnpm check:tier-file-adoption :: exit 0
pnpm check:type-check-coverage :: exit 0
pnpm check:type-check-debt :: exit 0
pnpm check:undeclared-dep-imports :: exit 0
pnpm check:watch-hint-literal :: exit 0
pnpm check:where-matcher :: exit 0
```
</details>
---
_Generated by [Claude
Code](https://claude.ai/code/session_016WV4cyadQ5Zhih2y1GNTQm)_
---------
Co-authored-by: Claude <noreply@anthropic.com>os lint warns on every bare package-authored metadata name, and os generate writes them prefixed (#30842)1 parent 6ff27b3 commit 1697d5c
10 files changed
Lines changed: 621 additions & 248 deletions
File tree
- .changeset
- packages/cli
- src
- commands
- utils
- test
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
59 | 59 | | |
60 | 60 | | |
61 | 61 | | |
62 | | - | |
| 62 | + | |
63 | 63 | | |
64 | 64 | | |
65 | 65 | | |
| |||
150 | 150 | | |
151 | 151 | | |
152 | 152 | | |
153 | | - | |
154 | | - | |
155 | | - | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
156 | 157 | | |
157 | | - | |
158 | | - | |
159 | | - | |
160 | | - | |
161 | | - | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
162 | 166 | | |
163 | 167 | | |
164 | 168 | | |
| |||
418 | 422 | | |
419 | 423 | | |
420 | 424 | | |
421 | | - | |
422 | | - | |
| 425 | + | |
| 426 | + | |
423 | 427 | | |
424 | 428 | | |
425 | 429 | | |
| |||
428 | 432 | | |
429 | 433 | | |
430 | 434 | | |
431 | | - | |
| 435 | + | |
432 | 436 | | |
433 | 437 | | |
434 | 438 | | |
| |||
494 | 498 | | |
495 | 499 | | |
496 | 500 | | |
497 | | - | |
| 501 | + | |
498 | 502 | | |
499 | | - | |
| 503 | + | |
500 | 504 | | |
501 | 505 | | |
502 | 506 | | |
| |||
509 | 513 | | |
510 | 514 | | |
511 | 515 | | |
512 | | - | |
| 516 | + | |
513 | 517 | | |
514 | 518 | | |
515 | 519 | | |
| |||
550 | 554 | | |
551 | 555 | | |
552 | 556 | | |
553 | | - | |
554 | | - | |
| 557 | + | |
| 558 | + | |
555 | 559 | | |
556 | 560 | | |
557 | 561 | | |
558 | 562 | | |
559 | 563 | | |
560 | | - | |
| 564 | + | |
561 | 565 | | |
562 | 566 | | |
563 | 567 | | |
| |||
588 | 592 | | |
589 | 593 | | |
590 | 594 | | |
591 | | - | |
592 | | - | |
| 595 | + | |
| 596 | + | |
593 | 597 | | |
594 | 598 | | |
595 | 599 | | |
596 | 600 | | |
597 | 601 | | |
598 | 602 | | |
599 | 603 | | |
600 | | - | |
| 604 | + | |
601 | 605 | | |
602 | 606 | | |
603 | 607 | | |
| |||
638 | 642 | | |
639 | 643 | | |
640 | 644 | | |
641 | | - | |
642 | | - | |
| 645 | + | |
| 646 | + | |
643 | 647 | | |
644 | 648 | | |
645 | 649 | | |
| |||
653 | 657 | | |
654 | 658 | | |
655 | 659 | | |
656 | | - | |
| 660 | + | |
657 | 661 | | |
658 | 662 | | |
659 | 663 | | |
| |||
682 | 686 | | |
683 | 687 | | |
684 | 688 | | |
685 | | - | |
| 689 | + | |
686 | 690 | | |
687 | 691 | | |
688 | 692 | | |
| |||
720 | 724 | | |
721 | 725 | | |
722 | 726 | | |
723 | | - | |
724 | | - | |
| 727 | + | |
| 728 | + | |
725 | 729 | | |
726 | 730 | | |
727 | 731 | | |
728 | 732 | | |
729 | 733 | | |
730 | | - | |
| 734 | + | |
731 | 735 | | |
732 | 736 | | |
733 | 737 | | |
734 | | - | |
| 738 | + | |
735 | 739 | | |
736 | 740 | | |
737 | 741 | | |
| |||
779 | 783 | | |
780 | 784 | | |
781 | 785 | | |
782 | | - | |
783 | | - | |
| 786 | + | |
| 787 | + | |
784 | 788 | | |
785 | 789 | | |
786 | 790 | | |
| |||
793 | 797 | | |
794 | 798 | | |
795 | 799 | | |
796 | | - | |
| 800 | + | |
797 | 801 | | |
798 | 802 | | |
799 | 803 | | |
| |||
841 | 845 | | |
842 | 846 | | |
843 | 847 | | |
844 | | - | |
845 | | - | |
| 848 | + | |
| 849 | + | |
846 | 850 | | |
847 | 851 | | |
848 | 852 | | |
| |||
857 | 861 | | |
858 | 862 | | |
859 | 863 | | |
860 | | - | |
| 864 | + | |
861 | 865 | | |
862 | 866 | | |
863 | 867 | | |
| |||
1093 | 1097 | | |
1094 | 1098 | | |
1095 | 1099 | | |
| 1100 | + | |
| 1101 | + | |
| 1102 | + | |
| 1103 | + | |
| 1104 | + | |
| 1105 | + | |
| 1106 | + | |
| 1107 | + | |
| 1108 | + | |
| 1109 | + | |
| 1110 | + | |
| 1111 | + | |
| 1112 | + | |
1096 | 1113 | | |
1097 | 1114 | | |
1098 | 1115 | | |
| |||
1585 | 1602 | | |
1586 | 1603 | | |
1587 | 1604 | | |
1588 | | - | |
| 1605 | + | |
1589 | 1606 | | |
1590 | 1607 | | |
1591 | 1608 | | |
| |||
1603 | 1620 | | |
1604 | 1621 | | |
1605 | 1622 | | |
1606 | | - | |
1607 | | - | |
1608 | | - | |
1609 | | - | |
1610 | | - | |
1611 | | - | |
1612 | | - | |
1613 | | - | |
1614 | | - | |
| 1623 | + | |
| 1624 | + | |
| 1625 | + | |
| 1626 | + | |
| 1627 | + | |
| 1628 | + | |
| 1629 | + | |
| 1630 | + | |
| 1631 | + | |
| 1632 | + | |
| 1633 | + | |
1615 | 1634 | | |
1616 | 1635 | | |
1617 | 1636 | | |
| |||
1644 | 1663 | | |
1645 | 1664 | | |
1646 | 1665 | | |
1647 | | - | |
1648 | 1666 | | |
| 1667 | + | |
1649 | 1668 | | |
1650 | 1669 | | |
1651 | 1670 | | |
| |||
0 commit comments