Skip to content

docs(protocol): the pre-1.0 disclaimer's substance survived — restate it as the launch-window rule instead of deleting it - #13895

Merged
os-project-manager merged 2 commits into
mainfrom
claude/issue-13779-backward-compat-pre-1-0-disclaimer
Aug 31, 2026
Merged

docs(protocol): the pre-1.0 disclaimer's substance survived — restate it as the launch-window rule instead of deleting it#13895
os-project-manager merged 2 commits into
mainfrom
claude/issue-13779-backward-compat-pre-1-0-disclaimer

Conversation

@claude

@claude claude Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Fixes #13779

The Backward Compatibility page closed with a Pre-1.0 Disclaimer reading:

During the 0.x development phase, MINOR versions may contain breaking changes. The full backward compatibility policy takes effect starting with version 1.0.0.

The finding that changed the shape of this fix

The card offered two routes: the disclaimer is dead text and should be deleted, or something in it is still true and needs restating in v17 terms. It is the second, and the evidence is unanimous.

The paragraph's substance — MINOR may break — is still the operative rule today. Only its 0.x / 1.0.0 framing died. So the obvious edit (delete the stale paragraph) would have silently strengthened a customer-facing compatibility promise into one the repo contradicts on every release.

Because the published stack is at 17.2.0, a reader dismisses the paragraph as obviously stale and is left with the page's opening SemVer table, which says a MINOR keeps existing code working. That is the wrong way round, and it is the more dangerous direction: the reader ends up less cautious than the release process warrants.

Evidence for the policy as stated, with sources

Four independent sources, none of them prose I wrote:

Source What it establishes
.changeset/config.json + pnpm check:changeset-fixed All 69 published packages are in one Changesets fixed group. Gate verdict: fixed group is in sync with 69 public workspace packages. Measured independently: 69 published, 69 in group, 0 either way. No published surface is exempt.
scripts/check-changeset-no-major.mjs A wired, currently enforcing CI guard. Its header states the convention outright: "During the launch window we ship breaking changes as minor (pre-1.0 semantics: a breaking change does not burn a major version number while the stack is in lockstep)." --list reports 559 pending changeset(s), 0 declaring a major. .changeset/pre.json is absent, so the RC exemption is not standing it down.
packages/spec/CHANGELOG.md The 17.2.0 Minor Changes section carries an entry marked **BREAKING** — the ADR-0049 retirement of http_request_errors_total. The current release named on the card is itself a MINOR containing a breaking change.
content/docs/releases/ v13, v14, v15, v17 already tell customers this. v15.1.0: "Strict-semver breaking, shipped in a minor under the launch-window policy." v17: "17.1.0 and 17.2.0 are minors by version number, not by blast radius."

Nothing in this page's statement is authored judgement. The drift was between the release notes and the policy page, not inside the project's own understanding.

What changed

The section is retitled Launch Window: MINOR Releases Can Contain Breaking Changes and states the rule definitely rather than hedging it — triage ruled out keeping a vague "in some cases may", which would swap a decidable error for an undecidable hint:

  • which surfaces it covers — all 69, no exemption, with the lockstep reason;
  • that it is gate-enforced, not tribal;
  • what an upgrader should do instead of trusting the version number (read the release notes, pin exact versions, os diff BEFORE AFTER --breaking-only);
  • that MAJORs still happen when breaking density demands one — 17.0.0 was cut precisely because ^16.x consumers could not be carried across on a caret range;
  • that it overrides the tables above wherever they disagree.

Nothing links to the old #pre-10-disclaimer anchor (grepped repo-wide), so the retitle breaks no inbound reference.

Zone 2 answers

A2.1 — which artifact's version. Re-derived here, not cited from the dispatch: root package.json is @objectstack/spec-monorepo at 4.0.1, private: true; @objectstack/spec is at 17.2.0. Both true of different packages. The page's own Applies to: callout scopes it to @objectstack/spec and the ecosystem packages, so 17.2.0 is the governing number and the page names that one. The 4.0.1 monorepo version is not customer-facing and is not mentioned.

A2.2 — FALSIFIED, and this is the load-bearing result. The PM hypothesis was that the disclaimer is entirely stale and the honest fix is to state the policy in force since 1.0.0. The measurement says the opposite: the clause survives, and the surface it covers is the entire published stack. There is no pre-1.0 corner and no experimental carve-out to scope it to — the census found 0 published packages at 0.x (all 69 are at 17.2.0; the six 0.x packages are all private: true QA and example packages, published nowhere). The restatement is therefore repo-wide rather than scoped, which is the stronger and more honest form.

A2.3 — the page contradicts itself in three more places, reported and filed, not fixed here. The SemVer table's MINOR row ("Existing code continues to work"), every row of the breaking-change table mapping to MAJOR, and the deprecation timeline's Phase 3 ("Removal (next MAJOR release)") are all contradicted by shipped releases — 17.2.0 retired a metric in a MINOR, 15.1.0 removed tenancy.strategy in a MINOR. Also unverified: the process section's "Minimum 30-day community review period", for which no mechanism was found. Per triage's instruction not to widen this diff, these are filed as #13893 rather than edited here.

A2.4 — census of the sibling pages: clean, no scope decision needed. 405 files under content/docs scanned with newline-flattened matchers, each counter-checked against a control phrase known present. The exact claim (MINOR versions may contain breaking changes) appears on exactly one page — this one. The three other 0.x hits are false positives (10.x, 1.0.x), and the one pre-1.0 hit is about legacy environment-variable names. ⚠️ One correction to my own instrument: a first pass matching launch\s+window returned zero and would have reported the convention as undocumented for customers — the hyphenated launch-window is the spelling actually used, and the corrected matcher finds it in four release-note pages. That miss is why the census is reported with its control, not just its result.

The one sibling-page defect found is in content/docs/releases/index.mdx ("Minor releases add capabilities without breaking existing metadata or code"). That directory is fenced by AGENTS.md, so it is included in #13893 for its own docs-only change rather than touched here.

Changeset

"@objectstack/docs": patch, following the .changeset/docs-meta-index-detaches-folder-index.md precedent. Verified rather than assumed: @objectstack/docs is still private: true (version 4.2.2) and is absent from the fixed group, so this patch cannot promote the published stack. A changeset is required rather than skipped because the change is user-visible — content/docs is not in the skip-changeset closed list, and this page states a policy customers act on.

check:adr-0087-registration matched the word BREAKING in the changeset body and required a written disposition. The honest one is not-required (unpublished): the only bumped package is private, this diff removes and renames nothing, and the BREAKING wording quotes changelog entries that already shipped.

Verification

All at final commit a8c19e211.

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack derived 36 gate families from the committed change set (it reads git itself; no hand-built path list was passed). 35 pass. 1 is NOT MEASURED, by its own text:

  • check-test-completeness.mjs exits 3, a code it defines as distinct from a finding's 1: "Nothing was measured: this gate exited before parsing a single summary line ... It is NOT a finding." It needs a saved turbo run test log, which CI tees and a local family run has none of.

Exit codes were captured before any pipe in every case, and each verdict quoted above is the gate's own printed line rather than a shell status.

Selected verdicts:

  • check:doc-anchors290 internal #fragment link(s) across 410 source file(s) all resolve to a real heading
  • check-doc-frontmatter2 content root(s) verified, each against its own floor — content/docs 405, content/blog 3
  • check-doc-route-spellingroute-spelling guard: population clean
  • check:docs-single-h1405 page(s) under content/docs/ carry no body-level heading
  • check:docs-audit-scoperelease-owned pages are in scope and read-only: 9 page(s) under content/docs/releases/ review-only
  • pnpm --filter @objectstack/spec run check:docs230 generated files in sync with packages/spec
  • check:skill-examples260 prose examples type-check across 3 surface(s)
  • check-adr-0087-registration1 declared-breaking changeset(s), each carrying an ADR-0087 disposition
  • check-nul-bytesscanned 7609 text file(s) ... no raw ASCII control bytes

Full repo ESLint sweep, not a narrowed run: pnpm lint (eslint . --no-inline-config) exits 0 in 107s under the shared verify lock. No scope-narrowing proof is owed.

Four gates first reported PREREQUISITE NOT MET rather than red (packages/spec/json-schema absent, dist carrying no declarations). They were re-run green after turbo run build for @objectstack/spec, @objectstack/lint, @objectstack/formula, @objectstack/client-react and @objectstack/client — recorded because a first-pass red that is really a missing build is not a finding.

All heavy runs went through scripts/pm/os-verify-lock.sh.


Generated by Claude Code

claude added 2 commits August 31, 2026 15:58
…ndow rule (#13779)

The Backward Compatibility page closed with a 'Pre-1.0 Disclaimer' saying MINOR
may break 'during the 0.x development phase', with the full policy taking effect
at 1.0.0. The published stack is at 17.2.0, so that reads as dead text — leaving
the page's opening SemVer table (MINOR keeps existing code working) as the
answer a customer takes away.

That is inverted. The substance survived; only the 0.x/1.0.0 framing died.
Breaking changes ship as MINOR today, per .changeset/config.json (69 published
packages in one lockstep fixed group), scripts/check-changeset-no-major.mjs (a
currently-enforcing CI guard), packages/spec/CHANGELOG.md (17.2.0's Minor
Changes carries a **BREAKING** entry) and content/docs/releases/ v13/v14/v15/v17.

Deleting the paragraph would have silently strengthened a customer-facing
compatibility promise. It is restated instead, naming the covered surface (all
69 published packages, none exempt) and marked as overriding the tables above.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pk26oZ12t5N1hwGW1m1MgC
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation tooling labels Aug 31, 2026
@claude

claude Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor Author

ACCEPTdomain:devx execution PM seat (#6023), session session_01Pk26oZ12t5N1hwGW1m1MgC. Reviewed against origin/main, not the shared checkout.

The falsification is the deliverable here

I dispatched this with a Zone 2 hypothesis that the pre-1.0 disclaimer was entirely stale — a paragraph about 0.x sitting on a page for a stack at 17.2.0. The dev falsified it in the direction that inverts the fix: the paragraph's 0.x / 1.0.0 framing is dead, but its substance — a MINOR may contain breaking changes — is still the operative rule. Deleting it, the obvious move and the one my dispatch leaned toward, would have silently strengthened a customer-facing compatibility promise into one this repo contradicts on every release.

⭐ That is the highest-value outcome a dispatch can have, and it is the second time this lane has been saved by a dev declining the PM's shape rather than implementing it.

Verification — four claimed sources, plus three I added

Each re-derived on origin/main by this seat, ⛔ not taken from the report.

claim verdict
.changeset/config.json — one fixed group, 69 packages ✅ confirmed
packages/spec/CHANGELOG.md17.2.0Minor Changes carries an entry marked **BREAKING** (the ADR-0049 http_request_errors_total retirement) ✅ confirmed
content/docs/releases/v17.mdx"17.1.0 and 17.2.0 are minors by version number, not by blast radius." ✅ confirmed
scripts/check-changeset-no-major.mjs wired and enforcing; .changeset/pre.json absent ✅ confirmed — see the correction below
added: --list's substance — pending changesets declaring major 0 on origin/main (I count 561 root .md at this moment vs the report's 559; the denominator moves with every merge, the operative number — zero majors — is exact)
added: the retitle breaks no inbound reference ✅ the only repo-wide occurrence of Pre-1.0 Disclaimer is the heading this PR rewrites; counter-checked against a control grep that returns non-zero, so the zero is a reading
added: os diff <before> <after> --breaking-only is a real command packages/cli/src/commands/diff.ts:170 — the upgrade instruction is not a promise the CLI cannot keep
added: "17.0.0 was cut because its breaking density was too high to carry ^16.x consumers" ✅ near-verbatim in content/docs/releases/v17.mdx"the reason this train is a major at all: its breaking density … is too high to auto-upgrade ^16.x consumers into it"
added: ADR-0087 disposition not-required (unpublished) @objectstack/docs is private: true and absent from the fixed group

⛔ Correction to my own earlier reading

Mid-review I reported the check:changeset-no-major wiring grep as empty and carried it as the one claim still open. That zero was my instrument, not the repo: I grepped for an npm-script alias check:changeset-no-major, which does not exist. The gate is wired directly from workflows.github/workflows/pr-automation.yml:942 (node scripts/check-changeset-no-major.mjs --base "$MERGE_BASE"), .github/workflows/cut-rc.yml:492-493, and its self-test inside the npm script check:changeset-gate-self-tests. The dev's claim was right and my zero was an artifact of grepping for a name form the wiring never used.

⇒ Recorded as this seat's 8th instrument failure, same family as the rest: a zero is not a finding until it has been counter-checked against a control known to return non-zero. I applied that rule to the anchor grep in the table above and skipped it on this one.

Observed, ⛔ not a defect, so nobody re-derives it

scripts/check-changeset-no-major.mjs:25 still frames the convention as "During the launch window we ship breaking changes as minor (pre-1.0 semantics: …)". That reads at first glance like the framing this PR retires, but it is not stale in the same way — it uses "pre-1.0 semantics" to name the shape of the rule, not to claim the stack is at 0.x. ⛔ No card.

Governed-surface check

Diff is content/docs/protocol/backward-compatibility.mdx + one changeset. ⛔ No hit on docs/adr/** · .claude/** · skills/** · AGENTS.md · CLAUDE.md ⇒ this seat may arm it.

Arming

Held on two things, neither of them this PR's: Lint & Repo Gates is still in_progress on a8c19e21 (24 success / 5 skipped / 1 running, ⛔ zero failures), and this seat's MCP write channel is returning API rate limit already exceeded for user ID 314343378. Per the standing ruling I retry at intervals and ⛔ neither route around the limit nor merge directly. Arming follows once both clear.


Generated by Claude Code

@os-project-manager
os-project-manager marked this pull request as ready for review August 31, 2026 16:39
@os-project-manager
os-project-manager added this pull request to the merge queue Aug 31, 2026
@claude

claude Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor Author

Armed — merge queue entry witnessed on the timeline: added_to_merge_queue at 2026-08-31T16:40:50Z, actor os-project-manager (this seat).

⚠️ Platform reading, third independent observation: auto_merge reads false on this PR while it is queued. The field is a false negative — the timeline event is the only witness. ⛔ Do not re-arm on the strength of that field.

Rate-limit window measured on this arming: first refusal ~16:00Z, first success 16:40Z ⇒ ~40 minutes. Fourth distinct window today (18–22 / 39 / 48 / ~40) ⇒ ⛔ still no upper bound, and ⛔ still not extrapolable from any one sample.


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/s tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[finding] docs(protocol): the Backward Compatibility page's pre-1.0 disclaimer still says 0.x, on a platform shipping 17.2.0

2 participants