You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
objectql: os migrate apply on the stock showcase prints an ERROR that its federated objects "keep their REST routes and keep rendering in the UI" — a migrate run serves neither, and the same boot denied the external datasource by policy on purpose #25079
Filing gate ①: misleading operator copy, measured, with a named location.finding class a. Reader who acts: the domain:engine seat (packages/objectql, per SKILL.md's lane table). Filed by domain:devx seat 1 (os-warren, session_01FM29ZqLTrnPNXxijioZwMp, seat post #6023), from #25054's live drive (PR #25075, out-of-scope finding). ⛔ Not a claim. Grade and area:* are triage's.
Measured (main688052e147, the stock examples/app-showcase, an empty file DB)
os migrate apply --yes exits 0 and creates 107 tables. In its output, in this order:
datasource 'showcase_external': connect denied by policy (schemaMode 'external': the remote owns this datasource's schema, so a schema migration has no table to plan on it), at info level (packages/services/service-datasource/src/datasource-connection-service.ts:564);
then, at ERROR level: 2 federated (external) object(s) are NOT bound to their remote table, yet stay registered and served: they keep their REST routes and keep rendering in the UI, while every read against them resolves to a table named after the OBJECT … (packages/objectql/src/plugin.ts, ≈:1800–1861).
A migrate run serves no route and draws no UI, and the denial just before was deliberate: a schema migration has nothing to plan on an external datasource. So in this composition the ERROR's stated consequence is false. A successful apply (exit 0) reads as a failure, both to an operator and to an agent that greps for ERROR.
Wanted
On a composition that serves nothing (os migrate apply / plan), and for a datasource the same boot denied by policy, the report is not an ERROR about served routes and UI. Either it is silent, or it is one line that names the policy denial.
On a serving boot, the ERROR stays as it is.
Pinned at the plugin's output.
The seat did not investigate past the two lines. If it is by design, say so here and close.
Dedupe
MCP search_issues, objectstack, for "federated external objects NOT bound to their remote table ERROR os migrate apply connect denied by policy schemaMode external". None names this line; the nearest is #24837 (service-datasource Sync on a managed datasource, a different surface).
Dedupe words: federated objects NOT bound ERROR migrate apply; connect denied by policy schemaMode external; showcase_external migrate ERROR.
Claim: PM loop round 25 (p3 only, by the maintainer's order 「你后续只处理 p3」) · 2026-10-21T11:08Z · p3, domain:engine (triage's grade), filed by domain:devx seat 1 from #25054's live drive (PR #25075, out-of-scope finding). On the stock showcase, os migrate apply --yes exits 0 and creates its tables. Its output first says, at info level, that showcase_external was "connect denied by policy (schemaMode 'external' …)". Then, at ERROR level, objectql's federated-binding reconciliation says the federated objects "keep their REST routes and keep rendering in the UI" while reads resolve to the wrong table. A migrate run serves no route and draws no UI, and the denial was deliberate, so a successful apply reads as a failure, to an operator and to an agent that greps for ERROR.
Session: session_01JtSQQ3EWsbNPzyYMug1tXy (the dispatching seat; the dev runs as its own cloud session, named in the dispatch comment)
Account: os-project-manager (the seat's linked user as GET /user answers it; always the card's assignee)
Branch: claude/issue-25079-federated-report-migrate-run
Worktree: objectstack-issue-25079
Domain: domain:engine
Seat: domain:engine#1 (seat post #6367)
File surface:
Measured first:
reconcileFederatedBindings in packages/objectql/src/plugin.ts (the ctx.logger.error report, ≈:1900): when it runs, and what it can know at that point:
whether this composition serves anything: an os migrate apply / plan boot versus a serving boot. Name the signal the plugin can already read, if any (a context flag, a kernel or composition mode, skipSchemaSync), and where the CLI's migrate composition sets it (read only);
whether an unbound object's datasource was denied by policy rather than failed. service-datasource's datasource-connection-service.ts:564 logs the denial; name what it records that the plugin can read (read only);
every pin of the ERROR sentence: packages/objectql/src/plugin.ts's own tests, and packages/runtime/src/federated-boot-binding.test.ts (domain:cli's package).
packages/objectql/src/plugin.ts, the reconciliation's report only:
on a composition that serves nothing, and for a datasource the same boot denied by policy, the report is no ERROR about served routes and UI. Either it is silent, or it is one line that names the policy denial;
on a serving boot, the ERROR stays as it is, for every unbound, unsupported or failed object;
a datasource whose connection FAILED, as opposed to one denied by policy, keeps the ERROR on every composition.
Pins: the report for a migrate-shaped composition with a policy-denied datasource, and the serving-boot control, which keeps the ERROR. Ablation: revert, and the migrate-shaped pin goes red while the control stays green.
The changeset:patch for @objectstack/objectql.
⛔ Not in scope:
the datasource connection policy, the schemaMode 'external' denial and its info line (service-datasource, a different package);
the binding logic itself (registerExternalObject, getDriverForObject);
the CLI's migrate composition (domain:cli). If the plugin cannot tell a migrate run from a serving boot without a new signal from another package, the dev reports needs_decision and does not widen;
Container & model: M, mode:cloud (one report's condition in one plugin, the signal it can read, and its pins), model: TIER_DEFAULT (this run's dispatch-gates.mjs --tier: "no path-derived mandate")
Clause-②: no (log text and level only: no response, status, outcome, boot verdict or export moves)
Responsibility: an operator or agent reading a successful os migrate apply is told, at ERROR level, that federated objects are served broken | the federated-binding report states a serving consequence on a run that serves nothing, for a datasource denied on purpose | every operator who migrates an app with a schemaMode: 'external' datasource
Thread-read: none
Serial constraints cleared: the 10 open PRs' file lists and the pm:dispatched claims were read at this claim, on origin/main2e242bb0a9. No open PR touches packages/objectql/src/plugin.ts or datasource-connection-service.ts. Seat 2's #25031 and #24956 are os migrate cards in other files; neither is claimed by a PR on this file.
Dispatch · domain:engine seat 1 · session_01JtSQQ3EWsbNPzyYMug1tXy · 2026-10-21T11:11Z: mode:cloud. The dev session is session_016cxs5HWHRyhQhA9EaXmnWy. It builds at the default tier on branch claude/issue-25079-federated-report-migrate-run, under claim 6314457843.
Read first:
what reconcileFederatedBindings can already read about the composition (is it a migrate run that serves nothing?) and about a datasource's connect verdict (denied by policy, or failed);
every pin of the ERROR sentence.
What lands:
on a non-serving composition, a policy-denied datasource's objects produce no ERROR claiming served routes and UI: silence, or one non-ERROR line naming the denial;
a serving boot, and a failed (not denied) connection on any composition, keep the ERROR as written;
pins for all three, with an ablation, and a patch changeset for @objectstack/objectql.
Fork, not widening: if a new signal from packages/cli, packages/runtime or service-datasource would be needed, the dev reports needs_decision instead.
Moving pins:packages/runtime's federated-boot-binding.test.ts is domain:cli's; if it moves, the seat declares it before the queue.
{
"issue": 25079,
"status": "needs_decision",
"branch": "claude/issue-25079-federated-report-migrate-run",
"pr": null,
"session": "session_016cxs5HWHRyhQhA9EaXmnWy",
"premise_still_valid": true,
"summary": "Read-only census on origin/main 2e242bb0a9; no code written and no PR opened. The empty branch is pushed at 2e242bb. The policy-denial half is readable inside objectql today: service-datasource's recordState() mirrors a skipped-policy verdict into the engine as markDatasourceUnavailable({name, kind:'blocked'}), versus kind:'failed' for a failed connect, and the plugin reads it back with this.ql.listUnavailableDatasources(). No cross-lane signal is needed for that half. The 'composition serves nothing' half has NO faithful signal the plugin can read. The only candidate, 'no http.server service at kernel:ready', misreads a serving host: the documented, published embed createHonoApp({ kernel }) from @objectstack/hono bootstraps a kernel with no http.server and then serves REST and the UI from it. A host-injected deny policy, the only way a serving boot sees a denial (the default policy is allow-all), is exactly the multi-tenant host shape that would be downgraded. The dispatch's fork rule applies, so this is needs_decision with the measurement and the smallest signal, and nothing is added in another lane. One option (C) needs no new signal but amends the claim's serving-boot clause for blocked datasources only.",
"tests": "NOT MEASURED: no code changed, so no test or ablation ran. Census readings, all on 2e242bb0a9, by symbol: (1) WHEN: reconcileFederatedBindings runs from ObjectQLPlugin's kernel:ready handler, after every start(), right after the bound-action seal (packages/objectql/src/plugin.ts, the call commented '#7737 — FIRST'). It can read the registry, this.ql, ctx.getService, and its own options (skipSchemaSync, lifecycle, runPlatformMigrations). (2) COMPOSITION: os migrate apply / plan boot through bootSchemaStack (packages/cli/src/utils/schema-migrate.ts). It passes createStandaloneStack skipSeedData:true, armLifecycleSweep:false, runPlatformMigrations:false and skipSchemaSync only for a Turso-remote primary, then new Runtime({ cluster:false }) with no server, DeferSchemaDdlPlugin, buildSchemaMigrationPlugins (composeServedPlatform) and DeclaredDatasourceConnectionPlugin with policy MANAGED_DATASOURCES_ONLY. Of those, createStandaloneStack hands ObjectQLPlugin only runPlatformMigrations:false and lifecycle:{enabled:false} (packages/runtime/src/standalone-stack.ts, new ObjectQLPlugin). Both are one-shot PROXIES, not declarations that nothing is served: a serving host may set either. No option, context flag or kernel mode says 'this composition serves nothing'. (3) http.server: registered only by HonoServerPlugin.init (also as the 'http-server' alias), qa/http-conformance node-plugin, and Runtime({ server }). It is absent on the migrate boot, and also absent on a createHonoApp host: packages/qa/http-conformance/src/hono-head-as-get.conformance.test.ts bootstraps hostedKernel and then calls createHonoApp({ kernel: hostedKernel }) with no HonoServerPlugin, and content/docs/api/index.mdx documents that embed. (4) DENIAL: datasource-connection-service.ts attemptConnect logs 'connect denied by policy' at info, returns status 'skipped-policy', then recordState(): availabilityOf('skipped-policy') = 'blocked' maps to engine.markDatasourceUnavailable({kind:'blocked'}). Every failed-* status and skipped-unsupported map to kind 'failed'. Readable in objectql through ObjectQL.listUnavailableDatasources(), objectql's own API. On a read, getDriver throws DatasourceUnavailableError(kind) for such a datasource (engine.ts, the unavailableDatasources.get(binding.datasource) branch), so a read against a blocked datasource REFUSES naming the policy. It never 'resolves to a table named after the OBJECT', on any composition. (5) PINS of the report: packages/runtime/src/federated-boot-binding.test.ts 'names the object, its datasource, the consequence and the fix at error level' matches stable parts (toContain 'fed_orphan', 'fed_missing', 'NOT bound', 'no such table', 'Fix'). Its datasource fed_missing is UNDECLARED (no unavailable record), on a Runtime({cluster:false}) boot with no http.server. 'says nothing when every federated object bound' asserts that no line contains the exact fragment 'NOT bound to their remote'. packages/objectql/src/plugin-registry-read-failure.test.ts pins the #9285 registry-read ERROR, a separate message, by regex fragments, plus two positive controls with zero errors. sync-schemas-federated-object.test.ts and skip-schema-sync-registers-object-metadata.test.ts pin syncRegisteredSchemas' own error lines, not this report. No test asserts the report sentence in full. None of these turns red under options A or C as sketched.",
"gates": "NOT MEASURED: no diff, so dispatch-gates --commands has no changed-file set to derive from, and no build, typecheck or suite ran. The only write was git push of the empty branch (exit 0, new branch at 2e242bb0a99129b5747e9b1bf489ac6ecd61542a). pnpm install --frozen-lockfile in the worktree: EXIT=0.",
"dogfood_battery": "n/a — no PR; the claim's Clause-② is 'no' with no (narrowing) arm",
"mcp_calls": "3 — mcp__github__issue_read x3 (get #25079, get_comments #25079, get #7737); all reads, no MCP write tool",
"api_writes": "1 — this os-dev-report comment, POST issues/25079/comments through the fleet-write relay (scripts/pm/post-stamped.mjs). Not counted as a REST write: git push of the empty branch. Not spent: pr_create.",
"open_questions": [
{
"question": "The plugin cannot faithfully tell a composition that serves nothing. Which signal should the report condition on?",
"options": [
"A — 'no http.server service at kernel:ready', read now in plugin.ts only (about +25 lines plus 3 pins, objectql only). Known misread, measured: a createHonoApp({ kernel }) host serves REST and UI with no http.server, so on that host a policy-denied datasource's report drops from ERROR to one info line, contradicting the claim's 'serving boot keeps the ERROR'. That host shape is exactly where a deny policy lives on a serving boot. It is inference from an absent service (AGENTS.md Route and surface ownership rule 2, explicit composition over default magic).",
"B — an explicit declaration: the smallest is one ObjectQLPluginOptions key (for example serving: false; objectql reads it), passed through createStandaloneStack's config the way skipSchemaSync and armLifecycleSweep already are (packages/runtime, domain:cli), and set by bootSchemaStack (packages/cli, domain:cli). It is faithful and explicit, but it adds a new option key whose only consumer is one log line, and it spans three lanes.",
"C — drop the composition clause and condition on the verdict alone. An unbound object whose datasource the engine records as kind 'blocked' is reported on EVERY composition as one info line naming the policy denial and the objects, and is not counted in the ERROR. Unbound or undeclared, unsupported, failed-registration and failed-connect (kind 'failed') keep the ERROR verbatim on every composition. plugin.ts only, no new signal. It amends the claim's clause 'on a serving boot every unbound ... object keeps the ERROR' for blocked datasources only."
],
"recommendation": "C, by the four axes. Real business need: the measured producer is the stock showcase's os migrate apply, which C fixes. The only serving-boot population C moves is hosts with an injected deny policy, and for them the ERROR's stated consequence ('no such table, or answer from the wrong table') is already false: a read against a blocked datasource refuses with DatasourceUnavailableError naming the policy (engine.ts). Long-term soundness: C conditions on the engine's own recorded verdict, which service-datasource documents as 'blocked — a decision, not a fault, expected to persist'. A is default magic, and B adds a declared surface for a log line. Preventing AI mistakes: C's text is true on every composition, while A misleads silently on the embed and so trains greppers to distrust both levels. Startup focus: C adds no key, no gate and no cross-lane change; B widens three lanes for one line. By the AGENTS.md degradation-log-level question, a deliberate policy denial loses no durability, so it is functional: info, and not silent, which keeps #7737's 'must stop being silent' ruling. If the claim's serving-boot clause must stand as written, B is the faithful route and A should not ship."
}
],
"out_of_scope_findings": [
"carrier: none — noted, not filed: on ANY composition, for a datasource recorded as kind 'blocked', the current ERROR's consequence clause ('every read ... resolves to a table named after the OBJECT ... no such table, or the wrong table') is false: the engine refuses those reads with DatasourceUnavailableError. That is option C's premise, so it rides this decision rather than a separate card."
]
}
Seat re-declaration · domain:engine seat 1 · session_01JtSQQ3EWsbNPzyYMug1tXy · 2026-10-21T11:48Z · amends claim 6314457843 in place, on the dev's needs_decision 6314587078. ⛔ Not a new claim; the branch, the worktree and the dev are unchanged.
What the dev measured (read-only, on 2e242bb0a9):
The policy-denial half is readable in objectql today.service-datasource maps skipped-policy to availability blocked (availabilityOf, datasource-connection-service.ts:206) and records it through engine.markDatasourceUnavailable({ kind: 'blocked' }). A failed connect records kind: 'failed'. objectql reads both back through its own listUnavailableDatasources().
The "this composition serves nothing" half has no faithful signal. The only candidate, "no http.server at kernel:ready", misreads the documented createHonoApp({ kernel }) embed, which serves REST and the UI with no http.server registered.
For a blocked datasource, the ERROR's consequence is false on every composition. A read against such a datasource never "resolves to a table named after the OBJECT". getDriver throws DatasourceUnavailableError(…, kind) naming the policy (engine.ts:12030). The seat read all three sites.
The seat's call: option C. It is within the seat's discretion: log level and text only, decided by an existing rule, and no public contract moves.
No new signal and no other lane: option B would add an ObjectQLPluginOptions key across three lanes for one log line, and option A infers from an absent service and misleads on the embed.
The scope, as amended:
An unbound federated object whose datasource the engine records as kind: 'blocked' is reported, on every composition, in one info line. The line names the policy denial, the datasource and the objects, and says that reads against them are refused. It is not counted in the ERROR.
Unchanged, on every composition, at error verbatim: an undeclared datasource (no unavailable record), kind: 'failed' (a failed connect), a driver without external-object registration, and a registration that threw.
Struck from the claim: "on a serving boot, the ERROR stays as it is" now holds for every class except blocked. The composition clause (migrate run vs serving boot) is dropped: the condition is the engine's recorded verdict alone.
The rest of the claim stands: the file surface (packages/objectql/src/plugin.ts, the report only), the out-of-scope list, Clause-②: no (log text and level only: no response, status, outcome, boot verdict or export moves), TIER_DEFAULT, objectql patch.
Pins: a blocked datasource gives one info line and no ERROR, on a serving-shaped boot and a migrate-shaped boot alike. Controls: undeclared, failed, unsupported and registration-threw keep the ERROR. Ablation: revert, and the blocked pin goes red while the controls stay green.
The filer (domain:devx seat 1) and the maintainer can object on this card; the seat holds the queue for any objection posted before the review of record.
{
"issue": 25079,
"status": "done",
"branch": "claude/issue-25079-federated-report-migrate-run",
"pr": "https://github.com/objectstack-ai/objectstack/pull/25117",
"session": "session_016cxs5HWHRyhQhA9EaXmnWy",
"premise_still_valid": true,
"summary": "Built option C per the seat's re-declaration 6315166970. In ObjectQLPlugin.reconcileFederatedBindings (packages/objectql/src/plugin.ts, the report only), an unbound federated object whose datasource this.ql.listUnavailableDatasources() records as kind 'blocked' is now reported, on every composition, in ONE info line. The line names the policy denial, the objects and their datasource, and says reads are refused with DatasourceUnavailableError. It is excluded from the ERROR and its counts. Undeclared, kind 'failed', unsupported-driver and registration-threw keep the ERROR verbatim; the binding logic and the #9285 seam are untouched. A live os migrate apply --yes on the stock showcase now exits 0 with the denial line and the new info line, and no ERROR. PR #25117 is a draft at b9f2cfec1, assignee os-project-manager.",
"files_changed": [
"packages/objectql/src/plugin.ts",
"packages/objectql/src/federated-binding-policy-denied-report.test.ts",
".changeset/25079-federated-report-policy-denied.md"
],
"line_budget": "none set; diff vs origin/main at b9f2cfec1: packages/objectql/src/plugin.ts +30 -1; packages/objectql/src/federated-binding-policy-denied-report.test.ts +215 -0 (new); .changeset/25079-federated-report-policy-denied.md +13 -0 (new). Total +258 -1.",
"deviations": [
"Metadata-protocol line added to the changeset and the PR body: 'Metadata-protocol: none (a boot log line's level and text; nothing a metadata author writes changes)'. #25114 (f2b6cf230) landed on main during this round and made the line required by AGENTS.md Post-Task Checklist step 3 and the changeset level gate. The claim predates it. Value none keeps the level at patch. The claim's Clause-② line is carried verbatim.",
"No cross-lane file touched: packages/runtime/src/federated-boot-binding.test.ts (domain:cli) was NOT moved and stays green.",
"The runtime full suite was measured once, at 5cf4a4529, before the two main merges. Of those merges only #25086 moved a package in runtime's closure (objectql engine.ts), and objectql's full suite was rerun after it. The diff touches no runtime file.",
"Harness-level conflicts settled by os-dev.md: the PR body ends with the AGENTS.md session-URL footer rather than the harness's suggested PR attribution line, and the platform's auto-subscribe-to-own-PR posture is not taken (os-dev: the dispatch contract outranks it; CI convergence is the PM's).",
"check:changeset-no-major's PR-body half (both declaration lines, read from the event payload) cannot be exercised locally; CI's Check Changeset reads it."
],
"tests": "Pins: new packages/objectql/src/federated-binding-policy-denied-report.test.ts, 11 cases, 11/11 green. Blocked: one info line plus no ERROR, on a serving-shaped and a migrate-shaped context. Controls on both shapes keep exactly one ERROR with unchanged counts: undeclared, failed, unsupported, registration-threw. Mixed: info for the denied object, an ERROR reading '2 federated ...' for the rest. ABLATION via scripts/ablation-replace.mjs, '(blocked.has(datasource) ? denied : unbound).push(' replaced by 'unbound.push(': anchor 1 -> 0, blob aea19b4003ed -> 45e012d1ed12. Result 'Tests 3 failed | 8 passed (11)': both blocked cases and the mixed case red, all 8 controls green. Restored: 'blob == HEAD (aea19b4003ed) and git diff HEAD is empty'. The test imports ./plugin.js from source, so no dist leg. objectql typecheck exit 0, including check:test-typecheck OK; the tsconfig.test.json program lists the new file (listFiles count 1), no new debt. objectql full suite: 459/459 files, 8621/8621 at 5cf4a4529, and 459/459, 8631/8631 at 55a4c8b9f after the #25086 merge (lock VERDICT command-exit 0 both times). runtime full suite: 432/432 files, 6794 passed and 19 skipped, VERDICT 0, at 5cf4a4529 against an objectql/dist carrying the change. core test:repo: 6/6 files, 82/82 tests, VERDICT 0. Full build pnpm exec turbo run build --concurrency=2: 77/77 at 55a4c8b9f and again at the merged head (e3e83ba11, with b9f2cfec1's changeset-only edit), followed by objectql typecheck exit 0. LIVE, stock examples/app-showcase, fresh file DB, same tree. BEFORE (routing line ablated, objectql rebuilt): migrate apply exit 0; 'INFO datasource showcase_external: connect denied by policy (schemaMode external: ...)' then 'ERROR 2 federated (external) object(s) are NOT bound to their remote table, yet stay registered and served: they keep their REST routes and keep rendering in the UI, ...'. AFTER: exit 0; the same denial line, then 'INFO 2 federated (external) object(s) left unbound because the connect policy denied their datasource: showcase_ext_customer -> datasource showcase_external, showcase_ext_order -> datasource showcase_external. Every read against them is refused (DatasourceUnavailableError) ...'; 0 ERROR lines; 'Created/extended 70 table(s)'. AFTER was repeated once objectql/dist was rebuilt from the restored source: exit 0, info line, 0 ERROR.",
"gates": "Local: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, no paths, derived 67 lines (change set 3 paths vs merge base f2b6cf230). Every line ran at the final head b9f2cfec1, exit code captured before any pipe: 67/67 exit 0. --ran with 'cmd :: exit N' records: 'Run reconciliation — 67 derived, 67 run, 0 NOT-MEASURED, 0 UNRUN' and '67 derived famil(ies) accounted for — 67 run, 0 NOT-MEASURED (a DERIVED zero — all 67 recorded an exit code and none of them is 3)'. Same 67/67 at 55a4c8b9f. An earlier pass at 5cf4a4529 had three non-zero lines, none a gate verdict: check:dual-build-cjs-loads exit 3 (PREREQUISITE NOT MET, no full build yet; built for and re-run: exit 0), and check:query-options-erasure and check:type-check-debt exit 124 (my own 240 s per-command timeout; re-run uncapped: exit 0). Selected verdict lines: check:durability-log-level '48 durability-critical catch seam(s), all loud ...'; check:nul-bytes OK; check-changeset-no-major 'This diff introduces no major bump'; check-engine-double-contract OK. Shallow clone deepened with --shallow-since=2026-07-13 before deriving. CI: PR #25117's check-runs were not yet concluded when this report was written (in_progress), not waited on per os-dev.",
"dogfood_battery": "n/a — no `!` in the PR title and the Clause-② line is 'no' with no (narrowing) arm",
"mcp_calls": "5 — mcp__github__issue_read x4 (get #25079, get_comments #25079 twice, get #7737), mcp__github__pull_request_read x1 (get_files #25117); all reads, no MCP write tool",
"api_writes": "3 relay writes in the session, through scripts/pm (fleet-write relay as objectstack-fleet[bot]): (1) POST issues/25079/comments, the needs_decision os-dev-report 6314587078 (previous round); (2) pr_create, POST pulls plus POST issues/25117/assignees, PR #25117 draft, body 6478 bytes stored identical, assignee os-project-manager; (3) POST issues/25079/comments, this os-dev-report. git push to the branch is not a REST write (5 pushes: the empty branch, two commits, a merge, the changeset fix).",
"open_questions": [],
"out_of_scope_findings": [
"carrier: none — noted, not filed: a createHonoApp({ kernel }) host serves REST and UI with no http.server service registered, so any code that reads 'no http.server' as 'this composition serves nothing' misreads that embed. Nothing reads it that way today; recorded because option A of the needs_decision would have."
]
}
TIER_DEFAULT. Record 6317969425 PASS on b9f2cfec12, against the re-declared scope 6315166970 (option C). ACCEPT 6318414988. Not governed.
Queue
It entered the merge queue at 2026-10-21T14:33Z and left it merged at 2026-10-21T15:07Z. No gh-readonly-queue/main/pr-25117-* branch remains.
origin/main
db9c02ad1a is on origin/main, one squash commit carrying PR #25117's 3 files, +258 / −1.
Card
Closed completed through Fixes #25079; pm:dispatched is cleared.
What main now holds:
A successful os migrate apply on the stock showcase no longer prints an ERROR. The managed-only connect policy of a migrate run denies showcase_external on purpose (schemaMode: 'external'). objectql's federated-binding reconciliation used to follow that denial with an ERROR saying the objects "keep their REST routes and keep rendering in the UI" while reads hit the wrong table. It now prints one info line instead: 2 federated (external) object(s) left unbound because the connect policy denied their datasource: showcase_ext_customer -> datasource 'showcase_external', showcase_ext_order -> datasource 'showcase_external'. Every read against them is refused (DatasourceUnavailableError) until the policy allows that datasource ….
The rule is the recorded verdict, on every composition. An object whose datasource the datasource layer records as refused by policy (availability blocked) gets the info line, on a serving boot and a migrate run alike. That is what its reads already do: the engine refuses them with DatasourceUnavailableError.
Unchanged, at ERROR, word for word:
an undeclared datasource;
a connect that failed;
a driver without external-object registration;
a registration that threw.
On a boot with both kinds, the info line covers the denied objects and the ERROR covers the rest, with counts that exclude the denied ones.
Shipped as:patch of @objectstack/objectql, Clause-②: no (log text and level only: …), Metadata-protocol: none.
Beside it:
The scope differs from the card's "Wanted" in one place, by the seat's re-declaration 6315166970. The card asked that a serving boot keep the ERROR. For a policy-denied datasource only, the ERROR's stated consequence ("resolves to a table named after the OBJECT") is false on every composition. Telling a non-serving composition apart would also have needed a new signal from three other lanes, so the condition is the verdict alone. No objection was posted on the card.
No file outside packages/objectql moved; packages/runtime's federated-boot-binding.test.ts stays as it was.
The dev session session_016cxs5HWHRyhQhA9EaXmnWy is archived.
Activity
objectstack-fleet commentedon Oct 21, 2026
Claim: PM loop round 25 (p3 only, by the maintainer's order 「你后续只处理 p3」) · 2026-10-21T11:08Z · p3,
domain:engine(triage's grade), filed bydomain:devxseat 1 from #25054's live drive (PR #25075, out-of-scope finding). On the stock showcase,os migrate apply --yesexits 0 and creates its tables. Its output first says, at info level, thatshowcase_externalwas "connect denied by policy (schemaMode 'external' …)". Then, at ERROR level, objectql's federated-binding reconciliation says the federated objects "keep their REST routes and keep rendering in the UI" while reads resolve to the wrong table. A migrate run serves no route and draws no UI, and the denial was deliberate, so a successful apply reads as a failure, to an operator and to an agent that greps forERROR.Session:
session_01JtSQQ3EWsbNPzyYMug1tXy(the dispatching seat; the dev runs as its own cloud session, named in the dispatch comment)Account:
os-project-manager(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-25079-federated-report-migrate-runWorktree:
objectstack-issue-25079Domain:
domain:engineSeat:
domain:engine#1(seat post #6367)File surface:
reconcileFederatedBindingsinpackages/objectql/src/plugin.ts(thectx.logger.errorreport, ≈:1900): when it runs, and what it can know at that point:os migrate apply/planboot versus a serving boot. Name the signal the plugin can already read, if any (a context flag, a kernel or composition mode,skipSchemaSync), and where the CLI's migrate composition sets it (read only);service-datasource'sdatasource-connection-service.ts:564logs the denial; name what it records that the plugin can read (read only);packages/objectql/src/plugin.ts's own tests, andpackages/runtime/src/federated-boot-binding.test.ts(domain:cli's package).packages/objectql/src/plugin.ts, the reconciliation's report only:patchfor@objectstack/objectql.⛔ Not in scope:
schemaMode 'external'denial and its info line (service-datasource, a different package);registerExternalObject,getDriverForObject);domain:cli). If the plugin cannot tell a migrate run from a serving boot without a new signal from another package, the dev reportsneeds_decisionand does not widen;os migrate plan/applyoffer--allow-destructivefor a unique index that duplicates BLOCK, and the re-run ends PARTIAL — the driver's apply-limit declaration does not cover a blockedcreate_index#25031 (--allow-destructiveonos migrate) and Boot drift lines on a 17.x database before the ownership ceremony prescribeos migrate apply --allow-destructivefor eachorganization_idcolumn, a run the drop gate refuses #24956, which seat 2 holds.Container & model:
M,mode:cloud(one report's condition in one plugin, the signal it can read, and its pins),model: TIER_DEFAULT(this run'sdispatch-gates.mjs --tier: "no path-derived mandate")Clause-②: no (log text and level only: no response, status, outcome, boot verdict or export moves)
Responsibility: an operator or agent reading a successful
os migrate applyis told, at ERROR level, that federated objects are served broken | the federated-binding report states a serving consequence on a run that serves nothing, for a datasource denied on purpose | every operator who migrates an app with aschemaMode: 'external'datasourceThread-read: none
Serial constraints cleared: the 10 open PRs' file lists and the
pm:dispatchedclaims were read at this claim, onorigin/main2e242bb0a9. No open PR touchespackages/objectql/src/plugin.tsordatasource-connection-service.ts. Seat 2's #25031 and #24956 areos migratecards in other files; neither is claimed by a PR on this file.Generated by Claude Code
objectstack-fleet commentedon Oct 21, 2026
Dispatch ·
domain:engineseat 1 ·session_01JtSQQ3EWsbNPzyYMug1tXy· 2026-10-21T11:11Z:mode:cloud. The dev session issession_016cxs5HWHRyhQhA9EaXmnWy. It builds at the default tier on branchclaude/issue-25079-federated-report-migrate-run, under claim 6314457843.reconcileFederatedBindingscan already read about the composition (is it a migrate run that serves nothing?) and about a datasource's connect verdict (denied by policy, or failed);patchchangeset for@objectstack/objectql.packages/cli,packages/runtimeorservice-datasourcewould be needed, the dev reportsneeds_decisioninstead.packages/runtime'sfederated-boot-binding.test.tsisdomain:cli's; if it moves, the seat declares it before the queue.os migrate plan/applyoffer--allow-destructivefor a unique index that duplicates BLOCK, and the re-run ends PARTIAL — the driver's apply-limit declaration does not cover a blockedcreate_index#25031, Boot drift lines on a 17.x database before the ownership ceremony prescribeos migrate apply --allow-destructivefor eachorganization_idcolumn, a run the drop gate refuses #24956.Generated by Claude Code
objectstack-fleet commentedon Oct 21, 2026
os-dev-report
{ "issue": 25079, "status": "needs_decision", "branch": "claude/issue-25079-federated-report-migrate-run", "pr": null, "session": "session_016cxs5HWHRyhQhA9EaXmnWy", "premise_still_valid": true, "summary": "Read-only census on origin/main 2e242bb0a9; no code written and no PR opened. The empty branch is pushed at 2e242bb. The policy-denial half is readable inside objectql today: service-datasource's recordState() mirrors a skipped-policy verdict into the engine as markDatasourceUnavailable({name, kind:'blocked'}), versus kind:'failed' for a failed connect, and the plugin reads it back with this.ql.listUnavailableDatasources(). No cross-lane signal is needed for that half. The 'composition serves nothing' half has NO faithful signal the plugin can read. The only candidate, 'no http.server service at kernel:ready', misreads a serving host: the documented, published embed createHonoApp({ kernel }) from @objectstack/hono bootstraps a kernel with no http.server and then serves REST and the UI from it. A host-injected deny policy, the only way a serving boot sees a denial (the default policy is allow-all), is exactly the multi-tenant host shape that would be downgraded. The dispatch's fork rule applies, so this is needs_decision with the measurement and the smallest signal, and nothing is added in another lane. One option (C) needs no new signal but amends the claim's serving-boot clause for blocked datasources only.", "tests": "NOT MEASURED: no code changed, so no test or ablation ran. Census readings, all on 2e242bb0a9, by symbol: (1) WHEN: reconcileFederatedBindings runs from ObjectQLPlugin's kernel:ready handler, after every start(), right after the bound-action seal (packages/objectql/src/plugin.ts, the call commented '#7737 — FIRST'). It can read the registry, this.ql, ctx.getService, and its own options (skipSchemaSync, lifecycle, runPlatformMigrations). (2) COMPOSITION: os migrate apply / plan boot through bootSchemaStack (packages/cli/src/utils/schema-migrate.ts). It passes createStandaloneStack skipSeedData:true, armLifecycleSweep:false, runPlatformMigrations:false and skipSchemaSync only for a Turso-remote primary, then new Runtime({ cluster:false }) with no server, DeferSchemaDdlPlugin, buildSchemaMigrationPlugins (composeServedPlatform) and DeclaredDatasourceConnectionPlugin with policy MANAGED_DATASOURCES_ONLY. Of those, createStandaloneStack hands ObjectQLPlugin only runPlatformMigrations:false and lifecycle:{enabled:false} (packages/runtime/src/standalone-stack.ts, new ObjectQLPlugin). Both are one-shot PROXIES, not declarations that nothing is served: a serving host may set either. No option, context flag or kernel mode says 'this composition serves nothing'. (3) http.server: registered only by HonoServerPlugin.init (also as the 'http-server' alias), qa/http-conformance node-plugin, and Runtime({ server }). It is absent on the migrate boot, and also absent on a createHonoApp host: packages/qa/http-conformance/src/hono-head-as-get.conformance.test.ts bootstraps hostedKernel and then calls createHonoApp({ kernel: hostedKernel }) with no HonoServerPlugin, and content/docs/api/index.mdx documents that embed. (4) DENIAL: datasource-connection-service.ts attemptConnect logs 'connect denied by policy' at info, returns status 'skipped-policy', then recordState(): availabilityOf('skipped-policy') = 'blocked' maps to engine.markDatasourceUnavailable({kind:'blocked'}). Every failed-* status and skipped-unsupported map to kind 'failed'. Readable in objectql through ObjectQL.listUnavailableDatasources(), objectql's own API. On a read, getDriver throws DatasourceUnavailableError(kind) for such a datasource (engine.ts, the unavailableDatasources.get(binding.datasource) branch), so a read against a blocked datasource REFUSES naming the policy. It never 'resolves to a table named after the OBJECT', on any composition. (5) PINS of the report: packages/runtime/src/federated-boot-binding.test.ts 'names the object, its datasource, the consequence and the fix at error level' matches stable parts (toContain 'fed_orphan', 'fed_missing', 'NOT bound', 'no such table', 'Fix'). Its datasource fed_missing is UNDECLARED (no unavailable record), on a Runtime({cluster:false}) boot with no http.server. 'says nothing when every federated object bound' asserts that no line contains the exact fragment 'NOT bound to their remote'. packages/objectql/src/plugin-registry-read-failure.test.ts pins the #9285 registry-read ERROR, a separate message, by regex fragments, plus two positive controls with zero errors. sync-schemas-federated-object.test.ts and skip-schema-sync-registers-object-metadata.test.ts pin syncRegisteredSchemas' own error lines, not this report. No test asserts the report sentence in full. None of these turns red under options A or C as sketched.", "gates": "NOT MEASURED: no diff, so dispatch-gates --commands has no changed-file set to derive from, and no build, typecheck or suite ran. The only write was git push of the empty branch (exit 0, new branch at 2e242bb0a99129b5747e9b1bf489ac6ecd61542a). pnpm install --frozen-lockfile in the worktree: EXIT=0.", "dogfood_battery": "n/a — no PR; the claim's Clause-② is 'no' with no (narrowing) arm", "mcp_calls": "3 — mcp__github__issue_read x3 (get #25079, get_comments #25079, get #7737); all reads, no MCP write tool", "api_writes": "1 — this os-dev-report comment, POST issues/25079/comments through the fleet-write relay (scripts/pm/post-stamped.mjs). Not counted as a REST write: git push of the empty branch. Not spent: pr_create.", "open_questions": [ { "question": "The plugin cannot faithfully tell a composition that serves nothing. Which signal should the report condition on?", "options": [ "A — 'no http.server service at kernel:ready', read now in plugin.ts only (about +25 lines plus 3 pins, objectql only). Known misread, measured: a createHonoApp({ kernel }) host serves REST and UI with no http.server, so on that host a policy-denied datasource's report drops from ERROR to one info line, contradicting the claim's 'serving boot keeps the ERROR'. That host shape is exactly where a deny policy lives on a serving boot. It is inference from an absent service (AGENTS.md Route and surface ownership rule 2, explicit composition over default magic).", "B — an explicit declaration: the smallest is one ObjectQLPluginOptions key (for example serving: false; objectql reads it), passed through createStandaloneStack's config the way skipSchemaSync and armLifecycleSweep already are (packages/runtime, domain:cli), and set by bootSchemaStack (packages/cli, domain:cli). It is faithful and explicit, but it adds a new option key whose only consumer is one log line, and it spans three lanes.", "C — drop the composition clause and condition on the verdict alone. An unbound object whose datasource the engine records as kind 'blocked' is reported on EVERY composition as one info line naming the policy denial and the objects, and is not counted in the ERROR. Unbound or undeclared, unsupported, failed-registration and failed-connect (kind 'failed') keep the ERROR verbatim on every composition. plugin.ts only, no new signal. It amends the claim's clause 'on a serving boot every unbound ... object keeps the ERROR' for blocked datasources only." ], "recommendation": "C, by the four axes. Real business need: the measured producer is the stock showcase's os migrate apply, which C fixes. The only serving-boot population C moves is hosts with an injected deny policy, and for them the ERROR's stated consequence ('no such table, or answer from the wrong table') is already false: a read against a blocked datasource refuses with DatasourceUnavailableError naming the policy (engine.ts). Long-term soundness: C conditions on the engine's own recorded verdict, which service-datasource documents as 'blocked — a decision, not a fault, expected to persist'. A is default magic, and B adds a declared surface for a log line. Preventing AI mistakes: C's text is true on every composition, while A misleads silently on the embed and so trains greppers to distrust both levels. Startup focus: C adds no key, no gate and no cross-lane change; B widens three lanes for one line. By the AGENTS.md degradation-log-level question, a deliberate policy denial loses no durability, so it is functional: info, and not silent, which keeps #7737's 'must stop being silent' ruling. If the claim's serving-boot clause must stand as written, B is the faithful route and A should not ship." } ], "out_of_scope_findings": [ "carrier: none — noted, not filed: on ANY composition, for a datasource recorded as kind 'blocked', the current ERROR's consequence clause ('every read ... resolves to a table named after the OBJECT ... no such table, or the wrong table') is false: the engine refuses those reads with DatasourceUnavailableError. That is option C's premise, so it rides this decision rather than a separate card." ] }Generated by Claude Code
objectstack-fleet commentedon Oct 21, 2026
Seat re-declaration ·
domain:engineseat 1 ·session_01JtSQQ3EWsbNPzyYMug1tXy· 2026-10-21T11:48Z · amends claim 6314457843 in place, on the dev'sneeds_decision6314587078. ⛔ Not a new claim; the branch, the worktree and the dev are unchanged.What the dev measured (read-only, on
2e242bb0a9):service-datasourcemapsskipped-policyto availabilityblocked(availabilityOf,datasource-connection-service.ts:206) and records it throughengine.markDatasourceUnavailable({ kind: 'blocked' }). A failed connect recordskind: 'failed'. objectql reads both back through its ownlistUnavailableDatasources().http.serveratkernel:ready", misreads the documentedcreateHonoApp({ kernel })embed, which serves REST and the UI with nohttp.serverregistered.blockeddatasource, the ERROR's consequence is false on every composition. A read against such a datasource never "resolves to a table named after the OBJECT".getDriverthrowsDatasourceUnavailableError(…, kind)naming the policy (engine.ts:12030). The seat read all three sites.The seat's call: option C. It is within the seat's discretion: log level and text only, decided by an existing rule, and no public contract moves.
erroris for a durability or consistency loss that looks normal from outside. A deliberate policy denial whose reads refuse loudly is a functional degradation, soinfoand not silent. That keeps external-datasource-federated-read: federated read returns empty — the external object→remote-table mapping never registers (boot ordering) #7737's ruling that the reconciliation must not be silent.ObjectQLPluginOptionskey across three lanes for one log line, and option A infers from an absent service and misleads on the embed.The scope, as amended:
kind: 'blocked'is reported, on every composition, in oneinfoline. The line names the policy denial, the datasource and the objects, and says that reads against them are refused. It is not counted in the ERROR.errorverbatim: an undeclared datasource (no unavailable record),kind: 'failed'(a failed connect), a driver without external-object registration, and a registration that threw.blocked. The composition clause (migrate run vs serving boot) is dropped: the condition is the engine's recorded verdict alone.packages/objectql/src/plugin.ts, the report only), the out-of-scope list,Clause-②: no (log text and level only: no response, status, outcome, boot verdict or export moves),TIER_DEFAULT, objectqlpatch.blockeddatasource gives one info line and no ERROR, on a serving-shaped boot and a migrate-shaped boot alike. Controls: undeclared,failed, unsupported and registration-threw keep the ERROR. Ablation: revert, and theblockedpin goes red while the controls stay green.The filer (
domain:devxseat 1) and the maintainer can object on this card; the seat holds the queue for any objection posted before the review of record.Generated by Claude Code
objectstack-fleet commentedon Oct 21, 2026
os-dev-report
{ "issue": 25079, "status": "done", "branch": "claude/issue-25079-federated-report-migrate-run", "pr": "https://github.com/objectstack-ai/objectstack/pull/25117", "session": "session_016cxs5HWHRyhQhA9EaXmnWy", "premise_still_valid": true, "summary": "Built option C per the seat's re-declaration 6315166970. In ObjectQLPlugin.reconcileFederatedBindings (packages/objectql/src/plugin.ts, the report only), an unbound federated object whose datasource this.ql.listUnavailableDatasources() records as kind 'blocked' is now reported, on every composition, in ONE info line. The line names the policy denial, the objects and their datasource, and says reads are refused with DatasourceUnavailableError. It is excluded from the ERROR and its counts. Undeclared, kind 'failed', unsupported-driver and registration-threw keep the ERROR verbatim; the binding logic and the #9285 seam are untouched. A live os migrate apply --yes on the stock showcase now exits 0 with the denial line and the new info line, and no ERROR. PR #25117 is a draft at b9f2cfec1, assignee os-project-manager.", "files_changed": [ "packages/objectql/src/plugin.ts", "packages/objectql/src/federated-binding-policy-denied-report.test.ts", ".changeset/25079-federated-report-policy-denied.md" ], "line_budget": "none set; diff vs origin/main at b9f2cfec1: packages/objectql/src/plugin.ts +30 -1; packages/objectql/src/federated-binding-policy-denied-report.test.ts +215 -0 (new); .changeset/25079-federated-report-policy-denied.md +13 -0 (new). Total +258 -1.", "deviations": [ "Metadata-protocol line added to the changeset and the PR body: 'Metadata-protocol: none (a boot log line's level and text; nothing a metadata author writes changes)'. #25114 (f2b6cf230) landed on main during this round and made the line required by AGENTS.md Post-Task Checklist step 3 and the changeset level gate. The claim predates it. Value none keeps the level at patch. The claim's Clause-② line is carried verbatim.", "No cross-lane file touched: packages/runtime/src/federated-boot-binding.test.ts (domain:cli) was NOT moved and stays green.", "The runtime full suite was measured once, at 5cf4a4529, before the two main merges. Of those merges only #25086 moved a package in runtime's closure (objectql engine.ts), and objectql's full suite was rerun after it. The diff touches no runtime file.", "Harness-level conflicts settled by os-dev.md: the PR body ends with the AGENTS.md session-URL footer rather than the harness's suggested PR attribution line, and the platform's auto-subscribe-to-own-PR posture is not taken (os-dev: the dispatch contract outranks it; CI convergence is the PM's).", "check:changeset-no-major's PR-body half (both declaration lines, read from the event payload) cannot be exercised locally; CI's Check Changeset reads it." ], "tests": "Pins: new packages/objectql/src/federated-binding-policy-denied-report.test.ts, 11 cases, 11/11 green. Blocked: one info line plus no ERROR, on a serving-shaped and a migrate-shaped context. Controls on both shapes keep exactly one ERROR with unchanged counts: undeclared, failed, unsupported, registration-threw. Mixed: info for the denied object, an ERROR reading '2 federated ...' for the rest. ABLATION via scripts/ablation-replace.mjs, '(blocked.has(datasource) ? denied : unbound).push(' replaced by 'unbound.push(': anchor 1 -> 0, blob aea19b4003ed -> 45e012d1ed12. Result 'Tests 3 failed | 8 passed (11)': both blocked cases and the mixed case red, all 8 controls green. Restored: 'blob == HEAD (aea19b4003ed) and git diff HEAD is empty'. The test imports ./plugin.js from source, so no dist leg. objectql typecheck exit 0, including check:test-typecheck OK; the tsconfig.test.json program lists the new file (listFiles count 1), no new debt. objectql full suite: 459/459 files, 8621/8621 at 5cf4a4529, and 459/459, 8631/8631 at 55a4c8b9f after the #25086 merge (lock VERDICT command-exit 0 both times). runtime full suite: 432/432 files, 6794 passed and 19 skipped, VERDICT 0, at 5cf4a4529 against an objectql/dist carrying the change. core test:repo: 6/6 files, 82/82 tests, VERDICT 0. Full build pnpm exec turbo run build --concurrency=2: 77/77 at 55a4c8b9f and again at the merged head (e3e83ba11, with b9f2cfec1's changeset-only edit), followed by objectql typecheck exit 0. LIVE, stock examples/app-showcase, fresh file DB, same tree. BEFORE (routing line ablated, objectql rebuilt): migrate apply exit 0; 'INFO datasource showcase_external: connect denied by policy (schemaMode external: ...)' then 'ERROR 2 federated (external) object(s) are NOT bound to their remote table, yet stay registered and served: they keep their REST routes and keep rendering in the UI, ...'. AFTER: exit 0; the same denial line, then 'INFO 2 federated (external) object(s) left unbound because the connect policy denied their datasource: showcase_ext_customer -> datasource showcase_external, showcase_ext_order -> datasource showcase_external. Every read against them is refused (DatasourceUnavailableError) ...'; 0 ERROR lines; 'Created/extended 70 table(s)'. AFTER was repeated once objectql/dist was rebuilt from the restored source: exit 0, info line, 0 ERROR.", "gates": "Local: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, no paths, derived 67 lines (change set 3 paths vs merge base f2b6cf230). Every line ran at the final head b9f2cfec1, exit code captured before any pipe: 67/67 exit 0. --ran with 'cmd :: exit N' records: 'Run reconciliation — 67 derived, 67 run, 0 NOT-MEASURED, 0 UNRUN' and '67 derived famil(ies) accounted for — 67 run, 0 NOT-MEASURED (a DERIVED zero — all 67 recorded an exit code and none of them is 3)'. Same 67/67 at 55a4c8b9f. An earlier pass at 5cf4a4529 had three non-zero lines, none a gate verdict: check:dual-build-cjs-loads exit 3 (PREREQUISITE NOT MET, no full build yet; built for and re-run: exit 0), and check:query-options-erasure and check:type-check-debt exit 124 (my own 240 s per-command timeout; re-run uncapped: exit 0). Selected verdict lines: check:durability-log-level '48 durability-critical catch seam(s), all loud ...'; check:nul-bytes OK; check-changeset-no-major 'This diff introduces no major bump'; check-engine-double-contract OK. Shallow clone deepened with --shallow-since=2026-07-13 before deriving. CI: PR #25117's check-runs were not yet concluded when this report was written (in_progress), not waited on per os-dev.", "dogfood_battery": "n/a — no `!` in the PR title and the Clause-② line is 'no' with no (narrowing) arm", "mcp_calls": "5 — mcp__github__issue_read x4 (get #25079, get_comments #25079 twice, get #7737), mcp__github__pull_request_read x1 (get_files #25117); all reads, no MCP write tool", "api_writes": "3 relay writes in the session, through scripts/pm (fleet-write relay as objectstack-fleet[bot]): (1) POST issues/25079/comments, the needs_decision os-dev-report 6314587078 (previous round); (2) pr_create, POST pulls plus POST issues/25117/assignees, PR #25117 draft, body 6478 bytes stored identical, assignee os-project-manager; (3) POST issues/25079/comments, this os-dev-report. git push to the branch is not a REST write (5 pushes: the empty branch, two commits, a merge, the changeset fix).", "open_questions": [], "out_of_scope_findings": [ "carrier: none — noted, not filed: a createHonoApp({ kernel }) host serves REST and UI with no http.server service registered, so any code that reads 'no http.server' as 'this composition serves nothing' misreads that embed. Nothing reads it that way today; recorded because option A of the needs_decision would have." ] }Generated by Claude Code
objectstack-fleet commentedon Oct 21, 2026
Landed ·
domain:engineseat 1 ·session_01JtSQQ3EWsbNPzyYMug1tXy· 2026-10-21T15:27ZTIER_DEFAULT. Record 6317969425 PASS onb9f2cfec12, against the re-declared scope 6315166970 (option C). ACCEPT 6318414988. Not governed.gh-readonly-queue/main/pr-25117-*branch remains.origin/maindb9c02ad1ais onorigin/main, one squash commit carrying PR #25117's 3 files, +258 / −1.completedthroughFixes #25079;pm:dispatchedis cleared.What
mainnow holds:A successful
os migrate applyon the stock showcase no longer prints an ERROR. The managed-only connect policy of a migrate run deniesshowcase_externalon purpose (schemaMode: 'external'). objectql's federated-binding reconciliation used to follow that denial with an ERROR saying the objects "keep their REST routes and keep rendering in the UI" while reads hit the wrong table. It now prints oneinfoline instead:2 federated (external) object(s) left unbound because the connect policy denied their datasource: showcase_ext_customer -> datasource 'showcase_external', showcase_ext_order -> datasource 'showcase_external'. Every read against them is refused (DatasourceUnavailableError) until the policy allows that datasource ….The rule is the recorded verdict, on every composition. An object whose datasource the datasource layer records as refused by policy (availability
blocked) gets the info line, on a serving boot and a migrate run alike. That is what its reads already do: the engine refuses them withDatasourceUnavailableError.Unchanged, at ERROR, word for word:
On a boot with both kinds, the info line covers the denied objects and the ERROR covers the rest, with counts that exclude the denied ones.
Shipped as:
patchof@objectstack/objectql,Clause-②: no (log text and level only: …),Metadata-protocol: none.Beside it:
packages/objectqlmoved;packages/runtime'sfederated-boot-binding.test.tsstays as it was.The dev session
session_016cxs5HWHRyhQhA9EaXmnWyis archived.Generated by Claude Code