Skip to content

Commit e169acb

Browse files
docs(changeset): make the two pending connectionTimeoutMs notes true when read as one release (#19918)
Fixes #19851 Clause-②: no ## What this changes Changeset text only: two PENDING notes on `origin/main`, `.changeset/18975-connector-retry-config-and-request-timeout.md` and `.changeset/19580-retire-connector-connection-timeout-ms.md`, `+47 / -29`. No code, no other file, and no frontmatter line: packages and levels are byte-identical to the merge base. Both notes go into the same next release. The last tag is `@objectstack/*@17.4.0`. On npm, `latest` for `@objectstack/spec`, `connector-rest`, `connector-openapi`, `connector-mcp`, `connector-slack` and `service-automation` is `17.4.0`, published 2026-09-09, with no version after it. Read together as that one release, the base text said that `ConnectorProviderContext` **gains** `connectionTimeoutMs`, and also that the same member, called "a published interface member", is **removed**. It also misstated what the residue stage does with the default value, and it anchored its read census to a moving ref. After this PR, every sentence the two notes publish is true of what that release ships. ## DELIBERATE CORRECTION: this PR awaits the maintainer's written confirmation, and `Check Changeset` is red on purpose This PR adds no changeset of its own. It changes two pending changesets it did not add. Route 0's discriminator against the merge base: ``` $ git diff --name-status 8490127 HEAD -- '.changeset/*.md' M .changeset/18975-connector-retry-config-and-request-timeout.md M .changeset/19580-retire-connector-connection-timeout-ms.md ``` Every row is `M` and none is `A`, so this is the DELIBERATE CORRECTION class that `scripts/check-empty-changeset.mjs` names. It is not a COLLISION: nothing of this PR's own was overwritten, and restoring the base copies would republish the false sentences. - ⛔ No `skip-changeset` label, and ⛔ no new changeset file (ruling D on #18375). - `Check Changeset` stays **advisory red**. It is not one of the seven required contexts. Every other check should be green. - **This PR awaits the maintainer's one-sentence confirmation of the correction.** The owning seat carries it to this PR with its provenance (who, the words, where). The PR is not to be armed before that confirmation is on it. ## Measurements (taken before editing a word) The worktree was cut at merge base `8490127962`. The checkout is a full clone (`git rev-parse --is-shallow-repository` answers `false`). ### M1: the three members entered after 17.4.0, and no release carried them | Question | Instrument | Reading | |---|---|---| | When did each member enter and leave? | `git log -G 'connectionTimeoutMs\?:' origin/main` on `connector-provider.ts`, `rest-connector.ts` and `openapi-connector.ts` | For all three files, it entered with `b929e0a662` (2026-09-20, #19388) and left with `fc29c74400` (2026-09-23, #19657). | | Is `b929e0a662` in any release? | `git tag --contains b929e0a` | 0 tags. | | Same question, by ancestry | `git merge-base --is-ancestor b929e0a '@objectstack/spec@17.4.0'` | **exit 1**. The control leg is `@objectstack/spec@17.3.0` (`8a1bad8b8e`), in the same checkout, against the same target, an older commit: **exit 0**. | | Is 17.4.0 the newest release? | `git ls-remote --tags origin 'refs/tags/@objectstack/spec@*'` and `npm view @objectstack/spec dist-tags time` | The newest tag is `17.4.0`, which peels to `7e6337007f`. The `connector-rest`, `connector-openapi` and `service-automation` 17.4.0 tags point at the same commit. npm has `latest` `17.4.0` and `rc` `17.0.0-rc.6`, and nothing was published after 2026-09-09T03:57Z. | | What did 17.4.0 ship? | `npm install @objectstack/spec@17.4.0`, then read `dist/integration/index.d.ts` | `interface ConnectorProviderContext` has `name`, `label`, `description`, `icon`, `type`, `providerConfig`, `auth` and `loadPackageFile`. It has no `connectionTimeoutMs`, and no `retryConfig` or `requestTimeoutMs` either. | | same | `npm pack @objectstack/connector-rest@17.4.0` and `@objectstack/connector-openapi@17.4.0`, then read every `.d.ts` | `interface RestConnectorOptions` and `interface OpenApiConnectorConfig` are present (the control), with **0** `connectionTimeoutMs` occurrences in any `.d.ts`. | | What does the next release ship? | `packages/spec/src/integration/connector-provider.ts:67` at the merge base | `ConnectorProviderContext` declares `retryConfig` and `requestTimeoutMs`. `connectionTimeoutMs` appears only in a "REMOVED" comment. `rest-connector.ts:42` and `openapi-connector.ts:130` have comments only. | The authorable key **was** published. In the 17.4.0 source, `connector.zod.ts:839` reads `connectionTimeoutMs: z.number().min(1000).max(300000).optional().default(30000)`, and `DeclarativeConnectorEntrySchema` (`:955`) is built on `ConnectorSchema`. The M2 probe of the released 17.4.0 package shows `ConnectorSchema` accepting and keeping an authored `15000`. So "a published authorable key is removed on two carriers" stays true, and it is now the only thing the Clause-② sentence rests on. ### M2: parse probes, with the path each refusal is reported at For today's tree, `tsx` ran against `packages/spec/src` at the merge base, for four carriers. The entry is `{ name: 'ledger_api', label: 'Ledger API', type: 'api' }` plus the key: | `connectionTimeoutMs` | `ConnectorSchema` | `DeclarativeConnectorEntrySchema` | `getMetadataTypeSchema('connector')` | `ObjectStackSchema` (`connectors: [entry]`) | |---|---|---|---|---| | absent (control) | accept, key absent | accept, key absent | accept, key absent | accept, key absent | | `30000` | **accept, key stripped** | **accept, key stripped** | **accept, key stripped** | **accept, key stripped** | | `15000` | refuse `invalid_type` @ `connectionTimeoutMs` | same | same | refuse `invalid_type` @ `connectors.0.connectionTimeoutMs` | | `1000` | same as `15000` | same | same | same | | `"30000"` (string) | same as `15000` | same | same | same | Every refusal message names `requestTimeoutMs`. In every accepted case `requestTimeoutMs` still reads `30000`, the control that shows the stage leaves the live sibling alone. `ConnectorSchema` is a `pipe` whose input stage is a `transform`. The tombstone **without the stage** is the pipe's inner object. It refuses `30000` at `connectionTimeoutMs`, and it accepts the same entry with the key absent (the control). Released side: `@objectstack/spec@17.4.0` from npm emits `connectionTimeoutMs: 30000` for that entry on `ConnectorSchema`, on `DeclarativeConnectorEntrySchema` and on `ObjectStackSchema`, and it accepts and keeps an authored `15000`. `npm pack` of `connector-mcp`, `connector-openapi`, `connector-rest` and `connector-slack` at `17.4.0` each ship one literal `connectionTimeoutMs: 3e4` in their JS. ### M3: which sites READ the key (one number: **six**) The instrument is `git grep -n connectionTimeoutMs SHA -- . ':!packages/spec'`, keeping non-test code files. It was run at `e07843b5a6`, the parent of the landing commit `fc29c74400`, and gives an identical result at `6eaa0f4a81`, the review's merge base. The result is 13 occurrences, 7 files, 5 packages: - **6 reads:** `openapi-connector.ts:242`, `openapi-provider.ts:193`, `rest-connector.ts:134`, `rest-provider.ts:64`, `plugin.ts:307`, `plugin.ts:1589` - 4 type declarations: `openapi-connector.ts:135`, `rest-connector.ts:47`, `plugin.ts:291`, `plugin.ts:339` - 3 literal `30000` writes: `mcp-connector.ts:247`, `slack-connector.ts:94`, `plugin.ts:1782` Six read expressions sit at six file:line locations. The "five sites" phrasing elsewhere counts the two `?? 30000` fallbacks as one site: it is the same set in a different unit (see the acceptance notes). Within the changesets, the one count used is **six reads**, and the tree it was taken on is now named. `0870fb5418`, which the note cites for the earlier census, re-measures at exactly five hits, all `connectionTimeoutMs: 30000,`, as the note says. ## Old and new, per file ### `.changeset/18975-connector-retry-config-and-request-timeout.md` **(a)** This release does not add a member that the same release removes (M1). > old: `ConnectorProviderContext` gains `retryConfig`, `connectionTimeoutMs` and `requestTimeoutMs`, read-only and resolved from the entry … > new: `ConnectorProviderContext` gains `retryConfig` and `requestTimeoutMs`, read-only and resolved from the entry … **(b)** The key is no longer described as "carried onto `ConnectorProviderContext`" and "owed a decision". The same release retires it, and no release carries it on the context (M1). The mapping and the ledger still record the reason: `connector-fetch-policy.ts:57` and `liveness/connector.json` `props.connectionTimeoutMs.status: dead`, both at the merge base. > old: **⚠️ `connectionTimeoutMs` is NOT enforced, deliberately, …** … So it is carried onto `ConnectorProviderContext` (a custom provider on a transport that *can* separate the phases may honour it) and left unenforced by the platform, with the reason recorded at the mapping and in `packages/spec/liveness/connector.json`, which keeps that one row `dead`. It is owed a second, narrower ADR-0049 decision: retire it, or re-describe it as something the platform can enforce. > new: **⚠️ `connectionTimeoutMs` is NOT made live, deliberately, …** … So this change leaves it unenforced, with the reason recorded at the mapping and in `packages/spec/liveness/connector.json`, whose row for it stays `dead`. That left it owed a second, narrower ADR-0049 decision, and this same release takes it: `connector.connectionTimeoutMs` is **retired**, and its own entry in this release says what to write instead. The key never reaches `ConnectorProviderContext` in any release. **(c)** The claim that the schema "keeps every key" is scoped to the change it describes. Read as a claim about the release, it is false twice. `connectionTimeoutMs` is retired by `fc29c74400`. `syncConfig.schedule` is deleted by `929d9e3f20`: present at 17.4.0, absent at the merge base, and `git merge-base --is-ancestor 929d9e3 '@objectstack/spec@17.4.0'` gives exit 1. As a claim about `b929e0a662` itself it holds: that commit changes 0 non-comment lines of `connector.zod.ts`, the file that also holds `RetryConfigSchema`. > old: Nine of the ten ledger rows flip `dead` → `live` with the consumer site named. No declaration moves: the connector schema keeps every key, every bound and every default it had. > new: Nine of the ten ledger rows flip `dead` → `live` with the consumer site named; the tenth is `connectionTimeoutMs`, above. This change itself moves no declaration: it leaves every key, every bound and every default on the connector schema as it found them. ### `.changeset/19580-retire-connector-connection-timeout-ms.md` **(d)** The never-released member is no longer called published. The Clause-② sentence now rests on the authorable key alone (M1). The line's leading token is unchanged, and `readClause2Line` reads it identically at base and head. > old: `Clause-②: yes (narrowing)` — a published authorable key is removed on two carriers and a published interface member leaves `ConnectorProviderContext`, so the accept set a consumer writes against narrows. > new: `Clause-②: yes (narrowing)` — a published authorable key is removed on two carriers, so the accept set a consumer writes against narrows. **(e)** The migration no longer tells a released-version factory to stop reading something it never had (M1). One paragraph says which members were never released and who could have read them. > old: **The one-line fix: delete the key** — and, for a custom provider factory, stop reading `ctx.connectionTimeoutMs`. > new: **The one-line fix: delete the key.** … The three interface members withdrawn with it were **never in a release**: `ConnectorProviderContext.connectionTimeoutMs`, `RestConnectorOptions.connectionTimeoutMs` and `OpenApiConnectorConfig.connectionTimeoutMs` all entered with `b929e0a662`, after the `@objectstack/*@17.4.0` tag, and leave in this same release. A factory or caller built against a released version never saw them; only code written against an unreleased `main` in between can read them, and it stops. Two sentences follow from the same reading. The FROM → TO row for `ConnectorProviderContext.connectionTimeoutMs` gains "added after `@objectstack/spec@17.4.0` and never in a release, see below". The D3 bullet now says the removal reaches "a factory author who read it — possible only against an unreleased `main` —" rather than any factory author. **(f)** The residue stage is stated as measured (M2). > old: … measured across two builds: the base build emits it for an entry that authored only `name`/`label`/`type`, and the tombstoned build refuses that exact object at `connectors.0.connectionTimeoutMs`. > new: … measured on both sides of the retirement: the released `@objectstack/spec@17.4.0` emits `connectionTimeoutMs: 30000` for an entry that authored only `name`/`label`/`type`, and the tombstone **without the stage** refuses that exact object at `connectionTimeoutMs`. With the stage, as it ships, that object is **accepted and the key stripped** before the tombstone reads it — on `ConnectorSchema`, `DeclarativeConnectorEntrySchema`, the `/meta/connector` schema and `stack.connectors[]` alike. > old: … and all four shipped connector packages put the materialized value straight into that def literal. So the emitted `30000` is accepted-and-stripped while `15000` keeps the tombstone's refusal, … > new: … and in 17.4.0 all four shipped connector packages put that `30000` straight into the def literal. So the emitted `30000` is accepted-and-stripped, while every other value (`15000`, `1000`, the string `"30000"`) keeps the tombstone's refusal — at `connectionTimeoutMs`, or at `connectors.0.connectionTimeoutMs` inside a stack — … The tombstone bullet's "`stack.connectors[]` and the `/meta/connector` door refuse it too" gains "every value but the retired default `30000`, which the residue stage below strips first". Without that clause, the bullet contradicted the residue bullet. **(g)** The read census names its tree (M3). > old: Measured with `git grep -n connectionTimeoutMs SHA -- . ':!packages/spec'` at `origin/main`: **thirteen** … > new: Measured with `git grep -n connectionTimeoutMs SHA -- . ':!packages/spec'` at `e07843b5a6`, the tree this retirement landed on: **thirteen** … ### What deliberately did not change - **Frontmatter, both files.** No level is wrong after the correction: - 18975's `minor`s cover real widenings: `ConnectorProviderContext` gains `retryConfig` and `requestTimeoutMs`, and the provider options and `resilientFetch` gain knobs. - 19580 stays `@objectstack/spec: minor` with the **BREAKING** banner, because the launch window refuses `major`. - 19580's `patch` for the connector and service packages is now better supported: the correction states outright that the option fields those packages withdraw were never released. - **The ADR-0087 marker and the remaining sentences.** The marker line is unchanged, and so is every sentence not quoted above. - **What the changeset gates read.** Base and head get the same reading from `check-adr-0087-registration` and `readClause2Line`: - 19580: `breaking true ["BREAKING","bang"]`, disposition `registered` with the same two ids, migration prescription found. - 18975: non-breaking, no migration prescription, `Clause-②: yes (widening)` declared. - An intermediate wording (`654adaba14`) mentioned the retirement entry's migration table by its house label. The detector's label branch read that as a migration prescription on 18975. It was reworded in `baf93b20fd`, and the parity above was re-measured on `f4fbb2203e`. ## Local gates, on `f4fbb2203e` The gate list is derived by `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands`: 19 commands. Reconciled with `--ran` and exit codes recorded: `19 derived, 19 run, 0 NOT-MEASURED, 0 UNRUN`. Every exit code was captured before any pipe. | Command | Exit | |---|---| | `node scripts/check-empty-changeset.mjs --base origin/main` | **1**, as intended: `✓ No empty-frontmatter changeset introduced`, then "This PR changes a changeset it did not add" naming both files, with the DELIBERATE CORRECTION remedy | | `node scripts/check-adr-0087-registration.mjs --base origin/main` | 0 (`✓ … this PR adds no declared-breaking changeset (2 non-breaking changeset(s) seen)`) | | `node scripts/check-changeset-no-major.mjs --base origin/main` | 0 (`✓ This diff introduces no major bump.`; the LEVEL axis is not applicable without a `pull_request` payload) | | `node scripts/check-changeset-fixed.mjs` (not derived, run as a `check-changeset*` gate) | 0 (`✓ … "fixed" group is in sync with 70 public workspace packages.`) | | `pnpm check:changeset-gate-self-tests` | 0 (159, 441 and 339 assertions) | | `pnpm check:nul-bytes` | 0 (`OK … no raw ASCII control bytes`) | | the `--self-test` of `check-adr-0087-registration`, `check-changeset-no-major` and `check-empty-changeset`, plus `check-closing-keyword-parity` (both), `check-comment-mask-corpus`, `pm/release-rehearsal-clone --self-test`, `check:driver-memory-census`, `check:gitlink-declared`, `check:objectui-changeset`, `check:pm-changeset-deadline-census`, `check:published-files`, `check:refd-timer-probe`, `check:watch-hint-literal` | 0 each | NOT MEASURED: the four type-check programs the derivation lists outside the derived total, which are CI's whole-workspace lanes. Reason: the diff touches no TypeScript, and no workspace build was bought for a text-only diff. Also scanned for control bytes (none, with a lit positive control) and for model identifiers in the diff (0 hits). ## Acceptance notes - **"five sites … READ" is still the wording in four code docblocks.** `packages/spec/src/integration/connector.zod.ts:565`, `packages/spec/src/conversions/registry.ts:9078`, `packages/spec/src/integration/connector-connection-timeout-retirement.test.ts:15` and `packages/spec/src/migrations/registry.ts:5255` say that. The retired-key entry (`18.integration__Connector__connectionTimeoutMs.ts:14`, `migrations/registry.ts:14678`), the liveness row and the 19580 changeset say "six reads". It is the same set, with the two `?? 30000` fallbacks counted as one site or two. Not touched here, because this PR is changeset text only. Carrier: none. - **The retired-key entry and the liveness `_note` still anchor the read census "at `origin/main`" without a sha.** This is the moving-ref reading corrected in the changeset by (g). Code and data, not changeset text, so not touched here. Carrier: none. - **The 19580 note's `Clause-②` sentence reads as `near-miss` (reason `describing`) in `readClause2Line`.** That is so at base and at head, because the token sits in backticks with prose after it. `check-adr-0087-registration` therefore classifies the note as breaking through the banner and the `!`, not through signal (4). It is left as it was: changing the line would change what the gate reads, which is outside a correction of false sentences. --- _Generated by [Claude Code](https://claude.ai/code/session_013RDBh5DqXd2xnLwvHLgLFr)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 19af43d commit e169acb

2 files changed

Lines changed: 47 additions & 29 deletions

File tree

‎.changeset/18975-connector-retry-config-and-request-timeout.md‎

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ declared policy onto those options — one execution site, not one per connector
2828
package.
2929

3030
**How the authored value gets there.** `ConnectorProviderContext` gains
31-
`retryConfig`, `connectionTimeoutMs` and `requestTimeoutMs`, read-only and
31+
`retryConfig` and `requestTimeoutMs`, read-only and
3232
resolved from the entry (the automation service parses `retryConfig` so a
3333
factory reads real values instead of re-deriving the schema's defaults), so a
3434
custom provider that does its own I/O can honour them. The built-in HTTP
@@ -56,19 +56,20 @@ policy could never reach. They now go through the same wrapper as
5656
`connector-rest` and `connector-slack`, which gives them the 30s per-attempt
5757
timeout and bounded retry those two already had.
5858

59-
**⚠️ `connectionTimeoutMs` is NOT enforced, deliberately, and is the one thing
59+
**⚠️ `connectionTimeoutMs` is NOT made live, deliberately, and is the one thing
6060
the ruling assumed that measurement refused.** A connector's call is a WHATWG
6161
`fetch`, whose only cancellation surface is one `AbortSignal` over the whole
6262
operation; nothing in that interface observes the connection phase separately.
6363
Bounding time-to-response with it would kill a slow-but-connected upstream the
6464
author meant to allow with a large `requestTimeoutMs` — breaking the very
65-
promise the key makes. So it is carried onto `ConnectorProviderContext` (a
66-
custom provider on a transport that *can* separate the phases may honour it)
67-
and left unenforced by the platform, with the reason recorded at the mapping and
68-
in `packages/spec/liveness/connector.json`, which keeps that one row `dead`. It
69-
is owed a second, narrower ADR-0049 decision: retire it, or re-describe it as
70-
something the platform can enforce.
65+
promise the key makes. So this change leaves it unenforced, with the reason
66+
recorded at the mapping and in `packages/spec/liveness/connector.json`, whose
67+
row for it stays `dead`. That left it owed a second, narrower ADR-0049
68+
decision, and this same release takes it: `connector.connectionTimeoutMs` is
69+
**retired**, and its own entry in this release says what to write instead. The
70+
key never reaches `ConnectorProviderContext` in any release.
7171

72-
Nine of the ten ledger rows flip `dead` → `live` with the consumer site named.
73-
No declaration moves: the connector schema keeps every key, every bound and
74-
every default it had.
72+
Nine of the ten ledger rows flip `dead` → `live` with the consumer site named;
73+
the tenth is `connectionTimeoutMs`, above. This change itself moves no
74+
declaration: it leaves every key, every bound and every default on the
75+
connector schema as it found them.

‎.changeset/19580-retire-connector-connection-timeout-ms.md‎

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,20 @@ The key was bounded (`min(1000).max(300000)`), defaulted (`30000`),
2525
| removed | what to write instead |
2626
| --- | --- |
2727
| `connector.connectionTimeoutMs` (on `Connector` and on `DeclarativeConnectorEntry`, so `stack.connectors[]` and `PUT /meta/connector/:name`) | `requestTimeoutMs` — the deadline the platform keeps, applied as `resilientFetch`'s per-attempt timeout. For a connect-only bound, configure it at a connector provider or upstream gateway on a transport that can separate the phases. |
28-
| `ConnectorProviderContext.connectionTimeoutMs` (handed to every `ConnectorProviderFactory`) | `ctx.requestTimeoutMs`, or the factory's own `providerConfig` where the provider owns the vocabulary. |
28+
| `ConnectorProviderContext.connectionTimeoutMs` (handed to every `ConnectorProviderFactory` — added after `@objectstack/spec@17.4.0` and never in a release, see below) | `ctx.requestTimeoutMs`, or the factory's own `providerConfig` where the provider owns the vocabulary. |
2929
| The `ZodObject` combinators on `ConnectorSchema` and `DeclarativeConnectorEntrySchema` — `.extend()`, `.omit()`, `.pick()`, `.partial()`, `.merge()`, `.strict()`, `.keyof()`, `.safeExtend()` | Both exports are now `z.preprocess` **pipes** (the residue stage below), so those methods no longer exist on them. **Build on the object and re-wrap:** `acceptRetiredDefaultResidue(<your extended object>, { connectionTimeoutMs: 30000 })`, the `EffectiveObjectPermissionSchema` route. ⚠️ `.superRefine()` still *exists* on a pipe but returns a schema with no read-through `shape`, so refine before wrapping, not after. Parsing, `z.input` / `z.infer`, and the read-through `.shape` are unchanged. |
3030

31-
**The one-line fix: delete the key** — and, for a custom provider factory, stop
32-
reading `ctx.connectionTimeoutMs`. `os migrate meta --from 17` lists the
31+
**The one-line fix: delete the key.** `os migrate meta --from 17` lists the
3332
mechanical edits for existing sources; apply them by hand.
3433

34+
The three interface members withdrawn with it were **never in a release**:
35+
`ConnectorProviderContext.connectionTimeoutMs`,
36+
`RestConnectorOptions.connectionTimeoutMs` and
37+
`OpenApiConnectorConfig.connectionTimeoutMs` all entered with `b929e0a662`,
38+
after the `@objectstack/*@17.4.0` tag, and leave in this same release. A factory
39+
or caller built against a released version never saw them; only code written
40+
against an unreleased `main` in between can read them, and it stops.
41+
3542
⚠️ Runtime behaviour is **unchanged for every shipped provider**, because none
3643
ever applied the value: a connector that authored `connectionTimeoutMs: 1000`
3744
made exactly the same calls, with exactly the same deadlines, as one that did
@@ -41,7 +48,8 @@ not. What does change is observable and intended: the def served by
4148
### ⭐ This is NOT the zero-mention retirement shape
4249

4350
Measured with `git grep -n connectionTimeoutMs SHA -- . ':!packages/spec'` at
44-
`origin/main`: **thirteen** non-test source occurrences over seven files in five
51+
`e07843b5a6`, the tree this retirement landed on: **thirteen** non-test source
52+
occurrences over seven files in five
4553
packages — **six reads** (`openapi-connector.ts:242`, `openapi-provider.ts:193`,
4654
`rest-connector.ts:134`, `rest-provider.ts:64`, `plugin.ts:307`,
4755
`plugin.ts:1589`), **four type declarations**, and **three** surviving hardcoded
@@ -73,7 +81,8 @@ ruling that made the siblings live forbids.)
7381
both channels — `tsc` (input type `never`) and the parse, which raises the
7482
prescription itself. `DeclarativeConnectorEntrySchema` carries it too — both
7583
published carriers wrap the same private `ConnectorBaseSchema` — so
76-
`stack.connectors[]` and the `/meta/connector` door refuse it too.
84+
`stack.connectors[]` and the `/meta/connector` door refuse it too: every value
85+
but the retired default `30000`, which the residue stage below strips first.
7786
- **A D2 conversion, `connector-connection-timeout-ms-removed`** — one strip per
7887
`connectors[]` entry, a pure lossless delete. ⭐ The ruling left whether one was
7988
owed to be **measured** ("a D2 conversion only if a stored connector row can
@@ -85,9 +94,11 @@ ruling that made the siblings live forbids.)
8594
written on 17.x therefore replay clean.
8695
- **A D3 semantic entry,
8796
`connector-provider-context-connection-timeout-ms-retired`**, for the withdrawn
88-
`ConnectorProviderContext` member. A provider factory is code: there is no
89-
authored source and no `sys_metadata` row for a conversion to rewrite, so the
90-
removal reaches a factory author as a `tsc` error and as that entry.
97+
`ConnectorProviderContext` member (never in a release, above). A provider
98+
factory is code: there is no authored source and no `sys_metadata` row for a
99+
conversion to rewrite, so the removal reaches a factory author who read it —
100+
possible only against an unreleased `main` — as a `tsc` error and as that
101+
entry.
91102
- **No def leaves.** The key was a bare `z.number()`, never a `ConfigSchema`
92103
shape, so `RETIRED_DEFS_BY_MAJOR[18]` gains nothing — and `api-surface/` and
93104
`json-schema.manifest/` are byte-identical, which is the correct reading for a
@@ -103,19 +114,26 @@ ruling that made the siblings live forbids.)
103114
carries both readings with their trees rather than one undated claim.
104115
- **An `acceptRetiredDefaultResidue` stage** (#12840), `{ connectionTimeoutMs: 30000 }`
105116
on both carriers. The key was `.optional().default(30000)`, so a 17.x parse
106-
materialized it into **every** connector — measured across two builds: the base
107-
build emits it for an entry that authored only `name`/`label`/`type`, and the
108-
tombstoned build refuses that exact object at `connectors.0.connectionTimeoutMs`.
117+
materialized it into **every** connector — measured on both sides of the
118+
retirement: the released
119+
`@objectstack/spec@17.4.0` emits `connectionTimeoutMs: 30000` for an entry that
120+
authored only `name`/`label`/`type`, and the tombstone **without the stage**
121+
refuses that exact object at `connectionTimeoutMs`. With the stage, as it
122+
ships, that object is **accepted and the key stripped** before the tombstone
123+
reads it — on `ConnectorSchema`, `DeclarativeConnectorEntrySchema`, the
124+
`/meta/connector` schema and `stack.connectors[]` alike.
109125
The D2 does **not** discharge the obligation, and the precedent shows it:
110126
`ObjectPermission:allowPurge` carries a D2 **and** the residue stage, for its
111127
own reason (a released toolchain materialized its default into every built
112128
artifact's entries). The reason *here* is a different one — this schema has a
113129
second door: `AutomationEngine.registerConnector` parses `ConnectorSchema` for
114130
a def a plugin or provider factory builds **in code**, where no conversion
115-
ever runs, and all four shipped connector packages put the materialized value
116-
straight into that def literal. So the emitted `30000`
117-
is accepted-and-stripped while `15000` keeps the tombstone's refusal, and
118-
nothing is un-retired: `z.input` stays `never` and the `[RETIRED]` row stays.
131+
ever runs, and in 17.4.0 all four shipped connector packages put that `30000`
132+
straight into the def literal. So the emitted `30000` is accepted-and-stripped,
133+
while every other value (`15000`, `1000`, the string `"30000"`) keeps the
134+
tombstone's refusal — at `connectionTimeoutMs`, or at
135+
`connectors.0.connectionTimeoutMs` inside a stack — and nothing is un-retired:
136+
`z.input` stays `never` and the `[RETIRED]` row stays.
119137
- **No deprecation window** (maintainer 2026-08-27: 「项目在创业阶段,用户也很少,短期不考虑渐进」),
120138
and no staged retirement.
121139

@@ -126,8 +144,7 @@ occurrences of the name at objectui `87af769e`, against a lit control on the sam
126144
command and scope, so no sibling fix or pin bump rides with this.
127145

128146
`Clause-②: yes (narrowing)` — a published authorable key is removed on two
129-
carriers and a published interface member leaves `ConnectorProviderContext`, so
130-
the accept set a consumer writes against narrows. Nothing is widened and nothing
131-
is renamed. Contract-review tier.
147+
carriers, so the accept set a consumer writes against narrows. Nothing is
148+
widened and nothing is renamed. Contract-review tier.
132149

133150
<!-- adr-0087: registered connector-connection-timeout-ms-removed, connector-provider-context-connection-timeout-ms-retired -->

0 commit comments

Comments
 (0)