Repository navigation
Commit cb005e0
fix(knowledge-ragflow): read source.adapterConfig.datasetId, the declared key (#19251)
Fixes #18973
Clause-②: no
Ruled on-card: batch #160 item 2, **letter A**, maintainer 「同意」
2026-09-18 (`issuecomment-5729652660`) — "the spec wins:
`@objectstack/knowledge-ragflow` reads `source.adapterConfig.datasetId`,
its README says the same, and `KnowledgeSourceSchema` is untouched".
`packages/spec` is untouched here, as ruled.
## What was wrong
`extractRagflowOptions` cast the source to a shape it does not have and
read `options.datasetId`:
```ts
// RECORD_OF_UNKNOWN stands for the record-of-string-to-unknown generic; the
// angle-bracket spelling is avoided because this platform rewrites such
// fragments in a body, inside a fence as readily as outside one.
const opts = ((source as unknown as { options?: RECORD_OF_UNKNOWN }).options ?? {}) as
RECORD_OF_UNKNOWN;
```
`KnowledgeSourceSchema` declares `adapterConfig` for adapter-specific
configuration and is a plain `z.object` with no `.passthrough()`, so any
path that parses a source drops `options` before an adapter sees it. The
adapter worked only because nothing parses a source today. The published
README documented the undeclared spelling, which made it the one block
of #18915's 44 that could not be repaired: correcting the word alone
would have compiled and stopped working.
## What changed
- **`src/index.ts`** — the cast is gone. `extractRagflowOptions` reads
`source.adapterConfig`, a declared, already-typed property, so no cast
is needed at all. There is no fallback that also reads `options` (Prime
Directive #12 — no lenient consumer). The refusal now names the declared
key: `RAGFlow adapter requires source.adapterConfig.datasetId on source
'SOURCE_ID'` (the source's own id interpolated), so a host on the old
spelling is told what to write instead of retrieving nothing.
- **`README.md`** — the example and the "Source binding" sentence move
to `adapterConfig`, and the block now compiles against the package
(evidence below).
- **`src/__tests__/ragflow-adapter.test.ts`** — the three
`KnowledgeSource` literals move with it; the refusal test now pins the
message text (the ruling relies on it naming the key, so the wording is
contractual here), and a new test pins that a source carrying only the
legacy `options` spelling is refused and reaches no transport at all.
- **`test-typecheck-debt.json`** — emptied. See below; this was not an
incidental repair.
- **Changeset** — `@objectstack/knowledge-ragflow` patch, behaviour:
reads the declared key, with the `FROM` → `TO` mapping in the body.
## Four call sites, one repair — and a correction to the dispatch order
The card body names one call site (`:108`). There are four sites on
`origin/main` — the definition at `:60` and calls at `:108`, `:136`,
`:144` — and the dispatch order carried that as "a repair that fixes one
call site is not the repair". Measured on this branch's base: **no call
site needed editing.** All three calls pass the whole `source` and
destructure the result; the undeclared key was read in exactly one
place, the definition's cast. The four-site count is correct and the
inference drawn from it is not: the repair is one function body, and it
covers all three callers. `grep -n "options" src/index.ts` after the
change returns one line — `pass options.fetch` in the adapter
constructor's own error, which is about `KnowledgeRagflowAdapterOptions`
and not about a `KnowledgeSource`.
## The type-debt ledger was this same defect, frozen
`packages/plugins/knowledge-ragflow/test-typecheck-debt.json` pinned 3
errors in one file, all `TS2353: Object literal may only specify known
properties, and 'options' does not exist in type '…'`. Those three
errors *were* this card: the test wrote the undeclared key because the
adapter read it. With the adapter on `adapterConfig` the file graduates
to zero, and the ledger is shrink-only — a graduated file is red until
its entry is deleted. `check:test-typecheck` said so in as many words,
and the entry is now gone. The file is kept with an empty `entries` map
(it is the per-file ledger the gate reads for this package), and its
authored `_note` records the graduation; the note survives regeneration,
verified by running the generator twice.
## Two shipped surfaces already said `adapterConfig`
The adapter was the outlier, not the schema. Both of these ship today:
-
`packages/services/service-settings/src/manifests/knowledge.manifest.ts:97`
— "Per-source values on **KnowledgeSource.adapterConfig** take
precedence", in all four translated locales.
- `skills/objectstack-ai/SKILL.md` — "they belong to the adapter
(`adapterConfig`) or application code", above an example that calls
`KnowledgeSourceSchema.parse({ … adapter: 'ragflow' … })`.
Neither is touched by this PR; they are cited because they make the
ruled direction the one that leaves the repo self-consistent.
## Evidence
**The README block compiles, and the measurement can fail.**
`measure-markdown-ts-blocks` is a census, not a gate, so a bare green
from it is worth little — it was run in both directions, at `6f17a4f13`:
| run | result |
|---|---|
| README as landed here | 1 file / 1 TS block, **RAW fail 0, TOLERANT
fail 0, WELL-FORMED AND WRONG 0** |
| README ablated back to `options` (via `scripts/ablation-replace.mjs`,
anchor hit 1→0, blob `c37eadb4744e` → `55123d3e9226`) | **TOLERANT fail
1 (100%), WELL-FORMED AND WRONG 1, `TS2353 x1`** |
The instrument's own `FIRING_CONTROL` reported 5 diagnostics on both
runs, so the zero is a reading and not a dead search. Restore was proven
byte-identical by `git hash-object` (`c37eadb4744e…` before and after)
with `git diff HEAD` clean, not by the wrapper's exit code.
**Gates.** `node scripts/pm/dispatch-gates.mjs --repo
objectstack-ai/objectstack --commands` derived **60 families** from this
change set; all 60 were run and all recorded **exit 0**, reconciled with
`--ran`: `60 derived, 60 run, 0 NOT-MEASURED, 0 UNRUN` — a derived zero,
since every family recorded its code. Two answered **exit 3
(PREREQUISITE NOT MET — not a pass)** on the first pass,
`check:dual-build-cjs-loads` and `check:type-check-debt`; both state the
same prerequisite, a built workspace. It was cleared (`turbo run build
--filter='./packages/*' --filter='./packages/*/*'`, 72/72 successful)
and both re-run green.
**Per-package.** `pnpm --filter @objectstack/knowledge-ragflow test` →
10 passed (was 9). `pnpm --filter @objectstack/knowledge-ragflow
typecheck` → exit 0 across both of its legs (`tsc --noEmit`, then
`check:test-typecheck`, which reports 0 files / 0 errors / 0 pinned
signatures). `pnpm lint` over the whole repo → exit 0.
## Acceptance notes
Noted here, not fixed, not filed by this PR:
- **`content/docs/ai/knowledge-rag.mdx:37` still writes `options: {
datasetId: 'rgf_doc_dataset' }`** on a `ragflow` source. It is the same
defect in a second, hand-written document, and after this PR it is a
live one: an author copying it now gets a source the adapter refuses by
name. It is outside this card's file surface
(`packages/plugins/knowledge-ragflow/`), and `content/docs/**` brings
its own gate family, so it is reported to the dispatching seat to file
rather than ridden in here.
- **`.changeset/18915-published-readme-examples-compile.md` closes with
"One block is deliberately left"**, describing this README. That
changeset belongs to PR #18968 and covers 20 other packages; its text
becomes stale when both land. Left alone deliberately — it accurately
records what that PR did — and the closure is stated in this PR's own
changeset instead.
- **This adapter throws bare `Error`s, with no ADR-0112 envelope**
(`code` / `status`) on any refusal, so the new refusal test pins the
message text rather than an envelope. Introducing an envelope on this
seam is a contract decision well outside a patch to one adapter's key
spelling.
- Triage's escalation condition on the card (a real path parsing
`KnowledgeSourceSchema` ⇒ p1) is **still unmet in runtime code**: `git
grep KnowledgeSourceSchema` outside `packages/spec` returns zero
importers in `packages/**/*.ts` (positive control: 8,741
`*Schema.parse|safeParse` call sites repo-wide). The only parse call
sites are `packages/spec`'s own tests and a published-skill example.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01AhQASwqJr2Z7XfGWUdvnbF)_
---------
Co-authored-by: claude <noreply@anthropic.com>1 parent 7056ca5 commit cb005e0
5 files changed
Lines changed: 64 additions & 21 deletions
File tree
- .changeset
- packages/plugins/knowledge-ragflow
- src
- __tests__
Lines changed: 22 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
28 | | - | |
| 28 | + | |
29 | 29 | | |
30 | 30 | | |
31 | 31 | | |
| |||
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
39 | | - | |
| 39 | + | |
40 | 40 | | |
41 | 41 | | |
42 | 42 | | |
| |||
Lines changed: 24 additions & 5 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
| 12 | + | |
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
33 | | - | |
| 33 | + | |
34 | 34 | | |
35 | 35 | | |
36 | | - | |
37 | | - | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
38 | 57 | | |
39 | 58 | | |
40 | 59 | | |
| |||
106 | 125 | | |
107 | 126 | | |
108 | 127 | | |
109 | | - | |
| 128 | + | |
110 | 129 | | |
111 | 130 | | |
112 | 131 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
57 | 57 | | |
58 | 58 | | |
59 | 59 | | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
60 | 67 | | |
61 | | - | |
62 | | - | |
63 | | - | |
| 68 | + | |
| 69 | + | |
64 | 70 | | |
65 | 71 | | |
66 | | - | |
| 72 | + | |
67 | 73 | | |
68 | 74 | | |
69 | 75 | | |
70 | 76 | | |
71 | | - | |
| 77 | + | |
72 | 78 | | |
73 | | - | |
| 79 | + | |
74 | 80 | | |
75 | | - | |
76 | | - | |
| 81 | + | |
| 82 | + | |
77 | 83 | | |
78 | 84 | | |
79 | 85 | | |
| |||
Lines changed: 2 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
4 | | - | |
5 | | - | |
6 | | - | |
7 | | - | |
8 | | - | |
| 3 | + | |
| 4 | + | |
9 | 5 | | |
0 commit comments