Skip to content

[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

Closed

Description

@os-project-manager

Path: docs/adr/0046-package-docs-as-metadata.md §3.2 (:138–:145) | Tier H — the maintainer's merge; the sanctioned form is the amended status line / supersession note, ⛔ not a rewrite of a dated record | graded by domain:skills#2

Filed by the domain:cli execution PM seat (#6024, session session_01QCdUBjM47SxioST9z5Zwdf) out of the #19359 round (PR #19406), where the delivering dev found it and declined to file — ⛔ correctly, because whether an ADR should be amended at all is a governance question, not a defect call. ⛔ Filed bare: finding only; domain:*, type and priority are triage's.

Dedupe words: ADR-0046 3.2 last-write-wins · silently overwrite each other · ADR-0048 supersession not annotated · retired claim upstream source · org/type/name no package coordinate.

The source text, read verbatim from origin/main

docs/adr/0046-package-docs-as-metadata.md, lines 138–145:

their uniqueness need is logical — the metadata registry key is org/type/name with no package coordinate, so two packages shipping the same bare name silently overwrite each other (last-write-wins), and the console route /docs/<name> plus all cross-references key on the name.

⭐ That is the whole inference — premise and conclusion — and it is the ancestor of every downstream copy.

⚠️ It has already regenerated TWICE. This is measured, ⛔ not projected.

downstream copy card state
packages/cli/src/utils/collect-docs.ts module header #19359 fixed in PR #19406
skills/objectstack-ui/rules/pages.md (Tier H, customer-published) #19358 open

⇒ fixing the two copies leaves the source able to regenerate it a third time. ⭐ That is the argument for this card existing at all: the downstream cards treat instances, this one treats the generator.

What ADR-0048 actually did to it, and why the premise was never fully true

  • §1.2 is headed "The silence is in the read, not the write".
  • The write is already composite-keyed. Verified by this seat on origin/main, packages/objectql/src/registry.ts:3452:
    const storageKey = packageId ? withDisc(`${packageId}:${baseName}`) : bareKey;
    and the Overwriting log at :3455 fires only on collection.has(storageKey) — the same composite key, i.e. the same package.
  • §3.4 then retired the cross-package throw outright.

⚠️ The premise is true of one key and false of the other, which is why it reads so convincingly: refKey (packages/metadata-core/src/types.ts:84) really does return `${ref.org}/${ref.type}/${ref.name}` with no package coordinate — but that is the cache key, ⛔ not the key an overwrite would happen on.

⇒ the real residual is a context-free first-match READ, ⛔ not an overwrite — a posture §3.3 accepts by design.

⚠️ No supersession annotation sits on that passage

Measured: ADR-0046 mentions ADR-0048 exactly twice, at lines 335 and 525 — ⛔ neither is near line 142, and neither annotates this passage. Its status line reads Status: Proposed (2026-06-12, revised …).

⭐ By contrast content/docs/ui/doc-pages.mdx:92 does carry the supersession — "The earlier 'one global URL per doc' framing from ADR-0046 was superseded by ADR-0048's package-scoped resolution." ⇒ the prose page records what the ADR itself does not.

⛔ The reason this was NOT filed by the dev, stated rather than hidden

ADRs are dated records. Prime Directive #13's "new ADR or amended status line" is arguably satisfied by ADR-0048 simply existing, and docs/adr/** is Tier H.

⇒ ⭐ this card does not assert that the ADR must be edited. It asserts that the source of a claim retired twice over is unannotated, and that the cost of leaving it so is now measured at two cards. Whether the remedy is an amended status line, a pointer at §3.2, or deliberately nothing at all, is the reader's call.

First act

Decide whether a superseded passage inside a dated record is amended at all. ⛔ Do not start by editing §3.2 — if the answer is "ADRs are immutable", the correct outcome is a recorded decision and this card closes, which is a complete result.


Generated by Claude Code

Activity

  1. added
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Sep 20, 2026
  2. added
    pm:queueReady for the PM dispatch loop
    and removed
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Sep 20, 2026
  3. 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:41Z; 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:p3 · docs.


    Generated by Claude Code

  4. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Sep 22, 2026
  5. self-assigned this
    on Sep 22, 2026
  6. huangyiirene commented on Sep 22, 2026

    @huangyiirene
    Collaborator

    Claim: PM loop round R1 (skills seat 1) — batch 5 on the maintainer's word of this date (「并发加到5」, 「不是要求并发5?」)
    Session: session_01Wnstp2kTth7sGXfr8fXypc
    Branch: claude/issue-19408-adr-0046-3-2-supersession-note
    Worktree: objectstack-issue-19408
    Domain: domain:skills
    Seat: domain:skills#1
    File surface: docs/adr/0046-package-docs-as-metadata.md only — §3.2 (:138–:145) gains the sanctioned amended status line / supersession note pointing at the ruling that retired the last-write-wins claim, ⛔ not a rewrite of the dated record; ⛔ no other ADR, no packages/** (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: TIER_DEFAULT — node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --tier on the surface at 7e1b048a1d (2026-09-22T09:16Z) printed verbatim: "Model tier — no path-derived mandate: the surface hits none of the 3 declared glob(s), derived here, not recalled." docs/adr/** — Tier H on the check-governed-merges.mjs register (人合): draft PR with the 维护者速读, the maintainer merges; the lane's review of record is rendered in-seat at the served tier (fable).
    Clause-②: no
    Thread-read: 5752868774
    Ruling-ref: none — a triage-graded card (the lane's first-touch grading comment is on the thread)
    Serial constraints cleared: none — all 20 open PRs' file lists read at 2026-09-22T09:16Z; no open PR touches this surface.

    Dispatch basis: the card's reading of §3.2 as the upstream source of the retired overwrite claim (premise and conclusion verbatim on origin/main), graded p3 docs Tier H by the lane (5752868774) with the sanctioned form named in its Path: line; 北极星「优先级」第 3 条 read fresh at 2026-09-22T09:16Z (objectstack non-epic p0 4 · p1 29, objectui p1 8): this card carries no tooling label and is not contract hygiene — applied by this seat as label-based, declared on seat post #7623 r15. Premise re-read on origin/main 7e1b048a1d by the dev before editing; premise_still_valid: false is a first-class outcome.


    Generated by Claude Code

  7. huangyiirene commented on Sep 22, 2026

    @huangyiirene
    Collaborator

    os-dev-report

    {
      "issue": 19408,
      "status": "done",
      "branch": "claude/issue-19408-adr-0046-3-2-supersession-note",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/19702",
      "session": "session_01Wnstp2kTth7sGXfr8fXypc",
      "premise_still_valid": true,
      "summary": "ADR-0046 is annotated, not rewritten. Line 3 (the dated Status line) is byte-identical; line 4 appends one clause — '· **Superseded in part (2026-06-13, ADR-0048)** — the bare-name overwrite premise; note at §3.2.' — and §3.2 closes with a 6-line blockquote in this file's own amendment style naming what §3.2 claimed, what retired it (ADR-0048 §1.2 premise, §3.4 retirement) and where the current truth lives (its §3.3 package-scoped resolution), plus the fact that §3.2's build/publish lint still stands on authoring hygiene and the flat link namespace. §3.2's own text is untouched. One file, +8 lines, no changeset (docs/adr publishes nothing). Assignee on the card was already set by the PM (huangyiirene) and was never written by this run.",
      "note_position": "End of §3.2, after the 'TS-first stacks may also pass docs: [...] inline' sentence and before '### 3.3 Cross-references' (file lines 159-164, blank-line separated both sides). Measured, not assumed: this file's own amendment (the §6.7 'Amendment' blockquote, old line 572) sits inside its section right after the prose it amends, so a section-internal blockquote IS the house form here; the §3.2 claim lives in bullet 1 of a 6-bullet list, and a block between bullets would split the list, so the note closes the section instead. Every section reference inside the note is spelled 'its §N' so it reads against ADR-0048 and never against ADR-0046's own §3.3 two lines below.",
      "note_text": "> **Superseded in part (2026-06-13) — the bare-name overwrite premise above.**\n> [ADR-0048](./0048-cross-package-metadata-collision.md) measured the write as already\n> composite-keyed (`packageId:name`) in its §1.2, so two packages on one bare name do\n> not overwrite each other, and its §3.4 retires the cross-package throw. The residual\n> is a context-free *read*, repaired by its §3.3 (package-scoped, prefer-local); the\n> lint above stands on authoring hygiene and the flat link namespace, not on overwrite.",
      "status_line_text": "· **Superseded in part (2026-06-13, ADR-0048)** — the bare-name overwrite premise; note at §3.2.",
      "line_budget": "+8 physical lines against the dispatched ceiling of +8; `git diff --stat` = '1 file changed, 8 insertions(+)'. Widths: status clause 96 cols; the 6 blockquote lines 78/86/85/86/84/87 cols — all under the 100-col budget, and inside the 77-85 band of this file's existing amendment blockquote.",
      "files_changed": [
        "docs/adr/0046-package-docs-as-metadata.md"
      ],
      "premise_evidence": "H1 measured on the worktree base 7e1b048a1d before editing: §3.2 carried the claim verbatim at lines 139-144 ('the metadata registry key is `org/type/name` with **no package coordinate**, so two packages shipping the same bare name silently overwrite each other (last-write-wins)'); the file mentioned ADR-0048 exactly twice, at lines 335 and 525, neither near the passage; grep for 'supersed' / '> **Status' / 'Ruling:' in the file returned zero. No supersession note existed. The claim string is still present verbatim after the edit (verified on disk, count 1) — the record is annotated, not rewritten.",
      "gates": [
        {
          "family": "check:adr-links",
          "command": "node scripts/check-adr-links.mjs",
          "exit": 0,
          "verdict": "check-adr-links: 690 relative link destination(s) under docs/adr/ resolve"
        },
        {
          "family": "check:adr-links (self-test)",
          "command": "node scripts/check-adr-links.mjs --self-test",
          "exit": 0,
          "verdict": "self-test clean"
        },
        {
          "family": "check:adr-symbol-anchors",
          "command": "node scripts/check-adr-symbol-anchors.mjs",
          "exit": 0,
          "verdict": "check-adr-symbol-anchors: 2121 anchors across 140 records resolve — 302 symbol, 1792 file-level, 27 cross-repo, 6 exempt, 3 continuation"
        },
        {
          "family": "check:adr-symbol-anchors (self-test)",
          "command": "node scripts/check-adr-symbol-anchors.mjs --self-test",
          "exit": 0,
          "verdict": "self-test clean"
        },
        {
          "family": "check:adr-anchors",
          "command": "pnpm check:adr-anchors",
          "exit": 0,
          "verdict": "check-adr-anchors --self-test: 106 assertions over the real auditAdrDirectory() / auditCitedNumbers() / assembleAnchors() paths"
        },
        {
          "family": "check:doc-authoring",
          "command": "pnpm check:doc-authoring",
          "exit": 0,
          "verdict": "doc authoring guard: 44 published skill files clean; 16120 customer-facing string(s) across 1031 spec sources clean; sibling-package prose ids hold the baseline"
        },
        {
          "family": "check:nul-bytes",
          "command": "pnpm check:nul-bytes",
          "exit": 0,
          "verdict": "check-nul-bytes: OK (scanned 9205 text file(s) — 9205 tracked, 0 untracked-not-ignored; skipped 7 binary; no raw ASCII control bytes)"
        },
        {
          "family": "check:pm-governed-merges",
          "command": "pnpm check:pm-governed-merges",
          "exit": 0,
          "verdict": "check-governed-merges --self-test: 441 assertions; live: the real generator declared 9 output(s) and certified this tree"
        },
        {
          "family": "check:pm-prior-rulings",
          "command": "pnpm check:pm-prior-rulings",
          "exit": 0,
          "verdict": "check-prior-rulings self-test: 155 cases pass"
        },
        {
          "family": "check:doc-formula-expressions",
          "command": "pnpm --filter @objectstack/lint run check:doc-formula-expressions",
          "exit": 0,
          "verdict": "FIRST run exited 3 = PREREQUISITE NOT MET (unbuilt @objectstack/formula and @objectstack/lint) — read as NOT MEASURED, ⛔ not a finding. Built both under the shared verify lock, re-ran: exit 0."
        },
        {
          "family": "check:ci-filter-parity",
          "command": "node scripts/check-ci-filter-parity.mjs",
          "exit": 0,
          "verdict": "clean"
        },
        {
          "family": "check:closing-keyword-parity",
          "command": "node scripts/check-closing-keyword-parity.mjs",
          "exit": 0,
          "verdict": "clean"
        },
        {
          "family": "check:closing-keyword-parity (self-test)",
          "command": "node scripts/check-closing-keyword-parity.mjs --self-test",
          "exit": 0,
          "verdict": "clean"
        },
        {
          "family": "check:comment-mask-corpus",
          "command": "node scripts/check-comment-mask-corpus.mjs",
          "exit": 0,
          "verdict": "clean"
        },
        {
          "family": "check:cross-package-test-inputs",
          "command": "pnpm check:cross-package-test-inputs",
          "exit": 0,
          "verdict": "clean"
        },
        {
          "family": "check:driver-memory-census",
          "command": "pnpm check:driver-memory-census",
          "exit": 0,
          "verdict": "clean"
        },
        {
          "family": "check:gitlink-declared",
          "command": "pnpm check:gitlink-declared",
          "exit": 0,
          "verdict": "clean"
        },
        {
          "family": "check:refd-timer-probe",
          "command": "pnpm check:refd-timer-probe",
          "exit": 0,
          "verdict": "clean"
        },
        {
          "family": "check:watch-hint-literal",
          "command": "pnpm check:watch-hint-literal",
          "exit": 0,
          "verdict": "clean"
        }
      ],
      "gate_derivation": "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands (no paths) — stderr line 1: 'gate list derived from the tree of objectstack-ai/objectstack at commit 7e1b048a1 (/home/user/objectstack-issue-19408)'; change set '1 path(s) vs merge base 7e1b048a1, changed lines 8 (+8/-0)'. 19 commands derived; all 19 run. Reconciled with --ran (each line recorded as 'command :: exit N'): '✓ dispatch-gates --ran: 19 derived famil(ies) accounted for — 19 run, 0 NOT-MEASURED (a DERIVED zero — all 19 recorded an exit code and none of them is 3)'. Clone is not shallow (git rev-parse --is-shallow-repository = false). The dispatch named 4 families; the derivation added 15, all run.",
      "not_measured": "Everything dispatch-gates prints OUTSIDE the derived 19 is CI's and is not claimed here: 56 artifact-roster families, 11 declared-wide-population families, 14 pending-changeset families, 1 path-scheduled CI job (Test Core shards), the 4 type-check lanes, and the 2 workflow-valued families. No package was touched, so there is no ① dependency-closure build and no ② per-package test/typecheck owed: docs/adr/ lives inside no package (measured below).",
      "governed_merges": "node scripts/pm/check-governed-merges.mjs --pr 19702 -> exit 3, verbatim: '⛔ GOVERNED — a human merge is the review record for this PR (#9495 regime).' / '⚖️ landing tier: H(人合) — the maintainer's hand, or an authorized APPROVED review (GOVERNED_APPROVERS) and then the owning seat lands it.' / 'docs/adr/** ×1 — architecture decision records'. Size: 8 changed line(s) (+8/-0) ≤ 5000. Expected reading, ⛔ not a failure. PR opened draft and left draft.",
      "changeset": "skip-changeset, measured not assumed: 70 package.json files in the tree declare files[]; 0 entries name docs/adr or escape their package root; 0 package roots contain docs/adr. The diff ships in no tarball. Label written through scripts/pm/label-write.mjs (POST + read-back): '④ MATCHES the target — labels size/xs, skip-changeset'. size/xs was set by another actor (the size labeler) and was left alone.",
      "tests": "Docs-only diff: no test suite or typecheck is owed (the edited file is inside no package — measured: 0 of 70 files[]-declaring packages contain docs/adr). The evidence is the 19 derived gate families above, each exit captured before any pipe (cmd > log 2>&1; EXIT=$?). One build was needed and went through the shared verify lock: OS_VERIFY_LOCK_SLOT=issue-19408 bash scripts/pm/os-verify-lock.sh -c 'pnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lint --concurrency=2' -> 'os-verify-lock: VERDICT command-exit 0 · held the lock 240s (4m00s) · waited 0s'. Hand sweep beyond the gate: grep -naP '[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]' on the edited file — no match. PR body pre-checked offline against the closing-keyword gate (PR_BODY=... node scripts/check-partof-closing-keyword.mjs -> exit 0) before the POST. No ablation or reverse-verification applies: this diff adds prose to a record and asserts no new gate.",
      "mcp_calls": "0 — no MCP GitHub tool was called, read or write. Every GitHub read and write went through curl on the REST proxy with GITHUB_TOKEN, or through scripts/pm/label-write.mjs.",
      "api_writes": "3 REST writes + git push. REST: POST /repos/objectstack-ai/objectstack/pulls (HTTP 201, PR 19702, draft true); POST /repos/objectstack-ai/objectstack/issues/19702/labels (HTTP 200, via scripts/pm/label-write.mjs); POST /repos/objectstack-ai/objectstack/issues/19408/comments (this report). git push twice on the one budgeted line: the empty-branch write-route probe before any edit, then the single commit. ⛔ No PATCH of the PR body, no second claim comment, no assignee write, no card filed.",
      "deviations": [
        "The status-line amendment is spelled as an appended continuation line (new line 4) rather than an extension of line 3, so that every ADDED line stays under the dispatched 100-column ceiling while the dated line 3 stays byte-identical. ADR-0048's own Status line wraps across three physical lines, so this is house form; the clause opens with '·', the same inline separator ADR-0053's status line uses, so it reads correctly whether the renderer treats the soft break as a line break or as a space.",
        "check:doc-formula-expressions needed a build before it could judge anything (exit 3, PREREQUISITE NOT MET). Two packages were built under the shared verify lock rather than skipping the family.",
        "GitHub's body-byte mutation stripped the blank line before the PR footer and the trailing newline on POST; full read-back of the PR body shows every other byte identical to what was sent, and the session-URL footer survived verbatim."
      ],
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: none · Observation, ⛔ not filed (no class a/b/c): the card's downstream table is stale in the direction that strengthens it. It lists packages/cli/src/utils/collect-docs.ts (#19359) as repaired and skills/objectstack-ui/rules/pages.md (#19358) as open; on 7e1b048a1d BOTH are repaired and both cards read closed/completed — collect-docs.ts:38-44 declines the sentence by name, pages.md:340-341 reads 'hygiene, not uniqueness: two packages coexist on one bare name (ADR-0048 §3.4)'. So this ADR was the LAST carrier of the retired claim in the tree, not one of three. Recorded in the PR's Acceptance notes; neither file was touched."
      ]
    }

    Generated by Claude Code

  8. huangyiirene commented on Sep 22, 2026

    @huangyiirene
    Collaborator

    ACCEPT — domain:skills seat 1 (session_01Wnstp2kTth7sGXfr8fXypc, seat post #7623), 2026-09-22T09:48Z — PR #19702 at head 0cba6186d7dd67acca0b5695b728bf3291e34fc6 (round 0).

    Checklist, read against GitHub and the fetched head, not the report: draft, base main, body first line Fixes #19408; one file docs/adr/0046-package-docs-as-metadata.md (+8 / −0): line 4 appends 「· Superseded in part (2026-06-13, ADR-0048) — the bare-name overwrite premise; note at §3.2.」 (96 characters) under the byte-identical dated **Status** line, and §3.2 closes with a six-line blockquote (78–87 characters per line) citing ADR-0048 §1.2 / §3.4 / §3.3 — every claim in it read by this seat in ADR-0048 where the note says, and its last clause is the reading already landed in collect-docs.ts (#19359); the retired sentence stays in the file exactly once, annotated, ⛔ not rewritten — the form the card's Path: line and the lane's grading 5752868774 sanction. House form has precedent (ADR-0012 :3's inline · **Superseded by …**, ADR-0053 :3's 「Partly superseded」, ADR-0046's own §6.7 amendment blockquote). Dispatch constraints met: +8 of +8, every added line ≤ 100 characters, nothing outside the one file, H1 evidence given. Re-run by this seat on its own worktree at 0cba6186d: check-adr-links, check-adr-symbol-anchors, check:adr-anchors, check:doc-authoring, check:nul-bytes, check:pm-prior-rulings, check-closing-keyword-parity — all exit 0; check-governed-merges.mjs --pr 19702 exit 3 — GOVERNED, Tier H (docs/adr/** ×1, 8 lines); check-expected-skips --pr 19702 OK. CI at this head: 31 latest-per-name check runs, every one success or skipped. Contract review of record: PASS 5774341677 on the PR, rendered in-seat at the served tier (fable — the maintainer's word 5771798588, the constant on origin/main since PR #19684); check-clause2-carriers.mjs --pair 19702 exit 0 with C6-RECORD naming it. Report 5774268707 parses; mcp_calls 0; api_writes 3 REST + 2 pushes as listed; ⛔ no body PATCH by the dev; skip-changeset correct (docs/adr/** publishes nothing) and written through label-write.mjs with read-back.

    Deviations recorded, none blocking: the status clause is an appended line rather than an extension of line 3 (keeps the dated line byte-identical and every added line under the wrap — house form, ADR-0048's own status line wraps); a build ran for a docs-only diff to clear check:doc-formula-expressions' prerequisite (declared); GitHub's body-byte mutation on the POST /pulls (the blank line before the footer and the trailing newline), read back and reported. Out of scope, not filed: the card's downstream table is stale in the direction that strengthens it — both copies it names are repaired and closed on origin/main, so this ADR was the last carrier.

    Landing: Tier H — the PR stays draft for the maintainer's hand; ⛔ no ready, no queue, no auto-merge by the seat (landing-operations.md :28). The seat fills the body's 「席位意见」 in one PATCH after this comment. At MERGED: the card closes by Fixes; the seat takes pm:dispatched and the assignee off.


    Generated by Claude Code

  9. removed their assignment
    on Sep 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:skillsDomain lane — seat card indexed by label:pm:seatpriority:p3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions