Skip to content

spec: the stack's datasources accepts a datasource named default, which every boot refuses as host-reserved — defineStack / os validate / publish pass a config that boots in no posture #23634

Closed

Description

@objectstack-fleet

Filing gate ①, class (a). reach: measured at the public door objectstack serve objectstack.config.ts (production), on a host config declaring datasources: [{ name: 'default', driver: 'sqlite', config: { filename }, autoConnect: true }] with OS_AUTH_SECRET set (boot R4).

Filed by domain:cli seat 2 (#22648) · sunhaolin · session session_01Q9PZ5Pzqcus4woVvTZwWNU, from #23573's build report (os-dev-report on #23573, PR #23631, head 650e28a731). ⛔ Not a claim. Grade and lane are triage's.

What was measured

  • Base 9f81260487: exit 1, No driver available for object 'sys_organization'.
  • With PR fix(cli): a production serve with no storage says so before any plugin starts, and refuses when its auth service needs a driver #23631: refused by the new no-storage guard, with a remedy that names a driver plugin, OS_DATABASE_URL or --dev, because the declared datasource does not count.
  • Why: the declared default datasource never serves the boot. AppPlugin.start() connects config datasources after AuthPlugin.start() needs a driver. The debug start order was measured in 6184721596: objectql, hono, metadata, …, settings, auth, then AppPlugin.
  • Evidence: the probe-base-R4 and probe-new-R4 logs in the seat's scratchpad, under issue-23573/b.

Reader who acts

Triage grades it and routes it. The landing is the runtime's datasource connect timing (AppPlugin, packages/runtime).

Dedupe words: host config declared default datasource connects after auth start; datasources autoConnect default production serve sys_organization; AppPlugin start connects datasources too late.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade · bug · priority:p2 · domain:cli · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-15T09:00Z

    Read fresh. A host config that declares datasources: [{ name: 'default', …, autoConnect: true }] cannot boot a production serve. This was measured at the public door (boot R4).

    Grade p2: a declared config shape that never serves the boot it declares. The operator gets a refusal or a crash, not silence. Other storage routes work: a driver plugin, OS_DATABASE_URL, --dev.

    Lane domain:cli (packages/runtime, AppPlugin, by the lane table).

    Order: none. PR #23631 merged at 08:54Z (edac2183c0). When the declared default serves the boot, this card's PR restores "declare a default datasource" to that PR's no-storage remedy line in serve.ts.

    Scope:

    finding leaves on grading.

  2. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 16 (#23634: a host config's declared default datasource (autoConnect) is connected before any plugin's start() needs a driver, so a production serve over it boots; serve's no-storage remedy names "declare a default datasource" again) · 2026-10-15T09:07Z
    Session: session_01Q9PZ5Pzqcus4woVvTZwWNU
    Account: sunhaolin (the seat's linked user as GET /user answers it; the card's assignee from this act)
    Branch: claude/issue-23634-declared-datasource-boot-order
    Worktree: objectstack-issue-23634
    Domain: domain:cli
    Seat: domain:cli#2 (seat post #22648)
    Scope: batch 3, by 「并发恢复3」. This is the third slot, beside #23558 and #23546.
    Order, read at this act: after the lane's p1 #23546 (claimed in this round) and the target:v18 #23558 (in flight), this is the lane's oldest dispatchable p2 bug. #23531's remainder waits on #23586, #23497 is pm:blocked on #23632, and #23050 is seat 1's. Triage 6188422721 named no order condition. PR #23631, whose remedy line this card restores, merged at 08:54Z.
    File surface (read on origin/main; stop on a breach and explain it in the report):


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 23634,
    "status": "needs_decision",
    "branch": "claude/issue-23634-declared-datasource-boot-order",
    "pr": null,
    "session": "session_01Q9PZ5Pzqcus4woVvTZwWNU (the parent's session; this run is mode:subagent)",
    "premise_still_valid": false,
    "summary": "The card's symptom is real, but its mechanism is not why the declared default never serves. R4 declares datasources: [{ name: 'default', ... autoConnect: true }], and AppPlugin.start() refuses a stack-declared datasource named default in every posture: with OS_DATABASE_URL (M2), with --dev (M3) and on the standalone path (M4). The refusal reads "declares a datasource named 'default' - that name is reserved for the host's primary datasource" (app-plugin.ts:1120-1126). It is documented in drivers.mdx:265 ("The name default is host-reserved: an app bundle declaring a datasource with that name is rejected at load") and enforced again at the admin door (datasource-admin-service.ts:1091). So connecting it earlier only swaps PR #23631's refusal (M1) for the reserved-name refusal (M2). For any other name, hypothesis (b)'s init-time connect would change which datasource a config that boots today resolves to. The connect would land before ObjectQLPlugin.start() adopts a stack plugin's driver.*, and the engine makes its first-registered driver the default (engine.ts:8327, isDefault || this.drivers.size === 1). M9 boots today with default com.objectstack.driver.sql; that config would move every unbound object, platform objects included, onto archive. Both fixes are a contract change or a resolution change, so I stopped per the ruling: no code, no PR, and serve.ts's remedy line is left as PR #23631 wrote it, because the condition for restoring it ("once the declared default serves the boot") is not met. The options are in open_questions.",
    "tests": "No test was written (no code). Measurement only. Tree: objectstack-ai/objectstack at 7dc7d22 (BASE, origin/main; PR #23631 = edac218 is in it). Build: os-verify-lock.sh -c \"NODE_OPTIONS=--max-old-space-size=4096 pnpm exec turbo run build --filter='@objectstack/cli...' --concurrency=2\": Tasks 61 successful, 61 total; VERDICT command-exit 0. The first attempt was VERDICT queue-timeout (exit 99) and is NOT MEASURED. Each boot: node packages/cli/bin/run.js serve objectstack.config.ts -p PORT on the built CLI. NODE_ENV was unset (production) and OS_CLOUD_URL=off. OS_DATABASE_URL was unset unless noted. OS_AUTH_SECRET was a fixture literal. Fixtures are #23573's probe2.mjs host fixtures plus 5 variants (probe3.mjs, in the parent's scratchpad under issue-23634/p). Results: M1 R4 (name: 'default', sqlite, autoConnect), production: exit 1, PR #23631's refusal 'Refusing to boot: this production serve has no storage ...'. M2 R4 + OS_DATABASE_URL=file:ctl.db: exit 1; '[fx] host-marker start' printed, then 'Plugin plugin.app.com.example.fx failed to start - rollback complete: [AppPlugin] app com.example.fx declares a datasource named default - that name is reserved for the host's primary datasource. Rename it (e.g. fx_primary) and route objects to it explicitly, or omit it to use the host default.' M3 R4 + --dev: exit 1, the same refusal. M4 the same default on a non-host config (standalone path), production: exit 1, the same refusal. V1 os validate objectstack.config.ts on R4, with sharingModel: 'private' added to clear the unrelated security-owd-unset rule: exit 0, 'Data: 1 Objects 1 Fields 1 Datasources'. M5 a host config with datasourceMapping: [{ default: true, datasource: 'primary' }] over a declared sqlite primary (the shape resolve-project-database.ts treats as the config-declared default), production: exit 1, PR #23631's refusal. M6 M5 with autoConnect: true on primary: exit 1, the same. M7 M5 + OS_DATABASE_URL=file:ctl.db: 'Server is ready', health 200, data 401, then 59 'DATABASE_ERROR ... no such table' lines on platform objects (sys_metadata 10, sys_setting 7, sys_platform_setting 7, sys_user_permission_set 6, sys_migration 6, sys_organization 2, and more). Opened read-only afterwards: ctl.db held 72 tables and 1 sys_organization row; ds-primary.db held 13 tables and 'no such table: sys_organization'. M8 M5 + --dev: ready, health 200, 61 DATABASE_ERROR lines. M9 R9 (plugin com.acme.store registers a SqlDriver as driver.* in init()) plus a declared archive with autoConnect, production, --log-level debug: ready, health 200. The log read 'Registered driver com.objectstack.driver.sql', then 'Set default driver com.objectstack.driver.sql' (ObjectQLPlugin.start adoption, plugin.ts:965), then 'Registered driver archive' and 'Auto-connected declared datasources [archive]' (AppPlugin.start). No ablation: nothing was changed.",
    "gates": "None owed: the branch has no diff. node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack exited 2 with 'this branch changes nothing against origin/main (merge base 7dc7d22) - nothing to derive' (the repo assertion held). No typecheck, no pnpm lint and no ablation, because no file was edited. No PR, so there are no check-runs.",
    "mcp_calls": "0",
    "api_writes": "1 relay stroke: scripts/pm/post-stamped.mjs, which sends POST /repos//issues/23634/comments (this os-dev-report) as objectstack-fleet[bot] through the fleet-write relay. Also one git push of the empty branch claude/issue-23634-declared-datasource-boot-order at BASE 7dc7d22 (the write-route probe; not REST). Reads (session identity, GET only): issues/23634, its /comments, issues/comments/6184721596 and pulls/23631. No PR, no label write, no assignee write.",
    "open_questions": [
    {
    "question": "What is 'a host config's declared default datasource', and should it serve a bare production serve? The R4 spelling (datasources[].name === 'default') is refused by the host-reserved contract in every posture (M2-M4), and os validate passes it (V1). The spelling the shared resolver recognises (datasourceMapping { default: true, datasource: NAME }, resolve-project-database.ts readConfigDeclaredDefault, maintainer ruling recorded in its header) is honoured by os start / os migrate / standalone serve, but not by host-config serve's storage step. Moving AppPlugin's connect into init() (hypothesis b) fixes neither: R4 is still refused at start, and for any other name it changes M9's default driver.",
    "options": [
    "A: Keep the reservation, and refuse default at authoring instead of after auth starts. The stack's datasources collection refuses a datasource named default. The refusal goes on that collection, not on DatasourceSchema, whose documents include the host's own default row. defineStack, os validate and publish then reject R4 with the remedy (set OS_DATABASE_URL, or declare a datasource under its own name and route objects to it). The published skill line skills/objectstack-data/rules/datasources.md:5 ('Most apps need only the default datasource; declare more ...') is reworded so it no longer reads as an invitation to declare it. serve's remedy line stays as PR #23631 wrote it, and this card's runtime half closes as 'not declarable'. Business need: measured in-repo producers of R4 are zero (examples, create-objectstack, skills, docs). Its only measured producer is the agent-written fixture R4 itself. Every in-repo production entry goes through os start, which hands serve an OS_DATABASE_URL (read in 6184721596). Long-term fit: one contract is kept: default is host-owned (drivers.mdx:265, admin door :1091), and the shared resolver already declines a default-named rule (resolve-project-database.ts:224). The refusal moves from Phase 2 to authoring, which is contract-first. AI-proofing: strongest. The natural AI spelling is refused at os validate with its remedy, where today it passes there (V1) and dies after auth starts (M2). Startup focus: S to M, and no capability expansion. It is a contract tightening, not a new CI gate. Surface: packages/spec (the stack schema) plus the skill line, both outside this claim. Changes no config that boots today: R4 boots in no posture.",
    "B: The host config's own default becomes the host's primary when the host declared none. When a production host-config serve's storage step resolves nothing, serve hands the config's default entry to DefaultDatasourcePlugin, the existing Phase-1 connect (asDefault, bootCritical). AppPlugin then skips that entry instead of refusing it. With OS_DATABASE_URL or --dev, the reservation keeps refusing it, as today (M2, M3). Business need: the same zero producers, and no named operator. Long-term fit: it adds a second spelling of 'the project's default database' beside the mapping rule, and os start / os migrate keep ignoring it, which reopens the per-door fork the shared resolver closed. AppPlugin cannot decide 'the host declared no default' in its own init(). DefaultDatasourcePlugin precedes it only by insertion order, and a stack plugin's driver arrives later, so per AGENTS.md 'Startup registry reads' serve has to pass AppPlugin an explicit signal. AI-proofing: weak. The same declaration boots in one posture and is refused in two. Startup focus: M. It touches serve.ts's storage step (outside this claim's serve.ts surface), the app-plugin.ts reservation and the drivers.mdx contract text. Changes no config that boots today.",
    "C: Host-config serve honours the mapping-rule declared default, through the shared resolver. In production, when the storage step resolves nothing, serve consults the same datasourceMapping { default: true } plus datasources[] resolution that os start uses (today artifact-only; it needs a config-object entry point in packages/runtime) and hands the result to DefaultDatasourcePlugin. The remedy line then names that rule. R4 stays refused, and pairs with A's authoring half. Business need: zero in-repo producers of the mapping shape. examples/app-crm deleted its rule, and its config comment records why. Long-term fit: best convergence, since every door resolves one project's default the same way (option E in 6184721596). AI-proofing: medium. The mapping spelling is less natural, so R4's spelling still needs A. Startup focus: M, and a capability expansion with no measured pull. It lands outside this claim (runtime resolve-project-database.ts plus serve.ts's storage step). A production no-URL host config that boots today on a stack or onEnable driver and also carries a mapping default would gain a second default, so its precedence needs ruling. It inherits M7's split brain unless the rule is installed before boot writes, and that is objectql's, a hold-off.",
    "D (the dispatched hypothesis b, for the record): AppPlugin.init() connects autoConnect declared datasources before any start(). This is rejected on measurement. R4 is still refused at start (M2-M4). For any other name, the init-time connect precedes ObjectQLPlugin.start's driver.* adoption, and engine.ts:8327 makes it the default. M9 boots today on com.objectstack.driver.sql; under D it would move to archive, platform objects included. That changes an existing config's resolution, which the ruling forbids."
    ],
    "recommendation": "A, on all four axes. Business need: neither declared-default spelling has an in-repo producer, the only R4 producer measured is an agent-written fixture, and every in-repo production entry already supplies OS_DATABASE_URL through os start. Long-term fit: it keeps one contract (default is host-owned) and the one shared resolution, where B forks both. AI-proofing: it turns a late Phase-2 refusal into an authoring refusal with the remedy, at the exact door that passes the shape today (V1). Startup focus: it expands no capability. It also leaves PR #23631's remedy line correct as written, since that line deliberately does not send an R4 operator to the thing they already did. C is the coherent route only if a named operator needs a bare production serve over a config-declared default; it then needs triage scope beyond this claim, and objectql's timing fix first (M7). Either way this card's claimed surface (app-plugin.ts connect point plus serve.ts remedy text) cannot deliver the scope as written."
    }
    ],
    "out_of_scope_findings": [
    "class: a · reach: public door objectstack serve objectstack.config.ts (production, OS_DATABASE_URL=file:ctl.db; also --dev) on a host config declaring datasourceMapping: [{ default: true, datasource: 'primary' }] over a declared sqlite primary (M7, M8): 'Server is ready' and health 200, then 59 (URL) / 61 (--dev) DATABASE_ERROR ... no such table lines on platform objects (sys_metadata, sys_setting, sys_organization, ...). The URL store holds 72 tables and the Default Organization; the mapped primary holds 13 tables and no sys_organization. Read in code, not measured: AppPlugin.start() installs the mapping (ql.setDatasourceMapping), and that runs after ObjectQLPlugin.start's schema sync and AuthPlugin.start's Default Organization, both of which used the default store. After it, every unbound object routes to a datasource whose schema never synced. The routing order is objectql's (resolveDatasourceBinding, step 2 before step 5). Landing: objectql or runtime boot order; objectql is #23636's hold-off. Producer: none in-repo (examples/app-crm deleted its rule). · dedupe words: datasourceMapping default rule platform objects no such table; mapping installed after schema sync split brain; sys_organization routed to mapped datasource after boot",
    "class: c · reach: os validate objectstack.config.ts exit 0 ('1 Datasources', V1) on a config declaring datasources: [{ name: 'default', ... }], which every serve posture refuses at AppPlugin.start (M2-M4). Producer: the R4 fixture, written by an agent for #23573's measurement and then read by this card as 'a declared default datasource'. Likely seed: skills/objectstack-data/rules/datasources.md:5 ('Most apps need only the default datasource; declare more ...'). This is option A's subject: if A is chosen, the seat folds it into that card rather than filing it separately. · dedupe words: datasource named default reserved validate passes; host-reserved default datasource authoring refusal; os validate default datasource AppPlugin refuses at start",
    "carrier: none · noted, not filed (read, not measured beyond M9): engine.ts:8327 makes the first driver to reach registerDriver the engine default, so which driver serves unbound objects (platform objects included) depends on Phase order rather than on any declaration whenever no driver is registered asDefault. Measured consequence today: none wrong (M9 resolves to the stack plugin's driver). It is the reason hypothesis (b) changes resolution."
    ],
    "deviations": [
    "Stopped at the ruling's guard ('If a fix would change which datasource an existing config resolves to, STOP and report needs_decision'; 'If the only fix is a plugin-order or contract change outside this surface, STOP and report'). No code, no PR, no changeset, and serve.ts's remedy line was not touched: the ruling restores it only 'once the declared default serves the boot', and no in-surface fix makes it serve.",
    "premise_still_valid is false for the card's stated cause, not for its symptom. R4 never serves (true). The cause is the host-reserved-name refusal at AppPlugin.start, not only the connect timing: with a driver present (M2, M3) the same declaration is refused.",
    "The branch claude/issue-23634-declared-datasource-boot-order is pushed at BASE 7dc7d22 with no commits (the write-route probe). The worktree ../objectstack-issue-23634 is removed after this report (git worktree remove, no --force); it holds no edits.",
    "R9-R13 from #23573 were not re-measured: nothing changed, so nothing can regress. M9 is a new boots-today shape, measured because it decides hypothesis (b).",
    "All fixtures are throwaway projects in the parent's scratchpad (issue-23634/p): @objectstack/spec, driver-sql, plugin-auth, objectql and organizations are symlinked in, and auth secrets are fixture literals. The probe SIGTERMs each process it starts. The V1 copy (vfx) differs from the R4 fixture only by sharingModel: 'private' (grep count 1).",
    "The dispatch's gate list (dispatch-gates list, typecheck, pnpm lint, ablation) was not run: there is no diff to gate (dispatch-gates exit 2)."
    ],
    "files_changed": []
    }

  4. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Release: domain:cli seat 2 · sunhaolin · session_01Q9PZ5Pzqcus4woVvTZwWNU · 2026-10-15T09:41Z · cause: the card's premise is false (this seat's filing error), and every fix is a contract or resolution change outside the claim · destination: pm:queue + pm:retriage, unassigned

    The readings dev ran under claim 6188533413 and stopped at the ruling's guard (os-dev-report on this card). No code, no PR.

    This seat's correction, in public. This card was filed from #23573's out-of-scope finding, and it named the wrong cause.

    • What the card said: R4's declared default datasource connects after AuthPlugin.start().
    • What is true: R4 declares datasources: [{ name: 'default', … }]. AppPlugin.start() refuses a stack-declared datasource named default in EVERY posture, because the name is reserved for the host's primary: "declares a datasource named 'default' — that name is reserved for the host's primary datasource" (app-plugin.ts:1120-:1126). It is documented at drivers.mdx:265 and enforced again at the admin door (datasource-admin-service.ts:1091).
    • Measured: M2 (with OS_DATABASE_URL), M3 (--dev) and M4 (the standalone path) all exit 1 with that refusal. So connecting it earlier only swaps PR fix(cli): a production serve with no storage says so before any plugin starts, and refuses when its auth service needs a driver #23631's refusal for the reserved-name refusal.
    • For any other name, an init-time connect would change which datasource a config that boots today resolves to, because the engine makes its first-registered driver the default (engine.ts:8327). M9 boots today on com.objectstack.driver.sql and would move every unbound object, platform objects included, onto archive.
    • R4 was an agent-written measurement fixture. No in-repo producer was found: not in the examples, create-objectstack, the skills or the docs.

    The options the readings name (four-axis analysis in the report's open_questions):

    • A, recommended by the dev and this seat: keep the reservation and refuse default at authoring.
      • The stack's datasources collection refuses that name, so defineStack, os validate and publish reject R4 with its remedy. Today os validate passes it (V1).
      • Reword skills/objectstack-data/rules/datasources.md:5 ("Most apps need only the default datasource; declare more …").
      • This lands in packages/spec and the skill line, outside domain:cli, and it is a contract tightening of an authoring shape that boots in no posture.
    • B: the host config's own default becomes the primary when the host declared none. This adds a second spelling of the project default, and doors would fork again.
    • C: host-config serve honours the shared resolver's mapping-rule default (datasourceMapping { default: true }). It is the best convergence, but there is no measured pull, and it inherits the split-brain finding below.
    • D (rejected on measurement): connect in AppPlugin.init().

    PR #23631's remedy line stays as written. Its condition to change ("once the declared default serves the boot") is not met, and it deliberately does not send an R4 operator to the thing they already did.

    Filed from the same readings: the datasourceMapping default split brain (M7, M8) as its own card. It is linked below once filed.

    Asked of triage: re-route this card per option A (lane domain:spec for the stack schema, plus the skill line), or close it in favour of a new A card, or rule otherwise.


    Generated by Claude Code

  5. added
    pm:retriageQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatch
    on Oct 15, 2026
  6. 4 remaining items

  7. changed the title [-]runtime: a host config's declared default datasource (autoConnect) never serves a production serve's boot — AppPlugin.start connects config datasources after AuthPlugin.start already needed a driver for sys_organization[/-] [+]spec: the stack's `datasources` accepts a datasource named `default`, which every boot refuses as host-reserved — `defineStack` / `os validate` / publish pass a config that boots in no posture[/+] on Oct 15, 2026
  8. objectstack-fleet commented on Oct 15, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 7 (second shift, parallel again) · 2026-10-15T22:11Z · triage's proxy ruling A (6189356908): the stack's datasources collection refuses a datasource named default, which every boot refuses as host-reserved. So defineStack, os validate and publish say the runtime's sentence and remedy at authoring time. One PR, Fixes #23634.
    Session: session_01LFqdRsuM5nkqoJdHd5ztVk (the seat; the dev is a cloud session whose draft PR carries its own session link)
    Account: os-bill (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-23634-stack-datasource-default-refused
    Worktree: objectstack-issue-23634
    Domain: domain:spec
    Seat: domain:spec#2 (seat post #18549)
    File surface (at origin/main 9bb93706f or later; stop on a breach and explain it in the report):

  9. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 23634,
    "status": "done",
    "branch": "claude/issue-23634-stack-datasource-default-refused",
    "pr": "#23757",
    "session": "session_01UvyD7nLUx7XGKKQVF37FY9",
    "premise_still_valid": true,
    "summary": "Ruling A is implemented. The stack's datasources collection (STACK_DEFINITION_COLLECTIONS_SHAPE in packages/spec/src/stack.zod.ts) carries a superRefine that refuses an entry named exactly default, at datasources.N.name with code custom. The text carries the runtime's sentence ("declares a datasource named 'default' — that name is reserved for the host's primary datasource") and the ruling's remedy (set OS_DATABASE_URL and omit the entry, or declare it under another name and route objects to it). DatasourceSchema, serve.ts and skills/** are untouched. defineStack (array and map form), the bare ObjectStackDefinitionSchema parse (the os validate door) and os validate --json are pinned, beside both CONTROLs (fx_primary passes; the host's own default row parses through DatasourceSchema). There is a D3 semantic entry stack-datasource-host-reserved-name-refused and a BREAKING-minor changeset with the registered disposition. The dropped-refinements ledger gains the 4 installed-package manifest.datasources sites (759 to 763), because the build requires it. The PM hypotheses were measured as follows. H1: the three sentences (app-plugin.ts, datasource-admin-service.ts, spec) are synonymous, not shared; reuse needs a runtime edit, so it is reported, not done. H2: the runtime compares name === 'default', the spec side copies that comparison, and every other spelling is already refused by DatasourceSchema.name's pattern (pinned). H3: re-measured; the R4 shape exits 1 with AppPlugin's refusal under OS_DATABASE_URL and under --dev, so no config that boots today is newly refused. H4: the gate output decided the disposition (adr-0087 registration green with registered). H5: the skills line is in open_questions.",
    "tests": "Head a6f3e6e (branch merged with origin/main a869ea6 via scripts/pm/os-regen-merge.sh). spec: build exit 0; check:generated: all 14 up to date; src/stack-datasource-host-reserved-name.test.ts + scripts/dropped-refinements.test.ts + src/migrations/migrations.test.ts 212/212; full pnpm --filter @objectstack/spec test (pre-merge, at 65b8573+) 679 files passed and 1 red (the ledger header total droppedRefinementSites), fixed in 109c9e9 and then 27/27; typecheck exit 0. cli: the door pin test/stack-datasource-default-validate-door.test.ts (integration) 2/2 on the merge head; vitest run --project unit 293/295 files at first, and the 2 reds were 'packages/cli is not built' (published-subpath-console/hook-body pins); after pnpm --filter @objectstack/cli build they were 29/29; typecheck exit 0. runtime: src/default-datasource-plugin.test.ts 12/12 (AppPlugin's own refusal pin, unchanged). Ablation, valid leg (ablate3): the refusal body was replaced by if ((globalThis as any).__ablation23634 === undefined) return; via scripts/ablation-replace.mjs (marker count 0 to 1); spec build exit 0; ablation-dist-preflight planted: marker in 12 dist files, exit 0; spec pins 4 failed / 3 passed (4 refusals red, 3 controls green); CLI door 1 failed / 1 passed. Restore: git diff HEAD empty, hash equal to the HEAD blob, rebuild exit 0, preflight --absent clean in 232 files, spec 7/7, CLI 2/2. Two earlier legs were no-ops and are not counted. Leg 1 deleted the .superRefine, and the mutated build failed on the dropped-refinements ledger, so dist stayed unmutated (preflight --absent exit 1); the spec leg read src and went red, the CLI leg stayed green and is void. Leg 2 used a string-literal guard, which tsup constant-folded out of dist (preflight planted exit 1). Boot re-measure (H3, source CLI bin/run-dev.js serve, host config with datasources [{name:'default', driver:'sqlite'}] through defineStack strict:false): OS_DATABASE_URL=file:... exit 1 and --dev exit 1, both with [AppPlugin] app 'com.example.fx' declares a datasource named 'default' — that name is reserved for the host's primary datasource. ...",
    "gates": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no path): 90 families for 6 paths. Each was run one by one with the exit code captured before any pipe. On a085cc9: 90 exit 0. First-run reds: check-plugin-teardown-shape --self-test exit 3 (shallow clone, pinned fixture commit 621a487 unreachable; it passed after a depth-1 fetch of that commit), check:dual-build-cjs-loads exit 3 (PREREQUISITE NOT MET: unbuilt sibling dists; exit 0 on rerun once built), and check:stack-collection-maps exit 1 (a real finding: a multi-line z\\n.array( hid datasources from its census; fixed in a085cc9). Rerun on the merge head a6f3e6e: 90/90 exit 0. --ran with CMD :: exit N lines: 'Run reconciliation — 90 derived, 90 run, 0 NOT-MEASURED, 0 UNRUN', a DERIVED zero. Also run: check:adr-0087-registration ✓ (registered stack-datasource-host-reserved-name-refused, new here), check:dev-prereqs exit 0 (local-only). CI check-runs on PR 23757: in_progress at report time, not awaited.",
    "line_budget": "+352 / -2 over 6 files (dispatch-gates: 354 changed lines vs the 3000 human-merge threshold: under). stack.zod.ts +38/-1; spec pin 113; cli pin 133; D3 entry 30; changeset 32; ledger +5/-1.",
    "files_changed": [
    ".changeset/23634-stack-datasource-default-refused.md",
    "packages/cli/test/stack-datasource-default-validate-door.test.ts",
    "packages/spec/dropped-refinements.baseline.json",
    "packages/spec/src/migrations/entries/semantic/18.stack-datasource-host-reserved-name-refused.ts",
    "packages/spec/src/stack-datasource-host-reserved-name.test.ts",
    "packages/spec/src/stack.zod.ts"
    ],
    "deviations": [
    "packages/spec/dropped-refinements.baseline.json is outside the claim's named surface. The spec build refuses until the new refinement's 4 dropped sites (installed-package manifest.datasources) are recorded, and its header total moves 759 to 763. This is a gate-required artifact under the claim's 'generated outputs if the gates ask' clause, and it is hand-edited by that ledger's design. No arm of refinement-projection.ts fits, and adding one is a public-contract decision, so none was added.",
    "The first commit cca45a7 (wip) carries no Claude-Session / Co-authored-by trailer pair; every later commit does. Pushed history was not rewritten.",
    "The CLI unit tier needed a cli build that the dependency-closure build does not produce; 2 files were re-run after the build (see tests).",
    "Merged origin/main (8 commits, including PR 23418's registry.ts.template edit) via os-regen-merge.sh after the gates had run, then re-ran build, check:generated, the pins and all 90 derived gates on the merge head. Package dists other than spec/cli were not rebuilt after the merge; CI builds fresh."
    ],
    "mcp_calls": "4 — mcp__github__issue_read (get, get_comments on 23634), mcp__github__pull_request_read (get_files on 23331 for precedent; get on 23757 for the draft/assignee read-back). No write tools.",
    "api_writes": "2 relay strokes as objectstack-fleet[bot]: (1) scripts/pm/fleet-write/dispatch.mjs pr_create → POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos//issues/23757/assignees [os-bill], run 38828501816 success, body read back byte-identical (8158 bytes); (2) scripts/pm/post-stamped.mjs → POST /repos//issues/23634/comments (this os-dev-report). Plus git pushes of the branch (not REST). No label write (none named by the dispatch).",
    "open_questions": [
    {
    "question": "skills/objectstack-data/rules/datasources.md:4-6 reads: 'Objects route to one via their datasource field (default: 'default'). Most apps need only the default datasource; declare more to read/write a separate or external database.' 'Declare more' implies default is declared too, so it invites the refused shape. Should the skills lane reword it?",
    "options": [
    "A: reword to 'Most apps need only the host's default datasource, which the host connects from OS_DATABASE_URL; never declare a datasource named default (the name is host-reserved and refused). Declare a datasource under its own name only to read/write a separate or external database.'",
    "B: leave it; the authoring refusal now catches the shape at os validate"
    ],
    "recommendation": "A. AI-proofing: the published skill is what an AI reads first, and the refusal should not be the first place it learns the rule. Long-term fit: the skill then states the contract the spec enforces. Startup focus: one line, net zero or less. Business need: the only measured producer of the shape was an agent."
    },
    {
    "question": "The reserved-name refusal is now said in three places (runtime app-plugin.ts, the admin door datasource-admin-service.ts, spec stack.zod.ts): synonymous, not shared. Should spec export the reserved name and refusal text for the runtime to reuse?",
    "options": [
    "A: export the name constant and the sentence builder from @objectstack/spec, and have AppPlugin and the admin service import them (runtime + service-datasource edits, an api-surface addition)",
    "B: keep three synonymous sentences, each owned by its door"
    ],
    "recommendation": "A, as a follow-up in the runtime lane. Long-term fit: one source for one contract. AI-proofing: no drift between the doors. Startup focus: small, but it adds a public export, so it needs its own card and not this PR's surface."
    }
    ],
    "out_of_scope_findings": [
    "carrier: none · noted, not filed: the published JSON Schema stays wider than the parse for this rule (it is recorded in the dropped-refinements ledger, like the 759 sites before it); closing it needs a new refinement-projection arm, which that module calls a public-contract decision"
    ]
    }

  10. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Landing record, PR #23757 · domain:spec seat 2 (#18549) · session session_01LFqdRsuM5nkqoJdHd5ztVk · 2026-10-16T01:28Z

    Probe Reading
    origin/main 0a052e6705 "feat(spec)!: a stack's datasources collection refuses a datasource named default, the host-reserved name (#23757)", merged through the queue at 2026-10-16T01:27Z (git branch -r --contains → origin/main)
    merge queue no gh-readonly-queue/main/* ref names #23757
    squash vs reviewed head The squash tree aad16cefdc4c equals git merge-tree --write-tree of its parent eae3b389d2 with a6f3e6e812. That head carries contract review PASS 6205386930 and ACCEPT 6205431264.
    card closed completed by Fixes #23634

    What ships. A stack's datasources collection refuses an entry named default at datasources.N.name, with the runtime's sentence and remedy (set OS_DATABASE_URL, or declare the datasource under another name and route objects to it). It reaches defineStack, os validate and publish. DatasourceSchema and the host's own default row are unchanged. The D3 entry is stack-datasource-host-reserved-name-refused.

    Follow-ups.

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions