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

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

Site What it says Which record Load-bearing? Action
SKILL.md:84 "Data retention/rotation/archival contract (ADR-0057)" system data lifecycle Decorative — the row already states the contract in full and already links ./rules/lifecycle.md, which does resolve for an external reader Bare citation dropped (−11 bytes)
SKILL.md:973 "retention / rotation / archival contract (ADR-0057)" system data lifecycle Decorative — same, checklist row, same in-bundle link Bare citation dropped (−11 bytes)
rules/lifecycle.md:4 "reclaimed (ADR-0057)" system data lifecycle Decorative provenance, but this is the page that is the substance — the right single anchor for the topic Slug-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 published — content/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

Reading Before After
bare ADR-0057 in skills/objectstack-data/ 3 0
slug-qualified ADR-0057 in skills/objectstack-data/ 0 1
CONTROL — ADR-0057 D1 at SKILL.md:651 1 1 (byte-identical)
CONTROL — ADR-0010 in SKILL.md 4 4
CONTROL — ADR-0052 in SKILL.md 1 1
CONTROL — all ADR-NNNN in SKILL.md 32 30 (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.

Surface Lines Tokens
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
@os-steve
os-steve requested a review from os-zhuang August 24, 2026 16:34
@claude claude Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 24, 2026
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation labels Aug 24, 2026

Copy link
Copy Markdown
Collaborator Author

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

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

Labels

documentation Improvements or additions to documentation size/s skip-changeset PR 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