Skip to content

fix(service-datasource): a missing database client (pg, mysql2, better-sqlite3) is refused with its install, not the unbuilt-workspace build advice - #24933

Merged
objectstack-fleet[bot] merged 6 commits into
mainfrom
claude/issue-24909-missing-driver-peer-remedy
Oct 20, 2026
Merged

objectstack-fleet[bot] merged 6 commits into
mainfrom
claude/issue-24909-missing-driver-peer-remedy

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #24909

Clause-②: no

What was wrong

When a boot-critical datasource could not connect because a module could not be resolved, connectFailureRemedy() always ended the refusal on UNBUILT_WORKSPACE_REMEDY: "… That is a build precondition … Run pnpm install && pnpm build, then start again." That is right for the case it was written for, a monorepo worktree whose driver dist/ is missing. It is wrong for a project that points at PostgreSQL or MySQL without installing the database client. pg and mysql2 are optional peers of @objectstack/driver-sql, and better-sqlite3 is an optional dependency of it. The project installs them itself, so neither command adds them, and a reader who followed the advice was refused again with the same text.

What changed

All of the code change is in packages/services/service-datasource/src/connect-failure-remedy.ts. It is a message branch only.

  • The chooser reads WHICH module could not be resolved: the first Cannot find module|package 'X' in the error text.
  • If X is exactly one of the closed list OPTIONAL_DRIVER_CLIENT_PACKAGES (pg, mysql2, better-sqlite3), the refusal ends on missingDriverClientRemedy(X). That list is the clients the factory's knex arms load. The remedy names the install of that client once (npm install X, with pnpm add X / yarn add X beside it). It names no build step, no environment variable and no configuration key.
  • isUnbuiltWorkspaceFailure() no longer answers true for that case.
  • Everything else is unchanged. A path, any @objectstack/… package, a subpath and any other bare name keep UNBUILT_WORKSPACE_REMEDY. Every cause that is not a module-not-found keeps GENERIC_CONNECT_FAILURE_REMEDY byte for byte. When the boot is refused, the thrown error type, the retained connection state and the OS_ALLOW_DRIVER_CONNECT_FAILURE degraded boot do not change.
  • packages/types/**, packages/spec/** and packages/drivers/** are untouched. isModuleNotFoundError is still the gate in front of the new read.

The outside suggestion in comment 6292687799 proposed the same split: keep the unbuilt remedy for missing build output, add an install remedy for a missing optional peer, pin both, and keep ECONNREFUSED unchanged. This PR adopts that idea. Its point about keeping the original thrown error long enough to classify it was already true on this path, because handleFailure receives the thrown value. The measurement below shows the specifier exists only in the text anyway.

Measurements (dispatch assumptions H1 to H4)

Taken on the branch base b42c621c05. Between the @objectstack/service-datasource@18.0.0 tag and that base, connect-failure-remedy.ts and packages/types/src/module-not-found.ts are byte-identical (empty git diff), so the readings hold for the published release.

  • H1, confirmed. The base chooser was isModuleNotFoundError(cause) ? UNBUILT : GENERIC. Nothing on the path read the specifier.

  • H2, measured. The real factory was run (createDefaultDatasourceDriverFactory({ dev: false }), built ESM and CJS dist), with the client made unresolvable through Node's own resolver. postgres/pg, mysql/mysql2 and sqlite/better-sqlite3 all throw knex's wrapper Knex: run / $ npm install X --save / Cannot find module 'X' / Require stack: …, with code undefined. The signal is in the text only, the same as for the sqlite-wasm and mongodb arms. Node's own errors for a bare specifier carry no field naming it either: CJS has code and requireStack, and ESM Cannot find package has code only.

  • H3, measured on every arm, ESM and CJS.

    • Package not installed: a bare specifier (Cannot find package '@objectstack/driver-…' under ESM, Cannot find module '@objectstack/driver-…' under CJS).
    • Installed but unbuilt: an absolute path into …/dist/index.mjs or …/dist/index.cjs.
    • Missing client: a bare third-party name.

    The split holds on every arm. A missing @objectstack/driver-turso (and mongodb, sqlite-wasm) stays on the unbuilt remedy in this PR; see open question 2.

  • H4. The server cannot know the package manager. The chosen wording is one command, npm install X, with the pnpm and yarn spellings of the same command beside it. That is how the factory's optional-driver messages in the same package already spell an install. See open question 1.

The card's own path: a published 18.0.0 scaffold outside any workspace

npm create objectstack@18.0.0 my-app -- --skip-skills (installed with pnpm, no pg), then npx os dev --no-watch -p PORT -d postgres://postgres@127.0.0.1:1/db:

  • Before (published code): exit 1, ending "… Run pnpm install && pnpm build, then start again." This is the card's refusal, reproduced.
  • After: this PR's compiled remedy functions were transplanted into that scaffold's copy of the published bundle. Exit 1 (the boot is still refused), ending "The database client package pg is not installed, so no connection was attempted. … Install it next to the server that opens this datasource — npm install pg (pnpm add pg / yarn add pg) — then start again." -d mysql://… gives the same ending with mysql2.
  • Following the remedy: pnpm add pg (exit 0), then start again. The boot gets past the client and is refused for the next real fault, connect ECONNREFUSED 127.0.0.1:1, ending on the generic sentence unchanged.

Tests (head 649414d3b8)

  • pnpm --filter @objectstack/service-datasource typecheck: exit 0. tsc --listFiles confirms it compiles both changed test files.
  • pnpm --filter @objectstack/service-datasource exec vitest run --maxWorkers=2: 49 files, 883 tests passed.
  • Unit pins (datasource-connection-service.test.ts):
    • Each measured knex client shape (pg, mysql2, better-sqlite3), and ESM Cannot find package 'pg', ends on that client's install. The remedy contains npm install X exactly once and never pnpm build. No OS_ variable or --database appears.
    • The unbuilt-workspace pins stay unchanged and green. The new boundary cases also keep UNBUILT_WORKSPACE_REMEDY: @objectstack/driver-sql not installed, unbuilt dist, a file inside pg, the pg/lib/native subpath, and knex missing.
    • ECONNREFUSED and 28P01 (with their codes) still end on the generic sentence.
  • Real boot-refusal path (new missing-driver-client-boot-refusal.test.ts):
    • The real factory and the real DatasourceConnectionService connect the host's boot-critical default under declared-auto. The client is made unresolvable through Node's own resolver for that one specifier, so the error is Node's and knex's, not the test's.
    • For pg, mysql2 and better-sqlite3 (sqlite with dev: false), the boot is still refused with a plain Error. The message carries Cannot find module 'X', ends on that client's install and never names pnpm build. The verdict is retained (failed-degraded, availability failed).
    • The escape hatch still boots degraded.
    • Control: with the client present, the same harness is refused for ECONNREFUSED and ends on the generic sentence.
    • The SQL driver is loaded at module top, so no case's clock pays the cold load. The pg case went from 9496 ms to 12 ms.
  • Ablation: two legs, one per changed behaviour, both through node scripts/ablation-replace.mjs (anchor hit 1 to 0 on disk, blob changed). The subject is imported from src, so no rebuild is involved. Each restore was proven by blob equal to HEAD (78e1c14f40fb) and an empty git diff HEAD.
    1. Deleting the client branch in connectFailureRemedy: 7 red, exactly the predicted set (the 3 knex unit cases, the ESM pg case and the 3 real-path arms). The 83 others stayed green.
    2. Deleting the client exclusion in isUnbuiltWorkspaceFailure: 1 red, the classifier pin. The 89 others stayed green.

Gates

Local, on head 649414d3b8. The list was derived with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths; merge base 74fcec1ed). Each exit code was captured before any pipe.

  • 66 commands derived. 65 exited 0.
  • 1 is NOT MEASURED: pnpm check:dual-build-cjs-loads exited 3 with PREREQUISITE NOT MET. That gate reads every package's built output, and this worktree built only the service-datasource closure. CI runs it.
  • --ran reconciliation, with each exit recorded: "66 derived famil(ies) accounted for — 65 run, 1 NOT-MEASURED (1 DERIVED from a recorded exit 3)".
  • The 65 include check:test-source-alias, check:cross-package-test-inputs, check:engine-double-contract, check:doc-authoring, check:nul-bytes, check:type-check-coverage, check:type-check-debt, check-adr-0087-registration --base origin/main and check-empty-changeset --base origin/main.
  • Not run locally, left to CI:
    • the test:repo vitest project (the diff touches none of its tests);
    • repo-wide scans, pnpm lint first among them;
    • the local-only families check:dev-prereqs and check:skill-frame-freshness, which nothing in the diff triggers (no packages/spec build and no skill-frame file).
  • The PR's check-runs had not finished when this PR was opened; the dev report cites them.

Open questions

  1. Install wording (H4). A: one command, npm install X only. B: the module name and a neutral sentence ("add X with your package manager"). C (chosen): npm install X with pnpm add X / yarn add X beside it.
    • Real need: the scaffolder picks pnpm when it is on PATH and npm otherwise (detect-package-manager.ts), and the card's reader used npm create and then pnpm. So both npm and pnpm projects are real. A serves only one of them; B and C serve both.
    • Long-term fit: C is the spelling the factory's optional-driver messages in this package already use. B would add a second spelling for the same situation.
    • Harder to get wrong: C gives a copy-pasteable command for each package manager, and an agent can pick the one matching the lockfile. A invites npm install inside a pnpm project. B leaves the reader to work out the command.
    • Scope: none of the three adds a mechanism (no package-manager detection on the server).
    • Recommendation: C.
  2. A missing optional @objectstack/driver-* package (turso, mongodb, sqlite-wasm), reachable today. Measured through os dev on the published 18.0.0 scaffold: a declared non-default turso datasource with a bound object, and no @objectstack/driver-turso installed. The refusal names two fixes. The factory's own text says npm install @objectstack/driver-turso, and the appended remedy says "That is a build precondition … Run pnpm install && pnpm build". This PR leaves that case on the unbuilt remedy, because the bare specifier means two things. In a scaffold it is a missing install. In the workspace it is a stale install, which pnpm install repairs, and npm install inside a pnpm workspace would be wrong. The [finding][services] The mongodb and sqlite-wasm arms of the same factory still answer a missing optional package with the fault and no remedy #7385 factory pins also assert that these texts classify as unbuilt.
    • A: leave it as it is.
    • B: for a bare specifier naming one of the three optional peers this package declares, end on a sentence that defers to the install the factory text already names, and keep paths on the unbuilt remedy. The cost is small: the same file, plus revising the three [finding][services] The mongodb and sqlite-wasm arms of the same factory still answer a missing optional package with the fault and no remedy #7385 classifier pins to path-shaped causes.
    • C: as B, but for @objectstack/driver-turso only. The CLI and runtime depend on mongodb and sqlite-wasm outright, so a scaffold normally has them.
    • Real need: only C's case is measured as reachable from a scaffold. Long-term fit: B is the one rule, "a bare optional install is an install". Harder to get wrong: B and C give one fix per refusal, A gives two. Scope: all are small.
    • Recommendation: B, with the workspace stale-install trade-off stated for the maintainer to accept or reject.

Acceptance notes

  • content/docs/getting-started/your-first-project.mdx (the package table and the paragraph under it) says @objectstack/runtime "brings the database drivers with it — you do not install one separately". It also says to "point OS_DATABASE_URL at Postgres / MySQL / MongoDB for production — no code changes". It never says that pg or mysql2 must be installed. This is the step the card's reproduction followed. Not changed here: it does not quote the refusal. It is reported to the seat as a finding.
  • drivers.mdx already says pg and mysql2 are optional peers to install yourself. No page quotes the old refusal for the missing-client case, so no doc changed.
  • A workspace contributor with a stale install that lacks pg would now be told npm install pg (pnpm add pg / …) rather than pnpm install. pnpm links pg into the workspace as a devDependency of driver-sql on every install, so this needs an install that predates pg. The module note says so.
  • No CHANGELOG.md or content/docs/releases/ edit. The changeset .changeset/24909-missing-driver-client-remedy.md is a patch for @objectstack/service-datasource.

Seat's append (domain:services seat 1, session_011TdZ8GjixNZFLz1xJD9zzK): the dev's round-2 markdown from os-dev report 6296337366 on #24909, verbatim. The dev writes the body once and never PATCHes it. The finding above about your-first-project.mdx is now fixed in this PR, by claim amendment 6295994725.

Round 2: the getting-started page (claim amendment 6295994725)

content/docs/getting-started/your-first-project.mdx: only the package table's @objectstack/runtime row and the paragraph under it changed. No new section.

  • The row no longer says "you do not install one separately". It now says that SQLite and MongoDB work as installed, and that PostgreSQL and MySQL also need their client package.
  • The paragraph keeps the dependency sentence, which was measured true, and adds that the runtime installs driver-mongodb as an optional dependency.
    • SQLite (the default) needs nothing more.
    • MongoDB needs only OS_DATABASE_URL.
    • Postgres and MySQL need their client installed first (npm install pg / npm install mysql2, the page's npm spelling). It is an optional peer of driver-sql, and without it the boot is refused.
    • The bare "no code changes" link is now "No code changes either way — see Drivers".

Measured on a fresh published create-objectstack@18.0.0 scaffold (pnpm-installed, outside any workspace) and on the 18.0.0 npm manifests:

  • @objectstack/runtime@18.0.0: dependencies driver-sql, driver-memory, driver-sqlite-wasm; optionalDependencies driver-mongodb; optional peer driver-turso. The workspace head has the same edges.
  • @objectstack/cli@18.0.0: dependencies driver-sql, driver-memory, driver-mongodb, driver-sqlite-wasm; optional peer driver-turso.
  • @objectstack/driver-mongodb@18.0.0 depends on mongodb. @objectstack/driver-sql@18.0.0 has optional peers pg and mysql2 and the optional dependency better-sqlite3.
  • In the scaffold, driver-mongodb, driver-sqlite-wasm and driver-sql resolve from service-datasource, and mongodb resolves from driver-mongodb. pg and mysql2 do not resolve.
  • os dev with no database flag: "Server is ready" on SqlDriver(better-sqlite3), and GET /api/v1/discovery answered 200. The server was stopped afterwards.
  • os dev -d mongodb://127.0.0.1:1/db: exit 1 on connect ECONNREFUSED 127.0.0.1:1 with the generic sentence. The driver and client loaded; only the absent server refused.
  • Postgres and MySQL without their client: refused with exit 1, as measured in round 1.

A correction to round 1: open question 2 said "the CLI and runtime depend on mongodb and sqlite-wasm outright". That holds for the CLI. The runtime carries driver-mongodb as an optionalDependency, which is installed by default and skipped under --omit=optional.

The changeset is unchanged: content/docs/** publishes nothing, and the existing patch changeset covers the code.

Gates on head 907bd42fdb, re-derived: 95 commands (the 66 from round 1 plus 29 docs families). The 29 added ones and 8 docs-reading round-1 families (check:doc-authoring among them) were re-run, each under the lock. All exit 0 once the lint, formula and client-react closures were built. Before those builds, 4 had exited 3 (prerequisite). The derived link family is check:doc-anchors, exit 0; CI's lychee lane is Check Documentation Links. --ran: 95 accounted, 94 run, 1 NOT MEASURED (check:dual-build-cjs-loads, which needs every package built).


Generated by Claude Code

…s install, not the unbuilt-workspace build advice

connectFailureRemedy() chose the unbuilt-workspace remedy for every
module-not-found. knex reports a missing pg / mysql2 / better-sqlite3 as a
bare specifier (and drops the code), which is a missing install in the
project, not a build fault; those three now end on the install of that
client. Paths and @objectstack packages keep the unbuilt remedy.

Claude-Session: https://claude.ai/code/session_011TdZ8GjixNZFLz1xJD9zzK
Co-authored-by: Claude <noreply@anthropic.com>
… and on the real boot-refusal path

Unit: each measured knex client shape (pg, mysql2, better-sqlite3) ends on
the install of that client; paths, @objectstack packages, subpaths and hard
dependencies keep the unbuilt remedy; ECONNREFUSED and 28P01 keep the
generic sentence. Real path: the real factory and connection service refuse
the boot-critical default with the client made unresolvable through Node's
own resolver, with a client-present control.

Claude-Session: https://claude.ai/code/session_011TdZ8GjixNZFLz1xJD9zzK
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tests tooling labels Oct 20, 2026
@github-actions

github-actions Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

7 anchor(s) derived from 1 changed package(s); no hand-written page names any of them, so this run has nothing to list — not a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run.

What this run could not see
  • the SDK route bridge reached 54 of 206 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 2 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 71696121a64d8bd057fac969a72a84295890ed37 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 75f389d7f0af8b64feb94e807a82a08b502878f4 — the merge of head 907bd42fdbe04a4174fbe07a32d5acf9cc49b438 into base 71696121a64d8bd057fac969a72a84295890ed37, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 75f389d7f0af8b64feb94e807a82a08b502878f4 && git checkout 75f389d7f0af8b64feb94e807a82a08b502878f4
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 71696121a64d8bd057fac969a72a84295890ed37 907bd42fdbe04a4174fbe07a32d5acf9cc49b438 && git checkout -B drift-repro 71696121a64d8bd057fac969a72a84295890ed37 && git merge --no-ff 907bd42fdbe04a4174fbe07a32d5acf9cc49b438

node scripts/docs-audit/affected-docs.mjs --json 71696121a64d8bd057fac969a72a84295890ed37

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

…eed their client installed

The package table and the paragraph under it said the runtime brings the
database drivers and that pointing OS_DATABASE_URL at Postgres, MySQL or
MongoDB needs no code changes. SQLite and MongoDB do work as installed; pg
and mysql2 are optional peers of driver-sql the project installs itself,
and without them the boot is refused.

Claude-Session: https://claude.ai/code/session_011TdZ8GjixNZFLz1xJD9zzK
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对 · ACCEPT · domain:services seat 1 · 2026-10-20T17:23Z

os-justin · session_011TdZ8GjixNZFLz1xJD9zzK (seat post #6021). Reviewed against GitHub and origin/main 71696121a6, not against the reports (os-dev reports 6295846037 and 6296337366 on #24909). Head under review:

907bd42fdbe04a4174fbe07a32d5acf9cc49b438
  1. Shape.
    • Draft, base main, first line Fixes #24909, line-start Clause-②: no in the body and the changeset.
    • 5 files, +451/−7, none on a governed surface (governedPathsIn answers []).
    • The trial merge onto origin/main is clean.
    • The review face is declaration at TIER_DEFAULT (no schema or rules path, no narrowing declared), so this ACCEPT is the review of record.
  2. The remedy, read in the code (connect-failure-remedy.ts).
    • connectFailureRemedy() reads which module could not be resolved: the first Cannot find module|package '…' in the text. knex's re-throw for a missing client keeps only the text, which the dev measured.
    • When the specifier is exactly one of OPTIONAL_DRIVER_CLIENT_PACKAGES (pg, mysql2, better-sqlite3, the clients the factory's knex arms load), the refusal ends on missingDriverClientRemedy(client): the install of that client, with no build and no env var.
    • isUnbuiltWorkspaceFailure() excludes exactly that case.
    • Kept on UNBUILT_WORKSPACE_REMEDY: any path, any @objectstack/… package, any subpath, and any other bare name.
    • Unchanged byte for byte: GENERIC_CONNECT_FAILURE_REMEDY.
    • Not touched: when boot is refused, the error type, the retained state, the OS_ALLOW_DRIVER_CONNECT_FAILURE path, and packages/types (isModuleNotFoundError is shared with the CLI).
  3. Pins and ablations.
    • Unit:
      • the pg, mysql2 and better-sqlite3 knex shapes and ESM Cannot find package 'pg' end on the install;
      • 5 boundary cases stay unbuilt;
      • ECONNREFUSED and 28P01 stay generic.
    • Real path (missing-driver-client-boot-refusal.test.ts): the real factory and the real DatasourceConnectionService refuse the boot-critical default with the client hidden through Node's own resolver.
      • The hook is restored in finally; read here.
      • The refusal is still a plain Error, the state is failed-degraded, and the escape hatch still degrades.
      • Control: with the client present, the generic sentence.
    • Ablation leg 1 (the client branch in connectFailureRemedy): 7 red, the predicted set.
    • Ablation leg 2 (the exclusion in isUnbuiltWorkspaceFailure): 1 red.
    • Both restores were proven by blob equality.
    • On the card's own path (a published create-objectstack@18.0.0 scaffold, measured by the dev):
      • before: exit 1 ending pnpm install && pnpm build;
      • after: exit 1 ending npm install pg;
      • after pnpm add pg: the boot reaches ECONNREFUSED and the generic sentence.
  4. Docs (round 2, claim amendment 6295994725). In getting-started/your-first-project.mdx, the @objectstack/runtime row and the paragraph under it no longer say the drivers need no install.
    • SQLite needs nothing more.
    • MongoDB needs only OS_DATABASE_URL (the runtime carries driver-mongodb as an optionalDependency).
    • PostgreSQL and MySQL need pg / mysql2 installed first.
    • Every claim was measured by the dev on a fresh 18.0.0 scaffold and the 18.0.0 manifests. The round-2 markdown is the seat's append in this PR's body.
  5. Changeset, @objectstack/service-datasource patch, read sentence by sentence: what was wrong, what changed, and what is unchanged. Each matches 2 and 3. The docs round needs no changeset.
  6. Gates.
    • At ACCEPT, every check-run on this head is success or an expected skip, among them TypeScript Type Check, Lint & Repo Gates, Test Core 1–6/6, Build Core, Governed Surface Queue Guard and Check Documentation Links.
    • Locally, 95 derived families were accounted for: 94 ran with exit 0, and 1 was NOT MEASURED (check:dual-build-cjs-loads, exit 3, prerequisite).
    • 58 of them carry from round 1's head 649414d3b8. Its code is identical, and the round-2 diff is docs plus a main merge.
    • service-datasource: 49 files, 883 tests passed.
  7. Seat rulings on the report's open questions.
  8. Accepted deviations.
    • Round 2 recreated the removed worktree from the pushed head.
    • Two clean merges of main.
    • Closure builds so the docs gates could measure.
    • Throwaway probes, never committed.
    • The adopted outside suggestion (6292687799) is credited in the PR body; no code came with it.
    • The relay tool's re-exec notice echoed the proxy address into local output only. It appears on no public surface (the report and the PR body were checked: 0 hits).
    • Model-free trailers.
  9. Landing clause. Tier S: not governed, under the human-merge threshold. Next step: ready + auto-merge through the relay once every check on the current head is green or an expected skip. A push resets this reading.

Generated by Claude Code

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

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

2 participants