Skip to content

docs(formulas): drop the M9.1 / M9.2 phase language from the docs page and the pending changesets - #17851

Merged
claude[bot] merged 1 commit into
mainfrom
claude/issue-17323-drop-m9-phase-language-docs-half
Sep 12, 2026
Merged

docs(formulas): drop the M9.1 / M9.2 phase language from the docs page and the pending changesets#17851
claude[bot] merged 1 commit into
mainfrom
claude/issue-17323-drop-m9-phase-language-docs-half

Conversation

@claude

@claude claude Bot commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

The M9.1 / M9.2 expression phases — including the promise that ast becomes required in build output — were asserted across the tree and defined in no ADR. Decision batch #123 item 1 (director seat, 2026-09-12) ruled option B, maintainer verbatim 「同意」: the phase assertions are removed, and ast stays an accepted optional persisted form with no promise of becoming required. This PR is the docs half of that ruling — the published docs page and the two still-unconsumed changesets now state the contract in the present tense: source is the canonical persisted form, ast is an optional opaque structured value. Per the ruling's item 4 (「Files under packages/spec and packages/formula are the spec seat's: the domain:skills taker edits docs and coordinates the spec half as a sibling PR by that seat, ⛔ not a cross-lane rider」), nothing under packages/ is touched here; the spec half is a sibling PR by that seat, tracked as #17849. No ADR is written — B means there is no phase to define.

Part of #17323

Acceptance notes

Premises, re-taken at this branch's base 758ac409

  1. HOLDS. git grep -l 'M9\.[12]' origin/main returns exactly seven files — .changeset/blank-node-condition-refused-at-registration.md (1 hit), .changeset/flow-edge-condition-evaluated-slot.md (3 hits), content/docs/data-modeling/formulas.mdx (1 hit), packages/formula/src/cel-engine.ts, packages/formula/src/normalize.ts, packages/spec/CHANGELOG.md, packages/spec/src/shared/expression.zod.ts. The last four are the spec seat's and are untouched here; after this PR the repo-wide count is those four and nothing else.
  2. HOLDS, with a timing note. Both changesets are present and unconsumed under .changeset/ at this base. ⚠️ The standing Version Packages PR chore: version packages #17076 (changeset-release/main, bot-authored) lists both of them as removed — it is the consuming side. So this correction has to land before that PR does; once a release consumes these files, the ruling's item 3 routes the same correction to a CHANGELOG.md erratum instead, which rides the spec half.
  3. HOLDS. formulas.mdx :27 (deleted in M9), :111 (M9.9b) and :583 (M9.5) are other milestone references and are byte-identical — they do not appear in the diff, and git grep -c 'M9' -- content/docs/data-modeling/formulas.mdx still reports 3 (now at :27 / :112 / :584, shifted by the one line this PR adds).
  4. HOLDS. All 22 open PRs' file lists were re-scanned; none names the three files, with the single qualification in premise 2 — chore: version packages #17076 lists the two changesets as consumed, which is not a competing edit.

The sentences, before → after

A · content/docs/data-modeling/formulas.mdx :86-87

- artifact always contains the full envelope (and, after M9.2, the AST).
+ artifact always contains the full envelope: `source` is the canonical persisted
+ form, and `ast` is an optional opaque structured value.

B1 · .changeset/flow-edge-condition-evaluated-slot.md :30 — inside the blockquote that reproduces the refusal sentence:

- > engine evaluates `source` (the canonical persisted form of phase M9.1) and
+ > engine evaluates `source` (the canonical persisted form) and

B2 · .changeset/flow-edge-condition-evaluated-slot.md :44-48 — the phase-2 promise itself:

-   the persistence contract (`source` OR `ast`), whose docblock declares that
-   `ast` becomes required in build output at phase M9.2. When AST-only
-   evaluation lands, `EvaluatedExpressionSchema` is the one place to relax, and
-   every evaluated slot follows.
+   the persistence contract (`source` OR `ast`), where `ast` is accepted as an
+   optional opaque structured value and carries no promise of becoming required.
+   If AST-only evaluation is ever chartered, `EvaluatedExpressionSchema` is the
+   one place to relax, and every evaluated slot follows.

B3 · .changeset/flow-edge-condition-evaluated-slot.md :73

- carried only `ast` has no evaluable form under M9.1: author its `source`. A
+ carried only `ast` has no evaluable form: author its `source`. A

C · .changeset/blank-node-condition-refused-at-registration.md :33 — the eighth site, which neither the card nor the ruling named. What it said: the same verbatim blockquote of the refusal sentence that B1 carries, with the identical (the canonical persisted form of phase M9.1) parenthetical; it is the only M9 reference in that file, and it gets the identical treatment:

- > engine evaluates `source` (the canonical persisted form of phase M9.1) and
+ > engine evaluates `source` (the canonical persisted form) and

Nothing else in the three files is touched: 3 files, 9 insertions, 8 deletions, and the changeset frontmatter (package and bump level) of both changesets is unchanged.

D · Verification

reading result
git grep -l 'M9\.[12]' -- content .changeset 0 files (exit 1, no match)
control — git grep -c 'M9' -- content/docs/data-modeling/formulas.mdx still 3 (the :27 / :112 / :584 milestones)
control — the pattern still matches elsewhere, so it is not a dead pattern: git grep -c 'M9\.[12]' 4 files, all the spec seat's
dark control — git grep -c 'M91zzz' -- content .changeset 0 (exit 1), so the pattern does not match everything
grep -naP for raw control bytes over the three files clean (exit 1)

Coordination with the spec half, #17849

The blockquote edited in B1 and C is a verbatim quote of an exported constantEVALUATED_EXPRESSION_SOURCE_REQUIRED in packages/spec/src/shared/expression.zod.ts, which still carries of phase M9.1 on main. This PR drops exactly that phase clause and keeps (the canonical persisted form), because "source is the canonical persisted form" is the present-tense contract the ruling's item 1 names. For the quote to stay a quote, the spec half must land that same wording in the constant. Flagged rather than worked around: packages/spec is not this lane's, per item 4.

Changeset: skip-changeset, measured

Two existing changesets are edited and none is added, so the changeset count this PR adds is 0 and the label is the applicable rule (AGENTS.md Post-Task Checklist step 3: the label is for a diff that publishes nothing from any released package). Measured rather than assumed:

  • no published package's files[] ships content/** or .changeset/** — 0 matching entries across every non-private workspace manifest;
  • the added strings (carries no promise of becoming required, is an optional opaque structured value) appear in 0 published paths;
  • positive control — canonical persisted form does hit a published path (packages/spec/CHANGELOG.md, packages/spec/src/shared/expression.zod.ts), so the measurement is not vacuous.

The publication this correction affects is already declared by the two changesets it edits (@objectstack/spec minor, @objectstack/service-automation minor); a third changeset would declare a release of its own for a prose correction that rides theirs. The CHANGELOG.md erratum for the already-published M9.2 text is the ruling's item 2 and belongs to the spec half.

Gates

Derived in this worktree with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths — the tool took the change set from git itself at 9e12d4a62 vs merge base 758ac4097): 51 commands. Every one was run; reconciliation with --ran reports 51 derived, 51 run, 0 NOT-MEASURED, 0 UNRUN, all exit 0.

Four of them first exited 3 / 1 as PREREQUISITE NOT MET — nothing measured, unbuilt workspace packages, not findings: check:doc-formula-expressions and check:doc-security-posture (@objectstack/formula, @objectstack/lint unbuilt), check:docs-transcript-drift (same), and check:skill-examples (packages/client-react/dist held no .d.ts). After pnpm exec turbo run build --filter='@objectstack/lint...' --filter='@objectstack/formula' --filter='@objectstack/client-react...' --concurrency=2, all four are exit 0. Verdict lines, as each gate printed them:

✓ check-adr-0087-registration: this PR adds no declared-breaking changeset (2 non-breaking changeset(s) seen).
✓ This diff introduces no `major` bump.
✓ No empty-frontmatter changeset introduced by this diff (2 declaring changeset(s) added).
✓ doc authoring guard: 401 files clean — no bare metadata literals.
check-nul-bytes: OK (scanned 8476 text file(s) -- 8476 tracked, 0 untracked-not-ignored; skipped 7 binary; no raw ASCII control bytes).
✓ check:doc-formula-expressions: 22 record-scoped formula example(s) across 438 files / 1374 TS blocks judged clean by @objectstack/formula.
✓ check-docs-transcript-drift: 4 declared transcript value(s) across 402 page(s) under content/docs/ equal what the registry derives today, and no undeclared block quotes one.

node scripts/check-changeset-fixed.mjs was run as well and is exit 0 — the derivation flags its roster as living under .changeset, one of this PR's paths, so its silence is evidence in neither direction until run. It reads .changeset/config.json and the workspace manifests, neither of which this PR touches.

Repo-wide scans (pnpm lint and the rest) are CI's, as are the two path-scheduled CI jobs and the 11 declared-wide families the derivation names as unplaceable locally.

Noted, not filed

  • scripts/check-adr-0087-registration.mjs's pass line labels every skipped changeset "non-breaking" (${result.skipped.length} non-breaking changeset(s) seen), so the two changesets here — both declared breaking at base and skipped as inherited stock by the specified M breaking at head, already breaking at base row — are reported as non-breaking. The verdict is correct and the row is a pinned self-test case; only the summary wording under-describes. A pass-line wording nit, not a defect class, not a contract violation and not an authoring trap, so no card. Taker: none — no queued PR touches that script.

Generated by Claude Code

…e and the pending changesets

The M9.1 / M9.2 expression phases — including the promise that `ast` becomes
required in build output — were asserted across the tree and defined in no ADR.
Decision batch #123 item 1 ruled option B: the phase assertions are removed and
`ast` stays an accepted optional persisted form with no promise of becoming
required. This is the docs half: the published page and the two unconsumed
changesets now state the contract in the present tense — `source` is the
canonical persisted form, `ast` is an optional opaque structured value.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MCLBsUgfykL74aU716rzVK
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 skip-changeset PR has no user-facing published change; bypasses the changeset gate tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant