Skip to content

docs(cli): the ⛔ notes over ORGANIZATIONS_RUNTIME_PKG state the reason that survives the resolver hop - #12636

Merged
os-litant merged 1 commit into
mainfrom
claude/issue-12579-organizations-pkg-note-scope
Aug 27, 2026
Merged

docs(cli): the ⛔ notes over ORGANIZATIONS_RUNTIME_PKG state the reason that survives the resolver hop#12636
os-litant merged 1 commit into
mainfrom
claude/issue-12579-organizations-pkg-note-scope

Conversation

@os-litant

Copy link
Copy Markdown
Collaborator

Part of #12579 — fork (a), the note repair. Comment-only.

⛔ Deliberately not a closing keyword. The dispatch asked for one; fork (b) — actually
single-sourcing the spelling — is maintainer-facing and is NOT in this diff, and the four
docblocks rewritten here now point at #12579 as the place that decision is open. Closing the
card would leave four notes citing a closed issue and drop the open half out of every
is:open filter. Flip it to a closing keyword in one edit if the lane wants the card closed
anyway; that direction is cheap and merging the other one is not.

What was wrong

Four docblocks carried the same explanation for the same ⛔: that
Serve.ORGANIZATIONS_RUNTIME_PKG must stay a string literal in serve.ts because the
host-anchoring sweep in serve-cluster-host-resolution.test.ts resolves the organizations
import() through that static and, quoting the spelling test, "needs the literal in that
file, or the load drops out of the host-anchoring sweep silently"
.

That was true, and measured true — #12492 attempted exactly that rewrite and the sweep's
named vacuity guard refused it by name. It stopped being true at 1ca763b60 (#12533,
PR #12582), which taught
resolveIdentifier() to follow an import alias into a sibling module of the same package.

A true prohibition carrying a false explanation is worse than no note: the next author reads
it as arbitrary and steps over it.

⚠️ The census in the card is short by one — there were FOUR copies, not three

Re-derived on origin/main @ 0043c9224 by grepping the reason's fingerprints
(drops out of the host-anchoring sweep, string LITERAL, re-export of, silent-vacuity,
one more hop / one further hop, LITERAL IN THAT FILE), each reverse-checked against
ORGANIZATIONS_RUNTIME_PKG, a term known present in all of these files:

#filethe quoted phrase that carried the dead reasonin the card?
1packages/cli/src/commands/serve.ts"This MUST stay a string LITERAL in this file""drops OUT of the swept population rather than failing inside it"yes — the cited authority
2packages/cli/src/utils/tenancy-posture-hints.ts"resolves the organizations load site through that static to a LITERAL IN THAT FILE"yes
3packages/cli/src/commands/serve-organizations-message-spelling.test.ts"needs the literal in that file, or the load drops out of the host-anchoring sweep silently"yes
4packages/cli/src/commands/doctor-organizations-message-spelling.test.ts"which must stay a string LITERAL in serve.ts or the host-anchoring sweep … can no longer resolve which package that command's import() names"NO — found by measurement

Site 4 is the same defect, one file further along the same citation chain, and repairing three
of four would have reproduced exactly the failure ruling ① exists to refuse. It is in this diff.

Nothing else in the tree carries the reason. serve-cluster-host-resolution.test.ts says
"deliberately a duplicated LITERAL today" and "single-sourcing a spelling silently empties
the sweep"
— both still true (the first is a fact about today, the second a counterfactual
about deleting the hop), so that file is untouched.

What each note says now

Each site records three things instead of one: the constraint as it stood, the commit that
retired it, and what actually survives. The dead reason is stated as history rather than
deleted
— a reader who meets neither half re-derives it from the duplication and puts the
⛔ back.

⚠️ Ruling ③ — tenancy-posture-hints.ts's ⛔ read on its own terms: still valid as written

The ⛔ there is "Do NOT close the gap by importing Serve.ORGANIZATIONS_RUNTIME_PKG here
instead"
, and its reason is "this module is read by os doctor, and a diagnostic command
taking a dependency on a serve command's export in order to spell a package name is a worse
coupling than the duplication it removes (#12464's ruling, unchanged)"
. That is a
coupling-direction ruling. It has nothing to do with the sweep, the hop does not touch it, and
its wording does not imply the dead reason. It is kept verbatim — including the
connective "instead", whose referent (the paragraph above it, about ending the duplication
for real) is preserved rather than removed.

What was stale in that same docblock is the two paragraphs around it: the ⚠️ one carrying the
sweep reason, and "an edit to a file #12492 does not own, and which was in flight elsewhere
when this landed"
— the hop landed, so that clause is now false too. Both repaired.

⭐ Ruling ⑤ — the reason that survives, measured rather than assumed

Does any reason remain for the literal to be in serve.ts specifically? Measured: no.

  • The sweep is the only thing in the tree that reads serve.ts's SOURCE for a package
    spelling. Everything else that reads this value reads the value:
    test/serve-capability-vocabulary.test.ts (roster key), site 8 of
    serve-organizations-message-spelling.test.ts (equality), doctor's leg (ii). All three are
    alias-safe.
  • The other repo scripts that name serve.tscheck-route-envelope.mjs,
    check-wildcard-fallthrough.mjs, cross-package-test-inputs.mjs, slot-lookup-baseline.json
    — read it for other populations, none for a package spelling.
  • The hop is pinned against the real target, not inferred from resolver code: the sweep's case
    "resolves an alias to a literal in a REAL sibling module of packages/cli" reads the live
    packages/cli/src/utils/tenancy-posture-hints.ts through serve.ts's own scan context, and
    a sibling case pins "the shape the refactor writes".
  • Precedent in the same class: Serve.ALWAYS_ON_CAPABILITIES is already assigned from an
    imported const, so a static sourced from an import is not itself the problem.

⇒ the honest answer, and what the notes now say: the only stated reason is false, and fork
(b) is the open question.
Not "⛔ don't, because someone decided so" — that is the
arbitrary-prohibition failure this card exists to end. Two constraints are recorded as
outliving the decision either way: the static keeps its NAME (the roster pins address
Serve.ORGANIZATIONS_RUNTIME_PKG; only a spelling may move), and the gap is never closed in
the other direction.

⛔ Site 8 stays

Untouched. While there are two declarations the pin has a subject; the note now says so
explicitly and says deleting it belongs to the reversal, not to this repair.

⛔ Not taken here

The reversal itself. PR #12532
shipped the duplication deliberately with reasoning at both ends, so ending it is a
maintainer-facing call. It is now easier to decide, which was the point of doing this first.

Verification — all on 40ce969b1, the final commit

Proof the diff is comment-only. Both blobs of all four files transpiled with
removeComments: true and the emitted program hashed (sha256, first 16 hex):

EQUAL c235255fc3dcae14 packages/cli/src/commands/serve.ts (source 287271 -> 288823 bytes, emitted 108218)
EQUAL b531434010a7895e packages/cli/src/utils/tenancy-posture-hints.ts (source 7436 -> 7703, emitted 433)
EQUAL 78e6b4188f5f16b5 .../serve-organizations-message-spelling.test.ts (source 15781 -> 16254, emitted 8097)
EQUAL 2520e192d47ecc9a .../doctor-organizations-message-spelling.test.ts (source 13557 -> 13814, emitted 5951)

The instrument is reverse-checked in both directions, or the equality means nothing —
in memory, against git blobs, so the working tree was never mutated:

code token changed (the declaration's literal) -> hash MOVED c235255fc3dcae14 -> eec8fedfe9972537
comment token changed (one repaired sentence) -> hash DID NOT MOVE (removeComments really is on)

Testspnpm --filter @objectstack/cli exec vitest run --maxWorkers=2 over a declared
consumer set (the full packages/cli suite does not finish in this container's foreground
window; ⛔ narrowing declared, CI runs the farm):

Test Files 4 passed (4)
Tests 64 passed (64)

The four: serve-cluster-host-resolution.test.ts (the sweep — it reads BOTH edited source
files as text, so it is the one that could have gone red on a comment edit),
serve-organizations-message-spelling.test.ts, doctor-organizations-message-spelling.test.ts,
test/serve-capability-vocabulary.test.ts.

Typecheckpnpm --filter @objectstack/cli typecheck (tsc --noEmit) exit 0, and it is
not a vacuous green: tsc --noEmit --listFiles lists all four edited files (1 hit each of 1279).

Gates — dependency closure built first (pnpm --filter '@objectstack/cli^...' build,
exit 0). Families from node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
(16 matched + the test-file convention kind); exit codes captured before any pipe. All green,
quoting each gate's own verdict line:

  • check:nul-bytes"OK (scanned 6986 text file(s) … no raw ASCII control bytes)"
  • check:comment-mask-adoption"OK … 20 private comment-stripper(s) … all 20 recorded"
  • check:slot-lookup"slot-lookup ratchet holds: 107 unswept site(s) … baseline key set verified against 0043c92: no files added"
  • check:route-envelope, check:cross-package-test-inputs ("20 package(s) read outside themselves, all declared"), check:page-declaration-shape, check:published-files, check:test-source-alias, check:type-source-resolution, check-ci-filter-parity, check-plugin-teardown-shape, check:engine-double-contract, check:where-matcher, check:query-options-erasure ("none new … baseline key set verified against 0043c92"), check:type-check-coverage — all exit 0
  • pnpm lint (eslint . --no-inline-config) — the whole repo, exit 0 in 95s. ⛔ No
    narrowing was needed, so none is claimed.

Not run locally: check:i18n / check:i18n-coverage (need packages/cli itself built) and
check:type-check-debt --re-measure (needs the whole workspace closure built) — CI runs the
farm regardless.

Changeset

None, and skip-changeset applied instead. The rule used is AGENTS.md's: "Add a
changeset for feature work … Pure bug fixes do not require a changeset."
This is neither —
it is comment-only and, proven above, emits a byte-identical program, so it releases nothing.
The repo's changeset-check is path-agnostic, and an empty-frontmatter changeset is refused
for new files, so the label is the mechanism here.


Generated by Claude Code

… ORGANIZATIONS_RUNTIME_PKG
The organizations package spelling is declared twice inside `packages/cli`, and
four docblocks explained why with the same reason: the host-anchoring sweep in
`serve-cluster-host-resolution.test.ts` resolved the load through
`Serve.ORGANIZATIONS_RUNTIME_PKG` and needed a LITERAL in `serve.ts`, or the load
dropped out of the swept population silently.
That reason died at `1ca763b60` (#12533, PR #12582), which taught
`resolveIdentifier()` to follow an import alias into a sibling module of the same
package. A true prohibition carrying a false explanation is worse than no note:
the next author reads it as arbitrary and steps over it.
Comment-only. Each note now records the constraint, the commit that retired it,
and what actually survives — the duplication is CHECKED rather than required, and
whether to end it is an open maintainer-facing decision (#12579). The ⛔ in
`tenancy-posture-hints.ts` against importing `Serve.ORGANIZATIONS_RUNTIME_PKG`
into the shared module is untouched: its reason is #12464's coupling ruling, not
the sweep.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UjujZN219uFzBhSYfMykCd
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/cli, touching 1 documentable anchor(s). ⚠️1 changed file(s) yielded no anchor (packages/cli/src/utils/tenancy-posture-hints.ts), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

17 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: node scripts/docs-audit/affected-docs.mjs --json aa5994e17a47187c5a09bc82b1fc1163f250092b.

4 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails.

What this run could not see
  • 1 changed file(s) yielded no anchor (packages/cli/src/utils/tenancy-posture-hints.ts) — pages documenting those are invisible to this run
  • 1 name(s) were too generic to anchor anything (single lowercase words)
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 23 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json aa5994e17a47187c5a09bc82b1fc1163f250092bpackageMentionDocs.

Which tree this was computed on

This run read content/docs from fabc6041352099099eeeffd9f9d0163dd9872d68 — the merge of head 40ce969b1c0e6937a40aaffb1eb37fa0114c278b into base aa5994e17a47187c5a09bc82b1fc1163f250092b, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin fabc6041352099099eeeffd9f9d0163dd9872d68 && git checkout fabc6041352099099eeeffd9f9d0163dd9872d68
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin aa5994e17a47187c5a09bc82b1fc1163f250092b 40ce969b1c0e6937a40aaffb1eb37fa0114c278b && git checkout -B drift-repro aa5994e17a47187c5a09bc82b1fc1163f250092b && git merge --no-ff 40ce969b1c0e6937a40aaffb1eb37fa0114c278b
node scripts/docs-audit/affected-docs.mjs --json aa5994e17a47187c5a09bc82b1fc1163f250092b

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs aa5994e17a47187c5a09bc82b1fc1163f250092b → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@os-litantos-litant added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 27, 2026 — with Claude
@os-litant
os-litant marked this pull request as ready for review August 27, 2026 02:30
@os-litant
os-litant added this pull request to the merge queueAug 27, 2026
Merged via the queue into main with commit 616a457Aug 27, 2026
37 checks passed
@os-litant
os-litant deleted the claude/issue-12579-organizations-pkg-note-scope branch August 27, 2026 03:08
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gatetests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@os-litant