Skip to content

Commit 1739f71

Browse files
docs(ai): knowledge-rag example declares adapterConfig, not the undeclared options key (#19261)
Fixes #19252 `content/docs/ai/knowledge-rag.mdx:37` configured its `ragflow` knowledge source with the undeclared `options` key. `KnowledgeSourceSchema` (`packages/spec/src/ai/knowledge-source.zod.ts`) declares **`adapterConfig`** and is a plain `z.object` with no `.passthrough()`, so the key is dropped before any adapter sees it. Since #19251 landed (card #18973; maintainer ruling batch #160 item 2, letter A: 「the spec wins」), `extractRagflowOptions` reads `source.adapterConfig` with **no fallback**, so a source copied off this page is refused by name at the first `upsert` / `search` / `delete`. One line, one page: ```diff - options: { datasetId: 'rgf_doc_dataset' }, + adapterConfig: { datasetId: 'rgf_doc_dataset' }, ``` No `packages/spec` change and **no ADR-0087 conversion**, exactly as the ruling states: `options` was never a key `KnowledgeSourceSchema` accepted, so nothing an author could declare is removed. ## Is :37 the only carrier? — measured, not assumed All readings taken on this branch at `6ec845878`, over `content/docs/`: | reading | result | |---|---| | `grep -rn "options: { datasetId" content/docs/` (pre-fix tree) | **1** — this line only | | firing control, same corpus, correct spelling | `content/docs/references/ai/knowledge-source.mdx:83` spells `adapterConfig` ⇒ the outlier is this page, not the docs tree | | positive control, same corpus, same term | `datasetId` anywhere under `content/docs/` ⇒ **1** hit (the same line) ⇒ the one-hit reading is a reading, not a dead search | | widened, different spellings: `grep -rn -A3 "options:" content/docs/` filtered to `datasetId` | **1** — no multi-line or differently-quoted second carrier | | widened, by subject: every `content/docs/` file naming `KnowledgeServicePlugin` / `adapter: 'ragflow'` / `adapter: 'memory'` / `KnowledgeSource` (10 files) read for a source literal | no second knowledge-source example carries `options` | | every `options *:` occurrence under `content/docs/` (41 lines) read | all are `Field.select` option lists, batch `options.atomic`, i18n option maps or a dashboard widget — **none is a knowledge source** | ⇒ this is a single-carrier card, and the single carrier is fixed here. The rest of `content/docs/**` is clean on this defect. ## The corrected example parses, and the old spelling is shown dropping A throwaway script (⛔ not committed; removed, `git diff HEAD` empty afterwards) lifted the `product_docs` literal **out of the page by content** — not retyped — and parsed it against the built `KnowledgeSourceSchema`: ``` --- block lifted from content/docs/ai/knowledge-rag.mdx (lines 33-37) --- id: 'product_docs', label: 'Product docs', adapter: 'ragflow', source: { kind: 'http', urls: ['https://docs.example.com/sitemap.xml'] }, adapterConfig: { datasetId: 'rgf_doc_dataset' }, === LEG A: the page as it now stands === safeParse success: true parsed adapterConfig: {"datasetId":"rgf_doc_dataset"} adapter's read of source.adapterConfig.datasetId: rgf_doc_dataset === LEG B: ABLATION — the pre-fix spelling, in this scratch object only === safeParse success: true unrecognized_keys issues: none post-parse keys: adapter,adapterConfig,aiExposed,id,label,refresh,source 'options' survives the parse: false parsed adapterConfig: {} adapter's read of source.adapterConfig.datasetId: [MISSING -- RAGFlow adapter requires source.adapterConfig.datasetId on source 'product_docs'] ``` *(one byte-level edit to the transcript above: the script's own placeholder brackets around the MISSING line are rendered here as square brackets, because this repo's rule is that angle-bracket-shaped fragments are spelled out in words before they go into a GitHub body — fences do not protect them.)* ⚠️ **The observed ablation direction is a silent drop, not a red parse** — worth stating because it is the defect's whole shape. `KnowledgeSourceSchema` is a plain `z.object`, so the old spelling still `safeParse`s green with **zero** `unrecognized_keys`; `options` simply is not in the post-parse keys and `adapterConfig` falls back to its `{}` default. The loud part arrives one layer later, at the adapter's named refusal. That is precisely why a reader could copy this page and get no warning until the first call. ## Verification - **Derived gate family**, run in this act, ⛔ not taken from the dispatch: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (no paths — derived from the real change set vs merge base `7d0f911da`) ⇒ **39** commands. **All 39 run, all 39 green.** Four first refused with `PREREQUISITE NOT MET` / unbuilt-package (exit 3, exit 1 — ⛔ not findings): `check:doc-formula-expressions`, `check:doc-security-posture`, `check:docs-transcript-drift` (`@objectstack/lint`, `@objectstack/formula` unbuilt) and `check:skill-examples` (`@objectstack/client-react` `dist` held no declarations). Those four packages were built, and all four gates re-run **green**. - `check:nul-bytes` green; plus an out-of-gate self-scan for control bytes on the changed file — no match. - **MDX still builds**: `pnpm --filter @objectstack/docs run postinstall` (`fumadocs-mdx`, the docs collection compile) exit **0**, working tree clean afterwards. - **Lint, narrowed — and the narrowing is itself measured** (at `6ec845878`): ① the inspected population read from eslint's own config is `files: ['**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}']` (and `['**/*.{ts,tsx,mts,cts}']`) — **`.mdx` appears in no `files` entry**; ② `eslint --no-inline-config --format json content/docs/ai/knowledge-rag.mdx` ⇒ 1 file entry, **0 errors**, its one message being `File ignored because no matching configuration was supplied.`; ③ invariance for untouched files: `eslint.config.mjs` declares **no** `parserOptions.project` and **no** `projectService`, so type-aware linting is off and this diff cannot move any untouched file's verdict. ⇒ the diff's only file lies wholly outside eslint's population; the repo-wide `pnpm lint` sweep is CI's run. - ⊘ **NOT MEASURED, by the derivation's own account**: the two path-scheduled CI jobs (`Test Core`, `Build Docs`) — CI's own shell in CI's environment, no local invocation exists — and the two workflow-valued families (`check-shard-attestation`, `check-test-completeness`). ## changeset `skip-changeset`. The criterion is whether anything **published** moves, not whether a changeset exists. Measured: `content/docs/**` is consumed only by `apps/docs` (`@objectstack/docs`, `"private": true`, no `files[]`), and a scan of **every** `package.json` in the repo found **zero** packages whose `files[]` ships anything under `content/`. ⇒ no published artifact moves. ## Acceptance notes - **Noted, not filed** — the corrected block on this page carries no `os:check` marker, so `check:skill-examples` (258 marked blocks across 106 files; 216 `os:check` markers under `content/docs/`) never type-checked it, which is why the wrong key could sit in a published page uncaught. ⛔ Out of this card's surface and ⛔ not one of the three fileable classes (it is a coverage gap, not a reproducible defect — the block is correct as of this PR). Successor: the next card that extends the compile-checked prose corpus into `content/docs/ai/`. - `.changeset/18973-ragflow-reads-declared-adapter-config.md:13` also contains the string `options: { datasetId: … }`. It is the **before** side of that changeset's migration example — correct as written, and ⛔ deliberately not touched. --- 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_017ef78bLdybu3AffehKkhfk _Generated by [Claude Code](https://claude.ai/code/session_017ef78bLdybu3AffehKkhfk)_ --- _Generated by [Claude Code](https://claude.ai/code/session_017ef78bLdybu3AffehKkhfk)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent c199772 commit 1739f71

1 file changed

Lines changed: 1 addition & 1 deletion

File tree

‎content/docs/ai/knowledge-rag.mdx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ kernel.use(new KnowledgeServicePlugin({
3434
label: 'Product docs',
3535
adapter: 'ragflow',
3636
source: { kind: 'http', urls: ['https://docs.example.com/sitemap.xml'] },
37-
options: { datasetId: 'rgf_doc_dataset' },
37+
adapterConfig: { datasetId: 'rgf_doc_dataset' },
3838
},
3939
],
4040
}));

0 commit comments

Comments
 (0)