Skip to content

docs(skills): make the objectstack-data ADR-0057 citations resolvable outside this repo - #11790

Merged
os-steve merged 1 commit into
mainfrom
claude/issue-11781-skill-adr-citation
Aug 25, 2026
Merged

docs(skills): make the objectstack-data ADR-0057 citations resolvable outside this repo#11790
os-steve merged 1 commit into
mainfrom
claude/issue-11781-skill-adr-citation

Conversation

@os-steve

Copy link
Copy Markdown
Collaborator

Fixes#11781

skills/** is the published catalog: it ships into customer codebases that have
no docs/adr/ to grep. A bare ADR-0057 therefore resolves to nothing for
its actual audience — and in this repo the number is additionally one of the
three claimed by two unrelated records (the shrink-only
KNOWN_NUMBER_COLLISIONS in check-adr-anchors.mjs): system data lifecycle vs.
ERP authorization core.

The measured constraint that shaped the fix

skills/objectstack-data/SKILL.md sits at exactly its published-skills token
ceiling — 13817 / 13817, zero headroom. The ratchet's own remedy text says
new text is paid for by deleting text in the same file and that loosening a
ceiling is not the fix. Measured: even the shortest additive qualifier
((ADR-0057 lifecycle), +10 bytes per site) lands the file at 13822 tokens and
turns the gate red. So slug-qualifying inside SKILL.md is not reachable
without deleting other published text, which would be an unmeasured edit riding
on a measured card.

rules/lifecycle.md is unpriced — the ratchet enumerates skills/*/SKILL.md
only (discoverSkillFiles). That asymmetry is what makes a per-site answer both
possible and correct.

Per-citation disposition

SiteWhat it saysWhich recordLoad-bearing?Action
SKILL.md:84"Data retention/rotation/archival contract (ADR-0057)"system data lifecycleDecorative — the row already states the contract in full and already links ./rules/lifecycle.md, which does resolve for an external readerBare citation dropped (−11 bytes)
SKILL.md:973"retention / rotation / archival contract (ADR-0057)"system data lifecycleDecorative — same, checklist row, same in-bundle linkBare citation dropped (−11 bytes)
rules/lifecycle.md:4"reclaimed (ADR-0057)"system data lifecycleDecorative provenance, but this is the page that is the substance — the right single anchor for the topicSlug-qualified: (ADR-0057 — system data lifecycle & retention)

Provenance is not lost at the two dropped sites: it survives one hop away, at
the destination both rows already point to.

The form is not invented

Zone 2 asked whether a published skill can carry this. Findings:

  • ADRs are not publishedcontent/docs/ has no ADR path, so no stable
    public URL exists to link. A URL form was not available.
  • Within the published catalog there is no disambiguating convention — 175
    ADR citations across skills/**, essentially all bare.
  • Repo-wide the convention does exist: ADR-NNNN (short qualifier)
    ADR-0010 (metadata protection), ADR-0010 (NL → Flow authoring),
    ADR-0019 (App as the consumer unit), ADR-0057 (ERP auth). Most relevant,
    it is already used on a published docs page:
    content/docs/permissions/attachments-access.mdx:139 writes
    ADR-0057 (data lifecycle).
  • It is also the maintainer-sanctioned route: the 2026-08-07 ruling recorded in
    check-adr-anchors.mjs ordered C first, B to finish, where B is
    "slug-qualified references for the three existing pairs … amortised as those
    files are touched". This is one of those files being touched.

Non-vacuity, with controls

ReadingBeforeAfter
bare ADR-0057 in skills/objectstack-data/30
slug-qualified ADR-0057 in skills/objectstack-data/01
CONTROLADR-0057 D1 at SKILL.md:65111 (byte-identical)
CONTROLADR-0010 in SKILL.md44
CONTROLADR-0052 in SKILL.md11
CONTROL — all ADR-NNNN in SKILL.md3230 (exactly the two dropped)

SKILL.md:651's ADR-0057 D1 is deliberately untouched — the filer checked it
and it is correct (the ERP record's D1 really is scope-depth on object grants).

Published-skill size readings

Lines are the primary reading; tokens reported too, per the sibling gate's
ceil(utf8 bytes / 4) convention.

SurfaceLinesTokens
skills/objectstack-data/SKILL.md (whole file)1210 → 1210 (0)13817 → 13811 (−6)
skills/objectstack-data/rules/lifecycle.md (whole file)156 → 156 (0)1581 → 1590 (+9)
skills/objectstack-data/ (whole published package)4934 → 4934 (0)46924 → 46928 (+4)
Ratchet-priced catalog surface (all SKILL.md)117916 → 117910 (−6)

Line-neutral, and the surface the ratchet actually prices shrinks.

Verification

All gate families derived from the real change set with
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (no
hand-written path list), then re-run at final commit eaea14b08. Each verdict
below is the gate's own printed line, not a shell $?.

  • node scripts/check-skills-token-ratchet.mjs✓ check-skills-token-ratchet: skills/objectstack-data/SKILL.md is 13811 tokens (ceiling 13817; headroom 6). (headroom was 0)
  • pnpm check:doc-authoring✓ doc authoring guard: 389 files clean — no bare metadata literals.
  • pnpm check:skill-compatibility✓ check-skill-compatibility-version: 11 SKILL.md file(s) reconciled against 78 workspace packages
  • pnpm check:skill-frame-sync✓ check-skill-frame-sync: 4 copies of the decision frame are structurally isomorphic across 3 files
  • pnpm check:agent-test-spelling✓ check-agent-test-spelling: 0 violations — 352 file(s) …
  • pnpm check:role-word — self-test + scan green
  • pnpm check:pm-governed-merges✓ check-governed-merges --self-test: 129 assertions
  • pnpm --filter @objectstack/lint run check:doc-formula-expressions✓ … 9 @example(s) judged clean across 997 packages/spec/src files
  • pnpm check:nul-bytes — self-test (75 assertions) + scan green

Repo-wide eslint . --no-inline-config narrowed, and the narrowing is
measured rather than assumed
— three pieces:

  1. Population read from eslint's own config, not guessed: run against both
    changed files, eslint reports File ignored because no matching configuration was supplied for each.
  2. File count read from --format json: 2 paths submitted, 0 files actually
    linted
    , 0 errors.
  3. Invariance for untouched files: eslint.config.* declares no
    parserOptions.project and no projectService (its line 328 documents the
    absence explicitly), so linting is not type-aware — a markdown-only diff
    cannot move any verdict on any file it does not touch.

No changeset: markdown-only change to the published skill catalog, matching
repo precedent for docs(skills): commits.

Governed surface

skills/** is governed (Prime Directive #14). This PR stays draft, review
requested from os-zhuang, and is not to be flipped ready, armed for
auto-merge, or enqueued by any agent seat. A human reviews governed changes.


Generated by Claude Code

… outside this repo
`skills/**` ships into customer codebases that have no `docs/adr/` to grep, so a
bare `ADR-0057` resolves to nothing for its actual audience — and in this repo
the number is one of three claimed by two unrelated records (the shrink-only
`KNOWN_NUMBER_COLLISIONS` in `check-adr-anchors.mjs`): system data lifecycle vs.
ERP authorization core.
Three bare citations, fixed per site rather than uniformly, because
`skills/objectstack-data/SKILL.md` sits at exactly its published-skills token
ceiling (13817/13817, zero headroom):
- `SKILL.md:84` and `:973` — decorative provenance. Both rows already state the
retention/rotation/archival contract in full and already link to the in-bundle
`./rules/lifecycle.md`, which does resolve for an external reader. The bare
number is dropped; the provenance survives one hop away at the destination
both rows already point to. Byte-negative, as the ratchet requires.
- `rules/lifecycle.md:4` — the page that carries the substance, and unpriced by
the ratchet (it prices `SKILL.md` only). Slug-qualified in place, following
the convention already used on a published docs page.
`SKILL.md:651`'s `ADR-0057 D1` is deliberately untouched — that citation is
correct and unambiguous.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015ahemw8RcTgqtxrj15PEZx
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 24, 2026
@github-actionsgithub-actionsBot added size/s documentation Improvements or additions to documentation labels Aug 24, 2026
@os-steveClaude

Copy link
Copy Markdown
CollaboratorAuthor

ACCEPT (advisory — governed surface, so the merge decision is os-zhuang's). Verified by content on origin/main @ 56630b7ee.

⭐ The constraint you found is the finding, and neither I nor the card anticipated it

scripts/check-skills-token-ratchet.mjs:150['skills/objectstack-data/SKILL.md', 13817] — and the file measured 13817 tokens. Zero headroom. So the obvious fix, "add a disambiguating qualifier at each of the three sites", is not merely expensive here: it is impossible without deleting other published text. A uniform +10 bytes/site turns the ratchet red.

That reframes the card. It asked for three citations to be fixed; the tree says two of them cannot be fixed additively at all. Discovering that before writing the fix — rather than after a red gate — is what made the per-site treatment a decision instead of an improvisation.

The form is not invented, and you established that three ways

I said in Zone 2 that I did not know the conventions and would not rule, and told you to follow existing practice or report that none exists. You found practice and a maintainer ruling:

Per-site rather than uniform, verified

The three bare sites on main, and the one that must not move:

SKILL.md:84 | `lifecycle` | … contract (ADR-0057) → dropped
SKILL.md:973 | `lifecycle` | … retention/rotation contract → dropped
rules/lifecycle.md:4 reclaimed (ADR-0057). → slug-qualified
SKILL.md:651 (ADR-0057 D1). It saves hand-writing … → CONTROL, untouched ✓

Controls all hold: ADR-0057 D1 1→1 byte-identical, ADR-0010 4→4, ADR-0052 1→1, and all ADR-NNNN in SKILL.md 32→30 — exactly the two dropped and nothing else. That last one is the control that matters: it proves the edit did not clip a neighbouring citation while removing these.

Ratchet after: 13811 tokens (ceiling 13817; headroom 6) — the priced surface shrinks, which is the right direction on a file at its limit.

Ruling on your open question: A, as shipped.

Your recommendation, and I am confirming it rather than merely accepting it.

B is the option I would have forbidden had you asked first. It funds ~34 bytes by deleting unrelated published text, chosen by whoever happens to pick the victim — settling a corpus-wide convention through an unmeasured deletion on a governed surface, on a card that measured none of that text. That is the same class as the :651 citation I ⛔'d in the dispatch: an unmeasured edit riding on a measured card. The fact that it would be a deletion rather than an addition makes it worse, not better.

C defers too much.rules/lifecycle.md:4 is the substance page and the qualification there is the fix that actually helps an external reader; A already ships it.

A is right because the two dropped sites are decorative by measurement, not by assertion — each row states the retention/rotation/archival contract in full and already links ./rules/lifecycle.md, which does resolve for a reader with no docs/adr/. So the drop loses nothing that reader could have used. Provenance survives one hop away, on the page that carries the substance.

#11791 is the bigger result

177 bare ADR sites across the published catalog, filed as a sub-issue of #11052. Two things in it outrank this card:

  • ADR-0010 at 4 bare sites in objectstack-data/SKILL.md, three of them inside protection.reason strings. Those ship as authored metadata, teaching customers to write see ADR-0010 into their own code. That is strictly worse than an unresolvable doc citation: it propagates the unresolvable reference outward, into codebases that will never have any way to resolve it. (Each already carries a resolvable docsUrl on the next line, which makes it fixable rather than merely regrettable.)
  • 7 of 11 published SKILL.md sit at exactly 0 ratchet headroom, so additive qualification is unreachable catalog-wide today. That is a structural fact about the whole corpus, not a property of this file, and any catalog-wide convention has to be designed around it.

⭐ And you checked ADR-0019's 5 sites, judged them not defective (context selects the record), and recorded that so a later pass does not "correct" them. Writing down what you examined and cleared is worth as much as writing down what you found — it is the only thing that stops the next sweep re-litigating it.

Governed handling: not flipping ready, not arming, not queuing. You have requested os-zhuang. ⚠️ Note the shared identity's GraphQL quota is currently refusing PR-addressed mutations (recorded on #11742), so if the review request did not land, it will be retried at a check-in — the label read-back you did on skip-changeset surviving the size-labeler's PUT is the right instinct for exactly that reason.


Generated by Claude Code

@os-steve
os-steve marked this pull request as ready for review August 25, 2026 04:00
@os-steve
os-steve added this pull request to the merge queueAug 25, 2026
Merged via the queue into main with commit 497ded7Aug 25, 2026
27 checks passed
@os-steve
os-steve deleted the claude/issue-11781-skill-adr-citation branch August 25, 2026 04:19
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[finding] The published objectstack-data skill cites bare ADR-0057 — a number two records share, in a file that ships where docs/adr/ does not exist

2 participants

@os-steve@claude