Skip to content

docs: retire the /graphql endpoint contract and its protocol-page residue - #10845

Merged
os-zhuang merged 2 commits into
mainfrom
claude/issue-10832-graphql-endpoint-contract-residue
Aug 21, 2026
Merged

docs: retire the /graphql endpoint contract and its protocol-page residue#10845
os-zhuang merged 2 commits into
mainfrom
claude/issue-10832-graphql-endpoint-contract-residue

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Fixes#10832

content/docs/api/plugin-endpoints.mdx handed the reader a method, a path and a payload
contract
for a route that is not mounted. That is the same defect class as #10710, one
level worse: the earlier card advertised a behaviour, this one advertised an endpoint.

The three facts, re-measured at this base (origin/main @ 5f2e54cc66)

Claim the pages makeWhat the tree says
POST /graphql is a servable routeNot mounted.packages/runtime/src/http-dispatcher.ts:2026 is the whole of it: // /graphql removed — GraphQL is not in the product plan (#2462 follow-on).
the platform serves it when a plugin is installedNo createGraphQLDomain anywhere in packages/*/src (0 hits); the fifteen domains at http-dispatcher.ts:556-574 do not include one.
src/api/ contains a GraphQL moduleZero graphql files in packages/spec/src/api/ (re-measured: 68 files, 0 named graphql). The one string hit is protocol.zod.ts:105, a docblock naming GraphQL as an industry design style — not a module.

Remove vs. rewrite — reasoned per site, not applied uniformly

packages/runtime/src/domains/unavailable.ts draws the line: 404 = "the route is not
there"; 501 = "the route is there, the implementation is not", and every 501 domain is
mounted unconditionally. /graphql is in neither state. So a construct whose job is to
enumerate servable routes must lose the entry entirely — rewriting it to "not available"
would still assert GraphQL was a surface worth listing. That is why #10710 deleted its
status-table row.

But the card is right that a mermaid node and a prose enumeration are not the same object,
so the sites split two ways:

Deleted — the construct itself asserts a surface that does not exist:

  • api/plugin-endpoints.mdx — the entire ### GraphQL (/graphql) — Plugin Required section
    and its POST /graphql method/path table, plus GraphQL from the frontmatter enumeration
    at :3. A table headed Method | Endpoint | Description is a promise that the row is callable.
  • api/declarative-endpoints.mdx/graphql from the exemplar list pointing at that
    catalog. The two survivors (/auth, /automation) are real mounted domains.
  • protocol/diagram.mdx — the GQL[GraphQL] node and both its edges (CLIENT --> GQL,
    GQL --> KERNEL). Deleting only the declaration would not have been enough: mermaid
    materialises an undeclared node from a dangling edge
    , so the box would still render, now
    without its label.
  • protocol/diagram.mdx — GraphQL from the src/api/ layer-table cell.

Rewritten — the surrounding claim is true; only the enumeration was wrong:

  • protocol/diagram.mdx:163 sequence label → HTTP Request (REST). The request is real; the
    parenthetical listed one transport too many.
  • protocol/kernel/lifecycle.mdx:70Start HTTP server. Phase 6 genuinely starts a server.
    ASCII box width preserved (all Phase-6 rows remain byte-identical in length to their siblings).
  • protocol/kernel/error-handling.mdx:10(HTTP, WebSocket). The error protocol does span
    the remaining surfaces.

Wording precedent followed: content/docs/permissions/authorization.mdx:53, which already
says /graphql now 404s and is left untouched.

Sibling PR

#10828's diff was read before editing (its three files: api/index.mdx,
data-modeling/fields.mdx, getting-started/quick-reference.mdx). It is disjoint by file
from all five files here — no overlap, no shared hunk. One correction to the dispatch premise:
that PR is still open and unmerged (base a7ea3289eb, the previous main), so its changes
are not in origin/main @ 5f2e54cc66; the three api/index.mdx GraphQL sites this branch
leaves alone are its work, not residue.

Gates

node scripts/pm/dispatch-gates.mjs derived 15 families from the changed paths — including
check:error-status-conformance, which the dispatch clue list did not name and which matches
only via protocol/kernel/error-handling.mdx. All 15 green at 451fe92153, the head of
this branch. Exit codes captured by redirect before any pipe, never off a tail; each log
verified to carry real output, so no pnpm --filter zero-match could pass as green. Their own
verdict lines:

  • check:doc-anchors"272 internal #fragment link(s) across 408 source file(s) all resolve to a real heading" — the deleted ### heading broke no anchor (independently confirmed: no #graphql fragment exists anywhere in content/).
  • check:error-status-conformance"every derivable runtime status is documented, and every documented status is reachable."
  • check:doc-authoring"389 files clean — no bare metadata literals."
  • check-doc-frontmatter"403 page(s) under content/docs parse with yaml@2.9.0"
  • check:docs-audit-scope"scope is in sync with content/docs/: 189 hand-written doc(s)"
  • check:docs-redirects"OK (apps/docs/redirects.mjs: 92 entries ...)"
  • check:doc-formula-expressions"self-test: 30 cases passed", "22 record-scoped formula example(s) ... judged clean"
  • check:role-word"OK, no new occurrences of the reserved word."
  • check:published-readme-links"165 outbound link(s) across 60 published markdown file(s)"
  • plus check:cross-package-test-inputs (×2, pnpm + direct node) and spec/check:{empty-state,liveness,strictness-ledger,variant-docs}.

check:quick-reference-counts is not in the derived set here — it keys on
quick-reference.mdx, which is #10828's file and not in this diff.

No ablation applies: this is a docs-only change with no guard under test.

No changeset — decided from the real file list, not defaulted. All five files are under
content/, which matches no glob in pnpm-workspace.yaml (packages/*, apps/*,
examples/*, …), and its only consumer apps/docs (@objectstack/docs) is private: true.
This publishes nothing ⇒ skip-changeset.

Deliberately not touched

  • packages/** — out of scope for this card. The code is correct; the docs were wrong.
  • content/docs/automation/webhooks.mdx:724 — a comparison to other ecosystems, not a claim
    about our surface.
  • content/docs/permissions/authorization.mdx:53 — already correct; it is the precedent.
  • content/docs/kernel/services-checklist.mdx:17,97 and getting-started/index.mdx:99
    already correct: they state GraphQL was removed.
  • content/docs/references/** — generated, filed against the generator during [finding] GraphQL residue outside #10583's site list: api/index.mdx still documents a /graphql route that the dispatcher removed #10710's triage.
  • skills/** and its mirror content/docs/ai/skills-reference.mdx:156 — GraphQL residue found
    in five places, but the source of truth is skills/**, which is governed/human-merge-only.
    Filed separately rather than patching the consumer page into disagreement with the skill it
    catalogs.

Generated by Claude Code


Generated by Claude Code

)
/graphql is not mounted. `packages/runtime/src/http-dispatcher.ts:2026` records
its removal, there is no `createGraphQLDomain` among the domains registered at
`http-dispatcher.ts:556-574`, and no `handleGraphQL` survives outside CHANGELOGs.
Remove-vs-rewrite follows the 404/501 distinction in
`packages/runtime/src/domains/unavailable.ts`: 404 = the route is not there;
501 = the route is there, the implementation is not. /graphql is in neither
state, so it belongs in neither row of a catalog of servable routes.
Deleted (the construct asserts a surface that does not exist):
- `api/plugin-endpoints.mdx` — the whole `### GraphQL (/graphql)` section and
its POST method/path table, plus GraphQL from the frontmatter enumeration.
- `api/declarative-endpoints.mdx` — /graphql from the exemplar list pointing at
that catalog; the two remaining examples are real mounted routes.
- `protocol/diagram.mdx` — the `GQL[GraphQL]` node AND both its edges
(`CLIENT --> GQL`, `GQL --> KERNEL`); mermaid materialises an undeclared node
from a dangling edge, so deleting the declaration alone still renders a box.
- `protocol/diagram.mdx` — GraphQL from the `src/api/` layer-table cell;
that directory contains zero graphql files (re-measured).
Rewritten (the surrounding claim is true; only the enumeration was wrong):
- `protocol/diagram.mdx` sequence label → `HTTP Request (REST)`.
- `protocol/kernel/lifecycle.mdx` → `Start HTTP server`, box width preserved.
- `protocol/kernel/error-handling.mdx` → `(HTTP, WebSocket)`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DdCnBGcHeufjrq7drTD3wt
…oval
Keeps the em dash attached to the clause it belongs to instead of orphaning
it at the start of a line, and refills the paragraph. No claim changes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DdCnBGcHeufjrq7drTD3wt
@github-actionsgithub-actionsBot added size/s documentation Improvements or additions to documentation labels Aug 21, 2026
@claudeclaudeBot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 21, 2026
@claude

claudeBot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

✅ ACCEPT — reviewer of record: domain:devx PM seat (#6023, session session_01DdCnBGcHeufjrq7drTD3wt). Reviewed against the diff, not the report.

The catch the card did not name, verified in the patch

⭐ The mermaid node needed both its edges deleted, not just its declaration — mermaid materialises an undeclared node from a dangling edge, so removing GQL[GraphQL] alone would still have rendered an unlabelled box. The diff removes the declaration andCLIENT --> GQLandGQL --> KERNEL. A naive edit would have left a silent visual artifact that no gate checks.

Per-site doctrine, applied rather than swept

The 404/501 split from packages/runtime/src/domains/unavailable.ts is applied per site, which is what I asked for and not what a uniform sweep would have done: constructs that enumerate servable routes are deleted (the ### GraphQL (/graphql) section and its POST table, the frontmatter mention, the declarative-endpoints.mdx exemplar, the src/api/ table cell); sites whose surrounding claim is true and whose enumeration was merely long are rewritten (the sequence label, the boot line, the API list). Deleting a status-table row rather than rewriting it to "not available" is right for the reason PR #10828 established: in a table headed "Status in this repo", the row itself asserts GraphQL was a surface worth listing.

Verified independently

  • No #graphql fragment exists anywhere in content/ — the deleted ### heading breaks no anchor. check:doc-anchors agrees: 272 internal #fragment link(s) across 408 source file(s) all resolve to a real heading.
  • packages/spec/src/api/ carries no graphql file, and the lone string hit is protocol.zod.ts:105, a docblock naming GraphQL as an industry design style — correctly left alone. (Your count read 68 files, mine reads 69; immaterial to the claim, which is 0 either way.)
  • check:error-status-conformance was derived by the tool and not in my dispatch clue list — you ran what the tool named rather than what I listed. Correct.

Correcting myself, and half-correcting you

⚠️I was wrong: my mid-flight message said "PR #10828 has now merged." It has not — merged=false, and content/docs/api/index.mdx on main still carries 2 GraphQL hits.

⚠️You were half-wrong too: #10828 is in the merge queueadded_to_merge_queue @ 13:19:11Z, with no removal event. "Open and unmerged" and "in the queue" are simultaneously true.

Neither error touches your conclusion, and you protected yourself from both by reading #10828's diff in full anyway and confirming the five files here are disjoint from its three. That is why the disjointness claim survives two wrong statements about the same PR.

#10846 (five skills/** residue sites plus their mirror) correctly filed rather than fixed — skills/** is governed, human-merge-only, and patching the consumer page alone would make the catalog disagree with the skill it catalogs.

Flipping ready and arming.


Generated by Claude Code

@os-zhuang
os-zhuang marked this pull request as ready for review August 21, 2026 13:41
@os-zhuang
os-zhuang enabled auto-merge August 21, 2026 13:41
@os-zhuang
os-zhuang added this pull request to the merge queueAug 21, 2026
Merged via the queue into main with commit dbb4803Aug 21, 2026
33 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

⛔ merge queue 构建失败 — 先分诊,再决定要不要重排

队列构建 32490852845 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集),
所以失败的测试可能在本 PR 没碰过的包里 —— 那不是重排能修的。每次盲目重排都会让排在后面的所有 PR 重建一轮。

失败的 job(日志抽取,best effort):

  • Console Pin Gate — 失败步骤: Build the Console SPA at the pinned objectui SHA

    ✗ Build failed in 5.97s
    

↳ 失败原因 是判读的关键:超时Test timed out in … / Hook timed out in …)多半是负载/时序,不是本 PR 的回归;
断言AssertionError: …)才指向真实的行为改变。两者的 FAIL 行长得一模一样,只有这一行能区分。

跨 PR 相同签名(24h,按失败测试文件聚合):

  • ⚠️本次没有可用的聚合签名(日志里没有能解析出测试文件名的 FAIL 行)—— 这不是「没有同签名的其他 PR」,是这一轮没测到。跨 PR 聚合本次不可用,请手工比对其他 PR 的同类评论。
  • ⚠️ 24h 评论账本没读完(超过 5 页仍未读到窗口尽头),所以上面的「不同 PR 数」是下界,不是全量。

历史信号:

  • 本 PR 过去 24h 无队列失败记录(首次)。
  • 过去 24h 队列共有 10 个失败构建(不含本次)。

分诊清单:

  1. 失败测试在本 PR 改动的包里 → 真回归,修 PR。
  2. 失败测试与本 PR 无关 → 看上面的「跨 PR 相同签名」;已有汇总 issue ⇒ flaky/环境问题实锤,去那张 issue 上谈,修好前重排只会再烧一轮全队列。
  3. 两者都不是 → 可能与同组 PR 语义冲突;等前面的 PR 落地或失败出队后再重排一次即可,不要连续重排。

Generated by Claude Code · merge-queue-triage workflow (#4859)

@os-zhuang
os-zhuang deleted the claude/issue-10832-graphql-endpoint-contract-residue branch August 21, 2026 14:26
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/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.

[finding] plugin-endpoints.mdx documents a POST /graphql endpoint contract for a route that is not mounted

2 participants

@os-zhuang@claude