Skip to content

Setup → Datasources: the default datasource reads "connected" while its Test and Sync answer that no driver is registered #24772

Closed

Description

@objectstack-fleet

Filing gate ③ a task the maintainer set: objectstack-ai/hotcrm#2188, the maintainer's browser pass of 2026-10-20. Each defect gets its own card, by the maintainer's ruling 「按照按照具体的issue单独提交卡片,不受数量限制。」 (recorded on objectstack-ai/hotcrm#2188, 6283467378). This is finding F-21 of track 2 (Setup as the system administrator), by the cloud tester session_01VuXyJvhGKJy8qeUvhKyxzv. It was measured on HotCRM main f22dfa52 with @objectstack/* 18.0.0-next.5, in Chromium at 1440×900 on a locally booted, seeded install. The evidence is on the branch claude/qa-setup-pass-2026-10-20 at ed4f40e42, which is never merged. Filed by the repo:hotcrm seat 2 (os-support-ai, session session_01KqkTQNLcxVc588eZpJmp1r). ⛔ Not a claim. Grade: triage's.

Reader (who acts): objectstack triage routes it.

The finding, as measured

  • Persona / URL: dev admin, Datasources.
  • Actual: card "default · sqlite · connected"; Test → 200 + toast "default: [ObjectQL] Datasource 'default' has no registered driver to introspect."; Sync objects → 400 GET /api/v1/datasources/default/remote-tables, then a dialog "No remote tables found on this datasource." A runtime :memory: datasource tests fine ("connection ok (0ms)"), and Setup has no edit or delete for it.
  • Evidence: 38-integrations-datasources-test.png, 38-integrations-datasources-sync-objects.png, 38-integrations-datasources-created.png.
  • class: a. Reach: every deployment.
  • Suspected landing: objectstack service-datasource (default datasource not registered for introspection) and console datasource page.
  • Dedupe words: no registered driver to introspect, remote-tables 400, datasource delete missing.

Seat review

  • Landing (seat review): service-datasource.

Dedupe

Method: semantic search_issues on objectstack-ai/objectstack and objectstack-ai/objectui, open and closed, using the finding's own dedupe words and a second phrasing; plus a grep of every issue title (objectstack #1–#24751, objectui #7–#13153) listed through the repo-scoped issues?state=all endpoint, because the semantic search can miss title words (objectstack#14743).

  • 15 hits in objectstack, 2 in objectui. The nearest is objectstack#24664 (remote-tables?schema=), a different defect. New.

Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 · 2026-10-20T08:52Z
    Session: session_01UmqzD97e14iws6hmVhgZ5y
    Account: os-support-ai (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-24772-default-datasource-status
    Worktree: objectstack-issue-24772
    Domain: domain:services
    Seat: domain:services#2 (seat post #21118)
    File surface: packages/services/service-datasource/src/** (the status the Datasources page reads for the default datasource, and its Test / remote-tables doors), its tests, one new .changeset/24772-*.md. ⛔ Not packages/objectql/** (a fix there is cross-lane: report it, do not edit), ⛔ not packages/spec/**, ⛔ no objectui edit (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: opus (TIER_DEFAULT; dispatch-gates --tier on this surface: no path-derived mandate, floor sonnet, default opus, ceiling fable)
    Clause-②: yes
    Responsibility: service-datasource reports the default datasource "connected" while its Test and remote-tables doors answer that no driver is registered for introspection | none known | every admin opening Setup → Datasources; measured on a HotCRM install 2026-10-20 (card)
    Thread-read: none
    Serial constraints cleared: no open PR touches packages/services/service-datasource (the file lists of all 18 open PRs read at this claim). The last change there, PR #24706 (#24664), landed as 60571dd179. Seat 1's in-flight cards are in plugin-security, plugin-approvals and service-settings' auth.manifest.ts.

    Correction at review: Clause-② changed from no to yes, per the seat record 6289043617 on PR #24852. The diff widens the published surface: ExternalDatasourceServiceConfig, exported from the package entry, gains the optional liveDriver member. Its changeset is minor.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 24772,
      "status": "needs_decision",
      "branch": "claude/issue-24772-default-datasource-status",
      "pr": null,
      "session": "session_01UmqzD97e14iws6hmVhgZ5y",
      "premise_still_valid": true,
      "summary": "All three readings reproduce on origin/main c3a8e07b6 source, through the real admin HTTP routes over a real ObjectQL engine, the real DatasourceConnectionService (connect asDefault, the DefaultDatasourcePlugin.init shape) and the real ExternalDatasourceServicePlugin: list status 'ok' (the UI's 'connected'); POST /api/v1/datasources/default/test -> 200 {ok:false, error:\"[ObjectQL] Datasource 'default' has no registered driver to introspect.\"}; GET /api/v1/datasources/default/remote-tables -> 400 EXTERNAL_DATASOURCE_ERROR, same message; a runtime sqlite :memory: datasource tests ok. M2 falsified: the default IS opened by service-datasource's DatasourceConnectionService (asDefault), and 'connected' is TRUE — the driver is live under its natural name com.objectstack.driver.sql. M1: the false answer is produced in packages/objectql, not service-datasource: ObjectQL.introspectDatasource does drivers.get(datasource), while ADR-0062 (#3826) registers the default under its natural name and records that routing to `default` never uses drivers.get('default'). M3: the default sqlite driver does introspect (engine.introspectDatasource by the natural name -> dialect sqlite), so route (i) is technically open. I stopped without editing for two reasons: (1) the producer is cross-lane (packages/objectql), which the dispatch says the seat declares first; (2) route (i) is not safe on its own — once introspection reaches the default, Sync lists, drafts and imports every platform table of the primary DB with the platform's own credentials, ObjectQL.assertWriteAllowed returns early for datasource 'default' and for every managed datasource, and I found no code enforcing ADR-0015 §4.2 ('object.external only when its datasource has schemaMode !== managed'). Which answer Sync owes a managed datasource is a contract decision (open_questions). M4: by design, not a defect — the card's own 38-integrations-datasources-created.png shows Edit and Delete on the runtime qa_mem row; only the code-origin `default` lacks them (datasource-admin-service.ts header: code-defined datasources are read-only; objectui hides both on origin 'code'). No edits, no commits, no PR.",
      "tests": "Measurement only, nothing committed. Dependency closure: `pnpm --workspace-concurrency=2 --filter '@objectstack/service-datasource^...' build` under os-verify-lock -> VERDICT command-exit 0. Scratch harness (kept at /tmp/claude-0/-home-user/baba1a33-5813-5ac5-906a-64b704dc6695/scratchpad/issue-24772/zz-measure-24772.test.ts, removed from the tree; objectql resolves to src through this package's vitest alias): `pnpm --filter @objectstack/service-datasource exec vitest run --maxWorkers=2 src/__tests__/zz-measure-24772.test.ts` -> VERDICT command-exit 0, 4 passed. Readings: engine default driver name -> com.objectstack.driver.sql; admin list -> default status ok, qa_mem status ok; HTTP POST /api/v1/datasources/default/test -> 200 {\"ok\":false,\"error\":\"[ObjectQL] Datasource 'default' has no registered driver to introspect.\"}; HTTP GET /api/v1/datasources/default/remote-tables -> 400 {\"code\":\"EXTERNAL_DATASOURCE_ERROR\"} same message; HTTP POST /api/v1/datasources/qa_mem/test -> 200 {\"ok\":true,\"tableCount\":0}; GET qa_mem/remote-tables -> 200 {\"tables\":[]}; M3 introspectDatasource(natural name) -> {\"dialect\":\"sqlite\"}; runtime memory datasource qa_ram: connect -> connected, POST /test -> 200 {\"ok\":false,\"error\":\"[ObjectQL] Driver for datasource 'qa_ram' does not support introspectSchema().\"}; option A simulated on the INSTANCE (objectql source untouched): Test default -> {\"ok\":true,\"tableCount\":1}, remote-tables default -> [{\"name\":\"acct\",\"columnCount\":2}]; option-B premise: checkHealth() on the default (natural name) -> true, on the memory runtime datasource -> true; resolving a MEMORY default to its natural name makes the engine name the driver as the datasource: \"[ObjectQL] Driver for datasource 'com.objectstack.driver.memory' does not support introspectSchema().\" The harness collapses DefaultDatasourcePlugin's local and shared connection services into one instance (state 'connected' instead of the shared service's 'already-registered'); both map to availability 'available' -> status 'ok'. A full `pnpm dev` boot on main: NOT MEASURED. Ablation: not applicable (no tested behaviour changed).",
      "gates": "No diff, so nothing to gate: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` -> exit 2, 'this branch changes nothing against origin/main (merge base c3a8e07b6) — nothing to derive'. The PM's 49-command reading was not executed (no diff to read). No PR, so no CI check-runs to cite. --ran reconciliation: not applicable.",
      "mcp_calls": "0",
      "api_writes": "1 — POST /repos/objectstack-ai/objectstack/issues/24772/comments (this os-dev-report, written by scripts/pm/post-stamped.mjs; transport chosen and printed by the tool). The empty-branch `git push` is not a REST write.",
      "line_budget": "n/a — zero lines changed; no skills/** or ratcheted ledger touched",
      "deviations": [
        "Stopped before any edit and opened no PR: the producer of the false answer is packages/objectql (cross-lane per the dispatch and the claim's file surface), and route (i) needs a contract decision first.",
        "The pushed branch claude/issue-24772-default-datasource-status carries no commits (it sits at c3a8e07b6, the write-route probe).",
        "The measurement test lived in packages/services/service-datasource/src/__tests__ while it ran (vitest needs the package config), was never committed, and was removed; the worktree was clean before removal.",
        "Option A was measured by an instance-level override in the scratch harness, not by editing packages/objectql."
      ],
      "files_changed": [],
      "open_questions": [
        {
          "question": "The default datasource's 'connected' is true; its Test and Sync are false because ObjectQL.introspectDatasource ignores ADR-0062's default-driver rule. What should Test and Sync answer for the default datasource, and what does Sync owe any managed datasource? Making introspection reach the default would put every platform table of the primary DB behind Sync: assertWriteAllowed exempts 'default' and every managed datasource, and nothing I found enforces ADR-0015 §4.2. The end-to-end import over a platform table was NOT MEASURED.",
          "options": [
            "A — Engine fix only, in packages/objectql (cross-lane): introspectDatasource resolves `default` through the default-driver rule (when no driver is literally named 'default'), and its messages keep naming the datasource. Cost: about 5 source lines, 3 objectql cases, 1 service-datasource end-to-end pin, and a patch changeset on @objectstack/objectql. Simulated effect: Test default ok:true, and Sync lists the primary DB's tables. Axes: business need is real for Test, but no producer needs Sync over platform tables (those tables ARE the platform's objects). Long-term, it contradicts ADR-0015 §1 for the managed primary. AI-error: it opens a door an agent admin can walk into (federate sys_secret / sys_account, with no write gate). Startup: it opens a capability nobody asked for. Not recommended alone.",
            "B — In-lane, service-datasource. listRemoteTables, generateObjectDraft, importObject and refreshCatalog refuse a schemaMode 'managed' datasource with the existing 400 EXTERNAL_DATASOURCE_ERROR, naming ADR-0015's rule. testConnection becomes a connectivity probe: it resolves the datasource's registered driver (the ADR-0062 rule for `default`, which DatasourceConnectionService.disconnect already applies; ideally one shared resolver there) and answers driver.checkHealth(), measured true for the sqlite default and for a memory datasource. Cost: medium. Clause-② turns (narrowing): Sync on managed RUNTIME datasources (the tester's qa_mem lists 200 today) becomes a 400, so it needs a BREAKING changeset with a migration line. objectui should hide Sync on managed rows; schemaMode is already in the list payload, so no API change. It also closes the memory/mongodb Test sibling. Axes: it keeps the Test need and drops a federation path ADR-0015 never declared. It enforces a declared invariant at the door (declared = enforced), refuses loudly where an AI would otherwise federate platform storage, and retires immediately with no shim.",
            "C — A + B: the engine fix (cross-lane) plus B's managed refusal; Test may stay introspection-based and keep tableCount. Most complete; two lanes; worth it only if the maintainer wants the engine contract fixed now regardless of Sync.",
            "D — Minimal, in-lane, Clause-② stays no. Test on `default` reaches the default driver (ADR-0062 rule plus checkHealth). remote-tables and object-draft on `default` keep today's 400 EXTERNAL_DATASOURCE_ERROR, with a true message ('the platform's managed primary datasource is not a federation source'). No status or code change on any route. Cost: small. It special-cases the host-reserved name and leaves the ADR-0015 managed-invariant gap on other managed datasources for a separate card."
          ],
          "recommendation": "B. It is the one option that makes all three answers on the page true for every datasource (status, Test, Sync). It enforces ADR-0015's declared managed/external line at the door instead of opening federation over platform storage, and it stays in this lane (no objectql edit). It also closes the memory/mongodb Test sibling. The startup-phase rule favours retiring the undeclared managed-Sync path at once. D if the seat wants no breaking change in this release. A is unsafe without B's guard. Whatever is chosen, ObjectQL.introspectDatasource's ADR-0062 inconsistency can be carded separately for the objectql lane."
        }
      ],
      "out_of_scope_findings": [
        "class: a · reach: public door POST /api/v1/datasources/qa_ram/test through the real admin route, on a runtime `memory` datasource (memory is in the Setup driver catalog, driver-catalog.ts), answered 200 {ok:false, error:\"[ObjectQL] Driver for datasource 'qa_ram' does not support introspectSchema().\"} while the list reports status ok ('connected'). mongodb is inferred, NOT MEASURED: MongoDBDriver has no introspectSchema. Producer: ExternalDatasourceService.testConnection uses introspection as its connectivity probe. Same family as #24772: option B closes it; otherwise file it as a sub-issue of #24772 · dedupe: testConnection introspectSchema, memory datasource Test fails, does not support introspectSchema connected, mongodb datasource test",
        "class: a · reach: the card's own screenshot 38-integrations-datasources-test.png (HotCRM, @objectstack 18.0.0-next.5) shows a green success toast (check icon) carrying the failure text · Seam: renderer: objectui packages/app-shell/src/views/metadata-admin/datasource/DatasourceResourcePage.tsx test() — calls toast.success for both ok and ok:false (objectui main 91b658a) · dedupe: datasource Test success toast on failure, toast.success ok false, connection test green toast",
        "class: a · reach: the card's own screenshot 38-integrations-datasources-sync-objects.png shows the dialog 'No remote tables found on this datasource.' after a refused introspection (error toast plus empty-state copy) · Seam: renderer: objectui DatasourceResourcePage.tsx openSync() — its catch sets tables to [] so a refusal renders as an empty datasource (objectui main 91b658a) · dedupe: Sync objects empty state on error, No remote tables found refusal, remote-tables 400 dialog",
        "carrier: #24772 (this decision) · ADR-0015 §4.2 states 'object.external only when its datasource has schemaMode !== managed' is enforced at metadata-load time; a repo grep finds no enforcing site, and ObjectQL.assertWriteAllowed returns early for 'default' and for managed datasources. Today it bites only managed RUNTIME datasources, whose credentials the admin supplied. Option A would extend it to the platform's primary DB. Noted, not filed: no public-door measurement of an import was taken."
      ]
    }

    Generated by Claude Code

  3. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    Seat ruling · #24772 · domain:services seat 2 (seat post #21118) · os-support-ai · session_01UmqzD97e14iws6hmVhgZ5y · 2026-10-20T09:23Z. It answers the dev's open question (report 6287715439). Basis: PM discretion. No escalation condition holds: the governing text below decides between the options for this card, and the chosen route changes no status, code or accepted value. The maintainer can veto; this is not a permission gate.

    Ruled: route D, widened to the Test sibling

    1. Test answers truthfully for every datasource the page lists.
      • For default, the driver is resolved by ADR-0062's default-driver rule: the default is registered under its natural name, and routing default never uses drivers.get('default'). Reuse the one resolver service-datasource already applies (DatasourceConnectionService.disconnect); ⛔ do not copy it.
      • Whether Test then introspects by the resolved name (keeping tableCount) or answers checkHealth() is the dev's measured choice. State it in the PR body.
      • For a driver with no introspectSchema (the dev measured memory; mongodb is inferred), Test answers the connectivity probe and says introspection is not supported, instead of ok: false on a connected datasource. That is the dev's out-of-scope finding 1, the same defect, so it is in this card.
    2. Sync on default keeps refusing with the existing 400 EXTERNAL_DATASOURCE_ERROR, with a true message: the platform's managed primary datasource is not a federation source (ADR-0015 §1). This covers remote-tables, object draft and import.
    3. No status code, error code or accepted value moves on any route. Clause-②: no.
    4. ⛔ No packages/objectql edit. ⛔ No change to Sync on other managed runtime datasources (route B's narrowing, below).

    Governing text: ADR-0062 (the default datasource is registered under its natural name; default resolves through the default-driver rule). ADR-0015 §1 and §4.2 (object.external only when the datasource's schemaMode is not managed).

    Premises the dev re-checks first (each a fork if false)

    • P1. The ADR-0062 resolver used by DatasourceConnectionService.disconnect is callable from the Test path without an objectql change.
    • P2. Every driver in the Setup driver catalog that lacks introspectSchema has a checkHealth() (or an equivalent connectivity probe) to answer with.
    • ⛔ If either fails, or the route needs an objectql edit or a status/code change, report a fork. Do not force it through, and do not fall back to A, B or C without saying so.

    Why not A, B or C on this card

    • A (the engine resolves default in introspectDatasource) alone makes Sync list and import the primary database's platform tables. assertWriteAllowed exempts default and managed datasources, so no write gate would stand behind it. Not taken.
    • B narrows a REST door (Sync on a managed runtime datasource answers 200 today and would answer 400) and needs a breaking changeset. That is protocol class, and its timing is the maintainer's. It is filed as its own card from this ruling, with this report's analysis as its evidence.
    • C is A + B. It waits on B.
    • ObjectQL's introspectDatasource not applying ADR-0062 is recorded on B's card. Fixing it alone is A, which is unsafe without B.

    维护者速读

    要定什么: 数据源页面上,默认数据源显示「已连接」(这是真的),但「测试」和「同步」都报「没有驱动」。席位按自身裁量定了路线 D,你可以否决。

    • D 是什么: 「测试」按 ADR-0062 的规则找到默认数据源的真实驱动并如实回答;内存这类不支持表结构读取的驱动,也改为如实回答「已连接、但不支持读取表结构」。「同步」对默认数据源继续拒绝,但提示改成真实原因:平台自己的主库不是外部数据源。
    • 不改什么: 任何接口的状态码、错误码都不变,不改 objectql。
    • 另立一张卡给你定: 托管(managed)数据源目前仍能「同步」出外部对象,这与 ADR-0015 的规定不符。收紧它会让现有的一个接口从 200 变成 400,属于破坏性变更,是否放进 18.0 由你定。

    Generated by Claude Code

  4. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    Filed from report 6287715439 and ruling 6287770114 · domain:services seat 2 · session_01UmqzD97e14iws6hmVhgZ5y · 2026-10-20T09:25Z

    The dev is implementing route D under claim 6287232559.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 24772,
      "status": "done",
      "branch": "claude/issue-24772-default-datasource-status",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/24852",
      "session": "session_01UmqzD97e14iws6hmVhgZ5y",
      "premise_still_valid": true,
      "summary": "Route D, widened as the seat ruled (comment 6287770114). P1 and P2 were re-checked first, and both hold. P1: the resolver disconnect() applied needs only getDefaultDriverName / getDriverByName, which are on IDataEngine, so no objectql change is needed. P2: memory and mongodb, the catalog's two drivers without introspectSchema, both implement checkHealth(), which IDataDriver declares as required. The resolver is extracted from DatasourceConnectionService.disconnect() as registeredDriverName(): disconnect() calls it with its own flag (behaviour unchanged), and the Test path reuses it through a new optional liveDriver seam that the plugin wires. Test on `default` answers checkHealth(): 200 {ok:true, latencyMs}, and the platform database is not introspected. Test on a driver without introspectSchema answers checkHealth() plus introspection:'unsupported'. A failed health check gives ok:false. Every other datasource keeps the old introspection probe and its tableCount. Sync on `default` (listRemoteTables, generateObjectDraft, importObject, and refreshCatalog under the bounded exemption) refuses before any introspection, with the same 400 EXTERNAL_DATASOURCE_ERROR, or EXTERNAL_IMPORT_ERROR on the import, and the true reason: it is the platform's managed primary datasource, not a federation source. Measured choice: checkHealth() over introspection by the resolved name. With the real SqlDriver on in-memory SQLite, introspectSchema took 14.0 ms at 10 tables and 132.0 ms at 120 tables; checkHealth took 0.79 ms and 0.28 ms. Clause-② is `no`, as ruled. Saying 'introspection unsupported' needed one optional response key (introspection), and the seam one optional config member (ExternalDatasourceServiceConfig.liveDriver). Both are named in the PR body so the seat can confirm the reading. No packages/objectql edit, and no change to Sync on other managed runtime datasources (pinned). PR body first line `Fixes #24772`.",
      "tests": "At HEAD 07aba4704 (origin/main 5fcc79497 merged): `pnpm --filter @objectstack/service-datasource test` -> 48 files, 862 tests passed, 41.48 s (VERDICT command-exit 0). `pnpm --filter @objectstack/service-datasource typecheck` -> exit 0; `tsc --listFiles` includes the new test (count 1). `pnpm --filter @objectstack/service-datasource build` -> exit 0, check-dts-emitted 4/4. `pnpm --workspace-concurrency=2 --filter '@objectstack/service-datasource^...' build` -> VERDICT command-exit 0. New file src/__tests__/primary-datasource-test-and-sync.test.ts: 10 cases, real ObjectQL source plus the connection service asDefault plus the plugin wiring plus the admin routes over Hono. Ablations ran through scripts/ablation-replace.mjs (anchor x1 -> x0, blob changed, restore proven blob == HEAD and `git diff HEAD` empty), each red as predicted: A1, Test path looks up by raw name -> 1 failed `expected { ok: false, …(1) } to match object { ok: true }`; A2, route A put back (no listRemoteTables guard + introspect resolves default) -> 2 failed `expected 200 to be 400` and listRemoteTables('default') resolved a value; A3, memory back to the introspection probe -> 2 failed `expected { ok: false, …(1) } to match object { ok: true, …(1) }`; A4, Test on default introspects by the resolved name -> 1 failed `expected { ok: true, latencyMs: 8, …(1) } to not have property \"tableCount\"`; A5, failed health check ignored -> 1 failed `expected true to be false`. The subject is this package's src, imported relatively, so no build sits between mutation and reading. test:repo was not run locally: CI owns it, and this diff touches no test of that project.",
      "gates": "Local: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` at 9e06f3d41 and again at 07aba4704 gave the same 69 commands. Each was run with its exit code captured before any pipe: 68 exit 0, and 1 NOT MEASURED. `pnpm check:dual-build-cjs-loads` exited 3, 'PREREQUISITE NOT MET — this gate reads built output, and some package has no dist/', because this worktree built only the service-datasource closure; CI's Lint & Repo Gates is its reading. `--ran` with `CMD :: exit N` lines -> '69 derived, 68 run, 1 NOT-MEASURED, 0 UNRUN', exit 0. check-platform-checklist is not owed: no exported symbol is renamed or deleted. CI on PR 24852 head 07aba4704 at report time: 'No other open PR may claim the same issue' success; '18.x upgrade harness (opt-in)' and 'Packed-tarball smoke (opt-in)' skipped. The rest are in_progress: Lint · PM dispatch-gates, Lint · ESLint, Lint · scoped · tooling self-tests, Type Check · workspace, Type Check · debt ledger, Type Check · consumer gates, Lint · CI, release & engine gates, Lint · docs & code guards, Lint · scoped · slot lookup & corpus, Lint · scoped · query-options erasure, Type Check · source gates, Lint · repo & tooling gates, Check PR Size, filter, Governed Surface Queue Guard, Check Documentation Links, The card this PR closes must claim this branch, Check Changeset, Flag docs affected by code changes, No other open PR may claim the same single-writer path, Part-of PR must not also close its card. Not awaited, per contract.",
      "mcp_calls": "0",
      "api_writes": "This round, 2 relay strokes: (1) pr_create through scripts/pm/fleet-write/dispatch.mjs, relay run 39409026658 success: POST /repos/objectstack-ai/objectstack/pulls (draft) and POST /repos/objectstack-ai/objectstack/issues/24852/assignees; read-back 10998 of 10998 bytes identical, assignee os-support-ai, no labels sent. (2) This os-dev-report through scripts/pm/post-stamped.mjs: POST /repos/objectstack-ai/objectstack/issues/24772/comments. Earlier round: 1 comment, POST /repos/objectstack-ai/objectstack/issues/24772/comments (6287715439). `git push` x4 is not a REST write.",
      "line_budget": "n/a: no skills/** or ratcheted ledger touched. Diff vs origin/main: 5 files, +453 / -4.",
      "deviations": [
        "refreshCatalog('default') gets the same refusal under the bounded in-place exemption: the same defect class (the same false 'no registered driver' for default), the same file and helper, the same 400 EXTERNAL_DATASOURCE_ERROR its REST door served. The ruling named remote-tables, draft and import. The PR body names this.",
        "The two additive optional surface items (Test answer key `introspection`, config member `liveDriver`) sit under the ruled `Clause-②: no`. They are named in the PR body and the changeset rather than chosen silently.",
        "Branch merged origin/main twice (fast-forward to 08d201a80, then merge commit 07aba4704 bringing in 5fcc79497); neither touched service-datasource. The merge commit carries git's default message with no trailers.",
        "Worktree /home/user/objectstack-issue-24772 removed after the PR opened (clean status, node_modules deleted first, no --force)."
      ],
      "files_changed": [
        ".changeset/24772-primary-datasource-test-sync.md",
        "packages/services/service-datasource/src/__tests__/primary-datasource-test-and-sync.test.ts",
        "packages/services/service-datasource/src/datasource-connection-service.ts",
        "packages/services/service-datasource/src/external-datasource-service.ts",
        "packages/services/service-datasource/src/plugin.ts"
      ],
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: none (承接者:无) · noted, not filed: an unmeasured read of the code only · The DRAFT probe (DatasourceAdminServicePlugin.probe, behind POST /api/v1/datasources/test) awaits `driver.checkHealth()` and discards its boolean, so a driver whose health check answers false would report ok:true. No public-door reading was taken. The seat may add it to PR 24852's Acceptance notes."
      ]
    }

    Generated by Claude Code

  6. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 24772,
      "status": "done",
      "branch": "claude/issue-24772-default-datasource-status",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/24852",
      "session": "session_01UmqzD97e14iws6hmVhgZ5y",
      "premise_still_valid": true,
      "summary": "Patch round 1, per seat record 6289043617 on PR 24852, at head 3226d4019. Both items are done. (1) `.changeset/24772-primary-datasource-test-sync.md` is now `'@objectstack/service-datasource': minor`. Its first body line is `Clause-②: yes (widening: the published ExternalDatasourceServiceConfig, exported from the package entry, gains one optional member, the liveDriver callback; ...)`, and it gains a bullet naming `ExternalDatasourceServiceConfig.liveDriver` as the new optional surface. scripts/pm/clause2-line.mjs reads it as declared, yes, widening. `liveDriver` is kept. (2) The `introspection: 'unsupported'` key and its type member are dropped: testConnection's return type is byte-identical to origin/main's again. A driver without introspectSchema now answers its health probe as `{ ok: true, latencyMs }` with no tableCount, like `default`. The pins for both now assert the exact answer keys ['latencyMs','ok']. The PR body was not edited. The exact replacement text the seat can apply is in `pr_body_edits` (old/new pairs), including the draft-probe note for Acceptance notes. No merge of origin/main this round: PR mergeable, no conflict, and no main-caused red (AGENTS.md §10).",
      "pr_body_edits": [
        {
          "where": "line 2, the whole line (the same text also appears inside the section replaced below)",
          "old": "Clause-②: no",
          "new": "Clause-②: yes (widening)"
        },
        {
          "where": "What changed, Test sub-bullet",
          "old": "  - for a driver with no `introspectSchema` (`memory`, `mongodb`), answers `checkHealth()` and says `introspection: 'unsupported'`, instead of `ok: false`;",
          "new": "  - for a driver with no `introspectSchema` (`memory`, `mongodb`), answers `checkHealth()` with the answer's existing keys, `{ ok: true, latencyMs }` and no `tableCount`, instead of `ok: false`;"
        },
        {
          "where": "Evidence after the change, third bullet",
          "old": "- A `memory` datasource tests `{ ok: true, introspection: 'unsupported' }`. A registered driver whose health check answers `false` or throws gives `ok: false`.",
          "new": "- A `memory` datasource tests `{ ok: true, latencyMs }`, exactly those two keys. A registered driver whose health check answers `false` or throws gives `ok: false`."
        },
        {
          "where": "ablation table, A3 row",
          "old": "| A3 | a driver without `introspectSchema` goes back to the introspection round trip | red, 2 failed: `expected { ok: false, …(1) } to match object { ok: true, …(1) }` |",
          "new": "| A3 | a driver without `introspectSchema` goes back to the introspection round trip | red, 2 failed: `expected { ok: false, …(1) } to match object { ok: true }` (re-run at `3226d4019`) |"
        },
        {
          "where": "ablation table, A4 row",
          "old": "| A4 | Test on `default` introspects by the resolved name | red, 1 failed: `expected { ok: true, latencyMs: 8, …(1) } to not have property \"tableCount\"` |",
          "new": "| A4 | Test on `default` introspects by the resolved name | red, 1 failed: `expected [ 'latencyMs', 'ok', 'tableCount' ] to deeply equal [ 'latencyMs', 'ok' ]` (re-run at `3226d4019`) |"
        },
        {
          "where": "ablation table, new row after A5",
          "old": "| A5 | a failed health check is ignored | red, 1 failed: `expected true to be false` |",
          "new": "| A5 | a failed health check is ignored | red, 1 failed: `expected true to be false` |\n| A6 | the dropped `introspection` key put back on a driver that cannot introspect | red, 1 failed: `expected [ 'introspection', 'latencyMs', 'ok' ] to deeply equal [ 'latencyMs', 'ok' ]` (at `3226d4019`) |"
        },
        {
          "where": "replace the whole section (heading, paragraph, two bullets)",
          "old": "## Two additive surface items, named so the Clause-② reading can be checked\n\n`Clause-②: no` is the seat's ruling: no status code, error code or accepted value moves on any route. Saying \"introspection is not supported\", as the ruling requires, needed one optional response key. Reaching the live driver needed one optional config member. Both are additive and optional:\n\n- Test's answer can carry `introspection: 'unsupported'`. The route is console-only (`datasource-route-ledger.ts` gives it no SDK disposition).\n- `ExternalDatasourceServiceConfig.liveDriver?`. A host that builds the service without it keeps the old probe.",
          "new": "## The published-surface addition: Clause-② yes (widening)\n\n`ExternalDatasourceServiceConfig` is exported from the package's `.` entry, so its new optional member `liveDriver` widens the published surface. The changeset is a `minor` bump that declares `Clause-②: yes (widening)` and names that member. No status code, error code or accepted value moves on any route. Test's answer keeps its existing keys (`ok`, `latencyMs`, `tableCount`, `error`): the `introspection` key from the first head was dropped, because nothing reads it.\n\n- `ExternalDatasourceServiceConfig.liveDriver?`: a host that builds the service without it keeps the old probe."
        },
        {
          "where": "Acceptance notes, new last bullet",
          "old": "- **Not in this PR, per the ruling.** `ObjectQL.introspectDatasource` still does not apply ADR-0062 (no objectql edit). Sync on other managed runtime datasources is unchanged (route B, filed separately by the seat). The two objectui renderer findings are filed by the seat.",
          "new": "- **Not in this PR, per the ruling.** `ObjectQL.introspectDatasource` still does not apply ADR-0062 (no objectql edit). Sync on other managed runtime datasources is unchanged (route B, filed separately by the seat). The two objectui renderer findings are filed by the seat.\n- **Noted, not filed: the draft probe discards the answer of `checkHealth()`.** `DatasourceAdminServicePlugin.probe`, behind `POST /api/v1/datasources/test`, awaits `driver.checkHealth()` and ignores the boolean it returns, so a draft whose driver's health check answers `false` would report `ok: true`. This comes from reading the code only: no public-door reading was taken."
        },
        {
          "where": "Verification, header line",
          "old": "At HEAD `07aba4704` (after merging `origin/main` `5fcc79497`):",
          "new": "At HEAD `3226d4019` (no further merge of `origin/main`: no conflict and no main-caused red, AGENTS.md §10):"
        },
        {
          "where": "Verification, test line",
          "old": "- `pnpm --filter @objectstack/service-datasource test`: 48 files, 862 tests passed, 41.5 s.",
          "new": "- `pnpm --filter @objectstack/service-datasource test`: 48 files, 862 tests passed, 47.6 s."
        }
      ],
      "tests": "At 3226d4019: closure build, then `pnpm --filter @objectstack/service-datasource build` (check-dts-emitted 4/4), typecheck (exit 0) and test (48 files, 862 passed, 47.61 s), chained with && under os-verify-lock -> VERDICT command-exit 0. Ablations on the changed pins ran through scripts/ablation-replace.mjs; each restore was proven blob == HEAD with `git diff HEAD` empty. A3 (memory back to the introspection probe) -> red, 2 failed: `expected { ok: false, …(1) } to match object { ok: true }` and `expected 'introspect must not be reached' to contain 'health check'`. A4 (Test on default introspects by the resolved name) -> red, 1 failed: `expected [ 'latencyMs', 'ok', 'tableCount' ] to deeply equal [ 'latencyMs', 'ok' ]`. A1 (raw-name lookup) -> red, 1 failed: `expected { ok: false, …(1) } to match object { ok: true }`. New A6 (the dropped `introspection` key put back) -> red, 1 failed: `expected [ 'introspection', 'latencyMs', 'ok' ] to deeply equal [ 'latencyMs', 'ok' ]`. A2 and A5 pins are unchanged; their round-0 readings stand.",
      "gates": "Local, at 3226d4019: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` gave 69 commands, the same list as the previous head. Each was run with its exit code captured before any pipe: 68 exit 0 and 1 NOT MEASURED. `pnpm check:dual-build-cjs-loads` exited 3, PREREQUISITE NOT MET: it needs every package's dist, and this worktree builds only the service-datasource closure. `--ran` with `CMD :: exit N` lines: '69 derived, 68 run, 1 NOT-MEASURED, 0 UNRUN', exit 0. CI on PR 24852 head 3226d4019 at report time: all 41 check-runs completed, 34 success, 7 skipped, 0 failure. The six read by name: Test Core=success, TypeScript Type Check=success, Lint & Repo Gates=success, Build Core=success, Governed Surface Queue Guard=success, Check Changeset=success. Lint & Repo Gates covers the locally unmeasured dual-build-cjs-loads.",
      "mcp_calls": "0",
      "api_writes": "This round 1: POST /repos/objectstack-ai/objectstack/issues/24772/comments (this os-dev-report, scripts/pm/post-stamped.mjs via the relay). No PR body PATCH and no label write. `git push` x1 (3226d4019) is not a REST write. Earlier rounds: POST /pulls plus POST /issues/24852/assignees (pr_create), and 2 os-dev-report comments on #24772.",
      "line_budget": "n/a: no skills/** or ratcheted ledger touched. Diff vs origin/main 5fcc79497: 5 files, +451 / -3.",
      "deviations": [
        "The PR body still reads `Clause-②: no` and mentions the dropped `introspection` key until the seat applies `pr_body_edits`. The dev writes the body only once.",
        "The previous head's PR body says Verification was at 07aba4704; this round's readings are at 3226d4019 (pr_body_edits carries the replacement).",
        "Worktree /home/user/objectstack-issue-24772 recreated from the remote branch for this round, then removed after the push (clean status, node_modules deleted first, no --force)."
      ],
      "files_changed": [
        ".changeset/24772-primary-datasource-test-sync.md",
        "packages/services/service-datasource/src/__tests__/primary-datasource-test-and-sync.test.ts",
        "packages/services/service-datasource/src/datasource-connection-service.ts",
        "packages/services/service-datasource/src/external-datasource-service.ts",
        "packages/services/service-datasource/src/plugin.ts"
      ],
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  7. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #24852 comment 6289983622 · domain:services seat 2 · session_01UmqzD97e14iws6hmVhgZ5y · 2026-10-20T11:38Z


    Generated by Claude Code

  8. objectstack-fleet commented on Oct 20, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:services seat 2 · os-support-ai · session_01UmqzD97e14iws6hmVhgZ5y · 2026-10-20T12:06Z

    Reading Value
    PR #24852 timeline added_to_merge_queue 2026-10-20T11:41Z → merged 2026-10-20T12:05Z
    origin/main merge commit 6b9e6df909 is an ancestor (git merge-base --is-ancestor, exit 0)
    By content on origin/main external-datasource-service.ts carries primaryDatasourceNotFederatedError (6 hits)
    This card closed completed by the PR's Fixes #24772; pm:dispatched removed in this act

    ACCEPT 6289983622 and contract review 6289966933 are on the PR. Route B (Sync on a managed datasource, ADR-0015 §4.2) is #24837. The renderer half is objectstack-ai/objectui#13207.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:apiThe API a customer can call, and integrations — REST, connectors, webhooks, jobsbugSomething isn't workingdomain:servicespriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions