Skip to content

Commit 0f9245c

Browse files
os-steveclaude
andauthored
docs(skills): pages.md rule 2 states the enforceable reason, not the retired ADR-0048 claim (#19445)
Fixes #19358 Clause-②: no Seat `domain:skills#2` (seat post #19287), dispatched from the claim on #19358. Tier H: `skills/**` — this PR stays DRAFT; the seat reviews and ACCEPTs, the maintainer's own click lands it. ## What changed `skills/objectstack-ui/rules/pages.md`, authoring rule 2 only (:337–:341 at both `23f1de0` and this head `127576f`). The rule (the stem must start with the package namespace) and the ADR-0048 citation stay; the REASON sentence is replaced with the facts the source enforces. Net 0 lines (+3 / −3), one file. Before (`23f1de0`, :337–:341): ```text 2. **Namespace-prefixed filename.** The filename stem becomes the doc `name` (`^[a-z][a-z0-9_]*$`) and must start with the package namespace (`crm_…`). Names share one flat, instance-global space with the URL, so a bare `user_guide` would collide across packages and fail at install (ADR-0048). ``` After (`127576f`, :337–:341): ```text 2. **Namespace-prefixed filename.** The filename stem becomes the doc `name` (`^[a-z][a-z0-9_]*$`) and must start with the package namespace (`crm_…`). `os build` refuses a bare `user_guide` (`docs/namespace-prefix`) — hygiene, not uniqueness: two packages coexist on one bare name (ADR-0048 §3.4). ``` ## The three false clauses, re-measured on this tree, and the source line beside each new clause | # | the old text said | measured refutation (all at `23f1de0`, unchanged at `127576f`) | the new clause it becomes | |---|---|---|---| | 1 | doc names share "one flat, instance-global space with the URL" | `docs/adr/0048-cross-package-metadata-collision.md` :182–:183 「The route/container coordinate for an installed package's UI is its **package id**」 (§3.1); :222–:223 「resolves a bare name **within the current package first**, keyed on the **package id**」 (§3.3); `packages/objectql/src/registry.ts` :3452 `const storageKey = packageId ? withDisc(`${packageId}:${baseName}`) : bareKey;` — the storage key is composite `PACKAGE_ID:NAME`, not one flat space | dropped; replaced by "two packages coexist on one bare name" | | 2 | a bare name "would collide across packages" | ADR-0048 :251–:252 「The cross-package **throw is retired**; two distinct packages coexist on the same bare name by construction」 (§3.4); `registry.ts` :3472–:3477 「ADR-0048 §3.4 — the per-item CROSS-package throw is retired … two installed packages shipping the same bare name (e.g. `page/home`) legitimately COEXIST under distinct composite keys」 — and no throw exists in :3458–:3511, only the ADR-0005 overlay `console.warn` | "hygiene, not uniqueness: two packages coexist on one bare name (ADR-0048 §3.4)" | | 3 | it "would fail at install" | BUILD door: `packages/cli/src/utils/collect-docs.ts` :654–:658 `if (namespace && !doc.name.startsWith(`${namespace}_`))` pushes `severity: 'error'`, `rule: 'docs/namespace-prefix'`; `packages/cli/src/commands/compile.ts` :802–:811 `if (docErrors.length > 0) { … this.exit(1); }`. INSTALL door: `registry.ts` :4155–:4168 refuses on `manifest.namespace` ownership and :1456 `constructor(namespace: string, existingPackageId: string, incomingPackageId: string)` — `NamespaceConflictError` is built from a namespace, never a doc name | "`os build` refuses a bare `user_guide` (`docs/namespace-prefix`)" | Reference wording the dispatch pointed at, unchanged and consistent with the new sentence: `content/docs/ui/doc-pages.mdx` :68–:69 「The build lint still requires every doc name to be **namespace-prefixed**, as a same-package authoring-hygiene rule」 and :77–:82 「It is no longer **load-bearing for uniqueness** … two installed packages may each ship a doc with the same bare name and coexist」. The build-check pin: `packages/cli/src/utils/collect-docs.package-docs.test.ts` :420–:424 (a bare `playbook` → one `docs/namespace-prefix` at `severity 'error'`). ## Restate vs drop — the card's "First act", decided on the four axes Option A (taken): restate — the enforceable fact plus one corrected clause naming where the refusal happens and what the prefix is not for, with the ADR section. Option B: drop to the bare enforceable fact ("must start with the package namespace; enforced by `os build`") and a bare `(ADR-0048)`. - **实际业务需求** — the reader is an AI author of package docs in a customer project (`skills/**` ships via `npx skills add` / `npm create objectstack`). Both options let it comply. What the old sentence did in practice was get copied as a *reason* into the author's own docs; B leaves the "why" blank, and a blank "why" beside an ADR number is the shape an author fills with the retired claim. A gives the one fact that closes it. Neither option adds any capability. - **项目长远合理性** — spec/ADR > implementation > docs. ADR-0048 §3.4 itself classifies this lint as authoring hygiene (:258–:259), and the source header (`collect-docs.ts` :32–:54) says the same. A keeps the skill's sentence tied to the ADR clause it cites (§3.4), so a future change to that clause has one sentence to update; B cites a document that then says nothing about the sentence. - **防 AI 写代码/元数据犯错** — A names the door (`os build`) and the rule id (`docs/namespace-prefix`), so an author hitting the refusal can find it, and states the negative ("not uniqueness: two packages coexist on one bare name") that stops an AI from re-deriving the retired collision claim or designing around a constraint that does not exist (e.g. inventing cross-package-unique names). B is silent on exactly the claim this card is about. - **创业阶段不扩散需求** — both are net 0 lines; A costs +2 ratchet units (see below), B would shrink. No new capability, no new surface, immediate correction, no transition text. Decision: A. The cost is stated honestly: this file's token headroom goes from 2 to 0, so the next edit to `pages.md` pays by deletion. Also considered and not written, for the byte budget: the second true reason the source states — the prefix is what separates a same-package link from a cross-package one, because a doc link is a bare `./NAME.md` with nowhere to carry a package coordinate (`collect-docs.ts` :45–:54 and the check at :737 `if (namespace && !target.startsWith(`${namespace}_`)) continue;`). It is measured and true; the sentence had room for one clause, and the §3.4 framing is the direct refutation of the retired claim. "authoring hygiene" was trimmed to "hygiene" for the same reason: the full spelling lands at 5504 units against a 5501 ceiling. ## Published-skill ratchet readings (both readings, per os-dev.md) - Gate: `node scripts/check-skills-token-ratchet.mjs` (`scripts/check-skills-token-ratchet.mjs`, invoked directly in `.github/workflows/lint.yml` :5527–:5528; unit = `ceil(utf8 bytes / 4)`). Ceiling row :473 `['skills/objectstack-ui/rules/pages.md', 5501]`. - File, tokens: before 21996 bytes → 5499 units (headroom 2); after 22003 bytes → **5501 units (headroom 0)**. Gate line: `✓ check-skills-token-ratchet: skills/objectstack-ui/rules/pages.md is 5501 tokens (ceiling 5501; headroom 0).` Paid within the replaced span (148 → 155 bytes); ceiling row untouched. - File, lines: before 448 → after 448 (net 0; the claim's budget was net ≤ +2). - Package, tokens: bundle total after 140368 (gate output); before 140366 — the unit is per-file additive and only this file changed (+2). - Package, lines (sum over all `skills/**/SKILL.md`, 10 files): before 6145 → after 6145. Sum over `skills/objectstack-ui/**`: 2155 → 2155. - ⛔ `pnpm check:pm-skill-ratchet` is the `.claude/**` LINE ratchet and deliberately excludes the published `skills/` root (its header says so); it is not the gate this file answers to. ## Gates — derived union, every exit captured before any pipe, reconciled with `--ran` Derived by `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (no paths; change set from merge base `23f1de0`, 1 path, +3/−3, under the 5000 human-merge threshold). Reconcile: `Run reconciliation — 23 derived, 23 run, 0 NOT-MEASURED, 0 UNRUN.` (exit 0). | command | exit | |---|---| | `node scripts/check-ci-filter-parity.mjs` | 0 | | `node scripts/check-closing-keyword-parity.mjs` | 0 | | `node scripts/check-closing-keyword-parity.mjs --self-test` | 0 | | `node scripts/check-comment-mask-corpus.mjs` | 0 | | `node scripts/check-doc-route-spelling.mjs --advisory` | 0 | | `node scripts/check-doc-route-spelling.mjs --self-test` | 0 | | `node scripts/check-skills-token-ratchet.mjs` | 0 | | `node scripts/check-skills-token-ratchet.mjs --self-test` | 0 | | `pnpm --filter @objectstack/lint run check:doc-formula-expressions` | first run 3 (PREREQUISITE NOT MET — `dist/` of `@objectstack/formula` / `@objectstack/lint` absent in a fresh worktree; NOT MEASURED); after `pnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lint --concurrency=2` under `os-verify-lock.sh` (`VERDICT command-exit 0`, held 390s): rerun **0** | | `pnpm check:agent-test-spelling` | 0 | | `pnpm check:corpus-claim-drift` | 0 | | `pnpm check:cross-package-test-inputs` | 0 | | `pnpm check:doc-authoring` | 0 | | `pnpm check:driver-memory-census` | 0 | | `pnpm check:gitlink-declared` | 0 | | `pnpm check:nul-bytes` | 0 | | `pnpm check:pm-governed-merges` | 0 | | `pnpm check:refd-timer-probe` | 0 | | `pnpm check:role-word` | 0 | | `pnpm check:skill-compatibility` | 0 | | `pnpm check:skill-frame-sync` | 0 | | `pnpm check:skill-identifier-liveness` | 0 | | `pnpm check:watch-hint-literal` | 0 | Outside the derived union, run as the dispatch ordered: `pnpm check:pm-dispatch-gates` launched detached with its exit captured to a file; its verdict is reported in the `os-dev-report` comment on #19358 (it was still in its self-test when this body was written). No package build or test is owed: the diff touches no package (① empty), and `packages/cli` / `packages/objectql` are cited, not edited. The `## Contract review` for this Tier H head is the seat's; `node scripts/pm/check-governed-merges.mjs --pr` on this PR is read after creation and goes into the report comment. ## PM mechanism assumptions, verified 1. Open PRs touching `skills/objectstack-ui/**`: **0 of 21** open PRs (read via REST `/pulls?state=open` + `/pulls/{n}/files`). Two open PRs touch `skills/` at all, neither in this surface: #19378 (`skills/objectstack-platform/SKILL.md`) and #19373 (`skills/objectstack-platform/references/_index.md`) — the claim named only the first; the second is a refinement of the reading, not a conflict. Holds. 2. `check-governed-merges.mjs --pr` → read after creation; expected GOVERNED / Tier H. Reported in the report comment. 3. The published-skill token ratchet (`scripts/check-skills-token-ratchet.mjs`) and `check:skill-identifier-liveness` are both in the derived union and both green on this diff. Holds, with the ratchet's name pinned — it has no `pnpm check:*` alias and is not `check:pm-skill-ratchet`. ## 维护者速读(草稿) - **改了什么**:对外发布的 `objectstack-ui` skill 里「页面文档」编写规则第 2 条,只改「为什么要加命名空间前缀」那一句;规则本身(文件名必须以包命名空间开头)与 ADR-0048 引用都保留。 - **为什么改**:原句说「裸名字会跨包冲突、安装时失败,依据 ADR-0048」——而 ADR-0048 §3.4 恰恰宣布跨包冲突这一说法已退役(两个包可以同时用同一个裸名字,按包 id 各自解析),真正的拒绝发生在 `os build`(`docs/namespace-prefix`),不在安装。这份 skill 是客户项目里 AI 写文档时读的权威,错误的理由会被原样抄进客户文档。 - **风险与代价(含回滚)**:纯文案,零代码、零发布产物、零 changeset;净 0 行;该文件的 token 上限余量从 2 变 0(下一次改这个文件须删字付账)。回滚 = revert 这一个 commit。 - **席位意见**:(留空,席位定稿) - **你要做的**:Tier H,本 PR 保持 draft;席位完成 `## Contract review` 与 ACCEPT 后,由你点合并。 ## Acceptance notes - noted, not filed: `packages/objectql/src/registry.ts` :3458–:3463 still opens with the pre-§3.4 framing ("refuse it loudly if a DIFFERENT code package already owns the same (type, name)") immediately above the :3472 retirement note — a stale lead-in comment, no behaviour behind it (no throw in :3458–:3511). Observation, outside the three filing classes. 承接者: none known (no open PR touches `registry.ts` for this; not scanned further). - noted, not filed: `content/docs/ui/doc-pages.mdx` :76–:77 calls `docs/namespace-prefix` "the same `namespace-prefix` lint the platform applies to other named metadata"; in `os lint` the `naming/namespace-prefix` rule (`packages/cli/src/commands/lint.ts` :313–:321) is a *warning* on a name declared twice within one package, while `docs/namespace-prefix` is an *error* on a missing prefix — same name stem, different predicate and severity. Docs imprecision, not a false claim about behaviour; out of this card's surface (the dispatch marked that page read-only). 承接者: none. - The claim's serial reading "0 of 20 open PRs" is 0 of 21 on this act, with #19373 as a second `skills/`-touching PR outside this surface — recorded above, no action. - ADR-0046 §3.2 (the origin of the retired framing) is #19408's, untouched here. #19408 is not addressed here. --- _Generated by [Claude Code](https://claude.ai/code/session_017ETYWqMQD4qMtZzAGovWNi)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 60152df commit 0f9245c

1 file changed

Lines changed: 3 additions & 3 deletions

File tree

‎skills/objectstack-ui/rules/pages.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -336,9 +336,9 @@ src/docs/
336336
— a reference resolves by basename, never by path.
337337
2. **Namespace-prefixed filename.** The filename stem becomes the doc
338338
`name` (`^[a-z][a-z0-9_]*$`) and must start with the package namespace
339-
(`crm_…`). Names share one flat, instance-global space with the URL, so
340-
a bare `user_guide` would collide across packages and fail at install
341-
(ADR-0048).
339+
(`crm_…`). `os build` refuses a bare `user_guide`
340+
(`docs/namespace-prefix`) — hygiene, not uniqueness: two packages
341+
coexist on one bare name (ADR-0048 §3.4).
342342
3. **Title** resolves: frontmatter `title:` → first `#` heading → `name`.
343343
Optional frontmatter `description:` is a one-line summary the docs portal
344344
shows under the title — add it on index/overview docs.

0 commit comments

Comments
 (0)