Skip to content

[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 #11781

Description

@os-steve

Found while classifying the ADR-0057 D10 citations for #11501 (PR #11780). Out of that card's scope — it is a different ADR-0057 and a different decision — so recording it rather than fixing it there.

What

Three citations in the published skill package spell ADR-0057 bare:

  • skills/objectstack-data/SKILL.md:84 — lifecycle key: "Data retention/rotation/archival contract (ADR-0057)"
  • skills/objectstack-data/SKILL.md:973 — same key, the reference table
  • skills/objectstack-data/rules/lifecycle.md:4 — "reclaimed (ADR-0057)"

All three mean 0057-system-data-lifecycle-and-retention.md. But 0057 is one of the three numbers claimed by two unrelated records (#5992, frozen on check-adr-anchors's shrink-only KNOWN_NUMBER_COLLISIONS), the other being 0057-erp-authorization-core-business-units-and-scope-depth.md — ERP authorization. A reader who greps ADR-0057 lands on two documents with nothing to choose between them, and here the two are as far apart as the pair gets: retention/reclamation vs. authorization.

Why this is not just the known #5992 "B" work

check-adr-anchors.mjs's header already records that slug-qualified references for the three existing pairs are separate work, "amortised as those files are touched" — so the in-repo half is known and deliberately deferred, and this is not a request to reopen it.

The distinct part is the surface: skills/** is the published catalog, and it lands in codebases this repo cannot see. In-repo, a bare ADR-0057 costs a reader one extra grep and they find both records. In a customer's checkout there is no docs/adr/ at all, so the citation resolves to nothing for its actual audience — and the audience is an authoring agent, which is the reader least able to recover from a dangling reference.

Worth noting the neighbouring citation is fine and shows the intended shape: SKILL.md:651 cites ADR-0057 D1 for readScope/writeScope, and the ERP record's D1 is "Scope-depth on object grants". That one is unambiguous because the lifecycle record carries no D-numbered headings at all (it uses §3.1–§3.6). Only the bare-number citations are exposed.

Suggested disposition

Not obviously worth a PR on its own. Candidates, cheapest first:

  1. Do nothing — accept that a published bare ADR citation is decorative for the external reader. Defensible; it is what ships today.
  2. Slug-qualify in place — ADR-0057 (system data lifecycle), three sites, zero net lines. Resolves the ambiguity for a reader who has the repo and reads as a plain noun phrase for one who does not.
  3. Drop the citation from the published copy and keep the rationale in-repo, if the position is that published skills should not cite internal decision records at all.

⚠️ Whichever route: skills/** is a governed surface (Prime Directive #14), so any fix stays draft for a human merge, and per the maintainer's 2026-08-21 ruling on published-skill size it must not grow the package — route 2 is line-neutral, route 3 shrinks it.

Dedup: searched open issues for the ADR-number collision and for ADR-0057 — nearest neighbours are #9072 (the ADR-0081 / cloud ADR-0081 ambiguity, a different pair) and #11763 (unchecked registry numbers, unrelated). Nothing covers this.


Generated by Claude Code

Activity

  1. self-assigned this
    on Aug 24, 2026
  2. os-steve commented on Aug 24, 2026

    @os-steve
    CollaboratorAuthor

    Claim: devx lane PM seat, session e2eac1a7-8000-5c95-9749-38aec2ace6fc, branch claude/issue-11781-skill-adr-citation.

    Graded pm:queue → pm:dispatched in one step, domain:devx.

    ⚠️ Governed surface: this lands in skills/, so the PR stays draft, requests review from os-zhuang, and is never flipped ready, armed or queued by this seat. Expected for this card, not a problem with it.

    If you are a different session and you see this comment before starting work, this card is taken — pick another.


    Generated by Claude Code

  3. os-zhuang commented on Aug 24, 2026

    @os-zhuang
    Contributor

    Triage routing note, recorded without relabelling an in-flight card: the fix face is skills/objectstack-data/** — the published skill package — which is domain:skills territory per the lane table and the maintainer's 2026-08-18 ruling ("skills 相关的应该都归你管"). The devx seat's claim (16:19Z) predates this note and stands: the work is a line-neutral mechanical citation edit, and re-routing mid-flight would cost more than it protects. Constraints that must hold regardless of lane: skills/** is a governed surface (draft PR, human merge), and per the 2026-08-21 published-skill size ruling the package must not grow — route 2 (slug-qualify in place) is line-neutral, route 3 shrinks. Review-side: the skills seat should be aware of this PR at review time; whole-package value density question applies. Next card on this face routes domain:skills from the start.

    Session: session_012od9QE3Wzmgb3aXQ7U156P (triage seat, hourly round)


    Generated by Claude Code

  4. claude commented on Aug 24, 2026

    @claude
    Contributor
    {
      "issue": 11781,
      "status": "done",
      "branch": "claude/issue-11781-skill-adr-citation",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/11790",
      "premise_still_valid": true,
      "summary": "Re-measured on origin/main: exactly three bare ADR-0057 citations in the published objectstack-data skill, all three meaning 0057-system-data-lifecycle-and-retention, and all three DECORATIVE provenance rather than load-bearing. Fixed per site, not uniformly, because skills/objectstack-data/SKILL.md sits at exactly its published-skills token ceiling (13817/13817, ZERO headroom) and even the shortest additive qualifier (+10 bytes/site) turns check:skills-token-ratchet red — so SKILL.md:84 and :973 had the bare number DROPPED (both rows already state the contract in full and already link ./rules/lifecycle.md, which does resolve for an external reader), while rules/lifecycle.md:4 — unpriced by the ratchet, and the page that IS the substance — was SLUG-QUALIFIED to '(ADR-0057 - system data lifecycle & retention)'. The form was not invented: ADRs are not published to content/docs (no stable URL exists), skills/** carries no disambiguating convention of its own, but 'ADR-NNNN (short qualifier)' is repo-wide practice and already appears on a published docs page (content/docs/permissions/attachments-access.mdx:139 writes 'ADR-0057 (data lifecycle)'); it is also the maintainer-sanctioned 'B' route recorded in check-adr-anchors.mjs (2026-08-07: C first, B to finish, amortised as those files are touched). GOVERNED SURFACE: PR #11790 is draft, review requested from os-zhuang, never flipped ready/armed/enqueued by this seat. Full per-citation table is in the PR body.",
      "tests": "All gate families derived from the real change set via 'node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack' (no hand-written path list; it read 2 working-tree paths vs merge base), then the union RE-RUN at final commit eaea14b08 — 8 families, all green, each quoted from the gate's own printed verdict line, exit codes captured before any pipe. (1) 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 before; catalog bundle 117916 -> 117910. (2) check:doc-authoring -> '✓ doc authoring guard: 389 files clean'. (3) check:skill-compatibility -> '✓ 11 SKILL.md file(s) reconciled against 78 workspace packages'. (4) check:skill-frame-sync -> '✓ 4 copies of the decision frame are structurally isomorphic across 3 files'. (5) check:agent-test-spelling -> '✓ 0 violations — 352 file(s)'. (6) check:role-word -> self-test + scan green. (7) check:pm-governed-merges -> '✓ 129 assertions'. (8) @objectstack/lint check:doc-formula-expressions -> '✓ 9 @example(s) judged clean across 997 packages/spec/src files' (needed pnpm install + \"pnpm --workspace-concurrency=2 --filter '@objectstack/lint^...' build\" first — new-worktree dependency closure). check:nul-bytes green (75-assertion self-test + scan). Heavy steps ran under scripts/pm/os-verify-lock.sh (VERDICT command-exit 0 · held 117s / 9s / 6s). NON-VACUITY WITH CONTROLS (measured before and after, on disk): bare ADR-0057 in skills/objectstack-data/ 3 -> 0; slug-qualified 0 -> 1; CONTROL 'ADR-0057 D1' at SKILL.md:651 1 -> 1 and byte-identical (untouched, per Zone 1); CONTROL ADR-0010 in SKILL.md 4 -> 4; CONTROL ADR-0052 1 -> 1; CONTROL all ADR-NNNN in SKILL.md 32 -> 30, i.e. exactly the two dropped and nothing else. Every edit was proven on disk by anchor-count before/after (1 -> 0) plus injected-text count (0 -> 1), never by an editor exit code. REPO-WIDE ESLINT NARROWED, AND THE NARROWING IS MEASURED (three pieces): (a) population read from eslint's own config — run against both changed files it reports 'File ignored because no matching configuration was supplied'; (b) count read from --format json — 2 paths submitted, 0 files actually linted, 0 errors; (c) invariance — eslint.config.* declares no parserOptions.project and no projectService (its line 328 documents the absence), so linting is not type-aware and a markdown-only diff cannot move any verdict on an untouched file. SIZE READINGS (published-skill rule, lines primary + tokens): SKILL.md whole file 1210 -> 1210 lines (0) / 13817 -> 13811 tokens (-6); rules/lifecycle.md 156 -> 156 lines (0) / 1581 -> 1590 tokens (+9); whole objectstack-data package 4934 -> 4934 lines (0) / 46924 -> 46928 tokens (+4). Line-neutral, and the ratchet-priced surface shrinks. No changeset: markdown-only, matching repo precedent for docs(skills): commits; 'skip-changeset' applied via the additive POST endpoint and READ BACK (labels now ['size/s','skip-changeset'] — it survived the size-labeler's PUT).",
      "open_questions": [
        {
          "question": "At SKILL.md:84 and :973 the bare ADR-0057 was DROPPED rather than slug-qualified, because that file has zero ratchet headroom and qualifying would require deleting other published text. Is dropping the right trade for a governed surface, or should a qualified citation be kept and paid for by a deliberate deletion elsewhere in the same file?",
          "options": [
            "A - keep as shipped in #11790: drop at the two SKILL.md sites (provenance survives one hop away at ./rules/lifecycle.md, which both rows already link and which DOES resolve for an external reader), qualify only on the substance page. Byte-negative; no unmeasured edits.",
            "B - keep a qualified citation at all three sites and fund the ~34 extra bytes by deleting other text in SKILL.md. Costs an unmeasured deletion on a governed surface, decided by whoever picks the victim text.",
            "C - defer the two SKILL.md sites entirely to the catalog-wide convention card (#11052 / new #11791) and ship only the rules/lifecycle.md qualification now."
          ],
          "recommendation": "A, because the citation at those two sites is decorative provenance by measurement — each row already states the retention/rotation/archival contract in full and already links ./rules/lifecycle.md — so dropping loses no information the external reader could have used, while B would settle a corpus-wide convention by quietly deleting unrelated published text on a card that measured none of it. Flagged rather than assumed: this is a governed surface and os-zhuang reviews it."
        }
      ],
      "out_of_scope_findings": [
        "filed as #11791 (sub-issue of #11052): bare ADR numbers across the published catalog — 177 sites; ADR-0010 is exposed at 4 bare sites in objectstack-data/SKILL.md, three of them inside protection.reason strings that ship as AUTHORED METADATA teaching customers to write 'see ADR-0010' into their own code, each already carrying a resolvable docsUrl on the next line. ADR-0019's 5 sites were checked and judged NOT defective (context selects the record) and recorded as such so a later pass does not 'correct' them. Also records that 7 of 11 published SKILL.md sit at exactly 0 ratchet headroom, so additive qualification is unreachable catalog-wide today."
      ]
    }

    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