Skip to content

docs(contract)!: P24 envelope rule, migration record, and the hardened ratchet (R1/R6/R7/R8) - #528

Merged
rejifald merged 3 commits into
mainfrom
docs/contract-p24-ratchet
Jul 31, 2026
Merged

docs(contract)!: P24 envelope rule, migration record, and the hardened ratchet (R1/R6/R7/R8)#528
rejifald merged 3 commits into
mainfrom
docs/contract-p24-ratchet

Conversation

@rejifald

Copy link
Copy Markdown
Owner

Broken out of #470 — the contract document + its enforcement. Opened as a draft: this lands LAST, by construction.

docs/CONTRACT.md

scripts/check-contract.mjs

Rule Change
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 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 new — the P24 envelope rule, with cross-file resolution

docs/adr/0006 carries 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 a
slice still in flight:

Rule Symbol Fixed by
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

✅ 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:

  • 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 genuinely compose, and the ratchet reaches the target once they land.

🤖 Generated with Claude Code

…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
rejifald enabled auto-merge (squash) July 31, 2026 15:49
@rejifald
rejifald merged commit a8eca88 into main Jul 31, 2026
12 checks passed
@rejifald
rejifald deleted the docs/contract-p24-ratchet branch July 31, 2026 15:51
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant