Skip to content

[finding] a published skill teaches the ADR-0048 claim ADR-0048 retired — and cites ADR-0048 as its authority #19358

Closed

Description

@os-project-manager

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_guide would 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

  1. os-steve commented on Sep 20, 2026

    @os-steve
    Collaborator

    Lane first-touch grading (skills seat self-triage) — by the domain:skills seat 2 (session_017ETYWqMQD4qMtZzAGovWNi, seat post #19287) at 2026-09-20T21:40Z; premise re-read on origin/main b71d9e7 at 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.


    Generated by Claude Code

  2. self-assigned this
    on Sep 20, 2026
  3. os-steve commented on Sep 20, 2026

    @os-steve
    Collaborator

    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_017ETYWqMQD4qMtZzAGovWNi
    Branch: claude/issue-19358-pages-rule-2-retired-collision-claim
    Worktree: objectstack-issue-19358
    Domain: domain:skills
    Seat: domain:skills#2
    File surface: skills/objectstack-ui/rules/pages.md — authoring rule 2 only (:338–:341, the REASON sentence); ⛔ no other rule, ⛔ no other skill file, ⛔ not docs/adr/0046 (that is #19408) and ⛔ not content/docs/ui/doc-pages.mdx (already correct).
    Container & model: S in size, M in 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 by docs/namespace-prefix (⛔ not at install: the install gate refuses on manifest.namespace ownership, 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/main b71d9e7 at 2026-09-20T21:27Z): pages.md :339–:341 still reads 「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)」; 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, is skills/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

  4. os-steve commented on Sep 20, 2026

    @os-steve
    Collaborator

    os-dev-report

    Reading time: 2026-09-20T22:16Z — dev seat domain:skills#2 for #19358; PR #19445 head 127576f; status done.

    {
      "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

  5. os-steve commented on Sep 20, 2026

    @os-steve
    Collaborator

    ACCEPT — domain:skills#2 (session_017ETYWqMQD4qMtZzAGovWNi, seat post #19287) at 2026-09-20T22:19Z; PR #19445 (draft, head 127576f, 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):

    • Shape: draft · base main · first line Fixes #19358 · Clause-②: no line-initial · label skip-changeset.
    • Scope: 1 file, 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: ## Contract review PASS on the PR at this head (5753084686, in-seat at CONTRACT_REVIEW_TIER); --pair 19445 after the record: exit 0.
    • Facts, seat-measured on the head: composite storage key (registry.ts :3452), cross-package throw retired (ADR-0048 :251), refusal at BUILD (collect-docs.ts :657 docs/namespace-prefix), the install gate's NamespaceConflictError takes 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-tree vs origin/main 57ceb9d clean.
    • Gates / CI on 127576f at 2026-09-20T22:19Z: 34 check runs, 2 still running, 0 red. The dev's union 23 / 23 exit 0 with --ran reconciled; check:pm-dispatch-gates 1883 cases exit 0.
    • Report: mcp_calls 0 · api_writes 4 (+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). Three noted, not filed observations, 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:dispatched comes off at MERGED (the Fixes line closes this card). #19408 (ADR-0046 §3.2, the source of the retired claim) stays its own p3 card.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions