Skip to content

docs(rest): correct the single-project fallback comment to the environments prefix - #16543

Merged
os-sales merged 1 commit into
mainfrom
claude/issue-15858-retired-projects-spelling-in-docblocks
Sep 7, 2026
Merged

docs(rest): correct the single-project fallback comment to the environments prefix#16543
os-sales merged 1 commit into
mainfrom
claude/issue-15858-retired-projects-spelling-in-docblocks

Conversation

@claude

@claude claude Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Refs #15858 (item 1) · Part of #15858 (item 1 of the two the card names).

#15858 stays open for item 2 — the reason is below, and it is a real fork, not an oversight.

What this changes

One line of prose in packages/rest/src/rest-server.ts, on step 3 of resolveRequestEnvironmentId:

-        //    (no `/projects/<id>` prefix, no hostname mapping, no header)
+        //    (no `/environments/<id>` prefix, no hostname mapping, no header)

ADR-0006 v4's second addendum (D2, executed 2026-08-28) renamed the scoped URL family to /environments/:environmentId with no alias and no dual-spelling interval, so the sentence named a prefix that no longer routes. content/docs/api/environment-routing.mdx says the same to callers: "there is no alias, so the old spelling does not resolve."

The placeholder spelling <id> is this file's own local convention, kept deliberately — the sibling comment on the scoped discovery route already writes /environments/<id>.

Prose only. The executable scoped-base construction in this file already spells /environments/:environmentId at 28 sites, and the measurement below shows the edit moves no shipped byte.

Item 2 is deliberately untouched

The card's other sentence — the 'platform' virtual-id docblock, which describes addressing the control plane "through the regular project URL shape (/projects/platform/...)" — is not edited here. Transliterating it to /environments/platform/... without first knowing whether that shape is still addressed at all would swap a known-stale sentence for one that may be equally stale while merely looking current, and a wrong reference that resolves is worse than one that dangles.

What this repository can answer, and does, is only half the fork. Measured at 7a5592f5a:

probe result
environmentId === 'platform' in rest-server.ts 3 — including if (environmentId === 'platform') return this.protocol;, exactly the control-plane short-circuit the docblock describes
guards spelled !== 'platform' in the same file 8
control: environmentId === 'zzz-absent-virtual-id', same file, same predicate family 0 (exit 1) — the predicate discriminates
any /platform/ URL-shaped literal in any package src 1, and it is the stale docblock sentence itself — no route literal mounts it

There is also a live pin: packages/rest/src/rest-env-resolution.test.ts asserts "keeps the 'platform' guard — the reserved id is never handed to getOrCreate", driving it through params: { environmentId: 'platform' }, i.e. through a route parameter.

The mechanism is live in this repo and pinned. ⛔ That does not settle the fork: whether any host still addresses it — the cloud repository's wiring — is out of this tree's reach. #15861 is the already-open reading request to the cloud seat on this exact ADR-0006 boundary and is the natural place for the answer to arrive.

Verification

  • Gatesnode scripts/pm/dispatch-gates.mjs --commands with no paths, letting it derive the change set from the merge base. Its own Reconciliation line reads 42 families, --commands printed exactly 42, and 41 exited 0.
  • The one exception is pnpm check:dual-build-cjs-loads, which exited 3 — PREREQUISITE NOT MET ("this gate reads built output, and some package has no dist/"). ⛔ That is NOT MEASURED, not a pass. It is declared to CI, which builds the whole tree. See the byte-identity measurement below for why its verdict here cannot differ from its verdict on main.
  • The Artifact rosters block (38 families) was run separately from the 42; its silence is a fact about a list, not a clearance.
  • pnpm --filter @objectstack/rest typecheck — green (tsc --noEmit plus check:test-typecheck: 0 files / 0 errors).
  • pnpm --filter @objectstack/rest exec vitest run --maxWorkers=2 src/rest-env-resolution.test.ts20 passed (20), the suite covering the very method this comment sits in.
  • check-system-context-censusgreen with no repair. That file anchors into rest-server.ts by absolute line number immediately below the edited line, so the edit was made line-count neutral on purpose: the file is 13442 lines before and after, and no anchor moved. The gate's --fix was never needed.

Why there is no changeset

Measured, not asserted. @objectstack/rest publishes ["dist","README.md","CHANGELOG.md"], so the question is whether this comment reaches dist. It does not, and the same file supplies both controls:

probe dist/index.js dist/index.cjs .d.ts / .d.cts
the edited sentence, and looser fragments of it 0 0 0
control — an adjacent, unedited // comment in the same method 0 0
control — // comment lines surviving into the bundle at all 4234 4236
control — projects/platform, a block comment in this same file 1
control — resolveRequestEnvironmentId, a runtime identifier from this module 16

esbuild keeps leading block comments and drops line comments inside function bodies, so this file has one comment that ships and one that does not — and the edited one is the one that does not. sourcesContent is absent from the sourcemap, so the source text does not ship there either.

The decisive check: rebuilding the package with only this file reverted to 7a5592f5a produces byte-identical output, all four published artifacts:

23a981433a1deea8  dist/index.js      5d61def843665906  dist/index.cjs
70eea005fc224e62  dist/index.d.ts    70eea005fc224e62  dist/index.d.cts

The mutation was proven to land on disk first (blob d2957e407… vs 5153c8e4d…, old-spelling count 1, new-spelling count 0), and the restore leg was verified by blob hash and an empty git diff HEAD, then rebuilt.

⇒ This diff publishes nothing, which is the skip-changeset criterion exactly. The label is applied.

验收备注

Filed, not repaired here — #16538. While locating the two sentences, a third site in this same file turned out to carry the same retired ADR-0006 spelling in executable code, which corrects a premise of this family: the card states, and triage endorses, "This is prose only." That is true of the two sentences; it is not true of the file.

registerDiscoveryEndpoints has two sibling unscopedBase computations eleven lines apart. The MCP one strips /\/(environments|projects)\/:environmentId$/; the auth one strips only /\/projects\/:environmentId$/. Since isScoped is true only when the base contains /environments/:environmentId, the auth regex can never match on the branch it guards, so a scoped discovery document advertises routes.auth with the scope still attached and an unsubstituted :environmentId — while the comment two lines above it states "Auth is a control-plane concern, so use the unscoped base." All three existing pins on routes.auth assert the unscoped base, where the branch never runs, which is why it is green today.

It is filed rather than repaired here because it is executable and changes an advertised route value, so it needs a behavioural test — a new verification surface outside this card's prose-only scope, and repairing it here would falsify the very classification this PR is graded under.

Noted, not filed: nothing else.

Docs-drift rows — verified, ⛔ no docs edited

docs-drift-check listed six hand-written pages plus one release-owned page against this diff. Verdict: CLEAN — none of the seven states anything this diff falsifies, and two rows are demonstrably spurious. ⛔ No content/docs/** file was edited, and content/docs/releases/v17.mdx was read only.

The diff corrects a retired /projects/ URL spelling to the current one. The direct test is therefore whether any listed page states that retired spelling:

page /projects/ resolveRequestEnvironmentId control: /api/v1 control: the word "project"
api/client-sdk.mdx 0 0 3 6
api/metadata-api.mdx 0 0 1 0
api/plugin-endpoints.mdx 0 0 2 0
kernel/contracts/metadata-service.mdx 0 0 8 6
kernel/services-checklist.mdx 0 0 21 0
protocol/objectui/concept.mdx 0 0 2 1
releases/v17.mdx (read-only) 0 0 45 44

The control discriminates: every page yields /api/v1 hits and most yield the word "project", so the grep reads the files and finds URL prose — and still returns a real zero for the retired segment.

Two spurious rows, named:

  1. resolveRequestEnvironmentId — the one anchor genuinely tied to the changed line — appears on zero of the seven pages. The row that named it is spurious on every page.
  2. content/docs/protocol/objectui/concept.mdx scores zero on all four anchors (getView, meta.getView, /view/:object/:type, resolveRequestEnvironmentId). Nothing connects it to this diff at all.

The surviving anchors are about a different surface that merely co-inhabits this 13,442-line file: client.meta.getView('account', 'list'), MetadataService.getView, and GET /ui/view/:object/:type are the view metadata surface. The changed line is about environment resolution for bare /api/v1/data/... URLs. Same file, unrelated concerns.

client-sdk.mdx does name X-Environment-Id (step 2 of the very chain this comment documents) — already in the current spelling, so it is not falsified either.

The structural argument stands behind all of it: this diff changes zero emitted bytes (measured above), so it cannot falsify documented behaviour by construction.

Grading

  • Clause ②: no — graded from the delivered diff. One comment line, no routing, contract or metadata change; the byte-identity measurement above is the evidence. ⇒ no needs:contract-review.
  • Draft, targeting main. ⛔ Not flipped ready, ⛔ not enqueued.

🤖 Generated with Claude Code

https://claude.ai/code/session_01YFY46JydE1gMxQG1TqBcMZ


Generated by Claude Code

…nments prefix

The comment on `resolveRequestEnvironmentId`'s step 3 described the bare
`/api/v1/data/...` fallback as taking effect when there is "no `/projects/<id>`
prefix". ADR-0006 v4's second addendum (D2) renamed that scoped URL family to
`/environments/:environmentId` with no alias and no dual-spelling interval, so
the sentence names a prefix that no longer resolves.

Prose only: the executable scoped-base construction in this file already spells
`/environments/:environmentId` at 28 sites. The edit is a same-line substitution
and leaves the file's line count unchanged, so the absolute line anchors that
`content/docs/permissions/system-context.mdx` holds into this file do not move.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YFY46JydE1gMxQG1TqBcMZ
@claude claude Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 7, 2026
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/rest, touching 4 documentable anchor(s).

6 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/api/client-sdk.mdx (via getView (sdk, the bare tail of client method meta.getView, bound to GET /api/v1/ui/view/:object/:type), meta.getView (sdk, the route ledger binds it to GET /api/v1/ui/view/:object/:type, selected by route anchor /view/:object/:type))
  • content/docs/api/metadata-api.mdx (via /view/:object/:type (route, bridged from symbol resolveRequestEnvironmentId — its route source's handler names it))
  • content/docs/api/plugin-endpoints.mdx (via /view/:object/:type (route, bridged from symbol resolveRequestEnvironmentId — its route source's handler names it))
  • content/docs/kernel/contracts/metadata-service.mdx (via getView (sdk, the bare tail of client method meta.getView, bound to GET /api/v1/ui/view/:object/:type))
  • content/docs/kernel/services-checklist.mdx (via getView (sdk, the bare tail of client method meta.getView, bound to GET /api/v1/ui/view/:object/:type), /view/:object/:type (route, bridged from symbol resolveRequestEnvironmentId — its route source's handler names it))
  • content/docs/protocol/objectui/concept.mdx (via /view/:object/:type (route, bridged from symbol resolveRequestEnvironmentId — its route source's handler names it))

1 release-owned page(s) also name something this change touched. These are read-only:

  • content/docs/releases/v17.mdx (via getView (sdk, the bare tail of client method meta.getView, bound to GET /api/v1/ui/view/:object/:type), meta.getView (sdk, the route ledger binds it to GET /api/v1/ui/view/:object/:type, selected by route anchor /view/:object/:type), /view/:object/:type (route, bridged from symbol resolveRequestEnvironmentId — its route source's handler names it))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see
  • the SDK route bridge reached 61 of 219 client-bound route-ledger rows — the other 158 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 158: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 56 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 102 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • 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 — 13 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 70e77ec3b566b92d7c6551637d6bc746fb840bb6packageMentionDocs.

Which tree this was computed on

This run read content/docs from 258527c9b17a62869721cc5f66d1ab6525f66335 — the merge of head 83e61be2987efb89e789688152329015bfd46774 into base 70e77ec3b566b92d7c6551637d6bc746fb840bb6, 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 258527c9b17a62869721cc5f66d1ab6525f66335 && git checkout 258527c9b17a62869721cc5f66d1ab6525f66335
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 70e77ec3b566b92d7c6551637d6bc746fb840bb6 83e61be2987efb89e789688152329015bfd46774 && git checkout -B drift-repro 70e77ec3b566b92d7c6551637d6bc746fb840bb6 && git merge --no-ff 83e61be2987efb89e789688152329015bfd46774

node scripts/docs-audit/affected-docs.mjs --json 70e77ec3b566b92d7c6551637d6bc746fb840bb6

⚠️ 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 70e77ec3b566b92d7c6551637d6bc746fb840bb6 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

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

Labels

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

2 participants