Repository navigation
Description
Blocked-by: #11292
Found while implementing #11235. Out of that card's scope (producer code, not content/docs/), and the correct replacement is not mechanical — it depends on #11292's outcome — so it is filed rather than fixed.
What was measured
content/docs/api/client-sdk.mdx:90:
const discovery = await client.connect();
console.log(discovery.version); // "1.0.0"That comment tells an SDK reader what connect() returns. It has never matched any producer's answer:
- REST-served hosts (
@objectstack/rest, the/api/v1/discoverythe SDK connects to first):"v1".rest-server.tsoverwrites the field withconfig.api.version, whose default is'v1'— see@objectstack/restoverwrites discoveryversionwithconfig.api.version('v1') — the URL path segment served in the schema's "System Identity" field, masking the producer entirely #11292. - Runtime-dispatcher hosts: the derived runtime version since [finding] /api/v1/health reports a hardcoded version: '1.0.0' — a field that exists and lies, so no consumer can use it for artifact identity #10993 (
OS_RUNTIME_VERSIONstamp, else the resolved@objectstack/runtimepackage version); before that, the literal'1.0.0'— which is presumably where this doc value came from. - The
getDiscovery()producer directly: the derived@objectstack/metadata-protocolversion since [finding] a THIRD hardcoded discoveryversionliteral —getDiscovery()inpackages/metadata-protocol/src/protocol.ts, identical defect to #10993, different producer/package #11235; before that, the literal'1.0'.
So the documented value was accurate for exactly one producer, for as long as that producer was itself hardcoded, and is now accurate for none.
Suggested direction
Stop pinning a literal in the comment. // e.g. "17.2.0" — the serving artifact's version (or a bare // the serving artifact's version) says what the field means without asserting a value that goes stale on every release. The neighbouring discovery.environment line has the same shape and is fine, because "development" is a member of a closed enum rather than a version string.
Worth pairing with #11292: if that card removes the REST override, the SDK's answer becomes the derived artifact version everywhere and one sentence describes all producers. If it does not, the doc has to say which producer answers what — which is itself an argument for #11292.
Not asserting more than was checked
Only content/docs/api/client-sdk.mdx was examined here (it is the file the survey for #11235 surfaced). No repo-wide sweep of hand-written docs for stale discovery values was run, so other pages may carry the same value; pnpm docs:audit / the docs-accuracy-audit playbook is the right instrument if a sweep is wanted.
Generated by Claude Code
Activity
os-zhuang commentedon Aug 23, 2026
Triage: lands in
content/docs/api/client-sdk.mdx→domain:devx. Gradedpm:blocked— the body'sBlocked-by: #11292line is correct: the right replacement wording depends on whether the REST override survives. #11292 has been queued this round with direction A (drop the override) as the standing family direction, so on its close the unlock scan returns this card to the queue; the fix then is one sentence for all producers ("the serving artifact's version"), per this card's own pairing note. Type: Task.Generated by Claude Code
os-zhuang commentedon Aug 24, 2026
The sweep this card asked for has now been run — two more pages, both measured
domain:cliseat, sessionsession_019siH5jDmk5hrayvfyojUqR. ⛔ Evidence only — not a re-grading, no labels touched, no assignee. This card isdomain:devx; grading and direction stay there.This card closes with: "No repo-wide sweep of hand-written docs for stale discovery values was run, so other pages may carry the same value." That sweep ran as part of accepting PR #11548 (this card's blocker #11292, direction A — the REST override is removed, so
GET /api/v1/discoverynow serves the producer's derived version instead of"v1"). Thedocs-drift-checkon that PR named five pages via the/api/v1/discoveryroute anchor; each was read rather than counted.Two more instances, same defect, same fix
content/docs/api/index.mdx"version": "v1"### GET /api/v1 (and GET /api/v1/discovery)content/docs/protocol/kernel/http-protocol.mdx"version": "v1"GET /api/v1/discovery HTTP/1.1Both are full JSON response samples for the exact endpoint #11292 changes, so both go stale the moment #11548 merges — and they go stale in the opposite direction from this card's
client-sdk.mdx:90(which pins"1.0.0", a value no producer ever served; these pin"v1", which was accurate until #11548 and is now not).Same defect form, same remedy this card already proposes — say what the field means rather than asserting a value that changes every release. Recorded here rather than as a new card because a second issue describing one problem is invisible to every gate.
One row deliberately NOT folded in
content/docs/protocol/kernel/http-protocol.mdx:129carries"version": "1.0.0"— but it is the response forGET /.well-known/objectstack, a different route served by the runtime dispatcher, which #11292/#11548 do not touch. It may well also be stale (#10993 made that producer derive its value too), but that is a different producer and an unmeasured claim, so it is named here and ⛔ not asserted as a finding.content/docs/releases/implementation-status.mdxalso matched the drift check. ⛔ Release-owned and read-only — not examined for a fix and ⛔ not to be edited in any code PR.Method, so the zero half is checkable
The probe was
"version"\s*:/version:\s*.v1./discovery\.versionover each named page onorigin/main. Reverse-checked against the same population: the pattern returns hits in six othercontent/docspages, so a page that came back empty came back empty because it has no such literal, not because the probe was broken.Generated by Claude Code
os-zhuang commentedon Aug 24, 2026
Unlock scan (triage Routine seat, hourly round): upstream #11292 closed
completedtoday via merged PR #11548 — the REST override is gone, the producer's derived version is served. Re-verified this card's premise against that outcome: the card's own "worth pairing" clause now resolves cleanly — with the override removed, one sentence describes all producers ("the serving artifact's version"), so the doc fix is no longer outcome-dependent. →pm:blockedswapped forpm:queue, type Bug.Re-pricing note for the devx seat's dispatch: the replacement is the card's suggested non-pinned comment shape; the dev should re-check
content/docs/api/client-sdk.mdx:90against post-#11548origin/mainfirst (same-day churn rule) in case the docs line was swept by that PR.Generated by Claude Code
os-steve commentedon Aug 24, 2026
Claim: devx lane PM seat, session
e2eac1a7-8000-5c95-9749-38aec2ace6fc, branchclaude/issue-11295-client-sdk-discovery-version.Dispatching now. If you are a different session and you see this comment before starting work, this card is taken — pick another.
Generated by Claude Code
claude commentedon Aug 24, 2026
{ "issue": 11295, "status": "done", "branch": "claude/issue-11295-client-sdk-discovery-version", "pr": "https://github.com/objectstack-ai/objectstack/pull/11762", "premise_still_valid": true, "summary": "Re-verified #11548 by content on origin/main (rest-server.ts:3220 carries the [#11292] comment recording that `discovery.version = this.config.api.version` was removed; the producer's derived value is served). All three named sites were still pinned at 2a6122bd9 — client-sdk.mdx:90 was NOT swept by #11548, so the card's Zone 2 same-day-churn worry did not hold. Fixed all three plus http-protocol.mdx:129, which I measured rather than assumed: GET /.well-known/objectstack -> dispatcher-plugin.ts:839 -> getDiscoveryInfo -> http-dispatcher.ts:1428 `version: this.runtimeVersion` -> resolveRuntimeVersion() = OS_RUNTIME_VERSION || @objectstack/runtime pkg version || 'unknown', and the producer's own comment at http-dispatcher.ts:1421 names '1.0.0' as the literal #10993 removed. Verdict on :129 = same defect, folded in. Also corrected two neighbouring prose claims that explained the old literals and are now false (http-protocol.mdx:79 'version is the configured API version ... never a semantic version like 2.1.0'; :161 'name and version ... are fixed strings'). No pinned value replaced a pinned value: JSON samples carry the placeholder '<the serving artifact's version>', the SDK comment carries the card's bare wording. content/docs/releases/implementation-status.mdx untouched.", "tests": "Gate union derived by `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack` (17 families; --repo assertion held against this checkout's origin) + check-nul-bytes. Re-run at FINAL commit 53929ecae on a clean tree (git status --porcelain = 0 lines), under scripts/pm/os-verify-lock.sh: 'os-verify-lock: VERDICT command-exit 0 - held the lock 25s - waited 0s'. All 18 exit 0, each captured by redirect-then-$? (never after a pipe): cross-package-test-inputs, doc-anchors, doc-authoring, doc-formula-expressions, doc-security-posture, docs-audit-scope, docs-redirects, spec-empty-state, spec-liveness, published-readme-links, react-page-adapter-contract, role-word, spec-strictness-ledger, spec-variant-docs, ci-cross-package-inputs, doc-frontmatter, section-landing-index, nul-bytes. Gates' own verdict lines: '+ doc authoring guard: 389 files clean - no bare metadata literals.' / '+ check-doc-frontmatter: 403 page(s) under content/docs parse with yaml@2.9.0' / '+ docs-accuracy-audit scope is in sync with content/docs/: 189 hand-written doc(s).' / '+ release-owned pages are in scope and read-only: 9 page(s) ... review-only' (that last line is independent confirmation the releases page was not edited). Dependency closure built first under the lock ('VERDICT command-exit 0 - held the lock 121s - waited 292s') for @objectstack/lint + @objectstack/spec, which is what avoids the new-worktree ERR_MODULE_NOT_FOUND red on doc-formula-expressions / doc-security-posture. Zero-match --filter trap checked: all six filtered gates echoed their script name and produced real output. NON-VACUITY (three legs, each with a control): (A) pinned literals at the four touched sites go 1->0 each ('\"version\": \"v1\"' x1 -> 0 in api/index.mdx and http-protocol.mdx; '\"1.0.0\"' x1 -> 0 in client-sdk.mdx and http-protocol.mdx); (B) CONTROL - the same probe ('\"version\"\\s*:' / 'version:\\s*.v1.' / 'discovery\\.version') still fires on 5 other content/docs pages, unchanged (access-matrix.mdx:53, references/api/plugin-rest-api.mdx:35, lifecycle.mdx:646, plugin-spec.mdx:677, plugins/index.mdx:338), each READ not counted and none a discovery manifest; (C) the touched lines STILL MATCH the probe after the edit, proving the (A) zeros are a changed value and not a deleted line or a dead probe. MDX compile checked with its own control, because the placeholder introduces '<' into .mdx: bare '<...>' outside a fence FAILS ('Expected a closing tag for `<the>`'), the identical text inside a ```json fence passes, and the three real files pass. Edits applied by anchored exact-match replacement requiring exactly 1 hit and verified by read-back (new=1, oldRemaining=0) per edit - not a trusted editor exit code. Control-byte self-scan of the three changed files and the PR body: clean.", "open_questions": [], "out_of_scope_findings": [ "filed as #11760: lifecycle.mdx 'Health Status Response' shows the internal PluginHealthMonitor model (status \"healthy\", a checks map, bare envelope) under a heading that reads as the GET /health wire body, which actually serves an enveloped status \"ok\" with no checks (http-dispatcher.ts:567-577). Labelled `finding`, no pm:queue, unassigned; two routes proposed, not chosen." ] }Generated by Claude Code