Skip to content

test(client,runtime): the last wildcard was wrong evidence, not weak — AI ratchet 3 → 0 (#3718) - #3727

Merged
os-zhuang merged 2 commits into
mainfrom
claude/route-audit-tranche-3-service-wsxqaf
Jul 28, 2026
Merged

test(client,runtime): the last wildcard was wrong evidence, not weak — AI ratchet 3 → 0 (#3718)#3727
os-zhuang merged 2 commits into
mainfrom
claude/route-audit-tranche-3-service-wsxqaf

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Closes the last family of the #3563 route audit. Paired with objectstack-ai/cloud#891, which carries the real ledger. Finding filed as #3718.

Test-and-comment changes only — no runtime behaviour is affected.

What the ratchet was really asking

§10's capstone ratcheted "matched only by a ** family" as weaker evidence, to be driven down by enumerating each dynamic family. 60 → 3 after #3656. The last 3 were ai.nlq / ai.suggest / ai.insights on * /ai/**.

Enumerating that family — in cloud, where service-ai lives — answered the question. buildAIRoutes() mounts 12 routes: chat, chat/stream, complete, models, status, effective-model, and six conversations routes.

None of them is /nlq, /suggest or /insights.

client.ai methods3
…answered by any repo0
Real AI routes12
…expressed by the SDK0

The two sets are disjoint. So the wildcard was not weak evidence — it was wrong evidence, certifying three URLs nothing anywhere serves. Its note even asserted the client "expresses nlq/suggest/insights against the REST AI routes"; never verified, and false.

DEFAULT_AI_ROUTES declares all three but has no runtime consumer (only the spec's own test reads it), and aiNlq? / aiSuggest? / aiInsights? are optional protocol methods nothing implements. Declared, never built — instances 7–9 of the the method exists ≠ the method can be called class, after #3584, #3611, #3636, #3702.

The change

  • /api/v1/ai/ becomes a bounded prefix exemption alongside the control plane — two cross-repo surfaces, both ledgered in cloud. Only ai.* may use it, and the namespace must still be reaching it, so the hole cannot widen.
  • The * /ai/** ledger row stays (the /ai domain is registered on the dispatcher, so removing it fails the domain-coverage guard) but its note is corrected and now points at cloud's ai-route-ledger.ts.
  • The wildcard assertion becomes toBe(0), not a ratchet. Zero is the point: every matched call now rests on an exact enumerated route, and reintroducing a ** match reintroduces the one kind of evidence this audit family has caught being wrong.

Mutation-checked both directions

  • Removing the AI exemption re-exposes exactly the three methods.
  • Running the pre-change capstone with the bound forced to 0 confirms the old wildcard set was exactly ai.insights, ai.nlq, ai.suggest — nothing else was resting on a wildcard, so the 3 → 0 claim is measured, not assumed.

Audit §14

Adds the section, and with it the lesson worth carrying out of §1–§14:

A claim about a family is not a claim about a member. Wildcards, prefixes and "the service handles that" all read as coverage in a green suite. Every one of them this audit opened turned out to be hiding something.

Not fixed here

Whether to implement the three endpoints, remove the namespace, or express the real surface instead is a product decision — #3718, with a recommendation. The guard is already in place either way: cloud's UNMOUNTED_AI_CLIENT_METHODS asserts all three still match nothing, so implementing any of them fails that test and forces an sdk row.

Tests

client-url-conformance 3 passed · route-ledger.conformance 4 passed · turbo run test --filter=@objectstack/runtime --filter=@objectstack/client — 28 tasks successful.

🤖 Generated with Claude Code

https://claude.ai/code/session_01K35y3ovfWtCkBHYFCqUfAt


Generated by Claude Code

…— AI ratchet 3 → 0 (#3718)
The capstone (#3642) ratcheted "matched only by a `**` family" as WEAKER
evidence, to be driven down by enumerating each dynamic family. 60 → 3 after
#3656. The last 3 were `ai.nlq` / `ai.suggest` / `ai.insights` on `* /ai/**`.
Enumerating that family — in `cloud`, where service-ai lives — answered the
question the ratchet was really asking. `buildAIRoutes()` mounts 12 routes
(chat, chat/stream, complete, models, status, effective-model, six
conversations) and NONE is `/nlq`, `/suggest` or `/insights`.
client.ai methods: 3 answered by any repo: 0
real AI routes: 12 expressed by the SDK: 0
The two sets are disjoint. So the wildcard was not weak evidence, it was WRONG
evidence: it certified three URLs nothing anywhere serves. Its note even
asserted the client "expresses nlq/suggest/insights against the REST AI
routes" — never verified, and false. `DEFAULT_AI_ROUTES` declares all three but
has no runtime consumer (only the spec's own test reads it), and
`aiNlq?`/`aiSuggest?`/`aiInsights?` are optional protocol methods nothing
implements. Declared, never built (#3718) — instances 7-9 of the
`the method exists != the method can be called` class.
`/api/v1/ai/` becomes a bounded prefix exemption alongside the control plane:
two cross-repo surfaces, both ledgered in `cloud`. Only `ai.*` may use it, and
the namespace must still be reaching it, so the hole cannot widen.
The wildcard assertion becomes `toBe(0)`, not a ratchet. Zero is the point:
every matched call now rests on an exact enumerated route, and reintroducing a
`**` match reintroduces the one kind of evidence this audit family has caught
being wrong.
Mutation-checked both ways: removing the exemption re-exposes exactly the three
methods, and running the PRE-change capstone with the bound at 0 confirms the
old wildcard set was exactly `ai.insights`, `ai.nlq`, `ai.suggest` and nothing
else.
Adds audit §14 with the lesson worth carrying out of §1-§14: a claim about a
family is not a claim about a member. Wildcards, prefixes and "the service
handles that" all read as coverage in a green suite, and every one this audit
opened was hiding something.
Test-and-comment changes only; no runtime behaviour is affected.
Co-Authored-By: Claude <noreply@anthropic.com>
@vercel

vercelBot commented Jul 28, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectstackIgnoredIgnoredJul 28, 2026 12:32am

Request Review

@github-actionsgithub-actionsBot added size/m documentation Improvements or additions to documentation tests tooling labels Jul 28, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/client, @objectstack/runtime.

26 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/skills-reference.mdx(via packages/client)
  • content/docs/api/client-sdk.mdx(via @objectstack/client, packages/runtime)
  • content/docs/api/data-flow.mdx(via @objectstack/client)
  • content/docs/api/environment-routing.mdx(via @objectstack/client)
  • content/docs/api/error-catalog.mdx(via @objectstack/client)
  • content/docs/api/index.mdx(via @objectstack/runtime)
  • content/docs/api/wire-format.mdx(via @objectstack/runtime)
  • content/docs/automation/hook-bodies.mdx(via @objectstack/runtime)
  • content/docs/concepts/north-star.mdx(via packages/runtime)
  • content/docs/data-modeling/drivers.mdx(via @objectstack/runtime)
  • content/docs/deployment/index.mdx(via @objectstack/runtime)
  • content/docs/deployment/production-readiness.mdx(via @objectstack/runtime)
  • content/docs/deployment/single-project-mode.mdx(via @objectstack/runtime)
  • content/docs/deployment/vercel.mdx(via @objectstack/runtime)
  • content/docs/getting-started/your-first-project.mdx(via @objectstack/client, @objectstack/runtime)
  • content/docs/kernel/runtime-services/data-service.mdx(via packages/client)
  • content/docs/kernel/runtime-services/index.mdx(via packages/client)
  • content/docs/permissions/authentication.mdx(via @objectstack/client, @objectstack/runtime)
  • content/docs/permissions/authorization.mdx(via packages/runtime)
  • content/docs/plugins/packages.mdx(via @objectstack/client, @objectstack/runtime)
  • content/docs/protocol/kernel/http-protocol.mdx(via @objectstack/runtime)
  • content/docs/protocol/kernel/index.mdx(via @objectstack/runtime)
  • content/docs/protocol/kernel/lifecycle.mdx(via @objectstack/runtime)
  • content/docs/protocol/kernel/realtime-protocol.mdx(via @objectstack/client)
  • content/docs/releases/implementation-status.mdx(via @objectstack/client, @objectstack/runtime)
  • content/docs/releases/v16.mdx(via @objectstack/client)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

The docs-drift advisory on this PR prompted a check of whether any published
doc advertises the three dead `ai.*` methods. It does, and the AI docs turn out
to be backwards in both directions at once:
- `plugin-endpoints.mdx` tabled `/ai/nlq`, `/ai/suggest`, `/ai/insights` as
the AI plugin's endpoints. None of the three is mounted by anything.
- The same section's callout stated "There is no `/ai/chat` route".
`/api/v1/ai/chat` IS mounted, along with `/chat/stream`, `/complete`,
`/models` and six `/conversations` routes.
So the documentation named the three routes that do not exist and explicitly
denied the one that does — while `client-sdk.mdx` carried three
copy-pasteable examples that 404 on every call. That is Prime Directive #10 in
the literal sense: advertising a capability the runtime does not deliver.
Corrected:
- `client-sdk.mdx` — the three examples are marked declared-but-unimplemented
with the reason, and the chat note now says the chat endpoint exists and it
is the SDK that lacks a method for it.
- `plugin-endpoints.mdx` — status column on the three, plus the real 12-route
table and a pointer to cloud's ai-route-ledger.ts. The callout's surviving
point (use `useChat()` directly) is kept; only its false premise is fixed.
- `services-checklist.mdx` — notes that all three are optional protocol
methods nothing implements.
Deliberately does NOT decide #3718 (implement vs remove vs express the real
surface). Every edit here states what is true today and stays true whichever
way that lands.
Co-Authored-By: Claude <noreply@anthropic.com>
@os-zhuang
os-zhuang marked this pull request as ready for review July 28, 2026 00:44
@os-zhuang
os-zhuang merged commit 6877e9a into mainJul 28, 2026
16 checks passed
@os-zhuang
os-zhuang deleted the claude/route-audit-tranche-3-service-wsxqaf branch July 28, 2026 00:44
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mteststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@os-zhuang@claude