docs(contract)!: P24 envelope rule, migration record, and the hardened ratchet (R1/R6/R7/R8) - #528
Merged
Merged
Conversation
…d ratchet (R1/R6/R7/R8) Broken out of #470 — the contract document + its enforcement. **Lands LAST**, by construction. **docs/CONTRACT.md** - New **P24** — a shared field-name prefix in a house contract is an envelope. `refreshOn`/ `refreshSkew`, `captureErrors`/`captureDrift`, `seamConfig`/`seamToken`, `maxIncrRetries` all folded under this rule; it is what the already-merged #508/#509/#510/#512/#513 were applying. - §6 changes from "Migration backlog (proposed renames — confirm during sweep)" to "Migration record (2026-07-08 hard-break sweep)": the proposals became history. - Records the blessed carve-outs so the ratchet's exemptions are documented, not folklore: `StitchQueryOptions` keeps TanStack's own vocabulary (P3/P18/P22 — the rule's own motivating example is itself exempt), `StitchLike`'s rich/minimal tiers, and the P8 default divergences (oauth2/cookie tenancy, pino/sentry lifecycle, RN keyPrefix). **scripts/check-contract.mjs** - **R1** additionally bans `*Return`/`*State` on a produced shape (the result suffix is `*Result`). This is what would have caught `UseStitchReturn`/`StitchQueryState`. - **R6** now sees nested toggle slots — a `boolean | AllOptionalOptions` union admits `{}` and enables silently, which the flat check missed. - **R7** is new: a `@deprecated` marker anywhere in a published package's `src` is itself a violation (P19 as amended — GA ships shim-free). R1–R4/R6 still skip deprecated declarations, so a shim is reported ONCE under R7 rather than double-counted. - **R8** is new: the P24 envelope rule, with cross-file resolution. **docs/adr/0006** carries the amendment #470 wrote for it — deliberately held out of the nest slice (#521), because it links to P24 and the renamed §6, and both arrive here. Its anchors resolve now. BLOCKED — this cannot be merged before its subjects. Run today against main the hardened ratchet reports 12 violations, every one of them fixed by a slice still in flight: R1 StitchQueryState, UseStitchReturn ......... #501 R6 SseOptions.reconnect, McpServerOptions .... #524 R7 @deprecated shims ×5 (the bindings) ....... #501 + #525 R8 AuthContext.run/runLogin .................. #524 R8 fastify seam/seamConfig ................... #520 VERIFIED end-to-end rather than assumed: I merged main + #514 + #516 + #520 + #521 + #524 + #525 + #526 into a scratch integration branch (all seven merged with NO conflicts) and ran this ratchet against that tree — **0 violations, baseline 0**, and `--update` rewrites the baseline to 0 rather than baselining anything away. The same tree typechecks clean across every package and passes all 67 workspace test suites, so the slices compose. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Conflict resolution (docs/CONTRACT.md, 4 hunks). Main reformatted markdown lists (`- ` → `- `) while this branch was pinned, so three hunks are pure formatting — take main's bullet style, keep this branch's newer prose: - P5 payload note: `SchemaFingerprint.value` "became `token`" (past tense) is correct — `packages/core/src/fingerprint.ts:58` declares `readonly token`. Main still said "e.g. rename … → token" as a proposal. - P15 required-fields note: keep the concrete tuple shorthand `circuit: [5, '30s']` (landed in #524); main still said "add a positional shorthand instead". - §7 enforcement: keep this branch's R1–R8 description; main's stops at R6. The fourth hunk is the real one: main gained **P25 · One canonical size form** (#547) at the same insertion point this branch adds **P24**, both immediately before §6. Resolved by keeping BOTH, in order — P24 then P25. They do not overlap: P24 is about folding prefix-sharing flat fields into an envelope, P25 about the `number | string` size intake. Also fixes an R7 false positive this merge exposed. R7 was `src.indexOf('@deprecated')` — a raw substring scan — so it flagged `packages/core/src/stitch.ts:766`, a `//` comment that merely EXPLAINS that a deprecated `key`/`keyOf` alias exists. That is documentation about the surface, not a shim on it. R7 now matches only at JSDoc TAG position (line start, after the optional leading `*`, inside a block comment). Verified by probe: a multi-line `@deprecated` tag is caught, a single-line `/** @deprecated */` is caught, mid-sentence JSDoc prose is not, and the tree is otherwise clean — 0 violations, baseline 0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
rejifald
marked this pull request as ready for review
July 31, 2026 15:11
rejifald
enabled auto-merge (squash)
July 31, 2026 15:49
rejifald
added a commit
that referenced
this pull request
Jul 31, 2026
…en entry #528 renamed §6 from "Migration backlog" to "Migration record", which broke both `(#6-migration-backlog)` links — the one this branch added under P4 and the one #528 left behind at P19. Both now point at the real heading. Also reconciles §6's intro with its new name (it still promised "proposed target spellings the sweep will apply" under a heading that says record), and states what the one surviving row actually is: `bodyKind` lives in `from-curl.ts`, imported by `cli.ts` alone, exported from no index and behind no subpath — so nothing on the published surface carries the name. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
rejifald
added a commit
that referenced
this pull request
Jul 31, 2026
…them (#548) * docs(contract): P4's violations and §6's backlog shipped — reconcile them The doc advertised work that is done. P4 listed four live violations; all four landed, and §6's own "Shipped" record below the table already says so — the two halves of the same section contradicted each other. Verified against source, not against the record: - `ReconnectOptions.maxAttempts` → `attempts` (`maxAttempts` survives only as engine.ts's resolved reconnect policy) - `CacheOptions.maxEntries` → `entries` (cache.ts reads `config.entries`; `maxEntries` is a local) - `CircuitOptions.failureThreshold` → `failures` (resilience.ts reads `opts.failures`; `failureThreshold` is a local) - `paginate.max` → `pages`, on the extracted `PaginateOptions` That pattern is itself the rule's boundary, so P4 now states it: a `max*` spelling is fine on a RESOLVED internal, which names a computed value; P4 governs the authoring surface. §6's table had the same rot — seven of its eight rows shipped (the cross-package clashes are qualified per-framework/per-ecosystem, `stitchQueryOptions`, `OAuth2Options`/`CookieSessionOptions`, `PaginateOptions`, `streamStitchSse`, `StitchErrorOptions`, and `RedisDriver`'s async `close` — `quit` survives only on the upstream client duck-types, which P18 keeps at their upstream spelling). Only `bodyKind` (from-curl) is still live, so the table is down to that one row. Complements #528, which reconciles the other principles' violation lists but leaves P4 and §6's table untouched. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * docs(contract): fix §6 anchors after the heading rename; scope the open entry #528 renamed §6 from "Migration backlog" to "Migration record", which broke both `(#6-migration-backlog)` links — the one this branch added under P4 and the one #528 left behind at P19. Both now point at the real heading. Also reconciles §6's intro with its new name (it still promised "proposed target spellings the sweep will apply" under a heading that says record), and states what the one surviving row actually is: `bodyKind` lives in `from-curl.ts`, imported by `cli.ts` alone, exported from no index and behind no subpath — so nothing on the published surface carries the name. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Broken out of #470 — the contract document + its enforcement. Opened as a draft: this lands LAST, by construction.
docs/CONTRACT.mdrefreshOn/refreshSkew,captureErrors/captureDrift,seamConfig/seamToken,maxIncrRetriesall fold under this rule.It is the principle the already-merged refactor(auth)!: fold refreshOn/refreshSkew/refreshWhen into one
refreshenvelope (P24) #508 / refactor(sentry)!: fold captureErrors/captureDrift into onecaptureenvelope (P24) #509 / refactor(nest)!: fold the feature-seam config + seamToken into oneseamenvelope (P24) #510 / refactor(deno-kv)!: maxIncrRetries → retry envelope (P4 + P12/P20) #512 / refactor(core)!: fold retry backoff into one envelope; reconnect.backoff → delay (P24 + P2) #513 were applying — those PRscited "P24" before the section existed.
sweep)" → "Migration record (2026-07-08 hard-break sweep)". The proposals became history.
folklore:
StitchQueryOptionskeeps TanStack's own vocabulary (P3/P18/P22 — the rule's ownmotivating example is itself exempt),
StitchLike's rich/minimal tiers, and the P8 defaultdivergences (oauth2/cookie tenancy, pino/sentry lifecycle, RN
keyPrefix).scripts/check-contract.mjs*Return/*Stateon a produced shape (the result suffix is*Result) — this is what would have caughtUseStitchReturn/StitchQueryStateboolean | AllOptionalOptionsunion admits{}and enables silently, which the flat check missed@deprecatedmarker anywhere in a published package'ssrcis itself a violation (P19 as amended: GA ships shim-free). R1–R4/R6 still skip deprecated declarations, so a shim is reported once under R7 rather than double-counteddocs/adr/0006carries the amendment #470 wrote for it. I deliberately held it out of the nest slice(#521) because it links to P24 and the renamed §6, both of which arrive here — its anchors
resolve now instead of dangling.
🚧 Blocked — and here is the exact list
Run today against
main, the hardened ratchet reports 12 violations. Every one is fixed by aslice still in flight:
StitchQueryState,UseStitchReturnSseOptions.reconnect,McpServerOptions@deprecatedshims ×5 (the bindings)AuthContext.run/runLoginseam/seamConfig✅ Baseline-0 verified end-to-end, not assumed
I merged
main+ #514 + #516 + #520 + #521 + #524 + #525 + #526 into a scratch integration branch —all seven merged with no conflicts — and ran this ratchet against that tree:
--updaterewrites the baseline to0rather than baselininganything away
So the slices genuinely compose, and the ratchet reaches the target once they land.
🤖 Generated with Claude Code