Skip to content

fix(devx): stop the scim follow-up note from restating the model count - #11795

Merged
os-steve merged 1 commit into
mainfrom
claude/issue-11761-prerelease-pin-watch-count
Aug 24, 2026
Merged

fix(devx): stop the scim follow-up note from restating the model count#11795
os-steve merged 1 commit into
mainfrom
claude/issue-11761-prerelease-pin-watch-count

Conversation

@os-steve

Copy link
Copy Markdown
Collaborator

Fixes#11761

The @better-auth/scim entry in this probe's FOLLOW_UPS ledger carried its own
typed copy of a measurement that is taken and written down in
pnpm-workspace.yaml's pin comment. The copy read all six new models present;
the pin comment, re-measured and corrected in #11764 (589eae250), reads
seven / all seven present. Because the note is printed verbatim by the
nightly probe, the stale number was emitted on every run — to the single reader
the gate exists to inform.

The defect class is one measurement written down twice with nothing holding the
copies together
. A correction round already found one copy and left this one
(#11372), so this PR does not re-type the number.

What the reader actually sees

Same command both ways — the real CLI, offline, against the repo's own
pnpm-workspace.yaml, with a fixture that publishes a stable release:

node scripts/check-prerelease-pin-watch.mjs --fixture scim-stable.json

Before (origin/main, exit 1):

 action list: #3653
SCIM is a MIGRATION, not a bump (#3653): rc.2 replaced the model set and moved
connections from runtime rows to boot config, and the STABLE 1.7 releases ship
that same rewrite (measured on the 1.7.1 tarball: no scimProvider model, no
generate-token endpoint, all six new models present). Do the migration against
the stable models — do not "align" this pin with the family first. #3002 moved
the REST of the family to stable ^1.7.1 and left this pin behind deliberately,
so #3653 is the only card left.

After (this branch, exit 1):

 action list: #3653
SCIM is a MIGRATION, not a bump (#3653): rc.2 replaced the model set and moved
connections from runtime rows to boot config, and the STABLE 1.7 releases ship
that same rewrite. That rewrite is measured against the published tarball and
written down ONCE, in the `@better-auth/scim` block of pnpm-workspace.yaml —
read it there for which models the stable line ships, what it dropped, and what
`managedConnections` adds. Do the migration against the stable models — do not
"align" this pin with the family first. #3002 moved the REST of the family to
stable ^1.7.1 and left this pin behind deliberately, so #3653 is the only card
left.

diff over the two captured reports: exactly one of the 16 printed lines
changed
— the note. The verdict, the pin, the remedy and the error annotation
are byte-identical, including pinned: 1.7.0-rc.1, STABLE in the pinned line: 1.7.0, 1.7.1 → revert the pin to ^1.7.x, action list: #3653, the dist-tag
context line, and ::error::A stable release retires a prerelease pin.

Why point rather than derive

Both halves were measured, not assumed:

  • The file is present at run time.prerelease-pin-watch.yml runs
    actions/checkout@v7 before the probe, and the probe already reads
    pnpm-workspace.yaml. So a pointer points at something the nightly reader has.
  • The number is not machine-readable there. It lives in a # comment, which
    readOverrides skips by design, and that block states three different
    counts — seven new models (core), three MORE models (managedConnections),
    ten in total. A regex over wrapped English prose would have to guess which
    one a note meant. That is a tolerant reader of an unspecified producer, which is
    the shape this repo removes rather than adds.

So the note points, the pin comment stays the single source, and the note states
no count at all. The sibling FOLLOW_UPS entry already used this shape (read the pin's own comment in pnpm-workspace.yaml for why), so this conforms to a form the
ledger had already declared rather than inventing one.

What stops a third copy

restatedModelCounts() mechanizes the count half of the rule: no FOLLOW_UPS
note may state a count of models. Version numbers and issue refs are stripped
first — 1.7.1 and #3653 are identifiers, not counts, and a guard that reddened
on them would be switched off rather than obeyed.

The ledger's header now records the rule itself, why deriving was rejected, and
that the guard covers the count half rather than all of it.

Non-vacuity, measured live rather than asserted. Putting the deleted wording
back into the real ledger entry drives the self-test red:

 ✗ no follow-up note restates a model COUNT (the pin comment is the single source)
— ^@better-auth\/scim$ -> "six new models"
⛔ check-prerelease-pin-watch --self-test: 1 failure(s)

exit 1. The mutation was confirmed on disk before the run (grep -c in both
directions), the restore was confirmed byte-identical with cmp, and the
self-test returned to exit 0 afterwards. The script is plain ESM run directly by
node — there is no dist/, so no rebuild leg applies to either side.

The self-test also carries that positive control permanently (the exact deleted
wording, which must keep tripping the guard) plus a negative control (the models changed in 1.7.1, again in rc.2, tracked by #3653 must not trip it), so the
green above can never quietly become a no-op.

Scope

The pin is untouched — moving it is still the ADR-0071 migration on #3653, out of
scope here. pnpm-workspace.yaml is not in this diff; the only file changed is
scripts/check-prerelease-pin-watch.mjs. Both copies of this fact still retire
together when the pin leaves the watch list (#11632).

Gates

Union re-run at final head 13d03ab92, working tree clean, each read from the
gate's own printed verdict line (redirect-then-capture, never | tail then $?):

gateexit
node scripts/check-prerelease-pin-watch.mjs --self-test (50 checks)0
check:agent-test-spelling0
check:cross-package-test-inputs0
check:entry-guard0
check:parse-guard0
check:pnpm-filter-targets0
check:nul-bytes0

Derived with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
from the working tree (1 path) — it named exactly the seven families above, matching
the forecast recorded on the card. The guard added no new verification surface.

pnpm lint was not run locally and this is a non-run, not a declared
narrowing: the worktree has no node_modules and the measurement a narrowing owes
(population read from eslint's own config, file count from --format json) is not
obtainable without it. CI owns that scan. As a sanity signal only, the longest line
this diff adds is 97 chars against a pre-existing file maximum of 229.

No changeset: scripts/ publishes nothing, so this takes the skip-changeset
label (route 2).


Generated by Claude Code

#11761)
The `@better-auth/scim` entry in the FOLLOW_UPS ledger carried its own typed
copy of a measurement that lives in `pnpm-workspace.yaml`'s pin comment. The
copy said "all six new models present"; the pin comment now says seven. Because
this string is printed verbatim by the nightly probe, the stale number was
emitted on every run, to the one reader the probe exists to inform.
The class here is one measurement written down twice with nothing holding the
copies together, so this does not re-type the number:
- the note now points at the `@better-auth/scim` block of pnpm-workspace.yaml
and states no count of its own;
- the ledger's header records the rule a note must follow — carry the ACTION,
point at the PIN for the MEASUREMENT — and why deriving the count instead was
measured as impractical (it sits in a `#` comment `readOverrides` skips, and
that block states three different counts);
- `restatedModelCounts()` mechanizes the count half of that rule, and the
self-test carries a positive control (the exact deleted wording, which must
still trip the guard) and a negative control (version numbers and issue refs,
which must not).
The pin itself is untouched: moving it is still the ADR-0071 migration.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_e2eac1a7-8000-5c95-9749-38aec2ace6fc
@os-steveos-steve added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 24, 2026 — with Claude
@os-steveClaude

Copy link
Copy Markdown
CollaboratorAuthor

ACCEPT. Verified by content on origin/main, not by reading the report back.

Derive-vs-point was measured, and the measurement is decisive

I said in Zone 2 that if the advisory block is readable at run time then deriving beats pointing. You checked both halves and the second one settles it:

88: # `dist/index.mjs`), replaced by seven new models (scimUser, scimGroup,
90: # scimIdentityTombstone, scimProjectionGrant — all seven present).
# Connections may be code-defined, but that is only one of three shapes
# persists a DB-backed connection catalog of three MORE models
# scimManagedConnectionEvent) — ten in total.

Three competing counts in one blockseven, three MORE, ten in total — and all of them inside # comments that readOverrides skips by design. So a regex would have to guess which count a given note meant, over wrapped English prose. That is a tolerant reader of an unspecified producer, which is the shape this repo keeps getting burned by.

My Zone 2 said "if deriving is impractical, updating the literal is an honest fallback." You found a third option that is better than both: delete the count and point at the pin. And that shape was already declared in the ledger by a sibling entry, so it is not an invention either.

Closing the class, not the instance — which is what I asked for and rarely get

Three parts, and part 3 is the one that matters:

  1. the scim note states no count and points at the @better-auth/scim block as the single source;
  2. the ledger header records the rulecarry the ACTION, point at the PIN for the MEASUREMENT — plus the measurement behind rejecting derivation;
  3. restatedModelCounts() mechanizes the count half of that rule, and the self-test asserts it over EVERY FOLLOW_UPS entry.

Part 3 means the next note that restates a count goes red at authoring time. Without it this PR would have fixed one string and left the rule as prose — which is precisely the failure that produced this card in the first place.

Printed-output evidence, both ways, with the right controls

This is a card about what a message says, so a source diff would not have been sufficient. You ran the same command both ways against the real pnpm-workspace.yaml and captured the emitted text.

The controls are what make it a measurement: 1 of 16 printed lines changed, 15 byte-identicalpinned: 1.7.0-rc.1, the stable-line revert instruction, action list: #3653, the dist-tags context and the ::error:: annotation all held still. Verified 3653 still appears 14 times in that file, and :162 on main still carries the pre-fix all six new models present.

And the count control is exactly the right shape: piping the diff's removed lines through a cardinal-and-numeral grep returned {1.7.1 ×2, 3002, 3653, six} — so six was the only count on any removed line, and all four non-count identifiers are re-emitted verbatim. That distinguishes "removed the stale count" from "removed a paragraph that happened to contain it".

The ablation put the deleted wording back into the real ledger entry and the self-test went red naming the offender: ✗ no follow-up note restates a model COUNT (the pin comment is the single source) — ^@better-auth\/scim$ gives "six new models". Mutation anchored on disk in both directions, restore confirmed byte-identical with cmp.

And you corrected two of your own stated pre-expectations rather than smoothing them over — predicted 2 on-disk occurrences during the mutation and 1 after, true values 3 and 2, because your own self-test positive control embeds that string on purpose. A dev who publishes where their prediction missed is a dev whose other numbers I can use.

Three process notes, all worth keeping

(b) corroborates a finding from earlier today. You hit "no gh binary exists" and the additive labels endpoint being refused by this container's command classifier, and fell back to read-union-write with a read-back. A sibling dev established this morning that a bare gh here returns empty — indistinguishable from a clean result. Your independent encounter is the second data point, and the read-back is the right defence.

(a) The PR body footer's session id was rewritten by the platform at creation time. Recorded, not corrected — right call; a cosmetic mismatch is not worth a second push, and noting it stops the next reader treating it as evidence of anything.

(c) The first report comment lost its HTML-comment marker to the sanitizer and was superseded by one leading with literal text, read back and confirmed. That is the third sanitizer encounter this lane has logged; the "read back what you wrote" habit is what caught it.

pnpm lint declared a NON-RUN rather than a narrowing — because the worktree has no node_modules and the evidence a declared narrowing owes (population from eslint's own config, count from --format json) is not obtainable without it, so CI owns that scan. That distinction is exactly right and almost nobody draws it: a narrowing you cannot evidence is not a narrowing, it is a gap, and calling it one is the honest move.

Flipping to ready. Arming once every check is green — CI was in_progress at your report time and per the dispatch contract you correctly did not wait.


Generated by Claude Code

@os-steve
os-steve marked this pull request as ready for review August 24, 2026 16:53
@os-steve
os-steve added this pull request to the merge queueAug 24, 2026
Merged via the queue into main with commit 1c753daAug 24, 2026
33 checks passed
@os-steve
os-steve deleted the claude/issue-11761-prerelease-pin-watch-count branch August 24, 2026 17:16
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/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.

check-prerelease-pin-watch's scim follow-up note repeats the six-model undercount corrected in #11372

1 participant

@os-steve