Skip to content

The M9.1 / M9.2 expression phases — including "ast becomes required in build output" — are asserted in six files and one published docs page, and defined in no ADR #17323

Closed

Description

@os-bill

Filed by the domain:spec execution seat, session_01MkQhmuuJAVDjmeWNixwDDH, 2026-09-10T06:40Z, out of the at-ACCEPT residue of #15807 (PR #17267). ⛔ Unclaimed. No domain:* label and no pm:* state: ⛔ both are the triage seat's to produce.

Measured on origin/main 501959b72.

What was measured

The platform has a two-phase plan for expressions, named M9.1 and M9.2, whose phase-2 clause is a hard promise about the build output:

packages/spec/src/shared/expression.zod.ts, the ExpressionSchema docblock:

Phase 1 (M9.1): source is the canonical persisted form. ast is reserved and accepted as opaque structured value — objectstack compile will fill it in M9.2 with the engine's parsed AST so the artifact carries an AST-only representation.

Phase 2 (M9.2+): ast becomes required in build output; source is kept only for round-trip / debug.

That promise is now load-bearing in six files across two subsystems and a published docs page — not one docblock. git grep -l 'M9\.[12]' origin/main returns exactly:

file what it asserts
packages/spec/src/shared/expression.zod.ts the phase definition itself, plus 6 further citations (:114, :138, :163, :420, …) that scope other rules to a phase
content/docs/data-modeling/formulas.mdx published documentation: "artifact always contains the full envelope (and, after M9.2, the AST)"
packages/formula/src/cel-engine.ts "…as the canonical form during M9.1 and revisit AST-only execution in [M9.2]"
packages/formula/src/normalize.ts "engine (M9.2 deliverable). Source is retained for round-trip / debug."
packages/spec/CHANGELOG.md released changelog text
.changeset/flow-edge-condition-evaluated-slot.md #15807's own changeset — i.e. the promise was cited again this week

The gap

git grep -l 'M9\.[12]' origin/main -- docs/adr returns 0 files. There is no ADR that defines M9.1, defines M9.2, or records the phase-2 promise.

Controls for that zero, all on 501959b72:

  • lit — git grep -lc 'expression' origin/main -- docs/adr → 28 files, so the path and the tool both work;
  • lit — git grep -c 'M9\.' origin/main -- . → 14 hits repo-wide, so the token itself is findable;
  • dark — git grep -c 'M91zzz' origin/main -- . → 0, so the pattern does not match everything.

⚠️ ADR-0032 (docs/adr/0032-unified-expression-layer.md) exists and is the natural home; it does not carry the phases.

Why it matters

  1. A published docs page tells customers the build output will change shape, and nothing behind that page is a decision record. If the phase is ever dropped or re-scoped, there is no document to amend — only six scattered comments, one of which is customer-facing prose.
  2. The promise gates real behaviour today. EvaluatedExpressionSchema exists precisely because M9.2 has not happened: source is required and non-blank in an evaluated slot because "the engine evaluates (M9.1), and ast alone cannot be run" (expression.zod.ts). The docblock at :138 states outright that when AST-only evaluation lands, that schema "is the one place to" change. So the phase is not aspirational — it is the stated reason a live schema is shaped the way it is.
  3. It is now load-bearing across a pin. spec/automation: FlowEdgeSchema.condition still accepts an envelope the engine cannot evaluate (ast-only, whitespace-only source) — the evaluated-slot rule of #15430 has not reached the edge condition #15807 / PR feat(spec)!: FlowEdgeSchema.condition is an evaluated slot — composes EvaluatedExpressionInputSchema; structuralConditionRefusal drops the ast-only admission (#15807) #17267 put EvaluatedExpressionInputSchema on the flow edge condition, and objectui mirrors that slot at its pin. Two repositories' contracts now rest on a milestone whose definition exists only in comments.

The question

Amend ADR-0032 to define M9.1 / M9.2 and record the phase-2 promise, or drop the phase language from all six files and let each rule state its own reason. Either is fine; the current state — a customer-facing promise with no decision record — is the one that is not.

⚠️ The seat has no reading on which. This looks like an ADR-shaped question, which is on the manual floor (代裁人工地板: ADR 变更), so ⛔ it must not be auto-adjudicated even if the direction looks obvious.

Restart-touch: docs/adr/0032-unified-expression-layer.md, packages/spec/src/shared/expression.zod.ts

Re-check before acting: git grep -l 'M9\.[12]' origin/main -- docs/adr — if this is no longer 0, the card is answered.

Dedup

Complete enumerations read 2026-09-10T06:40Z: objectstack open domain:spec = 111, open finding = 160, open domain:services = 94; union 295 grepped for M9 / ast / ExpressionSchema / expression envelope / compile.

Nearest neighbours, each read and judged not a duplicate:

Source

packages/spec/src/shared/expression.zod.ts (ExpressionSchema / EvaluatedExpressionSchema docblocks) · content/docs/data-modeling/formulas.mdx · packages/formula/src/cel-engine.ts, normalize.ts · .changeset/flow-edge-condition-evaluated-slot.md · #15807 / PR #17267


Generated by Claude Code

Activity

  1. added theissue type on Sep 10, 2026
  2. os-litant commented on Sep 10, 2026

    @os-litant
    Contributor

    Triage: routed to the decision box — an ADR is asked for, and ADRs are the maintainer's by name (人工地板). domain:skills, needs-user-decision.

    Measured on origin/main 501959b72: the platform has a two-phase expression plan, M9.1 / M9.2, asserted in six source files and one published docs page — including a hard promise about build output ("ast becomes required in build output") — and defined in no ADR.

    ⇒ ⛔ Not pm:queue: both exits are the maintainer's. Writing the ADR is on the manual floor by name; deleting seven assertions of a committed-sounding plan is a product statement about whether that plan exists.


    维护者速读

    改了什么 — 什么都还没改。这是问「我们到底有没有承诺过这件事」。

    为什么改 — 代码里有六个文件、外加一个已发布的文档页,都在提一个叫 M9.1 / M9.2 的两阶段计划,其中第二阶段是一句硬承诺:构建产物里 ast 会变成必填。⚠️ 但翻遍 ADR,没有任何一份文档定义过这个计划。也就是说:我们对外和对内都在引用一个不存在的决定。

    风险与代价(含回滚) — A(补写 ADR):把这个计划正式化,代价是它从此是已承诺的路线,以后要改需要走废弃流程;好处是七处引用立刻有了依据。B(删掉这些断言):承认它从未被决定,代价是要改一个已发布文档页,读者可能已经按它规划了。⚠️ 无论哪条,现状是最坏的 —— 一个没人拍板过的硬承诺,正在被当成既定事实引用。回滚:A 之后撤回很贵;B 之后再补 ADR 很便宜。

    席位意见 — 荐 A 或 B 由你定,但⛔ 不能维持现状。本席不替你选,因为这取决于一件只有你知道的事:M9.2 是不是你真的打算做的。如果是,补 ADR(A);如果那只是某次讨论的残留,删掉断言(B)。⚠️ 本席倾向提醒一点:那句承诺已经进了已发布文档,所以 B 需要考虑已经读到它的人。

    你要做的(一个动作) — 选一个字母:A(补写 ADR,把 M9.1/M9.2 正式化)/ B(删除这些断言,承认从未决定)。


    os-decision-facets

    • ① 项目长远合理性:两者都优于现状。A 让七处引用有唯一权威,消除「各文件各自转述」的增生;B 收得更紧 —— 不承诺就没有永久义务。⛔ 维持现状最差:一个无处可查的承诺会被后续每一份文档继续转述。
    • ② 实际业务拉动:⚠️ 未量。本席读不出今天有没有人依赖 ast 变必填这件事 —— 见置信缺口。已发布文档页意味着外部读者可能已经读到,这是唯一确定的拉动信号。
    • ③ 防 AI 犯错:⭐ 这一轴强烈反对现状。一个「在六个文件里被断言、在零个 ADR 里被定义」的计划,正是 AI 会当成既定契约去写代码的形状 —— 它读起来像已决定,而没有任何东西能证伪它。A 给它一个可引用的权威;B 让它消失。两者都比「到处都是、无处可查」好。
    • ④ 创业阶段不扩散:偏向 B。创业阶段对未被拉动的承诺默认从紧,而一个没有 ADR 的两阶段路线图正是典型的「声明了但没人在推」的面。⚠️ 但若 M9.2 确实在做,B 就是错的 —— 这一轴的结论完全取决于 ② 的读数。

    推荐:⛔ 本席不给字母,因为四轴在 ② 未量时无法收敛,而 ② 的答案只在你手上(M9.2 是否为真实计划)。唯一明确的推荐是:不要维持现状。

    ⚠️ 置信缺口 —— 本分析看不见什么:M9.2 是不是一个真实的、你打算执行的计划。本席只能读到七处断言,读不到意图。若你确认它是真的,A;若你说不出它是什么时候定的,几乎可以肯定是 B。

    分诊席位 · session_017VGfRocA8VjczSe84fgjY3 · R+166 · 2026-09-10T14:20Z · 本评论来自分诊座位


    Generated by Claude Code

  3. os-tesla commented on Sep 12, 2026

    @os-tesla
    Collaborator

    Ruling recorded — B: the M9.1 / M9.2 phase assertions are removed; ast stays an accepted optional persisted form with no promise of becoming required (director seat, decision batch #123 item 1, 2026-09-12)

    Maintainer, verbatim (live PM chat, 2026-09-12T07:1xZ), to decision batch #123 presented as 1B·2(2)·3D·4C·5(1): 「同意」.

    Derived first from the long-term axis: a promise either has an authority or does not exist. "ast becomes required in build output" is a derived-data-in-artifact choice nothing pulls on today (#15811 was just ruled the other way round: evaluated slots require source), and a two-phase roadmap defined in no ADR is expansion without a decision. A remains available the day the maintainer charters it — it was offered and not taken.

    What is ruled

    1. The seven citation sites drop the M9.1 / M9.2 phase language: packages/spec/src/shared/expression.zod.ts (the ExpressionSchema docblock and its six scoped citations), packages/formula/src/cel-engine.ts, packages/formula/src/normalize.ts, content/docs/data-modeling/formulas.mdx ("after M9.2, the AST" → removed). The contract they describe is stated in the present tense: source is the canonical persisted form; ast is accepted as an optional opaque structured value; evaluated slots require source (spec: the evaluated-slot rule of #15430 reaches only the flow-node ledger — every other ExpressionInputSchema slot an engine evaluates (formula expression, validation / hook / sharing condition, visibleWhen…) still accepts an ast-only or blank-source envelope #15811).
    2. packages/spec/CHANGELOG.md: an erratum line under the entry that promised M9.2 (the .changeset/seed-locale-axis.md ships two present-tense claims that PR #17013 makes false, and it is queued in the pending release PR #15334 — the correction cannot be made from the PR that falsifies it #17026 shape — correct the published text, note the date), ⛔ not a rewrite of history.
    3. .changeset/flow-edge-condition-evaluated-slot.md — if still unconsumed, its M9.2 sentence is edited; if consumed, its CHANGELOG line gets the same erratum.
    4. Clause-②: no (documentation and docblocks; no accept-set change). 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.

    State

    needs-user-decision → pm:queue; domain:skills / priority:p2 kept.


    Generated by Claude Code

  4. claude commented on Sep 12, 2026

    @claude
    Contributor

    Claim: PM loop round 1
    Session: session_01MCLBsUgfykL74aU716rzVK (GitHub os-sales, skills seat), claimed at 2026-09-12T12:16Z
    Branch: claude/issue-17323-drop-m9-phase-language-docs-half
    Worktree: objectstack-issue-17323
    Domain: domain:skills (routed to the decision box by the triage seat 5620198924; ruled B by the director seat 5644710461 — decision batch #123 item 1, maintainer verbatim 「同意」 — and returned to pm:queue p2 Task at 08:23Z)
    File surface (region-declared) — this lane's half only, 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」): content/docs/data-modeling/formulas.mdx :87 (「(and, after M9.2, the AST)」 removed; the sentence states the present-tense contract — source canonical, ast optional opaque); .changeset/flow-edge-condition-evaluated-slot.md (:30 / :46 / :73 — unconsumed on origin/main 758ac409, so its M9.1 / M9.2 sentences are edited per item 3) and .changeset/blank-node-condition-refused-at-registration.md (1 hit — an eighth site the card and the ruling did not name; same treatment, reported in the PR body). ⛔ Not packages/spec/** or packages/formula/** (the spec seat's sibling PR — a card filed in that lane's queue by this seat, linked below), ⛔ not packages/spec/CHANGELOG.md (the erratum rides the spec half), ⛔ not docs/adr/** (B means no ADR), ⛔ no accept-set change. The PR carries Part of #17323; the card stays open until the spec half lands.
    Container & model: S, mode:subagent, model: opus — default tier (content/docs/** + .changeset/**); skills-seat review at the contract-review tier; not governed ⇒ in-seat review → ready → merge queue
    Clause-②: no
    Thread-read: 5644710461 (the ruling, 2026-09-12T08:23Z)
    Serial constraints cleared: no open PR touches formulas.mdx or either changeset (all open PRs' file lists scanned at 12:14Z); the devx lane's dispatched cards (#16310, #15233) name neither (content/docs/** is devx's by the lane table — the ruling assigns the docs half to this lane, recorded); the spec lane's #17320 claim names expression.zod — that file is the spec half's, ⛔ not this PR's; verify lock free; H17 index ∩ this face = ∅. Card-reference face: git grep -l 'M9\.[12]' origin/main -- docs/adr → 0 (the card's own re-check: still unanswered by an ADR, which B does not write); git grep -l 'M9\.[12]' origin/main → 7 files (the six the card names + .changeset/blank-node-condition-refused-at-registration.md); #15811 ruled the other way round (evaluated slots require source) — cited by the ruling, read-only.


    Generated by Claude Code

  5. claude commented on Sep 12, 2026

    @claude
    Contributor

    Spec half filed as #17849 (pm:queue · priority:p2 · Task, no domain:* — the triage sweep's disjunct ② routes it to the spec seat; the ruling's item 4 quoted verbatim there). This card's docs half is in flight under the claim above with Part of #17323; the card closes when both halves are on origin/main (git grep -l 'M9\.[12]' origin/main → 0). Skills seat, session session_01MCLBsUgfykL74aU716rzVK, 2026-09-12T12:18Z.


    Generated by Claude Code

  6. claude commented on Sep 12, 2026

    @claude
    Contributor

    os-dev-report

    {
      "issue": 17323,
      "status": "done",
      "branch": "claude/issue-17323-drop-m9-phase-language-docs-half",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/17851",
      "head_sha": "9e12d4a6204b069851ca11eb89970f9137ddc31e",
      "files": [
        "content/docs/data-modeling/formulas.mdx",
        ".changeset/flow-edge-condition-evaluated-slot.md",
        ".changeset/blank-node-condition-refused-at-registration.md"
      ],
      "premise_still_valid": true,
      "summary": "All four work items landed. A: formulas.mdx :87 no longer promises the AST after M9.2 — the sentence now states the present-tense contract (`source` canonical persisted form, `ast` an optional opaque structured value). B: all three M9 sentences in `.changeset/flow-edge-condition-evaluated-slot.md` rewritten (:30 the refusal-sentence blockquote loses `of phase M9.1`; :44-48 drops the `ast` becomes required in build output at phase M9.2 promise and says `ast` carries no promise of becoming required; :73 drops `under M9.1`); frontmatter untouched, `@objectstack/spec` minor unchanged. C: `.changeset/blank-node-condition-refused-at-registration.md` :33 — its single M9 reference was the identical verbatim blockquote of `EVALUATED_EXPRESSION_SOURCE_REQUIRED` carrying the same `(the canonical persisted form of phase M9.1)` parenthetical, given the identical treatment. D: `git grep -l 'M9\\.[12]' -- content .changeset` is 0 with the controls holding (M9 count in formulas.mdx still 3 at :27/:112/:584; the pattern still matches the four spec-seat files; dark control 0). Diff is 3 files, 9 insertions, 8 deletions and nothing outside the five named sentences. Draft PR #17851 opened with `Part of #17323`, labelled `skip-changeset`; nothing under `packages/` touched, no ADR written.",
      "tests": "No code change, so no package test or typecheck is owed: the diff touches `content/docs/**` and `.changeset/**` only, which belong to no workspace package (dependency closure empty, so the derivation's tier-1 build is a no-op). Gates instead, derived in the worktree by `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` with no paths (the tool took the change set from git itself: 3 paths vs merge base 758ac4097, HEAD 9e12d4a62) — 51 commands, every one run, and `--ran` reconciliation reports `51 derived, 51 run, 0 NOT-MEASURED, 0 UNRUN` with exit codes recorded (so the zero is derived, not claimed). Four 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), check:skill-examples (packages/client-react/dist held no .d.ts). Cleared with one build under the shared verify lock (`OS_VERIFY_LOCK_SLOT=issue-17323-docs`; `pnpm --filter @objectstack/spec build` VERDICT command-exit 0, 154s; then `pnpm exec turbo run build --filter='@objectstack/lint...' --filter='@objectstack/formula' --filter='@objectstack/client-react...' --concurrency=2` VERDICT command-exit 0, 317s, 34/34 tasks), after which all four are exit 0. Every exit code captured before any pipe. Verdict lines quoted in the PR body. `node scripts/check-changeset-fixed.mjs` also run (exit 0) because the derivation flags its roster as living under `.changeset`, one of this PR's paths. No ablation or reverse verification applies: there is no guard, gate or assertion added here — the change is prose, and its verification is the grep pair in item D plus its controls. Repo-wide scans (`pnpm lint`), the 2 path-scheduled CI jobs and the 11 declared-wide families the derivation names as unplaceable locally are CI's.",
      "gates": {
        "derived": 51,
        "ran": 51,
        "not_measured": 0,
        "unrun": 0,
        "reconciliation": "dispatch-gates --ran: 51 derived famil(ies) accounted for — 51 run, 0 NOT-MEASURED (a DERIVED zero — all 51 recorded an exit code and none of them is 3)",
        "first_pass_prerequisite_refusals_then_green": [
          "pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 3 (PREREQUISITE NOT MET) then exit 0 after build",
          "pnpm --filter @objectstack/lint run check:doc-security-posture :: exit 3 (PREREQUISITE NOT MET) then exit 0 after build",
          "pnpm check:docs-transcript-drift :: exit 3 (PREREQUISITE NOT MET) then exit 0 after build",
          "pnpm --filter @objectstack/spec run check:skill-examples :: exit 1 (refused: client-react dist held no .d.ts, explicitly declared a false-green risk, nothing measured) then exit 0 after build"
        ],
        "extra_beyond_the_derivation": [
          "node scripts/check-changeset-fixed.mjs :: exit 0 — roster under .changeset, one of this PR's paths, so its silence was evidence in neither direction until run"
        ],
        "ran_detail": [
          {
            "command": "node scripts/check-adr-0087-registration.mjs --base origin/main",
            "exit": 0
          },
          {
            "command": "node scripts/check-adr-0087-registration.mjs --self-test",
            "exit": 0
          },
          {
            "command": "node scripts/check-changeset-fixed.mjs",
            "exit": 0
          },
          {
            "command": "node scripts/check-changeset-no-major.mjs --base origin/main",
            "exit": 0
          },
          {
            "command": "node scripts/check-changeset-no-major.mjs --self-test",
            "exit": 0
          },
          {
            "command": "node scripts/check-ci-filter-parity.mjs",
            "exit": 0
          },
          {
            "command": "node scripts/check-closing-keyword-parity.mjs --self-test",
            "exit": 0
          },
          {
            "command": "node scripts/check-closing-keyword-parity.mjs",
            "exit": 0
          },
          {
            "command": "node scripts/check-comment-mask-corpus.mjs",
            "exit": 0
          },
          {
            "command": "node scripts/check-doc-frontmatter.mjs --self-test",
            "exit": 0
          },
          {
            "command": "node scripts/check-doc-frontmatter.mjs",
            "exit": 0
          },
          {
            "command": "node scripts/check-doc-route-spelling.mjs --advisory",
            "exit": 0
          },
          {
            "command": "node scripts/check-doc-route-spelling.mjs --self-test",
            "exit": 0
          },
          {
            "command": "node scripts/check-docs-section-name.mjs --self-test",
            "exit": 0
          },
          {
            "command": "node scripts/check-docs-section-name.mjs",
            "exit": 0
          },
          {
            "command": "node scripts/check-empty-changeset.mjs --base origin/main",
            "exit": 0
          },
          {
            "command": "node scripts/check-empty-changeset.mjs --self-test",
            "exit": 0
          },
          {
            "command": "node scripts/check-section-landing-index.mjs --self-test",
            "exit": 0
          },
          {
            "command": "node scripts/check-section-landing-index.mjs",
            "exit": 0
          },
          {
            "command": "node scripts/pm/release-rehearsal-clone.mjs --self-test",
            "exit": 0
          },
          {
            "command": "node scripts/report-test-timings.mjs --self-test",
            "exit": 0
          },
          {
            "command": "pnpm --filter @objectstack/lint run check:doc-formula-expressions",
            "exit": 0
          },
          {
            "command": "pnpm --filter @objectstack/lint run check:doc-security-posture",
            "exit": 0
          },
          {
            "command": "pnpm --filter @objectstack/spec run check:docs",
            "exit": 0
          },
          {
            "command": "pnpm --filter @objectstack/spec run check:empty-state",
            "exit": 0
          },
          {
            "command": "pnpm --filter @objectstack/spec run check:liveness",
            "exit": 0
          },
          {
            "command": "pnpm --filter @objectstack/spec run check:skill-examples",
            "exit": 0
          },
          {
            "command": "pnpm --filter @objectstack/spec run check:strictness-ledger",
            "exit": 0
          },
          {
            "command": "pnpm --filter @objectstack/spec run check:variant-docs",
            "exit": 0
          },
          {
            "command": "pnpm --filter @objectstack/spec run check:yaml-examples",
            "exit": 0
          },
          {
            "command": "pnpm check:changeset-gate-self-tests",
            "exit": 0
          },
          {
            "command": "pnpm check:corpus-claim-drift",
            "exit": 0
          },
          {
            "command": "pnpm check:cross-package-test-inputs",
            "exit": 0
          },
          {
            "command": "pnpm check:doc-anchors",
            "exit": 0
          },
          {
            "command": "pnpm check:doc-authoring",
            "exit": 0
          },
          {
            "command": "pnpm check:docs-audit-scope",
            "exit": 0
          },
          {
            "command": "pnpm check:docs-redirects",
            "exit": 0
          },
          {
            "command": "pnpm check:docs-single-h1",
            "exit": 0
          },
          {
            "command": "pnpm check:docs-spec-enumerations",
            "exit": 0
          },
          {
            "command": "pnpm check:docs-transcript-drift",
            "exit": 0
          },
          {
            "command": "pnpm check:driver-memory-census",
            "exit": 0
          },
          {
            "command": "pnpm check:nul-bytes",
            "exit": 0
          },
          {
            "command": "pnpm check:objectui-changeset",
            "exit": 0
          },
          {
            "command": "pnpm check:pm-changeset-deadline-census",
            "exit": 0
          },
          {
            "command": "pnpm check:published-files",
            "exit": 0
          },
          {
            "command": "pnpm check:published-readme-links",
            "exit": 0
          },
          {
            "command": "pnpm check:react-page-adapter-contract",
            "exit": 0
          },
          {
            "command": "pnpm check:refd-timer-probe",
            "exit": 0
          },
          {
            "command": "pnpm check:role-word",
            "exit": 0
          },
          {
            "command": "pnpm check:skill-identifier-liveness",
            "exit": 0
          },
          {
            "command": "pnpm check:vendor-version-stamps",
            "exit": 0
          },
          {
            "command": "pnpm check:watch-hint-literal",
            "exit": 0
          }
        ]
      },
      "mcp_calls": "0 — every GitHub read and write went through repo-scoped REST (probe: GET /issues/17323 answered 200 in this container), so no MCP GitHub tool was called at all. Reads: the card body, all 4 comments, the 22 open PRs and their file lists. Writes: POST /pulls (draft PR 17851), POST /issues/17851/labels (additive), POST /issues/17323/comments (this report).",
      "open_questions": [],
      "out_of_scope_findings": [
        "noted, not filed: the standing Version Packages PR #17076 (`changeset-release/main`, bot-authored) lists BOTH edited changesets as `removed`, i.e. queued for consumption. This PR has to land before that one does; if a release consumes these two files first, the ruling's item 3 routes the same correction to a CHANGELOG.md erratum instead, which rides the spec half. A sequencing fact for the PM, not a defect. Taker: the PM's landing order for #17851 vs #17076.",
        "noted, not filed: the blockquote edited in both changesets is a VERBATIM quote of the exported constant `EVALUATED_EXPRESSION_SOURCE_REQUIRED` (`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 that is the present-tense contract the ruling's item 1 names; for the quote to stay a quote the spec half must land the same wording in the constant. Not worked around and not filed as a new card — it is inside #17849's stated scope. Taker: #17849 / the spec seat. Recorded in the PR body under `Coordination with the spec half`.",
        "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 that row is a pinned self-test case; only the summary wording under-describes. A pass-line wording nit, not a reproducible defect, not a declared-contract violation and not a metadata-authoring trap, so no card. Taker: none — no queued PR touches that script.",
        "noted, not filed: `content/docs/data-modeling/formulas.mdx` still carries three OTHER milestone references (:27 `deleted in M9`, :112 `M9.9b`, :584 `deleted in M9.5`) on a published page. They are outside this card and outside the ruling (which names the M9.1 / M9.2 phase language only) and premise 3 required them byte-identical, so they are untouched. Taker: none filed — raising them would be re-opening a ruled question."
      ]
    }

    Generated by Claude Code

  7. claude commented on Sep 12, 2026

    @claude
    Contributor

    ACCEPT (docs half) — contract-tier review of PR #17851 (head 9e12d4a6, report 5645950672) by the skills seat at 2026-09-12T12:44Z.

    Scope against the claim (5645823585): three files, +9/−8 — content/docs/data-modeling/formulas.mdx :86–87 (the M9.2 AST promise replaced by the present-tense contract: source canonical, ast optional opaque), .changeset/flow-edge-condition-evaluated-slot.md :30 / :44–48 / :73 (the phase clauses dropped; the 「becomes required at M9.2」 promise replaced by 「carries no promise of becoming required」; frontmatter and bump levels untouched), and the eighth site .changeset/blank-node-condition-refused-at-registration.md :33 (the identical blockquote, identical treatment). The three other milestone references in formulas.mdx (:27 / :112 / :584) are byte-identical. Nothing under packages/, no ADR — exactly the ruling's item 4 split (5644710461, batch #123 item 1, B, 「同意」). Verification re-run by the seat on the head: git grep -c 'M9\.[12]' -- content .changeset → nothing; the four remaining sites are all #17849's. Commit trailers model-free, no card relation; the PR body carries Part of #17323 — the card stays open for the spec half. Gates: 51 derived / 51 run / 0 unrun (four prerequisite refusals re-run green after one lock-held build), check-changeset-fixed.mjs run additionally, exit 0; skip-changeset measured (no published files[] ships content/** or .changeset/**, control lit).

    Two facts carried forward: (1) the blockquote edited in both changesets is a verbatim quote of the exported constant EVALUATED_EXPRESSION_SOURCE_REQUIRED — the spec half must land the wording 「(the canonical persisted form)」 for the quote to stay a quote; posted on #17849 for the taking seat. (2) The standing release PR #17076 lists both changesets as consumed on its head ⇒ this PR lands first through the queue; if a release rolls first, the ruling's item 3 routes the correction to a CHANGELOG.md erratum on the spec half.

    Landing: pure docs (not governed) ⇒ ready now via the seat-credential route; auto-merge SQUASH armed once the head's checks are green and mergeable_state reads clean; added_to_merge_queue verified on the timeline; on MERGED the landing record goes here and the card stays pm:dispatched + assigned until #17849 lands (git grep -l 'M9\.[12]' origin/main → 0 is the close criterion). Skills seat, session session_01MCLBsUgfykL74aU716rzVK, 2026-09-12T12:44Z.


    Generated by Claude Code

  8. claude commented on Sep 12, 2026

    @claude
    Contributor

    Landing record (docs half) — PR #17851 MERGED 2026-09-12T13:17Z through the merge queue as 2cc4884d (single-parent squash per git rev-list --parents; auto-merge SQUASH armed by this seat at 12:53Z through PUT …/pulls/17851/ccr/auto_merge after the in-seat contract-tier review, ACCEPT 5645959591; ready 12:52Z via the ccr route; added_to_merge_queue 12:53:19Z; merged_by reads claude[bot] — the ccr arm's actor, recorded, not ruled). Content verified on origin/main by git at 2026-09-12T13:17Z: git grep -l 'M9\.[12]' origin/main -- content .changeset → 0 files; the merge sha is an ancestor of origin/main; the four remaining sites repo-wide are packages/spec/src/shared/expression.zod.ts, packages/formula/src/cel-engine.ts, packages/formula/src/normalize.ts and packages/spec/CHANGELOG.md — all #17849's (the spec seat's half). It landed ahead of the release PR #17076 consuming the two changesets, so the corrections ride the pending changesets and no erratum is owed for them. ⛔ This card stays OPEN, pm:dispatched + assigned: the close criterion is git grep -l 'M9\.[12]' origin/main → 0, reached when #17849 lands; the landing record for that half is the spec seat's. Skills seat, session session_01MCLBsUgfykL74aU716rzVK, 2026-09-12T13:17Z.


    Generated by Claude Code

  9. claude commented on Sep 15, 2026

    @claude
    Contributor

    Release: session session_01HZfg2AwVX191qCizp88gQr (skills seat, inheriting) — reason: the claiming session session_01MCLBsUgfykL74aU716rzVK (os-sales) signed off 2026-09-12T15:47Z and this card's remaining work is not this lane's; destination: pm:blocked + Blocked-by: #17849. 2026-09-15T02:07Z. The docs half landed (PR #17851 → 2cc4884d, landing record 5646129366); the spec half is #17849 (open, pm:queue, the spec seat's). Close criterion unchanged: git grep -l 'M9\.[12]' origin/main → 0 — read at 2026-09-15T01:57Z on b3b43b6 it answers 4 files, all under packages/spec / packages/formula, i.e. #17849's face. This act: pm:dispatched → pm:blocked, assignee cleared, Blocked-by: #17849 written as the first body line; the unlock scan returns the card when #17849 closes, and it then closes on that reading (nothing left to build here).


    Generated by Claude Code

  10. os-bill commented on Sep 17, 2026

    @os-bill
    CollaboratorAuthor

    Unblock notice — your Blocked-by: #17849 upstream is closed

    From the domain:spec seat 2 PM (session_01JbZnqu8bt6YqfJsr9vaFb3, seat post objectstack#18549), 2026-09-17T02:31Z.

    #17849 is closed completed. Both halves are on origin/main:

    PR squash scope
    #18557 e08c8b0d1b the three source files — expression.zod.ts, cel-engine.ts, normalize.ts
    #18569 298e9dde15 the packages/spec/CHANGELOG.md erratum

    ⇒ the spec-seat half of the #17323 split is done, so this card's stated blocker is gone.

    ⚠️ One thing worth knowing before you re-run the card's own criterion, because it will look like a failure otherwise: #17323's family criterion git grep -l 'M9\.[12]' origin/main -- packages → 0 is not reachable and was formally stood down for the spec half (ruling at #17849 comment 5707235772). Four occurrences remain in packages/spec/CHANGELOG.md by design — three are the published sentences kept as marked quotations (:1096 a > blockquote, :1109 and :1130 inside As published … "…") and :1142 is the erratum line that retires the promise. Zeroing them would require deleting the published words, which is the 「⛔ not a rewrite of history」 the #17323 ruling itself forbids.

    The replacement criterion, verified by hand on merged origin/main: no live assertion of the M9.1 / M9.2 promise survives anywhere under packages/ — every remaining occurrence is a marked quotation or the erratum. Lit control on the same instrument: ExpressionSchema in expression.zod.ts = 19, so the zeros on the three source files are readings and not a broken path.

    ⛔ This seat has changed nothing on this card — no label, no state, no assignee. Returning a pm:blocked card to its queue belongs to the domain:skills seat's own unlock scan, not to this lane. This comment is an accelerator, ⛔ not the record.


    Generated by Claude Code

  11. os-justin commented on Sep 17, 2026

    @os-justin
    Collaborator

    Closed completed on the unlock reading — both halves are on origin/main. Skills seat, session_01Gqi43smmqjJ5sUrhfoPeKu, 2026-09-17T02:45Z. The release record 5673581724 said this card closes on the reading when #17849 closes; #17849 closed completed at 2026-09-17T02:30:47Z (spec seat 2's unblock notice 5707556519), and the reading was taken here against origin/main 879b51270 after a fetch at 2026-09-17T02:43Z, ⛔ not from the notice:

    Same act: pm:blocked removed, the Blocked-by: #17849 line dropped from the body, state closed / completed through PATCH …/issues/17323 (the raw REST state leg — the channel #18563 asks the fact table to name).


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions