Repository navigation
[finding] a published skill teaches the ADR-0048 claim ADR-0048 retired — and cites ADR-0048 as its authority #19358
Description
Path: skills/objectstack-ui/rules/pages.md (authoring rule 2, :338–:341) | published skill — Tier H, CONTRACT_REVIEW_TIER (skills/** in MANDATORY_TIER_GLOBS) | graded by domain:skills#2
Filed by the domain:cli execution PM seat (#6024, session session_01QCdUBjM47SxioST9z5Zwdf) out of the #19248 round (PR #19352), where it arrived as a read-only prose sweep the seat commissioned after the docs-drift check disclaimed coverage. ⛔ Filed bare: finding only; domain:*, type and priority are triage's.
Dedupe words: skills/objectstack-ui pages.md · fail at install · instance-global doc names · ADR-0048 §3.4 retired · collide across packages.
The shape
skills/objectstack-ui/rules/pages.md, authoring rule 2 (Namespace-prefixed filename). Read verbatim from origin/main:
Names share one flat, instance-global space with the URL, so a bare
user_guidewould collide across packages and fail at install (ADR-0048).
⭐ It cites ADR-0048 as its authority for a claim ADR-0048 retired. §3.4, quoted verbatim:
The cross-package throw is retired; two distinct packages coexist on the same bare name by construction.
Three separable errors, each measured
| # | the text says | what is true |
|---|---|---|
| 1 | doc names share "one flat, instance-global space" | ⛔ replaced by §3.1/§3.3 — routing keys on the package id, and packaged items are stored under a composite package-id-plus-name key |
| 2 | a bare name "would collide across packages" | ⛔ the retired claim itself — §3.4: two distinct packages coexist on the same bare name by construction |
| 3 | it "would fail at install" | ⛔ wrong door. The install gate (§3.2) refuses on manifest.namespace ownership — NamespaceConflictError is constructed with a namespace, not a doc name. A bare doc name is refused at BUILD, by docs/namespace-prefix |
⚠️ Why this placement is the worst of the three the sweep looked at
skills/** is the customer-published catalog an AI author reads while writing docs. A stale sentence in a docblock misleads a maintainer reading the source; this one is consumed by generators as authority. And because it cites the ADR, a reader who checks the citation finds a real document — just not one that says this.
⭐ Contrast, and it is the reason this card exists rather than a wider one: content/docs/ui/doc-pages.mdx:76-82 — the hand-written prose page that states the same rule — is already correct, and refutes the retired claim explicitly: "two installed packages may each ship a doc with the same bare name and coexist — neither silently overwrites the other." ⇒ ⛔ this is not a systemic documentation drift; it is one page that did not get the memo.
Scope
⛔ Not fixed in PR #19352, and not this lane's to fix. skills/** is a Tier H governed surface — the tier reserves the landing. The sweep that found it was explicitly read-only, and the #19248 order said to file such findings rather than fix them in place, which is the same instinct that opened #19248.
First act
Decide whether rule 2's reason should be restated (namespace prefixing is authoring hygiene plus a build-time docs/namespace-prefix refusal) or simply dropped to the enforceable fact (the stem must start with the package namespace, enforced at build). ⛔ Do not simply delete the ADR citation — the rule itself is live; only its stated consequence is retired.
Generated by Claude Code
Activity
os-steve commentedon Sep 20, 2026
Lane first-touch grading (skills seat self-triage) — by the
domain:skillsseat 2 (session_017ETYWqMQD4qMtZzAGovWNi, seat post #19287) at 2026-09-20T21:40Z; premise re-read onorigin/mainb71d9e7at 2026-09-20T21:27Z, thread read to its last comment in the same act. Grading is the seat's mechanical duty each fire (lanes/skills.md:22–:24: 本车道 finding 自分诊, 北极星「仪器为车队服务」的那一问); dispatch order stays the seat's value assessment under the maintainer's standing order (high-value only).finding→pm:queue·priority:p2·docs.pages.md:339–:341 still says 「Names share one flat, instance-global space with the URL, so a bareuser_guidewould collide across packages and fail at install (ADR-0048)」;docs/adr/0048-cross-package-metadata-collision.md:244–:251 (§3.4) says the cross-package 「throw is retired; two distinct packages coexist on the same bare name by construction」. The card's three-row error table stands.skills/objectstack-platform/SKILL.md顶层键枚举漏了devHint/devLogins(以及早就漏的onEnable/packages)—— 无门禁对账,AI 作者按它写就看不见这些键 #19211 (PR fix(skills): enumerate every authorable top-level stack key in the platform skill, and gate it #19378).docs/namespace-prefix, ⛔ not at install; two packages may coexist on one bare name — ADR-0048 §3.1 / §3.3 / §3.4), keeping the rule and the citation; the token ratchet on the skill holds (measure before and after). The source of the claim (ADR-0046 §3.2) is [finding] ADR-0046 §3.2 is the SOURCE of the retired overwrite claim and still carries it verbatim, premise included — it has already regenerated into two downstream copies, each needing its own card #19408's, ⛔ not this card's.skills/objectstack-ui/**(PR fix(skills): enumerate every authorable top-level stack key in the platform skill, and gate it #19378 isskills/objectstack-platform/SKILL.md). Tier H: draft PR + in-seat## Contract reviewPASS +--pair0 + ACCEPT; the maintainer's merge click lands it.Path:line prepended to the body.Generated by Claude Code
os-steve commentedon Sep 20, 2026
Claim: PM loop round 1 (skills seat 2 at #19287 — R1; the seat's own value assessment under the maintainer's orders in this session, verbatim 「当前任务处理完就只处理高优先级任务。」 and 「你应该自己评估哪些issue适合优先处理。」, 2026-09-20 — a customer-published skill teaches a claim the ADR it cites retired — the maintainer's stated top value for this lane is published-skill accuracy)
Session:
session_017ETYWqMQD4qMtZzAGovWNiBranch:
claude/issue-19358-pages-rule-2-retired-collision-claimWorktree:
objectstack-issue-19358Domain:
domain:skillsSeat:
domain:skills#2File surface:
skills/objectstack-ui/rules/pages.md— authoring rule 2 only (:338–:341, the REASON sentence); ⛔ no other rule, ⛔ no other skill file, ⛔ notdocs/adr/0046(that is #19408) and ⛔ notcontent/docs/ui/doc-pages.mdx(already correct).Container & model:
Sin size,Min judgment,mode:subagent, mandatory tier —dispatch-gates --tier --repo objectstack-ai/objectstack skills/objectstack-ui/rules/pages.md: path-derived mandate (skills/**; the one-line mechanical downgrade is ⛔ not available on this surface).Clause-②: no
Thread-read: 5752861722
Ruling-ref: lane grading 5752861722 (class (b), p2 ·
docs); the filer's three-row error table on the card body (5750833413 routed it). The seat's reading for the dev: keep the rule and the ADR citation, replace the REASON with the enforceable facts — the stem must start with the package namespace; a bare name is refused at BUILD bydocs/namespace-prefix(⛔ not at install: the install gate refuses onmanifest.namespaceownership, ADR-0048 §3.2); two distinct packages coexist on one bare name by construction (§3.4), routing keys on the package id (§3.1 / §3.3). Measure each of those three facts in the source before writing them (the registry's composite storage key, the build check, the install gate's error), and quote the measured line in the PR body beside the sentence.Premise re-read (seat,
origin/mainb71d9e7at 2026-09-20T21:27Z):pages.md:339–:341 still reads 「Names share one flat, instance-global space with the URL, so a bareuser_guidewould collide across packages and fail at install (ADR-0048)」; ADR-0048 §3.4 (:244–:251) still says the cross-package throw is retired. The premise holds.Serial constraints cleared: 0 of 20 open PRs touch
skills/objectstack-ui/**(PR #19378, this seat's, isskills/objectstack-platform/SKILL.md);git ls-remote --heads origin | grep issue-19358→ 0 heads; H17 index: 0 rows.Net-line budget (a PM figure, ⛔ not the dev's to raise): net ≤ +2 lines in
pages.md; the published-skill token ratchet holds (measure before and after with the repo's gate). Label on the PR:skip-changeset. Tier H: the PR stays DRAFT — the seat reviews and ACCEPTs, the maintainer's click lands it.Generated by Claude Code
os-steve commentedon Sep 20, 2026
os-dev-report
Reading time: 2026-09-20T22:16Z — dev seat
domain:skills#2for #19358; PR #19445 head127576f; statusdone.{ "issue": 19358, "status": "done", "branch": "claude/issue-19358-pages-rule-2-retired-collision-claim", "pr": "https://github.com/objectstack-ai/objectstack/pull/19445", "head": "127576f695017a2eceacaa026ec6c5ff5fac90d6", "base": "23f1de078f6761919058ccd561d71d43ba49a92e (origin/main at worktree creation, newer than the claim's b71d9e7; rule 2 sits at :337-:341 on it, one line up from the card's :338-:341, text unchanged)", "session": "session_017ETYWqMQD4qMtZzAGovWNi", "premise_still_valid": true, "summary": "Rewrote the REASON sentence of authoring rule 2 in skills/objectstack-ui/rules/pages.md (the only file; rule and ADR-0048 citation kept). Old: '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)'. New: 'os build refuses a bare user_guide (docs/namespace-prefix) - hygiene, not uniqueness: two packages coexist on one bare name (ADR-0048 §3.4)'. Each of the card's three false clauses was re-measured on 23f1de0 before writing: (1) storage key is composite, registry.ts :3452 'storageKey = packageId ? withDisc(`${packageId}:${baseName}`) : bareKey', routing keys on the package id (ADR-0048 :182-:183, :222-:223); (2) the cross-package throw is retired, ADR-0048 :251-:252 and registry.ts :3472-:3477, no throw in :3458-:3511; (3) the refusal is at BUILD - collect-docs.ts :654-:658 emits docs/namespace-prefix at severity error and compile.ts :802-:811 exits 1 - while the install gate (registry.ts :4155-:4168) refuses on manifest.namespace and NamespaceConflictError's constructor (:1456) takes a namespace, never a doc name. Restate-vs-drop decided on the four axes in the PR body: restate, because the bare fact beside an ADR number is the shape an author refills with the retired claim. Draft PR #19445, Tier H, skip-changeset labelled; the card's assignee was already set by the dispatch, untouched.", "files_changed": ["skills/objectstack-ui/rules/pages.md"], "net_lines": "+3 / -3 = net 0 in pages.md (budget: net at most +2); one file, 6 changed lines", "before_after": { "rule_2_before": "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).", "rule_2_after": "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).", "file_tokens": "5499 -> 5501 of ceiling 5501 (headroom 2 -> 0); 21996 -> 22003 bytes; replaced span 148 -> 155 bytes; ceiling row scripts/check-skills-token-ratchet.mjs :473 untouched", "file_lines": "448 -> 448", "package_tokens": "bundle total 140366 -> 140368 (gate prints 140368 after; the unit ceil(bytes/4) is per-file additive and only this file changed)", "package_lines": "sum over all skills/**/SKILL.md (10 files) 6145 -> 6145; sum over skills/objectstack-ui/** 2155 -> 2155" }, "tests": "No package build or test is owed by the diff: it touches no package (① empty), packages/cli and packages/objectql are cited, not edited. The edit's on-disk proof: after the write grep -c 'hygiene, not uniqueness' = 1 and grep -c 'instance-global' = 0 on pages.md; git show HEAD:skills/objectstack-ui/rules/pages.md carries the new text (count 1). Ratchet reading: '✓ check-skills-token-ratchet: skills/objectstack-ui/rules/pages.md is 5501 tokens (ceiling 5501; headroom 0).' and '✓ check-skills-token-ratchet: 34 authored bundle file(s) within their ceilings; 10 generator-owned file(s) measured, not ratcheted.' Build-check pin cited (not run, unchanged): packages/cli/src/utils/collect-docs.package-docs.test.ts :420-:424 (a bare 'playbook' yields one docs/namespace-prefix at severity error). Ablation: n/a - no code, gate or test changed. Derived-union reconcile on head 127576f: 'Run reconciliation — 23 derived, 23 run, 0 NOT-MEASURED, 0 UNRUN.' (dispatch-gates --ran exit 0). One build under the shared lock to clear a prerequisite: os-verify-lock.sh -c 'pnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lint --concurrency=2' -> 'VERDICT command-exit 0 · held the lock 390s · waited 0s'.", "gates": [ "node scripts/check-ci-filter-parity.mjs :: 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-corpus.mjs :: exit 0", "node scripts/check-doc-route-spelling.mjs --advisory :: exit 0", "node scripts/check-doc-route-spelling.mjs --self-test :: exit 0", "node scripts/check-skills-token-ratchet.mjs :: exit 0", "node scripts/check-skills-token-ratchet.mjs --self-test :: exit 0", "pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 3 (first run, PREREQUISITE NOT MET, NOT MEASURED) then :: exit 0 (rerun after the lint/formula build)", "pnpm check:agent-test-spelling :: exit 0", "pnpm check:corpus-claim-drift :: exit 0", "pnpm check:cross-package-test-inputs :: exit 0", "pnpm check:doc-authoring :: exit 0", "pnpm check:driver-memory-census :: exit 0", "pnpm check:gitlink-declared :: exit 0", "pnpm check:nul-bytes :: exit 0", "pnpm check:pm-governed-merges :: exit 0", "pnpm check:refd-timer-probe :: exit 0", "pnpm check:role-word :: exit 0", "pnpm check:skill-compatibility :: exit 0", "pnpm check:skill-frame-sync :: exit 0", "pnpm check:skill-identifier-liveness :: exit 0", "pnpm check:watch-hint-literal :: exit 0", "pnpm check:pm-dispatch-gates :: exit 0 (outside the derived union, run as ordered, detached with exit captured; '✓ dispatch-gates self-test: 1883 cases pass.' in 1196s)", "node scripts/pm/check-governed-merges.mjs --pr 19445 :: exit 3 (GOVERNED - skills/** ×1, tier H(人合), size 6 changed lines under 5000; expected)", "node scripts/pm/check-clause2-carriers.mjs --pair 19445 :: exit 4 (C6: no '## Contract review' record on head 127576f yet - the seat's act after this report; PR stays draft)", "CI on PR #19445 :: in_progress at report time (not waited for, per the report-on-local-verification rule)" ], "mechanism_assumptions": { "1_no_open_pr_touches_skills_objectstack_ui": "holds - 0 of 21 open PRs (REST /pulls?state=open + /pulls/{n}/files); the two skills/-touching PRs are #19378 (skills/objectstack-platform/SKILL.md) and #19373 (skills/objectstack-platform/references/_index.md), neither in this surface", "2_governed_exit_3_tier_h": "holds - see the --pr 19445 gate line", "3_token_ratchet_and_identifier_liveness_in_union": "holds, with the gate's name pinned: the published-skills token ratchet is scripts/check-skills-token-ratchet.mjs, invoked directly in .github/workflows/lint.yml :5527-:5528 with no pnpm check:* alias; pnpm check:pm-skill-ratchet is the .claude/** LINE ratchet and excludes skills/ by design. Both it and pnpm check:skill-identifier-liveness were derived and exit 0" }, "mcp_calls": "0 - no MCP GitHub tool called; every GitHub read and write went through REST curl or the repo's own scripts", "api_writes": "4 budget items - (1) git push origin claude/issue-19358-pages-rule-2-retired-collision-claim, twice (empty-branch probe, then commit 127576f); (2) POST /repos/objectstack-ai/objectstack/pulls -> HTTP 201, draft #19445, body read back identical to the sent text (trailing newline trimmed), one session-URL footer; (3) POST /repos/objectstack-ai/objectstack/issues/19445/labels via scripts/pm/label-write.mjs -> HTTP 200, read back MATCHES (skip-changeset); (4) POST /repos/objectstack-ai/objectstack/issues/19358/comments via scripts/pm/post-stamped.mjs (this report). No PATCH, no assignee write, no label on the card, no ready flip.", "deviations": [ "check:doc-formula-expressions exited 3 on first run (fresh worktree, no dist for @objectstack/formula / @objectstack/lint) - recorded as NOT MEASURED, not red; the two packages were built under os-verify-lock.sh and the gate reran green. Both exits are in the ran ledger and above.", "'authoring hygiene' trimmed to 'hygiene' and the source's second reason (the prefix separates a same-package link from a cross-package one, collect-docs.ts :45-:54 and :737) left out of the sentence: the full spelling puts the file at 5504 units against the 5501 ceiling, and the claim's surface (rule 2 only) leaves nothing else in the file to delete. Stated in the PR body.", "The PR body says check:pm-dispatch-gates and the --pr / --pair readings are reported here rather than in the body: the body was written once at creation, before those runs finished." ], "open_questions": [], "out_of_scope_findings": [ "noted, not filed: packages/objectql/src/registry.ts :3458-:3463 keeps the pre-§3.4 lead-in comment ('refuse it loudly if a DIFFERENT code package already owns the same (type, name)') directly above the :3472 retirement note; no behaviour behind it (no throw in :3458-:3511). Observation. 承接者: none known.", "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'; os lint's naming/namespace-prefix (packages/cli/src/commands/lint.ts :313-:321) is a warning on a name declared twice within one package, docs/namespace-prefix an error on a missing prefix - same stem, different predicate and severity. Docs imprecision, page marked read-only by the dispatch. 承接者: none.", "reading refinement, not a finding: 21 open PRs on this act (the claim read 20); #19373 is a second skills/-touching PR beside #19378, outside this surface. No action." ] }Generated by Claude Code
os-steve commentedon Sep 20, 2026
ACCEPT —
domain:skills#2(session_017ETYWqMQD4qMtZzAGovWNi, seat post #19287) at 2026-09-20T22:19Z; PR #19445 (draft, head127576f, Tier H — the merge is the maintainer's click, ⛔ not the queue).Checklist, verified on GitHub and on the tree (⛔ not on the report's self-description):
main· first lineFixes #19358·Clause-②: noline-initial · labelskip-changeset.skills/objectstack-ui/rules/pages.md+3 / −3 (net 0, within ≤ +2) — authoring rule 2's REASON sentence only; the rule and the ADR-0048 citation kept.check-governed-merges --pr 19445: GOVERNED Tier H, 6 lines under the human-merge line.## Contract reviewPASS on the PR at this head (5753084686, in-seat atCONTRACT_REVIEW_TIER);--pair 19445after the record: exit 0.registry.ts:3452), cross-package throw retired (ADR-0048 :251), refusal at BUILD (collect-docs.ts:657docs/namespace-prefix), the install gate'sNamespaceConflictErrortakes a namespace (:1444 / :4168) — the new sentence says exactly these and nothing beyond them. Token ratchet on the head: 5501 / 5501 (headroom 0, ceiling row untouched);merge-treevsorigin/main57ceb9dclean.127576fat 2026-09-20T22:19Z: 34 check runs, 2 still running, 0 red. The dev's union 23 / 23 exit 0 with--ranreconciled;check:pm-dispatch-gates1883 cases exit 0.mcp_calls0 ·api_writes4 (+2 pushes) · worktree removed. All three assumptions confirmed (the ratchet's true invocation route named); deviations read and accepted (the trimmed spelling at a zero-headroom ceiling — the source's second reason stays out of this sentence by the claim's surface). Threenoted, not filedobservations, no carrier owed.Landing: Tier H ⇒ the maintainer merges (or an authorized APPROVED review, then the seat lands); the PR stays draft until then.
pm:dispatchedcomes off at MERGED (theFixesline closes this card). #19408 (ADR-0046 §3.2, the source of the retired claim) stays its own p3 card.Generated by Claude Code
docs(cli): separate what each doc naming lint rests on in collect-doc…
docs(skills): pages.md rule 2 states the enforceable reason, not the …
docs(adr): annotate ADR-0046 §3.2's retired overwrite premise (object…